Skip to content

Commit

Permalink
Sprint 3 (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
dey4ss committed May 22, 2023
1 parent 2d5d2d1 commit 185423c
Show file tree
Hide file tree
Showing 16 changed files with 922 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ set(
SOURCES
all_type_variant.hpp
null_value.hpp
operators/abstract_operator.cpp
operators/abstract_operator.hpp
operators/get_table.hpp
operators/print.cpp
operators/print.hpp
operators/table_scan.hpp
operators/table_wrapper.cpp
operators/table_wrapper.hpp
resolve_type.hpp
storage/abstract_attribute_vector.hpp
storage/abstract_segment.hpp
storage/chunk.cpp
storage/chunk.hpp
storage/dictionary_segment.cpp
storage/dictionary_segment.hpp
storage/reference_segment.cpp
storage/reference_segment.hpp
storage/storage_manager.cpp
storage/storage_manager.hpp
storage/table.cpp
Expand Down
27 changes: 27 additions & 0 deletions src/lib/operators/abstract_operator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "abstract_operator.hpp"

namespace opossum {

AbstractOperator::AbstractOperator(const std::shared_ptr<const AbstractOperator> left,
const std::shared_ptr<const AbstractOperator> right)
: _left_input(left), _right_input(right) {}

void AbstractOperator::execute() {
_output = _on_execute();
}

std::shared_ptr<const Table> AbstractOperator::get_output() const {
// TODO(student): You should place some meaningful checks here

return _output;
}

std::shared_ptr<const Table> AbstractOperator::_left_input_table() const {
return _left_input->get_output();
}

std::shared_ptr<const Table> AbstractOperator::_right_input_table() const {
return _right_input->get_output();
}

} // namespace opossum
59 changes: 59 additions & 0 deletions src/lib/operators/abstract_operator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#pragma once

#include <memory>

#include "types.hpp"

namespace opossum {

class Table;

// AbstractOperator is the abstract super class for all operators. All operators have up to two input tables and one
// output table. Their lifecycle has three phases:
// 1. The operator is constructed. Previous operators are not guaranteed to have already executed, so operators must not
// call get_output in their execute method
// 2. The execute method is called from the outside (usually by the scheduler). This is where the heavy lifting is done.
// By now, the input operators have already executed.
// 3. The consumer (usually another operator) calls get_output. This should be very cheap. It is only guaranteed to
// succeed if execute was called before. Otherwise, a nullptr or an empty table could be returned.
//
// Operators shall not be executed twice.

class AbstractOperator : private Noncopyable {
public:
AbstractOperator(const std::shared_ptr<const AbstractOperator> left = nullptr,
const std::shared_ptr<const AbstractOperator> right = nullptr);

virtual ~AbstractOperator() = default;

// We need to explicitly set the move constructor to default when we overwrite the copy constructor.
AbstractOperator(AbstractOperator&&) = default;
AbstractOperator& operator=(AbstractOperator&&) = default;

void execute();

// Returns the result of the operator.
std::shared_ptr<const Table> get_output() const;

// Get the input operators.
std::shared_ptr<const AbstractOperator> left_input() const;
std::shared_ptr<const AbstractOperator> right_input() const;

protected:
// Abstract method to actually execute the operator execute and get_output are split into two methods to allow for
// easier asynchronous execution.
virtual std::shared_ptr<const Table> _on_execute() = 0;

std::shared_ptr<const Table> _left_input_table() const;
std::shared_ptr<const Table> _right_input_table() const;

// Shared pointers to input operators. Can be nullptr, for example, if an operator is the leaf operator in the query
// plan or if the operator has only one input operator.
std::shared_ptr<const AbstractOperator> _left_input;
std::shared_ptr<const AbstractOperator> _right_input;

// Is nullptr until the operator is executed.
std::shared_ptr<const Table> _output;
};

} // namespace opossum
27 changes: 27 additions & 0 deletions src/lib/operators/get_table.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "abstract_operator.hpp"
#include "utils/assert.hpp"

namespace opossum {

// Operator to retrieve a table from the StorageManager by specifying its name.
class GetTable : public AbstractOperator {
public:
explicit GetTable(const std::string& name) {
// TODO(student) implement it in a source file and change this to a declaration.
}

const std::string& table_name() const {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}

protected:
std::shared_ptr<const Table> _on_execute() override {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}
};

} // namespace opossum
110 changes: 110 additions & 0 deletions src/lib/operators/print.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "print.hpp"

#include <iomanip>

#include "operators/table_wrapper.hpp"
#include "storage/abstract_segment.hpp"
#include "storage/table.hpp"
#include "type_cast.hpp"

namespace {

using namespace opossum; // NOLINT(build/namespaces)

std::string print_column_type(const std::shared_ptr<const Table>& table, const ColumnID column_id) {
auto stream = std::stringstream{};
stream << table->column_type(column_id);
if (table->column_nullable(column_id)) {
stream << "_null";
}

return stream.str();
}

} // namespace

namespace opossum {

Print::Print(const std::shared_ptr<const AbstractOperator> in, std::ostream& out) : AbstractOperator(in), _out(out) {}

void Print::print(std::shared_ptr<const Table>& table, std::ostream& out) {
auto table_wrapper = std::make_shared<TableWrapper>(table);
table_wrapper->execute();
Print(table_wrapper, out).execute();
}

std::shared_ptr<const Table> Print::_on_execute() {
auto widths = _column_string_widths(8, 20, _left_input_table());

// Print column headers.
_out << "=== Columns" << std::endl;
const auto left_column_count = _left_input_table()->column_count();
for (auto column_id = ColumnID{0}; column_id < left_column_count; ++column_id) {
_out << "|" << std::setw(widths[column_id]) << _left_input_table()->column_name(column_id) << std::setw(0);
}
_out << "|" << std::endl;
for (auto column_id = ColumnID{0}; column_id < left_column_count; ++column_id) {
_out << "|" << std::setw(widths[column_id]) << print_column_type(_left_input_table(), column_id) << std::setw(0);
}
_out << "|" << std::endl;

// print each chunk
const auto left_chunk_count = _left_input_table()->chunk_count();
for (auto chunk_id = ChunkID{0}; chunk_id < left_chunk_count; ++chunk_id) {
const auto chunk = _left_input_table()->get_chunk(chunk_id);

_out << "=== Chunk " << chunk_id << " === " << std::endl;

if (chunk->size() == 0) {
_out << "Empty chunk." << std::endl;
continue;
}

// Print the rows in the chunk.
const auto chunk_size = chunk->size();
for (size_t row = 0; row < chunk_size; ++row) {
_out << "|";
const auto column_count = chunk->column_count();
for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
// Yes, we use AbstractSegment::operator[] here, but since Print is not an operation that should be part of a
// regular query plan, let's keep things simple here.
_out << std::setw(widths[column_id]) << (*chunk->get_segment(column_id))[row] << "|" << std::setw(0);
}

_out << std::endl;
}
}

return _left_input_table();
}

// In order to print the table as an actual table, with columns being aligned, we need to calculate the number of
// characters in the printed representation of each column `min` and `max` can be used to limit the width of the
// columns - however, every column fits at least the column's name.
std::vector<uint16_t> Print::_column_string_widths(uint16_t min, uint16_t max,
const std::shared_ptr<const Table>& table) const {
auto widths = std::vector<uint16_t>(table->column_count());
// Calculate the length of the column name.
const auto column_count = table->column_count();
for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
widths[column_id] = std::max(min, static_cast<uint16_t>(table->column_name(column_id).size()));
}

// Go over all rows and find the maximum length of the printed representation of a value, up to max.
const auto left_chunk_count = _left_input_table()->chunk_count();
for (auto chunk_id = ChunkID{0}; chunk_id < left_chunk_count; ++chunk_id) {
auto chunk = _left_input_table()->get_chunk(chunk_id);

const auto column_count = chunk->column_count();
for (auto column_id = ColumnID{0}; column_id < column_count; ++column_id) {
for (auto row = size_t{0}; row < chunk->size(); ++row) {
auto cell_length =
static_cast<uint16_t>(boost::lexical_cast<std::string>((*chunk->get_segment(column_id))[row]).size());
widths[column_id] = std::max({min, widths[column_id], std::min(max, cell_length)});
}
}
}
return widths;
}

} // namespace opossum
24 changes: 24 additions & 0 deletions src/lib/operators/print.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include "abstract_operator.hpp"

