{"id":40906112,"url":"https://github.com/tomyl/xl","last_synced_at":"2026-01-22T02:38:34.995Z","repository":{"id":57507709,"uuid":"125233536","full_name":"tomyl/xl","owner":"tomyl","description":"SQL query builder for golang","archived":false,"fork":false,"pushed_at":"2020-09-19T09:03:42.000Z","size":44,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T12:40:37.431Z","etag":null,"topics":["go","sql-builder"],"latest_commit_sha":null,"homepage":null,"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/tomyl.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}},"created_at":"2018-03-14T15:24:58.000Z","updated_at":"2024-06-20T12:40:37.432Z","dependencies_parsed_at":"2022-09-19T05:31:22.565Z","dependency_job_id":null,"html_url":"https://github.com/tomyl/xl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tomyl/xl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomyl%2Fxl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomyl%2Fxl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomyl%2Fxl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomyl%2Fxl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tomyl","download_url":"https://codeload.github.com/tomyl/xl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tomyl%2Fxl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28651809,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["go","sql-builder"],"created_at":"2026-01-22T02:38:34.315Z","updated_at":"2026-01-22T02:38:34.989Z","avatar_url":"https://github.com/tomyl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xl :pig:\n\n[![Build Status](https://travis-ci.com/tomyl/xl.svg?branch=master)](https://travis-ci.org/tomyl/xl)\n[![GoDoc](https://godoc.org/github.com/tomyl/xl?status.png)](http://godoc.org/github.com/tomyl/xl)\n[![Go Report Card](https://goreportcard.com/badge/github.com/tomyl/xl)](https://goreportcard.com/report/github.com/tomyl/xl)\n[![codecov](https://codecov.io/gh/tomyl/xl/branch/master/graph/badge.svg)](https://codecov.io/gh/tomyl/xl)\n\nSQL query builder for golang. Built on top of [sqlx](https://github.com/jmoiron/sqlx). Used by [mört](https://github.com/tomyl/mort).\n\n**Pre-alpha software**. Expect plenty of bugs and frequent breaking API changes.\n\n# TODO\n\n- [ ] Finish this TODO list.\n\n# Similar software\n\n* [dbr](https://github.com/gocraft/dbr)\n* [goqu](https://github.com/doug-martin/goqu)\n* [Squirrel](https://github.com/Masterminds/squirrel)\n\n# Usage\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"time\"\n\n\t_ \"github.com/mattn/go-sqlite3\"\n\t\"github.com/tomyl/xl\"\n\t\"github.com/tomyl/xl/logger\"\n)\n\nconst schema = `\ncreate table department (\n\tid integer primary key, \n\tcreated_at timestamp not null,\n\tname text not null,\n\tcity text not null\n);\n\ninsert into department (id, created_at, name, city) values (1, current_timestamp, 'HR', 'Stockholm');\ninsert into department (id, created_at, name, city) values (2, current_timestamp, 'R\u0026D', 'Hong Kong');\n\ncreate table employee (\n\tid integer primary key, \n\tcreated_at timestamp not null,\n\tdepartment_id integer references department (id) not null,\n\tname text not null,\n\tsalary integer not null\n);\n\ninsert into employee (id, created_at, department_id, name, salary) values (1, current_timestamp, 1, 'Alice Örn', 12000);\ninsert into employee (id, created_at, department_id, name, salary) values (2, current_timestamp, 2, 'Bob Älv', 9000);\n`\n\ntype Department struct {\n\tID        int64     `db:\"id\"`\n\tCreatedAt time.Time `db:\"created_at\"`\n\tName      string    `db:\"name\"`\n\tCity      string    `db:\"city\"`\n}\n\ntype Employee struct {\n\tID           int64     `db:\"id\"`\n\tCreatedAt    time.Time `db:\"created_at\"`\n\tDepartmentID int64     `db:\"department_id\"`\n\tName         string    `db:\"name\"`\n\tSalary       int64     `db:\"salary\"`\n}\n\nfunc main() {\n\tdb, err := xl.Open(\"sqlite3\", \":memory:\")\n\n\tif err != nil {\n\t\tlog.Fatalf(\"Failed to open database: %v\", err)\n\t}\n\n\txl.SetLogger(logger.Color)\n\n\tif err := xl.MultiExec(db, schema); err != nil {\n\t\tlog.Fatalf(\"Failed to create schema: %v\", err)\n\t}\n\n\t// Insert an employee\n\tvar empId int64\n\t{\n\t\tq := xl.Insert(\"employee\")\n\t\tq.SetRaw(\"created_at\", \"current_timestamp\")\n\t\tq.Set(\"department_id\", 1)\n\t\tq.Set(\"name\", \"Cecil Ål\")\n\t\tq.Set(\"salary\", 12345)\n\t\tid, err := q.ExecId(db)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Failed to insert: %v\", err)\n\t\t}\n\t\tempId = id\n\t\tlog.Printf(\"Inserted employee %d\", empId)\n\t}\n\n\t// Update employee\n\t{\n\t\tq := xl.Update(\"employee\")\n\t\tq.Where(\"id=?\", empId)\n\t\tq.Set(\"salary\", 14000)\n\t\tif err := q.ExecOne(db); err != nil {\n\t\t\tlog.Fatalf(\"Failed to update: %v\", err)\n\t\t}\n\t\tlog.Printf(\"Updated employee\")\n\t}\n\n\t// Select all employees\n\t{\n\t\tvar entries []Employee\n\t\tq := xl.Select(\"*\").From(\"employee\")\n\t\tif err := q.All(db, \u0026entries); err != nil {\n\t\t\tlog.Fatalf(\"Failed to select: %v\", err)\n\t\t}\n\t\tlog.Printf(\"Employees: %v\", entries)\n\t}\n\n\t// Select employee with highest salary\n\t{\n\t\tvar entry Employee\n\t\tq := xl.Select(\"*\").From(\"employee\")\n\t\tq.OrderBy(\"salary DESC\")\n\t\tq.LimitOffset(1, 0)\n\t\tif err := q.First(db, \u0026entry); err != nil {\n\t\t\tlog.Fatalf(\"Failed to select: %v\", err)\n\t\t}\n\t\tlog.Printf(\"Employee: %v\", entry)\n\t}\n\n\t// Select employee names from Stockholm department\n\t{\n\t\tvar entries []string\n\t\tq := xl.Select(\"e.name\")\n\t\tq.FromAs(\"employee\", \"e\")\n\t\tq.FromAs(\"department\", \"d\")\n\t\tq.Where(\"e.department_id=d.id\")\n\t\tq.Where(\"d.city=?\", \"Stockholm\")\n\t\tif err := q.All(db, \u0026entries); err != nil {\n\t\t\tlog.Fatalf(\"Failed to select: %v\", err)\n\t\t}\n\t\tlog.Printf(\"Employees: %v\", entries)\n\t}\n\n\t// Select employees with inner join\n\t{\n\t\tvar entries []struct {\n\t\t\tDepartment `db:\"department\"`\n\t\t\tEmployee   `db:\"employee\"`\n\t\t}\n\n\t\tiq := xl.Select(`d.name \"department.name\"`)\n\t\tiq.FromAs(\"department\", \"d\")\n\t\tiq.Where(\"d.city=?\", \"Stockholm\")\n\n\t\tq := xl.Select(`e.name \"employee.name\"`)\n\t\tq.FromAs(\"employee\", \"e\")\n\t\tq.InnerJoin(iq, \"d.id=e.department_id\")\n\t\tq.OrderBy(\"d.name, e.name\")\n\n\t\tif err := q.All(db, \u0026entries); err != nil {\n\t\t\tlog.Fatalf(\"Failed to select: %v\", err)\n\t\t}\n\n\t\tlog.Printf(\"Employees: %v\", entries)\n\t}\n\n\t// Same as above, just using SelectAlias instead of Select\n\t{\n\t\tvar entries []struct {\n\t\t\tDepartment `db:\"d\"`\n\t\t\tEmployee   `db:\"e\"`\n\t\t}\n\n\t\tiq := xl.SelectAlias(\"name\")\n\t\tiq.FromAs(\"department\", \"d\")\n\t\tiq.Where(\"d.city=?\", \"Stockholm\")\n\n\t\tq := xl.SelectAlias(\"name\")\n\t\tq.FromAs(\"employee\", \"e\")\n\t\tq.InnerJoin(iq, \"d.id=e.department_id\")\n\t\tq.OrderBy(\"d.name, e.name\")\n\n\t\tif err := q.All(db, \u0026entries); err != nil {\n\t\t\tlog.Fatalf(\"Failed to select: %v\", err)\n\t\t}\n\n\t\tlog.Printf(\"Employees: %v\", entries)\n\t}\n\n\t// Delete employee\n\t{\n\t\tq := xl.Delete(\"employee\")\n\t\tq.Where(\"id=?\", empId)\n\t\tcount, err := q.ExecCount(db)\n\t\tif err != nil {\n\t\t\tlog.Fatalf(\"Failed to update: %v\", err)\n\t\t}\n\t\tlog.Printf(\"Deleted %d employees\", count)\n\t}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomyl%2Fxl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomyl%2Fxl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomyl%2Fxl/lists"}