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

     1  // Copyright 2015 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 sql_test
    12  
    13  import (
    14  	"context"
    15  	gosql "database/sql"
    16  	"fmt"
    17  	"math/rand"
    18  	"regexp"
    19  	"testing"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/base"
    22  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    23  	"github.com/cockroachdb/cockroach/pkg/jobs"
    24  	"github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
    25  	"github.com/cockroachdb/cockroach/pkg/keys"
    26  	"github.com/cockroachdb/cockroach/pkg/kv"
    27  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver"
    28  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    29  	"github.com/cockroachdb/cockroach/pkg/security"
    30  	"github.com/cockroachdb/cockroach/pkg/server"
    31  	"github.com/cockroachdb/cockroach/pkg/sql"
    32  	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
    33  	"github.com/cockroachdb/cockroach/pkg/sql/gcjob"
    34  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    35  	"github.com/cockroachdb/cockroach/pkg/sql/sqltestutils"
    36  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    37  	"github.com/cockroachdb/cockroach/pkg/sqlmigrations"
    38  	"github.com/cockroachdb/cockroach/pkg/testutils"
    39  	"github.com/cockroachdb/cockroach/pkg/testutils/jobutils"
    40  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    41  	"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
    42  	"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
    43  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    44  	"github.com/cockroachdb/cockroach/pkg/util/protoutil"
    45  	"github.com/cockroachdb/cockroach/pkg/util/syncutil"
    46  	"github.com/cockroachdb/cockroach/pkg/util/tracing"
    47  	"github.com/cockroachdb/cockroach/pkg/util/uuid"
    48  	"github.com/cockroachdb/errors"
    49  	"github.com/opentracing/opentracing-go"
    50  	"github.com/stretchr/testify/require"
    51  )
    52  
    53  // Returns an error if a zone config for the specified table or
    54  // database ID doesn't match the expected parameter. If expected
    55  // is nil, then we verify no zone config exists.
    56  func zoneExists(sqlDB *gosql.DB, expected *zonepb.ZoneConfig, id sqlbase.ID) error {
    57  	rows, err := sqlDB.Query(`SELECT * FROM system.zones WHERE id = $1`, id)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	defer rows.Close()
    62  	if exists := (expected != nil); exists != rows.Next() {
    63  		return errors.Errorf("zone config exists = %v", exists)
    64  	}
    65  	if expected != nil {
    66  		// Ensure that the zone config matches.
    67  		var storedID sqlbase.ID
    68  		var val []byte
    69  		if err := rows.Scan(&storedID, &val); err != nil {
    70  			return errors.Errorf("row scan failed: %s", err)
    71  		}
    72  		if storedID != id {
    73  			return errors.Errorf("e = %d, v = %d", id, storedID)
    74  		}
    75  		var cfg zonepb.ZoneConfig
    76  		if err := protoutil.Unmarshal(val, &cfg); err != nil {
    77  			return err
    78  		}
    79  		if !expected.Equal(cfg) {
    80  			return errors.Errorf("e = %v, v = %v", expected, cfg)
    81  		}
    82  	}
    83  	return nil
    84  }
    85  
    86  // Returns an error if a descriptor "exists" for the table id.
    87  func descExists(sqlDB *gosql.DB, exists bool, id sqlbase.ID) error {
    88  	rows, err := sqlDB.Query(`SELECT * FROM system.descriptor WHERE id = $1`, id)
    89  	if err != nil {
    90  		return err
    91  	}
    92  	defer rows.Close()
    93  	if exists != rows.Next() {
    94  		return errors.Errorf("descriptor exists = %v", exists)
    95  	}
    96  	return nil
    97  }
    98  
    99  func TestDropDatabase(t *testing.T) {
   100  	defer leaktest.AfterTest(t)()
   101  	params, _ := tests.CreateTestServerParams()
   102  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   103  	defer s.Stopper().Stop(context.Background())
   104  	ctx := context.Background()
   105  
   106  	// Fix the column families so the key counts below don't change if the
   107  	// family heuristics are updated.
   108  	if _, err := sqlDB.Exec(`
   109  CREATE DATABASE t;
   110  CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR, FAMILY (k), FAMILY (v));
   111  INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd');
   112  `); err != nil {
   113  		t.Fatal(err)
   114  	}
   115  
   116  	dbNameKey := sqlbase.NewDatabaseKey("t").Key(keys.SystemSQLCodec)
   117  	r, err := kvDB.Get(ctx, dbNameKey)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  	if !r.Exists() {
   122  		t.Fatalf(`database "t" does not exist`)
   123  	}
   124  	dbDescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(r.ValueInt()))
   125  	desc := &sqlbase.Descriptor{}
   126  	if err := kvDB.GetProto(ctx, dbDescKey, desc); err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	dbDesc := desc.GetDatabase()
   130  
   131  	tbNameKey := sqlbase.NewPublicTableKey(dbDesc.ID, "kv").Key(keys.SystemSQLCodec)
   132  	gr, err := kvDB.Get(ctx, tbNameKey)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	if !gr.Exists() {
   137  		t.Fatalf(`table "kv" does not exist`)
   138  	}
   139  	tbDescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(gr.ValueInt()))
   140  	ts, err := kvDB.GetProtoTs(ctx, tbDescKey, desc)
   141  	if err != nil {
   142  		t.Fatal(err)
   143  	}
   144  	tbDesc := desc.Table(ts)
   145  
   146  	// Add a zone config for both the table and database.
   147  	cfg := zonepb.DefaultZoneConfig()
   148  	buf, err := protoutil.Marshal(&cfg)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, tbDesc.ID, buf); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	if _, err := sqlDB.Exec(`INSERT INTO system.zones VALUES ($1, $2)`, dbDesc.ID, buf); err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	if err := zoneExists(sqlDB, &cfg, tbDesc.ID); err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	if err := zoneExists(sqlDB, &cfg, dbDesc.ID); err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	tableSpan := tbDesc.TableSpan(keys.SystemSQLCodec)
   167  	tests.CheckKeyCount(t, kvDB, tableSpan, 6)
   168  
   169  	if _, err := sqlDB.Exec(`DROP DATABASE t RESTRICT`); !testutils.IsError(err,
   170  		`database "t" is not empty`) {
   171  		t.Fatal(err)
   172  	}
   173  
   174  	if _, err := sqlDB.Exec(`DROP DATABASE t CASCADE`); err != nil {
   175  		t.Fatal(err)
   176  	}
   177  
   178  	// Data is not deleted.
   179  	tests.CheckKeyCount(t, kvDB, tableSpan, 6)
   180  
   181  	if err := descExists(sqlDB, true, tbDesc.ID); err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	if gr, err := kvDB.Get(ctx, tbNameKey); err != nil {
   186  		t.Fatal(err)
   187  	} else if gr.Exists() {
   188  		t.Fatalf("table descriptor key still exists after database is dropped")
   189  	}
   190  
   191  	if err := descExists(sqlDB, false, dbDesc.ID); err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	// Database zone config is removed once all table data and zone configs are removed.
   195  	if err := zoneExists(sqlDB, &cfg, dbDesc.ID); err != nil {
   196  		t.Fatal(err)
   197  	}
   198  
   199  	if gr, err := kvDB.Get(ctx, dbNameKey); err != nil {
   200  		t.Fatal(err)
   201  	} else if gr.Exists() {
   202  		t.Fatalf("database descriptor key still exists after database is dropped")
   203  	}
   204  
   205  	if err := zoneExists(sqlDB, &cfg, tbDesc.ID); err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
   210  	// There are no more namespace entries referencing this database as its
   211  	// parent.
   212  	namespaceQuery := fmt.Sprintf(`SELECT * FROM system.namespace WHERE "parentID"  = %d`, dbDesc.ID)
   213  	sqlRun.CheckQueryResults(t, namespaceQuery, [][]string{})
   214  
   215  	// Job still running, waiting for GC.
   216  	// TODO (lucy): Maybe this test API should use an offset starting
   217  	// from the most recent job instead.
   218  	if err := jobutils.VerifySystemJob(t, sqlRun, 0, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   219  		Username:    security.RootUser,
   220  		Description: "DROP DATABASE t CASCADE",
   221  		DescriptorIDs: sqlbase.IDs{
   222  			tbDesc.ID,
   223  		},
   224  	}); err != nil {
   225  		t.Fatal(err)
   226  	}
   227  }
   228  
   229  // Test that an empty, dropped database's zone config gets deleted immediately.
   230  func TestDropDatabaseEmpty(t *testing.T) {
   231  	defer leaktest.AfterTest(t)()
   232  	params, _ := tests.CreateTestServerParams()
   233  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   234  	defer s.Stopper().Stop(context.Background())
   235  	ctx := context.Background()
   236  
   237  	if _, err := sqlDB.Exec(`
   238  CREATE DATABASE t;
   239  `); err != nil {
   240  		t.Fatal(err)
   241  	}
   242  
   243  	dKey := sqlbase.NewDatabaseKey("t")
   244  	r, err := kvDB.Get(ctx, dKey.Key(keys.SystemSQLCodec))
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	if !r.Exists() {
   249  		t.Fatalf(`database "t" does not exist`)
   250  	}
   251  	dbID := sqlbase.ID(r.ValueInt())
   252  
   253  	if cfg, err := sqltestutils.AddDefaultZoneConfig(sqlDB, dbID); err != nil {
   254  		t.Fatal(err)
   255  	} else if err := zoneExists(sqlDB, &cfg, dbID); err != nil {
   256  		t.Fatal(err)
   257  	}
   258  
   259  	if _, err := sqlDB.Exec(`DROP DATABASE t`); err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	if err := descExists(sqlDB, false, dbID); err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	if err := zoneExists(sqlDB, nil, dbID); err != nil {
   268  		t.Fatal(err)
   269  	}
   270  }
   271  
   272  // Test that a dropped database's data gets deleted properly.
   273  func TestDropDatabaseDeleteData(t *testing.T) {
   274  	defer leaktest.AfterTest(t)()
   275  
   276  	defer gcjob.SetSmallMaxGCIntervalForTest()()
   277  
   278  	params, _ := tests.CreateTestServerParams()
   279  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   280  	defer s.Stopper().Stop(context.Background())
   281  	ctx := context.Background()
   282  
   283  	// Disable strict GC TTL enforcement because we're going to shove a zero-value
   284  	// TTL into the system with AddImmediateGCZoneConfig.
   285  	defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)()
   286  
   287  	// Fix the column families so the key counts below don't change if the
   288  	// family heuristics are updated.
   289  	if _, err := sqlDB.Exec(`
   290  CREATE DATABASE t;
   291  CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR, FAMILY (k), FAMILY (v));
   292  INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd');
   293  CREATE TABLE t.kv2 (k CHAR PRIMARY KEY, v CHAR, FAMILY (k), FAMILY (v));
   294  INSERT INTO t.kv2 VALUES ('c', 'd'), ('a', 'b'), ('e', 'a');
   295  `); err != nil {
   296  		t.Fatal(err)
   297  	}
   298  
   299  	dKey := sqlbase.NewDatabaseKey("t")
   300  	r, err := kvDB.Get(ctx, dKey.Key(keys.SystemSQLCodec))
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  	if !r.Exists() {
   305  		t.Fatalf(`database "t" does not exist`)
   306  	}
   307  	dbDescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(r.ValueInt()))
   308  	desc := &sqlbase.Descriptor{}
   309  	if err := kvDB.GetProto(ctx, dbDescKey, desc); err != nil {
   310  		t.Fatal(err)
   311  	}
   312  	dbDesc := desc.GetDatabase()
   313  
   314  	tKey := sqlbase.NewPublicTableKey(dbDesc.ID, "kv")
   315  	gr, err := kvDB.Get(ctx, tKey.Key(keys.SystemSQLCodec))
   316  	if err != nil {
   317  		t.Fatal(err)
   318  	}
   319  	if !gr.Exists() {
   320  		t.Fatalf(`table "kv" does not exist`)
   321  	}
   322  	tbDescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(gr.ValueInt()))
   323  	ts, err := kvDB.GetProtoTs(ctx, tbDescKey, desc)
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  	tbDesc := desc.Table(ts)
   328  
   329  	t2Key := sqlbase.NewPublicTableKey(dbDesc.ID, "kv2")
   330  	gr2, err := kvDB.Get(ctx, t2Key.Key(keys.SystemSQLCodec))
   331  	if err != nil {
   332  		t.Fatal(err)
   333  	}
   334  	if !gr2.Exists() {
   335  		t.Fatalf(`table "kv2" does not exist`)
   336  	}
   337  	tb2DescKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(gr2.ValueInt()))
   338  	ts, err = kvDB.GetProtoTs(ctx, tb2DescKey, desc)
   339  	if err != nil {
   340  		t.Fatal(err)
   341  	}
   342  	tb2Desc := desc.Table(ts)
   343  
   344  	tableSpan := tbDesc.TableSpan(keys.SystemSQLCodec)
   345  	table2Span := tb2Desc.TableSpan(keys.SystemSQLCodec)
   346  	tests.CheckKeyCount(t, kvDB, tableSpan, 6)
   347  	tests.CheckKeyCount(t, kvDB, table2Span, 6)
   348  
   349  	if _, err := sqltestutils.AddDefaultZoneConfig(sqlDB, dbDesc.ID); err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	if _, err := sqlDB.Exec(`DROP DATABASE t RESTRICT`); !testutils.IsError(err,
   354  		`database "t" is not empty`) {
   355  		t.Fatal(err)
   356  	}
   357  
   358  	if _, err := sqlDB.Exec(`DROP DATABASE t CASCADE`); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	tests.CheckKeyCount(t, kvDB, tableSpan, 6)
   363  	tests.CheckKeyCount(t, kvDB, table2Span, 6)
   364  
   365  	// TODO (lucy): Maybe this test API should use an offset starting
   366  	// from the most recent job instead.
   367  	const migrationJobOffset = 0
   368  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
   369  	if err := jobutils.VerifySystemJob(t, sqlRun, migrationJobOffset, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   370  		Username:    security.RootUser,
   371  		Description: "DROP DATABASE t CASCADE",
   372  		DescriptorIDs: sqlbase.IDs{
   373  			tbDesc.ID, tb2Desc.ID,
   374  		},
   375  	}); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	// Push a new zone config for the table with TTL=0 so the data is
   380  	// deleted immediately.
   381  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tbDesc.ID); err != nil {
   382  		t.Fatal(err)
   383  	}
   384  
   385  	testutils.SucceedsSoon(t, func() error {
   386  		if err := descExists(sqlDB, false, tbDesc.ID); err != nil {
   387  			return err
   388  		}
   389  
   390  		return zoneExists(sqlDB, nil, tbDesc.ID)
   391  	})
   392  
   393  	// Table 1 data is deleted.
   394  	tests.CheckKeyCount(t, kvDB, tableSpan, 0)
   395  	tests.CheckKeyCount(t, kvDB, table2Span, 6)
   396  
   397  	def := zonepb.DefaultZoneConfig()
   398  	if err := zoneExists(sqlDB, &def, dbDesc.ID); err != nil {
   399  		t.Fatal(err)
   400  	}
   401  
   402  	testutils.SucceedsSoon(t, func() error {
   403  		return jobutils.VerifySystemJob(t, sqlRun, 0, jobspb.TypeSchemaChangeGC, jobs.StatusRunning, jobs.Record{
   404  			Username:    security.RootUser,
   405  			Description: "GC for DROP DATABASE t CASCADE",
   406  			DescriptorIDs: sqlbase.IDs{
   407  				tbDesc.ID, tb2Desc.ID,
   408  			},
   409  		})
   410  	})
   411  
   412  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tb2Desc.ID); err != nil {
   413  		t.Fatal(err)
   414  	}
   415  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, dbDesc.ID); err != nil {
   416  		t.Fatal(err)
   417  	}
   418  
   419  	testutils.SucceedsSoon(t, func() error {
   420  		if err := descExists(sqlDB, false, tb2Desc.ID); err != nil {
   421  			return err
   422  		}
   423  
   424  		return zoneExists(sqlDB, nil, tb2Desc.ID)
   425  	})
   426  
   427  	// Table 2 data is deleted.
   428  	tests.CheckKeyCount(t, kvDB, table2Span, 0)
   429  
   430  	if err := jobutils.VerifySystemJob(t, sqlRun, migrationJobOffset, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   431  		Username:    security.RootUser,
   432  		Description: "DROP DATABASE t CASCADE",
   433  		DescriptorIDs: sqlbase.IDs{
   434  			tbDesc.ID, tb2Desc.ID,
   435  		},
   436  	}); err != nil {
   437  		t.Fatal(err)
   438  	}
   439  
   440  	// Database zone config is removed once all table data and zone configs are removed.
   441  	if err := zoneExists(sqlDB, nil, dbDesc.ID); err != nil {
   442  		t.Fatal(err)
   443  	}
   444  }
   445  
   446  // Tests that SHOW TABLES works correctly when a database is recreated
   447  // during the time the underlying tables are still being deleted.
   448  func TestShowTablesAfterRecreateDatabase(t *testing.T) {
   449  	defer leaktest.AfterTest(t)()
   450  	params, _ := tests.CreateTestServerParams()
   451  	// Turn off the application of schema changes so that tables do not
   452  	// get completely dropped.
   453  	params.Knobs = base.TestingKnobs{
   454  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{
   455  			SchemaChangeJobNoOp: func() bool {
   456  				return true
   457  			},
   458  		},
   459  	}
   460  	s, sqlDB, _ := serverutils.StartServer(t, params)
   461  	defer s.Stopper().Stop(context.Background())
   462  
   463  	if _, err := sqlDB.Exec(`
   464  CREATE DATABASE t;
   465  CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR);
   466  INSERT INTO t.kv VALUES ('c', 'e'), ('a', 'c'), ('b', 'd');
   467  `); err != nil {
   468  		t.Fatal(err)
   469  	}
   470  
   471  	if _, err := sqlDB.Exec(`
   472  DROP DATABASE t CASCADE;
   473  CREATE DATABASE t;
   474  `); err != nil {
   475  		t.Fatal(err)
   476  	}
   477  
   478  	rows, err := sqlDB.Query(`
   479  SET DATABASE=t;
   480  SHOW TABLES;
   481  `)
   482  	if err != nil {
   483  		t.Fatal(err)
   484  	}
   485  	defer rows.Close()
   486  	if rows.Next() {
   487  		t.Fatal("table should be invisible through SHOW TABLES")
   488  	}
   489  }
   490  
   491  func TestDropIndex(t *testing.T) {
   492  	defer leaktest.AfterTest(t)()
   493  	const chunkSize = 200
   494  	params, _ := tests.CreateTestServerParams()
   495  	emptySpan := true
   496  	clearIndexAttempt := false
   497  	params.Knobs = base.TestingKnobs{
   498  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{
   499  			BackfillChunkSize: chunkSize,
   500  		},
   501  		DistSQL: &execinfra.TestingKnobs{
   502  			RunBeforeBackfillChunk: func(sp roachpb.Span) error {
   503  				if clearIndexAttempt && (sp.Key != nil || sp.EndKey != nil) {
   504  					emptySpan = false
   505  				}
   506  				return nil
   507  			},
   508  		},
   509  	}
   510  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   511  	defer s.Stopper().Stop(context.Background())
   512  
   513  	// Disable strict GC TTL enforcement because we're going to shove a zero-value
   514  	// TTL into the system with AddImmediateGCZoneConfig.
   515  	defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)()
   516  
   517  	numRows := 2*chunkSize + 1
   518  	if err := tests.CreateKVTable(sqlDB, "kv", numRows); err != nil {
   519  		t.Fatal(err)
   520  	}
   521  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   522  	tests.CheckKeyCount(t, kvDB, tableDesc.TableSpan(keys.SystemSQLCodec), 3*numRows)
   523  	idx, _, err := tableDesc.FindIndexByName("foo")
   524  	if err != nil {
   525  		t.Fatal(err)
   526  	}
   527  	indexSpan := tableDesc.IndexSpan(keys.SystemSQLCodec, idx.ID)
   528  	tests.CheckKeyCount(t, kvDB, indexSpan, numRows)
   529  	if _, err := sqlDB.Exec(`DROP INDEX t.kv@foo`); err != nil {
   530  		t.Fatal(err)
   531  	}
   532  
   533  	tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   534  	if _, _, err := tableDesc.FindIndexByName("foo"); err == nil {
   535  		t.Fatalf("table descriptor still contains index after index is dropped")
   536  	}
   537  	// Index data hasn't been deleted.
   538  	tests.CheckKeyCount(t, kvDB, indexSpan, numRows)
   539  	tests.CheckKeyCount(t, kvDB, tableDesc.TableSpan(keys.SystemSQLCodec), 3*numRows)
   540  
   541  	// TODO (lucy): Maybe this test API should use an offset starting
   542  	// from the most recent job instead.
   543  	const migrationJobOffset = 0
   544  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
   545  	if err := jobutils.VerifySystemJob(t, sqlRun, migrationJobOffset+1, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   546  		Username:    security.RootUser,
   547  		Description: `DROP INDEX t.public.kv@foo`,
   548  		DescriptorIDs: sqlbase.IDs{
   549  			tableDesc.ID,
   550  		},
   551  	}); err != nil {
   552  		t.Fatal(err)
   553  	}
   554  
   555  	if _, err := sqlDB.Exec(`CREATE INDEX foo on t.kv (v);`); err != nil {
   556  		t.Fatal(err)
   557  	}
   558  
   559  	tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   560  	newIdx, _, err := tableDesc.FindIndexByName("foo")
   561  	if err != nil {
   562  		t.Fatal(err)
   563  	}
   564  	newIdxSpan := tableDesc.IndexSpan(keys.SystemSQLCodec, newIdx.ID)
   565  	tests.CheckKeyCount(t, kvDB, newIdxSpan, numRows)
   566  	tests.CheckKeyCount(t, kvDB, tableDesc.TableSpan(keys.SystemSQLCodec), 4*numRows)
   567  
   568  	clearIndexAttempt = true
   569  	// Add a zone config for the table.
   570  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDesc.ID); err != nil {
   571  		t.Fatal(err)
   572  	}
   573  
   574  	testutils.SucceedsSoon(t, func() error {
   575  		return jobutils.VerifySystemJob(t, sqlRun, migrationJobOffset+1, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   576  			Username:    security.RootUser,
   577  			Description: `DROP INDEX t.public.kv@foo`,
   578  			DescriptorIDs: sqlbase.IDs{
   579  				tableDesc.ID,
   580  			},
   581  		})
   582  	})
   583  
   584  	testutils.SucceedsSoon(t, func() error {
   585  		return jobutils.VerifySystemJob(t, sqlRun, 0, jobspb.TypeSchemaChangeGC, jobs.StatusSucceeded, jobs.Record{
   586  			Username:    security.RootUser,
   587  			Description: `GC for DROP INDEX t.public.kv@foo`,
   588  			DescriptorIDs: sqlbase.IDs{
   589  				tableDesc.ID,
   590  			},
   591  		})
   592  	})
   593  
   594  	if !emptySpan {
   595  		t.Fatalf("tried to clear index with non-empty resume span")
   596  	}
   597  
   598  	tests.CheckKeyCount(t, kvDB, newIdxSpan, numRows)
   599  	tests.CheckKeyCount(t, kvDB, indexSpan, 0)
   600  	tests.CheckKeyCount(t, kvDB, tableDesc.TableSpan(keys.SystemSQLCodec), 3*numRows)
   601  }
   602  
   603  func TestDropIndexWithZoneConfigOSS(t *testing.T) {
   604  	defer leaktest.AfterTest(t)()
   605  
   606  	const chunkSize = 200
   607  	const numRows = 2*chunkSize + 1
   608  
   609  	params, _ := tests.CreateTestServerParams()
   610  	params.Knobs = base.TestingKnobs{
   611  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{BackfillChunkSize: chunkSize},
   612  	}
   613  	s, sqlDBRaw, kvDB := serverutils.StartServer(t, params)
   614  	sqlDB := sqlutils.MakeSQLRunner(sqlDBRaw)
   615  	defer s.Stopper().Stop(context.Background())
   616  
   617  	// Create a test table with a secondary index.
   618  	if err := tests.CreateKVTable(sqlDBRaw, "kv", numRows); err != nil {
   619  		t.Fatal(err)
   620  	}
   621  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   622  	indexDesc, _, err := tableDesc.FindIndexByName("foo")
   623  	if err != nil {
   624  		t.Fatal(err)
   625  	}
   626  	indexSpan := tableDesc.IndexSpan(keys.SystemSQLCodec, indexDesc.ID)
   627  	tests.CheckKeyCount(t, kvDB, indexSpan, numRows)
   628  
   629  	// Hack in zone configs for the primary and secondary indexes. (You need a CCL
   630  	// binary to do this properly.) Dropping the index will thus require
   631  	// regenerating the zone config's SubzoneSpans, which will fail with a "CCL
   632  	// required" error.
   633  	zoneConfig := zonepb.ZoneConfig{
   634  		Subzones: []zonepb.Subzone{
   635  			{IndexID: uint32(tableDesc.PrimaryIndex.ID), Config: s.(*server.TestServer).Cfg.DefaultZoneConfig},
   636  			{IndexID: uint32(indexDesc.ID), Config: s.(*server.TestServer).Cfg.DefaultZoneConfig},
   637  		},
   638  	}
   639  	zoneConfigBytes, err := protoutil.Marshal(&zoneConfig)
   640  	if err != nil {
   641  		t.Fatal(err)
   642  	}
   643  	sqlDB.Exec(t, `INSERT INTO system.zones VALUES ($1, $2)`, tableDesc.ID, zoneConfigBytes)
   644  	if !sqlutils.ZoneConfigExists(t, sqlDB, "INDEX t.public.kv@foo") {
   645  		t.Fatal("zone config for index does not exist")
   646  	}
   647  
   648  	// Verify that dropping the index works.
   649  	_, err = sqlDBRaw.Exec(`DROP INDEX t.kv@foo`)
   650  	require.NoError(t, err)
   651  
   652  	// Verify that the index and its zone config still exist.
   653  	if sqlutils.ZoneConfigExists(t, sqlDB, "INDEX t.public.kv@foo") {
   654  		t.Fatal("zone config for index still exists")
   655  	}
   656  	tests.CheckKeyCount(t, kvDB, indexSpan, numRows)
   657  	// TODO(benesch): Run scrub here. It can't currently handle the way t.kv
   658  	// declares column families.
   659  
   660  	tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   661  	if _, _, err := tableDesc.FindIndexByName("foo"); err == nil {
   662  		t.Fatalf("table descriptor still contains index after index is dropped")
   663  	}
   664  }
   665  
   666  func TestDropIndexInterleaved(t *testing.T) {
   667  	defer leaktest.AfterTest(t)()
   668  	const chunkSize = 200
   669  	params, _ := tests.CreateTestServerParams()
   670  	params.Knobs = base.TestingKnobs{
   671  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{
   672  			BackfillChunkSize: chunkSize,
   673  		},
   674  	}
   675  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   676  	defer s.Stopper().Stop(context.Background())
   677  
   678  	numRows := 2*chunkSize + 1
   679  	tests.CreateKVInterleavedTable(t, sqlDB, numRows)
   680  
   681  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   682  	tableSpan := tableDesc.TableSpan(keys.SystemSQLCodec)
   683  
   684  	tests.CheckKeyCount(t, kvDB, tableSpan, 3*numRows)
   685  
   686  	if _, err := sqlDB.Exec(`DROP INDEX t.intlv@intlv_idx`); err != nil {
   687  		t.Fatal(err)
   688  	}
   689  	tests.CheckKeyCount(t, kvDB, tableSpan, 2*numRows)
   690  
   691  	// Ensure that index is not active.
   692  	tableDesc = sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "intlv")
   693  	if _, _, err := tableDesc.FindIndexByName("intlv_idx"); err == nil {
   694  		t.Fatalf("table descriptor still contains index after index is dropped")
   695  	}
   696  }
   697  
   698  // Tests DROP TABLE and also checks that the table data is not deleted
   699  // via the synchronous path.
   700  func TestDropTable(t *testing.T) {
   701  	defer leaktest.AfterTest(t)()
   702  	params, _ := tests.CreateTestServerParams()
   703  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   704  	defer s.Stopper().Stop(context.Background())
   705  	ctx := context.Background()
   706  
   707  	numRows := 2*sql.TableTruncateChunkSize + 1
   708  	if err := tests.CreateKVTable(sqlDB, "kv", numRows); err != nil {
   709  		t.Fatal(err)
   710  	}
   711  
   712  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
   713  	nameKey := sqlbase.NewPublicTableKey(keys.MinNonPredefinedUserDescID, "kv").Key(keys.SystemSQLCodec)
   714  	gr, err := kvDB.Get(ctx, nameKey)
   715  
   716  	if err != nil {
   717  		t.Fatal(err)
   718  	}
   719  
   720  	if !gr.Exists() {
   721  		t.Fatalf("Name entry %q does not exist", nameKey)
   722  	}
   723  
   724  	// Add a zone config for the table.
   725  	cfg, err := sqltestutils.AddDefaultZoneConfig(sqlDB, tableDesc.ID)
   726  	if err != nil {
   727  		t.Fatal(err)
   728  	}
   729  
   730  	if err := zoneExists(sqlDB, &cfg, tableDesc.ID); err != nil {
   731  		t.Fatal(err)
   732  	}
   733  
   734  	tableSpan := tableDesc.TableSpan(keys.SystemSQLCodec)
   735  	tests.CheckKeyCount(t, kvDB, tableSpan, 3*numRows)
   736  	if _, err := sqlDB.Exec(`DROP TABLE t.kv`); err != nil {
   737  		t.Fatal(err)
   738  	}
   739  
   740  	// Test that deleted table cannot be used. This prevents
   741  	// regressions where name -> descriptor ID caches might make
   742  	// this statement erronously work.
   743  	if _, err := sqlDB.Exec(
   744  		`SELECT * FROM t.kv`,
   745  	); !testutils.IsError(err, `relation "t.kv" does not exist`) {
   746  		t.Fatalf("different error than expected: %+v", err)
   747  	}
   748  
   749  	if gr, err := kvDB.Get(ctx, nameKey); err != nil {
   750  		t.Fatal(err)
   751  	} else if gr.Exists() {
   752  		t.Fatalf("table namekey still exists")
   753  	}
   754  
   755  	// Job still running, waiting for GC.
   756  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
   757  	if err := jobutils.VerifySystemJob(t, sqlRun, 1, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   758  		Username:    security.RootUser,
   759  		Description: `DROP TABLE t.public.kv`,
   760  		DescriptorIDs: sqlbase.IDs{
   761  			tableDesc.ID,
   762  		},
   763  	}); err != nil {
   764  		t.Fatal(err)
   765  	}
   766  
   767  	// Can create a table with the same name.
   768  	if err := tests.CreateKVTable(sqlDB, "kv", numRows); err != nil {
   769  		t.Fatal(err)
   770  	}
   771  
   772  	// A lot of garbage has been left behind to be cleaned up by the
   773  	// asynchronous path.
   774  	tests.CheckKeyCount(t, kvDB, tableSpan, 3*numRows)
   775  
   776  	if err := descExists(sqlDB, true, tableDesc.ID); err != nil {
   777  		t.Fatal(err)
   778  	}
   779  
   780  	if err := zoneExists(sqlDB, &cfg, tableDesc.ID); err != nil {
   781  		t.Fatal(err)
   782  	}
   783  }
   784  
   785  // Test that after a DROP TABLE the table eventually gets deleted.
   786  func TestDropTableDeleteData(t *testing.T) {
   787  	defer leaktest.AfterTest(t)()
   788  	params, _ := tests.CreateTestServerParams()
   789  
   790  	defer gcjob.SetSmallMaxGCIntervalForTest()()
   791  
   792  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
   793  	defer s.Stopper().Stop(context.Background())
   794  	ctx := context.Background()
   795  
   796  	// Disable strict GC TTL enforcement because we're going to shove a zero-value
   797  	// TTL into the system with AddImmediateGCZoneConfig.
   798  	defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDB)()
   799  
   800  	const numRows = 2*sql.TableTruncateChunkSize + 1
   801  	const numKeys = 3 * numRows
   802  	const numTables = 5
   803  	var descs []*sqlbase.TableDescriptor
   804  	for i := 0; i < numTables; i++ {
   805  		tableName := fmt.Sprintf("test%d", i)
   806  		if err := tests.CreateKVTable(sqlDB, tableName, numRows); err != nil {
   807  			t.Fatal(err)
   808  		}
   809  
   810  		descs = append(descs, sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", tableName))
   811  
   812  		nameKey := sqlbase.NewPublicTableKey(keys.MinNonPredefinedUserDescID, tableName).Key(keys.SystemSQLCodec)
   813  		gr, err := kvDB.Get(ctx, nameKey)
   814  		if err != nil {
   815  			t.Fatal(err)
   816  		}
   817  		if !gr.Exists() {
   818  			t.Fatalf("Name entry %q does not exist", nameKey)
   819  		}
   820  
   821  		tableSpan := descs[i].TableSpan(keys.SystemSQLCodec)
   822  		tests.CheckKeyCount(t, kvDB, tableSpan, numKeys)
   823  
   824  		if _, err := sqlDB.Exec(fmt.Sprintf(`DROP TABLE t.%s`, tableName)); err != nil {
   825  			t.Fatal(err)
   826  		}
   827  	}
   828  
   829  	// TODO (lucy): Maybe this test API should use an offset starting
   830  	// from the most recent job instead.
   831  	const migrationJobOffset = 0
   832  
   833  	// Data hasn't been GC-ed.
   834  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
   835  	for i := 0; i < numTables; i++ {
   836  		if err := descExists(sqlDB, true, descs[i].ID); err != nil {
   837  			t.Fatal(err)
   838  		}
   839  		tableSpan := descs[i].TableSpan(keys.SystemSQLCodec)
   840  		tests.CheckKeyCount(t, kvDB, tableSpan, numKeys)
   841  
   842  		if err := jobutils.VerifySystemJob(t, sqlRun, 2*i+1+migrationJobOffset, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   843  			Username:    security.RootUser,
   844  			Description: fmt.Sprintf(`DROP TABLE t.public.%s`, descs[i].GetName()),
   845  			DescriptorIDs: sqlbase.IDs{
   846  				descs[i].ID,
   847  			},
   848  		}); err != nil {
   849  			t.Fatal(err)
   850  		}
   851  	}
   852  
   853  	// The closure pushes a zone config reducing the TTL to 0 for descriptor i.
   854  	pushZoneCfg := func(i int) {
   855  		if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, descs[i].ID); err != nil {
   856  			t.Fatal(err)
   857  		}
   858  	}
   859  
   860  	checkTableGCed := func(i int) {
   861  		testutils.SucceedsSoon(t, func() error {
   862  			if err := descExists(sqlDB, false, descs[i].ID); err != nil {
   863  				return err
   864  			}
   865  
   866  			return zoneExists(sqlDB, nil, descs[i].ID)
   867  		})
   868  		tableSpan := descs[i].TableSpan(keys.SystemSQLCodec)
   869  		tests.CheckKeyCount(t, kvDB, tableSpan, 0)
   870  
   871  		// Ensure that the job is marked as succeeded.
   872  		if err := jobutils.VerifySystemJob(t, sqlRun, 2*i+1+migrationJobOffset, jobspb.TypeSchemaChange, jobs.StatusSucceeded, jobs.Record{
   873  			Username:    security.RootUser,
   874  			Description: fmt.Sprintf(`DROP TABLE t.public.%s`, descs[i].GetName()),
   875  			DescriptorIDs: sqlbase.IDs{
   876  				descs[i].ID,
   877  			},
   878  		}); err != nil {
   879  			t.Fatal(err)
   880  		}
   881  
   882  		// Ensure that the job is marked as succeeded.
   883  		testutils.SucceedsSoon(t, func() error {
   884  			return jobutils.VerifySystemJob(t, sqlRun, i, jobspb.TypeSchemaChangeGC, jobs.StatusSucceeded, jobs.Record{
   885  				Username:    security.RootUser,
   886  				Description: fmt.Sprintf(`GC for DROP TABLE t.public.%s`, descs[i].GetName()),
   887  				DescriptorIDs: sqlbase.IDs{
   888  					descs[i].ID,
   889  				},
   890  			})
   891  		})
   892  	}
   893  
   894  	// Push a new zone config for a few tables with TTL=0 so the data
   895  	// is deleted immediately.
   896  	barrier := rand.Intn(numTables)
   897  	for i := 0; i < barrier; i++ {
   898  		pushZoneCfg(i)
   899  	}
   900  
   901  	// Check GC worked!
   902  	for i := 0; i < numTables; i++ {
   903  		if i < barrier {
   904  			checkTableGCed(i)
   905  		} else {
   906  			// Data still present for tables past barrier.
   907  			tableSpan := descs[i].TableSpan(keys.SystemSQLCodec)
   908  			tests.CheckKeyCount(t, kvDB, tableSpan, numKeys)
   909  		}
   910  	}
   911  
   912  	// Push the rest of the zone configs and check all the data gets GC-ed.
   913  	for i := barrier; i < numTables; i++ {
   914  		pushZoneCfg(i)
   915  	}
   916  	for i := barrier; i < numTables; i++ {
   917  		checkTableGCed(i)
   918  	}
   919  }
   920  
   921  func writeTableDesc(ctx context.Context, db *kv.DB, tableDesc *sqlbase.TableDescriptor) error {
   922  	return db.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
   923  		if err := txn.SetSystemConfigTrigger(); err != nil {
   924  			return err
   925  		}
   926  		tableDesc.ModificationTime = txn.CommitTimestamp()
   927  		return txn.Put(ctx, sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, tableDesc.ID), sqlbase.WrapDescriptor(tableDesc))
   928  	})
   929  }
   930  
   931  // TestDropTableWhileUpgradingFormat ensures that it's safe for a migration to
   932  // upgrade the table descriptor's format while the table is scheduled to be
   933  // dropped.
   934  //
   935  // The new format must be backwards-compatible with the old format, but that's
   936  // true in general.
   937  func TestDropTableWhileUpgradingFormat(t *testing.T) {
   938  	defer leaktest.AfterTest(t)()
   939  	ctx := context.Background()
   940  
   941  	defer gcjob.SetSmallMaxGCIntervalForTest()()
   942  
   943  	params, _ := tests.CreateTestServerParams()
   944  	params.Knobs = base.TestingKnobs{
   945  		SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{
   946  			DisableBackfillMigrations: true,
   947  		},
   948  	}
   949  
   950  	s, sqlDBRaw, kvDB := serverutils.StartServer(t, params)
   951  	defer s.Stopper().Stop(ctx)
   952  	sqlDB := sqlutils.MakeSQLRunner(sqlDBRaw)
   953  
   954  	// Disable strict GC TTL enforcement because we're going to shove a zero-value
   955  	// TTL into the system with AddImmediateGCZoneConfig.
   956  	defer sqltestutils.DisableGCTTLStrictEnforcement(t, sqlDBRaw)()
   957  
   958  	const numRows = 100
   959  	sqlutils.CreateTable(t, sqlDBRaw, "t", "a INT", numRows, sqlutils.ToRowFn(sqlutils.RowIdxFn))
   960  
   961  	// Give the table an old format version.
   962  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "test", "t")
   963  	tableDesc.FormatVersion = sqlbase.FamilyFormatVersion
   964  	tableDesc.Version++
   965  	if err := writeTableDesc(ctx, kvDB, tableDesc); err != nil {
   966  		t.Fatal(err)
   967  	}
   968  
   969  	tableSpan := tableDesc.TableSpan(keys.SystemSQLCodec)
   970  	tests.CheckKeyCount(t, kvDB, tableSpan, numRows)
   971  
   972  	sqlDB.Exec(t, `DROP TABLE test.t`)
   973  
   974  	// Simulate a migration upgrading the table descriptor's format version after
   975  	// the table has been dropped but before the truncation has occurred.
   976  	var err error
   977  	tableDesc, err = sqlbase.GetTableDescFromID(ctx, kvDB.NewTxn(ctx, ""), keys.SystemSQLCodec, tableDesc.ID)
   978  	if err != nil {
   979  		t.Fatal(err)
   980  	}
   981  	if !tableDesc.Dropped() {
   982  		t.Fatalf("expected descriptor to be in DROP state, but was in %s", tableDesc.State)
   983  	}
   984  	tableDesc.FormatVersion = sqlbase.InterleavedFormatVersion
   985  	tableDesc.Version++
   986  	if err := writeTableDesc(ctx, kvDB, tableDesc); err != nil {
   987  		t.Fatal(err)
   988  	}
   989  
   990  	// Set TTL so the data is deleted immediately.
   991  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDBRaw, tableDesc.ID); err != nil {
   992  		t.Fatal(err)
   993  	}
   994  
   995  	// Allow the schema change to proceed and verify that the data is eventually
   996  	// deleted, despite the interleaved modification to the table descriptor.
   997  	testutils.SucceedsSoon(t, func() error {
   998  		return descExists(sqlDBRaw, false, tableDesc.ID)
   999  	})
  1000  	tests.CheckKeyCount(t, kvDB, tableSpan, 0)
  1001  }
  1002  
  1003  // Tests dropping a table that is interleaved within
  1004  // another table.
  1005  func TestDropTableInterleavedDeleteData(t *testing.T) {
  1006  	defer leaktest.AfterTest(t)()
  1007  	params, _ := tests.CreateTestServerParams()
  1008  
  1009  	defer gcjob.SetSmallMaxGCIntervalForTest()()
  1010  
  1011  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
  1012  	defer s.Stopper().Stop(context.Background())
  1013  
  1014  	numRows := 2*sql.TableTruncateChunkSize + 1
  1015  	tests.CreateKVInterleavedTable(t, sqlDB, numRows)
  1016  
  1017  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
  1018  	tableDescInterleaved := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "intlv")
  1019  	tableSpan := tableDesc.TableSpan(keys.SystemSQLCodec)
  1020  
  1021  	tests.CheckKeyCount(t, kvDB, tableSpan, 3*numRows)
  1022  	if _, err := sqlDB.Exec(`DROP TABLE t.intlv`); err != nil {
  1023  		t.Fatal(err)
  1024  	}
  1025  
  1026  	// Test that deleted table cannot be used. This prevents regressions where
  1027  	// name -> descriptor ID caches might make this statement erronously work.
  1028  	if _, err := sqlDB.Exec(`SELECT * FROM t.intlv`); !testutils.IsError(
  1029  		err, `relation "t.intlv" does not exist`,
  1030  	) {
  1031  		t.Fatalf("different error than expected: %v", err)
  1032  	}
  1033  
  1034  	if _, err := sqltestutils.AddImmediateGCZoneConfig(sqlDB, tableDescInterleaved.ID); err != nil {
  1035  		t.Fatal(err)
  1036  	}
  1037  
  1038  	testutils.SucceedsSoon(t, func() error {
  1039  		return descExists(sqlDB, false, tableDescInterleaved.ID)
  1040  	})
  1041  
  1042  	tests.CheckKeyCount(t, kvDB, tableSpan, numRows)
  1043  }
  1044  
  1045  func TestDropTableInTxn(t *testing.T) {
  1046  	defer leaktest.AfterTest(t)()
  1047  	params, _ := tests.CreateTestServerParams()
  1048  	s, sqlDB, _ := serverutils.StartServer(t, params)
  1049  	defer s.Stopper().Stop(context.Background())
  1050  
  1051  	if _, err := sqlDB.Exec(`
  1052  CREATE DATABASE t;
  1053  CREATE TABLE t.kv (k CHAR PRIMARY KEY, v CHAR);
  1054  `); err != nil {
  1055  		t.Fatal(err)
  1056  	}
  1057  
  1058  	tx, err := sqlDB.Begin()
  1059  	if err != nil {
  1060  		t.Fatal(err)
  1061  	}
  1062  
  1063  	if _, err := tx.Exec(`DROP TABLE t.kv`); err != nil {
  1064  		t.Fatal(err)
  1065  	}
  1066  
  1067  	// We might still be able to read/write in the table inside this transaction
  1068  	// until the schema changer runs, but we shouldn't be able to ALTER it.
  1069  	if _, err := tx.Exec(`ALTER TABLE t.kv ADD COLUMN w CHAR`); !testutils.IsError(err,
  1070  		`relation "t.kv" does not exist`) {
  1071  		t.Fatalf("different error than expected: %v", err)
  1072  	}
  1073  
  1074  	// Can't commit after ALTER errored, so we ROLLBACK.
  1075  	if err := tx.Rollback(); err != nil {
  1076  		t.Fatal(err)
  1077  	}
  1078  
  1079  }
  1080  
  1081  // Tests DROP DATABASE after DROP TABLE just before the table name has been
  1082  // recycle.
  1083  func TestDropDatabaseAfterDropTable(t *testing.T) {
  1084  	defer leaktest.AfterTest(t)()
  1085  	// Disable schema change execution so that the dropped table name
  1086  	// doesn't get recycled.
  1087  	params, _ := tests.CreateTestServerParams()
  1088  	params.Knobs = base.TestingKnobs{
  1089  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{
  1090  			SchemaChangeJobNoOp: func() bool {
  1091  				return true
  1092  			},
  1093  		},
  1094  	}
  1095  	s, sqlDB, kvDB := serverutils.StartServer(t, params)
  1096  	defer s.Stopper().Stop(context.Background())
  1097  
  1098  	if err := tests.CreateKVTable(sqlDB, "kv", 100); err != nil {
  1099  		t.Fatal(err)
  1100  	}
  1101  
  1102  	tableDesc := sqlbase.GetTableDescriptor(kvDB, keys.SystemSQLCodec, "t", "kv")
  1103  
  1104  	if _, err := sqlDB.Exec(`DROP TABLE t.kv`); err != nil {
  1105  		t.Fatal(err)
  1106  	}
  1107  
  1108  	if _, err := sqlDB.Exec(`DROP DATABASE t`); err != nil {
  1109  		t.Fatal(err)
  1110  	}
  1111  
  1112  	// Job still running, waiting for draining names.
  1113  	// TODO (lucy): Maybe this test API should use an offset starting
  1114  	// from the most recent job instead.
  1115  	sqlRun := sqlutils.MakeSQLRunner(sqlDB)
  1116  	if err := jobutils.VerifySystemJob(
  1117  		t, sqlRun, 1, jobspb.TypeSchemaChange, jobs.StatusSucceeded,
  1118  		jobs.Record{
  1119  			Username:    security.RootUser,
  1120  			Description: "DROP TABLE t.public.kv",
  1121  			DescriptorIDs: sqlbase.IDs{
  1122  				tableDesc.ID,
  1123  			},
  1124  		}); err != nil {
  1125  		t.Fatal(err)
  1126  	}
  1127  }
  1128  
  1129  func TestDropAndCreateTable(t *testing.T) {
  1130  	defer leaktest.AfterTest(t)()
  1131  	params, _ := tests.CreateTestServerParams()
  1132  	params.UseDatabase = "test"
  1133  	s, db, _ := serverutils.StartServer(t, params)
  1134  	defer s.Stopper().Stop(context.Background())
  1135  
  1136  	if _, err := db.Exec(`CREATE DATABASE test`); err != nil {
  1137  		t.Fatal(err)
  1138  	}
  1139  
  1140  	for i := 0; i < 20; i++ {
  1141  		if _, err := db.Exec(`DROP TABLE IF EXISTS foo`); err != nil {
  1142  			t.Fatal(err)
  1143  		}
  1144  		if _, err := db.Exec(`CREATE TABLE foo (k INT PRIMARY KEY)`); err != nil {
  1145  			t.Fatal(err)
  1146  		}
  1147  		if _, err := db.Exec(`INSERT INTO foo VALUES (1), (2), (3)`); err != nil {
  1148  			t.Fatal(err)
  1149  		}
  1150  	}
  1151  }
  1152  
  1153  func TestDropAndCreateDatabase(t *testing.T) {
  1154  	defer leaktest.AfterTest(t)()
  1155  
  1156  	ctx := context.Background()
  1157  	s, db, _ := serverutils.StartServer(t, base.TestServerArgs{UseDatabase: `test`})
  1158  	defer s.Stopper().Stop(ctx)
  1159  	sqlDB := sqlutils.MakeSQLRunner(db)
  1160  
  1161  	for i := 0; i < 20; i++ {
  1162  		sqlDB.Exec(t, `DROP DATABASE IF EXISTS test`)
  1163  		sqlDB.Exec(t, `CREATE DATABASE test`)
  1164  		sqlDB.Exec(t, `CREATE TABLE foo (a INT PRIMARY KEY)`)
  1165  		sqlDB.Exec(t, `INSERT INTO foo VALUES (1), (2), (3)`)
  1166  	}
  1167  }
  1168  
  1169  // Test commands while a table is being dropped.
  1170  func TestCommandsWhileTableBeingDropped(t *testing.T) {
  1171  	defer leaktest.AfterTest(t)()
  1172  
  1173  	params, _ := tests.CreateTestServerParams()
  1174  	// Block schema changers so that the table we're about to DROP is not
  1175  	// actually dropped; it will be left in the "deleted" state.
  1176  	params.Knobs = base.TestingKnobs{
  1177  		SQLSchemaChanger: &sql.SchemaChangerTestingKnobs{
  1178  			SchemaChangeJobNoOp: func() bool {
  1179  				return true
  1180  			},
  1181  		},
  1182  	}
  1183  	s, db, _ := serverutils.StartServer(t, params)
  1184  	defer s.Stopper().Stop(context.Background())
  1185  
  1186  	sql := `
  1187  CREATE DATABASE test;
  1188  CREATE TABLE test.t(a INT PRIMARY KEY);
  1189  `
  1190  	if _, err := db.Exec(sql); err != nil {
  1191  		t.Fatal(err)
  1192  	}
  1193  
  1194  	// DROP the table
  1195  	if _, err := db.Exec(`DROP TABLE test.t`); err != nil {
  1196  		t.Fatal(err)
  1197  	}
  1198  
  1199  	// Check that SHOW TABLES marks a dropped table with the " (dropped)"
  1200  	// suffix.
  1201  	rows, err := db.Query(`SHOW TABLES FROM test`)
  1202  	if err != nil {
  1203  		t.Fatal(err)
  1204  	}
  1205  	defer rows.Close()
  1206  	if rows.Next() {
  1207  		t.Fatal("table should be invisible through SHOW TABLES")
  1208  	}
  1209  
  1210  	// Check that CREATE TABLE with the same name returns a proper error.
  1211  	if _, err := db.Exec(`CREATE TABLE test.t(a INT PRIMARY KEY)`); !testutils.IsError(err, `relation "t" already exists`) {
  1212  		t.Fatal(err)
  1213  	}
  1214  
  1215  	// Check that DROP TABLE with the same name returns a proper error.
  1216  	if _, err := db.Exec(`DROP TABLE test.t`); !testutils.IsError(err, `relation "test.t" does not exist`) {
  1217  		t.Fatal(err)
  1218  	}
  1219  }
  1220  
  1221  // Tests name reuse if a DROP VIEW|TABLE succeeds but fails
  1222  // before running the schema changer. Tests name GC via the
  1223  // asynchrous schema change path.
  1224  // TODO (lucy): This started as a test verifying that draining names still works
  1225  // in the async schema changer, which no longer exists. Should the test still
  1226  // exist?
  1227  func TestDropNameReuse(t *testing.T) {
  1228  	defer leaktest.AfterTest(t)()
  1229  
  1230  	params, _ := tests.CreateTestServerParams()
  1231  	params.Knobs = base.TestingKnobs{
  1232  		SQLMigrationManager: &sqlmigrations.MigrationManagerTestingKnobs{
  1233  			DisableBackfillMigrations: true,
  1234  		},
  1235  	}
  1236  
  1237  	s, db, _ := serverutils.StartServer(t, params)
  1238  	defer s.Stopper().Stop(context.Background())
  1239  
  1240  	sql := `
  1241  CREATE DATABASE test;
  1242  CREATE TABLE test.t(a INT PRIMARY KEY);
  1243  CREATE VIEW test.acol(a) AS SELECT a FROM test.t;
  1244  `
  1245  	if _, err := db.Exec(sql); err != nil {
  1246  		t.Fatal(err)
  1247  	}
  1248  
  1249  	// DROP the view.
  1250  	if _, err := db.Exec(`DROP VIEW test.acol`); err != nil {
  1251  		t.Fatal(err)
  1252  	}
  1253  
  1254  	testutils.SucceedsSoon(t, func() error {
  1255  		_, err := db.Exec(`CREATE TABLE test.acol(a INT PRIMARY KEY);`)
  1256  		return err
  1257  	})
  1258  
  1259  	// DROP the table.
  1260  	if _, err := db.Exec(`DROP TABLE test.t`); err != nil {
  1261  		t.Fatal(err)
  1262  	}
  1263  
  1264  	testutils.SucceedsSoon(t, func() error {
  1265  		_, err := db.Exec(`CREATE TABLE test.t(a INT PRIMARY KEY);`)
  1266  		return err
  1267  	})
  1268  }
  1269  
  1270  // TestDropIndexHandlesRetriableErrors is a regression test against #48474.
  1271  // The bug was that retriable errors, which are generally possible, were being
  1272  // treated as assertion failures.
  1273  func TestDropIndexHandlesRetriableErrors(t *testing.T) {
  1274  	defer leaktest.AfterTest(t)()
  1275  
  1276  	ctx := context.Background()
  1277  	rf := newDynamicRequestFilter()
  1278  	tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{
  1279  		ServerArgs: base.TestServerArgs{
  1280  			Knobs: base.TestingKnobs{
  1281  				Store: &kvserver.StoreTestingKnobs{
  1282  					TestingRequestFilter: rf.filter,
  1283  				},
  1284  			},
  1285  		},
  1286  	})
  1287  	defer tc.Stopper().Stop(ctx)
  1288  
  1289  	// What we want to do is have a transaction which does the planning work to
  1290  	// drop an index. Then we want to expose the execution of the DROP INDEX to
  1291  	// an error when retrieving the mutable table descriptor. We'll do this by
  1292  	// injecting a ReadWithinUncertainty error underneath the DROP INDEX
  1293  	// after planning has concluded.
  1294  
  1295  	tdb := sqlutils.MakeSQLRunner(tc.ServerConn(0))
  1296  	tdb.Exec(t, "CREATE TABLE foo (i INT PRIMARY KEY, j INT, INDEX j_idx (j))")
  1297  
  1298  	var tableID uint32
  1299  	tdb.QueryRow(t, `
  1300  SELECT
  1301      table_id
  1302  FROM
  1303      crdb_internal.tables
  1304  WHERE
  1305      name = $1 AND database_name = current_database();`,
  1306  		"foo").Scan(&tableID)
  1307  
  1308  	// Start the user transaction and enable tracing as we'll use the trace
  1309  	// to determine when planning has concluded.
  1310  	txn, err := tc.ServerConn(0).Begin()
  1311  	require.NoError(t, err)
  1312  	_, err = txn.Exec("SET TRACING = on")
  1313  	require.NoError(t, err)
  1314  	// Let's find out our transaction ID for our transaction by running a query.
  1315  	// We'll also use this query to install a refresh span over the table data.
  1316  	// Inject a request filter to snag the transaction ID.
  1317  	tablePrefix := keys.SystemSQLCodec.TablePrefix(tableID)
  1318  	tableSpan := roachpb.Span{
  1319  		Key:    tablePrefix,
  1320  		EndKey: tablePrefix.PrefixEnd(),
  1321  	}
  1322  	var filterState struct {
  1323  		syncutil.Mutex
  1324  		txnID uuid.UUID
  1325  	}
  1326  	getTxnID := func() uuid.UUID {
  1327  		filterState.Lock()
  1328  		defer filterState.Unlock()
  1329  		return filterState.txnID
  1330  	}
  1331  	rf.setFilter(func(ctx context.Context, request roachpb.BatchRequest) *roachpb.Error {
  1332  		if request.Txn == nil || request.Txn.Name != sql.SQLTxnName {
  1333  			return nil
  1334  		}
  1335  		filterState.Lock()
  1336  		defer filterState.Unlock()
  1337  		if filterState.txnID != (uuid.UUID{}) {
  1338  			return nil
  1339  		}
  1340  		if scanRequest, ok := request.GetArg(roachpb.Scan); ok {
  1341  			scan := scanRequest.(*roachpb.ScanRequest)
  1342  			if scan.Span().Overlaps(tableSpan) {
  1343  				filterState.txnID = request.Txn.ID
  1344  			}
  1345  		}
  1346  		return nil
  1347  	})
  1348  
  1349  	// Run the scan of the table to activate the filter as well as add the
  1350  	// refresh span over the table data.
  1351  	var trash int
  1352  	require.Equal(t, gosql.ErrNoRows,
  1353  		txn.QueryRow("SELECT * FROM foo").Scan(&trash))
  1354  	rf.setFilter(nil)
  1355  	require.NotEqual(t, uuid.UUID{}, getTxnID())
  1356  
  1357  	// Perform a write after the above read so that a refresh will fail and
  1358  	// observe its timestamp.
  1359  	tdb.Exec(t, "INSERT INTO foo VALUES (1)")
  1360  	var afterInsertStr string
  1361  	tdb.QueryRow(t, "SELECT cluster_logical_timestamp()").Scan(&afterInsertStr)
  1362  	afterInsert, err := sql.ParseHLC(afterInsertStr)
  1363  	require.NoError(t, err)
  1364  
  1365  	// Now set up a filter to detect when the DROP INDEX execution will begin
  1366  	// and inject an error forcing a refresh above the conflicting write which
  1367  	// will fail. We'll want to ensure that we get a retriable error.
  1368  	// Use the below pattern to detect when the user transaction has finished
  1369  	// planning and is now executing.
  1370  	dropIndexPlanningEndsRE := regexp.MustCompile("(?s)planning starts: DROP INDEX.*planning ends")
  1371  	rf.setFilter(func(ctx context.Context, request roachpb.BatchRequest) *roachpb.Error {
  1372  		if request.Txn == nil {
  1373  			return nil
  1374  		}
  1375  		filterState.Lock()
  1376  		defer filterState.Unlock()
  1377  		if filterState.txnID != request.Txn.ID {
  1378  			return nil
  1379  		}
  1380  		sp := opentracing.SpanFromContext(ctx)
  1381  		rec := tracing.GetRecording(sp)
  1382  		if !dropIndexPlanningEndsRE.MatchString(rec.String()) {
  1383  			return nil
  1384  		}
  1385  		if getRequest, ok := request.GetArg(roachpb.Get); ok {
  1386  			put := getRequest.(*roachpb.GetRequest)
  1387  			if put.Key.Equal(sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, sqlbase.ID(tableID))) {
  1388  				filterState.txnID = uuid.UUID{}
  1389  				return roachpb.NewError(roachpb.NewReadWithinUncertaintyIntervalError(
  1390  					request.Txn.ReadTimestamp, afterInsert, request.Txn))
  1391  			}
  1392  		}
  1393  		return nil
  1394  	})
  1395  
  1396  	_, err = txn.Exec("DROP INDEX foo@j_idx")
  1397  	require.Truef(t, isRetryableErr(err), "drop index error: %v", err)
  1398  	require.NoError(t, txn.Rollback())
  1399  }