[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10424":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":35,"readmeContent":36,"aiSummary":37,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":38,"discoverSource":39},10424,"sqlboiler","aarondl\u002Fsqlboiler","aarondl","Generate a Go ORM tailored to your database schema.","",null,"Go",6990,558,70,96,0,2,6,1,39.24,"Other",false,"master",true,[26,27,28,29,30,31,32,33,5,34],"database","go","golang","mssql","mysql","orm","postgres","postgresql","sqlite3","2026-06-12 02:02:21","![sqlboiler logo](https:\u002F\u002Fi.imgur.com\u002FlMXUTPE.png)\n\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-BSD-blue.svg)](https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fblob\u002Fmaster\u002FLICENSE)\n[![GoDoc](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fgodoc-reference-5272B4)](https:\u002F\u002Fpkg.go.dev\u002Fmod\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4)\n[![Slack](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fslack-%23general-lightgrey.svg)](https:\u002F\u002Fsqlboiler.from-the.cloud)\n![ActionsCI](https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fworkflows\u002Ftest\u002Fbadge.svg)\n[![Go Report Card](https:\u002F\u002Fgoreportcard.com\u002Fbadge\u002Faarondl\u002Fsqlboiler)](http:\u002F\u002Fgoreportcard.com\u002Freport\u002Faarondl\u002Fsqlboiler)\n\n# Maintenance Mode\n\nThis package is currently in maintenance mode, which means:\n\n1. It generally does not accept new features.\n2. It does accept bug fixes and version compatability changes provided by the community.\n3. Maintainers usually do not resolve reported issues.\n4. Community members are encouraged to help each other with reported issues.\n\n## Alternatives\n\nIf looking for an actively maintained alternative, consider the following:\n\n### 1. Bob - \u003Chttps:\u002F\u002Fgithub.com\u002Fstephenafamo\u002Fbob>\n\nBob is very similar to SQLBoiler. It was directly inspired by SQLBoiler and was created by a maintainer of SQLBoiler.\n\nA comparison can be found here: \u003Chttps:\u002F\u002Fbob.stephenafamo.com\u002Fvs\u002Fsqlboiler\u002F>.\n\n### 2. sqlc - \u003Chttps:\u002F\u002Fgithub.com\u002Fsqlc-dev\u002Fsqlc>\n\n`sqlc` is a command line tool that generates type-safe code from SQL.  \nIt is not an ORM but for many use cases it can be a good alternative to SQLBoiler.\n\n# About SQLBoiler\n\nSQLBoiler is a tool to generate a Go ORM tailored to your database schema.\n\nIt is a \"database-first\" ORM as opposed to \"code-first\" (like gorm\u002Fgorp).\nThat means you must first create your database schema. Please use something\nlike [sql-migrate](https:\u002F\u002Fgithub.com\u002Frubenv\u002Fsql-migrate)\nor some other migration tool to manage this part of the database's life-cycle.\n\n# Note on versions\n\nv1, v2, and v3 are no longer maintained.\n\nv3 is the last GOPATH-compatible version.\n\nv4 has no real breaking changes between v3 and itself other than Go modules\nand is the only maintained version. Note this does not work with GOPATH\nprojects.\n\n## Why another ORM\n\nWhile attempting to migrate a legacy Rails database, we realized how much ActiveRecord benefited us in terms of development velocity.\nComing over to the Go `database\u002Fsql` package after using ActiveRecord feels extremely repetitive, super long-winded and down-right boring.\nBeing Go veterans we knew the state of ORMs was shaky, and after a quick review we found what our fears confirmed. Most packages out\nthere are code-first, reflect-based and have a very weak story around relationships between models. So with that we set out with these goals:\n\n- Work with existing databases: Don't be the tool to define the schema, that's better left to other tools.\n- ActiveRecord-like productivity: Eliminate all sql boilerplate, have relationships as a first-class concept.\n- Go-like feel: Work with normal structs, call functions, no hyper-magical struct tags, small interfaces.\n- Go-like performance: [Benchmark](#benchmarks) and optimize the hot-paths, perform like hand-rolled `sql.DB` code.\n\nWe believe with SQLBoiler and our database-first code-generation approach we've been able to successfully meet all of these goals. On top\nof that SQLBoiler also confers the following benefits:\n\n- The models package is type safe. This means no chance of random panics due to passing in the wrong type. No need for interface{}.\n- Our types closely correlate to your database column types. This is expanded by our extended null package which supports nearly all Go data types.\n- 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.\n- Auto-completion provides work-flow efficiency gains.\n\n# Table of Contents\n\n- [SQLBoiler](#sqlboiler)\n  - [Why another ORM](#why-another-orm)\n  - [About SQL Boiler](#about-sql-boiler)\n    - [Features](#features)\n    - [Missing Features](#missing-features)\n    - [Supported Databases](#supported-databases)\n    - [A Small Taste](#a-small-taste)\n  - [Requirements &amp; Pro Tips](#requirements--pro-tips)\n    - [Requirements](#requirements)\n    - [Pro Tips](#pro-tips)\n  - [Getting started](#getting-started)\n    - [Videos](#videos)\n    - [Download](#download)\n    - [Configuration](#configuration)\n    - [Initial Generation](#initial-generation)\n    - [Regeneration](#regeneration)\n    - [Controlling Version](#controlling-version)\n    - [Controlling Generation](#controlling-generation)\n      - [Aliases](#aliases)\n      - [Types](#types)\n      - [Imports](#imports)\n      - [Templates](#templates)\n    - [Extending Generated Models](#extending-generated-models)\n  - [Diagnosing Problems](#diagnosing-problems)\n  - [Features &amp; Examples](#features--examples)\n    - [Automatic CreatedAt\u002FUpdatedAt](#automatic-createdatupdatedat)\n      - [Skipping Automatic Timestamps](#skipping-automatic-timestamps)\n      - [Overriding Automatic Timestamps](#overriding-automatic-timestamps)\n    - [Query Building](#query-building)\n    - [Query Mod System](#query-mod-system)\n    - [Function Variations](#function-variations)\n    - [Finishers](#finishers)\n    - [Raw Query](#raw-query)\n    - [Binding](#binding)\n    - [Relationships](#relationships)\n    - [Hooks](#hooks)\n      - [Skipping Hooks](#skipping-hooks)\n    - [Transactions](#transactions)\n    - [Debug Logging](#debug-logging)\n    - [Select](#select)\n    - [Find](#find)\n    - [Insert](#insert)\n    - [Update](#update)\n    - [Delete](#delete)\n    - [Upsert](#upsert)\n    - [Reload](#reload)\n    - [Exists](#exists)\n    - [Enums](#enums)\n    - [Constants](#constants)\n  - [FAQ](#faq)\n    - [Won't compiling models for a huge database be very slow?](#wont-compiling-models-for-a-huge-database-be-very-slow)\n    - [Missing imports for generated package](#missing-imports-for-generated-package)\n    - [How should I handle multiple schemas](#how-should-i-handle-multiple-schemas)\n    - [How do I use the types.BytesArray for Postgres bytea arrays?](#how-do-i-use-typesbytesarray-for-postgres-bytea-arrays)\n    - [Why aren't my time.Time or null.Time fields working in MySQL?](#why-arent-my-timetime-or-nulltime-fields-working-in-mysql)\n    - [Where is the homepage?](#where-is-the-homepage)\n    - [Why are the auto-generated tests failing?](#why-are-the-auto-generated-tests-failing)\n- [Benchmarks](#benchmarks)\n- [Third-Party Extensions](#third-party-extensions)\n\n## About SQL Boiler\n\n### Features\n\n- Full model generation\n- Extremely fast code generation\n- High performance through generation & intelligent caching\n- Uses boil.Executor (simple interface, sql.DB, sqlx.DB etc. compatible)\n- Uses context.Context\n- Easy workflow (models can always be regenerated, full auto-complete)\n- Strongly typed querying (usually no converting or binding to pointers)\n- Hooks (Before\u002FAfter Create\u002FSelect\u002FUpdate\u002FDelete\u002FUpsert)\n- Automatic CreatedAt\u002FUpdatedAt\n- Automatic DeletedAt\n- Table and column whitelist\u002Fblacklist\n- Relationships\u002FAssociations\n- Eager loading (recursive)\n- Custom struct tags\n- Transactions\n- Raw SQL fallback\n- Compatibility tests (Run against your own DB schema)\n- Debug logging\n- Basic multiple schema support (no cross-schema support)\n- 1d arrays, json, hstore & more\n- Enum types\n- Out of band driver support\n- Support for database views\n- Supports generated\u002Fcomputed columns\n\n### Missing features\n\n- Multi-column foreign key support\n- Materialized view support\n  - Only postgresql is supported\n\n### Supported Databases\n\n| Database          | Driver Location                                                                                     |\n| ----------------- | --------------------------------------------------------------------------------------------------- |\n| PostgreSQL        | [https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-psql](drivers\u002Fsqlboiler-psql)       |\n| MySQL             | [https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-mysql](drivers\u002Fsqlboiler-mysql)     |\n| MSSQLServer 2012+ | [https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-mssql](drivers\u002Fsqlboiler-mssql)     |\n| SQLite3           | [https:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-sqlite3](drivers\u002Fsqlboiler-sqlite3) |\n| CockroachDB       | https:\u002F\u002Fgithub.com\u002Fglerchundi\u002Fsqlboiler-crdb                                                        |\n\n**Note:** SQLBoiler supports out of band driver support so you can make your own\n\nWe are seeking contributors for other database engines.\n\n### A Small Taste\n\nFor a comprehensive list of available operations and examples please see [Features & Examples](#features--examples).\n\n```go\nimport (\n  \u002F\u002F Import this so we don't have to use qm.Limit etc.\n  . \"github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fqueries\u002Fqm\"\n)\n\n\u002F\u002F Open handle to database like normal\ndb, err := sql.Open(\"postgres\", \"dbname=fun user=abc\")\nif err != nil {\n  return err\n}\n\n\u002F\u002F If you don't want to pass in db to all generated methods\n\u002F\u002F you can use boil.SetDB to set it globally, and then use\n\u002F\u002F the G variant methods like so (--add-global-variants to enable)\nboil.SetDB(db)\nusers, err := models.Users().AllG(ctx)\n\n\u002F\u002F Query all users\nusers, err := models.Users().All(ctx, db)\n\n\u002F\u002F Panic-able if you like to code that way (--add-panic-variants to enable)\nusers := models.Users().AllP(db)\n\n\u002F\u002F More complex query\nusers, err := models.Users(Where(\"age > ?\", 30), Limit(5), Offset(6)).All(ctx, db)\n\n\u002F\u002F Ultra complex query\nusers, err := models.Users(\n  Select(\"id\", \"name\"),\n  InnerJoin(\"credit_cards c on c.user_id = users.id\"),\n  Where(\"age > ?\", 30),\n  AndIn(\"c.kind in ?\", \"visa\", \"mastercard\"),\n  Or(\"email like ?\", `%aol.com%`),\n  GroupBy(\"id\", \"name\"),\n  Having(\"count(c.id) > ?\", 2),\n  Limit(5),\n  Offset(6),\n).All(ctx, db)\n\n\u002F\u002F Use any \"boil.Executor\" implementation (*sql.DB, *sql.Tx, data-dog mock db)\n\u002F\u002F for any query.\ntx, err := db.BeginTx(ctx, nil)\nif err != nil {\n  return err\n}\nusers, err := models.Users().All(ctx, tx)\n\n\u002F\u002F Relationships\nuser, err := models.Users().One(ctx, db)\nif err != nil {\n  return err\n}\nmovies, err := user.FavoriteMovies().All(ctx, db)\n\n\u002F\u002F Eager loading\nusers, err := models.Users(Load(\"FavoriteMovies\")).All(ctx, db)\nif err != nil {\n  return err\n}\nfmt.Println(len(users.R.FavoriteMovies))\n```\n\n## Requirements & Pro Tips\n\n### Requirements\n\n- Go 1.13, older Go versions are not supported.\n- Join tables should use a _composite primary key_.\n  - For join tables to be used transparently for relationships your join table must have\n    a _composite primary key_ that encompasses both foreign table foreign keys and\n    no other columns in the table. For example, on a join table named\n    `user_videos` you should have: `primary key(user_id, video_id)`, with both\n    `user_id` and `video_id` being foreign key columns to the users and videos\n    tables respectively and there are no other columns on this table.\n- MySQL 5.6.30 minimum; ssl-mode option is not supported for earlier versions.\n- For MySQL if using the `github.com\u002Fgo-sql-driver\u002Fmysql` driver, please activate\n  [time.Time parsing](https:\u002F\u002Fgithub.com\u002Fgo-sql-driver\u002Fmysql#timetime-support) when making your\n  MySQL database connection. SQLBoiler uses `time.Time` and `null.Time` to represent time in\n  it's models and without this enabled any models with `DATE`\u002F`DATETIME` columns will not work.\n\n### Pro Tips\n\n- SQLBoiler generates type safe identifiers for table names, table column names,\n  a table's relationship names and type-safe where clauses. You should use these\n  instead of strings due to the ability to catch more errors at compile time\n  when your database schema changes. See [Constants](#constants) for details.\n- It's highly recommended to use transactions where sqlboiler will be doing\n  multiple database calls (relationship setops with insertions for example) for\n  both performance and data integrity.\n- Foreign key column names should end with `_id`.\n  - Foreign key column names in the format `x_id` will generate clearer method names.\n    It is advisable to use this naming convention whenever it makes sense for your database schema.\n- If you never plan on using the hooks functionality you can disable generation of this\n  feature using the `--no-hooks` flag. This will save you some binary size.\n\n## Getting started\n\n#### Videos\n\nIf you like learning via a video medium, sqlboiler has a number of screencasts\navailable.\n\n_NOTE:_ These videos predate modules (v4), the installation\u002Fimport paths will be\ndifferent though everything else should remain similar.\n\n[SQLBoiler: Getting Started](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=y5utRS9axfg)\n\n[SQLBoiler: What's New in v3](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=-B-OPsYRZJA)\n\n[SQLBoiler: Advanced Queries and Relationships](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=iiJuM9NR8No)\n\n[Old (v2): SQLBoiler Screencast #1: How to get started](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=fKmRemtmi0Y)\n\n#### Download\n\nFirst you have to install the code generator binaries. There's the main binary\nand then a separate driver binary (select the right one for your database).\n\nBe very careful when installing, there's confusion in the Go ecosystem and\nknowing what are the right commands to run for which Go version can be tricky.\nEnsure you don't forget any \u002Fv suffixes or you'll end up on an old version.\n\n```shell\n# Go 1.16 and above:\ngo install github.com\u002Faarondl\u002Fsqlboiler\u002Fv4@latest\ngo install github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-psql@latest\n\n# Go 1.15 and below:\n# Install sqlboiler v4 and the postgresql driver (mysql, mssql, sqlite3 also available)\n# NOTE: DO NOT run this inside another Go module (like your project) as it will\n# pollute your go.mod with a bunch of stuff you don't want and your binary\n# will not get installed.\nGO111MODULE=on go get -u -t github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\nGO111MODULE=on go get github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fdrivers\u002Fsqlboiler-psql\n```\n\nTo install `sqlboiler` as a dependency in your project use the commands below\ninside of your go module's directory tree. This will install the dependencies\ninto your `go.mod` file at the correct version.\n\n```shell\n# Do not forget the trailing \u002Fv4 and \u002Fv8 in the following commands\ngo get github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\n# Assuming you're going to use the null package for its additional null types\ngo get github.com\u002Faarondl\u002Fnull\u002Fv8\n```\n\n#### Configuration\n\nCreate a configuration file. Because the project uses\n[viper](https:\u002F\u002Fgithub.com\u002Fspf13\u002Fviper), TOML, JSON and YAML are all usable\nbut only TOML is supported. Environment variables are also able to be used.\n\nThe configuration file should be named `sqlboiler.toml` and is searched for in\nthe following directories in this order:\n\n- `.\u002F`\n- `$XDG_CONFIG_HOME\u002Fsqlboiler\u002F`\n- `$HOME\u002F.config\u002Fsqlboiler\u002F`\n\nWe will assume TOML for the rest of the documentation.\n\n##### Database Driver Configuration\n\nThe configuration for a specific driver (in these examples we'll use `psql`)\nmust all be prefixed by the driver name. You must use a configuration file or\nenvironment variables for configuring the database driver; there are no\ncommand-line options for providing driver-specific configuration.\n\nIn the configuration file for postgresql for example you would do:\n\n```toml\n[psql]\ndbname = \"your_database_name\"\n```\n\nWhen you use an environment variable it must also be prefixed by the driver\nname:\n\n```sh\nPSQL_DBNAME=\"your_database_name\"\n```\n\nThe values that exist for the drivers:\n\n| Name        | Required | Postgres Default | MySQL Default | MSSQL Default |\n| ----------- | -------- | ---------------- | ------------- | ------------- |\n| schema      | no       | \"public\"         | none          | \"dbo\"         |\n| dbname      | yes      | none             | none          | none          |\n| host        | yes      | none             | none          | none          |\n| port        | no       | 5432             | 3306          | 1433          |\n| user        | yes      | none             | none          | none          |\n| pass        | no       | none             | none          | none          |\n| sslmode     | no       | \"require\"        | \"true\"        | \"true\"        |\n| unix-socket | no       | N\u002FA              | \"\"            | N\u002FA           |\n| whitelist   | no       | []               | []            | []            |\n| blacklist   | no       | []               | []            | []            |\n\nExample of whitelist\u002Fblacklist:\n\n```toml\n[psql]\n# Removes migrations table, the name column from the addresses table, and\n# secret_col of any table from being generated. Foreign keys that reference tables\n# or columns that are no longer generated because of whitelists or blacklists may\n# cause problems.\nblacklist = [\"migrations\", \"addresses.name\", \"*.secret_col\"]\n```\n\n##### Generic config options\n\nYou can also pass in these top level configuration values if you would prefer\nnot to pass them through the command line or environment variables:\n\n| Name                      | Defaults |\n| ------------------------- | -------- |\n| pkgname                   | \"models\" |\n| output                    | \"models\" |\n| tag                       | []       |\n| debug                     | false    |\n| add-global-variants       | false    |\n| add-panic-variants        | false    |\n| add-enum-types            | false    |\n| enum-null-prefix          | \"Null\"   |\n| no-context                | false    |\n| no-hooks                  | false    |\n| no-tests                  | false    |\n| no-auto-timestamps        | false    |\n| no-rows-affected          | false    |\n| no-driver-templates       | false    |\n| no-relation-getters       | false    |\n| tag-ignore                | []       |\n| strict-verify-mod-version | false    |\n\n##### Full Example\n\n```toml\noutput   = \"my_models\"\nwipe     = true\nno-tests = true\nadd-enum-types = true\n\n[psql]\n  dbname = \"dbname\"\n  host   = \"localhost\"\n  port   = 5432\n  user   = \"dbusername\"\n  pass   = \"dbpassword\"\n  schema = \"myschema\"\n  blacklist = [\"migrations\", \"other\"]\n\n[mysql]\n  dbname  = \"dbname\"\n  host    = \"localhost\"\n  port    = 3306\n  user    = \"dbusername\"\n  pass    = \"dbpassword\"\n  sslmode = \"false\"\n  tinyint_as_int = true\n\n[mssql]\n  dbname  = \"dbname\"\n  host    = \"localhost\"\n  port    = 1433\n  user    = \"dbusername\"\n  pass    = \"dbpassword\"\n  sslmode = \"disable\"\n  schema  = \"notdbo\"\n```\n\n#### Initial Generation\n\nAfter creating a configuration file that points at the database we want to\ngenerate models for, we can invoke the sqlboiler command line utility.\n\n```text\nSQL Boiler generates a Go ORM from template files, tailored to your database schema.\nComplete documentation is available at http:\u002F\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\n\nUsage:\n  sqlboiler [flags] \u003Cdriver>\n\nExamples:\nsqlboiler psql\n\nFlags:\n      --add-global-variants        Enable generation for global variants\n      --add-panic-variants         Enable generation for panic variants\n      --add-soft-deletes           Enable soft deletion by updating deleted_at timestamp\n      --add-enum-types             Enable generation of types for enums\n      --enum-null-prefix           Name prefix of nullable enum types (default \"Null\")\n  -c, --config string              Filename of config file to override default lookup\n  -d, --debug                      Debug mode prints stack traces on error\n  -h, --help                       help for sqlboiler\n      --no-auto-timestamps         Disable automatic timestamps for created_at\u002Fupdated_at\n      --no-back-referencing        Disable back referencing in the loaded relationship structs\n      --no-context                 Disable context.Context usage in the generated code\n      --no-driver-templates        Disable parsing of templates defined by the database driver\n      --no-hooks                   Disable hooks feature for your models\n      --no-rows-affected           Disable rows affected in the generated API\n      --no-tests                   Disable generated go test files\n      --no-relation-getters        Disable generating getters for relationship tables\n  -o, --output string              The name of the folder to output to (default \"models\")\n  -p, --pkgname string             The name you wish to assign to your generated package (default \"models\")\n      --struct-tag-casing string   Decides the casing for go structure tag names. camel, title, alias or snake (default \"snake\")\n  -t, --tag strings                Struct tags to be included on your models in addition to json, yaml, toml\n      --tag-ignore strings         List of column names that should have tags values set to '-' (ignored during parsing)\n      --templates strings          A templates directory, overrides the embedded template folders in sqlboiler\n      --replace strings  An array of templates file and the actual template file to be replaces \n      --version                    Print the version\n      --strict-verify-mod-version  Prevent code generation, if project version of sqlboiler not match with executable\n      --wipe                       Delete the output folder (rm -rf) before generation to ensure sanity\n```\n\nFollow the steps below to do some basic model generation. Once you've generated\nyour models, you can run the compatibility tests which will exercise the entirety\nof the generated code. This way you can ensure that your database is compatible\nwith SQLBoiler. If you find there are some failing tests, please check the\n[Diagnosing Problems](#diagnosing-problems) section.\n\n```sh\n# Generate our models and exclude the migrations table\n# When passing 'psql' here, it looks for a binary called\n# 'sqlboiler-psql' in your CWD and PATH. You can also pass\n# an absolute path to a driver if you desire.\nsqlboiler psql\n\n# Run the generated tests\ngo test .\u002Fmodels\n```\n\n_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_\n\nYou can use `go generate` for SQLBoiler if you want to to make it easy to\nrun the command for your application:\n\n```go\n\u002F\u002Fgo:generate sqlboiler --flags-go-here psql\n```\n\nIt's important to not modify anything in the output folder, which brings us to\nthe next topic: regeneration.\n\n#### Regeneration\n\nWhen regenerating the models it's recommended that you completely delete the\ngenerated directory in a build script or use the `--wipe` flag in SQLBoiler.\nThe reasons for this are that sqlboiler doesn't try to diff your files in any\nsmart way, it simply writes the files it's going to write whether they're there\nor not and doesn't delete any files that were added by you or previous runs of\nSQLBoiler. In the best case this can cause compilation errors, in the worst case\nthis may leave extraneous and unusable code that was generated against tables\nthat are no longer in the database.\n\nThe bottom line is that this tool should always produce the same result from\nthe same source. And the intention is to always regenerate from a pure state.\nThe only reason the `--wipe` flag isn't defaulted to on is because we don't\nlike programs that `rm -rf` things on the filesystem without being asked to.\n\n#### Controlling Version\n\nWhen sqlboiler is used on a regular basis, sometimes problems arise on the\ndevelopers' side that the version they are using does not match the version\nspecified in the project.\n\nSqlboiler will warn, if version in project and executable mismatch.\nSqlboiler can also fail to prevent code generation, when\n`--strict-verify-mod-version` flag (or aliased version in toml) is enabled.\n\n#### Controlling Generation\n\nThe templates get executed in a specific way each time. There's a variety of\nconfiguration options on the command line\u002Fconfig file that can control what\nfeatures are turned on or off.\n\nIn addition to the command line flags there are a few features that are only\navailable via the config file and can use some explanation.\n\n##### Aliases\n\nIn sqlboiler, names are automatically generated for you. If you name your\ndatabase entities properly you will likely have descriptive names generated in\nthe end. However in the case where the names in your database are bad AND\nunchangeable, or sqlboiler's inference doesn't understand the names you do have\n(even though they are good and correct) you can use aliases to change the name\nof your tables, columns and relationships in the generated Go code.\n\n_Note: It is not required to provide all parts of all names. Anything left out\nwill be inferred as it was in the past._\n\n```toml\n# Although team_names works fine without configuration, we use it here for illustrative purposes\n[aliases.tables.team_names]\nup_plural     = \"TeamNames\"\nup_singular   = \"TeamName\"\ndown_plural   = \"teamNames\"\ndown_singular = \"teamName\"\n\n  # Columns can also be aliased.\n  [aliases.tables.team_names.columns]\n  team_name = \"OurTeamName\"\n```\n\nWhen creating aliases for relationships, it's important to know how sqlboiler\nnames relationships. For a given table the foreign key name is used as a unique\nidentifier to refer to a given relationship. If you are going to be aliasing\nrelationships it's **highly recommended** that you name your foreign keys\nexplicitly in your database or the auto-generated names could one day\nchange\u002Fbreak your aliases.\n\nEach relationship has a **local** and a **foreign** function name. The function name will\nbe inserted into your generated code as a function to retrieve relationship data as\nwell as refer to the relationship in a few other places. **local** means \"the function name\nthat refers to the table with the foreign key on it\" and conversely **foreign**\nmeans \"the function that refers to the table the foreign key points to\".\n\nFor example - let's have a `videos -> users` many to one relationship that looks\nlike this:\n\n```text\nThe tables and their columns:\n\n| videos  | users |\n|---------|-------|\n| user_id | id    |\n\nOur foreign key:\nvideos_user_id_fkey: videos.user_id -> users.id\n```\n\nIn this example `local` (how we refer to the table with the foreign key) is\ngoing to be inferred as `Videos`. We're going to override that below to be\n`AuthoredVideos`.\n\nConversely `foreign` (how we refer to the table the foreign key points to) is\ngoing to be inferred as `User`, which we'd like to rename to `Author` to suit\nour domain language a bit better.\n\nWith the configuration snippet below we can use the following relationship\nhelper functions off of the respective models: `video.Author` and\n`user.AuthoredVideos` which make a bit more sense than the inferred names when\nwe see it in the code for our domain. Note the use of the foreign key name to\nrefer to the relationship in the configuration key.\n\n```toml\n[aliases.tables.videos.relationships.videos_author_id_fkey]\n# The local side would originally be inferred as AuthorVideos, which\n# is probably good enough to not want to mess around with this feature, avoid it where possible.\nlocal   = \"AuthoredVideos\"\n# Even if left unspecified, the foreign side would have been inferred correctly\n# due to the proper naming of the foreign key column.\nforeign = \"Author\"\n```\n\nIn a many-to-many relationship it's a bit more complicated. Let's look at an\nexample relationship between `videos \u003C-> tags` with a join table in the middle.\nImagine if the join table didn't exist, and instead both of the id columns in\nthe join table were slapped on to the tables themselves. You'd have\n`videos.tag_id` and `tags.video_id`. Using a similar method to the above (local\nis the name with which we refer to the side that has the foreign key)\nwe can rename the relationships. To change `Videos.Tags` to `Videos.Rags`\nwe can use the example below.\n\nKeep in mind that naming ONE side of the many-to-many relationship is sufficient\nas the other side will be automatically mirrored, though you can specify both if\nyou so choose.\n\n```toml\n[aliases.tables.video_tags.relationships.fk_video_id]\nlocal   = \"Rags\"\nforeign = \"Videos\"\n```\n\nThe above definition will specify `Rags` as the name of the property with which\na given `Video` entity will be able to access all of it's tags. If we look the\nother way around - a single `Tag` entity will refer to all videos that have that\nspecific tag with the `Videos` property.\n\nThere is an alternative syntax available for those who are challenged by the key\nsyntax of toml or challenged by viper lowercasing all of your keys. Instead of\nusing a regular table in toml, use an array of tables, and add a name field to\neach object. The only one that changes past that is columns, which now has to\nhave a new field called `alias`.\n\n```toml\n[[aliases.tables]]\nname          = \"team_names\"\nup_plural     = \"TeamNames\"\nup_singular   = \"TeamName\"\ndown_plural   = \"teamNames\"\ndown_singular = \"teamName\"\n\n  [[aliases.tables.columns]]\n  name  = \"team_name\"\n  alias = \"OurTeamName\"\n\n  [[aliases.tables.relationships]]\n  name    = \"fk_video_id\"\n  local   = \"Rags\"\n  foreign = \"Videos\"\n```\n\n##### Custom Struct Tag Case\n\nSometimes you might want to customize the case style for different purpose, for example, use camel case for json format and use snake case for yaml,\nYou may create a section named `[struct-tag-cases]` to define these custom case for each different format:\n\n```toml\n[struct-tag-cases]\ntoml = \"snake\"\nyaml = \"camel\"\njson = \"camel\"\nboil = \"alias\"\n```\n\nBy default, the snake case will be used, so you can just setup only few formats:\n\n```toml\n[struct-tag-cases]\njson = \"camel\"\n```\n\n##### Foreign Keys\n\nYou can add foreign keys not defined in the database to your models using the following configuration:\n\n```toml\n[foreign_keys.jet_pilots_fkey]\ntable = \"jets\"\ncolumn = \"pilot_id\"\nforeign_table = \"pilots\"\nforeign_column = \"id\"\n\n[foreign_keys.pilot_language_pilots_fkey]\ntable = \"pilot_languages\"\ncolumn = \"pilot_id\"\nforeign_table = \"pilots\"\nforeign_column = \"id\"\n\n[foreign_keys.pilot_language_languages_fkey]\ntable = \"pilot_languages\"\ncolumn = \"language_id\"\nforeign_table = \"languages\"\nforeign_column = \"id\"\n```\n\n##### Inflections\n\nWith inflections, you can control the rules sqlboiler uses to generates singular\u002Fplural variants. This is useful if a certain word or suffix is used multiple times and you do not want to create aliases for every instance.\n\n```toml\n[inflections.plural]\n# Rules to convert a suffix to its plural form\nium = \"ia\"\n\n[inflections.plural_exact]\n# Rules to convert an exact word to its plural form\nstadium = \"stadia\"\n\n[inflections.singular]\n# Rules to convert a suffix to its singular form\nia = \"ium\"\n\n[inflections.singular_exact]\n# Rules to convert an exact word to its singular form\nstadia = \"stadium\"\n\n[inflections.irregular]\n# The singular -> plural mapping of an exact word that doen't follow conventional rules\nradius = \"radii\"\n```\n\n##### Types\n\nThere exists the ability to override types that the driver has inferred.\nThe way to accomplish this is through the config file.\n\n```toml\n[[types]]\n  # The match is a drivers.Column struct, and matches on almost all fields.\n  # Notable exception for the unique bool. Matches are done\n  # with \"logical and\" meaning it must match all specified matchers.\n  # Boolean values are only checked if all the string specifiers match first,\n  # and they must always match.\n  #\n  # Not shown here: db_type is the database type and a very useful matcher\n  # We can also whitelist tables for this replace by adding to the types.match:\n  # tables = ['users', 'videos']\n  #\n  # Note there is precedence for types.match, more specific things should appear\n  # further down in the config as once a matching rule is found it is executed\n  # immediately.\n  [types.match]\n    type = \"null.String\"\n    nullable = true\n\n  # The replace is what we replace the strings with. You cannot modify any\n  # boolean values in here. But we could change the Go type (the most useful thing)\n  # or the DBType or FullDBType etc. if for some reason we needed to.\n  [types.replace]\n    type = \"mynull.String\"\n\n  # These imports specified here overwrite the definition of the type's \"based_on_type\"\n  # list. The type entry that is replaced is the replaced type's \"type\" field.\n  # In the above example it would add an entry for mynull.String, if we did not\n  # change the type in our replacement, it would overwrite the null.String entry.\n  [types.imports]\n    third_party = ['\"github.com\u002Fme\u002Fmynull\"']\n```\n\n##### Imports\n\nImports are overridable by the user. This can be used in conjunction with\nreplacing the templates for extreme cases. Typically this should be avoided.\n\nNote that specifying any section of the imports completely overwrites that\nsection. It's also true that the driver can still specify imports and those\nwill be merged in to what is provided here.\n\n```toml\n[imports.all]\n  standard = ['\"context\"']\n  third_party = ['\"github.com\u002Fmy\u002Fpackage\"']\n\n# Changes imports for the boil_queries file\n[imports.singleton.\"boil_queries\"]\n  standard = ['\"context\"']\n  third_party = ['\"github.com\u002Fmy\u002Fpackage\"']\n\n# Same syntax as all\n[imports.test]\n\n# Same syntax as singleton\n[imports.test_singleton]\n\n# Changes imports when a model contains null.Int32\n[imports.based_on_type.string]\n  standard = ['\"context\"']\n  third_party = ['\"github.com\u002Fmy\u002Fpackage\"']\n```\n\nWhen defining maps it's possible to use an alternative syntax since\nviper automatically lowercases all configuration keys (same as aliases).\n\n```toml\n[[imports.singleton]]\n  name = \"boil_queries\"\n  third_party = ['\"github.com\u002Fmy\u002Fpackage\"']\n\n[[imports.based_on_type]]\n  name = \"null.Int64\"\n  third_party = ['\"github.com\u002Fmy\u002Fint64\"']\n```\n\n##### Templates\n\nIn advanced scenarios it may be desirable to generate additional files that are not go code.\nYou can accomplish this by using the `--templates` flag to specify **all** the directories you\nwish to generate code for. With this flag you specify root directories, that is top-level container\ndirectories.\n\nIf root directories have a `_test` suffix in the name, this folder is considered a folder\nfull of templates for testing only and will be omitted when `--no-tests` is specified and\nits templates will be generated into files with a `_test` suffix.\n\nEach root directory is recursively walked. Each template found will be merged into table_name.ext\nwhere ext is defined by the shared extension of the templates. The directory structure is preserved\nwith the exception of singletons.\n\nFor files that should not be generated for each model, you can use a `singleton` directory inside\nthe directory where the singleton file should be generated. This will make sure that the file is\nonly generated once.\n\nHere's an example:\n\n```text\ntemplates\u002F\n├── 00_struct.go.tpl               # Merged into output_dir\u002Ftable_name.go\n├── 00_struct.js.tpl               # Merged into output_dir\u002Ftable_name.js\n├── singleton\n│   └── boil_queries.go.tpl        # Rendered as output_dir\u002Fboil_queries.go\n└── js\n    ├── jsmodel.js.tpl             # Merged into output_dir\u002Fjs\u002Ftable_name.js\n    └── singleton\n        └── jssingle.js.tpl        # Merged into output_dir\u002Fjs\u002Fjssingle.js\n```\n\nThe output files of which would be:\n\n```\noutput_dir\u002F\n├── boil_queries.go\n├── table_name.go\n├── table_name.js\n└── js\n    ├── table_name.js\n    └── jssingle.js\n```\n\n**Note**: Because the `--templates` flag overrides the embedded templates of `sqlboiler`, if you still\nwish to generate the default templates it's recommended that you include the path to sqlboiler's templates\nas well.\n\n```toml\ntemplates = [\n  \"\u002Fpath\u002Fto\u002Fsqlboiler\u002Ftemplates\",\n  \"\u002Fpath\u002Fto\u002Fsqlboiler\u002Ftemplates_test\",\n  \"\u002Fpath\u002Fto\u002Fyour_project\u002Fmore_templates\"\n]\n```\n\n#### Extending generated models\n\nThere will probably come a time when you want to extend the generated models\nwith some kinds of helper functions. A general guideline is to put your\nextension functions into a separate package so that your functions aren't\naccidentally deleted when regenerating. Past that there are 3 main ways to\nextend the models, the first way is the most desirable:\n\n**Method 1: Simple Functions**\n\n```go\n\u002F\u002F Package modext is for SQLBoiler helper methods\npackage modext\n\n\u002F\u002F UserFirstTimeSetup is an extension of the user model.\nfunc UserFirstTimeSetup(ctx context.Context, db *sql.DB, u *models.User) error { ... }\n```\n\nCode organization is accomplished by using multiple files, and everything\nis passed as a parameter so these kinds of methods are very easy to test.\n\nCalling code is also very straightforward:\n\n```go\nuser, err := Users().One(ctx, db)\n\u002F\u002F elided error check\n\nerr = modext.UserFirstTimeSetup(ctx, db, user)\n\u002F\u002F elided error check\n```\n\n**Method 2: Empty struct methods**\n\nThe above is the best way to code extensions for SQLBoiler, however there may\nbe times when the number of methods grows too large and code completion is\nnot as helpful anymore. In these cases you may consider structuring the code\nlike this:\n\n```go\n\u002F\u002F Package modext is for SQLBoiler helper methods\npackage modext\n\ntype users struct {}\n\nvar Users = users{}\n\n\u002F\u002F FirstTimeSetup is an extension of the user model.\nfunc (users) FirstTimeSetup(ctx context.Context, db *sql.DB, u *models.User) error { ... }\n```\n\nCalling code then looks a little bit different:\n\n```go\nuser, err := Users().One(ctx, db)\n\u002F\u002F elided error check\n\nerr = modext.Users.FirstTimeSetup(ctx, db, user)\n\u002F\u002F elided error check\n```\n\nThis is almost identical to the method above, but gives slight amounts more\norganization at virtually no cost at runtime. It is however not as desirable\nas the first method since it does have some runtime cost and doesn't offer that\nmuch benefit over it.\n\n**Method 3: Embedding**\n\nThis pattern is not for the faint of heart, what it provides in benefits it\nmore than makes up for in downsides. It's possible to embed the SQLBoiler\nstructs inside your own to enhance them. However it's subject to easy breakages\nand a dependency on these additional objects. It can also introduce\ninconsistencies as some objects may have no extended functionality and therefore\nhave no reason to be embedded so you either have to have a struct for each\ngenerated struct even if it's empty, or have inconsistencies, some places where\nyou use the enhanced model, and some where you do not.\n\n```go\nuser, err := Users().One(ctx, db)\n\u002F\u002F elided error check\n\nenhUser := modext.User{user}\nerr = ehnUser.FirstTimeSetup(ctx, db)\n\u002F\u002F elided error check\n```\n\nI don't recommend this pattern, but included it so that people know it's an\noption and also know the problems with it.\n\n## Diagnosing Problems\n\nThe most common causes of problems and panics are:\n\n- Forgetting to exclude tables you do not want included in your generation, like migration tables.\n- Tables without a primary key. All tables require one.\n- Forgetting to put foreign key constraints on your columns that reference other tables.\n- The compatibility tests require privileges to create a database for testing purposes, ensure the user\n  supplied in your `sqlboiler.toml` config has adequate privileges.\n- A nil or closed database handle. Ensure your passed in `boil.Executor` is not nil.\n  - If you decide to use the `G` variant of functions instead, make sure you've initialized your\n    global database handle using `boil.SetDB()`.\n- Naming collisions, if the code fails to compile because there are naming collisions, look at the\n  [aliasing](#aliases) feature.\n- Race conditions in tests or when using global variable models and using\n  relationship set helpers in multiple goroutines. Note that Set\u002FAdd\u002FRemove\n  relationship helpers modify their input parameters to maintain parity between\n  the `.R` struct relationships and the database foreign keys but this can\n  produce subtle race conditions. Test for this using the `-race` flag on the\n  go tool.\n- A field not being inserted (usually a default true boolean), `boil.Infer` looks at the zero\n  value of your Go type (it doesn't care what the default value in the database is) to determine\n  if it should insert your field or not. In the case of a default true boolean value, when you\n  want to set it to false; you set that in the struct but that's the zero value for the bool\n  field in Go so sqlboiler assumes you do not want to insert that field and you want the default\n  value from the database. Use a whitelist\u002Fgreylist to add that field to the list of fields\n  to insert.\n- decimal library showing errors like: `pq: encode: unknown type types.NullDecimal`\n  is a result of a too-new and broken version of the github.com\u002Fericlargergren\u002Fdecimal\n  package, use the following version in your go.mod:\n  github.com\u002Fericlagergren\u002Fdecimal v0.0.0-20181231230500-73749d4874d5\n\nFor errors with other causes, it may be simple to debug yourself by looking at the generated code.\nSetting `boil.DebugMode` to `true` can help with this. You can change the output using `boil.DebugWriter` (defaults to `os.Stdout`).\n\nIf you're still stuck and\u002For you think you've found a bug, feel free to leave an issue and we'll do our best to help you.\n\n## Features & Examples\n\nMost examples in this section will be demonstrated using the following Postgres schema, structs and variables:\n\n```sql\nCREATE TABLE pilots (\n  id integer NOT NULL,\n  name text NOT NULL\n);\n\nALTER TABLE pilots ADD CONSTRAINT pilot_pkey PRIMARY KEY (id);\n\nCREATE TABLE jets (\n  id integer NOT NULL,\n  pilot_id integer NOT NULL,\n  age integer NOT NULL,\n  name text NOT NULL,\n  color text NOT NULL\n);\n\nALTER TABLE jets ADD CONSTRAINT jet_pkey PRIMARY KEY (id);\nALTER TABLE jets ADD CONSTRAINT jet_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id);\n\nCREATE TABLE languages (\n  id integer NOT NULL,\n  language text NOT NULL\n);\n\nALTER TABLE languages ADD CONSTRAINT language_pkey PRIMARY KEY (id);\n\n-- Join table\nCREATE TABLE pilot_languages (\n  pilot_id integer NOT NULL,\n  language_id integer NOT NULL\n);\n\n-- Composite primary key\nALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pkey PRIMARY KEY (pilot_id, language_id);\nALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_pilots_fkey FOREIGN KEY (pilot_id) REFERENCES pilots(id);\nALTER TABLE pilot_languages ADD CONSTRAINT pilot_language_languages_fkey FOREIGN KEY (language_id) REFERENCES languages(id);\n```\n\nThe generated model structs for this schema look like the following. Note that we've included the relationship\nstructs as well so you can see how it all pieces together:\n\n```go\ntype Pilot struct {\n  ID   int    `boil:\"id\" json:\"id\" toml:\"id\" yaml:\"id\"`\n  Name string `boil:\"name\" json:\"name\" toml:\"name\" yaml:\"name\"`\n\n  R *pilotR `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n  L pilotR  `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n}\n\ntype pilotR struct {\n  Languages LanguageSlice\n  Jets      JetSlice\n}\n\ntype Jet struct {\n  ID      int    `boil:\"id\" json:\"id\" toml:\"id\" yaml:\"id\"`\n  PilotID int    `boil:\"pilot_id\" json:\"pilot_id\" toml:\"pilot_id\" yaml:\"pilot_id\"`\n  Age     int    `boil:\"age\" json:\"age\" toml:\"age\" yaml:\"age\"`\n  Name    string `boil:\"name\" json:\"name\" toml:\"name\" yaml:\"name\"`\n  Color   string `boil:\"color\" json:\"color\" toml:\"color\" yaml:\"color\"`\n\n  R *jetR `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n  L jetR  `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n}\n\ntype jetR struct {\n  Pilot *Pilot\n}\n\ntype Language struct {\n  ID       int    `boil:\"id\" json:\"id\" toml:\"id\" yaml:\"id\"`\n  Language string `boil:\"language\" json:\"language\" toml:\"language\" yaml:\"language\"`\n\n  R *languageR `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n  L languageR  `boil:\"-\" json:\"-\" toml:\"-\" yaml:\"-\"`\n}\n\ntype languageR struct {\n  Pilots PilotSlice\n}\n```\n\n```go\n\u002F\u002F Open handle to database like normal\ndb, err := sql.Open(\"postgres\", \"dbname=fun user=abc\")\nif err != nil {\n  return err\n}\n```\n\n### Automatic CreatedAt\u002FUpdatedAt\n\nIf your generated SQLBoiler models package can find columns with the\nnames `created_at` or `updated_at` it will automatically set them\nto `time.Now()` in your database, and update your object appropriately.\nTo disable this feature use `--no-auto-timestamps`.\n\nNote: You can set the timezone for this feature by calling `boil.SetLocation()`\n\n#### Customizing the timestamp columns\n\nSet the `auto-columns` map in your configuration file\n\n```toml\n[auto-columns]\n    created = \"createdAt\"\n    updated = \"updatedAt\"\n```\n\n#### Skipping Automatic Timestamps\n\nIf for a given query you do not want timestamp columns to be re-computed prior\nto an insert or update then you can use `boil.SkipTimestamps` on the context you\npass in to the query to prevent them from being updated.\n\nKeep in mind this has no effect on whether or not the column is included in the\ninsert\u002Fupdate, it simply stops them from being set to `time.Now()` in the struct\nbefore being sent to the database (if they were going to be sent).\n\n#### Overriding Automatic Timestamps\n\n- **Insert**\n  - Timestamps for both `updated_at` and `created_at` that are zero values will be set automatically.\n  - To set the timestamp to null, set `Valid` to false and `Time` to a non-zero value.\n    This is somewhat of a work around until we can devise a better solution in a later version.\n- **Update**\n  - The `updated_at` column will always be set to `time.Now()`. If you need to override\n    this value you will need to fall back to another method in the meantime: `queries.Raw()`,\n    overriding `updated_at` in all of your objects using a hook, or create your own wrapper.\n- **Upsert**\n  - `created_at` will be set automatically if it is a zero value, otherwise your supplied value\n    will be used. To set `created_at` to `null`, set `Valid` to false and `Time` to a non-zero value.\n  - The `updated_at` column will always be set to `time.Now()`.\n\n### Automatic DeletedAt (Soft Delete)\n\nSoft deletes are a way of deleting records in a database for the average query\nwithout actually removing the data. This type of thing is important in certain\nscenarios where data retention is important. It is typically done by adding a\n`deleted` bool or a `deleted_at` timestamp to each table in the database\nthat can be soft deleted and subsequent queries on that table should always\nmake sure that `deleted != true` or `deleted_at is null` to prevent showing\n\"deleted\" data.\n\nSQLBoiler uses the `deleted_at` variant to provide this functionality. If your\ntable has a nullable timestamp field named `deleted_at` it will be a candidate\nfor soft-deletion.\n\n_NOTE_: As of writing soft-delete is opt-in via `--add-soft-deletes` and is\nliable to change in future versions.\n\n_NOTE_: There is a query mod to bypass soft delete for a specific query by using\n`qm.WithDeleted`, note that there is no way to do this for Exists\u002FFind helpers\nyet.\n\n_NOTE_: The `Delete` helpers will _not_ set `updated_at` currently. The current\nphilosophy is that deleting the object is simply metadata and since it returns\nin no queries (other than raw ones) the updated_at will no longer be relevant.\nThis could change in future versions if people disagree with this but it is\nthe current behavior.\n\n### Query Building\n\nWe generate \"Starter\" methods for you. These methods are named as the plural versions of your model,\nfor example: `models.Jets()`. Starter methods are used to build queries using our\n[Query Mod System](#query-mod-system). They take a slice of [Query Mods](#query-mod-system)\nas parameters, and end with a call to a [Finisher](#finishers) method.\n\nHere are a few examples:\n\n```go\n\u002F\u002F SELECT COUNT(*) FROM pilots;\ncount, err := models.Pilots().Count(ctx, db)\n\n\u002F\u002F SELECT * FROM \"pilots\" LIMIT 5;\npilots, err := models.Pilots(qm.Limit(5)).All(ctx, db)\n\n\u002F\u002F DELETE FROM \"pilots\" WHERE \"id\"=$1;\nerr := models.Pilots(qm.Where(\"id=?\", 1)).DeleteAll(ctx, db)\n\u002F\u002F type safe version of above\nerr := models.Pilots(models.PilotWhere.ID.EQ(1)).DeleteAll(ctx, db)\n```\n\nIn the event that you would like to build a query and specify the table yourself, you\ncan do so using `models.NewQuery()`:\n\n```go\n\u002F\u002F Select all rows from the pilots table by using the From query mod.\nerr := models.NewQuery(db, qm.From(\"pilots\")).All(ctx, db)\n```\n\nAs you can see, [Query Mods](#query-mod-system) allow you to modify your\nqueries, and [Finishers](#finishers) allow you to execute the final action.\n\nWe also generate query building helper methods for your relationships as well. Take a look at our\n[Relationships Query Building](#relationships) section for some additional query building information.\n\n### Query Mod System\n\nThe query mod system allows you to modify queries created with\n[Starter](#query-building) methods when performing query building.\nSee examples below.\n\n**NOTE:** SQLBoiler generates type-safe identifiers based on your database\ntables, columns and relationships. Using these is a bit more verbose, but is\nespecially safe since when the names change in the database the generated\ncode will be different causing compilation failures instead of runtime\nerrors. It is highly recommended you use these instead of regular strings.\nSee [Constants](#constants) for more details.\n\n**NOTE:** You will notice that there is printf used below mixed with SQL\nstatements. This is normally NOT OK if the user is able to supply any of\nthe sql string, but here we always use a `?` placeholder and pass arguments\nso that the only thing that's being printf'd are constants which makes it\nsafe, but be careful!\n\n```go\n\u002F\u002F Dot import so we can access query mods directly instead of prefixing with \"qm.\"\nimport . \"github.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fqueries\u002Fqm\"\n\n\u002F\u002F Use a raw query against a generated struct (Pilot in this example)\n\u002F\u002F If this query mod exists in your call, it will override the others.\n\u002F\u002F \"?\" placeholders are not supported here, use \"$1, $2\" etc.\nSQL(\"select * from pilots where id=$1\", 10)\nmodels.Pilots(SQL(\"select * from pilots where id=$1\", 10)).All()\n\nSelect(\"id\", \"name\") \u002F\u002F Select specific columns.\nSelect(models.PilotColumns.ID, models.PilotColumns.Name)\nFrom(\"pilots as p\") \u002F\u002F Specify the FROM table manually, can be useful for doing complex queries.\nFrom(models.TableNames.Pilots + \" as p\")\n\n\u002F\u002F WHERE clause building\nWhere(\"name=?\", \"John\")\nmodels.PilotWhere.Name.EQ(\"John\")\nAnd(\"age=?\", 24)\n\u002F\u002F No equivalent type safe query yet\nOr(\"height=?\", 183)\n\u002F\u002F No equivalent type safe query yet\n\nWhere(\"(name=? and age=?) or (age=?)\", \"John\", 5, 6)\n\u002F\u002F Expr allows manual grouping of statements\nWhere(\n  Expr(\n    models.PilotWhere.Name.EQ(\"John\"),\n    Or2(models.PilotWhere.Age.EQ(5)),\n  ),\n  Or2(models.PilotAge),\n)\n\n\u002F\u002F WHERE IN clause building\nWhereIn(\"(name, age) in ?\", \"John\", 24, \"Tim\", 33) \u002F\u002F Generates: WHERE (\"name\",\"age\") IN (($1,$2),($3,$4))\nWhereIn(fmt.Sprintf(\"(%s, %s) in ?\", models.PilotColumns.Name, models.PilotColumns.Age), \"John\", 24, \"Tim\", 33)\nAndIn(\"weight in ?\", 84)\nAndIn(models.PilotColumns.Weight + \" in ?\", 84)\nOrIn(\"height in ?\", 183, 177, 204)\nOrIn(models.PilotColumns.Height + \" in ?\", 183, 177, 204)\n\nInnerJoin(\"pilots p on jets.pilot_id=?\", 10)\nInnerJoin(models.TableNames.Pilots + \" p on \" + models.TableNames.Jets + \".\" + models.JetColumns.PilotID + \"=?\", 10)\n\nGroupBy(\"name\")\nGroupBy(\"name like ? DESC, name\", \"John\")\nGroupBy(models.PilotColumns.Name)\nOrderBy(\"age, height\")\nOrderBy(models.PilotColumns.Age, models.PilotColumns.Height)\n\nHaving(\"count(jets) > 2\")\nHaving(fmt.Sprintf(\"count(%s) > 2\", models.TableNames.Jets)\n\nLimit(15)\nOffset(5)\n\n\u002F\u002F Explicit locking\nFor(\"update nowait\")\n\n\u002F\u002F Common Table Expressions\nWith(\"cte_0 AS (SELECT * FROM table_0 WHERE thing=$1 AND stuff=$2)\")\n\n\u002F\u002F Eager Loading -- Load takes the relationship name, ie the struct field name of the\n\u002F\u002F Relationship struct field you want to load. Optionally also takes query mods to filter on that query.\nLoad(\"Languages\", Where(...)) \u002F\u002F If it's a ToOne relationship it's in singular form, ToMany is plural.\nLoad(models.PilotRels.Languages, Where(...))\n```\n\nNote: We don't force you to break queries apart like this if you don't want to, the following\nis also valid and supported by query mods that take a clause:\n\n```go\nWhere(\"(name=? OR age=?) AND height=?\", \"John\", 24, 183)\n```\n\n### Function Variations\n\nFunctions can have variations generated for them by using the flags\n`--add-global-variants` and `--add-panic-variants`. Once you've used these\nflags or set the appropriate values in your configuration file extra method\noverloads will be generated. We've used the `Delete` method to demonstrate:\n\n```go\n\u002F\u002F Set the global db handle for G method variants.\nboil.SetDB(db)\n\npilot, _ := models.FindPilot(ctx, db, 1)\n\nerr := pilot.Delete(ctx, db) \u002F\u002F Regular variant, takes a db handle (boil.Executor interface).\npilot.DeleteP(ctx, db)       \u002F\u002F Panic variant, takes a db handle and panics on error.\nerr := pilot.DeleteG(ctx)    \u002F\u002F Global variant, uses the globally set db handle (boil.SetDB()).\npilot.DeleteGP(ctx)          \u002F\u002F Global&Panic variant, combines the global db handle and panic on error.\n\ndb.Begin()                   \u002F\u002F Normal sql package way of creating a transaction\nboil.BeginTx(ctx, nil)       \u002F\u002F Uses the global database handle set by boil.SetDB() (doesn't require flag)\n```\n\nNote that it's slightly different for query building.\n\n### Finishers\n\nHere are a list of all of the finishers that can be used in combination with\n[Query Building](#query-building).\n\nFinishers all have `P` (panic) [method variations](#function-variations). To specify\nyour db handle use the `G` or regular variation of the [Starter](#query-building) method.\n\n```go\n\u002F\u002F These are called like the following:\nmodels.Pilots().All(ctx, db)\n\nOne() \u002F\u002F Retrieve one row as object (same as LIMIT(1))\nAll() \u002F\u002F Retrieve all rows as objects (same as SELECT * FROM)\nCount() \u002F\u002F Number of rows (same as COUNT(*))\nUpdateAll(models.M{\"name\": \"John\", \"age\": 23}) \u002F\u002F Update all rows matching the built query.\nDeleteAll() \u002F\u002F Delete all rows matching the built query.\nExists() \u002F\u002F Returns a bool indicating whether the row(s) for the built query exists.\nBind(&myObj) \u002F\u002F Bind the results of a query to your own struct object.\nExec() \u002F\u002F Execute an SQL query that does not require any rows returned.\nQueryRow() \u002F\u002F Execute an SQL query expected to return only a single row.\nQuery() \u002F\u002F Execute an SQL query expected to return multiple rows.\n```\n\n### Raw Query\n\nWe provide `queries.Raw()` for executing raw queries. Generally you will want to use `Bind()` with\nthis, like the following:\n\n```go\nerr := queries.Raw(\"select * from pilots where id=$1\", 5).Bind(ctx, db, &obj)\n```\n\nYou can use your own structs or a generated struct as a parameter to Bind. Bind supports both\na single object for single row queries and a slice of objects for multiple row queries.\n\n`queries.Raw()` also has a method that can execute a query without binding to an object, if required.\n\nYou also have `models.NewQuery()` at your disposal if you would still like to use [Query Building](#query-building)\nin combination with your own custom, non-generated model.\n\n### Binding\n\nFor a comprehensive ruleset for `Bind()` you can refer to our [pkg.go.dev](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fqueries#Bind).\n\nThe `Bind()` [Finisher](#finisher) allows the results of a query built with\nthe [Raw SQL](#raw-query) method or the [Query Builder](#query-building) methods to be bound\nto your generated struct objects, or your own custom struct objects.\n\nThis can be useful for complex queries, queries that only require a small subset of data\nand have no need for the rest of the object variables, or custom join struct objects like\nthe following:\n\n```go\n\u002F\u002F Custom struct using two generated structs\ntype PilotAndJet struct {\n  models.Pilot `boil:\",bind\"`\n  models.Jet   `boil:\",bind\"`\n}\n\nvar paj PilotAndJet\n\u002F\u002F Use a raw query\nerr := queries.Raw(`\n  select pilots.id as \"pilots.id\", pilots.name as \"pilots.name\",\n  jets.id as \"jets.id\", jets.pilot_id as \"jets.pilot_id\",\n  jets.age as \"jets.age\", jets.name as \"jets.name\", jets.color as \"jets.color\"\n  from pilots inner join jets on jets.pilot_id=?`, 23,\n).Bind(ctx, db, &paj)\n\n\u002F\u002F Use query building\nerr := models.NewQuery(\n  Select(\"pilots.id\", \"pilots.name\", \"jets.id\", \"jets.pilot_id\", \"jets.age\", \"jets.name\", \"jets.color\"),\n  From(\"pilots\"),\n  InnerJoin(\"jets on jets.pilot_id = pilots.id\"),\n).Bind(ctx, db, &paj)\n```\n\n```go\n\u002F\u002F Custom struct for selecting a subset of data\ntype JetInfo struct {\n  AgeSum int `boil:\"age_sum\"`\n  Count int `boil:\"juicy_count\"`\n}\n\nvar info JetInfo\n\n\u002F\u002F Use query building\nerr := models.NewQuery(Select(\"sum(age) as age_sum\", \"count(*) as juicy_count\", From(\"jets\"))).Bind(ctx, db, &info)\n\n\u002F\u002F Use a raw query\nerr := queries.Raw(`select sum(age) as \"age_sum\", count(*) as \"juicy_count\" from jets`).Bind(ctx, db, &info)\n```\n\nWe support the following struct tag modes for `Bind()` control:\n\n```go\ntype CoolObject struct {\n  \u002F\u002F Don't specify a name, Bind will TitleCase the column\n  \u002F\u002F name, and try to match against this.\n  Frog int\n\n  \u002F\u002F Specify an alternative name for the column, it will\n  \u002F\u002F be titlecased for matching, can be whatever you like.\n  Cat int  `boil:\"kitten\"`\n\n  \u002F\u002F Ignore this struct field, do not attempt to bind it.\n  Pig int  `boil:\"-\"`\n\n  \u002F\u002F Instead of binding to this as a regular struct field\n  \u002F\u002F (like other sql-able structs eg. time.Time)\n  \u002F\u002F Recursively search inside the Dog struct for field names from the query.\n  Dog      `boil:\",bind\"`\n\n  \u002F\u002F Same as the above, except specify a different table name\n  Mouse    `boil:\"rodent,bind\"`\n\n  \u002F\u002F Ignore this struct field, do not attempt to bind it.\n  Bird     `boil:\"-\"`\n}\n```\n\n### Relationships\n\nHelper methods will be generated for every to one and to many relationship structure\nyou have defined in your database by using foreign keys.\n\nWe attach these helpers directly to your model struct, for example:\n\n```go\njet, _ := models.FindJet(ctx, db, 1)\n\n\u002F\u002F \"to one\" relationship helper method.\n\u002F\u002F This will retrieve the pilot for the jet.\npilot, err := jet.Pilot().One(ctx, db)\n\n\u002F\u002F \"to many\" relationship helper method.\n\u002F\u002F This will retrieve all languages for the pilot.\nlanguages, err := pilot.Languages().All(ctx, db)\n```\n\nIf your relationship involves a join table SQLBoiler will figure it out for you transparently.\n\nIt is important to note that you should use `Eager Loading` if you plan\non loading large collections of rows, to avoid N+1 performance problems.\n\nFor example, take the following:\n\n```go\n\u002F\u002F Avoid this loop query pattern, it is slow.\njets, _ := models.Jets().All(ctx, db)\npilots := make([]models.Pilot, len(jets))\nfor i := 0; i \u003C len(jets); i++ {\n  pilots[i] = jets[i].Pilot().OneP(ctx, db)\n}\n\n\u002F\u002F Instead, use Eager Loading!\njets, _ := models.Jets(Load(\"Pilot\")).All(ctx, db)\n\u002F\u002F Type safe relationship names exist too:\njets, _ := models.Jets(Load(models.JetRels.Pilot)).All(ctx, db)\n\n\u002F\u002F Then access the loaded structs using the special Relation field\nfor _, j := range jets {\n  _ = j.R.Pilot\n}\n```\n\nEager loading can be combined with other query mods, and it can also eager load recursively.\n\n```go\n\u002F\u002F Example of a nested load.\n\u002F\u002F Each jet will have its pilot loaded, and each pilot will have its languages loaded.\njets, _ := models.Jets(Load(\"Pilot.Languages\")).All(ctx, db)\n\u002F\u002F Note that each level of a nested Load call will be loaded. No need to call Load() multiple times.\n\n\u002F\u002F Type safe queries exist for this too!\njets, _ := models.Jets(Load(Rels(models.JetRels.Pilot, models.PilotRels.Languages))).All(ctx, db)\n\n\u002F\u002F A larger example. In the below scenario, Pets will only be queried one time, despite\n\u002F\u002F showing up twice because they're the same query (the user's pets)\nusers, _ := models.Users(\n  Load(\"Pets.Vets\"),\n  \u002F\u002F the query mods passed in below only affect the query for Toys\n  \u002F\u002F to use query mods against Pets itself, you must declare it separately\n  Load(\"Pets.Toys\", Where(\"toys.deleted = ?\", isDeleted)),\n  Load(\"Property\"),\n  Where(\"age > ?\", 23),\n).All(ctx, db)\n```\n\nWe provide the following methods for managing relationships on objects:\n\n**To One**\n\n- `SetX()`: Set the foreign key to point to something else: jet.SetPilot(...)\n- `RemoveX()`: Null out the foreign key, effectively removing the relationship between these two objects: jet.RemovePilot(...)\n\n**To Many**\n\n- `AddX()`: Add more relationships to the existing set of related Xs: pilot.AddLanguages(...)\n- `SetX()`: Remove all existing relationships, and replace them with the provided set: pilot.SetLanguages(...)\n- `RemoveX()`: Remove all provided relationships: pilot.RemoveLanguages(...)\n\n**Important**: Remember to use transactions around these set helpers for performance\nand data integrity. SQLBoiler does not do this automatically due to it's transparent API which allows\nyou to batch any number of calls in a transaction without spawning subtransactions you don't know\nabout or are not supported by your database.\n\n**To One** code examples:\n\n```go\n  jet, _ := models.FindJet(ctx, db, 1)\n  pilot, _ := models.FindPilot(ctx, db, 1)\n\n  \u002F\u002F Set the pilot to an existing jet\n  err := jet.SetPilot(ctx, db, false, &pilot)\n\n  pilot = models.Pilot{\n    Name: \"Erlich\",\n  }\n\n  \u002F\u002F Insert the pilot into the database and assign it to a jet\n  err := jet.SetPilot(ctx, db, true, &pilot)\n\n  \u002F\u002F Remove a relationship. This method only exists for foreign keys that can be NULL.\n  err := jet.RemovePilot(ctx, db, &pilot)\n```\n\n**To Many** code examples:\n\n```go\n  pilots, _ := models.Pilots().All(ctx, db)\n  languages, _ := models.Languages().All(ctx, db)\n\n  \u002F\u002F Set a group of language relationships\n  err := pilots.SetLanguages(db, false, &languages)\n\n  languages := []*models.Language{\n    {Language: \"Strayan\"},\n    {Language: \"Yupik\"},\n    {Language: \"Pawnee\"},\n  }\n\n  \u002F\u002F Insert new a group of languages and assign them to a pilot\n  err := pilots.SetLanguages(ctx, db, true, languages...)\n\n  \u002F\u002F Add another language relationship to the existing set of relationships\n  err := pilots.AddLanguages(ctx, db, false, &someOtherLanguage)\n\n  anotherLanguage := models.Language{Language: \"Archi\"}\n\n  \u002F\u002F Insert and then add another language relationship\n  err := pilots.AddLanguages(ctx, db, true, &anotherLanguage)\n\n  \u002F\u002F Remove a group of relationships\n  err := pilots.RemoveLanguages(ctx, db, languages...)\n```\n\n### Hooks\n\nBefore and After hooks are available for most operations. If you don't need them you can\nshrink the size of the generated code by disabling them with the `--no-hooks` flag.\n\nEvery generated package that includes hooks has the following `HookPoints` defined:\n\n```go\nconst (\n  BeforeInsertHook HookPoint = iota + 1\n  BeforeUpdateHook\n  BeforeDeleteHook\n  BeforeUpsertHook\n  AfterInsertHook\n  AfterSelectHook\n  AfterUpdateHook\n  AfterDeleteHook\n  AfterUpsertHook\n)\n```\n\nTo register a hook for your model you will need to create the hook function, and attach\nit with the `AddModelHook` method. Here is an example of a before insert hook:\n\n```go\n\u002F\u002F Define my hook function\nfunc myHook(ctx context.Context, exec boil.ContextExecutor, p *Pilot) error {\n  \u002F\u002F Do stuff\n  return nil\n}\n\n\u002F\u002F Register my before insert hook for pilots\nmodels.AddPilotHook(boil.BeforeInsertHook, myHook)\n```\n\nYour `ModelHook` will always be defined as `func(context.Context, boil.ContextExecutor, *Model) error` if context is not turned off.\n\n#### Skipping Hooks\n\nYou can skip hooks by using the `boil.SkipHooks` on the context you pass in\nto a given query.\n\n### Transactions\n\nThe `boil.Executor` and `boil.ContextExecutor` interface powers all of SQLBoiler. This means\nanything that conforms to the three `Exec\u002FQuery\u002FQueryRow` methods (and their context-aware variants)\ncan be used to execute queries. `sql.DB`, `sql.Tx` as well as other\nlibraries (`sqlx`) conform to this interface, and therefore any of these things may be\nused as an executor for any query in the system. This makes using transactions very simple:\n\n```go\ntx, err := db.BeginTx(ctx, nil)\nif err != nil {\n  return err\n}\n\nusers, _ := models.Pilots().All(ctx, tx)\nusers.DeleteAll(ctx, tx)\n\n\u002F\u002F Rollback or commit\ntx.Commit()\ntx.Rollback()\n```\n\nIt's also worth noting that there's a way to take advantage of `boil.SetDB()`\nby using the\n[boil.BeginTx()](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Faarondl\u002Fsqlboiler\u002Fv4\u002Fboil#BeginTx)\nfunction. This opens a transaction using the globally stored database.\n\n### Debug Logging\n\nDebug logging will print your generated SQL statement and the arguments it is using.\nDebug logging can be toggled on globally by setting the following global variable to `true`:\n\n```go\nboil.DebugMode = true\n\n\u002F\u002F Optionally set the writer as well. Defaults to os.Stdout\nfh, _ := os.Open(\"debug.txt\")\nboil.DebugWriter = fh\n```\n\nNote: Debug output is messy at the moment. This is something we would like addressed.\n\n### Select\n\nSelect is done through [Query Building](#query-building) and [Find](#find). Here's a short example:\n\n```go\n\u002F\u002F Select one pilot\npilot, err := models.Pilots(qm.Where(\"name=?\", \"Tim\")).One(ctx, db)\n\u002F\u002F Type safe variant\npilot, err := models.Pilots(models.PilotWhere.Name.EQ(\"Tim\")).One(ctx, db)\n\n\u002F\u002F Select specific columns of many jets\njets, err := models.Jets(qm.Select(\"age\", \"name\")).All(ctx, db)\n\u002F\u002F Type safe variant\njets, err := models.Jets(qm.Select(models.JetColumns.Age, models.JetColumns.Name)).All(ctx, db)\n```\n\n### Find\n\nFind is used to find a single row by primary key:\n\n```go\n\u002F\u002F Retrieve pilot with all columns filled\npilot, err := models.FindPilot(ctx, db, 1)\n\n\u002F\u002F Retrieve a subset of column values\njet, err := models.FindJet(ctx, db, 1, \"name\", \"color\")\n```\n\n### Insert\n\nThe main thing to be aware of with `Insert` is how the `columns` argument\noperates. You can supply one of the following column lists:\n`boil.Infer`, `boil.Whitelist`, `boil.Blacklist`, or `boil.Greylist`.\n\nThese lists control what fields are inserted into the database, and what values\nare returned to your struct from the database (default, auto incrementing,\ntrigger-based columns are candidates for this). Your struct will have those\nvalues after the insert is complete.\n\nWhen you use inference `sqlboiler` looks at your Go struct field values and if\nthe field value is the Go zero value and that field has a default value in the\ndatabase it will not insert that field, instead it will get the value from the\ndataba","SQLBoiler 是一个根据数据库模式生成 Go 语言 ORM 的工具。它通过分析现有的数据库结构自动生成相应的 Go 代码，从而极大地减少了手动编写 SQL 语句的需求。支持多种数据库类型，包括 MySQL、PostgreSQL 和 SQLite3 等，并且强调使用普通结构体和函数调用来保持 Go 语言的风格特点。适用于需要快速开发基于现有数据库的应用场景，尤其是当开发者希望减少与数据库交互相关的冗余代码时。目前该项目处于维护模式，主要接受来自社区贡献的错误修复和版本兼容性调整。","2026-06-11 03:28:20","top_topic"]