From 259da8561c3229be8e182e093a6e191d88ab3a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Thu, 12 Aug 2021 16:52:17 +0200 Subject: [PATCH] Add AST value type validation & support for Number --- pkg/qlng/ast_nodes.go | 7 +- pkg/report/frame.go | 1 + pkg/report/step_join.go | 1 + store/rdbms/compose_record_datasource.go | 4 +- .../reporter/9007_filtering_specials_test.go | 70 ++++++++++++------- .../reporter/9009_filtering_vaidation_test.go | 4 +- .../S9007_filtering_specials/report.json | 19 +++++ 7 files changed, 78 insertions(+), 28 deletions(-) diff --git a/pkg/qlng/ast_nodes.go b/pkg/qlng/ast_nodes.go index ef30197ca..2476b3d1a 100644 --- a/pkg/qlng/ast_nodes.go +++ b/pkg/qlng/ast_nodes.go @@ -2,6 +2,7 @@ package qlng import ( "encoding/json" + "errors" "github.com/cortezaproject/corteza-server/pkg/expr" ) @@ -51,6 +52,10 @@ func (t *typedValue) UnmarshalJSON(in []byte) (err error) { return } + if aux.Type == "" { + return errors.New("invalid value definition: missing @type definition") + } + t.V, err = qlTypeRegistry(aux.Type).Cast(aux.Value) return } @@ -284,7 +289,7 @@ func qlTypeRegistry(ref string) expr.Type { return &expr.Integer{} case "UnsignedInteger": return &expr.UnsignedInteger{} - case "Float": + case "Float", "Number": return &expr.Float{} case "String": return &expr.String{} diff --git a/pkg/report/frame.go b/pkg/report/frame.go index 8355cf5d7..c6130fb27 100644 --- a/pkg/report/frame.go +++ b/pkg/report/frame.go @@ -26,6 +26,7 @@ type ( Paging *filter.Paging `json:"paging"` Sort filter.SortExprSet `json:"sort"` + Filter *Filter `json:"filter"` // params to help us perform things in place startIndex int diff --git a/pkg/report/step_join.go b/pkg/report/step_join.go index 06e51bc46..5827c52b2 100644 --- a/pkg/report/step_join.go +++ b/pkg/report/step_join.go @@ -508,6 +508,7 @@ func (d *joinedDataset) sliceFramesFurther(ff []*Frame, selfCol, relCol string) Columns: ff[0].Columns, Paging: ff[0].Paging, Sort: ff[0].Sort, + Filter: ff[0].Filter, }) } diff --git a/store/rdbms/compose_record_datasource.go b/store/rdbms/compose_record_datasource.go index 3b95dc355..3aaa776a2 100644 --- a/store/rdbms/compose_record_datasource.go +++ b/store/rdbms/compose_record_datasource.go @@ -320,6 +320,7 @@ func (r *recordDatasource) load(ctx context.Context, def *report.FrameDefinition Source: def.Source, Ref: def.Ref, Sort: def.Sort, + Filter: def.Filter, } checkCap := cap > 0 @@ -343,7 +344,8 @@ func (r *recordDatasource) load(ctx context.Context, def *report.FrameDefinition if checkCap && i > cap { out := []*report.Frame{f} f = &report.Frame{ - Sort: def.Sort, + Sort: def.Sort, + Filter: def.Filter, } i = 0 return r.calculatePaging(out, def.Sort, uint(cap), def.Paging.PageCursor), nil diff --git a/tests/reporter/9007_filtering_specials_test.go b/tests/reporter/9007_filtering_specials_test.go index cd1a60d09..842bfbfbe 100644 --- a/tests/reporter/9007_filtering_specials_test.go +++ b/tests/reporter/9007_filtering_specials_test.go @@ -11,33 +11,53 @@ func Test9007_filtering_specials(t *testing.T) { ff = loadNoErrMulti(ctx, h, m, dd...) ) - f := ff[0] - h.a.Equal(12, f.Size()) - h.a.Equal("empty_filter", f.Name) - h.a.Equal("first_name, last_name", f.Columns.String()) + t.Run(ff[0].Name, func(t *testing.T) { + f := ff[0] + h.a.Equal(12, f.Size()) + h.a.Equal("empty_filter", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + }) - f = ff[1] - h.a.Equal(0, f.Size()) - h.a.Equal("false_filter", f.Name) - h.a.Equal("first_name, last_name", f.Columns.String()) + t.Run(ff[1].Name, func(t *testing.T) { + f := ff[1] + h.a.Equal(0, f.Size()) + h.a.Equal("false_filter", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + }) - f = ff[2] - h.a.Equal(12, f.Size()) - h.a.Equal("true_filter", f.Name) - h.a.Equal("first_name, last_name", f.Columns.String()) + t.Run(ff[2].Name, func(t *testing.T) { + f := ff[2] + h.a.Equal(12, f.Size()) + h.a.Equal("true_filter", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + }) - f = ff[3] - h.a.Equal(4, f.Size()) - h.a.Equal("weird_filter", f.Name) - h.a.Equal("first_name, last_name", f.Columns.String()) - checkRows(h, f, - "Maria, Königsmann", - "Engel, Loritz", - "Maria, Krüger", - "Engel, Kiefer") + t.Run(ff[3].Name, func(t *testing.T) { + f := ff[3] + h.a.Equal(4, f.Size()) + h.a.Equal("weird_filter", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + checkRows(h, f, + "Maria, Königsmann", + "Engel, Loritz", + "Maria, Krüger", + "Engel, Kiefer") - f = ff[4] - h.a.Equal(12, f.Size()) - h.a.Equal("empty_filter_object", f.Name) - h.a.Equal("first_name, last_name", f.Columns.String()) + }) + + t.Run(ff[4].Name, func(t *testing.T) { + f := ff[4] + h.a.Equal(12, f.Size()) + h.a.Equal("empty_filter_object", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + }) + + t.Run(ff[5].Name, func(t *testing.T) { + f := ff[5] + h.a.Equal(1, f.Size()) + h.a.Equal("wildcard_number_value", f.Name) + h.a.Equal("first_name, last_name", f.Columns.String()) + checkRows(h, f, + "Engel, Loritz") + }) } diff --git a/tests/reporter/9009_filtering_vaidation_test.go b/tests/reporter/9009_filtering_vaidation_test.go index a57f99cf0..a5f3f1dd3 100644 --- a/tests/reporter/9009_filtering_vaidation_test.go +++ b/tests/reporter/9009_filtering_vaidation_test.go @@ -10,5 +10,7 @@ func Test9009_filtering_validation(t *testing.T) { m, _, dd = loadScenario(ctx, s, t, h) ) - loadErr(ctx, h, m, dd[0], "could not build query: expecting 1 or more arguments, got 0") + t.Run("empty conjunction", func(t *testing.T) { + loadErr(ctx, h, m, dd[0], "could not build query: expecting 1 or more arguments, got 0") + }) } diff --git a/tests/reporter/testdata/S9007_filtering_specials/report.json b/tests/reporter/testdata/S9007_filtering_specials/report.json index 8587a7467..812098394 100644 --- a/tests/reporter/testdata/S9007_filtering_specials/report.json +++ b/tests/reporter/testdata/S9007_filtering_specials/report.json @@ -68,5 +68,24 @@ ], "filter": {} + }, { + "name": "wildcard_number_value", + "source": "users", + "columns": [ + { "name": "first_name", "label": "first_name" }, + { "name": "last_name", "label": "last_name" } + ], + + "filter": { + "ref": "eq", + "args": [{ + "symbol": "number_of_numbers" + }, { + "value": { + "@type": "Number", + "@value": 46 + } + }] + } }] }