From 3c31bb52099cdb4ccd6eed887723c5250514ef1d Mon Sep 17 00:00:00 2001 From: Suyash Kumar Date: Fri, 12 Jul 2024 14:24:13 -0700 Subject: [PATCH] Fix issue with properties on null values inside queries. This ensures the valueProperty helper also returns null on null value inputs. PiperOrigin-RevId: 651886526 --- interpreter/property.go | 3 +++ interpreter/property_test.go | 38 ++++++++++++++++++++++++++++----- tests/enginetests/query_test.go | 6 ++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/interpreter/property.go b/interpreter/property.go index 31283b7..eba8251 100644 --- a/interpreter/property.go +++ b/interpreter/property.go @@ -60,6 +60,9 @@ func (i *interpreter) valueProperty(v result.Value, property string, staticResul if property == "" { return v, nil } + if result.IsNull(v) { + return result.New(nil) + } switch ot := v.GolangValue().(type) { case result.Tuple: diff --git a/interpreter/property_test.go b/interpreter/property_test.go index 9de03f5..6d3b8c8 100644 --- a/interpreter/property_test.go +++ b/interpreter/property_test.go @@ -83,11 +83,6 @@ func TestEvalPropertyValue_Errors(t *testing.T) { }), resultType: &types.List{ElementType: types.Integer}, }, - { - name: "null", - property: "name", - value: newOrFatal(t, nil), - }, { name: "interval invalid property", property: "invalid", @@ -119,6 +114,39 @@ func TestEvalPropertyValue_Errors(t *testing.T) { } } +func TestEvalPropertyValue(t *testing.T) { + tests := []struct { + name string + property string + value result.Value + resultType types.IType + wantValue result.Value + }{ + { + name: "property on null input value", + property: "apple", + value: newOrFatal(t, nil), + wantValue: newOrFatal(t, nil), + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + i := &interpreter{ + refs: reference.NewResolver[result.Value, *model.FunctionDef](), + modelInfo: newFHIRModelInfo(t), + evaluationTimestamp: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC), + } + got, err := i.valueProperty(tc.value, tc.property, tc.resultType) + if err != nil { + t.Errorf("evalPropertyValue(%q) unexpected error: %v", tc.property, err) + } + if !got.Equal(tc.wantValue) { + t.Errorf("evalPropertyValue(%q) = %v, want %v", tc.property, got, tc.wantValue) + } + }) + } +} + func newFHIRModelInfo(t *testing.T) *modelinfo.ModelInfos { t.Helper() fhirMIBytes, err := embeddata.ModelInfos.ReadFile("third_party/cqframework/fhir-modelinfo-4.0.1.xml") diff --git a/tests/enginetests/query_test.go b/tests/enginetests/query_test.go index 3ae4e81..956b67e 100644 --- a/tests/enginetests/query_test.go +++ b/tests/enginetests/query_test.go @@ -513,6 +513,12 @@ func TestQuery(t *testing.T) { StaticType: &types.List{ElementType: &types.Tuple{ElementTypes: map[string]types.IType{"A": types.Integer, "B": types.Integer}}}, }), }, + { + // This ensures that properties on null values inside queries are handled correctly. + name: "Property on null alias in query", + cql: "define TESTRESULT: (null as Code) l return l.code", + wantResult: newOrFatal(t, nil), + }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) {