github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/entity/genidx/genidx.go (about) 1 //go:build ignore 2 // +build ignore 3 4 // Copyright (C) 2019-2021 Zilliz. All rights reserved. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software distributed under the License 12 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 13 // or implied. See the License for the specific language governing permissions and limitations under the License. 14 15 // This program generates entity/indexes_gen.go. Invoked by go generate 16 package main 17 18 import ( 19 "fmt" 20 "os" 21 "strings" 22 "text/template" 23 24 "github.com/milvus-io/milvus-sdk-go/v2/entity" 25 ) 26 27 var indexTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT 28 // This file is generated by go generate 29 30 package entity 31 32 import ( 33 "errors" 34 "encoding/json" 35 "fmt" 36 ) 37 38 {{ range .Indexes }}{{with .}} 39 40 var _ Index = &Index{{.IdxName}}{} 41 42 // Index{{.IdxName}} idx type for {{.IdxType}} 43 type Index{{.IdxName}} struct { //auto generated fields{{range .ConstructParams}}{{with .}} 44 {{.Name}} {{.ParamType}}{{end}}{{end}} 45 metricType MetricType 46 } 47 48 // Name returns index type name, implementing Index interface 49 func(i *Index{{.IdxName}}) Name() string { 50 return "{{.IdxName}}" 51 } 52 53 // IndexType returns IndexType, implementing Index interface 54 func(i *Index{{.IdxName}}) IndexType() IndexType { 55 return IndexType("{{.IdxType}}") 56 } 57 58 // SupportBinary returns whether index type support binary vector 59 func(i *Index{{.IdxName}}) SupportBinary() bool { 60 return {{.VectorSupport}} & 2 > 0 61 } 62 63 // Params returns index construction params, implementing Index interface 64 func(i *Index{{.IdxName}}) Params() map[string]string { 65 params := map[string]string {//auto generated mapping {{range .ConstructParams}}{{with .}} 66 "{{.Name}}": fmt.Sprintf("%v",i.{{.Name}}),{{end}}{{end}} 67 } 68 bs, _ := json.Marshal(params) 69 return map[string]string { 70 "params": string(bs), 71 "index_type": string(i.IndexType()), 72 "metric_type": string(i.metricType), 73 } 74 } 75 76 // NewIndex{{.IdxName}} create index with construction parameters 77 func NewIndex{{.IdxName}}(metricType MetricType, {{range .ConstructParams}}{{with .}} 78 {{.Name}} {{.ParamType}}, 79 {{end}}{{end}}) (*Index{{.IdxName}}, error) { 80 // auto generate parameters validation code, if any{{range .ConstructParams}}{{with .}} 81 {{.ValidationCode}} 82 {{end}}{{end}} 83 return &Index{{.IdxName}}{ {{range .ConstructParams}}{{with .}} 84 //auto generated setting 85 {{.Name}}: {{.Name}},{{end}}{{end}} 86 metricType: metricType, 87 }, nil 88 } 89 {{end}}{{end}} 90 `)) 91 92 var indexTestTemplate = template.Must(template.New("").Funcs(template.FuncMap{ 93 "SContains": func(s, sub string) bool { return strings.Contains(s, sub) }, 94 }).Parse(`// Code generated by go generate; DO NOT EDIT 95 // This file is generated by go generate 96 97 package entity 98 99 import ( 100 "testing" 101 102 "github.com/stretchr/testify/assert" 103 ) 104 105 {{range $idx := .Indexes}}{{with.}} 106 func TestIndex{{.IdxName}}(t *testing.T){ 107 {{range .ConstructParams}}{{with.}} 108 var {{.Name}} {{.ParamType}}{{end}}{{end}} 109 110 {{if SContains $idx.IdxName "Bin" }}mt := HAMMING{{else}}mt := L2{{end}} 111 112 113 t.Run("valid usage case", func(t *testing.T){ 114 {{range $i, $example := .ValidExamples}} 115 {{$example}} 116 idx{{$i}}, err := NewIndex{{$idx.IdxName}}(mt, {{range $idx.ConstructParams}}{{with.}} 117 {{.Name}},{{end}}{{end}} 118 ) 119 assert.Nil(t, err) 120 assert.NotNil(t, idx{{$i}}) 121 assert.Equal(t, "{{$idx.IdxName}}", idx{{$i}}.Name()) 122 assert.EqualValues(t, "{{$idx.IdxType}}", idx{{$i}}.IndexType()) 123 assert.NotNil(t, idx{{$i}}.Params()) 124 {{if SContains $idx.IdxName "Bin" }}assert.True(t, idx{{$i}}.SupportBinary()){{else}}assert.False(t, idx{{$i}}.SupportBinary()){{end}} 125 {{end}} 126 }) 127 128 t.Run("invalid usage case", func(t *testing.T){ 129 {{range $i, $example := .InvalidExamples}} 130 {{$example}} 131 idx{{$i}}, err := NewIndex{{$idx.IdxName}}(mt, {{range $idx.ConstructParams}}{{with.}} 132 {{.Name}},{{end}}{{end}} 133 ) 134 assert.NotNil(t, err) 135 assert.Nil(t, idx{{$i}}) 136 {{end}} 137 }) 138 } 139 {{end}}{{end}} 140 `)) 141 142 var indexSearchParamTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT 143 // This file is generated by go generate 144 145 package entity 146 147 import ( 148 "errors" 149 ) 150 151 {{ range .Indexes }}{{with.}} 152 var _ SearchParam = &Index{{.IdxName}}SearchParam{} 153 154 // Index{{.IdxName}}SearchParam search param struct for index type {{.IdxType}} 155 type Index{{.IdxName}}SearchParam struct { //auto generated fields 156 baseSearchParams 157 {{range .SearchParams}}{{with.}} 158 {{.Name}} {{.ParamType}}{{end}}{{end}} 159 } 160 161 // NewIndex{{.IdxName}}SearchParam create index search param 162 func NewIndex{{.IdxName}}SearchParam({{range .SearchParams}}{{with .}} 163 {{.Name}} {{.ParamType}}, 164 {{end}}{{end}}) (*Index{{.IdxName}}SearchParam, error) { 165 // auto generate parameters validation code, if any{{range .SearchParams}}{{with .}} 166 {{.ValidationCode}} 167 {{end}}{{end}} 168 sp := &Index{{.IdxName}}SearchParam{ 169 baseSearchParams: newBaseSearchParams(), 170 } 171 172 //auto generated setting{{range .SearchParams}}{{with .}} 173 sp.params["{{.Name}}"] = {{.Name}}{{end}}{{end}} 174 175 return sp, nil 176 } 177 {{end}}{{end}} 178 `)) 179 180 var indexSearchParamTestTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT 181 // This file is generated by go generate 182 183 package entity 184 185 import ( 186 "testing" 187 188 "github.com/stretchr/testify/assert" 189 ) 190 191 {{range $idx := .Indexes}}{{with.}} 192 func TestIndex{{.IdxName}}SearchParam(t *testing.T) { 193 {{range .SearchParams}}{{with.}} 194 var {{.Name}} {{.ParamType}}{{end}}{{end}} 195 196 t.Run("valid usage case", func(t *testing.T){ 197 {{range $i, $example := .ValidSearchParams}} 198 {{$example}} 199 idx{{$i}}, err := NewIndex{{$idx.IdxName}}SearchParam({{range $idx.SearchParams}}{{with.}} 200 {{.Name}},{{end}}{{end}} 201 ) 202 assert.Nil(t, err) 203 assert.NotNil(t, idx{{$i}}) 204 assert.NotNil(t, idx{{$i}}.Params()) 205 {{end}} 206 }) 207 {{ if .InvalidSearchParams }} 208 t.Run("invalid usage case", func(t *testing.T){ 209 {{range $i, $example := .InvalidSearchParams}} 210 {{$example}} 211 idx{{$i}}, err := NewIndex{{$idx.IdxName}}SearchParam({{range $idx.SearchParams}}{{with.}} 212 {{.Name}},{{end}}{{end}} 213 ) 214 assert.NotNil(t, err) 215 assert.Nil(t, idx{{$i}}) 216 {{end}} 217 }) 218 {{end}} 219 } 220 {{end}}{{end}} 221 `)) 222 223 type idxDef struct { 224 IdxName string 225 IdxType entity.IndexType 226 VectorSupport int8 227 ConstructParams []idxParam 228 SearchParams []idxParam 229 ValidExamples []string // valid value examples, used in tests 230 InvalidExamples []string // invalid value examples, used in tests 231 ValidSearchParams []string 232 InvalidSearchParams []string 233 } 234 235 type idxParam struct { 236 Name string 237 Type string // default int 238 ValidationRule string // support format `[min, max]`, `in (...)` `{other param}===0 (mod self)` 239 } 240 241 // ParamType param definition type 242 func (ip idxParam) ParamType() string { 243 if ip.Type == "" { 244 return "int" 245 } 246 return ip.Type 247 } 248 249 // ValidationCode auto generate validation code by validation rule 250 func (ip idxParam) ValidationCode() string { 251 if ip.Type == "" { 252 ip.Type = "int" 253 } 254 switch { 255 case strings.HasPrefix(ip.ValidationRule, "in ("): // TODO change to regex 256 raw := ip.ValidationRule[4 : len(ip.ValidationRule)-1] 257 return fmt.Sprintf(`validRange := []%s{%s} 258 %sOk := false 259 for _, v := range validRange { 260 if v == %s { 261 %sOk = true 262 break 263 } 264 } 265 if !%sOk { 266 return nil, errors.New("%s not valid") 267 }`, ip.Type, raw, ip.Name, ip.Name, ip.Name, ip.Name, ip.Name) 268 case strings.Contains(ip.ValidationRule, "==="): // TODO change to regex 269 //TODO NOT IMPLEMENT YET 270 case strings.Contains(ip.ValidationRule, "[") && 271 strings.Contains(ip.ValidationRule, "]"): // TODO change to regex 272 // very restrict format contstraint to `[min, max]` 273 // not extra space allowed 274 raw := ip.ValidationRule[1 : len(ip.ValidationRule)-1] 275 parts := strings.Split(raw, ",") 276 min := strings.TrimSpace(parts[0]) 277 max := strings.TrimSpace(parts[1]) 278 return fmt.Sprintf(`if %s < %s { 279 return nil, errors.New("%s has to be in range [%s, %s]") 280 } 281 if %s > %s { 282 return nil, errors.New("%s has to be in range [%s, %s]") 283 }`, ip.Name, min, ip.Name, min, max, ip.Name, max, ip.Name, min, max) 284 default: 285 return "" 286 } 287 288 return "" 289 } 290 291 type vectorTypeSupport int8 292 293 const ( 294 floatVectorSupport vectorTypeSupport = 1 295 binaryVectorSupport vectorTypeSupport = 1 << 1 296 ) 297 298 func main() { 299 f, err := os.OpenFile("indexes_gen.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) 300 if err != nil { 301 fmt.Println(err.Error()) 302 os.Exit(1) 303 } 304 defer f.Close() 305 ft, err := os.OpenFile("indexes_gen_test.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) 306 if err != nil { 307 fmt.Println(err.Error()) 308 os.Exit(1) 309 } 310 defer ft.Close() 311 fp, err := os.OpenFile("indexes_search_param_gen.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) 312 if err != nil { 313 fmt.Println(err.Error()) 314 os.Exit(1) 315 } 316 defer fp.Close() 317 fpt, err := os.OpenFile("indexes_search_param_gen_test.go", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) 318 if err != nil { 319 fmt.Println(err.Error()) 320 os.Exit(1) 321 } 322 defer fpt.Close() 323 324 settings := struct { 325 Indexes []idxDef 326 }{ 327 Indexes: []idxDef{ 328 // FLAT 329 { 330 IdxName: "Flat", 331 IdxType: entity.Flat, 332 ConstructParams: []idxParam{}, 333 SearchParams: []idxParam{}, 334 ValidExamples: []string{ 335 "", 336 }, 337 InvalidExamples: []string{}, 338 ValidSearchParams: []string{ 339 "", 340 }, 341 InvalidSearchParams: []string{}, 342 }, 343 // BIN_FLAT 344 { 345 IdxName: "BinFlat", 346 IdxType: entity.BinFlat, 347 VectorSupport: int8(binaryVectorSupport), 348 ConstructParams: []idxParam{ 349 { 350 Name: "nlist", 351 ValidationRule: "[1, 65536]", 352 }, 353 }, 354 SearchParams: []idxParam{ 355 { 356 Name: "nprobe", 357 ValidationRule: "[1, 65536]", //[1, nlist] 358 }, 359 }, 360 ValidExamples: []string{ 361 "nlist = 10", 362 }, 363 InvalidExamples: []string{ 364 "nlist = 0", 365 "nlist = 65537", 366 }, 367 ValidSearchParams: []string{ 368 "nprobe = 10", 369 }, 370 InvalidSearchParams: []string{ 371 "nprobe = 0", 372 "nprobe = 65537", 373 }, 374 }, 375 // IVF_FLAT 376 { 377 IdxName: "IvfFlat", 378 IdxType: entity.IvfFlat, 379 ConstructParams: []idxParam{ 380 { 381 Name: "nlist", 382 ValidationRule: "[1, 65536]", 383 }, 384 }, 385 SearchParams: []idxParam{ 386 { 387 Name: "nprobe", 388 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 389 }, 390 }, 391 ValidExamples: []string{ 392 "nlist = 10", 393 }, 394 InvalidExamples: []string{ 395 "nlist = 0", 396 "nlist = 65537", 397 }, 398 ValidSearchParams: []string{ 399 "nprobe = 10", 400 }, 401 InvalidSearchParams: []string{ 402 "nprobe = 0", 403 "nprobe = 65537", 404 }, 405 }, 406 // BIN_IVF_FLAT 407 { 408 IdxName: "BinIvfFlat", 409 IdxType: entity.BinIvfFlat, 410 VectorSupport: int8(binaryVectorSupport), 411 ConstructParams: []idxParam{ 412 { 413 Name: "nlist", 414 ValidationRule: "[1, 65536]", 415 }, 416 }, 417 SearchParams: []idxParam{ 418 { 419 Name: "nprobe", 420 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 421 }, 422 }, 423 ValidExamples: []string{ 424 "nlist = 10", 425 }, 426 InvalidExamples: []string{ 427 "nlist = 0", 428 "nlist = 65537", 429 }, 430 ValidSearchParams: []string{ 431 "nprobe = 10", 432 }, 433 InvalidSearchParams: []string{ 434 "nprobe = 0", 435 "nprobe = 65537", 436 }, 437 }, 438 // IVF_SQ8 439 { 440 IdxName: "IvfSQ8", 441 IdxType: entity.IvfSQ8, 442 ConstructParams: []idxParam{ 443 { 444 Name: "nlist", 445 ValidationRule: "[1, 65536]", 446 }, 447 }, 448 SearchParams: []idxParam{ 449 { 450 Name: "nprobe", 451 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 452 }, 453 }, 454 ValidExamples: []string{ 455 "nlist = 10", 456 }, 457 InvalidExamples: []string{ 458 "nlist = 0", 459 "nlist = 65537", 460 }, 461 ValidSearchParams: []string{ 462 "nprobe = 10", 463 }, 464 InvalidSearchParams: []string{ 465 "nprobe = 0", 466 "nprobe = 65537", 467 }, 468 }, 469 // IVF_PQ 470 { 471 IdxName: "IvfPQ", 472 IdxType: entity.IvfPQ, 473 ConstructParams: []idxParam{ 474 { 475 Name: "nlist", 476 ValidationRule: "[1, 65536]", 477 }, 478 { 479 Name: "m", 480 ValidationRule: "dim===0 (mod self)", 481 }, 482 { 483 Name: "nbits", 484 ValidationRule: "[1, 16]", 485 }, 486 }, 487 SearchParams: []idxParam{ 488 { 489 Name: "nprobe", 490 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 491 }, 492 }, 493 ValidExamples: []string{ 494 "nlist, m, nbits = 10, 8, 8", 495 }, 496 InvalidExamples: []string{ 497 "nlist, m, nbits = 0, 8, 8", 498 "nlist, m, nbits = 65537, 8, 8", 499 "nlist, m, nbits = 10, 8, 0", 500 "nlist, m, nbits = 10, 8, 17", 501 }, 502 ValidSearchParams: []string{ 503 "nprobe = 10", 504 }, 505 InvalidSearchParams: []string{ 506 "nprobe = 0", 507 "nprobe = 65537", 508 }, 509 }, 510 // HNSW 511 { 512 IdxName: "HNSW", 513 IdxType: entity.HNSW, 514 ConstructParams: []idxParam{ 515 { 516 Name: "M", 517 ValidationRule: "[4, 64]", 518 }, 519 { 520 Name: "efConstruction", 521 ValidationRule: "[8, 512]", 522 }, 523 }, 524 SearchParams: []idxParam{ 525 { 526 Name: "ef", 527 ValidationRule: "[1, 32768]", // [topK, 32768], refer to index construct param, not supported yet 528 }, 529 }, 530 ValidExamples: []string{ 531 "M, efConstruction = 16, 40", 532 }, 533 InvalidExamples: []string{ 534 "M, efConstruction = 3, 40", 535 "M, efConstruction = 65, 40", 536 "M, efConstruction = 16, 7", 537 "M, efConstruction = 16, 513", 538 }, 539 ValidSearchParams: []string{ 540 "ef = 16", 541 }, 542 InvalidSearchParams: []string{ 543 "ef = 0", 544 "ef = 32769", 545 }, 546 }, 547 // IVF_HNSW 548 { 549 IdxName: "IvfHNSW", 550 IdxType: entity.IvfHNSW, 551 ConstructParams: []idxParam{ 552 { 553 Name: "nlist", 554 ValidationRule: "[1, 65536]", 555 }, 556 { 557 Name: "M", 558 ValidationRule: "[4, 64]", 559 }, 560 { 561 Name: "efConstruction", 562 ValidationRule: "[8, 512]", 563 }, 564 }, 565 SearchParams: []idxParam{ 566 { 567 Name: "nprobe", 568 ValidationRule: "[1, 65536]", //[1, nlist] 569 }, 570 { 571 Name: "ef", 572 ValidationRule: "[1, 32768]", // [topK, 32768], refer to index construct param, not supported yet 573 }, 574 }, 575 ValidExamples: []string{ 576 "nlist, M, efConstruction = 10, 16, 40", 577 }, 578 InvalidExamples: []string{ 579 "nlist, M, efConstruction = 0, 16, 40", 580 "nlist, M, efConstruction = 65537, 16, 40", 581 "nlist, M, efConstruction = 10, 3, 40", 582 "nlist, M, efConstruction = 10, 65, 40", 583 "nlist, M, efConstruction = 10, 16, 7", 584 "nlist, M, efConstruction = 10, 16, 513", 585 }, 586 ValidSearchParams: []string{ 587 "nprobe, ef = 10, 16", 588 }, 589 InvalidSearchParams: []string{ 590 "nprobe, ef = 0, 16", 591 "nprobe, ef = 65537, 16", 592 "nprobe, ef = 10, 0", 593 "nprobe, ef = 10, 32769", 594 }, 595 }, 596 { 597 IdxName: "DISKANN", 598 IdxType: entity.DISKANN, 599 ConstructParams: []idxParam{}, 600 SearchParams: []idxParam{ 601 { 602 Name: "search_list", 603 ValidationRule: "[1, 65535]", 604 }, 605 }, 606 ValidExamples: []string{ 607 "", 608 }, 609 InvalidExamples: []string{}, 610 ValidSearchParams: []string{ 611 "search_list = 30", 612 }, 613 InvalidSearchParams: []string{ 614 "search_list = 0", 615 "search_list = 65537", 616 }, 617 }, 618 { 619 IdxName: "AUTOINDEX", 620 IdxType: entity.AUTOINDEX, 621 ConstructParams: []idxParam{}, 622 SearchParams: []idxParam{ 623 { 624 Name: "level", 625 ValidationRule: "[1, 9223372036854775807]", 626 }, 627 }, 628 ValidExamples: []string{ 629 "", 630 }, 631 InvalidExamples: []string{}, 632 ValidSearchParams: []string{ 633 "level = 1", 634 }, 635 InvalidSearchParams: []string{ 636 "level = 0", 637 "level = -1", 638 }, 639 }, 640 { 641 IdxName: "GPUIvfFlat", 642 IdxType: entity.GPUIvfFlat, 643 ConstructParams: []idxParam{ 644 { 645 Name: "nlist", 646 ValidationRule: "[1, 65536]", 647 }, 648 }, 649 SearchParams: []idxParam{ 650 { 651 Name: "nprobe", 652 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 653 }, 654 }, 655 ValidExamples: []string{ 656 "nlist = 10", 657 }, 658 InvalidExamples: []string{ 659 "nlist = 0", 660 "nlist = 65537", 661 }, 662 ValidSearchParams: []string{ 663 "nprobe = 10", 664 }, 665 InvalidSearchParams: []string{ 666 "nprobe = 0", 667 "nprobe = 65537", 668 }, 669 }, 670 { 671 IdxName: "GPUIvfPQ", 672 IdxType: entity.GPUIvfPQ, 673 ConstructParams: []idxParam{ 674 { 675 Name: "nlist", 676 ValidationRule: "[1, 65536]", 677 }, 678 { 679 Name: "m", 680 ValidationRule: "dim===0 (mod self)", 681 }, 682 { 683 Name: "nbits", 684 ValidationRule: "[1, 64]", 685 }, 686 }, 687 SearchParams: []idxParam{ 688 { 689 Name: "nprobe", 690 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 691 }, 692 }, 693 ValidExamples: []string{ 694 "nlist, m, nbits = 10, 8, 8", 695 }, 696 InvalidExamples: []string{ 697 "nlist, m, nbits = 0, 8, 8", 698 "nlist, m, nbits = 65537, 8, 8", 699 "nlist, m, nbits = 10, 8, 0", 700 "nlist, m, nbits = 10, 8, 65", 701 }, 702 ValidSearchParams: []string{ 703 "nprobe = 10", 704 }, 705 InvalidSearchParams: []string{ 706 "nprobe = 0", 707 "nprobe = 65537", 708 }, 709 }, 710 { 711 IdxName: "SCANN", 712 IdxType: entity.SCANN, 713 ConstructParams: []idxParam{ 714 { 715 Name: "nlist", 716 ValidationRule: "[1, 65536]", 717 }, 718 { 719 Name: "with_raw_data", 720 Type: "bool", 721 ValidationRule: "in (false, true)", 722 }, 723 }, 724 SearchParams: []idxParam{ 725 { 726 Name: "nprobe", 727 ValidationRule: "[1, 65536]", // [1, nlist], refer to index construct param, not supported yet 728 }, 729 { 730 Name: "reorder_k", 731 ValidationRule: "[1, 9223372036854775807]", // [topk, MAX_INT], refer to index construct param, not supported yet 732 }, 733 }, 734 ValidExamples: []string{ 735 "nlist = 100", 736 "with_raw_data = true", 737 }, 738 InvalidExamples: []string{ 739 "nlist = 0", 740 "nlist = 65537", 741 }, 742 ValidSearchParams: []string{ 743 "nprobe, reorder_k = 10, 200", 744 }, 745 InvalidSearchParams: []string{ 746 "nprobe, reorder_k = 0, 200", 747 "nprobe, reorder_k = 65537, 200", 748 "nprobe, reorder_k = 10, -1", 749 }, 750 }, 751 }, 752 } 753 754 indexTemplate.Execute(f, settings) 755 indexTestTemplate.Execute(ft, settings) 756 indexSearchParamTemplate.Execute(fp, settings) 757 indexSearchParamTestTemplate.Execute(fpt, settings) 758 }