github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/abstract_document_query.go (about)

     1  package ravendb
     2  
     3  import (
     4  	"reflect"
     5  	"strconv"
     6  	"strings"
     7  	"time"
     8  )
     9  
    10  // Note: Java's IAbstractDocumentQuery is abstractDocumentQuery
    11  
    12  type abstractDocumentQuery struct {
    13  	aliasToGroupByFieldName map[string]string
    14  	defaultOperator         QueryOperator
    15  
    16  	// Note: rootTypes is not used in Go because we only have one ID property
    17  
    18  	negate             bool
    19  	indexName          string
    20  	collectionName     string
    21  	currentClauseDepth int
    22  	queryRaw           string
    23  	queryParameters    Parameters
    24  
    25  	isIntersect bool
    26  	isGroupBy   bool
    27  
    28  	theSession *InMemoryDocumentSessionOperations
    29  
    30  	pageSize *int
    31  
    32  	selectTokens       []queryToken
    33  	fromToken          *fromToken
    34  	declareToken       *declareToken
    35  	loadTokens         []*loadToken
    36  	fieldsToFetchToken *fieldsToFetchToken
    37  
    38  	whereTokens   []queryToken
    39  	groupByTokens []queryToken
    40  	orderByTokens []queryToken
    41  
    42  	start       int
    43  	conventions *DocumentConventions
    44  
    45  	timeout time.Duration
    46  
    47  	theWaitForNonStaleResults bool
    48  
    49  	includes []string
    50  
    51  	queryStats *QueryStatistics
    52  
    53  	disableEntitiesTracking bool
    54  
    55  	disableCaching bool
    56  
    57  	isInMoreLikeThis bool
    58  
    59  	// Go doesn't allow comparing functions so to remove we use index returned
    60  	// by add() function. We maintain stable index by never shrinking
    61  	// callback arrays. We assume there is no high churn of adding/removing
    62  	// callbacks
    63  	beforeQueryExecutedCallback []func(*IndexQuery)
    64  	afterQueryExecutedCallback  []func(*QueryResult)
    65  	afterStreamExecutedCallback []func(map[string]interface{})
    66  
    67  	queryOperation *queryOperation
    68  
    69  	// to allow "fluid" API, in many methods instead of returning an error, we
    70  	// remember it here and return in GetResults()
    71  	err error
    72  }
    73  
    74  func (q *abstractDocumentQuery) Err() error {
    75  	return q.err
    76  }
    77  
    78  func (q *abstractDocumentQuery) isDistinct() bool {
    79  	if len(q.selectTokens) == 0 {
    80  		return false
    81  	}
    82  	_, ok := q.selectTokens[0].(*distinctToken)
    83  	return ok
    84  }
    85  
    86  func (q *abstractDocumentQuery) getSession() *InMemoryDocumentSessionOperations {
    87  	return q.theSession
    88  }
    89  
    90  func (q *abstractDocumentQuery) isDynamicMapReduce() bool {
    91  	return len(q.groupByTokens) > 0
    92  }
    93  
    94  func getQueryDefaultTimeout() time.Duration {
    95  	return time.Second * 15
    96  }
    97  
    98  // at this point we assume all
    99  func newAbstractDocumentQuery(opts *DocumentQueryOptions) *abstractDocumentQuery {
   100  	res := &abstractDocumentQuery{
   101  		defaultOperator:         QueryOperatorAnd,
   102  		isGroupBy:               opts.isGroupBy,
   103  		indexName:               opts.IndexName,
   104  		collectionName:          opts.CollectionName,
   105  		declareToken:            opts.declareToken,
   106  		loadTokens:              opts.loadTokens,
   107  		theSession:              opts.session,
   108  		aliasToGroupByFieldName: make(map[string]string),
   109  		queryParameters:         make(map[string]interface{}),
   110  		queryStats:              NewQueryStatistics(),
   111  		queryRaw:                opts.rawQuery,
   112  	}
   113  
   114  	if opts.session == nil {
   115  		res.err = newIllegalArgumentError("session must be provided")
   116  		return res
   117  	}
   118  
   119  	if res.queryRaw == "" {
   120  		if opts.IndexName == "" && opts.CollectionName == "" {
   121  			res.err = newIllegalArgumentError("Either indexName or collectionName must be specified")
   122  			return res
   123  		}
   124  		res.fromToken = createFromToken(opts.IndexName, opts.CollectionName, opts.fromAlias)
   125  	}
   126  
   127  	f := func(queryResult *QueryResult) {
   128  		res.updateStatsAndHighlightings(queryResult)
   129  	}
   130  	res.addAfterQueryExecutedListener(f)
   131  	if opts.session == nil {
   132  		res.conventions = NewDocumentConventions()
   133  	} else {
   134  		res.conventions = opts.session.GetConventions()
   135  	}
   136  	return res
   137  }
   138  
   139  func (q *abstractDocumentQuery) usingDefaultOperator(operator QueryOperator) error {
   140  	if len(q.whereTokens) > 0 {
   141  		return newIllegalStateError("Default operator can only be set before any where clause is added.")
   142  	}
   143  
   144  	q.defaultOperator = operator
   145  	return nil
   146  }
   147  
   148  func (q *abstractDocumentQuery) waitForNonStaleResults(waitTimeout time.Duration) {
   149  	q.theWaitForNonStaleResults = true
   150  	if waitTimeout == 0 {
   151  		waitTimeout = getQueryDefaultTimeout()
   152  	}
   153  	q.timeout = waitTimeout
   154  }
   155  
   156  func (q *abstractDocumentQuery) initializeQueryOperation() (*queryOperation, error) {
   157  	indexQuery, err := q.GetIndexQuery()
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	return newQueryOperation(q.theSession, q.indexName, indexQuery, q.fieldsToFetchToken, q.disableEntitiesTracking, false, false)
   163  }
   164  
   165  func (q *abstractDocumentQuery) GetIndexQuery() (*IndexQuery, error) {
   166  	query, err := q.string()
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	indexQuery := q.generateIndexQuery(query)
   171  	q.invokeBeforeQueryExecuted(indexQuery)
   172  	return indexQuery, nil
   173  }
   174  
   175  func (q *abstractDocumentQuery) getProjectionFields() []string {
   176  
   177  	if q.fieldsToFetchToken != nil && q.fieldsToFetchToken.projections != nil {
   178  		return q.fieldsToFetchToken.projections
   179  	}
   180  	return nil
   181  }
   182  
   183  func (q *abstractDocumentQuery) randomOrdering() error {
   184  	if err := q.assertNoRawQuery(); err != nil {
   185  		return err
   186  	}
   187  
   188  	q.noCaching()
   189  	q.orderByTokens = append(q.orderByTokens, orderByTokenRandom)
   190  	return nil
   191  }
   192  
   193  func (q *abstractDocumentQuery) randomOrderingWithSeed(seed string) error {
   194  	err := q.assertNoRawQuery()
   195  	if err != nil {
   196  		return err
   197  	}
   198  
   199  	if stringIsBlank(seed) {
   200  		err = q.randomOrdering()
   201  		if err != nil {
   202  			return err
   203  		}
   204  		return nil
   205  	}
   206  
   207  	q.noCaching()
   208  	q.orderByTokens = append(q.orderByTokens, orderByTokenCreateRandom(seed))
   209  	return nil
   210  }
   211  
   212  func (q *abstractDocumentQuery) addGroupByAlias(fieldName string, projectedName string) {
   213  	q.aliasToGroupByFieldName[projectedName] = fieldName
   214  }
   215  
   216  func (q *abstractDocumentQuery) assertNoRawQuery() error {
   217  	if q.queryRaw != "" {
   218  		return newIllegalStateError("RawQuery was called, cannot modify this query by calling on operations that would modify the query (such as Where, Select, OrderBy, GroupBy, etc)")
   219  	}
   220  	return nil
   221  }
   222  
   223  func (q *abstractDocumentQuery) addParameter(name string, value interface{}) error {
   224  	name = strings.TrimPrefix(name, "$")
   225  	if _, ok := q.queryParameters[name]; ok {
   226  		return newIllegalStateError("The parameter " + name + " was already added")
   227  	}
   228  
   229  	q.queryParameters[name] = value
   230  	return nil
   231  }
   232  
   233  func (q *abstractDocumentQuery) groupBy(fieldName string, fieldNames ...string) error {
   234  	var mapping []*GroupBy
   235  	for _, x := range fieldNames {
   236  		el := NewGroupByField(x)
   237  		mapping = append(mapping, el)
   238  	}
   239  	return q.groupByFieldWithMethod(NewGroupByField(fieldName), mapping...)
   240  }
   241  
   242  func (q *abstractDocumentQuery) groupByFieldWithMethod(field *GroupBy, fields ...*GroupBy) error {
   243  	// TODO: if q.fromToken is nil, needs to do this check in ToList()
   244  	if q.fromToken != nil && !q.fromToken.isDynamic {
   245  		return newIllegalStateError("groupBy only works with dynamic queries")
   246  	}
   247  
   248  	if err := q.assertNoRawQuery(); err != nil {
   249  		return err
   250  	}
   251  	q.isGroupBy = true
   252  
   253  	fieldName, err := q.ensureValidFieldName(field.Field, false)
   254  	if err != nil {
   255  		return err
   256  	}
   257  
   258  	q.groupByTokens = append(q.groupByTokens, createGroupByToken(fieldName, field.Method))
   259  
   260  	if len(fields) == 0 {
   261  		return nil
   262  	}
   263  
   264  	for _, item := range fields {
   265  		fieldName, err = q.ensureValidFieldName(item.Field, false)
   266  		if err != nil {
   267  			return err
   268  		}
   269  		q.groupByTokens = append(q.groupByTokens, createGroupByToken(fieldName, item.Method))
   270  	}
   271  	return nil
   272  }
   273  
   274  func (q *abstractDocumentQuery) groupByKey(fieldName string, projectedName string) error {
   275  	if err := q.assertNoRawQuery(); err != nil {
   276  		return err
   277  	}
   278  	q.isGroupBy = true
   279  
   280  	_, hasProjectedName := q.aliasToGroupByFieldName[projectedName]
   281  	_, hasFieldName := q.aliasToGroupByFieldName[fieldName]
   282  
   283  	if projectedName != "" && hasProjectedName {
   284  		aliasedFieldName := q.aliasToGroupByFieldName[projectedName]
   285  		if fieldName == "" || strings.EqualFold(fieldName, projectedName) {
   286  			fieldName = aliasedFieldName
   287  		}
   288  	} else if fieldName != "" && hasFieldName {
   289  		aliasedFieldName := q.aliasToGroupByFieldName[fieldName]
   290  		fieldName = aliasedFieldName
   291  	}
   292  
   293  	q.selectTokens = append(q.selectTokens, createGroupByKeyToken(fieldName, projectedName))
   294  	return nil
   295  }
   296  
   297  // projectedName is optional
   298  func (q *abstractDocumentQuery) groupBySum(fieldName string, projectedName string) error {
   299  	if err := q.assertNoRawQuery(); err != nil {
   300  		return err
   301  	}
   302  	q.isGroupBy = true
   303  
   304  	var err error
   305  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   306  	if err != nil {
   307  		return err
   308  	}
   309  	q.selectTokens = append(q.selectTokens, createGroupBySumToken(fieldName, projectedName))
   310  	return nil
   311  }
   312  
   313  // projectedName is optional
   314  func (q *abstractDocumentQuery) groupByCount(projectedName string) error {
   315  	if err := q.assertNoRawQuery(); err != nil {
   316  		return err
   317  	}
   318  	q.isGroupBy = true
   319  
   320  	t := &groupByCountToken{
   321  		fieldName: projectedName,
   322  	}
   323  	q.selectTokens = append(q.selectTokens, t)
   324  	return nil
   325  }
   326  
   327  func (q *abstractDocumentQuery) whereTrue() error {
   328  	tokensRef, err := q.getCurrentWhereTokensRef()
   329  	if err != nil {
   330  		return err
   331  	}
   332  	err = q.appendOperatorIfNeeded(tokensRef)
   333  	if err != nil {
   334  		return err
   335  	}
   336  	err = q.negateIfNeeded(tokensRef, "")
   337  	if err != nil {
   338  		return err
   339  	}
   340  
   341  	tokens := *tokensRef
   342  	tokens = append(tokens, trueTokenInstance)
   343  	*tokensRef = tokens
   344  	return nil
   345  }
   346  
   347  func (q *abstractDocumentQuery) moreLikeThis() (*moreLikeThisScope, error) {
   348  	err := q.appendOperatorIfNeeded(&q.whereTokens)
   349  	if err != nil {
   350  		return nil, err
   351  	}
   352  
   353  	token := newMoreLikeThisToken()
   354  	q.whereTokens = append(q.whereTokens, token)
   355  
   356  	q.isInMoreLikeThis = true
   357  	add := func(o interface{}) string {
   358  		return q.addQueryParameter(o)
   359  	}
   360  	onDispose := func() {
   361  		q.isInMoreLikeThis = false
   362  	}
   363  	return newMoreLikeThisScope(token, add, onDispose), nil
   364  }
   365  
   366  func (q *abstractDocumentQuery) include(path string) {
   367  	q.includes = append(q.includes, path)
   368  }
   369  
   370  func (q *abstractDocumentQuery) take(count int) {
   371  	q.pageSize = &count
   372  }
   373  
   374  func (q *abstractDocumentQuery) skip(count int) {
   375  	q.start = count
   376  }
   377  
   378  func (q *abstractDocumentQuery) whereLucene(fieldName string, whereClause string) error {
   379  	var err error
   380  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   381  	if err != nil {
   382  		return err
   383  	}
   384  	tokensRef, err := q.getCurrentWhereTokensRef()
   385  	if err != nil {
   386  		return err
   387  	}
   388  	tokens := *tokensRef
   389  	err = q.appendOperatorIfNeeded(tokensRef)
   390  	if err != nil {
   391  		return err
   392  	}
   393  	err = q.negateIfNeeded(tokensRef, fieldName)
   394  	if err != nil {
   395  		return err
   396  	}
   397  
   398  	whereToken := createWhereTokenWithOptions(whereOperatorLucene, fieldName, q.addQueryParameter(whereClause), nil)
   399  	tokens = append(tokens, whereToken)
   400  	*tokensRef = tokens
   401  	return nil
   402  }
   403  
   404  func (q *abstractDocumentQuery) openSubclause() error {
   405  	q.currentClauseDepth++
   406  
   407  	tokensRef, err := q.getCurrentWhereTokensRef()
   408  	if err != nil {
   409  		return err
   410  	}
   411  	err = q.appendOperatorIfNeeded(tokensRef)
   412  	if err != nil {
   413  		return err
   414  	}
   415  	err = q.negateIfNeeded(tokensRef, "")
   416  	if err != nil {
   417  		return err
   418  	}
   419  
   420  	tokens := *tokensRef
   421  	tokens = append(tokens, openSubclauseTokenInstance)
   422  	*tokensRef = tokens
   423  	return nil
   424  }
   425  
   426  func (q *abstractDocumentQuery) closeSubclause() error {
   427  	q.currentClauseDepth--
   428  
   429  	tokensRef, err := q.getCurrentWhereTokensRef()
   430  	if err != nil {
   431  		return err
   432  	}
   433  	tokens := *tokensRef
   434  	tokens = append(tokens, closeSubclauseTokenInstance)
   435  	*tokensRef = tokens
   436  	return nil
   437  }
   438  
   439  func (q *abstractDocumentQuery) where(fieldName string, op string, value interface{}) error {
   440  	op = strings.TrimSpace(op)
   441  	switch op {
   442  	case "=", "==":
   443  		return q.whereEquals(fieldName, value)
   444  	case "!=":
   445  		return q.whereNotEquals(fieldName, value)
   446  	case "<":
   447  		return q.whereLessThan(fieldName, value)
   448  	case "<=":
   449  		return q.whereLessThanOrEqual(fieldName, value)
   450  	case ">":
   451  		return q.whereGreaterThan(fieldName, value)
   452  	case ">=":
   453  		return q.whereGreaterThanOrEqual(fieldName, value)
   454  	default:
   455  		return newIllegalArgumentError("'%s' is not a valid op", op)
   456  	}
   457  }
   458  
   459  func (q *abstractDocumentQuery) whereEquals(fieldName string, value interface{}) error {
   460  	params := &whereParams{
   461  		fieldName: fieldName,
   462  		value:     value,
   463  	}
   464  	return q.whereEqualsWithParams(params)
   465  }
   466  
   467  func (q *abstractDocumentQuery) whereEqualsWithMethodCall(fieldName string, method MethodCall) error {
   468  	return q.whereEquals(fieldName, method)
   469  }
   470  
   471  func (q *abstractDocumentQuery) whereEqualsWithParams(whereParams *whereParams) error {
   472  	if q.negate {
   473  		q.negate = false
   474  		return q.whereNotEqualsWithParams(whereParams)
   475  	}
   476  
   477  	var err error
   478  	whereParams.fieldName, err = q.ensureValidFieldName(whereParams.fieldName, whereParams.isNestedPath)
   479  	if err != nil {
   480  		return err
   481  	}
   482  
   483  	tokensRef, err := q.getCurrentWhereTokensRef()
   484  	if err != nil {
   485  		return err
   486  	}
   487  	err = q.appendOperatorIfNeeded(tokensRef)
   488  	if err != nil {
   489  		return err
   490  	}
   491  
   492  	if q.ifValueIsMethod(whereOperatorEquals, whereParams, tokensRef) {
   493  		return nil
   494  	}
   495  
   496  	transformToEqualValue := q.transformValue(whereParams)
   497  	addQueryParameter := q.addQueryParameter(transformToEqualValue)
   498  	whereToken := createWhereTokenWithOptions(whereOperatorEquals, whereParams.fieldName, addQueryParameter, newWhereOptionsWithExact(whereParams.isExact))
   499  
   500  	tokens := *tokensRef
   501  	tokens = append(tokens, whereToken)
   502  	*tokensRef = tokens
   503  	return nil
   504  }
   505  
   506  func (q *abstractDocumentQuery) ifValueIsMethod(op whereOperator, whereParams *whereParams, tokensRef *[]queryToken) bool {
   507  	if mc, ok := whereParams.value.(*CmpXchg); ok {
   508  		n := len(mc.args)
   509  		args := make([]string, n)
   510  		for i := 0; i < n; i++ {
   511  			args[i] = q.addQueryParameter(mc.args[i])
   512  		}
   513  
   514  		opts := newWhereOptionsWithMethod(MethodsTypeCmpXChg, args, mc.accessPath, whereParams.isExact)
   515  		token := createWhereTokenWithOptions(op, whereParams.fieldName, "", opts)
   516  
   517  		tokens := *tokensRef
   518  		tokens = append(tokens, token)
   519  		*tokensRef = tokens
   520  		return true
   521  	}
   522  
   523  	// add more if there are more types that "derive" from MethodCall
   524  	// (by embedding MethodCallData)
   525  
   526  	return false
   527  }
   528  
   529  func (q *abstractDocumentQuery) whereNotEquals(fieldName string, value interface{}) error {
   530  	params := &whereParams{
   531  		fieldName: fieldName,
   532  		value:     value,
   533  	}
   534  
   535  	return q.whereNotEqualsWithParams(params)
   536  }
   537  
   538  func (q *abstractDocumentQuery) whereNotEqualsWithMethod(fieldName string, method MethodCall) error {
   539  	return q.whereNotEquals(fieldName, method)
   540  }
   541  
   542  func (q *abstractDocumentQuery) whereNotEqualsWithParams(whereParams *whereParams) error {
   543  	if q.negate {
   544  		q.negate = false
   545  		return q.whereEqualsWithParams(whereParams)
   546  	}
   547  
   548  	transformToEqualValue := q.transformValue(whereParams)
   549  
   550  	tokensRef, err := q.getCurrentWhereTokensRef()
   551  	if err != nil {
   552  		return err
   553  	}
   554  	err = q.appendOperatorIfNeeded(tokensRef)
   555  	if err != nil {
   556  		return err
   557  	}
   558  
   559  	whereParams.fieldName, err = q.ensureValidFieldName(whereParams.fieldName, whereParams.isNestedPath)
   560  	if err != nil {
   561  		return err
   562  	}
   563  
   564  	if q.ifValueIsMethod(whereOperatorNotEquals, whereParams, tokensRef) {
   565  		return nil
   566  	}
   567  
   568  	whereToken := createWhereTokenWithOptions(whereOperatorNotEquals, whereParams.fieldName, q.addQueryParameter(transformToEqualValue), newWhereOptionsWithExact(whereParams.isExact))
   569  	tokens := *tokensRef
   570  	tokens = append(tokens, whereToken)
   571  	*tokensRef = tokens
   572  	return nil
   573  }
   574  
   575  func (q *abstractDocumentQuery) negateNext() {
   576  	q.negate = !q.negate
   577  }
   578  
   579  // mark last created token as exact. only applies to select number of tokens.
   580  // it allows fluid APIs like .Where().Exact()
   581  // will panic if last token wasn't of compatible type as that is considered
   582  // invalid use of API and returning an error would break fluid API
   583  func (q *abstractDocumentQuery) markLastTokenExact() error {
   584  	tokensRef, err := q.getCurrentWhereTokensRef()
   585  	if err != nil {
   586  		return err
   587  	}
   588  	tokens := *tokensRef
   589  	n := len(tokens)
   590  	lastToken := tokens[n-1]
   591  	switch tok := lastToken.(type) {
   592  	case *whereToken:
   593  		if tok.options == nil {
   594  			tok.options = newWhereOptionsWithExact(true)
   595  		} else {
   596  			tok.options.exact = true
   597  		}
   598  	default:
   599  		return newIllegalStateError("expected whereToken, got %T", lastToken)
   600  	}
   601  
   602  	*tokensRef = tokens
   603  	return nil
   604  }
   605  
   606  func (q *abstractDocumentQuery) whereIn(fieldName string, values []interface{}) error {
   607  	var err error
   608  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   609  	if err != nil {
   610  		return err
   611  	}
   612  
   613  	tokensRef, err := q.getCurrentWhereTokensRef()
   614  	if err != nil {
   615  		return err
   616  	}
   617  	err = q.appendOperatorIfNeeded(tokensRef)
   618  	if err != nil {
   619  		return err
   620  	}
   621  	err = q.negateIfNeeded(tokensRef, fieldName)
   622  	if err != nil {
   623  		return err
   624  	}
   625  
   626  	whereToken := createWhereToken(whereOperatorIn, fieldName, q.addQueryParameter(q.transformCollection(fieldName, abstractDocumentQueryUnpackCollection(values))))
   627  
   628  	tokens := *tokensRef
   629  	tokens = append(tokens, whereToken)
   630  	*tokensRef = tokens
   631  	return nil
   632  }
   633  
   634  func (q *abstractDocumentQuery) whereStartsWith(fieldName string, value interface{}) error {
   635  	whereParams := &whereParams{
   636  		fieldName:      fieldName,
   637  		value:          value,
   638  		allowWildcards: true,
   639  	}
   640  
   641  	transformToEqualValue := q.transformValue(whereParams)
   642  
   643  	tokensRef, err := q.getCurrentWhereTokensRef()
   644  	if err != nil {
   645  		return err
   646  	}
   647  	err = q.appendOperatorIfNeeded(tokensRef)
   648  	if err != nil {
   649  		return err
   650  	}
   651  
   652  	whereParams.fieldName, err = q.ensureValidFieldName(whereParams.fieldName, whereParams.isNestedPath)
   653  	if err != nil {
   654  		return err
   655  	}
   656  	err = q.negateIfNeeded(tokensRef, whereParams.fieldName)
   657  	if err != nil {
   658  		return err
   659  	}
   660  
   661  	whereToken := createWhereToken(whereOperatorStartsWith, whereParams.fieldName, q.addQueryParameter(transformToEqualValue))
   662  
   663  	tokens := *tokensRef
   664  	tokens = append(tokens, whereToken)
   665  	*tokensRef = tokens
   666  	return nil
   667  }
   668  
   669  func (q *abstractDocumentQuery) whereEndsWith(fieldName string, value interface{}) error {
   670  	whereParams := &whereParams{
   671  		fieldName:      fieldName,
   672  		value:          value,
   673  		allowWildcards: true,
   674  	}
   675  
   676  	transformToEqualValue := q.transformValue(whereParams)
   677  
   678  	tokensRef, err := q.getCurrentWhereTokensRef()
   679  	if err != nil {
   680  		return err
   681  	}
   682  	err = q.appendOperatorIfNeeded(tokensRef)
   683  	if err != nil {
   684  		return err
   685  	}
   686  
   687  	whereParams.fieldName, err = q.ensureValidFieldName(whereParams.fieldName, whereParams.isNestedPath)
   688  	if err != nil {
   689  		return err
   690  	}
   691  	err = q.negateIfNeeded(tokensRef, whereParams.fieldName)
   692  	if err != nil {
   693  		return err
   694  	}
   695  
   696  	whereToken := createWhereToken(whereOperatorEndsWith, whereParams.fieldName, q.addQueryParameter(transformToEqualValue))
   697  
   698  	tokens := *tokensRef
   699  	tokens = append(tokens, whereToken)
   700  	*tokensRef = tokens
   701  	return nil
   702  }
   703  
   704  func (q *abstractDocumentQuery) whereBetween(fieldName string, start interface{}, end interface{}) error {
   705  	var err error
   706  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   707  	if err != nil {
   708  		return err
   709  	}
   710  
   711  	tokensRef, err := q.getCurrentWhereTokensRef()
   712  	if err != nil {
   713  		return err
   714  	}
   715  	err = q.appendOperatorIfNeeded(tokensRef)
   716  	if err != nil {
   717  		return err
   718  	}
   719  	err = q.negateIfNeeded(tokensRef, fieldName)
   720  	if err != nil {
   721  		return err
   722  	}
   723  
   724  	startParams := &whereParams{
   725  		value:     start,
   726  		fieldName: fieldName,
   727  	}
   728  
   729  	endParams := &whereParams{
   730  		value:     end,
   731  		fieldName: fieldName,
   732  	}
   733  
   734  	fromParam := interface{}("*")
   735  	if start != nil {
   736  		fromParam = q.transformValueWithRange(startParams, true)
   737  	}
   738  	fromParameterName := q.addQueryParameter(fromParam)
   739  
   740  	toParam := interface{}("NULL")
   741  	if end != nil {
   742  		toParam = q.transformValueWithRange(endParams, true)
   743  	}
   744  	toParameterName := q.addQueryParameter(toParam)
   745  
   746  	whereToken := createWhereTokenWithOptions(whereOperatorBetween, fieldName, "", newWhereOptionsWithFromTo(false, fromParameterName, toParameterName))
   747  
   748  	tokens := *tokensRef
   749  	tokens = append(tokens, whereToken)
   750  	*tokensRef = tokens
   751  	return nil
   752  }
   753  
   754  func (q *abstractDocumentQuery) whereGreaterThan(fieldName string, value interface{}) error {
   755  	var err error
   756  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   757  	if err != nil {
   758  		return err
   759  	}
   760  
   761  	tokensRef, err := q.getCurrentWhereTokensRef()
   762  	if err != nil {
   763  		return err
   764  	}
   765  	err = q.appendOperatorIfNeeded(tokensRef)
   766  	if err != nil {
   767  		return err
   768  	}
   769  	err = q.negateIfNeeded(tokensRef, fieldName)
   770  	if err != nil {
   771  		return err
   772  	}
   773  
   774  	whereParams := &whereParams{
   775  		value:     value,
   776  		fieldName: fieldName,
   777  	}
   778  
   779  	paramValue := interface{}("*")
   780  	if value != nil {
   781  		paramValue = q.transformValueWithRange(whereParams, true)
   782  	}
   783  	parameter := q.addQueryParameter(paramValue)
   784  
   785  	whereToken := createWhereTokenWithOptions(whereOperatorGreaterThan, fieldName, parameter, nil)
   786  
   787  	tokens := *tokensRef
   788  	tokens = append(tokens, whereToken)
   789  	*tokensRef = tokens
   790  	return nil
   791  }
   792  
   793  func (q *abstractDocumentQuery) whereGreaterThanOrEqual(fieldName string, value interface{}) error {
   794  	var err error
   795  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   796  	if err != nil {
   797  		return err
   798  	}
   799  
   800  	tokensRef, err := q.getCurrentWhereTokensRef()
   801  	if err != nil {
   802  		return err
   803  	}
   804  	err = q.appendOperatorIfNeeded(tokensRef)
   805  	if err != nil {
   806  		return err
   807  	}
   808  	err = q.negateIfNeeded(tokensRef, fieldName)
   809  	if err != nil {
   810  		return err
   811  	}
   812  
   813  	whereParams := &whereParams{
   814  		value:     value,
   815  		fieldName: fieldName,
   816  	}
   817  
   818  	paramValue := interface{}("*")
   819  	if value != nil {
   820  		paramValue = q.transformValueWithRange(whereParams, true)
   821  	}
   822  
   823  	parameter := q.addQueryParameter(paramValue)
   824  
   825  	whereToken := createWhereTokenWithOptions(whereOperatorGreaterThanOrEqual, fieldName, parameter, nil)
   826  
   827  	tokens := *tokensRef
   828  	tokens = append(tokens, whereToken)
   829  	*tokensRef = tokens
   830  	return nil
   831  }
   832  
   833  func (q *abstractDocumentQuery) whereLessThan(fieldName string, value interface{}) error {
   834  	var err error
   835  	fieldName, err = q.ensureValidFieldName(fieldName, false)
   836  	if err != nil {
   837  		return err
   838  	}
   839  
   840  	tokensRef, err := q.getCurrentWhereTokensRef()
   841  	if err != nil {
   842  		return err
   843  	}
   844  	err = q.appendOperatorIfNeeded(tokensRef)
   845  	if err != nil {
   846  		return err
   847  	}
   848  	err = q.negateIfNeeded(tokensRef, fieldName)
   849  	if err != nil {
   850  		return err
   851  	}
   852  
   853  	whereParams := &whereParams{
   854  		value:     value,
   855  		fieldName: fieldName,
   856  	}
   857  
   858  	paramValue := interface{}("NULL")
   859  	if value != nil {
   860  		paramValue = q.transformValueWithRange(whereParams, true)
   861  	}
   862  	parameter := q.addQueryParameter(paramValue)
   863  	whereToken := createWhereTokenWithOptions(whereOperatorLessThan, fieldName, parameter, nil)
   864  
   865  	tokens := *tokensRef
   866  	tokens = append(tokens, whereToken)
   867  	*tokensRef = tokens
   868  	return nil
   869  }
   870  
   871  func (q *abstractDocumentQuery) whereLessThanOrEqual(fieldName string, value interface{}) error {
   872  	tokensRef, err := q.getCurrentWhereTokensRef()
   873  	if err != nil {
   874  		return err
   875  	}
   876  	err = q.appendOperatorIfNeeded(tokensRef)
   877  	if err != nil {
   878  		return err
   879  	}
   880  	err = q.negateIfNeeded(tokensRef, fieldName)
   881  	if err != nil {
   882  		return err
   883  	}
   884  
   885  	whereParams := &whereParams{
   886  		value:     value,
   887  		fieldName: fieldName,
   888  	}
   889  
   890  	paramValue := interface{}("NULL")
   891  	if value != nil {
   892  		paramValue = q.transformValueWithRange(whereParams, true)
   893  	}
   894  	parameter := q.addQueryParameter(paramValue)
   895  	whereToken := createWhereTokenWithOptions(whereOperatorLessThanOrEqual, fieldName, parameter, nil)
   896  
   897  	tokens := *tokensRef
   898  	tokens = append(tokens, whereToken)
   899  	*tokensRef = tokens
   900  	return nil
   901  }
   902  
   903  func (q *abstractDocumentQuery) whereRegex(fieldName string, pattern string) error {
   904  	tokensRef, err := q.getCurrentWhereTokensRef()
   905  	if err != nil {
   906  		return err
   907  	}
   908  	err = q.appendOperatorIfNeeded(tokensRef)
   909  	if err != nil {
   910  		return err
   911  	}
   912  	err = q.negateIfNeeded(tokensRef, fieldName)
   913  	if err != nil {
   914  		return err
   915  	}
   916  
   917  	whereParams := &whereParams{
   918  		value:     pattern,
   919  		fieldName: fieldName,
   920  	}
   921  
   922  	parameter := q.addQueryParameter(q.transformValue(whereParams))
   923  
   924  	whereToken := createWhereToken(whereOperatorRegex, fieldName, parameter)
   925  
   926  	tokens := *tokensRef
   927  	tokens = append(tokens, whereToken)
   928  	*tokensRef = tokens
   929  	return nil
   930  }
   931  
   932  func (q *abstractDocumentQuery) andAlso() error {
   933  	tokensRef, err := q.getCurrentWhereTokensRef()
   934  	if err != nil {
   935  		return err
   936  	}
   937  	tokens := *tokensRef
   938  
   939  	n := len(tokens)
   940  	if n == 0 {
   941  		return nil
   942  	}
   943  
   944  	lastToken := tokens[n-1]
   945  	if _, ok := lastToken.(*queryOperatorToken); ok {
   946  		return newIllegalStateError("Cannot add AND, previous token was already an operator token.")
   947  	}
   948  
   949  	tokens = append(tokens, queryOperatorTokenAnd)
   950  	*tokensRef = tokens
   951  	return nil
   952  }
   953  
   954  func (q *abstractDocumentQuery) orElse() error {
   955  	tokensRef, err := q.getCurrentWhereTokensRef()
   956  	if err != nil {
   957  		return err
   958  	}
   959  	tokens := *tokensRef
   960  	n := len(tokens)
   961  	if n == 0 {
   962  		return nil
   963  	}
   964  
   965  	lastToken := tokens[n-1]
   966  	if _, ok := lastToken.(*queryOperatorToken); ok {
   967  		return newIllegalStateError("Cannot add OR, previous token was already an operator token.")
   968  	}
   969  
   970  	tokens = append(tokens, queryOperatorTokenOr)
   971  	*tokensRef = tokens
   972  	return nil
   973  }
   974  
   975  func (q *abstractDocumentQuery) boost(boost float64) error {
   976  	if boost == 1.0 {
   977  		return nil
   978  	}
   979  
   980  	tokens, err := q.getCurrentWhereTokens()
   981  	if err != nil {
   982  		return err
   983  	}
   984  	n := len(tokens)
   985  	if n == 0 {
   986  		return newIllegalStateError("Missing where clause")
   987  	}
   988  
   989  	maybeWhereToken := tokens[n-1]
   990  	whereToken, ok := maybeWhereToken.(*whereToken)
   991  	if !ok {
   992  		return newIllegalStateError("Missing where clause")
   993  	}
   994  
   995  	if boost <= 0.0 {
   996  		return newIllegalArgumentError("Boost factor must be a positive number")
   997  	}
   998  
   999  	whereToken.options.boost = boost
  1000  	return nil
  1001  }
  1002  
  1003  func (q *abstractDocumentQuery) fuzzy(fuzzy float64) error {
  1004  	tokens, err := q.getCurrentWhereTokens()
  1005  	if err != nil {
  1006  		return err
  1007  	}
  1008  	n := len(tokens)
  1009  	if n == 0 {
  1010  		return newIllegalStateError("Missing where clause")
  1011  	}
  1012  
  1013  	maybeWhereToken := tokens[n-1]
  1014  	whereToken, ok := maybeWhereToken.(*whereToken)
  1015  	if !ok {
  1016  		return newIllegalStateError("Missing where clause")
  1017  	}
  1018  
  1019  	if fuzzy < 0.0 || fuzzy > 1.0 {
  1020  		return newIllegalArgumentError("Fuzzy distance must be between 0.0 and 1.0")
  1021  	}
  1022  
  1023  	whereToken.options.fuzzy = fuzzy
  1024  	return nil
  1025  }
  1026  
  1027  func (q *abstractDocumentQuery) proximity(proximity int) error {
  1028  	tokens, err := q.getCurrentWhereTokens()
  1029  	if err != nil {
  1030  		return err
  1031  	}
  1032  
  1033  	n := len(tokens)
  1034  	if n == 0 {
  1035  		return newIllegalStateError("Missing where clause")
  1036  	}
  1037  
  1038  	maybeWhereToken := tokens[n-1]
  1039  	whereToken, ok := maybeWhereToken.(*whereToken)
  1040  	if !ok {
  1041  		return newIllegalStateError("Missing where clause")
  1042  	}
  1043  
  1044  	if proximity < 1 {
  1045  		return newIllegalArgumentError("Proximity distance must be a positive number")
  1046  	}
  1047  
  1048  	whereToken.options.proximity = proximity
  1049  	return nil
  1050  }
  1051  
  1052  func (q *abstractDocumentQuery) orderBy(field string) error {
  1053  	return q.orderByWithOrdering(field, OrderingTypeString)
  1054  }
  1055  
  1056  func (q *abstractDocumentQuery) orderByWithOrdering(field string, ordering OrderingType) error {
  1057  	if err := q.assertNoRawQuery(); err != nil {
  1058  		return err
  1059  	}
  1060  	f, err := q.ensureValidFieldName(field, false)
  1061  	if err != nil {
  1062  		return err
  1063  	}
  1064  	q.orderByTokens = append(q.orderByTokens, orderByTokenCreateAscending(f, ordering))
  1065  	return nil
  1066  }
  1067  
  1068  func (q *abstractDocumentQuery) orderByDescending(field string) error {
  1069  	return q.orderByDescendingWithOrdering(field, OrderingTypeString)
  1070  }
  1071  
  1072  func (q *abstractDocumentQuery) orderByDescendingWithOrdering(field string, ordering OrderingType) error {
  1073  	if err := q.assertNoRawQuery(); err != nil {
  1074  		return err
  1075  	}
  1076  	f, err := q.ensureValidFieldName(field, false)
  1077  	if err != nil {
  1078  		return err
  1079  	}
  1080  	q.orderByTokens = append(q.orderByTokens, orderByTokenCreateDescending(f, ordering))
  1081  	return nil
  1082  }
  1083  
  1084  func (q *abstractDocumentQuery) orderByScore() error {
  1085  	if err := q.assertNoRawQuery(); err != nil {
  1086  		return err
  1087  	}
  1088  
  1089  	q.orderByTokens = append(q.orderByTokens, orderByTokenScoreAscending)
  1090  	return nil
  1091  }
  1092  
  1093  func (q *abstractDocumentQuery) orderByScoreDescending() error {
  1094  	if err := q.assertNoRawQuery(); err != nil {
  1095  		return err
  1096  	}
  1097  	q.orderByTokens = append(q.orderByTokens, orderByTokenScoreDescending)
  1098  	return nil
  1099  }
  1100  
  1101  func (q *abstractDocumentQuery) statistics(stats **QueryStatistics) {
  1102  	*stats = q.queryStats
  1103  }
  1104  
  1105  func (q *abstractDocumentQuery) invokeAfterQueryExecuted(result *QueryResult) {
  1106  	for _, cb := range q.afterQueryExecutedCallback {
  1107  		if cb != nil {
  1108  			cb(result)
  1109  		}
  1110  	}
  1111  }
  1112  
  1113  func (q *abstractDocumentQuery) invokeBeforeQueryExecuted(query *IndexQuery) {
  1114  	for _, cb := range q.beforeQueryExecutedCallback {
  1115  		if cb != nil {
  1116  			cb(query)
  1117  		}
  1118  	}
  1119  }
  1120  
  1121  func (q *abstractDocumentQuery) invokeAfterStreamExecuted(result map[string]interface{}) {
  1122  	for _, cb := range q.afterStreamExecutedCallback {
  1123  		if cb != nil {
  1124  			cb(result)
  1125  		}
  1126  	}
  1127  }
  1128  
  1129  func (q *abstractDocumentQuery) generateIndexQuery(query string) *IndexQuery {
  1130  	indexQuery := NewIndexQuery("")
  1131  	indexQuery.query = query
  1132  	indexQuery.start = q.start
  1133  	indexQuery.waitForNonStaleResults = q.theWaitForNonStaleResults
  1134  	indexQuery.waitForNonStaleResultsTimeout = q.timeout
  1135  	indexQuery.queryParameters = q.queryParameters
  1136  	indexQuery.disableCaching = q.disableCaching
  1137  
  1138  	if q.pageSize != nil {
  1139  		indexQuery.pageSize = *q.pageSize
  1140  	}
  1141  	return indexQuery
  1142  }
  1143  
  1144  func (q *abstractDocumentQuery) search(fieldName string, searchTerms string) error {
  1145  	return q.searchWithOperator(fieldName, searchTerms, SearchOperatorOr)
  1146  }
  1147  
  1148  func (q *abstractDocumentQuery) searchWithOperator(fieldName string, searchTerms string, operator SearchOperator) error {
  1149  	tokensRef, err := q.getCurrentWhereTokensRef()
  1150  	if err != nil {
  1151  		return err
  1152  	}
  1153  	err = q.appendOperatorIfNeeded(tokensRef)
  1154  	if err != nil {
  1155  		return err
  1156  	}
  1157  
  1158  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1159  	if err != nil {
  1160  		return err
  1161  	}
  1162  	err = q.negateIfNeeded(tokensRef, fieldName)
  1163  	if err != nil {
  1164  		return err
  1165  	}
  1166  
  1167  	whereToken := createWhereTokenWithOptions(whereOperatorSearch, fieldName, q.addQueryParameter(searchTerms), newWhereOptionsWithOperator(operator))
  1168  
  1169  	tokens := *tokensRef
  1170  	tokens = append(tokens, whereToken)
  1171  	*tokensRef = tokens
  1172  	return nil
  1173  }
  1174  
  1175  func (q *abstractDocumentQuery) string() (string, error) {
  1176  	if q.queryRaw != "" {
  1177  		return q.queryRaw, nil
  1178  	}
  1179  
  1180  	if q.currentClauseDepth != 0 {
  1181  		return "", newIllegalStateError("A clause was not closed correctly within this query, current clause depth = %d", q.currentClauseDepth)
  1182  	}
  1183  
  1184  	queryText := &strings.Builder{}
  1185  
  1186  	err := q.buildDeclare(queryText)
  1187  	if err != nil {
  1188  		return "", err
  1189  	}
  1190  	err = q.buildFrom(queryText)
  1191  	if err != nil {
  1192  		return "", err
  1193  	}
  1194  	err = q.buildGroupBy(queryText)
  1195  	if err != nil {
  1196  		return "", err
  1197  	}
  1198  	err = q.buildWhere(queryText)
  1199  	if err != nil {
  1200  		return "", err
  1201  	}
  1202  	err = q.buildOrderBy(queryText)
  1203  
  1204  	err = q.buildLoad(queryText)
  1205  	if err != nil {
  1206  		return "", err
  1207  	}
  1208  	err = q.buildSelect(queryText)
  1209  	if err != nil {
  1210  		return "", err
  1211  	}
  1212  	err = q.buildInclude(queryText)
  1213  	if err != nil {
  1214  		return "", err
  1215  	}
  1216  
  1217  	return queryText.String(), nil
  1218  }
  1219  
  1220  func (q *abstractDocumentQuery) buildInclude(queryText *strings.Builder) error {
  1221  	if len(q.includes) == 0 {
  1222  		return nil
  1223  	}
  1224  
  1225  	q.includes = stringArrayRemoveDuplicates(q.includes)
  1226  	queryText.WriteString(" include ")
  1227  	for i, include := range q.includes {
  1228  		if i > 0 {
  1229  			queryText.WriteString(",")
  1230  		}
  1231  
  1232  		requiredQuotes := false
  1233  
  1234  		for _, ch := range include {
  1235  			if !isLetterOrDigit(ch) && ch != '_' && ch != '.' {
  1236  				requiredQuotes = true
  1237  				break
  1238  			}
  1239  		}
  1240  
  1241  		if requiredQuotes {
  1242  			s := strings.Replace(include, "'", "\\'", -1)
  1243  			queryText.WriteString("'")
  1244  			queryText.WriteString(s)
  1245  			queryText.WriteString("'")
  1246  		} else {
  1247  			queryText.WriteString(include)
  1248  		}
  1249  	}
  1250  	return nil
  1251  }
  1252  
  1253  func (q *abstractDocumentQuery) intersect() error {
  1254  
  1255  	tokensRef, err := q.getCurrentWhereTokensRef()
  1256  	if err != nil {
  1257  		return err
  1258  	}
  1259  	tokens := *tokensRef
  1260  	n := len(tokens)
  1261  	if n > 0 {
  1262  		last := tokens[n-1]
  1263  		_, isWhere := last.(*whereToken)
  1264  		_, isClose := last.(*closeSubclauseToken)
  1265  		if isWhere || isClose {
  1266  			q.isIntersect = true
  1267  
  1268  			tokens = append(tokens, intersectMarkerTokenInstance)
  1269  			*tokensRef = tokens
  1270  			return nil
  1271  		}
  1272  	}
  1273  
  1274  	return newIllegalStateError("Cannot add INTERSECT at this point.")
  1275  }
  1276  
  1277  func (q *abstractDocumentQuery) whereExists(fieldName string) error {
  1278  	var err error
  1279  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1280  	if err != nil {
  1281  		return err
  1282  	}
  1283  
  1284  	tokensRef, err := q.getCurrentWhereTokensRef()
  1285  	if err != nil {
  1286  		return err
  1287  	}
  1288  	err = q.appendOperatorIfNeeded(tokensRef)
  1289  	if err != nil {
  1290  		return err
  1291  	}
  1292  	err = q.negateIfNeeded(tokensRef, fieldName)
  1293  	if err != nil {
  1294  		return err
  1295  	}
  1296  
  1297  	tokens := *tokensRef
  1298  	tokens = append(tokens, createWhereToken(whereOperatorExists, fieldName, ""))
  1299  	*tokensRef = tokens
  1300  	return nil
  1301  }
  1302  
  1303  func (q *abstractDocumentQuery) containsAny(fieldName string, values []interface{}) error {
  1304  	var err error
  1305  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1306  	if err != nil {
  1307  		return err
  1308  	}
  1309  
  1310  	tokensRef, err := q.getCurrentWhereTokensRef()
  1311  	if err != nil {
  1312  		return err
  1313  	}
  1314  	err = q.appendOperatorIfNeeded(tokensRef)
  1315  	if err != nil {
  1316  		return err
  1317  	}
  1318  	err = q.negateIfNeeded(tokensRef, fieldName)
  1319  	if err != nil {
  1320  		return err
  1321  	}
  1322  
  1323  	array := q.transformCollection(fieldName, abstractDocumentQueryUnpackCollection(values))
  1324  	whereToken := createWhereTokenWithOptions(whereOperatorIn, fieldName, q.addQueryParameter(array), newWhereOptionsWithExact(false))
  1325  
  1326  	tokens := *tokensRef
  1327  	tokens = append(tokens, whereToken)
  1328  	*tokensRef = tokens
  1329  	return nil
  1330  }
  1331  
  1332  func (q *abstractDocumentQuery) containsAll(fieldName string, values []interface{}) error {
  1333  	var err error
  1334  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1335  	if err != nil {
  1336  		return err
  1337  	}
  1338  
  1339  	tokensRef, err := q.getCurrentWhereTokensRef()
  1340  	if err != nil {
  1341  		return err
  1342  	}
  1343  	err = q.appendOperatorIfNeeded(tokensRef)
  1344  	if err != nil {
  1345  		return err
  1346  	}
  1347  	err = q.negateIfNeeded(tokensRef, fieldName)
  1348  	if err != nil {
  1349  		return err
  1350  	}
  1351  
  1352  	array := q.transformCollection(fieldName, abstractDocumentQueryUnpackCollection(values))
  1353  
  1354  	tokens := *tokensRef
  1355  	if len(array) == 0 {
  1356  		tokens = append(tokens, trueTokenInstance)
  1357  	} else {
  1358  		whereToken := createWhereToken(whereOperatorAllIn, fieldName, q.addQueryParameter(array))
  1359  		tokens = append(tokens, whereToken)
  1360  	}
  1361  	*tokensRef = tokens
  1362  	return nil
  1363  }
  1364  
  1365  func (q *abstractDocumentQuery) distinct() error {
  1366  	if q.isDistinct() {
  1367  		return newIllegalStateError("The is already a distinct query")
  1368  	}
  1369  
  1370  	if len(q.selectTokens) == 0 {
  1371  		q.selectTokens = []queryToken{distinctTokenInstance}
  1372  		return nil
  1373  	}
  1374  	q.selectTokens = append([]queryToken{distinctTokenInstance}, q.selectTokens...)
  1375  	return nil
  1376  }
  1377  
  1378  func (q *abstractDocumentQuery) updateStatsAndHighlightings(queryResult *QueryResult) {
  1379  	q.queryStats.UpdateQueryStats(queryResult)
  1380  	//TBD 4.1 Highlightings.Update(queryResult);
  1381  }
  1382  
  1383  func (q *abstractDocumentQuery) buildSelect(writer *strings.Builder) error {
  1384  	if len(q.selectTokens) == 0 {
  1385  		return nil
  1386  	}
  1387  
  1388  	writer.WriteString(" select ")
  1389  
  1390  	if len(q.selectTokens) == 1 {
  1391  		tok := q.selectTokens[0]
  1392  		if dtok, ok := tok.(*distinctToken); ok {
  1393  			if err := dtok.writeTo(writer); err != nil {
  1394  				return err
  1395  			}
  1396  			writer.WriteString(" *")
  1397  			return nil
  1398  		}
  1399  	}
  1400  
  1401  	for i, token := range q.selectTokens {
  1402  		if i > 0 {
  1403  			prevToken := q.selectTokens[i-1]
  1404  			if _, ok := prevToken.(*distinctToken); !ok {
  1405  				writer.WriteString(",")
  1406  			}
  1407  		}
  1408  
  1409  		var prevToken queryToken
  1410  		if i > 0 {
  1411  			prevToken = q.selectTokens[i-1]
  1412  		}
  1413  		documentQueryHelperAddSpaceIfNeeded(prevToken, token, writer)
  1414  
  1415  		if err := token.writeTo(writer); err != nil {
  1416  			return err
  1417  		}
  1418  	}
  1419  	return nil
  1420  }
  1421  
  1422  func (q *abstractDocumentQuery) buildFrom(writer *strings.Builder) error {
  1423  	return q.fromToken.writeTo(writer)
  1424  }
  1425  
  1426  func (q *abstractDocumentQuery) buildDeclare(writer *strings.Builder) error {
  1427  	if q.declareToken != nil {
  1428  		return q.declareToken.writeTo(writer)
  1429  	}
  1430  	return nil
  1431  }
  1432  
  1433  func (q *abstractDocumentQuery) buildLoad(writer *strings.Builder) error {
  1434  	if len(q.loadTokens) == 0 {
  1435  		return nil
  1436  	}
  1437  
  1438  	writer.WriteString(" load ")
  1439  
  1440  	for i, tok := range q.loadTokens {
  1441  		if i != 0 {
  1442  			writer.WriteString(", ")
  1443  		}
  1444  
  1445  		if err := tok.writeTo(writer); err != nil {
  1446  			return err
  1447  		}
  1448  	}
  1449  	return nil
  1450  }
  1451  
  1452  func (q *abstractDocumentQuery) buildWhere(writer *strings.Builder) error {
  1453  	if len(q.whereTokens) == 0 {
  1454  		return nil
  1455  	}
  1456  
  1457  	writer.WriteString(" where ")
  1458  
  1459  	if q.isIntersect {
  1460  		writer.WriteString("intersect(")
  1461  	}
  1462  
  1463  	for i, tok := range q.whereTokens {
  1464  		var prevToken queryToken
  1465  		if i > 0 {
  1466  			prevToken = q.whereTokens[i-1]
  1467  		}
  1468  		documentQueryHelperAddSpaceIfNeeded(prevToken, tok, writer)
  1469  		if err := tok.writeTo(writer); err != nil {
  1470  			return err
  1471  		}
  1472  	}
  1473  
  1474  	if q.isIntersect {
  1475  		writer.WriteString(") ")
  1476  	}
  1477  	return nil
  1478  }
  1479  
  1480  func (q *abstractDocumentQuery) buildGroupBy(writer *strings.Builder) error {
  1481  	if len(q.groupByTokens) == 0 {
  1482  		return nil
  1483  	}
  1484  
  1485  	writer.WriteString(" group by ")
  1486  
  1487  	for i, token := range q.groupByTokens {
  1488  		if i > 0 {
  1489  			writer.WriteString(", ")
  1490  		}
  1491  		if err := token.writeTo(writer); err != nil {
  1492  			return err
  1493  		}
  1494  	}
  1495  	return nil
  1496  }
  1497  
  1498  func (q *abstractDocumentQuery) buildOrderBy(writer *strings.Builder) error {
  1499  	if len(q.orderByTokens) == 0 {
  1500  		return nil
  1501  	}
  1502  
  1503  	writer.WriteString(" order by ")
  1504  
  1505  	for i, token := range q.orderByTokens {
  1506  		if i > 0 {
  1507  			writer.WriteString(", ")
  1508  		}
  1509  
  1510  		if err := token.writeTo(writer); err != nil {
  1511  			return err
  1512  		}
  1513  	}
  1514  	return nil
  1515  }
  1516  
  1517  func (q *abstractDocumentQuery) appendOperatorIfNeeded(tokensRef *[]queryToken) error {
  1518  	tokens := *tokensRef
  1519  	if err := q.assertNoRawQuery(); err != nil {
  1520  		return err
  1521  	}
  1522  
  1523  	n := len(tokens)
  1524  	if len(tokens) == 0 {
  1525  		return nil
  1526  	}
  1527  
  1528  	lastToken := tokens[n-1]
  1529  	_, isWhereToken := lastToken.(*whereToken)
  1530  	_, isCloseSubclauseToken := lastToken.(*closeSubclauseToken)
  1531  	if !isWhereToken && !isCloseSubclauseToken {
  1532  		return nil
  1533  	}
  1534  
  1535  	var lastWhere *whereToken
  1536  
  1537  	for i := n - 1; i >= 0; i-- {
  1538  		tok := tokens[i]
  1539  		if maybeLastWhere, ok := tok.(*whereToken); ok {
  1540  			lastWhere = maybeLastWhere
  1541  			break
  1542  		}
  1543  	}
  1544  
  1545  	var token *queryOperatorToken
  1546  	if q.defaultOperator == QueryOperatorAnd {
  1547  		token = queryOperatorTokenAnd
  1548  	} else {
  1549  		token = queryOperatorTokenOr
  1550  	}
  1551  
  1552  	if lastWhere != nil && lastWhere.options.searchOperator != SearchOperatorUnset {
  1553  		token = queryOperatorTokenOr // default to OR operator after search if AND was not specified explicitly
  1554  	}
  1555  
  1556  	tokens = append(tokens, token)
  1557  	*tokensRef = tokens
  1558  	return nil
  1559  }
  1560  
  1561  func (q *abstractDocumentQuery) transformCollection(fieldName string, values []interface{}) []interface{} {
  1562  	var result []interface{}
  1563  	for _, value := range values {
  1564  		if collectionValue, ok := value.([]interface{}); ok {
  1565  			tmp := q.transformCollection(fieldName, collectionValue)
  1566  			result = append(result, tmp...)
  1567  		} else {
  1568  			nestedWhereParams := &whereParams{
  1569  				allowWildcards: true,
  1570  				fieldName:      fieldName,
  1571  				value:          value,
  1572  			}
  1573  			tmp := q.transformValue(nestedWhereParams)
  1574  			result = append(result, tmp)
  1575  		}
  1576  	}
  1577  	return result
  1578  }
  1579  
  1580  func (q *abstractDocumentQuery) negateIfNeeded(tokensRef *[]queryToken, fieldName string) error {
  1581  	var err error
  1582  	if !q.negate {
  1583  		return nil
  1584  	}
  1585  
  1586  	q.negate = false
  1587  
  1588  	tokens := *tokensRef
  1589  
  1590  	n := len(tokens)
  1591  	isOpenSubclauseToken := false
  1592  	if n > 0 {
  1593  		_, isOpenSubclauseToken = tokens[n-1].(*openSubclauseToken)
  1594  	}
  1595  	if n == 0 || isOpenSubclauseToken {
  1596  		if fieldName != "" {
  1597  			err = q.whereExists(fieldName)
  1598  			if err != nil {
  1599  				return err
  1600  			}
  1601  		} else {
  1602  			err = q.whereTrue()
  1603  			if err != nil {
  1604  				return err
  1605  			}
  1606  		}
  1607  		err = q.andAlso()
  1608  		if err != nil {
  1609  			return err
  1610  		}
  1611  	}
  1612  
  1613  	tokens = append(tokens, negateTokenInstance)
  1614  	*tokensRef = tokens
  1615  	return nil
  1616  }
  1617  
  1618  func abstractDocumentQueryUnpackCollection(items []interface{}) []interface{} {
  1619  	var results []interface{}
  1620  
  1621  	for _, item := range items {
  1622  		if itemCollection, ok := item.([]interface{}); ok {
  1623  			els := abstractDocumentQueryUnpackCollection(itemCollection)
  1624  			results = append(results, els...)
  1625  		} else {
  1626  			results = append(results, item)
  1627  		}
  1628  	}
  1629  
  1630  	return results
  1631  }
  1632  
  1633  func (q *abstractDocumentQuery) ensureValidFieldName(fieldName string, isNestedPath bool) (string, error) {
  1634  	if q.theSession == nil || q.theSession.GetConventions() == nil || isNestedPath || q.isGroupBy {
  1635  		return queryFieldUtilEscapeIfNecessary(fieldName), nil
  1636  	}
  1637  
  1638  	if fieldName == documentConventionsIdentityPropertyName {
  1639  		return IndexingFieldNameDocumentID, nil
  1640  	}
  1641  
  1642  	return queryFieldUtilEscapeIfNecessary(fieldName), nil
  1643  }
  1644  
  1645  func (q *abstractDocumentQuery) transformValue(whereParams *whereParams) interface{} {
  1646  	return q.transformValueWithRange(whereParams, false)
  1647  }
  1648  
  1649  func (q *abstractDocumentQuery) transformValueWithRange(whereParams *whereParams, forRange bool) interface{} {
  1650  	if whereParams.value == nil {
  1651  		return nil
  1652  	}
  1653  
  1654  	if "" == whereParams.value {
  1655  		return ""
  1656  	}
  1657  
  1658  	var stringValueReference string
  1659  	if q.conventions.TryConvertValueForQuery(whereParams.fieldName, whereParams.value, forRange, &stringValueReference) {
  1660  		return stringValueReference
  1661  	}
  1662  
  1663  	val := whereParams.value
  1664  	switch v := val.(type) {
  1665  	case time.Time, string, int, int32, int64, float32, float64, bool:
  1666  		return val
  1667  	case time.Duration:
  1668  		n := int64(v/time.Nanosecond) / 100
  1669  		return n
  1670  	}
  1671  	return whereParams.value
  1672  }
  1673  
  1674  func (q *abstractDocumentQuery) addQueryParameter(value interface{}) string {
  1675  	parameterName := "p" + strconv.Itoa(len(q.queryParameters))
  1676  	q.queryParameters[parameterName] = value
  1677  	return parameterName
  1678  }
  1679  
  1680  func (q *abstractDocumentQuery) getCurrentWhereTokens() ([]queryToken, error) {
  1681  	if !q.isInMoreLikeThis {
  1682  		return q.whereTokens, nil
  1683  	}
  1684  
  1685  	n := len(q.whereTokens)
  1686  
  1687  	if n == 0 {
  1688  		return nil, newIllegalStateError("Cannot get moreLikeThisToken because there are no where token specified.")
  1689  	}
  1690  
  1691  	lastToken := q.whereTokens[n-1]
  1692  
  1693  	if moreLikeThisToken, ok := lastToken.(*moreLikeThisToken); ok {
  1694  		return moreLikeThisToken.whereTokens, nil
  1695  	}
  1696  	return nil, newIllegalStateError("Last token is not moreLikeThisToken")
  1697  }
  1698  
  1699  func (q *abstractDocumentQuery) getCurrentWhereTokensRef() (*[]queryToken, error) {
  1700  	if !q.isInMoreLikeThis {
  1701  		return &q.whereTokens, nil
  1702  	}
  1703  
  1704  	n := len(q.whereTokens)
  1705  
  1706  	if n == 0 {
  1707  		return nil, newIllegalStateError("Cannot get moreLikeThisToken because there are no where token specified.")
  1708  	}
  1709  
  1710  	lastToken := q.whereTokens[n-1]
  1711  
  1712  	if moreLikeThisToken, ok := lastToken.(*moreLikeThisToken); ok {
  1713  		return &moreLikeThisToken.whereTokens, nil
  1714  	}
  1715  	return nil, newIllegalStateError("Last token is not moreLikeThisToken")
  1716  }
  1717  
  1718  func (q *abstractDocumentQuery) updateFieldsToFetchToken(fieldsToFetch *fieldsToFetchToken) {
  1719  	q.fieldsToFetchToken = fieldsToFetch
  1720  
  1721  	if len(q.selectTokens) == 0 {
  1722  		q.selectTokens = append(q.selectTokens, fieldsToFetch)
  1723  		return
  1724  	}
  1725  
  1726  	for _, x := range q.selectTokens {
  1727  		if _, ok := x.(*fieldsToFetchToken); ok {
  1728  			for idx, tok := range q.selectTokens {
  1729  				if tok == x {
  1730  					q.selectTokens[idx] = fieldsToFetch
  1731  				}
  1732  			}
  1733  			return
  1734  		}
  1735  	}
  1736  	q.selectTokens = append(q.selectTokens, fieldsToFetch)
  1737  }
  1738  
  1739  func getSourceAliasIfExists(clazz reflect.Type, queryData *QueryData, fields []string) string {
  1740  	if len(fields) != 1 || fields[0] == "" {
  1741  		return ""
  1742  	}
  1743  
  1744  	if clazz != reflect.TypeOf("") && !isPrimitiveOrWrapper(clazz) {
  1745  		return ""
  1746  	}
  1747  	indexOf := strings.Index(fields[0], ".")
  1748  	if indexOf == -1 {
  1749  		return ""
  1750  	}
  1751  
  1752  	possibleAlias := fields[0][:indexOf]
  1753  	if queryData.fromAlias == possibleAlias {
  1754  		return possibleAlias
  1755  	}
  1756  
  1757  	if len(queryData.loadTokens) == 0 {
  1758  		return ""
  1759  	}
  1760  
  1761  	// TODO: is this the logic?
  1762  	for _, x := range queryData.loadTokens {
  1763  		if x.alias == possibleAlias {
  1764  			return possibleAlias
  1765  		}
  1766  	}
  1767  	return ""
  1768  }
  1769  
  1770  func (q *abstractDocumentQuery) addBeforeQueryExecutedListener(action func(*IndexQuery)) int {
  1771  	q.beforeQueryExecutedCallback = append(q.beforeQueryExecutedCallback, action)
  1772  	return len(q.beforeQueryExecutedCallback) - 1
  1773  }
  1774  
  1775  func (q *abstractDocumentQuery) removeBeforeQueryExecutedListener(idx int) {
  1776  	q.beforeQueryExecutedCallback[idx] = nil
  1777  }
  1778  
  1779  func (q *abstractDocumentQuery) addAfterQueryExecutedListener(action func(*QueryResult)) int {
  1780  	q.afterQueryExecutedCallback = append(q.afterQueryExecutedCallback, action)
  1781  	return len(q.afterQueryExecutedCallback) - 1
  1782  }
  1783  
  1784  func (q *abstractDocumentQuery) removeAfterQueryExecutedListener(idx int) {
  1785  	q.afterQueryExecutedCallback[idx] = nil
  1786  }
  1787  
  1788  func (q *abstractDocumentQuery) addAfterStreamExecutedListener(action func(map[string]interface{})) int {
  1789  	q.afterStreamExecutedCallback = append(q.afterStreamExecutedCallback, action)
  1790  	return len(q.afterStreamExecutedCallback) - 1
  1791  }
  1792  
  1793  func (q *abstractDocumentQuery) removeAfterStreamExecutedListener(idx int) {
  1794  	q.afterStreamExecutedCallback[idx] = nil
  1795  }
  1796  
  1797  func (q *abstractDocumentQuery) noTracking() {
  1798  	q.disableEntitiesTracking = true
  1799  }
  1800  
  1801  func (q *abstractDocumentQuery) noCaching() {
  1802  	q.disableCaching = true
  1803  }
  1804  
  1805  func (q *abstractDocumentQuery) withinRadiusOf(fieldName string, radius float64, latitude float64, longitude float64, radiusUnits SpatialUnits, distErrorPercent float64) error {
  1806  	var err error
  1807  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1808  	if err != nil {
  1809  		return err
  1810  	}
  1811  
  1812  	tokensRef, err := q.getCurrentWhereTokensRef()
  1813  	if err != nil {
  1814  		return err
  1815  	}
  1816  	err = q.appendOperatorIfNeeded(tokensRef)
  1817  	if err != nil {
  1818  		return err
  1819  	}
  1820  	err = q.negateIfNeeded(tokensRef, fieldName)
  1821  	if err != nil {
  1822  		return err
  1823  	}
  1824  
  1825  	shape := shapeTokenCircle(q.addQueryParameter(radius), q.addQueryParameter(latitude), q.addQueryParameter(longitude), radiusUnits)
  1826  	opts := newWhereOptionsWithTokenAndDistance(shape, distErrorPercent)
  1827  	whereToken := createWhereTokenWithOptions(whereOperatorSpatialWithin, fieldName, "", opts)
  1828  
  1829  	tokens := *tokensRef
  1830  	tokens = append(tokens, whereToken)
  1831  	*tokensRef = tokens
  1832  	return nil
  1833  }
  1834  
  1835  func (q *abstractDocumentQuery) spatial(fieldName string, shapeWkt string, relation SpatialRelation, distErrorPercent float64) error {
  1836  	var err error
  1837  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1838  	if err != nil {
  1839  		return err
  1840  	}
  1841  
  1842  	tokensRef, err := q.getCurrentWhereTokensRef()
  1843  	if err != nil {
  1844  		return err
  1845  	}
  1846  	err = q.appendOperatorIfNeeded(tokensRef)
  1847  	if err != nil {
  1848  		return err
  1849  	}
  1850  	err = q.negateIfNeeded(tokensRef, fieldName)
  1851  	if err != nil {
  1852  		return err
  1853  	}
  1854  
  1855  	wktToken := shapeTokenWkt(q.addQueryParameter(shapeWkt))
  1856  
  1857  	var whereOperator whereOperator
  1858  	switch relation {
  1859  	case SpatialRelationWithin:
  1860  		whereOperator = whereOperatorSpatialWithin
  1861  	case SpatialRelationContains:
  1862  		whereOperator = whereOperatorSpatialContains
  1863  	case SpatialRelationDisjoin:
  1864  		whereOperator = whereOperatorSpatialDisjoint
  1865  	case SpatialRelationIntersects:
  1866  		whereOperator = whereOperatorSpatialIntersects
  1867  	default:
  1868  		return newIllegalArgumentError("unknown relation %s", relation)
  1869  	}
  1870  
  1871  	tokens := *tokensRef
  1872  	opts := newWhereOptionsWithTokenAndDistance(wktToken, distErrorPercent)
  1873  	tok := createWhereTokenWithOptions(whereOperator, fieldName, "", opts)
  1874  	tokens = append(tokens, tok)
  1875  	*tokensRef = tokens
  1876  	return nil
  1877  }
  1878  
  1879  func (q *abstractDocumentQuery) spatial2(dynamicField DynamicSpatialField, criteria SpatialCriteria) error {
  1880  	if err := q.assertIsDynamicQuery(dynamicField, "spatial"); err != nil {
  1881  		return err
  1882  	}
  1883  
  1884  	tokensRef, err := q.getCurrentWhereTokensRef()
  1885  	if err != nil {
  1886  		return err
  1887  	}
  1888  	err = q.appendOperatorIfNeeded(tokensRef)
  1889  	if err != nil {
  1890  		return err
  1891  	}
  1892  	err = q.negateIfNeeded(tokensRef, "")
  1893  	if err != nil {
  1894  		return err
  1895  	}
  1896  
  1897  	ensure := func(fieldName string, isNestedPath bool) (string, error) {
  1898  		return q.ensureValidFieldName(fieldName, isNestedPath)
  1899  	}
  1900  	fieldName, err := dynamicField.ToField(ensure)
  1901  	if err != nil {
  1902  		return err
  1903  	}
  1904  	add := func(value interface{}) string {
  1905  		return q.addQueryParameter(value)
  1906  	}
  1907  	tok := criteria.ToQueryToken(fieldName, add)
  1908  	tokens := *tokensRef
  1909  	tokens = append(tokens, tok)
  1910  	*tokensRef = tokens
  1911  	return nil
  1912  }
  1913  
  1914  func (q *abstractDocumentQuery) spatial3(fieldName string, criteria SpatialCriteria) error {
  1915  	var err error
  1916  	fieldName, err = q.ensureValidFieldName(fieldName, false)
  1917  	if err != nil {
  1918  		return err
  1919  	}
  1920  
  1921  	tokensRef, err := q.getCurrentWhereTokensRef()
  1922  	if err != nil {
  1923  		return err
  1924  	}
  1925  	err = q.appendOperatorIfNeeded(tokensRef)
  1926  	if err != nil {
  1927  		return err
  1928  	}
  1929  	err = q.negateIfNeeded(tokensRef, fieldName)
  1930  	if err != nil {
  1931  		return err
  1932  	}
  1933  
  1934  	tokens := *tokensRef
  1935  	add := func(value interface{}) string {
  1936  		return q.addQueryParameter(value)
  1937  	}
  1938  	tok := criteria.ToQueryToken(fieldName, add)
  1939  	tokens = append(tokens, tok)
  1940  	*tokensRef = tokens
  1941  	return nil
  1942  }
  1943  
  1944  func (q *abstractDocumentQuery) orderByDistanceLatLongDynamic(field DynamicSpatialField, latitude float64, longitude float64) error {
  1945  	if field == nil {
  1946  		return newIllegalArgumentError("Field cannot be null")
  1947  	}
  1948  	if err := q.assertIsDynamicQuery(field, "orderByDistance"); err != nil {
  1949  		return err
  1950  	}
  1951  
  1952  	ensure := func(fieldName string, isNestedPath bool) (string, error) {
  1953  		return q.ensureValidFieldName(fieldName, isNestedPath)
  1954  	}
  1955  	fieldName, err := field.ToField(ensure)
  1956  	if err != nil {
  1957  		return err
  1958  	}
  1959  	return q.orderByDistanceLatLong("'"+fieldName+"'", latitude, longitude)
  1960  }
  1961  
  1962  func (q *abstractDocumentQuery) orderByDistanceLatLong(fieldName string, latitude float64, longitude float64) error {
  1963  	tok := orderByTokenCreateDistanceAscending(fieldName, q.addQueryParameter(latitude), q.addQueryParameter(longitude))
  1964  	q.orderByTokens = append(q.orderByTokens, tok)
  1965  	return nil
  1966  }
  1967  
  1968  func (q *abstractDocumentQuery) orderByDistanceWktDynamic(field DynamicSpatialField, shapeWkt string) error {
  1969  	if field == nil {
  1970  		return newIllegalArgumentError("Field cannot be null")
  1971  	}
  1972  	err := q.assertIsDynamicQuery(field, "orderByDistance2")
  1973  	if err != nil {
  1974  		return err
  1975  	}
  1976  
  1977  	ensure := func(fieldName string, isNestedPath bool) (string, error) {
  1978  		return q.ensureValidFieldName(fieldName, isNestedPath)
  1979  	}
  1980  	fieldName, err := field.ToField(ensure)
  1981  	if err != nil {
  1982  		return err
  1983  	}
  1984  	return q.orderByDistance3("'"+fieldName+"'", shapeWkt)
  1985  }
  1986  
  1987  func (q *abstractDocumentQuery) orderByDistance3(fieldName string, shapeWkt string) error {
  1988  	tok := orderByTokenCreateDistanceAscending2(fieldName, q.addQueryParameter(shapeWkt))
  1989  	q.orderByTokens = append(q.orderByTokens, tok)
  1990  	return nil
  1991  }
  1992  
  1993  func (q *abstractDocumentQuery) orderByDistanceDescendingLatLongDynamic(field DynamicSpatialField, latitude float64, longitude float64) error {
  1994  	if field == nil {
  1995  		return newIllegalArgumentError("Field cannot be null")
  1996  	}
  1997  	err := q.assertIsDynamicQuery(field, "orderByDistanceDescending")
  1998  	if err != nil {
  1999  		return err
  2000  	}
  2001  	ensure := func(fieldName string, isNestedPath bool) (string, error) {
  2002  		return q.ensureValidFieldName(fieldName, isNestedPath)
  2003  	}
  2004  	fieldName, err := field.ToField(ensure)
  2005  	if err != nil {
  2006  		return err
  2007  	}
  2008  	return q.orderByDistanceDescendingLatLong("'"+fieldName+"'", latitude, longitude)
  2009  }
  2010  
  2011  func (q *abstractDocumentQuery) orderByDistanceDescendingLatLong(fieldName string, latitude float64, longitude float64) error {
  2012  	tok := orderByTokenCreateDistanceDescending(fieldName, q.addQueryParameter(latitude), q.addQueryParameter(longitude))
  2013  	q.orderByTokens = append(q.orderByTokens, tok)
  2014  	return nil
  2015  }
  2016  
  2017  func (q *abstractDocumentQuery) orderByDistanceDescendingWktDynamic(field DynamicSpatialField, shapeWkt string) error {
  2018  	if field == nil {
  2019  		return newIllegalArgumentError("Field cannot be null")
  2020  	}
  2021  	err := q.assertIsDynamicQuery(field, "orderByDistanceDescending2")
  2022  	if err != nil {
  2023  		return err
  2024  	}
  2025  	ensure := func(fieldName string, isNestedPath bool) (string, error) {
  2026  		return q.ensureValidFieldName(fieldName, isNestedPath)
  2027  	}
  2028  	fieldName, err := field.ToField(ensure)
  2029  	if err != nil {
  2030  		return err
  2031  	}
  2032  	return q.orderByDistanceDescendingWkt("'"+fieldName+"'", shapeWkt)
  2033  }
  2034  
  2035  func (q *abstractDocumentQuery) orderByDistanceDescendingWkt(fieldName string, shapeWkt string) error {
  2036  	tok := orderByTokenCreateDistanceDescending2(fieldName, q.addQueryParameter(shapeWkt))
  2037  	q.orderByTokens = append(q.orderByTokens, tok)
  2038  	return nil
  2039  }
  2040  
  2041  func (q *abstractDocumentQuery) assertIsDynamicQuery(dynamicField DynamicSpatialField, methodName string) error {
  2042  	if q.fromToken != nil && !q.fromToken.isDynamic {
  2043  		f := func(s string, f bool) (string, error) {
  2044  			return q.ensureValidFieldName(s, f)
  2045  		}
  2046  		fld, err := dynamicField.ToField(f)
  2047  		if err != nil {
  2048  			return err
  2049  		}
  2050  		return newIllegalStateError("Cannot execute query method '" + methodName + "'. Field '" + fld + "' cannot be used when static index '" + q.fromToken.indexName + "' is queried. Dynamic spatial fields can only be used with dynamic queries, " + "for static index queries please use valid spatial fields defined in index definition.")
  2051  	}
  2052  	return nil
  2053  }
  2054  
  2055  func (q *abstractDocumentQuery) initSync() error {
  2056  	if q.queryOperation != nil {
  2057  		return nil
  2058  	}
  2059  
  2060  	delegate := &DocumentQueryCustomization{
  2061  		query: q,
  2062  	}
  2063  	beforeQueryEventArgs := &BeforeQueryEventArgs{
  2064  		Session:            q.theSession,
  2065  		QueryCustomization: delegate,
  2066  	}
  2067  	q.theSession.onBeforeQueryInvoke(beforeQueryEventArgs)
  2068  
  2069  	var err error
  2070  	q.queryOperation, err = q.initializeQueryOperation()
  2071  	if err != nil {
  2072  		return err
  2073  	}
  2074  	return q.executeActualQuery()
  2075  }
  2076  
  2077  func (q *abstractDocumentQuery) executeActualQuery() error {
  2078  	{
  2079  		context := q.queryOperation.enterQueryContext()
  2080  		defer func() {
  2081  			_ = context.Close()
  2082  		}()
  2083  
  2084  		command, err := q.queryOperation.createRequest()
  2085  		if err != nil {
  2086  			return err
  2087  		}
  2088  		if err = q.theSession.GetRequestExecutor().ExecuteCommand(command, q.theSession.sessionInfo); err != nil {
  2089  			return err
  2090  		}
  2091  		if err = q.queryOperation.setResult(command.Result); err != nil {
  2092  			return err
  2093  		}
  2094  	}
  2095  	q.invokeAfterQueryExecuted(q.queryOperation.currentQueryResults)
  2096  	return nil
  2097  }
  2098  
  2099  // GetQueryResult returns results of a query
  2100  func (q *abstractDocumentQuery) getQueryResult() (*QueryResult, error) {
  2101  	err := q.initSync()
  2102  	if err != nil {
  2103  		return nil, err
  2104  	}
  2105  
  2106  	return q.queryOperation.currentQueryResults.createSnapshot(), nil
  2107  }
  2108  
  2109  // check if v is a valid argument to query GetResults().
  2110  // it must be map[string]*<type> where <type> is struct
  2111  func checkValidGetResultsArg(v interface{}, argName string) error {
  2112  	return checkIsPtrSlice(v, argName)
  2113  }
  2114  
  2115  // GetResults executes the query and sets results to returned values.
  2116  // results should be of type *[]<type>
  2117  func (q *abstractDocumentQuery) GetResults(results interface{}) error {
  2118  	// Note: in Java it's called ToList
  2119  	if q.err != nil {
  2120  		return q.err
  2121  	}
  2122  	if q.err = checkValidGetResultsArg(results, "results"); q.err != nil {
  2123  		return q.err
  2124  	}
  2125  	return q.executeQueryOperation(results, -1)
  2126  }
  2127  
  2128  func checkValidSingleArg(v interface{}, argName string) error {
  2129  	if v == nil {
  2130  		return newIllegalArgumentError("%s can't be nil", argName)
  2131  	}
  2132  	return checkIsPtrPtrStruct(v, argName)
  2133  }
  2134  
  2135  // First runs a query and returns a first result.
  2136  func (q *abstractDocumentQuery) First(result interface{}) error {
  2137  	if q.err != nil {
  2138  		return q.err
  2139  	}
  2140  
  2141  	if q.err = checkValidSingleArg(result, "result"); q.err != nil {
  2142  		return q.err
  2143  	}
  2144  
  2145  	tp := reflect.TypeOf(result)
  2146  	// **struct => *struct
  2147  	if tp.Kind() == reflect.Ptr && tp.Elem().Kind() == reflect.Ptr {
  2148  		tp = tp.Elem()
  2149  	}
  2150  	// create a pointer to a slice. executeQueryOperation creates the actual slice
  2151  	sliceType := reflect.SliceOf(tp)
  2152  	slicePtr := reflect.New(sliceType)
  2153  	err := q.executeQueryOperation(slicePtr.Interface(), 1)
  2154  	if err != nil {
  2155  		return err
  2156  	}
  2157  	slice := slicePtr.Elem()
  2158  	if slice.Len() == 0 {
  2159  		return nil
  2160  	}
  2161  	el := slice.Index(0)
  2162  	return setInterfaceToValue(result, el.Interface())
  2163  }
  2164  
  2165  // Single runs a query that expects only a single result.
  2166  // If there is more than one result, it returns IllegalStateError.
  2167  func (q *abstractDocumentQuery) Single(result interface{}) error {
  2168  	if q.err != nil {
  2169  		return q.err
  2170  	}
  2171  
  2172  	if q.err = checkValidSingleArg(result, "result"); q.err != nil {
  2173  		return q.err
  2174  	}
  2175  
  2176  	tp := reflect.TypeOf(result)
  2177  	// **struct => *struct
  2178  	if tp.Kind() == reflect.Ptr && tp.Elem().Kind() == reflect.Ptr {
  2179  		tp = tp.Elem()
  2180  	}
  2181  	// create a pointer to a slice. executeQueryOperation creates the actual slice
  2182  	sliceType := reflect.SliceOf(tp)
  2183  	slicePtr := reflect.New(sliceType)
  2184  	err := q.executeQueryOperation(slicePtr.Interface(), 2)
  2185  	if err != nil {
  2186  		return err
  2187  	}
  2188  	slice := slicePtr.Elem()
  2189  	if slice.Len() != 1 {
  2190  		return newIllegalStateError("Expected single result, got: %d", slice.Len())
  2191  	}
  2192  	el := slice.Index(0)
  2193  	return setInterfaceToValue(result, el.Interface())
  2194  }
  2195  
  2196  func (q *abstractDocumentQuery) Count() (int, error) {
  2197  	if q.err != nil {
  2198  		return 0, q.err
  2199  	}
  2200  	q.take(0)
  2201  	queryResult, err := q.getQueryResult()
  2202  	if err != nil {
  2203  		return 0, err
  2204  	}
  2205  	return queryResult.TotalResults, nil
  2206  }
  2207  
  2208  // Any returns true if query returns at least one result
  2209  func (q *abstractDocumentQuery) Any() (bool, error) {
  2210  	if q.err != nil {
  2211  		return false, q.err
  2212  	}
  2213  	if q.isDistinct() {
  2214  		// for distinct it is cheaper to do count 1
  2215  
  2216  		q.take(1)
  2217  
  2218  		err := q.initSync()
  2219  		if err != nil {
  2220  			return false, err
  2221  		}
  2222  		return q.queryOperation.currentQueryResults.TotalResults > 0, nil
  2223  	}
  2224  
  2225  	q.take(0)
  2226  	queryResult, err := q.getQueryResult()
  2227  	if err != nil {
  2228  		return false, err
  2229  	}
  2230  	return queryResult.TotalResults > 0, nil
  2231  }
  2232  
  2233  func (q *abstractDocumentQuery) executeQueryOperation(results interface{}, take int) error {
  2234  	if take != -1 && (q.pageSize == nil || *q.pageSize > take) {
  2235  		q.take(take)
  2236  	}
  2237  
  2238  	err := q.initSync()
  2239  	if err != nil {
  2240  		return err
  2241  	}
  2242  
  2243  	return q.queryOperation.complete(results)
  2244  }
  2245  
  2246  func (q *abstractDocumentQuery) aggregateBy(facet FacetBase) error {
  2247  	for _, token := range q.selectTokens {
  2248  		if _, ok := token.(*facetToken); ok {
  2249  			continue
  2250  		}
  2251  
  2252  		return newIllegalStateError("Aggregation query can select only facets while it got %T token", token)
  2253  	}
  2254  
  2255  	add := func(o interface{}) string {
  2256  		return q.addQueryParameter(o)
  2257  	}
  2258  	t, err := createFacetTokenWithFacetBase(facet, add)
  2259  	if err != nil {
  2260  		return err
  2261  	}
  2262  	q.selectTokens = append(q.selectTokens, t)
  2263  	return nil
  2264  }
  2265  
  2266  func (q *abstractDocumentQuery) aggregateUsing(facetSetupDocumentID string) error {
  2267  	token, err := createFacetToken(facetSetupDocumentID)
  2268  	if err != nil {
  2269  		return err
  2270  	}
  2271  	q.selectTokens = append(q.selectTokens, token)
  2272  	return nil
  2273  }
  2274  
  2275  func (q *abstractDocumentQuery) Lazily() (*Lazy, error) {
  2276  	if q.err != nil {
  2277  		return nil, q.err
  2278  	}
  2279  	if q.queryOperation == nil {
  2280  		q.queryOperation, q.err = q.initializeQueryOperation()
  2281  		if q.err != nil {
  2282  			return nil, q.err
  2283  		}
  2284  	}
  2285  
  2286  	lazyQueryOperation := newLazyQueryOperation(q.theSession.GetConventions(), q.queryOperation, q.afterQueryExecutedCallback)
  2287  	return q.theSession.session.addLazyOperation(lazyQueryOperation, nil, nil), nil
  2288  }
  2289  
  2290  // CountLazily returns a lazy operation that returns number of results in a query. It'll set *count to
  2291  // number of results after Lazy.GetResult() is called.
  2292  // results should be of type []<type> and is only provided so that we know this is a query for <type>
  2293  // TODO: figure out better API.
  2294  func (q *abstractDocumentQuery) CountLazily() (*Lazy, error) {
  2295  	if q.queryOperation == nil {
  2296  		q.take(0)
  2297  		var err error
  2298  		q.queryOperation, err = q.initializeQueryOperation()
  2299  		if err != nil {
  2300  			return nil, err
  2301  		}
  2302  	}
  2303  
  2304  	lazyQueryOperation := newLazyQueryOperation(q.theSession.GetConventions(), q.queryOperation, q.afterQueryExecutedCallback)
  2305  	return q.theSession.session.addLazyCountOperation(lazyQueryOperation), nil
  2306  }
  2307  
  2308  // suggestUsing adds a query part for suggestions
  2309  func (q *abstractDocumentQuery) suggestUsing(suggestion SuggestionBase) error {
  2310  	if suggestion == nil {
  2311  		return newIllegalArgumentError("suggestion cannot be null")
  2312  	}
  2313  
  2314  	if err := q.assertCanSuggest(); err != nil {
  2315  		return err
  2316  	}
  2317  
  2318  	var token *suggestToken
  2319  
  2320  	if term, ok := suggestion.(*SuggestionWithTerm); ok {
  2321  		token = &suggestToken{
  2322  			fieldName:            term.Field,
  2323  			termParameterName:    q.addQueryParameter(term.Term),
  2324  			optionsParameterName: q.getOptionsParameterName(term.Options),
  2325  		}
  2326  	} else if terms, ok := suggestion.(*SuggestionWithTerms); ok {
  2327  		token = &suggestToken{
  2328  			fieldName:            terms.Field,
  2329  			termParameterName:    q.addQueryParameter(terms.Terms),
  2330  			optionsParameterName: q.getOptionsParameterName(terms.Options),
  2331  		}
  2332  	} else {
  2333  		return newUnsupportedOperationError("Unknown type of suggestion: %T", suggestion)
  2334  	}
  2335  	q.selectTokens = append(q.selectTokens, token)
  2336  	return nil
  2337  }
  2338  
  2339  func (q *abstractDocumentQuery) getOptionsParameterName(options *SuggestionOptions) string {
  2340  	optionsParameterName := ""
  2341  	if options != nil && options != SuggestionOptionsDefaultOptions {
  2342  		optionsParameterName = q.addQueryParameter(options)
  2343  	}
  2344  
  2345  	return optionsParameterName
  2346  }
  2347  
  2348  func (q *abstractDocumentQuery) assertCanSuggest() error {
  2349  	if len(q.whereTokens) > 0 {
  2350  		return newIllegalStateError("Cannot add suggest when WHERE statements are present.")
  2351  	}
  2352  
  2353  	if len(q.selectTokens) > 0 {
  2354  		return newIllegalStateError("Cannot add suggest when SELECT statements are present.")
  2355  	}
  2356  
  2357  	if len(q.orderByTokens) > 0 {
  2358  		return newIllegalStateError("Cannot add suggest when ORDER BY statements are present.")
  2359  	}
  2360  	return nil
  2361  }