diff --git a/runtime/compilers/rillv1/parse_api.go b/runtime/compilers/rillv1/parse_api.go index 102bbc841d7..7d8dc84b722 100644 --- a/runtime/compilers/rillv1/parse_api.go +++ b/runtime/compilers/rillv1/parse_api.go @@ -118,7 +118,9 @@ func (p *Parser) parseDataYAML(raw *DataYAML) (string, *structpb.Struct, []Resou count++ resolver = "sql" resolverProps["sql"] = raw.SQL - resolverProps["connector"] = raw.Connector + if raw.Connector != "" { + resolverProps["connector"] = raw.Connector + } } // Handle metrics SQL resolver diff --git a/runtime/compilers/rillv1/parse_canvas.go b/runtime/compilers/rillv1/parse_canvas.go index c4557008eb7..c81d490b412 100644 --- a/runtime/compilers/rillv1/parse_canvas.go +++ b/runtime/compilers/rillv1/parse_canvas.go @@ -48,7 +48,10 @@ func (p *Parser) parseCanvas(node *Node) error { } // Parse variable definitions. - variables := make([]*runtimev1.ComponentVariable, len(tmp.Variables)) + var variables []*runtimev1.ComponentVariable + if len(tmp.Variables) > 0 { + variables = make([]*runtimev1.ComponentVariable, len(tmp.Variables)) + } for i, v := range tmp.Variables { variables[i], err = v.Proto() if err != nil { diff --git a/runtime/compilers/rillv1/parse_component.go b/runtime/compilers/rillv1/parse_component.go index 3c37bfe7a30..70652f6e65d 100644 --- a/runtime/compilers/rillv1/parse_component.go +++ b/runtime/compilers/rillv1/parse_component.go @@ -3,6 +3,7 @@ package rillv1 import ( "errors" "fmt" + "strings" runtimev1 "github.com/rilldata/rill/proto/gen/rill/runtime/v1" "github.com/santhosh-tekuri/jsonschema/v5" @@ -98,7 +99,7 @@ func (p *Parser) parseComponentYAML(tmp *ComponentYAML) (*runtimev1.ComponentSpe n++ renderer = "vega_lite" - rendererProps = must(structpb.NewStruct(map[string]any{"spec": *tmp.VegaLite})) + rendererProps = must(structpb.NewStruct(map[string]any{"spec": strings.TrimSpace(*tmp.VegaLite)})) } if len(tmp.Other) == 1 { n++ @@ -130,7 +131,10 @@ func (p *Parser) parseComponentYAML(tmp *ComponentYAML) (*runtimev1.ComponentSpe } // Parse input variables - input := make([]*runtimev1.ComponentVariable, len(tmp.Input)) + var input []*runtimev1.ComponentVariable + if len(tmp.Input) > 0 { + input = make([]*runtimev1.ComponentVariable, len(tmp.Input)) + } for i, v := range tmp.Input { var err error input[i], err = v.Proto() diff --git a/runtime/compilers/rillv1/parser_test.go b/runtime/compilers/rillv1/parser_test.go index 3974c616b0d..618969d62ec 100644 --- a/runtime/compilers/rillv1/parser_test.go +++ b/runtime/compilers/rillv1/parser_test.go @@ -2,6 +2,7 @@ package rillv1 import ( "context" + "encoding/json" "fmt" "maps" "reflect" @@ -304,7 +305,10 @@ schema: default }, }, DefaultPreset: &runtimev1.ExplorePreset{ - TimeRange: "P4W", + DimensionsSelector: &runtimev1.FieldSelector{Selector: &runtimev1.FieldSelector_All{All: true}}, + MeasuresSelector: &runtimev1.FieldSelector{Selector: &runtimev1.FieldSelector_All{All: true}}, + TimeRange: "P4W", + ComparisonMode: runtimev1.ExploreComparisonMode_EXPLORE_COMPARISON_MODE_NONE, }, }, }, @@ -1586,7 +1590,7 @@ theme: } func TestComponentsAndCanvas(t *testing.T) { - vegaLiteSpec := ` + vegaLiteSpec := normalizeJSON(t, ` { "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "description": "A simple bar chart with embedded data.", @@ -1598,7 +1602,7 @@ func TestComponentsAndCanvas(t *testing.T) { "x": {"field": "time", "type": "nominal", "axis": {"labelAngle": 0}}, "y": {"field": "total_sales", "type": "quantitative"} } - }` + }`) ctx := context.Background() repo := makeRepo(t, map[string]string{ `rill.yaml`: ``, @@ -1608,7 +1612,8 @@ data: api: MetricsViewAggregation args: metrics_view: foo -vega_lite: |%s +vega_lite: > + %s `, vegaLiteSpec), `components/c2.yaml`: fmt.Sprintf(` type: component @@ -1616,7 +1621,8 @@ data: api: MetricsViewAggregation args: metrics_view: bar -vega_lite: |%s +vega_lite: > + %s `, vegaLiteSpec), `components/c3.yaml`: ` type: component @@ -1697,7 +1703,7 @@ items: Items: []*runtimev1.CanvasItem{ {Component: "c1"}, {Component: "c2", Width: asPtr(uint32(1)), Height: asPtr(uint32(2))}, - {Component: "d1--component-2"}, + {Component: "d1--component-2", DefinedInCanvas: true}, }, }, }, @@ -2020,10 +2026,15 @@ func requireResourcesAndErrors(t testing.TB, p *Parser, wantResources []*Resourc require.Equal(t, want.SourceSpec, got.SourceSpec, "for resource %q", want.Name) require.Equal(t, want.ModelSpec, got.ModelSpec, "for resource %q", want.Name) require.Equal(t, want.MetricsViewSpec, got.MetricsViewSpec, "for resource %q", want.Name) + require.Equal(t, want.ExploreSpec, got.ExploreSpec, "for resource %q", want.Name) require.Equal(t, want.MigrationSpec, got.MigrationSpec, "for resource %q", want.Name) - require.Equal(t, want.ThemeSpec, got.ThemeSpec, "for resource %q", want.Name) require.True(t, reflect.DeepEqual(want.ReportSpec, got.ReportSpec), "for resource %q", want.Name) require.True(t, reflect.DeepEqual(want.AlertSpec, got.AlertSpec), "for resource %q", want.Name) + require.Equal(t, want.ThemeSpec, got.ThemeSpec, "for resource %q", want.Name) + require.Equal(t, want.ComponentSpec, got.ComponentSpec, "for resource %q", want.Name) + require.Equal(t, want.CanvasSpec, got.CanvasSpec, "for resource %q", want.Name) + require.Equal(t, want.APISpec, got.APISpec, "for resource %q", want.Name) + require.Equal(t, want.ConnectorSpec, got.ConnectorSpec, "for resource %q", want.Name) delete(gotResources, got.Name) found = true @@ -2065,3 +2076,11 @@ func deleteRepo(t testing.TB, repo drivers.RepoStore, files ...string) { func asPtr[T any](val T) *T { return &val } + +func normalizeJSON(t *testing.T, s string) string { + var v interface{} + require.NoError(t, json.Unmarshal([]byte(s), &v)) + b, err := json.Marshal(v) + require.NoError(t, err) + return string(b) +} diff --git a/runtime/reconcilers/alert_test.go b/runtime/reconcilers/alert_test.go index fa7dc0cee61..42b1fe7facb 100644 --- a/runtime/reconcilers/alert_test.go +++ b/runtime/reconcilers/alert_test.go @@ -382,7 +382,7 @@ notify: IntervalsIsoDuration: "P1D", IntervalsCheckUnclosed: true, Resolver: "sql", - ResolverProperties: must(structpb.NewStruct(map[string]any{"connector": "", "sql": "select * from bar where country <> 'Denmark'"})), + ResolverProperties: must(structpb.NewStruct(map[string]any{"sql": "select * from bar where country <> 'Denmark'"})), NotifyOnRecover: false, NotifyOnFail: true, NotifyOnError: false,