Adding splat[] short hand to explode,collect,flatten,groupby,path,pivot,select and more

This commit is contained in:
Mike Farah 2024-06-16 10:48:01 +10:00
parent f1964dece0
commit d58870b056
14 changed files with 146 additions and 13 deletions

View File

@ -328,7 +328,7 @@ func flattenWithDepth() yqAction {
prefs := flattenPreferences{depth: depth} prefs := flattenPreferences{depth: depth}
op := &Operation{OperationType: flattenOpType, Value: flattenOpType.Type, StringValue: value, Preferences: prefs} op := &Operation{OperationType: flattenOpType, Value: flattenOpType.Type, StringValue: value, Preferences: prefs}
return &token{TokenType: operationToken, Operation: op}, nil return &token{TokenType: operationToken, Operation: op, CheckForPostTraverse: flattenOpType.CheckForPostTraverse}, nil
} }
} }

View File

@ -513,6 +513,7 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: "flatten(3)", StringValue: "flatten(3)",
Preferences: flattenPreferences{depth: 3}, Preferences: flattenPreferences{depth: 3},
}, },
CheckForPostTraverse: flattenOpType.CheckForPostTraverse,
}, },
}, },
}, },
@ -527,6 +528,7 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: "flatten", StringValue: "flatten",
Preferences: flattenPreferences{depth: -1}, Preferences: flattenPreferences{depth: -1},
}, },
CheckForPostTraverse: flattenOpType.CheckForPostTraverse,
}, },
}, },
}, },

View File

