mirror of
https://github.com/chaisql/chai.git
synced 2025-10-06 16:18:14 +08:00

* Add packaged functions support * Add tests for math.floor func * Export FunctionsTable * Extract func stuff into its own package * Rename stuff * Fix tests * Move doc package to cmd/genji * Adjust naming, typos
76 lines
1.9 KiB
Go
76 lines
1.9 KiB
Go
package functions
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/genjidb/genji/internal/expr"
|
|
"github.com/genjidb/genji/internal/stringutil"
|
|
)
|
|
|
|
// A Definition transforms a list of expressions into a Function.
|
|
type Definition interface {
|
|
Name() string
|
|
String() string
|
|
Function(...expr.Expr) (expr.Function, error)
|
|
Arity() int
|
|
}
|
|
|
|
// Definitions table holds a map of definition, indexed by their names.
|
|
type Definitions map[string]Definition
|
|
|
|
// Packages represent a table of SQL functions grouped by their packages
|
|
type Packages map[string]Definitions
|
|
|
|
func DefaultPackages() Packages {
|
|
return Packages{
|
|
"": BuiltinDefinitions(),
|
|
"math": MathFunctions(),
|
|
}
|
|
}
|
|
|
|
// GetFunc return a function definition by its package and name.
|
|
func (t Packages) GetFunc(pkg string, fname string) (Definition, error) {
|
|
fs, ok := t[pkg]
|
|
if !ok {
|
|
return nil, stringutil.Errorf("no such package: %q", fname)
|
|
}
|
|
def, ok := fs[strings.ToLower(fname)]
|
|
if !ok {
|
|
if pkg == "" {
|
|
return nil, stringutil.Errorf("no such function: %q", fname)
|
|
}
|
|
return nil, stringutil.Errorf("no such function: %q.%q", pkg, fname)
|
|
}
|
|
return def, nil
|
|
}
|
|
|
|
// A definition is the most basic version of a function definition.
|
|
type definition struct {
|
|
name string
|
|
arity int
|
|
constructorFn func(...expr.Expr) (expr.Function, error)
|
|
}
|
|
|
|
func (fd *definition) Name() string {
|
|
return fd.name
|
|
}
|
|
|
|
func (fd *definition) Function(args ...expr.Expr) (expr.Function, error) {
|
|
if len(args) != fd.arity {
|
|
return nil, stringutil.Errorf("%s() takes %d argument(s), not %d", fd.name, fd.arity, len(args))
|
|
}
|
|
return fd.constructorFn(args...)
|
|
}
|
|
|
|
func (fd *definition) String() string {
|
|
args := make([]string, 0, fd.arity)
|
|
for i := 0; i < fd.arity; i++ {
|
|
args = append(args, stringutil.Sprintf("arg%d", i+1))
|
|
}
|
|
return stringutil.Sprintf("%s(%s)", fd.name, strings.Join(args, ", "))
|
|
}
|
|
|
|
func (fd *definition) Arity() int {
|
|
return fd.arity
|
|
}
|