@@ -21,6 +21,7 @@ import (
2121 "strings"
2222
2323 "github.com/dgraph-io/dgraph/gql"
24+ "github.com/dgraph-io/dgraph/graphql/schema"
2425 "github.com/dgraph-io/dgraph/x"
2526)
2627
@@ -65,10 +66,24 @@ func writeQuery(b *strings.Builder, query *gql.GraphQuery, prefix string) {
6566 x .Check2 (b .WriteString (query .Alias ))
6667 x .Check2 (b .WriteString (" : " ))
6768 }
68- x .Check2 (b .WriteString (query .Attr ))
69+
70+ if query .IsCount {
71+ x .Check2 (b .WriteString (fmt .Sprintf ("count(%s)" , query .Attr )))
72+ } else if query .Attr != "val" {
73+ x .Check2 (b .WriteString (query .Attr ))
74+ } else if isAggregateFn (query .Func ) {
75+ x .Check2 (b .WriteString ("sum(val(" ))
76+ writeNeedVar (b , query )
77+ x .Check2 (b .WriteRune (')' ))
78+ } else {
79+ x .Check2 (b .WriteString ("val(" ))
80+ writeNeedVar (b , query )
81+ x .Check2 (b .WriteRune (')' ))
82+ }
6983
7084 if query .Func != nil {
7185 writeRoot (b , query )
86+ x .Check2 (b .WriteRune (')' ))
7287 }
7388
7489 if query .Filter != nil {
@@ -93,6 +108,12 @@ func writeQuery(b *strings.Builder, query *gql.GraphQuery, prefix string) {
93108 }
94109 }
95110
111+ if query .IsGroupby {
112+ x .Check2 (b .WriteString (" @groupby(" ))
113+ writeGroupByAttributes (b , query .GroupbyAttrs )
114+ x .Check2 (b .WriteRune (')' ))
115+ }
116+
96117 switch {
97118 case len (query .Children ) > 0 :
98119 prefixAdd := ""
@@ -112,7 +133,43 @@ func writeQuery(b *strings.Builder, query *gql.GraphQuery, prefix string) {
112133 }
113134}
114135
115- func writeUIDFunc (b * strings.Builder , uids []uint64 , args []gql.Arg ) {
136+ // writeNeedVar writes the NeedsVar of the query. For eg :-
137+ // `userFollowerCount as sum(val(followers))` has `followers`
138+ // as NeedsVar.
139+ func writeNeedVar (b * strings.Builder , query * gql.GraphQuery ) {
140+ for i , v := range query .NeedsVar {
141+ if i != 0 {
142+ x .Check2 (b .WriteString (", " ))
143+ }
144+ x .Check2 (b .WriteString (v .Name ))
145+ }
146+ }
147+
148+ func isAggregateFn (f * gql.Function ) bool {
149+ if f == nil {
150+ return false
151+ }
152+ switch f .Name {
153+ case "min" , "max" , "avg" , "sum" :
154+ return true
155+ }
156+ return false
157+ }
158+
159+ func writeGroupByAttributes (b * strings.Builder , attrList []gql.GroupByAttr ) {
160+ for i , attr := range attrList {
161+ if i != 0 {
162+ x .Check2 (b .WriteString (", " ))
163+ }
164+ if attr .Alias != "" {
165+ x .Check2 (b .WriteString (attr .Alias ))
166+ x .Check2 (b .WriteString (" : " ))
167+ }
168+ x .Check2 (b .WriteString (attr .Attr ))
169+ }
170+ }
171+
172+ func writeUIDFunc (b * strings.Builder , uids []uint64 , args []gql.Arg , needVar []gql.VarContext ) {
116173 x .Check2 (b .WriteString ("uid(" ))
117174 if len (uids ) > 0 {
118175 // uid function with uint64 - uid(0x123, 0x456, ...)
@@ -122,14 +179,21 @@ func writeUIDFunc(b *strings.Builder, uids []uint64, args []gql.Arg) {
122179 }
123180 x .Check2 (b .WriteString (fmt .Sprintf ("%#x" , uid )))
124181 }
125- } else {
182+ } else if len ( args ) > 0 {
126183 // uid function with a Dgraph query variable - uid(Post1)
127184 for i , arg := range args {
128185 if i != 0 {
129186 x .Check2 (b .WriteString (", " ))
130187 }
131188 x .Check2 (b .WriteString (arg .Value ))
132189 }
190+ } else {
191+ for i , v := range needVar {
192+ if i != 0 {
193+ x .Check2 (b .WriteString (", " ))
194+ }
195+ x .Check2 (b .WriteString (v .Name ))
196+ }
133197 }
134198 x .Check2 (b .WriteString (")" ))
135199}
@@ -145,25 +209,38 @@ func writeRoot(b *strings.Builder, q *gql.GraphQuery) {
145209 }
146210
147211 switch {
212+ case q .Func .Name == "has" :
213+ x .Check2 (b .WriteString (fmt .Sprintf ("(func: has(%s)" , q .Func .Attr )))
148214 case q .Func .Name == "uid" :
149215 x .Check2 (b .WriteString ("(func: " ))
150- writeUIDFunc (b , q .Func .UID , q .Func .Args )
216+ writeUIDFunc (b , q .Func .UID , q .Func .Args , q . Func . NeedsVar )
151217 case q .Func .Name == "type" && len (q .Func .Args ) == 1 :
152218 x .Check2 (b .WriteString (fmt .Sprintf ("(func: type(%s)" , q .Func .Args [0 ].Value )))
153219 case q .Func .Name == "eq" :
154220 x .Check2 (b .WriteString ("(func: eq(" ))
155- writeFilterArguments (b , q .Func . Args )
221+ writeFilterArguments (b , q .Func )
156222 x .Check2 (b .WriteRune (')' ))
157223 }
158224 writeOrderAndPage (b , q , true )
159- x .Check2 (b .WriteRune (')' ))
160225}
161226
162- func writeFilterArguments (b * strings.Builder , args []gql.Arg ) {
163- for i , arg := range args {
164- if i != 0 {
227+ // writeFilterArguments writes the filter arguments. If the filter
228+ // is constructed in graphql query rewriting then `Attr` is an empty
229+ // string since we add Attr in the argument itself.
230+ func writeFilterArguments (b * strings.Builder , q * gql.Function ) {
231+ if q .Attr != "" {
232+ x .Check2 (b .WriteString (q .Attr ))
233+ }
234+
235+ for i , arg := range q .Args {
236+ if i != 0 || q .Attr != "" {
165237 x .Check2 (b .WriteString (", " ))
166238 }
239+ if q .Attr != "" {
240+ // quote the arguments since this is the case of
241+ // @custom DQL string.
242+ arg .Value = schema .MaybeQuoteArg (q .Name , arg .Value )
243+ }
167244 x .Check2 (b .WriteString (arg .Value ))
168245 }
169246}
@@ -175,10 +252,10 @@ func writeFilterFunction(b *strings.Builder, f *gql.Function) {
175252
176253 switch {
177254 case f .Name == "uid" :
178- writeUIDFunc (b , f .UID , f .Args )
255+ writeUIDFunc (b , f .UID , f .Args , f . NeedsVar )
179256 default :
180257 x .Check2 (b .WriteString (fmt .Sprintf ("%s(" , f .Name )))
181- writeFilterArguments (b , f . Args )
258+ writeFilterArguments (b , f )
182259 x .Check2 (b .WriteRune (')' ))
183260 }
184261}
@@ -215,6 +292,15 @@ func hasOrderOrPage(q *gql.GraphQuery) bool {
215292 return len (q .Order ) > 0 || hasFirst || hasOffset
216293}
217294
295+ func IsValueVar (attr string , q * gql.GraphQuery ) bool {
296+ for _ , vars := range q .NeedsVar {
297+ if attr == vars .Name && vars .Typ == 2 {
298+ return true
299+ }
300+ }
301+ return false
302+ }
303+
218304func writeOrderAndPage (b * strings.Builder , query * gql.GraphQuery , root bool ) {
219305 var wroteOrder , wroteFirst bool
220306
@@ -227,7 +313,13 @@ func writeOrderAndPage(b *strings.Builder, query *gql.GraphQuery, root bool) {
227313 } else {
228314 x .Check2 (b .WriteString ("orderasc: " ))
229315 }
230- x .Check2 (b .WriteString (ord .Attr ))
316+ if IsValueVar (ord .Attr , query ) {
317+ x .Check2 (b .WriteString ("val(" ))
318+ x .Check2 (b .WriteString (ord .Attr ))
319+ x .Check2 (b .WriteRune (')' ))
320+ } else {
321+ x .Check2 (b .WriteString (ord .Attr ))
322+ }
231323 wroteOrder = true
232324 }
233325
0 commit comments