github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/row/fetcher_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package row
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"reflect"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/base"
    21  	"github.com/cockroachdb/cockroach/pkg/keys"
    22  	"github.com/cockroachdb/cockroach/pkg/kv"
    23  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    25  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    26  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    27  	"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
    28  	"github.com/cockroachdb/cockroach/pkg/util"
    29  	"github.com/cockroachdb/cockroach/pkg/util/encoding"
    30  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  type initFetcherArgs struct {
    35  	tableDesc       *sqlbase.ImmutableTableDescriptor
    36  	indexIdx        int
    37  	valNeededForCol util.FastIntSet
    38  	spans           roachpb.Spans
    39  }
    40  
    41  func makeFetcherArgs(entries []initFetcherArgs) []FetcherTableArgs {
    42  	fetcherArgs := make([]FetcherTableArgs, len(entries))
    43  
    44  	for i, entry := range entries {
    45  		var index *sqlbase.IndexDescriptor
    46  		var isSecondaryIndex bool
    47  
    48  		if entry.indexIdx > 0 {
    49  			index = &entry.tableDesc.Indexes[entry.indexIdx-1]
    50  			isSecondaryIndex = true
    51  		} else {
    52  			index = &entry.tableDesc.PrimaryIndex
    53  		}
    54  
    55  		fetcherArgs[i] = FetcherTableArgs{
    56  			Spans:            entry.spans,
    57  			Desc:             entry.tableDesc,
    58  			Index:            index,
    59  			ColIdxMap:        entry.tableDesc.ColumnIdxMap(),
    60  			IsSecondaryIndex: isSecondaryIndex,
    61  			Cols:             entry.tableDesc.Columns,
    62  			ValNeededForCol:  entry.valNeededForCol,
    63  		}
    64  	}
    65  	return fetcherArgs
    66  }
    67  
    68  func initFetcher(
    69  	entries []initFetcherArgs, reverseScan bool, alloc *sqlbase.DatumAlloc,
    70  ) (fetcher *Fetcher, err error) {
    71  	fetcher = &Fetcher{}
    72  
    73  	fetcherCodec := keys.SystemSQLCodec
    74  	fetcherArgs := makeFetcherArgs(entries)
    75  
    76  	if err := fetcher.Init(
    77  		fetcherCodec,
    78  		reverseScan,
    79  		sqlbase.ScanLockingStrength_FOR_NONE,
    80  		false, /* returnRangeInfo */
    81  		false, /* isCheck */
    82  		alloc,
    83  		fetcherArgs...,
    84  	); err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	return fetcher, nil
    89  }
    90  
    91  type fetcherEntryArgs struct {
    92  	tableName        string
    93  	indexName        string // Specify if this entry is an index
    94  	indexIdx         int    // 0 for primary index (default)
    95  	modFactor        int    // Useful modulo to apply for value columns
    96  	schema           string
    97  	interleaveSchema string // Specify if this entry is to be interleaved into another table
    98  	indexSchema      string // Specify if this entry is to be created as an index
    99  	nRows            int
   100  	nCols            int // Number of columns in the table
   101  	nVals            int // Number of values requested from scan
   102  	valNeededForCol  util.FastIntSet
   103  	genValue         sqlutils.GenRowFn
   104  }
   105  
   106  func TestNextRowSingle(t *testing.T) {
   107  	defer leaktest.AfterTest(t)()
   108  	ctx := context.Background()
   109  
   110  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   111  	defer s.Stopper().Stop(ctx)
   112  
   113  	tables := map[string]fetcherEntryArgs{
   114  		"t1": {
   115  			modFactor: 42,
   116  			nRows:     1337,
   117  			nCols:     2,
   118  		},
   119  		"t2": {
   120  			modFactor: 13,
   121  			nRows:     2014,
   122  			nCols:     2,
   123  		},
   124  		"norows": {
   125  			modFactor: 10,
   126  			nRows:     0,
   127  			nCols:     2,
   128  		},
   129  		"onerow": {
   130  			modFactor: 10,
   131  			nRows:     1,
   132  			nCols:     2,
   133  		},
   134  	}
   135  
   136  	// Initialize tables first.
   137  	for tableName, table := range tables {
   138  		sqlutils.CreateTable(
   139  			t, sqlDB, tableName,
   140  			"k INT PRIMARY KEY, v INT",
   141  			table.nRows,
   142  			sqlutils.ToRowFn(sqlutils.RowIdxFn, sqlutils.RowModuloFn(table.modFactor)),
   143  		)
   144  	}
   145  
   146  	alloc := &sqlbase.DatumAlloc{}
   147  
   148  	// We try to read rows from each table.
   149  	for tableName, table := range tables {
   150  		t.Run(tableName, func(t *testing.T) {
   151  			tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, tableName)
   152  
   153  			var valNeededForCol util.FastIntSet
   154  			valNeededForCol.AddRange(0, table.nCols-1)
   155  
   156  			args := []initFetcherArgs{
   157  				{
   158  					tableDesc:       tableDesc,
   159  					indexIdx:        0,
   160  					valNeededForCol: valNeededForCol,
   161  				},
   162  			}
   163  
   164  			rf, err := initFetcher(args, false /*reverseScan*/, alloc)
   165  			if err != nil {
   166  				t.Fatal(err)
   167  			}
   168  
   169  			if err := rf.StartScan(
   170  				context.Background(),
   171  				kv.NewTxn(ctx, kvDB, 0),
   172  				roachpb.Spans{tableDesc.IndexSpan(keys.SystemSQLCodec, tableDesc.PrimaryIndex.ID)},
   173  				false, /*limitBatches*/
   174  				0,     /*limitHint*/
   175  				false, /*traceKV*/
   176  			); err != nil {
   177  				t.Fatal(err)
   178  			}
   179  
   180  			count := 0
   181  
   182  			expectedVals := [2]int64{1, 1}
   183  			for {
   184  				datums, desc, index, err := rf.NextRowDecoded(context.Background())
   185  				if err != nil {
   186  					t.Fatal(err)
   187  				}
   188  				if datums == nil {
   189  					break
   190  				}
   191  
   192  				count++
   193  
   194  				if desc.ID != tableDesc.ID || index.ID != tableDesc.PrimaryIndex.ID {
   195  					t.Fatalf(
   196  						"unexpected row retrieved from fetcher.\nnexpected:  table %s - index %s\nactual: table %s - index %s",
   197  						tableDesc.Name, tableDesc.PrimaryIndex.Name,
   198  						desc.Name, index.Name,
   199  					)
   200  				}
   201  
   202  				if table.nCols != len(datums) {
   203  					t.Fatalf("expected %d columns, got %d columns", table.nCols, len(datums))
   204  				}
   205  
   206  				for i, expected := range expectedVals {
   207  					actual := int64(*datums[i].(*tree.DInt))
   208  					if expected != actual {
   209  						t.Fatalf("unexpected value for row %d, col %d.\nexpected: %d\nactual: %d", count, i, expected, actual)
   210  					}
   211  				}
   212  
   213  				expectedVals[0]++
   214  				expectedVals[1]++
   215  				// Value column is in terms of a modulo.
   216  				expectedVals[1] %= int64(table.modFactor)
   217  			}
   218  
   219  			if table.nRows != count {
   220  				t.Fatalf("expected %d rows, got %d rows", table.nRows, count)
   221  			}
   222  		})
   223  	}
   224  }
   225  
   226  func TestNextRowBatchLimiting(t *testing.T) {
   227  	defer leaktest.AfterTest(t)()
   228  	ctx := context.Background()
   229  
   230  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   231  	defer s.Stopper().Stop(ctx)
   232  
   233  	tables := map[string]fetcherEntryArgs{
   234  		"t1": {
   235  			modFactor: 42,
   236  			nRows:     1337,
   237  			nCols:     2,
   238  		},
   239  		"t2": {
   240  			modFactor: 13,
   241  			nRows:     2014,
   242  			nCols:     2,
   243  		},
   244  		"norows": {
   245  			modFactor: 10,
   246  			nRows:     0,
   247  			nCols:     2,
   248  		},
   249  		"onerow": {
   250  			modFactor: 10,
   251  			nRows:     1,
   252  			nCols:     2,
   253  		},
   254  	}
   255  
   256  	// Initialize tables first.
   257  	for tableName, table := range tables {
   258  		sqlutils.CreateTable(
   259  			t, sqlDB, tableName,
   260  			"k INT PRIMARY KEY, v INT, FAMILY f1 (k), FAMILY f2(v)",
   261  			table.nRows,
   262  			sqlutils.ToRowFn(sqlutils.RowIdxFn, sqlutils.RowModuloFn(table.modFactor)),
   263  		)
   264  	}
   265  
   266  	alloc := &sqlbase.DatumAlloc{}
   267  
   268  	// We try to read rows from each table.
   269  	for tableName, table := range tables {
   270  		t.Run(tableName, func(t *testing.T) {
   271  			tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, tableName)
   272  
   273  			var valNeededForCol util.FastIntSet
   274  			valNeededForCol.AddRange(0, table.nCols-1)
   275  
   276  			args := []initFetcherArgs{
   277  				{
   278  					tableDesc:       tableDesc,
   279  					indexIdx:        0,
   280  					valNeededForCol: valNeededForCol,
   281  				},
   282  			}
   283  
   284  			rf, err := initFetcher(args, false /*reverseScan*/, alloc)
   285  			if err != nil {
   286  				t.Fatal(err)
   287  			}
   288  
   289  			if err := rf.StartScan(
   290  				context.Background(),
   291  				kv.NewTxn(ctx, kvDB, 0),
   292  				roachpb.Spans{tableDesc.IndexSpan(keys.SystemSQLCodec, tableDesc.PrimaryIndex.ID)},
   293  				true,  /*limitBatches*/
   294  				10,    /*limitHint*/
   295  				false, /*traceKV*/
   296  			); err != nil {
   297  				t.Fatal(err)
   298  			}
   299  
   300  			count := 0
   301  
   302  			expectedVals := [2]int64{1, 1}
   303  			for {
   304  				datums, desc, index, err := rf.NextRowDecoded(context.Background())
   305  				if err != nil {
   306  					t.Fatal(err)
   307  				}
   308  				if datums == nil {
   309  					break
   310  				}
   311  
   312  				count++
   313  
   314  				if desc.ID != tableDesc.ID || index.ID != tableDesc.PrimaryIndex.ID {
   315  					t.Fatalf(
   316  						"unexpected row retrieved from fetcher.\nnexpected:  table %s - index %s\nactual: table %s - index %s",
   317  						tableDesc.Name, tableDesc.PrimaryIndex.Name,
   318  						desc.Name, index.Name,
   319  					)
   320  				}
   321  
   322  				if table.nCols != len(datums) {
   323  					t.Fatalf("expected %d columns, got %d columns", table.nCols, len(datums))
   324  				}
   325  
   326  				for i, expected := range expectedVals {
   327  					actual := int64(*datums[i].(*tree.DInt))
   328  					if expected != actual {
   329  						t.Fatalf("unexpected value for row %d, col %d.\nexpected: %d\nactual: %d", count, i, expected, actual)
   330  					}
   331  				}
   332  
   333  				expectedVals[0]++
   334  				expectedVals[1]++
   335  				// Value column is in terms of a modulo.
   336  				expectedVals[1] %= int64(table.modFactor)
   337  			}
   338  
   339  			if table.nRows != count {
   340  				t.Fatalf("expected %d rows, got %d rows", table.nRows, count)
   341  			}
   342  		})
   343  	}
   344  }
   345  
   346  // Regression test for #29374. Ensure that RowFetcher can handle multi-span
   347  // fetches where individual batches end in the middle of a multi-column family
   348  // row with not-null columns.
   349  func TestNextRowPartialColumnFamily(t *testing.T) {
   350  	defer leaktest.AfterTest(t)()
   351  	ctx := context.Background()
   352  
   353  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   354  	defer s.Stopper().Stop(ctx)
   355  
   356  	tableName := "t1"
   357  	table := fetcherEntryArgs{
   358  		modFactor: 42,
   359  		nRows:     2,
   360  		nCols:     4,
   361  	}
   362  
   363  	// Initialize a table with multiple column families with some not null ones.
   364  	// We'll insert rows that contain nulls for the nullable column families, to
   365  	// trick the rowfetcher heuristic that multiplies the input batch size by the
   366  	// number of columns in the table.
   367  	sqlutils.CreateTable(
   368  		t, sqlDB, tableName,
   369  		`
   370  k INT PRIMARY KEY, a INT NOT NULL, b INT NOT NULL, c INT NULL,
   371  FAMILY f1 (k), FAMILY f2(a), FAMILY f3(b), FAMILY f4(c),
   372  INDEX(c)
   373  `,
   374  		table.nRows,
   375  		sqlutils.ToRowFn(sqlutils.RowIdxFn,
   376  			sqlutils.RowModuloFn(table.modFactor),
   377  			sqlutils.RowModuloFn(table.modFactor),
   378  		),
   379  	)
   380  
   381  	alloc := &sqlbase.DatumAlloc{}
   382  
   383  	tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, tableName)
   384  
   385  	var valNeededForCol util.FastIntSet
   386  	valNeededForCol.AddRange(0, table.nCols-1)
   387  
   388  	args := []initFetcherArgs{
   389  		{
   390  			tableDesc:       tableDesc,
   391  			indexIdx:        0,
   392  			valNeededForCol: valNeededForCol,
   393  		},
   394  	}
   395  
   396  	rf, err := initFetcher(args, false /*reverseScan*/, alloc)
   397  	if err != nil {
   398  		t.Fatal(err)
   399  	}
   400  
   401  	// Start a scan that has multiple input spans, to tickle the codepath that
   402  	// sees an "empty batch". When we have multiple input spans, the kv server
   403  	// will always return one response per input span. Make sure that the
   404  	// empty response that will be produced in the case where the first span
   405  	// does not end before the limit is satisfied doesn't cause the rowfetcher
   406  	// to think that a row has ended, and therefore have issues when it sees
   407  	// the next kvs from that row in isolation in the next batch.
   408  
   409  	// We'll make the first span go to some random key in the middle of the
   410  	// key space (by appending a number to the index's start key) and the
   411  	// second span go from that key to the end of the index.
   412  	indexSpan := tableDesc.IndexSpan(keys.SystemSQLCodec, tableDesc.PrimaryIndex.ID)
   413  	endKey := indexSpan.EndKey
   414  	midKey := encoding.EncodeUvarintAscending(indexSpan.Key, uint64(100))
   415  	indexSpan.EndKey = midKey
   416  
   417  	if err := rf.StartScan(
   418  		context.Background(),
   419  		kv.NewTxn(ctx, kvDB, 0),
   420  		roachpb.Spans{indexSpan,
   421  			roachpb.Span{Key: midKey, EndKey: endKey},
   422  		},
   423  		true, /*limitBatches*/
   424  		// Set a limitHint of 1 to more quickly end the first batch, causing a
   425  		// batch that ends between rows.
   426  		1,     /*limitHint*/
   427  		false, /*traceKV*/
   428  	); err != nil {
   429  		t.Fatal(err)
   430  	}
   431  
   432  	var count int
   433  	for {
   434  		// Just try to grab the row - we don't need to validate the contents
   435  		// in this test.
   436  		datums, _, _, err := rf.NextRowDecoded(context.Background())
   437  		if err != nil {
   438  			t.Fatal(err)
   439  		}
   440  		if datums == nil {
   441  			break
   442  		}
   443  		count++
   444  	}
   445  
   446  	if table.nRows != count {
   447  		t.Fatalf("expected %d rows, got %d rows", table.nRows, count)
   448  	}
   449  }
   450  
   451  // Secondary indexes contain extra values (the primary key of the primary index
   452  // as well as STORING columns).
   453  func TestNextRowSecondaryIndex(t *testing.T) {
   454  	defer leaktest.AfterTest(t)()
   455  	ctx := context.Background()
   456  
   457  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   458  	defer s.Stopper().Stop(ctx)
   459  
   460  	// Modulo to use for s1, s2 storing columns.
   461  	storingMods := [2]int{7, 13}
   462  	// Number of NULL secondary index values.
   463  	nNulls := 20
   464  
   465  	tables := map[string]*fetcherEntryArgs{
   466  		"nonunique": {
   467  			modFactor: 20,
   468  			schema:    "p INT PRIMARY KEY, idx INT, s1 INT, s2 INT, INDEX i1 (idx)",
   469  			nRows:     422,
   470  			nCols:     4,
   471  			nVals:     2,
   472  		},
   473  		"unique": {
   474  			// Must be > nRows since this value must be unique.
   475  			modFactor: 1000,
   476  			schema:    "p INT PRIMARY KEY, idx INT, s1 INT, s2 INT, UNIQUE INDEX i1 (idx)",
   477  			nRows:     123,
   478  			nCols:     4,
   479  			nVals:     2,
   480  		},
   481  		"nonuniquestoring": {
   482  			modFactor: 42,
   483  			schema:    "p INT PRIMARY KEY, idx INT, s1 INT, s2 INT, INDEX i1 (idx) STORING (s1, s2)",
   484  			nRows:     654,
   485  			nCols:     4,
   486  			nVals:     4,
   487  		},
   488  		"uniquestoring": {
   489  			// Must be > nRows since this value must be unique.
   490  			modFactor: 1000,
   491  			nRows:     555,
   492  			schema:    "p INT PRIMARY KEY, idx INT, s1 INT, s2 INT, UNIQUE INDEX i1 (idx) STORING (s1, s2)",
   493  			nCols:     4,
   494  			nVals:     4,
   495  		},
   496  	}
   497  
   498  	// Initialize the generate value functions.
   499  	tables["nonunique"].genValue = sqlutils.ToRowFn(
   500  		sqlutils.RowIdxFn,
   501  		sqlutils.RowModuloFn(tables["nonunique"].modFactor),
   502  	)
   503  	tables["unique"].genValue = sqlutils.ToRowFn(
   504  		sqlutils.RowIdxFn,
   505  		sqlutils.RowModuloFn(tables["unique"].modFactor),
   506  	)
   507  	tables["nonuniquestoring"].genValue = sqlutils.ToRowFn(
   508  		sqlutils.RowIdxFn,
   509  		sqlutils.RowModuloFn(tables["nonuniquestoring"].modFactor),
   510  		sqlutils.RowModuloFn(storingMods[0]),
   511  		sqlutils.RowModuloFn(storingMods[1]),
   512  	)
   513  	tables["uniquestoring"].genValue = sqlutils.ToRowFn(
   514  		sqlutils.RowIdxFn,
   515  		sqlutils.RowModuloFn(tables["uniquestoring"].modFactor),
   516  		sqlutils.RowModuloFn(storingMods[0]),
   517  		sqlutils.RowModuloFn(storingMods[1]),
   518  	)
   519  
   520  	// Add family definitions to each table.
   521  	tablesWithFamilies := make(map[string]*fetcherEntryArgs)
   522  	for tableName, table := range tables {
   523  		argCopy := *table
   524  		argCopy.schema = argCopy.schema + ", FAMILY (p), FAMILY (idx), FAMILY (s1), FAMILY (s2)"
   525  		familyName := tableName + "_with_families"
   526  		tablesWithFamilies[familyName] = &argCopy
   527  	}
   528  	for tableName, args := range tablesWithFamilies {
   529  		tables[tableName] = args
   530  	}
   531  
   532  	r := sqlutils.MakeSQLRunner(sqlDB)
   533  	// Initialize tables first.
   534  	for tableName, table := range tables {
   535  		sqlutils.CreateTable(
   536  			t, sqlDB, tableName,
   537  			table.schema,
   538  			table.nRows,
   539  			table.genValue,
   540  		)
   541  
   542  		// Insert nNulls NULL secondary index values (this tests if
   543  		// we're properly decoding (UNIQUE) secondary index keys
   544  		// properly).
   545  		for i := 1; i <= nNulls; i++ {
   546  			r.Exec(t, fmt.Sprintf(
   547  				`INSERT INTO %s.%s VALUES (%d, NULL, %d, %d);`,
   548  				sqlutils.TestDB,
   549  				tableName,
   550  				table.nRows+i,
   551  				(table.nRows+i)%storingMods[0],
   552  				(table.nRows+i)%storingMods[1],
   553  			))
   554  		}
   555  		table.nRows += nNulls
   556  	}
   557  
   558  	alloc := &sqlbase.DatumAlloc{}
   559  	// We try to read rows from each index.
   560  	for tableName, table := range tables {
   561  		t.Run(tableName, func(t *testing.T) {
   562  			tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, tableName)
   563  
   564  			var valNeededForCol util.FastIntSet
   565  			valNeededForCol.AddRange(0, table.nVals-1)
   566  
   567  			args := []initFetcherArgs{
   568  				{
   569  					tableDesc: tableDesc,
   570  					// We scan from the first secondary index.
   571  					indexIdx:        1,
   572  					valNeededForCol: valNeededForCol,
   573  				},
   574  			}
   575  
   576  			rf, err := initFetcher(args, false /*reverseScan*/, alloc)
   577  			if err != nil {
   578  				t.Fatal(err)
   579  			}
   580  
   581  			if err := rf.StartScan(
   582  				context.Background(),
   583  				kv.NewTxn(ctx, kvDB, 0),
   584  				roachpb.Spans{tableDesc.IndexSpan(keys.SystemSQLCodec, tableDesc.Indexes[0].ID)},
   585  				false, /*limitBatches*/
   586  				0,     /*limitHint*/
   587  				false, /*traceKV*/
   588  			); err != nil {
   589  				t.Fatal(err)
   590  			}
   591  
   592  			count := 0
   593  			nullCount := 0
   594  			var prevIdxVal int64
   595  			for {
   596  				datums, desc, index, err := rf.NextRowDecoded(context.Background())
   597  				if err != nil {
   598  					t.Fatal(err)
   599  				}
   600  				if datums == nil {
   601  					break
   602  				}
   603  
   604  				count++
   605  
   606  				if desc.ID != tableDesc.ID || index.ID != tableDesc.Indexes[0].ID {
   607  					t.Fatalf(
   608  						"unexpected row retrieved from fetcher.\nnexpected:  table %s - index %s\nactual: table %s - index %s",
   609  						tableDesc.Name, tableDesc.Indexes[0].Name,
   610  						desc.Name, index.Name,
   611  					)
   612  				}
   613  
   614  				if table.nCols != len(datums) {
   615  					t.Fatalf("expected %d columns, got %d columns", table.nCols, len(datums))
   616  				}
   617  
   618  				// Verify that the correct # of values are returned.
   619  				numVals := 0
   620  				for _, datum := range datums {
   621  					if datum != tree.DNull {
   622  						numVals++
   623  					}
   624  				}
   625  
   626  				// Some secondary index values can be NULL. We keep track
   627  				// of how many we encounter.
   628  				idxNull := datums[1] == tree.DNull
   629  				if idxNull {
   630  					nullCount++
   631  					// It is okay to bump this up by one since we know
   632  					// this index value is suppose to be NULL.
   633  					numVals++
   634  				}
   635  
   636  				if table.nVals != numVals {
   637  					t.Fatalf("expected %d non-NULL values, got %d", table.nVals, numVals)
   638  				}
   639  
   640  				id := int64(*datums[0].(*tree.DInt))
   641  				// Verify the value in the value column is
   642  				// correct (if it is not NULL).
   643  				if !idxNull {
   644  					idx := int64(*datums[1].(*tree.DInt))
   645  					if id%int64(table.modFactor) != idx {
   646  						t.Fatalf("for row id %d, expected %d value, got %d", id, id%int64(table.modFactor), idx)
   647  					}
   648  
   649  					// Index values must be fetched in
   650  					// non-decreasing order.
   651  					if prevIdxVal > idx {
   652  						t.Fatalf("index value unexpectedly decreased from %d to %d", prevIdxVal, idx)
   653  					}
   654  					prevIdxVal = idx
   655  				}
   656  
   657  				// We verify that the storing values are
   658  				// decoded correctly.
   659  				if tableName == "nonuniquestoring" || tableName == "uniquestoring" {
   660  					s1 := int64(*datums[2].(*tree.DInt))
   661  					s2 := int64(*datums[3].(*tree.DInt))
   662  
   663  					if id%int64(storingMods[0]) != s1 {
   664  						t.Fatalf("for row id %d, expected %d for s1 value, got %d", id, id%int64(storingMods[0]), s1)
   665  					}
   666  					if id%int64(storingMods[1]) != s2 {
   667  						t.Fatalf("for row id %d, expected %d for s2 value, got %d", id, id%int64(storingMods[1]), s2)
   668  					}
   669  				}
   670  			}
   671  
   672  			if table.nRows != count {
   673  				t.Fatalf("expected %d rows, got %d rows", table.nRows, count)
   674  			}
   675  		})
   676  	}
   677  }
   678  
   679  // Appends all non-empty subsets of indices in [0, maxIdx).
   680  func generateIdxSubsets(maxIdx int, subsets [][]int) [][]int {
   681  	if maxIdx < 0 {
   682  		return subsets
   683  	}
   684  	subsets = generateIdxSubsets(maxIdx-1, subsets)
   685  	curLength := len(subsets)
   686  	for i := 0; i < curLength; i++ {
   687  		// Keep original subsets by duplicating them.
   688  		dupe := make([]int, len(subsets[i]))
   689  		copy(dupe, subsets[i])
   690  		subsets = append(subsets, dupe)
   691  		// Generate new subsets with the current index.
   692  		subsets[i] = append(subsets[i], maxIdx)
   693  	}
   694  	return append(subsets, []int{maxIdx})
   695  }
   696  
   697  // We test reading rows from six tables in a database that contains two
   698  // interleave hierarchies.
   699  // The tables are structured as follows:
   700  // parent1
   701  // parent2
   702  //   child1
   703  //      grandchild1
   704  //	      grandgrandchild1
   705  //   child2
   706  //   grandgrandchild1@ggc1_unique_idx
   707  // parent3
   708  // We test reading rows from every non-empty subset for completeness.
   709  func TestNextRowInterleaved(t *testing.T) {
   710  	defer leaktest.AfterTest(t)()
   711  	ctx := context.Background()
   712  
   713  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   714  	defer s.Stopper().Stop(ctx)
   715  
   716  	tableArgs := map[string]*fetcherEntryArgs{
   717  		"parent1": {
   718  			tableName: "parent1",
   719  			modFactor: 12,
   720  			schema:    "p1 INT PRIMARY KEY, v INT",
   721  			nRows:     100,
   722  			nCols:     2,
   723  			nVals:     2,
   724  		},
   725  		"parent2": {
   726  			tableName: "parent2",
   727  			modFactor: 3,
   728  			schema:    "p2 INT PRIMARY KEY, v INT",
   729  			nRows:     400,
   730  			nCols:     2,
   731  			nVals:     2,
   732  		},
   733  		"child1": {
   734  			tableName:        "child1",
   735  			modFactor:        5,
   736  			schema:           "p2 INT, c1 INT, v INT, PRIMARY KEY (p2, c1)",
   737  			interleaveSchema: "parent2 (p2)",
   738  			// child1 has more rows than parent2, thus some parent2
   739  			// rows will have multiple child1.
   740  			nRows: 500,
   741  			nCols: 3,
   742  			nVals: 3,
   743  		},
   744  		"grandchild1": {
   745  			tableName:        "grandchild1",
   746  			modFactor:        7,
   747  			schema:           "p2 INT, c1 INT, gc1 INT, v INT, PRIMARY KEY (p2, c1, gc1)",
   748  			interleaveSchema: "child1 (p2, c1)",
   749  			nRows:            2000,
   750  			nCols:            4,
   751  			nVals:            4,
   752  		},
   753  		"grandgrandchild1": {
   754  			tableName:        "grandgrandchild1",
   755  			modFactor:        12,
   756  			schema:           "p2 INT, c1 INT, gc1 INT, ggc1 INT, v INT, PRIMARY KEY (p2, c1, gc1, ggc1)",
   757  			interleaveSchema: "grandchild1 (p2, c1, gc1)",
   758  			nRows:            350,
   759  			nCols:            5,
   760  			nVals:            5,
   761  		},
   762  		"child2": {
   763  			tableName:        "child2",
   764  			modFactor:        42,
   765  			schema:           "p2 INT, c2 INT, v INT, PRIMARY KEY (p2, c2)",
   766  			interleaveSchema: "parent2 (p2)",
   767  			// child2 has less rows than parent2, thus not all
   768  			// parent2 rows will have a nested child2 row.
   769  			nRows: 100,
   770  			nCols: 3,
   771  			nVals: 3,
   772  		},
   773  		"parent3": {
   774  			tableName: "parent3",
   775  			modFactor: 42,
   776  			schema:    "p3 INT PRIMARY KEY, v INT",
   777  			nRows:     1,
   778  			nCols:     2,
   779  			nVals:     2,
   780  		},
   781  	}
   782  
   783  	for _, table := range tableArgs {
   784  		table.valNeededForCol.AddRange(0, table.nVals-1)
   785  	}
   786  
   787  	// Initialize generating value functions for each table.
   788  	tableArgs["parent1"].genValue = sqlutils.ToRowFn(
   789  		sqlutils.RowIdxFn,
   790  		sqlutils.RowModuloFn(tableArgs["parent1"].modFactor),
   791  	)
   792  
   793  	tableArgs["parent2"].genValue = sqlutils.ToRowFn(
   794  		sqlutils.RowIdxFn,
   795  		sqlutils.RowModuloFn(tableArgs["parent2"].modFactor),
   796  	)
   797  
   798  	tableArgs["child1"].genValue = sqlutils.ToRowFn(
   799  		// Foreign key needs a shifted modulo.
   800  		sqlutils.RowModuloShiftedFn(tableArgs["parent2"].nRows),
   801  		sqlutils.RowIdxFn,
   802  		sqlutils.RowModuloFn(tableArgs["child1"].modFactor),
   803  	)
   804  
   805  	tableArgs["grandchild1"].genValue = sqlutils.ToRowFn(
   806  		// Foreign keys need a shifted modulo.
   807  		sqlutils.RowModuloShiftedFn(
   808  			tableArgs["child1"].nRows,
   809  			tableArgs["parent2"].nRows,
   810  		),
   811  		sqlutils.RowModuloShiftedFn(tableArgs["child1"].nRows),
   812  		sqlutils.RowIdxFn,
   813  		sqlutils.RowModuloFn(tableArgs["grandchild1"].modFactor),
   814  	)
   815  
   816  	tableArgs["grandgrandchild1"].genValue = sqlutils.ToRowFn(
   817  		// Foreign keys need a shifted modulo.
   818  		sqlutils.RowModuloShiftedFn(
   819  			tableArgs["grandchild1"].nRows,
   820  			tableArgs["child1"].nRows,
   821  			tableArgs["parent2"].nRows,
   822  		),
   823  		sqlutils.RowModuloShiftedFn(
   824  			tableArgs["grandchild1"].nRows,
   825  			tableArgs["child1"].nRows,
   826  		),
   827  		sqlutils.RowModuloShiftedFn(tableArgs["grandchild1"].nRows),
   828  		sqlutils.RowIdxFn,
   829  		sqlutils.RowModuloFn(tableArgs["grandgrandchild1"].modFactor),
   830  	)
   831  
   832  	tableArgs["child2"].genValue = sqlutils.ToRowFn(
   833  		// Foreign key needs a shifted modulo.
   834  		sqlutils.RowModuloShiftedFn(tableArgs["parent2"].nRows),
   835  		sqlutils.RowIdxFn,
   836  		sqlutils.RowModuloFn(tableArgs["child2"].modFactor),
   837  	)
   838  
   839  	tableArgs["parent3"].genValue = sqlutils.ToRowFn(
   840  		sqlutils.RowIdxFn,
   841  		sqlutils.RowModuloFn(tableArgs["parent3"].modFactor),
   842  	)
   843  
   844  	ggc1idx := *tableArgs["grandgrandchild1"]
   845  	// This is only possible since nrows(ggc1) < nrows(p2) thus c1 is
   846  	// unique.
   847  	ggc1idx.indexSchema = fmt.Sprintf(
   848  		`CREATE UNIQUE INDEX ggc1_unique_idx ON %s.grandgrandchild1 (p2) INTERLEAVE IN PARENT %s.parent2 (p2);`,
   849  		sqlutils.TestDB,
   850  		sqlutils.TestDB,
   851  	)
   852  	ggc1idx.indexName = "ggc1_unique_idx"
   853  	ggc1idx.indexIdx = 1
   854  	// Last column v (idx 4) is not stored in this index.
   855  	ggc1idx.valNeededForCol = ggc1idx.valNeededForCol.Copy()
   856  	ggc1idx.valNeededForCol.Remove(4)
   857  	ggc1idx.nVals = 4
   858  
   859  	// We need an ordering of the tables in order to execute the interleave
   860  	// DDL statements.
   861  	interleaveEntries := []fetcherEntryArgs{
   862  		*tableArgs["parent1"],
   863  		*tableArgs["parent2"],
   864  		*tableArgs["child1"],
   865  		*tableArgs["grandchild1"],
   866  		*tableArgs["grandgrandchild1"],
   867  		*tableArgs["child2"],
   868  		ggc1idx,
   869  		*tableArgs["parent3"],
   870  	}
   871  
   872  	for _, table := range interleaveEntries {
   873  		if table.indexSchema != "" {
   874  			// Create interleaved secondary indexes.
   875  			r := sqlutils.MakeSQLRunner(sqlDB)
   876  			r.Exec(t, table.indexSchema)
   877  		} else {
   878  			// Create tables (primary indexes).
   879  			sqlutils.CreateTableInterleaved(
   880  				t, sqlDB, table.tableName,
   881  				table.schema,
   882  				table.interleaveSchema,
   883  				table.nRows,
   884  				table.genValue,
   885  			)
   886  		}
   887  	}
   888  
   889  	alloc := &sqlbase.DatumAlloc{}
   890  	// Retrieve rows from every non-empty subset of the tables/indexes.
   891  	for _, idxs := range generateIdxSubsets(len(interleaveEntries)-1, nil) {
   892  		// Initialize our subset of tables/indexes.
   893  		entries := make([]*fetcherEntryArgs, len(idxs))
   894  		testNames := make([]string, len(entries))
   895  		for i, idx := range idxs {
   896  			entries[i] = &interleaveEntries[idx]
   897  			testNames[i] = entries[i].tableName
   898  			// Use the index name instead if we're scanning an index.
   899  			if entries[i].indexName != "" {
   900  				testNames[i] = entries[i].indexName
   901  			}
   902  		}
   903  
   904  		testName := strings.Join(testNames, "-")
   905  
   906  		t.Run(testName, func(t *testing.T) {
   907  			// Initialize the RowFetcher.
   908  			args := make([]initFetcherArgs, len(entries))
   909  			lookupSpans := make([]roachpb.Span, len(entries))
   910  			// Used during NextRow to see if tableID << 32 |
   911  			// indexID (key) are with what we initialize
   912  			// RowFetcher.
   913  			idLookups := make(map[uint64]*fetcherEntryArgs, len(entries))
   914  			for i, entry := range entries {
   915  				tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, entry.tableName)
   916  				var indexID sqlbase.IndexID
   917  				if entry.indexIdx == 0 {
   918  					indexID = tableDesc.PrimaryIndex.ID
   919  				} else {
   920  					indexID = tableDesc.Indexes[entry.indexIdx-1].ID
   921  				}
   922  				idLookups[idLookupKey(tableDesc.ID, indexID)] = entry
   923  
   924  				// We take every entry's index span (primary or
   925  				// secondary) and use it to start our scan.
   926  				lookupSpans[i] = tableDesc.IndexSpan(keys.SystemSQLCodec, indexID)
   927  
   928  				args[i] = initFetcherArgs{
   929  					tableDesc:       tableDesc,
   930  					indexIdx:        entry.indexIdx,
   931  					valNeededForCol: entry.valNeededForCol,
   932  					spans:           roachpb.Spans{lookupSpans[i]},
   933  				}
   934  			}
   935  
   936  			lookupSpans, _ = roachpb.MergeSpans(lookupSpans)
   937  
   938  			rf, err := initFetcher(args, false /*reverseScan*/, alloc)
   939  			if err != nil {
   940  				t.Fatal(err)
   941  			}
   942  
   943  			if err := rf.StartScan(
   944  				context.Background(),
   945  				kv.NewTxn(ctx, kvDB, 0),
   946  				lookupSpans,
   947  				false, /*limitBatches*/
   948  				0,     /*limitHint*/
   949  				false, /*traceKV*/
   950  			); err != nil {
   951  				t.Fatal(err)
   952  			}
   953  
   954  			// Running count of rows processed for each table-index.
   955  			count := make(map[string]int, len(entries))
   956  
   957  			for {
   958  				datums, desc, index, err := rf.NextRowDecoded(context.Background())
   959  				if err != nil {
   960  					t.Fatal(err)
   961  				}
   962  				if datums == nil {
   963  					break
   964  				}
   965  
   966  				entry, found := idLookups[idLookupKey(desc.ID, index.ID)]
   967  				if !found {
   968  					t.Fatalf(
   969  						"unexpected row from table %s - index %s",
   970  						desc.Name, index.Name,
   971  					)
   972  				}
   973  
   974  				tableIdxName := fmt.Sprintf("%s@%s", entry.tableName, entry.indexName)
   975  				count[tableIdxName]++
   976  
   977  				// Check that the correct # of columns is returned.
   978  				if entry.nCols != len(datums) {
   979  					t.Fatalf("for table %s expected %d columns, got %d columns", tableIdxName, entry.nCols, len(datums))
   980  				}
   981  
   982  				// Verify that the correct # of values are returned.
   983  				numVals := 0
   984  				for _, datum := range datums {
   985  					if datum != tree.DNull {
   986  						numVals++
   987  					}
   988  				}
   989  				if entry.nVals != numVals {
   990  					t.Fatalf("for table %s expected %d non-NULL values, got %d", tableIdxName, entry.nVals, numVals)
   991  				}
   992  
   993  				// Verify the value in the value column is
   994  				// correct if it is requested.
   995  				if entry.nVals == entry.nCols {
   996  					id := int64(*datums[entry.nCols-2].(*tree.DInt))
   997  					val := int64(*datums[entry.nCols-1].(*tree.DInt))
   998  
   999  					if id%int64(entry.modFactor) != val {
  1000  						t.Fatalf("for table %s row id %d, expected %d value, got %d", tableIdxName, id, id%int64(entry.modFactor), val)
  1001  					}
  1002  				}
  1003  			}
  1004  
  1005  			for _, entry := range entries {
  1006  				lookup := fmt.Sprintf("%s@%s", entry.tableName, entry.indexName)
  1007  
  1008  				actual, ok := count[lookup]
  1009  				if !ok {
  1010  					t.Errorf("no rows were retrieved for table %s, expected %d rows", entry.tableName, entry.nRows)
  1011  					continue
  1012  				}
  1013  
  1014  				if entry.nRows != actual {
  1015  					t.Errorf("for table %s expected %d rows, got %d rows", entry.tableName, entry.nRows, actual)
  1016  				}
  1017  			}
  1018  		})
  1019  	}
  1020  }
  1021  
  1022  func TestRowFetcherReset(t *testing.T) {
  1023  	defer leaktest.AfterTest(t)()
  1024  	ctx := context.Background()
  1025  
  1026  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
  1027  	defer s.Stopper().Stop(ctx)
  1028  	sqlutils.CreateTable(
  1029  		t, sqlDB, "foo",
  1030  		"k INT PRIMARY KEY, v INT",
  1031  		0,
  1032  		sqlutils.ToRowFn(sqlutils.RowIdxFn, sqlutils.RowModuloFn(1)),
  1033  	)
  1034  	tableDesc := sqlbase.GetImmutableTableDescriptor(kvDB, keys.SystemSQLCodec, sqlutils.TestDB, "foo")
  1035  	var valNeededForCol util.FastIntSet
  1036  	valNeededForCol.AddRange(0, 1)
  1037  	args := []initFetcherArgs{
  1038  		{
  1039  			tableDesc:       tableDesc,
  1040  			indexIdx:        0,
  1041  			valNeededForCol: valNeededForCol,
  1042  		},
  1043  	}
  1044  	da := sqlbase.DatumAlloc{}
  1045  	fetcher, err := initFetcher(args, false, &da)
  1046  	if err != nil {
  1047  		t.Fatal(err)
  1048  	}
  1049  
  1050  	resetFetcher, err := initFetcher(args, false, &da)
  1051  	if err != nil {
  1052  		t.Fatal(err)
  1053  	}
  1054  
  1055  	resetFetcher.Reset()
  1056  	if len(resetFetcher.tables) != 0 || cap(resetFetcher.tables) != 1 {
  1057  		t.Fatal("Didn't find saved slice:", resetFetcher.tables)
  1058  	}
  1059  
  1060  	// Now re-init the reset fetcher and make sure its the same as the fetcher we
  1061  	// didn't reset.
  1062  
  1063  	fetcherArgs := makeFetcherArgs(args)
  1064  	if err := resetFetcher.Init(
  1065  		keys.SystemSQLCodec, false /*reverse*/, 0 /* todo */, false /* returnRangeInfo */, false /* isCheck */, &da, fetcherArgs...,
  1066  	); err != nil {
  1067  		t.Fatal(err)
  1068  	}
  1069  
  1070  	if !reflect.DeepEqual(resetFetcher, fetcher) {
  1071  		t.Fatal("unequal before and after reset", resetFetcher, fetcher)
  1072  	}
  1073  
  1074  }
  1075  
  1076  func idLookupKey(tableID TableID, indexID sqlbase.IndexID) uint64 {
  1077  	return (uint64(tableID) << 32) | uint64(indexID)
  1078  }
  1079  
  1080  func TestFetcherUninitialized(t *testing.T) {
  1081  	// Regression test for #39013: make sure it's okay to call GetRangesInfo and
  1082  	// GetBytesReader even before the fetcher was fully initialized.
  1083  	var fetcher Fetcher
  1084  
  1085  	assert.Nil(t, fetcher.GetRangesInfo())
  1086  	assert.Zero(t, fetcher.GetBytesRead())
  1087  }