github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/zone_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 sql_test
    12  
    13  import (
    14  	"context"
    15  	"fmt"
    16  	"testing"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    19  	"github.com/cockroachdb/cockroach/pkg/keys"
    20  	"github.com/cockroachdb/cockroach/pkg/server"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/lex"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/tests"
    23  	"github.com/cockroachdb/cockroach/pkg/testutils"
    24  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    25  	"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
    26  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    27  	"github.com/gogo/protobuf/proto"
    28  )
    29  
    30  func TestValidSetShowZones(t *testing.T) {
    31  	defer leaktest.AfterTest(t)()
    32  
    33  	params, _ := tests.CreateTestServerParams()
    34  	s, db, _ := serverutils.StartServer(t, params)
    35  	defer s.Stopper().Stop(context.Background())
    36  
    37  	sqlDB := sqlutils.MakeSQLRunner(db)
    38  	sqlDB.Exec(t, `CREATE DATABASE d; USE d; CREATE TABLE t ();`)
    39  
    40  	yamlDefault := fmt.Sprintf("gc: {ttlseconds: %d}", s.(*server.TestServer).Cfg.DefaultZoneConfig.GC.TTLSeconds)
    41  	yamlOverride := "gc: {ttlseconds: 42}"
    42  	zoneOverride := s.(*server.TestServer).Cfg.DefaultZoneConfig
    43  	zoneOverride.GC = &zonepb.GCPolicy{TTLSeconds: 42}
    44  	partialZoneOverride := *zonepb.NewZoneConfig()
    45  	partialZoneOverride.GC = &zonepb.GCPolicy{TTLSeconds: 42}
    46  
    47  	defaultRow := sqlutils.ZoneRow{
    48  		ID:     keys.RootNamespaceID,
    49  		Config: s.(*server.TestServer).Cfg.DefaultZoneConfig,
    50  	}
    51  	defaultOverrideRow := sqlutils.ZoneRow{
    52  		ID:     keys.RootNamespaceID,
    53  		Config: zoneOverride,
    54  	}
    55  	metaRow := sqlutils.ZoneRow{
    56  		ID:     keys.MetaRangesID,
    57  		Config: zoneOverride,
    58  	}
    59  	systemRow := sqlutils.ZoneRow{
    60  		ID:     keys.SystemDatabaseID,
    61  		Config: zoneOverride,
    62  	}
    63  	jobsRow := sqlutils.ZoneRow{
    64  		ID:     keys.JobsTableID,
    65  		Config: zoneOverride,
    66  	}
    67  
    68  	dbID := sqlutils.QueryDatabaseID(t, db, "d")
    69  	tableID := sqlutils.QueryTableID(t, db, "d", "public", "t")
    70  
    71  	dbRow := sqlutils.ZoneRow{
    72  		ID:     dbID,
    73  		Config: zoneOverride,
    74  	}
    75  	tableRow := sqlutils.ZoneRow{
    76  		ID:     tableID,
    77  		Config: zoneOverride,
    78  	}
    79  
    80  	// Partially filled config rows
    81  	partialMetaRow := sqlutils.ZoneRow{
    82  		ID:     keys.MetaRangesID,
    83  		Config: partialZoneOverride,
    84  	}
    85  	partialSystemRow := sqlutils.ZoneRow{
    86  		ID:     keys.SystemDatabaseID,
    87  		Config: partialZoneOverride,
    88  	}
    89  	partialJobsRow := sqlutils.ZoneRow{
    90  		ID:     keys.JobsTableID,
    91  		Config: partialZoneOverride,
    92  	}
    93  	partialDbRow := sqlutils.ZoneRow{
    94  		ID:     dbID,
    95  		Config: partialZoneOverride,
    96  	}
    97  	partialTableRow := sqlutils.ZoneRow{
    98  		ID:     tableID,
    99  		Config: partialZoneOverride,
   100  	}
   101  
   102  	// Remove stock zone configs installed at cluster bootstrap. Otherwise this
   103  	// test breaks whenever these stock zone configs are adjusted.
   104  	sqlutils.RemoveAllZoneConfigs(t, sqlDB)
   105  
   106  	// Ensure the default is reported for all zones at first.
   107  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow)
   108  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE default", defaultRow)
   109  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", defaultRow)
   110  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultRow)
   111  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultRow)
   112  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", defaultRow)
   113  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", defaultRow)
   114  
   115  	// Ensure a database zone config applies to that database and its tables, and
   116  	// no other zones.
   117  	sqlutils.SetZoneConfig(t, sqlDB, "DATABASE d", yamlOverride)
   118  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow, partialDbRow)
   119  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", defaultRow)
   120  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultRow)
   121  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultRow)
   122  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", dbRow)
   123  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", dbRow)
   124  
   125  	// Ensure a table zone config applies to that table and no others.
   126  	sqlutils.SetZoneConfig(t, sqlDB, "TABLE d.t", yamlOverride)
   127  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow, partialDbRow, partialTableRow)
   128  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", defaultRow)
   129  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultRow)
   130  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultRow)
   131  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", dbRow)
   132  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", tableRow)
   133  
   134  	// Ensure a named zone config applies to that named zone and no others.
   135  	sqlutils.SetZoneConfig(t, sqlDB, "RANGE meta", yamlOverride)
   136  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow, partialMetaRow, partialDbRow, partialTableRow)
   137  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", metaRow)
   138  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultRow)
   139  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultRow)
   140  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", dbRow)
   141  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", tableRow)
   142  
   143  	// Ensure updating the default zone propagates to zones without an override,
   144  	// but not to those with overrides.
   145  	sqlutils.SetZoneConfig(t, sqlDB, "RANGE default", yamlOverride)
   146  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultOverrideRow, partialMetaRow, partialDbRow, partialTableRow)
   147  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", metaRow)
   148  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultOverrideRow)
   149  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultOverrideRow)
   150  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", dbRow)
   151  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", tableRow)
   152  
   153  	// Ensure deleting a database deletes only the database zone, and not the
   154  	// table zone.
   155  	sqlutils.DeleteZoneConfig(t, sqlDB, "DATABASE d")
   156  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultOverrideRow, partialMetaRow, partialTableRow)
   157  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", defaultOverrideRow)
   158  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", tableRow)
   159  
   160  	// Ensure deleting a table zone works.
   161  	sqlutils.DeleteZoneConfig(t, sqlDB, "TABLE d.t")
   162  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultOverrideRow, partialMetaRow)
   163  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", defaultOverrideRow)
   164  
   165  	// Ensure deleting a named zone works.
   166  	sqlutils.DeleteZoneConfig(t, sqlDB, "RANGE meta")
   167  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultOverrideRow)
   168  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", defaultOverrideRow)
   169  
   170  	// Ensure deleting non-overridden zones is not an error.
   171  	sqlutils.DeleteZoneConfig(t, sqlDB, "RANGE meta")
   172  	sqlutils.DeleteZoneConfig(t, sqlDB, "DATABASE d")
   173  	sqlutils.DeleteZoneConfig(t, sqlDB, "TABLE d.t")
   174  
   175  	// Ensure updating the default zone config applies to zones that have had
   176  	// overrides added and removed.
   177  	sqlutils.SetZoneConfig(t, sqlDB, "RANGE default", yamlDefault)
   178  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow)
   179  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE default", defaultRow)
   180  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "RANGE meta", defaultRow)
   181  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", defaultRow)
   182  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.lease", defaultRow)
   183  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", defaultRow)
   184  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", defaultRow)
   185  
   186  	// Ensure the system database zone can be configured, even though zones on
   187  	// config tables are disallowed.
   188  	sqlutils.SetZoneConfig(t, sqlDB, "DATABASE system", yamlOverride)
   189  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow, partialSystemRow)
   190  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE system", systemRow)
   191  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.namespace", systemRow)
   192  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.jobs", systemRow)
   193  
   194  	// Ensure zones for non-config tables in the system database can be
   195  	// configured.
   196  	sqlutils.SetZoneConfig(t, sqlDB, "TABLE system.jobs", yamlOverride)
   197  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultRow, partialSystemRow, partialJobsRow)
   198  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE system.jobs", jobsRow)
   199  
   200  	// Verify that the session database is respected.
   201  	sqlutils.SetZoneConfig(t, sqlDB, "TABLE t", yamlOverride)
   202  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE t", tableRow)
   203  	sqlutils.DeleteZoneConfig(t, sqlDB, "TABLE t")
   204  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE t", defaultRow)
   205  
   206  	// Verify we can use composite values.
   207  	sqlDB.Exec(t, fmt.Sprintf("ALTER TABLE t CONFIGURE ZONE = '' || %s || ''",
   208  		lex.EscapeSQLString(yamlOverride)))
   209  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE t", tableRow)
   210  
   211  	// Ensure zone configs are read transactionally instead of from the cached
   212  	// system config.
   213  	txn, err := db.Begin()
   214  	if err != nil {
   215  		t.Fatal(err)
   216  	}
   217  	sqlutils.TxnSetZoneConfig(t, sqlDB, txn, "RANGE default", yamlOverride)
   218  	sqlutils.TxnSetZoneConfig(t, sqlDB, txn, "TABLE d.t", "") // this should pick up the overridden default config
   219  	if err := txn.Commit(); err != nil {
   220  		t.Fatal(err)
   221  	}
   222  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE d.t", tableRow)
   223  
   224  	sqlDB.Exec(t, "DROP TABLE d.t")
   225  	_, err = db.Exec("SHOW ZONE CONFIGURATION FOR TABLE d.t")
   226  	if !testutils.IsError(err, `relation "d.t" does not exist`) {
   227  		t.Errorf("expected SHOW ZONE CONFIGURATION to fail on dropped table, but got %q", err)
   228  	}
   229  	sqlutils.VerifyAllZoneConfigs(t, sqlDB, defaultOverrideRow, partialSystemRow, partialJobsRow)
   230  }
   231  
   232  func TestZoneInheritField(t *testing.T) {
   233  	defer leaktest.AfterTest(t)()
   234  
   235  	params, _ := tests.CreateTestServerParams()
   236  	s, db, _ := serverutils.StartServer(t, params)
   237  	defer s.Stopper().Stop(context.Background())
   238  
   239  	sqlDB := sqlutils.MakeSQLRunner(db)
   240  	sqlutils.RemoveAllZoneConfigs(t, sqlDB)
   241  	sqlDB.Exec(t, `CREATE DATABASE d; USE d; CREATE TABLE t ();`)
   242  
   243  	defaultRow := sqlutils.ZoneRow{
   244  		ID:     keys.RootNamespaceID,
   245  		Config: s.(*server.TestServer).Cfg.DefaultZoneConfig,
   246  	}
   247  
   248  	newReplicationFactor := 10
   249  	tableID := sqlutils.QueryTableID(t, db, "d", "public", "t")
   250  	newDefCfg := s.(*server.TestServer).Cfg.DefaultZoneConfig
   251  	newDefCfg.NumReplicas = proto.Int32(int32(newReplicationFactor))
   252  
   253  	newDefaultRow := sqlutils.ZoneRow{
   254  		ID:     keys.RootNamespaceID,
   255  		Config: newDefCfg,
   256  	}
   257  
   258  	newTableRow := sqlutils.ZoneRow{
   259  		ID:     tableID,
   260  		Config: s.(*server.TestServer).Cfg.DefaultZoneConfig,
   261  	}
   262  
   263  	// Doesn't have any values of its own.
   264  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE t", defaultRow)
   265  
   266  	// Solidify the num replicas value.
   267  	sqlDB.Exec(t, `ALTER TABLE t CONFIGURE ZONE USING num_replicas = COPY FROM PARENT`)
   268  
   269  	// Change the default replication factor.
   270  	sqlDB.Exec(t, fmt.Sprintf("ALTER RANGE default CONFIGURE ZONE USING num_replicas = %d",
   271  		newReplicationFactor))
   272  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "DATABASE d", newDefaultRow)
   273  
   274  	// Verify the table didn't take on the new value for the replication factor.
   275  	sqlutils.VerifyZoneConfigForTarget(t, sqlDB, "TABLE t", newTableRow)
   276  }
   277  
   278  func TestInvalidSetShowZones(t *testing.T) {
   279  	defer leaktest.AfterTest(t)()
   280  
   281  	params, _ := tests.CreateTestServerParams()
   282  	s, db, _ := serverutils.StartServer(t, params)
   283  	defer s.Stopper().Stop(context.Background())
   284  
   285  	for i, tc := range []struct {
   286  		query string
   287  		err   string
   288  	}{
   289  		{
   290  			"ALTER RANGE default CONFIGURE ZONE DISCARD",
   291  			"cannot remove default zone",
   292  		},
   293  		{
   294  			"ALTER RANGE default CONFIGURE ZONE = '&!@*@&'",
   295  			"could not parse zone config",
   296  		},
   297  		{
   298  			"ALTER TABLE system.namespace CONFIGURE ZONE USING DEFAULT",
   299  			"cannot set zone configs for system config tables",
   300  		},
   301  		{
   302  			"ALTER RANGE foo CONFIGURE ZONE USING DEFAULT",
   303  			`"foo" is not a built-in zone`,
   304  		},
   305  		{
   306  			"ALTER DATABASE foo CONFIGURE ZONE USING DEFAULT",
   307  			`database "foo" does not exist`,
   308  		},
   309  		{
   310  			"ALTER TABLE system.foo CONFIGURE ZONE USING DEFAULT",
   311  			`relation "system.foo" does not exist`,
   312  		},
   313  		{
   314  			"ALTER TABLE foo CONFIGURE ZONE USING DEFAULT",
   315  			`relation "foo" does not exist`,
   316  		},
   317  		{
   318  			"SHOW ZONE CONFIGURATION FOR RANGE foo",
   319  			`"foo" is not a built-in zone`,
   320  		},
   321  		{
   322  			"SHOW ZONE CONFIGURATION FOR DATABASE foo",
   323  			`database "foo" does not exist`,
   324  		},
   325  		{
   326  			"SHOW ZONE CONFIGURATION FOR TABLE foo",
   327  			`relation "foo" does not exist`,
   328  		},
   329  		{
   330  			"SHOW ZONE CONFIGURATION FOR TABLE system.foo",
   331  			`relation "system.foo" does not exist`,
   332  		},
   333  	} {
   334  		if _, err := db.Exec(tc.query); !testutils.IsError(err, tc.err) {
   335  			t.Errorf("#%d: expected error matching %q, but got %v", i, tc.err, err)
   336  		}
   337  	}
   338  }