{"id":13413717,"url":"https://github.com/hashicorp/mql","last_synced_at":"2025-10-14T09:40:02.958Z","repository":{"id":186907505,"uuid":"673937803","full_name":"hashicorp/mql","owner":"hashicorp","description":"Model Query Language (mql) is a query language for your database models.","archived":false,"fork":false,"pushed_at":"2025-03-07T13:00:25.000Z","size":191,"stargazers_count":54,"open_issues_count":3,"forks_count":12,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-09T19:19:00.794Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hashicorp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-02T19:05:45.000Z","updated_at":"2025-03-04T14:20:34.000Z","dependencies_parsed_at":"2023-08-08T07:37:18.863Z","dependency_job_id":"e1247eeb-0626-456e-8bf9-a803a5323e62","html_url":"https://github.com/hashicorp/mql","commit_stats":{"total_commits":54,"total_committers":9,"mean_commits":6.0,"dds":"0.18518518518518523","last_synced_commit":"206112480088724e117fce8b79de555c84636897"},"previous_names":["hashicorp/mql"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hashicorp%2Fmql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hashicorp%2Fmql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hashicorp%2Fmql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hashicorp%2Fmql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hashicorp","download_url":"https://codeload.github.com/hashicorp/mql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094990,"owners_count":21046770,"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":[],"created_at":"2024-07-30T20:01:47.291Z","updated_at":"2025-10-14T09:40:02.953Z","avatar_url":"https://github.com/hashicorp.png","language":"Go","readme":"# MQL\n[![Go\nReference](https://pkg.go.dev/badge/github.com/hashicorp/mql/mql.svg)](https://pkg.go.dev/github.com/hashicorp/mql)\n[![Go Report\nCard](https://goreportcard.com/badge/github.com/hashicorp/mql)](https://goreportcard.com/report/github.com/hashicorp/mql)\n[![Go Coverage](https://raw.githack.com/hashicorp/mql/main/coverage/coverage.svg)](https://raw.githack.com/hashicorp/mql/main/coverage/coverage.html)\n\nThe [mql](https://pkg.go.dev/github.com/hashicorp/mql) (Model Query Language) Go package provides a language that end users can use to query your\ndatabase models, without them having to learn SQL or exposing your\napplication to SQL injection.\n\n## Examples\n\n### [github.com/go-gorm/gorm](https://github.com/go-gorm/gorm)\n\n```Go\nw, err := mql.Parse(`name=\"alice\" or name=\"bob\"`,User{})\nif err != nil {\n  return nil, err\n}\nerr = db.Where(w.Condition, w.Args...).Find(\u0026users).Error\n```\n\n### [database/sql](https://pkg.go.dev/database/sql)\n\n```Go\nw, err := mql.Parse(`name=\"alice\" or name=\"bob\"`,User{}, mql.WithPgPlaceholders())\nif err != nil {\n  return nil, err\n}\nq := fmt.Sprintf(\"select * from users where %s\", w.Condition)\nrows, err := db.Query(q, w.Args...)\n```\n\n### [github.com/hashicorp/go-dbw](https://github.com/hashicorp/go-dbw)\n\n```Go\nw, err := mql.Parse(`name=\"alice\" or name=\"bob\")`,User{})\nif err != nil {\n  return nil, err\n}\nerr := rw.SearchWhere(ctx, \u0026users, w.Condition, w.Args)\n```\n\n## Some bits about usage\n\nFirst, you define a model you wish to query as a Go `struct` and then provide a [mql]((https://pkg.go.dev/badge/github.com/hashicorp/mql/mql.svg))\nquery. The package then uses the query along with a model to generate a\nparameterized SQL where clause.\n\nFields in your model can be compared with the following operators: `=`, `!=`,\n`\u003e=`, `\u003c=`, `\u003c`, `\u003e`, `%` .\n\nStrings must be quoted. Double quotes `\"`, single quotes `'` or backticks ``\n` `` can be used as delimiters.  Users can choose whichever supported delimiter\nmakes it easier to quote their string.\n\nComparison operators can have optional leading/trailing whitespace.\n\nThe `%` operator allows you to do partial string matching using LIKE \"%value%\". This\nmatching is case insensitive.\n\nThe `=` equality operator is case insensitive when used with string fields.\n\nComparisons can be combined using: `and`, `or`.\n\nMore complex queries can be created using parentheses.\n\nSee [GRAMMAR.md](./GRAMMAR.md) for a more complete documentation of [mql](https://pkg.go.dev/github.com/hashicorp/mql)'s grammar.\n\nExample query:\n\n`name=\"alice\" and age \u003e 11 and (region % 'Boston' or region=\"south shore\")`\n\n### Date/Time fields\n\nIf your model contains a time.Time field, then we'll append `::date` to the\ncolumn name when generating a where clause and the comparison value must be in\nan `ISO-8601` format.\n\nNote: It's possible to compare date-time fields down to the\nmillisecond using `::date` and a literal in `ISO-8601` format.\n\nCurrently, this is the only supported way to compare\ndates, if you need something different then you'll need to provide your own\ncustom validator/converter via\n[WithConverter(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithConverter)\nwhen calling\n[mql.Parse(...)](https://pkg.go.dev/github.com/hashicorp/mql#Parse).\n\nWe provide default validation+conversion of fields in a model when parsing\nand generating a\n[WhereClause](https://pkg.go.dev/github.com/hashicorp/mql#WhereClause).  You can\nprovide optional validation+conversion functions for fields in your model via\n[WithConverter(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithConverter).\n\nExample date comparison down to the HH::MM using an ISO-8601 format:\n\n`name=\"alice\" and created_at\u003e\"2023-12-01 14:01\"`\n\nNote: Expressions with the same level of precedence are evaluated right to left.\nExample:\n`name=\"alice\" and age \u003e 11 and region =\n\"Boston\"` is evaluated as: `name=\"alice\" and (age \u003e 11 and region =\n\"Boston\")`\n\n\n\n### Mapping field names\n\nYou can also provide an optional map from query column identifiers to model\nfield names via\n[WithColumnMap(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithColumnMap)\nif needed.\n\nExample\n[WithColumnMap(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithColumnMap)\nusage:\n\n``` Go\ntype User struct {\n    FullName string\n}\n\n// map the column alice to field name FullName\ncolumnMap := map[string]string{\n    \"name\": \"FullName\",\n}\n\nw, err := mql.Parse(\n    `name=\"alice\"`,\n    User{},\n    mql.WithColumnMap(columnMap))\n\nif err != nil {\n    return nil, err\n}\n```\n\n### Mapping via struct tags\n\nYou can use struct tags to map model fields to column names by using\n[WithColumnFieldTag(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithColumnFieldTag).\nThis allows you to define the mapping in your struct definition rather than at query time.\n\nExample\n[WithColumnFieldTag(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithColumnFieldTag)\nusage:\n\n``` Go\ntype User struct {\n    Name string `db:\"full_name\"`\n}\n\nw, err := mql.Parse(\n    `Name=\"alice\"`,\n    User{},\n    mql.WithColumnFieldTag(\"db\"))\n\nif err != nil {\n    return nil, err\n}\n\nfmt.Print(w.Condition) // prints full_name=?\n```\n\n### Mapping output column names\n\nYou can also provide an optional map from model field names to output column\nnames via\n[WithTableColumnMap(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithTableColumnMap)\nif needed.\n\nExample\n[WithTableColumnMap(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithTableColumnMap)\nusage:\n\n``` Go\ntype User struct {\n    FullName string\n}\n\n// map the field name FullName to column \"u.fullname\"\ntableColumnMap := map[string]string{\n    \"fullname\": \"u.fullname\",\n}\n\nw, err := mql.Parse(\n    `FullName=\"alice\"`,\n    User{},\n    mql.WithTableColumnMap(tableColumnMap))\n\nif err != nil {\n    return nil, err\n}\n\nfmt.Print(w.Condition) // prints u.fullname=?\n```\n\n### Ignoring fields\n\nIf your model (Go struct) has fields you don't want users searching then you can\noptionally provide a list of columns to be ignored via [WithIgnoreFields(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithIgnoreFields)\n\nExample\n[WithIgnoreFields(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithIgnoreFields)\nusage:\n\n```Go\ntype User {\n    Name string\n    CreatedAt time.Time\n    UpdatedAt time.Time\n}\n\n// you want to keep users from using queries that include the user fields\n// of: created_at updated_at\nw, err := mql.Parse(\n    `name=\"alice\"`,\n    User{},\n    mql.WithIgnoreFields(\"CreatedAt\", \"UpdatedAt\"))\n\nif err != nil {\n    return nil, err\n}\n```\n\n### Custom converters/validators\n\nSometimes the default out-of-the-box bits doesn't fit your needs.  If you need to\noverride how expressions (column name, operator and value) is converted and\nvalidated during the generation of a\n[WhereClause](https://pkg.go.dev/github.com/hashicorp/mql#WhereClause), then\nyou can optionally\nprovide your own validator/convertor via\n[WithConverter(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithConverter)\n\nExample\n[WithConverter(...)](https://pkg.go.dev/github.com/hashicorp/mql#WithConverter)\nusage:\n\n``` Go\n// define a converter for mySQL dates\nmySQLDateConverter := func(columnName string, comparisonOp mql.ComparisonOp, value *string) (*mql.WhereClause, error) {\n  // you should add some validation of function parameters here.\n  return \u0026mql.WhereClause{\n    Condition: fmt.Sprintf(\"%s%sSTR_TO_DATE(?)\", columnName, comparisonOp),\n    Args:      []any{*value},\n  }, nil\n}\n\nw, err := mql.Parse(\n    `name=\"alice\" and created_at \u003e \"2023-06-18\"`,\n    User{},\n    mql.WithConverter(\"CreatedAt\", mySqlDateConverter))\n\nif err != nil {\n    return nil, err\n}\n\n```\n\n### Grammar\n\nSee: [GRAMMAR.md](./GRAMMAR.md)\n\n\n## Security\n\n**Please note**: We take security and our users' trust very seriously. If you\nbelieve you have found a security issue, please *[responsibly\ndisclose](https://www.hashicorp.com/security#vulnerability-reporting)* by\ncontacting us at  security@hashicorp.com.\n## Contributing\n\nThank you for your interest in contributing! Please refer to\n[CONTRIBUTING.md](https://github.com/hashicorp/mql/blob/main/CONTRIBUTING.md)\nfor guidance.\n","funding_links":[],"categories":["Query Language","查询语言"],"sub_categories":["HTTP Clients","HTTP客户端"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhashicorp%2Fmql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhashicorp%2Fmql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhashicorp%2Fmql/lists"}