Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM] add HTTP service / Calcite query frontend for BusTub #628

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ set(BUSTUB_THIRD_PARTY_INCLUDE_DIR
${PROJECT_SOURCE_DIR}/third_party/argparse/include
${PROJECT_SOURCE_DIR}/third_party/cpp_random_distributions
${PROJECT_SOURCE_DIR}/third_party/backward-cpp/include
${PROJECT_SOURCE_DIR}/third_party/json/include
)

include_directories(${BUSTUB_SRC_INCLUDE_DIR} ${BUSTUB_TEST_INCLUDE_DIR} ${BUSTUB_THIRD_PARTY_INCLUDE_DIR})
Expand Down
44 changes: 44 additions & 0 deletions src/common/bustub_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,50 @@ auto BustubInstance::ExecuteSql(const std::string &sql, ResultWriter &writer,
}
}

auto BustubInstance::ExecutePlan(const AbstractPlanNodeRef &plan, ResultWriter &writer) -> bool {
auto txn = txn_manager_->Begin();
try {
auto result = ExecutePlanTxn(plan, txn, writer);
txn_manager_->Commit(txn);
delete txn;
return result;
} catch (bustub::Exception &ex) {
txn_manager_->Abort(txn);
delete txn;
throw ex;
}
}

auto BustubInstance::ExecutePlanTxn(const AbstractPlanNodeRef &plan, Transaction *txn, ResultWriter &writer) -> bool {
// Execute the query.
auto exec_ctx = MakeExecutorContext(txn, false);
std::vector<Tuple> result_set{};
auto is_successful = execution_engine_->Execute(plan, &result_set, txn, exec_ctx.get());

// Return the result set as a vector of string.
auto schema = plan->OutputSchema();

// Generate header for the result set.
writer.BeginTable(false);
writer.BeginHeader();
for (const auto &column : schema.GetColumns()) {
writer.WriteHeaderCell(column.GetName());
}
writer.EndHeader();

// Transforming result set into strings.
for (const auto &tuple : result_set) {
writer.BeginRow();
for (uint32_t i = 0; i < schema.GetColumnCount(); i++) {
writer.WriteCell(tuple.GetValue(&schema, i).ToString());
}
writer.EndRow();
}
writer.EndTable();

return is_successful;
}

