qfl

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Sep 6, 2025 License: Unlicense Imports: 5 Imported by: 0

README

GoDoc

Overview

This repository contains a parser for the QFL language that transforms into a filter data structure that stores a collection of rules for a given record, which the user can apply filters for searching for any database.

Library

Checkout documentation for examples on how to use the library.

Language

QFL is a simple filtering language for queries designed to have just enough functionality to provide a quite competent filtering scheme for your REST API or something similar.

Syntax

This is the syntax of how you define a filter:

[comparator!]value

If only the value is passed, it will use the eq comparator. Additionally, if you want to filter for some data that is equal to one of the specified values, you can specify a list of values separated with commas. Note that this is only supported on the eq comparator:

eq!value[,value...]

You can combine more than one filter by using the bar:

filter|filter

Comparators

  • eq: Equals
  • lt: Less than
  • gt: Greater than
  • le: Less or equal
  • ge: Greater or equal
  • lk: Searches for similar string

Symbols

  • | (bar): combine filters from both sides
  • , (comma): Separate elements in a list
  • ! (mark): Indicate start of a value
  • \ (backslash): escape the character in front of it (only affects symbols)

Contributing

If you found a bug, missing documentation or have any improvements for performance, you can contribute to the codebase by opening a PR addressing the problem. If you want to add a feature, open an issue describing why it is necessary and to be sure we both agree that this needs to be implemented, so you don't waste time implementing something that won't be accepted.

This library should be considered stable, so there shouldn't be any breaking changes. If however there is a feature that most users would benefit to, a new version of the module might be made for it.

Documentation

Overview

Package qfl exposes a parser for the QFL language and a filter data structure that stores the rules for a given data.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ComparasionType

type ComparasionType uint8

ComparasionType indicates the comparasion it should make for the values.

const (
	ComparasionInvalid ComparasionType = iota
	ComparasionEquals
	ComparasionLessThan
	ComparasionMoreThan
	ComparasionLessOrEqual
	ComparasionMoreOrEqual
	ComparasionLike
)

func (ComparasionType) String

func (c ComparasionType) String() string

type Filter

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

Filter is a specialized data structure that stores rules for a given key. It only supports some primitive data types. All get and set functions should be the exactly same except for the type it's manipulating, this is on purporse to ensure type safety.

Example
package main

import (
	"fmt"

	"github.com/robertoesteves13/qfl"
)

func main() {
	f := qfl.Filter{}

	// Set rules inside filter
	f.AddInt("age", []int{22}, qfl.ComparasionMoreThan)
	f.AddString("name", []string{"John"}, qfl.ComparasionLike)

	// Get filter rules
	age := f.GetInt("age")
	name := f.GetString("name")

	fmt.Printf("age %s %d\n", age[0].Comparasion, age[0].Values[0])
	fmt.Printf("name %s %s\n", name[0].Comparasion, name[0].Values[0])
}
Output:
age MoreThan 22
name Like John

func (*Filter) AddFloat

func (f *Filter) AddFloat(key string, values []float64, comparasion ComparasionType)

func (*Filter) AddInt

func (f *Filter) AddInt(key string, values []int, comparasion ComparasionType)

func (*Filter) AddString

func (f *Filter) AddString(key string, values []string, comparasion ComparasionType)

func (*Filter) AddTime

func (f *Filter) AddTime(key string, values []time.Time, comparasion ComparasionType)

func (*Filter) AddUint

func (f *Filter) AddUint(key string, values []uint, comparasion ComparasionType)

func (*Filter) GetFloat

func (f *Filter) GetFloat(key string) []FilterRule[float64]

func (*Filter) GetInt

func (f *Filter) GetInt(key string) []FilterRule[int]

func (*Filter) GetString

func (f *Filter) GetString(key string) []FilterRule[string]

func (*Filter) GetTime

func (f *Filter) GetTime(key string) []FilterRule[time.Time]

func (*Filter) GetUint

func (f *Filter) GetUint(key string) []FilterRule[uint]

type FilterRule

type FilterRule[T Primitive] struct {
	Comparasion ComparasionType
	Values      []T
}

FilterRule represents Note that `ComparasionEquals` is the only one that can have more than one value.

type Parser

