Conditional grep in record index expression seems buggy
tl;dr
The output from the following seems incorrect compared to when we compute each part separately and combine.
this[grep(one*, x) ? "one" : "two"]:=x
Details
Repro is with Zed commit d103420. I bumped into this while trying to write the Zed equivalent of the CASE logic in mgbench bench3/q6.
The following uses a conditional in a record index expression and works as expected:
$ zq -version
Version: v1.18.0-4-gd1034203
$ echo '{x:1} {x:2}' | zq -Z 'this[x==1 ? "one" : "two"]:=x' -
{
x: 1,
one: 1
}
{
x: 2,
two: 2
}
However, if I try what I think is the equivalent with strings and grep(), I no longer see the field name one in the output.
$ echo '{x:"one is a bun"} {x:"two is a shoe"}' | zq -Z 'this[grep(one*, x) ? "one" : "two"]:=x' -
{
x: "one is a bun",
two: "one is a bun"
}
{
x: "two is a shoe",
two: "two is a shoe"
}
It feels like it should work the same since grep() is supposed to return a boolean. And it does what I expect if I yield the result of the conditional on its own or launder the field name through an intermediate value.
$ echo '{x:"one is a bun"} {x:"two is a shoe"}' | zq -Z 'yield grep(one*, x) ? "one" : "two"' -
"one"
"two"
$ echo '{x:"one is a bun"} {x:"two is a shoe"}' | zq -Z '_fieldname := grep(one*, x) ? "one" : "two" | this[_fieldname] := x | drop _fieldname' -
{
x: "one is a bun",
one: "one is a bun"
}
{
x: "two is a shoe",
two: "two is a shoe"
}
$ echo '{x:"one is a bun"} {x:"two is a shoe"}' | zq -Z '_fieldname := grep(one*, x) ? "one" : "two" | this[_fieldname] := x | drop _fieldname' -
{
x: "one is a bun",
one: "one is a bun"
}
{
x: "two is a shoe",
two: "two is a shoe"
}
A preliminary reaction from @mattnibs:
Looks like there's a weird compiler bug here:
$ zed dev compile -s -C 'this[grep(one*, x) ? "one" : "two"]:=x' reader | put two:=x | output mainI'm guessing the lval logic is stripping out regexpSearch expression that grep gets converted into.
Verified in super commit 0165f09.
I've confirmed via binary search that this was fixed by the changes in #6267. Repeating the repro query while updating to modern syntax, we now see the field name one as expected in the first output record.
$ super -version
Version: 0165f09
$ echo '{x:"one is a bun"} {x:"two is a shoe"}' | super -S -c 'this[grep(r"one.*", x) ? "one" : "two"]:=x' -
{
x: "one is a bun",
one: "one is a bun"
}
{
x: "two is a shoe",
two: "two is a shoe"
}
Thanks @mccanne!