github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/index/dolt_index_test.go (about)

     1  // Copyright 2020 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package index_test
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"fmt"
    21  	"io"
    22  	"sort"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/dolthub/go-mysql-server/sql"
    28  	"github.com/dolthub/go-mysql-server/sql/types"
    29  	"github.com/shopspring/decimal"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  
    33  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    34  	"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
    35  	"github.com/dolthub/dolt/go/libraries/doltcore/sqle"
    36  	"github.com/dolthub/dolt/go/libraries/doltcore/sqle/index"
    37  	"github.com/dolthub/dolt/go/libraries/doltcore/sqle/sqlutil"
    38  )
    39  
    40  type indexComp int
    41  
    42  const (
    43  	indexComp_Eq = iota
    44  	indexComp_NEq
    45  	indexComp_Gt
    46  	indexComp_GtE
    47  	indexComp_Lt
    48  	indexComp_LtE
    49  )
    50  
    51  type doltIndexTestCase struct {
    52  	indexName    string
    53  	keys         []interface{}
    54  	expectedRows []sql.Row
    55  }
    56  
    57  type doltIndexBetweenTestCase struct {
    58  	indexName          string
    59  	greaterThanOrEqual []interface{}
    60  	lessThanOrEqual    []interface{}
    61  	expectedRows       []sql.Row
    62  }
    63  
    64  var typesTests = []struct {
    65  	indexName       string
    66  	belowfirstValue []interface{}
    67  	firstValue      []interface{}
    68  	secondValue     []interface{}
    69  	thirdValue      []interface{}
    70  	fourthValue     []interface{}
    71  	fifthValue      []interface{}
    72  	abovefifthValue []interface{}
    73  }{
    74  	{
    75  		"types:primaryKey",
    76  		[]interface{}{-4},
    77  		[]interface{}{-3},
    78  		[]interface{}{-1},
    79  		[]interface{}{0},
    80  		[]interface{}{1},
    81  		[]interface{}{3},
    82  		[]interface{}{4},
    83  	},
    84  	{
    85  		"types:idx_bit",
    86  		[]interface{}{0},
    87  		[]interface{}{1},
    88  		[]interface{}{2},
    89  		[]interface{}{3},
    90  		[]interface{}{4},
    91  		[]interface{}{5},
    92  		[]interface{}{6},
    93  	},
    94  	{
    95  		"types:idx_datetime",
    96  		[]interface{}{"2020-05-14 11:59:59"},
    97  		[]interface{}{"2020-05-14 12:00:00"},
    98  		[]interface{}{"2020-05-14 12:00:01"},
    99  		[]interface{}{"2020-05-14 12:00:02"},
   100  		[]interface{}{"2020-05-14 12:00:03"},
   101  		[]interface{}{"2020-05-14 12:00:04"},
   102  		[]interface{}{"2020-05-14 12:00:05"},
   103  	},
   104  	{
   105  		"types:idx_decimal",
   106  		[]interface{}{"-4"},
   107  		[]interface{}{"-3.3"},
   108  		[]interface{}{"-1.1"},
   109  		[]interface{}{0},
   110  		[]interface{}{"1.1"},
   111  		[]interface{}{"3.3"},
   112  		[]interface{}{4},
   113  	},
   114  	{
   115  		"types:idx_enum",
   116  		[]interface{}{"_"},
   117  		[]interface{}{"a"},
   118  		[]interface{}{"b"},
   119  		[]interface{}{"c"},
   120  		[]interface{}{"d"},
   121  		[]interface{}{"e"},
   122  		[]interface{}{"."},
   123  	},
   124  	{
   125  		"types:idx_double",
   126  		[]interface{}{-4},
   127  		[]interface{}{-3.3},
   128  		[]interface{}{-1.1},
   129  		[]interface{}{0},
   130  		[]interface{}{1.1},
   131  		[]interface{}{3.3},
   132  		[]interface{}{4},
   133  	},
   134  	{
   135  		"types:idx_set",
   136  		[]interface{}{""},
   137  		[]interface{}{"a"},
   138  		[]interface{}{"a,b"},
   139  		[]interface{}{"c"},
   140  		[]interface{}{"a,c"},
   141  		[]interface{}{"b,c"},
   142  		[]interface{}{"a,b,c"},
   143  	},
   144  	{
   145  		"types:idx_time",
   146  		[]interface{}{"-00:04:04"},
   147  		[]interface{}{"-00:03:03"},
   148  		[]interface{}{"-00:01:01"},
   149  		[]interface{}{"00:00:00"},
   150  		[]interface{}{"00:01:01"},
   151  		[]interface{}{"00:03:03"},
   152  		[]interface{}{"00:04:04"},
   153  	},
   154  	{
   155  		"types:idx_varchar",
   156  		[]interface{}{"_"},
   157  		[]interface{}{"a"},
   158  		[]interface{}{"b"},
   159  		[]interface{}{"c"},
   160  		[]interface{}{"d"},
   161  		[]interface{}{"e"},
   162  		[]interface{}{"f"},
   163  	},
   164  	{
   165  		"types:idx_year",
   166  		[]interface{}{1975},
   167  		[]interface{}{1980},
   168  		[]interface{}{1990},
   169  		[]interface{}{2000},
   170  		[]interface{}{2010},
   171  		[]interface{}{2020},
   172  		[]interface{}{2025},
   173  	},
   174  }
   175  
   176  var (
   177  	typesTableRow1 = sql.Row{int32(-3), uint64(1), mustTime("2020-05-14 12:00:00"), mustDecimal("-3.30000"), uint16(2), -3.3, uint64(1), types.Timespan(-183000000), "a", int16(1980)}
   178  	typesTableRow2 = sql.Row{int32(-1), uint64(2), mustTime("2020-05-14 12:00:01"), mustDecimal("-1.10000"), uint16(3), -1.1, uint64(3), types.Timespan(-61000000), "b", int16(1990)}
   179  	typesTableRow3 = sql.Row{int32(0), uint64(3), mustTime("2020-05-14 12:00:02"), mustDecimal("0.00000"), uint16(4), 0.0, uint64(4), types.Timespan(0), "c", int16(2000)}
   180  	typesTableRow4 = sql.Row{int32(1), uint64(4), mustTime("2020-05-14 12:00:03"), mustDecimal("1.10000"), uint16(5), 1.1, uint64(5), types.Timespan(61000000), "d", int16(2010)}
   181  	typesTableRow5 = sql.Row{int32(3), uint64(5), mustTime("2020-05-14 12:00:04"), mustDecimal("3.30000"), uint16(6), 3.3, uint64(6), types.Timespan(183000000), "e", int16(2020)}
   182  )
   183  
   184  func TestDoltIndexEqual(t *testing.T) {
   185  	root, indexMap := doltIndexSetup(t)
   186  
   187  	tests := []doltIndexTestCase{
   188  		{
   189  			"onepk:primaryKey",
   190  			[]interface{}{1},
   191  			[]sql.Row{{1, 1, 1}},
   192  		},
   193  		{
   194  			"onepk:primaryKey",
   195  			[]interface{}{3},
   196  			[]sql.Row{{3, 3, 3}},
   197  		},
   198  		{
   199  			"onepk:primaryKey",
   200  			[]interface{}{0},
   201  			nil,
   202  		},
   203  		{
   204  			"onepk:primaryKey",
   205  			[]interface{}{5},
   206  			nil,
   207  		},
   208  		{
   209  			"onepk:idx_v1",
   210  			[]interface{}{1},
   211  			[]sql.Row{{1, 1, 1}, {2, 1, 2}},
   212  		},
   213  		{
   214  			"onepk:idx_v1",
   215  			[]interface{}{3},
   216  			[]sql.Row{{3, 3, 3}},
   217  		},
   218  		{
   219  			"twopk:primaryKey",
   220  			[]interface{}{1, 1},
   221  			[]sql.Row{{1, 1, 3, 3}},
   222  		},
   223  		{
   224  			"twopk:primaryKey",
   225  			[]interface{}{2, 0},
   226  			nil,
   227  		},
   228  		{
   229  			"twopk:primaryKey",
   230  			[]interface{}{2, 1},
   231  			[]sql.Row{{2, 1, 4, 4}},
   232  		},
   233  		{
   234  			"twopk:idx_v2v1",
   235  			[]interface{}{3, 4},
   236  			[]sql.Row{{2, 2, 4, 3}},
   237  		},
   238  		{
   239  			"twopk:idx_v2v1",
   240  			[]interface{}{4, 3},
   241  			[]sql.Row{{1, 2, 3, 4}},
   242  		},
   243  		//{
   244  		//	"twopk:idx_v2v1_PARTIAL_1",
   245  		//	[]interface{}{3},
   246  		//	[]sql.Row{{1, 1, 3, 3}, {2, 2, 4, 3}},
   247  		//},
   248  		//{
   249  		//	"twopk:idx_v2v1_PARTIAL_1",
   250  		//	[]interface{}{4},
   251  		//	[]sql.Row{{1, 2, 3, 4}, {2, 1, 4, 4}},
   252  		//},
   253  	}
   254  
   255  	for _, typesTest := range typesTests {
   256  		tests = append(tests, doltIndexTestCase{
   257  			typesTest.indexName,
   258  			typesTest.belowfirstValue,
   259  			nil,
   260  		}, doltIndexTestCase{
   261  			typesTest.indexName,
   262  			typesTest.firstValue,
   263  			[]sql.Row{
   264  				typesTableRow1,
   265  			},
   266  		}, doltIndexTestCase{
   267  			typesTest.indexName,
   268  			typesTest.secondValue,
   269  			[]sql.Row{
   270  				typesTableRow2,
   271  			},
   272  		}, doltIndexTestCase{
   273  			typesTest.indexName,
   274  			typesTest.thirdValue,
   275  			[]sql.Row{
   276  				typesTableRow3,
   277  			},
   278  		}, doltIndexTestCase{
   279  			typesTest.indexName,
   280  			typesTest.fourthValue,
   281  			[]sql.Row{
   282  				typesTableRow4,
   283  			},
   284  		}, doltIndexTestCase{
   285  			typesTest.indexName,
   286  			typesTest.fifthValue,
   287  			[]sql.Row{
   288  				typesTableRow5,
   289  			},
   290  		}, doltIndexTestCase{
   291  			typesTest.indexName,
   292  			typesTest.abovefifthValue,
   293  			nil,
   294  		})
   295  	}
   296  
   297  	for _, test := range tests {
   298  		t.Run(fmt.Sprintf("%s|%v", test.indexName, test.keys), func(t *testing.T) {
   299  			ctx := sql.NewEmptyContext()
   300  			idx, ok := indexMap[test.indexName]
   301  			require.True(t, ok)
   302  			testDoltIndex(t, ctx, root, test.keys, test.expectedRows, idx, indexComp_Eq)
   303  		})
   304  	}
   305  }
   306  
   307  func TestDoltIndexGreaterThan(t *testing.T) {
   308  	root, indexMap := doltIndexSetup(t)
   309  
   310  	tests := []struct {
   311  		indexName    string
   312  		keys         []interface{}
   313  		expectedRows []sql.Row
   314  	}{
   315  		{
   316  			"onepk:primaryKey",
   317  			[]interface{}{1},
   318  			[]sql.Row{{2, 1, 2}, {3, 3, 3}, {4, 4, 3}},
   319  		},
   320  		{
   321  			"onepk:primaryKey",
   322  			[]interface{}{3},
   323  			[]sql.Row{{4, 4, 3}},
   324  		},
   325  		{
   326  			"onepk:primaryKey",
   327  			[]interface{}{4},
   328  			nil,
   329  		},
   330  		{
   331  			"onepk:idx_v1",
   332  			[]interface{}{1},
   333  			[]sql.Row{{3, 3, 3}, {4, 4, 3}},
   334  		},
   335  		{
   336  			"onepk:idx_v1",
   337  			[]interface{}{3},
   338  			[]sql.Row{{4, 4, 3}},
   339  		},
   340  		{
   341  			"onepk:idx_v1",
   342  			[]interface{}{4},
   343  			nil,
   344  		},
   345  		{
   346  			"twopk:primaryKey",
   347  			[]interface{}{1, 1},
   348  			[]sql.Row{{2, 2, 4, 3}},
   349  		},
   350  		{
   351  			"twopk:primaryKey",
   352  			[]interface{}{2, 1},
   353  			nil,
   354  		},
   355  		{
   356  			"twopk:idx_v2v1",
   357  			[]interface{}{2, 3},
   358  			[]sql.Row{{2, 1, 4, 4}, {2, 2, 4, 3}},
   359  		},
   360  		{
   361  			"twopk:idx_v2v1",
   362  			[]interface{}{3, 3},
   363  			[]sql.Row{{2, 1, 4, 4}},
   364  		},
   365  		{
   366  			"twopk:idx_v2v1",
   367  			[]interface{}{3, 4},
   368  			nil,
   369  		},
   370  		{
   371  			"twopk:idx_v2v1",
   372  			[]interface{}{4, 3},
   373  			nil,
   374  		},
   375  		//{
   376  		//	"twopk:idx_v2v1_PARTIAL_1",
   377  		//	[]interface{}{3},
   378  		//	[]sql.Row{{1, 2, 3, 4}, {2, 1, 4, 4}},
   379  		//},
   380  		//{
   381  		//	"twopk:idx_v2v1_PARTIAL_1",
   382  		//	[]interface{}{4},
   383  		//	nil,
   384  		//},
   385  	}
   386  
   387  	for _, typesTest := range typesTests {
   388  		tests = append(tests, doltIndexTestCase{
   389  			typesTest.indexName,
   390  			typesTest.belowfirstValue,
   391  			[]sql.Row{
   392  				typesTableRow1,
   393  				typesTableRow2,
   394  				typesTableRow3,
   395  				typesTableRow4,
   396  				typesTableRow5,
   397  			},
   398  		}, doltIndexTestCase{
   399  			typesTest.indexName,
   400  			typesTest.firstValue,
   401  			[]sql.Row{
   402  				typesTableRow2,
   403  				typesTableRow3,
   404  				typesTableRow4,
   405  				typesTableRow5,
   406  			},
   407  		}, doltIndexTestCase{
   408  			typesTest.indexName,
   409  			typesTest.secondValue,
   410  			[]sql.Row{
   411  				typesTableRow3,
   412  				typesTableRow4,
   413  				typesTableRow5,
   414  			},
   415  		}, doltIndexTestCase{
   416  			typesTest.indexName,
   417  			typesTest.thirdValue,
   418  			[]sql.Row{
   419  				typesTableRow4,
   420  				typesTableRow5,
   421  			},
   422  		}, doltIndexTestCase{
   423  			typesTest.indexName,
   424  			typesTest.fourthValue,
   425  			[]sql.Row{
   426  				typesTableRow5,
   427  			},
   428  		}, doltIndexTestCase{
   429  			typesTest.indexName,
   430  			typesTest.fifthValue,
   431  			nil,
   432  		}, doltIndexTestCase{
   433  			typesTest.indexName,
   434  			typesTest.abovefifthValue,
   435  			nil,
   436  		})
   437  	}
   438  
   439  	for _, test := range tests {
   440  		t.Run(fmt.Sprintf("%s|%v", test.indexName, test.keys), func(t *testing.T) {
   441  			ctx := sql.NewEmptyContext()
   442  			index, ok := indexMap[test.indexName]
   443  			require.True(t, ok)
   444  			testDoltIndex(t, ctx, root, test.keys, test.expectedRows, index, indexComp_Gt)
   445  		})
   446  	}
   447  }
   448  
   449  func TestDoltIndexGreaterThanOrEqual(t *testing.T) {
   450  	root, indexMap := doltIndexSetup(t)
   451  
   452  	tests := []struct {
   453  		indexName    string
   454  		keys         []interface{}
   455  		expectedRows []sql.Row
   456  	}{
   457  		{
   458  			"onepk:primaryKey",
   459  			[]interface{}{1},
   460  			[]sql.Row{{1, 1, 1}, {2, 1, 2}, {3, 3, 3}, {4, 4, 3}},
   461  		},
   462  		{
   463  			"onepk:primaryKey",
   464  			[]interface{}{3},
   465  			[]sql.Row{{3, 3, 3}, {4, 4, 3}},
   466  		},
   467  		{
   468  			"onepk:primaryKey",
   469  			[]interface{}{4},
   470  			[]sql.Row{{4, 4, 3}},
   471  		},
   472  		{
   473  			"onepk:idx_v1",
   474  			[]interface{}{1},
   475  			[]sql.Row{{1, 1, 1}, {2, 1, 2}, {3, 3, 3}, {4, 4, 3}},
   476  		},
   477  		{
   478  			"onepk:idx_v1",
   479  			[]interface{}{3},
   480  			[]sql.Row{{3, 3, 3}, {4, 4, 3}},
   481  		},
   482  		{
   483  			"onepk:idx_v1",
   484  			[]interface{}{4},
   485  			[]sql.Row{{4, 4, 3}},
   486  		},
   487  		{
   488  			"twopk:primaryKey",
   489  			[]interface{}{1, 1},
   490  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   491  		},
   492  		{
   493  			"twopk:primaryKey",
   494  			[]interface{}{2, 1},
   495  			[]sql.Row{{2, 1, 4, 4}, {2, 2, 4, 3}},
   496  		},
   497  		{
   498  			"twopk:idx_v2v1",
   499  			[]interface{}{3, 4},
   500  			[]sql.Row{{2, 1, 4, 4}, {2, 2, 4, 3}},
   501  		},
   502  		{
   503  			"twopk:idx_v2v1",
   504  			[]interface{}{4, 3},
   505  			[]sql.Row{{1, 2, 3, 4}, {2, 1, 4, 4}},
   506  		},
   507  		//{
   508  		//	"twopk:idx_v2v1_PARTIAL_1",
   509  		//	[]interface{}{3},
   510  		//	[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   511  		//},
   512  		//{
   513  		//	"twopk:idx_v2v1_PARTIAL_1",
   514  		//	[]interface{}{4},
   515  		//	[]sql.Row{{1, 2, 3, 4}, {2, 1, 4, 4}},
   516  		//},
   517  	}
   518  
   519  	for _, typesTest := range typesTests {
   520  		tests = append(tests, doltIndexTestCase{
   521  			typesTest.indexName,
   522  			typesTest.belowfirstValue,
   523  			[]sql.Row{
   524  				typesTableRow1,
   525  				typesTableRow2,
   526  				typesTableRow3,
   527  				typesTableRow4,
   528  				typesTableRow5,
   529  			},
   530  		}, doltIndexTestCase{
   531  			typesTest.indexName,
   532  			typesTest.firstValue,
   533  			[]sql.Row{
   534  				typesTableRow1,
   535  				typesTableRow2,
   536  				typesTableRow3,
   537  				typesTableRow4,
   538  				typesTableRow5,
   539  			},
   540  		}, doltIndexTestCase{
   541  			typesTest.indexName,
   542  			typesTest.secondValue,
   543  			[]sql.Row{
   544  				typesTableRow2,
   545  				typesTableRow3,
   546  				typesTableRow4,
   547  				typesTableRow5,
   548  			},
   549  		}, doltIndexTestCase{
   550  			typesTest.indexName,
   551  			typesTest.thirdValue,
   552  			[]sql.Row{
   553  				typesTableRow3,
   554  				typesTableRow4,
   555  				typesTableRow5,
   556  			},
   557  		}, doltIndexTestCase{
   558  			typesTest.indexName,
   559  			typesTest.fourthValue,
   560  			[]sql.Row{
   561  				typesTableRow4,
   562  				typesTableRow5,
   563  			},
   564  		}, doltIndexTestCase{
   565  			typesTest.indexName,
   566  			typesTest.fifthValue,
   567  			[]sql.Row{
   568  				typesTableRow5,
   569  			},
   570  		}, doltIndexTestCase{
   571  			typesTest.indexName,
   572  			typesTest.abovefifthValue,
   573  			nil,
   574  		})
   575  	}
   576  
   577  	for _, test := range tests {
   578  		t.Run(fmt.Sprintf("%s|%v", test.indexName, test.keys), func(t *testing.T) {
   579  			ctx := sql.NewEmptyContext()
   580  			index, ok := indexMap[test.indexName]
   581  			require.True(t, ok)
   582  			testDoltIndex(t, ctx, root, test.keys, test.expectedRows, index, indexComp_GtE)
   583  		})
   584  	}
   585  }
   586  
   587  func TestDoltIndexLessThan(t *testing.T) {
   588  	root, indexMap := doltIndexSetup(t)
   589  
   590  	tests := []struct {
   591  		indexName    string
   592  		keys         []interface{}
   593  		expectedRows []sql.Row
   594  	}{
   595  		{
   596  			"onepk:primaryKey",
   597  			[]interface{}{1},
   598  			nil,
   599  		},
   600  		{
   601  			"onepk:primaryKey",
   602  			[]interface{}{3},
   603  			[]sql.Row{{2, 1, 2}, {1, 1, 1}},
   604  		},
   605  		{
   606  			"onepk:primaryKey",
   607  			[]interface{}{4},
   608  			[]sql.Row{{3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   609  		},
   610  		{
   611  			"onepk:idx_v1",
   612  			[]interface{}{1},
   613  			nil,
   614  		},
   615  		{
   616  			"onepk:idx_v1",
   617  			[]interface{}{3},
   618  			[]sql.Row{{2, 1, 2}, {1, 1, 1}},
   619  		},
   620  		{
   621  			"onepk:idx_v1",
   622  			[]interface{}{4},
   623  			[]sql.Row{{3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   624  		},
   625  		{
   626  			"twopk:primaryKey",
   627  			[]interface{}{1, 1},
   628  			nil,
   629  		},
   630  		{
   631  			"twopk:primaryKey",
   632  			[]interface{}{2, 1},
   633  			nil,
   634  		},
   635  		{
   636  			"twopk:primaryKey",
   637  			[]interface{}{2, 2},
   638  			[]sql.Row{{1, 1, 3, 3}},
   639  		},
   640  		{
   641  			"twopk:primaryKey",
   642  			[]interface{}{2, 3},
   643  			[]sql.Row{{1, 2, 3, 4}, {1, 1, 3, 3}},
   644  		},
   645  		{
   646  			"twopk:idx_v2v1",
   647  			[]interface{}{3, 4},
   648  			nil,
   649  		},
   650  		{
   651  			"twopk:idx_v2v1",
   652  			[]interface{}{4, 3},
   653  			nil,
   654  		},
   655  		{
   656  			"twopk:idx_v2v1",
   657  			[]interface{}{4, 4},
   658  			[]sql.Row{{1, 1, 3, 3}},
   659  		},
   660  		//{
   661  		//	"twopk:idx_v2v1_PARTIAL_1",
   662  		//	[]interface{}{3},
   663  		//	nil,
   664  		//},
   665  		//{
   666  		//	"twopk:idx_v2v1_PARTIAL_1",
   667  		//	[]interface{}{4},
   668  		//	[]sql.Row{{2, 2, 4, 3}, {1, 1, 3, 3}},
   669  		//},
   670  	}
   671  
   672  	for _, typesTest := range typesTests {
   673  		tests = append(tests, doltIndexTestCase{
   674  			typesTest.indexName,
   675  			typesTest.belowfirstValue,
   676  			nil,
   677  		}, doltIndexTestCase{
   678  			typesTest.indexName,
   679  			typesTest.firstValue,
   680  			nil,
   681  		}, doltIndexTestCase{
   682  			typesTest.indexName,
   683  			typesTest.secondValue,
   684  			[]sql.Row{
   685  				typesTableRow1,
   686  			},
   687  		}, doltIndexTestCase{
   688  			typesTest.indexName,
   689  			typesTest.thirdValue,
   690  			[]sql.Row{
   691  				typesTableRow2,
   692  				typesTableRow1,
   693  			},
   694  		}, doltIndexTestCase{
   695  			typesTest.indexName,
   696  			typesTest.fourthValue,
   697  			[]sql.Row{
   698  				typesTableRow3,
   699  				typesTableRow2,
   700  				typesTableRow1,
   701  			},
   702  		}, doltIndexTestCase{
   703  			typesTest.indexName,
   704  			typesTest.fifthValue,
   705  			[]sql.Row{
   706  				typesTableRow4,
   707  				typesTableRow3,
   708  				typesTableRow2,
   709  				typesTableRow1,
   710  			},
   711  		}, doltIndexTestCase{
   712  			typesTest.indexName,
   713  			typesTest.abovefifthValue,
   714  			[]sql.Row{
   715  				typesTableRow5,
   716  				typesTableRow4,
   717  				typesTableRow3,
   718  				typesTableRow2,
   719  				typesTableRow1,
   720  			},
   721  		})
   722  	}
   723  
   724  	for _, test := range tests {
   725  		t.Run(fmt.Sprintf("%s|%v", test.indexName, test.keys), func(t *testing.T) {
   726  			ctx := sql.NewEmptyContext()
   727  			index, ok := indexMap[test.indexName]
   728  			require.True(t, ok)
   729  			testDoltIndex(t, ctx, root, test.keys, test.expectedRows, index, indexComp_Lt)
   730  		})
   731  	}
   732  }
   733  
   734  func TestDoltIndexLessThanOrEqual(t *testing.T) {
   735  	root, indexMap := doltIndexSetup(t)
   736  
   737  	tests := []struct {
   738  		indexName    string
   739  		keys         []interface{}
   740  		expectedRows []sql.Row
   741  	}{
   742  		{
   743  			"onepk:primaryKey",
   744  			[]interface{}{1},
   745  			[]sql.Row{{1, 1, 1}},
   746  		},
   747  		{
   748  			"onepk:primaryKey",
   749  			[]interface{}{3},
   750  			[]sql.Row{{3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   751  		},
   752  		{
   753  			"onepk:primaryKey",
   754  			[]interface{}{4},
   755  			[]sql.Row{{4, 4, 3}, {3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   756  		},
   757  		{
   758  			"onepk:idx_v1",
   759  			[]interface{}{1},
   760  			[]sql.Row{{2, 1, 2}, {1, 1, 1}},
   761  		},
   762  		{
   763  			"onepk:idx_v1",
   764  			[]interface{}{3},
   765  			[]sql.Row{{3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   766  		},
   767  		{
   768  			"onepk:idx_v1",
   769  			[]interface{}{4},
   770  			[]sql.Row{{4, 4, 3}, {3, 3, 3}, {2, 1, 2}, {1, 1, 1}},
   771  		},
   772  		{
   773  			"twopk:primaryKey",
   774  			[]interface{}{1, 1},
   775  			[]sql.Row{{1, 1, 3, 3}},
   776  		},
   777  		{
   778  			"twopk:primaryKey",
   779  			[]interface{}{2, 1},
   780  			[]sql.Row{{2, 1, 4, 4}, {1, 1, 3, 3}},
   781  		},
   782  		{
   783  			"twopk:primaryKey",
   784  			[]interface{}{2, 2},
   785  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   786  		},
   787  		{
   788  			"twopk:idx_v2v1",
   789  			[]interface{}{3, 4},
   790  			[]sql.Row{{2, 2, 4, 3}, {1, 1, 3, 3}},
   791  		},
   792  		{
   793  			"twopk:idx_v2v1",
   794  			[]interface{}{4, 3},
   795  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}},
   796  		},
   797  		{
   798  			"twopk:idx_v2v1",
   799  			[]interface{}{4, 4},
   800  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   801  		},
   802  		//{
   803  		//	"twopk:idx_v2v1_PARTIAL_1",
   804  		//	[]interface{}{3},
   805  		//	[]sql.Row{{1, 1, 3, 3}, {2, 2, 4, 3}},
   806  		//},
   807  		//{
   808  		//	"twopk:idx_v2v1_PARTIAL_1",
   809  		//	[]interface{}{4},
   810  		//	[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   811  		//},
   812  	}
   813  
   814  	for _, typesTest := range typesTests {
   815  		tests = append(tests, doltIndexTestCase{
   816  			typesTest.indexName,
   817  			typesTest.belowfirstValue,
   818  			nil,
   819  		}, doltIndexTestCase{
   820  			typesTest.indexName,
   821  			typesTest.firstValue,
   822  			[]sql.Row{
   823  				typesTableRow1,
   824  			},
   825  		}, doltIndexTestCase{
   826  			typesTest.indexName,
   827  			typesTest.secondValue,
   828  			[]sql.Row{
   829  				typesTableRow2,
   830  				typesTableRow1,
   831  			},
   832  		}, doltIndexTestCase{
   833  			typesTest.indexName,
   834  			typesTest.thirdValue,
   835  			[]sql.Row{
   836  				typesTableRow3,
   837  				typesTableRow2,
   838  				typesTableRow1,
   839  			},
   840  		}, doltIndexTestCase{
   841  			typesTest.indexName,
   842  			typesTest.fourthValue,
   843  			[]sql.Row{
   844  				typesTableRow4,
   845  				typesTableRow3,
   846  				typesTableRow2,
   847  				typesTableRow1,
   848  			},
   849  		}, doltIndexTestCase{
   850  			typesTest.indexName,
   851  			typesTest.fifthValue,
   852  			[]sql.Row{
   853  				typesTableRow5,
   854  				typesTableRow4,
   855  				typesTableRow3,
   856  				typesTableRow2,
   857  				typesTableRow1,
   858  			},
   859  		}, doltIndexTestCase{
   860  			typesTest.indexName,
   861  			typesTest.abovefifthValue,
   862  			[]sql.Row{
   863  				typesTableRow5,
   864  				typesTableRow4,
   865  				typesTableRow3,
   866  				typesTableRow2,
   867  				typesTableRow1,
   868  			},
   869  		})
   870  	}
   871  
   872  	for _, test := range tests {
   873  		t.Run(fmt.Sprintf("%s|%v", test.indexName, test.keys), func(t *testing.T) {
   874  			ctx := sql.NewEmptyContext()
   875  			index, ok := indexMap[test.indexName]
   876  			require.True(t, ok)
   877  			testDoltIndex(t, ctx, root, test.keys, test.expectedRows, index, indexComp_LtE)
   878  		})
   879  	}
   880  }
   881  
   882  func TestDoltIndexBetween(t *testing.T) {
   883  	root, indexMap := doltIndexSetup(t)
   884  
   885  	tests := []doltIndexBetweenTestCase{
   886  		{
   887  			"onepk:primaryKey",
   888  			[]interface{}{1},
   889  			[]interface{}{2},
   890  			[]sql.Row{{1, 1, 1}, {2, 1, 2}},
   891  		},
   892  		{
   893  			"onepk:primaryKey",
   894  			[]interface{}{3},
   895  			[]interface{}{3},
   896  			[]sql.Row{{3, 3, 3}},
   897  		},
   898  		{
   899  			"onepk:primaryKey",
   900  			[]interface{}{4},
   901  			[]interface{}{6},
   902  			[]sql.Row{{4, 4, 3}},
   903  		},
   904  		{
   905  			"onepk:primaryKey",
   906  			[]interface{}{0},
   907  			[]interface{}{10},
   908  			[]sql.Row{{1, 1, 1}, {2, 1, 2}, {3, 3, 3}, {4, 4, 3}},
   909  		},
   910  		{
   911  			"onepk:idx_v1",
   912  			[]interface{}{1},
   913  			[]interface{}{2},
   914  			[]sql.Row{{1, 1, 1}, {2, 1, 2}},
   915  		},
   916  		{
   917  			"onepk:idx_v1",
   918  			[]interface{}{2},
   919  			[]interface{}{4},
   920  			[]sql.Row{{3, 3, 3}, {4, 4, 3}},
   921  		},
   922  		{
   923  			"onepk:idx_v1",
   924  			[]interface{}{1},
   925  			[]interface{}{4},
   926  			[]sql.Row{{1, 1, 1}, {2, 1, 2}, {3, 3, 3}, {4, 4, 3}},
   927  		},
   928  		{
   929  			"twopk:primaryKey",
   930  			[]interface{}{1, 1},
   931  			[]interface{}{1, 1},
   932  			[]sql.Row{{1, 1, 3, 3}},
   933  		},
   934  		{
   935  			"twopk:primaryKey",
   936  			[]interface{}{1, 1},
   937  			[]interface{}{2, 1},
   938  			[]sql.Row{{1, 1, 3, 3}, {2, 1, 4, 4}},
   939  		},
   940  		{
   941  			"twopk:primaryKey",
   942  			[]interface{}{1, 1},
   943  			[]interface{}{2, 2},
   944  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   945  		},
   946  		{
   947  			"twopk:primaryKey",
   948  			[]interface{}{1, 1},
   949  			[]interface{}{2, 5},
   950  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   951  		},
   952  		{
   953  			"twopk:idx_v2v1",
   954  			[]interface{}{3, 3},
   955  			[]interface{}{3, 4},
   956  			[]sql.Row{{1, 1, 3, 3}, {2, 2, 4, 3}},
   957  		},
   958  		{
   959  			"twopk:idx_v2v1",
   960  			[]interface{}{3, 4},
   961  			[]interface{}{4, 4},
   962  			[]sql.Row{{2, 1, 4, 4}, {2, 2, 4, 3}},
   963  		},
   964  		{
   965  			"twopk:idx_v2v1",
   966  			[]interface{}{3, 3},
   967  			[]interface{}{4, 4},
   968  			[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   969  		},
   970  		//{
   971  		//	"twopk:idx_v2v1_PARTIAL_1",
   972  		//	[]interface{}{3},
   973  		//	[]interface{}{3},
   974  		//	[]sql.Row{{1, 1, 3, 3}, {2, 2, 4, 3}},
   975  		//},
   976  		//{
   977  		//	"twopk:idx_v2v1_PARTIAL_1",
   978  		//	[]interface{}{4},
   979  		//	[]interface{}{4},
   980  		//	[]sql.Row{{1, 2, 3, 4}, {2, 1, 4, 4}},
   981  		//},
   982  		//{
   983  		//	"twopk:idx_v2v1_PARTIAL_1",
   984  		//	[]interface{}{3},
   985  		//	[]interface{}{4},
   986  		//	[]sql.Row{{1, 1, 3, 3}, {1, 2, 3, 4}, {2, 1, 4, 4}, {2, 2, 4, 3}},
   987  		//},
   988  	}
   989  
   990  	for _, typesTest := range typesTests {
   991  		tests = append(tests, doltIndexBetweenTestCase{
   992  			typesTest.indexName,
   993  			typesTest.belowfirstValue,
   994  			typesTest.belowfirstValue,
   995  			nil,
   996  		}, doltIndexBetweenTestCase{
   997  			typesTest.indexName,
   998  			typesTest.belowfirstValue,
   999  			typesTest.firstValue,
  1000  			[]sql.Row{
  1001  				typesTableRow1,
  1002  			},
  1003  		}, doltIndexBetweenTestCase{
  1004  			typesTest.indexName,
  1005  			typesTest.belowfirstValue,
  1006  			typesTest.secondValue,
  1007  			[]sql.Row{
  1008  				typesTableRow1,
  1009  				typesTableRow2,
  1010  			},
  1011  		}, doltIndexBetweenTestCase{
  1012  			typesTest.indexName,
  1013  			typesTest.belowfirstValue,
  1014  			typesTest.thirdValue,
  1015  			[]sql.Row{
  1016  				typesTableRow1,
  1017  				typesTableRow2,
  1018  				typesTableRow3,
  1019  			},
  1020  		}, doltIndexBetweenTestCase{
  1021  			typesTest.indexName,
  1022  			typesTest.secondValue,
  1023  			typesTest.secondValue,
  1024  			[]sql.Row{
  1025  				typesTableRow2,
  1026  			},
  1027  		}, doltIndexBetweenTestCase{
  1028  			typesTest.indexName,
  1029  			typesTest.thirdValue,
  1030  			typesTest.fifthValue,
  1031  			[]sql.Row{
  1032  				typesTableRow3,
  1033  				typesTableRow4,
  1034  				typesTableRow5,
  1035  			},
  1036  		}, doltIndexBetweenTestCase{
  1037  			typesTest.indexName,
  1038  			typesTest.fifthValue,
  1039  			typesTest.abovefifthValue,
  1040  			[]sql.Row{
  1041  				typesTableRow5,
  1042  			},
  1043  		}, doltIndexBetweenTestCase{
  1044  			typesTest.indexName,
  1045  			typesTest.abovefifthValue,
  1046  			typesTest.abovefifthValue,
  1047  			nil,
  1048  		})
  1049  	}
  1050  
  1051  	for _, test := range tests {
  1052  		t.Run(fmt.Sprintf("%s|%v%v", test.indexName, test.greaterThanOrEqual, test.lessThanOrEqual), func(t *testing.T) {
  1053  			ctx := sql.NewEmptyContext()
  1054  
  1055  			idx, ok := indexMap[test.indexName]
  1056  			require.True(t, ok)
  1057  
  1058  			expectedRows := convertSqlRowToInt64(test.expectedRows)
  1059  
  1060  			exprs := idx.Expressions()
  1061  			sqlIndex := sql.NewIndexBuilder(idx)
  1062  			for i := range test.greaterThanOrEqual {
  1063  				sqlIndex = sqlIndex.GreaterOrEqual(ctx, exprs[i], test.greaterThanOrEqual[i]).LessOrEqual(ctx, exprs[i], test.lessThanOrEqual[i])
  1064  			}
  1065  			indexLookup, err := sqlIndex.Build(ctx)
  1066  			require.NoError(t, err)
  1067  
  1068  			pkSch, err := sqlutil.FromDoltSchema("", "fake_table", idx.Schema())
  1069  			require.NoError(t, err)
  1070  
  1071  			dt, ok, err := root.GetTable(ctx, doltdb.TableName{Name: idx.Table()})
  1072  			require.NoError(t, err)
  1073  			require.True(t, ok)
  1074  
  1075  			indexIter, err := index.RowIterForIndexLookup(ctx, NoCacheTableable{dt}, indexLookup, pkSch, nil)
  1076  			require.NoError(t, err)
  1077  
  1078  			var readRows []sql.Row
  1079  			var nextRow sql.Row
  1080  			for nextRow, err = indexIter.Next(ctx); err == nil; nextRow, err = indexIter.Next(ctx) {
  1081  				readRows = append(readRows, nextRow)
  1082  			}
  1083  			require.Equal(t, io.EOF, err)
  1084  
  1085  			requireUnorderedRowsEqual(t, pkSch.Schema, expectedRows, readRows)
  1086  		})
  1087  	}
  1088  }
  1089  
  1090  type NoCacheTableable struct {
  1091  	dt *doltdb.Table
  1092  }
  1093  
  1094  func (t NoCacheTableable) DoltTable(ctx *sql.Context) (*doltdb.Table, error) {
  1095  	return t.dt, nil
  1096  }
  1097  
  1098  func (t NoCacheTableable) DataCacheKey(ctx *sql.Context) (doltdb.DataCacheKey, bool, error) {
  1099  	return doltdb.DataCacheKey{}, false, nil
  1100  }
  1101  
  1102  type rowSlice struct {
  1103  	rows    []sql.Row
  1104  	sortErr error
  1105  }
  1106  
  1107  func (r *rowSlice) setSortErr(err error) {
  1108  	if err == nil || r.sortErr != nil {
  1109  		return
  1110  	}
  1111  
  1112  	r.sortErr = err
  1113  }
  1114  
  1115  func (r *rowSlice) Len() int {
  1116  	return len(r.rows)
  1117  }
  1118  
  1119  func (r *rowSlice) Less(i, j int) bool {
  1120  	r1 := r.rows[i]
  1121  	r2 := r.rows[j]
  1122  
  1123  	longerLen := len(r1)
  1124  	if len(r2) > longerLen {
  1125  		longerLen = len(r2)
  1126  	}
  1127  
  1128  	for pos := 0; pos < longerLen; pos++ {
  1129  		if pos == len(r1) {
  1130  			return true
  1131  		}
  1132  
  1133  		if pos == len(r2) {
  1134  			return false
  1135  		}
  1136  
  1137  		c1, c2 := r1[pos], r2[pos]
  1138  
  1139  		var cmp int
  1140  		var err error
  1141  		switch typedVal := c1.(type) {
  1142  		case int:
  1143  			cmp, err = signedCompare(int64(typedVal), c2)
  1144  		case int64:
  1145  			cmp, err = signedCompare(typedVal, c2)
  1146  		case int32:
  1147  			cmp, err = signedCompare(int64(typedVal), c2)
  1148  		case int16:
  1149  			cmp, err = signedCompare(int64(typedVal), c2)
  1150  		case int8:
  1151  			cmp, err = signedCompare(int64(typedVal), c2)
  1152  
  1153  		case uint:
  1154  			cmp, err = unsignedCompare(uint64(typedVal), c2)
  1155  		case uint64:
  1156  			cmp, err = unsignedCompare(typedVal, c2)
  1157  		case uint32:
  1158  			cmp, err = unsignedCompare(uint64(typedVal), c2)
  1159  		case uint16:
  1160  			cmp, err = unsignedCompare(uint64(typedVal), c2)
  1161  		case uint8:
  1162  			cmp, err = unsignedCompare(uint64(typedVal), c2)
  1163  
  1164  		case float64:
  1165  			cmp, err = floatCompare(float64(typedVal), c2)
  1166  		case float32:
  1167  			cmp, err = floatCompare(float64(typedVal), c2)
  1168  
  1169  		case string:
  1170  			cmp, err = stringCompare(typedVal, c2)
  1171  
  1172  		default:
  1173  			panic("not implemented please add")
  1174  		}
  1175  
  1176  		if err != nil {
  1177  			r.setSortErr(err)
  1178  			return false
  1179  		}
  1180  
  1181  		if cmp != 0 {
  1182  			return cmp < 0
  1183  		}
  1184  	}
  1185  
  1186  	// equal
  1187  	return false
  1188  }
  1189  
  1190  func (r *rowSlice) equals(other *rowSlice, sch sql.Schema) bool {
  1191  	if len(r.rows) != len(other.rows) {
  1192  		return false
  1193  	}
  1194  	for i := range r.rows {
  1195  		ok, err := r.rows[i].Equals(other.rows[i], sch)
  1196  		if err != nil || !ok {
  1197  			return false
  1198  		}
  1199  	}
  1200  	return true
  1201  }
  1202  
  1203  func signedCompare(n1 int64, c interface{}) (int, error) {
  1204  	var n2 int64
  1205  	switch typedVal := c.(type) {
  1206  	case int:
  1207  		n2 = int64(typedVal)
  1208  	case int64:
  1209  		n2 = typedVal
  1210  	case int32:
  1211  		n2 = int64(typedVal)
  1212  	case int16:
  1213  		n2 = int64(typedVal)
  1214  	case int8:
  1215  		n2 = int64(typedVal)
  1216  	default:
  1217  		return 0, errors.New("comparing rows with different schemas")
  1218  	}
  1219  
  1220  	return int(n1 - n2), nil
  1221  }
  1222  
  1223  func unsignedCompare(n1 uint64, c interface{}) (int, error) {
  1224  	var n2 uint64
  1225  	switch typedVal := c.(type) {
  1226  	case uint:
  1227  		n2 = uint64(typedVal)
  1228  	case uint64:
  1229  		n2 = typedVal
  1230  	case uint32:
  1231  		n2 = uint64(typedVal)
  1232  	case uint16:
  1233  		n2 = uint64(typedVal)
  1234  	case uint8:
  1235  		n2 = uint64(typedVal)
  1236  	default:
  1237  		return 0, errors.New("comparing rows with different schemas")
  1238  	}
  1239  
  1240  	if n1 == n2 {
  1241  		return 0, nil
  1242  	} else if n1 < n2 {
  1243  		return -1, nil
  1244  	} else {
  1245  		return 1, nil
  1246  	}
  1247  }
  1248  
  1249  func floatCompare(n1 float64, c interface{}) (int, error) {
  1250  	var n2 float64
  1251  	switch typedVal := c.(type) {
  1252  	case float32:
  1253  		n2 = float64(typedVal)
  1254  	case float64:
  1255  		n2 = typedVal
  1256  	default:
  1257  		return 0, errors.New("comparing rows with different schemas")
  1258  	}
  1259  
  1260  	if n1 == n2 {
  1261  		return 0, nil
  1262  	} else if n1 < n2 {
  1263  		return -1, nil
  1264  	} else {
  1265  		return 1, nil
  1266  	}
  1267  }
  1268  
  1269  func stringCompare(s1 string, c interface{}) (int, error) {
  1270  	s2, ok := c.(string)
  1271  	if !ok {
  1272  		return 0, errors.New("comparing rows with different schemas")
  1273  	}
  1274  
  1275  	return strings.Compare(s1, s2), nil
  1276  }
  1277  
  1278  func (r *rowSlice) Swap(i, j int) {
  1279  	r.rows[i], r.rows[j] = r.rows[j], r.rows[i]
  1280  }
  1281  
  1282  func requireUnorderedRowsEqual(t *testing.T, s sql.Schema, rows1, rows2 []sql.Row) {
  1283  	slice1 := &rowSlice{rows: rows1}
  1284  	sort.Stable(slice1)
  1285  	require.NoError(t, slice1.sortErr)
  1286  
  1287  	slice2 := &rowSlice{rows: rows2}
  1288  	sort.Stable(slice2)
  1289  	require.NoError(t, slice2.sortErr)
  1290  
  1291  	assert.True(t, slice1.equals(slice2, s))
  1292  }
  1293  
  1294  func testDoltIndex(t *testing.T, ctx *sql.Context, root doltdb.RootValue, keys []interface{}, expectedRows []sql.Row, idx index.DoltIndex, cmp indexComp) {
  1295  	ctx = sql.NewEmptyContext()
  1296  	exprs := idx.Expressions()
  1297  	builder := sql.NewIndexBuilder(idx)
  1298  	for i, key := range keys {
  1299  		switch cmp {
  1300  		case indexComp_Eq:
  1301  			builder = builder.Equals(ctx, exprs[i], key)
  1302  		case indexComp_NEq:
  1303  			builder = builder.NotEquals(ctx, exprs[i], key)
  1304  		case indexComp_Gt:
  1305  			builder = builder.GreaterThan(ctx, exprs[i], key)
  1306  		case indexComp_GtE:
  1307  			builder = builder.GreaterOrEqual(ctx, exprs[i], key)
  1308  		case indexComp_Lt:
  1309  			builder = builder.LessThan(ctx, exprs[i], key)
  1310  		case indexComp_LtE:
  1311  			builder = builder.LessOrEqual(ctx, exprs[i], key)
  1312  		default:
  1313  			panic("should not be hit")
  1314  		}
  1315  	}
  1316  	indexLookup, err := builder.Build(ctx)
  1317  	require.NoError(t, err)
  1318  
  1319  	dt, ok, err := root.GetTable(ctx, doltdb.TableName{Name: idx.Table()})
  1320  	require.NoError(t, err)
  1321  	require.True(t, ok)
  1322  
  1323  	pkSch, err := sqlutil.FromDoltSchema("", "fake_table", idx.Schema())
  1324  	require.NoError(t, err)
  1325  
  1326  	indexIter, err := index.RowIterForIndexLookup(ctx, NoCacheTableable{dt}, indexLookup, pkSch, nil)
  1327  	require.NoError(t, err)
  1328  
  1329  	var readRows []sql.Row
  1330  	var nextRow sql.Row
  1331  	for nextRow, err = indexIter.Next(ctx); err == nil; nextRow, err = indexIter.Next(ctx) {
  1332  		readRows = append(readRows, nextRow)
  1333  	}
  1334  	require.Equal(t, io.EOF, err)
  1335  
  1336  	requireUnorderedRowsEqual(t, pkSch.Schema, convertSqlRowToInt64(expectedRows), readRows)
  1337  }
  1338  
  1339  func doltIndexSetup(t *testing.T) (doltdb.RootValue, map[string]index.DoltIndex) {
  1340  	ctx := context.Background()
  1341  	dEnv := dtestutils.CreateTestEnv()
  1342  	root, err := dEnv.WorkingRoot(ctx)
  1343  	if err != nil {
  1344  		panic(err)
  1345  	}
  1346  	root, err = sqle.ExecuteSql(dEnv, root, `
  1347  CREATE TABLE onepk (
  1348    pk1 BIGINT PRIMARY KEY,
  1349    v1 BIGINT,
  1350    v2 BIGINT
  1351  );
  1352  CREATE TABLE twopk (
  1353    pk1 BIGINT,
  1354    pk2 BIGINT,
  1355    v1 BIGINT,
  1356    v2 BIGINT,
  1357    PRIMARY KEY (pk1,pk2)
  1358  );
  1359  CREATE TABLE types (
  1360    pk1 MEDIUMINT PRIMARY KEY,
  1361    v1 BIT(4),
  1362    v2 DATETIME,
  1363    v3 DECIMAL(10, 5),
  1364    v4 ENUM('_', 'a', 'b', 'c', 'd', 'e', '.'),
  1365    v5 DOUBLE,
  1366    v6 SET('a', 'b', 'c'),
  1367    v7 TIME,
  1368    v8 VARCHAR(2),
  1369    v9 YEAR
  1370  );
  1371  CREATE INDEX idx_v1 ON onepk(v1);
  1372  CREATE INDEX idx_v2v1 ON twopk(v2, v1);
  1373  CREATE INDEX idx_bit ON types(v1);
  1374  CREATE INDEX idx_datetime ON types(v2);
  1375  CREATE INDEX idx_decimal ON types(v3);
  1376  CREATE INDEX idx_enum ON types(v4);
  1377  CREATE INDEX idx_double ON types(v5);
  1378  CREATE INDEX idx_set ON types(v6);
  1379  CREATE INDEX idx_time ON types(v7);
  1380  CREATE INDEX idx_varchar ON types(v8);
  1381  CREATE INDEX idx_year ON types(v9);
  1382  INSERT INTO onepk VALUES (1, 1, 1), (2, 1, 2), (3, 3, 3), (4, 4, 3);
  1383  INSERT INTO twopk VALUES (1, 1, 3, 3), (1, 2, 3, 4), (2, 1, 4, 4), (2, 2, 4, 3);
  1384  INSERT INTO types VALUES (-3, 1, '2020-05-14 12:00:00', -3.3, 'a', -3.3, 'a', '-00:03:03', 'a', 1980);
  1385  INSERT INTO types VALUES (3, 5, '2020-05-14 12:00:04', 3.3, 'e', 3.3, 'b,c', '00:03:03', 'e', 2020);
  1386  INSERT INTO types VALUES (0, 3, '2020-05-14 12:00:02', 0.0, 'c', 0.0, 'c', '00:00:00', 'c', 2000);
  1387  INSERT INTO types VALUES (-1, 2, '2020-05-14 12:00:01', -1.1, 'b', -1.1, 'a,b', '-00:01:01', 'b', 1990);
  1388  INSERT INTO types VALUES (1, 4, '2020-05-14 12:00:03', 1.1, 'd', 1.1, 'a,c', '00:01:01', 'd', 2010);
  1389  `)
  1390  	require.NoError(t, err)
  1391  
  1392  	indexMap := make(map[string]index.DoltIndex)
  1393  
  1394  	dbname := "dolt"
  1395  	for _, name := range []string{"onepk", "twopk", "types"} {
  1396  		tbl, ok, err := root.GetTable(ctx, doltdb.TableName{Name: name})
  1397  		require.NoError(t, err)
  1398  		require.True(t, ok)
  1399  
  1400  		indexes, err := index.DoltIndexesFromTable(ctx, dbname, name, tbl)
  1401  		require.NoError(t, err)
  1402  
  1403  		pkName := name + ":" + "primaryKey"
  1404  		indexMap[pkName] = indexes[0].(index.DoltIndex)
  1405  
  1406  		for _, idx := range indexes[1:] {
  1407  			idxName := name + ":" + idx.ID()
  1408  			indexMap[idxName] = idx.(index.DoltIndex)
  1409  		}
  1410  	}
  1411  
  1412  	return root, indexMap
  1413  }
  1414  
  1415  func mustTime(timeString string) time.Time {
  1416  	t, err := time.Parse("2006-01-02 15:04:05", timeString)
  1417  	if err != nil {
  1418  		panic(err)
  1419  	}
  1420  	return t
  1421  }
  1422  
  1423  func mustDecimal(s string) decimal.Decimal {
  1424  	d, err := decimal.NewFromString(s)
  1425  	if err != nil {
  1426  		panic(err)
  1427  	}
  1428  	return d
  1429  }
  1430  
  1431  func convertSqlRowToInt64(sqlRows []sql.Row) []sql.Row {
  1432  	if sqlRows == nil {
  1433  		return nil
  1434  	}
  1435  	newSqlRows := make([]sql.Row, len(sqlRows))
  1436  	for i, sqlRow := range sqlRows {
  1437  		newSqlRow := make(sql.Row, len(sqlRow))
  1438  		for j := range sqlRow {
  1439  			switch v := sqlRow[j].(type) {
  1440  			case int:
  1441  				newSqlRow[j] = int64(v)
  1442  			case int8:
  1443  				newSqlRow[j] = int64(v)
  1444  			case int16:
  1445  				newSqlRow[j] = int64(v)
  1446  			case int32:
  1447  				newSqlRow[j] = int64(v)
  1448  			case int64:
  1449  				newSqlRow[j] = v
  1450  			case nil:
  1451  				newSqlRow[j] = nil
  1452  			default:
  1453  				return sqlRows
  1454  			}
  1455  		}
  1456  		newSqlRows[i] = newSqlRow
  1457  	}
  1458  	return newSqlRows
  1459  }
  1460  
  1461  func TestSplitNullsFromRange(t *testing.T) {
  1462  	t.Run("EmptyRange", func(t *testing.T) {
  1463  		r, err := index.SplitNullsFromRange(sql.Range{})
  1464  		assert.NoError(t, err)
  1465  		assert.NotNil(t, r)
  1466  		assert.Len(t, r, 1)
  1467  		assert.Len(t, r[0], 0)
  1468  	})
  1469  
  1470  	t.Run("ThreeColumnNoNullsRange", func(t *testing.T) {
  1471  		r := sql.Range{sql.LessThanRangeColumnExpr(10, types.Int8), sql.GreaterThanRangeColumnExpr(16, types.Int8), sql.NotNullRangeColumnExpr(types.Int8)}
  1472  		rs, err := index.SplitNullsFromRange(r)
  1473  		assert.NoError(t, err)
  1474  		assert.NotNil(t, rs)
  1475  		assert.Len(t, rs, 1)
  1476  		assert.Len(t, rs[0], 3)
  1477  		assert.Equal(t, r, rs[0])
  1478  	})
  1479  
  1480  	t.Run("LastColumnOnlyNull", func(t *testing.T) {
  1481  		r := sql.Range{sql.LessThanRangeColumnExpr(10, types.Int8), sql.GreaterThanRangeColumnExpr(16, types.Int8), sql.NullRangeColumnExpr(types.Int8)}
  1482  		rs, err := index.SplitNullsFromRange(r)
  1483  		assert.NoError(t, err)
  1484  		assert.NotNil(t, rs)
  1485  		assert.Len(t, rs, 1)
  1486  		assert.Len(t, rs[0], 3)
  1487  		assert.Equal(t, r, rs[0])
  1488  	})
  1489  
  1490  	t.Run("LastColumnAll", func(t *testing.T) {
  1491  		r := sql.Range{sql.LessThanRangeColumnExpr(10, types.Int8), sql.GreaterThanRangeColumnExpr(16, types.Int8), sql.AllRangeColumnExpr(types.Int8)}
  1492  		rs, err := index.SplitNullsFromRange(r)
  1493  		assert.NoError(t, err)
  1494  		assert.NotNil(t, rs)
  1495  		assert.Len(t, rs, 2)
  1496  		assert.Len(t, rs[0], 3)
  1497  		assert.Len(t, rs[1], 3)
  1498  		assert.Equal(t, r[:2], rs[0][:2])
  1499  		assert.Equal(t, r[:2], rs[1][:2])
  1500  		assert.Equal(t, sql.NullRangeColumnExpr(types.Int8), rs[0][2])
  1501  		assert.Equal(t, sql.NotNullRangeColumnExpr(types.Int8), rs[1][2])
  1502  	})
  1503  
  1504  	t.Run("FirstColumnAll", func(t *testing.T) {
  1505  		r := sql.Range{sql.AllRangeColumnExpr(types.Int8), sql.LessThanRangeColumnExpr(10, types.Int8), sql.GreaterThanRangeColumnExpr(16, types.Int8)}
  1506  		rs, err := index.SplitNullsFromRange(r)
  1507  		assert.NoError(t, err)
  1508  		assert.NotNil(t, rs)
  1509  		assert.Len(t, rs, 2)
  1510  		assert.Len(t, rs[0], 3)
  1511  		assert.Len(t, rs[1], 3)
  1512  		assert.Equal(t, r[1:], rs[0][1:])
  1513  		assert.Equal(t, r[1:], rs[1][1:])
  1514  		assert.Equal(t, sql.NullRangeColumnExpr(types.Int8), rs[0][0])
  1515  		assert.Equal(t, sql.NotNullRangeColumnExpr(types.Int8), rs[1][0])
  1516  	})
  1517  
  1518  	t.Run("AllColumnAll", func(t *testing.T) {
  1519  		r := sql.Range{sql.AllRangeColumnExpr(types.Int8), sql.AllRangeColumnExpr(types.Int8), sql.AllRangeColumnExpr(types.Int8)}
  1520  		rs, err := index.SplitNullsFromRange(r)
  1521  		assert.NoError(t, err)
  1522  		assert.NotNil(t, rs)
  1523  		assert.Len(t, rs, 8)
  1524  	})
  1525  }