auto BustubInstance::ExecuteSqlTxn(const std::string &sql, ResultWriter &writer, Transaction *txn,
std::shared_ptr<CheckOptions> check_options) -> bool {
if (!sql.empty() && sql[0] == '\\') {
Expand Down
4 changes: 4 additions & 0 deletions src/include/common/bustub_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "common/config.h"
#include "common/util/string_util.h"
#include "execution/check_options.h"
#include "execution/plans/abstract_plan.h"
#include "libfort/lib/fort.hpp"
#include "type/value.h"

Expand Down Expand Up @@ -265,6 +266,9 @@ class BustubInstance {
/** Get the current transaction. */
auto CurrentManagedTxn() -> Transaction *;

auto ExecutePlan(const AbstractPlanNodeRef &plan, ResultWriter &writer) -> bool;
auto ExecutePlanTxn(const AbstractPlanNodeRef &plan, Transaction *txn, ResultWriter &writer) -> bool;

/**
* FOR TEST ONLY. Generate test tables in this BusTub instance.
* It's used in the shell to predefine some tables, as we don't support
Expand Down
4 changes: 4 additions & 0 deletions third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ add_subdirectory(utf8proc)
add_subdirectory(backward-cpp)

add_subdirectory(readerwriterqueue)

add_subdirectory(json)

add_subdirectory(cpp-httplib)
304 changes: 304 additions & 0 deletions third_party/cpp-httplib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
#[[
Build options:
* BUILD_SHARED_LIBS (default off) builds as a shared library (if HTTPLIB_COMPILE is ON)
* HTTPLIB_USE_OPENSSL_IF_AVAILABLE (default on)
* HTTPLIB_USE_ZLIB_IF_AVAILABLE (default on)
* HTTPLIB_REQUIRE_OPENSSL (default off)
* HTTPLIB_REQUIRE_ZLIB (default off)
* HTTPLIB_USE_BROTLI_IF_AVAILABLE (default on)
* HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN (default on)
* HTTPLIB_REQUIRE_BROTLI (default off)
* HTTPLIB_COMPILE (default off)
* HTTPLIB_INSTALL (default on)
* HTTPLIB_TEST (default off)
* BROTLI_USE_STATIC_LIBS - tells Cmake to use the static Brotli libs (only works if you have them installed).
* OPENSSL_USE_STATIC_LIBS - tells Cmake to use the static OpenSSL libs (only works if you have them installed).

-------------------------------------------------------------------------------

After installation with Cmake, a find_package(httplib COMPONENTS OpenSSL ZLIB Brotli) is available.
This creates a httplib::httplib target (if found and if listed components are supported).
It can be linked like so:

target_link_libraries(your_exe httplib::httplib)

The following will build & install for later use.

Linux/macOS:

mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
sudo cmake --build . --target install

Windows:

mkdir build
cd build
cmake ..
runas /user:Administrator "cmake --build . --config Release --target install"

-------------------------------------------------------------------------------

These variables are available after you run find_package(httplib)
* HTTPLIB_HEADER_PATH - this is the full path to the installed header (e.g. /usr/include/httplib.h).
* HTTPLIB_IS_USING_OPENSSL - a bool for if OpenSSL support is enabled.
* HTTPLIB_IS_USING_ZLIB - a bool for if ZLIB support is enabled.
* HTTPLIB_IS_USING_BROTLI - a bool for if Brotli support is enabled.
* HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN - a bool for if support of loading system certs from the Apple Keychain is enabled.
* HTTPLIB_IS_COMPILED - a bool for if the library is compiled, or otherwise header-only.
* HTTPLIB_INCLUDE_DIR - the root path to httplib's header (e.g. /usr/include).
* HTTPLIB_LIBRARY - the full path to the library if compiled (e.g. /usr/lib/libhttplib.so).
* httplib_VERSION or HTTPLIB_VERSION - the project's version string.
* HTTPLIB_FOUND - a bool for if the target was found.

Want to use precompiled headers (Cmake feature since v3.16)?
It's as simple as doing the following (before linking):

target_precompile_headers(httplib::httplib INTERFACE "${HTTPLIB_HEADER_PATH}")

-------------------------------------------------------------------------------

FindPython3 requires Cmake v3.12
ARCH_INDEPENDENT option of write_basic_package_version_file() requires Cmake v3.14
]]
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR)

# Get the CPPHTTPLIB_VERSION value and use it as a version
# This gets the string with the CPPHTTPLIB_VERSION value from the header.
# This is so the maintainer doesn't actually need to update this manually.
file(STRINGS httplib.h _raw_version_string REGEX "CPPHTTPLIB_VERSION \"([0-9]+\\.[0-9]+\\.[0-9]+)\"")

# Needed since git tags have "v" prefixing them.
# Also used if the fallback to user agent string is being used.
string(REGEX MATCH "([0-9]+\\.?)+" _httplib_version "${_raw_version_string}")

project(httplib VERSION ${_httplib_version} LANGUAGES CXX)

# Lets you disable C++ exception during CMake configure time.
# The value is used in the install CMake config file.
option(HTTPLIB_NO_EXCEPTIONS "Disable the use of C++ exceptions" OFF)

# Change as needed to set an OpenSSL minimum version.
# This is used in the installed Cmake config file.
set(_HTTPLIB_OPENSSL_MIN_VER "1.1.1")

# Allow for a build to require OpenSSL to pass, instead of just being optional
option(HTTPLIB_REQUIRE_OPENSSL "Requires OpenSSL to be found & linked, or fails build." OFF)
option(HTTPLIB_REQUIRE_ZLIB "Requires ZLIB to be found & linked, or fails build." OFF)
# Allow for a build to casually enable OpenSSL/ZLIB support, but silently continue if not found.
# Make these options so their automatic use can be specifically disabled (as needed)
option(HTTPLIB_USE_OPENSSL_IF_AVAILABLE "Uses OpenSSL (if available) to enable HTTPS support." ON)
option(HTTPLIB_USE_ZLIB_IF_AVAILABLE "Uses ZLIB (if available) to enable Zlib compression support." ON)
# Lets you compile the program as a regular library instead of header-only
option(HTTPLIB_COMPILE "If ON, uses a Python script to split the header into a compilable header & source file (requires Python v3)." OFF)
# Lets you disable the installation (useful when fetched from another CMake project)
option(HTTPLIB_INSTALL "Enables the installation target" ON)
# Just setting this variable here for people building in-tree
if(HTTPLIB_COMPILE)
set(HTTPLIB_IS_COMPILED TRUE)
endif()
option(HTTPLIB_TEST "Enables testing and builds tests" OFF)
option(HTTPLIB_REQUIRE_BROTLI "Requires Brotli to be found & linked, or fails build." OFF)
option(HTTPLIB_USE_BROTLI_IF_AVAILABLE "Uses Brotli (if available) to enable Brotli decompression support." ON)
option(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN "Enable feature to load system certs from the Apple Keychain." ON)
# Defaults to static library
option(BUILD_SHARED_LIBS "Build the library as a shared library instead of static. Has no effect if using header-only." OFF)
if (BUILD_SHARED_LIBS AND WIN32 AND HTTPLIB_COMPILE)
# Necessary for Windows if building shared libs
# See https://stackoverflow.com/a/40743080
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()

# Threads needed for <thread> on some systems, and for <pthread.h> on Linux
set(THREADS_PREFER_PTHREAD_FLAG true)
find_package(Threads REQUIRED)
# Since Cmake v3.11, Crypto & SSL became optional when not specified as COMPONENTS.
if(HTTPLIB_REQUIRE_OPENSSL)
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL REQUIRED)
elseif(HTTPLIB_USE_OPENSSL_IF_AVAILABLE)
find_package(OpenSSL ${_HTTPLIB_OPENSSL_MIN_VER} COMPONENTS Crypto SSL QUIET)
endif()
# Just setting this variable here for people building in-tree
if(OPENSSL_FOUND AND NOT DEFINED HTTPLIB_IS_USING_OPENSSL)
set(HTTPLIB_IS_USING_OPENSSL TRUE)
endif()

if(HTTPLIB_REQUIRE_ZLIB)
find_package(ZLIB REQUIRED)
elseif(HTTPLIB_USE_ZLIB_IF_AVAILABLE)
find_package(ZLIB QUIET)
endif()
# Just setting this variable here for people building in-tree
# FindZLIB doesn't have a ZLIB_FOUND variable, so check the target.
if(TARGET ZLIB::ZLIB)
set(HTTPLIB_IS_USING_ZLIB TRUE)
endif()

# Adds our cmake folder to the search path for find_package
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
if(HTTPLIB_REQUIRE_BROTLI)
find_package(Brotli COMPONENTS encoder decoder common REQUIRED)
elseif(HTTPLIB_USE_BROTLI_IF_AVAILABLE)
find_package(Brotli COMPONENTS encoder decoder common QUIET)
endif()
# Just setting this variable here for people building in-tree
if(Brotli_FOUND)
set(HTTPLIB_IS_USING_BROTLI TRUE)
endif()

if(HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN)
set(HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN TRUE)
endif()

# Used for default, common dirs that the end-user can change (if needed)
# like CMAKE_INSTALL_INCLUDEDIR or CMAKE_INSTALL_DATADIR
include(GNUInstallDirs)

if(HTTPLIB_COMPILE)
# Put the split script into the build dir
configure_file(split.py "${CMAKE_CURRENT_BINARY_DIR}/split.py"
COPYONLY
)
# Needs to be in the same dir as the python script
configure_file(httplib.h "${CMAKE_CURRENT_BINARY_DIR}/httplib.h"
COPYONLY
)

# Used outside of this if-else
set(_INTERFACE_OR_PUBLIC PUBLIC)
# Brings in the Python3_EXECUTABLE path we can use.
find_package(Python3 REQUIRED)
# Actually split the file
# Keeps the output in the build dir to not pollute the main dir
execute_process(COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/split.py"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
ERROR_VARIABLE _httplib_split_error
)
if(_httplib_split_error)
message(FATAL_ERROR "Failed when trying to split cpp-httplib with the Python script.\n${_httplib_split_error}")
endif()

# split.py puts output in "out"
set(_httplib_build_includedir "${CMAKE_CURRENT_BINARY_DIR}/out")
# This will automatically be either static or shared based on the value of BUILD_SHARED_LIBS
add_library(${PROJECT_NAME} "${_httplib_build_includedir}/httplib.cc")
target_sources(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
)
set_target_properties(${PROJECT_NAME}
PROPERTIES
VERSION ${${PROJECT_NAME}_VERSION}
SOVERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}"
)
else()
# This is for header-only.
set(_INTERFACE_OR_PUBLIC INTERFACE)
add_library(${PROJECT_NAME} INTERFACE)
set(_httplib_build_includedir "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
# Lets you address the target with httplib::httplib
# Only useful if building in-tree, versus using it from an installation.
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})

# Require C++11
target_compile_features(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
cxx_std_11
)

target_include_directories(${PROJECT_NAME} SYSTEM ${_INTERFACE_OR_PUBLIC}
$<BUILD_INTERFACE:${_httplib_build_includedir}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

# Always require threads
target_link_libraries(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
Threads::Threads
# Needed for Windows libs on Mingw, as the pragma comment(lib, "xyz") aren't triggered.
$<$<PLATFORM_ID:Windows>:ws2_32>
$<$<PLATFORM_ID:Windows>:crypt32>
$<$<PLATFORM_ID:Windows>:cryptui>
# Needed for API from MacOS Security framework
"$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN}>>:-framework CoreFoundation -framework Security>"
# Can't put multiple targets in a single generator expression or it bugs out.
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::common>
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::encoder>
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:Brotli::decoder>
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:ZLIB::ZLIB>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::SSL>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:OpenSSL::Crypto>
)

# Set the definitions to enable optional features
target_compile_definitions(${PROJECT_NAME} ${_INTERFACE_OR_PUBLIC}
$<$<BOOL:${HTTPLIB_NO_EXCEPTIONS}>:CPPHTTPLIB_NO_EXCEPTIONS>
$<$<BOOL:${HTTPLIB_IS_USING_BROTLI}>:CPPHTTPLIB_BROTLI_SUPPORT>
$<$<BOOL:${HTTPLIB_IS_USING_ZLIB}>:CPPHTTPLIB_ZLIB_SUPPORT>
$<$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>:CPPHTTPLIB_OPENSSL_SUPPORT>
$<$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${HTTPLIB_IS_USING_OPENSSL}>,$<BOOL:${HTTPLIB_IS_USING_CERTS_FROM_MACOSX_KEYCHAIN}>>:CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN>
)

# CMake configuration files installation directory
set(_TARGET_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")

include(CMakePackageConfigHelpers)

# Configures the meta-file httplibConfig.cmake.in to replace variables with paths/values/etc.
configure_package_config_file("${PROJECT_NAME}Config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION "${_TARGET_INSTALL_CMAKEDIR}"
# Passes the includedir install path
PATH_VARS CMAKE_INSTALL_FULL_INCLUDEDIR
)

if(HTTPLIB_COMPILE)
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
# Example: if you find_package(httplib 0.5.4)
# then anything >= 0.5.4 and < 0.6 is accepted
COMPATIBILITY SameMinorVersion
)
else()
write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake"
# Example: if you find_package(httplib 0.5.4)
# then anything >= 0.5.4 and < 0.6 is accepted
COMPATIBILITY SameMinorVersion
# Tells Cmake that it's a header-only lib
# Mildly useful for end-users :)
ARCH_INDEPENDENT
)
endif()

if(HTTPLIB_INSTALL)
# Creates the export httplibTargets.cmake
# This is strictly what holds compilation requirements
# and linkage information (doesn't find deps though).
install(TARGETS ${PROJECT_NAME}
EXPORT httplibTargets
)

install(FILES "${_httplib_build_includedir}/httplib.h" TYPE INCLUDE)

install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
# Install it so it can be used later by the httplibConfig.cmake file.
# Put it in the same dir as our config file instead of a global path so we don't potentially stomp on other packages.
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindBrotli.cmake"
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)

# NOTE: This path changes depending on if it's on Windows or Linux
install(EXPORT httplibTargets
# Puts the targets into the httplib namespace
# So this makes httplib::httplib linkable after doing find_package(httplib)
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${_TARGET_INSTALL_CMAKEDIR}
)
endif()

if(HTTPLIB_TEST)
include(CTest)
add_subdirectory(test)
endif()
Loading
Loading