go.mercari.io/datastore@v1.8.2/clouddatastore/query.go (about)

     1  package clouddatastore
     2  
     3  import (
     4  	"context"
     5  
     6  	"cloud.google.com/go/datastore"
     7  	w "go.mercari.io/datastore"
     8  	"go.mercari.io/datastore/internal/shared"
     9  )
    10  
    11  var _ w.Query = (*queryImpl)(nil)
    12  var _ w.Iterator = (*iteratorImpl)(nil)
    13  var _ w.Cursor = (*cursorImpl)(nil)
    14  
    15  type queryImpl struct {
    16  	ctx context.Context
    17  	q   *datastore.Query
    18  
    19  	dump *w.QueryDump
    20  
    21  	firstError error
    22  }
    23  
    24  type iteratorImpl struct {
    25  	client    *datastoreImpl
    26  	q         *queryImpl
    27  	qDump     *w.QueryDump
    28  	t         *datastore.Iterator
    29  	cacheInfo *w.MiddlewareInfo
    30  
    31  	firstError error
    32  }
    33  
    34  type cursorImpl struct {
    35  	cursor datastore.Cursor
    36  }
    37  
    38  func (q *queryImpl) clone() *queryImpl {
    39  	x := *q
    40  	d := *q.dump
    41  	d.Filter = d.Filter[:]
    42  	d.Order = d.Order[:]
    43  	d.Project = d.Project[:]
    44  	x.dump = &d
    45  	return &x
    46  }
    47  
    48  func (q *queryImpl) Ancestor(ancestor w.Key) w.Query {
    49  	q = q.clone()
    50  	q.q = q.q.Ancestor(toOriginalKey(ancestor))
    51  	q.dump.Ancestor = ancestor
    52  	return q
    53  }
    54  
    55  func (q *queryImpl) EventualConsistency() w.Query {
    56  	q = q.clone()
    57  	q.q = q.q.EventualConsistency()
    58  	q.dump.EventualConsistency = true
    59  	return q
    60  }
    61  
    62  func (q *queryImpl) Namespace(ns string) w.Query {
    63  	q = q.clone()
    64  	q.q = q.q.Namespace(ns)
    65  	q.dump.Namespace = ns
    66  	return q
    67  }
    68  
    69  func (q *queryImpl) Transaction(t w.Transaction) w.Query {
    70  	q = q.clone()
    71  	q.q = q.q.Transaction(toOriginalTransaction(t))
    72  	q.dump.Transaction = t
    73  	return q
    74  }
    75  
    76  func (q *queryImpl) Filter(filterStr string, value interface{}) w.Query {
    77  	q = q.clone()
    78  	var err error
    79  	if pt, ok := value.(w.PropertyTranslator); ok {
    80  		value, err = pt.ToPropertyValue(q.ctx)
    81  		if err != nil {
    82  			if q.firstError == nil {
    83  				q.firstError = err
    84  			}
    85  			return q
    86  		}
    87  	}
    88  	origV := toOriginalValue(value)
    89  	q.q = q.q.Filter(filterStr, origV)
    90  	q.dump.Filter = append(q.dump.Filter, &w.QueryFilterCondition{
    91  		Filter: filterStr,
    92  		Value:  value,
    93  	})
    94  	return q
    95  }
    96  
    97  func (q *queryImpl) Order(fieldName string) w.Query {
    98  	q = q.clone()
    99  	q.q = q.q.Order(fieldName)
   100  	q.dump.Order = append(q.dump.Order, fieldName)
   101  	return q
   102  }
   103  
   104  func (q *queryImpl) Project(fieldNames ...string) w.Query {
   105  	q = q.clone()
   106  	q.q = q.q.Project(fieldNames...)
   107  	q.dump.Project = append([]string(nil), fieldNames...)
   108  	return q
   109  }
   110  
   111  func (q *queryImpl) DistinctOn(fieldNames ...string) w.Query {
   112  	q = q.clone()
   113  	q.q = q.q.DistinctOn(fieldNames...)
   114  	q.dump.DistinctOn = append([]string(nil), fieldNames...)
   115  	return q
   116  }
   117  
   118  func (q *queryImpl) Distinct() w.Query {
   119  	q = q.clone()
   120  	q.q = q.q.Distinct()
   121  	q.dump.Distinct = true
   122  	return q
   123  }
   124  
   125  func (q *queryImpl) KeysOnly() w.Query {
   126  	q = q.clone()
   127  	q.q = q.q.KeysOnly()
   128  	q.dump.KeysOnly = true
   129  	return q
   130  }
   131  
   132  func (q *queryImpl) Limit(limit int) w.Query {
   133  	q = q.clone()
   134  	q.q = q.q.Limit(limit)
   135  	q.dump.Limit = limit
   136  	return q
   137  }
   138  
   139  func (q *queryImpl) Offset(offset int) w.Query {
   140  	q = q.clone()
   141  	q.q = q.q.Offset(offset)
   142  	q.dump.Offset = offset
   143  	return q
   144  }
   145  
   146  func (q *queryImpl) Start(c w.Cursor) w.Query {
   147  	q = q.clone()
   148  	curImpl := c.(*cursorImpl)
   149  	q.q = q.q.Start(curImpl.cursor)
   150  	q.dump.Start = c
   151  	return q
   152  }
   153  
   154  func (q *queryImpl) End(c w.Cursor) w.Query {
   155  	q = q.clone()
   156  	curImpl := c.(*cursorImpl)
   157  	q.q = q.q.End(curImpl.cursor)
   158  	q.dump.End = c
   159  	return q
   160  }
   161  
   162  func (q *queryImpl) Dump() *w.QueryDump {
   163  	return q.dump
   164  }
   165  
   166  func (t *iteratorImpl) Next(dst interface{}) (w.Key, error) {
   167  	if t.firstError != nil {
   168  		return nil, t.firstError
   169  	}
   170  
   171  	cb := shared.NewCacheBridge(t.cacheInfo, &originalClientBridgeImpl{t.client}, nil, &originalIteratorBridgeImpl{t.qDump}, t.client.middlewares)
   172  	return shared.NextOps(t.client.ctx, t.qDump, dst, func(dst *w.PropertyList) (w.Key, error) {
   173  		return cb.Next(t.cacheInfo, t.q, t.qDump, t, dst)
   174  	})
   175  }
   176  
   177  func (t *iteratorImpl) Cursor() (w.Cursor, error) {
   178  	if t.firstError != nil {
   179  		return nil, t.firstError
   180  	}
   181  
   182  	cur, err := t.t.Cursor()
   183  	if err != nil {
   184  		return nil, toWrapperError(err)
   185  	}
   186  
   187  	return &cursorImpl{cursor: cur}, nil
   188  }
   189  
   190  func (cur *cursorImpl) String() string {
   191  	if cur == nil {
   192  		return ""
   193  	}
   194  	return cur.cursor.String()
   195  }