{"id":36593535,"url":"https://github.com/doytowin/goooqo","last_synced_at":"2026-03-14T12:20:16.527Z","repository":{"id":209424394,"uuid":"724022466","full_name":"doytowin/goooqo","owner":"doytowin","description":"GoooQo is a database access framework implemented in Go, based on OQM techniques.","archived":false,"fork":false,"pushed_at":"2025-07-19T13:35:13.000Z","size":441,"stargazers_count":143,"open_issues_count":8,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-19T17:42:25.345Z","etag":null,"topics":["ddd","go","goooqo","oqm","orm"],"latest_commit_sha":null,"homepage":"https://goooqo.docs.doyto.win","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause-clear","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/doytowin.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":"2023-11-27T08:34:51.000Z","updated_at":"2025-07-19T13:35:17.000Z","dependencies_parsed_at":"2024-08-23T11:03:53.847Z","dependency_job_id":"41c3767e-69bc-4307-a65c-b98306ec03d8","html_url":"https://github.com/doytowin/goooqo","commit_stats":null,"previous_names":["doytowin/doyto-query-go-sql","doytowin/goquery","doytowin/goooqo"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/doytowin/goooqo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doytowin%2Fgoooqo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doytowin%2Fgoooqo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doytowin%2Fgoooqo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doytowin%2Fgoooqo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/doytowin","download_url":"https://codeload.github.com/doytowin/goooqo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/doytowin%2Fgoooqo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28337591,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T06:09:07.588Z","status":"ssl_error","status_checked_at":"2026-01-12T06:05:18.301Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["ddd","go","goooqo","oqm","orm"],"created_at":"2026-01-12T08:24:05.286Z","updated_at":"2026-03-14T12:20:16.520Z","avatar_url":"https://github.com/doytowin.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Sonar Stats](https://sonarcloud.io/api/project_badges/measure?project=win.doyto.goooqo\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=win.doyto.goooqo)\n[![Code Lines](https://sonarcloud.io/api/project_badges/measure?project=win.doyto.goooqo\u0026metric=ncloc)](https://sonarcloud.io/component_measures?id=win.doyto.goooqo\u0026metric=ncloc)\n[![Coverage Status](https://coveralls.io/repos/github/doytowin/goooqo/badge.svg?branch=main)](https://coveralls.io/github/doytowin/goooqo?branch=main)\n[![CI](https://github.com/doytowin/goooqo/actions/workflows/go.yml/badge.svg)](https://github.com/doytowin/goooqo/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/doytowin/goooqo/rdb)](https://goreportcard.com/report/github.com/doytowin/goooqo/rdb)\n[![Go Reference](https://pkg.go.dev/badge/github.com/doytowin/goooqo/rdb.svg)](https://pkg.go.dev/github.com/doytowin/goooqo/rdb)\n\nGoooQo\n---\n\n## Introduction\n\nGoooQo is a database access framework implemented in Go, based on OQM techniques. It relies entirely on objects to construct various database query statements, eliminating boilerplate code associated with traditional ORM frameworks, and assists developers in achieving automated database access operations.\n\nThe first three Os in the name GoooQo stands for the three major object concepts in the OQM technique:\n\n- `Entity Object` is used to map the static part in the CRUD statements, e.g. table name and column names;\n- `Query Object` is used to map the dynamic part in the CRUD statements, e.g. filter conditions, pagination and sorting clause;\n- `View Object` is used to map the static part in the complex query statements, e.g. table names, column names, group-by clause and joins.\n\nCheck this [article](https://blog.doyto.win/post/introduction-to-goooqo-en/) for more details. \n\nCheck this [demo](https://github.com/doytowin/goooqo-demo) to take a quick tour.\n\nProduct documentation: https://goooqo.docs.doyto.win/\n\n## Quick start\n\n### Init project\n\nUse `go mod init` to init the project and add GoooQo dependency:\n\n```\ngo get -u github.com/doytowin/goooqo/rdb\n```\n\nInit a database connection `db` and a transaction manager `tm`:\n\n```go\npackage main\n\nimport (\n\t\"database/sql\"\n\t\"github.com/doytowin/goooqo/rdb\"\n\t_ \"github.com/mattn/go-sqlite3\"\n)\n\nfunc main() {\n\tdb, _ := sql.Open(\"sqlite3\", \"./test.db\")\n\ttm := rdb.NewTransactionManager(db)\n\t//...\n}\n```\n\n### Create a data access interface\n\nSuppose we have the following user table in `test.db`:\n\n| id | name  | score | memo  | deleted |\n|----|-------|-------|-------|---------|\n| 1  | Alley | 80    | Good  | false   |\n| 2  | Dave  | 75    | Well  | false   |\n| 3  | Bob   | 60    |       | false   |\n| 4  | Tim   | 92    | Great | true    |\n| 5  | Emy   | 100   | Great | false   |\n\nWe define an entity object, a query object and a database access interface for this table:\n\n```go\npackage main\n\nimport . \"github.com/doytowin/goooqo/core\"\n\ntype UserEntity struct {\n\tInt64Id\n\tName    *string `json:\"name\"`\n\tScore   *int    `json:\"score\"`\n\tMemo    *string `json:\"memo\"`\n\tDeleted *bool   `json:\"deleted\"`\n}\n\ntype UserQuery struct {\n\tPageQuery\n\tIdGt     *int64\n\tIdIn     *[]int64\n\tScoreLt  *int\n\tMemoNull *bool\n\tMemoLike *string\n\tDeleted  *bool\n\tUserOr   *[]UserQuery\n\n\tScoreLtAvg *UserQuery `subquery:\"select avg(score) from t_user\"`\n\tScoreLtAny *UserQuery `subquery:\"SELECT score FROM t_user\"`\n\tScoreLtAll *UserQuery `subquery:\"SELECT score FROM t_user\"`\n\tScoreGtAvg *UserQuery `select:\"avg(score)\" from:\"t_user\"`\n\n\tRole *RoleQuery `entitypath:\"user,role\"`\n\tPerm *PermQuery `entitypath:\"user,role,perm\"`\n}\n\nvar UserDataAccess TxDataAccess[UserEntity]\n```\n\nAfter establishing a database connection and creating the transaction manager `tm`,\ninitialize the `UserDataAccess` interface to perform CRUD operations:\n\n```go\nUserDataAccess = rdb.NewTxDataAccess[UserEntity](tm)\n```\n\n### Query examples: \n\n```go\nuserQuery := UserQuery{ScoreLt: P(80)}\nusers, err := UserDataAccess.Query(ctx, userQuery)\n// SQL=\"SELECT id, name, score, memo, deleted FROM t_user WHERE score \u003c ?\" args=\"[80]\"\n\nuserQuery := UserQuery{PageQuery: PageQuery{Size: 20, Sort: \"id,desc;score\"}, MemoLike: P(\"Great\")}\nusers, err := UserDataAccess.Query(ctx, userQuery)\n// SQL=\"SELECT id, name, score, memo, deleted FROM t_user WHERE memo LIKE ? ORDER BY id DESC, score LIMIT 20 OFFSET 0\" args=\"[Great]\"\n\nuserQuery := UserQuery{IdIn: \u0026[]int64{1, 4, 12}, Deleted: P(true)}\nusers, err := UserDataAccess.Query(ctx, userQuery)\n// SQL=\"SELECT id, name, score, memo, deleted FROM t_user WHERE id IN (?, ?, ?) AND deleted = ?\" args=\"[1 4 12 true]\"\n\nuserQuery := UserQuery{UserOr: \u0026[]UserQuery{{IdGt: P(int64(10)), MemoNull: P(true)}, {ScoreLt: P(80), MemoLike: P(\"Good\")}}}\nusers, err := UserDataAccess.Query(ctx, userQuery)\n// SQL=\"SELECT id, name, score, memo, deleted FROM t_user WHERE (id \u003e ? AND memo IS NULL OR score \u003c ? AND memo LIKE ?)\" args=\"[10 80 Good]\"\n\nuserQuery := UserQuery{ScoreGtAvg: \u0026UserQuery{Deleted: P(true)}, ScoreLtAny: \u0026UserQuery{}}\nusers, err := UserDataAccess.Query(ctx, userQuery)\n// SQL=\"SELECT id, name, score, memo, deleted FROM t_user WHERE score \u003e (SELECT avg(score) FROM t_user WHERE deleted = ?) AND score \u003c ANY(SELECT score FROM t_user)\" args=\"[true]\"\n```\n\nFor more CRUD examples, please refer to: https://goooqo.docs.doyto.win/api/crud\n\n### Code Generation\n\nGoooQo provides a code generation tool, `gooogen`, which supports automatically generating dynamic query construction methods for query objects.\n\n#### Install `gooogen`\n\nInstall the `gooogen` tool using the following command:\n\n```bash\ngo install github.com/doytowin/goooqo/gooogen@latest\n```\n\n#### Add Generate Directive\n\nAdd the `go:generate gooogen` directive to the query object definition. For example:\n\n```go\n//go:generate gooogen -type sql -o user_query_builder.go\ntype UserQuery struct {\n    // ...\n}\n```\n\n- **`-type`**: (Optional) Specifies the type of query language to generate, e.g. `sql`.\n- **`-f`**: (Optional) Defines the name of the input file which contains a query object, e.g. `user.go`.\n- **`-o`**: (Optional) Defines the name of the generated file, e.g. `user_query_builder.go`.\n\n#### Generate Code\n\nRun the `go generate` command to generate the corresponding query construction methods in the specified file.\n\n### Transaction Examples\n\nUse `TransactionManager#StartTransaction` to start a transaction, then manually commit or rollback the transaction:\n```go\ntc, err := UserDataAccess.StartTransaction(ctx)\nuserQuery := UserQuery{ScoreLt: P(80)}\ncnt, err := UserDataAccess.DeleteByQuery(tc, userQuery)\nif err != nil {\n\terr = tc.Rollback()\n\treturn 0, err\n}\nerr = tc.Commit()\nreturn cnt, err\n```\n\nOr use `TransactionManager#SubmitTransaction` to commit the transaction via callback function:\n```go\nerr := tm.SubmitTransaction(ctx, func(tc TransactionContext) (err error) {\n\t// transaction body\n\treturn\n})\n```\n\nLicense\n---\nThis project is under the [BSD 3-Clause Clear License](https://spdx.org/licenses/BSD-3-Clause-Clear).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoytowin%2Fgoooqo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdoytowin%2Fgoooqo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdoytowin%2Fgoooqo/lists"}