Skip to content
slashdevopsPublic

About

Abstract Syntax Tree (AST) parser for query fields, filters and sort operations

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

36 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Query Filters Validator (QFV)

Go Reference GitHub go.mod Go version license Release release

A Go library for parsing and validating the query expressions commonly used in REST APIs and database queries — fields selection, filtering, and sorting. Each parser is driven by an allow-list of fields, so only fields you permit can appear in a query, helping secure your endpoints against invalid or malicious input.

Install

go get github.com/slashdevops/qfv@latest

Update to the latest release with go get -u github.com/slashdevops/qfv@latest.

Quick start

package main

import (
    "fmt"
    "log"

    qfv "github.com/slashdevops/qfv"
)

func main() {
    allowedFields := []string{"first_name", "last_name", "email", "created_at"}

    // Parsers are safe to build once and reuse across goroutines.
    filterParser := qfv.NewFilterParser(allowedFields)
    sortParser := qfv.NewSortParser(allowedFields)
    fieldsParser := qfv.NewFieldsParser(allowedFields)

    node, err := filterParser.Parse("first_name = 'John' AND created_at > '2023-01-01'")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(node.String()) // ((first_name = 'John') AND (created_at > '2023-01-01'))

    if _, err := sortParser.Parse("first_name ASC, created_at DESC"); err != nil {
        log.Fatal(err)
    }
    if _, err := fieldsParser.Parse("first_name, last_name, email"); err != nil {
        log.Fatal(err)
    }
}

Features

  • Three validators — fields selection, filtering, and sorting, each gated by an allow-list of fields (nested dot-notation like user.profile.age supported).
  • The filter grammar of the database that runs it — comparison, logical, IN, BETWEEN [SYMMETRIC], LIKE/ILIKE with ESCAPE, SIMILAR TO, POSIX regex, IS NULL, IS [NOT] TRUE/FALSE/UNKNOWN, and IS [NOT] DISTINCT FROM, as PostgreSQL 18 runs them (the default), or as SQL:2023 (ISO/IEC 9075:2023) or MySQL 8.4 does with WithDialect. MySQL's dialect reads strings with MySQL's backslash escapes, so a filter cannot hide a predicate from the allow-list. See SQL Dialects.
  • Configurable — choose the SQL dialect (PostgreSQL 18, SQL:2023 or MySQL 8.4), and restrict which operators or sort directions are allowed.
  • Returns an AST you can walk or render, with precise, aggregated errors.
  • Concurrency-safe parsers.

How it works

Every parser is gated by the same allow-list of fields. Untrusted query-string parameters go in; validated, structured values come out — an AST for filters, typed lists for fields and sorting — so nothing outside your allow-list ever reaches your data layer.

flowchart LR
    Q["HTTP query string<br/>?fields=…&filter=…&sort=…"]

    Q --> FP["FieldsParser"]
    Q --> FI["FilterParser"]
    Q --> SP["SortParser"]

    AL(["Allow-list of fields"]) -. gates .-> FP
    AL -. gates .-> FI
    AL -. gates .-> SP
    DI(["SQL dialect<br/>PostgreSQL 18 (default) · SQL:2023 · MySQL 8.4"]) -. grammar .-> FI

    FP --> FN["FieldsNode<br/>[]string"]
    FI --> AST["Filter AST<br/>(Node tree)"]
    SP --> SN["SortNode<br/>[]SortFieldNode"]

    FN --> APP["Your handler / SQL builder"]
    AST --> APP
    SN --> APP

    APP --> DB[("Database")]
Loading

The filter parser is a hand-written recursive-descent parser: a Lexer tokenizes the input, then the parser builds the AST while honoring operator precedence (OR < AND < comparison), the dialect and the allow-lists.

flowchart LR
    IN["input string"] --> LEX["Lexer<br/>tokenize"]
    LEX --> TOK["[]Token"]
    TOK --> PAR["FilterParser<br/>recursive descent"]
    CHK(["dialect · field and<br/>operator allow-lists"]) -. "each field and operator" .-> PAR
    PAR --> AST["AST root (Node)"]
    PAR -. "collects every error" .-> ERR["errors.Join(…)"]
Loading

Documentation

Full documentation lives in docs/:

  • Getting Started — install, update, complete example
  • Filtering — the full operator/predicate reference
  • SQL Dialects — PostgreSQL 18 (the default), SQL:2023 or MySQL 8.4: why a filter parser needs one, choosing it, and every construct in each
  • Configuration — choose the dialect, restrict operators and sort directions
  • Error Handling — inspecting validation failures
  • Migration Guide — upgrading between versions

API reference and runnable examples are on pkg.go.dev.

License

QFV is licensed under the Apache License, Version 2.0 (text).

About

Abstract Syntax Tree (AST) parser for query fields, filters and sort operations

Resources

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages