From ed4d888bfa27895cce5348bb93e90f7021af4bba Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Mon, 11 Oct 2021 14:46:46 +1100 Subject: [PATCH] Speed up multiply --- pkg/yqlib/doc/Multiply (Merge).md | 2 +- pkg/yqlib/expression_tokeniser.go | 1 + pkg/yqlib/operator_multiply.go | 18 +++++++++++++----- pkg/yqlib/operator_multiply_test.go | 17 ++++++++++++++++- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/pkg/yqlib/doc/Multiply (Merge).md b/pkg/yqlib/doc/Multiply (Merge).md index 32d52e9c..e2d2c856 100644 --- a/pkg/yqlib/doc/Multiply (Merge).md +++ b/pkg/yqlib/doc/Multiply (Merge).md @@ -357,7 +357,7 @@ yq eval '.foobar * .foobarList' sample.yml will output ```yaml c: foobarList_c -<<: +!!merge <<: - *foo - *bar thing: foobar_thing diff --git a/pkg/yqlib/expression_tokeniser.go b/pkg/yqlib/expression_tokeniser.go index 1b23a08d..f19c5447 100644 --- a/pkg/yqlib/expression_tokeniser.go +++ b/pkg/yqlib/expression_tokeniser.go @@ -111,6 +111,7 @@ func multiplyWithPrefs() lex.Action { if strings.Contains(options, "d") { prefs.DeepMergeArrays = true } + prefs.TraversePrefs.DontFollowAlias = true op := &Operation{OperationType: multiplyOpType, Value: multiplyOpType.Type, StringValue: options, Preferences: prefs} return &token{TokenType: operationToken, Operation: op}, nil } diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go index ecf12623..00265387 100644 --- a/pkg/yqlib/operator_multiply.go +++ b/pkg/yqlib/operator_multiply.go @@ -6,6 +6,7 @@ import ( "container/list" + "github.com/jinzhu/copier" yaml "gopkg.in/yaml.v3" ) @@ -50,14 +51,21 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex if lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode || (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) { - - var newBlank = lhs.CreateChild(nil, newBlankNode) - log.Debugf("merge - merge lhs into blank") - var newThing, err = mergeObjects(d, context.WritableClone(), newBlank, lhs, multiplyPreferences{}) + var newBlank = CandidateNode{} + err := copier.CopyWithOption(&newBlank, lhs, copier.Option{IgnoreEmpty: true, DeepCopy: true}) if err != nil { return nil, err } - return mergeObjects(d, context.WritableClone(), newThing, rhs, preferences) + newBlank.Node.HeadComment = newBlankNode.HeadComment + newBlank.Node.FootComment = newBlankNode.FootComment + + // var newBlank = lhs.CreateChild(nil, newBlankNode) + // log.Debugf("merge - merge lhs into blank") + // var newThing, err = mergeObjects(d, context.WritableClone(), newBlank, lhs, multiplyPreferences{}) + // if err != nil { + // return nil, err + // } + return mergeObjects(d, context.WritableClone(), &newBlank, rhs, preferences) } else if lhs.Node.Tag == "!!int" && rhs.Node.Tag == "!!int" { return multiplyIntegers(lhs, rhs) } else if (lhs.Node.Tag == "!!int" || lhs.Node.Tag == "!!float") && (rhs.Node.Tag == "!!int" || rhs.Node.Tag == "!!float") { diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go index c1c93adf..b8a294e2 100644 --- a/pkg/yqlib/operator_multiply_test.go +++ b/pkg/yqlib/operator_multiply_test.go @@ -60,6 +60,13 @@ var nodeWithFooter = ` a: apple # footer` +var document = ` +a: &cat {name: cat} +b: {name: dog} +c: + <<: *cat +` + var multiplyOperatorScenarios = []expressionScenario{ { skipDoc: true, @@ -405,7 +412,15 @@ var multiplyOperatorScenarios = []expressionScenario{ document: mergeDocSample, expression: `.foobar * .foobarList`, expected: []string{ - "D0, P[foobar], (!!map)::c: foobarList_c\n<<: [*foo, *bar]\nthing: foobar_thing\nb: foobarList_b\n", + "D0, P[foobar], (!!map)::c: foobarList_c\n!!merge <<: [*foo, *bar]\nthing: foobar_thing\nb: foobarList_b\n", + }, + }, + { + skipDoc: true, + document: document, + expression: `.b * .c`, + expected: []string{ + "D0, P[b], (!!map)::{name: dog, <<: *cat}\n", }, }, }