@ -117,9 +117,9 @@ var toEntriesOpType = &operationType{Type: "TO_ENTRIES", NumArgs: 0, Precedence:
var fromEntriesOpType = &operationType{Type: "FROM_ENTRIES", NumArgs: 0, Precedence: 50, Handler: fromEntriesOperator} var fromEntriesOpType = &operationType{Type: "FROM_ENTRIES", NumArgs: 0, Precedence: 50, Handler: fromEntriesOperator}
var withEntriesOpType = &operationType{Type: "WITH_ENTRIES", NumArgs: 1, Precedence: 50, Handler: withEntriesOperator} var withEntriesOpType = &operationType{Type: "WITH_ENTRIES", NumArgs: 1, Precedence: 50, Handler: withEntriesOperator}
var withOpType = &operationType{Type: "WITH", NumArgs: 1, Precedence: 50, Handler: withOperator} var withOpType = &operationType{Type: "WITH", NumArgs: 1, Precedence: 52, Handler: withOperator, CheckForPostTraverse: true}
var splitDocumentOpType = &operationType{Type: "SPLIT_DOC", NumArgs: 0, Precedence: 50, Handler: splitDocumentOperator} var splitDocumentOpType = &operationType{Type: "SPLIT_DOC", NumArgs: 0, Precedence: 52, Handler: splitDocumentOperator, CheckForPostTraverse: true}
var getVariableOpType = &operationType{Type: "GET_VARIABLE", NumArgs: 0, Precedence: 55, Handler: getVariableOperator} var getVariableOpType = &operationType{Type: "GET_VARIABLE", NumArgs: 0, Precedence: 55, Handler: getVariableOperator}
var getStyleOpType = &operationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Handler: getStyleOperator} var getStyleOpType = &operationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Handler: getStyleOperator}
var getTagOpType = &operationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: getTagOperator} var getTagOpType = &operationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: getTagOperator}
@ -138,10 +138,10 @@ var getFileIndexOpType = &operationType{Type: "GET_FILE_INDEX", NumArgs: 0, Prec
var getPathOpType = &operationType{Type: "GET_PATH", NumArgs: 0, Precedence: 52, Handler: getPathOperator, CheckForPostTraverse: true} var getPathOpType = &operationType{Type: "GET_PATH", NumArgs: 0, Precedence: 52, Handler: getPathOperator, CheckForPostTraverse: true}
var setPathOpType = &operationType{Type: "SET_PATH", NumArgs: 1, Precedence: 50, Handler: setPathOperator} var setPathOpType = &operationType{Type: "SET_PATH", NumArgs: 1, Precedence: 50, Handler: setPathOperator}
var delPathsOpType = &operationType{Type: "DEL_PATHS", NumArgs: 1, Precedence: 50, Handler: delPathsOperator} var delPathsOpType = &operationType{Type: "DEL_PATHS", NumArgs: 1, Precedence: 52, Handler: delPathsOperator, CheckForPostTraverse: true}
var explodeOpType = &operationType{Type: "EXPLODE", NumArgs: 1, Precedence: 50, Handler: explodeOperator} var explodeOpType = &operationType{Type: "EXPLODE", NumArgs: 1, Precedence: 52, Handler: explodeOperator, CheckForPostTraverse: true}
var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator} var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator, CheckForPostTraverse: true}
var reverseOpType = &operationType{Type: "REVERSE", NumArgs: 0, Precedence: 52, Handler: reverseOperator, CheckForPostTraverse: true} var reverseOpType = &operationType{Type: "REVERSE", NumArgs: 0, Precedence: 52, Handler: reverseOperator, CheckForPostTraverse: true}
var sortOpType = &operationType{Type: "SORT", NumArgs: 0, Precedence: 52, Handler: sortOperator, CheckForPostTraverse: true} var sortOpType = &operationType{Type: "SORT", NumArgs: 0, Precedence: 52, Handler: sortOperator, CheckForPostTraverse: true}
var shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 52, Handler: shuffleOperator, CheckForPostTraverse: true} var shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 52, Handler: shuffleOperator, CheckForPostTraverse: true}
@ -153,7 +153,7 @@ var subStringOpType = &operationType{Type: "SUBSTR", NumArgs: 1, Precedence: 50,
var matchOpType = &operationType{Type: "MATCH", NumArgs: 1, Precedence: 50, Handler: matchOperator} var matchOpType = &operationType{Type: "MATCH", NumArgs: 1, Precedence: 50, Handler: matchOperator}
var captureOpType = &operationType{Type: "CAPTURE", NumArgs: 1, Precedence: 50, Handler: captureOperator} var captureOpType = &operationType{Type: "CAPTURE", NumArgs: 1, Precedence: 50, Handler: captureOperator}
var testOpType = &operationType{Type: "TEST", NumArgs: 1, Precedence: 50, Handler: testOperator} var testOpType = &operationType{Type: "TEST", NumArgs: 1, Precedence: 50, Handler: testOperator}
var splitStringOpType = &operationType{Type: "SPLIT", NumArgs: 1, Precedence: 50, Handler: splitStringOperator} var splitStringOpType = &operationType{Type: "SPLIT", NumArgs: 1, Precedence: 52, Handler: splitStringOperator, CheckForPostTraverse: true}
var changeCaseOpType = &operationType{Type: "CHANGE_CASE", NumArgs: 0, Precedence: 50, Handler: changeCaseOperator} var changeCaseOpType = &operationType{Type: "CHANGE_CASE", NumArgs: 0, Precedence: 50, Handler: changeCaseOperator}
var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator} var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator}
var toStringOpType = &operationType{Type: "TO_STRING", NumArgs: 0, Precedence: 50, Handler: toStringOperator} var toStringOpType = &operationType{Type: "TO_STRING", NumArgs: 0, Precedence: 50, Handler: toStringOperator}
@ -185,15 +185,15 @@ var envsubstOpType = &operationType{Type: "ENVSUBST", NumArgs: 0, Precedence: 50
var recursiveDescentOpType = &operationType{Type: "RECURSIVE_DESCENT", NumArgs: 0, Precedence: 50, Handler: recursiveDescentOperator} var recursiveDescentOpType = &operationType{Type: "RECURSIVE_DESCENT", NumArgs: 0, Precedence: 50, Handler: recursiveDescentOperator}
var selectOpType = &operationType{Type: "SELECT", NumArgs: 1, Precedence: 50, Handler: selectOperator} var selectOpType = &operationType{Type: "SELECT", NumArgs: 1, Precedence: 52, Handler: selectOperator, CheckForPostTraverse: true}
var hasOpType = &operationType{Type: "HAS", NumArgs: 1, Precedence: 50, Handler: hasOperator} var hasOpType = &operationType{Type: "HAS", NumArgs: 1, Precedence: 50, Handler: hasOperator}
var uniqueOpType = &operationType{Type: "UNIQUE", NumArgs: 0, Precedence: 50, Handler: unique} var uniqueOpType = &operationType{Type: "UNIQUE", NumArgs: 0, Precedence: 52, Handler: unique, CheckForPostTraverse: true}
var uniqueByOpType = &operationType{Type: "UNIQUE_BY", NumArgs: 1, Precedence: 50, Handler: uniqueBy} var uniqueByOpType = &operationType{Type: "UNIQUE_BY", NumArgs: 1, Precedence: 52, Handler: uniqueBy, CheckForPostTraverse: true}
var groupByOpType = &operationType{Type: "GROUP_BY", NumArgs: 1, Precedence: 50, Handler: groupBy} var groupByOpType = &operationType{Type: "GROUP_BY", NumArgs: 1, Precedence: 52, Handler: groupBy, CheckForPostTraverse: true}
var flattenOpType = &operationType{Type: "FLATTEN_BY", NumArgs: 0, Precedence: 50, Handler: flattenOp} var flattenOpType = &operationType{Type: "FLATTEN_BY", NumArgs: 0, Precedence: 52, Handler: flattenOp, CheckForPostTraverse: true}
var deleteChildOpType = &operationType{Type: "DELETE", NumArgs: 1, Precedence: 40, Handler: deleteChildOperator} var deleteChildOpType = &operationType{Type: "DELETE", NumArgs: 1, Precedence: 40, Handler: deleteChildOperator}
var pivotOpType = &operationType{Type: "PIVOT", NumArgs: 0, Precedence: 50, Handler: pivotOperator} var pivotOpType = &operationType{Type: "PIVOT", NumArgs: 0, Precedence: 52, Handler: pivotOperator, CheckForPostTraverse: true}
// debugging purposes only // debugging purposes only
func (p *Operation) toString() string { func (p *Operation) toString() string {

View File

@ -188,6 +188,16 @@ var anchorOperatorScenarios = []expressionScenario{
"D0, P[b], (!!str)::cat\n", "D0, P[b], (!!str)::cat\n",
}, },
}, },
{
description: "Explode splat",
skipDoc: true,
document: `{a: &a cat, b: *a}`,
expression: `explode(.)[]`,
expected: []string{
"D0, P[a], (!!str)::cat\n",
"D0, P[b], (!!str)::cat\n",
},
},
{ {
description: "Explode alias and anchor - check original parent", description: "Explode alias and anchor - check original parent",
skipDoc: true, skipDoc: true,

View File

@ -28,6 +28,16 @@ var collectObjectOperatorScenarios = []expressionScenario{
"D0, P[], (!!map)::dog: great\n", "D0, P[], (!!map)::dog: great\n",
}, },
}, },
{
description: "collect splat",
skipDoc: true,
document: `[{name: cat}, {name: dog}]`,
expression: `.[] | {.name: "great"}[]`,
expected: []string{
"D0, P[cat], (!!str)::great\n",
"D0, P[dog], (!!str)::great\n",
},
},
{ {
skipDoc: true, skipDoc: true,
expression: `({} + {}) | (.b = 3)`, expression: `({} + {}) | (.b = 3)`,

View File

@ -14,6 +14,17 @@ var flattenOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::[1, 2, 3]\n", "D0, P[], (!!seq)::[1, 2, 3]\n",
}, },
}, },
{
description: "Flatten splat",
skipDoc: true,
document: `[1, [2], [[3]]]`,
expression: `flatten[]`,
expected: []string{
"D0, P[0], (!!int)::1\n",
"D0, P[0], (!!int)::2\n",
"D0, P[0], (!!int)::3\n",
},
},
{ {
description: "Flatten with depth of one", description: "Flatten with depth of one",
document: `[1, [2], [[3]]]`, document: `[1, [2], [[3]]]`,
@ -22,6 +33,17 @@ var flattenOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::[1, 2, [3]]\n", "D0, P[], (!!seq)::[1, 2, [3]]\n",
}, },
}, },
{
description: "Flatten with depth and splat",
skipDoc: true,
document: `[1, [2], [[3]]]`,
expression: `flatten(1)[]`,
expected: []string{
"D0, P[0], (!!int)::1\n",
"D0, P[0], (!!int)::2\n",
"D0, P[0], (!!seq)::[3]\n",
},
},
{ {
description: "Flatten empty array", description: "Flatten empty array",
document: `[[]]`, document: `[[]]`,

View File

@ -13,6 +13,16 @@ var groupByOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::- - {foo: 1, bar: 10}\n - {foo: 1, bar: 1}\n- - {foo: 3, bar: 100}\n", "D0, P[], (!!seq)::- - {foo: 1, bar: 10}\n - {foo: 1, bar: 1}\n- - {foo: 3, bar: 100}\n",
}, },
}, },
{
description: "Group splat",
skipDoc: true,
document: `[{foo: 1, bar: 10}, {foo: 3, bar: 100}, {foo: 1, bar: 1}]`,
expression: `group_by(.foo)[]`,
expected: []string{
"D0, P[0], (!!seq)::- {foo: 1, bar: 10}\n- {foo: 1, bar: 1}\n",
"D0, P[1], (!!seq)::- {foo: 3, bar: 100}\n",
},
},
{ {
description: "Group by field, with nulls", description: "Group by field, with nulls",
document: `[{cat: dog}, {foo: 1, bar: 10}, {foo: 3, bar: 100}, {no: foo for you}, {foo: 1, bar: 1}]`, document: `[{cat: dog}, {foo: 1, bar: 10}, {foo: 3, bar: 100}, {no: foo for you}, {foo: 1, bar: 1}]`,

View File

@ -139,6 +139,15 @@ var pathOperatorScenarios = []expressionScenario{
"D0, P[], (!!map)::a: [frog]\n", "D0, P[], (!!map)::a: [frog]\n",
}, },
}, },
{
description: "Delete splat",
skipDoc: true,
document: `a: [cat, frog]`,
expression: `delpaths([["a", 0]])[]`,
expected: []string{
"D0, P[a], (!!seq)::[frog]\n",
},
},
{ {
description: "Delete - wrong parameter", description: "Delete - wrong parameter",
subdescription: "delpaths does not work with a single path array", subdescription: "delpaths does not work with a single path array",

View File

@ -11,6 +11,16 @@ var pivotOperatorScenarios = []expressionScenario{
"D0, P[], ()::- - foo\n - sis\n- - bar\n - boom\n- - baz\n - bah\n", "D0, P[], ()::- - foo\n - sis\n- - bar\n - boom\n- - baz\n - bah\n",
}, },
}, },
{
description: "Pivot splat",
skipDoc: true,
document: "[[foo, bar], [sis, boom]]\n",
expression: `pivot[]`,
expected: []string{
"D0, P[0], ()::- foo\n- sis\n",
"D0, P[1], ()::- bar\n- boom\n",
},
},
{ {
description: "Pivot sequence of heterogeneous sequences", description: "Pivot sequence of heterogeneous sequences",
subdescription: `Missing values are "padded" to null.`, subdescription: `Missing values are "padded" to null.`,

View File

@ -75,6 +75,17 @@ var selectOperatorScenarios = []expressionScenario{
"D0, P[], (!!map)::b: world\n", "D0, P[], (!!map)::b: world\n",
}, },
}, },
{
description: "select splat",
skipDoc: true,
document: "a: hello",
document2: "b: world",
expression: `select(.a == "hello" or .b == "world")[]`,
expected: []string{
"D0, P[a], (!!str)::hello\n",
"D0, P[b], (!!str)::world\n",
},
},
{ {
description: "select does not update the map", description: "select does not update the map",
skipDoc: true, skipDoc: true,

View File

@ -22,6 +22,16 @@ var splitDocOperatorScenarios = []expressionScenario{
"D1, P[1], (!!map)::{b: dog}\n", "D1, P[1], (!!map)::{b: dog}\n",
}, },
}, },
{
description: "Split splat",
skipDoc: true,
document: `[{a: cat}, {b: dog}]`,
expression: `.[] | split_doc[]`,
expected: []string{
"D0, P[0 a], (!!str)::cat\n",
"D1, P[1 b], (!!str)::dog\n",
},
},
} }
func TestSplitDocOperatorScenarios(t *testing.T) { func TestSplitDocOperatorScenarios(t *testing.T) {

View File

@ -320,6 +320,16 @@ var stringsOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::- word\n", "D0, P[], (!!seq)::- word\n",
}, },
}, },
{
description: "Split splat",
skipDoc: true,
document: `"word; cat"`,
expression: `split("; ")[]`,
expected: []string{
"D0, P[0], (!!str)::word\n",
"D0, P[1], (!!str)::cat\n",
},
},
{ {
skipDoc: true, skipDoc: true,
document: `!horse "word"`, document: `!horse "word"`,

View File

@ -14,6 +14,16 @@ var uniqueOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::[2, 1, 3]\n", "D0, P[], (!!seq)::[2, 1, 3]\n",
}, },
}, },
{
description: "Unique splat",
skipDoc: true,
document: `[2,1,2]`,
expression: `unique[]`,
expected: []string{
"D0, P[0], (!!int)::2\n",
"D0, P[1], (!!int)::1\n",
},
},
{ {
description: "Unique nulls", description: "Unique nulls",
subdescription: "Unique works on the node value, so it considers different representations of nulls to be different", subdescription: "Unique works on the node value, so it considers different representations of nulls to be different",
@ -64,6 +74,16 @@ var uniqueOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::[{name: harry, pet: cat}, {pet: fish}]\n", "D0, P[], (!!seq)::[{name: harry, pet: cat}, {pet: fish}]\n",
}, },
}, },
{
description: "unique by splat",
skipDoc: true,
document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`,
expression: `unique_by(.name)[]`,
expected: []string{
"D0, P[0], (!!map)::{name: harry, pet: cat}\n",
"D0, P[1], (!!map)::{pet: fish}\n",
},
},
{ {
skipDoc: true, skipDoc: true,
document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`, document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`,

View File

@ -11,6 +11,15 @@ var withOperatorScenarios = []expressionScenario{
"D0, P[], (!!map)::a: {deeply: {nested: 'newValue'}}\n", "D0, P[], (!!map)::a: {deeply: {nested: 'newValue'}}\n",
}, },
}, },
{
description: "with splat",
skipDoc: true,
document: `a: {deeply: {nested: value}}`,
expression: `with(.a.deeply.nested; . = "newValue" | . style="single")[]`,
expected: []string{
"D0, P[a], (!!map)::{deeply: {nested: 'newValue'}}\n",
},
},
{ {
description: "Update multiple deeply nested properties", description: "Update multiple deeply nested properties",
document: `a: {deeply: {nested: value, other: thing}}`, document: `a: {deeply: {nested: value, other: thing}}`,