Skip to content

Commit

Permalink
Adding splat[] short hand to explode,collect,flatten,groupby,path,piv…
Browse files Browse the repository at this point in the history
…ot,select and more
  • Loading branch information
mikefarah committed Jun 16, 2024
1 parent f1964de commit d58870b
Show file tree
Hide file tree
Showing 14 changed files with 146 additions and 13 deletions.
2 changes: 1 addition & 1 deletion pkg/yqlib/lexer_participle.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ func flattenWithDepth() yqAction {

prefs := flattenPreferences{depth: depth}
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
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/yqlib/lexer_participle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: "flatten(3)",
Preferences: flattenPreferences{depth: 3},
},
CheckForPostTraverse: flattenOpType.CheckForPostTraverse,
},
},
},
Expand All @@ -527,6 +528,7 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: "flatten",
Preferences: flattenPreferences{depth: -1},
},
CheckForPostTraverse: flattenOpType.CheckForPostTraverse,
},
},
},
Expand Down
24 changes: 12 additions & 12 deletions pkg/yqlib/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 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 getStyleOpType = &operationType{Type: "GET_STYLE", NumArgs: 0, Precedence: 50, Handler: getStyleOperator}
var getTagOpType = &operationType{Type: "GET_TAG", NumArgs: 0, Precedence: 50, Handler: getTagOperator}
Expand All @@ -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 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 sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator}
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, 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 shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 52, Handler: shuffleOperator, CheckForPostTraverse: true}
Expand All @@ -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 captureOpType = &operationType{Type: "CAPTURE", NumArgs: 1, Precedence: 50, Handler: captureOperator}
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 trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handler: trimSpaceOperator}
var toStringOpType = &operationType{Type: "TO_STRING", NumArgs: 0, Precedence: 50, Handler: toStringOperator}
Expand Down Expand Up @@ -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 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 uniqueOpType = &operationType{Type: "UNIQUE", NumArgs: 0, Precedence: 50, Handler: unique}
var uniqueByOpType = &operationType{Type: "UNIQUE_BY", NumArgs: 1, Precedence: 50, Handler: uniqueBy}
var groupByOpType = &operationType{Type: "GROUP_BY", NumArgs: 1, Precedence: 50, Handler: groupBy}
var flattenOpType = &operationType{Type: "FLATTEN_BY", NumArgs: 0, Precedence: 50, Handler: flattenOp}
var uniqueOpType = &operationType{Type: "UNIQUE", NumArgs: 0, Precedence: 52, Handler: unique, CheckForPostTraverse: true}
var uniqueByOpType = &operationType{Type: "UNIQUE_BY", NumArgs: 1, Precedence: 52, Handler: uniqueBy, CheckForPostTraverse: true}
var groupByOpType = &operationType{Type: "GROUP_BY", NumArgs: 1, Precedence: 52, Handler: groupBy, CheckForPostTraverse: true}
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 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
func (p *Operation) toString() string {
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_anchors_aliases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,16 @@ var anchorOperatorScenarios = []expressionScenario{
"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",
skipDoc: true,
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_collect_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ var collectObjectOperatorScenarios = []expressionScenario{
"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,
expression: `({} + {}) | (.b = 3)`,
Expand Down
22 changes: 22 additions & 0 deletions pkg/yqlib/operator_flatten_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ var flattenOperatorScenarios = []expressionScenario{
"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",
document: `[1, [2], [[3]]]`,
Expand All @@ -22,6 +33,17 @@ var flattenOperatorScenarios = []expressionScenario{
"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",
document: `[[]]`,
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_group_by_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
},
},
{
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",
document: `[{cat: dog}, {foo: 1, bar: 10}, {foo: 3, bar: 100}, {no: foo for you}, {foo: 1, bar: 1}]`,
Expand Down
9 changes: 9 additions & 0 deletions pkg/yqlib/operator_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ var pathOperatorScenarios = []expressionScenario{
"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",
subdescription: "delpaths does not work with a single path array",
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_pivot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ var pivotOperatorScenarios = []expressionScenario{
"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",
subdescription: `Missing values are "padded" to null.`,
Expand Down
11 changes: 11 additions & 0 deletions pkg/yqlib/operator_select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ var selectOperatorScenarios = []expressionScenario{
"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",
skipDoc: true,
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_split_document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ var splitDocOperatorScenarios = []expressionScenario{
"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) {
Expand Down
10 changes: 10 additions & 0 deletions pkg/yqlib/operator_strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,16 @@ var stringsOperatorScenarios = []expressionScenario{
"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,
document: `!horse "word"`,
Expand Down
20 changes: 20 additions & 0 deletions pkg/yqlib/operator_unique_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ var uniqueOperatorScenarios = []expressionScenario{
"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",
subdescription: "Unique works on the node value, so it considers different representations of nulls to be different",
Expand Down Expand Up @@ -64,6 +74,16 @@ var uniqueOperatorScenarios = []expressionScenario{
"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,
document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`,
Expand Down
9 changes: 9 additions & 0 deletions pkg/yqlib/operator_with_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ var withOperatorScenarios = []expressionScenario{
"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",
document: `a: {deeply: {nested: value, other: thing}}`,
Expand Down

0 comments on commit d58870b

Please sign in to comment.