Documentation
¶
Overview ¶
Package mql 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 ¶
Gorm: https://github.com/go-gorm/gorm
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
database/sql: https://pkg.go.dev/database/sql
w, err := mql.Parse(`name="alice" or name="bob"`,User{}) if err != nil { return nil, err } q := fmt.Sprintf("select * from users where %s", w.Condition) rows, err := db.Query(q, w.Args...)
go-dbw: https://github.com/hashicorp/go-dbw
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)
Simple Usage ¶
You define a model you wish to query as a Go struct and 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: =, !=, >=, <=, <, >, %
Strings must be quoted. Double quotes ", single quotes ' or backticks ` can be used as delimiters. Users can choose whichever supported delimiter makes it easier to quote their string.
Comparison operators can have optional leading/trailing whitespace.
The % operator allows you to do partial string matching using LIKE and 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]: https://github.com/hashicorp/mql/blob/main/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")
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInternal = errors.New("internal error") ErrInvalidParameter = errors.New("invalid parameter") ErrInvalidNotEqual = errors.New(`invalid "!=" token`) ErrMissingExpr = errors.New("missing expression") ErrUnexpectedExpr = errors.New("unexpected expression") ErrUnexpectedClosingParen = errors.New("unexpected closing paren") ErrMissingClosingParen = errors.New("missing closing paren") ErrUnexpectedOpeningParen = errors.New("unexpected opening paren") ErrUnexpectedLogicalOp = errors.New("unexpected logical operator") ErrUnexpectedToken = errors.New("unexpected token") ErrInvalidComparisonOp = errors.New("invalid comparison operator") ErrMissingComparisonOp = errors.New("missing comparison operator") ErrMissingColumn = errors.New("missing column") ErrInvalidLogicalOp = errors.New("invalid logical operator") ErrMissingLogicalOp = errors.New("missing logical operator") ErrMissingRightSideExpr = errors.New("logical operator without a right side expr") ErrMissingComparisonValue = errors.New("missing comparison value") ErrInvalidColumn = errors.New("invalid column") ErrInvalidNumber = errors.New("invalid number") ErrInvalidComparisonValueType = errors.New("invalid comparison value type") ErrMissingEndOfStringTokenDelimiter = errors.New("missing end of stringToken delimiter") ErrInvalidTrailingBackslash = errors.New("invalid trailing backslash") ErrInvalidDelimiter = errors.New("invalid delimiter") )
Functions ¶
This section is empty.
Types ¶
type ComparisonOp ¶
type ComparisonOp string
ComparisonOp defines a set of comparison operators
const ( GreaterThanOp ComparisonOp = ">" GreaterThanOrEqualOp ComparisonOp = ">=" LessThanOp ComparisonOp = "<" LessThanOrEqualOp ComparisonOp = "<=" EqualOp ComparisonOp = "=" NotEqualOp ComparisonOp = "!=" ContainsOp ComparisonOp = "%" )
type Option ¶
type Option func(*options) error
Option - how options are passed as args
func WithColumnFieldTag ¶ added in v0.1.5
WithColumnFieldTag provides an optional struct tag to use for field mapping If a field has this tag, the tag value will be used instead of the field name
func WithColumnMap ¶
WithColumnMap provides an optional map of columns from the user provided query to a field in the given model
func WithConverter ¶
func WithConverter(fieldName string, fn ValidateConvertFunc) Option
WithConverter provides an optional ConvertFunc for a column identifier in the query. This allows you to provide whatever custom validation+conversion you need on a per column basis. See: DefaultValidateConvert(...) for inspiration.
func WithIgnoredFields ¶
WithIgnoredFields provides an optional list of fields to ignore in the model (your Go struct) when parsing. Note: Field names are case sensitive.
func WithPgPlaceholders ¶ added in v0.1.1
func WithPgPlaceholders() Option
WithPgPlaceholders will use parameters placeholders that are compatible with the postgres pg driver which requires a placeholder like $1 instead of ?. See:
func WithTableColumnMap ¶ added in v0.1.5
WithTableColumnMap provides an optional map of columns from the model to the table.column name in the generated where clause
For example, if you need to map the language field name to something more complex in your SQL statement then you can use this map:
WithTableColumnMap(map[string]string{"language":"preferences->>'language'"})
In the example above we're mapping "language" field to a json field in the "preferences" column. A user can say `language="blah"` and the mql-created SQL where clause will contain `preferences->>'language'="blah"`
The field names in the keys to the map should always be lower case.
type ValidateConvertFunc ¶
type ValidateConvertFunc func(columnName string, comparisonOp ComparisonOp, value *string) (*WhereClause, error)
ValidateConvertFunc validates the value and then converts the columnName, comparisonOp and value to a WhereClause
type WhereClause ¶
type WhereClause struct { // Condition is the where clause condition Condition string // Args for the where clause condition Args []any }
WhereClause contains a SQL where clause condition and its arguments.