Computed literals

Functions parameters are either literals or expressions that can be evaluated for each row at runtime.

Sometimes, however, you need literals that are computed dynamically at compile time rather than runtime.

While traditional SQL typically uses jinja templates for this purpose, FeatureQL provides metaprogramming functions @echo and @literal to achieve this natively.

Metaprogramming functions

These functions allow you to inject computed values into the query before it is parsed.

@echo

Injects a computed string directly into the query text. The computed value must be a VARCHAR type.

@fql-playground(echo)

Note: @echo requires its argument to evaluate to VARCHAR. If you have a non VARCHAR value, you must explicitly cast it:

CONST MY_NUMBER := 42
SELECT @echo(MY_NUMBER::VARCHAR) AS RESULT
sql

@literal

Injects a computed literal as a parameter value in the query. Unlike @echo, @literal preserves the type of the computed value.

Persisting @literal in feature definitions

When you want to persist features that include compile time computed parameters, use the EVAL_CONST function.

@fql-playground(eval_const)

The type must be explicitly specified because the value is computed after type inference occurs.

CONST declarations

CONST declarations support multiple syntaxes for defining compile time constants:

-- Single constant
CONST MY_VALUE := 42

-- Multiple constants on one line
CONST CONST1 := 1, CONST2 := 2

-- Multiple constants across lines
CONST
    CONST1 := 1,
    CONST2 := 2

-- With optional trailing comma
CONST
    CONST1 := 1,
    CONST2 := 2,
sql

Constants can be used with both @echo and @literal functions, and support complex expressions:

CONST BASE := 10
SELECT @literal(BASE * 2 + 3) AS RESULT  -- Returns 23
sql

Working with non deterministic functions

NOW(), RANDOM(), CURRENT_TIMESTAMP(), and SHUFFLE() are non deterministic functions that return different values on each invocation. This violates pure function principles in FeatureQL.

These functions are only supported when wrapped in @echo() or @literal() to make them deterministic:

The value is evaluated once at query compilation time and remains constant for all rows.

Creating row specific random values

For deterministic random values that vary per row, use HASH01 which generates values based on input hash:

These values change for each row but remain consistent across executions.

Simulating non deterministic behavior

To mimic SQL's RANDOM() function while maintaining pure function principles, integrate a random seed that changes per execution:

Evaluation context

Computed literals are evaluated at compile time, not necessarily using the same backend as the main query. This enables several optimization patterns:

  1. Real time API calls to compute values before query execution
  2. Checking materialized column availability before overwriting feature definitions
  3. Computing expensive constants once rather than per row

@fql-playground(eval_const_real_time)

Error handling

Common error scenarios:

  1. Type mismatch with @echo: Must evaluate to VARCHAR
  2. Missing CONST references: Constants used in eval_const must be defined in the same statement
  3. Direct use of non deterministic functions: Must be wrapped in @echo or @literal

Best practices

  1. Use @literal when you need to preserve the original type of the computed value
  2. Use @echo only when you need to inject string representations into the query text
  3. Always specify types explicitly when using eval_const in feature definitions
  4. Define CONST declarations in the same statement where they're referenced by eval_const
  5. For random values, choose between compile time constants (@literal(RANDOM())) or deterministic per row values (HASH01) based on your use case
Last update at: 2025/10/13 10:23:46