promql/parser: consolidate label quoting logic

refactors binary expression formatting to reuse writeLabels() instead
of maintaining separate joinLabels() function. adds comprehensive
UTF-8 label tests for all expression types

Signed-off-by: ADITYA TIWARI <adityatiwari342005@gmail.com>
This commit is contained in:
ADITYA TIWARI 2025-12-15 12:38:12 +00:00
parent 5b299ef99e
commit 2e4f5e8cfc
2 changed files with 35 additions and 15 deletions

View file

@ -145,21 +145,9 @@ func (node *BinaryExpr) ShortString() string {
return node.Op.String() + node.returnBool() + node.getMatchingStr()
}
// joinLabels joins label names, quoting them if they are not valid legacy label names.
func joinLabels(labels []string) string {
quoted := make([]string, 0, len(labels))
for _, label := range labels {
if model.LegacyValidation.IsValidLabelName(label) {
quoted = append(quoted, label)
} else {
quoted = append(quoted, strconv.Quote(label))
}
}
return strings.Join(quoted, ", ")
}
func (node *BinaryExpr) getMatchingStr() string {
matching := ""
var b bytes.Buffer
vm := node.VectorMatching
if vm != nil {
if len(vm.MatchingLabels) > 0 || vm.On || vm.Card == CardManyToOne || vm.Card == CardOneToMany {
@ -167,7 +155,14 @@ func (node *BinaryExpr) getMatchingStr() string {
if vm.On {
vmTag = "on"
}
matching = fmt.Sprintf(" %s (%s)", vmTag, joinLabels(vm.MatchingLabels))
// Use writeLabels() instead of joinLabels()
b.Reset()
b.WriteString(" ")
b.WriteString(vmTag)
b.WriteString(" (")
writeLabels(&b, vm.MatchingLabels)
b.WriteString(")")
matching = b.String()
}
if vm.Card == CardManyToOne || vm.Card == CardOneToMany {
@ -175,7 +170,14 @@ func (node *BinaryExpr) getMatchingStr() string {
if vm.Card == CardManyToOne {
vmCard = "left"
}
matching += fmt.Sprintf(" group_%s (%s)", vmCard, joinLabels(vm.Include))
// Use writeLabels() instead of joinLabels()
b.Reset()
b.WriteString(" group_")
b.WriteString(vmCard)
b.WriteString(" (")
writeLabels(&b, vm.Include)
b.WriteString(")")
matching += b.String()
}
}
return matching

View file

@ -273,6 +273,14 @@ func TestExprString(t *testing.T) {
in: `sum by("üüü") (foo)`,
out: `sum by ("üüü") (foo)`,
},
{
in: `sum without("äää") (foo)`,
out: `sum without ("äää") (foo)`,
},
{
in: `count by("ööö", job) (foo)`,
out: `count by ("ööö", job) (foo)`,
},
}
EnableExtendedRangeSelectors = true
@ -410,11 +418,21 @@ func TestBinaryExprUTF8Labels(t *testing.T) {
input: `foo / on("äää") bar`,
expected: `foo / on ("äää") bar`,
},
{
name: "UTF-8 labels in ignoring clause",
input: `foo / ignoring("üüü") bar`,
expected: `foo / ignoring ("üüü") bar`,
},
{
name: "UTF-8 labels in group_left clause",
input: `foo / on("äää") group_left("ööö") bar`,
expected: `foo / on ("äää") group_left ("ööö") bar`,
},
{
name: "UTF-8 labels in group_right clause",
input: `foo / on("äää") group_right("ööö") bar`,
expected: `foo / on ("äää") group_right ("ööö") bar`,
},
{
name: "Mixed legacy and UTF-8 labels",
input: `foo / on(legacy, "üüü") bar`,