mirror of
				https://github.com/taigrr/yq
				synced 2025-01-18 04:53:17 -08:00 
			
		
		
		
	Fixed boolean ops
This commit is contained in:
		
							parent
							
								
									bc87aca8d7
								
							
						
					
					
						commit
						f03005f86d
					
				| @ -6,7 +6,7 @@ Which will assign the LHS node values to the RHS node values. The RHS expression | |||||||
| ### relative form: `|=` | ### relative form: `|=` | ||||||
| This will do a similar thing to the plain form, however, the RHS expression is run against _the LHS nodes_. This is useful for updating values based on old values, e.g. increment. | This will do a similar thing to the plain form, however, the RHS expression is run against _the LHS nodes_. This is useful for updating values based on old values, e.g. increment. | ||||||
| ## Examples | ## Examples | ||||||
| ### Update parent to be the child value | ### Update node to be the child value | ||||||
| Given a sample.yml file of: | Given a sample.yml file of: | ||||||
| ```yaml | ```yaml | ||||||
| a: | a: | ||||||
| @ -23,7 +23,7 @@ a: | |||||||
|   g: foof |   g: foof | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Update to be the sibling value | ### Update node to be the sibling value | ||||||
| Given a sample.yml file of: | Given a sample.yml file of: | ||||||
| ```yaml | ```yaml | ||||||
| a: | a: | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ package yqlib | |||||||
| import ( | import ( | ||||||
| 	"container/list" | 	"container/list" | ||||||
| 
 | 
 | ||||||
| 	"gopkg.in/yaml.v3" | 	yaml "gopkg.in/yaml.v3" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func isTruthy(c *CandidateNode) (bool, error) { | func isTruthy(c *CandidateNode) (bool, error) { | ||||||
| @ -25,9 +25,42 @@ func isTruthy(c *CandidateNode) (bool, error) { | |||||||
| 
 | 
 | ||||||
| type boolOp func(bool, bool) bool | type boolOp func(bool, bool) bool | ||||||
| 
 | 
 | ||||||
|  | func performBoolOp(results *list.List, lhs *list.List, rhs *list.List, op boolOp) error { | ||||||
|  | 	for lhsChild := lhs.Front(); lhsChild != nil; lhsChild = lhsChild.Next() { | ||||||
|  | 		lhsCandidate := lhsChild.Value.(*CandidateNode) | ||||||
|  | 		lhsTrue, errDecoding := isTruthy(lhsCandidate) | ||||||
|  | 		if errDecoding != nil { | ||||||
|  | 			return errDecoding | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for rhsChild := rhs.Front(); rhsChild != nil; rhsChild = rhsChild.Next() { | ||||||
|  | 			rhsCandidate := rhsChild.Value.(*CandidateNode) | ||||||
|  | 			rhsTrue, errDecoding := isTruthy(rhsCandidate) | ||||||
|  | 			if errDecoding != nil { | ||||||
|  | 				return errDecoding | ||||||
|  | 			} | ||||||
|  | 			boolResult := createBooleanCandidate(lhsCandidate, op(lhsTrue, rhsTrue)) | ||||||
|  | 			results.PushBack(boolResult) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode, op boolOp) (*list.List, error) { | func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode, op boolOp) (*list.List, error) { | ||||||
| 	var results = list.New() | 	var results = list.New() | ||||||
| 
 | 
 | ||||||
|  | 	if matchingNodes.Len() == 0 { | ||||||
|  | 		lhs, err := d.GetMatchingNodes(list.New(), pathNode.Lhs) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		rhs, err := d.GetMatchingNodes(list.New(), pathNode.Rhs) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		return results, performBoolOp(results, lhs, rhs, op) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	for el := matchingNodes.Front(); el != nil; el = el.Next() { | 	for el := matchingNodes.Front(); el != nil; el = el.Next() { | ||||||
| 		candidate := el.Value.(*CandidateNode) | 		candidate := el.Value.(*CandidateNode) | ||||||
| 		lhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Lhs) | 		lhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Lhs) | ||||||
| @ -39,23 +72,9 @@ func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTre | |||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for lhsChild := lhs.Front(); lhsChild != nil; lhsChild = lhsChild.Next() { | 		err = performBoolOp(results, lhs, rhs, op) | ||||||
| 			lhsCandidate := lhsChild.Value.(*CandidateNode) | 		if err != nil { | ||||||
| 			lhsTrue, errDecoding := isTruthy(lhsCandidate) | 			return nil, err | ||||||
| 			if errDecoding != nil { |  | ||||||
| 				return nil, errDecoding |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			for rhsChild := rhs.Front(); rhsChild != nil; rhsChild = rhsChild.Next() { |  | ||||||
| 				rhsCandidate := rhsChild.Value.(*CandidateNode) |  | ||||||
| 				rhsTrue, errDecoding := isTruthy(rhsCandidate) |  | ||||||
| 				if errDecoding != nil { |  | ||||||
| 					return nil, errDecoding |  | ||||||
| 				} |  | ||||||
| 				boolResult := createBooleanCandidate(lhsCandidate, op(lhsTrue, rhsTrue)) |  | ||||||
| 
 |  | ||||||
| 				results.PushBack(boolResult) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -24,8 +24,8 @@ var booleanOperatorScenarios = []expressionScenario{ | |||||||
| 		description: "Matching nodes with select, equals and or", | 		description: "Matching nodes with select, equals and or", | ||||||
| 		expression:  `.[] | select(.a == "cat" or .b == "dog")`, | 		expression:  `.[] | select(.a == "cat" or .b == "dog")`, | ||||||
| 		expected: []string{ | 		expected: []string{ | ||||||
| 			"D0, P[], (!!map)::{a: bird, b: dog}\n", | 			"D0, P[0], (!!map)::{a: bird, b: dog}\n", | ||||||
| 			"D0, P[], (!!map)::{a: cat, b: fly}\n", | 			"D0, P[2], (!!map)::{a: cat, b: fly}\n", | ||||||
| 		}, | 		}, | ||||||
| 	}, | 	}, | ||||||
| 	{ | 	{ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user