type Parser struct {
	TimeFormat string // defaults to RCF3339 if empty
	// contains filtered or unexported fields
}

Parser parses the QFL language for the keys you specify

Example
package main

import (
	"fmt"
	"time"

	"github.com/robertoesteves13/qfl"
)

func main() {
	data := map[string]string{
		"income":        "1234.56",
		"role":          "eq!Programmer,Tester",
		"age":           "gt!20|lt!60",
		"employedSince": "2023-05-02T09:34:01Z",
	}

	parser := qfl.Parser{}
	parser.AddFloat("income")
	parser.AddString("role")
	parser.AddInt("age")
	parser.AddTime("employedSince")

	filter, err := parser.Parse(data)
	if err != nil {
		// do error handling
	}

	age := filter.GetInt("age")
	income := filter.GetFloat("income")
	employedSince := filter.GetTime("employedSince")
	role := filter.GetString("role")

	fmt.Printf("age %v %d %v %d\n", age[0].Comparasion, age[0].Values[0], age[1].Comparasion, age[1].Values[0])
	fmt.Printf("income %s %.2f\n", income[0].Comparasion, income[0].Values[0])
	fmt.Printf("employedSince %s %s\n", employedSince[0].Comparasion, employedSince[0].Values[0].Format(time.RFC3339))
	fmt.Printf("role %s %s %s\n", role[0].Comparasion, role[0].Values[0], role[0].Values[1])
}
Output:
age MoreThan 20 LessThan 60
income Equals 1234.56
employedSince Equals 2023-05-02T09:34:01Z
role Equals Programmer Tester

func (*Parser) AddFloat

func (p *Parser) AddFloat(key string)

func (*Parser) AddInt

func (p *Parser) AddInt(key string)

func (*Parser) AddString

func (p *Parser) AddString(key string)

func (*Parser) AddTime

func (p *Parser) AddTime(key string)

func (*Parser) AddUint

func (p *Parser) AddUint(key string)

func (Parser) Parse

func (p Parser) Parse(kv map[string]string) (*Filter, error)

func (Parser) ParseURL

func (p Parser) ParseURL(u *url.URL) (*Filter, error)

ParseURL reads query variables and returns the filter containing all rules for them. Note that it only looks for the first definition of the variable.

type Primitive

type Primitive interface {
	int | uint | float64 | string | time.Time
}

Primitive is a generic interface that indicates the types the filter can store.

type SQLBuilder added in v1.1.0

type SQLBuilder struct {
	Filter            Filter
	Keys              map[string]string
	PlaceholderFormat SQLPlaceholderFormat
}

SQLBuilder is a generic WHERE-condition builder capable to convert filter rules automatically

Example
package main

import (
	"fmt"

	"github.com/robertoesteves13/qfl"
)

func main() {
	filter := qfl.Filter{}

	filter.AddString("name", []string{"Roberto"}, qfl.ComparasionLike)
	filter.AddUint("age", []uint{23}, qfl.ComparasionMoreThan)
	filter.AddUint("salary", []uint{3000}, qfl.ComparasionLessOrEqual)
	filter.AddString("role", []string{"Programmer", "Developer"}, qfl.ComparasionEquals)

	builder := qfl.SQLBuilder{
		Filter: filter,
		Keys: map[string]string{
			"name":   "name",
			"age":    "age",
			"salary": "salary",
			"role":   "role",
		},
		PlaceholderFormat: qfl.SQLPlaceholderDollarSign,
	}

	sql, params, err := builder.Build()
	if err != nil {
		// Treat error...
	}

	fmt.Println(sql)
	fmt.Println(params)
}
Output:
WHERE name LIKE $1 AND age > $2 AND salary <= $3 AND role IN ($4,$5)
[Roberto% 23 3000 Programmer Developer]

func (*SQLBuilder) Build added in v1.1.0

func (sq *SQLBuilder) Build() (string, []any, error)

type SQLPlaceholderFormat added in v1.1.0

type SQLPlaceholderFormat uint8
const (
	SQLPlaceholderQuestionMark SQLPlaceholderFormat = 0
	SQLPlaceholderDollarSign   SQLPlaceholderFormat = 1
)

Jump to

Keyboard shortcuts

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