namespace opossum {

/**
* operator to print the table with its data
*/
class Print : public AbstractOperator {
public:
explicit Print(const std::shared_ptr<const AbstractOperator> in, std::ostream& out = std::cout);

static void print(std::shared_ptr<const Table>& table, std::ostream& out = std::cout);

protected:
std::vector<uint16_t> _column_string_widths(uint16_t min, uint16_t max,
const std::shared_ptr<const Table>& table) const;
std::shared_ptr<const Table> _on_execute() override;

// stream to print the result
std::ostream& _out;
};
} // namespace opossum
37 changes: 37 additions & 0 deletions src/lib/operators/table_scan.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include "abstract_operator.hpp"
#include "utils/assert.hpp"

namespace opossum {

class TableScan : public AbstractOperator {
public:
TableScan(const std::shared_ptr<const AbstractOperator>& in, const ColumnID column_id, const ScanType scan_type,
const AllTypeVariant search_value) {
// TODO(student) implement it in a source file and change this to a declaration.
}

ColumnID column_id() const {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}

ScanType scan_type() const {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}

const AllTypeVariant& search_value() const {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}

protected:
std::shared_ptr<const Table> _on_execute() override {
// TODO(student) implement it in a source file and change this to a declaration.
Fail("Implementation missing.");
}
};

} // namespace opossum
10 changes: 10 additions & 0 deletions src/lib/operators/table_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "table_wrapper.hpp"

