github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/query/query.go (about)

     1  /*
     2   * Copyright 2015-2018 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package query
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"math"
    23  	"sort"
    24  	"strconv"
    25  	"strings"
    26  	"time"
    27  
    28  	"github.com/golang/glog"
    29  	"github.com/pkg/errors"
    30  	otrace "go.opencensus.io/trace"
    31  	"google.golang.org/grpc/metadata"
    32  
    33  	"github.com/dgraph-io/dgo/protos/api"
    34  	"github.com/dgraph-io/dgraph/algo"
    35  	"github.com/dgraph-io/dgraph/gql"
    36  	"github.com/dgraph-io/dgraph/protos/pb"
    37  	"github.com/dgraph-io/dgraph/schema"
    38  	"github.com/dgraph-io/dgraph/types"
    39  	"github.com/dgraph-io/dgraph/types/facets"
    40  	"github.com/dgraph-io/dgraph/worker"
    41  	"github.com/dgraph-io/dgraph/x"
    42  )
    43  
    44  /*
    45   * QUERY:
    46   * Let's take this query from GraphQL as example:
    47   * {
    48   *   me {
    49   *     id
    50   *     firstName
    51   *     lastName
    52   *     birthday {
    53   *       month
    54   *       day
    55   *     }
    56   *     friends {
    57   *       name
    58   *     }
    59   *   }
    60   * }
    61   *
    62   * REPRESENTATION:
    63   * This would be represented in SubGraph format pb.y, as such:
    64   * SubGraph [result uid = me]
    65   *    |
    66   *  Children
    67   *    |
    68   *    --> SubGraph [Attr = "xid"]
    69   *    --> SubGraph [Attr = "firstName"]
    70   *    --> SubGraph [Attr = "lastName"]
    71   *    --> SubGraph [Attr = "birthday"]
    72   *           |
    73   *         Children
    74   *           |
    75   *           --> SubGraph [Attr = "month"]
    76   *           --> SubGraph [Attr = "day"]
    77   *    --> SubGraph [Attr = "friends"]
    78   *           |
    79   *         Children
    80   *           |
    81   *           --> SubGraph [Attr = "name"]
    82   *
    83   * ALGORITHM:
    84   * This is a rough and simple algorithm of how to process this SubGraph query
    85   * and populate the results:
    86   *
    87   * For a given entity, a new SubGraph can be started off with NewGraph(id).
    88   * Given a SubGraph, is the Query field empty? [Step a]
    89   *   - If no, run (or send it to server serving the attribute) query
    90   *     and populate result.
    91   * Iterate over children and copy Result Uids to child Query Uids.
    92   *     Set Attr. Then for each child, use goroutine to run Step:a.
    93   * Wait for goroutines to finish.
    94   * Return errors, if any.
    95   */
    96  
    97  // Latency is used to keep track of the latency involved in parsing and processing
    98  // the query. It also contains information about the time it took to convert the
    99  // result into a format(JSON/Protocol Buffer) that the client expects.
   100  type Latency struct {
   101  	Start           time.Time     `json:"-"`
   102  	Parsing         time.Duration `json:"query_parsing"`
   103  	AssignTimestamp time.Duration `json:"assign_timestamp"`
   104  	Processing      time.Duration `json:"processing"`
   105  	Json            time.Duration `json:"json_conversion"`
   106  }
   107  
   108  // params contains the list of parameters required to execute a SubGraph.
   109  type params struct {
   110  	Alias    string
   111  	Count    int         // Value of "first" parameter in the query.
   112  	Offset   int         // Value of offset parameter.
   113  	AfterUID uint64      // Value of after
   114  	DoCount  bool        // True if count of predicate is requested instead of the value of predicate.
   115  	GetUid   bool        // True if uid should be returned. Used for debug requests.
   116  	Order    []*pb.Order // List of predicates to sort by and the sort order.
   117  	Langs    []string    // languages and their preference order for looking up a predicate value
   118  
   119  	// Facet tells us about the requested facets and their aliases.
   120  	Facet *pb.FacetParams
   121  	// FacetOrder has the name of the facet by which the results should be sorted.
   122  	FacetOrder     string
   123  	FacetOrderDesc bool
   124  
   125  	// The name of the variable defined in this SubGraph.
   126  	// for e.g. in x as name, this would be x
   127  	Var string
   128  	// map of predicate to the facet variable alias
   129  	// for e.g. @facets(L1 as weight) the map would be { "weight": "L1" }
   130  	FacetVar map[string]string
   131  	// The list of variables required by this SubGraph along with their type
   132  	NeedsVar []gql.VarContext
   133  
   134  	// ParentVars is a map of variables passed down recursively to children of a SubGraph in a query
   135  	// block. These are used to filter uids defined in a parent using a variable.
   136  	// TODO (pawan) - This can potentially be simplified to a map[string]*pb.List since we don't
   137  	// support reading from value variables defined in the parent and other fields that are part
   138  	// of varValue.
   139  	ParentVars map[string]varValue
   140  
   141  	// mapping of uid to values. This is populated into a SubGraph from a value variable that is
   142  	// part of req.Vars. This value variable variable would have been defined in some other query.
   143  	uidToVal map[uint64]types.Val
   144  
   145  	// directives
   146  	Normalize   bool // True if @normalize directive is specified
   147  	Recurse     bool // True if @recurse directive is specified
   148  	RecurseArgs gql.RecurseArgs
   149  
   150  	Cascade      bool // True if @cascade directive is specified
   151  	IgnoreReflex bool // True if ignorereflex directive is specified.
   152  
   153  	// ShortestPathArgs contains the from and to functions to execute a shortest path query.
   154  	// The function is evaluated and the value of the nodes between which to run the shortest path
   155  	// query is stored in From and To.
   156  	ShortestPathArgs gql.ShortestPathArgs
   157  	From             uint64
   158  	To               uint64
   159  	numPaths         int // used for k-shortest path query to specify number of paths to return.
   160  	MaxWeight        float64
   161  	MinWeight        float64
   162  
   163  	// used by recurse and shortest path queries to specify the graph depth to explore.
   164  	ExploreDepth uint64
   165  
   166  	isInternal   bool   // Determines if processTask has to be called or not.
   167  	ignoreResult bool   // Node results are ignored.
   168  	Expand       string // Value is either _all_/variable-name or empty.
   169  
   170  	isGroupBy    bool              // True if @groupby is specified.
   171  	groupbyAttrs []gql.GroupByAttr // list of attributes to groupby.
   172  
   173  	uidCount      bool
   174  	uidCountAlias string
   175  	parentIds     []uint64 // This is a stack that is maintained and passed down to children.
   176  	IsEmpty       bool     // Won't have any SrcUids or DestUids. Only used to get aggregated vars
   177  	expandAll     bool     // expand all languages
   178  	shortest      bool
   179  }
   180  
   181  type pathMetadata struct {
   182  	weight float64 // Total weight of the path.
   183  }
   184  
   185  // Function holds the information about gql functions.
   186  type Function struct {
   187  	Name       string    // Specifies the name of the function.
   188  	Args       []gql.Arg // Contains the arguments of the function.
   189  	IsCount    bool      // gt(count(friends),0)
   190  	IsValueVar bool      // eq(val(s), 10)
   191  	IsLenVar   bool      // eq(len(s), 10)
   192  }
   193  
   194  // SubGraph is the way to represent data. It contains both the request parameters and the response.
   195  // Once generated, this can then be encoded to other client convenient formats, like GraphQL / JSON.
   196  type SubGraph struct {
   197  	ReadTs      uint64
   198  	Cache       int
   199  	Attr        string
   200  	UnknownAttr bool
   201  	// read only parameters which are populated before the execution of the query and are used to
   202  	// execute this query.
   203  	Params params
   204  
   205  	// count stores the count of an edge (predicate). There would be one value corresponding to each
   206  	// uid in SrcUIDs.
   207  	counts []uint32
   208  	// valueMatrix is a slice of ValueList. If this SubGraph is for a scalar predicate type, then
   209  	// there would be one list for each uid in SrcUIDs storing the value of the predicate.
   210  	// The individual elements of the slice are a ValueList because we support scalar predicates
   211  	// of list type. For non-list type scalar predicates, there would be only one value in every
   212  	// ValueList.
   213  	valueMatrix []*pb.ValueList
   214  	// uidMatrix is a slice of List. There would be one List corresponding to each uid in SrcUIDs.
   215  	// In graph terms, a list is a slice of outgoing edges from a node.
   216  	uidMatrix []*pb.List
   217  
   218  	// facetsMatrix contains the facet values. There would a list corresponding to each uid in
   219  	// uidMatrix.
   220  	facetsMatrix []*pb.FacetsList
   221  	ExpandPreds  []*pb.ValueList
   222  	GroupbyRes   []*groupResults // one result for each uid list.
   223  	LangTags     []*pb.LangList
   224  
   225  	// SrcUIDs is a list of unique source UIDs. They are always copies of destUIDs
   226  	// of parent nodes in GraphQL structure.
   227  	SrcUIDs *pb.List
   228  	// SrcFunc specified using func. Should only be non-nil at root. At other levels,
   229  	// filters are used.
   230  	SrcFunc *Function
   231  
   232  	FilterOp     string
   233  	Filters      []*SubGraph // List of filters specified at the current node.
   234  	facetsFilter *pb.FilterTree
   235  	MathExp      *mathTree
   236  	Children     []*SubGraph // children of the current node, should be empty for leaf nodes.
   237  
   238  	// destUIDs is a list of destination UIDs, after applying filters, pagination.
   239  	DestUIDs *pb.List
   240  	List     bool // whether predicate is of list type
   241  
   242  	pathMeta *pathMetadata
   243  }
   244  
   245  func (sg *SubGraph) recurse(set func(sg *SubGraph)) {
   246  	set(sg)
   247  	for _, child := range sg.Children {
   248  		child.recurse(set)
   249  	}
   250  	for _, filter := range sg.Filters {
   251  		filter.recurse(set)
   252  	}
   253  }
   254  
   255  // IsGroupBy returns whether this subgraph is part of a groupBy query.
   256  func (sg *SubGraph) IsGroupBy() bool {
   257  	return sg.Params.isGroupBy
   258  }
   259  
   260  // IsInternal returns whether this subgraph is marked as internal.
   261  func (sg *SubGraph) IsInternal() bool {
   262  	return sg.Params.isInternal
   263  }
   264  
   265  func (sg *SubGraph) createSrcFunction(gf *gql.Function) {
   266  	if gf == nil {
   267  		return
   268  	}
   269  
   270  	sg.SrcFunc = &Function{
   271  		Name:       gf.Name,
   272  		Args:       append(gf.Args[:0:0], gf.Args...),
   273  		IsCount:    gf.IsCount,
   274  		IsValueVar: gf.IsValueVar,
   275  		IsLenVar:   gf.IsLenVar,
   276  	}
   277  
   278  	// type function is just an alias for eq(type, "dgraph.type").
   279  	if gf.Name == "type" {
   280  		sg.Attr = "dgraph.type"
   281  		sg.SrcFunc.Name = "eq"
   282  		sg.SrcFunc.IsCount = false
   283  		sg.SrcFunc.IsValueVar = false
   284  		sg.SrcFunc.IsLenVar = false
   285  		return
   286  	}
   287  
   288  	if gf.Lang != "" {
   289  		sg.Params.Langs = append(sg.Params.Langs, gf.Lang)
   290  	}
   291  }
   292  
   293  // DebugPrint prints out the SubGraph tree in a nice format for debugging purposes.
   294  func (sg *SubGraph) DebugPrint(prefix string) {
   295  	var src, dst int
   296  	if sg.SrcUIDs != nil {
   297  		src = len(sg.SrcUIDs.Uids)
   298  	}
   299  	if sg.DestUIDs != nil {
   300  		dst = len(sg.DestUIDs.Uids)
   301  	}
   302  	glog.Infof("%s[%q Alias:%q Func:%v SrcSz:%v Op:%q DestSz:%v IsCount: %v ValueSz:%v]\n",
   303  		prefix, sg.Attr, sg.Params.Alias, sg.SrcFunc, src, sg.FilterOp,
   304  		dst, sg.Params.DoCount, len(sg.valueMatrix))
   305  	for _, f := range sg.Filters {
   306  		f.DebugPrint(prefix + "|-f->")
   307  	}
   308  	for _, c := range sg.Children {
   309  		c.DebugPrint(prefix + "|->")
   310  	}
   311  }
   312  
   313  // getValue gets the value from the task.
   314  func getValue(tv *pb.TaskValue) (types.Val, error) {
   315  	vID := types.TypeID(tv.ValType)
   316  	val := types.ValueForType(vID)
   317  	val.Value = tv.Val
   318  	return val, nil
   319  }
   320  
   321  var (
   322  	// ErrEmptyVal is returned when a value is empty.
   323  	ErrEmptyVal = errors.New("Query: harmless error, e.g. task.Val is nil")
   324  	// ErrWrongAgg is returned when value aggregation is attempted in the root level of a query.
   325  	ErrWrongAgg = errors.New("Wrong level for var aggregation")
   326  )
   327  
   328  func (sg *SubGraph) isSimilar(ssg *SubGraph) bool {
   329  	if sg.Attr != ssg.Attr {
   330  		return false
   331  	}
   332  	if len(sg.Params.Langs) != len(ssg.Params.Langs) {
   333  		return false
   334  	}
   335  	for i := 0; i < len(sg.Params.Langs) && i < len(ssg.Params.Langs); i++ {
   336  		if sg.Params.Langs[i] != ssg.Params.Langs[i] {
   337  			return false
   338  		}
   339  	}
   340  	if sg.Params.DoCount {
   341  		return ssg.Params.DoCount
   342  	}
   343  	if ssg.Params.DoCount {
   344  		return false
   345  	}
   346  	if sg.SrcFunc != nil {
   347  		if ssg.SrcFunc != nil && sg.SrcFunc.Name == ssg.SrcFunc.Name {
   348  			return true
   349  		}
   350  		return false
   351  	}
   352  	return true
   353  }
   354  
   355  func isEmptyIneqFnWithVar(sg *SubGraph) bool {
   356  	return sg.SrcFunc != nil && isInequalityFn(sg.SrcFunc.Name) && len(sg.SrcFunc.Args) == 0 &&
   357  		len(sg.Params.NeedsVar) > 0
   358  }
   359  
   360  // convert from task.Val to types.Value, based on schema appropriate type
   361  // is already set in api.Value
   362  func convertWithBestEffort(tv *pb.TaskValue, attr string) (types.Val, error) {
   363  	// value would be in binary format with appropriate type
   364  	v, _ := getValue(tv)
   365  	if !v.Tid.IsScalar() {
   366  		return v, errors.Errorf("Leaf predicate:'%v' must be a scalar.", attr)
   367  	}
   368  
   369  	// creates appropriate type from binary format
   370  	sv, err := types.Convert(v, v.Tid)
   371  	x.Checkf(err, "Error while interpreting appropriate type from binary")
   372  	return sv, nil
   373  }
   374  
   375  func mathCopy(dst *mathTree, src *gql.MathTree) error {
   376  	// Either we'll have an operation specified, or the function specified.
   377  	dst.Const = src.Const
   378  	dst.Fn = src.Fn
   379  	dst.Val = src.Val
   380  	dst.Var = src.Var
   381  
   382  	for _, mc := range src.Child {
   383  		child := &mathTree{}
   384  		if err := mathCopy(child, mc); err != nil {
   385  			return err
   386  		}
   387  		dst.Child = append(dst.Child, child)
   388  	}
   389  	return nil
   390  }
   391  
   392  func filterCopy(sg *SubGraph, ft *gql.FilterTree) error {
   393  	// Either we'll have an operation specified, or the function specified.
   394  	if len(ft.Op) > 0 {
   395  		sg.FilterOp = ft.Op
   396  	} else {
   397  		sg.Attr = ft.Func.Attr
   398  		if !isValidFuncName(ft.Func.Name) {
   399  			return errors.Errorf("Invalid function name: %s", ft.Func.Name)
   400  		}
   401  
   402  		if isUidFnWithoutVar(ft.Func) {
   403  			sg.SrcFunc = &Function{Name: ft.Func.Name}
   404  			if err := sg.populate(ft.Func.UID); err != nil {
   405  				return err
   406  			}
   407  		} else {
   408  			if ft.Func.Attr == "uid" {
   409  				return errors.Errorf(`Argument cannot be "uid"`)
   410  			}
   411  			sg.createSrcFunction(ft.Func)
   412  			sg.Params.NeedsVar = append(sg.Params.NeedsVar, ft.Func.NeedsVar...)
   413  		}
   414  	}
   415  	for _, ftc := range ft.Child {
   416  		child := &SubGraph{}
   417  		if err := filterCopy(child, ftc); err != nil {
   418  			return err
   419  		}
   420  		sg.Filters = append(sg.Filters, child)
   421  	}
   422  	return nil
   423  }
   424  
   425  func uniqueKey(gchild *gql.GraphQuery) string {
   426  	key := gchild.Attr
   427  	if gchild.Func != nil {
   428  		key += fmt.Sprintf("%v", gchild.Func)
   429  	}
   430  	// This is the case when we ask for a variable.
   431  	if gchild.Attr == "val" {
   432  		// E.g. a as age, result is returned as var(a)
   433  		if gchild.Var != "" && gchild.Var != "val" {
   434  			key = fmt.Sprintf("val(%v)", gchild.Var)
   435  		} else if len(gchild.NeedsVar) > 0 {
   436  			// For var(s)
   437  			key = fmt.Sprintf("val(%v)", gchild.NeedsVar[0].Name)
   438  		}
   439  
   440  		// Could be min(var(x)) && max(var(x))
   441  		if gchild.Func != nil {
   442  			key += gchild.Func.Name
   443  		}
   444  	}
   445  	if gchild.IsCount { // ignore count subgraphs..
   446  		key += "count"
   447  	}
   448  	if len(gchild.Langs) > 0 {
   449  		key += fmt.Sprintf("%v", gchild.Langs)
   450  	}
   451  	if gchild.MathExp != nil {
   452  		// We would only be here if Alias is empty, so Var would be non
   453  		// empty because MathExp should have atleast one of them.
   454  		key = fmt.Sprintf("val(%+v)", gchild.Var)
   455  	}
   456  	if gchild.IsGroupby {
   457  		key += "groupby"
   458  	}
   459  	return key
   460  }
   461  
   462  func treeCopy(gq *gql.GraphQuery, sg *SubGraph) error {
   463  	// Typically you act on the current node, and leave recursion to deal with
   464  	// children. But, in this case, we don't want to muck with the current
   465  	// node, because of the way we're dealing with the root node.
   466  	// So, we work on the children, and then recurse for grand children.
   467  	attrsSeen := make(map[string]struct{})
   468  
   469  	for _, gchild := range gq.Children {
   470  		if sg.Params.Alias == "shortest" && gchild.Expand != "" {
   471  			return errors.Errorf("expand() not allowed inside shortest")
   472  		}
   473  
   474  		key := ""
   475  		if gchild.Alias != "" {
   476  			key = gchild.Alias
   477  		} else {
   478  			key = uniqueKey(gchild)
   479  		}
   480  		if _, ok := attrsSeen[key]; ok {
   481  			return errors.Errorf("%s not allowed multiple times in same sub-query.",
   482  				key)
   483  		}
   484  		attrsSeen[key] = struct{}{}
   485  
   486  		args := params{
   487  			Alias:          gchild.Alias,
   488  			Cascade:        sg.Params.Cascade,
   489  			Expand:         gchild.Expand,
   490  			Facet:          gchild.Facets,
   491  			FacetOrder:     gchild.FacetOrder,
   492  			FacetOrderDesc: gchild.FacetDesc,
   493  			FacetVar:       gchild.FacetVar,
   494  			GetUid:         sg.Params.GetUid,
   495  			IgnoreReflex:   sg.Params.IgnoreReflex,
   496  			Langs:          gchild.Langs,
   497  			NeedsVar:       append(gchild.NeedsVar[:0:0], gchild.NeedsVar...),
   498  			Normalize:      sg.Params.Normalize,
   499  			Order:          gchild.Order,
   500  			Var:            gchild.Var,
   501  			groupbyAttrs:   gchild.GroupbyAttrs,
   502  			isGroupBy:      gchild.IsGroupby,
   503  			isInternal:     gchild.IsInternal,
   504  			uidCount:       gchild.UidCount,
   505  			uidCountAlias:  gchild.UidCountAlias,
   506  		}
   507  
   508  		if gchild.IsCount {
   509  			if len(gchild.Children) != 0 {
   510  				return errors.New("Node with count cannot have child attributes")
   511  			}
   512  			args.DoCount = true
   513  		}
   514  
   515  		for argk := range gchild.Args {
   516  			if !isValidArg(argk) {
   517  				return errors.Errorf("Invalid argument: %s", argk)
   518  			}
   519  		}
   520  		if err := args.fill(gchild); err != nil {
   521  			return err
   522  		}
   523  
   524  		if len(args.Order) != 0 && len(args.FacetOrder) != 0 {
   525  			return errors.Errorf("Cannot specify order at both args and facets")
   526  		}
   527  
   528  		dst := &SubGraph{
   529  			Attr:   gchild.Attr,
   530  			Params: args,
   531  		}
   532  		if gchild.MathExp != nil {
   533  			mathExp := &mathTree{}
   534  			if err := mathCopy(mathExp, gchild.MathExp); err != nil {
   535  				return err
   536  			}
   537  			dst.MathExp = mathExp
   538  		}
   539  
   540  		if gchild.Func != nil &&
   541  			(gchild.Func.IsAggregator() || gchild.Func.IsPasswordVerifier()) {
   542  			if len(gchild.Children) != 0 {
   543  				return errors.Errorf("Node with %q cant have child attr", gchild.Func.Name)
   544  			}
   545  			// embedded filter will cause ambiguous output like following,
   546  			// director.film @filter(gt(initial_release_date, "2016")) {
   547  			//    min(initial_release_date @filter(gt(initial_release_date, "1986"))
   548  			// }
   549  			if gchild.Filter != nil {
   550  				return errors.Errorf(
   551  					"Node with %q cant have filter, please place the filter on the upper level",
   552  					gchild.Func.Name)
   553  			}
   554  			if gchild.Func.Attr == "uid" {
   555  				return errors.Errorf(`Argument cannot be "uid"`)
   556  			}
   557  			dst.createSrcFunction(gchild.Func)
   558  		}
   559  
   560  		if gchild.Filter != nil {
   561  			dstf := &SubGraph{}
   562  			if err := filterCopy(dstf, gchild.Filter); err != nil {
   563  				return err
   564  			}
   565  			dst.Filters = append(dst.Filters, dstf)
   566  		}
   567  
   568  		if gchild.FacetsFilter != nil {
   569  			facetsFilter, err := toFacetsFilter(gchild.FacetsFilter)
   570  			if err != nil {
   571  				return err
   572  			}
   573  			dst.facetsFilter = facetsFilter
   574  		}
   575  
   576  		sg.Children = append(sg.Children, dst)
   577  		if err := treeCopy(gchild, dst); err != nil {
   578  			return err
   579  		}
   580  	}
   581  	return nil
   582  }
   583  
   584  func (args *params) fill(gq *gql.GraphQuery) error {
   585  	if v, ok := gq.Args["offset"]; ok {
   586  		offset, err := strconv.ParseInt(v, 0, 32)
   587  		if err != nil {
   588  			return err
   589  		}
   590  		args.Offset = int(offset)
   591  	}
   592  	if v, ok := gq.Args["after"]; ok {
   593  		after, err := strconv.ParseUint(v, 0, 64)
   594  		if err != nil {
   595  			return err
   596  		}
   597  		args.AfterUID = after
   598  	}
   599  
   600  	if args.Alias == "shortest" {
   601  		if v, ok := gq.Args["depth"]; ok {
   602  			depth, err := strconv.ParseUint(v, 0, 64)
   603  			if err != nil {
   604  				return err
   605  			}
   606  			args.ExploreDepth = depth
   607  		}
   608  
   609  		if v, ok := gq.Args["numpaths"]; ok {
   610  			numPaths, err := strconv.ParseUint(v, 0, 64)
   611  			if err != nil {
   612  				return err
   613  			}
   614  			args.numPaths = int(numPaths)
   615  		}
   616  
   617  		if v, ok := gq.Args["maxweight"]; ok {
   618  			maxWeight, err := strconv.ParseFloat(v, 64)
   619  			if err != nil {
   620  				return err
   621  			}
   622  			args.MaxWeight = maxWeight
   623  		} else if !ok {
   624  			args.MaxWeight = math.MaxFloat64
   625  		}
   626  
   627  		if v, ok := gq.Args["minweight"]; ok {
   628  			minWeight, err := strconv.ParseFloat(v, 64)
   629  			if err != nil {
   630  				return err
   631  			}
   632  			args.MinWeight = minWeight
   633  		} else if !ok {
   634  			args.MinWeight = -math.MaxFloat64
   635  		}
   636  
   637  		if gq.ShortestPathArgs.From == nil || gq.ShortestPathArgs.To == nil {
   638  			return errors.Errorf("from/to can't be nil for shortest path")
   639  		}
   640  		if len(gq.ShortestPathArgs.From.UID) > 0 {
   641  			args.From = gq.ShortestPathArgs.From.UID[0]
   642  		}
   643  		if len(gq.ShortestPathArgs.To.UID) > 0 {
   644  			args.To = gq.ShortestPathArgs.To.UID[0]
   645  		}
   646  	}
   647  
   648  	if v, ok := gq.Args["first"]; ok {
   649  		first, err := strconv.ParseInt(v, 0, 32)
   650  		if err != nil {
   651  			return err
   652  		}
   653  		args.Count = int(first)
   654  	}
   655  	return nil
   656  }
   657  
   658  // ToSubGraph converts the GraphQuery into the pb.SubGraph instance type.
   659  func ToSubGraph(ctx context.Context, gq *gql.GraphQuery) (*SubGraph, error) {
   660  	sg, err := newGraph(ctx, gq)
   661  	if err != nil {
   662  		return nil, err
   663  	}
   664  	err = treeCopy(gq, sg)
   665  	if err != nil {
   666  		return nil, err
   667  	}
   668  	return sg, err
   669  }
   670  
   671  // ContextKey is used to set options in the context object.
   672  type ContextKey int
   673  
   674  const (
   675  	// DebugKey is the key used to toggle debug mode.
   676  	DebugKey ContextKey = iota
   677  )
   678  
   679  func isDebug(ctx context.Context) bool {
   680  	var debug bool
   681  
   682  	// gRPC client passes information about debug as metadata.
   683  	if md, ok := metadata.FromIncomingContext(ctx); ok {
   684  		// md is a map[string][]string
   685  		if len(md["debug"]) > 0 {
   686  			// We ignore the error here, because in error case,
   687  			// debug would be false which is what we want.
   688  			debug, _ = strconv.ParseBool(md["debug"][0])
   689  		}
   690  	}
   691  
   692  	// HTTP passes information about debug as query parameter which is attached to context.
   693  	d, _ := ctx.Value(DebugKey).(bool)
   694  	return debug || d
   695  }
   696  
   697  func (sg *SubGraph) populate(uids []uint64) error {
   698  	// Put sorted entries in matrix.
   699  	sort.Slice(uids, func(i, j int) bool { return uids[i] < uids[j] })
   700  	sg.uidMatrix = []*pb.List{{Uids: uids}}
   701  	// User specified list may not be sorted.
   702  	sg.SrcUIDs = &pb.List{Uids: uids}
   703  	return nil
   704  }
   705  
   706  // newGraph returns the SubGraph and its task query.
   707  func newGraph(ctx context.Context, gq *gql.GraphQuery) (*SubGraph, error) {
   708  	// This would set the Result field in SubGraph,
   709  	// and populate the children for attributes.
   710  
   711  	// For the root, the name to be used in result is stored in Alias, not Attr.
   712  	// The attr at root (if present) would stand for the source functions attr.
   713  	args := params{
   714  		Alias:            gq.Alias,
   715  		Cascade:          gq.Cascade,
   716  		GetUid:           isDebug(ctx),
   717  		IgnoreReflex:     gq.IgnoreReflex,
   718  		IsEmpty:          gq.IsEmpty,
   719  		Langs:            gq.Langs,
   720  		NeedsVar:         append(gq.NeedsVar[:0:0], gq.NeedsVar...),
   721  		Normalize:        gq.Normalize,
   722  		Order:            gq.Order,
   723  		ParentVars:       make(map[string]varValue),
   724  		Recurse:          gq.Recurse,
   725  		RecurseArgs:      gq.RecurseArgs,
   726  		ShortestPathArgs: gq.ShortestPathArgs,
   727  		Var:              gq.Var,
   728  		groupbyAttrs:     gq.GroupbyAttrs,
   729  		isGroupBy:        gq.IsGroupby,
   730  		uidCount:         gq.UidCount,
   731  		uidCountAlias:    gq.UidCountAlias,
   732  	}
   733  
   734  	for argk := range gq.Args {
   735  		if !isValidArg(argk) {
   736  			return nil, errors.Errorf("Invalid argument: %s", argk)
   737  		}
   738  	}
   739  	if err := args.fill(gq); err != nil {
   740  		return nil, errors.Wrapf(err, "while filling args")
   741  	}
   742  
   743  	sg := &SubGraph{Params: args}
   744  
   745  	if gq.Func != nil {
   746  		// Uid function doesnt have Attr. It just has a list of ids
   747  		if gq.Func.Attr != "uid" {
   748  			sg.Attr = gq.Func.Attr
   749  		} else {
   750  			// Disallow uid as attribute - issue#3110
   751  			if len(gq.Func.UID) == 0 {
   752  				return nil, errors.Errorf(`Argument cannot be "uid"`)
   753  			}
   754  		}
   755  		if !isValidFuncName(gq.Func.Name) {
   756  			return nil, errors.Errorf("Invalid function name: %s", gq.Func.Name)
   757  		}
   758  
   759  		sg.createSrcFunction(gq.Func)
   760  	}
   761  
   762  	if isUidFnWithoutVar(gq.Func) && len(gq.UID) > 0 {
   763  		if err := sg.populate(gq.UID); err != nil {
   764  			return nil, errors.Wrapf(err, "while populating UIDs")
   765  		}
   766  	}
   767  
   768  	// Copy roots filter.
   769  	if gq.Filter != nil {
   770  		sgf := &SubGraph{}
   771  		if err := filterCopy(sgf, gq.Filter); err != nil {
   772  			return nil, errors.Wrapf(err, "while copying filter")
   773  		}
   774  		sg.Filters = append(sg.Filters, sgf)
   775  	}
   776  	if gq.FacetsFilter != nil {
   777  		facetsFilter, err := toFacetsFilter(gq.FacetsFilter)
   778  		if err != nil {
   779  			return nil, errors.Wrapf(err, "while converting to facets filter")
   780  		}
   781  		sg.facetsFilter = facetsFilter
   782  	}
   783  	return sg, nil
   784  }
   785  
   786  func toFacetsFilter(gft *gql.FilterTree) (*pb.FilterTree, error) {
   787  	if gft == nil {
   788  		return nil, nil
   789  	}
   790  	if gft.Func != nil && len(gft.Func.NeedsVar) != 0 {
   791  		return nil, errors.Errorf("Variables not supported in pb.FilterTree")
   792  	}
   793  	ftree := &pb.FilterTree{Op: gft.Op}
   794  	for _, gftc := range gft.Child {
   795  		ftc, err := toFacetsFilter(gftc)
   796  		if err != nil {
   797  			return nil, err
   798  		}
   799  		ftree.Children = append(ftree.Children, ftc)
   800  	}
   801  	if gft.Func != nil {
   802  		ftree.Func = &pb.Function{
   803  			Key:  gft.Func.Attr,
   804  			Name: gft.Func.Name,
   805  		}
   806  		// TODO(Janardhan): Handle variable in facets later.
   807  		for _, arg := range gft.Func.Args {
   808  			ftree.Func.Args = append(ftree.Func.Args, arg.Value)
   809  		}
   810  	}
   811  	return ftree, nil
   812  }
   813  
   814  // createTaskQuery generates the query buffer.
   815  func createTaskQuery(sg *SubGraph) (*pb.Query, error) {
   816  	attr := sg.Attr
   817  	// Might be safer than just checking first byte due to i18n
   818  	reverse := strings.HasPrefix(attr, "~")
   819  	if reverse {
   820  		attr = strings.TrimPrefix(attr, "~")
   821  	}
   822  	var srcFunc *pb.SrcFunction
   823  	if sg.SrcFunc != nil {
   824  		srcFunc = &pb.SrcFunction{}
   825  		srcFunc.Name = sg.SrcFunc.Name
   826  		srcFunc.IsCount = sg.SrcFunc.IsCount
   827  		for _, arg := range sg.SrcFunc.Args {
   828  			srcFunc.Args = append(srcFunc.Args, arg.Value)
   829  			if arg.IsValueVar {
   830  				return nil, errors.Errorf("Unsupported use of value var")
   831  			}
   832  		}
   833  	}
   834  
   835  	// If the lang is set to *, query all the languages.
   836  	if len(sg.Params.Langs) == 1 && sg.Params.Langs[0] == "*" {
   837  		sg.Params.expandAll = true
   838  		sg.Params.Langs = nil
   839  	}
   840  
   841  	out := &pb.Query{
   842  		ReadTs:       sg.ReadTs,
   843  		Cache:        int32(sg.Cache),
   844  		Attr:         attr,
   845  		Langs:        sg.Params.Langs,
   846  		Reverse:      reverse,
   847  		SrcFunc:      srcFunc,
   848  		AfterUid:     sg.Params.AfterUID,
   849  		DoCount:      len(sg.Filters) == 0 && sg.Params.DoCount,
   850  		FacetParam:   sg.Params.Facet,
   851  		FacetsFilter: sg.facetsFilter,
   852  		ExpandAll:    sg.Params.expandAll,
   853  	}
   854  
   855  	if sg.SrcUIDs != nil {
   856  		out.UidList = sg.SrcUIDs
   857  	}
   858  	return out, nil
   859  }
   860  
   861  // varValue is a generic representation of a variable and holds multiple things.
   862  // TODO(pawan) - Come back to this and document what do individual fields mean and when are they
   863  // populated.
   864  type varValue struct {
   865  	Uids *pb.List // list of uids if this denotes a uid variable.
   866  	Vals map[uint64]types.Val
   867  	path []*SubGraph // This stores the subgraph path from root to var definition.
   868  	// strList stores the valueMatrix corresponding to a predicate and is later used in
   869  	// expand(val(x)) query.
   870  	strList []*pb.ValueList
   871  }
   872  
   873  func evalLevelAgg(
   874  	doneVars map[string]varValue,
   875  	sg, parent *SubGraph) (map[uint64]types.Val, error) {
   876  	var mp map[uint64]types.Val
   877  
   878  	if parent == nil {
   879  		return nil, ErrWrongAgg
   880  	}
   881  
   882  	needsVar := sg.Params.NeedsVar[0].Name
   883  	if parent.Params.IsEmpty {
   884  		// The aggregated value doesn't really belong to a uid, we put it in uidToVal map
   885  		// corresponding to uid 0 to avoid defining another field in SubGraph.
   886  		vals := doneVars[needsVar].Vals
   887  		if len(vals) == 0 {
   888  			mp = make(map[uint64]types.Val)
   889  			mp[0] = types.Val{Tid: types.FloatID, Value: 0.0}
   890  			return mp, nil
   891  		}
   892  
   893  		ag := aggregator{
   894  			name: sg.SrcFunc.Name,
   895  		}
   896  		for _, val := range vals {
   897  			ag.Apply(val)
   898  		}
   899  		v, err := ag.Value()
   900  		if err != nil && err != ErrEmptyVal {
   901  			return nil, err
   902  		}
   903  		if v.Value != nil {
   904  			mp = make(map[uint64]types.Val)
   905  			mp[0] = v
   906  		}
   907  		return mp, nil
   908  	}
   909  
   910  	var relSG *SubGraph
   911  	for _, ch := range parent.Children {
   912  		if sg == ch {
   913  			continue
   914  		}
   915  		for _, v := range ch.Params.FacetVar {
   916  			if v == needsVar {
   917  				relSG = ch
   918  			}
   919  		}
   920  		for _, cch := range ch.Children {
   921  			// Find the sibling node whose child has the required variable.
   922  			if cch.Params.Var == needsVar {
   923  				relSG = ch
   924  			}
   925  		}
   926  	}
   927  	if relSG == nil {
   928  		return nil, errors.Errorf("Invalid variable aggregation. Check the levels.")
   929  	}
   930  
   931  	vals := doneVars[needsVar].Vals
   932  	mp = make(map[uint64]types.Val)
   933  	// Go over the sibling node and aggregate.
   934  	for i, list := range relSG.uidMatrix {
   935  		ag := aggregator{
   936  			name: sg.SrcFunc.Name,
   937  		}
   938  		for _, uid := range list.Uids {
   939  			if val, ok := vals[uid]; ok {
   940  				ag.Apply(val)
   941  			}
   942  		}
   943  		v, err := ag.Value()
   944  		if err != nil && err != ErrEmptyVal {
   945  			return nil, err
   946  		}
   947  		if v.Value != nil {
   948  			mp[relSG.SrcUIDs.Uids[i]] = v
   949  		}
   950  	}
   951  	return mp, nil
   952  }
   953  
   954  func (mt *mathTree) extractVarNodes() []*mathTree {
   955  	var nodeList []*mathTree
   956  	for _, ch := range mt.Child {
   957  		nodeList = append(nodeList, ch.extractVarNodes()...)
   958  	}
   959  	if mt.Var != "" {
   960  		nodeList = append(nodeList, mt)
   961  		return nodeList
   962  	}
   963  	return nodeList
   964  }
   965  
   966  // transformTo transforms fromNode to toNode level using the path between them and the
   967  // corresponding uidMatrices.
   968  func (fromNode *varValue) transformTo(toPath []*SubGraph) (map[uint64]types.Val, error) {
   969  	if len(toPath) < len(fromNode.path) {
   970  		return fromNode.Vals, nil
   971  	}
   972  
   973  	idx := 0
   974  	for ; idx < len(fromNode.path); idx++ {
   975  		if fromNode.path[idx] != toPath[idx] {
   976  			return fromNode.Vals, nil
   977  		}
   978  	}
   979  
   980  	if len(fromNode.Vals) == 0 {
   981  		return fromNode.Vals, nil
   982  	}
   983  
   984  	newMap := fromNode.Vals
   985  	for ; idx < len(toPath); idx++ {
   986  		curNode := toPath[idx]
   987  		tempMap := make(map[uint64]types.Val)
   988  		if idx == 0 {
   989  			continue
   990  		}
   991  
   992  		for i := 0; i < len(curNode.uidMatrix); i++ {
   993  			ul := curNode.uidMatrix[i]
   994  			srcUid := curNode.SrcUIDs.Uids[i]
   995  			curVal, ok := newMap[srcUid]
   996  			if !ok || curVal.Value == nil {
   997  				continue
   998  			}
   999  			if curVal.Tid != types.IntID && curVal.Tid != types.FloatID {
  1000  				return nil, errors.Errorf("Encountered non int/float type for summing")
  1001  			}
  1002  			for j := 0; j < len(ul.Uids); j++ {
  1003  				dstUid := ul.Uids[j]
  1004  				ag := aggregator{name: "sum"}
  1005  				ag.Apply(curVal)
  1006  				ag.Apply(tempMap[dstUid])
  1007  				val, err := ag.Value()
  1008  				if err != nil {
  1009  					continue
  1010  				}
  1011  				tempMap[dstUid] = val
  1012  			}
  1013  		}
  1014  		newMap = tempMap
  1015  	}
  1016  	return newMap, nil
  1017  }
  1018  
  1019  // transformVars transforms all the variables to the variable at the lowest level
  1020  func (sg *SubGraph) transformVars(doneVars map[string]varValue, path []*SubGraph) error {
  1021  	mNode := sg.MathExp
  1022  	mvarList := mNode.extractVarNodes()
  1023  	for i := 0; i < len(mvarList); i++ {
  1024  		mt := mvarList[i]
  1025  		curNode := doneVars[mt.Var]
  1026  		newMap, err := curNode.transformTo(path)
  1027  		if err != nil {
  1028  			return err
  1029  		}
  1030  
  1031  		// This is the result of setting the result of count(uid) to a variable.
  1032  		// Treat this value as a constant.
  1033  		if val, ok := newMap[math.MaxUint64]; ok && len(newMap) == 1 {
  1034  			mt.Const = val
  1035  			continue
  1036  		}
  1037  
  1038  		mt.Val = newMap
  1039  	}
  1040  	return nil
  1041  }
  1042  
  1043  func (sg *SubGraph) valueVarAggregation(doneVars map[string]varValue, path []*SubGraph,
  1044  	parent *SubGraph) error {
  1045  	if !sg.IsInternal() && !sg.IsGroupBy() && !sg.Params.IsEmpty {
  1046  		return nil
  1047  	}
  1048  
  1049  	// Aggregation function won't be present at root.
  1050  	if sg.Params.IsEmpty && parent == nil {
  1051  		return nil
  1052  	}
  1053  
  1054  	if sg.IsGroupBy() {
  1055  		if err := sg.processGroupBy(doneVars, path); err != nil {
  1056  			return err
  1057  		}
  1058  	} else if sg.SrcFunc != nil && !parent.IsGroupBy() && isAggregatorFn(sg.SrcFunc.Name) {
  1059  		// Aggregate the value over level.
  1060  		mp, err := evalLevelAgg(doneVars, sg, parent)
  1061  		if err != nil {
  1062  			return err
  1063  		}
  1064  		if sg.Params.Var != "" {
  1065  			it := doneVars[sg.Params.Var]
  1066  			it.Vals = mp
  1067  			doneVars[sg.Params.Var] = it
  1068  		}
  1069  		sg.Params.uidToVal = mp
  1070  	} else if sg.MathExp != nil {
  1071  		// Preprocess to bring all variables to the same level.
  1072  		err := sg.transformVars(doneVars, path)
  1073  		if err != nil {
  1074  			return err
  1075  		}
  1076  
  1077  		err = evalMathTree(sg.MathExp)
  1078  		if err != nil {
  1079  			return err
  1080  		}
  1081  		if len(sg.MathExp.Val) != 0 {
  1082  			it := doneVars[sg.Params.Var]
  1083  			var isInt, isFloat bool
  1084  			for _, v := range sg.MathExp.Val {
  1085  				if v.Tid == types.FloatID {
  1086  					isFloat = true
  1087  				}
  1088  				if v.Tid == types.IntID {
  1089  					isInt = true
  1090  				}
  1091  			}
  1092  			if isInt && isFloat {
  1093  				for k, v := range sg.MathExp.Val {
  1094  					if v.Tid == types.IntID {
  1095  						v.Tid = types.FloatID
  1096  						v.Value = float64(v.Value.(int64))
  1097  					}
  1098  					sg.MathExp.Val[k] = v
  1099  				}
  1100  			}
  1101  
  1102  			it.Vals = sg.MathExp.Val
  1103  			// The path of math node is the path of max var node used in it.
  1104  			it.path = path
  1105  			doneVars[sg.Params.Var] = it
  1106  			sg.Params.uidToVal = sg.MathExp.Val
  1107  		} else if sg.MathExp.Const.Value != nil {
  1108  			// Assign the const for all the srcUids.
  1109  			mp := make(map[uint64]types.Val)
  1110  			rangeOver := sg.SrcUIDs
  1111  			if parent == nil {
  1112  				rangeOver = sg.DestUIDs
  1113  			}
  1114  			if rangeOver == nil {
  1115  				it := doneVars[sg.Params.Var]
  1116  				it.Vals = mp
  1117  				doneVars[sg.Params.Var] = it
  1118  				return nil
  1119  			}
  1120  			for _, uid := range rangeOver.Uids {
  1121  				mp[uid] = sg.MathExp.Const
  1122  			}
  1123  			it := doneVars[sg.Params.Var]
  1124  			it.Vals = mp
  1125  			doneVars[sg.Params.Var] = it
  1126  			sg.Params.uidToVal = mp
  1127  		} else {
  1128  			glog.V(3).Info("Warning: Math expression is using unassigned values or constants")
  1129  		}
  1130  		// Put it in this node.
  1131  	} else if len(sg.Params.NeedsVar) > 0 {
  1132  		// This is a var() block.
  1133  		srcVar := sg.Params.NeedsVar[0]
  1134  		srcMap := doneVars[srcVar.Name]
  1135  		// The value var can be empty. No need to check for nil.
  1136  		sg.Params.uidToVal = srcMap.Vals
  1137  	} else {
  1138  		return errors.Errorf("Unhandled pb.node %v with parent %v", sg.Attr, parent.Attr)
  1139  	}
  1140  
  1141  	return nil
  1142  }
  1143  
  1144  func (sg *SubGraph) populatePostAggregation(doneVars map[string]varValue, path []*SubGraph,
  1145  	parent *SubGraph) error {
  1146  	for idx := 0; idx < len(sg.Children); idx++ {
  1147  		child := sg.Children[idx]
  1148  		path = append(path, sg)
  1149  		err := child.populatePostAggregation(doneVars, path, sg)
  1150  		path = path[:len(path)-1]
  1151  		if err != nil {
  1152  			return err
  1153  		}
  1154  	}
  1155  	return sg.valueVarAggregation(doneVars, path, parent)
  1156  }
  1157  
  1158  // Filters might have updated the destuids. facetMatrix should also be updated to exclude uids that
  1159  // were removed..
  1160  func (sg *SubGraph) updateFacetMatrix() {
  1161  	if len(sg.facetsMatrix) != len(sg.uidMatrix) {
  1162  		return
  1163  	}
  1164  
  1165  	for lidx, l := range sg.uidMatrix {
  1166  		out := sg.facetsMatrix[lidx].FacetsList[:0]
  1167  		for idx, uid := range l.Uids {
  1168  			// If uid wasn't filtered then we keep the facet for it.
  1169  			if algo.IndexOf(sg.DestUIDs, uid) >= 0 {
  1170  				out = append(out, sg.facetsMatrix[lidx].FacetsList[idx])
  1171  			}
  1172  		}
  1173  		sg.facetsMatrix[lidx].FacetsList = out
  1174  	}
  1175  }
  1176  
  1177  // updateUidMatrix is used to filter out the uids in uidMatrix which are not part of DestUIDs
  1178  // anymore. Some uids might have been removed from DestUids after application of filters,
  1179  // we remove them from the uidMatrix as well.
  1180  // If the query didn't specify sorting, we can just intersect the DestUids with lists in the
  1181  // uidMatrix since they are both sorted. Otherwise we must filter out the uids within the
  1182  // lists in uidMatrix which are not in DestUIDs.
  1183  func (sg *SubGraph) updateUidMatrix() {
  1184  	sg.updateFacetMatrix()
  1185  	for _, l := range sg.uidMatrix {
  1186  		if len(sg.Params.Order) > 0 || len(sg.Params.FacetOrder) > 0 {
  1187  			// We can't do intersection directly as the list is not sorted by UIDs.
  1188  			// So do filter.
  1189  			algo.ApplyFilter(l, func(uid uint64, idx int) bool {
  1190  				return algo.IndexOf(sg.DestUIDs, uid) >= 0 // Binary search.
  1191  			})
  1192  		} else {
  1193  			// If we didn't order on UIDmatrix, it'll be sorted.
  1194  			algo.IntersectWith(l, sg.DestUIDs, l)
  1195  		}
  1196  	}
  1197  }
  1198  
  1199  // populateVarMap stores the value of the variable defined in this SubGraph into req.Vars so that it
  1200  // is available to other queries as well. It is called after a query has been executed.
  1201  // TODO (pawan) - This function also transforms the DestUids and uidMatrix if the query is a cascade
  1202  // query which should probably happen before.
  1203  func (sg *SubGraph) populateVarMap(doneVars map[string]varValue, sgPath []*SubGraph) error {
  1204  	if sg.DestUIDs == nil || sg.IsGroupBy() {
  1205  		return nil
  1206  	}
  1207  	out := make([]uint64, 0, len(sg.DestUIDs.Uids))
  1208  	if sg.Params.Alias == "shortest" {
  1209  		goto AssignStep
  1210  	}
  1211  
  1212  	if len(sg.Filters) > 0 {
  1213  		sg.updateUidMatrix()
  1214  	}
  1215  
  1216  	for _, child := range sg.Children {
  1217  		sgPath = append(sgPath, sg) // Add the current node to path
  1218  		if err := child.populateVarMap(doneVars, sgPath); err != nil {
  1219  			return err
  1220  		}
  1221  		sgPath = sgPath[:len(sgPath)-1] // Backtrack
  1222  		if !sg.Params.Cascade {
  1223  			continue
  1224  		}
  1225  
  1226  		// Intersect the UidMatrix with the DestUids as some UIDs might have been removed
  1227  		// by other operations. So we need to apply it on the UidMatrix.
  1228  		child.updateUidMatrix()
  1229  	}
  1230  
  1231  	if !sg.Params.Cascade {
  1232  		goto AssignStep
  1233  	}
  1234  
  1235  	// Filter out UIDs that don't have atleast one UID in every child.
  1236  	for i, uid := range sg.DestUIDs.Uids {
  1237  		var exclude bool
  1238  		for _, child := range sg.Children {
  1239  			// For uid we dont actually populate the uidMatrix or values. So a node asking for
  1240  			// uid would always be excluded. Therefore we skip it.
  1241  			if child.Attr == "uid" {
  1242  				continue
  1243  			}
  1244  
  1245  			// If the length of child UID list is zero and it has no valid value, then the
  1246  			// current UID should be removed from this level.
  1247  			if !child.IsInternal() &&
  1248  				// Check len before accessing index.
  1249  				(len(child.valueMatrix) <= i || len(child.valueMatrix[i].Values) == 0) &&
  1250  				(len(child.counts) <= i) &&
  1251  				(len(child.uidMatrix) <= i || len(child.uidMatrix[i].Uids) == 0) {
  1252  				exclude = true
  1253  				break
  1254  			}
  1255  		}
  1256  		if !exclude {
  1257  			out = append(out, uid)
  1258  		}
  1259  	}
  1260  	// Note the we can't overwrite DestUids, as it'd also modify the SrcUids of
  1261  	// next level and the mapping from SrcUids to uidMatrix would be lost.
  1262  	sg.DestUIDs = &pb.List{Uids: out}
  1263  
  1264  AssignStep:
  1265  	return sg.updateVars(doneVars, sgPath)
  1266  }
  1267  
  1268  // updateVars is used to update the doneVars map with the value of the variable from the SubGraph.
  1269  // The variable could be a uid or a value variable.
  1270  // It is called twice
  1271  // 1. To populate sg.Params.ParentVars map with the value of a variable to pass down to children
  1272  // subgraphs in a query.
  1273  // 2. To populate req.Vars, which is used by other queries requiring variables..
  1274  func (sg *SubGraph) updateVars(doneVars map[string]varValue, sgPath []*SubGraph) error {
  1275  	// NOTE: although we initialize doneVars (req.Vars) in ProcessQuery, this nil check is for
  1276  	// non-root lookups that happen to other nodes. Don't use len(doneVars) == 0 !
  1277  	if doneVars == nil || (sg.Params.Var == "" && sg.Params.FacetVar == nil) {
  1278  		return nil
  1279  	}
  1280  
  1281  	sgPathCopy := append(sgPath[:0:0], sgPath...)
  1282  	if err := sg.populateUidValVar(doneVars, sgPathCopy); err != nil {
  1283  		return err
  1284  	}
  1285  	return sg.populateFacetVars(doneVars, sgPathCopy)
  1286  }
  1287  
  1288  // populateUidValVar populates the value of the variable into doneVars.
  1289  func (sg *SubGraph) populateUidValVar(doneVars map[string]varValue, sgPath []*SubGraph) error {
  1290  	if sg.Params.Var == "" {
  1291  		return nil
  1292  	}
  1293  
  1294  	var v varValue
  1295  	var ok bool
  1296  	// 1. When count of a predicate is assigned a variable, we store the mapping of uid =>
  1297  	// count(predicate).
  1298  	if len(sg.counts) > 0 {
  1299  		// This implies it is a value variable.
  1300  		doneVars[sg.Params.Var] = varValue{
  1301  			Vals:    make(map[uint64]types.Val),
  1302  			path:    sgPath,
  1303  			strList: sg.valueMatrix,
  1304  		}
  1305  		for idx, uid := range sg.SrcUIDs.Uids {
  1306  			val := types.Val{
  1307  				Tid:   types.IntID,
  1308  				Value: int64(sg.counts[idx]),
  1309  			}
  1310  			doneVars[sg.Params.Var].Vals[uid] = val
  1311  		}
  1312  	} else if sg.Params.uidCount {
  1313  		// 2. This is the case where count(uid) is requested in the query and stored as variable.
  1314  		// In this case there is just one value which is stored corresponding to the uid
  1315  		// math.MaxUint64 which isn't entirely correct as there could be an actual uid with that
  1316  		// value.
  1317  		doneVars[sg.Params.Var] = varValue{
  1318  			Vals:    make(map[uint64]types.Val),
  1319  			path:    sgPath,
  1320  			strList: sg.valueMatrix,
  1321  		}
  1322  
  1323  		val := types.Val{
  1324  			Tid:   types.IntID,
  1325  			Value: int64(len(sg.DestUIDs.Uids)),
  1326  		}
  1327  		doneVars[sg.Params.Var].Vals[math.MaxUint64] = val
  1328  	} else if len(sg.DestUIDs.Uids) != 0 || (sg.Attr == "uid" && sg.SrcUIDs != nil) {
  1329  		// 3. A uid variable. The variable could be defined in one of two places.
  1330  		// a) Either on the actual predicate.
  1331  		//    me(func: (...)) {
  1332  		//      a as friend
  1333  		//    }
  1334  		//
  1335  		// b) Or on the uid edge
  1336  		//    me(func:(...)) {
  1337  		//      friend {
  1338  		//        a as uid
  1339  		//      }
  1340  		//    }
  1341  
  1342  		// Uid variable could be defined using uid or a predicate.
  1343  		uids := sg.DestUIDs
  1344  		if sg.Attr == "uid" {
  1345  			uids = sg.SrcUIDs
  1346  		}
  1347  
  1348  		if v, ok = doneVars[sg.Params.Var]; !ok {
  1349  			doneVars[sg.Params.Var] = varValue{
  1350  				Uids:    uids,
  1351  				path:    sgPath,
  1352  				Vals:    make(map[uint64]types.Val),
  1353  				strList: sg.valueMatrix,
  1354  			}
  1355  			return nil
  1356  		}
  1357  
  1358  		// For a recurse query this can happen. We don't allow using the same variable more than
  1359  		// once otherwise.
  1360  		lists := append([]*pb.List(nil), v.Uids, uids)
  1361  		v.Uids = algo.MergeSorted(lists)
  1362  		doneVars[sg.Params.Var] = v
  1363  	} else if len(sg.valueMatrix) != 0 && sg.SrcUIDs != nil && len(sgPath) != 0 {
  1364  		// 4. A value variable. We get the first value from every list thats part of ValueMatrix
  1365  		// and store it corresponding to a uid in SrcUIDs.
  1366  		if v, ok = doneVars[sg.Params.Var]; !ok {
  1367  			v.Vals = make(map[uint64]types.Val)
  1368  			v.path = sgPath
  1369  			v.strList = sg.valueMatrix
  1370  		}
  1371  
  1372  		for idx, uid := range sg.SrcUIDs.Uids {
  1373  			if len(sg.valueMatrix[idx].Values) > 1 {
  1374  				return errors.Errorf("Value variables not supported for predicate with list type.")
  1375  			}
  1376  
  1377  			if len(sg.valueMatrix[idx].Values) == 0 {
  1378  				continue
  1379  			}
  1380  			val, err := convertWithBestEffort(sg.valueMatrix[idx].Values[0], sg.Attr)
  1381  			if err != nil {
  1382  				continue
  1383  			}
  1384  			v.Vals[uid] = val
  1385  		}
  1386  		doneVars[sg.Params.Var] = v
  1387  	} else {
  1388  		// If the variable already existed and now we see it again without any DestUIDs or
  1389  		// ValueMatrix then lets just return.
  1390  		if _, ok := doneVars[sg.Params.Var]; ok {
  1391  			return nil
  1392  		}
  1393  		// Insert a empty entry to keep the dependency happy.
  1394  		doneVars[sg.Params.Var] = varValue{
  1395  			path:    sgPath,
  1396  			Vals:    make(map[uint64]types.Val),
  1397  			strList: sg.valueMatrix,
  1398  		}
  1399  	}
  1400  	return nil
  1401  }
  1402  
  1403  // populateFacetVars walks the facetsMatrix to compute the value of a facet variable.
  1404  // It sums up the value for float/int type facets so that there is only variable corresponding
  1405  // to each uid in the uidMatrix.
  1406  func (sg *SubGraph) populateFacetVars(doneVars map[string]varValue, sgPath []*SubGraph) error {
  1407  	if len(sg.Params.FacetVar) == 0 || sg.Params.Facet == nil {
  1408  		return nil
  1409  	}
  1410  
  1411  	sgPath = append(sgPath, sg)
  1412  	for _, it := range sg.Params.Facet.Param {
  1413  		fvar, ok := sg.Params.FacetVar[it.Key]
  1414  		if !ok {
  1415  			continue
  1416  		}
  1417  		// Assign an empty value for every facet that was assigned to a variable and hence is part
  1418  		// of FacetVar.
  1419  		doneVars[fvar] = varValue{
  1420  			Vals: make(map[uint64]types.Val),
  1421  			path: sgPath,
  1422  		}
  1423  	}
  1424  
  1425  	if len(sg.facetsMatrix) == 0 {
  1426  		return nil
  1427  	}
  1428  
  1429  	// Note: We ignore the facets if its a value edge as we can't
  1430  	// attach the value to any node.
  1431  	for i, uids := range sg.uidMatrix {
  1432  		for j, uid := range uids.Uids {
  1433  			facet := sg.facetsMatrix[i].FacetsList[j]
  1434  			for _, f := range facet.Facets {
  1435  				fvar, ok := sg.Params.FacetVar[f.Key]
  1436  				if !ok {
  1437  					continue
  1438  				}
  1439  				if pVal, ok := doneVars[fvar].Vals[uid]; !ok {
  1440  					fVal, err := facets.ValFor(f)
  1441  					if err != nil {
  1442  						return err
  1443  					}
  1444  
  1445  					doneVars[fvar].Vals[uid] = fVal
  1446  				} else {
  1447  					// If the value is int/float we add them up. Else we throw an error as
  1448  					// many to one maps are not allowed for other types.
  1449  					nVal, err := facets.ValFor(f)
  1450  					if err != nil {
  1451  						return err
  1452  					}
  1453  
  1454  					if nVal.Tid != types.IntID && nVal.Tid != types.FloatID {
  1455  						return errors.Errorf("Repeated id with non int/float value for " +
  1456  							"facet var encountered.")
  1457  					}
  1458  					ag := aggregator{name: "sum"}
  1459  					ag.Apply(pVal)
  1460  					ag.Apply(nVal)
  1461  					fVal, err := ag.Value()
  1462  					if err != nil {
  1463  						continue
  1464  					}
  1465  					doneVars[fvar].Vals[uid] = fVal
  1466  				}
  1467  			}
  1468  		}
  1469  	}
  1470  	return nil
  1471  }
  1472  
  1473  // recursiveFillVars fills the value of variables before a query is to be processed using the result
  1474  // of the values (doneVars) computed by other queries that were successfully run before this query.
  1475  func (sg *SubGraph) recursiveFillVars(doneVars map[string]varValue) error {
  1476  	err := sg.fillVars(doneVars)
  1477  	if err != nil {
  1478  		return err
  1479  	}
  1480  	for _, child := range sg.Children {
  1481  		err = child.recursiveFillVars(doneVars)
  1482  		if err != nil {
  1483  			return err
  1484  		}
  1485  	}
  1486  	for _, fchild := range sg.Filters {
  1487  		err = fchild.recursiveFillVars(doneVars)
  1488  		if err != nil {
  1489  			return err
  1490  		}
  1491  	}
  1492  	return nil
  1493  }
  1494  
  1495  // fillShortestPathVars reads value of the uid variable from mp map and fills it into From and To
  1496  // parameters.
  1497  func (sg *SubGraph) fillShortestPathVars(mp map[string]varValue) error {
  1498  	// The uidVar.Uids can be nil if the variable didn't return any uids. This would mean
  1499  	// sg.Params.From or sg.Params.To is 0 and the query would return an empty result.
  1500  	if sg.Params.ShortestPathArgs.From != nil && len(sg.Params.ShortestPathArgs.From.NeedsVar) > 0 {
  1501  		fromVar := sg.Params.ShortestPathArgs.From.NeedsVar[0].Name
  1502  		uidVar, ok := mp[fromVar]
  1503  		if !ok {
  1504  			return errors.Errorf("value of from var(%s) should have already been populated",
  1505  				fromVar)
  1506  		}
  1507  		if uidVar.Uids != nil {
  1508  			if len(uidVar.Uids.Uids) > 1 {
  1509  				return errors.Errorf("from variable(%s) should only expand to 1 uid", fromVar)
  1510  			}
  1511  			sg.Params.From = uidVar.Uids.Uids[0]
  1512  		}
  1513  	}
  1514  
  1515  	if sg.Params.ShortestPathArgs.To != nil && len(sg.Params.ShortestPathArgs.To.NeedsVar) > 0 {
  1516  		toVar := sg.Params.ShortestPathArgs.To.NeedsVar[0].Name
  1517  		uidVar, ok := mp[toVar]
  1518  		if !ok {
  1519  			return errors.Errorf("value of to var(%s) should have already been populated",
  1520  				toVar)
  1521  		}
  1522  		if uidVar.Uids != nil {
  1523  			if len(uidVar.Uids.Uids) > 1 {
  1524  				return errors.Errorf("to variable(%s) should only expand to 1 uid", toVar)
  1525  			}
  1526  			sg.Params.To = uidVar.Uids.Uids[0]
  1527  		}
  1528  	}
  1529  	return nil
  1530  }
  1531  
  1532  // fillVars reads the value corresponding to a variable from the map mp and stores it inside
  1533  // SubGraph. This value is then later used for execution of the SubGraph.
  1534  func (sg *SubGraph) fillVars(mp map[string]varValue) error {
  1535  	if sg.Params.Alias == "shortest" {
  1536  		if err := sg.fillShortestPathVars(mp); err != nil {
  1537  			return err
  1538  		}
  1539  	}
  1540  
  1541  	var lists []*pb.List
  1542  	// Go through all the variables in NeedsVar and see if we have a value for them in the map. If
  1543  	// we do, then we store that value in the appropriate variable inside SubGraph.
  1544  	for _, v := range sg.Params.NeedsVar {
  1545  		l, ok := mp[v.Name]
  1546  		if !ok {
  1547  			continue
  1548  		}
  1549  		switch {
  1550  		case (v.Typ == gql.AnyVar || v.Typ == gql.ListVar) && l.strList != nil:
  1551  			// This is for the case when we use expand(val(x)) with a value variable.
  1552  			// We populate the list of values into ExpandPreds and use that for the expand query
  1553  			// later.
  1554  			// TODO: If we support value vars for list type then this needn't be true
  1555  			sg.ExpandPreds = l.strList
  1556  
  1557  		case (v.Typ == gql.AnyVar || v.Typ == gql.UidVar) && l.Uids != nil:
  1558  			lists = append(lists, l.Uids)
  1559  
  1560  		case (v.Typ == gql.AnyVar || v.Typ == gql.ValueVar):
  1561  			// This should happen only once.
  1562  			// TODO: This allows only one value var per subgraph, change it later
  1563  			sg.Params.uidToVal = l.Vals
  1564  
  1565  		case (v.Typ == gql.AnyVar || v.Typ == gql.UidVar) && len(l.Vals) != 0:
  1566  			// Derive the UID list from value var.
  1567  			uids := make([]uint64, 0, len(l.Vals))
  1568  			for k := range l.Vals {
  1569  				uids = append(uids, k)
  1570  			}
  1571  			sort.Slice(uids, func(i, j int) bool { return uids[i] < uids[j] })
  1572  			lists = append(lists, &pb.List{Uids: uids})
  1573  
  1574  		case len(l.Vals) != 0 || l.Uids != nil:
  1575  			return errors.Errorf("Wrong variable type encountered for var(%v) %v.", v.Name, v.Typ)
  1576  
  1577  		default:
  1578  			glog.V(3).Infof("Warning: reached default case in fillVars for var: %v", v.Name)
  1579  		}
  1580  	}
  1581  	if err := sg.replaceVarInFunc(); err != nil {
  1582  		return err
  1583  	}
  1584  	lists = append(lists, sg.DestUIDs)
  1585  	sg.DestUIDs = algo.MergeSorted(lists)
  1586  	return nil
  1587  }
  1588  
  1589  // replaceVarInFunc gets values stored inside uidToVal(coming from a value variable defined in some
  1590  // other query) and adds them as arguments to the SrcFunc in SubGraph.
  1591  // E.g. - func: eq(score, val(myscore))
  1592  // NOTE - We disallow vars in facets filter so we don't need to worry about that as of now.
  1593  func (sg *SubGraph) replaceVarInFunc() error {
  1594  	if sg.SrcFunc == nil {
  1595  		return nil
  1596  	}
  1597  	var args []gql.Arg
  1598  	// Iterate over the args and replace value args with their values
  1599  	for _, arg := range sg.SrcFunc.Args {
  1600  		if !arg.IsValueVar {
  1601  			args = append(args, arg)
  1602  			continue
  1603  		}
  1604  		if len(sg.Params.uidToVal) == 0 {
  1605  			// This means that the variable didn't have any values and hence there is nothing to add
  1606  			// to args.
  1607  			break
  1608  		}
  1609  		// We don't care about uids, just take all the values and put as args.
  1610  		// There would be only one value var per subgraph as per current assumptions.
  1611  		seenArgs := make(map[string]struct{})
  1612  		for _, v := range sg.Params.uidToVal {
  1613  			data := types.ValueForType(types.StringID)
  1614  			if err := types.Marshal(v, &data); err != nil {
  1615  				return err
  1616  			}
  1617  			val := data.Value.(string)
  1618  			if _, ok := seenArgs[val]; ok {
  1619  				continue
  1620  			}
  1621  			seenArgs[val] = struct{}{}
  1622  			args = append(args, gql.Arg{Value: val})
  1623  		}
  1624  	}
  1625  	sg.SrcFunc.Args = args
  1626  	return nil
  1627  }
  1628  
  1629  // Used to evaluate an inequality function which uses a value variable instead of a predicate.
  1630  // E.g.
  1631  // 1. func: eq(val(x), 35) or @filter(eq(val(x), 35)
  1632  // 2. func: ge(val(x), 40) or @filter(ge(val(x), 40)
  1633  // ... other inequality functions
  1634  // The function filters uids corresponding to the variable which satisfy the inequality and stores
  1635  // the filtered uids in DestUIDs.
  1636  func (sg *SubGraph) applyIneqFunc() error {
  1637  	if len(sg.Params.uidToVal) == 0 {
  1638  		// Expected a valid value map. But got empty.
  1639  		// Don't return error, return empty - issue #2610
  1640  		return nil
  1641  	}
  1642  
  1643  	// A mapping of uid to their value should have already been stored in uidToVal.
  1644  	// Find out the type of value using the first value in the map and try to convert the function
  1645  	// argument to that type to make sure we can compare them. If we can't return an error.
  1646  	var typ types.TypeID
  1647  	for _, v := range sg.Params.uidToVal {
  1648  		typ = v.Tid
  1649  		break
  1650  	}
  1651  	val := sg.SrcFunc.Args[0].Value
  1652  	src := types.Val{Tid: types.StringID, Value: []byte(val)}
  1653  	dst, err := types.Convert(src, typ)
  1654  	if err != nil {
  1655  		return errors.Errorf("Invalid argment %v. Comparing with different type", val)
  1656  	}
  1657  
  1658  	if sg.SrcUIDs != nil {
  1659  		// This means its a filter.
  1660  		for _, uid := range sg.SrcUIDs.Uids {
  1661  			curVal, ok := sg.Params.uidToVal[uid]
  1662  			if ok && types.CompareVals(sg.SrcFunc.Name, curVal, dst) {
  1663  				sg.DestUIDs.Uids = append(sg.DestUIDs.Uids, uid)
  1664  			}
  1665  		}
  1666  	} else {
  1667  		// This means it's a function at root as SrcUIDs is nil
  1668  		for uid, curVal := range sg.Params.uidToVal {
  1669  			if types.CompareVals(sg.SrcFunc.Name, curVal, dst) {
  1670  				sg.DestUIDs.Uids = append(sg.DestUIDs.Uids, uid)
  1671  			}
  1672  		}
  1673  		sort.Slice(sg.DestUIDs.Uids, func(i, j int) bool {
  1674  			return sg.DestUIDs.Uids[i] < sg.DestUIDs.Uids[j]
  1675  		})
  1676  		sg.uidMatrix = []*pb.List{sg.DestUIDs}
  1677  	}
  1678  	return nil
  1679  }
  1680  
  1681  func (sg *SubGraph) appendDummyValues() {
  1682  	if sg.SrcUIDs == nil || len(sg.SrcUIDs.Uids) == 0 {
  1683  		return
  1684  	}
  1685  	var l pb.List
  1686  	var val pb.ValueList
  1687  	for range sg.SrcUIDs.Uids {
  1688  		// This is necessary so that preTraverse can be processed smoothly.
  1689  		sg.uidMatrix = append(sg.uidMatrix, &l)
  1690  		sg.valueMatrix = append(sg.valueMatrix, &val)
  1691  	}
  1692  }
  1693  
  1694  func getPredsFromVals(vl []*pb.ValueList) []string {
  1695  	preds := make([]string, 0)
  1696  	for _, l := range vl {
  1697  		for _, v := range l.Values {
  1698  			if len(v.Val) > 0 {
  1699  				preds = append(preds, string(v.Val))
  1700  			}
  1701  		}
  1702  	}
  1703  	return preds
  1704  }
  1705  
  1706  func uniquePreds(list []string) []string {
  1707  	predMap := make(map[string]struct{})
  1708  	for _, item := range list {
  1709  		predMap[item] = struct{}{}
  1710  	}
  1711  
  1712  	preds := make([]string, 0, len(predMap))
  1713  	for pred := range predMap {
  1714  		preds = append(preds, pred)
  1715  	}
  1716  	return preds
  1717  }
  1718  
  1719  func recursiveCopy(dst *SubGraph, src *SubGraph) {
  1720  	dst.Attr = src.Attr
  1721  	dst.Params = src.Params
  1722  	dst.Params.ParentVars = make(map[string]varValue)
  1723  	for k, v := range src.Params.ParentVars {
  1724  		dst.Params.ParentVars[k] = v
  1725  	}
  1726  
  1727  	dst.copyFiltersRecurse(src)
  1728  	dst.ReadTs = src.ReadTs
  1729  
  1730  	for _, c := range src.Children {
  1731  		copyChild := new(SubGraph)
  1732  		recursiveCopy(copyChild, c)
  1733  		dst.Children = append(dst.Children, copyChild)
  1734  	}
  1735  }
  1736  
  1737  func expandSubgraph(ctx context.Context, sg *SubGraph) ([]*SubGraph, error) {
  1738  	span := otrace.FromContext(ctx)
  1739  	stop := x.SpanTimer(span, "expandSubgraph: "+sg.Attr)
  1740  	defer stop()
  1741  
  1742  	out := make([]*SubGraph, 0, len(sg.Children))
  1743  	for i := 0; i < len(sg.Children); i++ {
  1744  		child := sg.Children[i]
  1745  
  1746  		if child.Params.Expand == "" {
  1747  			out = append(out, child)
  1748  			continue
  1749  		}
  1750  
  1751  		var preds []string
  1752  		types, err := getNodeTypes(ctx, sg)
  1753  		if err != nil {
  1754  			return out, err
  1755  		}
  1756  
  1757  		switch child.Params.Expand {
  1758  		// It could be expand(_all_), expand(_forward_), expand(_reverse_) or expand(val(x)).
  1759  		case "_all_":
  1760  			span.Annotate(nil, "expand(_all_)")
  1761  			if len(types) == 0 {
  1762  				break
  1763  			}
  1764  
  1765  			preds = getPredicatesFromTypes(types)
  1766  			rpreds, err := getReversePredicates(ctx, preds)
  1767  			if err != nil {
  1768  				return out, err
  1769  			}
  1770  			preds = append(preds, rpreds...)
  1771  		case "_forward_":
  1772  			span.Annotate(nil, "expand(_forward_)")
  1773  			if len(types) == 0 {
  1774  				break
  1775  			}
  1776  
  1777  			preds = getPredicatesFromTypes(types)
  1778  		case "_reverse_":
  1779  			span.Annotate(nil, "expand(_reverse_)")
  1780  			if len(types) == 0 {
  1781  				break
  1782  			}
  1783  
  1784  			typePreds := getPredicatesFromTypes(types)
  1785  			rpreds, err := getReversePredicates(ctx, typePreds)
  1786  			if err != nil {
  1787  				return out, err
  1788  			}
  1789  			preds = append(preds, rpreds...)
  1790  		default:
  1791  			span.Annotate(nil, "expand default")
  1792  			// We already have the predicates populated from the var.
  1793  			preds = getPredsFromVals(child.ExpandPreds)
  1794  		}
  1795  		preds = uniquePreds(preds)
  1796  
  1797  		for _, pred := range preds {
  1798  			temp := &SubGraph{
  1799  				ReadTs: sg.ReadTs,
  1800  				Attr:   pred,
  1801  			}
  1802  			temp.Params = child.Params
  1803  			temp.Params.expandAll = child.Params.Expand == "_all_"
  1804  			temp.Params.ParentVars = make(map[string]varValue)
  1805  			for k, v := range child.Params.ParentVars {
  1806  				temp.Params.ParentVars[k] = v
  1807  			}
  1808  			temp.Params.isInternal = false
  1809  			temp.Params.Expand = ""
  1810  			temp.Params.Facet = &pb.FacetParams{AllKeys: true}
  1811  
  1812  			// Go through each child, create a copy and attach to temp.Children.
  1813  			for _, cc := range child.Children {
  1814  				s := &SubGraph{}
  1815  				recursiveCopy(s, cc)
  1816  				temp.Children = append(temp.Children, s)
  1817  			}
  1818  
  1819  			for _, ch := range sg.Children {
  1820  				if ch.isSimilar(temp) {
  1821  					return out, errors.Errorf("Repeated subgraph: [%s] while using expand()",
  1822  						ch.Attr)
  1823  				}
  1824  			}
  1825  			out = append(out, temp)
  1826  		}
  1827  	}
  1828  	return out, nil
  1829  }
  1830  
  1831  // ProcessGraph processes the SubGraph instance accumulating result for the query
  1832  // from different instances. Note: taskQuery is nil for root node.
  1833  func ProcessGraph(ctx context.Context, sg, parent *SubGraph, rch chan error) {
  1834  	var suffix string
  1835  	if len(sg.Params.Alias) > 0 {
  1836  		suffix += "." + sg.Params.Alias
  1837  	}
  1838  	if len(sg.Attr) > 0 {
  1839  		suffix += "." + sg.Attr
  1840  	}
  1841  	span := otrace.FromContext(ctx)
  1842  	stop := x.SpanTimer(span, "query.ProcessGraph"+suffix)
  1843  	defer stop()
  1844  
  1845  	if sg.Attr == "uid" {
  1846  		// We dont need to call ProcessGraph for uid, as we already have uids
  1847  		// populated from parent and there is nothing to process but uidMatrix
  1848  		// and values need to have the right sizes so that preTraverse works.
  1849  		sg.appendDummyValues()
  1850  		rch <- nil
  1851  		return
  1852  	}
  1853  	var err error
  1854  	if parent == nil && sg.SrcFunc != nil && sg.SrcFunc.Name == "uid" {
  1855  		// I'm root and I'm using some variable that has been populated.
  1856  		// Retain the actual order in uidMatrix. But sort the destUids.
  1857  		if sg.SrcUIDs != nil && len(sg.SrcUIDs.Uids) != 0 {
  1858  			// I am root. I don't have any function to execute, and my
  1859  			// result has been prepared for me already by list passed by the user.
  1860  			// uidmatrix retains the order. SrcUids are sorted (in newGraph).
  1861  			sg.DestUIDs = sg.SrcUIDs
  1862  		} else {
  1863  			// Populated variable.
  1864  			o := append(sg.DestUIDs.Uids[:0:0], sg.DestUIDs.Uids...)
  1865  			sg.uidMatrix = []*pb.List{{Uids: o}}
  1866  			sort.Slice(sg.DestUIDs.Uids, func(i, j int) bool {
  1867  				return sg.DestUIDs.Uids[i] < sg.DestUIDs.Uids[j]
  1868  			})
  1869  		}
  1870  	} else if len(sg.Attr) == 0 {
  1871  		// This is when we have uid function in children.
  1872  		if sg.SrcFunc != nil && sg.SrcFunc.Name == "uid" {
  1873  			// If its a uid() filter, we just have to intersect the SrcUIDs with DestUIDs
  1874  			// and return.
  1875  			if err := sg.fillVars(sg.Params.ParentVars); err != nil {
  1876  				rch <- err
  1877  				return
  1878  			}
  1879  			algo.IntersectWith(sg.DestUIDs, sg.SrcUIDs, sg.DestUIDs)
  1880  			rch <- nil
  1881  			return
  1882  		}
  1883  
  1884  		if sg.SrcUIDs == nil {
  1885  			glog.Errorf("SrcUIDs is unexpectedly nil. Subgraph: %+v", sg)
  1886  			rch <- errors.Errorf("SrcUIDs shouldn't be nil.")
  1887  			return
  1888  		}
  1889  		// If we have a filter SubGraph which only contains an operator,
  1890  		// it won't have any attribute to work on.
  1891  		// This is to allow providing SrcUIDs to the filter children.
  1892  		// Each filter use it's own (shallow) copy of SrcUIDs, so there is no race conditions,
  1893  		// when multiple filters replace their sg.DestUIDs
  1894  		sg.DestUIDs = &pb.List{Uids: sg.SrcUIDs.Uids}
  1895  	} else {
  1896  		isInequalityFn := sg.SrcFunc != nil && isInequalityFn(sg.SrcFunc.Name)
  1897  		if isInequalityFn && sg.SrcFunc.IsValueVar {
  1898  			// This is a ineq function which uses a value variable.
  1899  			err = sg.applyIneqFunc()
  1900  			if parent != nil {
  1901  				rch <- err
  1902  				return
  1903  			}
  1904  		} else if isInequalityFn && sg.SrcFunc.IsLenVar {
  1905  			// Safe to access 0th element here because if no variable was given, parser would throw
  1906  			// an error.
  1907  			val := sg.SrcFunc.Args[0].Value
  1908  			src := types.Val{Tid: types.StringID, Value: []byte(val)}
  1909  			dst, err := types.Convert(src, types.IntID)
  1910  			if err != nil {
  1911  				// TODO(Aman): needs to do parent check?
  1912  				rch <- errors.Wrapf(err, "invalid argument %v. Comparing with different type", val)
  1913  				return
  1914  			}
  1915  
  1916  			curVal := types.Val{Tid: types.IntID, Value: int64(len(sg.DestUIDs.Uids))}
  1917  			if types.CompareVals(sg.SrcFunc.Name, curVal, dst) {
  1918  				sg.DestUIDs.Uids = sg.SrcUIDs.Uids
  1919  			} else {
  1920  				sg.DestUIDs.Uids = nil
  1921  			}
  1922  		} else {
  1923  			taskQuery, err := createTaskQuery(sg)
  1924  			if err != nil {
  1925  				rch <- err
  1926  				return
  1927  			}
  1928  			result, err := worker.ProcessTaskOverNetwork(ctx, taskQuery)
  1929  			if err != nil && strings.Contains(err.Error(), worker.ErrNonExistentTabletMessage) {
  1930  				sg.UnknownAttr = true
  1931  			} else if err != nil {
  1932  				rch <- err
  1933  				return
  1934  			}
  1935  
  1936  			sg.uidMatrix = result.UidMatrix
  1937  			sg.valueMatrix = result.ValueMatrix
  1938  			sg.facetsMatrix = result.FacetMatrix
  1939  			sg.counts = result.Counts
  1940  			sg.LangTags = result.LangMatrix
  1941  			sg.List = result.List
  1942  
  1943  			if sg.Params.DoCount {
  1944  				if len(sg.Filters) == 0 {
  1945  					// If there is a filter, we need to do more work to get the actual count.
  1946  					rch <- nil
  1947  					return
  1948  				}
  1949  				sg.counts = make([]uint32, len(sg.uidMatrix))
  1950  			}
  1951  
  1952  			if result.IntersectDest {
  1953  				sg.DestUIDs = algo.IntersectSorted(result.UidMatrix)
  1954  			} else {
  1955  				sg.DestUIDs = algo.MergeSorted(result.UidMatrix)
  1956  			}
  1957  
  1958  			if parent == nil {
  1959  				// I'm root. We reach here if root had a function.
  1960  				sg.uidMatrix = []*pb.List{sg.DestUIDs}
  1961  			}
  1962  		}
  1963  	}
  1964  
  1965  	// Run filters if any.
  1966  	if len(sg.Filters) > 0 {
  1967  		// Run all filters in parallel.
  1968  		filterChan := make(chan error, len(sg.Filters))
  1969  		for _, filter := range sg.Filters {
  1970  			isUidFuncWithoutVar := filter.SrcFunc != nil && filter.SrcFunc.Name == "uid" &&
  1971  				len(filter.Params.NeedsVar) == 0
  1972  			// For uid function filter, no need for processing. User already gave us the
  1973  			// list. Lets just update DestUIDs.
  1974  			if isUidFuncWithoutVar {
  1975  				filter.DestUIDs = filter.SrcUIDs
  1976  				filterChan <- nil
  1977  				continue
  1978  			}
  1979  
  1980  			filter.SrcUIDs = sg.DestUIDs
  1981  			// Passing the pointer is okay since the filter only reads.
  1982  			filter.Params.ParentVars = sg.Params.ParentVars // Pass to the child.
  1983  			go ProcessGraph(ctx, filter, sg, filterChan)
  1984  		}
  1985  
  1986  		var filterErr error
  1987  		for range sg.Filters {
  1988  			if err = <-filterChan; err != nil {
  1989  				// Store error in a variable and wait for all filters to run
  1990  				// before returning. Else tracing causes crashes.
  1991  				filterErr = err
  1992  			}
  1993  		}
  1994  
  1995  		if filterErr != nil {
  1996  			rch <- filterErr
  1997  			return
  1998  		}
  1999  
  2000  		// Now apply the results from filter.
  2001  		var lists []*pb.List
  2002  		for _, filter := range sg.Filters {
  2003  			lists = append(lists, filter.DestUIDs)
  2004  		}
  2005  		if sg.FilterOp == "or" {
  2006  			sg.DestUIDs = algo.MergeSorted(lists)
  2007  		} else if sg.FilterOp == "not" {
  2008  			x.AssertTrue(len(sg.Filters) == 1)
  2009  			sg.DestUIDs = algo.Difference(sg.DestUIDs, sg.Filters[0].DestUIDs)
  2010  		} else if sg.FilterOp == "and" {
  2011  			sg.DestUIDs = algo.IntersectSorted(lists)
  2012  		} else {
  2013  			// We need to also intersect the original dest uids in this case to get the final
  2014  			// DestUIDs.
  2015  			// me(func: eq(key, "key1")) @filter(eq(key, "key2"))
  2016  
  2017  			// TODO - See if the server performing the filter can intersect with the srcUIDs before
  2018  			// returning them in this case.
  2019  			lists = append(lists, sg.DestUIDs)
  2020  			sg.DestUIDs = algo.IntersectSorted(lists)
  2021  		}
  2022  	}
  2023  
  2024  	if len(sg.Params.Order) == 0 && len(sg.Params.FacetOrder) == 0 {
  2025  		// There is no ordering. Just apply pagination and return.
  2026  		if err = sg.applyPagination(ctx); err != nil {
  2027  			rch <- err
  2028  			return
  2029  		}
  2030  	} else {
  2031  		// If we are asked for count, we don't need to change the order of results.
  2032  		if !sg.Params.DoCount {
  2033  			// We need to sort first before pagination.
  2034  			if err = sg.applyOrderAndPagination(ctx); err != nil {
  2035  				rch <- err
  2036  				return
  2037  			}
  2038  		}
  2039  	}
  2040  
  2041  	// Here we consider handling count with filtering. We do this after
  2042  	// pagination because otherwise, we need to do the count with pagination
  2043  	// taken into account. For example, a PL might have only 50 entries but the
  2044  	// user wants to skip 100 entries and return 10 entries. In this case, you
  2045  	// should return a count of 0, not 10.
  2046  	// take care of the order
  2047  	if sg.Params.DoCount {
  2048  		x.AssertTrue(len(sg.Filters) > 0)
  2049  		sg.counts = make([]uint32, len(sg.uidMatrix))
  2050  		sg.updateUidMatrix()
  2051  		for i, ul := range sg.uidMatrix {
  2052  			// A possible optimization is to return the size of the intersection
  2053  			// without forming the intersection.
  2054  			sg.counts[i] = uint32(len(ul.Uids))
  2055  		}
  2056  		rch <- nil
  2057  		return
  2058  	}
  2059  
  2060  	if sg.Children, err = expandSubgraph(ctx, sg); err != nil {
  2061  		rch <- err
  2062  		return
  2063  	}
  2064  
  2065  	if sg.IsGroupBy() {
  2066  		// Add the attrs required by groupby nodes
  2067  		for _, it := range sg.Params.groupbyAttrs {
  2068  			// TODO - Throw error if Attr is of list type.
  2069  			sg.Children = append(sg.Children, &SubGraph{
  2070  				Attr:   it.Attr,
  2071  				ReadTs: sg.ReadTs,
  2072  				Params: params{
  2073  					Alias:        it.Alias,
  2074  					ignoreResult: true,
  2075  					Langs:        it.Langs,
  2076  				},
  2077  			})
  2078  		}
  2079  	}
  2080  
  2081  	if len(sg.Children) > 0 {
  2082  		// We store any variable defined by this node in the map and pass it on
  2083  		// to the children which might depend on it. We only need to do this if the SubGraph
  2084  		// has children.
  2085  		if err = sg.updateVars(sg.Params.ParentVars, []*SubGraph{}); err != nil {
  2086  			rch <- err
  2087  			return
  2088  		}
  2089  	}
  2090  
  2091  	childChan := make(chan error, len(sg.Children))
  2092  	for i := 0; i < len(sg.Children); i++ {
  2093  		child := sg.Children[i]
  2094  		child.Params.ParentVars = make(map[string]varValue)
  2095  		for k, v := range sg.Params.ParentVars {
  2096  			child.Params.ParentVars[k] = v
  2097  		}
  2098  
  2099  		child.SrcUIDs = sg.DestUIDs // Make the connection.
  2100  		if child.IsInternal() {
  2101  			// We dont have to execute these nodes.
  2102  			continue
  2103  		}
  2104  		go ProcessGraph(ctx, child, sg, childChan)
  2105  	}
  2106  
  2107  	var childErr error
  2108  	// Now get all the results back.
  2109  	for _, child := range sg.Children {
  2110  		if child.IsInternal() {
  2111  			continue
  2112  		}
  2113  		if err = <-childChan; err != nil {
  2114  			childErr = err
  2115  		}
  2116  	}
  2117  
  2118  	if sg.DestUIDs == nil || len(sg.DestUIDs.Uids) == 0 {
  2119  		// Looks like we're done here. Be careful with nil srcUIDs!
  2120  		if span != nil {
  2121  			span.Annotatef(nil, "Zero uids for %q", sg.Attr)
  2122  		}
  2123  		out := sg.Children[:0]
  2124  		for _, child := range sg.Children {
  2125  			if child.IsInternal() && child.Attr == "expand" {
  2126  				continue
  2127  			}
  2128  			out = append(out, child)
  2129  		}
  2130  		sg.Children = out // Remove any expand nodes we might have added.
  2131  		rch <- nil
  2132  		return
  2133  	}
  2134  
  2135  	rch <- childErr
  2136  }
  2137  
  2138  // applyPagination applies count and offset to lists inside uidMatrix.
  2139  func (sg *SubGraph) applyPagination(ctx context.Context) error {
  2140  	if sg.Params.Count == 0 && sg.Params.Offset == 0 { // No pagination.
  2141  		return nil
  2142  	}
  2143  
  2144  	sg.updateUidMatrix()
  2145  	for i := 0; i < len(sg.uidMatrix); i++ {
  2146  		// Apply the offsets.
  2147  		start, end := x.PageRange(sg.Params.Count, sg.Params.Offset, len(sg.uidMatrix[i].Uids))
  2148  		sg.uidMatrix[i].Uids = sg.uidMatrix[i].Uids[start:end]
  2149  	}
  2150  	// Re-merge the UID matrix.
  2151  	sg.DestUIDs = algo.MergeSorted(sg.uidMatrix)
  2152  	return nil
  2153  }
  2154  
  2155  // applyOrderAndPagination orders each posting list by a given attribute
  2156  // before applying pagination.
  2157  func (sg *SubGraph) applyOrderAndPagination(ctx context.Context) error {
  2158  	if len(sg.Params.Order) == 0 && len(sg.Params.FacetOrder) == 0 {
  2159  		return nil
  2160  	}
  2161  
  2162  	sg.updateUidMatrix()
  2163  
  2164  	// See if we need to apply order based on facet.
  2165  	if len(sg.Params.FacetOrder) != 0 {
  2166  		return sg.sortAndPaginateUsingFacet(ctx)
  2167  	}
  2168  
  2169  	for _, it := range sg.Params.NeedsVar {
  2170  		// TODO(pawan) - Return error if user uses var order with predicates.
  2171  		if len(sg.Params.Order) > 0 && it.Name == sg.Params.Order[0].Attr &&
  2172  			(it.Typ == gql.ValueVar) {
  2173  			// If the Order name is same as var name and it's a value variable, we sort using that variable.
  2174  			return sg.sortAndPaginateUsingVar(ctx)
  2175  		}
  2176  	}
  2177  
  2178  	if sg.Params.Count == 0 {
  2179  		// Only retrieve up to 1000 results by default.
  2180  		sg.Params.Count = 1000
  2181  	}
  2182  
  2183  	x.AssertTrue(len(sg.Params.Order) > 0)
  2184  
  2185  	sort := &pb.SortMessage{
  2186  		Order:     sg.Params.Order,
  2187  		UidMatrix: sg.uidMatrix,
  2188  		Offset:    int32(sg.Params.Offset),
  2189  		Count:     int32(sg.Params.Count),
  2190  		ReadTs:    sg.ReadTs,
  2191  	}
  2192  	result, err := worker.SortOverNetwork(ctx, sort)
  2193  	if err != nil {
  2194  		return err
  2195  	}
  2196  
  2197  	x.AssertTrue(len(result.UidMatrix) == len(sg.uidMatrix))
  2198  	if sg.facetsMatrix != nil {
  2199  		// The order of uids in the lists which are part of the uidMatrix would have been changed
  2200  		// after sort. We want to update the order of lists in the facetMatrix accordingly.
  2201  		for idx, rl := range result.UidMatrix {
  2202  			fl := make([]*pb.Facets, 0, len(sg.facetsMatrix[idx].FacetsList))
  2203  			for _, uid := range rl.Uids {
  2204  				// Find index of this uid in original sorted uid list.
  2205  				oidx := algo.IndexOf(sg.uidMatrix[idx], uid)
  2206  				// Find corresponding facet.
  2207  				fl = append(fl, sg.facetsMatrix[idx].FacetsList[oidx])
  2208  			}
  2209  			sg.facetsMatrix[idx].FacetsList = fl
  2210  		}
  2211  	}
  2212  
  2213  	sg.uidMatrix = result.UidMatrix
  2214  	// Update the destUids as we might have removed some UIDs for which we didn't find any values
  2215  	// while sorting.
  2216  	sg.updateDestUids()
  2217  	return nil
  2218  }
  2219  
  2220  func (sg *SubGraph) updateDestUids() {
  2221  	// Update sg.destUID. Iterate over the UID matrix (which is not sorted by
  2222  	// UID). For each element in UID matrix, we do a binary search in the
  2223  	// current destUID and mark it. Then we scan over this bool array and
  2224  	// rebuild destUIDs.
  2225  	included := make([]bool, len(sg.DestUIDs.Uids))
  2226  	for _, ul := range sg.uidMatrix {
  2227  		for _, uid := range ul.Uids {
  2228  			idx := algo.IndexOf(sg.DestUIDs, uid) // Binary search.
  2229  			if idx >= 0 {
  2230  				included[idx] = true
  2231  			}
  2232  		}
  2233  	}
  2234  	algo.ApplyFilter(sg.DestUIDs, func(uid uint64, idx int) bool { return included[idx] })
  2235  }
  2236  
  2237  func (sg *SubGraph) sortAndPaginateUsingFacet(ctx context.Context) error {
  2238  	if len(sg.facetsMatrix) == 0 {
  2239  		return nil
  2240  	}
  2241  	if len(sg.facetsMatrix) != len(sg.uidMatrix) {
  2242  		return errors.Errorf("Facet matrix and UID matrix mismatch: %d vs %d",
  2243  			len(sg.facetsMatrix), len(sg.uidMatrix))
  2244  	}
  2245  	orderby := sg.Params.FacetOrder
  2246  	for i := 0; i < len(sg.uidMatrix); i++ {
  2247  		ul := sg.uidMatrix[i]
  2248  		fl := sg.facetsMatrix[i]
  2249  		uids := ul.Uids[:0]
  2250  		values := make([][]types.Val, 0, len(ul.Uids))
  2251  		facetList := fl.FacetsList[:0]
  2252  		for j := 0; j < len(ul.Uids); j++ {
  2253  			var facet *api.Facet
  2254  			uid := ul.Uids[j]
  2255  			f := fl.FacetsList[j]
  2256  			uids = append(uids, uid)
  2257  			facetList = append(facetList, f)
  2258  			for _, it := range f.Facets {
  2259  				if it.Key == orderby {
  2260  					facet = it
  2261  					break
  2262  				}
  2263  			}
  2264  			if facet != nil {
  2265  				fVal, err := facets.ValFor(facet)
  2266  				if err != nil {
  2267  					return err
  2268  				}
  2269  
  2270  				values = append(values, []types.Val{fVal})
  2271  			} else {
  2272  				values = append(values, []types.Val{{Value: nil}})
  2273  			}
  2274  		}
  2275  		if len(values) == 0 {
  2276  			continue
  2277  		}
  2278  		if err := types.SortWithFacet(values, &pb.List{Uids: uids},
  2279  			facetList, []bool{sg.Params.FacetOrderDesc}); err != nil {
  2280  			return err
  2281  		}
  2282  		sg.uidMatrix[i].Uids = uids
  2283  		// We need to update the facetmarix corresponding to changes to uidmatrix.
  2284  		sg.facetsMatrix[i].FacetsList = facetList
  2285  	}
  2286  
  2287  	if sg.Params.Count != 0 || sg.Params.Offset != 0 {
  2288  		// Apply the pagination.
  2289  		for i := 0; i < len(sg.uidMatrix); i++ {
  2290  			start, end := x.PageRange(sg.Params.Count, sg.Params.Offset, len(sg.uidMatrix[i].Uids))
  2291  			sg.uidMatrix[i].Uids = sg.uidMatrix[i].Uids[start:end]
  2292  			// We also have to paginate the facetsMatrix for safety.
  2293  			sg.facetsMatrix[i].FacetsList = sg.facetsMatrix[i].FacetsList[start:end]
  2294  		}
  2295  	}
  2296  
  2297  	// Update the destUids as we might have removed some UIDs.
  2298  	sg.updateDestUids()
  2299  	return nil
  2300  }
  2301  
  2302  func (sg *SubGraph) sortAndPaginateUsingVar(ctx context.Context) error {
  2303  	// nil has a different meaning from an initialized map of zero length here. If the variable
  2304  	// didn't return any values then uidToVal would be an empty with zero length. If the variable
  2305  	// was used before definition, uidToVal would be nil.
  2306  	if sg.Params.uidToVal == nil {
  2307  		return errors.Errorf("Variable: [%s] used before definition.", sg.Params.Order[0].Attr)
  2308  	}
  2309  
  2310  	for i := 0; i < len(sg.uidMatrix); i++ {
  2311  		ul := sg.uidMatrix[i]
  2312  		uids := make([]uint64, 0, len(ul.Uids))
  2313  		values := make([][]types.Val, 0, len(ul.Uids))
  2314  		for _, uid := range ul.Uids {
  2315  			v, ok := sg.Params.uidToVal[uid]
  2316  			if !ok {
  2317  				// We skip the UIDs which don't have a value.
  2318  				continue
  2319  			}
  2320  			values = append(values, []types.Val{v})
  2321  			uids = append(uids, uid)
  2322  		}
  2323  		if len(values) == 0 {
  2324  			continue
  2325  		}
  2326  		if err := types.Sort(values, &pb.List{Uids: uids}, []bool{sg.Params.Order[0].Desc}); err != nil {
  2327  			return err
  2328  		}
  2329  		sg.uidMatrix[i].Uids = uids
  2330  	}
  2331  
  2332  	if sg.Params.Count != 0 || sg.Params.Offset != 0 {
  2333  		// Apply the pagination.
  2334  		for i := 0; i < len(sg.uidMatrix); i++ {
  2335  			start, end := x.PageRange(sg.Params.Count, sg.Params.Offset, len(sg.uidMatrix[i].Uids))
  2336  			sg.uidMatrix[i].Uids = sg.uidMatrix[i].Uids[start:end]
  2337  		}
  2338  	}
  2339  
  2340  	// Update the destUids as we might have removed some UIDs.
  2341  	sg.updateDestUids()
  2342  	return nil
  2343  }
  2344  
  2345  // isValidArg checks if arg passed is valid keyword.
  2346  func isValidArg(a string) bool {
  2347  	switch a {
  2348  	case "numpaths", "from", "to", "orderasc", "orderdesc", "first", "offset", "after", "depth",
  2349  		"minweight", "maxweight":
  2350  		return true
  2351  	}
  2352  	return false
  2353  }
  2354  
  2355  // isValidFuncName checks if fn passed is valid keyword.
  2356  func isValidFuncName(f string) bool {
  2357  	switch f {
  2358  	case "anyofterms", "allofterms", "val", "regexp", "anyoftext", "alloftext",
  2359  		"has", "uid", "uid_in", "anyof", "allof", "type", "match":
  2360  		return true
  2361  	}
  2362  	return isInequalityFn(f) || types.IsGeoFunc(f)
  2363  }
  2364  
  2365  func isInequalityFn(f string) bool {
  2366  	switch f {
  2367  	case "eq", "le", "ge", "gt", "lt":
  2368  		return true
  2369  	}
  2370  	return false
  2371  }
  2372  
  2373  func isAggregatorFn(f string) bool {
  2374  	switch f {
  2375  	case "min", "max", "sum", "avg":
  2376  		return true
  2377  	}
  2378  	return false
  2379  }
  2380  
  2381  func isUidFnWithoutVar(f *gql.Function) bool {
  2382  	return f != nil && f.Name == "uid" && len(f.NeedsVar) == 0
  2383  }
  2384  
  2385  func getNodeTypes(ctx context.Context, sg *SubGraph) ([]string, error) {
  2386  	temp := &SubGraph{
  2387  		Attr:    "dgraph.type",
  2388  		SrcUIDs: sg.DestUIDs,
  2389  		ReadTs:  sg.ReadTs,
  2390  	}
  2391  	taskQuery, err := createTaskQuery(temp)
  2392  	if err != nil {
  2393  		return nil, err
  2394  	}
  2395  	result, err := worker.ProcessTaskOverNetwork(ctx, taskQuery)
  2396  	if err != nil {
  2397  		return nil, err
  2398  	}
  2399  	return getPredsFromVals(result.ValueMatrix), nil
  2400  }
  2401  
  2402  // getPredicatesFromTypes returns the list of preds contained in the given types.
  2403  func getPredicatesFromTypes(types []string) []string {
  2404  	var preds []string
  2405  
  2406  	for _, typeName := range types {
  2407  		typeDef, ok := schema.State().GetType(typeName)
  2408  		if !ok {
  2409  			continue
  2410  		}
  2411  
  2412  		for _, field := range typeDef.Fields {
  2413  			preds = append(preds, field.Predicate)
  2414  		}
  2415  	}
  2416  	return preds
  2417  }
  2418  
  2419  // getReversePredicates queries the schema and returns a list of the reverse
  2420  // predicates that exist within the given preds.
  2421  func getReversePredicates(ctx context.Context, preds []string) ([]string, error) {
  2422  	var rpreds []string
  2423  	predMap := make(map[string]bool)
  2424  	for _, pred := range preds {
  2425  		predMap[pred] = true
  2426  	}
  2427  
  2428  	schs, err := worker.GetSchemaOverNetwork(ctx, &pb.SchemaRequest{Predicates: preds})
  2429  	if err != nil {
  2430  		return nil, err
  2431  	}
  2432  
  2433  	for _, sch := range schs {
  2434  		if _, ok := predMap[sch.Predicate]; !ok {
  2435  			continue
  2436  		}
  2437  		if !sch.Reverse {
  2438  			continue
  2439  		}
  2440  		rpreds = append(rpreds, "~"+sch.Predicate)
  2441  	}
  2442  	return rpreds, nil
  2443  }
  2444  
  2445  // GetAllPredicates returns the list of all the unique predicates present in the list of subgraphs.
  2446  func GetAllPredicates(subGraphs []*SubGraph) []string {
  2447  	predicatesMap := make(map[string]struct{})
  2448  	for _, sg := range subGraphs {
  2449  		sg.getAllPredicates(predicatesMap)
  2450  	}
  2451  	predicates := make([]string, 0, len(predicatesMap))
  2452  	for predicate := range predicatesMap {
  2453  		predicates = append(predicates, predicate)
  2454  	}
  2455  	return predicates
  2456  }
  2457  
  2458  func (sg *SubGraph) getAllPredicates(predicates map[string]struct{}) {
  2459  	if len(sg.Attr) != 0 {
  2460  		predicates[sg.Attr] = struct{}{}
  2461  	}
  2462  	for _, o := range sg.Params.Order {
  2463  		predicates[o.Attr] = struct{}{}
  2464  	}
  2465  	for _, pred := range sg.Params.groupbyAttrs {
  2466  		predicates[pred.Attr] = struct{}{}
  2467  	}
  2468  	for _, filter := range sg.Filters {
  2469  		filter.getAllPredicates(predicates)
  2470  	}
  2471  	for _, child := range sg.Children {
  2472  		child.getAllPredicates(predicates)
  2473  	}
  2474  }
  2475  
  2476  // UidsToHex converts the new UIDs to hex string.
  2477  func UidsToHex(m map[string]uint64) map[string]string {
  2478  	res := make(map[string]string)
  2479  	for k, v := range m {
  2480  		res[k] = fmt.Sprintf("%#x", v)
  2481  	}
  2482  	return res
  2483  }
  2484  
  2485  // Request wraps the state that is used when executing query.
  2486  // Initially ReadTs, Cache and GqlQuery are set.
  2487  // Subgraphs, Vars and Latency are filled when processing query.
  2488  type Request struct {
  2489  	ReadTs   uint64 // ReadTs for the transaction.
  2490  	Cache    int    // 0 represents use txn cache, 1 represents not to use cache.
  2491  	Latency  *Latency
  2492  	GqlQuery *gql.Result
  2493  
  2494  	Subgraphs []*SubGraph
  2495  
  2496  	Vars map[string]varValue
  2497  }
  2498  
  2499  // ProcessQuery processes query part of the request (without mutations).
  2500  // Fills Subgraphs and Vars.
  2501  // It can process multiple query blocks that are part of the query..
  2502  func (req *Request) ProcessQuery(ctx context.Context) (err error) {
  2503  	span := otrace.FromContext(ctx)
  2504  	stop := x.SpanTimer(span, "query.ProcessQuery")
  2505  	defer stop()
  2506  
  2507  	// doneVars stores the processed variables.
  2508  	req.Vars = make(map[string]varValue)
  2509  	loopStart := time.Now()
  2510  	queries := req.GqlQuery.Query
  2511  	// first loop converts queries to SubGraph representation and populates ReadTs And Cache.
  2512  	for i := 0; i < len(queries); i++ {
  2513  		gq := queries[i]
  2514  
  2515  		if gq == nil || (len(gq.UID) == 0 && gq.Func == nil && len(gq.NeedsVar) == 0 &&
  2516  			gq.Alias != "shortest" && !gq.IsEmpty) {
  2517  			return errors.Errorf("Invalid query. No function used at root and no aggregation" +
  2518  				" or math variables found in the body.")
  2519  		}
  2520  		sg, err := ToSubGraph(ctx, gq)
  2521  		if err != nil {
  2522  			return errors.Wrapf(err, "while converting to subgraph")
  2523  		}
  2524  		sg.recurse(func(sg *SubGraph) {
  2525  			sg.ReadTs = req.ReadTs
  2526  			sg.Cache = req.Cache
  2527  		})
  2528  		span.Annotate(nil, "Query parsed")
  2529  		req.Subgraphs = append(req.Subgraphs, sg)
  2530  	}
  2531  	req.Latency.Parsing += time.Since(loopStart)
  2532  
  2533  	execStart := time.Now()
  2534  	hasExecuted := make([]bool, len(req.Subgraphs))
  2535  	numQueriesDone := 0
  2536  
  2537  	// canExecute returns true if a query block is ready to execute with all the variables
  2538  	// that it depends on are already populated or are defined in the same block.
  2539  	canExecute := func(idx int) bool {
  2540  		queryVars := req.GqlQuery.QueryVars[idx]
  2541  		for _, v := range queryVars.Needs {
  2542  			// here we check if this block defines the variable v.
  2543  			var selfDep bool
  2544  			for _, vd := range queryVars.Defines {
  2545  				if v == vd {
  2546  					selfDep = true
  2547  					break
  2548  				}
  2549  			}
  2550  			// The variable should be defined in this block or should have already been
  2551  			// populated by some other block, otherwise we are not ready to execute yet.
  2552  			_, ok := req.Vars[v]
  2553  			if !ok && !selfDep {
  2554  				return false
  2555  			}
  2556  		}
  2557  		return true
  2558  	}
  2559  
  2560  	var shortestSg []*SubGraph
  2561  	for i := 0; i < len(req.Subgraphs) && numQueriesDone < len(req.Subgraphs); i++ {
  2562  		errChan := make(chan error, len(req.Subgraphs))
  2563  		var idxList []int
  2564  		// If we have N blocks in a query, it can take a maximum of N iterations for all of them
  2565  		// to be executed.
  2566  		for idx := 0; idx < len(req.Subgraphs); idx++ {
  2567  			if hasExecuted[idx] {
  2568  				continue
  2569  			}
  2570  			sg := req.Subgraphs[idx]
  2571  			// Check the list for the requires variables.
  2572  			if !canExecute(idx) {
  2573  				continue
  2574  			}
  2575  
  2576  			err = sg.recursiveFillVars(req.Vars)
  2577  			if err != nil {
  2578  				return err
  2579  			}
  2580  			hasExecuted[idx] = true
  2581  			numQueriesDone++
  2582  			idxList = append(idxList, idx)
  2583  			// A query doesn't need to be executed if
  2584  			// 1. It just does aggregation and math functions which is when sg.Params.IsEmpty is true.
  2585  			// 2. Its has an inequality fn at root without any args which can happen when it uses
  2586  			// value variables for args which don't expand to any value.
  2587  			if sg.Params.IsEmpty || isEmptyIneqFnWithVar(sg) {
  2588  				errChan <- nil
  2589  				continue
  2590  			}
  2591  
  2592  			if sg.Params.Alias == "shortest" {
  2593  				// We allow only one shortest path block per query.
  2594  				go func() {
  2595  					shortestSg, err = shortestPath(ctx, sg)
  2596  					errChan <- err
  2597  				}()
  2598  			} else if sg.Params.Recurse {
  2599  				go func() {
  2600  					errChan <- recurse(ctx, sg)
  2601  				}()
  2602  			} else {
  2603  				go ProcessGraph(ctx, sg, nil, errChan)
  2604  			}
  2605  		}
  2606  
  2607  		var ferr error
  2608  		// Wait for the execution that was started in this iteration.
  2609  		for i := 0; i < len(idxList); i++ {
  2610  			if err = <-errChan; err != nil {
  2611  				ferr = err
  2612  				continue
  2613  			}
  2614  		}
  2615  		if ferr != nil {
  2616  			return ferr
  2617  		}
  2618  
  2619  		// If the executed subgraph had some variable defined in it, Populate it in the map.
  2620  		for _, idx := range idxList {
  2621  			sg := req.Subgraphs[idx]
  2622  
  2623  			var sgPath []*SubGraph
  2624  			if err := sg.populateVarMap(req.Vars, sgPath); err != nil {
  2625  				return err
  2626  			}
  2627  			if err := sg.populatePostAggregation(req.Vars, []*SubGraph{}, nil); err != nil {
  2628  				return err
  2629  			}
  2630  		}
  2631  	}
  2632  
  2633  	// Ensure all the queries are executed.
  2634  	for _, it := range hasExecuted {
  2635  		if !it {
  2636  			return errors.Errorf("Query couldn't be executed")
  2637  		}
  2638  	}
  2639  	req.Latency.Processing += time.Since(execStart)
  2640  
  2641  	// If we had a shortestPath SG, append it to the result.
  2642  	if len(shortestSg) != 0 {
  2643  		req.Subgraphs = append(req.Subgraphs, shortestSg...)
  2644  	}
  2645  	return nil
  2646  }
  2647  
  2648  // ExecutionResult holds the result of running a query.
  2649  type ExecutionResult struct {
  2650  	Subgraphs  []*SubGraph
  2651  	SchemaNode []*pb.SchemaNode
  2652  	Types      []*pb.TypeUpdate
  2653  }
  2654  
  2655  // Process handles a query request.
  2656  func (req *Request) Process(ctx context.Context) (er ExecutionResult, err error) {
  2657  	err = req.ProcessQuery(ctx)
  2658  	if err != nil {
  2659  		return er, err
  2660  	}
  2661  	er.Subgraphs = req.Subgraphs
  2662  
  2663  	schemaProcessingStart := time.Now()
  2664  	if req.GqlQuery.Schema != nil {
  2665  		if er.SchemaNode, err = worker.GetSchemaOverNetwork(ctx, req.GqlQuery.Schema); err != nil {
  2666  			return er, errors.Wrapf(err, "while fetching schema")
  2667  		}
  2668  		if er.Types, err = worker.GetTypes(ctx, req.GqlQuery.Schema); err != nil {
  2669  			return er, errors.Wrapf(err, "while fetching types")
  2670  		}
  2671  	}
  2672  	req.Latency.Processing += time.Since(schemaProcessingStart)
  2673  
  2674  	return er, nil
  2675  }
  2676  
  2677  // StripBlankNode returns a copy of the map where all the keys have the blank node prefix removed.
  2678  func StripBlankNode(mp map[string]uint64) map[string]uint64 {
  2679  	temp := make(map[string]uint64)
  2680  	for k, v := range mp {
  2681  		if strings.HasPrefix(k, "_:") {
  2682  			temp[k[2:]] = v
  2683  		}
  2684  	}
  2685  	return temp
  2686  }