mirror of
				https://github.com/TomWright/dasel.git
				synced 2022-05-22 02:32:45 +03:00 
			
		
		
		
	Remove duplicate code and add support for key name matches in dynamic selectors
This commit is contained in:
		| @@ -119,12 +119,21 @@ func findNextAvailableIndex(n *Node, createIfNotExists bool) (reflect.Value, err | ||||
| } | ||||
|  | ||||
| // processFindDynamicItem is used by findValueDynamic. | ||||
| func processFindDynamicItem(n *Node, object reflect.Value) (bool, error) { | ||||
| func processFindDynamicItem(n *Node, object reflect.Value, key string) (bool, error) { | ||||
| 	// Loop through each condition. | ||||
| 	allConditionsMatched := true | ||||
| 	for _, c := range n.Selector.Conditions { | ||||
| 		// If the object doesn't match any checks, return a ValueNotFound. | ||||
| 		found, err := c.Check(object) | ||||
|  | ||||
| 		var found bool | ||||
| 		var err error | ||||
| 		switch cond := c.(type) { | ||||
| 		case *KeyEqualCondition: | ||||
| 			found, err = cond.Check(reflect.ValueOf(key)) | ||||
| 		default: | ||||
| 			found, err = cond.Check(object) | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| @@ -152,7 +161,7 @@ func findValueDynamic(n *Node, createIfNotExists bool) (reflect.Value, error) { | ||||
| 	case reflect.Slice: | ||||
| 		for i := 0; i < value.Len(); i++ { | ||||
| 			object := value.Index(i) | ||||
| 			found, err := processFindDynamicItem(n, object) | ||||
| 			found, err := processFindDynamicItem(n, object, fmt.Sprint(i)) | ||||
| 			if err != nil { | ||||
| 				return nilValue(), err | ||||
| 			} | ||||
| @@ -171,7 +180,7 @@ func findValueDynamic(n *Node, createIfNotExists bool) (reflect.Value, error) { | ||||
| 	case reflect.Map: | ||||
| 		for _, key := range value.MapKeys() { | ||||
| 			object := value.MapIndex(key) | ||||
| 			found, err := processFindDynamicItem(n, object) | ||||
| 			found, err := processFindDynamicItem(n, object, key.String()) | ||||
| 			if err != nil { | ||||
| 				return nilValue(), err | ||||
| 			} | ||||
|   | ||||
| @@ -182,12 +182,21 @@ func findNextAvailableIndexNodes(selector Selector, previousValue reflect.Value, | ||||
| } | ||||
|  | ||||
| // processFindDynamicItems is used by findNodesDynamic. | ||||
| func processFindDynamicItems(selector Selector, object reflect.Value) (bool, error) { | ||||
| func processFindDynamicItems(selector Selector, object reflect.Value, key string) (bool, error) { | ||||
| 	// Loop through each condition. | ||||
| 	allConditionsMatched := true | ||||
| 	for _, c := range selector.Conditions { | ||||
| 		// If the object doesn't match any checks, return a ValueNotFound. | ||||
| 		found, err := c.Check(object) | ||||
|  | ||||
| 		var found bool | ||||
| 		var err error | ||||
| 		switch cond := c.(type) { | ||||
| 		case *KeyEqualCondition: | ||||
| 			found, err = cond.Check(reflect.ValueOf(key)) | ||||
| 		default: | ||||
| 			found, err = cond.Check(object) | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| @@ -215,7 +224,7 @@ func findNodesDynamic(selector Selector, previousValue reflect.Value, createIfNo | ||||
| 		results := make([]*Node, 0) | ||||
| 		for i := 0; i < value.Len(); i++ { | ||||
| 			object := value.Index(i) | ||||
| 			found, err := processFindDynamicItems(selector, object) | ||||
| 			found, err := processFindDynamicItems(selector, object, fmt.Sprint(i)) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| @@ -246,7 +255,7 @@ func findNodesDynamic(selector Selector, previousValue reflect.Value, createIfNo | ||||
| 		results := make([]*Node, 0) | ||||
| 		for _, key := range value.MapKeys() { | ||||
| 			object := value.MapIndex(key) | ||||
| 			found, err := processFindDynamicItems(selector, object) | ||||
| 			found, err := processFindDynamicItems(selector, object, key.String()) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|   | ||||
							
								
								
									
										33
									
								
								node_test.go
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								node_test.go
									
									
									
									
									
								
							| @@ -269,6 +269,29 @@ func TestParseSelector(t *testing.T) { | ||||
| 			}, | ||||
| 		}, | ||||
| 	})) | ||||
| 	t.Run("DynamicKey", testParseSelector(".(-=asd)", dasel.Selector{ | ||||
| 		Raw:       ".(-=asd)", | ||||
| 		Current:   ".(-=asd)", | ||||
| 		Remaining: "", | ||||
| 		Type:      "DYNAMIC", | ||||
| 		Conditions: []dasel.Condition{ | ||||
| 			&dasel.KeyEqualCondition{ | ||||
| 				Value: "asd", | ||||
| 			}, | ||||
| 		}, | ||||
| 	})) | ||||
| 	t.Run("DynamicKeyNotEqual", testParseSelector(".(-!=asd)", dasel.Selector{ | ||||
| 		Raw:       ".(-!=asd)", | ||||
| 		Current:   ".(-!=asd)", | ||||
| 		Remaining: "", | ||||
| 		Type:      "DYNAMIC", | ||||
| 		Conditions: []dasel.Condition{ | ||||
| 			&dasel.KeyEqualCondition{ | ||||
| 				Value: "asd", | ||||
| 				Not:   true, | ||||
| 			}, | ||||
| 		}, | ||||
| 	})) | ||||
| 	t.Run("DynamicEqual", testParseSelector(".(name=asd)", dasel.Selector{ | ||||
| 		Raw:       ".(name=asd)", | ||||
| 		Current:   ".(name=asd)", | ||||
| @@ -418,12 +441,18 @@ func TestNode_QueryMultiple(t *testing.T) { | ||||
| 	t.Run("SingleResult", testNodeQueryMultipleArray(".[0].name", []interface{}{ | ||||
| 		"Tom", | ||||
| 	})) | ||||
| 	t.Run("SingleResultDynamic", testNodeQueryMultipleArray(".(age=25).name", []interface{}{ | ||||
| 	t.Run("SingleResultDynamicEqual", testNodeQueryMultipleArray(".(age=25).name", []interface{}{ | ||||
| 		"Amelia", | ||||
| 	})) | ||||
| 	t.Run("SingleResultDynamic", testNodeQueryMultipleArray(".(age!=27).name", []interface{}{ | ||||
| 	t.Run("SingleResultDynamicNotEqual", testNodeQueryMultipleArray(".(age!=27).name", []interface{}{ | ||||
| 		"Amelia", | ||||
| 	})) | ||||
| 	t.Run("SingleResultDynamicKeyEqual", testNodeQueryMultipleArray(".(-=0).name", []interface{}{ | ||||
| 		"Tom", | ||||
| 	})) | ||||
| 	t.Run("MultipleResultDynamicKeyNotEqual", testNodeQueryMultipleArray(".(-!=0).name", []interface{}{ | ||||
| 		"Jim", "Amelia", | ||||
| 	})) | ||||
| 	t.Run("MultipleResultSearchKeyNotEqual", testNodeQueryMultipleArray(".[*].(?:-!=name)", []interface{}{ | ||||
| 		"27", "27", "25", | ||||
| 	})) | ||||
|   | ||||
| @@ -46,6 +46,66 @@ func ParseSelector(selector string) (Selector, error) { | ||||
| 	return sel, err | ||||
| } | ||||
|  | ||||
| func getCondition(parts DynamicSelectorParts) (Condition, error) { | ||||
| 	switch parts.Key { | ||||
| 	case "-", "keyValue": | ||||
| 		switch parts.Comparison { | ||||
| 		case "=": | ||||
| 			return &KeyEqualCondition{ | ||||
| 				Value: parts.Value, | ||||
| 			}, nil | ||||
| 		case "!=": | ||||
| 			return &KeyEqualCondition{ | ||||
| 				Value: parts.Value, | ||||
| 				Not:   true, | ||||
| 			}, nil | ||||
| 		default: | ||||
| 			return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison} | ||||
| 		} | ||||
| 	default: | ||||
|  | ||||
| 		switch parts.Comparison { | ||||
| 		case "=": | ||||
| 			return &EqualCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 			}, nil | ||||
| 		case "!=": | ||||
| 			return &EqualCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 				Not:   true, | ||||
| 			}, nil | ||||
| 		case ">=": | ||||
| 			return &SortedComparisonCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 				Equal: true, | ||||
| 				After: true, | ||||
| 			}, nil | ||||
| 		case ">": | ||||
| 			return &SortedComparisonCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 				After: true, | ||||
| 			}, nil | ||||
| 		case "<=": | ||||
| 			return &SortedComparisonCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 				Equal: true, | ||||
| 			}, nil | ||||
| 		case "<": | ||||
| 			return &SortedComparisonCondition{ | ||||
| 				Key:   parts.Key, | ||||
| 				Value: parts.Value, | ||||
| 			}, nil | ||||
| 		default: | ||||
| 			return nil, &UnknownComparisonOperatorErr{Operator: parts.Comparison} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func processParseSelectorDynamic(selector string, sel Selector) (Selector, error) { | ||||
| 	sel.Type = "DYNAMIC" | ||||
| 	dynamicGroups, err := DynamicSelectorToGroups(selector) | ||||
| @@ -54,61 +114,14 @@ func processParseSelectorDynamic(selector string, sel Selector) (Selector, error | ||||
| 	} | ||||
|  | ||||
| 	for _, g := range dynamicGroups { | ||||
| 		// evaluable, err := gvalInstance.NewEvaluable(g) | ||||
| 		// if err != nil { | ||||
| 		// 	return sel, fmt.Errorf("could not parse dynamic expression: %w", err) | ||||
| 		// } | ||||
| 		// | ||||
| 		// todo : how do we execute sub queries? | ||||
| 		// sel.Conditions = append(sel.Conditions, &GvalCondition{ | ||||
| 		// 	Evaluable: evaluable, | ||||
| 		// }) | ||||
|  | ||||
| 		m := FindDynamicSelectorParts(g) | ||||
|  | ||||
| 		var cond Condition | ||||
|  | ||||
| 		switch m.Comparison { | ||||
| 		case "=": | ||||
| 			cond = &EqualCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 			} | ||||
| 		case "!=": | ||||
| 			cond = &EqualCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 				Not:   true, | ||||
| 			} | ||||
| 		case ">=": | ||||
| 			cond = &SortedComparisonCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 				Equal: true, | ||||
| 				After: true, | ||||
| 			} | ||||
| 		case ">": | ||||
| 			cond = &SortedComparisonCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 				After: true, | ||||
| 			} | ||||
| 		case "<=": | ||||
| 			cond = &SortedComparisonCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 				Equal: true, | ||||
| 			} | ||||
| 		case "<": | ||||
| 			cond = &SortedComparisonCondition{ | ||||
| 				Key:   m.Key, | ||||
| 				Value: m.Value, | ||||
| 			} | ||||
| 		default: | ||||
| 			return sel, &UnknownComparisonOperatorErr{Operator: m.Comparison} | ||||
| 		parts := FindDynamicSelectorParts(g) | ||||
| 		cond, err := getCondition(parts) | ||||
| 		if err != nil { | ||||
| 			return sel, err | ||||
| 		} | ||||
| 		if cond != nil { | ||||
| 			sel.Conditions = append(sel.Conditions, cond) | ||||
| 		} | ||||
|  | ||||
| 		sel.Conditions = append(sel.Conditions, cond) | ||||
| 	} | ||||
|  | ||||
| 	return sel, nil | ||||
| @@ -126,69 +139,15 @@ func processParseSelectorSearch(selector string, sel Selector) (Selector, error) | ||||
| 	} | ||||
|  | ||||
| 	for _, g := range dynamicGroups { | ||||
| 		m := FindDynamicSelectorParts(g) | ||||
|  | ||||
| 		m.Key = strings.TrimPrefix(m.Key, "?:") | ||||
|  | ||||
| 		var cond Condition | ||||
| 		switch m.Key { | ||||
| 		case "-", "keyValue": | ||||
| 			switch m.Comparison { | ||||
| 			case "=": | ||||
| 				cond = &KeyEqualCondition{ | ||||
| 					Value: m.Value, | ||||
| 				} | ||||
| 			case "!=": | ||||
| 				cond = &KeyEqualCondition{ | ||||
| 					Value: m.Value, | ||||
| 					Not:   true, | ||||
| 				} | ||||
| 			default: | ||||
| 				return sel, &UnknownComparisonOperatorErr{Operator: m.Comparison} | ||||
| 			} | ||||
| 		default: | ||||
| 			switch m.Comparison { | ||||
| 			case "=": | ||||
| 				cond = &EqualCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 				} | ||||
| 			case "!=": | ||||
| 				cond = &EqualCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 					Not:   true, | ||||
| 				} | ||||
| 			case ">=": | ||||
| 				cond = &SortedComparisonCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 					Equal: true, | ||||
| 					After: true, | ||||
| 				} | ||||
| 			case ">": | ||||
| 				cond = &SortedComparisonCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 					After: true, | ||||
| 				} | ||||
| 			case "<=": | ||||
| 				cond = &SortedComparisonCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 					Equal: true, | ||||
| 				} | ||||
| 			case "<": | ||||
| 				cond = &SortedComparisonCondition{ | ||||
| 					Key:   m.Key, | ||||
| 					Value: m.Value, | ||||
| 				} | ||||
| 			default: | ||||
| 				return sel, &UnknownComparisonOperatorErr{Operator: m.Comparison} | ||||
| 			} | ||||
| 		parts := FindDynamicSelectorParts(g) | ||||
| 		parts.Key = strings.TrimPrefix(parts.Key, "?:") | ||||
| 		cond, err := getCondition(parts) | ||||
| 		if err != nil { | ||||
| 			return sel, err | ||||
| 		} | ||||
| 		if cond != nil { | ||||
| 			sel.Conditions = append(sel.Conditions, cond) | ||||
| 		} | ||||
|  | ||||
| 		sel.Conditions = append(sel.Conditions, cond) | ||||
| 	} | ||||
|  | ||||
| 	return sel, nil | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tom Wright
					Tom Wright