Setting up BeeDB for summer semester 2024

This commit is contained in:
Roland Kühn 2024-04-14 16:35:04 +02:00
commit 4cc3333444
226 changed files with 52399 additions and 0 deletions

127
.clang-format Normal file
View File

@ -0,0 +1,127 @@
---
Language: Cpp
# BasedOnStyle: Microsoft
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Never
...

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
*.o
build
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles/
Makefile
bee.db
cmake_install.cmake
lib/include/
lib/libsqlparser.so
patch/*
**/.DS_Store

29
.pre-commit-hook Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
STYLE=$(git config --get hooks.clangformat.style)
if [ -n "${STYLE}" ] ; then
STYLEARG="-style=${STYLE}"
else
STYLEARG=""
fi
format_file() {
file="${1}"
if [ -f $file ]; then
if [ "${file##*.}" = "cpp" ] || [ "${file##*.}" = "h" ] || [ "${file##*.}" = "hpp" ]; then
clang-format -i ${STYLEARG} ${1}
git add ${1}
fi
fi
}
case "${1}" in
--about )
echo "Runs clang-format on source files"
;;
* )
for file in `git diff-index --cached --name-only HEAD` ; do
format_file "${file}"
done
;;
esac

128
CMakeLists.txt Normal file
View File

@ -0,0 +1,128 @@
include(ExternalProject)
cmake_minimum_required(VERSION 3.9)
project(BeeDB)
## Set default settings
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Wno-unused")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g -DNDEBUG")
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE DEBUG) # "Debug" is default build type, if nothing is defined
endif()
message( "Setting up '" ${CMAKE_BUILD_TYPE} "' build.")
## External dependencies
find_package(BISON REQUIRED)
find_package(FLEX REQUIRED)
## Include and link directories
include_directories(${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/lib/ ${PROJECT_SOURCE_DIR}/lib/linenoise ${PROJECT_SOURCE_DIR}/include/parser)
link_directories(${PROJECT_SOURCE_DIR}/lib)
## Add Parser targets
BISON_TARGET(parser
src/parser/parser.yy
src/parser/parser.cpp
DEFINES_FILE include/parser/parser.hpp
VERBOSE
COMPILE_FLAGS "--defines --language=C++"
)
FLEX_TARGET(lexer
src/parser/scanner.ll
src/parser/scanner.cpp
COMPILE_FLAGS "--c+ -i"
)
ADD_FLEX_BISON_DEPENDENCY(lexer parser)
## BeeDB Server Sources
add_executable(beedb
lib/linenoise/linenoise.c
${FLEX_lexer_OUTPUTS}
${BISON_parser_OUTPUTS}
src/beedb_server.cpp
src/database.cpp
src/concurrency/transaction_manager.cpp
src/concurrency/transaction_visibility.cpp
src/storage/manager.cpp
src/buffer/manager.cpp
src/buffer/random_strategy.cpp
src/buffer/lru_strategy.cpp
src/buffer/lru_k_strategy.cpp
src/buffer/lfu_strategy.cpp
src/buffer/clock_strategy.cpp
src/table/table.cpp
src/table/column.cpp
src/table/value.cpp
src/table/table_disk_manager.cpp
src/parser/driver.cpp
src/parser/sql_parser.cpp
src/execution/binary_operator.cpp
src/execution/sequential_scan_operator.cpp
src/execution/index_scan_operator.cpp
src/execution/create_table_operator.cpp
src/execution/create_index_operator.cpp
src/execution/insert_operator.cpp
src/execution/selection_operator.cpp
src/execution/projection_operator.cpp
src/execution/nested_loops_join_operator.cpp
src/execution/hash_join_operator.cpp
src/execution/limit_operator.cpp
src/execution/build_index_operator.cpp
src/execution/order_operator.cpp
src/execution/aggregate_operator.cpp
src/execution/cross_product_operator.cpp
src/execution/tuple_buffer_operator.cpp
src/execution/add_to_index_operator.cpp
src/execution/update_operator.cpp
src/execution/delete_operator.cpp
src/execution/transaction_operator.cpp
src/execution/arithmetic_operator.cpp
src/expression/operation.cpp
src/plan/physical/plan.cpp
src/plan/logical/builder.cpp
src/plan/logical/plan_view.cpp
src/plan/physical/builder.cpp
src/io/executor.cpp
src/io/file_executor.cpp
src/io/result_output_formatter.cpp
src/io/command/commander.cpp
src/io/command/custom_commands.cpp
src/io/client_handler.cpp
src/io/client_console.cpp
src/io/query_result_serializer.cpp
src/util/text_table.cpp
src/util/ini_parser.cpp
src/util/random_generator.cpp
src/plan/optimizer/optimizer.cpp
src/plan/optimizer/rule/index_scan_optimization_rule.cpp
src/plan/optimizer/rule/hash_join_optimization_rule.cpp
src/plan/optimizer/rule/swap_operands_optimization_rule.cpp
src/plan/optimizer/rule/predicate_push_down_optimization_rule.cpp
src/plan/optimizer/rule/remove_projection_optimization_rule.cpp
src/plan/optimizer/rule/cross_product_optimization_rule.cpp
src/plan/optimizer/rule/merge_selection_optimization_rule.cpp
src/network/server.cpp
src/network/client.cpp
src/boot/execution_callback.cpp
)
add_executable(beedb_client
lib/linenoise/linenoise.c
src/beedb_client.cpp
src/io/client_console.cpp
src/io/result_output_formatter.cpp
src/util/text_table.cpp
src/network/client.cpp
)
## Build target
target_link_libraries(beedb pthread)
## Git install hook target
add_custom_target(git-hook cp ${PROJECT_SOURCE_DIR}/.pre-commit-hook ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit && chmod +x ${PROJECT_SOURCE_DIR}/.git/hooks/pre-commit)

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 TheScriptbot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

114
README.md Normal file
View File

@ -0,0 +1,114 @@
![BeeDB](logo.png)
Welcome to **BeeDB**, the educational DBMS tailored for the course **Architecture and Implementation of DBMS**.
BeeDB bridges theory and practice, fostering a deep understanding of DBMS structures and operations.
Dive into the world of databases with BeeDB, your gateway to mastering database management.
**Architecture and Implementation of DBMS** is usually taught every summer term, see [dbis page of TU Dortmund](http://dbis.cs.tu-dortmund.de/cms/en/teaching/index.html) for more information.
## Dependencies
* `git`
* `cmake` (at least version `3.9`)
* `build-essential`
* `bison` and `flex` (and in Ubuntu the package `libfl-dev`)
## How to build
### Option (a): Build into current folder:
* `cmake .`
* `make` (or `make -j` for parallel compilation)
### Option (b): Build into separate `build` folder:
* `mkdir build && cd build`
* `cmake ..`
* `make` (or `make -j` for parallel compilation)
### Switch between `Release` and `Debug` modes
* Default build is in `Debug` mode.
* If you want to build in `Release` mode use:
* `cmake . -DCMAKE_BUILD_TYPE=Release`
* **or** set `CMAKE_BUILD_TYPE` in `CMakeLists.txt`.
## How to use
BeeDB uses a client/server model where the executable `beedb` starts the server and `beedb_client` runs a client.
### Server
Usage: beedb [options] db-file
Positional arguments:
db-file File the database is stored in. Default: bee.db
Optional arguments:
-h --help show this help message and exit
-p --port Port of the server
-l --load Load SQL file into database.
-q --query Execute Query.
-cmd --custom_command Execute custom command and exit right after.
-k --keep Keep server running after executing query, command or loading a file.
-c --client Start an additional client next to the server
--buffer-manager-frames Number of frames within the frame buffer.
--scan-page-limit Number of pages the SCAN operator can pin at a time.
--enable-index-scan Enable index scan and use whenever possible.
--enable-hash-join Enable hash join and use whenever possible.
--enable-predicate-push-down Enable predicate push down and use whenever possible.
--stats Print all execution statistics
### Client
Usage: beedb_client [options] host
Positional arguments:
host Name or IP of the beedb server
Optional arguments:
-h --help show this help message and exit
-p --port Port of the server
### Please note!
Just stopping the server by killing (or `Ctrl-C`) crashes the server; you may lose (unflushed) data.
To stop the server clean, use `:stop` command by a client.
## Configuration
Some configuration outside the console arguments is stored in the file `beedb.ini`.
* The number of pages stored as frames in the buffer manager (`buffer manager.frames`)
* The replacement strategy of frames in the buffer manager (`buffer manager.strategy`)
* The `k` parameter for `LRU-K` replacement strategy (`buffer manager.k`)
* The number of how many pages can be pinned by a scan at a time (`scan.page-limit`)
* Enable or disable usage of index scan (`optimizer.enable-index-scan`)
* Enable or disable usage of hash join (`optimizer.enable-hash-join`)
* Enable or disable predicate push down (`optimizer.enable-predicate-push-down`)
## Non-SQL Commands
Despite SQL commands, you can use the following special commands from the client.
* `:explain <query>`: prints the query plan, either as a table or a graph (a list of nodes and edges)
* `:get <option-name>`: prints either all or the secified option of the database configuration
* `:set <option-name> <numerical-value>`: changes the specified option. Only numerical values are valid
* `:show [tables,indices,columns]`: A quick way to show available tables, their columns or indices
* `:stop`: Stops the server (and flushes all data to the disk).
## Examples
##### Import and SQL file (containing `CREATE` and `INSERT`)
`./beedb -l movies.sql`
##### Run a single query and terminate
`./beedb -q "SELECT * FROM movie;"`
##### Run a query and open console afterwards
`./beedb -q "SELECT * FROM movie;" -c`
##### Start the BeeDB server only (connect clients later)
`./beedb`
##### Start the BeeDB server and open a client console
`./beedb -c`
#### Start a BeeDB client (you can start multiple ones)
`./beedb_client`
# For developers
* If you want to commit to the repository please `make git-hook` before commit.
# Credits
* Thanks to **p-ranav** for `argparse` (MIT license, [See on GitHub](https://github.com/p-ranav/argparse)).
* Thanks to **antirez** for `linenoise` (BSD license, [See on Github](https://github.com/antirez/linenoise)).
* Thanks to **nlohmann** and further contributors for `nlohmann_json` (MIT license, [See on GitHub](https://github.com/nlohmann/json)).

15
beedb.ini Normal file
View File

@ -0,0 +1,15 @@
[buffer manager]
frames = 256
strategy = Random ; Random | LRU-K | LFU | LRU | CLOCK
k = 2 ; LRU-K parameter
[scan]
page-limit = 64
[optimizer]
enable-index-scan = 0 ; 1 for enable index scan
enable-hash-join = 0 ; 1 for enable hash join
enable-predicate-push-down = 0 ; 1 for enabling predicate push down
[executor]
print-statistics = 0 ; 1 for printing all execution statistics

View File

@ -0,0 +1,131 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <database.h>
namespace beedb::boot
{
class TableExecutionCallback final : public io::ExecutionCallback
{
public:
TableExecutionCallback(Database &database, concurrency::Transaction *transaction,
std::atomic_uint32_t &next_table_id, std::atomic_uint32_t &next_column_id,
std::atomic_uint32_t &next_index_id, std::unordered_map<std::string, table::Table *> &tables)
: _database(database), _transaction(transaction), _next_table_id(next_table_id),
_next_column_id(next_column_id), _next_index_id(next_index_id), _tables(tables)
{
}
void on_schema(const table::Schema &) override
{
}
void on_tuple(const table::Tuple &tuple) override;
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
private:
Database &_database;
concurrency::Transaction *_transaction;
std::atomic_uint32_t &_next_table_id;
std::atomic_uint32_t &_next_column_id;
std::atomic_uint32_t &_next_index_id;
std::unordered_map<std::string, table::Table *> &_tables;
};
class ColumnExecutionCallback final : public io::ExecutionCallback
{
public:
ColumnExecutionCallback(Database &database, concurrency::Transaction *transaction,
std::atomic_uint32_t &next_column_id, std::atomic_uint32_t &next_index_id,
table::Schema &schema)
: _database(database), _transaction(transaction), _next_column_id(next_column_id),
_next_index_id(next_index_id), _schema(schema)
{
}
~ColumnExecutionCallback() override = default;
void on_schema(const table::Schema &) override
{
}
void on_tuple(const table::Tuple &tuple) override;
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
private:
Database &_database;
concurrency::Transaction *_transaction;
std::atomic_uint32_t &_next_column_id;
std::atomic_uint32_t &_next_index_id;
table::Schema &_schema;
};
class IndexExecutionCallback final : public io::ExecutionCallback
{
public:
IndexExecutionCallback(std::atomic_uint32_t &next_index_id,
std::vector<std::shared_ptr<index::IndexInterface>> &indices)
: _next_index_id(next_index_id), _indices(indices)
{
}
~IndexExecutionCallback() override = default;
void on_schema(const table::Schema &) override
{
}
void on_tuple(const table::Tuple &tuple) override;
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
private:
std::atomic_uint32_t &_next_index_id;
std::vector<std::shared_ptr<index::IndexInterface>> &_indices;
};
class StatisticExecutionCallback final : public io::ExecutionCallback
{
public:
explicit StatisticExecutionCallback(statistic::SystemStatistics &system_statistics)
: _system_statistics(system_statistics)
{
}
~StatisticExecutionCallback() override = default;
void on_schema(const table::Schema &) override
{
}
void on_tuple(const table::Tuple &tuple) override;
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
private:
statistic::SystemStatistics &_system_statistics;
};
} // namespace beedb::boot

View File

@ -0,0 +1,44 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "replacement_strategy.h"
namespace beedb::buffer
{
class ClockStrategy final : public ReplacementStrategy
{
public:
ClockStrategy(std::size_t count_frames);
~ClockStrategy() override = default;
std::size_t find_victim(std::vector<storage::Page> &pages) override;
void on_pin(std::size_t frame_index, std::size_t timestamp) override;
private:
const std::size_t _pool_size;
std::size_t _current_frame = 0u;
std::vector<bool> _last_chance_bits;
};
} // namespace beedb::buffer

184
include/buffer/frame.h Normal file
View File

@ -0,0 +1,184 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstddef>
#include <limits>
#include <storage/page.h>
#include <vector>
namespace beedb::buffer
{
/**
* Storage for a page that is loaded from disk to memory.
*/
using Frame = std::array<std::byte, sizeof(storage::Page)>;
/**
* Stores information about a frame that holds a page
* in memory.
* Information are:
* - The id of the current page hold by the frame
* - Number of pins
* - Dirty bit; if set, the page has to be written back
* to disk when the page is replaced.
* - History of pin timestamps
*/
class FrameInformation
{
public:
FrameInformation() = default;
~FrameInformation() = default;
void occupy(const storage::Page::id_t page_id, const std::size_t timestamp)
{
this->_page_id = page_id;
this->_pin_count = 1u;
this->_is_dirty = false;
this->_is_last_chance = false;
this->_pin_timestamps.clear();
this->_pin_timestamps.push_back(timestamp);
}
/**
* @return Id of the occupied page.
*/
[[nodiscard]] storage::Page::id_t page_id() const
{
return _page_id;
}
/**
* @return True, if the frame is occupied by a page.
*/
[[nodiscard]] bool is_occupied() const
{
return _page_id != storage::Page::INVALID_PAGE_ID;
}
/**
* @return Number of active pins.
*/
[[nodiscard]] std::size_t pin_count() const
{
return _pin_count;
}
/**
* @return True, if the frame is pinned at the moment.
*/
[[nodiscard]] bool is_pinned() const
{
return _pin_count > 0u;
}
/**
* Increases the pin count and adds the timestamp to history.
* @param timestamp Timestamp of the pin.
*/
void increase_pin_count(const std::size_t timestamp)
{
_pin_count++;
_pin_timestamps.push_back(timestamp);
}
/**
* Decreases the pin count.
*/
void decrease_pin_count()
{
_pin_count--;
}
/**
* @return True, if the frame is dirty ergo the content
* of the page was modified.
*/
[[nodiscard]] bool is_dirty() const
{
return _is_dirty;
}
/**
* Update the dirty flag.
* @param is_dirty
*/
void is_dirty(const bool is_dirty)
{
_is_dirty = is_dirty;
}
/**
* @return Timestamp of the last pin.
*/
[[nodiscard]] std::size_t last_pin_timestamp() const
{
if (_pin_timestamps.empty())
{
return std::numeric_limits<std::size_t>::max();
}
return _pin_timestamps.back();
}
/**
* @return Timestamp of the i-th pin.
*/
[[nodiscard]] std::size_t pin_timestamp(const std::size_t i) const
{
return _pin_timestamps[i];
}
/**
* @return Number of how many times the frame was pinned.
*/
[[nodiscard]] std::size_t count_all_pins() const
{
return _pin_timestamps.size();
}
[[nodiscard]] bool is_last_chance() const
{
return _is_last_chance;
}
void is_last_chance(bool is_last_chance)
{
_is_last_chance = is_last_chance;
}
private:
// Id of the page that is loaded into this frame.
storage::Page::id_t _page_id = storage::Page::INVALID_PAGE_ID;
// Number of current pins.
std::size_t _pin_count = 0u;
// Is the frame modified and should be written back to disk?
bool _is_dirty = false;
// Last chance bit for clock strategy.
bool _is_last_chance = false;
// List of timestamps.
std::vector<std::size_t> _pin_timestamps;
};
} // namespace beedb::buffer

View File

@ -0,0 +1,42 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "replacement_strategy.h"
namespace beedb::buffer
{
/**
* Replaces the last frequently used frame.
*/
class LFUStrategy final : public ReplacementStrategy
{
public:
LFUStrategy(std::size_t count_frames);
~LFUStrategy() override = default;
std::size_t find_victim(std::vector<storage::Page> &pages) override;
void on_pin(std::size_t frame_index, std::size_t timestamp) override;
private:
std::vector<std::size_t> _pin_count;
};
} // namespace beedb::buffer

View File

@ -0,0 +1,54 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "replacement_strategy.h"
#include <list>
namespace beedb::buffer
{
class LRUKStrategy final : public ReplacementStrategy
{
public:
LRUKStrategy(std::size_t count_frames, std::size_t k);
~LRUKStrategy() override = default;
std::size_t find_victim(std::vector<storage::Page> &pages) override;
void on_pin(std::size_t frame_index, std::size_t timestamp) override;
private:
// Configured K-parameter.
const std::size_t _k = 0;
// List of timestamps for every page.
std::vector<std::vector<std::size_t>> _history;
[[nodiscard]] std::size_t last_timestamp(std::size_t frame_index) const
{
if (_history[frame_index].empty())
{
return std::numeric_limits<std::size_t>::max();
}
return _history[frame_index].back();
}
};
} // namespace beedb::buffer

View File

@ -0,0 +1,42 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "replacement_strategy.h"
namespace beedb::buffer
{
/**
* Replaces the last recently used frame.
*/
class LRUStrategy final : public ReplacementStrategy
{
public:
LRUStrategy(std::size_t count_frames);
~LRUStrategy() override = default;
std::size_t find_victim(std::vector<storage::Page> &pages) override;
void on_pin(std::size_t frame_index, std::size_t timestamp) override;
private:
std::vector<std::size_t> _last_pin_timestamps;
};
} // namespace beedb::buffer

140
include/buffer/manager.h Normal file
View File

@ -0,0 +1,140 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "frame.h"
#include "replacement_strategy.h"
#include <cstdint>
#include <memory>
#include <mutex>
#include <storage/manager.h>
#include <storage/page.h>
#include <vector>
namespace beedb::buffer
{
/**
* The BufferManager buffers pages stored on the disk in memory.
* Since the system has not infinite memory, the number of buffered
* pages (named "frames") is limited.
*
* Every access to a page on the disk is done by pinning the page
* through the BufferManager. When the page is not needed any more
* (e.g. all tuples are scanned), the page can be unpinned by the
* BufferManager.
*/
class Manager
{
public:
Manager(std::size_t count_frames, storage::Manager &space_manager,
std::unique_ptr<ReplacementStrategy> &&replacement_strategy = nullptr);
~Manager();
/**
* Loads the page from disk into memory and returns a pointer
* to the page. When the page is still buffered, the page will
* not be loaded twice, but guaranteed to stay in memory until
* it is unpinned.
*
* @param page_id Id of the page.
* @return Pointer to the page, that allows accessing the data.
*/
storage::Page *pin(storage::Page::id_t page_id);
/**
* Notifies the BufferManager that the page is not needed anymore.
* In case no one needs the page, the frame can be used for other
* pages buffered from disk in memory.
*
* @param page_id Id of the page.
* @param is_dirty True, when the content of the page was modified.
*/
void unpin(storage::Page::id_t page_id, bool is_dirty);
/**
* Notifies the BufferManager that the page is not needed anymore.
* In case no one needs the page, the frame can be used for other
* pages buffered from disk in memory.
*
* @param page_id Id of the page.
* @param is_dirty True, when the content of the page was modified.
*/
void unpin(storage::Page *page, bool is_dirty)
{
unpin(page->id(), is_dirty);
}
/**
* Allocates a new page on the disk and loads the page to memory.
*
* @return Pointer to the pinned(!) page.
*/
template <typename P = storage::Page> storage::Page *allocate()
{
return this->pin(this->_space_manager.allocate<P>());
}
/**
* Set the replacement strategy which picks frames to be replaced,
* when all frames are occupied, but a new page is requested to
* be loaded from disk to memory.
* @param replacement_strategy
*/
void replacement_strategy(std::unique_ptr<ReplacementStrategy> &&replacement_strategy)
{
_replacement_strategy = std::move(replacement_strategy);
}
/**
* @return Number of evicted frames.
*/
[[nodiscard]] std::size_t evicted_frames() const
{
return _evicted_frames;
}
private:
storage::Manager &_space_manager;
std::unique_ptr<ReplacementStrategy> _replacement_strategy;
std::vector<storage::Page> _frames;
std::size_t _pin_sequence = 0u;
std::size_t _evicted_frames = 0u;
std::mutex _latch;
/**
* Writes all dirty pages from memory to disk.
*/
void flush();
/**
* Lookup for frame information for a specific page.
* The frame information stores information like pin
* history, pinned page for a frame.
*
* @param page_id Id of the page.
* @return An iterator to the frame information or end() if the frame was not found.
*/
std::vector<storage::Page>::iterator frame_information(storage::Page::id_t page_id);
};
} // namespace beedb::buffer

View File

@ -0,0 +1,44 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "replacement_strategy.h"
#include <util/random_generator.h>
namespace beedb::buffer
{
class RandomStrategy final : public ReplacementStrategy
{
public:
RandomStrategy(std::size_t count_frames);
~RandomStrategy() override = default;
std::size_t find_victim(std::vector<storage::Page> &pages) override;
void on_pin(std::size_t frame_index, std::size_t timestamp) override;
private:
const std::size_t _pool_size;
util::RandomGenerator _random_generator{};
};
} // namespace beedb::buffer

View File

@ -0,0 +1,58 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <storage/page.h>
#include <vector>
namespace beedb::buffer
{
/**
* The BufferReplacementStrategy decides which frame should
* be re-used for a new page, when no free frame is available.
*/
class ReplacementStrategy
{
public:
ReplacementStrategy() = default;
virtual ~ReplacementStrategy() = default;
/**
* Picks a frame that holds a unused page and should be
* replaced by a new page, requested by a query.
*
* @param frame_information Information of all frames.
* @return Index of the frame, that should be used for a new page.
*/
virtual std::size_t find_victim(std::vector<storage::Page> &pages) = 0;
/**
* This callback is called every time the buffer manager pins a page
* to given index in the frame buffer. This gives the strategy the
* possibility to notice some additional information like the pin
* history that is used for finding a victim.
* @param frame_index Index in the frame buffer that is used for pinning.
* @param timestamp Timestamp the page was pinned in the frame buffer.
*/
virtual void on_pin(std::size_t frame_index, std::size_t timestamp) = 0;
};
} // namespace beedb::buffer

View File

@ -0,0 +1,98 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cassert>
#include <cstdint>
namespace beedb::compression
{
class WAHBitVector
{
public:
WAHBitVector() : _is_literal_word(0), _content(0)
{
}
~WAHBitVector() = default;
inline bool is_fill() const
{
return _is_literal_word == 0;
}
inline bool is_literal() const
{
return _is_literal_word;
}
inline void is_fill(bool is_fill)
{
_is_literal_word = !is_fill;
}
inline bool fill_bit() const
{
return _content >> 30;
}
inline void fill_bit(const bool fill_bit)
{
_content = (fill_bit << 30) | count();
}
inline std::uint32_t count() const
{
return _content & 0x3FFFFFFF;
}
WAHBitVector &operator++()
{
_content = (count() + 1) | (fill_bit() << 30);
return *this;
}
WAHBitVector operator++(int)
{
WAHBitVector copy(*this);
++(*this);
return copy;
}
inline void set(const std::size_t index, const bool bit)
{
assert(index >= 0 && index <= 31);
_content ^= (-bit ^ _content) & (1UL << index);
}
inline bool get(const std::size_t index) const
{
assert(index >= 0 && index <= 31);
return (_content >> index) & 1U;
}
inline void clear()
{
_content = 0;
}
private:
std::uint32_t _is_literal_word : 1, _content : 31;
} __attribute__((packed));
} // namespace beedb::compression

View File

@ -0,0 +1,172 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "timestamp.h"
#include <atomic>
#include <storage/page.h>
#include <storage/record_identifier.h>
namespace beedb::concurrency
{
/**
* Information about a tuple, stored in front of the data on a page.
* The information contains begin and end timestamp of the data and
* also a pointer (in form of a record identifier) to the "original"
* record.
* The original record is the record placed in the table space while
* versioned records are stored in the time travel space.
*/
class Metadata
{
public:
explicit Metadata(const timestamp begin_timestamp)
: _begin_timestamp(begin_timestamp), _end_timestamp(timestamp::make_infinity())
{
}
Metadata(const storage::RecordIdentifier original_record_identifier, const timestamp begin_timestamp)
: _original_record_identifier(original_record_identifier), _begin_timestamp(begin_timestamp),
_end_timestamp(timestamp::make_infinity())
{
}
Metadata(const Metadata &other)
: _original_record_identifier(other._original_record_identifier), _begin_timestamp(timestamp::make_infinity()),
_end_timestamp(timestamp::make_infinity())
{
_begin_timestamp = other._begin_timestamp;
_end_timestamp = other._end_timestamp;
_next_in_version_chain = other._next_in_version_chain;
}
~Metadata() = default;
/**
* @return Timestamp the related record was created.
*/
[[nodiscard]] timestamp begin_timestamp() const
{
return _begin_timestamp;
}
/**
* @return Timestamp the related record was removed
* or overridden by an update.
*/
[[nodiscard]] timestamp end_timestamp() const
{
return _end_timestamp;
}
/**
* @return Pointer to the next record in the version chain.
*/
[[nodiscard]] storage::RecordIdentifier next_in_version_chain() const
{
return _next_in_version_chain;
}
/**
* Set the creation timestamp.
* @param timestamp Timestamp the related records gets alive.
*/
void begin_timestamp(const timestamp timestamp)
{
_begin_timestamp = timestamp;
}
/**
* Tries to set the timestamp but if and only if
* the timestamp holds the value given in the old_timestamp
* argument.
* @param old_timestamp Expected timestamp.
* @param timestamp New timestamp.
* @return True, if the timestamp could be set.
*/
bool try_begin_timestamp(timestamp old_timestamp, const timestamp timestamp)
{
if (_begin_timestamp == old_timestamp)
{
_begin_timestamp = timestamp;
return true;
}
return false;
}
/**
* Updates the end timestamp.
* @param timestamp Timestamp the record ends.
*/
void end_timestamp(const timestamp timestamp)
{
_end_timestamp.store(timestamp);
}
/**
* Tries to set the timestamp but if and only if
* the timestamp holds the value given in the old_timestamp
* argument.
* @param old_timestamp Expected timestamp.
* @param timestamp New timestamp.
* @return True, if the timestamp could be set.
*/
bool try_end_timestamp(timestamp old_timestamp, const timestamp timestamp)
{
if (_end_timestamp == old_timestamp)
{
_end_timestamp = timestamp;
return true;
}
return false;
}
/**
* Update the pointer to the next version in history.
* @param next Pointer to the next version.
*/
void next_in_version_chain(const storage::RecordIdentifier next)
{
_next_in_version_chain = next;
}
/**
* @return Pointer to the current version in the table space.
*/
[[nodiscard]] storage::RecordIdentifier original_record_identifier() const
{
return _original_record_identifier;
}
// Pointer to the record in the table space.
storage::RecordIdentifier _original_record_identifier;
// Timestamp the record begins living.
timestamp _begin_timestamp;
// Timestamp the record dies.
timestamp _end_timestamp;
// Pointer to the next record in version chain.
storage::RecordIdentifier _next_in_version_chain;
};
} // namespace beedb::concurrency

View File

@ -0,0 +1,116 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
namespace beedb::concurrency
{
/**
* Represents a transaction timestamp, e.g., a begin or end timestamp
* of a record or begin or commit time of a transaction.
* The timestamp contains the "real" time (that is a global counter incremented
* for each new transaction) and a flag that indices the commit-state of the timestamp.
* The flag may be 1 for committed and else 0.
*
* The time "0" in combination with the set committed flag indicates "infinity".
*/
class timestamp
{
public:
using timestamp_t = std::uint64_t;
static auto make_infinity()
{
return timestamp{};
}
timestamp(const timestamp_t t, bool is_committed) : _timestamp_and_committed_flag((t << 1u) | is_committed)
{
}
timestamp &operator=(const timestamp &) = default;
~timestamp() = default;
/**
* @return True, if the transaction of the timestamp was committed.
*/
[[nodiscard]] bool is_committed() const
{
return _timestamp_and_committed_flag & 1u;
}
/**
* @return The "real" time without "committed" flag.
*/
[[nodiscard]] timestamp_t time() const
{
return _timestamp_and_committed_flag >> 1u;
}
/**
* @return True, when this timestamp is "never ending".
*/
[[nodiscard]] bool is_infinity() const
{
return _timestamp_and_committed_flag == 1u;
}
bool operator==(const timestamp other) const
{
return other._timestamp_and_committed_flag == _timestamp_and_committed_flag;
}
bool operator!=(const timestamp other) const
{
return other._timestamp_and_committed_flag != _timestamp_and_committed_flag;
}
bool operator<(const timestamp other) const
{
return time() < other.time();
}
bool operator<=(const timestamp other) const
{
return time() <= other.time();
}
bool operator>(const timestamp other) const
{
return time() > other.time();
}
bool operator>=(const timestamp other) const
{
return time() >= other.time();
}
private:
timestamp() = default;
// Time and committed flag (last bit).
timestamp_t _timestamp_and_committed_flag = 1u;
};
} // namespace beedb::concurrency

View File

@ -0,0 +1,367 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "metadata.h"
#include "timestamp.h"
#include <execution/predicate_matcher.h>
#include <functional>
#include <optional>
#include <storage/record_page.h>
#include <table/table.h>
#include <unordered_set>
#include <vector>
namespace beedb::concurrency
{
/**
* Isolation levels with more (serializable) or
* less (read uncommitted) isolation.
*/
enum IsolationLevel : std::uint8_t
{
Serializable = 0,
// RepeatableRead = 1,
// ReadCommitted = 2,
// ReadUncommitted = 3
};
/**
* A read set item contains two pointers (in form of record identifiers):
* - A pointer to the "original" record placed in the table space
* - A pointer to the read version (which may be the same as the "original").
* The first one is needed to compare read set items with the write set items
* of other transactions.
*/
class ReadSetItem
{
public:
ReadSetItem(const storage::RecordIdentifier in_place_record_identifier,
const storage::RecordIdentifier read_record_identifier)
: _in_place_record_identifier(in_place_record_identifier), _read_record_identifier(read_record_identifier)
{
}
ReadSetItem(ReadSetItem &&) = default;
~ReadSetItem() = default;
/**
* @return Pointer to the record in the table space.
*/
[[nodiscard]] storage::RecordIdentifier in_place_record_identifier() const
{
return _read_record_identifier;
}
/**
* @return Pointer to the really read record (which may
* be in table or time travel space).
*/
[[nodiscard]] storage::RecordIdentifier read_record_identifier() const
{
return _read_record_identifier;
}
private:
// Pointer to the record in the table space.
storage::RecordIdentifier _in_place_record_identifier;
// Pointer to the really read record.
storage::RecordIdentifier _read_record_identifier;
};
/**
* The scan set indicates that a transaction read a set
* of tuples (select * from ... or aggregation for example).
* A scan can miss a record that is inserted/updated/deleted
* by a concurrent transaction. Therefore the scan has to be
* validated at commit time.
*/
class ScanSetItem
{
public:
ScanSetItem() = default;
explicit ScanSetItem(std::unique_ptr<execution::PredicateMatcherInterface> &&predicate)
: _predicate(std::move(predicate))
{
}
explicit ScanSetItem(const table::Table &table) : _table(std::make_optional(std::ref(table)))
{
}
ScanSetItem(ScanSetItem &&) = default;
~ScanSetItem() = default;
/**
* @return Table that was scanned.
*/
[[nodiscard]] std::optional<std::reference_wrapper<const table::Table>> table() const
{
return _table;
}
/**
* Update table that was scanned.
* @param table Table
*/
void table(const table::Table &table)
{
_table = std::make_optional(std::ref(table));
}
/**
* @return Predicate that was used for scanning.
*/
[[nodiscard]] const std::unique_ptr<execution::PredicateMatcherInterface> &predicate() const
{
return _predicate;
}
/**
* Update predicate that was used for scanning.
* @param predicate Predicate that was used for scanning.
*/
void predicate(std::unique_ptr<execution::PredicateMatcherInterface> &&predicate)
{
_predicate = std::move(predicate);
}
private:
// Table, needed for re-execution.
std::optional<std::reference_wrapper<const table::Table>> _table = std::nullopt;
// Predicates, needed for re-execution.
std::unique_ptr<execution::PredicateMatcherInterface> _predicate{nullptr};
};
/**
* A write set item contains two pointers (in form of record identifiers):
* - A pointer to the "original" record placed in the table space
* - A pointer to the updated/deleted version.
* Also the type of modification (inserted/updated/removed) is stored in
* the write set.
*/
class WriteSetItem
{
public:
enum ModificationType
{
Inserted,
Updated,
Deleted
};
WriteSetItem(const table::Table::id_t table_id, const storage::RecordIdentifier in_place_record_identifier,
const storage::RecordIdentifier old_version_record_identifier,
const ModificationType modification_type, const storage::Page::offset_t size_written)
: _table_id(table_id), _in_place_record_identifier(in_place_record_identifier),
_old_version_record_identifier(old_version_record_identifier), _type(modification_type),
_written_size(size_written)
{
}
WriteSetItem(const table::Table::id_t table_id, const storage::RecordIdentifier record_identifier,
const storage::Page::offset_t size_written)
: WriteSetItem(table_id, record_identifier, record_identifier, ModificationType::Inserted, size_written)
{
}
WriteSetItem(WriteSetItem &&) = default;
WriteSetItem(const WriteSetItem &) = default;
~WriteSetItem() = default;
/**
* @return The id of the table this write belongs to.
*/
[[nodiscard]] table::Table::id_t table_id() const
{
return _table_id;
}
/**
* @return Pointer to the record that was really written.
*/
[[nodiscard]] storage::RecordIdentifier in_place_record_identifier() const
{
return _in_place_record_identifier;
}
/**
* @return Pointer to the record that was overwritten (for updates
* and deletes).
*/
[[nodiscard]] storage::RecordIdentifier old_version_record_identifier() const
{
return _old_version_record_identifier;
}
bool operator==(const ModificationType type) const
{
return _type == type;
}
/**
* @return Number of bytes written.
*/
[[nodiscard]] storage::Page::offset_t written_size() const
{
return _written_size;
}
private:
// Id of the table, this write belongs to.
table::Table::id_t _table_id;
// The record identifier of the record that was updated in place.
storage::RecordIdentifier _in_place_record_identifier;
// The record identifier of the record that was versioned.
storage::RecordIdentifier _old_version_record_identifier;
// Type of the update.
ModificationType _type;
// Size of the written data (inclusively metadata).
storage::Page::offset_t _written_size;
};
/**
* The transaction stores the begin and commit timestamp of the transaction,
* as well as the read and write set.
*/
class Transaction
{
public:
explicit Transaction(const IsolationLevel isolation_level, const timestamp begin)
: _isolation_level(isolation_level), _begin_timestamp(begin), _commit_timestamp(timestamp::make_infinity())
{
}
~Transaction() = default;
/**
* @return Isolation level of this transaction.
*/
[[maybe_unused]] [[nodiscard]] IsolationLevel isolation_level() const
{
return _isolation_level;
}
/**
* Update the commit timestamp of this transaction.
* @param commit_timestamp Timestamp this transaction commits.
*/
void commit_timestamp(const timestamp commit_timestamp)
{
_commit_timestamp = commit_timestamp;
}
/**
* @return Timestamp this transaction was started.
*/
[[nodiscard]] timestamp begin_timestamp() const
{
return _begin_timestamp;
}
/**
* @return Timestamp this transaction was committed.
*/
[[nodiscard]] timestamp commit_timestamp() const
{
return _commit_timestamp;
}
/**
* Adds an item to the read set.
* @param read_set_item Item that was read by this transaction.
*/
void add_to_read_set(ReadSetItem &&read_set_item)
{
_read_set.emplace_back(std::move(read_set_item));
}
/**
* Adds an item to the write set.
* @param write_set_item Item that was written by this transaction.
*/
void add_to_write_set(WriteSetItem &&write_set_item)
{
_write_set.emplace_back(std::move(write_set_item));
}
/**
* Adds an item to the scan set.
* @param scan_set_item Item that was scanned by this transaction.
*/
void add_to_scan_set(ScanSetItem *scan_set_item)
{
_scan_set.emplace_back(scan_set_item);
}
/**
* @return Read set of this transaction.
*/
[[nodiscard]] const std::vector<ReadSetItem> &read_set() const
{
return _read_set;
}
/**
* @return Write set of this transaction.
*/
[[nodiscard]] const std::vector<WriteSetItem> &write_set() const
{
return _write_set;
}
/**
* @return Scan set of this transaction.
*/
[[nodiscard]] const std::vector<ScanSetItem *> &scan_set() const
{
return _scan_set;
}
private:
// Isolation level of the transaction.
const IsolationLevel _isolation_level;
// Timestamp this transaction was created.
const timestamp _begin_timestamp;
// Timestamp this transaction committed.
timestamp _commit_timestamp;
// Items that were read by this transaction.
std::vector<ReadSetItem> _read_set;
// Items that were written by this transaction.
std::vector<WriteSetItem> _write_set;
// Items that were scanned by this transaction.
std::vector<ScanSetItem *> _scan_set;
};
} // namespace beedb::concurrency

View File

@ -0,0 +1,98 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "transaction.h"
#include <functional>
namespace beedb::concurrency
{
/**
* The transaction callback will be called when a transaction begins
* and when the transaction was aborted or committed.
*/
class TransactionCallback
{
public:
TransactionCallback() = default;
virtual ~TransactionCallback() = default;
/**
* Will be called when a transaction starts.
* @param transaction Transaction that started.
*/
virtual void on_begin(Transaction *transaction) = 0;
/**
* Will be called when a transaction ends. This may be
* a successful or not successful commit or abort.
* @param transaction Transaction that ends.
* @param successful True, when successful committed.
*/
virtual void on_end(Transaction *transaction, const bool successful) = 0;
};
class SilentTransactionCallback : public TransactionCallback
{
public:
SilentTransactionCallback() = default;
~SilentTransactionCallback() override = default;
void on_begin(Transaction *) override
{
}
void on_end(Transaction *, const bool) override
{
}
};
/**
* This implementation of a transaction callback takes two lambdas
* that will be invoked on start and end of a transaction.
*/
class FunctionTransactionCallback : public TransactionCallback
{
public:
FunctionTransactionCallback(std::function<void(Transaction *)> &&begin_callback,
std::function<void(Transaction *, const bool)> &&end_callback)
: _begin_transaction_callback(std::move(begin_callback)), _end_transaction_callback(std::move(end_callback))
{
}
~FunctionTransactionCallback() override = default;
void on_begin(Transaction *transaction) override
{
_begin_transaction_callback(transaction);
}
void on_end(Transaction *transaction, const bool successful) override
{
_end_transaction_callback(transaction, successful);
}
private:
std::function<void(Transaction *)> _begin_transaction_callback;
std::function<void(Transaction *, const bool)> _end_transaction_callback;
};
} // namespace beedb::concurrency

View File

@ -0,0 +1,170 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "metadata.h"
#include "transaction.h"
#include <array>
#include <atomic>
#include <buffer/manager.h>
#include <shared_mutex>
#include <unordered_map>
namespace beedb::concurrency
{
/**
* The TransactionManager creates new transactions and performs
* commit and abort of those transactions.
*/
class TransactionManager
{
public:
explicit TransactionManager(buffer::Manager &buffer_manager);
~TransactionManager();
/**
* Creates a new transaction with the given isolation level.
*
* @param isolation_level Isolation level.
* @return New transaction.
*/
Transaction *new_transaction(const IsolationLevel isolation_level = IsolationLevel::Serializable);
/**
* Aborts the given transaction and reverts all
* writes done by this transaction.
* @param transaction Transaction to abort.
*/
void abort(Transaction &transaction);
/**
* Commits a transaction. Before writing the data written by the transaction
* to the global state, the transaction is validated.
* @param transaction Transaction to commit.
* @return True, when the commit was successful. Otherwise, the transaction
* will be aborted automatically.
*/
bool commit(Transaction &transaction);
/**
* Tests if a given timestamp range is visible for the given transaction.
* @param transaction Transaction to test.
* @param begin_timestamp Start timestamp.
* @param end_timestamp End timestamp.
* @return True, when the transaction is allowed to see the data living in the given range.
*/
static bool is_visible(const Transaction &transaction, const timestamp begin_timestamp,
const timestamp end_timestamp);
/**
* Tests if a given metadata is visible for the given transaction.
* @param transaction Transaction to test.
* @param metadata Metadata of a record.
* @return True, when the transaction is allowed to see the data living in the given range.
*/
static bool is_visible(const Transaction &transaction, Metadata *const metadata)
{
return is_visible(transaction, metadata->begin_timestamp(), metadata->end_timestamp());
}
/**
* @return The next timestamp for transactions.
*/
timestamp::timestamp_t next_timestamp() const
{
return _next_timestamp.load();
}
/**
* Updates the next timestamp for transactions.
* @param timestamp Next timestamp for the next transaction.
*/
void next_timestamp(const timestamp::timestamp_t timestamp)
{
_next_timestamp.store(timestamp);
}
private:
// Buffer manager to read/write to pages.
buffer::Manager &_buffer_manager;
// Timestamp for the next transaction.
std::atomic<timestamp::timestamp_t> _next_timestamp{2u};
// Map of Timestamp => Transaction of only committed transactions.
std::unordered_map<timestamp::timestamp_t, Transaction *> _commit_history;
// Latch for the history map.
std::shared_mutex _commit_history_latch;
/**
* Validates a transaction to commit.
* @param transaction Transaction to commit.
* @return True, when the transaction is valid.
*/
bool validate(Transaction &transaction);
/**
* Validates write skew anomalies. A write skew anomaly can occur,
* when a transaction T reads a record A and writes a record B,
* but a concurrent transaction T' writes to A between T reading A and
* writing B.
* What the DBMS can not see is how A affects B in T, therefore we have
* to abort the transaction.
* @param transaction Transaction to validate.
* @param concurrent_transactions List of transactions that committed between
* the transactions started and committed.
* @return True, when the transaction is valid.
*/
static bool validate_write_skew_anomalies(Transaction &transaction,
const std::vector<Transaction *> &concurrent_transactions);
/**
* Validates the scan set of a transaction. A transaction T
* may scan a table while a concurrent transaction inserts/deletes/updates
* a record that would be part of the scan. Therefore, the scan
* has to be (re)checked to validate that the scan would be the same
* at commit time.
* @param transaction Transaction to validate.
* @param concurrent_transactions List of concurrent transactions.
* @return True, when the transaction is valid.
*/
bool validate_scan_set(Transaction &transaction, const std::vector<Transaction *> &concurrent_transactions);
/**
* Validates a single scan of a transaction against the write sets of concurrent transactions.
* @param scan_set_item Single scan set.
* @param write_set List of write sets of concurrent transactions.
* @return True, when the scan set is valid.
*/
bool validate_scan_set_item(ScanSetItem *scan_set_item, const std::vector<WriteSetItem> &write_set);
/**
* Calculates the transactions that have committed between begin and end.
* @param begin Begin.
* @param end End.
* @return List of transactions that committed in the given time range.
*/
std::vector<Transaction *> committed_transactions(const timestamp::timestamp_t begin,
const timestamp::timestamp_t end);
};
} // namespace beedb::concurrency

196
include/config.h Normal file
View File

@ -0,0 +1,196 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cassert>
#include <cstdint>
#include <exception/config_exception.h>
#include <iostream>
#include <string>
#include <unordered_map>
namespace beedb
{
/**
* Holds all configuration for the DBMS.
*/
class Config
{
public:
using ConfigKey = std::string;
using ConfigValue = std::int32_t; // TODO: consider renaming this or the struct below...?
///// COMPILE TIME OPTIONS - CHANGES REQUIRE REBUILDING
static constexpr std::uint16_t page_size = 4096;
static constexpr std::uint16_t b_plus_tree_page_size = 1024;
static constexpr auto max_clients = 64u;
static constexpr auto cli_history_file = "beedb-cli.txt";
public:
// defining constants and other values, for convenience and ease-of-reading
enum BufferReplacementStrategy
{
Random,
LRU,
LRU_K,
LFU,
Clock
};
// important key's for non-string based notation:
static constexpr auto k_PageSize = "page_size";
static constexpr auto k_BPlusTreePageSize = "b_plus_tree_page_size";
static constexpr auto k_ScanPageLimit = "scan_page_limit";
static constexpr auto k_BufferFrames = "buffer_frames";
static constexpr auto k_BufferReplacementStrategy = "buffer_replacement_strategy";
static constexpr auto k_LRU_K = "lru_k";
static constexpr auto k_CheckFinalPlan = "check_final_plan";
static constexpr auto k_OptimizationEnableHashJoin = "enable_hash_join";
static constexpr auto k_OptimizationEnableIndexScan = "enable_index_scan";
static constexpr auto k_OptimizationEnablePredicatePushDown = "enable_predicate_push_down";
static constexpr auto k_OptimizationDisableOptimization = "no_optimization";
static constexpr auto k_PrintExecutionStatistics = "print_execution_statistics";
// this object represents a ConfigValue in the map and stores some meta information
struct ConfigMapValue
{
ConfigValue value;
bool is_mutable = true;
bool requires_restart = false;
explicit operator ConfigValue() const
{
return value;
}
explicit operator std::size_t() const
{
return static_cast<std::size_t>(value);
}
explicit operator std::uint32_t() const
{
return static_cast<std::uint32_t>(value);
}
explicit operator bool() const
{
return value != 0u;
}
explicit operator BufferReplacementStrategy() const
{
return static_cast<BufferReplacementStrategy>(value);
}
static constexpr bool immutable = false;
};
Config()
{
// for transparency, we make compile-time options available in the config map (read only)
_configuration.insert({k_PageSize, {page_size, ConfigMapValue::immutable}});
_configuration.insert({k_BPlusTreePageSize, {b_plus_tree_page_size, ConfigMapValue::immutable}});
}
~Config() = default; // TODO: persist changes in config
/**
* @brief operator [] Read only access to values of the Configuration!
*
* This method is identical to get.
*
* @param key
* @return
*/
ConfigMapValue operator[](const ConfigKey &key) const
{
if (_configuration.find(key) == _configuration.end())
{
throw exception::ConfigException(key);
}
return _configuration.at(key);
}
ConfigMapValue get(const ConfigKey &key) const
{
return this->operator[](key);
}
/**
* @brief set sets a configuration value. Can override existing values, if the flag ConfigMapValue.is_mutable is not
* set!
* @param key a new or existing key
* @param value the new value
* @param is_mutable defaults to true
* @param requires_restart defaults to false. currently unused.
* @return the input value, returned from the map
*/
void set(const ConfigKey &key, ConfigValue value, bool is_mutable = true, bool requires_restart = false)
{
if (_configuration.find(key) != _configuration.end())
{
// if this key already exists, check if it is read only
if (!_configuration.at(key).is_mutable)
{
throw exception::CanNotModifyAtRuntimeException(key);
}
}
// // TODO implement: persist config map on shutdown and uncomment this
// if (_configuration[key].requires_restart) {
// std::cout << "Note: " << "This option requires a restart of the application to take effect!"
// << std::endl;
// }
_configuration[key] = ConfigMapValue{value, is_mutable, requires_restart};
}
bool contains(const ConfigKey &key) const
{
return _configuration.find(key) != _configuration.end();
}
explicit operator std::string()
{
auto str = std::string{"Current Configuration:\n"};
for (const auto &[k, value] : _configuration)
{
str += "";
str += std::to_string(value.value);
// str += ", " + (value.is_mutable ? std::string("r/w") : std::string("r") );
str += "\t<- " + k + (!value.is_mutable ? " (immutable)" : "") + "\n";
}
return str;
}
private:
using ConfigurationMap = std::unordered_map<ConfigKey, ConfigMapValue>;
// holds the actual configuration values
ConfigurationMap _configuration;
};
} // namespace beedb

203
include/database.h Normal file
View File

@ -0,0 +1,203 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <atomic>
#include <buffer/manager.h>
#include <concurrency/transaction_manager.h>
#include <config.h>
#include <cstdint>
#include <functional>
#include <index/type.h>
#include <io/execution_callback.h>
#include <shared_mutex>
#include <statistic/system_statistics.h>
#include <storage/manager.h>
#include <storage/page.h>
#include <string>
#include <table/table.h>
#include <table/table_disk_manager.h>
#include <table/tuple.h>
#include <unordered_map>
#include <utility>
namespace beedb
{
class Database
{
public:
Database(Config &config, const std::string &file_name);
~Database();
/**
* Boots the database management system.
* During the boot, all persisted tables, their schemas and indices
* will be loaded to memory.
* All indices will be filled with data from disk.
*/
void boot();
/**
* @return Instance of the TableDiskManager.
*/
[[nodiscard]] table::TableDiskManager &table_disk_manager()
{
return _table_disk_manager;
}
/**
* @return Instance of the BufferManager.
*/
[[nodiscard]] buffer::Manager &buffer_manager()
{
return _buffer_manager;
}
/**
* @return Instance of the transaction manager.
*/
[[nodiscard]] concurrency::TransactionManager &transaction_manager()
{
return _transaction_manager;
}
/**
* @return Immutable instance of the config.
*/
[[nodiscard]] const Config &config() const
{
return _config;
}
/**
* @return Mutable instance of the config.
*/
[[nodiscard]] Config &config()
{
return _config;
}
[[nodiscard]] statistic::SystemStatistics &system_statistics()
{
return _statistics;
}
/**
* Checks whether a table exists.
*
* @param name Name of the table.
* @return True, if the table exists.
*/
[[nodiscard]] bool table_exists(const std::string &name)
{
std::shared_lock _{_tables_latch};
return _tables.find(name) != _tables.end();
}
/**
* Returns a pointer to the requested table.
*
* @param name Name of the requested table.
* @return Pointer to the table.
*/
[[nodiscard]] table::Table *table(const std::string &name)
{
std::shared_lock _{_tables_latch};
if (table_exists(name))
{
return _tables[name];
}
return nullptr;
}
table::Table *operator[](const std::string &table_name)
{
std::shared_lock _{_tables_latch};
return table(table_name);
}
/**
* Creates a table with a given schema.
* The table will be persisted and available after creation.
*
* @param schema Schema for the table.
*/
void create_table(concurrency::Transaction *transaction, const table::Schema &schema);
/**
* Creates an index for a specific column.
* The index will be persisted, filled, and available after creation.
*
* @param column Column to be indexed.
* @param type Type of the index.
* @param name Name of the index.
* @param is_unique True, when the index is a unique index.
*/
void create_index(concurrency::Transaction *transaction, const table::Column &column, index::Type type,
const std::string &name, bool is_unique);
private:
enum SystemPageIds : storage::Page::id_t
{
Metadata = 0,
Tables = 1,
Columns = 2,
Indices = 3,
Statistics = 4,
};
Config &_config;
storage::Manager _storage_manager;
buffer::Manager _buffer_manager;
table::TableDiskManager _table_disk_manager;
concurrency::TransactionManager _transaction_manager;
std::unordered_map<std::string, table::Table *> _tables;
std::shared_mutex _tables_latch;
std::atomic_uint32_t _next_table_id = 1;
std::atomic_uint32_t _next_column_id = 1;
std::atomic_uint32_t _next_index_id = 1;
statistic::SystemStatistics _statistics;
/**
* Initializes the database. When the database is empty,
* we will create a new database schema containing all meta tables.
*
* @param create_schema True, when a database schema should be created.
*/
void initialize_database(bool create_schema);
/**
* Persists the table statistics.
*
* @param table Table
* @param cardinality Cardinality
*/
void persist_table_statistics(table::Table *table, std::uint64_t cardinality);
};
} // namespace beedb

View File

@ -0,0 +1,88 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <exception>
#include <string>
namespace beedb::exception
{
class CommandException : public std::exception
{
public:
explicit CommandException(const std::string &message) : _message(message)
{
}
~CommandException() override = default;
[[nodiscard]] const char *what() const noexcept override
{
return _message.c_str();
}
private:
const std::string _message;
};
class UnknownCommandException final : public CommandException
{
public:
explicit UnknownCommandException(const std::string &command)
: CommandException("Unknown command '" + command + "'.")
{
}
UnknownCommandException() : UnknownCommandException("Unknown command")
{
}
~UnknownCommandException() override = default;
};
class CommandSyntaxException final : public CommandException
{
public:
CommandSyntaxException(const std::string &command, const std::string &syntax_hint)
: CommandException("Command syntax exception '" + command + "'.\n" + syntax_hint)
{
}
CommandSyntaxException() : CommandException("Command syntax exception")
{
}
~CommandSyntaxException() override = default;
};
class UnknownCommandInputException final : public CommandException
{
public:
explicit UnknownCommandInputException(const std::string &input)
: CommandException("Not supported input '" + input + "'")
{
}
~UnknownCommandInputException() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,47 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
namespace beedb::exception
{
class AbortTransactionException final : public DatabaseException
{
public:
AbortTransactionException() : DatabaseException(DatabaseException::Concurrency, "Transaction aborted")
{
}
~AbortTransactionException() override = default;
};
class TransactionDisabledException final : public DatabaseException
{
public:
TransactionDisabledException() : DatabaseException(DatabaseException::Concurrency, "Transactions are disabled")
{
}
~TransactionDisabledException() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,59 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
#include <string>
namespace beedb::exception
{
class ConfigException : public DatabaseException
{
public:
explicit ConfigException(const std::string &message) : DatabaseException(DatabaseException::Configuration, message)
{
}
~ConfigException() override = default;
};
class KeyNotFoundException final : public ConfigException
{
public:
explicit KeyNotFoundException(const std::string &key) : ConfigException("Option " + key + " not found.")
{
}
~KeyNotFoundException() override = default;
};
class CanNotModifyAtRuntimeException final : public ConfigException
{
public:
explicit CanNotModifyAtRuntimeException(const std::string &key)
: ConfigException("Option " + key + " can not be changed at runtime.")
{
}
~CanNotModifyAtRuntimeException() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,80 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
#include <string>
namespace beedb::exception
{
class DiskException : public DatabaseException
{
public:
explicit DiskException(const std::string &message) : DatabaseException(DatabaseException::Disk, message)
{
}
~DiskException() override = default;
};
class EvictedPagePinnedException final : public DiskException
{
public:
explicit EvictedPagePinnedException(const std::uint64_t frame_index)
: DiskException("Can not evict page, frame " + std::to_string(frame_index) + " is pinned.")
{
}
~EvictedPagePinnedException() override = default;
};
class PageWasNotPinnedException final : public DiskException
{
public:
explicit PageWasNotPinnedException(const std::uint64_t disk_id)
: DiskException("Page " + std::to_string(disk_id) + " is not pinned, but unpin() called.")
{
}
~PageWasNotPinnedException() override = default;
};
class NoFreeFrameException final : public DiskException
{
public:
NoFreeFrameException() : DiskException("No free frame found for eviction.")
{
}
~NoFreeFrameException() override = default;
};
class CanNotOpenStorageFile final : public DiskException
{
public:
explicit CanNotOpenStorageFile(const std::string &file_name)
: DiskException("Can not open storage file '" + file_name + "'.")
{
}
~CanNotOpenStorageFile() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,64 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <exception>
#include <string>
namespace beedb::exception
{
/**
* Generic exception for plan building and execution.
*/
class DatabaseException : public std::exception
{
public:
enum Layer
{
Parser,
LogicalPlan,
Execution,
Index,
Disk,
OutputHandler,
Configuration,
Concurrency
};
~DatabaseException() override = default;
[[nodiscard]] const char *what() const noexcept override
{
return _message.c_str();
}
protected:
DatabaseException(const Layer layer, const std::string &message) : _layer(layer), _message(message)
{
}
private:
const Layer _layer;
const std::string _message;
};
} // namespace beedb::exception

View File

@ -0,0 +1,58 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
#include <string>
namespace beedb::exception
{
class ExecutionException : public DatabaseException
{
public:
explicit ExecutionException(const std::string &message) : DatabaseException(DatabaseException::Execution, message)
{
}
~ExecutionException() override = default;
};
class NoPhysicalOperatorForNode final : public ExecutionException
{
public:
explicit NoPhysicalOperatorForNode(const std::string &operator_name)
: ExecutionException("Operator " + operator_name + " is not implemented physically.")
{
}
~NoPhysicalOperatorForNode() override = default;
};
class NotInTransactionException final : public ExecutionException
{
public:
NotInTransactionException() : ExecutionException("No active transaction. Please BEGIN TRANSACTION first.")
{
}
~NotInTransactionException() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,215 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
#include <string>
namespace beedb::exception
{
class LogicalException : public DatabaseException
{
public:
explicit LogicalException(const std::string &message) : DatabaseException(DatabaseException::LogicalPlan, message)
{
}
~LogicalException() override = default;
};
class ColumnCanNotBeNull final : public LogicalException
{
public:
ColumnCanNotBeNull(const std::string &table_name, const std::string &column_name)
: LogicalException("Value for column " + table_name + "." + column_name + " can not be NULL.")
{
}
~ColumnCanNotBeNull() override = default;
};
class ColumnNotFoundException final : public LogicalException
{
public:
ColumnNotFoundException(const std::string &table_name, const std::string &column_name)
: ColumnNotFoundException(table_name + "." + column_name)
{
}
explicit ColumnNotFoundException(const std::string &table_and_column_name)
: LogicalException("Column " + table_and_column_name + " not found.")
{
}
~ColumnNotFoundException() override = default;
};
class ColumnNotGroupedException final : public LogicalException
{
public:
ColumnNotGroupedException(const std::string &table_name, const std::string &column_name)
: LogicalException("Column " + table_name + "." + column_name + " is neither aggregated nor grouped.")
{
}
~ColumnNotGroupedException() override = default;
};
class ColumnNotIndexed final : public LogicalException
{
public:
ColumnNotIndexed(const std::string &table_name, const std::string &column_name)
: LogicalException("Index for " + table_name + "." + column_name + " not found.")
{
}
~ColumnNotIndexed() override = default;
};
class IndexAlreadyExistsException final : public LogicalException
{
public:
IndexAlreadyExistsException(const std::string &table_name, const std::string &column_name)
: LogicalException("Index for " + table_name + "." + column_name + " already exists.")
{
}
~IndexAlreadyExistsException() override = default;
};
class IndexUnsupportedTypeException final : public LogicalException
{
public:
explicit IndexUnsupportedTypeException(const std::string &type_name)
: LogicalException("Type " + type_name + " can not be indexed, Type is unsupported.")
{
}
~IndexUnsupportedTypeException() override = default;
};
class MultipleGroupByException final : public LogicalException
{
public:
MultipleGroupByException() : LogicalException("Only one GROUP BY argument supported!")
{
}
~MultipleGroupByException() override = default;
};
class MultipleTableReferences final : public LogicalException
{
public:
explicit MultipleTableReferences(const std::string &table_name)
: LogicalException("Multiple references to table " + table_name + " without disambiguation.")
{
}
~MultipleTableReferences() override = default;
};
class TableAlreadyExists final : public LogicalException
{
public:
explicit TableAlreadyExists(const std::string &table_name)
: LogicalException("Table " + table_name + " already exists.")
{
}
~TableAlreadyExists() override = default;
};
class TableNotFoundException final : public LogicalException
{
public:
explicit TableNotFoundException(const std::string &table_name)
: LogicalException("Table " + table_name + " not found.")
{
}
TableNotFoundException(const std::string &table_name, const std::string &reference_name)
: LogicalException("Can not resolve table reference " + table_name + " in statement " + reference_name + ".")
{
}
~TableNotFoundException() override = default;
};
class CanNotResolveColumnException final : public LogicalException
{
public:
CanNotResolveColumnException(const std::string &column_name, const std::string &statement)
: LogicalException("Can not resolve attribute reference " + column_name + " to a table in statement " +
statement + ".")
{
}
explicit CanNotResolveColumnException(const std::string &column_name)
: LogicalException("Can not resolve attribute reference " + column_name + ".")
{
}
~CanNotResolveColumnException() override = default;
};
class NoUniqueReferenceException final : public LogicalException
{
public:
NoUniqueReferenceException(const std::string &attribute_name, const std::string &table1, const std::string &table2)
: LogicalException("Can not uniquely reference attribute " + attribute_name + ". Both table " + table1 +
" and " + table2 + " include this attribute!")
{
}
~NoUniqueReferenceException() override = default;
};
class CanNotCreateTableException final : public LogicalException
{
public:
CanNotCreateTableException() : LogicalException("Can not create table.")
{
}
~CanNotCreateTableException() override = default;
};
class CanNotCreateIndexException final : public LogicalException
{
public:
CanNotCreateIndexException() : LogicalException("Can not create index.")
{
}
~CanNotCreateIndexException() override = default;
};
class CanNotInsertException final : public LogicalException
{
public:
CanNotInsertException() : LogicalException("Can not insert.")
{
}
~CanNotInsertException() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,90 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "exception.h"
#include <string>
namespace beedb::exception
{
class ParserException : public DatabaseException
{
public:
explicit ParserException(const std::string &message) : DatabaseException(DatabaseException::Parser, message)
{
}
~ParserException() override = default;
};
class SqlException final : public ParserException
{
public:
SqlException(const std::string &parser_error, const std::size_t line, const std::size_t column)
: ParserException(parser_error + " in line " + std::to_string(line) + ":" + std::to_string(column) + ".")
{
}
~SqlException() override = default;
};
class UnsupportedStatementException final : public ParserException
{
public:
explicit UnsupportedStatementException(const std::string &statement)
: ParserException(statement + " is not supported.")
{
}
~UnsupportedStatementException() override = default;
};
class CanNotConvertNullptrException final : public ParserException
{
public:
CanNotConvertNullptrException() : ParserException("Can not convert nulltptr expression.")
{
}
~CanNotConvertNullptrException() override = default;
};
class UnsupportedOperatorException final : public ParserException
{
public:
explicit UnsupportedOperatorException(const std::string &operator_name)
: ParserException("Unsupported predicate operator: " + operator_name + ".")
{
}
~UnsupportedOperatorException() override = default;
};
class UnsupportedColumnType final : public ParserException
{
public:
UnsupportedColumnType() : ParserException("Unsupported column type.")
{
}
~UnsupportedColumnType() override = default;
};
} // namespace beedb::exception

View File

@ -0,0 +1,60 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <index/index_interface.h>
#include <memory>
namespace beedb::execution
{
/**
* Operator for adding tuples to an existing index.
*/
class AddToIndexOperator final : public UnaryOperator
{
public:
AddToIndexOperator(concurrency::Transaction *transaction, const std::uint32_t column_index,
const std::shared_ptr<index::IndexInterface> index);
~AddToIndexOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
};
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
table::Schema _schema;
const std::uint32_t _column_index;
const std::shared_ptr<index::IndexInterface> _index;
};
} // namespace beedb::execution

View File

@ -0,0 +1,145 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <cstddef>
#include <execution/aggregator.h>
#include <string_view>
#include <table/memory_table.h>
#include <unordered_map>
#include <utility>
#include <vector>
namespace beedb::execution
{
class GroupByKey
{
public:
GroupByKey(const std::vector<std::pair<std::uint16_t, std::uint16_t>> &grouped_columns,
const std::uint16_t grouped_row_size, const table::Tuple &tuple)
{
_data = new std::byte[grouped_row_size];
auto current_index = 0u;
for (const auto &[column_id, _] : grouped_columns)
{
const auto &column = tuple.schema().column(column_id);
const auto size = column.type().size();
std::memcpy(&_data[current_index], &tuple.data()[tuple.schema().offset(column_id)], size);
current_index += size;
}
}
GroupByKey(const GroupByKey &) = delete;
GroupByKey(GroupByKey &&other) noexcept : _data(other._data)
{
other._data = nullptr;
}
~GroupByKey()
{
delete[] _data;
}
bool operator==(const GroupByKey &other) const
{
return std::strcmp(reinterpret_cast<const char *>(_data), reinterpret_cast<const char *>(other._data)) == 0;
}
explicit operator std::string_view() const
{
return std::string_view{reinterpret_cast<const char *>(this->_data)};
}
private:
std::byte *_data;
};
class AggregateOperator : public UnaryOperator
{
public:
AggregateOperator(concurrency::Transaction *transaction, table::Schema &&schema,
std::vector<std::pair<std::uint16_t, std::uint16_t>> &&groups,
std::unordered_map<expression::Term, std::unique_ptr<AggregatorInterface>> &&aggregators);
~AggregateOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
// The output schema, generated by this operator.
const table::Schema _schema;
// List of [output tuple schema index, aggregator]. The aggregator will produce
// a value for the tuple at the given index.
std::vector<std::pair<std::uint16_t, std::unique_ptr<AggregatorInterface>>> _aggregators;
// Map of child attribute index to this attribute index.
std::vector<std::pair<std::uint16_t, std::uint16_t>> _group_attribute_map;
// Because next() will be called multiple times, we have to
// remember if we have grouped, yet.
bool _has_grouped = false;
// Because next() will be called multiple times, we have to
// remember if we have aggregated, yet.
bool _has_aggregated = false;
// List of grouped tiles. May be empty, even if we have grouped.
std::vector<table::MemoryTable> _tiles;
// Because next() will be called multiple times, we have to remember
// the index of the tile we want to aggregate.
std::size_t _current_tile = 0u;
/**
* Groups the tuples returned by the given child into "tiles", which are
* memory tables, containing all tuples with the identical group key.
*
* @param group_attribute_map List of indices to group.
* @param source Child that produces tuples.
* @return List of tiles.
*/
static std::vector<table::MemoryTable> group(
const std::vector<std::pair<std::uint16_t, std::uint16_t>> &group_attribute_map,
const std::unique_ptr<OperatorInterface> &source);
};
} // namespace beedb::execution
namespace std
{
template <> struct hash<beedb::execution::GroupByKey>
{
public:
std::size_t operator()(const beedb::execution::GroupByKey &key) const
{
return std::hash<std::string_view>()(static_cast<std::string_view>(key));
}
};
} // namespace std

View File

@ -0,0 +1,222 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <table/tuple.h>
#include <table/value.h>
namespace beedb::execution
{
class AggregatorInterface
{
public:
explicit AggregatorInterface(const std::uint16_t schema_index) : _schema_index(schema_index)
{
}
virtual ~AggregatorInterface() = default;
virtual void aggregate(const table::Tuple &tuple) = 0;
virtual table::Value value() = 0;
virtual void reset() = 0;
protected:
[[nodiscard]] std::uint16_t schema_index() const
{
return _schema_index;
}
private:
const std::uint16_t _schema_index;
};
class CountAggregator : public AggregatorInterface
{
public:
explicit CountAggregator(const std::uint16_t schema_index) : AggregatorInterface(schema_index)
{
}
~CountAggregator() override = default;
void aggregate(const table::Tuple &) override
{
++_count;
}
table::Value value() override
{
return table::Value(table::Type{table::Type::LONG}, {static_cast<std::int64_t>(_count)});
}
void reset() override
{
_count = 0u;
}
private:
std::uint64_t _count = 0u;
};
class SumAggregator : public AggregatorInterface
{
public:
SumAggregator(const std::uint16_t schema_index, const table::Type::Id type)
: AggregatorInterface(schema_index), _type(type), _sum(table::Value::make_zero(_type))
{
}
~SumAggregator() override = default;
void aggregate(const table::Tuple &tuple) override
{
_sum += tuple.get(AggregatorInterface::schema_index());
}
table::Value value() override
{
return _sum;
}
void reset() override
{
_sum = table::Value::make_zero(_type);
}
private:
const table::Type::Id _type;
table::Value _sum;
};
class AverageAggregator : public AggregatorInterface
{
public:
AverageAggregator(const std::uint16_t schema_index, const table::Type::Id type)
: AggregatorInterface(schema_index), _type(type), _sum(table::Value::make_zero(_type))
{
}
~AverageAggregator() override = default;
void aggregate(const table::Tuple &tuple) override
{
_sum += tuple.get(AggregatorInterface::schema_index());
_count++;
}
table::Value value() override
{
if (_type == table::Type::Id::LONG)
{
return table::Value(table::Type{table::Type::Id::DECIMAL},
_sum.get<std::int64_t>() / static_cast<double>(_count));
}
else if (_type == table::Type::Id::INT)
{
return table::Value(table::Type{table::Type::Id::DECIMAL},
_sum.get<std::int32_t>() / static_cast<double>(_count));
}
else if (_type == table::Type::Id::DECIMAL)
{
return table::Value(table::Type{table::Type::Id::DECIMAL},
_sum.get<double>() / static_cast<double>(_count));
}
return table::Value::make_zero(_type);
}
void reset() override
{
_sum = table::Value::make_zero(_type);
_count = 0u;
}
private:
const table::Type::Id _type;
table::Value _sum;
std::uint64_t _count = 0u;
};
class MinAggregator : public AggregatorInterface
{
public:
MinAggregator(const std::uint16_t schema_index, const table::Type::Id type)
: AggregatorInterface(schema_index), _type(type), _min(table::Value::make_null(_type))
{
}
~MinAggregator() override = default;
void aggregate(const table::Tuple &tuple) override
{
const auto value = tuple.get(AggregatorInterface::schema_index());
if ((value == nullptr) == false && (_min == nullptr || value < _min))
{
_min = value;
}
}
table::Value value() override
{
return _min;
}
void reset() override
{
_min = table::Value::make_null(_type);
}
private:
const table::Type::Id _type;
table::Value _min;
};
class MaxAggregator : public AggregatorInterface
{
public:
MaxAggregator(const std::uint16_t schema_index, const table::Type::Id type)
: AggregatorInterface(schema_index), _type(type), _max(table::Value::make_null(_type))
{
}
~MaxAggregator() override = default;
void aggregate(const table::Tuple &tuple) override
{
const auto value = tuple.get(AggregatorInterface::schema_index());
if ((value == nullptr) == false && (_max == nullptr || value > _max))
{
_max = value;
}
}
table::Value value() override
{
return _max;
}
void reset() override
{
_max = table::Value::make_null(_type);
}
private:
const table::Type::Id _type;
table::Value _max;
};
} // namespace beedb::execution

View File

@ -0,0 +1,211 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <expression/term.h>
#include <table/tuple.h>
#include <table/value.h>
namespace beedb::execution
{
/**
* TODO:
* The operation(+,-,*,/) on two values tries to find the matching underlying type for both.
* We could make a huge optimization by injecting the correct types and only do the operator
* for one type (depending on the type of one of the values), which will never fail if both
* hold the same type.
*/
class ArithmeticCalculatorInterface
{
public:
enum Type
{
Add,
Sub,
Multiply,
Divide
};
ArithmeticCalculatorInterface() = default;
virtual ~ArithmeticCalculatorInterface() = default;
virtual table::Value calculate(const table::Tuple &tuple) = 0;
};
template <ArithmeticCalculatorInterface::Type T>
class ValueArithmeticCalculator final : public ArithmeticCalculatorInterface
{
public:
ValueArithmeticCalculator(table::Value &&left_value, table::Value &&right_value)
: _result_value(calculate(std::move(left_value), std::move(right_value)))
{
}
~ValueArithmeticCalculator() override = default;
table::Value calculate(const table::Tuple &) override
{
return _result_value;
}
private:
table::Value _result_value;
table::Value calculate(table::Value &&left_value, table::Value &&right_value)
{
if constexpr (T == ArithmeticCalculatorInterface::Add)
{
return left_value + right_value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Sub)
{
return left_value - right_value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Multiply)
{
return left_value * right_value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Divide)
{
return left_value / right_value;
}
return std::move(left_value);
}
};
template <ArithmeticCalculatorInterface::Type T>
class AttributeValueArithmeticCalculator final : public ArithmeticCalculatorInterface
{
public:
AttributeValueArithmeticCalculator(std::uint16_t index, table::Value &&value)
: _index(index), _value(std::move(value))
{
}
~AttributeValueArithmeticCalculator() override = default;
table::Value calculate(const table::Tuple &tuple) override
{
if constexpr (T == ArithmeticCalculatorInterface::Add)
{
return tuple.get(_index) + _value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Sub)
{
return tuple.get(_index) - _value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Multiply)
{
return tuple.get(_index) * _value;
}
else if constexpr (T == ArithmeticCalculatorInterface::Divide)
{
return tuple.get(_index) / _value;
}
else
{
return tuple.get(_index);
}
}
private:
const std::uint16_t _index;
const table::Value _value;
};
template <ArithmeticCalculatorInterface::Type T>
class ValueAttributeArithmeticCalculator final : public ArithmeticCalculatorInterface
{
public:
ValueAttributeArithmeticCalculator(table::Value &&value, std::uint16_t index)
: _value(std::move(value)), _index(index)
{
}
~ValueAttributeArithmeticCalculator() override = default;
table::Value calculate(const table::Tuple &tuple) override
{
if constexpr (T == ArithmeticCalculatorInterface::Add)
{
return _value + tuple.get(_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Sub)
{
return _value - tuple.get(_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Multiply)
{
return _value * tuple.get(_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Divide)
{
return _value / tuple.get(_index);
}
else
{
return _value;
}
}
private:
const table::Value _value;
const std::uint16_t _index;
};
template <ArithmeticCalculatorInterface::Type T>
class AttributeArithmeticCalculator final : public ArithmeticCalculatorInterface
{
public:
AttributeArithmeticCalculator(std::uint16_t left_index, std::uint16_t right_index)
: _left_index(left_index), _right_index(right_index)
{
}
~AttributeArithmeticCalculator() override = default;
table::Value calculate(const table::Tuple &tuple) override
{
if constexpr (T == ArithmeticCalculatorInterface::Add)
{
return tuple.get(_left_index) + tuple.get(_right_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Sub)
{
return tuple.get(_left_index) - tuple.get(_right_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Multiply)
{
return tuple.get(_left_index) * tuple.get(_right_index);
}
else if constexpr (T == ArithmeticCalculatorInterface::Divide)
{
return tuple.get(_left_index) / tuple.get(_right_index);
}
else
{
return tuple.get(_left_index);
}
}
private:
const std::uint16_t _left_index;
const std::uint16_t _right_index;
};
} // namespace beedb::execution

View File

@ -0,0 +1,54 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "arithmetic_calculator.h"
#include "unary_operator.h"
#include <memory>
#include <unordered_map>
namespace beedb::execution
{
class ArithmeticOperator : public UnaryOperator
{
public:
ArithmeticOperator(
concurrency::Transaction *transaction, table::Schema &&schema,
std::unordered_map<std::uint16_t, std::unique_ptr<ArithmeticCalculatorInterface>> &&arithmetic_calculators);
~ArithmeticOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
table::Schema _schema;
std::unordered_map<std::uint16_t, std::unique_ptr<ArithmeticCalculatorInterface>> _arithmetic_calculators;
std::unordered_map<std::uint16_t, std::uint16_t> _child_schema_map;
};
} // namespace beedb::execution

View File

@ -0,0 +1,69 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include <memory>
#include <table/schema.h>
#include <table/tuple.h>
namespace beedb::execution
{
/**
* Abstract operator that has to children (left and right)
* for operators JOIN-like operators.
*/
class BinaryOperator : public OperatorInterface
{
public:
explicit BinaryOperator(concurrency::Transaction *transaction) : OperatorInterface(transaction)
{
}
~BinaryOperator() override = default;
void left_child(std::unique_ptr<OperatorInterface> child)
{
_left_child = std::move(child);
}
void right_child(std::unique_ptr<OperatorInterface> child)
{
_right_child = std::move(child);
}
[[nodiscard]] const std::unique_ptr<OperatorInterface> &left_child() const
{
return _left_child;
}
[[nodiscard]] const std::unique_ptr<OperatorInterface> &right_child() const
{
return _right_child;
}
protected:
[[nodiscard]] table::Tuple combine(const table::Schema &new_schema, const table::Tuple &left,
const table::Tuple &right) const;
private:
std::unique_ptr<OperatorInterface> _left_child;
std::unique_ptr<OperatorInterface> _right_child;
};
} // namespace beedb::execution

View File

@ -0,0 +1,77 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "binary_operator.h"
#include <database.h>
#include <index/index_interface.h>
#include <memory>
#include <string>
#include <table/schema.h>
namespace beedb::execution
{
/**
* Fills an existing index with values.
* May have two children: One operator creating the index (left)
* which is called once and one operator (right) which provides the
* data for the index.
*/
class BuildIndexOperator final : public BinaryOperator
{
public:
BuildIndexOperator(Database &database, concurrency::Transaction *transaction, const std::string &table_name,
const table::Schema::ColumnIndexType column_index, const std::string &index_name);
~BuildIndexOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
void create_index_operator(std::unique_ptr<OperatorInterface> op)
{
this->left_child(std::move(op));
}
void data_operator(std::unique_ptr<OperatorInterface> op)
{
this->right_child(std::move(op));
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema;
Database &_database;
const std::string _table_name;
const std::uint32_t _column_index;
const std::string _index_name;
};
} // namespace beedb::execution

View File

@ -0,0 +1,78 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include <database.h>
#include <index/type.h>
#include <string>
#include <table/table.h>
#include <table/tuple.h>
#include <table/type.h>
#include <tuple>
#include <vector>
namespace beedb::execution
{
/**
* Operator that creates and persists a new index for a given
* column with given index attributes (type, unique or non-unique).
*/
class CreateIndexOperator final : public OperatorInterface
{
public:
CreateIndexOperator(Database &database, concurrency::Transaction *transaction, const std::string &table_name,
const std::string &column_name, const std::string &index_name, const bool is_unique,
const index::Type type);
~CreateIndexOperator() override = default;
void open() override
{
}
util::optional<table::Tuple> next() override;
void close() override
{
}
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema;
Database &_database;
const std::string _table_name;
const std::string _column_name;
const std::string _index_name;
const bool _is_unique;
const index::Type _index_type;
};
} // namespace beedb::execution

View File

@ -0,0 +1,65 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include <database.h>
#include <string>
#include <table/table.h>
#include <table/tuple.h>
#include <table/type.h>
#include <tuple>
#include <vector>
namespace beedb::execution
{
/**
* Creates and persists a new table.
*/
class CreateTableOperator final : public OperatorInterface
{
public:
CreateTableOperator(Database &database, concurrency::Transaction *transaction, table::Schema &&schema_to_create);
~CreateTableOperator() override = default;
void open() override{};
util::optional<table::Tuple> next() override;
void close() override{};
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
};
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
Database &_database;
const table::Schema _schema;
const table::Schema _schema_to_create;
};
} // namespace beedb::execution

View File

@ -0,0 +1,58 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "binary_operator.h"
#include <string>
#include <table/memory_table.h>
#include <table/schema.h>
#include <table/tuple.h>
#include <table/value.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
/**
* Generates a cross product of two sources.
*/
class CrossProductOperator final : public BinaryOperator
{
public:
CrossProductOperator(concurrency::Transaction *transaction, table::Schema &&schema);
~CrossProductOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema _schema;
util::optional<table::Tuple> _next_left_tuple;
};
} // namespace beedb::execution

View File

@ -0,0 +1,64 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <buffer/manager.h>
#include <cstdint>
#include <table/table_disk_manager.h>
#include <table/value.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
class DeleteOperator : public UnaryOperator
{
public:
DeleteOperator(concurrency::Transaction *transaction, table::Table &table,
table::TableDiskManager &table_disk_manager, buffer::Manager &buffer_manager)
: UnaryOperator(transaction), _table(table), _table_disk_manager(table_disk_manager),
_buffer_manager(buffer_manager)
{
}
~DeleteOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _table.schema();
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
table::Table &_table;
table::TableDiskManager _table_disk_manager;
buffer::Manager &_buffer_manager;
};
} // namespace beedb::execution

View File

@ -0,0 +1,109 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "binary_operator.h"
#include "tuple_buffer.h"
#include <memory>
#include <string>
#include <table/memory_table.h>
#include <table/schema.h>
#include <table/tuple.h>
#include <unordered_map>
#include <utility>
#include <vector>
namespace beedb::execution
{
/**
* Hash table for hash join.
*/
class HashTable
{
public:
explicit HashTable(const std::uint32_t key_index) : _key_index(key_index)
{
}
~HashTable() = default;
bool contains(const table::Value &key)
{
return this->_map.find(key) != _map.end();
}
void put(const table::Tuple &tuple)
{
table::Tuple in_memory_tuple(tuple);
this->_map[tuple.get(_key_index)].push_back(std::move(in_memory_tuple));
}
const std::vector<table::Tuple> &get(const table::Value &key)
{
return _map[key];
}
private:
const std::uint32_t _key_index;
std::unordered_map<table::Value, std::vector<table::Tuple>> _map;
};
/**
* Operator that joins two sources using a hash table over
* the left source.
*/
class HashJoinOperator final : public BinaryOperator
{
public:
HashJoinOperator(concurrency::Transaction *transaction, table::Schema &&schema, const std::uint32_t left_index,
const std::uint32_t right_index);
~HashJoinOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema _schema;
const std::uint32_t _left_index;
const std::uint32_t _right_index;
HashTable _hash_table;
bool _is_built = false;
TupleBuffer _tuple_buffer;
/**
* Builds the hash table.
*/
void build_hash_table();
/**
* Probes the hash table.
*/
util::optional<table::Tuple> probe_hash_table();
};
} // namespace beedb::execution

View File

@ -0,0 +1,141 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include "tuple_buffer.h"
#include <buffer/manager.h>
#include <index/index_interface.h>
#include <memory>
#include <queue>
#include <storage/page.h>
#include <table/table.h>
#include <table/table_disk_manager.h>
#include <table/tuple.h>
#include <unordered_set>
#include <vector>
namespace beedb::execution
{
/**
* Key (range) that have to be looked up in the.
* May be a range or a single key.
*/
class KeyRange
{
public:
explicit KeyRange(const std::int64_t single_key) : _from(single_key), _to(std::numeric_limits<std::int64_t>::max())
{
}
KeyRange(const std::int64_t from, const std::int64_t to) : _from(from), _to(to)
{
}
~KeyRange() = default;
[[nodiscard]] bool is_single_key() const
{
return _to == std::numeric_limits<std::int64_t>::max();
}
[[nodiscard]] std::int64_t single_key() const
{
return _from;
}
[[nodiscard]] std::int64_t from() const
{
return _from;
}
[[nodiscard]] std::int64_t to() const
{
return _to;
}
bool operator<(const KeyRange &other) const
{
return _from < other._from;
}
bool operator==(const KeyRange &other) const
{
return _from == other._from && _to == other._to;
}
private:
const std::int64_t _from;
const std::int64_t _to;
};
} // namespace beedb::execution
namespace std
{
template <> struct hash<beedb::execution::KeyRange>
{
public:
std::size_t operator()(const beedb::execution::KeyRange &range) const
{
return std::hash<std::int64_t>()(range.from()) ^ std::hash<std::int64_t>()(range.to());
}
};
} // namespace std
namespace beedb::execution
{
/**
* Takes an index and keys to be looked up in the index
* and scans only over pages found in the index instead
* of scanning all pages from the table.
*/
class IndexScanOperator final : public OperatorInterface
{
public:
IndexScanOperator(concurrency::Transaction *transaction, const std::uint32_t scan_page_limit,
const table::Schema &schema, buffer::Manager &buffer_manager,
table::TableDiskManager &table_disk_manager, std::unordered_set<KeyRange> &&key_ranges,
std::shared_ptr<index::IndexInterface> index);
~IndexScanOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const std::uint32_t _scan_page_limit;
const table::Schema _schema;
buffer::Manager &_buffer_manager;
table::TableDiskManager &_table_disk_manager;
std::unordered_set<KeyRange> _key_ranges;
std::shared_ptr<index::IndexInterface> _index;
std::queue<storage::Page::id_t> _pages_to_scan;
std::vector<storage::Page::id_t> _pinned_pages;
TupleBuffer _buffer;
};
} // namespace beedb::execution

View File

@ -0,0 +1,69 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <buffer/manager.h>
#include <set>
#include <statistic/system_statistics.h>
#include <table/table.h>
#include <table/table_disk_manager.h>
#include <table/tuple.h>
namespace beedb::execution
{
/**
* Inserts all tuples provided by the children operator.
* The child may be a tuple buffer or a subquery.
*/
class InsertOperator final : public UnaryOperator
{
public:
InsertOperator(concurrency::Transaction *transaction, buffer::Manager &buffer_manager,
table::TableDiskManager &table_disk_manager, statistic::SystemStatistics &statistics,
table::Table &table);
~InsertOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema;
buffer::Manager &_buffer_manager;
table::TableDiskManager &_table_disk_manager;
statistic::SystemStatistics &_statistics;
table::Table &_table;
storage::Page::id_t _last_pinned_page = storage::Page::INVALID_PAGE_ID;
};
} // namespace beedb::execution

View File

@ -0,0 +1,60 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <cstdint>
#include <table/schema.h>
#include <table/tuple.h>
#include <vector>
namespace beedb::execution
{
/**
* Limits the output result.
*/
class LimitOperator final : public UnaryOperator
{
public:
LimitOperator(concurrency::Transaction *transaction, const table::Schema &schema, const std::uint64_t limit,
const std::uint64_t offset);
~LimitOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
};
private:
const table::Schema &_schema;
const std::uint64_t _limit;
const std::uint64_t _offset;
bool _has_skipped = false;
std::uint64_t _count = 0;
};
} // namespace beedb::execution

View File

@ -0,0 +1,67 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "binary_operator.h"
#include "predicate_matcher.h"
#include <string>
#include <table/memory_table.h>
#include <table/schema.h>
#include <table/tuple.h>
#include <table/value.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
/**
* Joins two sources by outer-looping over the left
* and inner looping over the right children tuples.
*/
class NestedLoopsJoinOperator final : public BinaryOperator
{
public:
NestedLoopsJoinOperator(concurrency::Transaction *transaction, table::Schema &&schema,
std::unique_ptr<PredicateMatcherInterface> &&predicate_matcher);
~NestedLoopsJoinOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema _schema;
std::unique_ptr<PredicateMatcherInterface> _predicate_matcher;
util::optional<table::Tuple> _next_left_tuple;
[[nodiscard]] bool matches(const table::Tuple &left, const table::Tuple &right)
{
return this->_predicate_matcher->matches(left, right);
}
};
} // namespace beedb::execution

View File

@ -0,0 +1,63 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <concurrency/transaction.h>
#include <table/schema.h>
#include <table/tuple.h>
#include <util/optional.h>
namespace beedb::execution
{
/**
* Interface for all physical execution operators.
* The interface is volcano-style (using open, next, and close).
*/
class OperatorInterface
{
public:
explicit OperatorInterface(concurrency::Transaction *transaction) : _transaction(transaction)
{
}
virtual ~OperatorInterface() = default;
virtual void open() = 0;
virtual util::optional<table::Tuple> next() = 0;
virtual void close() = 0;
[[nodiscard]] virtual bool yields_data() const
{
return true;
}
[[nodiscard]] virtual const table::Schema &schema() const = 0;
protected:
[[nodiscard]] concurrency::Transaction *transaction() const
{
return _transaction;
}
private:
concurrency::Transaction *_transaction;
};
} // namespace beedb::execution

View File

@ -0,0 +1,111 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <cstdint>
#include <memory>
#include <table/memory_table.h>
#include <table/schema.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
/**
* Comparator for comparing two tuples during
* sort.
*/
class TupleComparator
{
public:
explicit TupleComparator(const std::vector<std::pair<std::uint32_t, bool>> &indices) : _indices(indices)
{
}
~TupleComparator() = default;
bool operator()(const table::Tuple &left, const table::Tuple &right) const
{
for (auto &[index, is_ascending] : _indices)
{
const auto value_left = left.get(index);
const auto value_right = right.get(index);
if (is_ascending)
{
if (value_left < value_right)
{
return true;
}
else if (value_left > value_right)
{
return false;
}
}
else
{
if (value_right < value_left)
{
return true;
}
else if (value_right > value_left)
{
return false;
}
}
}
return false;
}
private:
const std::vector<std::pair<std::uint32_t, bool>> &_indices;
};
/**
* Sorts the result provided by a child using quicksort.
*/
class OrderOperator final : public UnaryOperator
{
public:
OrderOperator(concurrency::Transaction *transaction, const table::Schema &schema,
std::vector<std::pair<std::uint32_t, bool>> &&order_columns);
~OrderOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema &_schema;
const std::vector<std::pair<std::uint32_t, bool>> _order_columns;
std::unique_ptr<table::MemoryTable> _result_table;
std::size_t _stack_index = 0u;
};
} // namespace beedb::execution

View File

@ -0,0 +1,299 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <memory>
#include <table/schema.h>
#include <table/tuple.h>
namespace beedb::execution
{
/**
* Interface for predicate matcher. The predicate matcher
* takes one or two tuples and compares them with a constant
* or a value from another tuple.
*/
class PredicateMatcherInterface
{
public:
enum Comparison
{
EQ,
LE,
LT,
GE,
GT,
NEQ
};
virtual ~PredicateMatcherInterface() = default;
virtual bool matches(const table::Tuple &tuple) = 0;
virtual bool matches(const table::Tuple &left, const table::Tuple &right) = 0;
virtual std::unique_ptr<PredicateMatcherInterface> clone() = 0;
};
/**
* The given tuple will always match.
*/
class AlwaysTrueMatcher final : public PredicateMatcherInterface
{
public:
AlwaysTrueMatcher() = default;
~AlwaysTrueMatcher() override = default;
bool matches(const table::Tuple &) override
{
return true;
}
bool matches(const table::Tuple &, const table::Tuple &) override
{
return true;
}
std::unique_ptr<PredicateMatcherInterface> clone() override
{
return std::make_unique<AlwaysTrueMatcher>();
}
};
/**
* Takes two predicate matchers p1 and p2 and connects them using AND.
* Tuple matches when p1 AND p2 matches.
*/
class AndMatcher final : public PredicateMatcherInterface
{
public:
AndMatcher(std::unique_ptr<PredicateMatcherInterface> &&left, std::unique_ptr<PredicateMatcherInterface> &&right)
: _left(std::move(left)), _right(std::move(right))
{
}
~AndMatcher() override = default;
bool matches(const table::Tuple &tuple) override
{
return _left->matches(tuple) && _right->matches(tuple);
}
bool matches(const table::Tuple &left, const table::Tuple &right) override
{
return _left->matches(left, right) && _right->matches(left, right);
}
std::unique_ptr<PredicateMatcherInterface> clone() override
{
return std::make_unique<AndMatcher>(_left->clone(), _right->clone());
}
private:
std::unique_ptr<PredicateMatcherInterface> _left;
std::unique_ptr<PredicateMatcherInterface> _right;
};
/**
* Takes two predicate matchers p1 and p2 and connects them using OR.
* Tuple matches when p1 OR p2 matches.
*/
class OrMatcher final : public PredicateMatcherInterface
{
public:
OrMatcher(std::unique_ptr<PredicateMatcherInterface> &&left, std::unique_ptr<PredicateMatcherInterface> &&right)
: _left(std::move(left)), _right(std::move(right))
{
}
~OrMatcher() override = default;
bool matches(const table::Tuple &tuple) override
{
return _left->matches(tuple) || _right->matches(tuple);
}
bool matches(const table::Tuple &left, const table::Tuple &right) override
{
return _left->matches(left, right) || _right->matches(left, right);
}
std::unique_ptr<PredicateMatcherInterface> clone() override
{
return std::make_unique<OrMatcher>(_left->clone(), _right->clone());
}
private:
std::unique_ptr<PredicateMatcherInterface> _left;
std::unique_ptr<PredicateMatcherInterface> _right;
};
/**
* Compares a specific column in a tuple with a constant.
*/
template <PredicateMatcherInterface::Comparison C> class AttributeValueMatcher final : public PredicateMatcherInterface
{
public:
AttributeValueMatcher(const table::Schema::ColumnIndexType schema_index, table::Value &&value)
: _schema_index(schema_index), _value(std::move(value))
{
}
AttributeValueMatcher(const table::Schema::ColumnIndexType schema_index, const table::Value &value)
: _schema_index(schema_index), _value(value)
{
}
~AttributeValueMatcher() override = default;
bool matches(const table::Tuple &tuple) override
{
if constexpr (C == EQ)
{
return tuple.get(_schema_index) == _value;
}
else if constexpr (C == LE)
{
return tuple.get(_schema_index) <= _value;
}
else if constexpr (C == LT)
{
return tuple.get(_schema_index) < _value;
}
else if constexpr (C == GE)
{
return tuple.get(_schema_index) >= _value;
}
else if constexpr (C == GT)
{
return tuple.get(_schema_index) > _value;
}
else
{
return tuple.get(_schema_index) != _value;
}
}
bool matches(const table::Tuple &, const table::Tuple &) override
{
return false;
}
std::unique_ptr<PredicateMatcherInterface> clone() override
{
return std::make_unique<AttributeValueMatcher<C>>(_schema_index, _value);
}
protected:
const table::Schema::ColumnIndexType _schema_index;
const table::Value _value;
};
/**
* Compares two columns in a tuple or one column of two tuples.
*/
template <PredicateMatcherInterface::Comparison C> class AttributeMatcher final : public PredicateMatcherInterface
{
public:
AttributeMatcher(const table::Schema::ColumnIndexType schema_index_left,
const table::Schema::ColumnIndexType schema_index_right)
: _schema_index_left(schema_index_left), _schema_index_right(schema_index_right)
{
}
~AttributeMatcher() override = default;
bool matches(const table::Tuple &tuple) override
{
if constexpr (C == EQ)
{
return tuple.get(_schema_index_left) == tuple.get(_schema_index_right);
}
else if constexpr (C == LE)
{
return tuple.get(_schema_index_left) <= tuple.get(_schema_index_right);
}
else if constexpr (C == LT)
{
return tuple.get(_schema_index_left) < tuple.get(_schema_index_right);
}
else if constexpr (C == GE)
{
return tuple.get(_schema_index_left) >= tuple.get(_schema_index_right);
}
else if constexpr (C == GT)
{
return tuple.get(_schema_index_left) > tuple.get(_schema_index_right);
}
else
{
return tuple.get(_schema_index_left) != tuple.get(_schema_index_right);
}
}
bool matches(const table::Tuple &left, const table::Tuple &right) override
{
if constexpr (C == EQ)
{
return left.get(_schema_index_left) == right.get(_schema_index_right);
}
else if constexpr (C == LE)
{
return left.get(_schema_index_left) <= right.get(_schema_index_right);
}
else if constexpr (C == LT)
{
return left.get(_schema_index_left) < right.get(_schema_index_right);
}
else if constexpr (C == GE)
{
return left.get(_schema_index_left) >= right.get(_schema_index_right);
}
else if constexpr (C == GT)
{
return left.get(_schema_index_left) > right.get(_schema_index_right);
}
else
{
return left.get(_schema_index_left) != right.get(_schema_index_right);
}
}
std::unique_ptr<PredicateMatcherInterface> clone() override
{
return std::make_unique<AttributeMatcher<C>>(_schema_index_left, _schema_index_right);
}
[[nodiscard]] table::Schema::ColumnIndexType left_index() const
{
return _schema_index_left;
}
[[nodiscard]] table::Schema::ColumnIndexType right_index() const
{
return _schema_index_right;
}
protected:
const table::Schema::ColumnIndexType _schema_index_left;
const table::Schema::ColumnIndexType _schema_index_right;
};
} // namespace beedb::execution

View File

@ -0,0 +1,56 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <cstdint>
#include <string>
#include <table/schema.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
/**
* Applies a new schema to all tuples provided by the children.
* May hide or re-order columns.
*/
class ProjectionOperator final : public UnaryOperator
{
public:
ProjectionOperator(concurrency::Transaction *transaction, table::Schema &&schema);
~ProjectionOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema _schema;
};
} // namespace beedb::execution

View File

@ -0,0 +1,68 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "predicate_matcher.h"
#include "unary_operator.h"
#include <cstdint>
#include <memory>
#include <string>
#include <table/column.h>
#include <table/schema.h>
#include <table/value.h>
namespace beedb::execution
{
/**
* Selects tuples matching a given predicate.
* Some tuples may be filtered.
*/
class SelectionOperator final : public UnaryOperator
{
public:
SelectionOperator(concurrency::Transaction *transaction, const table::Schema &schema,
std::unique_ptr<PredicateMatcherInterface> &&predicate_matcher);
~SelectionOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const table::Schema &_schema;
std::unique_ptr<PredicateMatcherInterface> _predicate_matcher;
[[nodiscard]] bool matches(const table::Tuple &tuple)
{
return this->_predicate_matcher->matches(tuple);
}
};
} // namespace beedb::execution

View File

@ -0,0 +1,68 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "tuple_buffer.h"
#include "unary_operator.h"
#include <buffer/manager.h>
#include <storage/page.h>
#include <table/table.h>
#include <table/table_disk_manager.h>
#include <table/tuple.h>
#include <vector>
namespace beedb::execution
{
/**
* Scans all pages of a given table and returns all tuples.
*/
class SequentialScanOperator final : public UnaryOperator
{
public:
SequentialScanOperator(concurrency::Transaction *transaction, std::uint32_t scan_page_limit, table::Schema &&schema,
buffer::Manager &buffer_manager, table::TableDiskManager &table_disk_manager,
const table::Table &table);
~SequentialScanOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
private:
const std::uint32_t _scan_page_limit;
const table::Schema _schema;
buffer::Manager &_buffer_manager;
table::TableDiskManager &_table_disk_manager;
const table::Table &_table;
storage::Page::id_t _next_page_id_to_scan = storage::Page::INVALID_PAGE_ID;
std::vector<storage::Page::id_t> _pinned_pages;
TupleBuffer _buffer;
};
} // namespace beedb::execution

View File

@ -0,0 +1,125 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include <concurrency/transaction.h>
#include <concurrency/transaction_callback.h>
#include <concurrency/transaction_manager.h>
namespace beedb::execution
{
class BeginTransactionOperator : public OperatorInterface
{
public:
BeginTransactionOperator(concurrency::TransactionManager &transaction_manager,
concurrency::TransactionCallback &transaction_callback)
: OperatorInterface(nullptr), _transaction_manager(transaction_manager),
_transaction_callback(transaction_callback)
{
}
~BeginTransactionOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema = {};
concurrency::TransactionManager &_transaction_manager;
concurrency::TransactionCallback &_transaction_callback;
};
class AbortTransactionOperator : public OperatorInterface
{
public:
AbortTransactionOperator(concurrency::TransactionManager &transaction_manager,
concurrency::Transaction *transaction,
concurrency::TransactionCallback &transaction_callback)
: OperatorInterface(transaction), _transaction_manager(transaction_manager),
_transaction_callback(transaction_callback)
{
}
~AbortTransactionOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema = {};
concurrency::TransactionManager &_transaction_manager;
concurrency::TransactionCallback &_transaction_callback;
};
class CommitTransactionOperator : public OperatorInterface
{
public:
CommitTransactionOperator(concurrency::TransactionManager &transaction_manager,
concurrency::Transaction *transaction,
concurrency::TransactionCallback &transaction_callback)
: OperatorInterface(transaction), _transaction_manager(transaction_manager),
_transaction_callback(transaction_callback)
{
}
~CommitTransactionOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
const table::Schema _schema = {};
concurrency::TransactionManager &_transaction_manager;
concurrency::TransactionCallback &_transaction_callback;
};
} // namespace beedb::execution

View File

@ -0,0 +1,69 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <table/tuple.h>
#include <vector>
namespace beedb::execution
{
/**
* Buffers tuples; needed by blocking operators.
*/
class TupleBuffer
{
public:
TupleBuffer() = default;
~TupleBuffer() = default;
void add(table::Tuple &&tuple)
{
_buffer.push_back(std::move(tuple));
}
void add(std::vector<table::Tuple> &&tuples)
{
std::move(tuples.begin(), tuples.end(), std::back_inserter(_buffer));
}
[[nodiscard]] bool empty() const
{
return _buffer.empty() || _head > _buffer.size() - 1;
}
[[nodiscard]] table::Tuple &&pop()
{
return std::move(_buffer[_head++]);
}
void clear()
{
_buffer.clear();
_head = 0u;
}
private:
std::vector<table::Tuple> _buffer;
std::size_t _head = 0u;
};
} // namespace beedb::execution

View File

@ -0,0 +1,70 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include "tuple_buffer.h"
#include <table/schema.h>
#include <table/tuple.h>
#include <vector>
namespace beedb::execution
{
/**
* Buffers tuples and pops the on next().
*/
class TupleBufferOperator final : public OperatorInterface
{
public:
TupleBufferOperator(concurrency::Transaction *transaction, const table::Schema &schema);
~TupleBufferOperator() override = default;
void open() override
{
}
util::optional<table::Tuple> next() override;
void close() override
{
}
[[nodiscard]] const table::Schema &schema() const override
{
return _schema;
}
void add(table::Tuple &tuple)
{
_tuple_buffer.add(std::move(tuple));
}
void add(std::vector<table::Tuple> &tuples)
{
_tuple_buffer.add(std::move(tuples));
}
private:
const table::Schema _schema;
TupleBuffer _tuple_buffer;
};
} // namespace beedb::execution

View File

@ -0,0 +1,54 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "operator_interface.h"
#include <memory>
namespace beedb::execution
{
/**
* Interface for operators providing a single child.
*/
class UnaryOperator : public OperatorInterface
{
public:
explicit UnaryOperator(concurrency::Transaction *transaction) : OperatorInterface(transaction)
{
}
~UnaryOperator() override = default;
void child(std::unique_ptr<OperatorInterface> &&child)
{
_child = std::move(child);
}
[[nodiscard]] const std::unique_ptr<OperatorInterface> &child() const
{
return _child;
}
private:
std::unique_ptr<OperatorInterface> _child;
};
} // namespace beedb::execution

View File

@ -0,0 +1,66 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "unary_operator.h"
#include <buffer/manager.h>
#include <cstdint>
#include <table/table_disk_manager.h>
#include <table/value.h>
#include <utility>
#include <vector>
namespace beedb::execution
{
class UpdateOperator : public UnaryOperator
{
public:
UpdateOperator(concurrency::Transaction *transaction, table::Table &table,
table::TableDiskManager &table_disk_manager, buffer::Manager &buffer_manager,
std::vector<std::pair<table::Schema::ColumnIndexType, table::Value>> &&values)
: UnaryOperator(transaction), _table(table), _table_disk_manager(table_disk_manager),
_buffer_manager(buffer_manager), _new_column_values(std::move(values))
{
}
~UpdateOperator() override = default;
void open() override;
util::optional<table::Tuple> next() override;
void close() override;
[[nodiscard]] const table::Schema &schema() const override
{
return _table.schema();
}
[[nodiscard]] bool yields_data() const override
{
return false;
}
private:
table::Table &_table;
table::TableDiskManager _table_disk_manager;
buffer::Manager &_buffer_manager;
std::vector<std::pair<table::Schema::ColumnIndexType, table::Value>> _new_column_values;
};
} // namespace beedb::execution

View File

@ -0,0 +1,130 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <optional>
#include <string>
namespace beedb::expression
{
class Attribute
{
public:
Attribute() = default;
explicit Attribute(std::string &&column_name) : _table_name{std::nullopt}, _column_name(std::move(column_name))
{
}
explicit Attribute(const std::string &column_name) : _table_name{std::nullopt}, _column_name(column_name)
{
}
Attribute(std::string &&table_name, std::string &&column_name)
: _table_name(std::move(table_name)), _column_name(std::move(column_name))
{
}
Attribute(const std::string &table_name, const std::string &column_name)
: _table_name(table_name), _column_name(column_name)
{
}
Attribute(const std::string &table_name, std::string &&column_name)
: _table_name(table_name), _column_name(std::move(column_name))
{
}
Attribute(std::optional<std::string> &&table_name, std::string &&column_name)
: _table_name(std::move(table_name)), _column_name(std::move(column_name))
{
}
Attribute(std::optional<std::string> &&table_name, std::string &&column_name, const bool print_table_name)
: _table_name(std::move(table_name)), _column_name(std::move(column_name)), _print_table_name(print_table_name)
{
}
Attribute(const std::optional<std::string> &table_name, std::string &&column_name)
: _table_name(table_name), _column_name(std::move(column_name))
{
}
Attribute(const Attribute &other, const bool print_table_name)
: _table_name(other._table_name), _column_name(other._column_name), _print_table_name(print_table_name)
{
}
Attribute(Attribute &&) = default;
Attribute(const Attribute &) = default;
~Attribute() = default;
Attribute &operator=(const Attribute &) = default;
Attribute &operator=(Attribute &&) = default;
bool operator==(const Attribute &other) const
{
return _table_name == other._table_name && _column_name == other._column_name;
}
void table_name(const std::string &table_name)
{
_table_name = table_name;
}
[[nodiscard]] const std::optional<std::string> &table_name() const
{
return _table_name;
}
[[nodiscard]] const std::string &column_name() const
{
return _column_name;
}
[[nodiscard]] bool is_asterisk() const
{
return _column_name == "*";
}
[[nodiscard]] bool is_print_table_name() const
{
return _print_table_name;
}
explicit operator std::string() const
{
if (_table_name.has_value() && _print_table_name)
{
return _table_name.value() + "." + _column_name;
}
return _column_name;
}
private:
std::optional<std::string> _table_name;
std::string _column_name;
bool _print_table_name = false;
};
} // namespace beedb::expression
namespace std
{
template <> struct hash<beedb::expression::Attribute>
{
public:
std::size_t operator()(const beedb::expression::Attribute &attribute) const
{
return std::hash<std::string>()(
std::string{attribute.table_name().value_or("") + "." + attribute.column_name()});
}
};
} // namespace std

View File

@ -0,0 +1,384 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "term.h"
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace beedb::expression
{
class Operation
{
public:
enum Type : std::uint8_t
{
Identity = 0,
Count = 4,
Average = 5,
Sum = 6,
Min = 7,
Max = 8,
Add = 16,
Sub = 17,
Multiply = 18,
Divide = 19,
And = 32,
Or = 33,
Equals = 64,
NotEquals = 65,
Lesser = 66,
LesserEquals = 67,
Greater = 68,
GreaterEquals = 69
};
[[nodiscard]] bool is_nullary() const
{
return _type == Identity;
}
[[nodiscard]] bool is_unary() const
{
return _type >= static_cast<std::uint8_t>(Type::Count) && _type <= static_cast<std::uint8_t>(Type::Max);
}
[[nodiscard]] bool is_aggregation() const
{
return _type >= static_cast<std::uint8_t>(Type::Count) && _type <= static_cast<std::uint8_t>(Type::Max);
}
[[nodiscard]] bool is_logical_connective() const
{
return _type == Type::And || _type == Type::Or;
}
[[nodiscard]] bool is_comparison() const
{
return _type >= static_cast<std::uint8_t>(Type::Equals) &&
_type <= static_cast<std::uint8_t>(Type::GreaterEquals);
}
[[nodiscard]] bool is_arithmetic() const
{
return _type >= static_cast<std::uint8_t>(Type::Add) && _type <= static_cast<std::uint8_t>(Type::Divide);
}
[[nodiscard]] bool is_binary() const
{
return is_logical_connective() || is_comparison() || is_arithmetic();
}
[[nodiscard]] Type type() const
{
return _type;
}
void type(Type type)
{
_type = type;
}
[[nodiscard]] const std::optional<Term> &result() const
{
return _result;
}
[[nodiscard]] std::optional<Term> &result()
{
return _result;
}
void alias(std::string &&alias)
{
_result->alias(std::move(alias));
}
[[nodiscard]] virtual std::unique_ptr<Operation> copy() const = 0;
virtual ~Operation() = default;
protected:
explicit Operation(const Type type) : _type(type), _result(std::nullopt)
{
}
Operation(const Type type, Term &&result) : _type(type), _result(std::move(result))
{
}
Operation(const Type type, std::optional<Term> &&result) : _type(type), _result(std::move(result))
{
}
Type _type;
std::optional<Term> _result;
};
class NullaryOperation : public Operation
{
public:
explicit NullaryOperation(Term &&term) : Operation(Operation::Identity, term)
{
}
NullaryOperation(const NullaryOperation &) = default;
NullaryOperation(NullaryOperation &&) = default;
~NullaryOperation() override = default;
[[nodiscard]] const Term &term() const
{
return _result.value();
}
[[nodiscard]] Term &term()
{
return _result.value();
}
[[nodiscard]] std::unique_ptr<Operation> copy() const override
{
return std::make_unique<NullaryOperation>(Term{_result.value()});
}
};
class UnaryOperation : public Operation
{
public:
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_count(std::unique_ptr<Operation> &&child)
{
return UnaryOperation::make_operation(Operation::Type::Count, "COUNT", std::move(child));
}
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_avg(std::unique_ptr<Operation> &&child)
{
return UnaryOperation::make_operation(Operation::Type::Average, "AVG", std::move(child));
}
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_sum(std::unique_ptr<Operation> &&child)
{
return UnaryOperation::make_operation(Operation::Type::Sum, "SUM", std::move(child));
}
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_min(std::unique_ptr<Operation> &&child)
{
return UnaryOperation::make_operation(Operation::Type::Min, "MIN", std::move(child));
}
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_max(std::unique_ptr<Operation> &&child)
{
return UnaryOperation::make_operation(Operation::Type::Max, "MAX", std::move(child));
}
UnaryOperation(const Type type, Term &&result, std::unique_ptr<Operation> &&child)
: Operation(type, std::move(result)), _child(std::move(child))
{
}
UnaryOperation(const Type type, std::optional<Term> &&result, std::unique_ptr<Operation> &&child)
: Operation(type, std::move(result)), _child(std::move(child))
{
}
UnaryOperation(const Type type, std::unique_ptr<Operation> &&child) : Operation(type), _child(std::move(child))
{
}
~UnaryOperation() override = default;
[[nodiscard]] const std::unique_ptr<Operation> &child() const
{
return _child;
}
[[nodiscard]] std::unique_ptr<Operation> &child()
{
return _child;
}
[[nodiscard]] std::unique_ptr<Operation> copy() const override
{
return std::make_unique<UnaryOperation>(
_type, _result.has_value() ? std::make_optional(Term{_result.value()}) : std::nullopt, _child->copy());
}
private:
std::unique_ptr<Operation> _child;
[[nodiscard]] static std::unique_ptr<UnaryOperation> make_operation(const Operation::Type type, std::string &&name,
std::unique_ptr<Operation> &&child)
{
return std::make_unique<UnaryOperation>(
type,
expression::Term{
expression::Attribute{std::move(name) + "(" + static_cast<std::string>(child->result().value()) + ")"},
std::nullopt, true},
std::move(child));
}
};
class BinaryOperation : public Operation
{
public:
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_and(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::And, " AND ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_or(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Or, " OR ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_equals(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Equals, " = ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_not_equals(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::NotEquals, " != ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_lesser(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Lesser, " < ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_lesser_equals(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::LesserEquals, " <= ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_greater(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Greater, " > ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_greater_equals(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::GreaterEquals, " >= ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_add(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Add, " + ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_sub(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Sub, " - ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_mul(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Multiply, " * ", std::move(left_child),
std::move(right_child));
}
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_div(std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
return BinaryOperation::make_operation(Operation::Type::Divide, " / ", std::move(left_child),
std::move(right_child));
}
BinaryOperation(const Type type, Term &&result, std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
: Operation(type, std::move(result)), _left_child(std::move(left_child)), _right_child(std::move(right_child))
{
}
BinaryOperation(const Type type, std::optional<Term> &&result, std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
: Operation(type, std::move(result)), _left_child(std::move(left_child)), _right_child(std::move(right_child))
{
}
BinaryOperation(const Type type, std::unique_ptr<Operation> &&left_child, std::unique_ptr<Operation> &&right_child)
: Operation(type), _left_child(std::move(left_child)), _right_child(std::move(right_child))
{
}
~BinaryOperation() override = default;
[[nodiscard]] const std::unique_ptr<Operation> &left_child() const
{
return _left_child;
}
[[nodiscard]] const std::unique_ptr<Operation> &right_child() const
{
return _right_child;
}
[[nodiscard]] std::unique_ptr<Operation> &left_child()
{
return _left_child;
}
[[nodiscard]] std::unique_ptr<Operation> &right_child()
{
return _right_child;
}
[[nodiscard]] std::unique_ptr<Operation> copy() const override
{
return std::make_unique<BinaryOperation>(
_type, _result.has_value() ? std::make_optional(Term{_result.value()}) : std::nullopt, _left_child->copy(),
_right_child->copy());
}
private:
std::unique_ptr<Operation> _left_child;
std::unique_ptr<Operation> _right_child;
[[nodiscard]] static std::unique_ptr<BinaryOperation> make_operation(const Operation::Type type, std::string &&name,
std::unique_ptr<Operation> &&left_child,
std::unique_ptr<Operation> &&right_child)
{
auto attribute =
expression::Attribute{"(" + static_cast<std::string>(left_child->result().value()) + std::move(name) +
static_cast<std::string>(right_child->result().value()) + ")"};
return std::make_unique<BinaryOperation>(type, expression::Term{std::move(attribute), std::nullopt, true},
std::move(left_child), std::move(right_child));
}
};
void visit(std::function<void(const std::unique_ptr<NullaryOperation> &)> &&nullary_callback,
std::function<void(const std::unique_ptr<UnaryOperation> &)> &&unary_callback,
std::function<void(const std::unique_ptr<BinaryOperation> &)> &&binary_callback,
const std::unique_ptr<Operation> &operation);
void for_attribute(const std::unique_ptr<Operation> &operation, std::function<void(Attribute &)> &&callback);
std::vector<Attribute> attributes(const std::unique_ptr<Operation> &operation);
std::vector<Attribute> attributes(std::unique_ptr<Operation> &&operation);
std::vector<NullaryOperation> nullaries(const std::unique_ptr<Operation> &operation,
const bool attribute_required = false);
std::vector<NullaryOperation> nullaries(std::unique_ptr<Operation> &&operation, const bool attribute_required = false);
} // namespace beedb::expression

241
include/expression/term.h Normal file
View File

@ -0,0 +1,241 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "attribute.h"
#include <cstdint>
#include <optional>
#include <string>
#include <table/value.h>
#include <variant>
namespace beedb::expression
{
using NullValue = std::nullptr_t;
class Term
{
public:
Term() = default;
explicit Term(Attribute &&reference) : _attribute_or_value(std::move(reference))
{
}
explicit Term(const Attribute &reference) : _attribute_or_value(reference)
{
}
explicit Term(std::string &&value) : _attribute_or_value(std::move(value))
{
}
explicit Term(std::int64_t value) : _attribute_or_value(value)
{
}
explicit Term(std::int32_t value) : _attribute_or_value(value)
{
}
explicit Term(double value) : _attribute_or_value(value)
{
}
explicit Term(NullValue) : _attribute_or_value(NullValue{})
{
}
explicit Term(table::Value &&value)
{
std::visit([&attr_or_value = _attribute_or_value](auto &v) { attr_or_value = std::move(v); }, value.value());
}
Term(Attribute &&reference, std::optional<std::string> &&alias)
: _attribute_or_value(std::move(reference)), _alias(std::move(alias))
{
}
Term(Attribute &&reference, std::optional<std::string> &&alias, bool is_generated)
: _attribute_or_value(std::move(reference)), _alias(std::move(alias)), _is_generated(is_generated)
{
}
Term(const Attribute &reference, std::optional<std::string> &&alias)
: _attribute_or_value(reference), _alias(std::move(alias))
{
}
Term(std::string &&value, std::optional<std::string> &&alias)
: _attribute_or_value(std::move(value)), _alias(std::move(alias))
{
}
Term(std::int64_t value, std::optional<std::string> &&alias) : _attribute_or_value(value), _alias(std::move(alias))
{
}
Term(std::int32_t value, std::optional<std::string> &&alias) : _attribute_or_value(value), _alias(std::move(alias))
{
}
Term(double value, std::optional<std::string> &&alias) : _attribute_or_value(value), _alias(std::move(alias))
{
}
Term(NullValue, std::optional<std::string> &&alias) : _attribute_or_value(NullValue{}), _alias(std::move(alias))
{
}
Term(Term &&) = default;
Term(const Term &) = default;
~Term() = default;
Term &operator=(const Term &) = default;
Term &operator=(Term &&) = default;
[[nodiscard]] static Term make_attribute(std::string &&table_name, std::string &&column_name,
const bool display_table = false)
{
return Term{Attribute{std::move(table_name), std::move(column_name), display_table}};
}
[[nodiscard]] static Term make_attribute(const std::string &table_name, std::string &&column_name,
const bool display_table = false)
{
return Term{Attribute{table_name, std::move(column_name), display_table}};
}
[[nodiscard]] static Term make_attribute(const std::string &table_name, const std::string &column_name)
{
return Term{Attribute{table_name, column_name}};
}
[[nodiscard]] static Term make_attribute(std::string &&column_name)
{
return Term{Attribute{std::nullopt, std::move(column_name)}};
}
[[nodiscard]] const auto &attribute_or_value() const
{
return _attribute_or_value;
}
[[nodiscard]] const std::optional<std::string> alias() const
{
return _alias;
}
void alias(const std::string &alias)
{
_alias = alias;
}
void alias(std::string &&alias)
{
_alias = std::move(alias);
}
[[nodiscard]] bool is_attribute() const
{
return std::holds_alternative<Attribute>(_attribute_or_value);
}
[[nodiscard]] bool is_null() const
{
return std::holds_alternative<NullValue>(_attribute_or_value);
}
[[nodiscard]] bool is_value() const
{
return std::holds_alternative<std::string>(_attribute_or_value) ||
std::holds_alternative<std::int64_t>(_attribute_or_value) ||
std::holds_alternative<std::int32_t>(_attribute_or_value) ||
std::holds_alternative<double>(_attribute_or_value);
}
template <typename T> [[nodiscard]] const T &get() const
{
return std::get<T>(_attribute_or_value);
}
template <typename T> [[nodiscard]] T &get()
{
return std::get<T>(_attribute_or_value);
}
[[nodiscard]] bool is_generated() const
{
return _is_generated;
}
bool operator==(const Term &other) const
{
return _attribute_or_value == other._attribute_or_value && _alias == other._alias;
}
explicit operator std::string() const
{
if (_alias.has_value())
{
return _alias.value();
}
if (std::holds_alternative<Attribute>(_attribute_or_value))
{
return static_cast<std::string>(std::get<Attribute>(_attribute_or_value));
}
else if (std::holds_alternative<std::string>(_attribute_or_value))
{
return std::get<std::string>(_attribute_or_value);
}
else if (std::holds_alternative<std::int64_t>(_attribute_or_value))
{
return std::to_string(std::get<std::int64_t>(_attribute_or_value));
}
else if (std::holds_alternative<std::int32_t>(_attribute_or_value))
{
return std::to_string(std::get<std::int32_t>(_attribute_or_value));
}
else if (std::holds_alternative<double>(_attribute_or_value))
{
return std::to_string(std::get<double>(_attribute_or_value));
}
else if (std::holds_alternative<NullValue>(_attribute_or_value))
{
return std::string{"NULL"};
}
return "";
}
private:
std::variant<Attribute, std::string, std::string_view, std::int64_t, std::int32_t, double, table::Date, NullValue>
_attribute_or_value{NullValue{}};
std::optional<std::string> _alias{std::nullopt};
bool _is_generated{false};
};
} // namespace beedb::expression
namespace std
{
template <> struct hash<beedb::expression::Term>
{
public:
std::size_t operator()(const beedb::expression::Term &term) const
{
std::size_t h = std::hash<std::string>()(term.alias().value_or(""));
std::visit(
[&h](const auto &v) {
using T = std::decay_t<decltype(v)>;
h ^= std::hash<T>()(v);
},
term.attribute_or_value());
return h;
}
};
} // namespace std

View File

@ -0,0 +1,287 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "b_plus_tree_node.h"
#include <cstdint>
#include <index/non_unique_index_interface.h>
#include <index/return_value.h>
#include <optional>
#include <ostream>
#include <set>
#include <utility>
#include <vector>
namespace beedb::index::bplustree
{
template <typename K, typename V, bool U> class BPlusTree
{
public:
using Node = BPlusTreeNode<K, V, U>;
BPlusTree() : _root(new Node(true))
{
}
~BPlusTree()
{
delete _root;
}
/**
* Inserts the given key-value-pair into the tree.
*
* @param key
* @param value
*/
void put(const K key, V value);
/**
* Finds the value by the given key.
*
* @param key
* @return The found value.
*/
[[nodiscard]] std::optional<typename ReturnValue<V, U>::type> get(const K key) const;
[[nodiscard]] std::optional<std::set<V>> get(const K key_from, const K key_to) const;
[[nodiscard]] Node *root() const
{
return _root;
}
[[nodiscard]] size_type height() const
{
return _height;
}
private:
Node *_root;
size_type _height = 1;
/**
* Locates a leaf node for a given key.
*
* @param key
* @param node_path
* @return
*/
Node *locate_leaf(const K key, std::vector<Node *> *node_path = nullptr) const;
/**
* Inserts the given key-value-tuple into the give leaf node.
*
* @param leaf_node
* @param key
* @param value
* @return
*/
Node *insert_into_leaf(Node *leaf_node, const K key, const V value);
/**
* Inserts the given key and separator into the given inner node.
*
* @param inner_node
* @param key
* @param separator
* @return
*/
std::pair<Node *, K> insert_into_inner(Node *inner_node, const K key, Node *separator);
/**
* Creates a new root with pointer to the two given new child nodes.
*
* @param left
* @param right
* @param key
*/
void install_new_root_node(Node *left, Node *right, const K key);
/**
* Splits the given inner node and returns the new node and a key,
* that has to be inserted into the parent node.
*
* @param inner_node
* @param key
* @param separator
* @return
*/
std::pair<Node *, K> split_inner_node(Node *inner_node, const K key, Node *separator);
/**
* Splits the given leaf node and returns the new node.
*
* @param leaf_node
* @return
*/
Node *split_leaf_node(Node *leaf_node);
friend std::ostream &operator<<(std::ostream &stream, const BPlusTree<K, V, U> &tree)
{
Node *root = tree.root();
if (root == nullptr)
{
return stream;
}
const auto items = tree.root()->size_include_children();
const auto nodes = tree.root()->count_children();
return stream << "Height = " << tree.height() << "\n"
<< "Key-Value-Pairs = " << items.second << "\n"
<< "Inner-Nodes = " << nodes.first << "\n"
<< "Leaf-Nodes = " << nodes.second << "\n"
<< "Memory = "
<< ((nodes.first + nodes.second) * Config::b_plus_tree_page_size) / 1024 / 1024 << " MB\n";
}
};
template <typename K, typename V, bool U> void BPlusTree<K, V, U>::put(const K key, V value)
{
// Path for traversal. All nodes from root excluding the leaf node will be stored.
std::vector<Node *> path;
path.reserve(6);
// Locate the possible leaf.
Node *leaf = this->locate_leaf(key, &path);
// Insert into leaf
K up_key;
Node *new_node = this->insert_into_leaf(leaf, key, value);
if (new_node != nullptr)
{
up_key = new_node->leaf_key(0u);
}
// Propagate up.
while (new_node != nullptr && path.empty() == false)
{
Node *parent = path.back();
path.pop_back();
auto [n, u] = this->insert_into_inner(parent, up_key, new_node);
new_node = n;
up_key = u;
}
// Create new root
if (new_node != nullptr)
{
this->install_new_root_node(_root, new_node, up_key);
}
}
template <typename K, typename V, bool U>
std::pair<BPlusTreeNode<K, V, U> *, K> BPlusTree<K, V, U>::insert_into_inner(BPlusTree<K, V, U>::Node *inner_node,
const K key,
BPlusTree<K, V, U>::Node *separator)
{
if (inner_node->is_full() == false)
{
const size_type index = inner_node->index(key);
inner_node->insert_separator(index, separator, key);
return {static_cast<Node *>(nullptr), 0};
}
else
{
return this->split_inner_node(inner_node, key, separator);
}
}
template <typename K, typename V, bool U>
void BPlusTree<K, V, U>::install_new_root_node(BPlusTree<K, V, U>::Node *left, BPlusTree<K, V, U>::Node *right,
const K key)
{
Node *new_root = new Node(false);
new_root->separator(0, left);
new_root->insert_separator(0, right, key);
_height++;
_root = new_root;
}
template <typename K, typename V, bool U>
std::pair<BPlusTreeNode<K, V, U> *, K> BPlusTree<K, V, U>::split_inner_node(BPlusTree<K, V, U>::Node *inner_node,
const K key,
BPlusTree<K, V, U>::Node *separator)
{
constexpr size_type left_size = BPlusTreeInnerNode<K, V, U>::max_keys / 2;
constexpr size_type right_size = BPlusTreeInnerNode<K, V, U>::max_keys - left_size;
K key_up;
Node *new_inner_node = new Node(false);
new_inner_node->right(inner_node->right());
inner_node->right(new_inner_node);
if (key < inner_node->inner_key(left_size - 1))
{
inner_node->copy(new_inner_node, left_size, right_size);
new_inner_node->separator(0, inner_node->separator(left_size));
new_inner_node->size(right_size);
key_up = inner_node->inner_key(left_size - 1);
inner_node->size(left_size - 1);
const size_type index = inner_node->index(key);
inner_node->insert_separator(index, separator, key);
}
else if (key < inner_node->inner_key(left_size))
{
inner_node->copy(new_inner_node, left_size, right_size);
new_inner_node->separator(0, separator);
key_up = key;
inner_node->size(left_size);
new_inner_node->size(right_size);
}
else
{
inner_node->copy(new_inner_node, left_size + 1, right_size - 1);
new_inner_node->separator(0, inner_node->separator(left_size + 1));
inner_node->size(left_size);
new_inner_node->size(right_size - 1);
key_up = inner_node->inner_key(left_size);
const size_type index = new_inner_node->index(key);
new_inner_node->insert_separator(index, separator, key);
}
return {new_inner_node, key_up};
}
template <typename K, typename V, bool U>
BPlusTreeNode<K, V, U> *BPlusTree<K, V, U>::split_leaf_node(BPlusTree<K, V, U>::Node *leaf_node)
{
constexpr size_type left_size = BPlusTreeLeafNode<K, V, U>::max_items / 2;
constexpr size_type right_size = BPlusTreeLeafNode<K, V, U>::max_items - left_size;
Node *new_leaf_node = new Node(true);
new_leaf_node->right(leaf_node->right());
leaf_node->right(new_leaf_node);
leaf_node->copy(new_leaf_node, left_size, right_size);
new_leaf_node->size(right_size);
leaf_node->size(left_size);
return new_leaf_node;
}
} // namespace beedb::index::bplustree
#include "b_plus_tree.hpp"

View File

@ -0,0 +1,206 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#include <index/b_plus_tree/b_plus_tree_node.h>
#include <index/return_value.h>
#include <iostream>
#include <optional>
#include <utility>
#include <vector>
namespace beedb::index::bplustree
{
template <typename K, typename V, bool U>
BPlusTreeNode<K, V, U> *BPlusTree<K, V, U>::locate_leaf(
[[maybe_unused]] const K key, [[maybe_unused]] std::vector<BPlusTreeNode<K, V, U> *> *node_path) const
{
/**
* Assignment (2): Implement a B+-Tree
*
* The B+-Tree is used for indexing files. Using the index
* for bigger data sets will reduce the amount of scanned disk pages
* in case the query wants to filter the data.
*
* This method is used to traverse the tree and locate a leaf that may
* contain the wanted key. During the traversal for inserts, all visited nodes
* are stored in the node_path container. For lookups, the container is null.
*
* Hints for implementation:
* - "this->_root" stores the root node of the tree, where every
* lookup for a leaf is started.
* - Every inner node (also the root) has a "child(k)" method, which returns
* the next node on the way for the leaf, that may contain the key "k".
* - To check a node whether it is a leaf or inner node, use the "is_leaf()"
* method on a node, which returns true if the node is a leaf.
* - If "node_path" is not a "nullptr", push all nodes during traversal
* to that vector (also the root).
*
*
* Procedure:
* - Start the traversal at the root node.
* - Get the next node using "current_node->child(key)" while "current_node"
* is not a leaf.
* - Push every node to the "node_path", if "node_path != nullptr".
* - Return the leaf you found during traversal.
*/
Node *current_node = this->_root;
// TODO: Insert your code here.
return current_node;
}
template <typename K, typename V, bool U>
std::optional<typename ReturnValue<V, U>::type> BPlusTree<K, V, U>::get([[maybe_unused]] const K key) const
{
/**
* Assignment (2): Implement a B+-Tree
*
* This method tries to find the value for a given key.
* The tree is a very generic data structure which can hold
* one value per key or multiple values per key. The specific
* variant is given by the template parameter U which is a bool
* and stands for Unique. True means: Return one value of type V;
* false means: Return a set of values of type V.
*
* Hints for implementation:
* - You have already implemented "locate_leaf(k)" which returns the
* leaf that may contain the searched key-value pair.
* - Every leaf node provides a method "index(k)" which returns the index
* of the key "k".
* - Every leaf node provides a method "leaf_key(i)" which returns the
* key at index "i".
* - Every leaf node provides a method "value(i)" which returns the value
* at index "i". The "value(i)" method will automatically pick the correct
* return type, depending on the U-template-parameter.
*
* Procedure:
* - Locate the leaf node that may contain the wanted key.
* - Check the leaf node: Is the wanted key available?
* - If yes: return the value of the key.
* - Otherwise return an empty result, using "return std::nullopt;".
*/
// TODO: Insert your code here.
return std::nullopt;
}
template <typename K, typename V, bool U>
std::optional<std::set<V>> BPlusTree<K, V, U>::get([[maybe_unused]] const K key_from,
[[maybe_unused]] const K key_to) const
{
/**
* Assignment (2): Implement a B+-Tree
*
* This method tries to find one or multiple values for a given
* range of keys.
* The tree is a very generic data structure which can hold
* one value per key or multiple values per key. The specific
* variant is given by the template parameter U which is a bool
* and stands for Unique. True means: Return one value of type V;
* false means: Return a set of values of type V.
*
* Hints for implementation:
* - You have already implemented "locate_leaf(k)" which returns the
* leaf that may contain the searched key-value pair.
* - Every node provides a method "right()" which returns a pointer
* to the right neighbour node.
* - Every node provides a method "size()" which returns the number of
* items that are stored in the node.
* - Every leaf node provides a method "index(k)" which returns the index
* of the key "k".
* - Every leaf node provides a method "leaf_key(i)" which returns the
* key at index "i".
* - Every leaf node provides a method "value(i)" which returns the value
* at index "i". The "value(i)" method will automatically pick the correct
* return type, depending on the U-template-parameter.
* - You can test whether it is a unique or non-unique tree, using
* "if constexpr(U) { code for unique... } else { boot for non-unique... }.
* - Both containers std::set (https://en.cppreference.com/w/cpp/container/set)
* and std::optional (https://en.cppreference.com/w/cpp/utility/optional) may
* be helpful on compiler errors.
*
* Procedure:
* - Locate the leaf node that may contain the wanted key.
* - Add all keys that are equal or greater than the key "key_from"
* and equal or lesser than the key "key_to" to a set of values.
* - When the last key of the node matches that predicate, also
* take a look to the right neighbour using the "right()" method
* (and also the rights right,...).
*/
std::set<V> values;
// TODO: Insert your code here.
return values;
}
template <typename K, typename V, bool U>
BPlusTreeNode<K, V, U> *BPlusTree<K, V, U>::insert_into_leaf([[maybe_unused]] BPlusTreeNode<K, V, U> *leaf_node,
[[maybe_unused]] const K key,
[[maybe_unused]] const V value)
{
/**
* Assignment (2): Implement a B+-Tree
*
* This method adds a value to a leaf node. The correct leaf node, key and
* value are all given. When inserting results in splitting the leaf,
* the pointer to the new created node is returned.
*
* Hints for implementation:
* - Every node provides a method "full()" which returns true, if there
* is no more place for a new item.
* - Every leaf node provides a method "index(k)" which returns the index
* of the key "k".
* - Every leaf node provides a method "leaf_key(i)" which returns the
* key at index "i".
* - Every leaf node provides a method "insert_value(i, v, k)" which adds
* a key-value pair (k,v) to the leaf at index i.
* - The tree has a method "this->split_leaf_node(l)" which splits the leaf
* node l and returns a pointer to the new node.
* - You can test whether it is a unique or non-unique tree, using
* "if constexpr(U) { code for unique... } else { boot for non-unique... }.
*
* Procedure:
* - Check if the leaf node already contains the key
* - If yes and the tree is non-unique: add the value to the list of values
* in the node and return a "nullptr".
* - If yey and the tree is unique: Just return a "nullptr".
* - If the key is not in the node, check for space for a new (key,value) pair.
* - If the node is not full, insert the new pair and return a "nullptr"
* - Otherwise, we have to split the node. Splitting will create a new leaf node,
* the new right neighbour of the given leaf node.
* - After splitting, we have enough space to insert the pair. Check whether the key
* should take place in the given leaf or the new leaf, created on splitting:
* When the key is lower than the first key of the new leaf, the key should be insert
* into the given leaf, otherwise in the new leaf.
* - After splitting, return the pointer to the new leaf.
*/
// TODO: Insert your code here.
return nullptr;
}
} // namespace beedb::index::bplustree

View File

@ -0,0 +1,294 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <array>
#include <config.h>
#include <cstdint>
#include <cstring>
#include <index/return_value.h>
#include <utility>
namespace beedb::index::bplustree
{
using size_type = std::size_t;
template <typename K, typename V, bool U> class BPlusTreeNode;
template <typename K, typename V, bool U> struct BPlusTreeNodeHeader
{
size_type size = 0;
bool is_leaf;
BPlusTreeNode<K, V, U> *right = nullptr;
explicit BPlusTreeNodeHeader(const bool is_leaf_) : is_leaf(is_leaf_)
{
}
};
template <typename K, typename V, bool U> struct BPlusTreeLeafNode
{
static constexpr size_type max_items = (Config::b_plus_tree_page_size - sizeof(BPlusTreeNodeHeader<K, V, U>)) /
(sizeof(K) + sizeof(typename ReturnValue<V, U>::type));
std::array<K, BPlusTreeLeafNode::max_items> keys;
std::array<typename ReturnValue<V, U>::type, BPlusTreeLeafNode::max_items> values;
};
template <typename K, typename V, bool U> struct BPlusTreeInnerNode
{
static constexpr size_type max_keys =
(Config::b_plus_tree_page_size - sizeof(BPlusTreeNodeHeader<K, V, U>) - sizeof(BPlusTreeNode<K, V, U> *)) /
(sizeof(K) + sizeof(BPlusTreeInnerNode<K, V, U> *));
static constexpr size_type max_separators = max_keys + 1;
std::array<K, BPlusTreeInnerNode::max_keys> keys;
std::array<BPlusTreeNode<K, V, U> *, BPlusTreeInnerNode::max_separators> separators;
};
template <typename K, typename V, bool U> class BPlusTreeNode
{
public:
explicit BPlusTreeNode(const bool is_leaf) : _header(is_leaf)
{
}
~BPlusTreeNode();
[[nodiscard]] bool is_leaf() const
{
return _header.is_leaf;
}
[[nodiscard]] bool is_inner() const
{
return is_leaf() == false;
}
[[nodiscard]] size_type size() const
{
return _header.size;
}
void size(const size_type size)
{
_header.size = size;
}
[[nodiscard]] BPlusTreeNode<K, V, U> *right()
{
return _header.right;
}
[[nodiscard]] bool has_right() const
{
return _header.right != nullptr;
}
void right(BPlusTreeNode<K, V, U> *right)
{
_header.right = right;
}
[[nodiscard]] typename ReturnValue<V, U>::type &value(const size_type index)
{
return _leaf_node.values[index];
}
[[nodiscard]] BPlusTreeNode<K, V, U> *separator(const size_type index)
{
return _inner_node.separators[index];
}
void separator(const size_type index, BPlusTreeNode<K, V, U> *separator)
{
_inner_node.separators[index] = separator;
}
[[nodiscard]] K leaf_key(const size_type index)
{
return _leaf_node.keys[index];
}
[[nodiscard]] K inner_key(const size_type index)
{
return _inner_node.keys[index];
}
[[nodiscard]] bool is_full() const
{
const size_type max_size =
is_leaf() ? BPlusTreeLeafNode<K, V, U>::max_items : BPlusTreeInnerNode<K, V, U>::max_keys;
return size() >= max_size;
}
size_type index(const K key);
BPlusTreeNode<K, V, U> *child(const K key);
void insert_separator(const size_type index, BPlusTreeNode<K, V, U> *separator, const K key);
void insert_value(const size_type index, const V value, const K key);
void copy(BPlusTreeNode *other, const size_type from_index, const size_type count);
std::pair<std::size_t, std::size_t> size_include_children();
std::pair<std::size_t, std::size_t> count_children();
private:
BPlusTreeNodeHeader<K, V, U> _header;
union {
BPlusTreeInnerNode<K, V, U> _inner_node;
BPlusTreeLeafNode<K, V, U> _leaf_node;
};
};
template <typename K, typename V, bool U> BPlusTreeNode<K, V, U>::~BPlusTreeNode()
{
if (is_leaf() == false)
{
for (size_type i = 0; i < size(); i++)
{
delete _inner_node.separators[i];
}
}
}
template <typename K, typename V, bool U> size_type BPlusTreeNode<K, V, U>::index(const K key)
{
auto keys = is_leaf() ? _leaf_node.keys.begin() : _inner_node.keys.begin();
auto iterator = std::lower_bound(keys, keys + size(), key);
return std::distance(keys, iterator);
}
template <typename K, typename V, bool U> BPlusTreeNode<K, V, U> *BPlusTreeNode<K, V, U>::child(const K key)
{
std::int32_t low = 0, high = size() - 1;
while (low <= high)
{
const std::int32_t mid = (low + high) / 2;
if (_inner_node.keys[mid] <= key)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
return _inner_node.separators[high + 1];
}
template <typename K, typename V, bool U>
void BPlusTreeNode<K, V, U>::insert_separator(const size_type index, BPlusTreeNode<K, V, U> *separator, const K key)
{
if (index < size())
{
const size_type offset = size() - index;
std::memmove(&_inner_node.keys[index + 1], &_inner_node.keys[index], offset * sizeof(K));
std::memmove(&_inner_node.separators[index + 2], &_inner_node.separators[index + 1],
offset * sizeof(BPlusTreeNode<K, V, U> *));
}
_inner_node.keys[index] = key;
_inner_node.separators[index + 1] = separator;
_header.size++;
}
template <typename K, typename V, bool U>
void BPlusTreeNode<K, V, U>::insert_value(const size_type index, const V value, const K key)
{
if (index < size())
{
const size_type offset = size() - index;
std::memmove(&_leaf_node.keys[index + 1], &_leaf_node.keys[index], offset * sizeof(K));
std::memmove(static_cast<void *>(&_leaf_node.values[index + 1]), &_leaf_node.values[index],
offset * sizeof(typename ReturnValue<V, U>::type));
}
_leaf_node.keys[index] = key;
if constexpr (U)
{
_leaf_node.values[index] = value;
}
else
{
new (&_leaf_node.values[index]) typename ReturnValue<V, U>::type();
_leaf_node.values[index].insert(value);
}
_header.size++;
}
template <typename K, typename V, bool U>
void BPlusTreeNode<K, V, U>::copy(BPlusTreeNode<K, V, U> *other, const size_type from_index, const size_type count)
{
if (is_leaf())
{
std::memcpy(&other->_leaf_node.keys[0], &_leaf_node.keys[from_index], count * sizeof(K));
std::memcpy(static_cast<void *>(&other->_leaf_node.values[0]), &_leaf_node.values[from_index],
count * sizeof(typename ReturnValue<V, U>::type));
}
else
{
std::memcpy(&other->_inner_node.keys[0], &_inner_node.keys[from_index], count * sizeof(K));
std::memcpy(&other->_inner_node.separators[1], &_inner_node.separators[from_index + 1],
count * sizeof(BPlusTreeNode<K, V, U> *));
}
}
template <typename K, typename V, bool U>
std::pair<std::size_t, std::size_t> BPlusTreeNode<K, V, U>::size_include_children()
{
if (is_leaf())
{
return {0u, size()};
}
std::size_t leaf_sizes = 0, inner_sizes = 0;
for (auto i = 0u; i <= size(); i++)
{
BPlusTreeNode<K, V, U> *child = _inner_node.separators[i];
const auto child_size = child->size_include_children();
inner_sizes += child_size.first;
leaf_sizes += child_size.second;
}
return {inner_sizes, leaf_sizes};
}
template <typename K, typename V, bool U> std::pair<std::size_t, std::size_t> BPlusTreeNode<K, V, U>::count_children()
{
if (is_leaf())
{
return {0u, 0u};
}
if (_inner_node.separators[0]->is_leaf())
{
return {0u, size() + 1u};
}
std::size_t leaf_children = 0, inner_children = 0;
for (auto i = 0u; i <= size(); i++)
{
BPlusTreeNode<K, V, U> *child = _inner_node.separators[i];
const auto child_size = child->count_children();
inner_children += child_size.first;
leaf_children += child_size.second;
}
return {inner_children + size(), leaf_children};
}
} // namespace beedb::index::bplustree

View File

@ -0,0 +1,74 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "b_plus_tree.h"
#include <index/index_interface.h>
#include <index/non_unique_index_interface.h>
#include <index/range_index_interface.h>
#include <storage/page.h>
namespace beedb::index::bplustree
{
/**
* B+-Tree implementation for non-unique (key,value) pairs.
* Can store multiple values for each key.
* Supports range queries.
*/
class NonUniqueBPlusTreeIndex : public IndexInterface, public NonUniqueIndexInterface, public RangeIndexInterface
{
public:
explicit NonUniqueBPlusTreeIndex(const std::string &name) : IndexInterface(name)
{
}
~NonUniqueBPlusTreeIndex() override = default;
[[nodiscard]] bool supports_range() const override
{
return true;
}
[[nodiscard]] bool is_unique() const override
{
return false;
}
void put(const std::int64_t key, storage::Page::id_t page_pointer) override
{
_tree.put(key, page_pointer);
}
[[nodiscard]] std::optional<std::set<storage::Page::id_t>> get(const std::int64_t key) const override
{
return _tree.get(key);
}
[[nodiscard]] std::optional<std::set<storage::Page::id_t>> get(const std::int64_t key_from,
const std::int64_t key_to) override
{
return _tree.get(key_from, key_to);
}
private:
BPlusTree<std::int64_t, storage::Page::id_t, false> _tree;
};
} // namespace beedb::index::bplustree

View File

@ -0,0 +1,73 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "b_plus_tree.h"
#include <index/index_interface.h>
#include <index/range_index_interface.h>
#include <index/unique_index_interface.h>
#include <storage/page.h>
namespace beedb::index::bplustree
{
/**
* B+-Tree implementation for unique (key,value) pairs.
* Supports range queries.
*/
class UniqueBPlusTreeIndex : public IndexInterface, public UniqueIndexInterface, public RangeIndexInterface
{
public:
explicit UniqueBPlusTreeIndex(const std::string &name) : IndexInterface(name)
{
}
~UniqueBPlusTreeIndex() override = default;
[[nodiscard]] bool supports_range() const override
{
return true;
}
[[nodiscard]] bool is_unique() const override
{
return true;
}
void put(const std::int64_t key, storage::Page::id_t page_pointer) override
{
_tree.put(key, page_pointer);
}
[[nodiscard]] std::optional<storage::Page::id_t> get(const std::int64_t key) const override
{
return _tree.get(key);
}
[[nodiscard]] std::optional<std::set<storage::Page::id_t>> get(const std::int64_t key_from,
const std::int64_t key_to) override
{
return _tree.get(key_from, key_to);
}
private:
BPlusTree<std::int64_t, storage::Page::id_t, true> _tree;
};
} // namespace beedb::index::bplustree

View File

@ -0,0 +1,60 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "b_plus_tree/non_unique_b_plus_tree_index.h"
#include "b_plus_tree/unique_b_plus_tree_index.h"
#include "index_interface.h"
#include "type.h"
#include <memory>
namespace beedb::index
{
class IndexFactory
{
public:
/**
* Builds an empty index.
*
* @param name Name for the index.
* @param type The index type identifies the underlying data structure like BTree, Hashtable, ...
* @param is_unique Identifies whether the index can hold multiple values for one key.
* @return Pointer to the in-memory index structure.
*/
static std::shared_ptr<IndexInterface> new_index(const std::string &name, const Type type, const bool is_unique)
{
if (type == Type::BTree)
{
if (is_unique)
{
return std::make_shared<bplustree::UniqueBPlusTreeIndex>(name);
}
else
{
return std::make_shared<bplustree::NonUniqueBPlusTreeIndex>(name);
}
}
return {};
}
};
} // namespace beedb::index

View File

@ -0,0 +1,70 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <storage/page.h>
namespace beedb::index
{
/**
* The index interface offers an API for multiple indices, whether
* they are range-indices, support multiple values for one key.
*/
class IndexInterface
{
public:
explicit IndexInterface(const std::string &name) : _name(name)
{
}
virtual ~IndexInterface() = default;
/**
* @return True, if the index supports just one value per key.
*/
[[nodiscard]] virtual bool is_unique() const = 0;
/**
* @return True, if the index supports range queries (like B+Trees).
*/
[[nodiscard]] virtual bool supports_range() const = 0;
/**
* Stores a (Key,Page) pair in the index.
*
* @param key Key for lookups.
* @param page_id Value.
*/
virtual void put(const std::int64_t key, storage::Page::id_t page_id) = 0;
/**
* @return Name of the index.
*/
[[nodiscard]] const std::string &name() const
{
return _name;
}
private:
const std::string _name;
};
} // namespace beedb::index

View File

@ -0,0 +1,49 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <optional>
#include <set>
#include <storage/page.h>
namespace beedb::index
{
/**
* Interface for non-unique indices.
* The index can store multiple values per key.
*/
class NonUniqueIndexInterface
{
public:
NonUniqueIndexInterface() = default;
virtual ~NonUniqueIndexInterface() = default;
/**
* Lookup for all values of a key.
*
* @param key Key to lookup.
* @return All stored values for the key.
*/
[[nodiscard]] virtual std::optional<std::set<storage::Page::id_t>> get(const std::int64_t key) const = 0;
};
} // namespace beedb::index

View File

@ -0,0 +1,52 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <optional>
#include <set>
#include <storage/page.h>
namespace beedb::index
{
/**
* Interface for range indices.
* The index can lookup a range of keys for range-queries.
*/
class RangeIndexInterface
{
public:
RangeIndexInterface() = default;
~RangeIndexInterface() = default;
/**
* Lookup of a key-range.
*
* @param key_from From key.
* @param key_to To key.
* @return All values for the given key-range.
*/
[[nodiscard]] virtual std::optional<std::set<storage::Page::id_t>> get(const std::int64_t key_from,
const std::int64_t key_to) = 0;
};
} // namespace beedb::index

View File

@ -0,0 +1,38 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <optional>
#include <set>
namespace beedb::index
{
template <typename Value, bool Unique> struct ReturnValue
{
using type = Value;
};
template <typename Value> struct ReturnValue<Value, false>
{
using type = std::set<Value>;
};
} // namespace beedb::index

39
include/index/type.h Normal file
View File

@ -0,0 +1,39 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <regex>
namespace beedb::index
{
/**
* Possible index types.
*/
enum Type
{
None,
BTree,
Hashtable,
Skiplist,
Bitmap /*, some more like: SkipList,... */
};
} // namespace beedb::index

View File

@ -0,0 +1,48 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <optional>
#include <storage/page.h>
namespace beedb::index
{
/**
* Interface for unique indices.
* The index can store only one value per key.
*/
class UniqueIndexInterface
{
public:
UniqueIndexInterface() = default;
virtual ~UniqueIndexInterface() = default;
/**
* Lookup for a value for a given key.
*
* @param key Key to lookup.
* @return The stored value or an empty optional.
*/
[[nodiscard]] virtual std::optional<storage::Page::id_t> get(const std::int64_t key) const = 0;
};
} // namespace beedb::index

View File

@ -0,0 +1,48 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <network/client.h>
#include <nlohmann/json.hpp>
#include <ostream>
#include <string>
#include <util/text_table.h>
namespace beedb::io
{
class ClientConsole
{
public:
ClientConsole(std::string &&server, const std::uint16_t port);
~ClientConsole() = default;
void run();
private:
network::Client _client;
static bool handle_response(const std::string &response);
static void plan_to_table(util::TextTable &table, nlohmann::json &layer, std::uint16_t depth = 0u);
};
} // namespace beedb::io

View File

@ -0,0 +1,77 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <array>
#include <concurrency/transaction.h>
#include <concurrency/transaction_callback.h>
#include <config.h>
#include <database.h>
#include <io/command/commander.h>
#include <io/command/custom_commands.h>
#include <network/server.h>
namespace beedb::io
{
class ClientHandler : public network::ClientHandler
{
public:
ClientHandler(Database &database) noexcept;
~ClientHandler() noexcept override = default;
std::optional<std::string> handle_message(const std::uint32_t client_id, const std::string &message) override;
void on_client_connected(const std::uint32_t id) override;
void on_client_disconnected(const std::uint32_t id) override;
void server(network::Server *server) override
{
network::ClientHandler::server(server);
_commander.register_command("stop", std::make_unique<command::StopServerCommand>(server));
}
private:
Database &_database;
command::Commander _commander;
std::array<concurrency::Transaction *, Config::max_clients> _client_transactions;
};
class TransactionCallback : public concurrency::TransactionCallback
{
public:
TransactionCallback(concurrency::Transaction *&transaction) : _transaction(transaction)
{
}
~TransactionCallback() override = default;
void on_begin(concurrency::Transaction *transaction) override
{
_transaction = transaction;
}
void on_end(concurrency::Transaction *, const bool) override
{
_transaction = nullptr;
}
private:
concurrency::Transaction *&_transaction;
};
} // namespace beedb::io

View File

@ -0,0 +1,72 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "execution_callback.h"
#include "query_result_serializer.h"
#include <nlohmann/json.hpp>
#include <plan/logical/node/node_interface.h>
#include <string>
namespace beedb::io
{
class ClientMessageSerializer final : public ExecutionCallback
{
public:
ClientMessageSerializer() = default;
~ClientMessageSerializer() override = default;
void on_schema(const table::Schema &schema) override
{
_query_result_serializer.serialize(schema);
}
void on_tuple(const table::Tuple &tuple) override
{
_query_result_serializer.serialize(tuple);
}
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &plan) override
{
_query_plan = plan->to_json();
}
[[nodiscard]] const QueryResultSerializer &query_result() const
{
return _query_result_serializer;
}
[[nodiscard]] QueryResultSerializer &query_result()
{
return _query_result_serializer;
}
[[nodiscard]] const nlohmann::json &query_plan() const
{
return _query_plan;
}
private:
QueryResultSerializer _query_result_serializer;
nlohmann::json _query_plan;
};
} // namespace beedb::io

View File

@ -0,0 +1,56 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "custom_command_interface.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
namespace beedb::io::command
{
class Commander
{
public:
explicit Commander(Database &database);
~Commander() = default;
[[nodiscard]] static bool is_command(const std::string &input)
{
return input.at(0u) == ':';
}
void register_command(std::string &&name, std::unique_ptr<CustomCommandInterface> &&command)
{
_registered_commands.insert(std::make_pair(std::move(name), std::move(command)));
}
std::optional<beedb::io::ExecutionResult> execute(const std::string &user_input, Executor &executor,
ExecutionCallback &execution_callback);
private:
std::unordered_map<std::string, std::unique_ptr<CustomCommandInterface>> _registered_commands;
Database &_database;
};
} // namespace beedb::io::command

View File

@ -0,0 +1,40 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <io/executor.h>
#include <string>
#include <vector>
namespace beedb::io::command
{
class CustomCommandInterface
{
public:
CustomCommandInterface() = default;
virtual ~CustomCommandInterface() = default;
[[nodiscard]] virtual std::optional<ExecutionResult> execute(const std::string &input, Executor &executor,
ExecutionCallback &execution_callback) = 0;
[[nodiscard]] virtual std::string help() = 0;
};
} // namespace beedb::io::command

View File

@ -0,0 +1,142 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "custom_command_interface.h"
#include <network/server.h>
namespace beedb::io::command
{
class ShowCommand final : public CustomCommandInterface
{
public:
ShowCommand() = default;
~ShowCommand() override = default;
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &parameters, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :show [tables,indices,columns]{1}");
};
};
class ExplainCommand final : public CustomCommandInterface
{
public:
ExplainCommand() = default;
~ExplainCommand() override = default;
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &input, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :explain <SQL-Statement>");
};
};
class SetCommand final : public CustomCommandInterface
{
public:
explicit SetCommand(Config &config) : _config(config)
{
}
~SetCommand() override = default;
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &input, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :set <Argument Name> <Numerical Value>");
};
private:
Config &_config;
};
class GetCommand final : public CustomCommandInterface
{
public:
explicit GetCommand(Config &config) : _config(config)
{
}
~GetCommand() override = default;
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &input, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :get [<Argument Name>]?");
};
private:
Config &_config;
};
class StatsCommand final : public CustomCommandInterface
{
public:
explicit StatsCommand(Database &db) : _stats(db.system_statistics()), _db(db)
{
}
~StatsCommand() override = default;
/**
* @brief execute This triggers computation of statistics for a specified,
* existing table. After confirming that the table exists,
* computations are triggered.
* @param input the table name
* @return the plan that computes the statistics
*/
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &input, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :stats <Table Name>");
};
private:
statistic::SystemStatistics &_stats;
Database &_db;
};
class StopServerCommand final : public CustomCommandInterface
{
public:
explicit StopServerCommand(network::Server *server) : _server(server)
{
}
~StopServerCommand() override = default;
[[nodiscard]] std::optional<ExecutionResult> execute(const std::string &parameters, Executor &executor,
ExecutionCallback &execution_callback) override;
[[nodiscard]] std::string help() override
{
return std::string("Syntax> :stop");
}
private:
network::Server *_server;
};
} // namespace beedb::io::command

View File

@ -0,0 +1,104 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <memory>
#include <table/schema.h>
#include <table/tuple.h>
namespace beedb::plan::logical
{
class NodeInterface;
}
namespace beedb::io
{
class ExecutionCallback
{
public:
ExecutionCallback() = default;
virtual ~ExecutionCallback() = default;
virtual void on_schema(const table::Schema &schema) = 0;
virtual void on_tuple(const table::Tuple &tuple) = 0;
virtual void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &plan) = 0;
};
class SilentExecutionCallback final : public ExecutionCallback
{
public:
SilentExecutionCallback() = default;
~SilentExecutionCallback() override = default;
void on_schema(const table::Schema &) override
{
}
void on_tuple(const table::Tuple &) override
{
}
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
};
class FunctionalExecutionCallback final : public ExecutionCallback
{
public:
FunctionalExecutionCallback(
std::function<void(const table::Schema &)> &&schema_callback,
std::function<void(const table::Tuple &)> &&tuple_callback,
std::function<void(const std::unique_ptr<plan::logical::NodeInterface> &)> &&plan_callback)
: _schema_callback(std::move(schema_callback)), _tuple_callback(std::move(tuple_callback)),
_plan_callback(std::move(plan_callback))
{
}
FunctionalExecutionCallback(std::function<void(const table::Schema &)> &&schema_callback,
std::function<void(const table::Tuple &)> &&tuple_callback)
: FunctionalExecutionCallback(std::move(schema_callback), std::move(tuple_callback),
[](const std::unique_ptr<plan::logical::NodeInterface> &) {})
{
}
~FunctionalExecutionCallback() override = default;
void on_schema(const table::Schema &schema) override
{
_schema_callback(schema);
}
void on_tuple(const table::Tuple &tuple) override
{
_tuple_callback(tuple);
}
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &plan) override
{
_plan_callback(plan);
}
private:
std::function<void(const table::Schema &)> _schema_callback;
std::function<void(const table::Tuple &)> _tuple_callback;
std::function<void(const std::unique_ptr<plan::logical::NodeInterface> &)> _plan_callback;
};
} // namespace beedb::io

157
include/io/executor.h Normal file
View File

@ -0,0 +1,157 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "execution_callback.h"
#include <chrono>
#include <concurrency/transaction.h>
#include <concurrency/transaction_callback.h>
#include <database.h>
#include <plan/physical/plan.h>
#include <string>
namespace beedb::io
{
/**
* @brief The Query struct contains the query-string and some parameters
* that influence the execution of a query, e.g. printing the logical plan
*/
struct Query
{
enum ExplainLevel
{
None,
Plan,
Graph
};
const std::string query_string;
ExplainLevel explain = None;
};
/**
* Wrapper for time and performance statistics, measured
* while query execution.
*/
class ExecutionResult
{
public:
explicit ExecutionResult(std::string &&error) : _is_successful(false), _error(std::move(error))
{
}
ExecutionResult(const std::uint64_t count_tuples, const std::chrono::milliseconds build_time,
const std::chrono::milliseconds execution_time, const std::size_t evicted_pages)
: _is_successful(true), _count_tuples(count_tuples), _build_ms(build_time), _execution_ms(execution_time),
_evicted_pages(evicted_pages)
{
}
~ExecutionResult() = default;
[[nodiscard]] std::chrono::milliseconds build_time() const
{
return _build_ms;
}
[[nodiscard]] std::chrono::milliseconds execution_time() const
{
return _execution_ms;
}
[[nodiscard]] std::size_t evicted_pages() const
{
return _evicted_pages;
}
[[nodiscard]] bool is_successful() const
{
return _is_successful;
}
[[nodiscard]] const std::string &error() const
{
return _error;
}
[[nodiscard]] std::uint64_t count_tuples() const
{
return _count_tuples;
}
private:
const bool _is_successful = false;
const std::string _error;
const std::uint64_t _count_tuples = 0u;
const std::chrono::milliseconds _build_ms{};
const std::chrono::milliseconds _execution_ms{};
const std::size_t _evicted_pages = 0u;
};
/**
* Executes queries and query plans.
*/
class Executor
{
public:
explicit Executor(Database &database, concurrency::Transaction *transaction = nullptr)
: _database(database), _transaction(transaction)
{
}
virtual ~Executor() = default;
ExecutionResult execute(const Query &query, ExecutionCallback &execution_callback,
concurrency::TransactionCallback &transaction_callback);
ExecutionResult execute(const Query &query, concurrency::TransactionCallback &transaction_callback)
{
SilentExecutionCallback execution_callback;
return execute(query, execution_callback, transaction_callback);
}
ExecutionResult execute(const Query &query, ExecutionCallback &execution_callback)
{
concurrency::SilentTransactionCallback silent_transaction_callback;
return execute(query, execution_callback, silent_transaction_callback);
}
ExecutionResult execute(const Query &query)
{
SilentExecutionCallback silent_execution_callback;
concurrency::SilentTransactionCallback silent_transaction_callback;
return execute(query, silent_execution_callback, silent_transaction_callback);
}
ExecutionResult execute(plan::physical::Plan &plan, ExecutionCallback &execution_callback);
ExecutionResult execute(plan::physical::Plan &plan)
{
SilentExecutionCallback execution_callback;
return execute(plan, execution_callback);
}
protected:
Database &_database;
concurrency::Transaction *_transaction;
};
} // namespace beedb::io

View File

@ -0,0 +1,50 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "executor.h"
#include <fstream>
#include <string>
#include <vector>
namespace beedb::io
{
/**
* Parses files for SQL-queries and executes them.
*/
class FileExecutor : private Executor
{
public:
FileExecutor(Database &database) : Executor(database, database.transaction_manager().new_transaction())
{
}
virtual ~FileExecutor() = default;
void execute(const std::string &file_name);
protected:
void execute_sql_file(std::ifstream &&file);
void execute_tbl_file(const std::string &file_name, std::ifstream &&file);
void execute_statements(std::vector<std::string> &&statements);
};
} // namespace beedb::io

View File

@ -0,0 +1,77 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "execution_callback.h"
#include <cstddef>
#include <string>
#include <table/schema.h>
#include <table/tuple.h>
#include <vector>
namespace beedb::io
{
/**
* Results of queries are serialized as follows:
* - First 2 bytes: Number of columns
* - For every column:
* - the type (table::Type)
* - the offset (std::size_t)
* - the column order index (std::uint16_t)
* - the null-terminated name of the column
* - After the schema, the bytes of the tuples will serialized.
*/
class QueryResultSerializer
{
public:
QueryResultSerializer();
~QueryResultSerializer();
void serialize(const table::Schema &schema);
void serialize(const table::Tuple &tuple);
[[nodiscard]] std::byte *data()
{
return _data;
}
[[nodiscard]] std::size_t size() const
{
return _size;
}
[[nodiscard]] bool empty() const
{
return _size == 0u;
}
private:
std::byte *_data = nullptr;
std::size_t _size = 0u;
std::size_t _capacity = 0u;
void append(const std::byte *data, const std::uint16_t size);
void prepend(const std::byte *data, const std::uint16_t size);
void allocate(const std::size_t capacity);
};
} // namespace beedb::io

View File

@ -0,0 +1,109 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "execution_callback.h"
#include <cstddef>
#include <cstdint>
#include <ostream>
#include <table/schema.h>
#include <table/tuple.h>
#include <util/text_table.h>
#include <vector>
namespace beedb::io
{
/**
* Formats the result of a query, given by schema and set of tuples.
*/
class ResultOutputFormatter final : public ExecutionCallback
{
friend std::ostream &operator<<(std::ostream &stream, const ResultOutputFormatter &result_output_formatter);
public:
ResultOutputFormatter() = default;
~ResultOutputFormatter() override = default;
static ResultOutputFormatter from_serialized_data(const std::size_t count_tuples, const std::byte *data);
void on_schema(const table::Schema &schema) override
{
header(schema);
}
void on_tuple(const table::Tuple &tuple) override
{
push_back(tuple);
}
void on_plan(const std::unique_ptr<plan::logical::NodeInterface> &) override
{
}
/**
* Set the header for the output.
*
* @param schema Schema for the header.
*/
void header(const table::Schema &schema);
/**
* Add a set of tuples to the result.
* @param tuples Set of tuples.
*/
void push_back(const std::vector<table::Tuple> &tuples);
/**
* Add a single tuple to the result.
* @param tuple
*/
void push_back(const table::Tuple &tuple);
/**
* Clear the formatter.
*/
inline void clear()
{
_table.clear();
}
/**
* @return True, when no tuple as added.
*/
inline bool empty() const
{
return _table.empty();
}
/**
* @return Number of added tuples.
*/
inline std::size_t count() const
{
return _count_tuples;
}
private:
util::TextTable _table;
std::size_t _count_tuples = 0u;
};
} // namespace beedb::io

View File

@ -0,0 +1,198 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "query_result_serializer.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <string_view>
namespace beedb::io
{
class ServerResponse
{
public:
enum Type : std::uint8_t
{
Empty,
Error,
AnalyticalResult,
TransactionalResult,
PlanExplanation,
ServerClosed
};
ServerResponse(const Type type, const std::uint64_t execution_time_in_ms)
: _type(type), _execution_time_in_ms(execution_time_in_ms)
{
}
virtual ~ServerResponse() = default;
[[nodiscard]] Type type() const
{
return _type;
}
[[nodiscard]] std::uint64_t execution_time_in_ms() const
{
return _execution_time_in_ms;
}
private:
const Type _type;
const std::uint64_t _execution_time_in_ms;
};
class EmptyResponse final : public ServerResponse
{
public:
EmptyResponse() : ServerResponse(Type::Empty, 0u)
{
}
~EmptyResponse() override = default;
static std::string build()
{
std::string response = std::string(sizeof(EmptyResponse), '\0');
new (response.data()) EmptyResponse();
return response;
}
};
class ErrorResponse final : public ServerResponse
{
public:
ErrorResponse() : ServerResponse(Type::Error, 0u)
{
}
~ErrorResponse() override = default;
static std::string build(std::string_view &&error_message)
{
std::string response = std::string(sizeof(ErrorResponse) + error_message.length(), '\0');
new (response.data()) ErrorResponse();
std::memcpy(response.data() + sizeof(ErrorResponse), error_message.data(), error_message.size());
return response;
}
[[nodiscard]] const char *message() const
{
return reinterpret_cast<const char *>(this + 1);
}
};
class AnalyticalResponse final : public ServerResponse
{
public:
AnalyticalResponse(const std::uint64_t execution_time_in_ms, const std::uint64_t count_rows)
: ServerResponse(Type::AnalyticalResult, execution_time_in_ms), _count_rows(count_rows)
{
}
~AnalyticalResponse() override = default;
[[nodiscard]] std::uint64_t count_rows() const
{
return _count_rows;
}
static std::string build(const std::uint64_t execution_time_in_ms, const std::uint64_t count_rows,
QueryResultSerializer &&query_serializer)
{
std::string response = std::string(sizeof(AnalyticalResponse) + query_serializer.size(), '\0');
new (response.data()) AnalyticalResponse(execution_time_in_ms, count_rows);
std::memmove(response.data() + sizeof(AnalyticalResponse), query_serializer.data(), query_serializer.size());
return response;
}
[[nodiscard]] const std::byte *data() const
{
return reinterpret_cast<const std::byte *>(this + 1);
}
private:
const std::uint64_t _count_rows;
};
class TransactionalResponse final : public ServerResponse
{
public:
TransactionalResponse(const std::uint64_t execution_time_in_ms, const std::uint64_t count_rows)
: ServerResponse(Type::TransactionalResult, execution_time_in_ms), _count_rows(count_rows)
{
}
~TransactionalResponse() override = default;
[[nodiscard]] std::uint64_t affected_rows() const
{
return _count_rows;
}
private:
const std::uint64_t _count_rows;
};
class QueryPlanResponse final : public ServerResponse
{
public:
QueryPlanResponse() : ServerResponse(Type::PlanExplanation, 0u)
{
}
~QueryPlanResponse() override = default;
static std::string build(std::string &&plan)
{
std::string response = std::string(sizeof(QueryPlanResponse) + plan.length(), '\0');
new (response.data()) QueryPlanResponse();
std::memmove(response.data() + sizeof(QueryPlanResponse), plan.data(), plan.size());
return response;
}
const char *payload() const
{
return reinterpret_cast<const char *>(this + 1);
}
};
class ServerClosedResponse final : public ServerResponse
{
public:
ServerClosedResponse() : ServerResponse(Type::ServerClosed, 0U)
{
}
~ServerClosedResponse() override = default;
static std::string build()
{
std::string response = std::string(sizeof(ServerClosedResponse), '\0');
new (response.data()) ServerClosedResponse();
return response;
}
};
} // namespace beedb::io

56
include/network/client.h Normal file
View File

@ -0,0 +1,56 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <cstdint>
#include <string>
namespace beedb::network
{
class Client
{
public:
Client(std::string &&server, std::uint16_t port);
~Client() = default;
bool connect();
void disconnect() const;
std::string send(const std::string &message);
[[nodiscard]] const std::string &server() const
{
return _server;
}
[[nodiscard]] std::uint16_t port() const
{
return _port;
}
private:
const std::string _server;
const std::uint16_t _port;
std::int32_t _socket;
std::uint64_t read_into_buffer(std::uint64_t length, void *buffer) const;
};
} // namespace beedb::network

90
include/network/server.h Normal file
View File

@ -0,0 +1,90 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <array>
#include <config.h>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
namespace beedb::network
{
class Server;
class ClientHandler
{
public:
ClientHandler() noexcept = default;
virtual ~ClientHandler() noexcept = default;
virtual std::optional<std::string> handle_message(const std::uint32_t client_id, const std::string &message) = 0;
virtual void on_client_connected(const std::uint32_t id) = 0;
virtual void on_client_disconnected(const std::uint32_t id) = 0;
virtual void server(Server *server)
{
_server = server;
}
protected:
[[nodiscard]] Server *server() const
{
return _server;
}
private:
Server *_server = nullptr;
};
class Server
{
public:
Server(ClientHandler &message_handler, std::uint16_t port) noexcept;
~Server() noexcept = default;
[[nodiscard]] std::uint16_t port() const noexcept
{
return _port;
}
[[nodiscard]] bool is_running() const noexcept
{
return _is_running;
}
void stop() noexcept
{
_is_running = false;
}
void send(std::uint32_t client_id, std::string &&message);
bool listen();
private:
const std::uint16_t _port;
std::int32_t _socket;
std::array<std::uint32_t, Config::max_clients> _client_sockets;
std::array<char, 512> _buffer;
ClientHandler &_handler;
alignas(64) bool _is_running = true;
std::uint16_t add_client(std::int32_t client_socket);
};
} // namespace beedb::network

2
include/parser/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
location.hh
parser.hpp

63
include/parser/driver.h Normal file
View File

@ -0,0 +1,63 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "location.hh"
#include "node.h"
#include <iostream>
#include <memory>
#include <vector>
namespace beedb::parser
{
class Parser;
class Driver
{
public:
Driver() noexcept = default;
~Driver() noexcept = default;
int parse(std::istream &&in);
[[nodiscard]] const std::unique_ptr<NodeInterface> &ast() const
{
return _root;
}
[[nodiscard]] std::unique_ptr<NodeInterface> &ast()
{
return _root;
}
void ast(std::unique_ptr<NodeInterface> &&root)
{
_root = std::move(root);
}
friend class Parser;
friend class Scanner;
private:
std::unique_ptr<NodeInterface> _root;
};
} // namespace beedb::parser

291
include/parser/node.h Normal file
View File

@ -0,0 +1,291 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <expression/operation.h>
#include <expression/term.h>
#include <memory>
#include <optional>
#include <string>
#include <table/schema.h>
#include <table/value.h>
#include <vector>
namespace beedb::parser
{
using Alias = std::optional<std::string>;
using TableDescr = std::pair<std::string, Alias>;
using JoinDescr = std::pair<TableDescr, std::unique_ptr<expression::Operation>>;
using WhereExpression = std::unique_ptr<expression::Operation>;
using GroupByExpression = std::vector<expression::Term>;
using OrderByItem = std::pair<std::unique_ptr<expression::Operation>, bool>;
using OrderByExpression = std::vector<OrderByItem>;
struct LimitExpression
{
std::uint64_t limit;
std::uint64_t offset;
};
class NodeInterface
{
public:
NodeInterface() noexcept = default;
virtual ~NodeInterface() noexcept = default;
};
class CreateTableStatement final : public NodeInterface
{
public:
CreateTableStatement(std::string &&table_name, const bool if_not_exists, table::Schema &&schema) noexcept
: _table_name(std::move(table_name)), _if_not_exists(if_not_exists), _schema(std::move(schema))
{
}
~CreateTableStatement() noexcept override = default;
[[nodiscard]] std::string &table_name() noexcept
{
return _table_name;
}
[[nodiscard]] bool if_not_exists() const noexcept
{
return _if_not_exists;
}
[[nodiscard]] table::Schema &schema()
{
return _schema;
}
private:
std::string _table_name;
bool _if_not_exists;
table::Schema _schema;
};
class CreateIndexStatement final : public NodeInterface
{
public:
CreateIndexStatement(std::string &&index_name, std::string &&table_name, std::string &&column_name,
const bool is_unique) noexcept
: _index_name(std::move(index_name)), _table_name(std::move(table_name)), _column_name(std::move(column_name)),
_is_unique(is_unique)
{
}
~CreateIndexStatement() noexcept override = default;
[[nodiscard]] std::string &index_name() noexcept
{
return _index_name;
}
[[nodiscard]] std::string &table_name() noexcept
{
return _table_name;
}
[[nodiscard]] std::string &column_name() noexcept
{
return _column_name;
}
[[nodiscard]] bool is_unique() const noexcept
{
return _is_unique;
}
private:
std::string _index_name;
std::string _table_name;
std::string _column_name;
bool _is_unique;
};
class InsertStatement final : public NodeInterface
{
public:
InsertStatement(std::string &&table_name, std::vector<std::string> &&column_names,
std::vector<std::vector<table::Value>> &&values) noexcept
: _table_name(std::move(table_name)), _column_names(std::move(column_names)), _values(std::move(values))
{
}
~InsertStatement() noexcept override = default;
[[nodiscard]] std::string &table_name() noexcept
{
return _table_name;
}
[[nodiscard]] std::vector<std::string> &column_names() noexcept
{
return _column_names;
}
[[nodiscard]] std::vector<std::vector<table::Value>> &values() noexcept
{
return _values;
}
private:
std::string _table_name;
std::vector<std::string> _column_names;
std::vector<std::vector<table::Value>> _values;
};
class UpdateStatement final : public NodeInterface
{
public:
UpdateStatement(std::string &&table_name,
std::vector<std::pair<expression::Attribute, std::unique_ptr<expression::Operation>>> &&updates,
WhereExpression &&where) noexcept
: _table_name(std::move(table_name)), _updates(std::move(updates)), _where(std::move(where))
{
}
~UpdateStatement() noexcept override = default;
[[nodiscard]] std::string &table_name() noexcept
{
return _table_name;
}
[[nodiscard]] std::vector<std::pair<expression::Attribute, std::unique_ptr<expression::Operation>>>
&updates() noexcept
{
return _updates;
}
[[nodiscard]] WhereExpression &where() noexcept
{
return _where;
}
private:
std::string _table_name;
std::vector<std::pair<expression::Attribute, std::unique_ptr<expression::Operation>>> _updates;
WhereExpression _where;
};
class DeleteStatement final : public NodeInterface
{
public:
DeleteStatement(std::string &&table_name, WhereExpression &&where) noexcept
: _table_name(std::move(table_name)), _where(std::move(where))
{
}
~DeleteStatement() noexcept override = default;
[[nodiscard]] std::string &table_name() noexcept
{
return _table_name;
}
[[nodiscard]] WhereExpression &where() noexcept
{
return _where;
}
private:
std::string _table_name;
WhereExpression _where;
};
class TransactionStatement final : public NodeInterface
{
public:
enum Type
{
BeginTransaction,
CommitTransaction,
AbortTransaction
};
explicit TransactionStatement(const Type type) : _type(type)
{
}
~TransactionStatement() override = default;
[[nodiscard]] bool is_begin() const noexcept
{
return _type == Type::BeginTransaction;
}
[[nodiscard]] bool is_commit() const noexcept
{
return _type == Type::CommitTransaction;
}
[[nodiscard]] bool is_abort() const noexcept
{
return _type == Type::AbortTransaction;
}
private:
const Type _type;
};
class SelectQuery final : public NodeInterface
{
public:
SelectQuery(std::vector<std::unique_ptr<expression::Operation>> &&attributes, std::vector<TableDescr> &&from,
std::optional<std::vector<JoinDescr>> &&join, WhereExpression &&where,
std::optional<GroupByExpression> &&group_by, std::optional<OrderByExpression> &&order_by,
std::optional<LimitExpression> &&limit) noexcept
: _attributes(std::move(attributes)), _from(std::move(from)), _join(std::move(join)), _where(std::move(where)),
_group_by(std::move(group_by)), _order_by(std::move(order_by)), _limit(limit)
{
}
~SelectQuery() noexcept override = default;
[[nodiscard]] std::vector<std::unique_ptr<expression::Operation>> &attributes() noexcept
{
return _attributes;
}
[[nodiscard]] std::vector<TableDescr> &from() noexcept
{
return _from;
}
[[nodiscard]] std::optional<std::vector<JoinDescr>> &join() noexcept
{
return _join;
}
[[nodiscard]] WhereExpression &where() noexcept
{
return _where;
}
[[nodiscard]] std::optional<GroupByExpression> &group_by() noexcept
{
return _group_by;
}
[[nodiscard]] std::optional<OrderByExpression> &order_by() noexcept
{
return _order_by;
}
[[nodiscard]] std::optional<LimitExpression> &limit() noexcept
{
return _limit;
}
private:
std::vector<std::unique_ptr<expression::Operation>> _attributes;
std::vector<TableDescr> _from;
std::optional<std::vector<JoinDescr>> _join;
WhereExpression _where;
std::optional<GroupByExpression> _group_by;
std::optional<OrderByExpression> _order_by;
std::optional<LimitExpression> _limit;
};
} // namespace beedb::parser

View File

@ -0,0 +1,54 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#undef YY_DECL
#define YY_DECL db::parser::symbol_type db::Scanner::lex()
#include <iostream>
#ifndef yyFlexLexerOnce
#include <FlexLexer.h>
#endif
#include "location.hh"
#include "parser.hpp"
namespace beedb::parser
{
// forward declare to avoid an include
class Driver;
class Scanner : public yyFlexLexer
{
public:
explicit Scanner(std::istream &stream) : yyFlexLexer(stream, std::cout)
{
}
~Scanner() override
{
}
Parser::symbol_type lex(Driver &driver);
};
} // namespace beedb::parser

View File

@ -0,0 +1,42 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "driver.h"
#include "node.h"
#include <memory>
#include <string>
namespace beedb::parser
{
class SQLParser
{
public:
SQLParser() noexcept = default;
~SQLParser() noexcept = default;
std::unique_ptr<NodeInterface> parse(std::string &&query);
private:
Driver _driver;
};
} // namespace beedb::parser

View File

@ -0,0 +1,297 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include <algorithm>
#include <cassert>
#include <iostream>
#include <memory>
#include <set>
#include <tuple>
#include <unordered_map>
#include <vector>
namespace beedb::util
{
/**
* @brief The Graph class represents a directed graph with "weighted edges".
*
* Individual node store objects of type NodeData and have a unique id of type NodeIDType.
* Edges are directional and carry objects of type EdgeData.
* There can only be one edge from node A to node B.
*
* This class makes extensive use of the subscript operator[]. Edges and nodes can be created and accessed by simply
* using the operator. For example: `graph[edge] = edge_value`, `NodeDataType value = graph[node]` or
* `graph[edge].remove()`.
*/
template <typename NodeDataType, typename EdgeDataType, typename NodeIDType> class Graph
{
public:
using EdgeID = std::pair<NodeIDType, NodeIDType>; // edge is a pair: <from,to>
using NodeIDs = std::vector<NodeIDType>; // a collection of node id's
Graph() = default;
Graph(Graph &&) noexcept = default;
Graph(const Graph &) = delete;
virtual ~Graph() = default;
protected:
struct EdgeIdHash
{
std::size_t operator()(const EdgeID &id) const
{
return std::hash<NodeIDType>()(std::get<0>(id)) ^ std::hash<NodeIDType>()(std::get<1>(id));
}
};
using NodeData = std::unordered_map<NodeIDType, std::unique_ptr<NodeDataType>>; // holds actual node data
using EdgeData = std::unordered_map<EdgeID, EdgeDataType, EdgeIdHash>; // holds actual edge data
using NodeIDMap = std::unordered_map<NodeIDType, NodeIDs>; // used for aux. data structures
/**
* @brief The Edges struct Proxy data structure that helps implement
* the subscript-assignement operators for edges. This is more complicated
* (compared to node data), because we make use of auxillary data
* structures for edges (incoming and outgoing edges).
*/
class Edge
{
public:
Edge(Graph *ref, const EdgeID &edge) : _ref(ref), _edge(edge)
{
}
~Edge() = default;
/**
* @brief operator =
* This gets called, when a call similar to
* `graph[{A,B}] = edge_value;` (clone-assignement) is made.
*
* This structure is required to keep auxillary structures (incomin- and outgoing nodes) consistent!
*
* @param data
*/
void operator=(const EdgeDataType &data)
{
// check graph consistency: we can not add an edge to nodes that dont exist:
if (_ref->_node_data.find(_edge.first) == _ref->_node_data.end() ||
_ref->_node_data.find(_edge.second) == _ref->_node_data.end())
{
std::cerr << "ERROR: Trying to add edge, but nodes do not exist in graph!"
<< " Edge is < " << _edge.first << " , " << _edge.second << " >" << std::endl;
return;
}
// the assertions test, if all auxillary structures are properly initialized:
assert(_ref->_incoming_node_ids.find(_edge.first) != _ref->_incoming_node_ids.end());
assert(_ref->_incoming_node_ids.find(_edge.second) != _ref->_incoming_node_ids.end());
assert(_ref->_outgoing_node_ids.find(_edge.first) != _ref->_outgoing_node_ids.end());
assert(_ref->_outgoing_node_ids.find(_edge.second) != _ref->_outgoing_node_ids.end());
// create edge:
_ref->_outgoing_node_ids[_edge.first].push_back(_edge.second);
_ref->_incoming_node_ids[_edge.second].push_back(_edge.first);
_ref->_edge_data.insert({_edge, data});
}
/**
* @brief operator EdgeData & conversion operator, that enables the
* subscript operator to be used as a simple getter for the data behind
* this proxy object.
*/
explicit operator const EdgeDataType &() const
{
return _ref->_edge_data[_edge];
}
/**
* @brief remove just removes this edge and its data.
*
* We also remove it from auxillary data structures ("incoming" and "outgoing" nodes).
*/
void remove()
{
// first, remove edge and its data
_ref->_edge_data.erase(_edge);
// then remove id from auxillary edge-structures:
auto &out_nodes = _ref->_outgoing_node_ids[_edge.first];
out_nodes.erase(std::remove(out_nodes.begin(), out_nodes.end(), _edge.second), out_nodes.end());
auto &in_nodes = _ref->_incoming_node_ids[_edge.second];
in_nodes.erase(std::remove(in_nodes.begin(), in_nodes.end(), _edge.second), in_nodes.end());
}
private:
Graph *_ref;
const EdgeID &_edge;
};
class Node
{
public:
Node(Graph *ref, const NodeIDType &nid) : _ref(ref), _nid(nid)
{
}
/**
* @brief operator =
* This gets called, when a call similar to
* `graph[node_id] = node_data;` is made.
*
* This structure is required to keep auxillary structures (incomin- and outgoing nodes) consistent!
*
* @param data
*/
void operator=(std::unique_ptr<NodeDataType> data)
{
_ref->insert({_nid, std::move(data)});
}
/**
* @brief operator NodeDataType & conversion operator, that enables the
* subscript operator to be used as a simple getter for the data behind
* this proxy object.
*/
explicit operator std::unique_ptr<NodeDataType> &()
{
return _ref->_node_data[_nid];
}
explicit operator const NodeDataType &() const
{
return **(_ref->_node_data[_nid]);
}
[[maybe_unused]] const NodeIDs &incomingNodes() const
{
return _ref->_incoming_node_ids[_nid];
}
[[maybe_unused]] const NodeIDs &outgoingNodes() const
{
return _ref->_outgoing_node_ids[_nid];
}
/**
* @brief remove removes this node and all connected edges.
*/
void remove()
{
// remove node data:
_ref->_node_data.erase(_nid);
// remove incoming edges:
for (auto &other_node_id : _ref->_incoming_node_ids[_nid])
{
_ref->_edge_data.erase({other_node_id, _nid}); // actual edge
// remove edges to this node from _outgoing_node_ids of other_node:
NodeIDs &out_nodes = _ref->_outgoing_node_ids[other_node_id];
out_nodes.erase(std::remove(out_nodes.begin(), out_nodes.end(), _nid), out_nodes.end());
}
// remove outgoing edges:
for (auto &other_node_id : _ref->_outgoing_node_ids[_nid])
{
_ref->_edge_data.erase({_nid, other_node_id}); // actual edge
// remove edges to this node from _incoming_node_ids of other_node:
NodeIDs &in_nodes = _ref->_incoming_node_ids[other_node_id];
in_nodes.erase(std::remove(in_nodes.begin(), in_nodes.end(), _nid), in_nodes.end());
}
// remove auxillary entries for this node:
_ref->_incoming_node_ids.erase(_nid);
_ref->_outgoing_node_ids.erase(_nid);
}
private:
Graph *_ref;
const NodeIDType &_nid;
};
public:
// getter and setter for nodes/their data. can change node's data
Node operator[](const NodeIDType &nid)
{
return Node(this, nid);
}
const NodeIDType &insert(
typename NodeData::value_type &&map_pair) // parameter type is a std::pair<NodeIDType, NodeDataType>
{
const NodeIDType &id = _node_data.insert({map_pair.first, std::move(map_pair.second)}).first->first;
_incoming_node_ids.insert({id, {}});
_outgoing_node_ids.insert({id, {}});
return id;
}
// simple read-only getter for node-data
const std::unique_ptr<NodeDataType> &operator[](const NodeIDType &nid) const
{
return _node_data.at(nid);
}
// getter for mutable edge-data. Access via pair <from,to>
Edge operator[](const EdgeID &edge)
{
return Edge(this, edge);
}
// simple read-only getter for edge-data. Access via pair <from,to>
const EdgeDataType &operator[](const EdgeID &edge_id) const
{
return _edge_data[edge_id];
}
/**
* @brief toConsole exhaustive dump of all node- and edge ids to console, without data.
*/
void toConsole() const
{
std::cout << "Nodes:" << std::endl;
for (const auto &node : _node_data)
{
std::cout << "\t{" << node.first << ": " << static_cast<std::string>(*(node.second)) << "}" << std::endl;
}
std::cout << "Edges:" << std::endl;
for (auto const &edge : _edge_data)
{
std::cout << "\t<" << edge.first.first << "," << edge.first.second << ">" << std::endl;
}
}
[[maybe_unused]] [[nodiscard]] const NodeIDs &outgoing_nodes(const NodeIDType &nid) const
{
return _outgoing_node_ids.at(nid);
}
[[nodiscard]] const NodeIDs &incoming_nodes(const NodeIDType &nid) const
{
return _incoming_node_ids.at(nid);
}
[[nodiscard]] bool empty() const
{
return _node_data.empty();
}
protected: // actual graph data should be available to daughter classes
NodeData _node_data; // contains node data. key is a NodeIDType
EdgeData _edge_data; // contains edge data. key is a pair <A_ID,B_ID>
NodeIDMap _outgoing_node_ids; // for efficient connectivity lookup
NodeIDMap _incoming_node_ids; // for efficient connectivity lookup
};
} // namespace beedb::util

View File

@ -0,0 +1,58 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node/node_interface.h"
#include <database.h>
#include <parser/node.h>
namespace beedb::plan::logical
{
class Builder
{
public:
static std::unique_ptr<NodeInterface> build(Database &database,
const std::unique_ptr<parser::NodeInterface> &query);
static std::unique_ptr<NodeInterface> build(Database &database, parser::SelectQuery *select_query);
static std::unique_ptr<NodeInterface> build(Database &database, parser::CreateTableStatement *create_statement);
static std::unique_ptr<NodeInterface> build(Database &database,
parser::CreateIndexStatement *create_index_statement);
static std::unique_ptr<NodeInterface> build(Database &database, parser::InsertStatement *insert_statement);
static std::unique_ptr<NodeInterface> build(Database &database, parser::UpdateStatement *update_statement);
static std::unique_ptr<NodeInterface> build(Database &database, parser::DeleteStatement *delete_statement);
static std::unique_ptr<NodeInterface> build(Database &database,
parser::TransactionStatement *transaction_statement);
private:
[[nodiscard]] static std::unique_ptr<NodeInterface> create_from(
Database &database, std::vector<parser::TableDescr> &&from,
std::optional<std::vector<parser::JoinDescr>> &&join);
[[nodiscard]] static std::unique_ptr<NodeInterface> parse_select_expression(
std::unique_ptr<NodeInterface> &&top_node, std::vector<expression::Term> &projection_terms,
std::vector<std::unique_ptr<expression::Operation>> &aggregations,
std::unique_ptr<expression::Operation> &&select_expression, bool add_to_projection);
[[nodiscard]] static std::vector<std::unique_ptr<expression::Operation>> split_logical_and(
std::unique_ptr<expression::Operation> &&root);
static void split_logical_and(std::unique_ptr<expression::Operation> &&root,
std::vector<std::unique_ptr<expression::Operation>> &container);
};
} // namespace beedb::plan::logical

View File

@ -0,0 +1,82 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node_interface.h"
namespace beedb::plan::logical
{
class AggregationNode final : public UnaryNode
{
public:
AggregationNode(std::vector<std::unique_ptr<expression::Operation>> &&aggregations,
std::vector<expression::Term> &&group_by)
: UnaryNode("Aggregation"), _aggregation_expressions(std::move(aggregations)),
_group_expressions(std::move(group_by))
{
}
~AggregationNode() override = default;
[[nodiscard]] const std::vector<std::unique_ptr<expression::Operation>> &aggregation_expressions() const
{
return _aggregation_expressions;
}
[[nodiscard]] const std::vector<expression::Term> &group_expressions() const
{
return _group_expressions;
}
const Schema &check_and_emit_schema(TableMap &tables) override
{
_schema.clear();
child()->check_and_emit_schema(tables);
for (auto &group : _group_expressions)
{
tables.check_and_replace_table(group.get<expression::Attribute>());
}
for (const auto &aggregation : _aggregation_expressions)
{
if (aggregation->result().has_value())
{
_schema.push_back(aggregation->result().value());
}
}
std::copy(_group_expressions.begin(), _group_expressions.end(), std::back_inserter(_schema));
return _schema;
}
[[nodiscard]] const Schema &schema() const override
{
return _schema;
}
private:
std::vector<std::unique_ptr<expression::Operation>> _aggregation_expressions;
std::vector<expression::Term> _group_expressions;
Schema _schema;
};
} // namespace beedb::plan::logical

View File

@ -0,0 +1,69 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node_interface.h"
namespace beedb::plan::logical
{
class ArithmeticNode final : public UnaryNode
{
public:
explicit ArithmeticNode(std::unique_ptr<expression::Operation> &&expression)
: UnaryNode("Arithmetic"), _expression(std::move(expression))
{
}
~ArithmeticNode() override = default;
[[nodiscard]] const std::unique_ptr<expression::Operation> &expression() const
{
return _expression;
}
const Schema &check_and_emit_schema(TableMap &tables) override
{
_schema.clear();
const auto &child_schema = child()->check_and_emit_schema(tables);
// TODO: Check
tables.check_and_replace_table(_expression);
std::copy(child_schema.begin(), child_schema.end(), std::back_inserter(_schema));
if (_expression->result().has_value())
{
_schema.push_back(_expression->result().value());
}
return _schema;
}
[[nodiscard]] const Schema &schema() const override
{
return _schema;
}
private:
std::unique_ptr<expression::Operation> _expression{};
Schema _schema;
};
} // namespace beedb::plan::logical

View File

@ -0,0 +1,79 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node_interface.h"
#include <index/type.h>
namespace beedb::plan::logical
{
class CreateIndexNode final : public NotSchematizedNode
{
public:
CreateIndexNode(Database &database, expression::Attribute &&attribute, std::string &&index_name,
const index::Type index_type, const bool is_unique)
: NotSchematizedNode("Create Index"), _database(database), _attribute(std::move(attribute)),
_index_name(std::move(index_name)), _index_type(index_type), _is_unique(is_unique)
{
}
~CreateIndexNode() override = default;
[[nodiscard]] const expression::Attribute &attribute() const
{
return _attribute;
}
[[nodiscard]] const std::string &index_name() const
{
return _index_name;
}
[[nodiscard]] bool is_unique() const
{
return _is_unique;
}
[[nodiscard]] index::Type index_type() const
{
return _index_type;
}
const Schema &check_and_emit_schema(TableMap &tables) override
{
if (_database.table_exists(_attribute.table_name().value()) == false)
{
throw exception::TableNotFoundException(_attribute.table_name().value());
}
tables.insert(_database.table(_attribute.table_name().value()), _attribute.table_name().value());
tables.check_and_replace_table(_attribute);
return NotSchematizedNode::check_and_emit_schema(tables);
}
private:
Database &_database;
expression::Attribute _attribute;
std::string _index_name;
index::Type _index_type;
bool _is_unique;
};
} // namespace beedb::plan::logical

View File

@ -0,0 +1,73 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node_interface.h"
namespace beedb::plan::logical
{
class CreateTableNode final : public NotSchematizedNode
{
public:
CreateTableNode(Database &database, std::string &&table_name, table::Schema &&schema)
: NotSchematizedNode("Create Table"), _database(database), _table_name(std::move(table_name)),
_schema(std::move(schema))
{
}
~CreateTableNode() override = default;
[[nodiscard]] const std::string &table_name() const
{
return _table_name;
}
[[nodiscard]] std::string &table_name()
{
return _table_name;
}
[[nodiscard]] const table::Schema &table_schema() const
{
return _schema;
}
[[nodiscard]] table::Schema &table_schema()
{
return _schema;
}
const Schema &check_and_emit_schema(TableMap &tables) override
{
if (_database.table_exists(_table_name))
{
throw exception::TableAlreadyExists(_table_name);
}
return NotSchematizedNode::check_and_emit_schema(tables);
}
private:
Database &_database;
std::string _table_name;
table::Schema _schema;
};
} // namespace beedb::plan::logical

View File

@ -0,0 +1,59 @@
/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "node_interface.h"
namespace beedb::plan::logical
{
class CrossProductNode final : public BinaryNode
{
public:
CrossProductNode() : BinaryNode("Cross Product")
{
}
~CrossProductNode() override = default;
const Schema &check_and_emit_schema(TableMap &tables) override
{
_schema.clear();
const auto &left_schema = left_child()->check_and_emit_schema(tables);
const auto &right_schema = right_child()->check_and_emit_schema(tables);
_schema.reserve(left_schema.size() + right_schema.size());
std::copy(left_schema.begin(), left_schema.end(), std::back_inserter(_schema));
std::copy(right_schema.begin(), right_schema.end(), std::back_inserter(_schema));
return _schema;
}
[[nodiscard]] const Schema &schema() const override
{
return _schema;
}
private:
Schema _schema;
};
} // namespace beedb::plan::logical

Some files were not shown because too many files have changed in this diff Show More