github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ccl/importccl/load_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Licensed as a CockroachDB Enterprise file under the Cockroach Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //     https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt
     8  
     9  package importccl_test
    10  
    11  import (
    12  	"bytes"
    13  	"context"
    14  	gosql "database/sql"
    15  	"fmt"
    16  	"strings"
    17  	"testing"
    18  
    19  	"github.com/cockroachdb/cockroach/pkg/base"
    20  	"github.com/cockroachdb/cockroach/pkg/ccl/importccl"
    21  	"github.com/cockroachdb/cockroach/pkg/keys"
    22  	"github.com/cockroachdb/cockroach/pkg/kv"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils"
    26  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    27  	"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
    28  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    29  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    30  	"github.com/cockroachdb/cockroach/pkg/workload/bank"
    31  	"github.com/cockroachdb/cockroach/pkg/workload/workloadsql"
    32  	"github.com/stretchr/testify/assert"
    33  	"github.com/stretchr/testify/require"
    34  )
    35  
    36  func bankBuf(numAccounts int) *bytes.Buffer {
    37  	bankData := bank.FromRows(numAccounts).Tables()[0]
    38  	var buf bytes.Buffer
    39  	fmt.Fprintf(&buf, "CREATE TABLE %s %s;\n", bankData.Name, bankData.Schema)
    40  	for rowIdx := 0; rowIdx < bankData.InitialRows.NumBatches; rowIdx++ {
    41  		for _, row := range bankData.InitialRows.BatchRows(rowIdx) {
    42  			rowTuple := strings.Join(workloadsql.StringTuple(row), `,`)
    43  			fmt.Fprintf(&buf, "INSERT INTO %s VALUES (%s);\n", bankData.Name, rowTuple)
    44  		}
    45  	}
    46  	return &buf
    47  }
    48  
    49  func TestGetDescriptorFromDB(t *testing.T) {
    50  	defer leaktest.AfterTest(t)()
    51  
    52  	ctx := context.Background()
    53  	params, _ := tests.CreateTestServerParams()
    54  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
    55  	defer s.Stopper().Stop(ctx)
    56  
    57  	aliceDesc := &sqlbase.DatabaseDescriptor{Name: "alice"}
    58  	bobDesc := &sqlbase.DatabaseDescriptor{Name: "bob"}
    59  
    60  	err := kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
    61  		if err := txn.SetSystemConfigTrigger(); err != nil {
    62  			return err
    63  		}
    64  		batch := txn.NewBatch()
    65  		batch.Put(sqlbase.NewDatabaseKey("bob").Key(keys.SystemSQLCodec), 9999)
    66  		batch.Put(sqlbase.NewDeprecatedDatabaseKey("alice").Key(keys.SystemSQLCodec), 10000)
    67  
    68  		batch.Put(sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, 9999), sqlbase.WrapDescriptor(bobDesc))
    69  		batch.Put(sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, 10000), sqlbase.WrapDescriptor(aliceDesc))
    70  		return txn.CommitInBatch(ctx, batch)
    71  	})
    72  	require.NoError(t, err)
    73  
    74  	for _, tc := range []struct {
    75  		dbName string
    76  
    77  		expected    *sqlbase.DatabaseDescriptor
    78  		expectedErr error
    79  	}{
    80  		{"bob", bobDesc, nil},
    81  		{"alice", aliceDesc, nil},
    82  		{"not_found", nil, gosql.ErrNoRows},
    83  	} {
    84  		t.Run(tc.dbName, func(t *testing.T) {
    85  			ret, err := importccl.TestingGetDescriptorFromDB(ctx, sqlDB, tc.dbName)
    86  			if tc.expectedErr != nil {
    87  				assert.Error(t, err)
    88  				assert.Equal(t, tc.expectedErr, err)
    89  			} else {
    90  				assert.NoError(t, err)
    91  				assert.Equal(t, tc.expected, ret)
    92  			}
    93  		})
    94  	}
    95  }
    96  
    97  func TestImportChunking(t *testing.T) {
    98  	defer leaktest.AfterTest(t)()
    99  
   100  	// Generate at least 2 chunks.
   101  	const chunkSize = 1024 * 500
   102  	numAccounts := int(chunkSize / 100 * 2)
   103  
   104  	ctx := context.Background()
   105  	dir, cleanup := testutils.TempDir(t)
   106  	defer cleanup()
   107  
   108  	tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{ServerArgs: base.TestServerArgs{ExternalIODir: dir}})
   109  	defer tc.Stopper().Stop(ctx)
   110  
   111  	if _, err := tc.Conns[0].Exec("CREATE DATABASE data"); err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	ts := hlc.Timestamp{WallTime: hlc.UnixNano()}
   116  	desc, err := importccl.Load(ctx, tc.Conns[0], bankBuf(numAccounts), "data", "nodelocal://0"+dir, ts, chunkSize, dir, dir)
   117  	if err != nil {
   118  		t.Fatalf("%+v", err)
   119  	}
   120  	if len(desc.Files) < 2 {
   121  		t.Errorf("expected at least 2 ranges")
   122  	}
   123  }
   124  
   125  func TestImportOutOfOrder(t *testing.T) {
   126  	defer leaktest.AfterTest(t)()
   127  
   128  	ctx := context.Background()
   129  	dir, cleanup := testutils.TempDir(t)
   130  	defer cleanup()
   131  
   132  	tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{ServerArgs: base.TestServerArgs{ExternalIODir: dir}})
   133  	defer tc.Stopper().Stop(ctx)
   134  
   135  	if _, err := tc.Conns[0].Exec("CREATE DATABASE data"); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	bankData := bank.FromRows(2).Tables()[0]
   139  	row1 := workloadsql.StringTuple(bankData.InitialRows.BatchRows(0)[0])
   140  	row2 := workloadsql.StringTuple(bankData.InitialRows.BatchRows(1)[0])
   141  
   142  	var buf bytes.Buffer
   143  	fmt.Fprintf(&buf, "CREATE TABLE %s %s;\n", bankData.Name, bankData.Schema)
   144  	// Intentionally write the rows out of order.
   145  	fmt.Fprintf(&buf, "INSERT INTO %s VALUES (%s);\n", bankData.Name, strings.Join(row2, `,`))
   146  	fmt.Fprintf(&buf, "INSERT INTO %s VALUES (%s);\n", bankData.Name, strings.Join(row1, `,`))
   147  
   148  	ts := hlc.Timestamp{WallTime: hlc.UnixNano()}
   149  	_, err := importccl.Load(ctx, tc.Conns[0], &buf, "data", "nodelocal://0/foo", ts, 0, dir, dir)
   150  	if !testutils.IsError(err, "out of order row") {
   151  		t.Fatalf("expected out of order row, got: %+v", err)
   152  	}
   153  }
   154  
   155  func BenchmarkLoad(b *testing.B) {
   156  	if testing.Short() {
   157  		b.Skip("TODO: fix benchmark")
   158  	}
   159  	// NB: This benchmark takes liberties in how b.N is used compared to the go
   160  	// documentation's description. We're getting useful information out of it,
   161  	// but this is not a pattern to cargo-cult.
   162  	ctx := context.Background()
   163  	dir, cleanup := testutils.TempDir(b)
   164  	defer cleanup()
   165  
   166  	tc := testcluster.StartTestCluster(b, 1, base.TestClusterArgs{ServerArgs: base.TestServerArgs{ExternalIODir: dir}})
   167  	defer tc.Stopper().Stop(ctx)
   168  	if _, err := tc.Conns[0].Exec("CREATE DATABASE data"); err != nil {
   169  		b.Fatal(err)
   170  	}
   171  
   172  	ts := hlc.Timestamp{WallTime: hlc.UnixNano()}
   173  	buf := bankBuf(b.N)
   174  	b.SetBytes(int64(buf.Len() / b.N))
   175  	b.ResetTimer()
   176  	if _, err := importccl.Load(ctx, tc.Conns[0], buf, "data", dir, ts, 0, dir, dir); err != nil {
   177  		b.Fatalf("%+v", err)
   178  	}
   179  }