55
66package jsonpath
77
8- import "fmt"
8+ import (
9+ "strings"
10+
11+ "github.com/cockroachdb/errors"
12+ )
913
1014type OperationType int
1115
@@ -64,26 +68,47 @@ type Operation struct {
6468
6569var _ Path = Operation {}
6670
67- func (o Operation ) String () string {
68- if int (o .Type ) < 0 || int (o .Type ) >= len (OperationTypeStrings ) || o .Type == OpInvalid {
69- panic (fmt .Sprintf ("invalid operation type: %d" , o .Type ))
70- }
71- // TODO(normanchenn): Fix recursive brackets. When there is a operation like
72- // 1 == 1 && 1 != 1, postgres will output (1 == 1 && 1 != 1), but we output
73- // ((1 == 1) && (1 != 1)).
74- if o .Type == OpLogicalNot {
75- return fmt .Sprintf ("%s(%s)" , OperationTypeStrings [o .Type ], o .Left )
76- }
77- if o .Type == OpPlus || o .Type == OpMinus {
78- return fmt .Sprintf ("(%s%s)" , OperationTypeStrings [o .Type ], o .Left )
79- }
80- if o .Type == OpExists {
81- return fmt .Sprintf ("%s (%s)" , OperationTypeStrings [o .Type ], o .Left )
82- }
83- if o .Type == OpIsUnknown {
84- return fmt .Sprintf ("(%s) %s" , o .Left , OperationTypeStrings [o .Type ])
71+ func (o Operation ) ToString (sb * strings.Builder , _ , printBrackets bool ) {
72+ switch o .Type {
73+ case OpCompEqual , OpCompNotEqual , OpCompLess , OpCompLessEqual ,
74+ OpCompGreater , OpCompGreaterEqual , OpLogicalAnd , OpLogicalOr , OpAdd ,
75+ OpSub , OpMult , OpDiv , OpMod , OpStartsWith , OpLikeRegex :
76+ if printBrackets {
77+ sb .WriteString ("(" )
78+ defer sb .WriteString (")" )
79+ }
80+ o .Left .ToString (sb , false /* inKey */ , opPriority (o .Left ) <= opPriority (o ))
81+ sb .WriteString (" " )
82+ sb .WriteString (OperationTypeStrings [o .Type ])
83+ sb .WriteString (" " )
84+ o .Right .ToString (sb , false /* inKey */ , opPriority (o .Right ) <= opPriority (o ))
85+ return
86+ case OpLogicalNot :
87+ sb .WriteString ("!(" )
88+ o .Left .ToString (sb , false /* inKey */ , false /* printBrackets */ )
89+ sb .WriteString (")" )
90+ return
91+ case OpPlus , OpMinus :
92+ if printBrackets {
93+ sb .WriteString ("(" )
94+ defer sb .WriteString (")" )
95+ }
96+ sb .WriteString (OperationTypeStrings [o .Type ])
97+ o .Left .ToString (sb , false /* inKey */ , opPriority (o .Left ) <= opPriority (o ))
98+ return
99+ case OpExists :
100+ sb .WriteString ("exists (" )
101+ o .Left .ToString (sb , false /* inKey */ , false /* printBrackets */ )
102+ sb .WriteString (")" )
103+ return
104+ case OpIsUnknown :
105+ sb .WriteString ("(" )
106+ o .Left .ToString (sb , false /* inKey */ , false /* printBrackets */ )
107+ sb .WriteString (") is unknown" )
108+ return
109+ default :
110+ panic (errors .AssertionFailedf ("unhandled operation type: %d" , o .Type ))
85111 }
86- return fmt .Sprintf ("(%s %s %s)" , o .Left , OperationTypeStrings [o .Type ], o .Right )
87112}
88113
89114func (o Operation ) Validate (nestingLevel int , insideArraySubscript bool ) error {
@@ -97,3 +122,28 @@ func (o Operation) Validate(nestingLevel int, insideArraySubscript bool) error {
97122 }
98123 return nil
99124}
125+
126+ func opPriority (path Path ) int {
127+ switch path := path .(type ) {
128+ case Operation :
129+ switch path .Type {
130+ case OpLogicalOr :
131+ return 0
132+ case OpLogicalAnd :
133+ return 1
134+ case OpCompEqual , OpCompNotEqual , OpCompLess , OpCompLessEqual ,
135+ OpCompGreater , OpCompGreaterEqual , OpStartsWith :
136+ return 2
137+ case OpAdd , OpSub :
138+ return 3
139+ case OpMult , OpDiv , OpMod :
140+ return 4
141+ case OpPlus , OpMinus :
142+ return 5
143+ default :
144+ return 6
145+ }
146+ default :
147+ return 6
148+ }
149+ }
0 commit comments