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

     1  package testsuite
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  	"time"
     9  
    10  	"go.mercari.io/datastore"
    11  	"google.golang.org/api/iterator"
    12  )
    13  
    14  func queryCount(ctx context.Context, t *testing.T, client datastore.Client) {
    15  	defer func() {
    16  		err := client.Close()
    17  		if err != nil {
    18  			t.Fatal(err)
    19  		}
    20  	}()
    21  
    22  	type Data struct {
    23  		Str string
    24  	}
    25  
    26  	key1, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "A"})
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  	key2, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "B"})
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	key3, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "B"})
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  
    39  	t.Log(key1, key2, key3)
    40  
    41  	q := client.NewQuery("Data").Filter("Str =", "B")
    42  	count, err := client.Count(ctx, q)
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  
    47  	if count != 2 {
    48  		t.Errorf("unexpected: %v", count)
    49  	}
    50  }
    51  
    52  func queryGetAll(ctx context.Context, t *testing.T, client datastore.Client) {
    53  	defer func() {
    54  		err := client.Close()
    55  		if err != nil {
    56  			t.Fatal(err)
    57  		}
    58  	}()
    59  
    60  	type Data struct {
    61  		Str   string
    62  		Order int
    63  	}
    64  
    65  	key1, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "A", Order: 1})
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	key2, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "B", Order: 2})
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	key3, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Str: "B", Order: 3})
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	t.Log(key1, key2, key3)
    79  
    80  	{
    81  		client.GetMulti(ctx, []datastore.Key{key1, key2, key3}, []interface{}{&Data{}, &Data{}, &Data{}})
    82  	}
    83  
    84  	q := client.NewQuery("Data").Filter("Str =", "B").Order("Order")
    85  	var dataList []*Data
    86  	keys, err := client.GetAll(ctx, q, &dataList)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	if v := len(keys); v != 2 {
    92  		t.Fatalf("unexpected: %v", v)
    93  	}
    94  
    95  	if v := dataList[0].Order; v != 2 {
    96  		t.Errorf("unexpected: %v", v)
    97  	}
    98  	if v := dataList[1].Order; v != 3 {
    99  		t.Errorf("unexpected: %v", v)
   100  	}
   101  }
   102  
   103  func queryCursor(ctx context.Context, t *testing.T, client datastore.Client) {
   104  	defer func() {
   105  		err := client.Close()
   106  		if err != nil {
   107  			t.Fatal(err)
   108  		}
   109  	}()
   110  
   111  	type Data struct {
   112  		Str string
   113  	}
   114  
   115  	{
   116  		var keys []datastore.Key
   117  		var entities []*Data
   118  		for i := 0; i < 100; i++ {
   119  			keys = append(keys, client.IncompleteKey("Data", nil))
   120  			entities = append(entities, &Data{Str: fmt.Sprintf("#%d", i+1)})
   121  		}
   122  		var err error
   123  		_, err = client.PutMulti(ctx, keys, entities)
   124  		if err != nil {
   125  			t.Fatal(err)
   126  		}
   127  	}
   128  
   129  	var cur datastore.Cursor
   130  	var err error
   131  	var startCur datastore.Cursor
   132  	var endCur datastore.Cursor
   133  
   134  	var dataList []*Data
   135  	const limit = 3
   136  outer:
   137  	for {
   138  		q := client.NewQuery("Data").Order("Str").Limit(limit)
   139  		if cur != nil {
   140  			q = q.Start(cur)
   141  		}
   142  		it := client.Run(ctx, q)
   143  
   144  		count := 0
   145  		for {
   146  			obj := &Data{}
   147  			_, err := it.Next(obj)
   148  			if err == iterator.Done {
   149  				break
   150  			} else if err != nil {
   151  				t.Fatal(err)
   152  			}
   153  
   154  			dataList = append(dataList, obj)
   155  			count++
   156  		}
   157  		if count != limit {
   158  			break
   159  		}
   160  
   161  		cur, err = it.Cursor()
   162  		if err != nil {
   163  			t.Fatal(err)
   164  		}
   165  		if cur.String() == "" {
   166  			break outer
   167  		}
   168  		if startCur == nil {
   169  			startCur = cur
   170  		} else if endCur == nil {
   171  			endCur = cur
   172  		}
   173  	}
   174  
   175  	if v := len(dataList); v != 100 {
   176  		t.Errorf("unexpected: %v", v)
   177  	}
   178  
   179  	q := client.NewQuery("Data").Order("Str").Limit(limit)
   180  	q = q.Start(startCur).End(endCur).KeysOnly()
   181  	newKeys, err := client.GetAll(ctx, q, nil)
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	if v := len(newKeys); v != limit {
   186  		t.Errorf("unexpected: %v", v)
   187  	}
   188  }
   189  
   190  func queryNextByPropertyList(ctx context.Context, t *testing.T, client datastore.Client) {
   191  	defer func() {
   192  		err := client.Close()
   193  		if err != nil {
   194  			t.Fatal(err)
   195  		}
   196  	}()
   197  
   198  	type Data struct {
   199  		Name string
   200  	}
   201  
   202  	_, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Name: "A"})
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	q := client.NewQuery("Data")
   208  
   209  	{ // passed datastore.PropertyList, would be error.
   210  		iter := client.Run(ctx, q)
   211  
   212  		var ps datastore.PropertyList
   213  		_, err = iter.Next(ps)
   214  		if err == nil {
   215  			t.Fatal(err)
   216  		}
   217  	}
   218  	{ // ok! *datastore.PropertyList
   219  		iter := client.Run(ctx, q)
   220  
   221  		var ps datastore.PropertyList
   222  		_, err = iter.Next(&ps)
   223  		if err != nil {
   224  			t.Fatal(err)
   225  		}
   226  	}
   227  }
   228  
   229  func queryGetAllByPropertyListSlice(ctx context.Context, t *testing.T, client datastore.Client) {
   230  	defer func() {
   231  		err := client.Close()
   232  		if err != nil {
   233  			t.Fatal(err)
   234  		}
   235  	}()
   236  
   237  	type Data struct {
   238  		Name string
   239  	}
   240  
   241  	_, err := client.Put(ctx, client.IncompleteKey("Data", nil), &Data{Name: "A"})
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	q := client.NewQuery("Data")
   247  	var psList []datastore.PropertyList
   248  
   249  	// passed []datastore.PropertyList, would be error.
   250  	_, err = client.GetAll(ctx, q, psList)
   251  	if err == nil {
   252  		t.Fatal(err)
   253  	}
   254  
   255  	// ok! *[]datastore.PropertyList
   256  	psList = nil
   257  	_, err = client.GetAll(ctx, q, &psList)
   258  	if err != nil {
   259  		t.Fatal(err)
   260  	}
   261  }
   262  
   263  func filterBasic(ctx context.Context, t *testing.T, client datastore.Client) {
   264  	defer func() {
   265  		err := client.Close()
   266  		if err != nil {
   267  			t.Fatal(err)
   268  		}
   269  	}()
   270  
   271  	type Data struct {
   272  		Int      int
   273  		Bool     bool
   274  		String   string
   275  		Float    float64
   276  		Key      datastore.Key
   277  		GeoPoint datastore.GeoPoint
   278  		Time     time.Time
   279  	}
   280  
   281  	now := time.Now()
   282  
   283  	obj1 := &Data{
   284  		Int:      1,
   285  		Bool:     true,
   286  		String:   "1",
   287  		Float:    1.1,
   288  		Key:      client.IDKey("Test", 1, nil),
   289  		GeoPoint: datastore.GeoPoint{Lat: 1.1, Lng: 1.2},
   290  		Time:     now,
   291  	}
   292  	key1, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj1)
   293  	if err != nil {
   294  		t.Fatal(err)
   295  	}
   296  
   297  	obj2 := &Data{
   298  		Int:      2,
   299  		Bool:     false,
   300  		String:   "2",
   301  		Float:    2.2,
   302  		Key:      client.IDKey("Test", 2, nil),
   303  		GeoPoint: datastore.GeoPoint{Lat: 2.1, Lng: 2.2},
   304  		Time:     now.Add(1 * time.Hour),
   305  	}
   306  	key2, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj2)
   307  	if err != nil {
   308  		t.Fatal(err)
   309  	}
   310  
   311  	t.Log(key1, key2)
   312  
   313  	expects := []struct {
   314  		Name  string
   315  		Value interface{}
   316  	}{
   317  		{"Int", 1},
   318  		{"Bool", true},
   319  		{"String", "1"},
   320  		{"Float", 1.1},
   321  		{"Key", client.IDKey("Test", 1, nil)},
   322  		{"GeoPoint", datastore.GeoPoint{Lat: 1.1, Lng: 1.2}},
   323  		{"Time", now},
   324  	}
   325  
   326  	for _, expect := range expects {
   327  		t.Logf("expect: %#v", expect)
   328  		filterStr := fmt.Sprintf("%s =", expect.Name)
   329  		{ // Count
   330  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   331  			cnt, err := client.Count(ctx, q)
   332  			if err != nil {
   333  				t.Fatal(err)
   334  			}
   335  			if cnt != 1 {
   336  				t.Errorf("unexpected: %v", cnt)
   337  			}
   338  		}
   339  		{ // GetAll
   340  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   341  			var list []*Data
   342  			keys, err := client.GetAll(ctx, q, &list)
   343  			if err != nil {
   344  				t.Fatal(err)
   345  			}
   346  			if v := len(keys); v != 1 {
   347  				t.Fatalf("unexpected: %v", v)
   348  			}
   349  			if v := keys[0]; v.ID() != key1.ID() {
   350  				t.Errorf("unexpected: %v", v)
   351  			}
   352  			if v := len(list); v != 1 {
   353  				t.Errorf("unexpected: %v", v)
   354  			}
   355  		}
   356  		{ // Run
   357  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   358  			iter := client.Run(ctx, q)
   359  			cnt := 0
   360  			for {
   361  				obj := &Data{}
   362  				key, err := iter.Next(obj)
   363  				if err == iterator.Done {
   364  					break
   365  				} else if err != nil {
   366  					t.Fatal(err)
   367  				}
   368  				cnt++
   369  				if v := key; v.ID() != key1.ID() {
   370  					t.Errorf("unexpected: %v", v)
   371  				}
   372  			}
   373  			if cnt != 1 {
   374  				t.Errorf("unexpected: %v", cnt)
   375  			}
   376  		}
   377  	}
   378  }
   379  
   380  func filterPropertyTranslater(ctx context.Context, t *testing.T, client datastore.Client) {
   381  	defer func() {
   382  		err := client.Close()
   383  		if err != nil {
   384  			t.Fatal(err)
   385  		}
   386  	}()
   387  	ctx = context.WithValue(ctx, contextClient{}, client)
   388  	client.SetContext(ctx)
   389  
   390  	type Data struct {
   391  		UserID   userID
   392  		UnixTime unixTime
   393  	}
   394  
   395  	now := time.Now()
   396  
   397  	obj1 := &Data{
   398  		UserID:   userID(1),
   399  		UnixTime: unixTime(now),
   400  	}
   401  	key1, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj1)
   402  	if err != nil {
   403  		t.Fatal(err)
   404  	}
   405  
   406  	obj2 := &Data{
   407  		UserID:   userID(2),
   408  		UnixTime: unixTime(now.Add(1 * time.Hour)),
   409  	}
   410  	key2, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj2)
   411  	if err != nil {
   412  		t.Fatal(err)
   413  	}
   414  
   415  	t.Log(key1, key2)
   416  
   417  	expects := []struct {
   418  		Name  string
   419  		Value interface{}
   420  	}{
   421  		{"UserID", userID(1)},
   422  		{"UnixTime", unixTime(now)},
   423  	}
   424  
   425  	for _, expect := range expects {
   426  		t.Logf("expect: %#v", expect)
   427  		filterStr := fmt.Sprintf("%s =", expect.Name)
   428  		{ // Count
   429  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   430  			cnt, err := client.Count(ctx, q)
   431  			if err != nil {
   432  				t.Fatal(err)
   433  			}
   434  			if cnt != 1 {
   435  				t.Errorf("unexpected: %v", cnt)
   436  			}
   437  		}
   438  		{ // GetAll
   439  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   440  			var list []*Data
   441  			keys, err := client.GetAll(ctx, q, &list)
   442  			if err != nil {
   443  				t.Fatal(err)
   444  			}
   445  			if v := len(keys); v != 1 {
   446  				t.Fatalf("unexpected: %v", v)
   447  			}
   448  			if v := keys[0]; v.ID() != key1.ID() {
   449  				t.Errorf("unexpected: %v", v)
   450  			}
   451  			if v := len(list); v != 1 {
   452  				t.Errorf("unexpected: %v", v)
   453  			}
   454  		}
   455  		{ // Run
   456  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   457  			iter := client.Run(ctx, q)
   458  			cnt := 0
   459  			for {
   460  				obj := &Data{}
   461  				key, err := iter.Next(obj)
   462  				if err == iterator.Done {
   463  					break
   464  				} else if err != nil {
   465  					t.Fatal(err)
   466  				}
   467  				cnt++
   468  				if v := key; v.ID() != key1.ID() {
   469  					t.Errorf("unexpected: %v", v)
   470  				}
   471  			}
   472  			if cnt != 1 {
   473  				t.Errorf("unexpected: %v", cnt)
   474  			}
   475  		}
   476  	}
   477  }
   478  
   479  func filterPropertyTranslaterWithOriginalTypes(ctx context.Context, t *testing.T, client datastore.Client) {
   480  	defer func() {
   481  		err := client.Close()
   482  		if err != nil {
   483  			t.Fatal(err)
   484  		}
   485  	}()
   486  	ctx = context.WithValue(ctx, contextClient{}, client)
   487  	client.SetContext(ctx)
   488  
   489  	type Data struct {
   490  		UserID   userID
   491  		UnixTime unixTime
   492  	}
   493  
   494  	now := time.Now()
   495  
   496  	obj1 := &Data{
   497  		UserID:   userID(1),
   498  		UnixTime: unixTime(now),
   499  	}
   500  	key1, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj1)
   501  	if err != nil {
   502  		t.Fatal(err)
   503  	}
   504  
   505  	obj2 := &Data{
   506  		UserID:   userID(2),
   507  		UnixTime: unixTime(now.Add(1 * time.Hour)),
   508  	}
   509  	key2, err := client.Put(ctx, client.IncompleteKey("Data", nil), obj2)
   510  	if err != nil {
   511  		t.Fatal(err)
   512  	}
   513  
   514  	t.Log(key1, key2)
   515  
   516  	expects := []struct {
   517  		Name  string
   518  		Value interface{}
   519  	}{
   520  		{"UserID", client.IDKey("User", 1, nil)},
   521  		{"UnixTime", now},
   522  	}
   523  
   524  	for _, expect := range expects {
   525  		t.Logf("expect: %#v", expect)
   526  		filterStr := fmt.Sprintf("%s =", expect.Name)
   527  		{ // Count
   528  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   529  			cnt, err := client.Count(ctx, q)
   530  			if err != nil {
   531  				t.Fatal(err)
   532  			}
   533  			if cnt != 1 {
   534  				t.Errorf("unexpected: %v", cnt)
   535  			}
   536  		}
   537  		{ // GetAll
   538  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   539  			var list []*Data
   540  			keys, err := client.GetAll(ctx, q, &list)
   541  			if err != nil {
   542  				t.Fatal(err)
   543  			}
   544  			if v := len(keys); v != 1 {
   545  				t.Fatalf("unexpected: %v", v)
   546  			}
   547  			if v := keys[0]; v.ID() != key1.ID() {
   548  				t.Errorf("unexpected: %v", v)
   549  			}
   550  			if v := len(list); v != 1 {
   551  				t.Errorf("unexpected: %v", v)
   552  			}
   553  		}
   554  		{ // Run
   555  			q := client.NewQuery("Data").Filter(filterStr, expect.Value)
   556  			iter := client.Run(ctx, q)
   557  			cnt := 0
   558  			for {
   559  				obj := &Data{}
   560  				key, err := iter.Next(obj)
   561  				if err == iterator.Done {
   562  					break
   563  				} else if err != nil {
   564  					t.Fatal(err)
   565  				}
   566  				cnt++
   567  				if v := key; v.ID() != key1.ID() {
   568  					t.Errorf("unexpected: %v", v)
   569  				}
   570  			}
   571  			if cnt != 1 {
   572  				t.Errorf("unexpected: %v", cnt)
   573  			}
   574  		}
   575  	}
   576  }
   577  
   578  var _ datastore.PropertyTranslator = (*mustReturnsError)(nil)
   579  
   580  type mustReturnsError int
   581  
   582  func (mustReturnsError) ToPropertyValue(ctx context.Context) (interface{}, error) {
   583  	return nil, errors.New("error from MustReturnsError")
   584  }
   585  
   586  func (mustReturnsError) FromPropertyValue(ctx context.Context, p datastore.Property) (dst interface{}, err error) {
   587  	return nil, errors.New("error from MustReturnsError")
   588  }
   589  
   590  func filterPropertyTranslaterMustError(ctx context.Context, t *testing.T, client datastore.Client) {
   591  	defer func() {
   592  		err := client.Close()
   593  		if err != nil {
   594  			t.Fatal(err)
   595  		}
   596  	}()
   597  
   598  	type Data struct {
   599  		TMP int
   600  	}
   601  
   602  	{ // Count
   603  		q := client.NewQuery("Data").Filter("TMP =", mustReturnsError(1))
   604  		_, err := client.Count(ctx, q)
   605  		if err == nil || err.Error() != "error from MustReturnsError" {
   606  			t.Fatal(err)
   607  		}
   608  	}
   609  	{ // GetAll
   610  		q := client.NewQuery("Data").Filter("TMP =", mustReturnsError(1))
   611  		var list []*Data
   612  		_, err := client.GetAll(ctx, q, &list)
   613  		if err == nil || err.Error() != "error from MustReturnsError" {
   614  			t.Fatal(err)
   615  		}
   616  	}
   617  	{ // Run
   618  		q := client.NewQuery("Data").Filter("TMP =", mustReturnsError(1))
   619  		iter := client.Run(ctx, q)
   620  		obj := &Data{}
   621  		_, err := iter.Next(obj)
   622  		if err == nil || err.Error() != "error from MustReturnsError" {
   623  			t.Fatal(err)
   624  		}
   625  	}
   626  }