Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions fixtures/multi_vql_queries.golden
Original file line number Diff line number Diff line change
Expand Up @@ -1416,5 +1416,20 @@
}
]
}
],
"090/000 Function definition with defaults: LET Y \u003c= 7": null,
"090/001 Function definition with defaults: LET F(X=2, Y) = X + Y": null,
"090/002 Function definition with defaults: SELECT F(Y=1), F(), F(X=1, Y=4) FROM scope()": [
{
"F(Y=1)": 3,
"F()": 9,
"F(X=1, Y=4)": 5
}
],
"091/000 Stored Query definition with defaults: LET F(X=2, Y) = SELECT X + Y AS Total FROM scope()": null,
"091/001 Stored Query definition with defaults: SELECT * FROM F(Y=1)": [
{
"Total": 3
}
]
}
14 changes: 8 additions & 6 deletions functions/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ type GenericFunctionInterface func(ctx context.Context, scope types.Scope, args
// helper plugin allows callers to use these within VFilter
// easily. Example:

// scope.AppendPlugins(GenericListPlugin{
// PluginName: "my_plugin",
// Function: func(args types.Row) []types.Row {
// ....
// }
// })
// scope.AppendPlugins(GenericListPlugin{
// PluginName: "my_plugin",
// Function: func(args types.Row) []types.Row {
// ....
// }
// })
type GenericFunction struct {
FunctionName string
Doc string
Function GenericFunctionInterface
Metadata *ordereddict.Dict
Version int
ArgType types.Any
}

Expand All @@ -47,6 +48,7 @@ func (self GenericFunction) Info(scope types.Scope, type_map *types.TypeMap) *ty
Name: self.FunctionName,
Doc: self.Doc,
Metadata: self.Metadata,
Version: self.Version,
}

if self.ArgType != nil {
Expand Down
10 changes: 9 additions & 1 deletion lambda.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,16 @@ type Lambda struct {
func (self *Lambda) GetParameters() []string {
result := []string{}

var visitor func(parameters *_ParameterList)
visitor = func(parameters *_ParameterList) {
result = append(result, parameters.Left)
if parameters.Right != nil {
visitor(parameters.Right.Term)
}
}

if self.Parameters != nil {
visitor(self.Parameters, &result)
visitor(self.Parameters)
}

return result
Expand Down
47 changes: 47 additions & 0 deletions stored.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type _StoredQuery struct {
query *_Select
name string
parameters []string
defaults map[string]*_Args
}

func NewStoredQuery(query *_Select, name string) *_StoredQuery {
Expand All @@ -46,6 +47,15 @@ func NewStoredQuery(query *_Select, name string) *_StoredQuery {
}
}

func (self *_StoredQuery) ApplyDefaults(
ctx context.Context, scope types.Scope, args *ordereddict.Dict) {
if self.defaults == nil {
return
}

applyDefaults(ctx, scope, args, self.defaults)
}

func (self *_StoredQuery) GoString() string {
scope := NewScope()
return fmt.Sprintf("StoredQuery{name: %v, query: {%v}, parameters: %v}",
Expand Down Expand Up @@ -155,13 +165,48 @@ type StoredExpression struct {
Expr *_AndExpression
name string
parameters []string
defaults map[string]*_Args
}

func (self *StoredExpression) Reduce(
ctx context.Context, scope types.Scope) types.Any {
return self.Expr.Reduce(ctx, scope)
}

func (self *StoredExpression) ApplyDefaults(
ctx context.Context, scope types.Scope, args *ordereddict.Dict) {
// Add in any missing args
if self.defaults == nil {
return
}

applyDefaults(ctx, scope, args, self.defaults)
}

func applyDefaults(ctx context.Context, scope types.Scope,
args *ordereddict.Dict,
defaults map[string]*_Args) {

for name, arg := range defaults {
_, pres := args.Get(name)

// If the user did not specify the arg we fill it in from
// the defaults. NOTE: The default expressions are
// evaluated at the calling scope.
if !pres {
if arg.Right != nil {
args.Set(name, arg.Right.Reduce(ctx, scope))
} else if arg.SubSelect != nil {
args.Set(arg.Left, arg.SubSelect)
} else if arg.Array != nil {
args.Set(name, arg.Array.Reduce(ctx, scope))
} else if arg.ArrayOpenBrace != "" {
args.Set(name, []Row{})
}
}
}
}

// Act as a function
func (self *StoredExpression) Call(ctx context.Context,
scope types.Scope, args *ordereddict.Dict) types.Any {
Expand All @@ -183,6 +228,8 @@ func (self *StoredExpression) Call(ctx context.Context,
vars.Set(k, v)
}

self.ApplyDefaults(ctx, scope, vars)

sub_scope.AppendVars(vars)

return self.Reduce(ctx, sub_scope)
Expand Down
20 changes: 20 additions & 0 deletions types/defaults.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package types

import (
"context"

"github.com/Velocidex/ordereddict"
)

type DefaultArgInterface interface {
ApplyDefaults(ctx context.Context, scope Scope, vars *ordereddict.Dict)
}

func MaybeApplyDefaultArgs(callable interface{},
ctx context.Context, scope Scope, args *ordereddict.Dict) {

defaults, ok := callable.(DefaultArgInterface)
if ok {
defaults.ApplyDefaults(ctx, scope, args)
}
}
26 changes: 0 additions & 26 deletions types/frozen.go

This file was deleted.

Loading