open-consul/agent/consul/state/prepared_query_index.go

55 lines
1.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package state
import (
"fmt"
"strings"
"github.com/hashicorp/consul/agent/consul/prepared_query"
)
// PreparedQueryIndex is a custom memdb indexer used to manage index prepared
// query templates. None of the built-in indexers do what we need, and our
// use case is pretty specific so it's better to put the logic here.
type PreparedQueryIndex struct {
}
// FromObject is used to compute the index key when inserting or updating an
// object.
func (*PreparedQueryIndex) FromObject(obj interface{}) (bool, []byte, error) {
wrapped, ok := obj.(*queryWrapper)
if !ok {
return false, nil, fmt.Errorf("invalid object given to index as prepared query")
}
query := toPreparedQuery(wrapped)
if !prepared_query.IsTemplate(query) {
return false, nil, nil
}
// Always prepend a null so that we can represent even an empty name.
out := "\x00" + strings.ToLower(query.Name)
return true, []byte(out), nil
}
// FromArgs is used when querying for an exact match. Since we don't add any
// suffix we can just call the prefix version.
func (p *PreparedQueryIndex) FromArgs(args ...interface{}) ([]byte, error) {
return p.PrefixFromArgs(args...)
}
// PrefixFromArgs is used when doing a prefix scan for an object.
func (*PreparedQueryIndex) PrefixFromArgs(args ...interface{}) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
arg, ok := args[0].(string)
if !ok {
return nil, fmt.Errorf("argument must be a string: %#v", args[0])
}
arg = "\x00" + strings.ToLower(arg)
return []byte(arg), nil
}