{"id":37883735,"url":"https://github.com/imdatngo/gowhere","last_synced_at":"2026-01-16T16:50:37.985Z","repository":{"id":56012856,"uuid":"182285219","full_name":"imdatngo/gowhere","owner":"imdatngo","description":"SQL WHERE clause builder for Go","archived":false,"fork":false,"pushed_at":"2020-12-01T08:20:01.000Z","size":17,"stargazers_count":9,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-13T21:41:54.128Z","etag":null,"topics":["builder","go","golang","query","sql"],"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/imdatngo.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":"2019-04-19T15:24:42.000Z","updated_at":"2023-02-22T10:11:03.000Z","dependencies_parsed_at":"2022-08-15T11:20:52.602Z","dependency_job_id":null,"html_url":"https://github.com/imdatngo/gowhere","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/imdatngo/gowhere","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imdatngo%2Fgowhere","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imdatngo%2Fgowhere/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imdatngo%2Fgowhere/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imdatngo%2Fgowhere/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/imdatngo","download_url":"https://codeload.github.com/imdatngo/gowhere/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/imdatngo%2Fgowhere/sbom","scorecard":{"id":485314,"data":{"date":"2025-08-11","repo":{"name":"github.com/imdatngo/gowhere","commit":"a9a264777ea9afa85b73ce23fbed1e81018f555b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":1,"reason":"Found 1/10 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T17:36:20.652Z","repository_id":56012856,"created_at":"2025-08-19T17:36:20.653Z","updated_at":"2025-08-19T17:36:20.653Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: 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":["builder","go","golang","query","sql"],"created_at":"2026-01-16T16:50:37.218Z","updated_at":"2026-01-16T16:50:37.976Z","avatar_url":"https://github.com/imdatngo.png","language":"Go","readme":"# SQL WHERE clause builder for Go\n\n`gowhere` is neither an ORM package nor full-featured SQL builder. It only provides a flexible and powerful way to build SQL WHERE string from a simple array/slice or a map.\n\nThe goal of this package is to create an adapter for frontend app to easily \"query\" the given data. In the other way around, backend app can \"understand\" the request from frontend app to correctly build the SQL query. With minimum configurations and coding!\n\nThis package can also be used together with standard \"database/sql\" package or other ORM packages for better experience, if any :)\n\n## Install\n\n```bash\ngo get -u github.com/imdatngo/gowhere\n```\n\nThis package is dependency-free!\n\n## Usages\n\nThe simple way:\n\n```go\nimport \"github.com/imdatngo/gowhere\"\n\nplan := gowhere.Where(map[string]interface{}{\n    \"name__contains\": \"Gopher\",\n    \"budget__gte\": 1000,\n    \"date__between\": []interface{}{\"2019-04-13\", \"2019-04-15\"},\n})\n\nplan.SQL()\n// (\"name\" LIKE ? AND \"budget\" \u003e= ? and \"date\" BETWEEN ? AND ?)\n\nplan.Vars()\n// [%Gopher% 1000 2019-04-13 2019-04-15]\n```\n\nThe advanced way:\n\n```go\nimport \"github.com/imdatngo/gowhere\"\n\n// initialize with all available configurations\nplan := gowhere.WithConfig(gowhere.Config{\n    Separator: \"__\",\n    Dialect: gowhere.DialectPostgreSQL,\n    Strict: true,\n    Table: \"\",\n    ColumnAliases: map[string]string{},\n    CustomConditions: map[string]CustomConditionFn{\n        \"search\": func(key string, val interface{}, cfg *gowhere.Config) interface{} {\n            val = \"%\" + val.(string) + \"%\"\n            return []interface{}{\"lower(full_name) like ? OR lower(title) like ?\", val, val}\n        },\n    },\n})\n\n// modify the config on the demands\nplan.SetTable(\"trips\").SetColumnAliases(map[string]string{\"name\": \"full_name\"})\n\n// a map will be translated to \"AND\" conditions\nplan.Where(map[string]interface{}{\n    \"name__contains\": \"Gopher\",\n    \"budget__gte\": 1000,\n})\n\n// a slice will be \"OR\" conditions\nplan.Where([]map[string]interface{}{\n    {\"started_at__date\": \"2019-04-13\"},\n    {\"started_at__date\": \"2019-04-15\"},\n    {\"started_at__gte\": time.Date(2019, 4, 19, 0, 0, 0, 0, time.Local)},\n})\n\n// same as `Where`, `Not` receives either map, slice or raw SQL string. Then it simply wraps the conditions with \"NOT\" keyword\nplan.Not(\"members \u003c ? AND members \u003e ?\", 2, 10)\n\n// `Or` be like: ((all_current_conditions) OR (new_conditions))\nplan.Or(\"anywhere = TRUE\")\n\n// In \"Strict\" mode, any invalid conditions/operators if given will cause `InvalidCond` error. Not to mention the not-tested runtime errors :)\nif err := plan.Build().Error; err != nil {\n    panic(err)\n}\n\nplan.SQL()\n// (((\"trips\".\"full_name\" LIKE ? AND \"trips\".\"budget\" \u003e= ?) AND ((DATE(\"trips\".\"started_at\") = ?) OR (DATE(\"trips\".\"started_at\") = ?) OR (\"trips\".\"started_at\" \u003e= ?)) AND NOT (members \u003c ? AND members \u003e ?)) OR (anywhere = TRUE))\n\nplan.Vars()\n// [%Gopher% 1000 2019-04-13 2019-04-15 2019-04-19 2 10]\n```\n\n## Operator\n\nFor example: `\"name__startswith\"`, `name` is the field(column) and `startswith` is the operator. Django developer might find this familiar ;)\n\nOperator is an user friendly name for a specific SQL operator. It's a suffix which added into the field to reduce the complexity from input schema, yet flexible enough to generate complex conditions.\n\nOperator is optional. If not given, it's set to:\n\n- `isnull` if the value is `nil`. E.g: `{\"name\": nil}` =\u003e sql, vars: `name IS NULL, []`\n- `in` if the value is slice or array. E.g: `{\"id\": []int{1, 2, 3}}` =\u003e `id in (?), [[1 2 3]]`\n- `exact` if otherwise. E.g: `{\"name\": \"Gopher\"}` =\u003e `name = ?, [Gopher]`\n\nBuilt-in operators:\n\n- `exact`: Exact match, using `=` operator.\n- `iexact`: Case-insensitive exact match, wrap both column and value with `lower()` function.\n- `notexact`: Opposite of `exact`\n- `notiexact`: Opposite of `iexact`\n- `gt`: Greater than\n- `gte`: Greater than or equal to\n- `lt`: Less than\n- `lte`: Less than or equal to\n- `startswith`: Case-sensitive starts-with, auto cast value to string with `%` suffix\n- `istartswith`: Case-insensitive starts-with\n- `endswith`: Case-sensitive ends-with, auto cast value to string with `%` prefix\n- `iendswith`: Case-insensitive ends-with\n- `contains`: Case-insensitive containment test, auto cast value to string with both `%` suffix, prefix\n- `icontains`: Case-sensitive containment test\n- `in`: In a given slice, array\n- `date`: For datetime fields, casts the value as date\n- `between`: For datetime string fields, range test\n- `isnull`: Takes either True or False, which correspond to SQL\n  queries of IS NULL and IS NOT NULL, respectively.\n- `datebetween`: For query datetime range fields\n\n## TODO\n\n- [x] Publish!\n- [x] Ability to add custom operators\n- [x] Ability to add custom conditions\n- [ ] Full tests with 100% code coverage\n- [ ] Manipulate the conditions? Such as `HasCondition()`, `UpdateCondition()`, `RemoveCondition()`?\n\n## License\n\n© Dat Ngo, 2019~time.Now()\n\nReleased under the [MIT License](./LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimdatngo%2Fgowhere","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimdatngo%2Fgowhere","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimdatngo%2Fgowhere/lists"}