55 lines
1.6 KiB
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
|
|
}
|