diff --git a/tfstate/lookup.go b/tfstate/lookup.go index d6e3dc0..c9dc279 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -242,32 +242,32 @@ func (s *TFState) Lookup(key string) (*Object, error) { // we must quote them like `.outputs["repository-arn"]`. // // quoteJQQuery does it. -func quoteJQQuery(query string) string { - splitRegex := regexp.MustCompile(`[.\[\]]`) - indexRegex := regexp.MustCompile(`^-?[0-9]+$`) - parts := splitRegex.Split(query, -1) - parts_coalesced := make([]string, 0, len(parts)) +var ( + quoteSplitRegex = regexp.MustCompile(`[.\[\]]`) + quoteIndexRegex = regexp.MustCompile(`^-?[0-9]+$`) +) - for _, part := range parts { - if part != "" { - parts_coalesced = append(parts_coalesced, part) - } +func quoteJQQuery(query string) string { + if query == "" || !strings.Contains(query, "-") { + // short-circuit if query is empty or doesn't contain hyphen + return query } - + parts := quoteSplitRegex.Split(query, -1) var builder strings.Builder + builder.Grow(len(query) + 5*len(parts)) builder.WriteByte('.') - - for _, part := range parts_coalesced { + for _, part := range parts { + if part == "" { + continue + } builder.WriteByte('[') - if indexRegex.MatchString(part) { + if quoteIndexRegex.MatchString(part) { builder.WriteString(part) } else { if !strings.HasPrefix(part, `"`) { builder.WriteByte('"') } - builder.WriteString(part) - if !strings.HasSuffix(part, `"`) { builder.WriteByte('"') } diff --git a/tfstate/lookup_test.go b/tfstate/lookup_test.go index 77a1c11..8ea1ef0 100644 --- a/tfstate/lookup_test.go +++ b/tfstate/lookup_test.go @@ -229,6 +229,25 @@ func TestLookupFileURL(t *testing.T) { testLookupState(t, state) } +func BenchmarkLookupFile(b *testing.B) { + f, err := os.Open("test/terraform.tfstate") + if err != nil { + b.Error(err) + } + state, err := tfstate.Read(context.Background(), f) + if err != nil { + b.Error(err) + } + for i := 0; i < b.N; i++ { + for _, ts := range TestSuitesOK { + _, err := state.Lookup(ts.Key) + if err != nil { + b.Error(err) + } + } + } +} + func TestLookupHTTPURL(t *testing.T) { h := http.FileServer(http.Dir(".")) ts := httptest.NewServer(h)