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

     1  // Copyright 2019 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 delegate
    12  
    13  import (
    14  	"fmt"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/sql/lex"
    17  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
    22  	"github.com/cockroachdb/errors"
    23  )
    24  
    25  func (d *delegator) delegateShowPartitions(n *tree.ShowPartitions) (tree.Statement, error) {
    26  	sqltelemetry.IncrementShowCounter(sqltelemetry.Partitions)
    27  	if n.IsTable {
    28  		flags := cat.Flags{AvoidDescriptorCaches: true, NoTableStats: true}
    29  		tn := n.Table.ToTableName()
    30  
    31  		dataSource, resName, err := d.catalog.ResolveDataSource(d.ctx, flags, &tn)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  		if err := d.catalog.CheckAnyPrivilege(d.ctx, dataSource); err != nil {
    36  			return nil, err
    37  		}
    38  
    39  		// We use the raw_config_sql from the partition_lookup result to get the
    40  		// official zone config for the partition, and use the full_config_sql from the zones table
    41  		// which is the result of looking up the partition's inherited zone configuraion.
    42  		const showTablePartitionsQuery = `
    43  		SELECT
    44  			tables.database_name,
    45  			tables.name AS table_name,
    46  			partitions.name AS partition_name,
    47  			partitions.parent_name AS parent_partition,
    48  			partitions.column_names,
    49  			concat(tables.name, '@', table_indexes.index_name) AS index_name,
    50  			coalesce(partitions.list_value, partitions.range_value) as partition_value,
    51  			replace(regexp_extract(partition_lookup.raw_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as zone_config,
    52  			replace(regexp_extract(zones.full_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as full_zone_config
    53  		FROM
    54  			%[3]s.crdb_internal.partitions
    55  			JOIN %[3]s.crdb_internal.tables ON partitions.table_id = tables.table_id
    56  			JOIN %[3]s.crdb_internal.table_indexes ON
    57  					table_indexes.descriptor_id = tables.table_id
    58  					AND table_indexes.index_id = partitions.index_id
    59  			LEFT JOIN %[3]s.crdb_internal.zones ON
    60  					partitions.zone_id = zones.zone_id
    61  					AND partitions.subzone_id = zones.subzone_id
    62  			LEFT JOIN %[3]s.crdb_internal.zones AS partition_lookup ON
    63  				partition_lookup.database_name = tables.database_name
    64  				AND partition_lookup.table_name = tables.name
    65  				AND partition_lookup.index_name = table_indexes.index_name
    66  				AND partition_lookup.partition_name = partitions.name
    67  		WHERE
    68  			tables.name = %[1]s AND tables.database_name = %[2]s;
    69  		`
    70  		return parse(fmt.Sprintf(showTablePartitionsQuery,
    71  			lex.EscapeSQLString(resName.Table()),
    72  			lex.EscapeSQLString(resName.Catalog()),
    73  			resName.CatalogName.String()))
    74  	} else if n.IsDB {
    75  		const showDatabasePartitionsQuery = `
    76  		SELECT
    77  			tables.database_name,
    78  			tables.name AS table_name,
    79  			partitions.name AS partition_name,
    80  			partitions.parent_name AS parent_partition,
    81  			partitions.column_names,
    82  			concat(tables.name, '@', table_indexes.index_name) AS index_name,
    83  			coalesce(partitions.list_value, partitions.range_value) as partition_value,
    84  			replace(regexp_extract(partition_lookup.raw_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as zone_config,
    85  			replace(regexp_extract(zones.full_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as full_zone_config
    86  		FROM
    87  			%[1]s.crdb_internal.partitions
    88  			JOIN %[1]s.crdb_internal.tables ON partitions.table_id = tables.table_id
    89  			JOIN %[1]s.crdb_internal.table_indexes ON
    90  					table_indexes.descriptor_id = tables.table_id
    91  					AND table_indexes.index_id = partitions.index_id
    92  			LEFT JOIN %[1]s.crdb_internal.zones ON
    93  					partitions.zone_id = zones.zone_id
    94  					AND partitions.subzone_id = zones.subzone_id
    95  			LEFT JOIN %[1]s.crdb_internal.zones AS partition_lookup ON
    96  				partition_lookup.database_name = tables.database_name
    97  				AND partition_lookup.table_name = tables.name
    98  				AND partition_lookup.index_name = table_indexes.index_name
    99  				AND partition_lookup.partition_name = partitions.name
   100  		WHERE
   101  			tables.database_name = %[2]s
   102  		ORDER BY
   103  			tables.name, partitions.name;
   104  		`
   105  		// Note: n.Database.String() != string(n.Database)
   106  		return parse(fmt.Sprintf(showDatabasePartitionsQuery, n.Database.String(), lex.EscapeSQLString(string(n.Database))))
   107  	}
   108  
   109  	flags := cat.Flags{AvoidDescriptorCaches: true, NoTableStats: true}
   110  	tn := n.Index.Table
   111  
   112  	// Throw a more descriptive error if the user did not use the index hint syntax.
   113  	if tn.ObjectName == "" {
   114  		err := errors.New("no table specified")
   115  		err = pgerror.WithCandidateCode(err, pgcode.InvalidParameterValue)
   116  		err = errors.WithHint(err, "Specify a table using the hint syntax of table@index")
   117  		return nil, err
   118  	}
   119  
   120  	dataSource, resName, err := d.catalog.ResolveDataSource(d.ctx, flags, &tn)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	if err := d.catalog.CheckAnyPrivilege(d.ctx, dataSource); err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	// Force resolution of the index.
   130  	_, _, err = cat.ResolveTableIndex(d.ctx, d.catalog, flags, &n.Index)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	const showIndexPartitionsQuery = `
   136  	SELECT
   137  		tables.database_name,
   138  		tables.name AS table_name,
   139  		partitions.name AS partition_name,
   140  		partitions.parent_name AS parent_partition,
   141  		partitions.column_names,
   142  		concat(tables.name, '@', table_indexes.index_name) AS index_name,
   143  		coalesce(partitions.list_value, partitions.range_value) as partition_value,
   144  		replace(regexp_extract(partition_lookup.raw_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as zone_config,
   145  		replace(regexp_extract(zones.full_config_sql, 'CONFIGURE ZONE USING\n((?s:.)*)'), e'\t', '') as full_zone_config
   146  	FROM
   147  		%[5]s.crdb_internal.partitions
   148  		JOIN %[5]s.crdb_internal.table_indexes ON
   149  				partitions.index_id = table_indexes.index_id
   150  				AND partitions.table_id = table_indexes.descriptor_id
   151  		JOIN %[5]s.crdb_internal.tables ON table_indexes.descriptor_id = tables.table_id
   152  		LEFT JOIN %[5]s.crdb_internal.zones ON
   153  			partitions.zone_id = zones.zone_id
   154  			AND partitions.subzone_id = zones.subzone_id
   155  		LEFT JOIN %[5]s.crdb_internal.zones AS partition_lookup ON
   156  			partition_lookup.database_name = tables.database_name
   157  			AND partition_lookup.table_name = tables.name
   158  			AND partition_lookup.index_name = table_indexes.index_name
   159  			AND partition_lookup.partition_name = partitions.name
   160  	WHERE
   161  		table_indexes.index_name = %[1]s AND tables.name = %[2]s;
   162  	`
   163  	return parse(fmt.Sprintf(showIndexPartitionsQuery,
   164  		lex.EscapeSQLString(n.Index.Index.String()),
   165  		lex.EscapeSQLString(resName.Table()),
   166  		resName.Table(),
   167  		n.Index.Index.String(),
   168  		// note: CatalogName.String() != Catalog()
   169  		resName.CatalogName.String()))
   170  }