blob: b3109f9ebd03cfc1adcc60b2c15678e7e995ae84 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#include "cli/CommandExecutorUtil.hpp"
#include <algorithm>
#include <cstddef>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogDatabase.hpp"
#include "catalog/CatalogRelation.hpp"
#include "catalog/IndexScheme.hpp"
#include "catalog/PartitionScheme.hpp"
#include "cli/PrintToScreen.hpp"
#include "parser/ParseString.hpp"
#include "storage/StorageBlockLayout.pb.h"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "utility/PtrVector.hpp"
#include "utility/SqlError.hpp"
#include "utility/StringUtil.hpp"
using std::ostringstream;
using std::setw;
using std::size_t;
using std::string;
using std::vector;
namespace quickstep {
namespace cli {
namespace {
// Adding the max column width as 6 as the default initializer
// as the length of the word Column is 6 characters.
// This is used while describing the table.
constexpr int kInitMaxColumnWidth = 6;
} // namespace
string ExecuteDescribeDatabase(
const PtrVector<ParseString> &arguments,
const CatalogDatabase &catalog_database) {
// Column width initialized to 6 to take into account the header name
// and the column value table
int max_column_width = kInitMaxColumnWidth;
vector<std::size_t> num_blocks;
const CatalogRelation *relation = nullptr;
if (arguments.empty()) {
for (const CatalogRelation &rel : catalog_database) {
max_column_width =
std::max(static_cast<int>(rel.getName().length()), max_column_width);
num_blocks.push_back(rel.size_blocks());
}
} else {
const ParseString &table_name = arguments.front();
const std::string &table_name_val = table_name.value();
relation = catalog_database.getRelationByName(table_name_val);
if (relation == nullptr) {
THROW_SQL_ERROR_AT(&(arguments.front())) << " Unrecognized relation " << table_name_val;
}
max_column_width = std::max(static_cast<int>(relation->getName().length()),
max_column_width);
num_blocks.push_back(relation->size_blocks());
}
ostringstream oss;
// Only if we have relations work on the printing logic.
if (!catalog_database.empty()) {
const std::size_t max_num_blocks = *std::max_element(num_blocks.begin(), num_blocks.end());
const int max_num_blocks_digits = std::max(PrintToScreen::GetNumberOfDigits(max_num_blocks),
kInitMaxColumnWidth + 2);
oss << " List of relations\n\n"
<< std::left << setw(max_column_width + 1) << " Name" << " |"
<< setw(kInitMaxColumnWidth) << " Type" << " |"
<< setw(max_num_blocks_digits) << " Blocks" << '\n'
<< PrintToScreen::GenerateHBar({ max_column_width + 1, kInitMaxColumnWidth + 1, max_num_blocks_digits + 1 });
// If there are no argument print the entire list of tables
// else print the particular table only.
vector<std::size_t>::const_iterator num_blocks_it = num_blocks.begin();
if (arguments.empty()) {
for (const CatalogRelation &rel : catalog_database) {
oss << ' ' << setw(max_column_width) << rel.getName() << " |"
<< setw(kInitMaxColumnWidth) << " table" << " | "
<< setw(max_num_blocks_digits - 1) << *num_blocks_it << '\n';
++num_blocks_it;
}
} else {
oss << ' ' << setw(max_column_width) << relation->getName() << " |"
<< setw(kInitMaxColumnWidth) << " table" << " | "
<< setw(max_num_blocks_digits - 1) << *num_blocks_it << '\n';
++num_blocks_it;
}
oss << '\n';
}
return oss.str();
}
string ExecuteDescribeTable(
const PtrVector<ParseString> &arguments,
const CatalogDatabase &catalog_database) {
const ParseString &table_name = arguments.front();
const std::string &table_name_val = table_name.value();
const CatalogRelation *relation =
catalog_database.getRelationByName(table_name_val);
if (relation == nullptr) {
THROW_SQL_ERROR_AT(&(arguments.front())) << " Unrecognized relation " << table_name_val;
}
int max_attr_column_width = kInitMaxColumnWidth;
int max_type_column_width = kInitMaxColumnWidth;
for (const CatalogAttribute &attr : *relation) {
// Printed column needs to be wide enough to print:
// 1. The attribute name (in the printed "header").
// 2. Any value of the attribute's Type.
max_attr_column_width =
std::max(max_attr_column_width,
static_cast<int>(attr.getDisplayName().length()));
max_type_column_width =
std::max(max_type_column_width,
static_cast<int>(attr.getType().getName().length()));
}
ostringstream oss;
oss << setw(kInitMaxColumnWidth) << "Table" << " \"" << table_name_val << "\"\n"
<< std::left << setw(max_attr_column_width + 1) << " Column" << " |"
<< setw(max_type_column_width + 1) << " Type" << '\n';
// Add room for one extra character to allow spacing between the column ending and the vertical bar
oss << PrintToScreen::GenerateHBar({ max_attr_column_width + 1, max_type_column_width + 1 });
for (const CatalogAttribute &attr : *relation) {
oss << ' ' << setw(max_attr_column_width) << attr.getDisplayName() << " | "
<< setw(max_type_column_width) << attr.getType().getName() << '\n';
}
if (relation->hasIndexScheme()) {
oss << setw(kInitMaxColumnWidth + 2) << " Indexes" << '\n';
for (const auto &index : relation->getIndexScheme()) {
const IndexSubBlockDescription &index_description = index.second;
oss << " \"" << index.first << "\" "
<< index_description.IndexSubBlockType_Name(index_description.sub_block_type())
<< " ("
<< relation->getAttributeById(index_description.indexed_attribute_ids(0))->getDisplayName();
for (int i = 1; i < index_description.indexed_attribute_ids_size(); ++i) {
oss << ", " << relation->getAttributeById(index_description.indexed_attribute_ids(i))->getDisplayName();
}
oss << ")\n";
}
}
if (relation->hasPartitionScheme()) {
oss << setw(kInitMaxColumnWidth + 2) << " Partition Info\n "
<< relation->getPartitionScheme()->toString(*relation);
}
return oss.str();
}
} // namespace cli
} // namespace quickstep