go.temporal.io/server/common/searchattribute/stringify.go

210 LOC · 135 covered · 75 uncovered · 47 ranges · 64 concepts · 33 introducers · 36 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the fileHistory_succeeds_but_visibility_fails, Visibility_succeeds_but_history_fails · 0 introduced LOCHistory_succeeds_but_vis…Search_attribute_with_no_embedded_type_information · 0 introduced LOCSearch_attribute_with_no…archiver.go ×1 · 2 introduced LOCarchiver.go ×1Both_targets_succeed · 0 introduced LOCBoth_targets_succeedVisibility_archival_succeeds · 0 introduced LOCVisibility_archival_succ…archiver.go ×1 · 2 introduced LOCarchiver.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1interface_mock.go ×3 · 30 introduced LOCinterface_mock.go ×3archiver.go ×1 · 2 introduced LOCarchiver.go ×1visibility_archiver.go ×1 · 1 introduced LOCvisibility_archiver.go ×…query_parser.go ×1 · 4 introduced LOCquery_parser.go ×1TestQuery_Success_SmallPageSize · 0 introduced LOCTestQuery_Success_SmallP…visibility_archiver.go ×1 · 10 introduced LOCvisibility_archiver.go ×…TestQuery_Success_NoNextPageToken · 0 introduced LOCTestQuery_Success_NoNext…TestArchiveAndQuery · 0 introduced LOCTestArchiveAndQueryvisibility_archiver.go ×5 · 58 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×2 · 11 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×7 · 39 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×1 · 2 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×3 · 9 introduced LOCvisibility_archiver.go ×…TestQuery_Success_NoNextPageToken · 0 introduced LOCTestQuery_Success_NoNext…TestQuery_Success_SmallPageSize · 0 introduced LOCTestQuery_Success_SmallP…visibility_archiver.go ×11 · 44 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×3 · 6 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×2 · 11 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×2 · 6 introduced LOCvisibility_archiver.go ×…visibility_archiver.go ×11 · 57 introduced LOCvisibility_archiver.go ×…stringify.go ×2 · 6 introduced LOCstringify.go ×2stringify.go ×2 · 4 introduced LOCstringify.go ×2Test_Parse_MissedFieldsInTypeMap · 0 introduced LOCTest_Parse_MissedFieldsI…stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×2 · 4 introduced LOCstringify.go ×2Test_Parse_ValidTypeMap · 0 introduced LOCTest_Parse_ValidTypeMapTest_Parse_Array · 0 introduced LOCTest_Parse_Arraystringify.go ×2 · 2 introduced LOCstringify.go ×2Test_Parse_NilTypeMap · 0 introduced LOCTest_Parse_NilTypeMapstringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×2 · 4 introduced LOCstringify.go ×2stringify.go ×1 · 3 introduced LOCstringify.go ×1stringify.go ×4 · 12 introduced LOCstringify.go ×4stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×2 · 11 introduced LOCstringify.go ×2stringify.go ×2 · 5 introduced LOCstringify.go ×2stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×2 · 5 introduced LOCstringify.go ×2stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×3 · 13 introduced LOCstringify.go ×3stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×2 · 6 introduced LOCstringify.go ×2unspecified · 0 introduced LOCunspecifiedstringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 2 introduced LOCstringify.go ×1stringify.go ×1 · 4 introduced LOCstringify.go ×1TestArchiveAndQuery · introduced test · go.temporal.io/server/common/archiver/filestore/TestVisibilityArchiverSuite/TestArchiveAndQueryTestArchiveAndQueryTestQuery_EmptyQuery_Pagination · introduced test · go.temporal.io/server/common/archiver/filestore/TestVisibilityArchiverSuite/TestQuery_EmptyQuery_PaginationTestQuery_EmptyQuery_Pag…TestQuery_Success_NoNextPageToken · introduced test · go.temporal.io/server/common/archiver/filestore/TestVisibilityArchiverSuite/TestQuery_Success_NoNextPageTokenTestQuery_Success_NoNext…TestQuery_Success_SmallPageSize · introduced test · go.temporal.io/server/common/archiver/filestore/TestVisibilityArchiverSuite/TestQuery_Success_SmallPageSizeTestQuery_Success_SmallP…TestQuery_EmptyQuery_Pagination · introduced test · go.temporal.io/server/common/archiver/gcloud/TestVisibilityArchiverSuiteSuite/TestQuery_EmptyQuery_PaginationTestQuery_EmptyQuery_Pag…TestQuery_Success_NoNextPageToken · introduced test · go.temporal.io/server/common/archiver/gcloud/TestVisibilityArchiverSuiteSuite/TestQuery_Success_NoNextPageTokenTestQuery_Success_NoNext…TestQuery_Success_SmallPageSize · introduced test · go.temporal.io/server/common/archiver/gcloud/TestVisibilityArchiverSuiteSuite/TestQuery_Success_SmallPageSizeTestQuery_Success_SmallP…TestArchiveAndQuery · introduced test · go.temporal.io/server/common/archiver/s3store/TestVisibilityArchiverSuite/TestArchiveAndQueryTestArchiveAndQueryTestArchiveAndQueryPrecisions · introduced test · go.temporal.io/server/common/archiver/s3store/TestVisibilityArchiverSuite/TestArchiveAndQueryPrecisionsTestArchiveAndQueryPreci…TestQuery_EmptyQuery_Pagination · introduced test · go.temporal.io/server/common/archiver/s3store/TestVisibilityArchiverSuite/TestQuery_EmptyQuery_PaginationTestQuery_EmptyQuery_Pag…TestQuery_Success_NoNextPageToken · introduced test · go.temporal.io/server/common/archiver/s3store/TestVisibilityArchiverSuite/TestQuery_Success_NoNextPageTokenTestQuery_Success_NoNext…TestQuery_Success_SmallPageSize · introduced test · go.temporal.io/server/common/archiver/s3store/TestVisibilityArchiverSuite/TestQuery_Success_SmallPageSizeTestQuery_Success_SmallP…Test_Parse_Array · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Parse_ArrayTest_Parse_ArrayTest_Parse_MissedFieldsInTypeMap · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Parse_MissedFieldsInTypeMapTest_Parse_MissedFieldsI…Test_Parse_NilTypeMap · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Parse_NilTypeMapTest_Parse_NilTypeMapTest_Parse_ValidTypeMap · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Parse_ValidTypeMapTest_Parse_ValidTypeMapTest_Parse_WrongTypesInTypeMap · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Parse_WrongTypesInTypeMapTest_Parse_WrongTypesInT…Test_Stringify · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_StringifyTest_StringifyTest_Stringify_Array · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_Stringify_ArrayTest_Stringify_ArrayTest_isJSONArray · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_isJSONArrayTest_isJSONArraybool · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/boolbooldatetime · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/datetimedatetimedouble · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/doubledoubleint · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/intintstring · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/stringstringunspecified · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseJSONArray/unspecifiedunspecifiedTest_parseValueOrArray · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseValueOrArrayTest_parseValueOrArrayTest_parseValueTyped · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseValueTypedTest_parseValueTypedTest_parseValueUnspecified · introduced test · go.temporal.io/server/common/searchattribute/TestStringifySuite/Test_parseValueUnspecifiedTest_parseValueUnspecifi…Both_targets_succeed · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Both_targets_succeedBoth_targets_succeedHistory_succeeds_but_visibility_fails · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/History_succeeds_but_visibility_failsHistory_succeeds_but_vis…Search_attribute_missing_in_type_map · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Search_attribute_missing_in_type_mapSearch_attribute_missing…Search_attribute_with_no_embedded_type_information · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Search_attribute_with_no_embedded_type_informationSearch_attribute_with_no…Visibility_archival_succeeds · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Visibility_archival_succeedsVisibility_archival_succ…Visibility_archival_succeeds_with_nil_HistoryURI · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Visibility_archival_succeeds_with_nil_HistoryURIVisibility_archival_succ…Visibility_succeeds_but_history_fails · introduced test · go.temporal.io/server/service/history/archival/TestArchiver/Visibility_succeeds_but_history_failsVisibility_succeeds_but_…Focused file · go.temporal.io/server/common/searchattribute/stringify.go · 210 LOCsearchattribute/stringif…

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 package searchattribute
2
3 import (
4 "encoding/json"
5 "fmt"
6 "reflect"
7 "strconv"
8 "strings"
9 "time"
10
11 commonpb "go.temporal.io/api/common/v1"
12 enumspb "go.temporal.io/api/enums/v1"
13 "go.temporal.io/server/common/searchattribute/sadefs"
14 )
15
16 // Stringify converts search attributes to map of strings using (in order):
17 // 1. type from MetadataType field,
18 // 2. type from typeMap (can be nil).
19 // In case of error, it will continue to next search attribute and return last error.
20 // Single values are converted using strconv, arrays are converted using json.Marshal.
21 // Search attributes with `nil` values are skipped.
22 > func Stringify(searchAttributes *commonpb.SearchAttributes, typeMap *NameTypeMap) (map[string]string, error) { stringify.go ×1
23 > if len(searchAttributes.GetIndexedFields()) == 0 {
24 > return nil, nil stringify.go ×1
25 > }
26
27 > result := make(map[string]string, len(searchAttributes.GetIndexedFields())) stringify.go ×2
28 > var lastErr error
29 >
30 > for saName, saPayload := range searchAttributes.GetIndexedFields() {
31 > saType := enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED
32 > if typeMap != nil {
33 > saType, _ = typeMap.getType(saName, customCategory|predefinedCategory)
34 > }
35 > saValue, err := sadefs.DecodeValue(saPayload, saType, true)
36 > if err != nil {
37 > // If DecodeValue failed, save error and use raw JSON from Data field. stringify.go ×1
38 > result[saName] = string(saPayload.GetData())
39 > lastErr = err
40 > continue
41 }
42
43 > if saValue == nil { stringify.go ×2
44 continue
45 }
46
47 > switch saTypedValue := saValue.(type) { stringify.go ×2
48 > case string: stringify.go ×1
49 > result[saName] = saTypedValue
50 > case int64: stringify.go ×2
51 > result[saName] = strconv.FormatInt(saTypedValue, 10)
52 case float64:
53 result[saName] = strconv.FormatFloat(saTypedValue, 'f', -1, 64)
54 > case bool: stringify.go ×2
55 > result[saName] = strconv.FormatBool(saTypedValue)
56 case time.Time:
57 result[saName] = saTypedValue.Format(time.RFC3339Nano)
58 > default: stringify.go ×2
59 > switch reflect.TypeOf(saValue).Kind() {
60 > case reflect.Slice, reflect.Array:
61 > valBytes, err := json.Marshal(saValue)
62 > if err != nil {
63 result[saName] = string(saPayload.GetData())
64 lastErr = err
65 continue
66 }
67 > result[saName] = string(valBytes) stringify.go ×2
68 default:
69 result[saName] = fmt.Sprintf("%v", saTypedValue)
70 }
71 }
72 }
73
74 > return result, lastErr stringify.go ×2
75 }
76
77 // Parse converts maps of search attribute strings to search attributes.
78 // typeMap can be nil (values will be parsed with strconv and MetadataType field won't be set).
79 // In case of error, it will continue to next search attribute and return last error.
80 // Single values are parsed using strconv, arrays are parsed using json.Unmarshal.
81 > func Parse(searchAttributesStr map[string]string, typeMap *NameTypeMap) (*commonpb.SearchAttributes, error) { stringify.go ×1
82 > if len(searchAttributesStr) == 0 {
83 > return nil, nil stringify.go ×1
84 > }
85
86 > searchAttributes := &commonpb.SearchAttributes{ stringify.go ×4
87 > IndexedFields: make(map[string]*commonpb.Payload, len(searchAttributesStr)),
88 > }
89 > var lastErr error
90 >
91 > for saName, saValStr := range searchAttributesStr {
92 > saType := enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED
93 > if typeMap != nil {
94 > saType, _ = typeMap.getType(saName, customCategory|predefinedCategory) stringify.go ×1
95 > }
96 > saValPayload, err := parseValueOrArray(saValStr, saType) stringify.go ×4
97 > if err != nil {
98 > lastErr = err stringify.go ×2
99 > }
100 > searchAttributes.IndexedFields[saName] = saValPayload stringify.go ×4
101 }
102
103 > return searchAttributes, lastErr stringify.go ×4
104 }
105
106 > func parseValueOrArray(valStr string, t enumspb.IndexedValueType) (*commonpb.Payload, error) { stringify.go ×2
107 > var val any
108 >
109 > if isJSONArray(valStr) {
110 > var err error stringify.go ×1
111 > val, err = parseJSONArray(valStr, t)
112 > if err != nil {
113 > return nil, err stringify.go ×1
114 > }
115 > } else { stringify.go ×1
116 > var err error
117 > val, err = parseValueTyped(valStr, t)
118 > if err != nil {
119 > return nil, err stringify.go ×2
120 > }
121 }
122
123 > return sadefs.EncodeValue(val, t) stringify.go ×2
124 }
125
126 > func parseValueTyped(valStr string, t enumspb.IndexedValueType) (any, error) { stringify.go ×2
127 > var val any
128 > var err error
129 >
130 > switch t {
131 case enumspb.INDEXED_VALUE_TYPE_TEXT,
132 enumspb.INDEXED_VALUE_TYPE_KEYWORD,
133 > enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST: stringify.go ×1
134 > val = valStr
135 > case enumspb.INDEXED_VALUE_TYPE_INT: stringify.go ×1
136 > val, err = strconv.ParseInt(valStr, 10, 64)
137 > case enumspb.INDEXED_VALUE_TYPE_DOUBLE: stringify.go ×2
138 > val, err = strconv.ParseFloat(valStr, 64)
139 > case enumspb.INDEXED_VALUE_TYPE_BOOL: stringify.go ×1
140 > val, err = strconv.ParseBool(valStr)
141 > case enumspb.INDEXED_VALUE_TYPE_DATETIME: stringify.go ×2
142 > val, err = time.Parse(time.RFC3339Nano, valStr)
143 > case enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED: stringify.go ×1
144 > val = parseValueUnspecified(valStr)
145 default:
146 err = fmt.Errorf("%w: %v", sadefs.ErrInvalidType, t)
147 }
148
149 > return val, err stringify.go ×2
150 }
151
152 > func parseValueUnspecified(valStr string) any { stringify.go ×3
153 > var val any
154 > var err error
155 >
156 > if val, err = strconv.ParseInt(valStr, 10, 64); err == nil {
157 > } else if val, err = strconv.ParseBool(valStr); err == nil {
158 > } else if val, err = strconv.ParseFloat(valStr, 64); err == nil {
159 > } else if val, err = time.Parse(time.RFC3339Nano, valStr); err == nil {
160 > } else if isJSONArray(valStr) {
161 > arr, err := parseJSONArray(valStr, enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED) stringify.go ×2
162 > if err != nil {
163 val = valStr
164 > } else { stringify.go ×2
165 > val = arr
166 > }
167 > } else { stringify.go ×3
168 > val = valStr
169 > }
170
171 > return val stringify.go ×3
172 }
173
174 > func isJSONArray(str string) bool { stringify.go ×1
175 > str = strings.TrimSpace(str)
176 > return strings.HasPrefix(str, "[") && strings.HasSuffix(str, "]")
177 > }
178
179 > func parseJSONArray(str string, t enumspb.IndexedValueType) (any, error) { stringify.go ×1
180 > switch t {
181 case enumspb.INDEXED_VALUE_TYPE_TEXT,
182 enumspb.INDEXED_VALUE_TYPE_KEYWORD,
183 > enumspb.INDEXED_VALUE_TYPE_KEYWORD_LIST: stringify.go ×1
184 > var result []string
185 > err := json.Unmarshal([]byte(str), &result)
186 > return result, err
187 > case enumspb.INDEXED_VALUE_TYPE_INT: stringify.go ×1
188 > var result []int64
189 > err := json.Unmarshal([]byte(str), &result)
190 > return result, err
191 > case enumspb.INDEXED_VALUE_TYPE_DOUBLE: stringify.go ×1
192 > var result []float64
193 > err := json.Unmarshal([]byte(str), &result)
194 > return result, err
195 > case enumspb.INDEXED_VALUE_TYPE_BOOL: stringify.go ×1
196 > var result []bool
197 > err := json.Unmarshal([]byte(str), &result)
198 > return result, err
199 > case enumspb.INDEXED_VALUE_TYPE_DATETIME: stringify.go ×1
200 > var result []time.Time
201 > err := json.Unmarshal([]byte(str), &result)
202 > return result, err
203 > case enumspb.INDEXED_VALUE_TYPE_UNSPECIFIED: stringify.go ×1
204 > var result []any
205 > err := json.Unmarshal([]byte(str), &result)
206 > return result, err
207 default:
208 return nil, fmt.Errorf("%w: %v", sadefs.ErrInvalidType, t)
209 }
210 }