rql

package module
v1.3.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2020 License: MIT Imports: 17 Imported by: 0

README

Resource Query Language

This library is based on another go rql implementation.

This supports positional parameters and other features required by atomic tools and libraries.

Documentation

Index

Constants

View Source
const (
	EQ   = Op("eq")   // =
	NEQ  = Op("neq")  // <>
	LT   = Op("lt")   // <
	GT   = Op("gt")   // >
	LTE  = Op("lte")  // <=
	GTE  = Op("gte")  // >=
	LIKE = Op("like") // LIKE "PATTERN"
	OR   = Op("or")   // disjunction
	AND  = Op("and")  // conjunction
)

Operators that support by rql.

View Source
const (
	DefaultTagName     = "rql"
	DefaultOpPrefix    = "$"
	DefaultFieldSep    = "_"
	DefaultLimit       = 25
	DefaultMaxLimit    = 100
	DefaultParamOffset = 1
	DefaultParamSymbol = "?"
	Offset             = "offset"
	Limit              = "limit"
)

Default values for configuration.

Variables

This section is empty.

Functions

func Column

func Column(s string) string

Column is the default function that converts field name into a database column. It used to convert the struct fields into their database names. For example:

Username => username
FullName => full_name
HTTPCode => http_code

Types

type Config

type Config struct {
	// TagName is an optional tag name for configuration. t defaults to "rql".
	TagName string
	// Model is the resource definition. The parser is configured based on the its definition.
	// For example, given the following struct definition:
	//
	//	type User struct {
	//		Age	 int	`rql:"filter,sort"`
	// 		Name string	`rql:"filter"`
	// 	}
	//
	// In order to create a parser for the given resource, you will do it like so:
	//
	//	var QueryParser = rql.MustNewParser(
	// 		Model: User{},
	// 	})
	//
	Model interface{}
	// OpPrefix is the prefix for operators. it defaults to "$". for example, in order
	// to use the "gt" (greater-than) operator, you need to prefix it with "$".
	// It similar to the MongoDB query language.
	OpPrefix string
	// FieldSep is the separator for nested fields in a struct. For example, given the following struct:
	//
	//	type User struct {
	// 		Name 	string	`rql:"filter"`
	//		Address	struct {
	//			City string `rql:"filter"“
	//		}
	// 	}
	//
	// We assume the schema for this struct contains a column named "address_city". Therefore, the default
	// separator is underscore ("_"). But, you can change it to "." for convenience or readability reasons.
	// Then you will be able to query your resource like this:
	//
	//	{
	//		"filter": {
	//			"address.city": "DC"
	// 		}
	//	}
	//
	// The parser will automatically convert it to underscore ("_"). If you want to control the name of
	// the column, use the "column" option in the struct definition. For example:
	//
	//	type User struct {
	// 		Name 	string	`rql:"filter,column=full_name"`
	// 	}
	//
	FieldSep string
	// ColumnFn is the function that translate the struct field string into a table column.
	// For example, given the following fields and their column names:
	//
	//	FullName => "full_name"
	// 	HTTPPort => "http_port"
	//
	// It is preferred that you will follow the same convention that your ORM or other DB helper use.
	// For example, If you are using `gorm` you want to se this option like this:
	//
	//	var QueryParser = rql.MustNewParser(
	// 		ColumnFn: gorm.ToDBName,
	// 	})
	//
	ColumnFn func(string) string
	// Log the the logging function used to log debug information in the initialization of the parser.
	// It defaults `to log.Printf`.
	Log func(string, ...interface{})
	// DefaultLimit is the default value for the `Limit` field that returns when no limit supplied by the caller.
	// It defaults to 25.
	DefaultLimit int
	// LimitMaxValue is the upper boundary for the limit field. User will get an error if the given value is greater
	// than this value. It defaults to 100.
	LimitMaxValue int
	// DefaultSort is the default value for the 'Sort' field that returns when no sort expression is supplied by the caller.
	// It defaults to an empty string slice.
	DefaultSort []string
	// ParamSymbol is the placehold for parameters in the Filter expression the default is '?', postgres for example uses '$'
	ParamSymbol string
	// PositionalParams if true will append a numerical suffix to the ParamSymbol, i.e. ?1, ?2, etc.
	PositionalParams bool
	// ParamOffset is the zero-based parameter offset added to positional parameters
	// This allows the parameters to begin at another offeset and useful when the FilterExp falls after other arguments
	// manually numbered in the SQL statement, the default is 1
	ParamOffset int
}

Config is the configuration for the parser.

type Filter

type Filter map[string]interface{}

Filter is as filter object

type Op

type Op string

Op is a filter operator used by rql.

func (Op) SQL

func (o Op) SQL() string

SQL returns the SQL representation of the operator.

type Params

