Package com.darkcollective.relix.function
The split this package draws is between a function's form and its
processing. The form — name, parameters, arity, return type, purity, the
spelling a backend would understand — is what the engine reasons about while it is
checking a script, rewriting it and planning it. The processing is the lambda that
turns arguments into a value. Sin and Cos have the same form; nothing
in analysis or planning is served by knowing which of them a call names.
So the engine holds the form and a library supplies the processing:
FunctionSignatureandAggregateSignaturedescribe a function;Arityis how many arguments it takes, checked by the engine so an implementation never counts its own.ScalarFunctionpairs a signature with an implementation —StrictScalarFunctionfor the ordinary kind,LazyScalarFunctionfor a special form that chooses which arguments to evaluate.AggregateFunctiondoes the same for a reduction, through anAccumulatorper group.PushdownSpellingis how a call is written for a backend that could evaluate it itself, so a library ships its implementation and its SQL together and declining is always safe.FunctionLibraryis the unit that is installed and discovered;FunctionCatalogindexes what was found.
Nothing here is privileged. The library the engine ships with is discovered by the same mechanism, described by the same records and reached through the same catalogue as one written elsewhere, so anything a built-in function does is available to any function.
What the SPI deliberately does not open is the set of value types: a library adds
functions over Value, not new kinds of value.
A domain type is carried as a struct with a discriminating field, with the library's
own functions over it.
-
ClassDescriptionThe running state of one aggregate over one group.One aggregate a library supplies: its form plus the
Accumulatorthat reduces a group.A contract an aggregate makes with the optimizer, in the wayFunctionPropertydoes for scalar functions.The form of an aggregate — what the engine needs to plan a grouping before any row is read.One argument of aLazyScalarFunctioncall, not yet evaluated.How many arguments a function accepts — an inclusive range, withArity.UNBOUNDEDstanding for "no upper limit".Every function available to a run, indexed by name.The ambient state a function implementation may read while it runs.A collection of functions offered to the engine — the unit that is installed, discovered and versioned.The form of a scalar function — everything the engine reasons about before anything is evaluated.A scalar function that decides which of its arguments to evaluate — a special form.How a function call is written in a backend that could evaluate it itself.The backend a call is being rendered for, named in a way the SPI can carry without knowing anything about query planning.One scalar function a library supplies: its form plus the processing behind it.A scalar function whose arguments are all evaluated before it is called — the ordinary kind.