github.com/dolthub/go-mysql-server@v0.18.0/sql/range_test.go (about)

     1  // Copyright 2021 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 sql_test
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"github.com/shopspring/decimal"
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  
    25  	"github.com/dolthub/go-mysql-server/sql"
    26  	"github.com/dolthub/go-mysql-server/sql/expression"
    27  	"github.com/dolthub/go-mysql-server/sql/types"
    28  )
    29  
    30  var rangeType = types.Uint8
    31  
    32  func TestRangeOverlapTwoColumns(t *testing.T) {
    33  	ctx := sql.NewEmptyContext()
    34  	x, y, _, values2, _, _ := setup()
    35  
    36  	tests := []struct {
    37  		reference sql.Expression
    38  		ranges    sql.RangeCollection
    39  	}{
    40  		{
    41  			or(
    42  				and(lt(x, 2), gt(y, 5)),
    43  				and(gt(x, 8), gt(y, 5)),
    44  				and(gt(x, 5), gt(y, 8)),
    45  			),
    46  			sql.RangeCollection{
    47  				r(rlt(2), rgt(5)),
    48  				r(rgt(8), rgt(5)),
    49  				r(rgt(5), rgt(8)),
    50  			},
    51  		},
    52  		{
    53  			or(
    54  				and(lt(x, 2), gt(y, 5)),
    55  				and(gt(x, 8), gt(y, 5)),
    56  				and(gt(x, 5), lt(y, 8)),
    57  			),
    58  			sql.RangeCollection{
    59  				r(rlt(2), rgt(5)),
    60  				r(rgt(8), rgt(5)),
    61  				r(rgt(5), rlt(8)),
    62  			},
    63  		},
    64  		{
    65  			or(
    66  				and(gt(x, 1), gt(y, 1)),
    67  				and(gt(x, 2), gt(y, 2)),
    68  				and(gt(x, 3), gt(y, 3)),
    69  				and(gt(x, 4), gt(y, 4)),
    70  				and(gt(x, 5), gt(y, 5)),
    71  				and(gt(x, 6), gt(y, 6)),
    72  				and(gt(x, 7), gt(y, 7)),
    73  				and(gt(x, 8), gt(y, 8)),
    74  				and(gt(x, 9), gt(y, 9)),
    75  				and(lt(x, 1), lt(y, 1)),
    76  				and(lt(x, 2), lt(y, 2)),
    77  				and(lt(x, 3), lt(y, 3)),
    78  				and(lt(x, 4), lt(y, 4)),
    79  				and(lt(x, 5), lt(y, 5)),
    80  				and(lt(x, 6), lt(y, 6)),
    81  				and(lt(x, 7), lt(y, 7)),
    82  				and(lt(x, 8), lt(y, 8)),
    83  				and(lt(x, 9), lt(y, 9)),
    84  			),
    85  			sql.RangeCollection{
    86  				r(rgt(1), rgt(1)),
    87  				r(rgt(2), rgt(2)),
    88  				r(rgt(3), rgt(3)),
    89  				r(rgt(4), rgt(4)),
    90  				r(rgt(5), rgt(5)),
    91  				r(rgt(6), rgt(6)),
    92  				r(rgt(7), rgt(7)),
    93  				r(rgt(8), rgt(8)),
    94  				r(rgt(9), rgt(9)),
    95  				r(rlt(1), rlt(1)),
    96  				r(rlt(2), rlt(2)),
    97  				r(rlt(3), rlt(3)),
    98  				r(rlt(4), rlt(4)),
    99  				r(rlt(5), rlt(5)),
   100  				r(rlt(6), rlt(6)),
   101  				r(rlt(7), rlt(7)),
   102  				r(rlt(8), rlt(8)),
   103  				r(rlt(9), rlt(9)),
   104  			},
   105  		},
   106  		{
   107  			or(
   108  				and(gt(x, 2), gt(y, 2)),
   109  				and(eq(x, 4), eq(y, 4)),
   110  				and(lt(x, 9), lt(y, 9)),
   111  				and(eq(x, 6), eq(y, 6)),
   112  				and(eq(x, 8), eq(y, 8)),
   113  			),
   114  			sql.RangeCollection{
   115  				r(rgt(2), rgt(2)),
   116  				r(req(4), req(4)),
   117  				r(rlt(9), rlt(9)),
   118  				r(req(6), req(6)),
   119  				r(req(8), req(8)),
   120  			},
   121  		},
   122  		{
   123  			or(
   124  				and(gt(x, 2), gt(y, 2)),
   125  				and(eq(x, 4), eq(y, 4)),
   126  				and(lt(x, 9), lt(y, 9)),
   127  				and(eq(x, 6), eq(y, 6)),
   128  				and(eq(x, 8), eq(y, 8)),
   129  			),
   130  			sql.RangeCollection{
   131  				r(rgt(2), rgt(2)),
   132  				r(req(4), req(4)),
   133  				r(rlt(9), rlt(9)),
   134  				r(req(6), req(6)),
   135  				r(req(8), req(8)),
   136  			},
   137  		},
   138  		{
   139  			or(
   140  				and(cc(x, 2, 6), cc(y, 5, 10)),
   141  				and(cc(x, 3, 7), cc(y, 1, 4)),
   142  				and(oo(x, 4, 8), oo(y, 2, 5)),
   143  				and(oc(x, 5, 10), oc(y, 4, 7)),
   144  			),
   145  			sql.RangeCollection{
   146  				r(rcc(2, 6), rcc(5, 10)),
   147  				r(rcc(3, 7), rcc(1, 4)),
   148  				r(roo(4, 8), roo(2, 5)),
   149  				r(roc(5, 10), roc(4, 7)),
   150  			},
   151  		},
   152  		{
   153  			or(
   154  				and(cc(x, 1, 6), cc(y, 1, 3)),
   155  				and(cc(x, 1, 2), cc(y, 1, 3)),
   156  				and(cc(x, 3, 4), cc(y, 1, 3)),
   157  				and(cc(x, 5, 6), cc(y, 1, 3)),
   158  				and(cc(x, 2, 3), cc(y, 1, 2)),
   159  			),
   160  			sql.RangeCollection{
   161  				r(rcc(1, 6), rcc(1, 3)),
   162  				r(rcc(1, 2), rcc(1, 3)),
   163  				r(rcc(3, 4), rcc(1, 3)),
   164  				r(rcc(5, 6), rcc(1, 3)),
   165  			},
   166  		},
   167  		{
   168  			or(
   169  				and(cc(x, 1, 6), cc(y, 4, 7)),
   170  				and(cc(x, 4, 5), cc(y, 3, 8)),
   171  				and(cc(x, 3, 8), cc(y, 1, 6)),
   172  			),
   173  			sql.RangeCollection{
   174  				r(rcc(1, 6), rcc(4, 7)),
   175  				r(rcc(4, 5), rcc(3, 8)),
   176  				r(rcc(3, 8), rcc(1, 6)),
   177  			},
   178  		},
   179  	}
   180  
   181  	for _, test := range tests {
   182  		t.Run(fmt.Sprintf("Expr:  %s\nRange: %s", test.reference.String(), test.ranges.DebugString()), func(t *testing.T) {
   183  			discreteRanges, err := sql.RemoveOverlappingRanges(test.ranges...)
   184  			require.NoError(t, err)
   185  			verificationRanges, err := removeOverlappingRangesVerification(test.ranges...)
   186  			require.NoError(t, err)
   187  			for _, row := range values2 {
   188  				referenceBool, err := test.reference.Eval(ctx, row)
   189  				require.NoError(t, err)
   190  				rangeBool := evalRanges(t, discreteRanges, row)
   191  				assert.Equal(t, referenceBool, rangeBool, fmt.Sprintf("%v: DiscreteRanges: %s", row, discreteRanges.DebugString()))
   192  			}
   193  			discreteRanges, err = sql.SortRanges(discreteRanges...)
   194  			require.NoError(t, err)
   195  			verificationRanges, err = sql.SortRanges(verificationRanges...)
   196  			require.NoError(t, err)
   197  			ok, err := discreteRanges.Equals(verificationRanges)
   198  			require.NoError(t, err)
   199  			assert.True(t, ok)
   200  		})
   201  	}
   202  }
   203  
   204  func TestRangeOverlapThreeColumns(t *testing.T) {
   205  	ctx := sql.NewEmptyContext()
   206  	x, y, z, _, values3, _ := setup()
   207  
   208  	tests := []struct {
   209  		reference sql.Expression
   210  		ranges    sql.RangeCollection
   211  	}{
   212  		{
   213  			or(
   214  				and(gt(x, 2), gt(y, 2), gt(z, 2)),
   215  				and(lt(x, 8), lt(y, 8), lt(z, 8)),
   216  			),
   217  			sql.RangeCollection{
   218  				r(rgt(2), rgt(2), rgt(2)),
   219  				r(rlt(8), rlt(8), rlt(8)),
   220  			},
   221  		},
   222  		{
   223  			or(
   224  				and(gte(x, 3), gte(y, 3), gte(z, 3)),
   225  				and(lte(x, 5), lte(y, 5), lte(z, 5)),
   226  			),
   227  			sql.RangeCollection{
   228  				r(rgte(3), rgte(3), rgte(3)),
   229  				r(rlte(5), rlte(5), rlte(5)),
   230  			},
   231  		},
   232  		{
   233  			or(
   234  				and(gte(x, 3), gte(y, 4), gt(z, 5)),
   235  				and(lte(x, 6), lt(y, 7), lte(z, 8)),
   236  			),
   237  			sql.RangeCollection{
   238  				r(rgte(3), rgte(4), rgt(5)),
   239  				r(rlte(6), rlt(7), rlte(8)),
   240  			},
   241  		},
   242  		{
   243  			or(
   244  				and(gte(x, 4), gte(y, 4), gte(z, 3)),
   245  				and(lte(x, 4), lte(y, 4), lte(z, 5)),
   246  			),
   247  			sql.RangeCollection{
   248  				r(rgte(4), rgte(4), rgte(3)),
   249  				r(rlte(4), rlte(4), rlte(5)),
   250  			},
   251  		},
   252  		{
   253  			or(
   254  				and(gte(x, 4), gte(y, 3), gte(z, 4)),
   255  				and(lte(x, 4), lte(y, 5), lte(z, 4)),
   256  			),
   257  			sql.RangeCollection{
   258  				r(rgte(4), rgte(3), rgte(4)),
   259  				r(rlte(4), rlte(5), rlte(4)),
   260  			},
   261  		},
   262  		{
   263  			or(
   264  				and(gte(x, 3), gte(y, 4), gte(z, 4)),
   265  				and(lte(x, 5), lte(y, 4), lte(z, 4)),
   266  			),
   267  			sql.RangeCollection{
   268  				r(rgte(3), rgte(4), rgte(4)),
   269  				r(rlte(5), rlte(4), rlte(4)),
   270  			},
   271  		},
   272  		{
   273  			or(
   274  				and(lt(x, 4), gte(y, 3), lt(z, 4)),
   275  				and(gt(x, 4), lte(y, 5), gt(z, 4)),
   276  			),
   277  			sql.RangeCollection{
   278  				r(rlt(4), rgte(3), rlt(4)),
   279  				r(rgt(4), rlte(5), rgt(4)),
   280  			},
   281  		},
   282  		{
   283  			or(
   284  				and(gt(x, 3), gt(y, 2), eq(z, 2)),
   285  				and(lt(x, 4), gte(y, 7), lte(z, 2)),
   286  				and(lte(x, 9), gt(y, 5), gt(z, 1)),
   287  			),
   288  			sql.RangeCollection{
   289  				r(rgt(3), rgt(2), req(2)),
   290  				r(rlt(4), rgte(7), rlte(2)),
   291  				r(rlte(9), rgt(5), rgt(1)),
   292  			},
   293  		},
   294  	}
   295  
   296  	for _, test := range tests {
   297  		t.Run(fmt.Sprintf("Expr:  %s\nRange: %s", test.reference.String(), test.ranges.DebugString()), func(t *testing.T) {
   298  			discreteRanges, err := sql.RemoveOverlappingRanges(test.ranges...)
   299  			require.NoError(t, err)
   300  			verificationRanges, err := removeOverlappingRangesVerification(test.ranges...)
   301  			require.NoError(t, err)
   302  			for _, row := range values3 {
   303  				referenceBool, err := test.reference.Eval(ctx, row)
   304  				require.NoError(t, err)
   305  				rangeBool := evalRanges(t, discreteRanges, row)
   306  				assert.Equal(t, referenceBool, rangeBool, fmt.Sprintf("%v: DiscreteRanges: %s", row, discreteRanges.DebugString()))
   307  			}
   308  			discreteRanges, err = sql.SortRanges(discreteRanges...)
   309  			require.NoError(t, err)
   310  			verificationRanges, err = sql.SortRanges(verificationRanges...)
   311  			require.NoError(t, err)
   312  			ok, err := discreteRanges.Equals(verificationRanges)
   313  			require.NoError(t, err)
   314  			assert.True(t, ok)
   315  		})
   316  	}
   317  }
   318  
   319  func TestRangeOverlapNulls(t *testing.T) {
   320  	ctx := sql.NewEmptyContext()
   321  	x, y, _, _, _, valuesNull := setup()
   322  
   323  	tests := []struct {
   324  		reference sql.Expression
   325  		ranges    sql.RangeCollection
   326  	}{
   327  		{
   328  			reference: or(
   329  				and(isNull(x), gt(y, 5)),
   330  			),
   331  			ranges: sql.RangeCollection{
   332  				r(null(), rgt(5)),
   333  			},
   334  		},
   335  		{
   336  			reference: or(
   337  				and(isNull(x), isNotNull(y)),
   338  			),
   339  			ranges: sql.RangeCollection{
   340  				r(null(), notNull()),
   341  			},
   342  		},
   343  		{
   344  			reference: or(
   345  				and(isNull(x), lt(y, 5)),
   346  			),
   347  			ranges: sql.RangeCollection{
   348  				r(null(), rlt(5)),
   349  			},
   350  		},
   351  		{
   352  			reference: or(
   353  				and(isNull(x), gte(y, 5)),
   354  			),
   355  			ranges: sql.RangeCollection{
   356  				r(null(), rgte(5)),
   357  			},
   358  		},
   359  		{
   360  			reference: or(
   361  				and(isNull(x), lte(y, 5)),
   362  			),
   363  			ranges: sql.RangeCollection{
   364  				r(null(), rlte(5)),
   365  			},
   366  		},
   367  		{
   368  			reference: or(
   369  				and(isNull(x), lte(y, 5)),
   370  			),
   371  			ranges: sql.RangeCollection{
   372  				r(null(), rlte(5)),
   373  			},
   374  		},
   375  		{
   376  			reference: or(
   377  				and(isNull(x), eq(y, 1)),
   378  			),
   379  			ranges: sql.RangeCollection{
   380  				r(null(), req(1)),
   381  			},
   382  		},
   383  	}
   384  
   385  	for _, test := range tests {
   386  		t.Run(fmt.Sprintf("Expr:  %s\nRange: %s", test.reference.String(), test.ranges.DebugString()), func(t *testing.T) {
   387  			discreteRanges, err := sql.RemoveOverlappingRanges(test.ranges...)
   388  			require.NoError(t, err)
   389  			verificationRanges, err := removeOverlappingRangesVerification(test.ranges...)
   390  			require.NoError(t, err)
   391  			for _, row := range valuesNull {
   392  				referenceBool, err := test.reference.Eval(ctx, row)
   393  				require.NoError(t, err)
   394  				rangeBool := evalRanges(t, discreteRanges, row)
   395  				assert.Equal(t, referenceBool, rangeBool, fmt.Sprintf("%v: DiscreteRanges: %s", row, discreteRanges.DebugString()))
   396  			}
   397  			discreteRanges, err = sql.SortRanges(discreteRanges...)
   398  			require.NoError(t, err)
   399  			verificationRanges, err = sql.SortRanges(verificationRanges...)
   400  			require.NoError(t, err)
   401  			ok, err := discreteRanges.Equals(verificationRanges)
   402  			require.NoError(t, err)
   403  			assert.True(t, ok)
   404  		})
   405  	}
   406  }
   407  
   408  func TestComplexRange(t *testing.T) {
   409  	tests := []struct {
   410  		skip   bool
   411  		ranges sql.RangeCollection
   412  	}{
   413  		{
   414  			// derived from sqllogictest/index/in/100/slt_good_1.test:12655
   415  			ranges: sql.RangeCollection{
   416  				r(
   417  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   418  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   419  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveNull{}, Typ: types.Float32},
   420  				),
   421  				r(
   422  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Below{Key: int16(848)}, Typ: types.Int16},
   423  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: int16(560)}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   424  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   425  				),
   426  				r(
   427  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Above{Key: 953}, Typ: types.Int16},
   428  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   429  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: decimal.New(53978, -2)}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   430  				),
   431  				r(
   432  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: int16(234)}, UpperBound: sql.Above{Key: int16(234)}, Typ: types.Int16},
   433  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   434  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: decimal.New(48843, -2)}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   435  				),
   436  				r(
   437  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: int16(258)}, UpperBound: sql.Above{Key: int16(258)}, Typ: types.Int16},
   438  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   439  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   440  				),
   441  				r(
   442  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: int16(372)}, UpperBound: sql.Above{Key: int16(372)}, Typ: types.Int16},
   443  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   444  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: decimal.New(48843, -2)}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   445  				),
   446  				r(
   447  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: int16(583)}, UpperBound: sql.Above{Key: int16(583)}, Typ: types.Int16},
   448  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   449  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: decimal.New(48843, -2)}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   450  				),
   451  				r(
   452  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: int16(883)}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   453  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int16},
   454  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   455  				),
   456  			},
   457  		},
   458  		{
   459  			// derived from index query plan test
   460  			// `SELECT * FROM comp_index_t2 WHERE (((v1>25 AND v2 BETWEEN 23 AND 54) OR (v1<>40 AND v3>90)) OR (v1<>7 AND v4<=78));`
   461  			ranges: sql.RangeCollection{
   462  				r(
   463  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 25}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   464  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 23}, UpperBound: sql.Above{Key: 54}, Typ: types.Int32},
   465  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   466  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   467  				),
   468  				r(
   469  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 40}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   470  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   471  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 90}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   472  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   473  				),
   474  				r(
   475  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Below{Key: 40}, Typ: types.Int32},
   476  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   477  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 90}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   478  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   479  				),
   480  				r(
   481  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 7}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   482  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   483  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   484  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Above{Key: 78}, Typ: types.Int32},
   485  				),
   486  				r(
   487  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Below{Key: 7}, Typ: types.Int32},
   488  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   489  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   490  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Above{Key: 78}, Typ: types.Int32},
   491  				),
   492  			},
   493  		},
   494  		{
   495  			ranges: sql.RangeCollection{
   496  				r(
   497  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   498  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   499  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 0}, Typ: types.Int16},
   500  				),
   501  				r(
   502  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 0}, UpperBound: sql.Below{Key: 5}, Typ: types.Int16},
   503  					sql.RangeColumnExpr{LowerBound: sql.Above{Key: 3}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   504  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   505  				),
   506  				r(
   507  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 1}, UpperBound: sql.Above{Key: 1}, Typ: types.Int16},
   508  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   509  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   510  				),
   511  				r(
   512  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 2}, UpperBound: sql.Above{Key: 2}, Typ: types.Int16},
   513  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   514  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 1}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   515  				),
   516  				r(
   517  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 4}, UpperBound: sql.Above{Key: 4}, Typ: types.Int16},
   518  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 0}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   519  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 1}, UpperBound: sql.Above{Key: 6}, Typ: types.Int16},
   520  				),
   521  			},
   522  		},
   523  		{
   524  			ranges: sql.RangeCollection{
   525  				r(
   526  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 69}, UpperBound: sql.Above{Key: 69}, Typ: types.Int32},
   527  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   528  				),
   529  				r(
   530  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 73}, UpperBound: sql.Above{Key: 73}, Typ: types.Int32},
   531  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   532  				),
   533  				r(
   534  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 12}, UpperBound: sql.Above{Key: 12}, Typ: types.Int32},
   535  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   536  				),
   537  				r(
   538  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 3}, UpperBound: sql.Above{Key: 3}, Typ: types.Int32},
   539  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   540  				),
   541  				r(
   542  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 17}, UpperBound: sql.Above{Key: 17}, Typ: types.Int32},
   543  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   544  				),
   545  				r(
   546  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 70}, UpperBound: sql.Above{Key: 70}, Typ: types.Int32},
   547  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   548  				),
   549  				r(
   550  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 20}, UpperBound: sql.Above{Key: 20}, Typ: types.Int32},
   551  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   552  				),
   553  				r(
   554  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 4}, UpperBound: sql.Above{Key: 4}, Typ: types.Int32},
   555  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   556  				),
   557  				r(
   558  					sql.RangeColumnExpr{LowerBound: sql.Below{Key: 39}, UpperBound: sql.Above{Key: 39}, Typ: types.Int32},
   559  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Float32},
   560  				),
   561  				r(
   562  					sql.RangeColumnExpr{LowerBound: sql.BelowNull{}, UpperBound: sql.AboveAll{}, Typ: types.Int32},
   563  					sql.RangeColumnExpr{LowerBound: sql.AboveNull{}, UpperBound: sql.Below{Key: 69.67}, Typ: types.Float32},
   564  				),
   565  			},
   566  		},
   567  	}
   568  
   569  	for _, test := range tests {
   570  		t.Run(fmt.Sprintf("Range: %s", test.ranges.DebugString()), func(t *testing.T) {
   571  			if test.skip {
   572  				t.Skip()
   573  			}
   574  			discreteRanges, err := sql.RemoveOverlappingRanges(test.ranges...)
   575  			require.NoError(t, err)
   576  			verificationRanges, err := removeOverlappingRangesVerification(test.ranges...)
   577  			require.NoError(t, err)
   578  			discreteRanges, err = sql.SortRanges(discreteRanges...)
   579  			require.NoError(t, err)
   580  			verificationRanges, err = sql.SortRanges(verificationRanges...)
   581  			require.NoError(t, err)
   582  			ok, err := discreteRanges.Equals(verificationRanges)
   583  			require.NoError(t, err)
   584  			assert.True(t, ok)
   585  			if !ok {
   586  				t.Logf("DiscreteRanges: %s", discreteRanges.DebugString())
   587  				t.Logf("VerificationRanges: %s", verificationRanges.DebugString())
   588  			}
   589  
   590  			// TODO: need a way to either verify that the ranges cover the area, or that they're the same
   591  			for i := 0; i < len(discreteRanges)-1; i++ {
   592  				for j := i + 1; j < len(discreteRanges); j++ {
   593  					r1 := discreteRanges[i]
   594  					r2 := discreteRanges[j]
   595  					hasOverlap, err := r1.Overlaps(r2)
   596  					if hasOverlap {
   597  						t.Logf("Overlap: %s\n%s", r1.String(), r2.String())
   598  					}
   599  					assert.NoError(t, err)
   600  					assert.False(t, hasOverlap)
   601  				}
   602  			}
   603  		})
   604  	}
   605  }
   606  
   607  func setup() (x, y, z sql.Expression, values2, values3, valuesNull [][]interface{}) {
   608  	values2 = make([][]interface{}, 0, 100)
   609  	values3 = make([][]interface{}, 0, 1000)
   610  	for i := byte(1); i <= 10; i++ {
   611  		for j := byte(1); j <= 10; j++ {
   612  			for k := byte(1); k <= 10; k++ {
   613  				values3 = append(values3, []interface{}{i, j, k})
   614  			}
   615  			values2 = append(values2, []interface{}{i, j})
   616  			if i%2 == 0 {
   617  				valuesNull = append(valuesNull, []interface{}{nil, j})
   618  			} else {
   619  				valuesNull = append(valuesNull, []interface{}{i, j})
   620  			}
   621  		}
   622  	}
   623  	x = expression.NewGetField(0, rangeType, "x", true)
   624  	y = expression.NewGetField(1, rangeType, "y", true)
   625  	z = expression.NewGetField(2, rangeType, "z", true)
   626  	return
   627  }
   628  
   629  func evalRanges(t *testing.T, ranges []sql.Range, row []interface{}) bool {
   630  	found := false
   631  	for _, rang := range ranges {
   632  		if evalRange(t, rang, row) {
   633  			if !found {
   634  				found = true
   635  			} else {
   636  				assert.FailNow(t, "overlap in ranges")
   637  			}
   638  		}
   639  	}
   640  	return found
   641  }
   642  
   643  func evalRange(t *testing.T, rang sql.Range, row []interface{}) bool {
   644  	rowRange := make(sql.Range, len(rang))
   645  	for i, val := range row {
   646  		if val == nil {
   647  			rowRange[i] = sql.NullRangeColumnExpr(rangeType)
   648  		} else {
   649  			rowRange[i] = sql.ClosedRangeColumnExpr(val, val, rangeType)
   650  		}
   651  	}
   652  	ok, err := rang.IsSupersetOf(rowRange)
   653  	require.NoError(t, err)
   654  	return ok
   655  }
   656  
   657  func removeOverlappingRangesVerification(ranges ...sql.Range) (sql.RangeCollection, error) {
   658  	if len(ranges) == 0 {
   659  		return nil, nil
   660  	}
   661  
   662  	var newRanges sql.RangeCollection
   663  	for i := 0; i < len(ranges); i++ {
   664  		hadOverlap := false
   665  		for nri := 0; nri < len(newRanges); nri++ {
   666  			if resultingRanges, ok, err := ranges[i].RemoveOverlap(newRanges[nri]); err != nil {
   667  				return nil, err
   668  			} else if ok {
   669  				hadOverlap = true
   670  				// Remove the overlapping Range from newRanges
   671  				nrLast := len(newRanges) - 1
   672  				newRanges[nri], newRanges[nrLast] = newRanges[nrLast], newRanges[nri]
   673  				newRanges = newRanges[:nrLast]
   674  				// Add the new ranges to the end of the given slice allowing us to compare those against everything else.
   675  				ranges = append(ranges, resultingRanges...)
   676  				break
   677  			}
   678  		}
   679  		if !hadOverlap {
   680  			newRanges = append(newRanges, ranges[i])
   681  		}
   682  	}
   683  
   684  	return newRanges, nil
   685  }
   686  
   687  func eq(field sql.Expression, val uint8) sql.Expression {
   688  	return expression.NewNullSafeEquals(field, expression.NewLiteral(val, rangeType))
   689  }
   690  
   691  func lt(field sql.Expression, val uint8) sql.Expression {
   692  	return expression.NewLessThan(field, expression.NewLiteral(val, rangeType))
   693  }
   694  
   695  func lte(field sql.Expression, val uint8) sql.Expression {
   696  	return expression.NewLessThanOrEqual(field, expression.NewLiteral(val, rangeType))
   697  }
   698  
   699  func gt(field sql.Expression, val uint8) sql.Expression {
   700  	return expression.NewGreaterThan(field, expression.NewLiteral(val, rangeType))
   701  }
   702  
   703  func gte(field sql.Expression, val uint8) sql.Expression {
   704  	return expression.NewGreaterThanOrEqual(field, expression.NewLiteral(val, rangeType))
   705  }
   706  
   707  func isNull(field sql.Expression) sql.Expression {
   708  	return expression.NewIsNull(field)
   709  }
   710  
   711  func isNotNull(field sql.Expression) sql.Expression {
   712  	return expression.NewNot(expression.NewIsNull(field))
   713  }
   714  
   715  func cc(field sql.Expression, lowerbound, upperbound uint8) sql.Expression {
   716  	return and(
   717  		expression.NewGreaterThanOrEqual(field, expression.NewLiteral(lowerbound, rangeType)),
   718  		expression.NewLessThanOrEqual(field, expression.NewLiteral(upperbound, rangeType)),
   719  	)
   720  }
   721  
   722  func co(field sql.Expression, lowerbound, upperbound uint8) sql.Expression {
   723  	return and(
   724  		expression.NewGreaterThanOrEqual(field, expression.NewLiteral(lowerbound, rangeType)),
   725  		expression.NewLessThan(field, expression.NewLiteral(upperbound, rangeType)),
   726  	)
   727  }
   728  
   729  func oc(field sql.Expression, lowerbound, upperbound uint8) sql.Expression {
   730  	return and(
   731  		expression.NewGreaterThan(field, expression.NewLiteral(lowerbound, rangeType)),
   732  		expression.NewLessThanOrEqual(field, expression.NewLiteral(upperbound, rangeType)),
   733  	)
   734  }
   735  
   736  func oo(field sql.Expression, lowerbound, upperbound uint8) sql.Expression {
   737  	return and(
   738  		expression.NewGreaterThan(field, expression.NewLiteral(lowerbound, rangeType)),
   739  		expression.NewLessThan(field, expression.NewLiteral(upperbound, rangeType)),
   740  	)
   741  }
   742  
   743  func not(field sql.Expression, val uint8) sql.Expression {
   744  	return expression.NewNot(eq(field, val))
   745  }
   746  
   747  func r(colExprs ...sql.RangeColumnExpr) sql.Range {
   748  	return colExprs
   749  }
   750  
   751  func req(val byte) sql.RangeColumnExpr {
   752  	return sql.ClosedRangeColumnExpr(val, val, rangeType)
   753  }
   754  
   755  func rlt(val byte) sql.RangeColumnExpr {
   756  	return sql.LessThanRangeColumnExpr(val, rangeType)
   757  }
   758  
   759  func rlte(val byte) sql.RangeColumnExpr {
   760  	return sql.LessOrEqualRangeColumnExpr(val, rangeType)
   761  }
   762  
   763  func rgt(val byte) sql.RangeColumnExpr {
   764  	return sql.GreaterThanRangeColumnExpr(val, rangeType)
   765  }
   766  
   767  func rgte(val byte) sql.RangeColumnExpr {
   768  	return sql.GreaterOrEqualRangeColumnExpr(val, rangeType)
   769  }
   770  
   771  func null() sql.RangeColumnExpr {
   772  	return sql.NullRangeColumnExpr(rangeType)
   773  }
   774  
   775  func notNull() sql.RangeColumnExpr {
   776  	return sql.NotNullRangeColumnExpr(rangeType)
   777  }
   778  
   779  func rcc(lowerbound, upperbound byte) sql.RangeColumnExpr {
   780  	return sql.CustomRangeColumnExpr(lowerbound, upperbound, sql.Closed, sql.Closed, rangeType)
   781  }
   782  
   783  func rco(lowerbound, upperbound byte) sql.RangeColumnExpr {
   784  	return sql.CustomRangeColumnExpr(lowerbound, upperbound, sql.Closed, sql.Open, rangeType)
   785  }
   786  
   787  func roc(lowerbound, upperbound byte) sql.RangeColumnExpr {
   788  	return sql.CustomRangeColumnExpr(lowerbound, upperbound, sql.Open, sql.Closed, rangeType)
   789  }
   790  
   791  func roo(lowerbound, upperbound byte) sql.RangeColumnExpr {
   792  	return sql.CustomRangeColumnExpr(lowerbound, upperbound, sql.Open, sql.Open, rangeType)
   793  }
   794  
   795  func or(expressions ...sql.Expression) sql.Expression {
   796  	if len(expressions) == 1 {
   797  		return expressions[0]
   798  	}
   799  	if expressions[0] == nil {
   800  		return or(expressions[1:]...)
   801  	}
   802  	return expression.NewOr(expressions[0], or(expressions[1:]...))
   803  }
   804  
   805  func and(expressions ...sql.Expression) sql.Expression {
   806  	if len(expressions) == 1 {
   807  		return expressions[0]
   808  	}
   809  	if expressions[0] == nil {
   810  		return and(expressions[1:]...)
   811  	}
   812  	return expression.NewAnd(expressions[0], and(expressions[1:]...))
   813  }
   814  
   815  func buildTestRangeTree(ranges []sql.Range) (*sql.RangeColumnExprTree, error) {
   816  	tree, err := sql.NewRangeColumnExprTree(ranges[0], []sql.Type{rangeType})
   817  	if err != nil {
   818  		return nil, err
   819  	}
   820  	for _, rng := range ranges[1:] {
   821  		err = tree.Insert(rng)
   822  		if err != nil {
   823  			return nil, err
   824  		}
   825  	}
   826  	return tree, nil
   827  }
   828  
   829  func TestRangeTreeInsert(t *testing.T) {
   830  	tests := []struct {
   831  		name      string
   832  		setupRngs []sql.Range
   833  		setupExp  string
   834  		rng       sql.Range
   835  		exp       string
   836  	}{
   837  		{
   838  			name:      "insert smallest",
   839  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11))},
   840  			setupExp: "RangeColumnExprTree\n" +
   841  				"│   ┌── [11, 11] max: Above[11] color: 1\n" +
   842  				"└── [7, 7] max: Above[11] color: 0\n" +
   843  				"    └── [3, 3] max: Above[3] color: 1\n" +
   844  				"",
   845  			rng: r(req(0)),
   846  			exp: "RangeColumnExprTree\n" +
   847  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
   848  				"└── [7, 7] max: Above[11] color: 0\n" +
   849  				"    └── [3, 3] max: Above[3] color: 0\n" +
   850  				"        └── [0, 0] max: Above[0] color: 1\n" +
   851  				"",
   852  		},
   853  		{
   854  			name:      "insert largest",
   855  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11))},
   856  			setupExp: "RangeColumnExprTree\n" +
   857  				"│   ┌── [11, 11] max: Above[11] color: 1\n" +
   858  				"└── [7, 7] max: Above[11] color: 0\n" +
   859  				"    └── [3, 3] max: Above[3] color: 1\n" +
   860  				"",
   861  			rng: r(req(14)),
   862  			exp: "RangeColumnExprTree\n" +
   863  				"│       ┌── [14, 14] max: Above[14] color: 1\n" +
   864  				"│   ┌── [11, 11] max: Above[14] color: 0\n" +
   865  				"└── [7, 7] max: Above[14] color: 0\n" +
   866  				"    └── [3, 3] max: Above[3] color: 0\n" +
   867  				"",
   868  		},
   869  		{
   870  			name:      "insert rebalance left child",
   871  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(0))},
   872  			setupExp: "RangeColumnExprTree\n" +
   873  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
   874  				"└── [7, 7] max: Above[11] color: 0\n" +
   875  				"    └── [3, 3] max: Above[3] color: 0\n" +
   876  				"        └── [0, 0] max: Above[0] color: 1\n" +
   877  				"",
   878  			rng: r(req(1)),
   879  			exp: "RangeColumnExprTree\n" +
   880  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
   881  				"└── [7, 7] max: Above[11] color: 0\n" +
   882  				"    │   ┌── [3, 3] max: Above[3] color: 1\n" +
   883  				"    └── [1, 1] max: Above[3] color: 0\n" +
   884  				"        └── [0, 0] max: Above[0] color: 1\n" +
   885  				"",
   886  		},
   887  		{
   888  			name:      "insert rebalance right child",
   889  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(12))},
   890  			setupExp: "RangeColumnExprTree\n" +
   891  				"│       ┌── [12, 12] max: Above[12] color: 1\n" +
   892  				"│   ┌── [11, 11] max: Above[12] color: 0\n" +
   893  				"└── [7, 7] max: Above[12] color: 0\n" +
   894  				"    └── [3, 3] max: Above[3] color: 0\n" +
   895  				"",
   896  			rng: r(req(13)),
   897  			exp: "RangeColumnExprTree\n" +
   898  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
   899  				"│   ┌── [12, 12] max: Above[13] color: 0\n" +
   900  				"│   │   └── [11, 11] max: Above[11] color: 1\n" +
   901  				"└── [7, 7] max: Above[13] color: 0\n" +
   902  				"    └── [3, 3] max: Above[3] color: 0\n" +
   903  				"",
   904  		},
   905  		{
   906  			name:      "insert rebalance root from left",
   907  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(0)), r(req(1)), r(req(2)), r(req(4))},
   908  			setupExp: "RangeColumnExprTree\n" +
   909  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
   910  				"└── [7, 7] max: Above[11] color: 0\n" +
   911  				"    │       ┌── [4, 4] max: Above[4] color: 1\n" +
   912  				"    │   ┌── [3, 3] max: Above[4] color: 0\n" +
   913  				"    │   │   └── [2, 2] max: Above[2] color: 1\n" +
   914  				"    └── [1, 1] max: Above[4] color: 1\n" +
   915  				"        └── [0, 0] max: Above[0] color: 0\n" +
   916  				"",
   917  			rng: r(req(5)),
   918  			exp: "RangeColumnExprTree\n" +
   919  				"│       ┌── [11, 11] max: Above[11] color: 0\n" +
   920  				"│   ┌── [7, 7] max: Above[11] color: 1\n" +
   921  				"│   │   │   ┌── [5, 5] max: Above[5] color: 1\n" +
   922  				"│   │   └── [4, 4] max: Above[5] color: 0\n" +
   923  				"└── [3, 3] max: Above[11] color: 0\n" +
   924  				"    │   ┌── [2, 2] max: Above[2] color: 0\n" +
   925  				"    └── [1, 1] max: Above[2] color: 1\n" +
   926  				"        └── [0, 0] max: Above[0] color: 0\n" +
   927  				"",
   928  		},
   929  		{
   930  			name:      "insert rebalance root from right",
   931  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(8)), r(req(9)), r(req(10)), r(req(12))},
   932  			setupExp: "RangeColumnExprTree\n" +
   933  				"│           ┌── [12, 12] max: Above[12] color: 1\n" +
   934  				"│       ┌── [11, 11] max: Above[12] color: 0\n" +
   935  				"│       │   └── [10, 10] max: Above[10] color: 1\n" +
   936  				"│   ┌── [9, 9] max: Above[12] color: 1\n" +
   937  				"│   │   └── [8, 8] max: Above[8] color: 0\n" +
   938  				"└── [7, 7] max: Above[12] color: 0\n" +
   939  				"    └── [3, 3] max: Above[3] color: 0\n" +
   940  				"",
   941  			rng: r(req(13)),
   942  			exp: "RangeColumnExprTree\n" +
   943  				"│           ┌── [13, 13] max: Above[13] color: 1\n" +
   944  				"│       ┌── [12, 12] max: Above[13] color: 0\n" +
   945  				"│   ┌── [11, 11] max: Above[13] color: 1\n" +
   946  				"│   │   └── [10, 10] max: Above[10] color: 0\n" +
   947  				"└── [9, 9] max: Above[13] color: 0\n" +
   948  				"    │   ┌── [8, 8] max: Above[8] color: 0\n" +
   949  				"    └── [7, 7] max: Above[8] color: 1\n" +
   950  				"        └── [3, 3] max: Above[3] color: 0\n" +
   951  				"",
   952  		},
   953  		{
   954  			name:      "insert smallest",
   955  			setupRngs: []sql.Range{r(rcc(4, 6)), r(req(3)), r(req(11))},
   956  			setupExp: "RangeColumnExprTree\n" +
   957  				"│   ┌── [11, 11] max: Above[11] color: 1\n" +
   958  				"└── [4, 6] max: Above[11] color: 0\n" +
   959  				"    └── [3, 3] max: Above[3] color: 1\n" +
   960  				"",
   961  			rng: r(req(0)),
   962  			exp: "RangeColumnExprTree\n" +
   963  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
   964  				"└── [4, 6] max: Above[11] color: 0\n" +
   965  				"    └── [3, 3] max: Above[3] color: 0\n" +
   966  				"        └── [0, 0] max: Above[0] color: 1\n" +
   967  				"",
   968  		},
   969  		{
   970  			name:      "insert compare above and below",
   971  			setupRngs: []sql.Range{r(roo(4, 6)), r(req(4))},
   972  			setupExp: "RangeColumnExprTree\n" +
   973  				"└── (4, 6) max: Below[6] color: 0\n" +
   974  				"    └── [4, 4] max: Above[4] color: 1\n" +
   975  				"",
   976  			rng: r(req(6)),
   977  			exp: "RangeColumnExprTree\n" +
   978  				"│   ┌── [6, 6] max: Above[6] color: 1\n" +
   979  				"└── (4, 6) max: Above[6] color: 0\n" +
   980  				"    └── [4, 4] max: Above[4] color: 1\n" +
   981  				"",
   982  		},
   983  	}
   984  
   985  	for _, test := range tests {
   986  		t.Run(test.name, func(t *testing.T) {
   987  			tree, err := buildTestRangeTree(test.setupRngs)
   988  			require.NoError(t, err)
   989  			assert.Equal(t, test.setupExp, tree.String())
   990  
   991  			err = tree.Insert(test.rng)
   992  			require.NoError(t, err)
   993  			assert.Equal(t, test.exp, tree.String())
   994  		})
   995  	}
   996  }
   997  
   998  func TestRangeTreeRemove(t *testing.T) {
   999  	tests := []struct {
  1000  		name      string
  1001  		setupRngs []sql.Range
  1002  		setupExp  string
  1003  		rng       sql.Range
  1004  		exp       string
  1005  	}{
  1006  		{
  1007  			name:      "remove smallest",
  1008  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(9)), r(req(13))},
  1009  			setupExp: "RangeColumnExprTree\n" +
  1010  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1011  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1012  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1013  				"└── [7, 7] max: Above[13] color: 0\n" +
  1014  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1015  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1016  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1017  				"",
  1018  			rng: r(req(1)),
  1019  			exp: "RangeColumnExprTree\n" +
  1020  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1021  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1022  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1023  				"└── [7, 7] max: Above[13] color: 0\n" +
  1024  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1025  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1026  				"",
  1027  		},
  1028  		{
  1029  			name:      "remove largest",
  1030  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(9)), r(req(13))},
  1031  			setupExp: "RangeColumnExprTree\n" +
  1032  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1033  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1034  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1035  				"└── [7, 7] max: Above[13] color: 0\n" +
  1036  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1037  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1038  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1039  				"",
  1040  			rng: r(req(13)),
  1041  			exp: "RangeColumnExprTree\n" +
  1042  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
  1043  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1044  				"└── [7, 7] max: Above[11] color: 0\n" +
  1045  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1046  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1047  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1048  				"",
  1049  		},
  1050  		{
  1051  			name:      "remove largest without left child",
  1052  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(13))},
  1053  			setupExp: "RangeColumnExprTree\n" +
  1054  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1055  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1056  				"└── [7, 7] max: Above[13] color: 0\n" +
  1057  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1058  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1059  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1060  				"",
  1061  			rng: r(req(13)),
  1062  			exp: "RangeColumnExprTree\n" +
  1063  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
  1064  				"└── [7, 7] max: Above[11] color: 0\n" +
  1065  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1066  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1067  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1068  				"",
  1069  		},
  1070  		{
  1071  			name:      "remove left parent",
  1072  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(9)), r(req(13))},
  1073  			setupExp: "RangeColumnExprTree\n" +
  1074  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1075  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1076  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1077  				"└── [7, 7] max: Above[13] color: 0\n" +
  1078  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1079  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1080  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1081  				"",
  1082  			rng: r(req(3)),
  1083  			exp: "RangeColumnExprTree\n" +
  1084  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1085  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1086  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1087  				"└── [7, 7] max: Above[13] color: 0\n" +
  1088  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1089  				"    └── [1, 1] max: Above[5] color: 0\n" +
  1090  				"",
  1091  		},
  1092  		{
  1093  			name:      "remove right parent",
  1094  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(9)), r(req(13))},
  1095  			setupExp: "RangeColumnExprTree\n" +
  1096  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1097  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1098  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1099  				"└── [7, 7] max: Above[13] color: 0\n" +
  1100  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1101  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1102  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1103  				"",
  1104  			rng: r(req(11)),
  1105  			exp: "RangeColumnExprTree\n" +
  1106  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1107  				"│   ┌── [9, 9] max: Above[13] color: 0\n" +
  1108  				"└── [7, 7] max: Above[13] color: 0\n" +
  1109  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1110  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1111  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1112  				"",
  1113  		},
  1114  		{
  1115  			name:      "remove root",
  1116  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5)), r(req(9)), r(req(13))},
  1117  			setupExp: "RangeColumnExprTree\n" +
  1118  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1119  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1120  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1121  				"└── [7, 7] max: Above[13] color: 0\n" +
  1122  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1123  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1124  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1125  				"",
  1126  			rng: r(req(7)),
  1127  			exp: "RangeColumnExprTree\n" +
  1128  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1129  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1130  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1131  				"└── [5, 5] max: Above[13] color: 0\n" +
  1132  				"    └── [3, 3] max: Above[3] color: 0\n" +
  1133  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1134  				"",
  1135  		},
  1136  		{
  1137  			name:      "remove rotate left",
  1138  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(1)), r(req(5))},
  1139  			setupExp: "RangeColumnExprTree\n" +
  1140  				"│   ┌── [11, 11] max: Above[11] color: 0\n" +
  1141  				"└── [7, 7] max: Above[11] color: 0\n" +
  1142  				"    │   ┌── [5, 5] max: Above[5] color: 1\n" +
  1143  				"    └── [3, 3] max: Above[5] color: 0\n" +
  1144  				"        └── [1, 1] max: Above[1] color: 1\n" +
  1145  				"",
  1146  			rng: r(req(11)),
  1147  			exp: "RangeColumnExprTree\n" +
  1148  				"│   ┌── [7, 7] max: Above[7] color: 0\n" +
  1149  				"│   │   └── [5, 5] max: Above[5] color: 1\n" +
  1150  				"└── [3, 3] max: Above[7] color: 0\n" +
  1151  				"    └── [1, 1] max: Above[1] color: 0\n" +
  1152  				"",
  1153  		},
  1154  		{
  1155  			name:      "remove root",
  1156  			setupRngs: []sql.Range{r(req(7)), r(req(3)), r(req(11)), r(req(9)), r(req(13))},
  1157  			setupExp: "RangeColumnExprTree\n" +
  1158  				"│       ┌── [13, 13] max: Above[13] color: 1\n" +
  1159  				"│   ┌── [11, 11] max: Above[13] color: 0\n" +
  1160  				"│   │   └── [9, 9] max: Above[9] color: 1\n" +
  1161  				"└── [7, 7] max: Above[13] color: 0\n" +
  1162  				"    └── [3, 3] max: Above[3] color: 0\n" +
  1163  				"",
  1164  			rng: r(req(3)),
  1165  			exp: "RangeColumnExprTree\n" +
  1166  				"│   ┌── [13, 13] max: Above[13] color: 0\n" +
  1167  				"└── [11, 11] max: Above[13] color: 0\n" +
  1168  				"    │   ┌── [9, 9] max: Above[9] color: 1\n" +
  1169  				"    └── [7, 7] max: Above[9] color: 0\n" +
  1170  				"",
  1171  		},
  1172  		{
  1173  			name:      "remove ranges",
  1174  			setupRngs: []sql.Range{r(roo(3, 5)), r(roo(1, 3)), r(roo(5, 7))},
  1175  			setupExp: "RangeColumnExprTree\n" +
  1176  				"│   ┌── (5, 7) max: Below[7] color: 1\n" +
  1177  				"└── (3, 5) max: Below[7] color: 0\n" +
  1178  				"    └── (1, 3) max: Below[3] color: 1\n" +
  1179  				"",
  1180  			rng: r(roo(1, 3)),
  1181  			exp: "RangeColumnExprTree\n" +
  1182  				"│   ┌── (5, 7) max: Below[7] color: 1\n" +
  1183  				"└── (3, 5) max: Below[7] color: 0\n" +
  1184  				"",
  1185  		},
  1186  		{
  1187  			name:      "remove ranges",
  1188  			setupRngs: []sql.Range{r(roo(3, 5)), r(roo(1, 3)), r(roo(5, 7))},
  1189  			setupExp: "RangeColumnExprTree\n" +
  1190  				"│   ┌── (5, 7) max: Below[7] color: 1\n" +
  1191  				"└── (3, 5) max: Below[7] color: 0\n" +
  1192  				"    └── (1, 3) max: Below[3] color: 1\n" +
  1193  				"",
  1194  			rng: r(roo(3, 5)),
  1195  			exp: "RangeColumnExprTree\n" +
  1196  				"│   ┌── (5, 7) max: Below[7] color: 1\n" +
  1197  				"└── (1, 3) max: Below[7] color: 0\n" +
  1198  				"",
  1199  		},
  1200  	}
  1201  
  1202  	for _, test := range tests {
  1203  		t.Run(test.name, func(t *testing.T) {
  1204  			tree, err := buildTestRangeTree(test.setupRngs)
  1205  			require.NoError(t, err)
  1206  			assert.Equal(t, test.setupExp, tree.String())
  1207  
  1208  			err = tree.Remove(test.rng)
  1209  			require.NoError(t, err)
  1210  			assert.Equal(t, test.exp, tree.String())
  1211  		})
  1212  	}
  1213  }