View all results

Parameters

Parameters let the host application inject values into FQL queries. They are the primary way to pass dynamic data — user IDs, URLs, configuration values, thresholds — from Go into a script without string interpolation or query rewriting.

FQL source is code. Do not insert runtime data with fmt.Sprintf or string concatenation. See Construct FQL safely for URL, selector, HTML, and source-composition examples.

FQL parameter syntax

In FQL, parameters are referenced with the @ prefix:

example.fql
read-only
let result = @base_url + "/users/" + to_string(@user_id) return result

Engine-level parameters

Parameters set on the engine apply as defaults to every session. Use these for values that rarely change — base URLs, API keys, environment names.

From Go values

WithParams accepts a map[string]any and converts each value to a runtime value automatically:

example.go
read-only
engine, err := ferret.New( ferret.WithParams(map[string]any{ "base_url": "https://api.example.com", "environment": "production", "max_retries": 3, }), )

WithParam sets a single parameter:

example.go
read-only
engine, err := ferret.New( ferret.WithParam("base_url", "https://api.example.com"), ferret.WithParam("timeout", 30), )

From runtime values

When you already have a ferret.Value, use the runtime variants to skip conversion. ferret.Value and ferret.Params preserve the identity of the corresponding runtime types, while constructors for concrete values remain in pkg/runtime:

example.go
read-only
var threshold ferret.Value = runtime.NewFloat(0.95) params := ferret.Params{ "tag": runtime.NewString("v2"), } engine, err := ferret.New( ferret.WithRuntimeParam("threshold", threshold), ferret.WithRuntimeParams(params), )

Session-level parameters

Session parameters override engine defaults for a single execution. Use these for per-request values — user context, request IDs, pagination offsets.

From Go values

example.go
read-only
session, err := plan.NewSession(ctx, ferret.WithSessionParams(map[string]any{ "user_id": 42, "page": 1, "limit": 25, }), )
example.go
read-only
session, err := plan.NewSession(ctx, ferret.WithSessionParam("user_id", 42), )

Session options are also Universal API options. Import github.com/MontFerret/api as api to use the portable setters directly:

example.go
read-only
session, err := plan.NewSession(ctx, api.WithParams(map[string]any{"user_id": 42}), api.WithParam("page", 2), )

Non-nil options run once in order against the native session configuration. Later values override earlier ones. Validation failures are joined before resources are acquired. Native-only options, such as runtime-value setters, require a native target.

From runtime values

example.go
read-only
var fallback ferret.Value = runtime.NewString("guest") params := ferret.Params{ "score": runtime.NewFloat(0.85), } session, err := plan.NewSession(ctx, ferret.WithSessionRuntimeParams(params), ferret.WithSessionRuntimeParam("fallback", fallback), )

Inspecting referenced parameters

A compiled plan records the parameters referenced by the query. Use plan.Params() to get their names in first-seen order:

example.go
read-only
plan, err := engine.Compile(ctx, ferret.NewSource( "parameters.fql", `let url = @base_url + "/users/" + to_string(@user_id) return url`, )) if err != nil { log.Fatal(err) } defer plan.Close() fmt.Println(plan.Params()) // [base_url user_id]

This is useful for validating that all required parameters are provided before creating a session.

Supported Go types

WithParams, WithParam, WithSessionParams, and WithSessionParam convert Go values through runtime.ValueOf:

Go input Runtime value
nil None
An existing ferret.Value The same value, without conversion
bool Boolean
string String
int, int8, int16, int32, int64 Int
uint, uint8, uint16, uint32, uint64 Int, when the value fits in int64
float32, float64 Float
time.Time DateTime
time.Duration Duration
[]byte Binary
Slices and arrays Array, with elements converted recursively
Maps Object, with values converted recursively and keys represented as strings
Structs Object, with exported fields converted recursively
Pointers The pointed-to value converted recursively; a nil pointer becomes None

Struct field names are used exactly as declared in Go. Unexported fields are skipped, and runtime.ValueOf does not read struct tags or flatten embedded fields. The scalar cases above apply to the concrete built-in types; a defined scalar type must implement ferret.Value or be converted to a supported Go type first. Unsupported values, nested unsupported values, and unsigned integers larger than math.MaxInt64 return an error.

runtime.ValueOf(nil) returns None, so nil entries work in the map-based WithParams and WithSessionParams options. The single-value WithParam and WithSessionParam options reject a nil any; pass runtime.None through the corresponding runtime-value option when you need an explicit None.

This conversion produces in-memory ferret.Value instances for execution. It is separate from result encoding: Session.Run returns a *ferret.Output whose Content contains encoded bytes. The default output codec is JSON.

Example: parameterized query with per-session overrides

example.go
read-only
package main import ( "context" "errors" "fmt" "log" "github.com/MontFerret/ferret/v2" ) func main() { if err := run(); err != nil { log.Fatal(err) } } func run() error { engine, err := ferret.New( ferret.WithParam("greeting", "hello"), ferret.WithParam("punctuation", "!"), ) if err != nil { return err } defer engine.Close() ctx := context.Background() plan, err := engine.Compile(ctx, ferret.NewSource( "greeting.fql", `return concat(@greeting, " ", @name, @punctuation)`, )) if err != nil { return err } defer plan.Close() users := []struct{ name, greeting string }{ {"Alice", "hello"}, {"Bob", "hey"}, {"Carol", "hi"}, } for _, u := range users { session, err := plan.NewSession(ctx, ferret.WithSessionParam("name", u.name), ferret.WithSessionParam("greeting", u.greeting), ) if err != nil { return err } output, runErr := session.Run(ctx) closeErr := session.Close() if err := errors.Join(runErr, closeErr); err != nil { return err } fmt.Println(string(output.Content)) } // "hello Alice!" // "hey Bob!" // "hi Carol!" return nil }

The greeting parameter is set at the engine level but overridden per session for Bob and Carol. The punctuation parameter uses the engine default for all sessions.

Next steps