{"id":24930527,"url":"https://github.com/mazrean/genorm","last_synced_at":"2025-12-15T18:59:24.562Z","repository":{"id":38080963,"uuid":"317857196","full_name":"mazrean/genorm","owner":"mazrean","description":"SQL Builder to prevent SQL mistakes using the Golang generics","archived":false,"fork":false,"pushed_at":"2025-03-28T15:32:43.000Z","size":472,"stargazers_count":46,"open_issues_count":8,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T21:51:28.553Z","etag":null,"topics":["generics","go","golang","hacktoberfest","mysql","orm","sql"],"latest_commit_sha":null,"homepage":"https://mazrean.github.io/genorm-docs/en/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mazrean.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}},"created_at":"2020-12-02T12:37:24.000Z","updated_at":"2025-03-11T17:11:05.000Z","dependencies_parsed_at":"2023-02-06T05:31:33.833Z","dependency_job_id":"e3aebd65-5f83-425b-91a3-985c12cb47fa","html_url":"https://github.com/mazrean/genorm","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mazrean%2Fgenorm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mazrean%2Fgenorm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mazrean%2Fgenorm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mazrean%2Fgenorm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mazrean","download_url":"https://codeload.github.com/mazrean/genorm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248119402,"owners_count":21050754,"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":["generics","go","golang","hacktoberfest","mysql","orm","sql"],"created_at":"2025-02-02T13:54:47.527Z","updated_at":"2025-12-15T18:59:24.555Z","avatar_url":"https://github.com/mazrean.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GenORM\n\n[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)\n[![](https://pkg.go.dev/badge/github.com/mazrean/genorm)](https://pkg.go.dev/github.com/mazrean/genorm)\n[![](https://github.com/mazrean/genorm/workflows/CI/badge.svg)](https://github.com/mazrean/genorm/actions)\n\nSQL Builder to prevent SQL mistakes using the Golang generics\n\n#### document\n- [English](https://mazrean.github.io/genorm-docs/en/)\n- [日本語](https://mazrean.github.io/genorm-docs/ja/)\n\n## Feature\n\nBy mapping SQL expressions to appropriate golang types using generics, you can discover many SQL mistakes at the time of compilation that are not prevented by traditional Golang ORMs or query builders.\n\nFor example:\n\n* Compilation error occurs when using values of different Go types in SQL for = etc. comparisons or updating values in UPDATE statements\n* Compile error occurs when using column names of unavailable tables\n\nIt also supports many CRUD syntaxes in SQL.\n\n## Example\n#### Example 1\n\nString column `users.name` can be compared to a `string` value, but comparing it to an `int` value will result in a compile error.\n\n```go\n// correct\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tWhere(genorm.EqLit(user.NameExpr, genorm.Wrap(\"name\"))).\n\tGetAll(db)\n\n// compile error\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tWhere(genorm.EqLit(user.NameExpr, genorm.Wrap(1))).\n\tGetAll(db)\n```\n\n#### Example 2\n\nYou can use an `id` column from the `users` table in a `SELECT` statement that retrieves data from the `users` table, but using an `id` column from the `messages` table will result in a compile error.\n\n```go\n// correct\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tWhere(genorm.EqLit(user.IDExpr, uuid.New())).\n\tGetAll(db)\n\n// compile error\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tWhere(genorm.EqLit(message.IDExpr, uuid.New())).\n\tGetAll(db)\n```\n\n## Install\n\nGenORM uses the CLI to generate code. The `genorm`package is used to invoke queries. For this reason, both the CLI and Package must be install.\n\n#### CLI\n\n```\ngo install github.com/mazrean/genorm/cmd/genorm@v1.0.0\n```\n\n#### Package\n\n```\ngo get -u github.com/mazrean/genorm\n```\n\n### Configuration\n\n#### Example\n\nThe `users` table can join the `messages` table.\n\n```go\nimport \"github.com/mazrean/genorm\"\n\ntype User struct {\n    // Column Information\n    Message genorm.Ref[Message]\n}\n\nfunc (*User) TableName() string {\n    return \"users\"\n}\n\ntype Message struct {\n    // Column Information\n}\n\nfunc (*Message) TableName() string {\n    return \"messages\"\n}\n```\n\n## Usage\n### Connecting to a Database\n```go\nimport (\n  \"database/sql\"\n  _ \"github.com/go-sql-driver/mysql\"\n)\n\ndb, err := sql.Open(\"mysql\", \"user:pass@tcp(host:port)/database?parseTime=true\u0026loc=Asia%2FTokyo\u0026charset=utf8mb4\")\n```\n\n### Insert\n```go\n// INSERT INTO users (id, name, created_at) VALUES ({{uuid.New()}}, \"name1\", {{time.Now()}}), ({{uuid.New()}}, \"name2\", {{time.Now()}})\naffectedRows, err := genorm.\n    Insert(orm.User()).\n    Values(\u0026orm.UserTable{\n        ID: uuid.New(),\n        Name: genorm.Wrap(\"name1\"),\n        CreatedAt: genorm.Wrap(time.Now()),\n    }, \u0026orm.UserTable{\n        ID: uuid.New(),\n        Name: genorm.Wrap(\"name2\"),\n        CreatedAt: genorm.Wrap(time.Now()),\n    }).\n    Do(db)\n```\n\n### Select\n\n```go\n// SELECT id, name, created_at FROM users\n// userValues: []orm.UserTable\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tGetAll(db)\n\n// SELECT id, name, created_at FROM users LIMIT 1\n// userValue: orm.UserTable\nuserValue, err := genorm.\n\tSelect(orm.User()).\n\tGet(db)\n\n// SELECT id FROM users\n// userIDs: []uuid.UUID\nuserIDs, err := genorm.\n\tPluck(orm.User(), user.IDExpr).\n\tGetAll(db)\n\n// SELECT COUNT(id) AS result FROM users LIMIT 1\n// userNum: int64\nuserNum, err := genorm.\n\tPluck(orm.User(), genorm.Count(user.IDExpr, false)).\n\tGet(db)\n```\n\n### Update\n```go\n// UPDATE users SET name=\"name\"\naffectedRows, err = genorm.\n    Update(orm.User()).\n    Set(\n        genorm.AssignLit(user.Name, genorm.Wrap(\"name\")),\n    ).\n    Do(db)\n```\n\n\n### Delete\n```go\n// DELETE FROM users\naffectedRows, err = genorm.\n    Delete(orm.User()).\n    Do(db)\n```\n\n### Join\n#### Select\n```go\n// SELECT users.name, messages.content FROM users INNER JOIN messages ON users.id = messages.user_id\n// messageUserValues: []orm.MessageUserTable\nuserID := orm.MessageUserParseExpr(user.ID)\nuserName := orm.MessageUserParse(user.Name)\nmessageUserID := orm.MessageUserParseExpr(message.UserID)\nmessageContent := orm.MessageUserParse(message.Content)\nmessageUserValues, err := genorm.\n\tSelect(orm.User().\n\t\tMessage().Join(genorm.Eq(userID, messageUserID))).\n\tFields(userName, messageContent).\n\tGetAll(db)\n```\n\n#### Update\n```go\n// UPDATE users INNER JOIN messages ON users.id = messages.id SET content=\"hello world\"\nuserIDColumn := orm.MessageUserParseExpr(user.ID)\nmessageUserIDColumn := orm.MessageUserParseExpr(message.UserID)\nmessageContent := orm.MessageUserParse(message.Content)\naffectedRows, err := genorm.\n  Update(orm.User().\n\t\tMessage().Join(genorm.Eq(userID, messageUserID))).\n  Set(genorm.AssignLit(messageContent, genorm.Wrap(\"hello world\"))).\n  Do(db)\n```\n\n### Transaction\n```go\ntx, err := db.Begin()\nif err != nil {\n    log.Fatal(err)\n}\n\n_, err = genorm.\n    Insert(orm.User()).\n    Values(\u0026orm.UserTable{\n        ID: uuid.New(),\n        Name: genorm.Wrap(\"name1\"),\n        CreatedAt: genorm.Wrap(time.Now()),\n    }, \u0026orm.UserTable{\n        ID: uuid.New(),\n        Name: genorm.Wrap(\"name2\"),\n        CreatedAt: genorm.Wrap(time.Now()),\n    }).\n    Do(db)\nif err != nil {\n    _ = tx.Rollback()\n    log.Fatal(err)\n}\n\nerr = tx.Commit()\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Context\n\n```go\n// SELECT id, name, created_at FROM users\n// userValues: []orm.UserTable\nuserValues, err := genorm.\n\tSelect(orm.User()).\n\tGetAllCtx(context.Background(), db)\n```\n\n```go\n// INSERT INTO users (id, name, created_at) VALUES ({{uuid.New()}}, \"name\", {{time.Now()}})\naffectedRows, err := genorm.\n    Insert(orm.User()).\n    Values(\u0026orm.UserTable{\n        ID: uuid.New(),\n        Name: genorm.Wrap(\"name\"),\n        CreatedAt: genorm.Wrap(time.Now()),\n    }).\n    DoCtx(context.Background(), db)\n```\n\n## Supports\n\nThis project receives support from GMO FlattSecurity's “GMO Open Source Developer Support Program” and regularly conducts security assessments using “Takumi byGMO.”\n\n\u003ca href=\"https://flatt.tech/oss/gmo/trampoline\" target=\"_blank\"\u003e\u003cimg src=\"https://flatt.tech/assets/images/badges/gmo-oss.svg\" height=\"24px\"/\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmazrean%2Fgenorm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmazrean%2Fgenorm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmazrean%2Fgenorm/lists"}