namespace opossum {

TableWrapper::TableWrapper(const std::shared_ptr<const Table>& table) : _table(table) {}

std::shared_ptr<const Table> TableWrapper::_on_execute() {
return _table;
}
} // namespace opossum
21 changes: 21 additions & 0 deletions src/lib/operators/table_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "abstract_operator.hpp"
#include "utils/assert.hpp"

namespace opossum {

/**
* Operator that wraps a table.
*/
class TableWrapper : public AbstractOperator {
public:
explicit TableWrapper(const std::shared_ptr<const Table>& table);

protected:
std::shared_ptr<const Table> _on_execute() override;

// Table to retrieve
const std::shared_ptr<const Table> _table;
};
} // namespace opossum
43 changes: 43 additions & 0 deletions src/lib/storage/reference_segment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "reference_segment.hpp"

#include "storage/table.hpp"
#include "utils/assert.hpp"

namespace opossum {

ReferenceSegment::ReferenceSegment(const std::shared_ptr<const Table>& referenced_table,
const ColumnID referenced_column_id, const std::shared_ptr<const PosList>& pos) {
// Implementation goes here
}

AllTypeVariant ReferenceSegment::operator[](const ChunkOffset chunk_offset) const {
// Implementation goes here
Fail("Implementation is missing.");
}

ChunkOffset ReferenceSegment::size() const {
// Implementation goes here
Fail("Implementation is missing.");
}

const std::shared_ptr<const PosList>& ReferenceSegment::pos_list() const {
// Implementation goes here
Fail("Implementation is missing.");
}

const std::shared_ptr<const Table>& ReferenceSegment::referenced_table() const {
// Implementation goes here
Fail("Implementation is missing.");
}

ColumnID ReferenceSegment::referenced_column_id() const {
// Implementation goes here
Fail("Implementation is missing.");
}

size_t ReferenceSegment::estimate_memory_usage() const {
// Implementation goes here
Fail("Implementation is missing.");
}

} // namespace opossum
Loading

0 comments on commit 185423c

Please sign in to comment.