From 89091fea10ee032bd635a10e981561448f02a219 Mon Sep 17 00:00:00 2001 From: Adam Storm Date: Wed, 23 Feb 2022 09:53:53 -0500 Subject: [PATCH] settings: Add syntax for cluster settings Before this commit, there was no syntax to SET or SHOW cluster settings which exist for a given tenant. This commit adds the following syntax: * ALTER TENANT SET CLUSTER SETTING = * ALTER TENANT ALL SET CLUSTER SETTING = * ALTER TENANT RESET CLUSTER SETTING * ALTER TENANT ALL RESET CLUSTER SETTING * SHOW CLUSTER SETTING FOR TENANT * SHOW [ALL] CLUSTER SETTINGS FOR TENANT Note that the syntax is added but the underlying commands are currently unimplemented. The implementation of these commands will come with a subsequent commit. Release note (sql change): Added syntax for modifying cluster settings at the tenant level. Release justification: Completion of feature for 22.1. --- docs/generated/sql/bnf/BUILD.bazel | 1 + docs/generated/sql/bnf/alter_stmt.bnf | 1 + .../sql/bnf/alter_tenant_csetting_stmt.bnf | 5 + .../sql/bnf/show_cluster_setting.bnf | 4 + docs/generated/sql/bnf/stmt_block.bnf | 49 ++-- pkg/gen/docs.bzl | 1 + pkg/sql/BUILD.bazel | 1 + pkg/sql/alter_tenant.go | 90 +++++++ pkg/sql/delegate/show_all_cluster_settings.go | 5 + .../testdata/logic_test/cluster_settings | 53 ++++ pkg/sql/opaque.go | 3 + pkg/sql/parser/help_test.go | 9 + pkg/sql/parser/sql.y | 92 ++++++- pkg/sql/parser/testdata/alter_tenant | 31 +++ pkg/sql/parser/testdata/show | 48 ++++ pkg/sql/randgen/mutator.go | 2 +- pkg/sql/sem/tree/BUILD.bazel | 1 + pkg/sql/sem/tree/alter_tenant.go | 53 ++++ pkg/sql/sem/tree/set.go | 9 +- pkg/sql/sem/tree/show.go | 15 +- pkg/sql/sem/tree/stmt.go | 10 + pkg/sql/sem/tree/walk.go | 20 ++ pkg/sql/set_cluster_setting.go | 28 +- pkg/sql/show_cluster_setting.go | 5 + pkg/sql/walk.go | 244 +++++++++--------- 25 files changed, 622 insertions(+), 158 deletions(-) create mode 100644 docs/generated/sql/bnf/alter_tenant_csetting_stmt.bnf create mode 100644 pkg/sql/alter_tenant.go create mode 100644 pkg/sql/parser/testdata/alter_tenant create mode 100644 pkg/sql/sem/tree/alter_tenant.go diff --git a/docs/generated/sql/bnf/BUILD.bazel b/docs/generated/sql/bnf/BUILD.bazel index 706e8a799fc0..f4594adb359f 100644 --- a/docs/generated/sql/bnf/BUILD.bazel +++ b/docs/generated/sql/bnf/BUILD.bazel @@ -38,6 +38,7 @@ FILES = [ "alter_table_partition_by", "alter_table_set_schema_stmt", "alter_table_stmt", + "alter_tenant_csetting_stmt", "alter_type", "alter_view", "alter_view_owner_stmt", diff --git a/docs/generated/sql/bnf/alter_stmt.bnf b/docs/generated/sql/bnf/alter_stmt.bnf index 50297fc69343..c41f5092df99 100644 --- a/docs/generated/sql/bnf/alter_stmt.bnf +++ b/docs/generated/sql/bnf/alter_stmt.bnf @@ -1,3 +1,4 @@ alter_stmt ::= alter_ddl_stmt | alter_role_stmt + | alter_tenant_csetting_stmt diff --git a/docs/generated/sql/bnf/alter_tenant_csetting_stmt.bnf b/docs/generated/sql/bnf/alter_tenant_csetting_stmt.bnf new file mode 100644 index 000000000000..e605b3613be1 --- /dev/null +++ b/docs/generated/sql/bnf/alter_tenant_csetting_stmt.bnf @@ -0,0 +1,5 @@ +alter_tenant_csetting_stmt ::= + 'ALTER' 'TENANT' iconst64 'SET' 'CLUSTER' 'SETTING' var_name to_or_eq var_value + | 'ALTER' 'TENANT' 'ALL' 'SET' 'CLUSTER' 'SETTING' var_name to_or_eq var_value + | 'ALTER' 'TENANT' iconst64 'RESET' 'CLUSTER' 'SETTING' var_name + | 'ALTER' 'TENANT' 'ALL' 'RESET' 'CLUSTER' 'SETTING' var_name diff --git a/docs/generated/sql/bnf/show_cluster_setting.bnf b/docs/generated/sql/bnf/show_cluster_setting.bnf index 1faef0311955..5ff43300647c 100644 --- a/docs/generated/sql/bnf/show_cluster_setting.bnf +++ b/docs/generated/sql/bnf/show_cluster_setting.bnf @@ -4,3 +4,7 @@ show_csettings_stmt ::= | 'SHOW' 'ALL' 'CLUSTER' 'SETTINGS' | 'SHOW' 'CLUSTER' 'SETTINGS' | 'SHOW' 'PUBLIC' 'CLUSTER' 'SETTINGS' + | 'SHOW' 'CLUSTER' 'SETTING' var_name 'FOR' 'TENANT' iconst64 + | 'SHOW' 'ALL' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 + | 'SHOW' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 + | 'SHOW' 'PUBLIC' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index 2141dc8aa5ea..f44d865a9a25 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -135,6 +135,7 @@ fetch_cursor_stmt ::= alter_stmt ::= alter_ddl_stmt | alter_role_stmt + | alter_tenant_csetting_stmt backup_stmt ::= 'BACKUP' opt_backup_targets 'INTO' sconst_or_placeholder 'IN' string_or_placeholder_opt_list opt_as_of_clause opt_with_backup_options @@ -456,6 +457,12 @@ alter_role_stmt ::= | 'ALTER' 'ROLE_ALL' 'ALL' opt_in_database set_or_reset_clause | 'ALTER' 'USER_ALL' 'ALL' opt_in_database set_or_reset_clause +alter_tenant_csetting_stmt ::= + 'ALTER' 'TENANT' iconst64 'SET' 'CLUSTER' 'SETTING' var_name to_or_eq var_value + | 'ALTER' 'TENANT' 'ALL' 'SET' 'CLUSTER' 'SETTING' var_name to_or_eq var_value + | 'ALTER' 'TENANT' iconst64 'RESET' 'CLUSTER' 'SETTING' var_name + | 'ALTER' 'TENANT' 'ALL' 'RESET' 'CLUSTER' 'SETTING' var_name + opt_backup_targets ::= targets @@ -715,6 +722,10 @@ show_csettings_stmt ::= | 'SHOW' 'ALL' 'CLUSTER' 'SETTINGS' | 'SHOW' 'CLUSTER' 'SETTINGS' | 'SHOW' 'PUBLIC' 'CLUSTER' 'SETTINGS' + | 'SHOW' 'CLUSTER' 'SETTING' var_name 'FOR' 'TENANT' iconst64 + | 'SHOW' 'ALL' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 + | 'SHOW' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 + | 'SHOW' 'PUBLIC' 'CLUSTER' 'SETTINGS' 'FOR' 'TENANT' iconst64 show_databases_stmt ::= 'SHOW' 'DATABASES' with_comment @@ -1501,6 +1512,18 @@ set_or_reset_clause ::= | 'RESET_ALL' 'ALL' | 'RESET' session_var +var_name ::= + name + | name attrs + +to_or_eq ::= + '=' + | 'TO' + +var_value ::= + a_expr + | extra_var_value + as_of_clause ::= 'AS' 'OF' 'SYSTEM' 'TIME' a_expr @@ -1671,10 +1694,6 @@ session_var ::= | 'LC_CTYPE' | 'TIME' 'ZONE' -var_name ::= - name - | name attrs - restore_options_list ::= ( restore_options ) ( ( ',' restore_options ) )* @@ -1716,14 +1735,6 @@ set_rest_more ::= set_rest ::= generic_set -to_or_eq ::= - '=' - | 'TO' - -var_value ::= - a_expr - | extra_var_value - with_comment ::= 'WITH' 'COMMENT' | @@ -1991,6 +2002,13 @@ alter_backup_cmds ::= role_options ::= ( role_option ) ( ( role_option ) )* +attrs ::= + ( '.' unrestricted_name ) ( ( '.' unrestricted_name ) )* + +extra_var_value ::= + 'ON' + | cockroachdb_extra_reserved_keyword + backup_options ::= 'ENCRYPTION_PASSPHRASE' '=' string_or_placeholder | 'REVISION_HISTORY' @@ -2225,9 +2243,6 @@ column_name ::= session_var_parts ::= ( '.' 'identifier' ) ( ( '.' 'identifier' ) )* -attrs ::= - ( '.' unrestricted_name ) ( ( '.' unrestricted_name ) )* - restore_options ::= 'ENCRYPTION_PASSPHRASE' '=' string_or_placeholder | 'KMS' '=' string_or_placeholder_opt_list @@ -2272,10 +2287,6 @@ offset_clause ::= generic_set ::= var_name to_or_eq var_list -extra_var_value ::= - 'ON' - | cockroachdb_extra_reserved_keyword - targets_roles ::= 'ROLE' role_spec_list | 'SCHEMA' schema_name_list diff --git a/pkg/gen/docs.bzl b/pkg/gen/docs.bzl index 7af9c489b395..7a9d5b858340 100644 --- a/pkg/gen/docs.bzl +++ b/pkg/gen/docs.bzl @@ -50,6 +50,7 @@ DOCS_SRCS = [ "//docs/generated/sql/bnf:alter_table_partition_by.bnf", "//docs/generated/sql/bnf:alter_table_set_schema_stmt.bnf", "//docs/generated/sql/bnf:alter_table_stmt.bnf", + "//docs/generated/sql/bnf:alter_tenant_csetting_stmt.bnf", "//docs/generated/sql/bnf:alter_type.bnf", "//docs/generated/sql/bnf:alter_view.bnf", "//docs/generated/sql/bnf:alter_view_owner_stmt.bnf", diff --git a/pkg/sql/BUILD.bazel b/pkg/sql/BUILD.bazel index 03d19ae024b5..76d8272c53be 100644 --- a/pkg/sql/BUILD.bazel +++ b/pkg/sql/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "alter_table_locality.go", "alter_table_owner.go", "alter_table_set_schema.go", + "alter_tenant.go", "alter_type.go", "analyze_expr.go", "apply_join.go", diff --git a/pkg/sql/alter_tenant.go b/pkg/sql/alter_tenant.go new file mode 100644 index 000000000000..57d0f85fa7a5 --- /dev/null +++ b/pkg/sql/alter_tenant.go @@ -0,0 +1,90 @@ +// Copyright 2022 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package sql + +import ( + "context" + "strings" + + "github.com/cockroachdb/cockroach/pkg/roachpb" + "github.com/cockroachdb/cockroach/pkg/settings" + "github.com/cockroachdb/cockroach/pkg/settings/cluster" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" + "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" + "github.com/cockroachdb/errors" +) + +// alterTenantSetClusterSettingNode represents an +// ALTER TENANT ... SET CLUSTER SETTING statement. +type alterTenantSetClusterSettingNode struct { + name string + tenantID roachpb.TenantID + tenantAll bool + st *cluster.Settings + setting settings.NonMaskedSetting + // If value is nil, the setting should be reset. + value tree.TypedExpr +} + +// AlterTenantSetClusterSetting sets tenant level session variables. +// Privileges: super user. +func (p *planner) AlterTenantSetClusterSetting( + ctx context.Context, n *tree.AlterTenantSetClusterSetting, +) (planNode, error) { + name := strings.ToLower(n.Name) + st := p.EvalContext().Settings + v, ok := settings.Lookup(name, settings.LookupForLocalAccess, p.ExecCfg().Codec.ForSystemTenant()) + if !ok { + return nil, errors.Errorf("unknown cluster setting '%s'", name) + } + + if err := checkPrivilegesForSetting(ctx, p, name, "set"); err != nil { + return nil, err + } + + setting, ok := v.(settings.NonMaskedSetting) + if !ok { + return nil, errors.AssertionFailedf("expected writable setting, got %T", v) + } + + // Error out if we're trying to call this from a non-system tenant or if + // we're trying to set a system-only variable. + if !p.execCfg.Codec.ForSystemTenant() { + return nil, pgerror.Newf(pgcode.InsufficientPrivilege, + "ALTER TENANT can only be called by system operators") + } + if setting.Class() == settings.SystemOnly { + return nil, pgerror.Newf(pgcode.InsufficientPrivilege, + "%s is a system-only setting and must be set at the host cluster level using SET CLUSTER SETTING", name) + } + + value, err := p.getAndValidateTypedClusterSetting(ctx, name, n.Value, setting) + if err != nil { + return nil, err + } + + node := alterTenantSetClusterSettingNode{ + name: name, tenantID: n.TenantID, tenantAll: n.TenantAll, st: st, + setting: setting, value: value, + } + return &node, nil +} + +func (n *alterTenantSetClusterSettingNode) startExec(params runParams) error { + return unimplemented.NewWithIssue(73857, + `unimplemented: tenant-level cluster settings not supported`) +} + +func (n *alterTenantSetClusterSettingNode) Next(_ runParams) (bool, error) { return false, nil } +func (n *alterTenantSetClusterSettingNode) Values() tree.Datums { return nil } +func (n *alterTenantSetClusterSettingNode) Close(_ context.Context) {} diff --git a/pkg/sql/delegate/show_all_cluster_settings.go b/pkg/sql/delegate/show_all_cluster_settings.go index 4f31c36105fb..d1115dcd15ba 100644 --- a/pkg/sql/delegate/show_all_cluster_settings.go +++ b/pkg/sql/delegate/show_all_cluster_settings.go @@ -15,6 +15,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/roleoption" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" ) func (d *delegator) delegateShowClusterSettingList( @@ -24,6 +25,10 @@ func (d *delegator) delegateShowClusterSettingList( if err != nil { return nil, err } + if stmt.TenantID.IsSet() { + return nil, unimplemented.NewWithIssue(73857, + `unimplemented: tenant-level cluster settings not supported`) + } hasModify, err := d.catalog.HasRoleOption(d.ctx, roleoption.MODIFYCLUSTERSETTING) if err != nil { return nil, err diff --git a/pkg/sql/logictest/testdata/logic_test/cluster_settings b/pkg/sql/logictest/testdata/logic_test/cluster_settings index 4ebdabe7ba28..fe1a731a9e81 100644 --- a/pkg/sql/logictest/testdata/logic_test/cluster_settings +++ b/pkg/sql/logictest/testdata/logic_test/cluster_settings @@ -22,6 +22,9 @@ SET CLUSTER SETTING sql.conn.max_read_buffer_message_size = '1b' statement ok SET CLUSTER SETTING sql.conn.max_read_buffer_message_size = '64MB' +statement ok +RESET CLUSTER SETTING sql.conn.max_read_buffer_message_size + # Test permissions for modifying cluster settings. user testuser @@ -162,3 +165,53 @@ SET CLUSTER SETTING kv.snapshot_rebalance.max_rate = '10Mib' onlyif config 3node-tenant statement error unknown setting SHOW CLUSTER SETTING kv.snapshot_rebalance.max_rate + +# Test a cluster setting which is SystemOnly +subtest tenant-cluster-settings + +# Skip this test when inside a tenant, as this setting won't be visible in +# there. +skipif config 3node-tenant +statement error admission.kv.enabled is a system-only setting and must be set at the host cluster level using SET CLUSTER SETTING +ALTER TENANT 10 SET CLUSTER SETTING admission.kv.enabled=true + +onlyif config 3node-tenant +statement error ALTER TENANT can only be called by system operators +ALTER TENANT 10 SET CLUSTER SETTING server.mem_profile.total_dump_size_limit='10M' + +skipif config 3node-tenant +statement error unimplemented +ALTER TENANT 10 SET CLUSTER SETTING server.mem_profile.total_dump_size_limit='10M' + +skipif config 3node-tenant +statement error unimplemented +ALTER TENANT ALL SET CLUSTER SETTING server.mem_profile.total_dump_size_limit='10M' + +skipif config 3node-tenant +statement error unimplemented +ALTER TENANT 10 RESET CLUSTER SETTING server.mem_profile.total_dump_size_limit + +skipif config 3node-tenant +statement error unimplemented +ALTER TENANT ALL RESET CLUSTER SETTING server.mem_profile.total_dump_size_limit + +skipif config 3node-tenant +statement error pq: at or near "EOF": syntax error: invalid tenant ID +ALTER TENANT 0 SET CLUSTER SETTING server.mem_profile.total_dump_size_limit='10M' + +skipif config 3node-tenant +statement error pq: at or near "EOF": syntax error: invalid tenant ID +ALTER TENANT 0 RESET CLUSTER SETTING server.mem_profile.total_dump_size_limit + +statement error unimplemented +SHOW CLUSTER SETTING server.mem_profile.total_dump_size_limit FOR TENANT 10 + +statement error unimplemented +SHOW CLUSTER SETTINGS FOR TENANT 10 + +statement error unimplemented +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 10 + +statement error unimplemented +SHOW ALL CLUSTER SETTINGS FOR TENANT 10 + diff --git a/pkg/sql/opaque.go b/pkg/sql/opaque.go index e170fabfecb9..50f24c967a99 100644 --- a/pkg/sql/opaque.go +++ b/pkg/sql/opaque.go @@ -105,6 +105,8 @@ func planOpaque(ctx context.Context, p *planner, stmt tree.Statement) (planNode, return p.AlterTableOwner(ctx, n) case *tree.AlterTableSetSchema: return p.AlterTableSetSchema(ctx, n) + case *tree.AlterTenantSetClusterSetting: + return p.AlterTenantSetClusterSetting(ctx, n) case *tree.AlterType: return p.AlterType(ctx, n) case *tree.AlterRole: @@ -251,6 +253,7 @@ func init() { &tree.AlterTableLocality{}, &tree.AlterTableOwner{}, &tree.AlterTableSetSchema{}, + &tree.AlterTenantSetClusterSetting{}, &tree.AlterType{}, &tree.AlterSequence{}, &tree.AlterRole{}, diff --git a/pkg/sql/parser/help_test.go b/pkg/sql/parser/help_test.go index e0ae7109e9ee..3d8e60c1a2ce 100644 --- a/pkg/sql/parser/help_test.go +++ b/pkg/sql/parser/help_test.go @@ -50,6 +50,11 @@ func TestContextualHelp(t *testing.T) { {`ALTER TABLE blah RENAME TO blih ??`, `ALTER TABLE`}, {`ALTER TABLE blah SPLIT AT (SELECT 1) ??`, `ALTER TABLE`}, + {`ALTER TENANT 1 SET CLUSTER SETTING ???`, `ALTER TENANT`}, + {`ALTER TENANT 1 RESET CLUSTER SETTING ???`, `ALTER TENANT`}, + {`ALTER TENANT ALL SET CLUSTER SETTING ???`, `ALTER TENANT`}, + {`ALTER TENANT ALL RESET CLUSTER SETTING ???`, `ALTER TENANT`}, + {`ALTER TYPE ??`, `ALTER TYPE`}, {`ALTER TYPE t ??`, `ALTER TYPE`}, {`ALTER TYPE t ADD VALUE ??`, `ALTER TYPE`}, @@ -327,6 +332,10 @@ func TestContextualHelp(t *testing.T) { {`SHOW CLUSTER SETTING all ??`, `SHOW CLUSTER SETTING`}, {`SHOW ALL CLUSTER ??`, `SHOW CLUSTER SETTING`}, + {`SHOW CLUSTER SETTING a FOR TENANT ??`, `SHOW CLUSTER SETTING`}, + {`SHOW ALL CLUSTER SETTINGS FOR TENANT ??`, `SHOW CLUSTER SETTING`}, + {`SHOW CLUSTER SETTINGS FOR TENANT ??`, `SHOW CLUSTER SETTING`}, + {`SHOW PUBLIC CLUSTER SETTINGS FOR TENANT ??`, `SHOW CLUSTER SETTING`}, {`SHOW COLUMNS FROM ??`, `SHOW COLUMNS`}, {`SHOW COLUMNS FROM foo ??`, `SHOW COLUMNS`}, diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 831629b874fe..9a3433b213c4 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -958,6 +958,9 @@ func (u *sqlSymUnion) fetchCursor() *tree.FetchCursor { %type alter_table_locality_stmt %type alter_table_owner_stmt +// ALTER TENANT CLUSTER SETTINGS +%type alter_tenant_csetting_stmt + // ALTER PARTITION %type alter_zone_partition_stmt @@ -1572,10 +1575,11 @@ stmt: // %Help: ALTER // %Category: Group -// %Text: ALTER TABLE, ALTER INDEX, ALTER VIEW, ALTER SEQUENCE, ALTER DATABASE, ALTER USER, ALTER ROLE, ALTER DEFAULT PRIVILEGES +// %Text: ALTER TABLE, ALTER INDEX, ALTER VIEW, ALTER SEQUENCE, ALTER DATABASE, ALTER USER, ALTER ROLE, ALTER DEFAULT PRIVILEGES, ALTER TENANT alter_stmt: alter_ddl_stmt // help texts in sub-rule | alter_role_stmt // EXTEND WITH HELP: ALTER ROLE +| alter_tenant_csetting_stmt // EXTEND WITH HELP: ALTER TENANT | alter_unsupported_stmt | ALTER error // SHOW HELP: ALTER @@ -4947,6 +4951,56 @@ set_csetting_stmt: } | SET CLUSTER error // SHOW HELP: SET CLUSTER SETTING +// %Help: ALTER TENANT - alter tenant configuration +// %Category: Cfg +// %Text: +// ALTER TENANT { | ALL } SET CLUSTER SETTING { TO | = } +// ALTER TENANT { | ALL } RESET CLUSTER SETTING +// %SeeAlso: SET CLUSTER SETTING +alter_tenant_csetting_stmt: + ALTER TENANT iconst64 SET CLUSTER SETTING var_name to_or_eq var_value + { + tenID := uint64($3.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.AlterTenantSetClusterSetting{ + Name: strings.Join($7.strs(), "."), + Value: $9.expr(), + TenantID: roachpb.MakeTenantID(tenID), + } + } +| ALTER TENANT ALL SET CLUSTER SETTING var_name to_or_eq var_value + { + $$.val = &tree.AlterTenantSetClusterSetting{ + Name: strings.Join($7.strs(), "."), + Value: $9.expr(), + TenantAll: true, + } + } +| ALTER TENANT iconst64 RESET CLUSTER SETTING var_name + { + tenID := uint64($3.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.AlterTenantSetClusterSetting{ + Name: strings.Join($7.strs(), "."), + Value: tree.DefaultVal{}, + TenantID: roachpb.MakeTenantID(tenID), + } + } +| ALTER TENANT ALL RESET CLUSTER SETTING var_name + { + $$.val = &tree.AlterTenantSetClusterSetting{ + Name: strings.Join($7.strs(), "."), + Value: tree.DefaultVal{}, + TenantAll: true, + } + } +| ALTER TENANT error // SHOW HELP: ALTER TENANT + + to_or_eq: '=' | TO @@ -5642,8 +5696,8 @@ show_backup_stmt: // %Help: SHOW CLUSTER SETTING - display cluster settings // %Category: Cfg // %Text: -// SHOW CLUSTER SETTING -// SHOW [ PUBLIC | ALL ] CLUSTER SETTINGS +// SHOW CLUSTER SETTING [ FOR TENANT ] +// SHOW [ PUBLIC | ALL ] CLUSTER SETTINGS [ FOR TENANT ] // %SeeAlso: WEBDOCS/cluster-settings.html show_csettings_stmt: SHOW CLUSTER SETTING var_name @@ -5668,6 +5722,38 @@ show_csettings_stmt: { $$.val = &tree.ShowClusterSettingList{} } +| SHOW CLUSTER SETTING var_name FOR TENANT iconst64 + { + tenID := uint64($7.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.ShowClusterSetting{Name: strings.Join($4.strs(), "."), TenantID: roachpb.MakeTenantID(tenID)} + } +| SHOW ALL CLUSTER SETTINGS FOR TENANT iconst64 + { + tenID := uint64($7.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.ShowClusterSettingList{All: true, TenantID: roachpb.MakeTenantID(tenID)} + } +| SHOW CLUSTER SETTINGS FOR TENANT iconst64 + { + tenID := uint64($6.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.ShowClusterSettingList{TenantID: roachpb.MakeTenantID(tenID)} + } +| SHOW PUBLIC CLUSTER SETTINGS FOR TENANT iconst64 + { + tenID := uint64($7.int64()) + if tenID == 0 { + return setErr(sqllex, errors.New("invalid tenant ID")) + } + $$.val = &tree.ShowClusterSettingList{TenantID: roachpb.MakeTenantID(tenID)} + } | SHOW PUBLIC CLUSTER error // SHOW HELP: SHOW CLUSTER SETTING // %Help: SHOW COLUMNS - list columns in relation diff --git a/pkg/sql/parser/testdata/alter_tenant b/pkg/sql/parser/testdata/alter_tenant new file mode 100644 index 000000000000..c1a2881ca452 --- /dev/null +++ b/pkg/sql/parser/testdata/alter_tenant @@ -0,0 +1,31 @@ +parse +ALTER TENANT 1 SET CLUSTER SETTING a = 3 +---- +ALTER TENANT 1 SET CLUSTER SETTING a = 3 +ALTER TENANT 1 SET CLUSTER SETTING a = (3) -- fully parenthesized +ALTER TENANT 1 SET CLUSTER SETTING a = _ -- literals removed +ALTER TENANT 1 SET CLUSTER SETTING a = 3 -- identifiers removed + +parse +ALTER TENANT ALL SET CLUSTER SETTING a = 3 +---- +ALTER TENANT ALL SET CLUSTER SETTING a = 3 +ALTER TENANT ALL SET CLUSTER SETTING a = (3) -- fully parenthesized +ALTER TENANT ALL SET CLUSTER SETTING a = _ -- literals removed +ALTER TENANT ALL SET CLUSTER SETTING a = 3 -- identifiers removed + +parse +ALTER TENANT 1 RESET CLUSTER SETTING a +---- +ALTER TENANT 1 SET CLUSTER SETTING a = DEFAULT -- normalized! +ALTER TENANT 1 SET CLUSTER SETTING a = (DEFAULT) -- fully parenthesized +ALTER TENANT 1 SET CLUSTER SETTING a = DEFAULT -- literals removed +ALTER TENANT 1 SET CLUSTER SETTING a = DEFAULT -- identifiers removed + +parse +ALTER TENANT ALL RESET CLUSTER SETTING a +---- +ALTER TENANT ALL SET CLUSTER SETTING a = DEFAULT -- normalized! +ALTER TENANT ALL SET CLUSTER SETTING a = (DEFAULT) -- fully parenthesized +ALTER TENANT ALL SET CLUSTER SETTING a = DEFAULT -- literals removed +ALTER TENANT ALL SET CLUSTER SETTING a = DEFAULT -- identifiers removed diff --git a/pkg/sql/parser/testdata/show b/pkg/sql/parser/testdata/show index 44d84d143057..a5b88da84ae8 100644 --- a/pkg/sql/parser/testdata/show +++ b/pkg/sql/parser/testdata/show @@ -126,6 +126,54 @@ SHOW PUBLIC CLUSTER SETTINGS -- fully parenthesized SHOW PUBLIC CLUSTER SETTINGS -- literals removed SHOW PUBLIC CLUSTER SETTINGS -- identifiers removed +parse +SHOW CLUSTER SETTING a FOR TENANT 1 +---- +SHOW CLUSTER SETTING a FOR TENANT 1 +SHOW CLUSTER SETTING a FOR TENANT 1 -- fully parenthesized +SHOW CLUSTER SETTING a FOR TENANT 1 -- literals removed +SHOW CLUSTER SETTING a FOR TENANT 1 -- identifiers removed + +parse +EXPLAIN SHOW CLUSTER SETTING a FOR TENANT 1 +---- +EXPLAIN SHOW CLUSTER SETTING a FOR TENANT 1 +EXPLAIN SHOW CLUSTER SETTING a FOR TENANT 1 -- fully parenthesized +EXPLAIN SHOW CLUSTER SETTING a FOR TENANT 1 -- literals removed +EXPLAIN SHOW CLUSTER SETTING a FOR TENANT 1 -- identifiers removed + +parse +SHOW ALL CLUSTER SETTINGS FOR TENANT 1 +---- +SHOW ALL CLUSTER SETTINGS FOR TENANT 1 +SHOW ALL CLUSTER SETTINGS FOR TENANT 1 -- fully parenthesized +SHOW ALL CLUSTER SETTINGS FOR TENANT 1 -- literals removed +SHOW ALL CLUSTER SETTINGS FOR TENANT 1 -- identifiers removed + +parse +SHOW CLUSTER SETTING a FOR TENANT 1 +---- +SHOW CLUSTER SETTING a FOR TENANT 1 +SHOW CLUSTER SETTING a FOR TENANT 1 -- fully parenthesized +SHOW CLUSTER SETTING a FOR TENANT 1 -- literals removed +SHOW CLUSTER SETTING a FOR TENANT 1 -- identifiers removed + +parse +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 +---- +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- fully parenthesized +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- literals removed +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- identifiers removed + +parse +SHOW CLUSTER SETTINGS FOR TENANT 1 +---- +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- normalized! +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- fully parenthesized +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- literals removed +SHOW PUBLIC CLUSTER SETTINGS FOR TENANT 1 -- identifiers removed + parse SHOW DATABASES ---- diff --git a/pkg/sql/randgen/mutator.go b/pkg/sql/randgen/mutator.go index eac35e1b6437..2f3d69244b83 100644 --- a/pkg/sql/randgen/mutator.go +++ b/pkg/sql/randgen/mutator.go @@ -641,7 +641,7 @@ func postgresMutator(rng *rand.Rand, q string) string { var postgresStatementMutator MultiStatementMutation = func(rng *rand.Rand, stmts []tree.Statement) (mutated []tree.Statement, changed bool) { for _, stmt := range stmts { switch stmt := stmt.(type) { - case *tree.SetClusterSetting, *tree.SetVar: + case *tree.SetClusterSetting, *tree.SetVar, *tree.AlterTenantSetClusterSetting: continue case *tree.CreateTable: if stmt.PartitionByTable != nil { diff --git a/pkg/sql/sem/tree/BUILD.bazel b/pkg/sql/sem/tree/BUILD.bazel index c907535a623b..00b326e27b1d 100644 --- a/pkg/sql/sem/tree/BUILD.bazel +++ b/pkg/sql/sem/tree/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "alter_schema.go", "alter_sequence.go", "alter_table.go", + "alter_tenant.go", "alter_type.go", "analyze.go", "annotation.go", diff --git a/pkg/sql/sem/tree/alter_tenant.go b/pkg/sql/sem/tree/alter_tenant.go new file mode 100644 index 000000000000..1ec4485d32bb --- /dev/null +++ b/pkg/sql/sem/tree/alter_tenant.go @@ -0,0 +1,53 @@ +// Copyright 2022 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package tree + +import ( + "fmt" + + "github.com/cockroachdb/cockroach/pkg/roachpb" +) + +// AlterTenantSetClusterSetting represents an ALTER TENANT +// SET CLUSTER SETTING statement. +type AlterTenantSetClusterSetting struct { + Name string + Value Expr + TenantID roachpb.TenantID + TenantAll bool +} + +// Format implements the NodeFormatter interface. +func (n *AlterTenantSetClusterSetting) Format(ctx *FmtCtx) { + if n.TenantAll { + ctx.WriteString("ALTER TENANT ALL ") + } else if n.TenantID.IsSet() { + ctx.WriteString(fmt.Sprintf("ALTER TENANT %d ", n.TenantID.ToUint64())) + } + ctx.WriteString("SET CLUSTER SETTING ") + + // Cluster setting names never contain PII and should be distinguished + // for feature tracking purposes. + ctx.WithFlags(ctx.flags & ^FmtAnonymize & ^FmtMarkRedactionNode, func() { + ctx.FormatNameP(&n.Name) + }) + + ctx.WriteString(" = ") + + switch v := n.Value.(type) { + case *DBool, *DInt: + ctx.WithFlags(ctx.flags & ^FmtAnonymize & ^FmtMarkRedactionNode, func() { + ctx.FormatNode(v) + }) + default: + ctx.FormatNode(v) + } +} diff --git a/pkg/sql/sem/tree/set.go b/pkg/sql/sem/tree/set.go index a6827fb87fc4..b045ba2b5c62 100644 --- a/pkg/sql/sem/tree/set.go +++ b/pkg/sql/sem/tree/set.go @@ -19,6 +19,8 @@ package tree +import "github.com/cockroachdb/cockroach/pkg/roachpb" + // SetVar represents a SET or RESET statement. type SetVar struct { Name string @@ -65,13 +67,16 @@ func (node *SetVar) Format(ctx *FmtCtx) { // SetClusterSetting represents a SET CLUSTER SETTING statement. type SetClusterSetting struct { - Name string - Value Expr + Name string + Value Expr + TenantID roachpb.TenantID + TenantAll bool } // Format implements the NodeFormatter interface. func (node *SetClusterSetting) Format(ctx *FmtCtx) { ctx.WriteString("SET CLUSTER SETTING ") + // Cluster setting names never contain PII and should be distinguished // for feature tracking purposes. ctx.WithFlags(ctx.flags & ^FmtAnonymize & ^FmtMarkRedactionNode, func() { diff --git a/pkg/sql/sem/tree/show.go b/pkg/sql/sem/tree/show.go index 8e3615e3f0e1..1832d799df30 100644 --- a/pkg/sql/sem/tree/show.go +++ b/pkg/sql/sem/tree/show.go @@ -22,6 +22,7 @@ package tree import ( "fmt" + "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/sql/lexbase" ) @@ -42,7 +43,8 @@ func (node *ShowVar) Format(ctx *FmtCtx) { // ShowClusterSetting represents a SHOW CLUSTER SETTING statement. type ShowClusterSetting struct { - Name string + Name string + TenantID roachpb.TenantID } // Format implements the NodeFormatter interface. @@ -53,12 +55,17 @@ func (node *ShowClusterSetting) Format(ctx *FmtCtx) { ctx.WithFlags(ctx.flags & ^FmtAnonymize & ^FmtMarkRedactionNode, func() { ctx.FormatNameP(&node.Name) }) + if node.TenantID.IsSet() { + s := fmt.Sprintf(" FOR TENANT %d", node.TenantID.ToUint64()) + ctx.WriteString(s) + } } // ShowClusterSettingList represents a SHOW [ALL|PUBLIC] CLUSTER SETTINGS statement. type ShowClusterSettingList struct { // All indicates whether to include non-public settings in the output. - All bool + All bool + TenantID roachpb.TenantID } // Format implements the NodeFormatter interface. @@ -70,6 +77,10 @@ func (node *ShowClusterSettingList) Format(ctx *FmtCtx) { } ctx.WriteString(qual) ctx.WriteString(" CLUSTER SETTINGS") + if node.TenantID.IsSet() { + s := fmt.Sprintf(" FOR TENANT %d", node.TenantID.ToUint64()) + ctx.WriteString(s) + } } // BackupDetails represents the type of details to display for a SHOW BACKUP diff --git a/pkg/sql/sem/tree/stmt.go b/pkg/sql/sem/tree/stmt.go index f5735107091d..350823752745 100644 --- a/pkg/sql/sem/tree/stmt.go +++ b/pkg/sql/sem/tree/stmt.go @@ -342,6 +342,15 @@ func (*AlterSchema) StatementTag() string { return "ALTER SCHEMA" } func (*AlterSchema) hiddenFromShowQueries() {} +// StatementReturnType implements the Statement interface. +func (*AlterTenantSetClusterSetting) StatementReturnType() StatementReturnType { return Ack } + +// StatementType implements the Statement interface. +func (*AlterTenantSetClusterSetting) StatementType() StatementType { return TypeDCL } + +// StatementTag returns a short string identifying the type of statement. +func (*AlterTenantSetClusterSetting) StatementTag() string { return "ALTER TENANT SET CLUSTER SETTING" } + // StatementReturnType implements the Statement interface. func (*AlterType) StatementReturnType() StatementReturnType { return DDL } @@ -1751,6 +1760,7 @@ func (n *AlterTableSetVisible) String() string { return AsString(n) } func (n *AlterTableSetNotNull) String() string { return AsString(n) } func (n *AlterTableOwner) String() string { return AsString(n) } func (n *AlterTableSetSchema) String() string { return AsString(n) } +func (n *AlterTenantSetClusterSetting) String() string { return AsString(n) } func (n *AlterType) String() string { return AsString(n) } func (n *AlterRole) String() string { return AsString(n) } func (n *AlterRoleSet) String() string { return AsString(n) } diff --git a/pkg/sql/sem/tree/walk.go b/pkg/sql/sem/tree/walk.go index c748532f5202..53e1e154b5be 100644 --- a/pkg/sql/sem/tree/walk.go +++ b/pkg/sql/sem/tree/walk.go @@ -868,6 +868,25 @@ func walkReturningClause(v Visitor, clause ReturningClause) (ReturningClause, bo } } +// copyNode makes a copy of this Statement without recursing in any child Statements. +func (n *AlterTenantSetClusterSetting) copyNode() *AlterTenantSetClusterSetting { + stmtCopy := *n + return &stmtCopy +} + +// walkStmt is part of the walkableStmt interface. +func (n *AlterTenantSetClusterSetting) walkStmt(v Visitor) Statement { + ret := n + if n.Value != nil { + e, changed := WalkExpr(v, n.Value) + if changed { + ret = n.copyNode() + ret.Value = e + } + } + return ret +} + // copyNode makes a copy of this Statement without recursing in any child Statements. func (stmt *Backup) copyNode() *Backup { stmtCopy := *stmt @@ -1571,6 +1590,7 @@ func (stmt *BeginTransaction) walkStmt(v Visitor) Statement { return ret } +var _ walkableStmt = &AlterTenantSetClusterSetting{} var _ walkableStmt = &CreateTable{} var _ walkableStmt = &Backup{} var _ walkableStmt = &Delete{} diff --git a/pkg/sql/set_cluster_setting.go b/pkg/sql/set_cluster_setting.go index 19a9d8512163..688d73e31efc 100644 --- a/pkg/sql/set_cluster_setting.go +++ b/pkg/sql/set_cluster_setting.go @@ -121,11 +121,25 @@ func (p *planner) SetClusterSetting( return nil, errors.Errorf("cluster setting '%s' is currently overridden by the operator", name) } + value, err := p.getAndValidateTypedClusterSetting(ctx, name, n.Value, setting) + if err != nil { + return nil, err + } + + csNode := setClusterSettingNode{ + name: name, st: st, setting: setting, value: value, + versionUpgradeHook: p.execCfg.VersionUpgradeHook, + } + return &csNode, nil +} + +func (p *planner) getAndValidateTypedClusterSetting( + ctx context.Context, name string, expr tree.Expr, setting settings.NonMaskedSetting, +) (tree.TypedExpr, error) { var value tree.TypedExpr - if n.Value != nil { + if expr != nil { // For DEFAULT, let the value reference be nil. That's a RESET in disguise. - if _, ok := n.Value.(tree.DefaultVal); !ok { - expr := n.Value + if _, ok := expr.(tree.DefaultVal); !ok { expr = paramparse.UnresolvedNameToStrVal(expr) var requiredType *types.T @@ -172,18 +186,12 @@ func (p *planner) SetClusterSetting( } return nil, err } - value = typed } else if _, isVersionSetting := setting.(*settings.VersionSetting); isVersionSetting { return nil, errors.New("cannot RESET cluster version setting") } } - - csNode := setClusterSettingNode{ - name: name, st: st, setting: setting, value: value, - versionUpgradeHook: p.execCfg.VersionUpgradeHook, - } - return &csNode, nil + return value, nil } func (n *setClusterSettingNode) startExec(params runParams) error { diff --git a/pkg/sql/show_cluster_setting.go b/pkg/sql/show_cluster_setting.go index 511cb122054c..ea8555e36e63 100644 --- a/pkg/sql/show_cluster_setting.go +++ b/pkg/sql/show_cluster_setting.go @@ -30,6 +30,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util/contextutil" "github.com/cockroachdb/cockroach/pkg/util/duration" + "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" "github.com/cockroachdb/cockroach/pkg/util/protoutil" "github.com/cockroachdb/cockroach/pkg/util/retry" "github.com/cockroachdb/cockroach/pkg/util/timeutil" @@ -117,6 +118,10 @@ func (p *planner) showVersionSetting( func (p *planner) ShowClusterSetting( ctx context.Context, n *tree.ShowClusterSetting, ) (planNode, error) { + if n.TenantID.IsSet() { + return nil, unimplemented.NewWithIssue(73857, + `unimplemented: tenant-level cluster settings not supported`) + } name := strings.ToLower(n.Name) st := p.ExecCfg().Settings val, ok := settings.Lookup( diff --git a/pkg/sql/walk.go b/pkg/sql/walk.go index 6beefefdef35..2a545edfd792 100644 --- a/pkg/sql/walk.go +++ b/pkg/sql/walk.go @@ -215,6 +215,7 @@ func (v *planVisitor) visitInternal(plan planNode, name string) { n.sourcePlan = v.visit(n.sourcePlan) } + case *alterTenantSetClusterSettingNode: case *createViewNode: case *setVarNode: case *setClusterSettingNode: @@ -333,125 +334,126 @@ func nodeName(plan planNode) string { // strings are constant and not precomputed so that the type names can // be changed without changing the output of "EXPLAIN". var planNodeNames = map[reflect.Type]string{ - reflect.TypeOf(&alterDatabaseOwnerNode{}): "alter database owner", - reflect.TypeOf(&alterDatabaseAddRegionNode{}): "alter database add region", - reflect.TypeOf(&alterDatabasePrimaryRegionNode{}): "alter database primary region", - reflect.TypeOf(&alterDatabasePlacementNode{}): "alter database placement", - reflect.TypeOf(&alterDatabaseSurvivalGoalNode{}): "alter database survive", - reflect.TypeOf(&alterDatabaseDropRegionNode{}): "alter database drop region", - reflect.TypeOf(&alterDefaultPrivilegesNode{}): "alter default privileges", - reflect.TypeOf(&alterIndexNode{}): "alter index", - reflect.TypeOf(&alterSequenceNode{}): "alter sequence", - reflect.TypeOf(&alterSchemaNode{}): "alter schema", - reflect.TypeOf(&alterTableNode{}): "alter table", - reflect.TypeOf(&alterTableOwnerNode{}): "alter table owner", - reflect.TypeOf(&alterTableSetLocalityNode{}): "alter table set locality", - reflect.TypeOf(&alterTableSetSchemaNode{}): "alter table set schema", - reflect.TypeOf(&alterTypeNode{}): "alter type", - reflect.TypeOf(&alterRoleNode{}): "alter role", - reflect.TypeOf(&alterRoleSetNode{}): "alter role set var", - reflect.TypeOf(&applyJoinNode{}): "apply join", - reflect.TypeOf(&bufferNode{}): "buffer", - reflect.TypeOf(&cancelQueriesNode{}): "cancel queries", - reflect.TypeOf(&cancelSessionsNode{}): "cancel sessions", - reflect.TypeOf(&changePrivilegesNode{}): "change privileges", - reflect.TypeOf(&commentOnColumnNode{}): "comment on column", - reflect.TypeOf(&commentOnConstraintNode{}): "comment on constraint", - reflect.TypeOf(&commentOnDatabaseNode{}): "comment on database", - reflect.TypeOf(&commentOnIndexNode{}): "comment on index", - reflect.TypeOf(&commentOnTableNode{}): "comment on table", - reflect.TypeOf(&commentOnSchemaNode{}): "comment on schema", - reflect.TypeOf(&controlJobsNode{}): "control jobs", - reflect.TypeOf(&controlSchedulesNode{}): "control schedules", - reflect.TypeOf(&createDatabaseNode{}): "create database", - reflect.TypeOf(&createExtensionNode{}): "create extension", - reflect.TypeOf(&createIndexNode{}): "create index", - reflect.TypeOf(&createSequenceNode{}): "create sequence", - reflect.TypeOf(&createSchemaNode{}): "create schema", - reflect.TypeOf(&createStatsNode{}): "create statistics", - reflect.TypeOf(&createTableNode{}): "create table", - reflect.TypeOf(&createTypeNode{}): "create type", - reflect.TypeOf(&CreateRoleNode{}): "create user/role", - reflect.TypeOf(&createViewNode{}): "create view", - reflect.TypeOf(&delayedNode{}): "virtual table", - reflect.TypeOf(&deleteNode{}): "delete", - reflect.TypeOf(&deleteRangeNode{}): "delete range", - reflect.TypeOf(&distinctNode{}): "distinct", - reflect.TypeOf(&dropDatabaseNode{}): "drop database", - reflect.TypeOf(&dropIndexNode{}): "drop index", - reflect.TypeOf(&dropSequenceNode{}): "drop sequence", - reflect.TypeOf(&dropSchemaNode{}): "drop schema", - reflect.TypeOf(&dropTableNode{}): "drop table", - reflect.TypeOf(&dropTypeNode{}): "drop type", - reflect.TypeOf(&DropRoleNode{}): "drop user/role", - reflect.TypeOf(&dropViewNode{}): "drop view", - reflect.TypeOf(&errorIfRowsNode{}): "error if rows", - reflect.TypeOf(&explainPlanNode{}): "explain plan", - reflect.TypeOf(&explainVecNode{}): "explain vectorized", - reflect.TypeOf(&explainDDLNode{}): "explain ddl", - reflect.TypeOf(&exportNode{}): "export", - reflect.TypeOf(&fetchNode{}): "fetch", - reflect.TypeOf(&filterNode{}): "filter", - reflect.TypeOf(&GrantRoleNode{}): "grant role", - reflect.TypeOf(&groupNode{}): "group", - reflect.TypeOf(&hookFnNode{}): "plugin", - reflect.TypeOf(&indexJoinNode{}): "index join", - reflect.TypeOf(&insertNode{}): "insert", - reflect.TypeOf(&insertFastPathNode{}): "insert fast path", - reflect.TypeOf(&invertedFilterNode{}): "inverted filter", - reflect.TypeOf(&invertedJoinNode{}): "inverted join", - reflect.TypeOf(&joinNode{}): "join", - reflect.TypeOf(&limitNode{}): "limit", - reflect.TypeOf(&lookupJoinNode{}): "lookup join", - reflect.TypeOf(&max1RowNode{}): "max1row", - reflect.TypeOf(&ordinalityNode{}): "ordinality", - reflect.TypeOf(&projectSetNode{}): "project set", - reflect.TypeOf(&reassignOwnedByNode{}): "reassign owned by", - reflect.TypeOf(&dropOwnedByNode{}): "drop owned by", - reflect.TypeOf(&recursiveCTENode{}): "recursive cte", - reflect.TypeOf(&refreshMaterializedViewNode{}): "refresh materialized view", - reflect.TypeOf(&relocateNode{}): "relocate", - reflect.TypeOf(&relocateRange{}): "relocate range", - reflect.TypeOf(&renameColumnNode{}): "rename column", - reflect.TypeOf(&renameDatabaseNode{}): "rename database", - reflect.TypeOf(&renameIndexNode{}): "rename index", - reflect.TypeOf(&renameTableNode{}): "rename table", - reflect.TypeOf(&reparentDatabaseNode{}): "reparent database", - reflect.TypeOf(&renderNode{}): "render", - reflect.TypeOf(&resetAllNode{}): "reset all", - reflect.TypeOf(&RevokeRoleNode{}): "revoke role", - reflect.TypeOf(&rowCountNode{}): "count", - reflect.TypeOf(&rowSourceToPlanNode{}): "row source to plan node", - reflect.TypeOf(&saveTableNode{}): "save table", - reflect.TypeOf(&scanBufferNode{}): "scan buffer", - reflect.TypeOf(&scanNode{}): "scan", - reflect.TypeOf(&scatterNode{}): "scatter", - reflect.TypeOf(&scrubNode{}): "scrub", - reflect.TypeOf(&sequenceSelectNode{}): "sequence select", - reflect.TypeOf(&serializeNode{}): "run", - reflect.TypeOf(&setClusterSettingNode{}): "set cluster setting", - reflect.TypeOf(&setVarNode{}): "set", - reflect.TypeOf(&setZoneConfigNode{}): "configure zone", - reflect.TypeOf(&showFingerprintsNode{}): "show fingerprints", - reflect.TypeOf(&showTraceNode{}): "show trace for", - reflect.TypeOf(&showTraceReplicaNode{}): "replica trace", - reflect.TypeOf(&showVarNode{}): "show", - reflect.TypeOf(&sortNode{}): "sort", - reflect.TypeOf(&splitNode{}): "split", - reflect.TypeOf(&topKNode{}): "top-k", - reflect.TypeOf(&unsplitNode{}): "unsplit", - reflect.TypeOf(&unsplitAllNode{}): "unsplit all", - reflect.TypeOf(&spoolNode{}): "spool", - reflect.TypeOf(&truncateNode{}): "truncate", - reflect.TypeOf(&unaryNode{}): "emptyrow", - reflect.TypeOf(&unionNode{}): "union", - reflect.TypeOf(&updateNode{}): "update", - reflect.TypeOf(&upsertNode{}): "upsert", - reflect.TypeOf(&valuesNode{}): "values", - reflect.TypeOf(&virtualTableNode{}): "virtual table values", - reflect.TypeOf(&vTableLookupJoinNode{}): "virtual table lookup join", - reflect.TypeOf(&windowNode{}): "window", - reflect.TypeOf(&zeroNode{}): "norows", - reflect.TypeOf(&zigzagJoinNode{}): "zigzag join", - reflect.TypeOf(&schemaChangePlanNode{}): "schema change", + reflect.TypeOf(&alterDatabaseOwnerNode{}): "alter database owner", + reflect.TypeOf(&alterDatabaseAddRegionNode{}): "alter database add region", + reflect.TypeOf(&alterDatabasePrimaryRegionNode{}): "alter database primary region", + reflect.TypeOf(&alterDatabasePlacementNode{}): "alter database placement", + reflect.TypeOf(&alterDatabaseSurvivalGoalNode{}): "alter database survive", + reflect.TypeOf(&alterDatabaseDropRegionNode{}): "alter database drop region", + reflect.TypeOf(&alterDefaultPrivilegesNode{}): "alter default privileges", + reflect.TypeOf(&alterIndexNode{}): "alter index", + reflect.TypeOf(&alterSequenceNode{}): "alter sequence", + reflect.TypeOf(&alterSchemaNode{}): "alter schema", + reflect.TypeOf(&alterTableNode{}): "alter table", + reflect.TypeOf(&alterTableOwnerNode{}): "alter table owner", + reflect.TypeOf(&alterTableSetLocalityNode{}): "alter table set locality", + reflect.TypeOf(&alterTableSetSchemaNode{}): "alter table set schema", + reflect.TypeOf(&alterTenantSetClusterSettingNode{}): "alter tenant set cluster setting", + reflect.TypeOf(&alterTypeNode{}): "alter type", + reflect.TypeOf(&alterRoleNode{}): "alter role", + reflect.TypeOf(&alterRoleSetNode{}): "alter role set var", + reflect.TypeOf(&applyJoinNode{}): "apply join", + reflect.TypeOf(&bufferNode{}): "buffer", + reflect.TypeOf(&cancelQueriesNode{}): "cancel queries", + reflect.TypeOf(&cancelSessionsNode{}): "cancel sessions", + reflect.TypeOf(&changePrivilegesNode{}): "change privileges", + reflect.TypeOf(&commentOnColumnNode{}): "comment on column", + reflect.TypeOf(&commentOnConstraintNode{}): "comment on constraint", + reflect.TypeOf(&commentOnDatabaseNode{}): "comment on database", + reflect.TypeOf(&commentOnIndexNode{}): "comment on index", + reflect.TypeOf(&commentOnTableNode{}): "comment on table", + reflect.TypeOf(&commentOnSchemaNode{}): "comment on schema", + reflect.TypeOf(&controlJobsNode{}): "control jobs", + reflect.TypeOf(&controlSchedulesNode{}): "control schedules", + reflect.TypeOf(&createDatabaseNode{}): "create database", + reflect.TypeOf(&createExtensionNode{}): "create extension", + reflect.TypeOf(&createIndexNode{}): "create index", + reflect.TypeOf(&createSequenceNode{}): "create sequence", + reflect.TypeOf(&createSchemaNode{}): "create schema", + reflect.TypeOf(&createStatsNode{}): "create statistics", + reflect.TypeOf(&createTableNode{}): "create table", + reflect.TypeOf(&createTypeNode{}): "create type", + reflect.TypeOf(&CreateRoleNode{}): "create user/role", + reflect.TypeOf(&createViewNode{}): "create view", + reflect.TypeOf(&delayedNode{}): "virtual table", + reflect.TypeOf(&deleteNode{}): "delete", + reflect.TypeOf(&deleteRangeNode{}): "delete range", + reflect.TypeOf(&distinctNode{}): "distinct", + reflect.TypeOf(&dropDatabaseNode{}): "drop database", + reflect.TypeOf(&dropIndexNode{}): "drop index", + reflect.TypeOf(&dropSequenceNode{}): "drop sequence", + reflect.TypeOf(&dropSchemaNode{}): "drop schema", + reflect.TypeOf(&dropTableNode{}): "drop table", + reflect.TypeOf(&dropTypeNode{}): "drop type", + reflect.TypeOf(&DropRoleNode{}): "drop user/role", + reflect.TypeOf(&dropViewNode{}): "drop view", + reflect.TypeOf(&errorIfRowsNode{}): "error if rows", + reflect.TypeOf(&explainPlanNode{}): "explain plan", + reflect.TypeOf(&explainVecNode{}): "explain vectorized", + reflect.TypeOf(&explainDDLNode{}): "explain ddl", + reflect.TypeOf(&exportNode{}): "export", + reflect.TypeOf(&fetchNode{}): "fetch", + reflect.TypeOf(&filterNode{}): "filter", + reflect.TypeOf(&GrantRoleNode{}): "grant role", + reflect.TypeOf(&groupNode{}): "group", + reflect.TypeOf(&hookFnNode{}): "plugin", + reflect.TypeOf(&indexJoinNode{}): "index join", + reflect.TypeOf(&insertNode{}): "insert", + reflect.TypeOf(&insertFastPathNode{}): "insert fast path", + reflect.TypeOf(&invertedFilterNode{}): "inverted filter", + reflect.TypeOf(&invertedJoinNode{}): "inverted join", + reflect.TypeOf(&joinNode{}): "join", + reflect.TypeOf(&limitNode{}): "limit", + reflect.TypeOf(&lookupJoinNode{}): "lookup join", + reflect.TypeOf(&max1RowNode{}): "max1row", + reflect.TypeOf(&ordinalityNode{}): "ordinality", + reflect.TypeOf(&projectSetNode{}): "project set", + reflect.TypeOf(&reassignOwnedByNode{}): "reassign owned by", + reflect.TypeOf(&dropOwnedByNode{}): "drop owned by", + reflect.TypeOf(&recursiveCTENode{}): "recursive cte", + reflect.TypeOf(&refreshMaterializedViewNode{}): "refresh materialized view", + reflect.TypeOf(&relocateNode{}): "relocate", + reflect.TypeOf(&relocateRange{}): "relocate range", + reflect.TypeOf(&renameColumnNode{}): "rename column", + reflect.TypeOf(&renameDatabaseNode{}): "rename database", + reflect.TypeOf(&renameIndexNode{}): "rename index", + reflect.TypeOf(&renameTableNode{}): "rename table", + reflect.TypeOf(&reparentDatabaseNode{}): "reparent database", + reflect.TypeOf(&renderNode{}): "render", + reflect.TypeOf(&resetAllNode{}): "reset all", + reflect.TypeOf(&RevokeRoleNode{}): "revoke role", + reflect.TypeOf(&rowCountNode{}): "count", + reflect.TypeOf(&rowSourceToPlanNode{}): "row source to plan node", + reflect.TypeOf(&saveTableNode{}): "save table", + reflect.TypeOf(&scanBufferNode{}): "scan buffer", + reflect.TypeOf(&scanNode{}): "scan", + reflect.TypeOf(&scatterNode{}): "scatter", + reflect.TypeOf(&scrubNode{}): "scrub", + reflect.TypeOf(&sequenceSelectNode{}): "sequence select", + reflect.TypeOf(&serializeNode{}): "run", + reflect.TypeOf(&setClusterSettingNode{}): "set cluster setting", + reflect.TypeOf(&setVarNode{}): "set", + reflect.TypeOf(&setZoneConfigNode{}): "configure zone", + reflect.TypeOf(&showFingerprintsNode{}): "show fingerprints", + reflect.TypeOf(&showTraceNode{}): "show trace for", + reflect.TypeOf(&showTraceReplicaNode{}): "replica trace", + reflect.TypeOf(&showVarNode{}): "show", + reflect.TypeOf(&sortNode{}): "sort", + reflect.TypeOf(&splitNode{}): "split", + reflect.TypeOf(&topKNode{}): "top-k", + reflect.TypeOf(&unsplitNode{}): "unsplit", + reflect.TypeOf(&unsplitAllNode{}): "unsplit all", + reflect.TypeOf(&spoolNode{}): "spool", + reflect.TypeOf(&truncateNode{}): "truncate", + reflect.TypeOf(&unaryNode{}): "emptyrow", + reflect.TypeOf(&unionNode{}): "union", + reflect.TypeOf(&updateNode{}): "update", + reflect.TypeOf(&upsertNode{}): "upsert", + reflect.TypeOf(&valuesNode{}): "values", + reflect.TypeOf(&virtualTableNode{}): "virtual table values", + reflect.TypeOf(&vTableLookupJoinNode{}): "virtual table lookup join", + reflect.TypeOf(&windowNode{}): "window", + reflect.TypeOf(&zeroNode{}): "norows", + reflect.TypeOf(&zigzagJoinNode{}): "zigzag join", + reflect.TypeOf(&schemaChangePlanNode{}): "schema change", }