/
metrics_sql.go
83 lines (70 loc) · 2.32 KB
/
metrics_sql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package resolvers
import (
"context"
"errors"
"github.com/mitchellh/mapstructure"
runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1"
"github.com/rilldata/rill/runtime"
metricssqlparser "github.com/rilldata/rill/runtime/pkg/metricssql"
)
func init() {
runtime.RegisterResolverInitializer("metrics_sql", newMetricsSQL)
}
type metricsSQLProps struct {
SQL string `mapstructure:"sql"`
}
type metricsSQLArgs struct {
Priority int `mapstructure:"priority"`
// NOTE: Not exhaustive. Any other args are passed to the "args" property of sqlResolverOpts.
}
// newMetricsSQL creates a resolver for evaluating metrics SQL.
// It wraps the regular SQL resolver and compiles the metrics SQL to a regular SQL query first.
// The compiler preserves templating in the SQL, allowing the regular SQL resolver to handle SQL templating rules.
func newMetricsSQL(ctx context.Context, opts *runtime.ResolverOptions) (runtime.Resolver, error) {
props := &metricsSQLProps{}
if err := mapstructure.Decode(opts.Properties, props); err != nil {
return nil, err
}
if props.SQL == "" {
return nil, errors.New(`metrics SQL: missing required property "sql"`)
}
instance, err := opts.Runtime.Instance(ctx, opts.InstanceID)
if err != nil {
return nil, err
}
var finalRefs []*runtimev1.ResourceName
props.SQL, finalRefs, err = resolveTemplate(props.SQL, opts.Args, instance, opts.UserAttributes, opts.ForExport)
if err != nil {
return nil, err
}
ctrl, err := opts.Runtime.Controller(ctx, opts.InstanceID)
if err != nil {
return nil, err
}
sqlArgs := &metricsSQLArgs{}
if err := mapstructure.Decode(opts.Args, sqlArgs); err != nil {
return nil, err
}
compiler := metricssqlparser.New(ctrl, opts.InstanceID, opts.UserAttributes, sqlArgs.Priority)
sql, connector, refs, err := compiler.Compile(ctx, props.SQL)
if err != nil {
return nil, err
}
if refs != nil {
finalRefs = append(finalRefs, refs...)
finalRefs = normalizeRefs(finalRefs)
}
// Build the options for the regular SQL resolver
sqlResolverOpts := &runtime.ResolverOptions{
Runtime: opts.Runtime,
InstanceID: opts.InstanceID,
Properties: map[string]any{
"connector": connector,
"sql": sql,
},
Args: opts.Args,
UserAttributes: opts.UserAttributes,
ForExport: opts.ForExport,
}
return newSQLSimple(ctx, sqlResolverOpts, finalRefs)
}