{"id":13412167,"url":"https://github.com/go-jet/jet","last_synced_at":"2025-05-13T18:18:41.472Z","repository":{"id":38185274,"uuid":"173437670","full_name":"go-jet/jet","owner":"go-jet","description":"Type safe SQL builder with code generation and automatic query result data mapping","archived":false,"fork":false,"pushed_at":"2025-04-20T11:13:47.000Z","size":7080,"stargazers_count":3106,"open_issues_count":39,"forks_count":140,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-04-25T18:02:21.646Z","etag":null,"topics":["cockroachdb","code-completion","code-generator","codegenerator","database","datamapper","golang","mariadb","mysql","postgres","postgresql","sql","sql-builder","sql-queries","sql-query","sql-query-builder","sqlbuilder","sqlite","typesafe","typesafety"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-jet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-03-02T11:06:23.000Z","updated_at":"2025-04-25T10:51:23.000Z","dependencies_parsed_at":"2024-02-13T15:11:09.846Z","dependency_job_id":"2a9084bb-b2b8-4924-9bf5-442c2bf44658","html_url":"https://github.com/go-jet/jet","commit_stats":{"total_commits":577,"total_committers":36,"mean_commits":16.02777777777778,"dds":"0.20277296360485264","last_synced_commit":"6a0798eb06193b8833c7914fc09c257334520c52"},"previous_names":["sub0zero/go-sqlbuilder"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-jet%2Fjet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-jet%2Fjet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-jet%2Fjet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-jet%2Fjet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-jet","download_url":"https://codeload.github.com/go-jet/jet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254000895,"owners_count":21997444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cockroachdb","code-completion","code-generator","codegenerator","database","datamapper","golang","mariadb","mysql","postgres","postgresql","sql","sql-builder","sql-queries","sql-query","sql-query-builder","sqlbuilder","sqlite","typesafe","typesafety"],"created_at":"2024-07-30T20:01:21.708Z","updated_at":"2025-05-13T18:18:41.134Z","avatar_url":"https://github.com/go-jet.png","language":"Go","readme":"# Jet\n\n\u003cimg align=\"right\" width=\"175px\" src=\"https://github.com/go-jet/jet/wiki/image/mascot.png\"\u003e\n\n[![go-jet](https://circleci.com/gh/go-jet/jet.svg?style=svg)](https://app.circleci.com/pipelines/github/go-jet/jet?branch=master)\n[![codecov](https://codecov.io/gh/go-jet/jet/branch/master/graph/badge.svg)](https://codecov.io/gh/go-jet/jet)\n[![Go Report Card](https://goreportcard.com/badge/github.com/go-jet/jet)](https://goreportcard.com/report/github.com/go-jet/jet/v2)\n[![Documentation](https://godoc.org/github.com/go-jet/jet?status.svg)](http://godoc.org/github.com/go-jet/jet/v2)\n[![GitHub release](https://img.shields.io/github/release/go-jet/jet.svg)](https://github.com/go-jet/jet/releases)\n\nJet is a complete solution for efficient and high performance database access, combining a type-safe SQL builder with code generation\nand automatic query result mapping.\n\nJet currently supports the following database engines:\n\n* `PostgreSQL`\n* `MySQL`\n* `SQLite`\n\nThis list is not exclusive, as many other databases implement compatible wire protocols. For example, `CockroachDB` uses the\n`PostgreSQL` wire protocol, and `MariaDB` is based on the `MySQL` protocol. Both databases are tested and known to work with Jet.\n\nSupport for additional databases may be introduced in future releases.\n\n![jet](https://github.com/go-jet/jet/wiki/image/jet.png)  \nJet is the easiest, and the fastest way to write complex type-safe SQL queries as a Go code and map database query result\ninto complex object composition.\n\n\u003e [!Note]\n\u003e Jet is __not__ an ORM.\n\n## Contents\n- [Motivation](#motivation)\n- [Features](#features)\n- [Getting Started](#getting-started)\n    - [Prerequisites](#prerequisites)\n    - [Installation](#installation)\n    - [Quick Start](#quick-start)\n        - [Generate sql builder and model types](#generate-sql-builder-and-model-types)\n        - [Lets write some SQL queries in Go](#lets-write-some-sql-queries-in-go)\n        - [Execute query and store result](#execute-query-and-store-result)\n- [Benefits](#benefits)\n- [Dependencies](#dependencies)\n- [Versioning](#versioning)\n- [License](#license)\n- [Support the Project](#support-the-project)\n\n## Motivation\nhttps://medium.com/@go.jet/jet-5f3667efa0cc\n\n## Features\n1) Auto-generated type-safe SQL Builder. Statements supported:\n    * [SELECT](https://github.com/go-jet/jet/wiki/SELECT), [SELECT_JSON](https://github.com/go-jet/jet/wiki/SELECT_JSON-Statements) `(DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, LOCK_IN_SHARE_MODE, UNION, INTERSECT, EXCEPT, WINDOW, sub-queries)`\n    * [INSERT](https://github.com/go-jet/jet/wiki/INSERT) `(VALUES, MODEL, MODELS, QUERY, ON_CONFLICT/ON_DUPLICATE_KEY_UPDATE, RETURNING)`,\n    * [UPDATE](https://github.com/go-jet/jet/wiki/UPDATE) `(SET, MODEL, WHERE, RETURNING)`,\n    * [DELETE](https://github.com/go-jet/jet/wiki/DELETE) `(WHERE, ORDER_BY, LIMIT, RETURNING)`,\n    * [LOCK](https://github.com/go-jet/jet/wiki/LOCK) `(IN, NOWAIT)`, `(READ, WRITE)`\n    * [WITH](https://github.com/go-jet/jet/wiki/WITH)\n\n2) Auto-generated Data Model types - Go types mapped to database type (table, view or enum), used to store\n   result of database queries. Can be combined to create complex query result destination.\n3) Query execution with result mapping to arbitrary destination.\n\n## Getting Started\n\n### Prerequisites\n\nTo install Jet package, you need to install Go and set your Go workspace first.\n\n[Go](https://golang.org/) **version 1.22+ is required**\n\n### Installation\n\nUse the command bellow to add jet as a dependency into `go.mod` project:\n```sh\n$ go get -u github.com/go-jet/jet/v2\n```\n\nJet generator can be installed using one of the following methods:\n\n- ✅ Option 1: Install via go install:\n```sh\ngo install github.com/go-jet/jet/v2/cmd/jet@latest\n```\n\n\u003e [!Tip]\n\u003e Jet generator is installed to the directory named by the `GOBIN` environment variable,\nwhich defaults to `$GOPATH/bin` or `$HOME/go/bin` if the `GOPATH` environment variable is not set.\n\n- ✅ Option 2: Build manually from source and install jet generator to specific folder:\n```sh\ngit clone https://github.com/go-jet/jet.git\ncd jet \u0026\u0026 go build -o \u003ctarget_directory\u003e ./cmd/jet\n```\n\u003e [!Tip]\n\u003e Make sure `target_directory` is included in your system’s `PATH` environment variable to allow global access to the jet command.\n\n\n### Quick Start\nFor this quick start example we will use PostgreSQL sample _'dvd rental'_ database. Full database dump can be found in\n[./tests/testdata/init/postgres/dvds.sql](https://github.com/go-jet/jet-test-data/blob/master/init/postgres/dvds.sql).\nA schema diagram illustrating the relevant part of the database is available [here](./examples/quick-start/diagram.png).\n\n#### Generate SQL Builder and Model types\nTo generate jet SQL Builder and Data Model types from running postgres database, we need to call `jet` generator with postgres\nconnection parameters and destination folder path.\nAssuming we are running local postgres database, with user `user`, user password `pass`, database `jetdb` and\nschema `dvds` we will use this command:\n```sh\njet -dsn=postgresql://user:pass@localhost:5432/jetdb?sslmode=disable -schema=dvds -path=./.gen\n```\n```sh\nConnecting to postgres database: postgresql://user:pass@localhost:5432/jetdb?sslmode=disable \nRetrieving schema information...\n  FOUND 15 table(s), 7 view(s), 1 enum(s)\nCleaning up destination directory...\nGenerating table sql builder files...\nGenerating view sql builder files...\nGenerating enum sql builder files...\nGenerating table model files...\nGenerating view model files...\nGenerating enum model files...\nDone\n```\nProcedure is similar for MySQL, CockroachDB, MariaDB and SQLite. For example:\n```sh\njet -source=mysql -dsn=\"user:pass@tcp(localhost:3306)/dbname\" -path=./.gen\njet -dsn=postgres://user:pass@localhost:26257/jetdb?sslmode=disable -schema=dvds -path=./.gen  #cockroachdb\njet -dsn=\"mariadb://user:pass@tcp(localhost:3306)/dvds\" -path=./.gen              # source flag can be omitted if data source appears in dsn\njet -source=sqlite -dsn=\"/path/to/sqlite/database/file\" -schema=dvds -path=./.gen\njet -dsn=\"file:///path/to/sqlite/database/file\" -schema=dvds -path=./.gen         # sqlite database assumed for 'file' data sources\n```\n_*User has to have a permission to read information schema tables._\n\nAs indicated by the command output, Jet will perform the following actions:\n- ✅ Connect to the PostgreSQL database and retrieve metadata for all `tables`, `views`, and `enums` within the `dvds` schema.\n- ⚠️ **Delete all contents** in the target schema folder: `./.gen/jetdb/dvds`.\n- ⚙️ Generate **SQL Builder** and **Data Model** types for each table, view, and enum found in the schema.\n\nGenerated files folder structure will look like this:\n```sh \n|-- .gen                              # path\n|   -- jetdb                          # database name\n|       -- dvds                       # schema name\n|           |-- enum                  # sql builder package for enums\n|           |   |-- mpaa_rating.go\n|           |-- table                 # sql builder package for tables\n|               |-- actor.go\n|               |-- address.go\n|               |-- category.go\n|               ...\n|           |-- view                  # sql builder package for views\n|               |-- actor_info.go\n|               |-- film_list.go\n|               ...\n|           |-- model                 # data model types for each table, view and enum\n|           |   |-- actor.go\n|           |   |-- address.go\n|           |   |-- mpaa_rating.go\n|           |   ...\n```\n\nTypes from the `table`, `view`, and `enum` packages are used to write **type-safe SQL queries in Go**, while types from the `model` types are combined to store\nresults of the SQL queries.\n\n\u003e [!Note]\n\u003e It is possible to customize the default Jet generator behavior. All the aspects of generated SQLBuilder and model types \n\u003e are customizable(see [wiki](https://github.com/go-jet/jet/wiki/Generator#generator-customization)).\n\n\n#### Let's write some SQL queries in Go\n\nFirst we need to import postgres SQLBuilder and generated packages from the previous step:\n```go\nimport (\n  // dot import so go code would resemble as much as native SQL\n  // dot import is not mandatory\n  . \"github.com/go-jet/jet/v2/examples/quick-start/.gen/jetdb/dvds/table\"\n  . \"github.com/go-jet/jet/v2/postgres\"\n\n  \"github.com/go-jet/jet/v2/examples/quick-start/.gen/jetdb/dvds/enum\"\n  \"github.com/go-jet/jet/v2/examples/quick-start/.gen/jetdb/dvds/model\"  \n)\n```\nLet's say we want to retrieve the list of all _actors_ who acted in _films_ longer than 180 minutes, _film language_ is 'English', \n_film category_ is not 'Action' and _film rating_ is not 'R'.\n```golang\nstmt := SELECT(\n    Actor.ActorID, Actor.FirstName, Actor.LastName, Actor.LastUpdate,  // or just Actor.AllColumns\n    Film.AllColumns,                                                  \n    Language.AllColumns.Except(Language.LastUpdate),  // all language columns except last_update \n    Category.AllColumns,\n).FROM(\n    Actor.\n        INNER_JOIN(FilmActor, Actor.ActorID.EQ(FilmActor.ActorID)).  \n        INNER_JOIN(Film, Film.FilmID.EQ(FilmActor.FilmID)).          \n        INNER_JOIN(Language, Language.LanguageID.EQ(Film.LanguageID)).\n        INNER_JOIN(FilmCategory, FilmCategory.FilmID.EQ(Film.FilmID)).\n        INNER_JOIN(Category, Category.CategoryID.EQ(FilmCategory.CategoryID)),\n).WHERE(\n    Language.Name.EQ(Char(20)(\"English\")).             \n        AND(Category.Name.NOT_EQ(Text(\"Action\"))).  \n        AND(Film.Length.GT(Int32(180))).\n        AND(Film.Rating.NOT_EQ(enum.MpaaRating.R)),              \n).ORDER_BY(\n    Actor.ActorID.ASC(),\n    Film.FilmID.ASC(),\n)\n```\n\u003e [!Tip]\n\u003e Package(dot) import is used, so the statements look as close as possible to the native SQL.  \n\nNote that every column has a type. String columns, such as `Language.Name` and `Category.Name` can only be compared with\nstring columns and expressions. Similarity, `Actor.ActorID`, `FilmActor.ActorID`, `Film.Length` are integer columns\nand can only be compared with integer columns and expressions.\n\n__How to Get a Parametrized SQL Query from the Statement?__\n```go\nquery, args := stmt.Sql()\n```\nquery - parametrized query  \nargs - query arguments\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see `query` and `args`\u003c/summary\u003e\n\n```sql\nSELECT actor.actor_id AS \"actor.actor_id\",\n       actor.first_name AS \"actor.first_name\",\n       actor.last_name AS \"actor.last_name\",\n       actor.last_update AS \"actor.last_update\",\n       film.film_id AS \"film.film_id\",\n       film.title AS \"film.title\",\n       film.description AS \"film.description\",\n       film.release_year AS \"film.release_year\",\n       film.language_id AS \"film.language_id\",\n       film.rental_duration AS \"film.rental_duration\",\n       film.rental_rate AS \"film.rental_rate\",\n       film.length AS \"film.length\",\n       film.replacement_cost AS \"film.replacement_cost\",\n       film.rating AS \"film.rating\",\n       film.last_update AS \"film.last_update\",\n       film.special_features AS \"film.special_features\",\n       film.fulltext AS \"film.fulltext\",\n       language.language_id AS \"language.language_id\",\n       language.name AS \"language.name\",\n       language.last_update AS \"language.last_update\",\n       category.category_id AS \"category.category_id\",\n       category.name AS \"category.name\",\n       category.last_update AS \"category.last_update\"\nFROM dvds.actor\n         INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.actor_id)\n         INNER JOIN dvds.film ON (film.film_id = film_actor.film_id)\n         INNER JOIN dvds.language ON (language.language_id = film.language_id)\n         INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id)\n         INNER JOIN dvds.category ON (category.category_id = film_category.category_id)\nWHERE (((language.name = $1::char(20)) AND (category.name != $2::text)) AND (film.length \u003e $3)) AND (film.rating != 'R')\nORDER BY actor.actor_id ASC, film.film_id ASC;\n```\n```sh \n[English Action 180]\n```\n\n\n\u003c/details\u003e\n\n__How to Get Debug SQL from Statement?__\n ```go\ndebugSql := stmt.DebugSql()\n```\ndebugSql - this query string can be copy-pasted into sql editor and executed. \n\u003e [!Warning]\n\u003e Debug SQL is not intended to be used in production. For debug purposes only!!!\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see debug sql\u003c/summary\u003e\n\n```sql\nSELECT actor.actor_id AS \"actor.actor_id\",\n     actor.first_name AS \"actor.first_name\",\n     actor.last_name AS \"actor.last_name\",\n     actor.last_update AS \"actor.last_update\",\n     film.film_id AS \"film.film_id\",\n     film.title AS \"film.title\",\n     film.description AS \"film.description\",\n     film.release_year AS \"film.release_year\",\n     film.language_id AS \"film.language_id\",\n     film.rental_duration AS \"film.rental_duration\",\n     film.rental_rate AS \"film.rental_rate\",\n     film.length AS \"film.length\",\n     film.replacement_cost AS \"film.replacement_cost\",\n     film.rating AS \"film.rating\",\n     film.last_update AS \"film.last_update\",\n     film.special_features AS \"film.special_features\",\n     film.fulltext AS \"film.fulltext\",\n     language.language_id AS \"language.language_id\",\n     language.name AS \"language.name\",\n     language.last_update AS \"language.last_update\",\n     category.category_id AS \"category.category_id\",\n     category.name AS \"category.name\",\n     category.last_update AS \"category.last_update\"\nFROM dvds.actor\n     INNER JOIN dvds.film_actor ON (actor.actor_id = film_actor.actor_id)\n     INNER JOIN dvds.film ON (film.film_id = film_actor.film_id)\n     INNER JOIN dvds.language ON (language.language_id = film.language_id)\n     INNER JOIN dvds.film_category ON (film_category.film_id = film.film_id)\n     INNER JOIN dvds.category ON (category.category_id = film_category.category_id)\nWHERE (((language.name = 'English'::char(20)) AND (category.name != 'Action'::text)) AND (film.length \u003e 180)) AND (film.rating != 'R')\nORDER BY actor.actor_id ASC, film.film_id ASC;\n```\n\u003c/details\u003e\n\n\n#### Execute Query and Store Result\n\nWell-formed SQL is just a first half of the job. Let's see how can we make some sense of result set returned executing\nabove statement. Usually this is the most complex and tedious work, but with Jet it is the easiest.\n\nFirst, we need to define the structure in which to store the query result. This\ncan be achieved by combining autogenerated model types, or by using custom\nmodel types(see [wiki](https://github.com/go-jet/jet/wiki/Query-Result-Mapping-(QRM)#custom-model-types) for more information).\n\nLet's say this is our desired structure made of autogenerated types:\n```go\nvar dest []struct {\n    model.Actor\n    \n    Films []struct {\n        model.Film\n        \n        Language    model.Language\n        Categories  []model.Category\n    }\n}\n```\n\nThe `Films` field is a slice because an actor can appear in multiple films,\nand each film is associated with a single language. The `Language` field,\non the other hand, is a single model struct. A `Film` can belong to multiple\ncategories.\n \n\u003e [!Note]\n\u003e There is no limitation of how big or nested destination can be.\n\nNow, let's execute the above statement on an open database connection (or\ntransaction) `db` and store the result in the `dest` variable.\n\n```go\nerr := stmt.Query(db, \u0026dest)\nhandleError(err)\n```\n\n__And that's it.__\n\nThe `dest` variable now contains a list of all actors (each with a list of\nfilms they acted in). Each film includes information about its language and\na list of categories it belongs to. This list is filtered to include only\nfilms longer than 180 minutes, where the film language is 'English', and\nthe film category is not 'Action'.\n\n\u003e [!Tip]  \n\u003e It is recommended to enable **Strict Scan** on application startup, especially when destination contains \n\u003e custom model types. For more details, see the [wiki](https://github.com/go-jet/jet/wiki/Query-Result-Mapping-(QRM)#strict-scan).\n\nLets print `dest` as a JSON to see:\n```go\njsonText, _ := json.MarshalIndent(dest, \"\", \"\\t\")\nfmt.Println(string(jsonText))\n```\n\n```js\n[\n  {\n    \"ActorID\": 1,\n    \"FirstName\": \"Penelope\",\n    \"LastName\": \"Guiness\",\n    \"LastUpdate\": \"2013-05-26T14:47:57.62Z\",\n    \"Films\": [\n      {\n        \"FilmID\": 499,\n        \"Title\": \"King Evolution\",\n        \"Description\": \"A Action-Packed Tale of a Boy And a Lumberjack who must Chase a Madman in A Baloon\",\n        \"ReleaseYear\": 2006,\n        \"LanguageID\": 1,\n        \"RentalDuration\": 3,\n        \"RentalRate\": 4.99,\n        \"Length\": 184,\n        \"ReplacementCost\": 24.99,\n        \"Rating\": \"NC-17\",\n        \"LastUpdate\": \"2013-05-26T14:50:58.951Z\",\n        \"SpecialFeatures\": \"{Trailers,\\\"Deleted Scenes\\\",\\\"Behind the Scenes\\\"}\",\n        \"Fulltext\": \"'action':5 'action-pack':4 'baloon':21 'boy':10 'chase':16 'evolut':2 'king':1 'lumberjack':13 'madman':18 'must':15 'pack':6 'tale':7\",\n        \"Language\": {\n          \"LanguageID\": 1,\n          \"Name\": \"English             \",\n          \"LastUpdate\": \"0001-01-01T00:00:00Z\"\n        },\n        \"Categories\": [\n          {\n            \"CategoryID\": 8,\n            \"Name\": \"Family\",\n            \"LastUpdate\": \"2006-02-15T09:46:27Z\"\n          }\n        ]\n      }\n    ]\n  },\n  {\n    \"ActorID\": 3,\n    \"FirstName\": \"Ed\",\n    \"LastName\": \"Chase\",\n    \"LastUpdate\": \"2013-05-26T14:47:57.62Z\",\n    \"Films\": [\n      {\n        \"FilmID\": 996,\n        \"Title\": \"Young Language\",\n        \"Description\": \"A Unbelieveable Yarn of a Boat And a Database Administrator who must Meet a Boy in The First Manned Space Station\",\n        \"ReleaseYear\": 2006,\n        \"LanguageID\": 1,\n        \"RentalDuration\": 6,\n        \"RentalRate\": 0.99,\n        \"Length\": 183,\n        \"ReplacementCost\": 9.99,\n        \"Rating\": \"G\",\n        \"LastUpdate\": \"2013-05-26T14:50:58.951Z\",\n        \"SpecialFeatures\": \"{Trailers,\\\"Behind the Scenes\\\"}\",\n        \"Fulltext\": \"'administr':12 'boat':8 'boy':17 'databas':11 'first':20 'languag':2 'man':21 'meet':15 'must':14 'space':22 'station':23 'unbeliev':4 'yarn':5 'young':1\",\n        \"Language\": {\n          \"LanguageID\": 1,\n          \"Name\": \"English             \",\n          \"LastUpdate\": \"0001-01-01T00:00:00Z\"\n        },\n        \"Categories\": [\n          {\n            \"CategoryID\": 6,\n            \"Name\": \"Documentary\",\n            \"LastUpdate\": \"2006-02-15T09:46:27Z\"\n          }\n        ]\n      }\n    ]\n  },\n  //...(125 more items)\n]\n```\n\nWhat if, we also want to have list of films per category and actors per category, where films are longer than 180 minutes, film language is 'English'\nand film category is not 'Action'.  \nIn that case we can reuse above statement `stmt`, and just change our destination:\n\n```go\nvar dest2 []struct {\n    model.Category\n\n    Films []model.Film\n    Actors []model.Actor\n}\n\nerr = stmt.Query(db, \u0026dest2)\nhandleError(err)\n```\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see `dest2` json\u003c/summary\u003e\n\n```js\n[\n  {\n    \"CategoryID\": 8,\n    \"Name\": \"Family\",\n    \"LastUpdate\": \"2006-02-15T09:46:27Z\",\n    \"Films\": [\n      {\n        \"FilmID\": 499,\n        \"Title\": \"King Evolution\",\n        \"Description\": \"A Action-Packed Tale of a Boy And a Lumberjack who must Chase a Madman in A Baloon\",\n        \"ReleaseYear\": 2006,\n        \"LanguageID\": 1,\n        \"RentalDuration\": 3,\n        \"RentalRate\": 4.99,\n        \"Length\": 184,\n        \"ReplacementCost\": 24.99,\n        \"Rating\": \"NC-17\",\n        \"LastUpdate\": \"2013-05-26T14:50:58.951Z\",\n        \"SpecialFeatures\": \"{Trailers,\\\"Deleted Scenes\\\",\\\"Behind the Scenes\\\"}\",\n        \"Fulltext\": \"'action':5 'action-pack':4 'baloon':21 'boy':10 'chase':16 'evolut':2 'king':1 'lumberjack':13 'madman':18 'must':15 'pack':6 'tale':7\"\n      },\n      {\n        \"FilmID\": 50,\n        \"Title\": \"Baked Cleopatra\",\n        \"Description\": \"A Stunning Drama of a Forensic Psychologist And a Husband who must Overcome a Waitress in A Monastery\",\n        \"ReleaseYear\": 2006,\n        \"LanguageID\": 1,\n        \"RentalDuration\": 3,\n        \"RentalRate\": 2.99,\n        \"Length\": 182,\n        \"ReplacementCost\": 20.99,\n        \"Rating\": \"G\",\n        \"LastUpdate\": \"2013-05-26T14:50:58.951Z\",\n        \"SpecialFeatures\": \"{Commentaries,\\\"Behind the Scenes\\\"}\",\n        \"Fulltext\": \"'bake':1 'cleopatra':2 'drama':5 'forens':8 'husband':12 'monasteri':20 'must':14 'overcom':15 'psychologist':9 'stun':4 'waitress':17\"\n      }\n    ],\n    \"Actors\": [\n      {\n        \"ActorID\": 1,\n        \"FirstName\": \"Penelope\",\n        \"LastName\": \"Guiness\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 20,\n        \"FirstName\": \"Lucille\",\n        \"LastName\": \"Tracy\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 36,\n        \"FirstName\": \"Burt\",\n        \"LastName\": \"Dukakis\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 70,\n        \"FirstName\": \"Michelle\",\n        \"LastName\": \"Mcconaughey\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 118,\n        \"FirstName\": \"Cuba\",\n        \"LastName\": \"Allen\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 187,\n        \"FirstName\": \"Renee\",\n        \"LastName\": \"Ball\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      },\n      {\n        \"ActorID\": 198,\n        \"FirstName\": \"Mary\",\n        \"LastName\": \"Keitel\",\n        \"LastUpdate\": \"2013-05-26T14:47:57.62Z\"\n      }\n    ]\n  },\n    //...\n]\n```\n\u003c/details\u003e\n\nComplete code example can be found at [./examples/quick-start/quick-start.go](./examples/quick-start/quick-start.go)\n\n\nThis example represent probably the most common use case.  Detail info about additional statements, features and use cases can be\nfound at project [Wiki](https://github.com/go-jet/jet/wiki) page.\n\n## Benefits\n\nWhat are the benefits of writing SQL in Go using Jet?  \nThe biggest benefit is speed. Speed is being improved in 3 major areas:\n\n##### Speed of Development\n\nWriting SQL queries becomes faster and more efficient, as developers benefit\nfrom SQL code completion and type safety directly within Go code. Automatic\nscanning to arbitrary structures eliminates much of the headache and boilerplate required\nto structure database query results, reducing both complexity and development time.\n\n##### Speed of Execution\n\nWhile ORM libraries can introduce significant performance penalties when\nmultiple tables are involved, due to multiple round-trips to the database\n(i.e., the `N+1` query problem), Jet will always perform better. Developers\ncan write queries of any complexity and retrieve results with a single database call.\nAs a result, handler time lost to latency between the server and database\nremains constant. Handler execution time is proportional only to query\ncomplexity and the number of rows returned from the database.\n\n\u003e [!Tip]\n\u003e As of the version `v2.13.0`, developers can leverage [SELECT_JSON](https://github.com/go-jet/jet/wiki/SELECT_JSON-Statements) \n\u003e statements to encode query result as JSON on the SQL server, and then return that JSON as a result. Instead of \n\u003e returning a large set of rows, the query now returns a single row with one column containing the entire result as JSON, \n\u003e further reducing latency.\n\nWith Jet, it is even possible to join the whole database and store the whole structured result in one database call.\nThis is exactly what is being done in one of the tests: [TestJoinEverything](https://github.com/go-jet/jet/blob/6706f4b228f51cf810129f57ba90bbdb60b85fe7/tests/postgres/chinook_db_test.go#L187).\nThe whole test database is joined and query result(~10,000 rows and 68 columns) is stored in a structured variable in less than 0.5s, or \nin case of `SELECT_JSON` statement in around 0.3s.\n\n##### How Quickly Bugs are Found\n\nThe most expensive bugs are those discovered in production, while the least expensive are those found during development.\nWith automatically generated, type-safe SQL, queries are not only written faster but bugs are caught sooner.\n\nConsider the following line from the quick start example:\n ```go\nAND(Film.Length.GT(Int32(180))),\n```\nLet's say someone changes column `length` to `duration` from `film` table. The next go build will fail at that line, and\nthe bug will be caught at compile time.\n\nLet's say someone changes the type of `length` column to some non-integer type. Build will also fail at the same line\nbecause integer columns and expressions can be only compared to other integer columns and expressions.\n\nBuild will also fail if someone removes `length` column from `film` table. `Film` field will be omitted from SQL Builder and Model types,\nnext time `jet` generator is run.\n\nWithout Jet these bugs will have to be either caught by tests or by manual testing.\n\n## Dependencies\n\nTo execute Jet SQL statements, **ANY** SQL driver that implements Go's standard `database/sql` interface can be used. \n\nBy default, the `Jet` generator executable uses the following SQL drivers to read database schema information:\n- `github.com/lib/pq` _(`PostgreSQL` and `CockroachDB` )_\n- `github.com/go-sql-driver/mysql` _(`MySQL` and `MariaDB`)_\n- `github.com/mattn/go-sqlite3` _(`SQLite`)_\n\nThe default SQL driver used by the Jet generator can be replaced, if needed, by \n[customizing the generator](https://github.com/go-jet/jet/wiki/Generator#generator-customization).\n\n## Versioning\n\n[SemVer](http://semver.org/) is used for versioning. For the versions available, take a look at the [releases](https://github.com/go-jet/jet/releases).\n   \nTypically, two releases are published each year — one in early spring and another in late autumn.\n\n## License\n\nCopyright 2019-2025 Goran Bjelanovic  \nLicensed under the Apache License, Version 2.0.\n\n## Support the Project\n\nWays to donate:\n- [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/E1E71CXDAE)\n- BTC: bc1qtjhxe8mqx0yzff2l0f6stjpjj92kgwr0a53wxv\n- ETH: 0xe98e4535C744c617e8E45828B63fDFf9367E3574","funding_links":["https://ko-fi.com/E1E71CXDAE"],"categories":["Database","数据库","Go","Generators","数据库管理系统","Data Integration Frameworks","Uncategorized","数据库  `go语言实现的数据库`"],"sub_categories":["Advanced Console UIs","SQL Query Builders","SQL查询生成器","资源传输下载","SQL 查询语句构建库"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-jet%2Fjet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-jet%2Fjet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-jet%2Fjet/lists"}