blob: b655c204005427411c26024ffdbc90f81afcb51e [file]
/**
* Copyright 2011-2015 Quickstep Technologies LLC.
* Copyright 2015 Pivotal Software, Inc.
*
* Licensed 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/PrintToScreen.hpp"
#include <cstddef>
#include <cstdio>
#include <memory>
#include <vector>
#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogRelation.hpp"
#include "storage/StorageBlock.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "types/TypedValue.hpp"
#include "storage/StorageManager.hpp"
#include "storage/TupleIdSequence.hpp"
#include "storage/TupleStorageSubBlock.hpp"
#include "types/Type.hpp"
#include "utility/Macros.hpp"
#include "gflags/gflags.h"
using std::fprintf;
using std::fputc;
using std::size_t;
using std::vector;
namespace quickstep {
DEFINE_bool(printing_enabled, true,
"If true, print query results to screen normally. If false, skip "
"printing output (e.g. for benchmarking).");
void PrintToScreen::computeColumnWidths() {
column_widths_.reserve(relation_.size());
for (CatalogRelation::const_iterator attr_it = relation_.begin();
attr_it != relation_.end();
++attr_it) {
// 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.
// 3. If the attribute's Type is nullable, the 4-character string "NULL".
// We pick the largest of these 3 widths as the column width.
int column_width = static_cast<int>(attr_it->getDisplayName().length());
column_width = column_width < attr_it->getType().getPrintWidth()
? attr_it->getType().getPrintWidth()
: column_width;
column_width = attr_it->getType().isNullable() && (column_width < 4)
? 4
: column_width;
column_widths_.push_back(column_width);
}
}
void PrintToScreen::printRelation(FILE *out) {
if (!FLAGS_printing_enabled) {
return;
}
printHeader(out);
std::vector<block_id> blocks = relation_.getBlocksSnapshot();
for (const block_id current_block_id : blocks) {
printBlock(current_block_id, out);
}
printHBar(out);
}
void PrintToScreen::printHeader(FILE *out) const {
if (!FLAGS_printing_enabled) {
return;
}
printHBar(out);
fputc('|', out);
vector<int>::const_iterator width_it = column_widths_.begin();
CatalogRelation::const_iterator attr_it = relation_.begin();
for (; width_it != column_widths_.end(); ++width_it, ++attr_it) {
fprintf(out, "%-*s|", *width_it, attr_it->getDisplayName().c_str());
}
fputc('\n', out);
printHBar(out);
}
void PrintToScreen::printBlock(block_id bid, FILE *out) {
if (!FLAGS_printing_enabled) {
return;
}
BlockReference block = storage_manager_->getBlock(bid, relation_);
const TupleStorageSubBlock &tuple_store = block->getTupleStorageSubBlock();
if (tuple_store.isPacked()) {
for (tuple_id tid = 0; tid <= tuple_store.getMaxTupleID(); ++tid) {
printTuple(tuple_store, tid, out);
}
} else {
std::unique_ptr<TupleIdSequence> existence_map(
tuple_store.getExistenceMap());
for (tuple_id tid : *existence_map) {
printTuple(tuple_store, tid, out);
}
}
}
void PrintToScreen::printHBar(FILE *out) const {
fputc('+', out);
for (const int width : column_widths_) {
for (int i = 0; i < width; ++i) {
fputc('-', out);
}
fputc('+', out);
}
fputc('\n', out);
}
void PrintToScreen::printTuple(const TupleStorageSubBlock &tuple_store,
const tuple_id tid,
FILE *out) const {
DEBUG_ASSERT(tuple_store.hasTupleWithID(tid));
fputc('|', out);
const CatalogRelationSchema &relation = tuple_store.getRelation();
vector<int>::const_iterator width_it = column_widths_.begin();
CatalogRelation::const_iterator attr_it = relation.begin();
for (; attr_it != relation.end(); ++attr_it, ++width_it) {
TypedValue value(
tuple_store.getAttributeValueTyped(tid, attr_it->getID()));
if (value.isNull()) {
fprintf(out, "%*s", *width_it, "NULL");
} else {
attr_it->getType().printValueToFile(value, out, *width_it);
}
fputc('|', out);
}
fputc('\n', out);
}
} // namespace quickstep