8000 GitHub - bluebrown/mql: Model Query Language (mql) is a query language for your database models.
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
/ mql Public
forked from hashicorp/mql

Model Query Language (mql) is a query language for your database models.

License

Notifications You must be signed in to change notification settings

bluebrown/mql

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MQL

Go Reference Go Report Card Go Coverage

The mql (Model Query Language) Go package provides a language that end users can use to query your database models, without them having to learn SQL or exposing your application to SQL injection.

Examples

w, err := mql.Parse("name=alice or name=bob)",User{})
if err != nil {
  return nil, err
}
err = db.Where(w.Condition, w.Args...).Find(&users).Error
w, err := mql.Parse("name=alice or name=bob)",User{}, mql.WithPgPlaceholders())
if err != nil {
  return nil, err
}
q := fmt.Sprintf("select * from users where %s", w.Condition)
rows, err := db.Query(q, w.Args...)
w, err := mql.Parse("name=alice or name=bob)",User{})
if err != nil {
  return nil, err
}
err := rw.SearchWhere(ctx, &users, w.Condition, w.Args)

Some bits about usage

First, you define a model you wish to query as a Go struct and then provide a mql query. The package then uses the query along with a model to generate a parameterized SQL where clause.

Fields in your model can be compared with the following operators: =, !=, >=, <=, <, >, % .

Double quotes " can be used to quote strings.

Comparison operators can have optional leading/trailing whitespace.

The % operator allows you to do partial string matching using LIKE "%value%". This matching is case insensitive.

The = equality operator is case insensitive when used with string fields.

Comparisons can be combined using: and, or.

More complex queries can be created using parentheses.

See GRAMMAR.md for a more complete documentation of mql's grammar.

Example query:

name=alice and age > 11 and (region % Boston or region="south shore")

Date/Time fields

If your model contains a time.Time field, then we'll append ::date to the column name when generating a where clause and the comparison value must be in an ISO-8601 format.

Note: It's possible to compare date-time fields down to the millisecond using ::date and a literal in ISO-8601 format.

Currently, this is the only supported way to compare dates, if you need something different then you'll need to provide your own custom validator/converter via WithConverter(...) when calling mql.Parse(...).

We provide default validation+conversion of fields in a model when parsing and generating a WhereClause. You can provide optional validation+conversion functions for fields in your model via WithConverter(...).

Example date comparison down to the HH::MM using an ISO-8601 format:

name=alice and created_at>"2023-12-01 14:01"

Mapping column names

You can also provide an optional map from query column identifiers to model field names via WithColumnMap(...) if needed.

Example WithColumnMap(...) usage:

type User {
    FullName string
}

// map the column alice to field name FullName
columnMap := map[string]string{
    "name": "FullName",
}

w, err := mql.Parse(
    "name=alice",
    User{}, 
    mql.WithColumnMap(columnMap))

if err != nil {
    return nil, err
}

Ignoring fields

If your model (Go struct) has fields you don't want users searching then you can optionally provide a list of columns to be ignored via WithIgnoreFields(...)

Example WithIgnoreFields(...) usage:

type User {
    Name string
    CreatedAt time.Time
    UpdatedAt time.Time
}

// you want to keep users from using queries that include the user fields
// of: created_at updated_at
w, err := mql.Parse(
    "name=alice",
    User{}, 
    mql.WithIgnoreFields("CreatedAt", "UpdatedAt"))

if err != nil {
    return nil, err
}

Custom converters/validators

Sometimes the default out-of-the-box bits doesn't fit your needs. If you need to override how expressions (column name, operator and value) is converted and validated during the generation of a WhereClause, then you can optionally provide your own validator/convertor via WithConverter(...)

Example WithConverter(...) usage:

// define a converter for mySQL dates
mySQLDateConverter := func(columnName string, comparisonOp mql.ComparisonOp, value *string) (*mql.WhereClause, error) {
  // you should add some validation of function parameters here.
  return &mql.WhereClause{
    Condition: fmt.Sprintf("%s%sSTR_TO_DATE(?)", columnName, comparisonOp),
    Args:      []any{*value},
  }, nil
}

w, err := mql.Parse(
    `name=alice and created_at > "2023-06-18"`,
    User{}, 
    mql.WithConverter("CreatedAt", mySqlDateConverter))

if err != nil {
    return nil, err
}

Grammar

See: GRAMMAR.md

Security

Please note: We take security and our users' trust very seriously. If you believe you have found a security issue, please responsibly disclose by contacting us at security@hashicorp.com.

Contributing

Thank you for your interest in contributing! Please refer to CONTRIBUTING.md for guidance.

About

Model Query Language (mql) is a query language for your database models.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 57.8%
  • HTML 38.7%
  • Shell 2.4%
  • Other 1.1%
0