├── .circleci └── config.yml ├── .clang-format ├── .clang-tidy ├── .dockerignore ├── .github ├── pull_request_template.md └── workflows │ └── cmake.yml ├── .gitignore ├── CMakeLists.txt ├── Dockerfile ├── LICENSE ├── README.md ├── Vagrantfile ├── build_support ├── clang_format_exclusions.txt ├── cpplint.py ├── gtest_CMakeLists.txt.in ├── packages.sh ├── run_clang_format.py ├── run_clang_tidy.py ├── run_clang_tidy_extra.py └── valgrind.supp ├── logo ├── bustub-whiteborder.svg └── bustub.svg ├── src ├── CMakeLists.txt ├── buffer │ ├── buffer_pool_manager_instance.cpp │ ├── clock_replacer.cpp │ ├── lru_replacer.cpp │ └── parallel_buffer_pool_manager.cpp ├── catalog │ ├── column.cpp │ ├── schema.cpp │ └── table_generator.cpp ├── common │ ├── config.cpp │ └── util │ │ └── string_util.cpp ├── concurrency │ ├── lock_manager.cpp │ └── transaction_manager.cpp ├── container │ └── hash │ │ ├── extendible_hash_table.cpp │ │ └── linear_probe_hash_table.cpp ├── execution │ ├── aggregation_executor.cpp │ ├── delete_executor.cpp │ ├── distinct_executor.cpp │ ├── executor_factory.cpp │ ├── hash_join_executor.cpp │ ├── index_scan_executor.cpp │ ├── insert_executor.cpp │ ├── limit_executor.cpp │ ├── nested_index_join_executor.cpp │ ├── nested_loop_join_executor.cpp │ ├── seq_scan_executor.cpp │ └── update_executor.cpp ├── include │ ├── buffer │ │ ├── buffer_pool_manager.h │ │ ├── buffer_pool_manager_instance.h │ │ ├── clock_replacer.h │ │ ├── lru_replacer.h │ │ ├── parallel_buffer_pool_manager.h │ │ └── replacer.h │ ├── catalog │ │ ├── catalog.h │ │ ├── column.h │ │ ├── schema.h │ │ └── table_generator.h │ ├── common │ │ ├── bustub_instance.h │ │ ├── config.h │ │ ├── exception.h │ │ ├── logger.h │ │ ├── macros.h │ │ ├── rid.h │ │ ├── rwlatch.h │ │ └── util │ │ │ ├── hash_util.h │ │ │ └── string_util.h │ ├── concurrency │ │ ├── lock_manager.h │ │ ├── transaction.h │ │ └── transaction_manager.h │ ├── container │ │ └── hash │ │ │ ├── extendible_hash_table.h │ │ │ ├── hash_function.h │ │ │ ├── hash_table.h │ │ │ └── linear_probe_hash_table.h │ ├── execution │ │ ├── execution_engine.h │ │ ├── executor_context.h │ │ ├── executor_factory.h │ │ ├── executors │ │ │ ├── abstract_executor.h │ │ │ ├── aggregation_executor.h │ │ │ ├── delete_executor.h │ │ │ ├── distinct_executor.h │ │ │ ├── hash_join_executor.h │ │ │ ├── index_scan_executor.h │ │ │ ├── insert_executor.h │ │ │ ├── limit_executor.h │ │ │ ├── nested_index_join_executor.h │ │ │ ├── nested_loop_join_executor.h │ │ │ ├── seq_scan_executor.h │ │ │ └── update_executor.h │ │ ├── expressions │ │ │ ├── abstract_expression.h │ │ │ ├── aggregate_value_expression.h │ │ │ ├── column_value_expression.h │ │ │ ├── comparison_expression.h │ │ │ └── constant_value_expression.h │ │ └── plans │ │ │ ├── abstract_plan.h │ │ │ ├── aggregation_plan.h │ │ │ ├── delete_plan.h │ │ │ ├── distinct_plan.h │ │ │ ├── hash_join_plan.h │ │ │ ├── index_scan_plan.h │ │ │ ├── insert_plan.h │ │ │ ├── limit_plan.h │ │ │ ├── nested_index_join_plan.h │ │ │ ├── nested_loop_join_plan.h │ │ │ ├── seq_scan_plan.h │ │ │ └── update_plan.h │ ├── primer │ │ └── p0_starter.h │ ├── recovery │ │ ├── checkpoint_manager.h │ │ ├── log_manager.h │ │ ├── log_record.h │ │ └── log_recovery.h │ ├── storage │ │ ├── disk │ │ │ └── disk_manager.h │ │ ├── index │ │ │ ├── b_plus_tree.h │ │ │ ├── b_plus_tree_index.h │ │ │ ├── extendible_hash_table_index.h │ │ │ ├── generic_key.h │ │ │ ├── hash_comparator.h │ │ │ ├── index.h │ │ │ ├── index_iterator.h │ │ │ ├── int_comparator.h │ │ │ └── linear_probe_hash_table_index.h │ │ ├── page │ │ │ ├── b_plus_tree_internal_page.h │ │ │ ├── b_plus_tree_leaf_page.h │ │ │ ├── b_plus_tree_page.h │ │ │ ├── hash_table_block_page.h │ │ │ ├── hash_table_bucket_page.h │ │ │ ├── hash_table_directory_page.h │ │ │ ├── hash_table_header_page.h │ │ │ ├── hash_table_page_defs.h │ │ │ ├── header_page.h │ │ │ ├── page.h │ │ │ ├── table_page.h │ │ │ └── tmp_tuple_page.h │ │ └── table │ │ │ ├── table_heap.h │ │ │ ├── table_iterator.h │ │ │ ├── tmp_tuple.h │ │ │ └── tuple.h │ └── type │ │ ├── abstract_pool.h │ │ ├── bigint_type.h │ │ ├── boolean_type.h │ │ ├── decimal_type.h │ │ ├── integer_parent_type.h │ │ ├── integer_type.h │ │ ├── limits.h │ │ ├── numeric_type.h │ │ ├── smallint_type.h │ │ ├── timestamp_type.h │ │ ├── tinyint_type.h │ │ ├── type.h │ │ ├── type_id.h │ │ ├── type_util.h │ │ ├── value.h │ │ ├── value_factory.h │ │ └── varlen_type.h ├── recovery │ ├── checkpoint_manager.cpp │ ├── log_manager.cpp │ └── log_recovery.cpp ├── storage │ ├── disk │ │ └── disk_manager.cpp │ ├── index │ │ ├── b_plus_tree.cpp │ │ ├── b_plus_tree_index.cpp │ │ ├── extendible_hash_table_index.cpp │ │ ├── index_iterator.cpp │ │ └── linear_probe_hash_table_index.cpp │ ├── page │ │ ├── b_plus_tree_internal_page.cpp │ │ ├── b_plus_tree_leaf_page.cpp │ │ ├── b_plus_tree_page.cpp │ │ ├── hash_table_block_page.cpp │ │ ├── hash_table_bucket_page.cpp │ │ ├── hash_table_directory_page.cpp │ │ ├── hash_table_header_page.cpp │ │ ├── header_page.cpp │ │ └── table_page.cpp │ └── table │ │ ├── table_heap.cpp │ │ ├── table_iterator.cpp │ │ └── tuple.cpp └── type │ ├── bigint_type.cpp │ ├── boolean_type.cpp │ ├── decimal_type.cpp │ ├── integer_parent_type.cpp │ ├── integer_type.cpp │ ├── smallint_type.cpp │ ├── timestamp_type.cpp │ ├── tinyint_type.cpp │ ├── type.cpp │ ├── value.cpp │ └── varlen_type.cpp ├── test ├── CMakeLists.txt ├── buffer │ ├── buffer_pool_manager_instance_test.cpp │ ├── clock_replacer_test.cpp │ ├── counter.h │ ├── lru_replacer_test.cpp │ ├── mock_buffer_pool_manager.h │ └── parallel_buffer_pool_manager_test.cpp ├── catalog │ └── catalog_test.cpp ├── common │ └── rwlatch_test.cpp ├── concurrency │ ├── lock_manager_test.cpp │ └── transaction_test.cpp ├── container │ ├── hash_table_page_test.cpp │ └── hash_table_test.cpp ├── execution │ ├── executor_test.cpp │ └── executor_test_util.h ├── include │ ├── logging │ │ └── common.h │ └── test_util.h ├── primer │ └── starter_test.cpp ├── recovery │ └── recovery_test.cpp ├── storage │ ├── b_plus_tree_concurrent_test.cpp │ ├── b_plus_tree_delete_test.cpp │ ├── b_plus_tree_insert_test.cpp │ ├── b_plus_tree_print_test.cpp │ ├── disk_manager_test.cpp │ └── tmp_tuple_page_test.cpp ├── table │ └── tuple_test.cpp └── type │ └── type_test.cpp └── third_party ├── .clang-tidy ├── murmur3 ├── MurmurHash3.cpp └── MurmurHash3.h └── versions.txt /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build_test: 4 | docker: 5 | - image: ubuntu:18.04 6 | steps: 7 | # install dependencies 8 | # TODO (Chenyao): I'm not sure which packages are useful. Trim unused packages to speed up. 9 | - run: apt-get -y update && 10 | apt-get -y install 11 | build-essential 12 | clang-8 13 | clang-format-8 14 | clang-tidy-8 15 | cmake 16 | doxygen 17 | git 18 | g++-7 19 | libjemalloc-dev 20 | llvm-8 21 | pkg-config 22 | valgrind 23 | - checkout 24 | - run: mkdir build 25 | - run: cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. 26 | # 2020-12-01: We only want to buid with 2 cores to prevent us from running out of memory 27 | - run: cd build && make -j 2 28 | - run: cd build && make check-lint 29 | - run: cd build && make check-clang-tidy 30 | - run: cd build && make check-tests 31 | 32 | workflows: 33 | version: 2 34 | workflow: 35 | jobs: 36 | - build_test 37 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | DerivePointerAlignment: false 3 | PointerAlignment: Right 4 | ColumnLimit: 120 5 | 6 | # Default for clang-8, changed in later clangs. Set explicitly for forwards 7 | # compatibility for students with modern clangs 8 | IncludeBlocks: Preserve 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Don't send any build context to Docker. 2 | ** -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | DO NOT PUSH PROJECT SOLUTIONS PUBLICLY. 2 | 3 | And especially do NOT open pull requests with project solutions! 4 | 5 | Please be considerate of this free educational resource. 6 | -------------------------------------------------------------------------------- /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake Build Matrix 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | BUILD_TYPE: Debug 11 | 12 | jobs: 13 | build: 14 | name: ${{ matrix.config.name }} 15 | runs-on: ${{ matrix.config.os }} 16 | 17 | strategy: 18 | fail-fast: true 19 | matrix: 20 | config: 21 | - { 22 | name: "Ubuntu Latest GCC", 23 | os: ubuntu-latest, 24 | cc: "/usr/bin/gcc", 25 | cxx: "/usr/bin/g++", 26 | format: "/usr/bin/clang-format-8", 27 | tidy: "/usr/bin/clang-tidy-8" 28 | } 29 | - { 30 | name: "Ubuntu Latest Clang", 31 | os: ubuntu-latest, 32 | cc: "/usr/bin/clang-8", 33 | cxx: "/usr/bin/clang++8", 34 | format: "/usr/bin/clang-format-8", 35 | tidy: "/usr/bin/clang-tidy-8" 36 | } 37 | - { 38 | name: "macOS Latest Clang", 39 | os: macos-latest, 40 | cc: "/usr/bin/clang", 41 | cxx: "/usr/bin/clang++", 42 | format: "/usr/local/opt/llvm@8/bin/clang-format", 43 | tidy: "/usr/local/opt/llvm@8/bin/clang-tidy" 44 | } 45 | 46 | steps: 47 | - uses: actions/checkout@v2 48 | 49 | - name: Print env 50 | run: | 51 | echo github.event.action: ${{ github.event.action }} 52 | echo github.event_name: ${{ github.event_name }} 53 | - name: Install Dependencies (Ubuntu) 54 | if: runner.os == 'Linux' 55 | working-directory: ${{github.workspace}} 56 | run: sudo bash ./build_support/packages.sh -y 57 | 58 | - name: Install Dependencies (OSX) 59 | if: runner.os == 'macOS' 60 | working-directory: ${{github.workspace}} 61 | run: bash ./build_support/packages.sh -y 62 | 63 | - name: Configure CMake 64 | run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCC=${{matrix.config.cc}} -DCXX=${{matrix.config.cxx}} -DCLANG_FORMAT_BIN=${{matrix.config.format}} -DCLANG_TIDY_BIN=${{matrix.config.tidy}} 65 | 66 | - name: Build 67 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} 68 | 69 | - name: Check Format 70 | working-directory: ${{github.workspace}}/build 71 | run: make check-format 72 | 73 | - name: Check Lint 74 | working-directory: ${{github.workspace}}/build 75 | run: make check-lint 76 | 77 | - name: Check Clang Tidy 78 | working-directory: ${{github.workspace}}/build 79 | run: make check-clang-tidy 80 | 81 | - name: Check Tests (Ubuntu) 82 | if: runner.os == 'Linux' 83 | working-directory: ${{github.workspace}}/build 84 | run: make check-tests 85 | 86 | - name: Check Tests (OSX) 87 | if: runner.os == 'macOS' 88 | working-directory: ${{github.workspace}}/build 89 | # Disable container overflow checks on OSX 90 | run: ASAN_OPTIONS=detect_container_overflow=0 make check-tests -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | CMD bash 3 | 4 | # Install Ubuntu packages. 5 | # Please add packages in alphabetical order. 6 | ARG DEBIAN_FRONTEND=noninteractive 7 | RUN apt-get -y update && \ 8 | apt-get -y install \ 9 | build-essential \ 10 | clang-8 \ 11 | clang-format-8 \ 12 | clang-tidy-8 \ 13 | cmake \ 14 | doxygen \ 15 | git \ 16 | g++-7 \ 17 | pkg-config \ 18 | valgrind \ 19 | zlib1g-dev 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 CMU Database Group 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby et: 3 | 4 | # Customize VM resources 5 | VM_CPUS = "4" 6 | VM_MEMORY = "2048" # MB 7 | VM_NAME = "BustubVM" 8 | 9 | Vagrant.configure(2) do |config| 10 | 11 | # Pick a box to use 12 | config.vm.box = "ubuntu/focal64" 13 | 14 | # Config VM 15 | config.vm.provider :virtualbox do |vb| 16 | vb.customize [ "modifyvm", :id, 17 | "--memory", VM_MEMORY, 18 | "--name", VM_NAME, 19 | "--nicspeed1", 1000000, 20 | "--nicspeed2", 1000000, 21 | "--ioapic", "on", 22 | "--cpus", VM_CPUS ] 23 | 24 | end 25 | 26 | # SSH 27 | config.ssh.forward_agent = true 28 | config.ssh.forward_x11 = true 29 | 30 | # Link current repo into VM 31 | config.vm.synced_folder "..", "/bustub" 32 | 33 | # Setup environment 34 | config.vm.provision :shell, :inline => "apt-get update" 35 | config.vm.provision "shell" do |s| 36 | s.path = "https://raw.githubusercontent.com/cmu-db/bustub/master/build_support/packages.sh" 37 | s.args = "-y" 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laotan0926/cmu15445/48216418bbf0d38836a619530c5eca29cde31f32/build_support/clang_format_exclusions.txt -------------------------------------------------------------------------------- /build_support/gtest_CMakeLists.txt.in: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | project(googletest-download NONE) 4 | 5 | include(ExternalProject) 6 | ExternalProject_Add(googletest 7 | GIT_REPOSITORY https://github.com/google/googletest.git 8 | GIT_TAG main 9 | SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" 10 | BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" 11 | CONFIGURE_COMMAND "" 12 | BUILD_COMMAND "" 13 | INSTALL_COMMAND "" 14 | TEST_COMMAND "" 15 | ) -------------------------------------------------------------------------------- /build_support/packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## ================================================================= 4 | ## BUSTUB PACKAGE INSTALLATION 5 | ## 6 | ## This script will install all the packages that are needed to 7 | ## build and run the DBMS. 8 | ## 9 | ## Supported environments: 10 | ## * Ubuntu 18.04 11 | ## * macOS 12 | ## ================================================================= 13 | 14 | main() { 15 | set -o errexit 16 | 17 | if [ $1 == "-y" ] 18 | then 19 | install 20 | else 21 | echo "PACKAGES WILL BE INSTALLED. THIS MAY BREAK YOUR EXISTING TOOLCHAIN." 22 | echo "YOU ACCEPT ALL RESPONSIBILITY BY PROCEEDING." 23 | read -p "Proceed? [Y/n] : " yn 24 | 25 | case $yn in 26 | Y|y) install;; 27 | *) ;; 28 | esac 29 | fi 30 | 31 | echo "Script complete." 32 | } 33 | 34 | install() { 35 | set -x 36 | UNAME=$(uname | tr "[:lower:]" "[:upper:]" ) 37 | 38 | case $UNAME in 39 | DARWIN) install_mac ;; 40 | 41 | LINUX) 42 | version=$(cat /etc/os-release | grep VERSION_ID | cut -d '"' -f 2) 43 | case $version in 44 | 18.04) install_linux ;; 45 | 20.04) install_linux ;; 46 | *) give_up ;; 47 | esac 48 | ;; 49 | 50 | *) give_up ;; 51 | esac 52 | } 53 | 54 | give_up() { 55 | set +x 56 | echo "Unsupported distribution '$UNAME'" 57 | echo "Please contact our support team for additional help." 58 | echo "Be sure to include the contents of this message." 59 | echo "Platform: $(uname -a)" 60 | echo 61 | echo "https://github.com/cmu-db/bustub/issues" 62 | echo 63 | exit 1 64 | } 65 | 66 | install_mac() { 67 | # Install Homebrew. 68 | if test ! $(which brew); then 69 | echo "Installing Homebrew (https://brew.sh/)" 70 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 71 | fi 72 | # Update Homebrew. 73 | brew update 74 | # Install packages. 75 | brew ls --versions cmake || brew install cmake 76 | brew ls --versions coreutils || brew install coreutils 77 | brew ls --versions doxygen || brew install doxygen 78 | brew ls --versions git || brew install git 79 | (brew ls --versions llvm | grep 8) || brew install llvm@8 80 | } 81 | 82 | install_linux() { 83 | # Update apt-get. 84 | apt-get -y update 85 | # Install packages. 86 | apt-get -y install \ 87 | build-essential \ 88 | clang-8 \ 89 | clang-format-8 \ 90 | clang-tidy-8 \ 91 | cmake \ 92 | doxygen \ 93 | git \ 94 | g++-7 \ 95 | pkg-config \ 96 | valgrind \ 97 | zlib1g-dev 98 | } 99 | 100 | main "$@" 101 | -------------------------------------------------------------------------------- /build_support/run_clang_tidy_extra.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | A helper class, to suppress execution of clang-tidy. 5 | 6 | In clang-tidy-6.0, if the clang-tidy configuration file suppresses ALL checks, 7 | (e.g. via a .clang-tidy file), clang-tidy will print usage information and 8 | exit with a return code of 0. Harmless but verbose. In later versions of 9 | clang-tidy the return code becomes 1, making this a bigger problem. 10 | 11 | This helper addresses the problem by suppressing execution according to 12 | the configuration in this file. 13 | """ 14 | 15 | import re 16 | 17 | class CheckConfig(object): 18 | """ Check paths against the built-in config """ 19 | 20 | def __init__(self): 21 | self._init_config() 22 | # debug prints 23 | self.debug = False 24 | return 25 | 26 | def _init_config(self): 27 | """ Any path matching one of the ignore_pats regular expressions, 28 | denotes that we do NOT want to run clang-tidy on that item. 29 | """ 30 | self.ignore_pats = [".*/third_party/.*", ] 31 | return 32 | 33 | def should_skip(self, path): 34 | """ Should execution of clang-tidy be skipped? 35 | path - to check, against the configuration. 36 | Typically the full path. 37 | returns - False if we want to run clang-tidy 38 | True of we want to skip execution on this item 39 | """ 40 | for pat in self.ignore_pats: 41 | if re.match(pat, path): 42 | if self.debug: 43 | print("match pat: {}, {} => don't run".format(pat, path)) 44 | return True 45 | return False 46 | 47 | -------------------------------------------------------------------------------- /build_support/valgrind.supp: -------------------------------------------------------------------------------- 1 | { 2 | Handle GFLAGS leaks - Debug mode 3 | Memcheck:Leak 4 | ... 5 | fun:_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag 6 | fun:_ZNSsC1EPKcRKSaIcE 7 | fun:_ZN3fLS25dont_pass0toDEFINE_stringEPcPKc 8 | ... 9 | } 10 | 11 | { 12 | Handle GFLAGS leaks - Release mode 13 | Memcheck:Leak 14 | ... 15 | fun:_ZNSsC1EPKcRKSaIcE 16 | fun:_GLOBAL__sub_I_config.cpp 17 | ... 18 | } 19 | 20 | { 21 | Handle init leak (32 bytes) 22 | Memcheck:Leak 23 | ... 24 | fun:_GLOBAL__sub_I_configuration.cpp 25 | fun:call_init.part.0 26 | fun:call_init 27 | fun:_dl_init 28 | ... 29 | } 30 | 31 | { 32 | Handles invalid free in NetworkAddress::Parse because of 'getaddrinfo' 33 | Memcheck:Free 34 | fun:free 35 | fun:__libc_freeres 36 | fun:_vgnU_freeres 37 | fun:__run_exit_handlers 38 | fun:exit 39 | fun:(below main) 40 | } 41 | 42 | { 43 | Handles leaks in libpg_query 44 | Memcheck:Leak 45 | match-leak-kinds: definite 46 | ... 47 | fun:AllocSetContextCreate 48 | fun:MemoryContextInit 49 | fun:pg_query_init 50 | fun:pg_query_enter_memory_context 51 | ... 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This is hacky :( 2 | file(GLOB_RECURSE bustub_sources ${PROJECT_SOURCE_DIR}/src/*/*.cpp ${PROJECT_SOURCE_DIR}/src/*/*/*.cpp) 3 | add_library(bustub_shared SHARED ${bustub_sources}) 4 | 5 | ###################################################################################################################### 6 | # THIRD-PARTY SOURCES 7 | ###################################################################################################################### 8 | 9 | # murmur3 10 | file(GLOB_RECURSE murmur3_sources 11 | ${PROJECT_SOURCE_DIR}/third_party/murmur3/*.cpp ${PROJECT_SOURCE_DIR}/third_party/murmur3/*.h) 12 | add_library(thirdparty_murmur3 SHARED ${murmur3_sources}) 13 | target_link_libraries(bustub_shared thirdparty_murmur3) -------------------------------------------------------------------------------- /src/buffer/clock_replacer.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // clock_replacer.cpp 6 | // 7 | // Identification: src/buffer/clock_replacer.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "buffer/clock_replacer.h" 14 | 15 | namespace bustub { 16 | 17 | ClockReplacer::ClockReplacer(size_t num_pages) {} 18 | 19 | ClockReplacer::~ClockReplacer() = default; 20 | 21 | bool ClockReplacer::Victim(frame_id_t *frame_id) { return false; } 22 | 23 | void ClockReplacer::Pin(frame_id_t frame_id) {} 24 | 25 | void ClockReplacer::Unpin(frame_id_t frame_id) {} 26 | 27 | size_t ClockReplacer::Size() { return 0; } 28 | 29 | } // namespace bustub 30 | -------------------------------------------------------------------------------- /src/buffer/lru_replacer.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // lru_replacer.cpp 6 | // 7 | // Identification: src/buffer/lru_replacer.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "buffer/lru_replacer.h" 14 | 15 | namespace bustub { 16 | 17 | LRUReplacer::LRUReplacer(size_t num_pages) {} 18 | 19 | LRUReplacer::~LRUReplacer() = default; 20 | 21 | bool LRUReplacer::Victim(frame_id_t *frame_id) { 22 | std::lock_guard lock(mutex_); 23 | if(lru_list_.empty()){ 24 | *frame_id = INVALID_PAGE_ID; 25 | return false; 26 | } 27 | *frame_id = lru_list_.back(); 28 | lru_list_.pop_back(); 29 | lru_map_.erase(*frame_id); 30 | return true; 31 | } 32 | 33 | void LRUReplacer::Pin(frame_id_t frame_id) { 34 | std::lock_guard lock(mutex_); 35 | auto iterator = lru_map_.find(frame_id); 36 | if(iterator!=lru_map_.end()){ 37 | lru_list_.erase(iterator->second); 38 | lru_map_.erase(frame_id); 39 | } 40 | } 41 | 42 | void LRUReplacer::Unpin(frame_id_t frame_id) { 43 | std::lock_guard lock(mutex_); 44 | auto iterator = lru_map_.find(frame_id); 45 | if(iterator==lru_map_.end()){ 46 | lru_list_.push_front(frame_id); 47 | lru_map_.emplace(frame_id,lru_list_.begin()); 48 | } 49 | } 50 | 51 | size_t LRUReplacer::Size() { 52 | std::lock_guard lock(mutex_); 53 | return lru_list_.size(); 54 | } 55 | 56 | } // namespace bustub 57 | -------------------------------------------------------------------------------- /src/catalog/column.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // column.cpp 6 | // 7 | // Identification: src/catalog/column.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "catalog/column.h" 14 | 15 | #include 16 | #include 17 | 18 | namespace bustub { 19 | 20 | std::string Column::ToString() const { 21 | std::ostringstream os; 22 | 23 | os << "Column[" << column_name_ << ", " << Type::TypeIdToString(column_type_) << ", " 24 | << "Offset:" << column_offset_ << ", "; 25 | 26 | if (IsInlined()) { 27 | os << "FixedLength:" << fixed_length_; 28 | } else { 29 | os << "VarLength:" << variable_length_; 30 | } 31 | os << "]"; 32 | return (os.str()); 33 | } 34 | 35 | } // namespace bustub 36 | -------------------------------------------------------------------------------- /src/catalog/schema.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // schema.cpp 6 | // 7 | // Identification: src/catalog/schema.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "catalog/schema.h" 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | namespace bustub { 20 | 21 | Schema::Schema(const std::vector &columns) : tuple_is_inlined_(true) { 22 | uint32_t curr_offset = 0; 23 | for (uint32_t index = 0; index < columns.size(); index++) { 24 | Column column = columns[index]; 25 | // handle uninlined column 26 | if (!column.IsInlined()) { 27 | tuple_is_inlined_ = false; 28 | uninlined_columns_.push_back(index); 29 | } 30 | // set column offset 31 | column.column_offset_ = curr_offset; 32 | curr_offset += column.GetFixedLength(); 33 | 34 | // add column 35 | this->columns_.push_back(column); 36 | } 37 | // set tuple length 38 | length_ = curr_offset; 39 | } 40 | 41 | std::string Schema::ToString() const { 42 | std::ostringstream os; 43 | 44 | os << "Schema[" 45 | << "NumColumns:" << GetColumnCount() << ", " 46 | << "IsInlined:" << tuple_is_inlined_ << ", " 47 | << "Length:" << length_ << "]"; 48 | 49 | bool first = true; 50 | os << " :: ("; 51 | for (uint32_t i = 0; i < GetColumnCount(); i++) { 52 | if (first) { 53 | first = false; 54 | } else { 55 | os << ", "; 56 | } 57 | os << columns_[i].ToString(); 58 | } 59 | os << ")"; 60 | 61 | return os.str(); 62 | } 63 | 64 | } // namespace bustub 65 | -------------------------------------------------------------------------------- /src/common/config.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // config.cpp 6 | // 7 | // Identification: src/common/config.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "common/config.h" 14 | 15 | namespace bustub { 16 | 17 | std::atomic enable_logging(false); 18 | 19 | std::chrono::duration log_timeout = std::chrono::seconds(1); 20 | 21 | std::chrono::milliseconds cycle_detection_interval = std::chrono::milliseconds(50); 22 | 23 | } // namespace bustub 24 | -------------------------------------------------------------------------------- /src/concurrency/lock_manager.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // lock_manager.cpp 6 | // 7 | // Identification: src/concurrency/lock_manager.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "concurrency/lock_manager.h" 14 | 15 | #include 16 | #include 17 | 18 | namespace bustub { 19 | 20 | bool LockManager::LockShared(Transaction *txn, const RID &rid) { 21 | txn->GetSharedLockSet()->emplace(rid); 22 | return true; 23 | } 24 | 25 | bool LockManager::LockExclusive(Transaction *txn, const RID &rid) { 26 | txn->GetExclusiveLockSet()->emplace(rid); 27 | return true; 28 | } 29 | 30 | bool LockManager::LockUpgrade(Transaction *txn, const RID &rid) { 31 | txn->GetSharedLockSet()->erase(rid); 32 | txn->GetExclusiveLockSet()->emplace(rid); 33 | return true; 34 | } 35 | 36 | bool LockManager::Unlock(Transaction *txn, const RID &rid) { 37 | txn->GetSharedLockSet()->erase(rid); 38 | txn->GetExclusiveLockSet()->erase(rid); 39 | return true; 40 | } 41 | 42 | } // namespace bustub 43 | -------------------------------------------------------------------------------- /src/execution/aggregation_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // aggregation_executor.cpp 6 | // 7 | // Identification: src/execution/aggregation_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include 13 | #include 14 | 15 | #include "execution/executors/aggregation_executor.h" 16 | 17 | namespace bustub { 18 | 19 | AggregationExecutor::AggregationExecutor(ExecutorContext *exec_ctx, const AggregationPlanNode *plan, 20 | std::unique_ptr &&child) 21 | : AbstractExecutor(exec_ctx) 22 | , plan_(plan) 23 | , child_(std::move(child)) 24 | , aht_(plan_->GetAggregates(),plan_->GetAggregateTypes()) 25 | , aht_iterator_(aht_.Begin()) {} 26 | 27 | void AggregationExecutor::Init() { 28 | child_->Init(); 29 | Tuple tuple; 30 | RID rid; 31 | bool is_group_by = !plan_->GetGroupBys().empty(); 32 | auto group_bys = plan_->GetGroupBys(); 33 | auto aggr_exprs = plan_->GetAggregates(); 34 | std::vector keys; 35 | keys.reserve(group_bys.size()); 36 | std::vector vals; 37 | vals.reserve(aggr_exprs.size()); 38 | 39 | while(child_->Next(&tuple, &rid)){ 40 | keys.clear(); 41 | if(is_group_by){ 42 | for(auto &group_by: group_bys){ 43 | keys.emplace_back(group_by->Evaluate(&tuple,child_->GetOutputSchema())); 44 | } 45 | } 46 | vals.clear(); 47 | for(auto &aggr_expr: aggr_exprs){ 48 | vals.emplace_back(aggr_expr->Evaluate(&tuple,child_->GetOutputSchema())); 49 | } 50 | aht_.InsertCombine(AggregateKey{keys},AggregateValue{vals}); 51 | } 52 | aht_iterator_ = aht_.Begin(); 53 | } 54 | 55 | bool AggregationExecutor::Next(Tuple *tuple, RID *rid) { 56 | std::vector group_bys; 57 | std::vector aggregates; 58 | do{ 59 | if(aht_iterator_== aht_.End()){ 60 | return false; 61 | } 62 | group_bys = aht_iterator_.Key().group_bys_; 63 | aggregates = aht_iterator_.Val().aggregates_; 64 | ++aht_iterator_; 65 | }while(plan_->GetHaving()!=nullptr && 66 | !plan_->GetHaving()->EvaluateAggregate(group_bys,aggregates).GetAs()); 67 | // 生成输出元组 68 | std::vector values; 69 | size_t column_count = plan_->OutputSchema()->GetColumnCount(); 70 | for(size_t i = 0 ;iOutputSchema()->GetColumn(i).GetExpr(); 72 | values.emplace_back(col_expr->EvaluateAggregate(group_bys, aggregates)); 73 | } 74 | *tuple = Tuple{values, plan_->OutputSchema()}; 75 | return true; 76 | } 77 | 78 | const AbstractExecutor *AggregationExecutor::GetChildExecutor() const { return child_.get(); } 79 | 80 | } // namespace bustub 81 | -------------------------------------------------------------------------------- /src/execution/delete_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // delete_executor.cpp 6 | // 7 | // Identification: src/execution/delete_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "execution/executors/delete_executor.h" 16 | 17 | namespace bustub { 18 | 19 | DeleteExecutor::DeleteExecutor(ExecutorContext *exec_ctx, const DeletePlanNode *plan, 20 | std::unique_ptr &&child_executor) 21 | : AbstractExecutor(exec_ctx) 22 | ,plan_(plan) 23 | ,child_executor_(std::move(child_executor)){ 24 | table_infos_ = exec_ctx_->GetCatalog()->GetTable(plan_->TableOid()); 25 | table_indexs_ = exec_ctx_->GetCatalog()->GetTableIndexes(table_infos_->name_); 26 | } 27 | 28 | void DeleteExecutor::Init() { 29 | child_executor_->Init(); 30 | } 31 | 32 | bool DeleteExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { 33 | if(!child_executor_->Next(tuple,rid)){ 34 | return false; 35 | } 36 | //删除 37 | table_infos_->table_->MarkDelete(*rid,exec_ctx_->GetTransaction()); 38 | // 删索引 39 | for (auto &table_index :table_indexs_){ 40 | auto key_tuple = tuple->KeyFromTuple(table_infos_->schema_, table_index->key_schema_, table_index->index_->GetKeyAttrs()); 41 | table_index->index_->DeleteEntry(key_tuple,*rid,exec_ctx_->GetTransaction()); 42 | } 43 | return true; 44 | } 45 | 46 | } // namespace bustub 47 | -------------------------------------------------------------------------------- /src/execution/distinct_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // distinct_executor.cpp 6 | // 7 | // Identification: src/execution/distinct_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "execution/executors/distinct_executor.h" 14 | 15 | namespace bustub { 16 | 17 | DistinctExecutor::DistinctExecutor(ExecutorContext *exec_ctx, const DistinctPlanNode *plan, 18 | std::unique_ptr &&child_executor) 19 | : AbstractExecutor(exec_ctx) 20 | , plan_(plan) 21 | , child_executor_(std::move(child_executor)) {} 22 | 23 | void DistinctExecutor::Init() { 24 | child_executor_->Init(); 25 | hash_map_.clear(); 26 | } 27 | 28 | bool DistinctExecutor::Next(Tuple *tuple, RID *rid) { 29 | while(child_executor_->Next(tuple,rid) ){ 30 | if(!hash_map_.count(MakeDistinctKey(tuple,child_executor_->GetOutputSchema())) ){ 31 | hash_map_.insert({MakeDistinctKey(tuple,child_executor_->GetOutputSchema()), MakeDistinctValue(tuple,child_executor_->GetOutputSchema()) }); 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | } // namespace bustub 39 | -------------------------------------------------------------------------------- /src/execution/index_scan_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // index_scan_executor.cpp 6 | // 7 | // Identification: src/execution/index_scan_executor.cpp 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include "execution/executors/index_scan_executor.h" 13 | 14 | namespace bustub { 15 | IndexScanExecutor::IndexScanExecutor(ExecutorContext *exec_ctx, const IndexScanPlanNode *plan) 16 | : AbstractExecutor(exec_ctx) {} 17 | 18 | void IndexScanExecutor::Init() {} 19 | 20 | bool IndexScanExecutor::Next(Tuple *tuple, RID *rid) { return false; } 21 | 22 | } // namespace bustub 23 | -------------------------------------------------------------------------------- /src/execution/insert_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // insert_executor.cpp 6 | // 7 | // Identification: src/execution/insert_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "execution/executors/insert_executor.h" 16 | 17 | namespace bustub { 18 | 19 | InsertExecutor::InsertExecutor(ExecutorContext *exec_ctx, const InsertPlanNode *plan, 20 | std::unique_ptr &&child_executor) 21 | : AbstractExecutor(exec_ctx), 22 | plan_(plan), 23 | child_executor_(std::move(child_executor)) { 24 | table_info_ = exec_ctx_->GetCatalog()->GetTable(plan_->TableOid()); 25 | table_indexs_ = exec_ctx_->GetCatalog()->GetTableIndexes(table_info_->name_); 26 | } 27 | 28 | void InsertExecutor::Init() { 29 | if(child_executor_!=nullptr){ 30 | child_executor_->Init(); 31 | } 32 | } 33 | 34 | bool InsertExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { 35 | bool isinserted = true; 36 | 37 | if(plan_->IsRawInsert()){ 38 | if(insert_next_>=plan_->RawValues().size()){ 39 | return false; 40 | }else{ 41 | const std::vector &raw_val = plan_->RawValuesAt(insert_next_); 42 | *tuple = Tuple(raw_val, &table_info_->schema_); 43 | ++insert_next_; 44 | } 45 | }else{ 46 | if(!child_executor_->Next(tuple,rid)){ 47 | return false; 48 | } 49 | } 50 | isinserted = table_info_->table_->InsertTuple(*tuple,rid,exec_ctx_->GetTransaction()); 51 | // 索引插入 52 | if(isinserted){ 53 | for(auto &table_index: table_indexs_){ 54 | auto key_index = tuple->KeyFromTuple(table_info_->schema_,table_index->key_schema_, table_index->index_->GetKeyAttrs()); 55 | table_index->index_->InsertEntry( key_index, *rid, exec_ctx_->GetTransaction()); 56 | } 57 | } 58 | return isinserted; 59 | } 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/execution/limit_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // limit_executor.cpp 6 | // 7 | // Identification: src/execution/limit_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "execution/executors/limit_executor.h" 14 | 15 | namespace bustub { 16 | 17 | LimitExecutor::LimitExecutor(ExecutorContext *exec_ctx, const LimitPlanNode *plan, 18 | std::unique_ptr &&child_executor) 19 | : AbstractExecutor(exec_ctx) 20 | , plan_(plan) 21 | , child_executor_(std::move(child_executor)) {} 22 | 23 | void LimitExecutor::Init() { 24 | child_executor_->Init(); 25 | limit_ = 0; 26 | } 27 | 28 | bool LimitExecutor::Next(Tuple *tuple, RID *rid) { 29 | while(limit_ GetLimit()&&child_executor_->Next(tuple,rid)){ 30 | limit_++; 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | } // namespace bustub 37 | -------------------------------------------------------------------------------- /src/execution/nested_index_join_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_index_join_executor.cpp 6 | // 7 | // Identification: src/execution/nested_index_join_executor.cpp 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "execution/executors/nested_index_join_executor.h" 14 | 15 | namespace bustub { 16 | 17 | NestIndexJoinExecutor::NestIndexJoinExecutor(ExecutorContext *exec_ctx, const NestedIndexJoinPlanNode *plan, 18 | std::unique_ptr &&child_executor) 19 | : AbstractExecutor(exec_ctx) {} 20 | 21 | void NestIndexJoinExecutor::Init() {} 22 | 23 | bool NestIndexJoinExecutor::Next(Tuple *tuple, RID *rid) { return false; } 24 | 25 | } // namespace bustub 26 | -------------------------------------------------------------------------------- /src/execution/nested_loop_join_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_loop_join_executor.cpp 6 | // 7 | // Identification: src/execution/nested_loop_join_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "execution/executors/nested_loop_join_executor.h" 14 | 15 | namespace bustub { 16 | 17 | NestedLoopJoinExecutor::NestedLoopJoinExecutor(ExecutorContext *exec_ctx, const NestedLoopJoinPlanNode *plan, 18 | std::unique_ptr &&left_executor, 19 | std::unique_ptr &&right_executor) 20 | : AbstractExecutor(exec_ctx) 21 | ,plan_(plan) 22 | ,left_executor_(std::move(left_executor)) 23 | ,right_executor_(std::move(right_executor)){} 24 | 25 | void NestedLoopJoinExecutor::Init() { 26 | left_executor_->Init(); 27 | right_executor_->Init(); 28 | } 29 | 30 | bool NestedLoopJoinExecutor::Next(Tuple *tuple, RID *rid) { 31 | RID left_rid, right_rid; 32 | //初始left_rid 33 | if(left_tuple_.GetLength()==0&&!left_executor_->Next(&left_tuple_,&left_rid)){ 34 | return false; 35 | } 36 | 37 | do{ 38 | if(!right_executor_->Next(&right_tuple_,&right_rid)){ 39 | if(!left_executor_->Next(&left_tuple_,&left_rid)){ 40 | return false; 41 | } 42 | right_executor_->Init(); 43 | if(!right_executor_->Next(&right_tuple_,&right_rid)){ 44 | return false; 45 | } 46 | } 47 | }while(plan_->Predicate()!=nullptr&&!plan_->Predicate()->EvaluateJoin( 48 | &left_tuple_, left_executor_->GetOutputSchema(), &right_tuple_,right_executor_->GetOutputSchema()).GetAs()); 49 | 50 | std::vector values; 51 | size_t out_schema_size = plan_->OutputSchema()->GetColumnCount(); 52 | values.reserve(out_schema_size); 53 | for (size_t i =0; i< out_schema_size;i++){ 54 | const AbstractExpression* col_expr = plan_->OutputSchema()->GetColumn(i).GetExpr(); 55 | values.emplace_back(col_expr->EvaluateJoin(&left_tuple_, left_executor_->GetOutputSchema(), &right_tuple_, 56 | right_executor_->GetOutputSchema())); 57 | } 58 | *tuple = Tuple(values, plan_->OutputSchema()); 59 | return true; 60 | } 61 | 62 | } // namespace bustub 63 | -------------------------------------------------------------------------------- /src/execution/seq_scan_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // seq_scan_executor.cpp 6 | // 7 | // Identification: src/execution/seq_scan_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "execution/executors/seq_scan_executor.h" 14 | 15 | namespace bustub { 16 | 17 | SeqScanExecutor::SeqScanExecutor(ExecutorContext *exec_ctx, const SeqScanPlanNode *plan) 18 | : AbstractExecutor(exec_ctx), 19 | plan_(plan), 20 | table_iterator_(exec_ctx->GetCatalog()->GetTable(plan->GetTableOid())->table_->Begin(exec_ctx_->GetTransaction())) {} 21 | 22 | void SeqScanExecutor::Init() { 23 | table_iterator_ = exec_ctx_->GetCatalog()->GetTable(plan_->GetTableOid())->table_->Begin(exec_ctx_->GetTransaction()); 24 | } 25 | 26 | bool SeqScanExecutor::Next(Tuple *tuple, RID *rid) { 27 | table_oid_t table_oid = plan_->GetTableOid(); 28 | TableInfo* table_info = exec_ctx_->GetCatalog()->GetTable(table_oid); 29 | Schema* table_schema = &table_info->schema_; 30 | const Schema *output_schema = plan_->OutputSchema(); 31 | 32 | uint32_t output_schema_col_count = output_schema->GetColumnCount(); 33 | const std::vector & output_cols = output_schema->GetColumns(); 34 | // predicate 35 | 36 | const AbstractExpression *predicate = plan_->GetPredicate(); 37 | 38 | TableHeap *table_heap = table_info->table_.get(); 39 | Tuple original_tuple; 40 | 41 | while (table_iterator_ != table_heap->End()) { 42 | original_tuple = *table_iterator_++; 43 | if ((predicate != nullptr) ? predicate->Evaluate(&original_tuple, table_schema).GetAs() : true) { 44 | // original tuple qualified, build output tuple 45 | std::vector output_values; 46 | output_values.reserve(output_schema_col_count); 47 | for (size_t i = 0; i < output_schema_col_count; i++) { 48 | output_values.emplace_back(output_cols[i].GetExpr()->Evaluate(&original_tuple, table_schema)); 49 | } 50 | assert(output_values.size() == output_schema_col_count); 51 | *tuple = Tuple(output_values, output_schema); 52 | *rid = original_tuple.GetRid(); 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | } // namespace bustub 59 | -------------------------------------------------------------------------------- /src/execution/update_executor.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // update_executor.cpp 6 | // 7 | // Identification: src/execution/update_executor.cpp 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include 13 | 14 | #include "execution/executors/update_executor.h" 15 | 16 | namespace bustub { 17 | 18 | UpdateExecutor::UpdateExecutor(ExecutorContext *exec_ctx, const UpdatePlanNode *plan, 19 | std::unique_ptr &&child_executor) 20 | : AbstractExecutor(exec_ctx), 21 | plan_(plan), 22 | child_executor_(std::move(child_executor)) { 23 | table_info_ = exec_ctx->GetCatalog()->GetTable(plan->TableOid()); 24 | table_indexs_ = exec_ctx_->GetCatalog()->GetTableIndexes(table_info_->name_); 25 | } 26 | 27 | void UpdateExecutor::Init() { 28 | child_executor_->Init(); 29 | } 30 | 31 | bool UpdateExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { 32 | Tuple old_tuple; 33 | if(!child_executor_->Next(&old_tuple,rid)){ 34 | return false; 35 | } 36 | //回表查询 37 | if(!table_info_->table_->GetTuple(*rid, &old_tuple, exec_ctx_->GetTransaction())){ 38 | return false; 39 | } 40 | //生成新 41 | *tuple = GenerateUpdatedTuple(old_tuple); 42 | 43 | bool isupdated = true; 44 | //插入 45 | isupdated = table_info_->table_->UpdateTuple(*tuple,*rid,exec_ctx_->GetTransaction()); 46 | //更改索引 47 | if(isupdated){ 48 | for(auto &table_index: table_indexs_){ 49 | auto key_old_tuple = old_tuple.KeyFromTuple(table_info_->schema_,table_index->key_schema_, table_index->index_->GetKeyAttrs()); 50 | table_index->index_->DeleteEntry(key_old_tuple, *rid, exec_ctx_->GetTransaction()); 51 | auto key_tuple = tuple->KeyFromTuple(table_info_->schema_,table_index->key_schema_, table_index->index_->GetKeyAttrs()); 52 | table_index->index_->InsertEntry(key_tuple, *rid, exec_ctx_->GetTransaction()); 53 | } 54 | } 55 | // 56 | return isupdated; 57 | } 58 | 59 | Tuple UpdateExecutor::GenerateUpdatedTuple(const Tuple &src_tuple) { 60 | const auto &update_attrs = plan_->GetUpdateAttr(); 61 | Schema schema = table_info_->schema_; 62 | uint32_t col_count = schema.GetColumnCount(); 63 | std::vector values; 64 | for (uint32_t idx = 0; idx < col_count; idx++) { 65 | if (update_attrs.find(idx) == update_attrs.cend()) { 66 | values.emplace_back(src_tuple.GetValue(&schema, idx)); 67 | } else { 68 | const UpdateInfo info = update_attrs.at(idx); 69 | Value val = src_tuple.GetValue(&schema, idx); 70 | switch (info.type_) { 71 | case UpdateType::Add: 72 | values.emplace_back(val.Add(ValueFactory::GetIntegerValue(info.update_val_))); 73 | break; 74 | case UpdateType::Set: 75 | values.emplace_back(ValueFactory::GetIntegerValue(info.update_val_)); 76 | break; 77 | } 78 | } 79 | } 80 | return Tuple{values, &schema}; 81 | } 82 | 83 | } // namespace bustub 84 | -------------------------------------------------------------------------------- /src/include/buffer/clock_replacer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // clock_replacer.h 6 | // 7 | // Identification: src/include/buffer/clock_replacer.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include 18 | 19 | #include "buffer/replacer.h" 20 | #include "common/config.h" 21 | 22 | namespace bustub { 23 | 24 | /** 25 | * ClockReplacer implements the clock replacement policy, which approximates the Least Recently Used policy. 26 | */ 27 | class ClockReplacer : public Replacer { 28 | public: 29 | /** 30 | * Create a new ClockReplacer. 31 | * @param num_pages the maximum number of pages the ClockReplacer will be required to store 32 | */ 33 | explicit ClockReplacer(size_t num_pages); 34 | 35 | /** 36 | * Destroys the ClockReplacer. 37 | */ 38 | ~ClockReplacer() override; 39 | 40 | bool Victim(frame_id_t *frame_id) override; 41 | 42 | void Pin(frame_id_t frame_id) override; 43 | 44 | void Unpin(frame_id_t frame_id) override; 45 | 46 | size_t Size() override; 47 | 48 | private: 49 | // TODO(student): implement me! 50 | }; 51 | 52 | } // namespace bustub 53 | -------------------------------------------------------------------------------- /src/include/buffer/lru_replacer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // lru_replacer.h 6 | // 7 | // Identification: src/include/buffer/lru_replacer.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include 18 | #include 19 | 20 | #include "buffer/replacer.h" 21 | #include "common/config.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * LRUReplacer implements the Least Recently Used replacement policy. 27 | */ 28 | class LRUReplacer : public Replacer { 29 | public: 30 | /** 31 | * Create a new LRUReplacer. 32 | * @param num_pages the maximum number of pages the LRUReplacer will be required to store 33 | */ 34 | explicit LRUReplacer(size_t num_pages); 35 | 36 | /** 37 | * Destroys the LRUReplacer. 38 | */ 39 | ~LRUReplacer() override; 40 | 41 | bool Victim(frame_id_t *frame_id) override; 42 | 43 | void Pin(frame_id_t frame_id) override; 44 | 45 | void Unpin(frame_id_t frame_id) override; 46 | 47 | size_t Size() override; 48 | 49 | private: 50 | // TODO(student): implement me! 51 | std::mutex mutex_; 52 | std::list lru_list_; 53 | std::unordered_map::iterator> lru_map_; 54 | }; 55 | 56 | } // namespace bustub 57 | -------------------------------------------------------------------------------- /src/include/buffer/replacer.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // replacer.h 6 | // 7 | // Identification: src/include/buffer/replacer.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "common/config.h" 16 | 17 | namespace bustub { 18 | 19 | /** 20 | * Replacer is an abstract class that tracks page usage. 21 | */ 22 | class Replacer { 23 | public: 24 | Replacer() = default; 25 | virtual ~Replacer() = default; 26 | 27 | /** 28 | * Remove the victim frame as defined by the replacement policy. 29 | * @param[out] frame_id id of frame that was removed, nullptr if no victim was found 30 | * @return true if a victim frame was found, false otherwise 31 | */ 32 | virtual bool Victim(frame_id_t *frame_id) = 0; 33 | 34 | /** 35 | * Pins a frame, indicating that it should not be victimized until it is unpinned. 36 | * @param frame_id the id of the frame to pin 37 | */ 38 | virtual void Pin(frame_id_t frame_id) = 0; 39 | 40 | /** 41 | * Unpins a frame, indicating that it can now be victimized. 42 | * @param frame_id the id of the frame to unpin 43 | */ 44 | virtual void Unpin(frame_id_t frame_id) = 0; 45 | 46 | /** @return the number of elements in the replacer that can be victimized */ 47 | virtual size_t Size() = 0; 48 | }; 49 | 50 | } // namespace bustub 51 | -------------------------------------------------------------------------------- /src/include/common/bustub_instance.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // bustub_instance.h 6 | // 7 | // Identification: src/include/common/bustub_instance.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "buffer/buffer_pool_manager_instance.h" 16 | #include "common/config.h" 17 | #include "concurrency/lock_manager.h" 18 | #include "recovery/checkpoint_manager.h" 19 | #include "recovery/log_manager.h" 20 | #include "storage/disk/disk_manager.h" 21 | 22 | namespace bustub { 23 | 24 | class BustubInstance { 25 | public: 26 | explicit BustubInstance(const std::string &db_file_name) { 27 | enable_logging = false; 28 | 29 | // storage related 30 | disk_manager_ = new DiskManager(db_file_name); 31 | 32 | // log related 33 | log_manager_ = new LogManager(disk_manager_); 34 | 35 | buffer_pool_manager_ = new BufferPoolManagerInstance(BUFFER_POOL_SIZE, disk_manager_, log_manager_); 36 | 37 | // txn related 38 | lock_manager_ = new LockManager(); 39 | transaction_manager_ = new TransactionManager(lock_manager_, log_manager_); 40 | 41 | // checkpoints 42 | checkpoint_manager_ = new CheckpointManager(transaction_manager_, log_manager_, buffer_pool_manager_); 43 | } 44 | 45 | ~BustubInstance() { 46 | if (enable_logging) { 47 | log_manager_->StopFlushThread(); 48 | } 49 | delete checkpoint_manager_; 50 | delete log_manager_; 51 | delete buffer_pool_manager_; 52 | delete lock_manager_; 53 | delete transaction_manager_; 54 | delete disk_manager_; 55 | } 56 | 57 | DiskManager *disk_manager_; 58 | BufferPoolManager *buffer_pool_manager_; 59 | LockManager *lock_manager_; 60 | TransactionManager *transaction_manager_; 61 | LogManager *log_manager_; 62 | CheckpointManager *checkpoint_manager_; 63 | }; 64 | 65 | } // namespace bustub 66 | -------------------------------------------------------------------------------- /src/include/common/config.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // config.h 6 | // 7 | // Identification: src/include/common/config.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include 18 | 19 | namespace bustub { 20 | 21 | /** Cycle detection is performed every CYCLE_DETECTION_INTERVAL milliseconds. */ 22 | extern std::chrono::milliseconds cycle_detection_interval; 23 | 24 | /** True if logging should be enabled, false otherwise. */ 25 | extern std::atomic enable_logging; 26 | 27 | /** If ENABLE_LOGGING is true, the log should be flushed to disk every LOG_TIMEOUT. */ 28 | extern std::chrono::duration log_timeout; 29 | 30 | static constexpr int INVALID_PAGE_ID = -1; // invalid page id 31 | static constexpr int INVALID_TXN_ID = -1; // invalid transaction id 32 | static constexpr int INVALID_LSN = -1; // invalid log sequence number 33 | static constexpr int HEADER_PAGE_ID = 0; // the header page id 34 | static constexpr int PAGE_SIZE = 4096; // size of a data page in byte 35 | static constexpr int BUFFER_POOL_SIZE = 10; // size of buffer pool 36 | static constexpr int LOG_BUFFER_SIZE = ((BUFFER_POOL_SIZE + 1) * PAGE_SIZE); // size of a log buffer in byte 37 | static constexpr int BUCKET_SIZE = 50; // size of extendible hash bucket 38 | 39 | using frame_id_t = int32_t; // frame id type 40 | using page_id_t = int32_t; // page id type 41 | using txn_id_t = int32_t; // transaction id type 42 | using lsn_t = int32_t; // log sequence number type 43 | using slot_offset_t = size_t; // slot offset type 44 | using oid_t = uint16_t; 45 | 46 | } // namespace bustub 47 | -------------------------------------------------------------------------------- /src/include/common/macros.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // macros.h 6 | // 7 | // Identification: src/include/common/macros.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | namespace bustub { 19 | 20 | #define BUSTUB_ASSERT(expr, message) assert((expr) && (message)) 21 | 22 | #define UNREACHABLE(message) throw std::logic_error(message) 23 | 24 | // Macros to disable copying and moving 25 | #define DISALLOW_COPY(cname) \ 26 | cname(const cname &) = delete; /* NOLINT */ \ 27 | cname &operator=(const cname &) = delete; /* NOLINT */ 28 | 29 | #define DISALLOW_MOVE(cname) \ 30 | cname(cname &&) = delete; /* NOLINT */ \ 31 | cname &operator=(cname &&) = delete; /* NOLINT */ 32 | 33 | #define DISALLOW_COPY_AND_MOVE(cname) \ 34 | DISALLOW_COPY(cname); \ 35 | DISALLOW_MOVE(cname); 36 | 37 | } // namespace bustub 38 | -------------------------------------------------------------------------------- /src/include/common/rid.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // rid.h 6 | // 7 | // Identification: src/include/common/rid.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "common/config.h" 20 | 21 | namespace bustub { 22 | 23 | class RID { 24 | public: 25 | /** The default constructor creates an invalid RID! */ 26 | RID() = default; 27 | 28 | /** 29 | * Creates a new Record Identifier for the given page identifier and slot number. 30 | * @param page_id page identifier 31 | * @param slot_num slot number 32 | */ 33 | RID(page_id_t page_id, uint32_t slot_num) : page_id_(page_id), slot_num_(slot_num) {} 34 | 35 | explicit RID(int64_t rid) : page_id_(static_cast(rid >> 32)), slot_num_(static_cast(rid)) {} 36 | 37 | inline int64_t Get() const { return (static_cast(page_id_)) << 32 | slot_num_; } 38 | 39 | inline page_id_t GetPageId() const { return page_id_; } 40 | 41 | inline uint32_t GetSlotNum() const { return slot_num_; } 42 | 43 | inline void Set(page_id_t page_id, uint32_t slot_num) { 44 | page_id_ = page_id; 45 | slot_num_ = slot_num; 46 | } 47 | 48 | inline std::string ToString() const { 49 | std::stringstream os; 50 | os << "page_id: " << page_id_; 51 | os << " slot_num: " << slot_num_ << "\n"; 52 | 53 | return os.str(); 54 | } 55 | 56 | friend std::ostream &operator<<(std::ostream &os, const RID &rid) { 57 | os << rid.ToString(); 58 | return os; 59 | } 60 | 61 | bool operator==(const RID &other) const { return page_id_ == other.page_id_ && slot_num_ == other.slot_num_; } 62 | 63 | private: 64 | page_id_t page_id_{INVALID_PAGE_ID}; 65 | uint32_t slot_num_{0}; // logical offset from 0, 1... 66 | }; 67 | 68 | } // namespace bustub 69 | 70 | namespace std { 71 | template <> 72 | struct hash { 73 | size_t operator()(const bustub::RID &obj) const { return hash()(obj.Get()); } 74 | }; 75 | } // namespace std 76 | -------------------------------------------------------------------------------- /src/include/common/rwlatch.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // rwmutex.h 6 | // 7 | // Identification: src/include/common/rwlatch.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include // NOLINT 18 | 19 | #include "common/macros.h" 20 | 21 | namespace bustub { 22 | 23 | /** 24 | * Reader-Writer latch backed by std::mutex. 25 | */ 26 | class ReaderWriterLatch { 27 | using mutex_t = std::mutex; 28 | using cond_t = std::condition_variable; 29 | static const uint32_t MAX_READERS = UINT_MAX; 30 | 31 | public: 32 | ReaderWriterLatch() = default; 33 | ~ReaderWriterLatch() { std::lock_guard guard(mutex_); } 34 | 35 | DISALLOW_COPY(ReaderWriterLatch); 36 | 37 | /** 38 | * Acquire a write latch. 39 | */ 40 | void WLock() { 41 | std::unique_lock latch(mutex_); 42 | while (writer_entered_) { 43 | reader_.wait(latch); 44 | } 45 | writer_entered_ = true; 46 | while (reader_count_ > 0) { 47 | writer_.wait(latch); 48 | } 49 | } 50 | 51 | /** 52 | * Release a write latch. 53 | */ 54 | void WUnlock() { 55 | std::lock_guard guard(mutex_); 56 | writer_entered_ = false; 57 | reader_.notify_all(); 58 | } 59 | 60 | /** 61 | * Acquire a read latch. 62 | */ 63 | void RLock() { 64 | std::unique_lock latch(mutex_); 65 | while (writer_entered_ || reader_count_ == MAX_READERS) { 66 | reader_.wait(latch); 67 | } 68 | reader_count_++; 69 | } 70 | 71 | /** 72 | * Release a read latch. 73 | */ 74 | void RUnlock() { 75 | std::lock_guard guard(mutex_); 76 | reader_count_--; 77 | if (writer_entered_) { 78 | if (reader_count_ == 0) { 79 | writer_.notify_one(); 80 | } 81 | } else { 82 | if (reader_count_ == MAX_READERS - 1) { 83 | reader_.notify_one(); 84 | } 85 | } 86 | } 87 | 88 | private: 89 | mutex_t mutex_; 90 | cond_t writer_; 91 | cond_t reader_; 92 | uint32_t reader_count_{0}; 93 | bool writer_entered_{false}; 94 | }; 95 | 96 | } // namespace bustub 97 | -------------------------------------------------------------------------------- /src/include/container/hash/hash_function.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_function.h 6 | // 7 | // Identification: src/include/container/hash/hash_function.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "murmur3/MurmurHash3.h" 18 | 19 | namespace bustub { 20 | 21 | template 22 | class HashFunction { 23 | public: 24 | /** 25 | * @param key the key to be hashed 26 | * @return the hashed value 27 | */ 28 | virtual uint64_t GetHash(KeyType key) { 29 | uint64_t hash[2]; 30 | murmur3::MurmurHash3_x64_128(reinterpret_cast(&key), static_cast(sizeof(KeyType)), 0, 31 | reinterpret_cast(&hash)); 32 | return hash[0]; 33 | } 34 | }; 35 | 36 | } // namespace bustub 37 | -------------------------------------------------------------------------------- /src/include/container/hash/hash_table.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_table.h 6 | // 7 | // Identification: src/include/container/hash/hash_table.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "concurrency/transaction.h" 20 | #include "storage/page/hash_table_page_defs.h" 21 | 22 | namespace bustub { 23 | 24 | template 25 | class HashTable { 26 | public: 27 | virtual ~HashTable() = default; 28 | 29 | /** 30 | * Inserts a key-value pair into the hash table. 31 | * @param transaction the current transaction 32 | * @param key the key to create 33 | * @param value the value to be associated with the key 34 | * @return true if insert succeeded, false otherwise 35 | */ 36 | virtual bool Insert(Transaction *transaction, const KeyType &key, const ValueType &value) = 0; 37 | 38 | /** 39 | * Deletes the associated value for the given key. 40 | * @param transaction the current transaction 41 | * @param key the key to delete 42 | * @param value the value to delete 43 | * @return true if remove succeeded, false otherwise 44 | */ 45 | virtual bool Remove(Transaction *transaction, const KeyType &key, const ValueType &value) = 0; 46 | 47 | /** 48 | * Performs a point query on the hash table. 49 | * @param transaction the current transaction 50 | * @param key the key to look up 51 | * @param[out] result the value(s) associated with a given key 52 | * @return the value(s) associated with the given key 53 | */ 54 | virtual bool GetValue(Transaction *transaction, const KeyType &key, std::vector *result) = 0; 55 | }; 56 | 57 | } // namespace bustub 58 | -------------------------------------------------------------------------------- /src/include/execution/execution_engine.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // execution_engine.h 6 | // 7 | // Identification: src/include/execution/execution_engine.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "buffer/buffer_pool_manager.h" 18 | #include "catalog/catalog.h" 19 | #include "concurrency/transaction_manager.h" 20 | #include "execution/executor_context.h" 21 | #include "execution/executor_factory.h" 22 | #include "execution/plans/abstract_plan.h" 23 | #include "storage/table/tuple.h" 24 | namespace bustub { 25 | 26 | /** 27 | * The ExecutionEngine class executes query plans. 28 | */ 29 | class ExecutionEngine { 30 | public: 31 | /** 32 | * Construct a new ExecutionEngine instance. 33 | * @param bpm The buffer pool manager used by the execution engine 34 | * @param txn_mgr The transaction manager used by the execution engine 35 | * @param catalog The catalog used by the execution engine 36 | */ 37 | ExecutionEngine(BufferPoolManager *bpm, TransactionManager *txn_mgr, Catalog *catalog) 38 | : bpm_{bpm}, txn_mgr_{txn_mgr}, catalog_{catalog} {} 39 | 40 | DISALLOW_COPY_AND_MOVE(ExecutionEngine); 41 | 42 | /** 43 | * Execute a query plan. 44 | * @param plan The query plan to execute 45 | * @param result_set The set of tuples produced by executing the plan 46 | * @param txn The transaction context in which the query executes 47 | * @param exec_ctx The executor context in which the query executes 48 | * @return `true` if execution of the query plan succeeds, `false` otherwise 49 | */ 50 | bool Execute(const AbstractPlanNode *plan, std::vector *result_set, Transaction *txn, 51 | ExecutorContext *exec_ctx) { 52 | // Construct and executor for the plan 53 | auto executor = ExecutorFactory::CreateExecutor(exec_ctx, plan); 54 | 55 | // Prepare the root executor 56 | executor->Init(); 57 | 58 | // Execute the query plan 59 | try { 60 | Tuple tuple; 61 | RID rid; 62 | while (executor->Next(&tuple, &rid)) { 63 | if (result_set != nullptr) { 64 | result_set->push_back(tuple); 65 | } 66 | } 67 | } catch (Exception &e) { 68 | // TODO(student): handle exceptions 69 | } 70 | 71 | return true; 72 | } 73 | 74 | private: 75 | /** The buffer pool manager used during query execution */ 76 | [[maybe_unused]] BufferPoolManager *bpm_; 77 | /** The transaction manager used during query execution */ 78 | [[maybe_unused]] TransactionManager *txn_mgr_; 79 | /** The catalog used during query execution */ 80 | [[maybe_unused]] Catalog *catalog_; 81 | }; 82 | 83 | } // namespace bustub 84 | -------------------------------------------------------------------------------- /src/include/execution/executor_context.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // executor_context.h 6 | // 7 | // Identification: src/include/execution/executor_context.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "catalog/catalog.h" 20 | #include "concurrency/transaction.h" 21 | #include "storage/page/tmp_tuple_page.h" 22 | 23 | namespace bustub { 24 | /** 25 | * ExecutorContext stores all the context necessary to run an executor. 26 | */ 27 | class ExecutorContext { 28 | public: 29 | /** 30 | * Creates an ExecutorContext for the transaction that is executing the query. 31 | * @param transaction The transaction executing the query 32 | * @param catalog The catalog that the executor uses 33 | * @param bpm The buffer pool manager that the executor uses 34 | * @param txn_mgr The transaction manager that the executor uses 35 | * @param lock_mgr The lock manager that the executor uses 36 | */ 37 | ExecutorContext(Transaction *transaction, Catalog *catalog, BufferPoolManager *bpm, TransactionManager *txn_mgr, 38 | LockManager *lock_mgr) 39 | : transaction_(transaction), catalog_{catalog}, bpm_{bpm}, txn_mgr_(txn_mgr), lock_mgr_(lock_mgr) {} 40 | 41 | ~ExecutorContext() = default; 42 | 43 | DISALLOW_COPY_AND_MOVE(ExecutorContext); 44 | 45 | /** @return the running transaction */ 46 | Transaction *GetTransaction() const { return transaction_; } 47 | 48 | /** @return the catalog */ 49 | Catalog *GetCatalog() { return catalog_; } 50 | 51 | /** @return the buffer pool manager */ 52 | BufferPoolManager *GetBufferPoolManager() { return bpm_; } 53 | 54 | /** @return the log manager - don't worry about it for now */ 55 | LogManager *GetLogManager() { return nullptr; } 56 | 57 | /** @return the lock manager */ 58 | LockManager *GetLockManager() { return lock_mgr_; } 59 | 60 | /** @return the transaction manager */ 61 | TransactionManager *GetTransactionManager() { return txn_mgr_; } 62 | 63 | private: 64 | /** The transaction context associated with this executor context */ 65 | Transaction *transaction_; 66 | /** The datbase catalog associated with this executor context */ 67 | Catalog *catalog_; 68 | /** The buffer pool manager associated with this executor context */ 69 | BufferPoolManager *bpm_; 70 | /** The transaction manager associated with this executor context */ 71 | TransactionManager *txn_mgr_; 72 | /** The lock manager associated with this executor context */ 73 | LockManager *lock_mgr_; 74 | }; 75 | 76 | } // namespace bustub 77 | -------------------------------------------------------------------------------- /src/include/execution/executor_factory.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // executor_factory.h 6 | // 7 | // Identification: src/include/execution/executor_factory.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "execution/executors/abstract_executor.h" 18 | #include "execution/plans/abstract_plan.h" 19 | 20 | namespace bustub { 21 | /** 22 | * ExecutorFactory creates executors for arbitrary plan nodes. 23 | */ 24 | class ExecutorFactory { 25 | public: 26 | /** 27 | * Creates a new executor given the executor context and plan node. 28 | * @param exec_ctx The executor context for the created executor 29 | * @param plan The plan node that needs to be executed 30 | * @return An executor for the given plan in the provided context 31 | */ 32 | static std::unique_ptr CreateExecutor(ExecutorContext *exec_ctx, const AbstractPlanNode *plan); 33 | }; 34 | } // namespace bustub 35 | -------------------------------------------------------------------------------- /src/include/execution/executors/abstract_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // abstract_executor.h 6 | // 7 | // Identification: src/include/execution/executors/abstract_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "execution/executor_context.h" 16 | #include "storage/table/tuple.h" 17 | 18 | namespace bustub { 19 | /** 20 | * The AbstractExecutor implements the Volcano tuple-at-a-time iterator model. 21 | * This is the base class from which all executors in the BustTub execution 22 | * engine inherit, and defines the minimal interface that all executors support. 23 | */ 24 | class AbstractExecutor { 25 | public: 26 | /** 27 | * Construct a new AbstractExecutor instance. 28 | * @param exec_ctx the executor context that the executor runs with 29 | */ 30 | explicit AbstractExecutor(ExecutorContext *exec_ctx) : exec_ctx_{exec_ctx} {} 31 | 32 | /** Virtual destructor. */ 33 | virtual ~AbstractExecutor() = default; 34 | 35 | /** 36 | * Initialize the executor. 37 | * @warning This function must be called before Next() is called! 38 | */ 39 | virtual void Init() = 0; 40 | 41 | /** 42 | * Yield the next tuple from this executor. 43 | * @param[out] tuple The next tuple produced by this executor 44 | * @param[out] rid The next tuple RID produced by this executor 45 | * @return `true` if a tuple was produced, `false` if there are no more tuples 46 | */ 47 | virtual bool Next(Tuple *tuple, RID *rid) = 0; 48 | 49 | /** @return The schema of the tuples that this executor produces */ 50 | virtual const Schema *GetOutputSchema() = 0; 51 | 52 | /** @return The executor context in which this executor runs */ 53 | ExecutorContext *GetExecutorContext() { return exec_ctx_; } 54 | 55 | protected: 56 | /** The executor context in which the executor runs */ 57 | ExecutorContext *exec_ctx_; 58 | }; 59 | } // namespace bustub 60 | -------------------------------------------------------------------------------- /src/include/execution/executors/delete_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // delete_executor.h 6 | // 7 | // Identification: src/include/execution/executors/delete_executor.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "execution/executor_context.h" 20 | #include "execution/executors/abstract_executor.h" 21 | #include "execution/plans/delete_plan.h" 22 | #include "storage/table/tuple.h" 23 | 24 | namespace bustub { 25 | 26 | /** 27 | * DeletedExecutor executes a delete on a table. 28 | * Deleted values are always pulled from a child. 29 | */ 30 | class DeleteExecutor : public AbstractExecutor { 31 | public: 32 | /** 33 | * Construct a new DeleteExecutor instance. 34 | * @param exec_ctx The executor context 35 | * @param plan The delete plan to be executed 36 | * @param child_executor The child executor that feeds the delete 37 | */ 38 | DeleteExecutor(ExecutorContext *exec_ctx, const DeletePlanNode *plan, 39 | std::unique_ptr &&child_executor); 40 | 41 | /** Initialize the delete */ 42 | void Init() override; 43 | 44 | /** 45 | * Yield the next tuple from the delete. 46 | * @param[out] tuple The next tuple produced by the update 47 | * @param[out] rid The next tuple RID produced by the update 48 | * @return `false` unconditionally (throw to indicate failure) 49 | * 50 | * NOTE: DeleteExecutor::Next() does not use the `tuple` out-parameter. 51 | * NOTE: DeleteExecutor::Next() does not use the `rid` out-parameter. 52 | */ 53 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 54 | 55 | /** @return The output schema for the delete */ 56 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 57 | 58 | private: 59 | /** The delete plan node to be executed */ 60 | const DeletePlanNode *plan_; 61 | /** The child executor from which RIDs for deleted tuples are pulled */ 62 | std::unique_ptr child_executor_; 63 | 64 | TableInfo* table_infos_; 65 | std::vector table_indexs_; 66 | }; 67 | } // namespace bustub 68 | -------------------------------------------------------------------------------- /src/include/execution/executors/index_scan_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // index_scan_executor.h 6 | // 7 | // Identification: src/include/execution/executors/index_scan_executor.h 8 | // 9 | // Copyright (c) 2015-20, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "common/rid.h" 18 | #include "execution/executor_context.h" 19 | #include "execution/executors/abstract_executor.h" 20 | #include "execution/plans/index_scan_plan.h" 21 | #include "storage/table/tuple.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * IndexScanExecutor executes an index scan over a table. 27 | */ 28 | 29 | class IndexScanExecutor : public AbstractExecutor { 30 | public: 31 | /** 32 | * Creates a new index scan executor. 33 | * @param exec_ctx the executor context 34 | * @param plan the index scan plan to be executed 35 | */ 36 | IndexScanExecutor(ExecutorContext *exec_ctx, const IndexScanPlanNode *plan); 37 | 38 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 39 | 40 | void Init() override; 41 | 42 | bool Next(Tuple *tuple, RID *rid) override; 43 | 44 | private: 45 | /** The index scan plan node to be executed. */ 46 | const IndexScanPlanNode *plan_; 47 | }; 48 | } // namespace bustub 49 | -------------------------------------------------------------------------------- /src/include/execution/executors/insert_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // insert_executor.h 6 | // 7 | // Identification: src/include/execution/executors/insert_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "execution/executor_context.h" 19 | #include "execution/executors/abstract_executor.h" 20 | #include "execution/plans/insert_plan.h" 21 | #include "storage/table/tuple.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * InsertExecutor executes an insert on a table. 27 | * 28 | * Unlike UPDATE and DELETE, inserted values may either be 29 | * embedded in the plan itself or be pulled from a child executor. 30 | */ 31 | class InsertExecutor : public AbstractExecutor { 32 | public: 33 | /** 34 | * Construct a new InsertExecutor instance. 35 | * @param exec_ctx The executor context 36 | * @param plan The insert plan to be executed 37 | * @param child_executor The child executor from which inserted tuples are pulled (may be `nullptr`) 38 | */ 39 | InsertExecutor(ExecutorContext *exec_ctx, const InsertPlanNode *plan, 40 | std::unique_ptr &&child_executor); 41 | 42 | /** Initialize the insert */ 43 | void Init() override; 44 | 45 | /** 46 | * Yield the next tuple from the insert. 47 | * @param[out] tuple The next tuple produced by the insert 48 | * @param[out] rid The next tuple RID produced by the insert 49 | * @return `true` if a tuple was produced, `false` if there are no more tuples 50 | * 51 | * NOTE: InsertExecutor::Next() does not use the `tuple` out-parameter. 52 | * NOTE: InsertExecutor::Next() does not use the `rid` out-parameter. 53 | */ 54 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 55 | 56 | /** @return The output schema for the insert */ 57 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 58 | 59 | private: 60 | /** The insert plan node to be executed*/ 61 | const InsertPlanNode *plan_; 62 | size_t insert_next_{0}; 63 | /** child executor for non-raw insert. */ 64 | std::unique_ptr child_executor_; 65 | TableInfo* table_info_; 66 | std::vector table_indexs_; 67 | }; 68 | 69 | } // namespace bustub 70 | -------------------------------------------------------------------------------- /src/include/execution/executors/limit_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // limit_executor.h 6 | // 7 | // Identification: src/include/execution/executors/limit_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "execution/executors/abstract_executor.h" 19 | #include "execution/plans/limit_plan.h" 20 | 21 | namespace bustub { 22 | 23 | /** 24 | * LimitExecutor limits the number of output tuples produced by a child operator. 25 | */ 26 | class LimitExecutor : public AbstractExecutor { 27 | public: 28 | /** 29 | * Construct a new LimitExecutor instance. 30 | * @param exec_ctx The executor context 31 | * @param plan The limit plan to be executed 32 | * @param child_executor The child executor from which limited tuples are pulled 33 | */ 34 | LimitExecutor(ExecutorContext *exec_ctx, const LimitPlanNode *plan, 35 | std::unique_ptr &&child_executor); 36 | 37 | /** Initialize the limit */ 38 | void Init() override; 39 | 40 | /** 41 | * Yield the next tuple from the limit. 42 | * @param[out] tuple The next tuple produced by the limit 43 | * @param[out] rid The next tuple RID produced by the limit 44 | * @return `true` if a tuple was produced, `false` if there are no more tuples 45 | */ 46 | bool Next(Tuple *tuple, RID *rid) override; 47 | 48 | /** @return The output schema for the limit */ 49 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 50 | 51 | private: 52 | /** The limit plan node to be executed */ 53 | const LimitPlanNode *plan_; 54 | /** The child executor from which tuples are obtained */ 55 | std::unique_ptr child_executor_; 56 | /** limit */ 57 | std::size_t limit_; 58 | }; 59 | } // namespace bustub 60 | -------------------------------------------------------------------------------- /src/include/execution/executors/nested_index_join_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_index_join_executor.h 6 | // 7 | // Identification: src/include/execution/executors/nested_index_join_executor.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "execution/executor_context.h" 22 | #include "execution/executors/abstract_executor.h" 23 | #include "execution/expressions/abstract_expression.h" 24 | #include "execution/plans/nested_index_join_plan.h" 25 | #include "storage/table/tmp_tuple.h" 26 | #include "storage/table/tuple.h" 27 | 28 | namespace bustub { 29 | 30 | /** 31 | * IndexJoinExecutor executes index join operations. 32 | */ 33 | class NestIndexJoinExecutor : public AbstractExecutor { 34 | public: 35 | /** 36 | * Creates a new nested index join executor. 37 | * @param exec_ctx the context that the hash join should be performed in 38 | * @param plan the nested index join plan node 39 | * @param outer table child 40 | */ 41 | NestIndexJoinExecutor(ExecutorContext *exec_ctx, const NestedIndexJoinPlanNode *plan, 42 | std::unique_ptr &&child_executor); 43 | 44 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); } 45 | 46 | void Init() override; 47 | 48 | bool Next(Tuple *tuple, RID *rid) override; 49 | 50 | private: 51 | /** The nested index join plan node. */ 52 | const NestedIndexJoinPlanNode *plan_; 53 | }; 54 | } // namespace bustub 55 | -------------------------------------------------------------------------------- /src/include/execution/executors/nested_loop_join_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_loop_join_executor.h 6 | // 7 | // Identification: src/include/execution/executors/nested_loop_join_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "execution/executor_context.h" 19 | #include "execution/executors/abstract_executor.h" 20 | #include "execution/plans/nested_loop_join_plan.h" 21 | #include "storage/table/tuple.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * NestedLoopJoinExecutor executes a nested-loop JOIN on two tables. 27 | */ 28 | class NestedLoopJoinExecutor : public AbstractExecutor { 29 | public: 30 | /** 31 | * Construct a new NestedLoopJoinExecutor instance. 32 | * @param exec_ctx The executor context 33 | * @param plan The NestedLoop join plan to be executed 34 | * @param left_executor The child executor that produces tuple for the left side of join 35 | * @param right_executor The child executor that produces tuple for the right side of join 36 | */ 37 | NestedLoopJoinExecutor(ExecutorContext *exec_ctx, const NestedLoopJoinPlanNode *plan, 38 | std::unique_ptr &&left_executor, 39 | std::unique_ptr &&right_executor); 40 | 41 | /** Initialize the join */ 42 | void Init() override; 43 | 44 | /** 45 | * Yield the next tuple from the join. 46 | * @param[out] tuple The next tuple produced by the join 47 | * @param[out] rid The next tuple RID produced by the join 48 | * @return `true` if a tuple was produced, `false` if there are no more tuples 49 | */ 50 | bool Next(Tuple *tuple, RID *rid) override; 51 | 52 | /** @return The output schema for the insert */ 53 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 54 | 55 | private: 56 | /** The NestedLoopJoin plan node to be executed. */ 57 | const NestedLoopJoinPlanNode *plan_; 58 | std::unique_ptr left_executor_; 59 | std::unique_ptr right_executor_; 60 | Tuple left_tuple_; 61 | Tuple right_tuple_; 62 | }; 63 | 64 | } // namespace bustub 65 | -------------------------------------------------------------------------------- /src/include/execution/executors/seq_scan_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // seq_scan_executor.h 6 | // 7 | // Identification: src/include/execution/executors/seq_scan_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "execution/executor_context.h" 18 | #include "execution/executors/abstract_executor.h" 19 | #include "execution/plans/seq_scan_plan.h" 20 | #include "storage/table/tuple.h" 21 | 22 | namespace bustub { 23 | 24 | /** 25 | * The SeqScanExecutor executor executes a sequential table scan. 26 | */ 27 | class SeqScanExecutor : public AbstractExecutor { 28 | public: 29 | /** 30 | * Construct a new SeqScanExecutor instance. 31 | * @param exec_ctx The executor context 32 | * @param plan The sequential scan plan to be executed 33 | */ 34 | SeqScanExecutor(ExecutorContext *exec_ctx, const SeqScanPlanNode *plan); 35 | 36 | /** Initialize the sequential scan */ 37 | void Init() override; 38 | 39 | /** 40 | * Yield the next tuple from the sequential scan. 41 | * @param[out] tuple The next tuple produced by the scan 42 | * @param[out] rid The next tuple RID produced by the scan 43 | * @return `true` if a tuple was produced, `false` if there are no more tuples 44 | */ 45 | bool Next(Tuple *tuple, RID *rid) override; 46 | 47 | /** @return The output schema for the sequential scan */ 48 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); } 49 | 50 | private: 51 | /** The sequential scan plan node to be executed */ 52 | const SeqScanPlanNode *plan_; 53 | /** The table iterator for table sequential scan */ 54 | TableIterator table_iterator_; 55 | }; 56 | } // namespace bustub 57 | -------------------------------------------------------------------------------- /src/include/execution/executors/update_executor.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // update_executor.h 6 | // 7 | // Identification: src/include/execution/executors/update_executor.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "execution/executor_context.h" 20 | #include "execution/executors/abstract_executor.h" 21 | #include "execution/plans/update_plan.h" 22 | #include "storage/table/tuple.h" 23 | #include "type/value_factory.h" 24 | 25 | namespace bustub { 26 | 27 | /** 28 | * UpdateExecutor executes an update on a table. 29 | * Updated values are always pulled from a child. 30 | */ 31 | class UpdateExecutor : public AbstractExecutor { 32 | friend class UpdatePlanNode; 33 | 34 | public: 35 | /** 36 | * Construct a new UpdateExecutor instance. 37 | * @param exec_ctx The executor context 38 | * @param plan The update plan to be executed 39 | * @param child_executor The child executor that feeds the update 40 | */ 41 | UpdateExecutor(ExecutorContext *exec_ctx, const UpdatePlanNode *plan, 42 | std::unique_ptr &&child_executor); 43 | 44 | /** Initialize the update */ 45 | void Init() override; 46 | 47 | /** 48 | * Yield the next tuple from the udpate. 49 | * @param[out] tuple The next tuple produced by the update 50 | * @param[out] rid The next tuple RID produced by the update 51 | * @return `true` if a tuple was produced, `false` if there are no more tuples 52 | * 53 | * NOTE: UpdateExecutor::Next() does not use the `tuple` out-parameter. 54 | * NOTE: UpdateExecutor::Next() does not use the `rid` out-parameter. 55 | */ 56 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 57 | 58 | /** @return The output schema for the update */ 59 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 60 | 61 | private: 62 | /** 63 | * Given a tuple, creates a new, updated tuple 64 | * based on the `UpdateInfo` provided in the plan. 65 | * @param src_tuple The tuple to be updated 66 | */ 67 | Tuple GenerateUpdatedTuple(const Tuple &src_tuple); 68 | 69 | /** The update plan node to be executed */ 70 | const UpdatePlanNode *plan_; 71 | /** Metadata identifying the table that should be updated */ 72 | const TableInfo *table_info_; 73 | std::vector table_indexs_; 74 | /** The child executor to obtain value from */ 75 | std::unique_ptr child_executor_; 76 | }; 77 | } // namespace bustub 78 | -------------------------------------------------------------------------------- /src/include/execution/expressions/abstract_expression.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // abstract_expression.h 6 | // 7 | // Identification: src/include/expression/abstract_expression.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "catalog/schema.h" 19 | #include "storage/table/tuple.h" 20 | 21 | namespace bustub { 22 | /** 23 | * AbstractExpression is the base class of all the expressions in the system. 24 | * Expressions are modeled as trees, i.e. every expression may have a variable number of children. 25 | */ 26 | class AbstractExpression { 27 | public: 28 | /** 29 | * Create a new AbstractExpression with the given children and return type. 30 | * @param children the children of this abstract expression 31 | * @param ret_type the return type of this abstract expression when it is evaluated 32 | */ 33 | AbstractExpression(std::vector &&children, TypeId ret_type) 34 | : children_{std::move(children)}, ret_type_{ret_type} {} 35 | 36 | /** Virtual destructor. */ 37 | virtual ~AbstractExpression() = default; 38 | 39 | /** @return The value obtained by evaluating the tuple with the given schema */ 40 | virtual Value Evaluate(const Tuple *tuple, const Schema *schema) const = 0; 41 | 42 | /** 43 | * Returns the value obtained by evaluating a JOIN. 44 | * @param left_tuple The left tuple 45 | * @param left_schema The left tuple's schema 46 | * @param right_tuple The right tuple 47 | * @param right_schema The right tuple's schema 48 | * @return The value obtained by evaluating a JOIN on the left and right 49 | */ 50 | virtual Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 51 | const Schema *right_schema) const = 0; 52 | 53 | /** 54 | * Returns the value obtained by evaluating the aggregates. 55 | * @param group_bys The group by values 56 | * @param aggregates The aggregate values 57 | * @return The value obtained by checking the aggregates and group-bys 58 | */ 59 | virtual Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const = 0; 60 | 61 | /** @return the child_idx'th child of this expression */ 62 | const AbstractExpression *GetChildAt(uint32_t child_idx) const { return children_[child_idx]; } 63 | 64 | /** @return the children of this expression, ordering may matter */ 65 | const std::vector &GetChildren() const { return children_; } 66 | 67 | /** @return the type of this expression if it were to be evaluated */ 68 | virtual TypeId GetReturnType() const { return ret_type_; } 69 | 70 | private: 71 | /** The children of this expression. Note that the order of appearance of children may matter. */ 72 | std::vector children_; 73 | /** The return type of this expression. */ 74 | TypeId ret_type_; 75 | }; 76 | } // namespace bustub 77 | -------------------------------------------------------------------------------- /src/include/execution/expressions/aggregate_value_expression.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // aggregate_value_expression.h 6 | // 7 | // Identification: src/include/expression/aggregate_value_expression.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "catalog/schema.h" 18 | #include "execution/expressions/abstract_expression.h" 19 | #include "storage/table/tuple.h" 20 | 21 | namespace bustub { 22 | /** 23 | * AggregateValueExpression represents aggregations such as MAX(a), MIN(b), COUNT(c) 24 | */ 25 | class AggregateValueExpression : public AbstractExpression { 26 | public: 27 | /** 28 | * Creates a new AggregateValueExpression. 29 | * @param is_group_by_term true if this is a group by 30 | * @param term_idx the index of the term 31 | * @param ret_type the return type of the aggregate value expression 32 | */ 33 | AggregateValueExpression(bool is_group_by_term, uint32_t term_idx, TypeId ret_type) 34 | : AbstractExpression({}, ret_type), is_group_by_term_{is_group_by_term}, term_idx_{term_idx} {} 35 | 36 | /** Invalid operation for `AggregateValueExpression` */ 37 | Value Evaluate(const Tuple *tuple, const Schema *schema) const override { 38 | UNREACHABLE("Aggregation should only refer to group-by and aggregates."); 39 | } 40 | 41 | /** Invalid operation for `AggregateValueExpression` */ 42 | Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 43 | const Schema *right_schema) const override { 44 | UNREACHABLE("Aggregation should only refer to group-by and aggregates."); 45 | } 46 | 47 | /** 48 | * Returns the value obtained by evaluating the aggregates. 49 | * @param group_bys The group by values 50 | * @param aggregates The aggregate values 51 | * @return The value obtained by checking the aggregates and group-bys 52 | */ 53 | Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const override { 54 | return is_group_by_term_ ? group_bys[term_idx_] : aggregates[term_idx_]; 55 | } 56 | 57 | private: 58 | /** The flag indicating if this expression is a group-by term */ 59 | bool is_group_by_term_; 60 | /** The index of the term in the collection of aggregates */ 61 | uint32_t term_idx_; 62 | }; 63 | } // namespace bustub 64 | -------------------------------------------------------------------------------- /src/include/execution/expressions/column_value_expression.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // column_value_expression.h 6 | // 7 | // Identification: src/include/expression/column_value_expression.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "catalog/schema.h" 18 | #include "execution/expressions/abstract_expression.h" 19 | #include "storage/table/tuple.h" 20 | 21 | 22 | namespace bustub { 23 | /** 24 | * ColumnValueExpression maintains the tuple index and column index relative to a particular schema or join. 25 | */ 26 | class ColumnValueExpression : public AbstractExpression { 27 | public: 28 | /** 29 | * ColumnValueExpression is an abstraction around "Table.member" in terms of indexes. 30 | * @param tuple_idx {tuple index 0 = left side of join, tuple index 1 = right side of join} 31 | * @param col_idx the index of the column in the schema 32 | * @param ret_type the return type of the expression 33 | */ 34 | ColumnValueExpression(uint32_t tuple_idx, uint32_t col_idx, TypeId ret_type) 35 | : AbstractExpression({}, ret_type), tuple_idx_{tuple_idx}, col_idx_{col_idx} {} 36 | 37 | Value Evaluate(const Tuple *tuple, const Schema *schema) const override { return tuple->GetValue(schema, col_idx_); } 38 | 39 | Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 40 | const Schema *right_schema) const override { 41 | return tuple_idx_ == 0 ? left_tuple->GetValue(left_schema, col_idx_) 42 | : right_tuple->GetValue(right_schema, col_idx_); 43 | } 44 | 45 | Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const override { 46 | BUSTUB_ASSERT(false, "Aggregation should only refer to group-by and aggregates."); 47 | } 48 | 49 | uint32_t GetTupleIdx() const { return tuple_idx_; } 50 | uint32_t GetColIdx() const { return col_idx_; } 51 | 52 | private: 53 | /** Tuple index 0 = left side of join, tuple index 1 = right side of join */ 54 | uint32_t tuple_idx_; 55 | /** Column index refers to the index within the schema of the tuple, e.g. schema {A,B,C} has indexes {0,1,2} */ 56 | uint32_t col_idx_; 57 | }; 58 | } // namespace bustub 59 | -------------------------------------------------------------------------------- /src/include/execution/expressions/constant_value_expression.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // constant_value_expression.h 6 | // 7 | // Identification: src/include/expression/constant_value_expression.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "execution/expressions/abstract_expression.h" 18 | 19 | namespace bustub { 20 | /** 21 | * ConstantValueExpression represents constants. 22 | */ 23 | class ConstantValueExpression : public AbstractExpression { 24 | public: 25 | /** Creates a new constant value expression wrapping the given value. */ 26 | explicit ConstantValueExpression(const Value &val) : AbstractExpression({}, val.GetTypeId()), val_(val) {} 27 | 28 | Value Evaluate(const Tuple *tuple, const Schema *schema) const override { return val_; } 29 | 30 | Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 31 | const Schema *right_schema) const override { 32 | return val_; 33 | } 34 | 35 | Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const override { 36 | return val_; 37 | } 38 | 39 | private: 40 | Value val_; 41 | }; 42 | } // namespace bustub 43 | -------------------------------------------------------------------------------- /src/include/execution/plans/abstract_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // abstract_plan.h 6 | // 7 | // Identification: src/include/execution/plans/abstract_plan.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "catalog/schema.h" 19 | 20 | namespace bustub { 21 | 22 | /** PlanType represents the types of plans that we have in our system. */ 23 | enum class PlanType { 24 | SeqScan, 25 | IndexScan, 26 | Insert, 27 | Update, 28 | Delete, 29 | Aggregation, 30 | Limit, 31 | Distinct, 32 | NestedLoopJoin, 33 | NestedIndexJoin, 34 | HashJoin 35 | }; 36 | 37 | /** 38 | * AbstractPlanNode represents all the possible types of plan nodes in our system. 39 | * Plan nodes are modeled as trees, so each plan node can have a variable number of children. 40 | * Per the Volcano model, the plan node receives the tuples of its children. 41 | * The ordering of the children may matter. 42 | */ 43 | class AbstractPlanNode { 44 | public: 45 | /** 46 | * Create a new AbstractPlanNode with the specified output schema and children. 47 | * @param output_schema the schema for the output of this plan node 48 | * @param children the children of this plan node 49 | */ 50 | AbstractPlanNode(const Schema *output_schema, std::vector &&children) 51 | : output_schema_(output_schema), children_(std::move(children)) {} 52 | 53 | /** Virtual destructor. */ 54 | virtual ~AbstractPlanNode() = default; 55 | 56 | /** @return the schema for the output of this plan node */ 57 | const Schema *OutputSchema() const { return output_schema_; } 58 | 59 | /** @return the child of this plan node at index child_idx */ 60 | const AbstractPlanNode *GetChildAt(uint32_t child_idx) const { return children_[child_idx]; } 61 | 62 | /** @return the children of this plan node */ 63 | const std::vector &GetChildren() const { return children_; } 64 | 65 | /** @return the type of this plan node */ 66 | virtual PlanType GetType() const = 0; 67 | 68 | private: 69 | /** 70 | * The schema for the output of this plan node. In the volcano model, every plan node will spit out tuples, 71 | * and this tells you what schema this plan node's tuples will have. 72 | */ 73 | const Schema *output_schema_; 74 | /** The children of this plan node. */ 75 | std::vector children_; 76 | }; 77 | } // namespace bustub 78 | -------------------------------------------------------------------------------- /src/include/execution/plans/delete_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // delete_plan.h 6 | // 7 | // Identification: src/include/execution/plans/delete_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "catalog/catalog.h" 16 | #include "execution/expressions/abstract_expression.h" 17 | #include "execution/plans/abstract_plan.h" 18 | 19 | namespace bustub { 20 | 21 | /** 22 | * The DeletePlanNode identifies a table from which tuples should be deleted. 23 | * The tuple(s) to be updated come from the child of the DeleteExecutor. 24 | * 25 | * NOTE: To simplify the assignment, DeletePlanNode has at most one child. 26 | */ 27 | class DeletePlanNode : public AbstractPlanNode { 28 | public: 29 | /** 30 | * Construct a new DeletePlanNode. 31 | * @param child The child plan to obtain tuple from 32 | * @param table_oid The identifier of the table from which tuples are deleted 33 | */ 34 | DeletePlanNode(const AbstractPlanNode *child, table_oid_t table_oid) 35 | : AbstractPlanNode(nullptr, {child}), table_oid_{table_oid} {} 36 | 37 | /** @return The type of the plan node */ 38 | PlanType GetType() const override { return PlanType::Delete; } 39 | 40 | /** @return The identifier of the table from which tuples are deleted*/ 41 | table_oid_t TableOid() const { return table_oid_; } 42 | 43 | /** @return The child plan providing tuples to be deleted */ 44 | const AbstractPlanNode *GetChildPlan() const { 45 | BUSTUB_ASSERT(GetChildren().size() == 1, "delete should have at most one child plan."); 46 | return GetChildAt(0); 47 | } 48 | 49 | private: 50 | /** The identifier of the table from which tuples are deleted */ 51 | table_oid_t table_oid_; 52 | 53 | }; 54 | 55 | } // namespace bustub 56 | -------------------------------------------------------------------------------- /src/include/execution/plans/distinct_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // distinct_plan.h 6 | // 7 | // Identification: src/include/execution/plans/distinct_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "common/util/hash_util.h" 16 | #include "execution/plans/abstract_plan.h" 17 | 18 | namespace bustub { 19 | 20 | /** 21 | * Distinct removes duplicate rows from the output of a child node. 22 | */ 23 | class DistinctPlanNode : public AbstractPlanNode { 24 | public: 25 | /** 26 | * Construct a new DistinctPlanNode instance. 27 | * @param child The child plan from which tuples are obtained 28 | */ 29 | DistinctPlanNode(const Schema *output_schema, const AbstractPlanNode *child) 30 | : AbstractPlanNode(output_schema, {child}) {} 31 | 32 | /** @return The type of the plan node */ 33 | PlanType GetType() const override { return PlanType::Distinct; } 34 | 35 | /** @return The child plan node */ 36 | const AbstractPlanNode *GetChildPlan() const { 37 | BUSTUB_ASSERT(GetChildren().size() == 1, "Distinct should have at most one child plan."); 38 | return GetChildAt(0); 39 | } 40 | }; 41 | 42 | 43 | } // namespace bustub 44 | 45 | -------------------------------------------------------------------------------- /src/include/execution/plans/hash_join_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_join_plan.h 6 | // 7 | // Identification: src/include/execution/plans/hash_join_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "execution/plans/abstract_plan.h" 19 | 20 | namespace bustub { 21 | 22 | /** 23 | * Hash join performs a JOIN operation with a hash table. 24 | */ 25 | class HashJoinPlanNode : public AbstractPlanNode { 26 | public: 27 | /** 28 | * Construct a new HashJoinPlanNode instance. 29 | * @param output_schema The output schema for the JOIN 30 | * @param children The child plans from which tuples are obtained 31 | * @param left_key_expression The expression for the left JOIN key 32 | * @param right_key_expression The expression for the right JOIN key 33 | */ 34 | HashJoinPlanNode(const Schema *output_schema, std::vector &&children, 35 | const AbstractExpression *left_key_expression, const AbstractExpression *right_key_expression) 36 | : AbstractPlanNode(output_schema, std::move(children)), 37 | left_key_expression_{left_key_expression}, 38 | right_key_expression_{right_key_expression} {} 39 | 40 | /** @return The type of the plan node */ 41 | PlanType GetType() const override { return PlanType::HashJoin; } 42 | 43 | /** @return The expression to compute the left join key */ 44 | const AbstractExpression *LeftJoinKeyExpression() const { return left_key_expression_; } 45 | 46 | /** @return The expression to compute the right join key */ 47 | const AbstractExpression *RightJoinKeyExpression() const { return right_key_expression_; } 48 | 49 | /** @return The left plan node of the hash join */ 50 | const AbstractPlanNode *GetLeftPlan() const { 51 | BUSTUB_ASSERT(GetChildren().size() == 2, "Hash joins should have exactly two children plans."); 52 | return GetChildAt(0); 53 | } 54 | 55 | /** @return The right plan node of the hash join */ 56 | const AbstractPlanNode *GetRightPlan() const { 57 | BUSTUB_ASSERT(GetChildren().size() == 2, "Hash joins should have exactly two children plans."); 58 | return GetChildAt(1); 59 | } 60 | 61 | private: 62 | /** The expression to compute the left JOIN key */ 63 | const AbstractExpression *left_key_expression_; 64 | /** The expression to compute the right JOIN key */ 65 | const AbstractExpression *right_key_expression_; 66 | }; 67 | 68 | } // namespace bustub 69 | -------------------------------------------------------------------------------- /src/include/execution/plans/index_scan_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // index_scan_plan.h 6 | // 7 | // Identification: src/include/execution/plans/index_scan_plan.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "catalog/catalog.h" 16 | #include "execution/expressions/abstract_expression.h" 17 | #include "execution/plans/abstract_plan.h" 18 | 19 | namespace bustub { 20 | /** 21 | * IndexScanPlanNode identifies a table that should be scanned with an optional predicate. 22 | */ 23 | class IndexScanPlanNode : public AbstractPlanNode { 24 | public: 25 | /** 26 | * Creates a new index scan plan node. 27 | * @param output the output format of this scan plan node 28 | * @param predicate the predicate to scan with, tuples are returned if predicate(tuple) == true or predicate == 29 | * nullptr 30 | * @param table_oid the identifier of table to be scanned 31 | */ 32 | IndexScanPlanNode(const Schema *output, const AbstractExpression *predicate, index_oid_t index_oid) 33 | : AbstractPlanNode(output, {}), predicate_{predicate}, index_oid_(index_oid) {} 34 | 35 | PlanType GetType() const override { return PlanType::IndexScan; } 36 | 37 | /** @return the predicate to test tuples against; tuples should only be returned if they evaluate to true */ 38 | const AbstractExpression *GetPredicate() const { return predicate_; } 39 | 40 | /** @return the identifier of the table that should be scanned */ 41 | index_oid_t GetIndexOid() const { return index_oid_; } 42 | 43 | private: 44 | /** The predicate that all returned tuples must satisfy. */ 45 | const AbstractExpression *predicate_; 46 | /** The table whose tuples should be scanned. */ 47 | index_oid_t index_oid_; 48 | }; 49 | 50 | } // namespace bustub 51 | -------------------------------------------------------------------------------- /src/include/execution/plans/limit_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // limit_plan.h 6 | // 7 | // Identification: src/include/execution/plans/limit_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "execution/plans/abstract_plan.h" 16 | 17 | namespace bustub { 18 | 19 | /** 20 | * Limit constraints the number of output tuples produced by its child executor. 21 | */ 22 | class LimitPlanNode : public AbstractPlanNode { 23 | public: 24 | /** 25 | * Construct a new LimitPlanNode instance. 26 | * @param child The child plan from which tuples are obtained 27 | * @param limit The number of output tuples 28 | */ 29 | LimitPlanNode(const Schema *output_schema, const AbstractPlanNode *child, std::size_t limit) 30 | : AbstractPlanNode(output_schema, {child}), limit_{limit} {} 31 | 32 | /** @return The type of the plan node */ 33 | PlanType GetType() const override { return PlanType::Limit; } 34 | 35 | /** @return The limit */ 36 | size_t GetLimit() const { return limit_; } 37 | 38 | /** @return The child plan node */ 39 | const AbstractPlanNode *GetChildPlan() const { 40 | BUSTUB_ASSERT(GetChildren().size() == 1, "Limit should have at most one child plan."); 41 | return GetChildAt(0); 42 | } 43 | 44 | private: 45 | /** The limit */ 46 | std::size_t limit_; 47 | }; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /src/include/execution/plans/nested_index_join_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_index_join_plan.h 6 | // 7 | // Identification: src/include/execution/plans/nested_index_join_plan.h 8 | // 9 | // Copyright (c) 2015-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "catalog/catalog.h" 20 | #include "execution/plans/abstract_plan.h" 21 | #include "storage/table/tuple.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * NestedIndexJoinPlanNode is used to represent performing a nested index join between two tables 27 | * The outer table tuples are propogated using a child executor, but the inner table tuples should be 28 | * obtained using the outer table tuples as well as the index from the catalog. 29 | */ 30 | class NestedIndexJoinPlanNode : public AbstractPlanNode { 31 | public: 32 | NestedIndexJoinPlanNode(const Schema *output_schema, std::vector &&children, 33 | const AbstractExpression *predicate, table_oid_t inner_table_oid, std::string index_name, 34 | const Schema *outer_table_schema, const Schema *inner_table_schema) 35 | : AbstractPlanNode(output_schema, std::move(children)), 36 | predicate_(predicate), 37 | inner_table_oid_(inner_table_oid), 38 | index_name_(std::move(index_name)), 39 | outer_table_schema_(outer_table_schema), 40 | inner_table_schema_(inner_table_schema) {} 41 | 42 | PlanType GetType() const override { return PlanType::NestedIndexJoin; } 43 | 44 | /** @return the predicate to be used in the nested index join */ 45 | const AbstractExpression *Predicate() const { return predicate_; } 46 | 47 | /** @return the plan node for the outer table of the nested index join */ 48 | const AbstractPlanNode *GetChildPlan() const { return GetChildAt(0); } 49 | 50 | /** @return the table oid for the inner table of the nested index join */ 51 | table_oid_t GetInnerTableOid() const { return inner_table_oid_; } 52 | 53 | /** @return the index associated with the nested index join */ 54 | std::string GetIndexName() const { return index_name_; } 55 | 56 | /** @return Schema with needed columns in from the outer table */ 57 | const Schema *OuterTableSchema() const { return outer_table_schema_; } 58 | 59 | /** @return Schema with needed columns in from the inner table */ 60 | const Schema *InnerTableSchema() const { return inner_table_schema_; } 61 | 62 | private: 63 | /** The nested index join predicate. */ 64 | const AbstractExpression *predicate_; 65 | table_oid_t inner_table_oid_; 66 | const std::string index_name_; 67 | const Schema *outer_table_schema_; 68 | const Schema *inner_table_schema_; 69 | }; 70 | } // namespace bustub 71 | -------------------------------------------------------------------------------- /src/include/execution/plans/nested_loop_join_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // nested_loop_join.h 6 | // 7 | // Identification: src/include/execution/plans/nested_loop_join.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #include "catalog/catalog.h" 19 | #include "execution/expressions/abstract_expression.h" 20 | #include "execution/plans/abstract_plan.h" 21 | 22 | namespace bustub { 23 | 24 | /** 25 | * NestedLoopJoinPlanNode joins tuples from two child plan nodes. 26 | */ 27 | class NestedLoopJoinPlanNode : public AbstractPlanNode { 28 | public: 29 | /** 30 | * Construct a new NestedLoopJoinPlanNode instance. 31 | * @param output The output format of this nested loop join node 32 | * @param children Two sequential scan children plans 33 | * @param predicate The predicate to join with, the tuples are joined 34 | * if predicate(tuple) = true or predicate = `nullptr` 35 | */ 36 | NestedLoopJoinPlanNode(const Schema *output_schema, std::vector &&children, 37 | const AbstractExpression *predicate) 38 | : AbstractPlanNode(output_schema, std::move(children)), predicate_(predicate) {} 39 | 40 | /** @return The type of the plan node */ 41 | PlanType GetType() const override { return PlanType::NestedLoopJoin; } 42 | 43 | /** @return The predicate to be used in the nested loop join */ 44 | const AbstractExpression *Predicate() const { return predicate_; } 45 | 46 | /** @return The left plan node of the nested loop join, by convention it should be the smaller table */ 47 | const AbstractPlanNode *GetLeftPlan() const { 48 | BUSTUB_ASSERT(GetChildren().size() == 2, "Nested loop joins should have exactly two children plans."); 49 | return GetChildAt(0); 50 | } 51 | 52 | /** @return The right plan node of the nested loop join */ 53 | const AbstractPlanNode *GetRightPlan() const { 54 | BUSTUB_ASSERT(GetChildren().size() == 2, "Nested loop joins should have exactly two children plans."); 55 | return GetChildAt(1); 56 | } 57 | 58 | private: 59 | /** The join predicate */ 60 | const AbstractExpression *predicate_; 61 | }; 62 | 63 | } // namespace bustub 64 | -------------------------------------------------------------------------------- /src/include/execution/plans/seq_scan_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // seq_scan_plan.h 6 | // 7 | // Identification: src/include/execution/plans/seq_scan_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "catalog/catalog.h" 16 | #include "execution/expressions/abstract_expression.h" 17 | #include "execution/plans/abstract_plan.h" 18 | 19 | namespace bustub { 20 | 21 | /** 22 | * The SeqScanPlanNode represents a sequential table scan operation. 23 | * It identifies a table to be scanned and an optional predicate. 24 | */ 25 | class SeqScanPlanNode : public AbstractPlanNode { 26 | public: 27 | /** 28 | * Construct a new SeqScanPlanNode instance. 29 | * @param output The output schema of this sequential scan plan node 30 | * @param predicate The predicate applied during the scan operation 31 | * @param table_oid The identifier of table to be scanned 32 | */ 33 | SeqScanPlanNode(const Schema *output, const AbstractExpression *predicate, table_oid_t table_oid) 34 | : AbstractPlanNode(output, {}), predicate_{predicate}, table_oid_{table_oid} {} 35 | 36 | /** @return The type of the plan node */ 37 | PlanType GetType() const override { return PlanType::SeqScan; } 38 | 39 | /** @return The predicate to test tuples against; tuples should only be returned if they evaluate to true */ 40 | const AbstractExpression *GetPredicate() const { return predicate_; } 41 | 42 | /** @return The identifier of the table that should be scanned */ 43 | table_oid_t GetTableOid() const { return table_oid_; } 44 | 45 | private: 46 | /** The predicate that all returned tuples must satisfy */ 47 | const AbstractExpression *predicate_; 48 | /** The table whose tuples should be scanned */ 49 | table_oid_t table_oid_; 50 | }; 51 | 52 | } // namespace bustub 53 | -------------------------------------------------------------------------------- /src/include/execution/plans/update_plan.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // update_plan.h 6 | // 7 | // Identification: src/include/execution/plans/update_plan.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include 16 | 17 | #include "catalog/catalog.h" 18 | #include "execution/expressions/abstract_expression.h" 19 | #include "execution/plans/abstract_plan.h" 20 | 21 | namespace bustub { 22 | 23 | /** The UpdateType enumeration describes the supported update operations */ 24 | enum class UpdateType { Add, Set }; 25 | 26 | /** Metadata about an Update. */ 27 | struct UpdateInfo { 28 | UpdateInfo(UpdateType type, int update_val) : type_{type}, update_val_{update_val} {} 29 | UpdateType type_; 30 | int update_val_; 31 | }; 32 | 33 | /** 34 | * The UpdatePlanNode identifies a table that should be updated. 35 | * The tuple(s) to be updated come from the child of the UpdateExecutor. 36 | * 37 | * NOTE: To simplify the assignment, UpdatePlanNode has at most one child. 38 | */ 39 | class UpdatePlanNode : public AbstractPlanNode { 40 | public: 41 | /** 42 | * Construct a new UpdatePlanNode instance. 43 | * @param child the child plan to obtain tuple from 44 | * @param table_oid the identifier of the table that should be updated 45 | */ 46 | UpdatePlanNode(const AbstractPlanNode *child, table_oid_t table_oid, 47 | std::unordered_map update_attrs) 48 | : AbstractPlanNode(nullptr, {child}), table_oid_{table_oid}, update_attrs_{std::move(update_attrs)} {} 49 | 50 | /** @return The type of the plan node */ 51 | PlanType GetType() const override { return PlanType::Update; } 52 | 53 | /** @return The identifier of the table that should be updated */ 54 | table_oid_t TableOid() const { return table_oid_; } 55 | 56 | /** @return The child plan providing tuples to be inserted */ 57 | const AbstractPlanNode *GetChildPlan() const { 58 | BUSTUB_ASSERT(GetChildren().size() == 1, "UPDATE should have at most one child plan."); 59 | return GetChildAt(0); 60 | } 61 | 62 | /** @return The update attributes */ 63 | const std::unordered_map &GetUpdateAttr() const { return update_attrs_; } 64 | 65 | private: 66 | /** The table to be updated. */ 67 | table_oid_t table_oid_; 68 | /** Map from column index -> update operation */ 69 | const std::unordered_map update_attrs_; 70 | }; 71 | 72 | } // namespace bustub 73 | -------------------------------------------------------------------------------- /src/include/recovery/checkpoint_manager.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // checkpoint_manager.h 6 | // 7 | // Identification: src/include/recovery/checkpoint_manager.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include "buffer/buffer_pool_manager.h" 16 | #include "concurrency/transaction_manager.h" 17 | #include "recovery/log_manager.h" 18 | 19 | namespace bustub { 20 | 21 | /** 22 | * CheckpointManager creates consistent checkpoints by blocking all other transactions temporarily. 23 | */ 24 | class CheckpointManager { 25 | public: 26 | CheckpointManager(TransactionManager *transaction_manager, LogManager *log_manager, 27 | BufferPoolManager *buffer_pool_manager) 28 | : transaction_manager_(transaction_manager), 29 | log_manager_(log_manager), 30 | buffer_pool_manager_(buffer_pool_manager) {} 31 | 32 | ~CheckpointManager() = default; 33 | 34 | void BeginCheckpoint(); 35 | void EndCheckpoint(); 36 | 37 | private: 38 | TransactionManager *transaction_manager_ __attribute__((__unused__)); 39 | LogManager *log_manager_ __attribute__((__unused__)); 40 | BufferPoolManager *buffer_pool_manager_ __attribute__((__unused__)); 41 | }; 42 | 43 | } // namespace bustub 44 | -------------------------------------------------------------------------------- /src/include/recovery/log_manager.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // log_manager.h 6 | // 7 | // Identification: src/include/recovery/log_manager.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include // NOLINT 18 | #include // NOLINT 19 | 20 | #include "recovery/log_record.h" 21 | #include "storage/disk/disk_manager.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * LogManager maintains a separate thread that is awakened whenever the log buffer is full or whenever a timeout 27 | * happens. When the thread is awakened, the log buffer's content is written into the disk log file. 28 | */ 29 | class LogManager { 30 | public: 31 | explicit LogManager(DiskManager *disk_manager) 32 | : next_lsn_(0), persistent_lsn_(INVALID_LSN), disk_manager_(disk_manager) { 33 | log_buffer_ = new char[LOG_BUFFER_SIZE]; 34 | flush_buffer_ = new char[LOG_BUFFER_SIZE]; 35 | } 36 | 37 | ~LogManager() { 38 | delete[] log_buffer_; 39 | delete[] flush_buffer_; 40 | log_buffer_ = nullptr; 41 | flush_buffer_ = nullptr; 42 | } 43 | 44 | void RunFlushThread(); 45 | void StopFlushThread(); 46 | 47 | lsn_t AppendLogRecord(LogRecord *log_record); 48 | 49 | inline lsn_t GetNextLSN() { return next_lsn_; } 50 | inline lsn_t GetPersistentLSN() { return persistent_lsn_; } 51 | inline void SetPersistentLSN(lsn_t lsn) { persistent_lsn_ = lsn; } 52 | inline char *GetLogBuffer() { return log_buffer_; } 53 | 54 | private: 55 | // TODO(students): you may add your own member variables 56 | 57 | /** The atomic counter which records the next log sequence number. */ 58 | std::atomic next_lsn_; 59 | /** The log records before and including the persistent lsn have been written to disk. */ 60 | std::atomic persistent_lsn_; 61 | 62 | char *log_buffer_; 63 | char *flush_buffer_; 64 | 65 | std::mutex latch_; 66 | 67 | std::thread *flush_thread_ __attribute__((__unused__)); 68 | 69 | std::condition_variable cv_; 70 | 71 | DiskManager *disk_manager_ __attribute__((__unused__)); 72 | }; 73 | 74 | } // namespace bustub 75 | -------------------------------------------------------------------------------- /src/include/recovery/log_recovery.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // log_recovery.h 6 | // 7 | // Identification: src/include/recovery/log_recovery.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 17 | #include 18 | 19 | #include "buffer/buffer_pool_manager.h" 20 | #include "concurrency/lock_manager.h" 21 | #include "recovery/log_record.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * Read log file from disk, redo and undo. 27 | */ 28 | class LogRecovery { 29 | public: 30 | LogRecovery(DiskManager *disk_manager, BufferPoolManager *buffer_pool_manager) 31 | : disk_manager_(disk_manager), buffer_pool_manager_(buffer_pool_manager), offset_(0) { 32 | log_buffer_ = new char[LOG_BUFFER_SIZE]; 33 | } 34 | 35 | ~LogRecovery() { 36 | delete[] log_buffer_; 37 | log_buffer_ = nullptr; 38 | } 39 | 40 | void Redo(); 41 | void Undo(); 42 | bool DeserializeLogRecord(const char *data, LogRecord *log_record); 43 | 44 | private: 45 | DiskManager *disk_manager_ __attribute__((__unused__)); 46 | BufferPoolManager *buffer_pool_manager_ __attribute__((__unused__)); 47 | 48 | /** Maintain active transactions and its corresponding latest lsn. */ 49 | std::unordered_map active_txn_; 50 | /** Mapping the log sequence number to log file offset for undos. */ 51 | std::unordered_map lsn_mapping_; 52 | 53 | int offset_ __attribute__((__unused__)); 54 | char *log_buffer_; 55 | }; 56 | 57 | } // namespace bustub 58 | -------------------------------------------------------------------------------- /src/include/storage/index/b_plus_tree_index.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/include/index/b_plus_tree_index.h 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #pragma once 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "storage/index/b_plus_tree.h" 20 | #include "storage/index/index.h" 21 | 22 | namespace bustub { 23 | 24 | #define BPLUSTREE_INDEX_TYPE BPlusTreeIndex 25 | 26 | INDEX_TEMPLATE_ARGUMENTS 27 | class BPlusTreeIndex : public Index { 28 | public: 29 | BPlusTreeIndex(std::unique_ptr &&metadata, BufferPoolManager *buffer_pool_manager); 30 | 31 | void InsertEntry(const Tuple &key, RID rid, Transaction *transaction) override; 32 | 33 | void DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) override; 34 | 35 | void ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) override; 36 | 37 | INDEXITERATOR_TYPE GetBeginIterator(); 38 | 39 | INDEXITERATOR_TYPE GetBeginIterator(const KeyType &key); 40 | 41 | INDEXITERATOR_TYPE GetEndIterator(); 42 | 43 | protected: 44 | // comparator for key 45 | KeyComparator comparator_; 46 | // container 47 | BPlusTree container_; 48 | }; 49 | 50 | } // namespace bustub 51 | -------------------------------------------------------------------------------- /src/include/storage/index/extendible_hash_table_index.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // extendible_hash_table_index.h 6 | // 7 | // Identification: src/include/storage/index/extendible_hash_table_index.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "container/hash/extendible_hash_table.h" 21 | #include "container/hash/hash_function.h" 22 | #include "storage/index/index.h" 23 | 24 | namespace bustub { 25 | 26 | #define HASH_TABLE_INDEX_TYPE ExtendibleHashTableIndex 27 | 28 | template 29 | class ExtendibleHashTableIndex : public Index { 30 | public: 31 | ExtendibleHashTableIndex(std::unique_ptr &&metadata, BufferPoolManager *buffer_pool_manager, 32 | const HashFunction &hash_fn); 33 | 34 | ~ExtendibleHashTableIndex() override = default; 35 | 36 | void InsertEntry(const Tuple &key, RID rid, Transaction *transaction) override; 37 | 38 | void DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) override; 39 | 40 | void ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) override; 41 | 42 | protected: 43 | // comparator for key 44 | KeyComparator comparator_; 45 | // container 46 | ExtendibleHashTable container_; 47 | }; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /src/include/storage/index/hash_comparator.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_comparator.h 6 | // 7 | // Identification: src/include/storage/index/hash_comparator.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | namespace bustub { 16 | 17 | /** 18 | * HashComparator is for comparing hash_t, it returns: 19 | * < 0 if lhs < rhs 20 | * > 0 if lhs > rhs 21 | * = 0 if lhs = rhs 22 | */ 23 | class HashComparator { 24 | public: 25 | inline int operator()(const hash_t lhs, const hash_t rhs) { return lhs < rhs ? -1 : (lhs > rhs ? 1 : 0); } 26 | }; 27 | 28 | } // namespace bustub 29 | -------------------------------------------------------------------------------- /src/include/storage/index/index_iterator.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/include/index/index_iterator.h 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | /** 12 | * index_iterator.h 13 | * For range scan of b+ tree 14 | */ 15 | #pragma once 16 | #include "storage/page/b_plus_tree_leaf_page.h" 17 | 18 | namespace bustub { 19 | 20 | #define INDEXITERATOR_TYPE IndexIterator 21 | 22 | INDEX_TEMPLATE_ARGUMENTS 23 | class IndexIterator { 24 | public: 25 | // you may define your own constructor based on your member variables 26 | IndexIterator(); 27 | ~IndexIterator(); 28 | 29 | bool IsEnd(); 30 | 31 | const MappingType &operator*(); 32 | 33 | IndexIterator &operator++(); 34 | 35 | bool operator==(const IndexIterator &itr) const { throw std::runtime_error("unimplemented"); } 36 | 37 | bool operator!=(const IndexIterator &itr) const { throw std::runtime_error("unimplemented"); } 38 | 39 | private: 40 | // add your own private member variables here 41 | }; 42 | 43 | } // namespace bustub 44 | -------------------------------------------------------------------------------- /src/include/storage/index/int_comparator.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // int_comparator.h 6 | // 7 | // Identification: src/include/storage/index/int_comparator.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | namespace bustub { 16 | 17 | /** 18 | * Function object return is > 0 if lhs > rhs, < 0 if lhs < rhs, 19 | * = 0 if lhs = rhs . 20 | */ 21 | class IntComparator { 22 | public: 23 | inline int operator()(const int lhs, const int rhs) const { 24 | if (lhs < rhs) { 25 | return -1; 26 | } 27 | if (rhs < lhs) { 28 | return 1; 29 | } 30 | return 0; 31 | } 32 | }; 33 | } // namespace bustub 34 | -------------------------------------------------------------------------------- /src/include/storage/index/linear_probe_hash_table_index.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // linear_probe_hash_table_index.h 6 | // 7 | // Identification: src/include/storage/index/linear_probe_hash_table_index.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "container/hash/hash_function.h" 21 | #include "container/hash/linear_probe_hash_table.h" 22 | #include "storage/index/index.h" 23 | 24 | namespace bustub { 25 | 26 | #define HASH_TABLE_INDEX_TYPE LinearProbeHashTableIndex 27 | 28 | template 29 | class LinearProbeHashTableIndex : public Index { 30 | public: 31 | LinearProbeHashTableIndex(std::unique_ptr &&metadata, BufferPoolManager *buffer_pool_manager, 32 | size_t num_buckets, const HashFunction &hash_fn); 33 | 34 | ~LinearProbeHashTableIndex() override = default; 35 | 36 | void InsertEntry(const Tuple &key, RID rid, Transaction *transaction) override; 37 | 38 | void DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) override; 39 | 40 | void ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) override; 41 | 42 | protected: 43 | // comparator for key 44 | KeyComparator comparator_; 45 | // container 46 | LinearProbeHashTable container_; 47 | }; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /src/include/storage/page/b_plus_tree_page.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/include/page/b_plus_tree_page.h 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "buffer/buffer_pool_manager.h" 19 | #include "storage/index/generic_key.h" 20 | 21 | namespace bustub { 22 | 23 | #define MappingType std::pair 24 | 25 | #define INDEX_TEMPLATE_ARGUMENTS template 26 | 27 | // define page type enum 28 | enum class IndexPageType { INVALID_INDEX_PAGE = 0, LEAF_PAGE, INTERNAL_PAGE }; 29 | 30 | /** 31 | * Both internal and leaf page are inherited from this page. 32 | * 33 | * It actually serves as a header part for each B+ tree page and 34 | * contains information shared by both leaf page and internal page. 35 | * 36 | * Header format (size in byte, 24 bytes in total): 37 | * ---------------------------------------------------------------------------- 38 | * | PageType (4) | LSN (4) | CurrentSize (4) | MaxSize (4) | 39 | * ---------------------------------------------------------------------------- 40 | * | ParentPageId (4) | PageId(4) | 41 | * ---------------------------------------------------------------------------- 42 | */ 43 | class BPlusTreePage { 44 | public: 45 | bool IsLeafPage() const; 46 | bool IsRootPage() const; 47 | void SetPageType(IndexPageType page_type); 48 | 49 | int GetSize() const; 50 | void SetSize(int size); 51 | void IncreaseSize(int amount); 52 | 53 | int GetMaxSize() const; 54 | void SetMaxSize(int max_size); 55 | int GetMinSize() const; 56 | 57 | page_id_t GetParentPageId() const; 58 | void SetParentPageId(page_id_t parent_page_id); 59 | 60 | page_id_t GetPageId() const; 61 | void SetPageId(page_id_t page_id); 62 | 63 | void SetLSN(lsn_t lsn = INVALID_LSN); 64 | 65 | private: 66 | // member variable, attributes that both internal and leaf page share 67 | IndexPageType page_type_ __attribute__((__unused__)); 68 | lsn_t lsn_ __attribute__((__unused__)); 69 | int size_ __attribute__((__unused__)); 70 | int max_size_ __attribute__((__unused__)); 71 | page_id_t parent_page_id_ __attribute__((__unused__)); 72 | page_id_t page_id_ __attribute__((__unused__)); 73 | }; 74 | 75 | } // namespace bustub 76 | -------------------------------------------------------------------------------- /src/include/storage/page/hash_table_header_page.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_table_header_page.h 6 | // 7 | // Identification: src/include/storage/page/hash_table_header_page.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "storage/index/generic_key.h" 21 | #include "storage/page/hash_table_page_defs.h" 22 | 23 | namespace bustub { 24 | 25 | /** 26 | * 27 | * Header Page for linear probing hash table. 28 | * 29 | * Header format (size in byte, 16 bytes in total): 30 | * ------------------------------------------------------------- 31 | * | LSN (4) | Size (4) | PageId(4) | NextBlockIndex(4) 32 | * ------------------------------------------------------------- 33 | */ 34 | class HashTableHeaderPage { 35 | public: 36 | /** 37 | * @return the number of buckets in the hash table; 38 | */ 39 | size_t GetSize() const; 40 | 41 | /** 42 | * Sets the size field of the hash table to size 43 | * 44 | * @param size the size for the size field to be set to 45 | */ 46 | void SetSize(size_t size); 47 | 48 | /** 49 | * @return the page ID of this page 50 | */ 51 | page_id_t GetPageId() const; 52 | 53 | /** 54 | * Sets the page ID of this page 55 | * 56 | * @param page_id the page id for the page id field to be set to 57 | */ 58 | void SetPageId(page_id_t page_id); 59 | 60 | /** 61 | * @return the lsn of this page 62 | */ 63 | lsn_t GetLSN() const; 64 | 65 | /** 66 | * Sets the LSN of this page 67 | * 68 | * @param lsn the log sequence number for the lsn field to be set to 69 | */ 70 | void SetLSN(lsn_t lsn); 71 | 72 | /** 73 | * Adds a block page_id to the end of header page 74 | * 75 | * @param page_id page_id to be added 76 | */ 77 | void AddBlockPageId(page_id_t page_id); 78 | 79 | /** 80 | * Returns the page_id of the index-th block 81 | * 82 | * @param index the index of the block 83 | * @return the page_id for the block. 84 | */ 85 | page_id_t GetBlockPageId(size_t index); 86 | 87 | /** 88 | * @return the number of blocks currently stored in the header page 89 | */ 90 | size_t NumBlocks(); 91 | 92 | private: 93 | __attribute__((unused)) lsn_t lsn_; 94 | __attribute__((unused)) size_t size_; 95 | __attribute__((unused)) page_id_t page_id_; 96 | __attribute__((unused)) size_t next_ind_; 97 | __attribute__((unused)) page_id_t block_page_ids_[0]; 98 | }; 99 | 100 | } // namespace bustub 101 | -------------------------------------------------------------------------------- /src/include/storage/page/hash_table_page_defs.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_table_page_defs.h 6 | // 7 | // Identification: src/include/storage/page/hash_table_page_defs.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #define MappingType std::pair 16 | 17 | /** 18 | * Linear Probe Hashing Definitions 19 | */ 20 | #define HASH_TABLE_BLOCK_TYPE HashTableBlockPage 21 | 22 | /** 23 | * BLOCK_ARRAY_SIZE is the number of (key, value) pairs that can be stored in a linear probe hash block page. It is an 24 | * approximate calculation based on the size of MappingType (which is a std::pair of KeyType and ValueType). For each 25 | * key/value pair, we need two additional bits for occupied_ and readable_. 4 * PAGE_SIZE / (4 * sizeof (MappingType) + 26 | * 1) = PAGE_SIZE/(sizeof (MappingType) + 0.25) because 0.25 bytes = 2 bits is the space required to maintain the 27 | * occupied and readable flags for a key value pair. 28 | */ 29 | #define BLOCK_ARRAY_SIZE (4 * PAGE_SIZE / (4 * sizeof(MappingType) + 1)) 30 | 31 | /** 32 | * Extendible Hashing Definitions 33 | */ 34 | #define HASH_TABLE_BUCKET_TYPE HashTableBucketPage 35 | #define DIRECTORY_ARRAY_SIZE 512 36 | 37 | /** 38 | * BUCKET_ARRAY_SIZE is the number of (key, value) pairs that can be stored in an extendible hashing bucket page. 39 | * It is an approximate calculation based on the size of MappingType (which is a std::pair of KeyType and ValueType). 40 | * For each key/value pair, we need two additional bits for occupied_ and readable_. 4 * (PAGE_SIZE - 4) / (4 * sizeof 41 | * (MappingType) + 1) = (PAGE_SIZE - 4)/(sizeof (MappingType) + 0.25) because 0.25 bytes = 2 bits is the space required 42 | * to maintain the occupied and readable flags for a key value pair. 43 | */ 44 | #define BUCKET_ARRAY_SIZE (4 * PAGE_SIZE / (4 * sizeof(MappingType) + 1)) 45 | -------------------------------------------------------------------------------- /src/include/storage/page/header_page.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/include/page/header_page.h 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include "storage/page/page.h" 16 | 17 | namespace bustub { 18 | 19 | /** 20 | * Database use the first page (page_id = 0) as header page to store metadata, in 21 | * our case, we will contain information about table/index name (length less than 22 | * 32 bytes) and their corresponding root_id 23 | * 24 | * Format (size in byte): 25 | * ----------------------------------------------------------------- 26 | * | RecordCount (4) | Entry_1 name (32) | Entry_1 root_id (4) | ... | 27 | * ----------------------------------------------------------------- 28 | */ 29 | class HeaderPage : public Page { 30 | public: 31 | void Init() { SetRecordCount(0); } 32 | /** 33 | * Record related 34 | */ 35 | bool InsertRecord(const std::string &name, page_id_t root_id); 36 | bool DeleteRecord(const std::string &name); 37 | bool UpdateRecord(const std::string &name, page_id_t root_id); 38 | 39 | // return root_id if success 40 | bool GetRootId(const std::string &name, page_id_t *root_id); 41 | int GetRecordCount(); 42 | 43 | private: 44 | /** 45 | * helper functions 46 | */ 47 | int FindRecord(const std::string &name); 48 | 49 | void SetRecordCount(int record_count); 50 | }; 51 | } // namespace bustub 52 | -------------------------------------------------------------------------------- /src/include/storage/page/tmp_tuple_page.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "storage/page/page.h" 4 | #include "storage/table/tmp_tuple.h" 5 | #include "storage/table/tuple.h" 6 | 7 | namespace bustub { 8 | 9 | // To pass the test cases for this class, you must follow the existing TmpTuplePage format and implement the 10 | // existing functions exactly as they are! It may be helpful to look at TablePage. 11 | // Remember that this task is optional, you get full credit if you finish the next task. 12 | 13 | /** 14 | * TmpTuplePage format: 15 | * 16 | * Sizes are in bytes. 17 | * | PageId (4) | LSN (4) | FreeSpace (4) | (free space) | TupleSize2 | TupleData2 | TupleSize1 | TupleData1 | 18 | * 19 | * We choose this format because DeserializeExpression expects to read Size followed by Data. 20 | */ 21 | class TmpTuplePage : public Page { 22 | public: 23 | void Init(page_id_t page_id, uint32_t page_size) {} 24 | 25 | page_id_t GetTablePageId() { return INVALID_PAGE_ID; } 26 | 27 | bool Insert(const Tuple &tuple, TmpTuple *out) { return false; } 28 | 29 | private: 30 | static_assert(sizeof(page_id_t) == 4); 31 | }; 32 | 33 | } // namespace bustub 34 | -------------------------------------------------------------------------------- /src/include/storage/table/table_iterator.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // table_iterator.h 6 | // 7 | // Identification: src/include/storage/table/table_iterator.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include "common/rid.h" 18 | #include "concurrency/transaction.h" 19 | #include "storage/table/tuple.h" 20 | 21 | namespace bustub { 22 | 23 | class TableHeap; 24 | 25 | /** 26 | * TableIterator enables the sequential scan of a TableHeap. 27 | */ 28 | class TableIterator { 29 | friend class Cursor; 30 | 31 | public: 32 | TableIterator(TableHeap *table_heap, RID rid, Transaction *txn); 33 | 34 | TableIterator(const TableIterator &other) 35 | : table_heap_(other.table_heap_), tuple_(new Tuple(*other.tuple_)), txn_(other.txn_) {} 36 | 37 | ~TableIterator() { delete tuple_; } 38 | 39 | inline bool operator==(const TableIterator &itr) const { return tuple_->rid_.Get() == itr.tuple_->rid_.Get(); } 40 | 41 | inline bool operator!=(const TableIterator &itr) const { return !(*this == itr); } 42 | 43 | const Tuple &operator*(); 44 | 45 | Tuple *operator->(); 46 | 47 | TableIterator &operator++(); 48 | 49 | TableIterator operator++(int); 50 | 51 | TableIterator &operator=(const TableIterator &other) { 52 | table_heap_ = other.table_heap_; 53 | *tuple_ = *other.tuple_; 54 | txn_ = other.txn_; 55 | return *this; 56 | } 57 | 58 | private: 59 | TableHeap *table_heap_; 60 | Tuple *tuple_; 61 | Transaction *txn_; 62 | }; 63 | 64 | } // namespace bustub 65 | -------------------------------------------------------------------------------- /src/include/storage/table/tmp_tuple.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common/config.h" 4 | 5 | namespace bustub { 6 | 7 | // Document this class! What does it represent? 8 | 9 | class TmpTuple { 10 | public: 11 | TmpTuple(page_id_t page_id, size_t offset) : page_id_(page_id), offset_(offset) {} 12 | 13 | inline bool operator==(const TmpTuple &rhs) const { return page_id_ == rhs.page_id_ && offset_ == rhs.offset_; } 14 | 15 | page_id_t GetPageId() const { return page_id_; } 16 | size_t GetOffset() const { return offset_; } 17 | 18 | private: 19 | page_id_t page_id_; 20 | size_t offset_; 21 | }; 22 | 23 | } // namespace bustub 24 | -------------------------------------------------------------------------------- /src/include/type/abstract_pool.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // abstract_pool.h 6 | // 7 | // Identification: src/include/type/abstract_pool.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | namespace bustub { 18 | 19 | // Interface of a memory pool that can quickly allocate chunks of memory 20 | class AbstractPool { 21 | public: 22 | // Virtual destructor 23 | virtual ~AbstractPool() = default; 24 | 25 | /** 26 | * @brief Allocate a contiguous block of memory of the given size 27 | * @param size The size (in bytes) of memory to allocate 28 | * @return A non-null pointer if allocation is successful. A null pointer if 29 | * allocation fails. 30 | * 31 | * TODO: Provide good error codes for failure cases 32 | */ 33 | virtual void *Allocate(size_t size) = 0; 34 | 35 | /** 36 | * @brief Returns the provided chunk of memory back into the pool 37 | */ 38 | virtual void Free(void *ptr) = 0; 39 | }; 40 | 41 | } // namespace bustub 42 | -------------------------------------------------------------------------------- /src/include/type/bigint_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // bigint_type.h 6 | // 7 | // Identification: src/include/type/bigint_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/integer_parent_type.h" 16 | 17 | namespace bustub { 18 | // An integer value of the common sizes. 19 | class BigintType : public IntegerParentType { 20 | public: 21 | ~BigintType() override = default; 22 | 23 | BigintType(); 24 | 25 | // Other mathematical functions 26 | Value Add(const Value &left, const Value &right) const override; 27 | Value Subtract(const Value &left, const Value &right) const override; 28 | Value Multiply(const Value &left, const Value &right) const override; 29 | Value Divide(const Value &left, const Value &right) const override; 30 | Value Modulo(const Value &left, const Value &right) const override; 31 | Value Sqrt(const Value &val) const override; 32 | 33 | // Comparison functions 34 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 35 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 38 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 40 | 41 | Value CastAs(const Value &val, TypeId type_id) const override; 42 | 43 | // Debug 44 | std::string ToString(const Value &val) const override; 45 | 46 | // Serialize this value into the given storage space 47 | void SerializeTo(const Value &val, char *storage) const override; 48 | 49 | // Deserialize a value of the given type from the given storage space. 50 | Value DeserializeFrom(const char *storage) const override; 51 | 52 | // Create a copy of this value 53 | Value Copy(const Value &val) const override; 54 | 55 | protected: 56 | Value OperateNull(const Value &left, const Value &right) const override; 57 | 58 | bool IsZero(const Value &val) const override; 59 | }; 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/include/type/boolean_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // boolean_type.h 6 | // 7 | // Identification: src/include/type/boolean_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "common/exception.h" 16 | #include "type/type.h" 17 | #include "type/value.h" 18 | 19 | namespace bustub { 20 | // A boolean value isn't a real SQL type, but we treat it as one to keep 21 | // consistent in the expression subsystem. 22 | class BooleanType : public Type { 23 | public: 24 | ~BooleanType() override = default; 25 | BooleanType(); 26 | 27 | // Comparison functions 28 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 29 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 30 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 31 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 32 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 33 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 34 | 35 | // Decimal types are always inlined 36 | bool IsInlined(const Value &val) const override { return true; } 37 | 38 | // Debug 39 | std::string ToString(const Value &val) const override; 40 | 41 | // Serialize this value into the given storage space 42 | void SerializeTo(const Value &val, char *storage) const override; 43 | 44 | // Deserialize a value of the given type from the given storage space. 45 | Value DeserializeFrom(const char *storage) const override; 46 | 47 | // Create a copy of this value 48 | Value Copy(const Value &val) const override; 49 | 50 | Value CastAs(const Value &val, TypeId type_id) const override; 51 | }; 52 | } // namespace bustub 53 | -------------------------------------------------------------------------------- /src/include/type/decimal_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // decimal_type.h 6 | // 7 | // Identification: src/include/type/decimal_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/numeric_type.h" 16 | 17 | namespace bustub { 18 | class DecimalType : public NumericType { 19 | public: 20 | DecimalType(); 21 | // DecimalValue(DecDef definition); 22 | 23 | // Other mathematical functions 24 | Value Add(const Value &left, const Value &right) const override; 25 | Value Subtract(const Value &left, const Value &right) const override; 26 | Value Multiply(const Value &left, const Value &right) const override; 27 | Value Divide(const Value &left, const Value &right) const override; 28 | Value Modulo(const Value &left, const Value &right) const override; 29 | Value Min(const Value &left, const Value &right) const override; 30 | Value Max(const Value &left, const Value &right) const override; 31 | Value Sqrt(const Value &val) const override; 32 | bool IsZero(const Value &val) const override; 33 | 34 | // Comparison functions 35 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 38 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 40 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 41 | 42 | Value CastAs(const Value &val, TypeId type_id) const override; 43 | 44 | // Decimal types are always inlined 45 | bool IsInlined(const Value &val) const override { return true; } 46 | 47 | // Debug 48 | std::string ToString(const Value &val) const override; 49 | 50 | // Serialize this value into the given storage space 51 | void SerializeTo(const Value &val, char *storage) const override; 52 | 53 | // Deserialize a value of the given type from the given storage space. 54 | Value DeserializeFrom(const char *storage) const override; 55 | 56 | // Create a copy of this value 57 | Value Copy(const Value &val) const override; 58 | 59 | private: 60 | Value OperateNull(const Value &left, const Value &right) const override; 61 | }; 62 | } // namespace bustub 63 | -------------------------------------------------------------------------------- /src/include/type/integer_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // integer_type.h 6 | // 7 | // Identification: src/include/type/integer_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/integer_parent_type.h" 16 | 17 | namespace bustub { 18 | // An integer value of the common sizes. 19 | class IntegerType : public IntegerParentType { 20 | public: 21 | ~IntegerType() override = default; 22 | 23 | explicit IntegerType(TypeId type); 24 | 25 | // Other mathematical functions 26 | Value Add(const Value &left, const Value &right) const override; 27 | Value Subtract(const Value &left, const Value &right) const override; 28 | Value Multiply(const Value &left, const Value &right) const override; 29 | Value Divide(const Value &left, const Value &right) const override; 30 | Value Modulo(const Value &left, const Value &right) const override; 31 | Value Sqrt(const Value &val) const override; 32 | 33 | // Comparison functions 34 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 35 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 38 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 40 | 41 | Value CastAs(const Value &val, TypeId type_id) const override; 42 | 43 | // Debug 44 | std::string ToString(const Value &val) const override; 45 | 46 | // Serialize this value into the given storage space 47 | void SerializeTo(const Value &val, char *storage) const override; 48 | 49 | // Deserialize a value of the given type from the given storage space. 50 | Value DeserializeFrom(const char *storage) const override; 51 | 52 | // Create a copy of this value 53 | Value Copy(const Value &val) const override; 54 | 55 | protected: 56 | Value OperateNull(const Value &left, const Value &right) const override; 57 | 58 | bool IsZero(const Value &val) const override; 59 | }; 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/include/type/limits.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // limits.h 6 | // 7 | // Identification: src/include/type/limits.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace bustub { 20 | 21 | static constexpr double DBL_LOWEST = std::numeric_limits::lowest(); 22 | static constexpr double FLT_LOWEST = std::numeric_limits::lowest(); 23 | 24 | static constexpr int8_t BUSTUB_INT8_MIN = (SCHAR_MIN + 1); 25 | static constexpr int16_t BUSTUB_INT16_MIN = (SHRT_MIN + 1); 26 | static constexpr int32_t BUSTUB_INT32_MIN = (INT_MIN + 1); 27 | static constexpr int64_t BUSTUB_INT64_MIN = (LLONG_MIN + 1); 28 | static constexpr double BUSTUB_DECIMAL_MIN = FLT_LOWEST; 29 | static constexpr uint64_t BUSTUB_TIMESTAMP_MIN = 0; 30 | static constexpr uint32_t BUSTUB_DATE_MIN = 0; 31 | static constexpr int8_t BUSTUB_BOOLEAN_MIN = 0; 32 | 33 | static constexpr int8_t BUSTUB_INT8_MAX = SCHAR_MAX; 34 | static constexpr int16_t BUSTUB_INT16_MAX = SHRT_MAX; 35 | static constexpr int32_t BUSTUB_INT32_MAX = INT_MAX; 36 | static constexpr int64_t BUSTUB_INT64_MAX = LLONG_MAX; 37 | static constexpr uint64_t BUSTUB_UINT64_MAX = ULLONG_MAX - 1; 38 | static constexpr double BUSTUB_DECIMAL_MAX = DBL_MAX; 39 | static constexpr uint64_t BUSTUB_TIMESTAMP_MAX = 11231999986399999999U; 40 | static constexpr uint64_t BUSTUB_DATE_MAX = INT_MAX; 41 | static constexpr int8_t BUSTUB_BOOLEAN_MAX = 1; 42 | 43 | static constexpr uint32_t BUSTUB_VALUE_NULL = UINT_MAX; 44 | static constexpr int8_t BUSTUB_INT8_NULL = SCHAR_MIN; 45 | static constexpr int16_t BUSTUB_INT16_NULL = SHRT_MIN; 46 | static constexpr int32_t BUSTUB_INT32_NULL = INT_MIN; 47 | static constexpr int64_t BUSTUB_INT64_NULL = LLONG_MIN; 48 | static constexpr uint64_t BUSTUB_DATE_NULL = 0; 49 | static constexpr uint64_t BUSTUB_TIMESTAMP_NULL = ULLONG_MAX; 50 | static constexpr double BUSTUB_DECIMAL_NULL = DBL_LOWEST; 51 | static constexpr int8_t BUSTUB_BOOLEAN_NULL = SCHAR_MIN; 52 | 53 | static constexpr uint32_t BUSTUB_VARCHAR_MAX_LEN = UINT_MAX; 54 | 55 | // Use to make TEXT type as the alias of VARCHAR(TEXT_MAX_LENGTH) 56 | static constexpr uint32_t BUSTUB_TEXT_MAX_LEN = 1000000000; 57 | 58 | // Objects (i.e., VARCHAR) with length prefix of -1 are NULL 59 | static constexpr int OBJECTLENGTH_NULL = -1; 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/include/type/numeric_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // numeric_type.h 6 | // 7 | // Identification: src/include/type/numeric_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | 16 | #include "type/value.h" 17 | 18 | namespace bustub { 19 | // A numeric value is an abstract type representing a number. Numerics can be 20 | // either integral or non-integral (decimal), but must provide arithmetic 21 | // operations on its value. 22 | class NumericType : public Type { 23 | public: 24 | explicit NumericType(TypeId type) : Type(type) {} 25 | ~NumericType() override = default; 26 | 27 | // Other mathematical functions 28 | Value Add(const Value &left, const Value &right) const override = 0; 29 | Value Subtract(const Value &left, const Value &right) const override = 0; 30 | Value Multiply(const Value &left, const Value &right) const override = 0; 31 | Value Divide(const Value &left, const Value &right) const override = 0; 32 | Value Modulo(const Value &left, const Value &right) const override = 0; 33 | Value Min(const Value &left, const Value &right) const override = 0; 34 | Value Max(const Value &left, const Value &right) const override = 0; 35 | Value Sqrt(const Value &val) const override = 0; 36 | Value OperateNull(const Value &left, const Value &right) const override = 0; 37 | bool IsZero(const Value &val) const override = 0; 38 | 39 | protected: 40 | static inline double ValMod(double x, double y) { 41 | return x - std::trunc(static_cast(x) / static_cast(y)) * y; 42 | } 43 | }; 44 | } // namespace bustub 45 | -------------------------------------------------------------------------------- /src/include/type/smallint_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // smallint_type.h 6 | // 7 | // Identification: src/include/type/smallint_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/integer_parent_type.h" 16 | 17 | namespace bustub { 18 | // An integer value of the common sizes. 19 | class SmallintType : public IntegerParentType { 20 | public: 21 | ~SmallintType() override = default; 22 | 23 | SmallintType(); 24 | 25 | // Other mathematical functions 26 | Value Add(const Value &left, const Value &right) const override; 27 | Value Subtract(const Value &left, const Value &right) const override; 28 | Value Multiply(const Value &left, const Value &right) const override; 29 | Value Divide(const Value &left, const Value &right) const override; 30 | Value Modulo(const Value &left, const Value &right) const override; 31 | Value Sqrt(const Value &val) const override; 32 | 33 | // Comparison functions 34 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 35 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 38 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 40 | 41 | Value CastAs(const Value &val, TypeId type_id) const override; 42 | 43 | // Debug 44 | std::string ToString(const Value &val) const override; 45 | 46 | // Serialize this value into the given storage space 47 | void SerializeTo(const Value &val, char *storage) const override; 48 | 49 | // Deserialize a value of the given type from the given storage space. 50 | Value DeserializeFrom(const char *storage) const override; 51 | 52 | // Create a copy of this value 53 | Value Copy(const Value &val) const override; 54 | 55 | protected: 56 | Value OperateNull(const Value &left, const Value &right) const override; 57 | 58 | bool IsZero(const Value &val) const override; 59 | }; 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/include/type/timestamp_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // timestamp_type.h 6 | // 7 | // Identification: src/include/type/timestamp_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include "type/abstract_pool.h" 17 | #include "type/value.h" 18 | 19 | namespace bustub { 20 | 21 | class TimestampType : public Type { 22 | public: 23 | static constexpr uint64_t K_USECS_PER_DATE = 86400000000UL; 24 | 25 | ~TimestampType() override = default; 26 | TimestampType(); 27 | 28 | // Comparison functions 29 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 30 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 31 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 32 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 33 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 34 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 35 | 36 | // Other mathematical functions 37 | Value Min(const Value &left, const Value &right) const override; 38 | Value Max(const Value &left, const Value &right) const override; 39 | 40 | bool IsInlined(const Value &val) const override { return true; } 41 | 42 | // Debug 43 | std::string ToString(const Value &val) const override; 44 | 45 | // Serialize this value into the given storage space 46 | void SerializeTo(const Value &val, char *storage) const override; 47 | 48 | // Deserialize a value of the given type from the given storage space. 49 | Value DeserializeFrom(const char *storage) const override; 50 | 51 | // Create a copy of this value 52 | Value Copy(const Value &val) const override; 53 | 54 | Value CastAs(const Value &val, TypeId type_id) const override; 55 | }; 56 | 57 | } // namespace bustub 58 | -------------------------------------------------------------------------------- /src/include/type/tinyint_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // tinyint_type.h 6 | // 7 | // Identification: src/include/type/tinyint_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/integer_parent_type.h" 16 | 17 | namespace bustub { 18 | // An integer value of the common sizes. 19 | class TinyintType : public IntegerParentType { 20 | public: 21 | ~TinyintType() override = default; 22 | 23 | TinyintType(); 24 | 25 | // Other mathematical functions 26 | Value Add(const Value &left, const Value &right) const override; 27 | Value Subtract(const Value &left, const Value &right) const override; 28 | Value Multiply(const Value &left, const Value &right) const override; 29 | Value Divide(const Value &left, const Value &right) const override; 30 | Value Modulo(const Value &left, const Value &right) const override; 31 | Value Sqrt(const Value &val) const override; 32 | 33 | // Comparison functions 34 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 35 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 38 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 40 | 41 | Value CastAs(const Value &val, TypeId type_id) const override; 42 | 43 | // Debug 44 | std::string ToString(const Value &val) const override; 45 | 46 | // Serialize this value into the given storage space 47 | void SerializeTo(const Value &val, char *storage) const override; 48 | 49 | // Deserialize a value of the given type from the given storage space. 50 | Value DeserializeFrom(const char *storage) const override; 51 | 52 | // Create a copy of this value 53 | Value Copy(const Value &val) const override; 54 | 55 | protected: 56 | Value OperateNull(const Value &left, const Value &right) const override; 57 | 58 | bool IsZero(const Value &val) const override; 59 | }; 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /src/include/type/type_id.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // type_id.h 6 | // 7 | // Identification: src/include/type/type_id.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | namespace bustub { 16 | // Every possible SQL type ID 17 | enum TypeId { INVALID = 0, BOOLEAN, TINYINT, SMALLINT, INTEGER, BIGINT, DECIMAL, VARCHAR, TIMESTAMP }; 18 | } // namespace bustub 19 | -------------------------------------------------------------------------------- /src/include/type/varlen_type.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // varlen_type.h 6 | // 7 | // Identification: src/include/type/varlen_type.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | #include 15 | #include "type/value.h" 16 | 17 | namespace bustub { 18 | /* A varlen value is an abstract class representing all objects that have 19 | * variable length. 20 | * For simplicity, for valen_type we always set flag "inline" as true, which 21 | * means we store actual data along with its size rather than a pointer 22 | */ 23 | class VarlenType : public Type { 24 | public: 25 | explicit VarlenType(TypeId type); 26 | ~VarlenType() override; 27 | 28 | // Access the raw variable length data 29 | const char *GetData(const Value &val) const override; 30 | 31 | // Get the length of the variable length data 32 | uint32_t GetLength(const Value &val) const override; 33 | 34 | // Comparison functions 35 | CmpBool CompareEquals(const Value &left, const Value &right) const override; 36 | CmpBool CompareNotEquals(const Value &left, const Value &right) const override; 37 | CmpBool CompareLessThan(const Value &left, const Value &right) const override; 38 | CmpBool CompareLessThanEquals(const Value &left, const Value &right) const override; 39 | CmpBool CompareGreaterThan(const Value &left, const Value &right) const override; 40 | CmpBool CompareGreaterThanEquals(const Value &left, const Value &right) const override; 41 | 42 | // Other mathematical functions 43 | Value Min(const Value &left, const Value &right) const override; 44 | Value Max(const Value &left, const Value &right) const override; 45 | 46 | Value CastAs(const Value &value, TypeId type_id) const override; 47 | 48 | // Decimal types are always inlined 49 | bool IsInlined(const Value & /*val*/) const override { return false; } 50 | 51 | // Debug 52 | std::string ToString(const Value &val) const override; 53 | 54 | // Serialize this value into the given storage space 55 | void SerializeTo(const Value &val, char *storage) const override; 56 | 57 | // Deserialize a value of the given type from the given storage space. 58 | Value DeserializeFrom(const char *storage) const override; 59 | 60 | // Create a copy of this value 61 | Value Copy(const Value &val) const override; 62 | }; 63 | } // namespace bustub 64 | -------------------------------------------------------------------------------- /src/recovery/checkpoint_manager.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // checkpoint_manager.cpp 6 | // 7 | // Identification: src/recovery/checkpoint_manager.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "recovery/checkpoint_manager.h" 14 | 15 | namespace bustub { 16 | 17 | void CheckpointManager::BeginCheckpoint() { 18 | // Block all the transactions and ensure that both the WAL and all dirty buffer pool pages are persisted to disk, 19 | // creating a consistent checkpoint. Do NOT allow transactions to resume at the end of this method, resume them 20 | // in CheckpointManager::EndCheckpoint() instead. This is for grading purposes. 21 | } 22 | 23 | void CheckpointManager::EndCheckpoint() { 24 | // Allow transactions to resume, completing the checkpoint. 25 | } 26 | 27 | } // namespace bustub 28 | -------------------------------------------------------------------------------- /src/recovery/log_manager.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // log_manager.cpp 6 | // 7 | // Identification: src/recovery/log_manager.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "recovery/log_manager.h" 14 | 15 | namespace bustub { 16 | /* 17 | * set enable_logging = true 18 | * Start a separate thread to execute flush to disk operation periodically 19 | * The flush can be triggered when timeout or the log buffer is full or buffer 20 | * pool manager wants to force flush (it only happens when the flushed page has 21 | * a larger LSN than persistent LSN) 22 | * 23 | * This thread runs forever until system shutdown/StopFlushThread 24 | */ 25 | void LogManager::RunFlushThread() {} 26 | 27 | /* 28 | * Stop and join the flush thread, set enable_logging = false 29 | */ 30 | void LogManager::StopFlushThread() {} 31 | 32 | /* 33 | * append a log record into log buffer 34 | * you MUST set the log record's lsn within this method 35 | * @return: lsn that is assigned to this log record 36 | * 37 | * 38 | * example below 39 | * // First, serialize the must have fields(20 bytes in total) 40 | * log_record.lsn_ = next_lsn_++; 41 | * memcpy(log_buffer_ + offset_, &log_record, 20); 42 | * int pos = offset_ + 20; 43 | * 44 | * if (log_record.log_record_type_ == LogRecordType::INSERT) { 45 | * memcpy(log_buffer_ + pos, &log_record.insert_rid_, sizeof(RID)); 46 | * pos += sizeof(RID); 47 | * // we have provided serialize function for tuple class 48 | * log_record.insert_tuple_.SerializeTo(log_buffer_ + pos); 49 | * } 50 | * 51 | */ 52 | lsn_t LogManager::AppendLogRecord(LogRecord *log_record) { return INVALID_LSN; } 53 | 54 | } // namespace bustub 55 | -------------------------------------------------------------------------------- /src/recovery/log_recovery.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // log_recovery.cpp 6 | // 7 | // Identification: src/recovery/log_recovery.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "recovery/log_recovery.h" 14 | 15 | #include "storage/page/table_page.h" 16 | 17 | namespace bustub { 18 | /* 19 | * deserialize a log record from log buffer 20 | * @return: true means deserialize succeed, otherwise can't deserialize cause 21 | * incomplete log record 22 | */ 23 | bool LogRecovery::DeserializeLogRecord(const char *data, LogRecord *log_record) { return false; } 24 | 25 | /* 26 | *redo phase on TABLE PAGE level(table/table_page.h) 27 | *read log file from the beginning to end (you must prefetch log records into 28 | *log buffer to reduce unnecessary I/O operations), remember to compare page's 29 | *LSN with log_record's sequence number, and also build active_txn_ table & 30 | *lsn_mapping_ table 31 | */ 32 | void LogRecovery::Redo() {} 33 | 34 | /* 35 | *undo phase on TABLE PAGE level(table/table_page.h) 36 | *iterate through active txn map and undo each operation 37 | */ 38 | void LogRecovery::Undo() {} 39 | 40 | } // namespace bustub 41 | -------------------------------------------------------------------------------- /src/storage/index/b_plus_tree_index.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/index/b_plus_tree_index.cpp 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include "storage/index/b_plus_tree_index.h" 13 | 14 | namespace bustub { 15 | /* 16 | * Constructor 17 | */ 18 | INDEX_TEMPLATE_ARGUMENTS 19 | BPLUSTREE_INDEX_TYPE::BPlusTreeIndex(std::unique_ptr &&metadata, BufferPoolManager *buffer_pool_manager) 20 | : Index(std::move(metadata)), 21 | comparator_(GetMetadata()->GetKeySchema()), 22 | container_(GetMetadata()->GetName(), buffer_pool_manager, comparator_) {} 23 | 24 | INDEX_TEMPLATE_ARGUMENTS 25 | void BPLUSTREE_INDEX_TYPE::InsertEntry(const Tuple &key, RID rid, Transaction *transaction) { 26 | // construct insert index key 27 | KeyType index_key; 28 | index_key.SetFromKey(key); 29 | 30 | container_.Insert(index_key, rid, transaction); 31 | } 32 | 33 | INDEX_TEMPLATE_ARGUMENTS 34 | void BPLUSTREE_INDEX_TYPE::DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) { 35 | // construct delete index key 36 | KeyType index_key; 37 | index_key.SetFromKey(key); 38 | 39 | container_.Remove(index_key, transaction); 40 | } 41 | 42 | INDEX_TEMPLATE_ARGUMENTS 43 | void BPLUSTREE_INDEX_TYPE::ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) { 44 | // construct scan index key 45 | KeyType index_key; 46 | index_key.SetFromKey(key); 47 | 48 | container_.GetValue(index_key, result, transaction); 49 | } 50 | 51 | INDEX_TEMPLATE_ARGUMENTS 52 | INDEXITERATOR_TYPE BPLUSTREE_INDEX_TYPE::GetBeginIterator() { return container_.Begin(); } 53 | 54 | INDEX_TEMPLATE_ARGUMENTS 55 | INDEXITERATOR_TYPE BPLUSTREE_INDEX_TYPE::GetBeginIterator(const KeyType &key) { return container_.Begin(key); } 56 | 57 | INDEX_TEMPLATE_ARGUMENTS 58 | INDEXITERATOR_TYPE BPLUSTREE_INDEX_TYPE::GetEndIterator() { return container_.End(); } 59 | 60 | template class BPlusTreeIndex, RID, GenericComparator<4>>; 61 | template class BPlusTreeIndex, RID, GenericComparator<8>>; 62 | template class BPlusTreeIndex, RID, GenericComparator<16>>; 63 | template class BPlusTreeIndex, RID, GenericComparator<32>>; 64 | template class BPlusTreeIndex, RID, GenericComparator<64>>; 65 | 66 | } // namespace bustub 67 | -------------------------------------------------------------------------------- /src/storage/index/extendible_hash_table_index.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "storage/index/extendible_hash_table_index.h" 4 | 5 | namespace bustub { 6 | /* 7 | * Constructor 8 | */ 9 | template 10 | HASH_TABLE_INDEX_TYPE::ExtendibleHashTableIndex(std::unique_ptr &&metadata, 11 | BufferPoolManager *buffer_pool_manager, 12 | const HashFunction &hash_fn) 13 | : Index(std::move(metadata)), 14 | comparator_(GetMetadata()->GetKeySchema()), 15 | container_(GetMetadata()->GetName(), buffer_pool_manager, comparator_, hash_fn) {} 16 | 17 | template 18 | void HASH_TABLE_INDEX_TYPE::InsertEntry(const Tuple &key, RID rid, Transaction *transaction) { 19 | // construct insert index key 20 | KeyType index_key; 21 | index_key.SetFromKey(key); 22 | 23 | container_.Insert(transaction, index_key, rid); 24 | } 25 | 26 | template 27 | void HASH_TABLE_INDEX_TYPE::DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) { 28 | // construct delete index key 29 | KeyType index_key; 30 | index_key.SetFromKey(key); 31 | 32 | container_.Remove(transaction, index_key, rid); 33 | } 34 | 35 | template 36 | void HASH_TABLE_INDEX_TYPE::ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) { 37 | // construct scan index key 38 | KeyType index_key; 39 | index_key.SetFromKey(key); 40 | 41 | container_.GetValue(transaction, index_key, result); 42 | } 43 | template class ExtendibleHashTableIndex, RID, GenericComparator<4>>; 44 | template class ExtendibleHashTableIndex, RID, GenericComparator<8>>; 45 | template class ExtendibleHashTableIndex, RID, GenericComparator<16>>; 46 | template class ExtendibleHashTableIndex, RID, GenericComparator<32>>; 47 | template class ExtendibleHashTableIndex, RID, GenericComparator<64>>; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /src/storage/index/index_iterator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * index_iterator.cpp 3 | */ 4 | #include 5 | 6 | #include "storage/index/index_iterator.h" 7 | 8 | namespace bustub { 9 | 10 | /* 11 | * NOTE: you can change the destructor/constructor method here 12 | * set your own input parameters 13 | */ 14 | INDEX_TEMPLATE_ARGUMENTS 15 | INDEXITERATOR_TYPE::IndexIterator() = default; 16 | 17 | INDEX_TEMPLATE_ARGUMENTS 18 | INDEXITERATOR_TYPE::~IndexIterator() = default; 19 | 20 | INDEX_TEMPLATE_ARGUMENTS 21 | bool INDEXITERATOR_TYPE::IsEnd() { throw std::runtime_error("unimplemented"); } 22 | 23 | INDEX_TEMPLATE_ARGUMENTS 24 | const MappingType &INDEXITERATOR_TYPE::operator*() { throw std::runtime_error("unimplemented"); } 25 | 26 | INDEX_TEMPLATE_ARGUMENTS 27 | INDEXITERATOR_TYPE &INDEXITERATOR_TYPE::operator++() { throw std::runtime_error("unimplemented"); } 28 | 29 | template class IndexIterator, RID, GenericComparator<4>>; 30 | 31 | template class IndexIterator, RID, GenericComparator<8>>; 32 | 33 | template class IndexIterator, RID, GenericComparator<16>>; 34 | 35 | template class IndexIterator, RID, GenericComparator<32>>; 36 | 37 | template class IndexIterator, RID, GenericComparator<64>>; 38 | 39 | } // namespace bustub 40 | -------------------------------------------------------------------------------- /src/storage/index/linear_probe_hash_table_index.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "storage/index/linear_probe_hash_table_index.h" 4 | 5 | namespace bustub { 6 | /* 7 | * Constructor 8 | */ 9 | template 10 | HASH_TABLE_INDEX_TYPE::LinearProbeHashTableIndex(std::unique_ptr &&metadata, 11 | BufferPoolManager *buffer_pool_manager, size_t num_buckets, 12 | const HashFunction &hash_fn) 13 | : Index(std::move(metadata)), 14 | comparator_(GetMetadata()->GetKeySchema()), 15 | container_(GetMetadata()->GetName(), buffer_pool_manager, comparator_, num_buckets, hash_fn) {} 16 | 17 | template 18 | void HASH_TABLE_INDEX_TYPE::InsertEntry(const Tuple &key, RID rid, Transaction *transaction) { 19 | // construct insert index key 20 | KeyType index_key; 21 | index_key.SetFromKey(key); 22 | 23 | container_.Insert(transaction, index_key, rid); 24 | } 25 | 26 | template 27 | void HASH_TABLE_INDEX_TYPE::DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) { 28 | // construct delete index key 29 | KeyType index_key; 30 | index_key.SetFromKey(key); 31 | 32 | container_.Remove(transaction, index_key, rid); 33 | } 34 | 35 | template 36 | void HASH_TABLE_INDEX_TYPE::ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) { 37 | // construct scan index key 38 | KeyType index_key; 39 | index_key.SetFromKey(key); 40 | 41 | container_.GetValue(transaction, index_key, result); 42 | } 43 | template class LinearProbeHashTableIndex, RID, GenericComparator<4>>; 44 | template class LinearProbeHashTableIndex, RID, GenericComparator<8>>; 45 | template class LinearProbeHashTableIndex, RID, GenericComparator<16>>; 46 | template class LinearProbeHashTableIndex, RID, GenericComparator<32>>; 47 | template class LinearProbeHashTableIndex, RID, GenericComparator<64>>; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /src/storage/page/b_plus_tree_page.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/page/b_plus_tree_page.cpp 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include "storage/page/b_plus_tree_page.h" 13 | 14 | namespace bustub { 15 | 16 | /* 17 | * Helper methods to get/set page type 18 | * Page type enum class is defined in b_plus_tree_page.h 19 | */ 20 | bool BPlusTreePage::IsLeafPage() const { return false; } 21 | bool BPlusTreePage::IsRootPage() const { return false; } 22 | void BPlusTreePage::SetPageType(IndexPageType page_type) {} 23 | 24 | /* 25 | * Helper methods to get/set size (number of key/value pairs stored in that 26 | * page) 27 | */ 28 | int BPlusTreePage::GetSize() const { return 0; } 29 | void BPlusTreePage::SetSize(int size) {} 30 | void BPlusTreePage::IncreaseSize(int amount) {} 31 | 32 | /* 33 | * Helper methods to get/set max size (capacity) of the page 34 | */ 35 | int BPlusTreePage::GetMaxSize() const { return 0; } 36 | void BPlusTreePage::SetMaxSize(int size) {} 37 | 38 | /* 39 | * Helper method to get min page size 40 | * Generally, min page size == max page size / 2 41 | */ 42 | int BPlusTreePage::GetMinSize() const { return 0; } 43 | 44 | /* 45 | * Helper methods to get/set parent page id 46 | */ 47 | page_id_t BPlusTreePage::GetParentPageId() const { return 0; } 48 | void BPlusTreePage::SetParentPageId(page_id_t parent_page_id) {} 49 | 50 | /* 51 | * Helper methods to get/set self page id 52 | */ 53 | page_id_t BPlusTreePage::GetPageId() const { return 0; } 54 | void BPlusTreePage::SetPageId(page_id_t page_id) {} 55 | 56 | /* 57 | * Helper methods to set lsn 58 | */ 59 | void BPlusTreePage::SetLSN(lsn_t lsn) { lsn_ = lsn; } 60 | 61 | } // namespace bustub 62 | -------------------------------------------------------------------------------- /src/storage/page/hash_table_block_page.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_table_block_page.cpp 6 | // 7 | // Identification: src/storage/page/hash_table_block_page.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "storage/page/hash_table_block_page.h" 14 | #include "storage/index/generic_key.h" 15 | 16 | namespace bustub { 17 | 18 | template 19 | KeyType HASH_TABLE_BLOCK_TYPE::KeyAt(slot_offset_t bucket_ind) const { 20 | return {}; 21 | } 22 | 23 | template 24 | ValueType HASH_TABLE_BLOCK_TYPE::ValueAt(slot_offset_t bucket_ind) const { 25 | return {}; 26 | } 27 | 28 | template 29 | bool HASH_TABLE_BLOCK_TYPE::Insert(slot_offset_t bucket_ind, const KeyType &key, const ValueType &value) { 30 | return false; 31 | } 32 | 33 | template 34 | void HASH_TABLE_BLOCK_TYPE::Remove(slot_offset_t bucket_ind) {} 35 | 36 | template 37 | bool HASH_TABLE_BLOCK_TYPE::IsOccupied(slot_offset_t bucket_ind) const { 38 | return false; 39 | } 40 | 41 | template 42 | bool HASH_TABLE_BLOCK_TYPE::IsReadable(slot_offset_t bucket_ind) const { 43 | return false; 44 | } 45 | 46 | // DO NOT REMOVE ANYTHING BELOW THIS LINE 47 | template class HashTableBlockPage; 48 | template class HashTableBlockPage, RID, GenericComparator<4>>; 49 | template class HashTableBlockPage, RID, GenericComparator<8>>; 50 | template class HashTableBlockPage, RID, GenericComparator<16>>; 51 | template class HashTableBlockPage, RID, GenericComparator<32>>; 52 | template class HashTableBlockPage, RID, GenericComparator<64>>; 53 | 54 | } // namespace bustub 55 | -------------------------------------------------------------------------------- /src/storage/page/hash_table_header_page.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // hash_table_header_page.cpp 6 | // 7 | // Identification: src/storage/page/hash_table_header_page.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include "storage/page/hash_table_header_page.h" 14 | 15 | namespace bustub { 16 | page_id_t HashTableHeaderPage::GetBlockPageId(size_t index) { return 0; } 17 | 18 | page_id_t HashTableHeaderPage::GetPageId() const { return 0; } 19 | 20 | void HashTableHeaderPage::SetPageId(bustub::page_id_t page_id) {} 21 | 22 | lsn_t HashTableHeaderPage::GetLSN() const { return 0; } 23 | 24 | void HashTableHeaderPage::SetLSN(lsn_t lsn) {} 25 | 26 | void HashTableHeaderPage::AddBlockPageId(page_id_t page_id) {} 27 | 28 | size_t HashTableHeaderPage::NumBlocks() { return 0; } 29 | 30 | void HashTableHeaderPage::SetSize(size_t size) {} 31 | 32 | size_t HashTableHeaderPage::GetSize() const { return 0; } 33 | 34 | } // namespace bustub 35 | -------------------------------------------------------------------------------- /src/storage/page/header_page.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // CMU-DB Project (15-445/645) 4 | // ***DO NO SHARE PUBLICLY*** 5 | // 6 | // Identification: src/page/header_page.cpp 7 | // 8 | // Copyright (c) 2018, Carnegie Mellon University Database Group 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #include 13 | #include 14 | 15 | #include "storage/page/header_page.h" 16 | 17 | namespace bustub { 18 | 19 | /** 20 | * Record related 21 | */ 22 | bool HeaderPage::InsertRecord(const std::string &name, const page_id_t root_id) { 23 | assert(name.length() < 32); 24 | assert(root_id > INVALID_PAGE_ID); 25 | 26 | int record_num = GetRecordCount(); 27 | int offset = 4 + record_num * 36; 28 | // check for duplicate name 29 | if (FindRecord(name) != -1) { 30 | return false; 31 | } 32 | // copy record content 33 | memcpy(GetData() + offset, name.c_str(), (name.length() + 1)); 34 | memcpy((GetData() + offset + 32), &root_id, 4); 35 | 36 | SetRecordCount(record_num + 1); 37 | return true; 38 | } 39 | 40 | bool HeaderPage::DeleteRecord(const std::string &name) { 41 | int record_num = GetRecordCount(); 42 | assert(record_num > 0); 43 | 44 | int index = FindRecord(name); 45 | // record does not exsit 46 | if (index == -1) { 47 | return false; 48 | } 49 | int offset = index * 36 + 4; 50 | memmove(GetData() + offset, GetData() + offset + 36, (record_num - index - 1) * 36); 51 | 52 | SetRecordCount(record_num - 1); 53 | return true; 54 | } 55 | 56 | bool HeaderPage::UpdateRecord(const std::string &name, const page_id_t root_id) { 57 | assert(name.length() < 32); 58 | 59 | int index = FindRecord(name); 60 | // record does not exsit 61 | if (index == -1) { 62 | return false; 63 | } 64 | int offset = index * 36 + 4; 65 | // update record content, only root_id 66 | memcpy((GetData() + offset + 32), &root_id, 4); 67 | 68 | return true; 69 | } 70 | 71 | bool HeaderPage::GetRootId(const std::string &name, page_id_t *root_id) { 72 | assert(name.length() < 32); 73 | 74 | int index = FindRecord(name); 75 | // record does not exsit 76 | if (index == -1) { 77 | return false; 78 | } 79 | int offset = (index + 1) * 36; 80 | *root_id = *reinterpret_cast(GetData() + offset); 81 | 82 | return true; 83 | } 84 | 85 | /** 86 | * helper functions 87 | */ 88 | // record count 89 | int HeaderPage::GetRecordCount() { return *reinterpret_cast(GetData()); } 90 | 91 | void HeaderPage::SetRecordCount(int record_count) { memcpy(GetData(), &record_count, 4); } 92 | 93 | int HeaderPage::FindRecord(const std::string &name) { 94 | int record_num = GetRecordCount(); 95 | 96 | for (int i = 0; i < record_num; i++) { 97 | char *raw_name = reinterpret_cast(GetData() + (4 + i * 36)); 98 | if (strcmp(raw_name, name.c_str()) == 0) { 99 | return i; 100 | } 101 | } 102 | return -1; 103 | } 104 | } // namespace bustub 105 | -------------------------------------------------------------------------------- /src/storage/table/table_iterator.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // table_iterator.cpp 6 | // 7 | // Identification: src/storage/table/table_iterator.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "storage/table/table_heap.h" 16 | 17 | namespace bustub { 18 | 19 | TableIterator::TableIterator(TableHeap *table_heap, RID rid, Transaction *txn) 20 | : table_heap_(table_heap), tuple_(new Tuple(rid)), txn_(txn) { 21 | if (rid.GetPageId() != INVALID_PAGE_ID) { 22 | table_heap_->GetTuple(tuple_->rid_, tuple_, txn_); 23 | } 24 | } 25 | 26 | const Tuple &TableIterator::operator*() { 27 | assert(*this != table_heap_->End()); 28 | return *tuple_; 29 | } 30 | 31 | Tuple *TableIterator::operator->() { 32 | assert(*this != table_heap_->End()); 33 | return tuple_; 34 | } 35 | 36 | TableIterator &TableIterator::operator++() { 37 | BufferPoolManager *buffer_pool_manager = table_heap_->buffer_pool_manager_; 38 | auto cur_page = static_cast(buffer_pool_manager->FetchPage(tuple_->rid_.GetPageId())); 39 | cur_page->RLatch(); 40 | assert(cur_page != nullptr); // all pages are pinned 41 | 42 | RID next_tuple_rid; 43 | if (!cur_page->GetNextTupleRid(tuple_->rid_, 44 | &next_tuple_rid)) { // end of this page 45 | while (cur_page->GetNextPageId() != INVALID_PAGE_ID) { 46 | auto next_page = static_cast(buffer_pool_manager->FetchPage(cur_page->GetNextPageId())); 47 | cur_page->RUnlatch(); 48 | buffer_pool_manager->UnpinPage(cur_page->GetTablePageId(), false); 49 | cur_page = next_page; 50 | cur_page->RLatch(); 51 | if (cur_page->GetFirstTupleRid(&next_tuple_rid)) { 52 | break; 53 | } 54 | } 55 | } 56 | tuple_->rid_ = next_tuple_rid; 57 | 58 | if (*this != table_heap_->End()) { 59 | table_heap_->GetTuple(tuple_->rid_, tuple_, txn_); 60 | } 61 | // release until copy the tuple 62 | cur_page->RUnlatch(); 63 | buffer_pool_manager->UnpinPage(cur_page->GetTablePageId(), false); 64 | return *this; 65 | } 66 | 67 | TableIterator TableIterator::operator++(int) { 68 | TableIterator clone(*this); 69 | ++(*this); 70 | return clone; 71 | } 72 | 73 | } // namespace bustub 74 | -------------------------------------------------------------------------------- /src/type/integer_parent_type.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // integer_parent_type.cpp 6 | // 7 | // Identification: src/type/integer_parent_type.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | #include 15 | 16 | #include "type/integer_parent_type.h" 17 | 18 | namespace bustub { 19 | IntegerParentType::IntegerParentType(TypeId type) : NumericType(type) {} 20 | 21 | Value IntegerParentType::Min(const Value &left, const Value &right) const { 22 | assert(left.CheckInteger()); 23 | assert(left.CheckComparable(right)); 24 | if (left.IsNull() || right.IsNull()) { 25 | return left.OperateNull(right); 26 | } 27 | 28 | if (left.CompareLessThan(right) == CmpBool::CmpTrue) { 29 | return left.Copy(); 30 | } 31 | return right.Copy(); 32 | } 33 | 34 | Value IntegerParentType::Max(const Value &left, const Value &right) const { 35 | assert(left.CheckInteger()); 36 | assert(left.CheckComparable(right)); 37 | if (left.IsNull() || right.IsNull()) { 38 | return left.OperateNull(right); 39 | } 40 | 41 | if (left.CompareGreaterThanEquals(right) == CmpBool::CmpTrue) { 42 | return left.Copy(); 43 | } 44 | return right.Copy(); 45 | } 46 | } // namespace bustub 47 | -------------------------------------------------------------------------------- /test/buffer/clock_replacer_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // clock_replacer_test.cpp 6 | // 7 | // Identification: test/buffer/clock_replacer_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | #include // NOLINT 15 | #include 16 | 17 | #include "buffer/clock_replacer.h" 18 | #include "gtest/gtest.h" 19 | 20 | namespace bustub { 21 | 22 | TEST(ClockReplacerTest, DISABLED_SampleTest) { 23 | ClockReplacer clock_replacer(7); 24 | 25 | // Scenario: unpin six elements, i.e. add them to the replacer. 26 | clock_replacer.Unpin(1); 27 | clock_replacer.Unpin(2); 28 | clock_replacer.Unpin(3); 29 | clock_replacer.Unpin(4); 30 | clock_replacer.Unpin(5); 31 | clock_replacer.Unpin(6); 32 | clock_replacer.Unpin(1); 33 | EXPECT_EQ(6, clock_replacer.Size()); 34 | 35 | // Scenario: get three victims from the clock. 36 | int value; 37 | clock_replacer.Victim(&value); 38 | EXPECT_EQ(1, value); 39 | clock_replacer.Victim(&value); 40 | EXPECT_EQ(2, value); 41 | clock_replacer.Victim(&value); 42 | EXPECT_EQ(3, value); 43 | 44 | // Scenario: pin elements in the replacer. 45 | // Note that 3 has already been victimized, so pinning 3 should have no effect. 46 | clock_replacer.Pin(3); 47 | clock_replacer.Pin(4); 48 | EXPECT_EQ(2, clock_replacer.Size()); 49 | 50 | // Scenario: unpin 4. We expect that the reference bit of 4 will be set to 1. 51 | clock_replacer.Unpin(4); 52 | 53 | // Scenario: continue looking for victims. We expect these victims. 54 | clock_replacer.Victim(&value); 55 | EXPECT_EQ(5, value); 56 | clock_replacer.Victim(&value); 57 | EXPECT_EQ(6, value); 58 | clock_replacer.Victim(&value); 59 | EXPECT_EQ(4, value); 60 | } 61 | 62 | } // namespace bustub 63 | -------------------------------------------------------------------------------- /test/buffer/counter.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // counter.h 6 | // 7 | // Identification: test/buffer/counter.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include "gtest/gtest.h" 17 | 18 | namespace bustub { 19 | 20 | enum FuncType { FetchPage, UnpinPage, FlushPage, NewPage, DeletePage, FlushAllPages }; 21 | 22 | struct Counter { 23 | // 0-FetchPage 1-UnpinPage 2-FlushPage 3-NewPage 4-DeletePage 24 | // 5-FlushAllPages 25 | static const int num_types = 6; 26 | std::atomic_int counts[num_types]; 27 | 28 | void Reset() { 29 | for (auto &count : counts) { 30 | count = 0; 31 | } 32 | } 33 | 34 | void AddCount(FuncType func_type) { ++counts[func_type]; } 35 | 36 | // Make sure fetch page function only calls fetch page once and 37 | // does not call other functions 38 | void CheckFetchPage() { 39 | EXPECT_EQ(counts[0], 1) << "has to call FetchPage once"; 40 | for (int i = 1; i < num_types; ++i) { 41 | EXPECT_EQ(counts[i], 0) << "FetchPage Should not call other functions"; 42 | } 43 | } 44 | 45 | void CheckUnpinPage() { 46 | EXPECT_EQ(counts[1], 1) << "has to call UnpinPage once"; 47 | for (int i = 0; i < num_types; ++i) { 48 | if (i != 1) { 49 | EXPECT_EQ(counts[i], 0) << "UnPinPage Should not call other functions"; 50 | } 51 | } 52 | } 53 | 54 | void CheckFlushPage() { 55 | EXPECT_EQ(counts[2], 1) << "has to call FlushPage once"; 56 | for (int i = 0; i < num_types; ++i) { 57 | if (i != 2) { 58 | EXPECT_EQ(counts[i], 0) << "FlushPage Should not call other functions"; 59 | } 60 | } 61 | } 62 | 63 | void CheckNewPage() { 64 | EXPECT_EQ(counts[3], 1) << "has to call NewPage once"; 65 | for (int i = 0; i < num_types; ++i) { 66 | if (i != 3) { 67 | EXPECT_EQ(counts[i], 0) << "NewPage Should not call other functions"; 68 | } 69 | } 70 | } 71 | 72 | void CheckDeletePage() { 73 | EXPECT_EQ(counts[4], 1) << "has to call DeletePage once"; 74 | for (int i = 0; i < num_types; ++i) { 75 | if (i != 4) { 76 | EXPECT_EQ(counts[i], 0) << "DeletePage Should not call other functions"; 77 | } 78 | } 79 | } 80 | 81 | void CheckFlushAllPages() { 82 | for (int i = 1; i < 5; ++i) { 83 | EXPECT_EQ(counts[i], 0) << "FlushAllPage Should not call other functions"; 84 | } 85 | EXPECT_EQ(counts[5], 1) << "has to call FlushAllPage once"; 86 | } 87 | }; 88 | 89 | } // namespace bustub 90 | -------------------------------------------------------------------------------- /test/buffer/lru_replacer_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // lru_replacer_test.cpp 6 | // 7 | // Identification: test/buffer/lru_replacer_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | #include // NOLINT 15 | #include 16 | 17 | #include "buffer/lru_replacer.h" 18 | #include "gtest/gtest.h" 19 | 20 | namespace bustub { 21 | 22 | TEST(LRUReplacerTest, SampleTest) { 23 | LRUReplacer lru_replacer(7); 24 | 25 | // Scenario: unpin six elements, i.e. add them to the replacer. 26 | lru_replacer.Unpin(1); 27 | lru_replacer.Unpin(2); 28 | lru_replacer.Unpin(3); 29 | lru_replacer.Unpin(4); 30 | lru_replacer.Unpin(5); 31 | lru_replacer.Unpin(6); 32 | lru_replacer.Unpin(1); 33 | EXPECT_EQ(6, lru_replacer.Size()); 34 | 35 | // Scenario: get three victims from the lru. 36 | int value; 37 | lru_replacer.Victim(&value); 38 | EXPECT_EQ(1, value); 39 | lru_replacer.Victim(&value); 40 | EXPECT_EQ(2, value); 41 | lru_replacer.Victim(&value); 42 | EXPECT_EQ(3, value); 43 | 44 | // Scenario: pin elements in the replacer. 45 | // Note that 3 has already been victimized, so pinning 3 should have no effect. 46 | lru_replacer.Pin(3); 47 | lru_replacer.Pin(4); 48 | EXPECT_EQ(2, lru_replacer.Size()); 49 | 50 | // Scenario: unpin 4. We expect that the reference bit of 4 will be set to 1. 51 | lru_replacer.Unpin(4); 52 | 53 | // Scenario: continue looking for victims. We expect these victims. 54 | lru_replacer.Victim(&value); 55 | EXPECT_EQ(5, value); 56 | lru_replacer.Victim(&value); 57 | EXPECT_EQ(6, value); 58 | lru_replacer.Victim(&value); 59 | EXPECT_EQ(4, value); 60 | } 61 | 62 | } // namespace bustub 63 | -------------------------------------------------------------------------------- /test/common/rwlatch_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // rwlatch_test.cpp 6 | // 7 | // Identification: test/common/rwlatch_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include // NOLINT 14 | #include 15 | 16 | #include "common/rwlatch.h" 17 | #include "gtest/gtest.h" 18 | 19 | namespace bustub { 20 | 21 | class Counter { 22 | public: 23 | Counter() = default; 24 | void Add(int num) { 25 | mutex_.WLock(); 26 | count_ += num; 27 | mutex_.WUnlock(); 28 | } 29 | int Read() { 30 | int res; 31 | mutex_.RLock(); 32 | res = count_; 33 | mutex_.RUnlock(); 34 | return res; 35 | } 36 | 37 | private: 38 | int count_{0}; 39 | ReaderWriterLatch mutex_{}; 40 | }; 41 | 42 | // NOLINTNEXTLINE 43 | TEST(RWLatchTest, BasicTest) { 44 | int num_threads = 100; 45 | Counter counter{}; 46 | counter.Add(5); 47 | std::vector threads; 48 | for (int tid = 0; tid < num_threads; tid++) { 49 | if (tid % 2 == 0) { 50 | threads.emplace_back([&counter]() { counter.Read(); }); 51 | } else { 52 | threads.emplace_back([&counter]() { counter.Add(1); }); 53 | } 54 | } 55 | for (int i = 0; i < num_threads; i++) { 56 | threads[i].join(); 57 | } 58 | EXPECT_EQ(counter.Read(), 55); 59 | } 60 | } // namespace bustub 61 | -------------------------------------------------------------------------------- /test/include/logging/common.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // common.h 6 | // 7 | // Identification: test/include/logging/common.h 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include // NOLINT 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "storage/table/tuple.h" 22 | 23 | namespace bustub { 24 | 25 | // use a fixed schema to construct a random tuple 26 | Tuple ConstructTuple(Schema *schema) { 27 | std::vector values; 28 | Value v(TypeId::INVALID); 29 | 30 | auto seed = std::chrono::system_clock::now().time_since_epoch().count(); 31 | 32 | std::mt19937 generator(seed); // mt19937 is a standard mersenne_twister_engine 33 | 34 | for (uint32_t i = 0; i < schema->GetColumnCount(); i++) { 35 | // get type 36 | const auto &col = schema->GetColumn(i); 37 | TypeId type = col.GetType(); 38 | switch (type) { 39 | case TypeId::BOOLEAN: 40 | v = Value(type, static_cast(generator() % 2)); 41 | break; 42 | case TypeId::TINYINT: 43 | v = Value(type, static_cast(generator()) % 1000); 44 | break; 45 | case TypeId::SMALLINT: 46 | v = Value(type, static_cast(generator()) % 1000); 47 | break; 48 | case TypeId::INTEGER: 49 | v = Value(type, static_cast(generator()) % 1000); 50 | break; 51 | case TypeId::BIGINT: 52 | v = Value(type, static_cast(generator()) % 1000); 53 | break; 54 | case TypeId::VARCHAR: { 55 | static const char alphanum[] = 56 | "0123456789" 57 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 58 | "abcdefghijklmnopqrstuvwxyz"; 59 | auto len = static_cast(1 + generator() % 9); 60 | char s[10]; 61 | for (uint32_t j = 0; j < len; ++j) { 62 | s[j] = alphanum[generator() % (sizeof(alphanum) - 1)]; 63 | } 64 | s[len] = 0; 65 | v = Value(type, s, len + 1, true); 66 | break; 67 | } 68 | default: 69 | break; 70 | } 71 | values.emplace_back(v); 72 | } 73 | return Tuple(values, schema); 74 | } 75 | 76 | } // namespace bustub 77 | -------------------------------------------------------------------------------- /test/include/test_util.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // test_util.h 6 | // 7 | // Identification: test/include/test_util.h 8 | // 9 | // Copyright (c) 2015-2021, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "catalog/schema.h" 24 | #include "common/exception.h" 25 | #include "common/logger.h" 26 | #include "common/util/string_util.h" 27 | #include "storage/page/header_page.h" 28 | 29 | namespace bustub { 30 | 31 | std::unique_ptr ParseCreateStatement(const std::string &sql_base) { 32 | std::string::size_type n; 33 | std::vector v{}; 34 | std::string column_name; 35 | std::string column_type; 36 | int column_length = 0; 37 | TypeId type = INVALID; 38 | 39 | // create a copy of the sql query 40 | std::string sql = sql_base; 41 | 42 | // Preprocess, transform sql string into lower case 43 | std::transform(sql.begin(), sql.end(), sql.begin(), ::tolower); 44 | std::vector tok = StringUtil::Split(sql, ','); 45 | 46 | // Iterate through returned result 47 | for (const std::string &t : tok) { 48 | type = INVALID; 49 | column_length = 0; 50 | 51 | // whitespace separate column name and type 52 | n = t.find_first_of(' '); 53 | column_name = t.substr(0, n); 54 | column_type = t.substr(n + 1); 55 | 56 | // Deal with varchar(size) situation 57 | n = column_type.find_first_of('('); 58 | if (n != std::string::npos) { 59 | column_length = std::stoi(column_type.substr(n + 1)); 60 | column_type = column_type.substr(0, n); 61 | } 62 | if (column_type == "bool" || column_type == "boolean") { 63 | type = BOOLEAN; 64 | } else if (column_type == "tinyint") { 65 | type = TINYINT; 66 | } else if (column_type == "smallint") { 67 | type = SMALLINT; 68 | } else if (column_type == "int" || column_type == "integer") { 69 | type = INTEGER; 70 | } else if (column_type == "bigint") { 71 | type = BIGINT; 72 | } else if (column_type == "double" || column_type == "float") { 73 | type = DECIMAL; 74 | } else if (column_type == "varchar" || column_type == "char") { 75 | type = VARCHAR; 76 | column_length = (column_length == 0) ? 32 : column_length; 77 | } 78 | 79 | // Construct each column 80 | if (type != INVALID) { 81 | if (type == VARCHAR) { 82 | Column col(column_name, type, column_length); 83 | v.emplace_back(col); 84 | } else { 85 | Column col(column_name, type); 86 | v.emplace_back(col); 87 | } 88 | } else { 89 | throw Exception(ExceptionType::UNKNOWN_TYPE, "unknown type for create table"); 90 | } 91 | } 92 | return std::make_unique(v); 93 | } 94 | 95 | } // namespace bustub 96 | -------------------------------------------------------------------------------- /test/storage/disk_manager_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // disk_manager_test.cpp 6 | // 7 | // Identification: test/storage/disk/disk_manager_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "common/exception.h" 16 | #include "gtest/gtest.h" 17 | #include "storage/disk/disk_manager.h" 18 | 19 | namespace bustub { 20 | 21 | class DiskManagerTest : public ::testing::Test { 22 | protected: 23 | // This function is called before every test. 24 | void SetUp() override { 25 | remove("test.db"); 26 | remove("test.log"); 27 | } 28 | 29 | // This function is called after every test. 30 | void TearDown() override { 31 | remove("test.db"); 32 | remove("test.log"); 33 | }; 34 | }; 35 | 36 | // NOLINTNEXTLINE 37 | TEST_F(DiskManagerTest, ReadWritePageTest) { 38 | char buf[PAGE_SIZE] = {0}; 39 | char data[PAGE_SIZE] = {0}; 40 | std::string db_file("test.db"); 41 | auto dm = DiskManager(db_file); 42 | std::strncpy(data, "A test string.", sizeof(data)); 43 | 44 | dm.ReadPage(0, buf); // tolerate empty read 45 | 46 | dm.WritePage(0, data); 47 | dm.ReadPage(0, buf); 48 | EXPECT_EQ(std::memcmp(buf, data, sizeof(buf)), 0); 49 | 50 | std::memset(buf, 0, sizeof(buf)); 51 | dm.WritePage(5, data); 52 | dm.ReadPage(5, buf); 53 | EXPECT_EQ(std::memcmp(buf, data, sizeof(buf)), 0); 54 | 55 | dm.ShutDown(); 56 | } 57 | 58 | // NOLINTNEXTLINE 59 | TEST_F(DiskManagerTest, ReadWriteLogTest) { 60 | char buf[16] = {0}; 61 | char data[16] = {0}; 62 | std::string db_file("test.db"); 63 | auto dm = DiskManager(db_file); 64 | std::strncpy(data, "A test string.", sizeof(data)); 65 | 66 | dm.ReadLog(buf, sizeof(buf), 0); // tolerate empty read 67 | 68 | dm.WriteLog(data, sizeof(data)); 69 | dm.ReadLog(buf, sizeof(buf), 0); 70 | EXPECT_EQ(std::memcmp(buf, data, sizeof(buf)), 0); 71 | 72 | dm.ShutDown(); 73 | } 74 | 75 | // NOLINTNEXTLINE 76 | TEST_F(DiskManagerTest, ThrowBadFileTest) { EXPECT_THROW(DiskManager("dev/null\\/foo/bar/baz/test.db"), Exception); } 77 | 78 | } // namespace bustub 79 | -------------------------------------------------------------------------------- /test/storage/tmp_tuple_page_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // tmp_tuple_page_test.cpp 6 | // 7 | // Identification: test/storage/tmp_tuple_page_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "gtest/gtest.h" 16 | #include "storage/page/tmp_tuple_page.h" 17 | #include "type/value_factory.h" 18 | 19 | namespace bustub { 20 | 21 | // NOLINTNEXTLINE 22 | TEST(TmpTuplePageTest, DISABLED_BasicTest) { 23 | // There are many ways to do this assignment, and this is only one of them. 24 | // If you don't like the TmpTuplePage idea, please feel free to delete this test case entirely. 25 | // You will get full credit as long as you are correctly using a linear probe hash table. 26 | 27 | TmpTuplePage page{}; 28 | page_id_t page_id = 15445; 29 | page.Init(page_id, PAGE_SIZE); 30 | 31 | char *data = page.GetData(); 32 | ASSERT_EQ(*reinterpret_cast(data), page_id); 33 | ASSERT_EQ(*reinterpret_cast(data + sizeof(page_id_t) + sizeof(lsn_t)), PAGE_SIZE); 34 | 35 | std::vector columns; 36 | columns.emplace_back("A", TypeId::INTEGER); 37 | Schema schema(columns); 38 | 39 | std::vector values; 40 | values.emplace_back(ValueFactory::GetIntegerValue(123)); 41 | 42 | Tuple tuple(values, &schema); 43 | TmpTuple tmp_tuple(INVALID_PAGE_ID, 0); 44 | page.Insert(tuple, &tmp_tuple); 45 | 46 | ASSERT_EQ(*reinterpret_cast(data + sizeof(page_id_t) + sizeof(lsn_t)), PAGE_SIZE - 8); 47 | ASSERT_EQ(*reinterpret_cast(data + PAGE_SIZE - 8), 4); 48 | ASSERT_EQ(*reinterpret_cast(data + PAGE_SIZE - 4), 123); 49 | } 50 | 51 | } // namespace bustub 52 | -------------------------------------------------------------------------------- /test/table/tuple_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // tuple_test.cpp 6 | // 7 | // Identification: test/table/tuple_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "buffer/buffer_pool_manager_instance.h" 20 | #include "gtest/gtest.h" 21 | #include "logging/common.h" 22 | #include "storage/table/table_heap.h" 23 | #include "storage/table/tuple.h" 24 | 25 | namespace bustub { 26 | // NOLINTNEXTLINE 27 | TEST(TupleTest, DISABLED_TableHeapTest) { 28 | // test1: parse create sql statement 29 | std::string create_stmt = "a varchar(20), b smallint, c bigint, d bool, e varchar(16)"; 30 | Column col1{"a", TypeId::VARCHAR, 20}; 31 | Column col2{"b", TypeId::SMALLINT}; 32 | Column col3{"c", TypeId::BIGINT}; 33 | Column col4{"d", TypeId::BOOLEAN}; 34 | Column col5{"e", TypeId::VARCHAR, 16}; 35 | std::vector cols{col1, col2, col3, col4, col5}; 36 | Schema schema{cols}; 37 | Tuple tuple = ConstructTuple(&schema); 38 | 39 | // create transaction 40 | auto *transaction = new Transaction(0); 41 | auto *disk_manager = new DiskManager("test.db"); 42 | auto *buffer_pool_manager = new BufferPoolManagerInstance(50, disk_manager); 43 | auto *lock_manager = new LockManager(); 44 | auto *log_manager = new LogManager(disk_manager); 45 | auto *table = new TableHeap(buffer_pool_manager, lock_manager, log_manager, transaction); 46 | 47 | std::vector rid_v; 48 | for (int i = 0; i < 5000; ++i) { 49 | RID rid; 50 | table->InsertTuple(tuple, &rid, transaction); 51 | rid_v.push_back(rid); 52 | } 53 | 54 | TableIterator itr = table->Begin(transaction); 55 | while (itr != table->End()) { 56 | // std::cout << itr->ToString(schema) << std::endl; 57 | ++itr; 58 | } 59 | 60 | // int i = 0; 61 | std::shuffle(rid_v.begin(), rid_v.end(), std::default_random_engine(0)); 62 | for (const auto &rid : rid_v) { 63 | // std::cout << i++ << std::endl; 64 | assert(table->MarkDelete(rid, transaction) == 1); 65 | } 66 | disk_manager->ShutDown(); 67 | remove("test.db"); // remove db file 68 | remove("test.log"); 69 | delete table; 70 | delete buffer_pool_manager; 71 | delete disk_manager; 72 | } 73 | 74 | } // namespace bustub 75 | -------------------------------------------------------------------------------- /third_party/.clang-tidy: -------------------------------------------------------------------------------- 1 | # Disable all checks for third-party sources. 2 | 3 | Checks: ' 4 | -*, 5 | ' -------------------------------------------------------------------------------- /third_party/murmur3/MurmurHash3.h: -------------------------------------------------------------------------------- 1 | // This source file was originally from: 2 | // https://github.com/PeterScott/murmur3 3 | // 4 | // We've changed it for use with VoltDB: 5 | // - We changed the functions declared below to return their hash by 6 | // value, rather than accept a pointer to storage for the result 7 | 8 | //----------------------------------------------------------------------------- 9 | // MurmurHash3 was written by Austin Appleby, and is placed in the public 10 | // domain. The author hereby disclaims copyright to this source code. 11 | 12 | #ifndef _MURMURHASH3_H_ 13 | #define _MURMURHASH3_H_ 14 | 15 | #include 16 | 17 | namespace murmur3 { 18 | 19 | //----------------------------------------------------------------------------- 20 | // Platform-specific functions and macros 21 | 22 | // Microsoft Visual Studio 23 | 24 | #if defined(_MSC_VER) 25 | 26 | typedef unsigned char uint8_t; 27 | typedef unsigned long uint32_t; 28 | typedef unsigned __int64 uint64_t; 29 | 30 | // Other compilers 31 | 32 | #else // defined(_MSC_VER) 33 | 34 | #include 35 | 36 | #endif // !defined(_MSC_VER) 37 | 38 | //----------------------------------------------------------------------------- 39 | 40 | int32_t MurmurHash3_x64_128 (const void * key, int len, uint32_t seed ); 41 | 42 | inline int32_t MurmurHash3_x64_128(int32_t value, uint32_t seed) { 43 | return MurmurHash3_x64_128(&value, 4, seed); 44 | } 45 | inline int32_t MurmurHash3_x64_128(int32_t value) { 46 | return MurmurHash3_x64_128(&value, 4, 0); 47 | } 48 | 49 | inline int32_t MurmurHash3_x64_128(int64_t value, uint32_t seed) { 50 | return MurmurHash3_x64_128(&value, 8, seed); 51 | } 52 | inline int32_t MurmurHash3_x64_128(int64_t value) { 53 | return MurmurHash3_x64_128(&value, 8, 0); 54 | } 55 | 56 | inline int32_t MurmurHash3_x64_128(double value, uint32_t seed) { 57 | return MurmurHash3_x64_128(&value, 8, seed); 58 | } 59 | 60 | inline int32_t MurmurHash3_x64_128(std::string &value, uint32_t seed) { 61 | return MurmurHash3_x64_128(value.data(), static_cast(value.size()), seed); 62 | } 63 | 64 | uint32_t MurmurHash3_x86_32(const void* key, uint32_t len, uint32_t seed); 65 | 66 | void MurmurHash3_x64_128 ( const void * key, const int len, 67 | const uint32_t seed, void * out ); 68 | 69 | //----------------------------------------------------------------------------- 70 | 71 | } 72 | #endif // _MURMURHASH3_H_ 73 | -------------------------------------------------------------------------------- /third_party/versions.txt: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | 18 | # Toolchain library versions 19 | 20 | GTEST_VERSION=1.8.0 21 | GFLAGS_VERSION=2.2.0 22 | GBENCHMARK_VERSION=1.4.1 23 | 24 | # Library, Version, Commit Hash 25 | 26 | # murmur3 27 | # url: https://github.com/aappleby/smhasher.git 28 | # branch: master 29 | # commit hash: 61a0530f28277f2e850bfc39600ce61d02b518de 30 | # commit hash date: 9 Jan 2018 31 | --------------------------------------------------------------------------------