queryp

package module
v0.3.6 Latest Latest
Warning

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

Go to latest
Published: May 19, 2023 License: MIT Imports: 6 Imported by: 5

README

QueryP

GoDoc

This is a Go library for generating (mostly) database agnostic query parameters with:

  • Filter
  • Sort
  • Limit/Offsets

Parsing

The library also supports parsing a string with a specific format into the query parameters. It's most useful as a library for parsing GET-like query parameters.

For example:

field1=value1&(field2=value2|field3=value3)&limit=10&offset=10&sort=name,-description

Get all things where field1=value1 AND ( field2=value2 OR field3=value3 ) sort by name ascending, description descending limit to 10 records and skip the first 10

Supported Operators:

* &		- Logic AND (as well as splitting operators)
* |		- Logic OR

* =     - Exactly Equals
* !=    - Not Equals
* < 	- Less Than
* >		- Greater Than
* <=	- Less than or equals
* >=	- Greater than or equals
* =~	- Like (supports % wildcards)
* !=~   - Not Like (supports % wildcards)
* =~~   - Like case-insensitive (supports % wildcards)
* !=~~	- Not Like case-insensitive (supports % wildcards)
* :		- Regular Expression Match
* !:	- Not Regular Expression Match
* :~	- Regular Expression Match (case-insensitive
* !:~	- Not Regular Expression Match (case-insensitive)
* @     - Bits are set (for numeric values)
* @~    - Bits are clear (for numeric values)

* ()	- Parenthesis can be use for precedence.

Drivers

Database drivers are built into the package

  • qppg - Postgres syntax driver

Usage

queryString := "field1=value1&(field2=value2|field3=value3)&limit=10&offset=10&sort=name,-description"

qp, err := queryp.ParseQuery(queryString)
if err != nil {
	log.Fatal(err)
}

var queryClause strings.Builder
var queryParams = []interface{}{}

// Fields we are allowed to filter by
filterFields := queryp.FilterFieldTypes{
	"table_name.thing_id":          queryp.FilterTypeSimple, // Simple matching good for equal/not equal
	"table_name.thing_name":        queryp.FilterTypeString, // Matching with like and regexp
	"table_name.created":           queryp.FilterTypeTime,   // Matching based on times
	"table_name.exists":            queryp.FilterTypeBool,   // Supports true/false only
	"table_name.quantity":          queryp.FilterTypeNumeric,// Supports numeric comparisons
	"someotherfield":               queryp.FilterFieldCustom{FieldName: "whoathird", FilterType: queryp.FilterTypeString}, // Use one field name in URL and another for database field
}

// Fields we are allowed to sort by
sortFields := queryp.SortFields{
	"source.source_id",
	"source.source_name",
}

// Default sort if none specified
if len(qp.Sort) == 0 {
	qp.Sort = queryp.Sort{queryp.SortTerm{Field: "source.source_name", Desc: false}}
}

// If we will filter
if len(qp.Filter) > 0 {
	queryClause.WriteString(" WHERE ")
}

// Generate the WHERE criteria for postgres
if err := qppg.FilterQuery(filterFields, qp.Filter, &queryClause, &queryParams); err != nil {
	return nil, 0, err
}

// Generate the sort criteria at the end of the query clause 
if err := qppg.SortQuery(sortFields, qp.Sort, &queryClause, &queryParams); err != nil {
	return nil, 0, err
}

// Append limit and offset if specified
if qp.Limit > 0 {
	queryClause.WriteString(" LIMIT " + strconv.Itoa(qp.Limit))
}
if qp.Offset > 0 {
	queryClause.WriteString(" OFFSET " + strconv.Itoa(qp.Offset))
}

query, err := db.Query("SELECT * FROM table_name "+queryClause.String(), queryParams...)
if err != nil {
	log.Fatal(err)
}

Thanks

Special thanks to my employer https://geneticnetworks.com for letting me work on this and open source it.

Documentation

Index

Constants

View Source
const (
	FilterLogicAnd FilterLogic = 0
	FilterLogicOr  FilterLogic = 1

	FilterLogicSymAnd = "&"
	FilterLogicSymOr  = "|"

	ValueNeedsQuote = `&|)"`
)
View Source
const (
	FilterOpEquals           FilterOp = 0
	FilterOpNotEquals        FilterOp = 1
	FilterOpLessThan         FilterOp = 2
	FilterOpLessThanEqual    FilterOp = 3
	FilterOpGreaterThan      FilterOp = 4
	FilterOpGreaterThanEqual FilterOp = 5
	FilterOpLike             FilterOp = 6
	FilterOpNotLike          FilterOp = 7
	FilterOpILike            FilterOp = 8
	FilterOpNotILike         FilterOp = 9
	FilterOpRegexp           FilterOp = 10
	FilterOpNotRegexp        FilterOp = 11
	FilterOpIRegexp          FilterOp = 12
	FilterOpNotIRegexp       FilterOp = 13
	FilterOpBitsSet          FilterOp = 14
	FilterOpBitsClear        FilterOp = 15

	FilterOpSymEquals      = "="
	FilterOpSymNotEquals   = "!="
	FilterOpSymLessThan    = "<"
	FilterOpSymGreaterThan = ">"

	FilterOpSymLessThanEqual     = "<="
	FilterOpSymLessThanEqual2    = "=<"
	FilterOpSymGreaterThanEqual  = ">="
	FilterOpSymGreaterThanEqual2 = "=>"

	FilterOpSymLike     = "=~"
	FilterOpSymNotLike  = "!=~"
	FilterOpSymILike    = "=~~"
	FilterOpSymNotILike = "!=~~"

	FilterOpSymRegexp     = ":"
	FilterOpSymNotRegexp  = "!:"
	FilterOpSymIRegexp    = ":~"
	FilterOpSymNotIRegexp = "!:~"

	FilterOpSymBitsSet   = "@"
	FilterOpSymBitsClear = "@~"

	FieldNeedsQuote = `!=<>~:"@`
)
View Source
const NullValue = "null"

Variables

Functions

func SafeField added in v0.2.5

func SafeField(field string) string

SafeField will quote and escape fields if they contain op symbols or quotes

func ValueString added in v0.2.6

func ValueString(value interface{}) string

Convert our values to a string

Types

type Field

type Field = string

Field is just a string

type Filter

type Filter []*FilterTerm

Filter is a slice of FilterTerms that are combined to make the full filter

func NewFilter added in v0.3.1

func NewFilter() *Filter

Creates a new filter

func (*Filter) Append added in v0.2.1

func (f *Filter) Append(logic FilterLogic, field Field, op FilterOp, value interface{}) *Filter

Convienience function for appending to a filter

func (*Filter) Filter added in v0.3.4

func (f *Filter) Filter() Filter

Conveinience function for assigning to a qp.Filter

func (Filter) String added in v0.2.5

func (f Filter) String() string

Filter turns it into it's string representations

func (*Filter) SubFilter added in v0.3.1

func (f *Filter) SubFilter(logic FilterLogic, subFilter *Filter) *Filter

Convienience function for appending a sub filter

type FilterField added in v0.1.2

type FilterField interface {
	GetFieldName() string
	GetFilterType() FilterType
}

FilterField is an interface used to allow specifying a filter for a particular filter type. if GetFieldName returns an empty string, it will assume the FieldName is the same as the field name specified in the map

type FilterFieldCustom added in v0.1.2

type FilterFieldCustom struct {
	FieldName  string
	FilterType FilterType
}

FilterFieldCustom is used to have a different name for a field from what can be specified in the parsable string

func (FilterFieldCustom) GetFieldName added in v0.2.4

func (ffc FilterFieldCustom) GetFieldName() Field

GetFieldName to return filter name from a Custom filter type

func (FilterFieldCustom) GetFilterType added in v0.2.4

func (ffc FilterFieldCustom) GetFilterType() FilterType

GetFilterType to return the filter type from a Custom filter type

type FilterFieldTypes

type FilterFieldTypes map[Field]FilterField

func (FilterFieldTypes) FindFilterType

func (fft FilterFieldTypes) FindFilterType(search string) (string, FilterType)

FindFilterType search the FilterFieldTypes to find a matching field name. First it searches for exact matches and then

type FilterLogic

type FilterLogic int

func (FilterLogic) String

func (logic FilterLogic) String() string

type FilterOp

type FilterOp int

func (FilterOp) MarshalJSON

func (op FilterOp) MarshalJSON() ([]byte, error)

func (FilterOp) String

func (op FilterOp) String() string

type FilterTerm

type FilterTerm struct {
	Logic     FilterLogic   `json:"logic"`
	Op        FilterOp      `json:"op"`
	Field     Field         `json:"field"`
	Value     interface{}   `json:"value"`
	SubFilter []*FilterTerm `json:"sub_filter,omitempty"`
}

func (FilterTerm) String added in v0.2.4

func (ft FilterTerm) String() string

String converts FilterTerm into it's string representation

type FilterType

type FilterType int
const (
	FilterTypeNotFound FilterType = 0
	FilterTypeSimple   FilterType = 1
	FilterTypeString   FilterType = 2
	FilterTypeNumeric  FilterType = 3
	FilterTypeTime     FilterType = 4
	FilterTypeBool     FilterType = 5
)

func (FilterType) GetFieldName added in v0.2.4

func (ft FilterType) GetFieldName() Field

GetFieldName returns empty field indicating it should use the same name as the filter type

func (FilterType) GetFilterType added in v0.2.4

func (ft FilterType) GetFilterType() FilterType

GetFilterType for the default filter types

type NullSort added in v0.3.6

type NullSort int
const (
	NullSortDefault NullSort = 0
	NullSortFirst   NullSort = 1
	NullSortLast    NullSort = 2
)

type Options

type Options map[string]string // Just a lookup of string

func (Options) Get added in v0.2.5

func (o Options) Get(option string) string

func (Options) Has added in v0.2.5

func (o Options) Has(option string) bool

func (*Options) Set added in v0.2.2

func (o *Options) Set(option string, value string)

func (Options) String added in v0.2.5

func (o Options) String() string

type QueryParameters

type QueryParameters struct {
	Filter  Filter  `json:"filter"`
	Sort    Sort    `json:"sort"`
	Options Options `json:"options"`
	Limit   int64   `json:"limit"`
	Offset  int64   `json:"offset"`
}

func ParseQuery

func ParseQuery(q string) (*QueryParameters, error)

ParseQuery converts a string into query parameters This loosely follows standard HTTP URL encoding

func ParseRawQuery

func ParseRawQuery(rq string) (*QueryParameters, error)

func (*QueryParameters) Reset added in v0.2.2

func (qp *QueryParameters) Reset()

Reset clears query parameters for reuse

func (*QueryParameters) String

func (qp *QueryParameters) String() string

String will turn query parameters back into a string that is equivalent to what can be parsed

type Sort

type Sort []*SortTerm

Sort is a slice of SortTerms

func (*Sort) Append added in v0.3.0

func (s *Sort) Append(field Field, desc bool) *Sort

Convienience function for appending to a filter

type SortFields

type SortFields map[string]Field

SortFields is how you specify what fields are available to select for sorting

type SortTerm

type SortTerm struct {
	Field    Field    `json:"field"`
	Desc     bool     `json:"desc"`
	NullSort NullSort `json:"null_sort"`
}

func (SortTerm) String added in v0.2.4

func (st SortTerm) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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