@@ -17,6 +17,7 @@ import (
17
17
"sync"
18
18
"testing"
19
19
"time"
20
+ "unicode/utf8"
20
21
21
22
"github.com/cockroachdb/cockroach/pkg/sql/vecindex/cspann"
22
23
"github.com/cockroachdb/cockroach/pkg/sql/vecindex/cspann/commontest"
@@ -162,7 +163,30 @@ func (s *testState) LoadIndex(d *datadriven.TestData) string {
162
163
s .makeNewIndex (d )
163
164
164
165
lines := strings .Split (d .Input , "\n " )
165
- s .loadIndexFromFormat (s .TreeKey , lines , 0 )
166
+
167
+ // Determine the root level by determining max indent.
168
+ maxIndent := 0
169
+ for _ , line := range lines {
170
+ // Lines ending with the "│" rune don't increase the level
171
+ if strings .HasSuffix (line , "│" ) {
172
+ continue
173
+ }
174
+
175
+ // Leaf vector lines don't increase the level.
176
+ idx := strings .Index (line , "• " )
177
+ if idx != - 1 {
178
+ // Note that the '•' rune is 3 UTF-8 bytes.
179
+ firstChar := line [idx + 4 ]
180
+ if firstChar < '0' || firstChar > '9' {
181
+ // This is a leaf vector.
182
+ continue
183
+ }
184
+ }
185
+
186
+ maxIndent = max (maxIndent , getIndexFormatIndent (line ))
187
+ }
188
+
189
+ s .loadIndexFromFormat (s .TreeKey , lines , cspann .Level (maxIndent + 1 ))
166
190
167
191
return fmt .Sprintf ("Loaded %d vectors.\n " , len (s .MemStore .GetAllVectors ()))
168
192
}
@@ -848,8 +872,8 @@ func (s *testState) parseKeyAndVector(line string) (cspann.KeyBytes, vector.T) {
848
872
}
849
873
850
874
func (s * testState ) loadIndexFromFormat (
851
- treeKey cspann.TreeKey , lines []string , indent int ,
852
- ) (remaining []string , level cspann. Level , centroid vector.T , childKey cspann.ChildKey ) {
875
+ treeKey cspann.TreeKey , lines []string , level cspann. Level ,
876
+ ) (remaining []string , centroid vector.T , childKey cspann.ChildKey ) {
853
877
// Ensure line contains "• ", note that the '•' rune is 3 UTF-8 bytes.
854
878
idx := strings .Index (lines [0 ], "• " )
855
879
require .NotEqual (s .T , - 1 , idx )
@@ -863,7 +887,7 @@ func (s *testState) loadIndexFromFormat(
863
887
vec := s .parseVector (line )
864
888
s .MemStore .InsertVector (keyBytes , vec )
865
889
randomized := s .Index .TransformVector (vec , make (vector.T , len (vec )))
866
- return lines [1 :], cspann . LeafLevel , randomized , cspann.ChildKey {KeyBytes : keyBytes }
890
+ return lines [1 :], randomized , cspann.ChildKey {KeyBytes : keyBytes }
867
891
}
868
892
869
893
// This is an interior partition.
@@ -885,33 +909,33 @@ func (s *testState) loadIndexFromFormat(
885
909
centroid = s .parseVector (line )
886
910
centroid = s .Index .TransformVector (centroid , make (vector.T , len (centroid )))
887
911
912
+ // Parse any children.
913
+ parentIndent := getIndexFormatIndent (lines [0 ])
888
914
lines = lines [1 :]
889
915
890
- childLevel := cspann .LeafLevel
891
916
childVectors := vector .MakeSet (len (centroid ))
892
917
childKeys := []cspann.ChildKey (nil )
893
918
894
- if len (lines ) > 0 && strings .HasSuffix (lines [0 ], "│" ) {
895
- // There are children, so loop over them.
896
- childIndent := len (lines [0 ]) - len ("│" )
897
- for len (lines ) > 0 && len (lines [0 ]) > childIndent {
898
- remainder := lines [0 ][childIndent :]
899
- if remainder == "│" {
900
- // Skip line.
901
- lines = lines [1 :]
902
- continue
903
- } else if strings .HasPrefix (remainder , "├" ) || strings .HasPrefix (remainder , "└" ) {
904
- var childVector vector.T
905
- lines , childLevel , childVector , childKey = s .loadIndexFromFormat (treeKey , lines , childIndent )
906
- childVectors .Add (childVector )
907
- childKeys = append (childKeys , childKey )
908
- }
919
+ for len (lines ) > 0 {
920
+ childIndent := getIndexFormatIndent (lines [0 ])
921
+ if childIndent <= parentIndent {
922
+ break
923
+ }
924
+ if strings .HasSuffix (lines [0 ], "│" ) {
925
+ // Skip line.
926
+ lines = lines [1 :]
927
+ continue
928
+ } else {
929
+ var childVector vector.T
930
+ lines , childVector , childKey = s .loadIndexFromFormat (treeKey , lines , level - 1 )
931
+ childVectors .Add (childVector )
932
+ childKeys = append (childKeys , childKey )
909
933
}
910
934
}
911
935
912
936
// Always create partition in Ready state so that adds are allowed.
913
937
metadata := cspann.PartitionMetadata {
914
- Level : childLevel ,
938
+ Level : level ,
915
939
Centroid : centroid ,
916
940
}
917
941
metadata .StateDetails .MakeReady ()
@@ -934,7 +958,7 @@ func (s *testState) loadIndexFromFormat(
934
958
require .NoError (s .T , err )
935
959
}
936
960
937
- return lines , childLevel + 1 , centroid , cspann.ChildKey {PartitionKey : partitionKey }
961
+ return lines , centroid , cspann.ChildKey {PartitionKey : partitionKey }
938
962
}
939
963
940
964
// parsePartitionStateDetails parses a partition state details string in this
@@ -1267,3 +1291,22 @@ func validateIndex(
1267
1291
})
1268
1292
require .Empty (t , missingKeys )
1269
1293
}
1294
+
1295
+ // getIndexFormatIndent returns the number of indentation levels in the given
1296
+ // formatted line. For example, for this snippet:
1297
+ //
1298
+ // • 1 (0, 0)
1299
+ // │
1300
+ // ├───• 2 (-9, 18)
1301
+ //
1302
+ // Line 1 would have indent of 0 and lines 2 and 3 would have indent of 1.
1303
+ func getIndexFormatIndent (line string ) int {
1304
+ // Compute level for line containing the "•" rune.
1305
+ idx := strings .Index (line , "• " )
1306
+ if idx != - 1 {
1307
+ return utf8 .RuneCountInString (line [:idx ]) / 4
1308
+ }
1309
+
1310
+ // Otherwise, this must be a line ending with the "│" rune.
1311
+ return utf8 .RuneCountInString (line )/ 4 + 1
1312
+ }
0 commit comments