type Params struct {
	// Limit represents the number of rows returned by the SELECT statement.
	Limit int
	// Offset specifies the offset of the first row to return. Useful for pagination.
	Offset int
	// Select contains the expression for the `SELECT` clause defined in the Query.
	Select string
	// Sort used as a parameter for the `ORDER BY` clause. For example, "age desc, name".
	Sort string
	// FilterExp and FilterArgs come together and used as a parameters for the `WHERE` clause.
	//
	// examples:
	// 	1. Exp: "name = ?"
	//	   Args: "a8m"
	//
	//	2. Exp: "name = ? AND age >= ?"
	// 	   Args: "a8m", 22
	FilterExp  string
	FilterArgs []interface{}
	// PositionalParams if true will append a numerical suffix to the ParamSymbol, i.e. ?1, ?2, etc.
	PositionalParams bool
	// ParamSymbol is the placehold for parameters in the Filter expression the default is '?', postgres for example uses '$'
	ParamSymbol string
}

Params is the parser output after calling to `Parse`. You should pass its field values to your query tool. For example, Suppose you use `gorm`:

params, err := p.Parse(b)
if err != nil {
	return nil, err
}
var users []User
err := db.Where(params.FilterExp, params.FilterArgs...).
	Order(params.Sort).
	Find(&users).
	Error
if err != nil {
	return nil, err
}
return users, nil

func (Params) Build added in v1.3.2

func (p Params) Build(table string) string

Build builds a sql string

type ParseError

type ParseError struct {
	// contains filtered or unexported fields
}

ParseError is type of error returned when there is a parsing problem.

func (ParseError) Error

func (p ParseError) Error() string

type Parser

type Parser struct {
	Config
	// contains filtered or unexported fields
}

A Parser parses various types. The result from the Parse method is a Param object. It is safe for concurrent use by multiple goroutines except for configuration changes.

func MustNewParser

func MustNewParser(c Config) *Parser

MustNewParser is like NewParser but panics if the configuration is invalid. It simplifies safe initialization of global variables holding a resource parser.

func NewParser

func NewParser(c Config) (*Parser, error)

NewParser creates a new Parser. it fails if the configuration is invalid.

func (*Parser) Parse

func (p *Parser) Parse(b []byte) (pr *Params, err error)

Parse parses the given buffer into a Param object. It returns an error if the JSON is invalid, or its values don't follow the schema of rql.

func (*Parser) ParseQuery

func (p *Parser) ParseQuery(q *Query) (pr *Params, err error)

ParseQuery parses the given struct into a Param object. It returns an error if one of the query values don't follow the schema of rql.

type Query

type Query struct {
	// Limit must be > 0 and <= to `LimitMaxValue`.
	Limit int `json:"limit,omitempty"`
	// Offset must be >= 0.
	Offset int `json:"offset,omitempty"`
	// Select contains the list of expressions define the value for the `SELECT` clause.
	// For example:
	//
	//	params, err := p.Parse([]byte(`{
	//		"select": ["name", "age"]
	//	}`))
	//
	Select []string `json:"select,omitempty"`
	// Sort contains list of expressions define the value for the `ORDER BY` clause.
	// In order to return the rows in descending order you can prefix your field with `-`.
	// For example:
	//
	//	params, err := p.Parse([]byte(`{
	//		"sort": ["name", "-age", "+redundant"]
	//	}`))
	//
	Sort []string `json:"sort,omitempty"`
	// Filter is the query object for building the value for the `WHERE` clause.
	// The full documentation of the supported operators is writtern in the README.
	// An example for filter object:
	//
	//	params, err := p.Parse([]byte(`{
	//		"filter": {
	//			"account": { "$like": "%github%" },
	//			"$or": [
	//				{ "city": "TLV" },
	//				{ "city": "NYC" }
	//			]
	//		}
	//	}`))
	//
	Filter Filter `json:"filter,omitempty"`
}

Query is the decoded result of the user input.

func NewQuery added in v1.3.4

func NewQuery(filter ...interface{}) *Query

NewQuery builds a query from the key, value,....passed

func (Query) MarshalEasyJSON

func (v Query) MarshalEasyJSON(w *jwriter.Writer)

MarshalEasyJSON supports easyjson.Marshaler interface

func (Query) MarshalJSON

func (v Query) MarshalJSON() ([]byte, error)

MarshalJSON supports json.Marshaler interface

func (*Query) UnmarshalEasyJSON

func (v *Query) UnmarshalEasyJSON(l *jlexer.Lexer)

UnmarshalEasyJSON supports easyjson.Unmarshaler interface

func (*Query) UnmarshalJSON

func (v *Query) UnmarshalJSON(data []byte) error

UnmarshalJSON supports json.Unmarshaler interface

func (*Query) WithFilter added in v1.3.4

func (q *Query) WithFilter(f Filter) *Query

WithFilter sets the filter

func (*Query) WithLimit added in v1.3.4

func (q *Query) WithLimit(limit int) *Query

WithLimit sets the limit

func (*Query) WithOffset added in v1.3.4

func (q *Query) WithOffset(off int) *Query

WithOffset sets the offset

func (*Query) WithSelect added in v1.3.4

func (q *Query) WithSelect(sel []string) *Query

WithSelect sets the sorting

func (*Query) WithSort added in v1.3.4

func (q *Query) WithSort(sort []string) *Query

WithSort sets the sorting

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL