From 1941bb66a5aa88cf245548b57b25fb84fe962898 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Mon, 18 Jan 2021 10:15:31 +1100 Subject: [PATCH] wip --- pkg/yqlib/candidate_node.go | 3 ++ pkg/yqlib/operator_multiply.go | 55 +++++++++++++++++------------ pkg/yqlib/operator_multiply_test.go | 4 ++- pkg/yqlib/utils.go | 9 ++--- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index 0fd2fe59..f3801f63 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -15,6 +15,9 @@ type CandidateNode struct { Document uint // the document index of this node Filename string FileIndex int + // when performing op against all nodes given, this will treat all the nodes as one + // (e.g. top level cross document merge). This property does not propegate to child nodes. + EvaluateTogether bool } func (n *CandidateNode) GetKey() string { diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go index 4d98246c..98919632 100644 --- a/pkg/yqlib/operator_multiply.go +++ b/pkg/yqlib/operator_multiply.go @@ -10,38 +10,49 @@ import ( type crossFunctionCalculation func(d *dataTreeNavigator, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) -func crossFunction(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (*list.List, error) { +func doCrossFunc(d *dataTreeNavigator, contextList *list.List, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (*list.List, error) { + var results = list.New() + lhs, err := d.GetMatchingNodes(contextList, expressionNode.Lhs) + if err != nil { + return nil, err + } + log.Debugf("crossFunction LHS len: %v", lhs.Len()) + rhs, err := d.GetMatchingNodes(contextList, expressionNode.Rhs) + + if err != nil { + return nil, err + } + + for el := lhs.Front(); el != nil; el = el.Next() { + lhsCandidate := el.Value.(*CandidateNode) + + for rightEl := rhs.Front(); rightEl != nil; rightEl = rightEl.Next() { + log.Debugf("Applying calc") + rhsCandidate := rightEl.Value.(*CandidateNode) + resultCandidate, err := calculation(d, lhsCandidate, rhsCandidate) + if err != nil { + return nil, err + } + results.PushBack(resultCandidate) + } + + } + return results, nil +} + +func crossFunction(d *dataTreeNavigator, matchingNodes *list.List, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (*list.List, error) { var results = list.New() for matchEl := matchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() { contextList := nodeToMap(matchEl.Value.(*CandidateNode)) - lhs, err := d.GetMatchingNodes(contextList, expressionNode.Lhs) - if err != nil { - return nil, err - } - log.Debugf("crossFunction LHS len: %v", lhs.Len()) - - rhs, err := d.GetMatchingNodes(contextList, expressionNode.Rhs) + innerResults, err := doCrossFunc(d, contextList, expressionNode, calculation) if err != nil { return nil, err } - for el := lhs.Front(); el != nil; el = el.Next() { - lhsCandidate := el.Value.(*CandidateNode) - - for rightEl := rhs.Front(); rightEl != nil; rightEl = rightEl.Next() { - log.Debugf("Applying calc") - rhsCandidate := rightEl.Value.(*CandidateNode) - resultCandidate, err := calculation(d, lhsCandidate, rhsCandidate) - if err != nil { - return nil, err - } - results.PushBack(resultCandidate) - } - - } + results.PushBackList(innerResults) } diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go index 8635686d..09b466d8 100644 --- a/pkg/yqlib/operator_multiply_test.go +++ b/pkg/yqlib/operator_multiply_test.go @@ -12,6 +12,8 @@ import ( // d0a d1a d0b d1b // run it for (d0a d1a) x (d0b d1b) - noting that we dont do (d0a x d1a) nor (d0b d1b) // I think this will work for eval-all correctly then.. + +//alternative, like jq, eval-all puts all docs in an single array. var multiplyOperatorScenarios = []expressionScenario{ { skipDoc: true, @@ -25,7 +27,7 @@ var multiplyOperatorScenarios = []expressionScenario{ skipDoc: true, document: `a: {also: [1]}`, document2: `b: {also: me}`, - expression: `. * {"a" : .b}`, + expression: `.a * .b`, expected: []string{ "D0, P[], (!!map)::{a: {also: me}, b: {also: me}}\n", }, diff --git a/pkg/yqlib/utils.go b/pkg/yqlib/utils.go index 3e8084bc..dd93d248 100644 --- a/pkg/yqlib/utils.go +++ b/pkg/yqlib/utils.go @@ -36,10 +36,11 @@ func readDocuments(reader io.Reader, filename string, fileIndex int) (*list.List return nil, errorReading } candidateNode := &CandidateNode{ - Document: currentIndex, - Filename: filename, - Node: &dataBucket, - FileIndex: fileIndex, + Document: currentIndex, + Filename: filename, + Node: &dataBucket, + FileIndex: fileIndex, + EvaluateTogether: true, } inputList.PushBack(candidateNode)