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

     1  /*
     2   * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package query
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"github.com/dgraph-io/dgo"
    28  	"github.com/dgraph-io/dgo/protos/api"
    29  	"github.com/dgraph-io/dgraph/testutil"
    30  	"github.com/dgraph-io/dgraph/x"
    31  	"google.golang.org/grpc"
    32  )
    33  
    34  func getNewClient() *dgo.Dgraph {
    35  	conn, err := grpc.Dial(testutil.SockAddr, grpc.WithInsecure())
    36  	x.Check(err)
    37  	return dgo.NewDgraphClient(api.NewDgraphClient(conn))
    38  }
    39  
    40  func setSchema(schema string) {
    41  	err := client.Alter(context.Background(), &api.Operation{
    42  		Schema: schema,
    43  	})
    44  	if err != nil {
    45  		panic(fmt.Sprintf("Could not alter schema. Got error %v", err.Error()))
    46  	}
    47  }
    48  
    49  func dropPredicate(pred string) {
    50  	err := client.Alter(context.Background(), &api.Operation{
    51  		DropAttr: pred,
    52  	})
    53  	if err != nil {
    54  		panic(fmt.Sprintf("Could not drop predicate. Got error %v", err.Error()))
    55  	}
    56  }
    57  
    58  func processQuery(ctx context.Context, t *testing.T, query string) (string, error) {
    59  	txn := client.NewTxn()
    60  	defer txn.Discard(ctx)
    61  
    62  	res, err := txn.Query(ctx, query)
    63  	if err != nil {
    64  		return "", err
    65  	}
    66  
    67  	response := map[string]interface{}{}
    68  	response["data"] = json.RawMessage(string(res.Json))
    69  
    70  	jsonResponse, err := json.Marshal(response)
    71  	require.NoError(t, err)
    72  	return string(jsonResponse), err
    73  }
    74  
    75  func processQueryNoErr(t *testing.T, query string) string {
    76  	res, err := processQuery(context.Background(), t, query)
    77  	require.NoError(t, err)
    78  	return res
    79  }
    80  
    81  func processQueryWithVars(t *testing.T, query string,
    82  	vars map[string]string) (string, error) {
    83  	txn := client.NewTxn()
    84  	defer txn.Discard(context.Background())
    85  
    86  	res, err := txn.QueryWithVars(context.Background(), query, vars)
    87  	if err != nil {
    88  		return "", err
    89  	}
    90  
    91  	response := map[string]interface{}{}
    92  	response["data"] = json.RawMessage(string(res.Json))
    93  
    94  	jsonResponse, err := json.Marshal(response)
    95  	require.NoError(t, err)
    96  	return string(jsonResponse), err
    97  }
    98  
    99  func addTriplesToCluster(triples string) {
   100  	txn := client.NewTxn()
   101  	ctx := context.Background()
   102  	defer txn.Discard(ctx)
   103  
   104  	_, err := txn.Mutate(ctx, &api.Mutation{
   105  		SetNquads: []byte(triples),
   106  		CommitNow: true,
   107  	})
   108  	if err != nil {
   109  		panic(fmt.Sprintf("Could not add triples. Got error %v", err.Error()))
   110  	}
   111  
   112  }
   113  
   114  func deleteTriplesInCluster(triples string) {
   115  	txn := client.NewTxn()
   116  	ctx := context.Background()
   117  	defer txn.Discard(ctx)
   118  
   119  	_, err := txn.Mutate(ctx, &api.Mutation{
   120  		DelNquads: []byte(triples),
   121  		CommitNow: true,
   122  	})
   123  	if err != nil {
   124  		panic(fmt.Sprintf("Could not delete triples. Got error %v", err.Error()))
   125  	}
   126  }
   127  
   128  func addGeoPointToCluster(uid uint64, pred string, point []float64) {
   129  	triple := fmt.Sprintf(
   130  		`<%d> <%s> "{'type':'Point', 'coordinates':[%v, %v]}"^^<geo:geojson> .`,
   131  		uid, pred, point[0], point[1])
   132  	addTriplesToCluster(triple)
   133  }
   134  
   135  func addGeoPolygonToCluster(uid uint64, pred string, polygon [][][]float64) {
   136  	coordinates := "["
   137  	for i, ring := range polygon {
   138  		coordinates += "["
   139  		for j, point := range ring {
   140  			coordinates += fmt.Sprintf("[%v, %v]", point[0], point[1])
   141  
   142  			if j != len(ring)-1 {
   143  				coordinates += ","
   144  			}
   145  		}
   146  
   147  		coordinates += "]"
   148  		if i != len(polygon)-1 {
   149  			coordinates += ","
   150  		}
   151  	}
   152  	coordinates += "]"
   153  
   154  	triple := fmt.Sprintf(
   155  		`<%d> <%s> "{'type':'Polygon', 'coordinates': %s}"^^<geo:geojson> .`,
   156  		uid, pred, coordinates)
   157  	addTriplesToCluster(triple)
   158  }
   159  
   160  func addGeoMultiPolygonToCluster(uid uint64, polygons [][][][]float64) {
   161  	coordinates := "["
   162  	for i, polygon := range polygons {
   163  		coordinates += "["
   164  		for j, ring := range polygon {
   165  			coordinates += "["
   166  			for k, point := range ring {
   167  				coordinates += fmt.Sprintf("[%v, %v]", point[0], point[1])
   168  
   169  				if k != len(ring)-1 {
   170  					coordinates += ","
   171  				}
   172  			}
   173  
   174  			coordinates += "]"
   175  			if j != len(polygon)-1 {
   176  				coordinates += ","
   177  			}
   178  		}
   179  
   180  		coordinates += "]"
   181  		if i != len(polygons)-1 {
   182  			coordinates += ","
   183  		}
   184  	}
   185  	coordinates += "]"
   186  
   187  	triple := fmt.Sprintf(
   188  		`<%d> <geometry> "{'type':'MultiPolygon', 'coordinates': %s}"^^<geo:geojson> .`,
   189  		uid, coordinates)
   190  	addTriplesToCluster(triple)
   191  }
   192  
   193  const testSchema = `
   194  type Person {
   195  	name: string
   196  	pet: Animal
   197  }
   198  
   199  type Animal {
   200  	name: string
   201  }
   202  
   203  type CarModel {
   204  	make: string
   205  	model: string
   206  	year: int
   207  	previous_model: CarModel
   208  }
   209  
   210  type SchoolInfo {
   211  	name: string
   212  	abbr: string
   213  	school: [uid]
   214  	district: [uid]
   215  	state: [uid]
   216  	county: [uid]
   217  }
   218  
   219  type User {
   220  	name: string
   221  	password: password
   222  }
   223  
   224  type Node {
   225  	node: uid
   226  	name: string
   227  }
   228  
   229  name                           : string @index(term, exact, trigram) @count @lang .
   230  alias                          : string @index(exact, term, fulltext) .
   231  dob                            : dateTime @index(year) .
   232  dob_day                        : dateTime @index(day) .
   233  film.film.initial_release_date : dateTime @index(year) .
   234  loc                            : geo @index(geo) .
   235  genre                          : [uid] @reverse .
   236  survival_rate                  : float .
   237  alive                          : bool @index(bool) .
   238  age                            : int @index(int) .
   239  shadow_deep                    : int .
   240  friend                         : [uid] @reverse @count .
   241  geometry                       : geo @index(geo) .
   242  value                          : string @index(trigram) .
   243  full_name                      : string @index(hash) .
   244  nick_name                      : string @index(term) .
   245  royal_title                    : string @index(hash, term, fulltext) @lang .
   246  noindex_name                   : string .
   247  school                         : [uid] @count .
   248  lossy                          : string @index(term) @lang .
   249  occupations                    : [string] @index(term) .
   250  graduation                     : [dateTime] @index(year) @count .
   251  salary                         : float @index(float) .
   252  password                       : password .
   253  pass                           : password .
   254  symbol                         : string @index(exact) .
   255  room                           : string @index(term) .
   256  office.room                    : [uid] .
   257  best_friend                    : uid @reverse .
   258  pet                            : [uid] .
   259  node                           : [uid] .
   260  model                          : string @index(term) @lang .
   261  make                           : string @index(term) .
   262  year                           : int .
   263  previous_model                 : uid @reverse .
   264  created_at                     : datetime @index(hour) .
   265  updated_at                     : datetime @index(year) .
   266  number                         : int @index(int) .
   267  `
   268  
   269  func populateCluster() {
   270  	err := client.Alter(context.Background(), &api.Operation{DropAll: true})
   271  	if err != nil {
   272  		panic(fmt.Sprintf("Could not perform DropAll op. Got error %v", err.Error()))
   273  	}
   274  
   275  	setSchema(testSchema)
   276  	testutil.AssignUids(100000)
   277  
   278  	addTriplesToCluster(`
   279  		<1> <name> "Michonne" .
   280  		<2> <name> "King Lear" .
   281  		<3> <name> "Margaret" .
   282  		<4> <name> "Leonard" .
   283  		<5> <name> "Garfield" .
   284  		<6> <name> "Bear" .
   285  		<7> <name> "Nemo" .
   286  		<11> <name> "name" .
   287  		<23> <name> "Rick Grimes" .
   288  		<24> <name> "Glenn Rhee" .
   289  		<25> <name> "Daryl Dixon" .
   290  		<31> <name> "Andrea" .
   291  		<33> <name> "San Mateo High School" .
   292  		<34> <name> "San Mateo School District" .
   293  		<35> <name> "San Mateo County" .
   294  		<36> <name> "California" .
   295  		<110> <name> "Alice" .
   296  		<240> <name> "Andrea With no friends" .
   297  		<1000> <name> "Alice" .
   298  		<1001> <name> "Bob" .
   299  		<1002> <name> "Matt" .
   300  		<1003> <name> "John" .
   301  		<2300> <name> "Andre" .
   302  		<2301> <name> "Alice\"" .
   303  		<2333> <name> "Helmut" .
   304  		<3500> <name> "" .
   305  		<3500> <name> "상현"@ko .
   306  		<3501> <name> "Alex" .
   307  		<3501> <name> "Alex"@en .
   308  		<3502> <name> "" .
   309  		<3502> <name> "Amit"@en .
   310  		<3502> <name> "अमित"@hi .
   311  		<3503> <name> "Andrew"@en .
   312  		<3503> <name> ""@hi .
   313  		<4097> <name> "Badger" .
   314  		<4097> <name> "European badger"@en .
   315  		<4097> <name> "European badger barger European"@xx .
   316  		<4097> <name> "Borsuk europejski"@pl .
   317  		<4097> <name> "Europäischer Dachs"@de .
   318  		<4097> <name> "Барсук"@ru .
   319  		<4097> <name> "Blaireau européen"@fr .
   320  		<4098> <name> "Honey badger"@en .
   321  		<4099> <name> "Honey bee"@en .
   322  		<4100> <name> "Artem Tkachenko"@en .
   323  		<4100> <name> "Артём Ткаченко"@ru .
   324  		<5000> <name> "School A" .
   325  		<5001> <name> "School B" .
   326  		<5101> <name> "Googleplex" .
   327  		<5102> <name> "Shoreline Amphitheater" .
   328  		<5103> <name> "San Carlos Airport" .
   329  		<5104> <name> "SF Bay area" .
   330  		<5105> <name> "Mountain View" .
   331  		<5106> <name> "San Carlos" .
   332  		<5107> <name> "New York" .
   333  		<8192> <name> "Regex Master" .
   334  		<10000> <name> "Alice" .
   335  		<10001> <name> "Elizabeth" .
   336  		<10002> <name> "Alice" .
   337  		<10003> <name> "Bob" .
   338  		<10004> <name> "Alice" .
   339  		<10005> <name> "Bob" .
   340  		<10006> <name> "Colin" .
   341  		<10007> <name> "Elizabeth" .
   342  
   343  		<11000> <name> "Baz Luhrmann"@en .
   344  		<11001> <name> "Strictly Ballroom"@en .
   345  		<11002> <name> "Puccini: La boheme (Sydney Opera)"@en .
   346  		<11003> <name> "No. 5 the film"@en .
   347  		<11100> <name> "expand" .
   348  
   349  		<1> <full_name> "Michonne's large name for hashing" .
   350  
   351  		<1> <noindex_name> "Michonne's name not indexed" .
   352  
   353  		<1> <friend> <23> .
   354  		<1> <friend> <24> .
   355  		<1> <friend> <25> .
   356  		<1> <friend> <31> .
   357  		<1> <friend> <101> .
   358  		<31> <friend> <24> .
   359  		<23> <friend> <1> .
   360  
   361  		<2> <best_friend> <64> (since=2019-03-28T14:41:57+30:00) .
   362  		<3> <best_friend> <64> (since=2018-03-24T14:41:57+05:30) .
   363  		<4> <best_friend> <64> (since=2019-03-27) .
   364  
   365  		<1> <age> "38" .
   366  		<23> <age> "15" .
   367  		<24> <age> "15" .
   368  		<25> <age> "17" .
   369  		<31> <age> "19" .
   370  		<10000> <age> "25" .
   371  		<10001> <age> "75" .
   372  		<10002> <age> "75" .
   373  		<10003> <age> "75" .
   374  		<10004> <age> "75" .
   375  		<10005> <age> "25" .
   376  		<10006> <age> "25" .
   377  		<10007> <age> "25" .
   378  
   379  		<1> <alive> "true" .
   380  		<23> <alive> "true" .
   381  		<25> <alive> "false" .
   382  		<31> <alive> "false" .
   383  
   384  		<1> <gender> "female" .
   385  		<23> <gender> "male" .
   386  
   387  		<4001> <office> "office 1" .
   388  		<4002> <room> "room 1" .
   389  		<4003> <room> "room 2" .
   390  		<4004> <room> "" .
   391  		<4001> <office.room> <4002> .
   392  		<4001> <office.room> <4003> .
   393  		<4001> <office.room> <4004> .
   394  
   395  		<3001> <symbol> "AAPL" .
   396  		<3002> <symbol> "AMZN" .
   397  		<3003> <symbol> "AMD" .
   398  		<3004> <symbol> "FB" .
   399  		<3005> <symbol> "GOOG" .
   400  		<3006> <symbol> "MSFT" .
   401  
   402  		<1> <dob> "1910-01-01" .
   403  		<23> <dob> "1910-01-02" .
   404  		<24> <dob> "1909-05-05" .
   405  		<25> <dob> "1909-01-10" .
   406  		<31> <dob> "1901-01-15" .
   407  
   408  		<1> <path> <31> (weight = 0.1, weight1 = 0.2) .
   409  		<1> <path> <24> (weight = 0.2) .
   410  		<31> <path> <1000> (weight = 0.1) .
   411  		<1000> <path> <1001> (weight = 0.1) .
   412  		<1000> <path> <1002> (weight = 0.7) .
   413  		<1001> <path> <1002> (weight = 0.1) .
   414  		<1002> <path> <1003> (weight = 0.6) .
   415  		<1001> <path> <1003> (weight = 1.5) .
   416  		<1003> <path> <1001> .
   417  
   418  		<1> <follow> <31> .
   419  		<1> <follow> <24> .
   420  		<31> <follow> <1001> .
   421  		<1001> <follow> <1000> .
   422  		<1002> <follow> <1000> .
   423  		<1001> <follow> <1003> .
   424  		<1003> <follow> <1002> .
   425  
   426  		<1> <survival_rate> "98.99" .
   427  		<23> <survival_rate> "1.6" .
   428  		<24> <survival_rate> "1.6" .
   429  		<25> <survival_rate> "1.6" .
   430  		<31> <survival_rate> "1.6" .
   431  
   432  		<1> <school> <5000> .
   433  		<23> <school> <5001> .
   434  		<24> <school> <5000> .
   435  		<25> <school> <5000> .
   436  		<31> <school> <5001> .
   437  		<101> <school> <5001> .
   438  
   439  		<1> <_xid_> "mich" .
   440  		<24> <_xid_> "g\"lenn" .
   441  		<110> <_xid_> "a.bc" .
   442  
   443  		<23> <alias> "Zambo Alice" .
   444  		<24> <alias> "John Alice" .
   445  		<25> <alias> "Bob Joe" .
   446  		<31> <alias> "Allan Matt" .
   447  		<101> <alias> "John Oliver" .
   448  
   449  		<1> <bin_data> "YmluLWRhdGE=" .
   450  
   451  		<1> <graduation> "1932-01-01" .
   452  		<31> <graduation> "1933-01-01" .
   453  		<31> <graduation> "1935-01-01" .
   454  
   455  		<10000> <salary> "10000" .
   456  		<10002> <salary> "10002" .
   457  
   458  		<1> <address> "31, 32 street, Jupiter" .
   459  		<23> <address> "21, mark street, Mars" .
   460  
   461  		<1> <dob_day> "1910-01-01" .
   462  		<23> <dob_day> "1910-01-02" .
   463  		<24> <dob_day> "1909-05-05" .
   464  		<25> <dob_day> "1909-01-10" .
   465  		<31> <dob_day> "1901-01-15" .
   466  
   467  		<1> <power> "13.25"^^<xs:float> .
   468  
   469  		<1> <sword_present> "true" .
   470  
   471  		<1> <son> <2300> .
   472  		<1> <son> <2333> .
   473  
   474  		<5010> <nick_name> "Two Terms" .
   475  
   476  		<4097> <lossy> "Badger" .
   477  		<4097> <lossy> "European badger"@en .
   478  		<4097> <lossy> "European badger barger European"@xx .
   479  		<4097> <lossy> "Borsuk europejski"@pl .
   480  		<4097> <lossy> "Europäischer Dachs"@de .
   481  		<4097> <lossy> "Барсук"@ru .
   482  		<4097> <lossy> "Blaireau européen"@fr .
   483  		<4098> <lossy> "Honey badger"@en .
   484  
   485  		<23> <film.film.initial_release_date> "1900-01-02" .
   486  		<24> <film.film.initial_release_date> "1909-05-05" .
   487  		<25> <film.film.initial_release_date> "1929-01-10" .
   488  		<31> <film.film.initial_release_date> "1801-01-15" .
   489  
   490  		<0x10000> <royal_title> "Her Majesty Elizabeth the Second, by the Grace of God of the United Kingdom of Great Britain and Northern Ireland and of Her other Realms and Territories Queen, Head of the Commonwealth, Defender of the Faith"@en .
   491  		<0x10000> <royal_title> "Sa Majesté Elizabeth Deux, par la grâce de Dieu Reine du Royaume-Uni, du Canada et de ses autres royaumes et territoires, Chef du Commonwealth, Défenseur de la Foi"@fr .
   492  
   493  		<32> <school> <33> .
   494  		<33> <district> <34> .
   495  		<34> <county> <35> .
   496  		<35> <state> <36> .
   497  
   498  		<36> <abbr> "CA" .
   499  
   500  		<1> <password> "123456" .
   501  		<32> <password> "123456" .
   502  		<23> <pass> "654321" .
   503  
   504  		<23> <shadow_deep> "4" .
   505  		<24> <shadow_deep> "14" .
   506  
   507  		<1> <dgraph.type> "User" .
   508  		<2> <dgraph.type> "Person" .
   509  		<3> <dgraph.type> "Person" .
   510  		<4> <dgraph.type> "Person" .
   511  		<5> <dgraph.type> "Animal" .
   512  		<5> <dgraph.type> "Pet" .
   513  		<6> <dgraph.type> "Animal" .
   514  		<6> <dgraph.type> "Pet" .
   515  		<32> <dgraph.type> "SchoolInfo" .
   516  		<33> <dgraph.type> "SchoolInfo" .
   517  		<34> <dgraph.type> "SchoolInfo" .
   518  		<35> <dgraph.type> "SchoolInfo" .
   519  		<36> <dgraph.type> "SchoolInfo" .
   520  		<11100> <dgraph.type> "Node" .
   521  
   522  		<2> <pet> <5> .
   523  		<3> <pet> <6> .
   524  		<4> <pet> <7> .
   525  
   526  		<2> <enemy> <3> .
   527  		<2> <enemy> <4> .
   528  
   529  		<11000> <director.film> <11001> .
   530  		<11000> <director.film> <11002> .
   531  		<11000> <director.film> <11003> .
   532  
   533  		<11100> <node> <11100> .
   534  
   535  		<200> <make> "Ford" .
   536  		<200> <model> "Focus" .
   537  		<200> <year> "2008" .
   538  		<200> <dgraph.type> "CarModel" .
   539  
   540  		<201> <make> "Ford" .
   541  		<201> <model> "Focus" .
   542  		<201> <year> "2009" .
   543  		<201> <dgraph.type> "CarModel" .
   544  		<201> <previous_model> <200> .
   545  
   546  		<202> <make> "Toyota" .
   547  		<202> <year> "2009" .
   548  		<202> <model> "Prius" .
   549  		<202> <model> "プリウス"@jp .
   550  		<202> <dgraph.type> "CarModel" .
   551  	`)
   552  
   553  	addGeoPointToCluster(1, "loc", []float64{1.1, 2.0})
   554  	addGeoPointToCluster(24, "loc", []float64{1.10001, 2.000001})
   555  	addGeoPointToCluster(25, "loc", []float64{1.1, 2.0})
   556  	addGeoPointToCluster(5101, "geometry", []float64{-122.082506, 37.4249518})
   557  	addGeoPointToCluster(5102, "geometry", []float64{-122.080668, 37.426753})
   558  	addGeoPointToCluster(5103, "geometry", []float64{-122.2527428, 37.513653})
   559  
   560  	addGeoPolygonToCluster(23, "loc", [][][]float64{
   561  		{{0.0, 0.0}, {2.0, 0.0}, {2.0, 2.0}, {0.0, 2.0}, {0.0, 0.0}},
   562  	})
   563  	addGeoPolygonToCluster(5104, "geometry", [][][]float64{
   564  		{{-121.6, 37.1}, {-122.4, 37.3}, {-122.6, 37.8}, {-122.5, 38.3}, {-121.9, 38},
   565  			{-121.6, 37.1}},
   566  	})
   567  	addGeoPolygonToCluster(5105, "geometry", [][][]float64{
   568  		{{-122.06, 37.37}, {-122.1, 37.36}, {-122.12, 37.4}, {-122.11, 37.43},
   569  			{-122.04, 37.43}, {-122.06, 37.37}},
   570  	})
   571  	addGeoPolygonToCluster(5106, "geometry", [][][]float64{
   572  		{{-122.25, 37.49}, {-122.28, 37.49}, {-122.27, 37.51}, {-122.25, 37.52},
   573  			{-122.25, 37.49}},
   574  	})
   575  
   576  	addGeoMultiPolygonToCluster(5107, [][][][]float64{
   577  		{{{-74.29504394531249, 40.19146303804063}, {-74.59716796875, 40.39258071969131},
   578  			{-74.6466064453125, 40.20824570152502}, {-74.454345703125, 40.06125658140474},
   579  			{-74.28955078125, 40.17467622056341}, {-74.29504394531249, 40.19146303804063}}},
   580  		{{{-74.102783203125, 40.8595252289932}, {-74.2730712890625, 40.718119379753446},
   581  			{-74.0478515625, 40.66813955408042}, {-73.98193359375, 40.772221877329024},
   582  			{-74.102783203125, 40.8595252289932}}},
   583  	})
   584  
   585  	// Add data for regex tests.
   586  	nextId := uint64(0x2000)
   587  	patterns := []string{"mississippi", "missouri", "mission", "missionary",
   588  		"whissle", "transmission", "zipped", "monosiphonic", "vasopressin", "vapoured",
   589  		"virtuously", "zurich", "synopsis", "subsensuously",
   590  		"admission", "commission", "submission", "subcommission", "retransmission", "omission",
   591  		"permission", "intermission", "dimission", "discommission",
   592  	}
   593  	for _, p := range patterns {
   594  		triples := fmt.Sprintf(`
   595  			<%d> <value> "%s" .
   596  			<0x1234> <pattern> <%d> .
   597  		`, nextId, p, nextId)
   598  		addTriplesToCluster(triples)
   599  		nextId++
   600  	}
   601  
   602  	// Add data for datetime tests
   603  	addTriplesToCluster(`
   604  		<301> <created_at> "2019-03-28T14:41:57+30:00" (modified_at=2019-05-28T14:41:57+30:00) .
   605  		<302> <created_at> "2019-03-28T13:41:57+29:00" (modified_at=2019-03-28T14:41:57+30:00) .
   606  		<303> <created_at> "2019-03-27T14:41:57+06:00" (modified_at=2019-03-29) .
   607  		<304> <created_at> "2019-03-28T15:41:57+30:00" (modified_at=2019-03-27T14:41:57+06:00) .
   608  		<305> <created_at> "2019-03-28T13:41:57+30:00" (modified_at=2019-03-28) .
   609  		<306> <created_at> "2019-03-24T14:41:57+05:30" (modified_at=2019-03-28T13:41:57+30:00) .
   610  		<307> <created_at> "2019-05-28T14:41:57+30:00" .
   611  
   612  		<301> <updated_at> "2019-03-28T14:41:57+30:00" (modified_at=2019-05-28) .
   613  		<302> <updated_at> "2019-03-28T13:41:57+29:00" (modified_at=2019-03-28T14:41:57+30:00) .
   614  		<303> <updated_at> "2019-03-27T14:41:57+06:00" (modified_at=2019-03-28T13:41:57+29:00) .
   615  		<304> <updated_at> "2019-03-27T09:41:57" .
   616  		<305> <updated_at> "2019-03-28T13:41:57+30:00" (modified_at=2019-03-28T15:41:57+30:00) .
   617  		<306> <updated_at> "2019-03-24T14:41:57+05:30" (modified_at=2019-03-28T13:41:57+30:00) .
   618  		<307> <updated_at> "2019-05-28" (modified_at=2019-03-24T14:41:57+05:30) .
   619  	`)
   620  }