From f0b06e454858c090e76e0dd1b4009c9fe29fac81 Mon Sep 17 00:00:00 2001 From: Evan Wall Date: Thu, 19 Jan 2023 13:10:48 -0500 Subject: [PATCH] multitenant: append `WITH REPLICATION STATUS` columns to `SHOW TENANT` columns Informs #87851 `WITH CAPABILITIES` will be adding another set of columns so append relevant columns instead of creating all possible column sets ahead of time. Release note: None --- pkg/sql/catalog/colinfo/result_columns.go | 6 +- pkg/sql/show_tenant.go | 102 +++++++++++----------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/pkg/sql/catalog/colinfo/result_columns.go b/pkg/sql/catalog/colinfo/result_columns.go index b68d7abb857d..3f75744c281f 100644 --- a/pkg/sql/catalog/colinfo/result_columns.go +++ b/pkg/sql/catalog/colinfo/result_columns.go @@ -275,16 +275,16 @@ var ExportColumns = ResultColumns{ {Name: "bytes", Typ: types.Int}, } +// TenantColumns appear in all SHOW TENANT queries. var TenantColumns = ResultColumns{ {Name: "id", Typ: types.Int}, {Name: "name", Typ: types.String}, {Name: "status", Typ: types.String}, } +// TenantColumnsWithReplication is appended to TenantColumns for +// SHOW TENANT ... WITH REPLICATION STATUS queries. var TenantColumnsWithReplication = ResultColumns{ - {Name: "id", Typ: types.Int}, - {Name: "name", Typ: types.String}, - {Name: "status", Typ: types.String}, {Name: "source_tenant_name", Typ: types.String}, {Name: "source_cluster_uri", Typ: types.String}, {Name: "replication_job_id", Typ: types.Int}, diff --git a/pkg/sql/show_tenant.go b/pkg/sql/show_tenant.go index fe22c3a224b3..fd087c95a231 100644 --- a/pkg/sql/show_tenant.go +++ b/pkg/sql/show_tenant.go @@ -73,10 +73,10 @@ func (p *planner) ShowTenant(ctx context.Context, n *tree.ShowTenant) (planNode, tenantSpec: tspec, withReplication: n.WithReplication, } + + node.columns = colinfo.TenantColumns if n.WithReplication { - node.columns = colinfo.TenantColumnsWithReplication - } else { - node.columns = colinfo.TenantColumns + node.columns = append(node.columns, colinfo.TenantColumnsWithReplication...) } return node, nil @@ -234,61 +234,59 @@ func (n *showTenantNode) Next(params runParams) (bool, error) { func (n *showTenantNode) Values() tree.Datums { v := n.values - tenantId := tree.NewDInt(tree.DInt(v.tenantInfo.ID)) - tenantName := tree.NewDString(string(v.tenantInfo.Name)) - tenantStatus := tree.NewDString(string(v.tenantStatus)) - if !n.withReplication { - return tree.Datums{ - tenantId, - tenantName, - tenantStatus, - } + tenantInfo := v.tenantInfo + result := tree.Datums{ + tree.NewDInt(tree.DInt(tenantInfo.ID)), + tree.NewDString(string(tenantInfo.Name)), + tree.NewDString(string(v.tenantStatus)), } - // This is a 'SHOW TENANT name WITH REPLICATION STATUS' command. - sourceTenantName := tree.DNull - sourceClusterUri := tree.DNull - replicationJobId := tree.NewDInt(tree.DInt(v.tenantInfo.TenantReplicationJobID)) - replicatedTimestamp := tree.DNull - retainedTimestamp := tree.DNull - cutoverTimestamp := tree.DNull + if n.withReplication { + // This is a 'SHOW TENANT name WITH REPLICATION STATUS' command. + sourceTenantName := tree.DNull + sourceClusterUri := tree.DNull + replicationJobId := tree.NewDInt(tree.DInt(tenantInfo.TenantReplicationJobID)) + replicatedTimestamp := tree.DNull + retainedTimestamp := tree.DNull + cutoverTimestamp := tree.DNull - if v.replicationInfo != nil { - sourceTenantName = tree.NewDString(string(v.replicationInfo.IngestionDetails.SourceTenantName)) - sourceClusterUri = tree.NewDString(v.replicationInfo.IngestionDetails.StreamAddress) - if v.replicationInfo.ReplicationLagInfo != nil { - minIngested := v.replicationInfo.ReplicationLagInfo.MinIngestedTimestamp - // The latest fully replicated time. Truncating to the nearest microsecond - // because if we don't, then MakeDTimestamp rounds to the nearest - // microsecond. In that case a user may want to cutover to a rounded-up - // time, which is a time that we may never replicate to. Instead, we show - // a time that we know we replicated to. - replicatedTimestamp, _ = tree.MakeDTimestampTZ(minIngested.GoTime().Truncate(time.Microsecond), time.Nanosecond) - } - // The protected timestamp on the destination cluster. Same as with the - // replicatedTimestamp, we want to show a retained time that is within the - // window (retained to replicated) and not below it. We take a timestamp - // that is greater than the protected timestamp by a microsecond or less - // (it's not exactly ceil but close enough). - retainedCeil := v.protectedTimestamp.GoTime().Truncate(time.Microsecond).Add(time.Microsecond) - retainedTimestamp, _ = tree.MakeDTimestampTZ(retainedCeil, time.Nanosecond) - progress := v.replicationInfo.IngestionProgress - if progress != nil && !progress.CutoverTime.IsEmpty() { - cutoverTimestamp = eval.TimestampToDecimalDatum(progress.CutoverTime) + replicationInfo := v.replicationInfo + if replicationInfo != nil { + sourceTenantName = tree.NewDString(string(replicationInfo.IngestionDetails.SourceTenantName)) + sourceClusterUri = tree.NewDString(replicationInfo.IngestionDetails.StreamAddress) + if replicationInfo.ReplicationLagInfo != nil { + minIngested := replicationInfo.ReplicationLagInfo.MinIngestedTimestamp + // The latest fully replicated time. Truncating to the nearest microsecond + // because if we don't, then MakeDTimestamp rounds to the nearest + // microsecond. In that case a user may want to cutover to a rounded-up + // time, which is a time that we may never replicate to. Instead, we show + // a time that we know we replicated to. + replicatedTimestamp, _ = tree.MakeDTimestampTZ(minIngested.GoTime().Truncate(time.Microsecond), time.Nanosecond) + } + // The protected timestamp on the destination cluster. Same as with the + // replicatedTimestamp, we want to show a retained time that is within the + // window (retained to replicated) and not below it. We take a timestamp + // that is greater than the protected timestamp by a microsecond or less + // (it's not exactly ceil but close enough). + retainedCeil := v.protectedTimestamp.GoTime().Truncate(time.Microsecond).Add(time.Microsecond) + retainedTimestamp, _ = tree.MakeDTimestampTZ(retainedCeil, time.Nanosecond) + progress := replicationInfo.IngestionProgress + if progress != nil && !progress.CutoverTime.IsEmpty() { + cutoverTimestamp = eval.TimestampToDecimalDatum(progress.CutoverTime) + } } - } - return tree.Datums{ - tenantId, - tenantName, - tenantStatus, - sourceTenantName, - sourceClusterUri, - replicationJobId, - replicatedTimestamp, - retainedTimestamp, - cutoverTimestamp, + result = append(result, + sourceTenantName, + sourceClusterUri, + replicationJobId, + replicatedTimestamp, + retainedTimestamp, + cutoverTimestamp, + ) } + + return result } func (n *showTenantNode) Close(_ context.Context) {}