├── .circleci └── config.yml ├── .clang-format ├── .clang-tidy ├── .dockerignore ├── .github └── pull_request_template.md ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Dockerfile ├── LICENSE ├── README.md ├── Vagrantfile ├── auto-archive.sh ├── auto-test.sh ├── 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 ├── doc-generator.sh ├── logo ├── bustub-whiteborder.svg └── bustub.svg ├── project1.sh ├── project2.sh ├── src ├── CMakeLists.txt ├── buffer │ ├── buffer_pool_manager.cpp │ ├── clock_replacer.cpp │ └── lru_replacer.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 │ │ └── linear_probe_hash_table.cpp ├── execution │ ├── aggregation_executor.cpp │ ├── delete_executor.cpp │ ├── executor_factory.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 │ │ ├── clock_replacer.h │ │ ├── lru_replacer.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 │ │ │ ├── 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 │ │ │ ├── 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 │ │ │ ├── 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 │ │ │ ├── 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_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 │ │ ├── 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_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_test.cpp │ ├── clock_replacer_test.cpp │ ├── counter.h │ ├── grading_buffer_pool_manager_concurrency_test.cpp │ ├── grading_buffer_pool_manager_test.cpp │ ├── grading_leaderboard_test.cpp │ ├── grading_lru_replacer_test.cpp │ ├── lru_replacer_test.cpp │ └── mock_buffer_pool_manager.h ├── 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 ├── include │ ├── logging │ │ └── common.h │ └── storage │ │ └── b_plus_tree_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 │ ├── b_plus_tree_test_util.h │ ├── disk_manager_test.cpp │ ├── grading_b_plus_tree_bench_test.cpp │ ├── grading_b_plus_tree_checkpoint_1_test.cpp │ ├── grading_b_plus_tree_checkpoint_2_concurrent_test.cpp │ ├── grading_b_plus_tree_checkpoint_2_sequential_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 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: cpp 3 | matrix: 4 | fast_finish: true 5 | include: 6 | - os: osx 7 | osx_image: xcode10.1 8 | compiler: clang 9 | env: 10 | - NAME="macos-10.14/AppleClang-1001.0.46.4 (Debug/packages.sh)" CMAKE_BUILD_TYPE=debug 11 | install: 12 | - echo 'y' | ./build_support/packages.sh 13 | - export LLVM_DIR=/usr/local/Cellar/llvm/8.0.1 14 | - os: linux 15 | dist: trusty 16 | env: 17 | - NAME="ubuntu-18.04/gcc-7.3.0 (Debug/packages.sh)" CMAKE_BUILD_TYPE=debug DOCKER=true 18 | install: 19 | - docker pull ubuntu:18.04 20 | - docker run -itd --name build ubuntu:18.04 21 | - docker cp . build:/repo 22 | - docker exec build /bin/sh -c "echo 'y' | /repo/build_support/packages.sh" 23 | - os: linux 24 | dist: trusty 25 | env: 26 | - NAME="ubuntu-18.04/gcc-7.3.0 (Debug/Dockerfile)" CMAKE_BUILD_TYPE=debug DOCKER=true 27 | install: 28 | - docker build -t cmu-db/bustub . 29 | - docker run -itd --name build cmu-db/bustub 30 | - docker cp . build:/repo 31 | - os: linux 32 | dist: trusty 33 | env: 34 | - NAME="ubuntu-18.04/clang-8.0.0 (Debug/Dockerfile)" CMAKE_BUILD_TYPE=debug DOCKER=true 35 | install: 36 | - docker build -t cmu-db/bustub . 37 | - docker run -itd -e "CC=/usr/bin/clang-8" -e "CXX=/usr/bin/clang++-8" --name build cmu-db/bustub 38 | - docker cp . build:/repo 39 | 40 | before_script: 41 | - if [[ "$DOCKER" = true ]]; then 42 | docker exec build /bin/sh -c "mkdir -p /repo/build" && 43 | docker exec -e CMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" build /bin/sh -c "cd /repo/build && cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE .." && 44 | docker exec build /bin/sh -c "cd /repo/build && make check-format" && 45 | docker exec build /bin/sh -c "cd /repo/build && make check-lint" && 46 | docker exec build /bin/sh -c "cd /repo/build && make check-clang-tidy" && 47 | docker exec build /bin/sh -c "cd /repo/build && make check-tests"; 48 | else 49 | mkdir build && 50 | cd build && 51 | cmake -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE .. && 52 | make check-lint && 53 | make check-tests; 54 | fi 55 | 56 | script: 57 | - if [[ "$DOCKER" = true ]]; then 58 | docker exec build /bin/sh -c "cd /repo/build && make -j4"; 59 | else 60 | make -j4; 61 | fi 62 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## cmu-db的安装 2 | 3 | Database system project based on CMU 15-445/645 (FALL 2020) 4 | 5 | 参考:https://github.com/cmu-db/bustub/blob/master/README.md 6 | 7 | 8 | --- 9 | 10 | ### 克隆存储库 11 | 12 | github上新建一个仓库,名为`database-cmu15445-fall2020`。 13 | 14 | ```bash 15 | git clone git@github.com:cmu-db/bustub.git ./database-cmu15445-fall2020 16 | cd database-cmu15445-fall2020 17 | 18 | $ git reset --hard 444765a 19 | HEAD 现在位于 444765a Add PR template. (#156) 20 | 21 | git branch -m master main #本地分支重命名 22 | git remote rm origin #删除原仓库的远程分支 23 | git remote add origin git@github.com:nefu-ljw/database-cmu15445-fall2020.git #添加自己仓库作为远程分支 24 | 25 | #git remote add public git@github.com:cmu-db/bustub.git 26 | #git pull public master 27 | 28 | git push -u origin main 29 | ``` 30 | 31 | ### build 32 | 33 | 经测试,不支持CentOS,支持ubuntu 18.04或20.04。 34 | 35 | ```bash 36 | sudo build_support/packages.sh #自动安装BusTub需要的包(支持ubuntu 18.04或20.04) 37 | mkdir build 38 | cd build 39 | cmake -DCMAKE_BUILD_TYPE=Debug .. #调试模式 40 | make -j 8 41 | ``` 42 | -------------------------------------------------------------------------------- /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://github.com/cmu-db/bustub/raw/vagrant/build_support/packages.sh" 37 | s.args = "-y" 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /auto-archive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # filename: auto-archive.sh 4 | 5 | print_help() { 6 | echo "Please input correct project number." 7 | echo "" 8 | echo "Usage:" 9 | echo " $ sh auto-archive.sh \"project number\"" 10 | echo "" 11 | echo "Example:" 12 | echo " $ sh auto-archive.sh 0" 13 | echo "This will archive project 0." 14 | echo "" 15 | echo "Choices:" 16 | echo " 0 - Project#0 C++ Primer" 17 | echo " 1 - Project#1 Buffer Pool Manager" 18 | echo " 2 - Project#2 B+ Tree Index" 19 | echo " 3 - Project#3 Query Execution" 20 | echo " 4 - Project#4 Concurrency Control" 21 | } 22 | 23 | out="project$1-submission" 24 | if [ -f ./$out.zip ]; then 25 | rm $out.zip 26 | fi 27 | 28 | case $1 in 29 | 4) 30 | zip $out -urq \ 31 | src/concurrency/lock_manager.cpp \ 32 | src/include/concurrency/lock_manager.h 33 | ;; 34 | 3) 35 | zip $out -urq \ 36 | src/include/catalog/catalog.h \ 37 | src/include/execution/execution_engine.h \ 38 | src/include/execution/executor_factory.h \ 39 | src/include/execution/executors/seq_scan_executor.h \ 40 | src/include/execution/executors/index_scan_executor.h \ 41 | src/include/execution/executors/insert_executor.h \ 42 | src/include/execution/executors/update_executor.h \ 43 | src/include/execution/executors/delete_executor.h \ 44 | src/include/execution/executors/nested_loop_join_executor.h \ 45 | src/include/execution/executors/nested_index_join_executor.h \ 46 | src/include/execution/executors/limit_executor.h \ 47 | src/include/execution/executors/aggregation_executor.h \ 48 | src/include/storage/index/b_plus_tree_index.h \ 49 | src/include/storage/index/index.h \ 50 | src/execution/executor_factory.cpp \ 51 | src/execution/seq_scan_executor.cpp \ 52 | src/execution/index_scan_executor.cpp \ 53 | src/execution/insert_executor.cpp \ 54 | src/execution/update_executor.cpp \ 55 | src/execution/delete_executor.cpp \ 56 | src/execution/nested_loop_join_executor.cpp \ 57 | src/execution/nested_index_join_executor.cpp \ 58 | src/execution/limit_executor.cpp \ 59 | src/execution/aggregation_executor.cpp \ 60 | src/storage/index/b_plus_tree_index.cpp 61 | ;; 62 | 2) 63 | zip $out -urq \ 64 | src/include/storage/page/b_plus_tree_page.h \ 65 | src/storage/page/b_plus_tree_page.cpp \ 66 | src/include/storage/page/b_plus_tree_internal_page.h \ 67 | src/storage/page/b_plus_tree_internal_page.cpp \ 68 | src/include/storage/page/b_plus_tree_leaf_page.h \ 69 | src/storage/page/b_plus_tree_leaf_page.cpp \ 70 | src/include/storage/index/b_plus_tree.h \ 71 | src/storage/index/b_plus_tree.cpp \ 72 | src/include/storage/index/index_iterator.h \ 73 | src/storage/index/index_iterator.cpp 74 | ;; 75 | 1) 76 | zip $out -urq \ 77 | src/include/buffer/lru_replacer.h \ 78 | src/buffer/lru_replacer.cpp \ 79 | src/include/buffer/buffer_pool_manager.h \ 80 | src/buffer/buffer_pool_manager.cpp 81 | ;; 82 | 0) 83 | zip $out -urq src/include/primer/p0_starter.h 84 | ;; 85 | *) 86 | # echo "Invalid input: $1\n" 87 | print_help 88 | exit 1 89 | ;; 90 | esac 91 | echo "Files has been writen into $out.zip" 92 | unzip -l $out.zip 93 | -------------------------------------------------------------------------------- /build_support/clang_format_exclusions.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nefu-ljw/database-cmu15445-fall2020/9744b3cd460e1592ea681d60734d3753239cbaca/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 | -------------------------------------------------------------------------------- /doc-generator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf ./doc 4 | mkdir doc 5 | cd doc 6 | 7 | cp -r ../src ./ 8 | doxygen -g Doxygen.config # 生成配置文件 9 | 10 | # 修改配置文件 sed -i 11 | sed -i '867c RECURSIVE = YES' Doxygen.config 12 | sed -i '35c PROJECT_NAME = "CMU Project"' Doxygen.config 13 | 14 | doxygen Doxygen.config # 根据代码生成文档 15 | 16 | rm -rf ./src 17 | 18 | # 打包 19 | zip -r doc.zip ./ 20 | 21 | -------------------------------------------------------------------------------- /project1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | zip -r project1.zip \ 3 | src/include/buffer/lru_replacer.h \ 4 | src/buffer/lru_replacer.cpp \ 5 | src/include/buffer/buffer_pool_manager.h \ 6 | src/buffer/buffer_pool_manager.cpp 7 | -------------------------------------------------------------------------------- /project2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | zip -r project2.zip \ 3 | src/include/buffer/lru_replacer.h \ 4 | src/buffer/lru_replacer.cpp \ 5 | src/include/buffer/buffer_pool_manager.h \ 6 | src/buffer/buffer_pool_manager.cpp \ 7 | src/include/storage/page/b_plus_tree_page.h \ 8 | src/storage/page/b_plus_tree_page.cpp \ 9 | src/include/storage/page/b_plus_tree_internal_page.h \ 10 | src/storage/page/b_plus_tree_internal_page.cpp \ 11 | src/include/storage/page/b_plus_tree_leaf_page.h \ 12 | src/storage/page/b_plus_tree_leaf_page.cpp \ 13 | src/include/storage/index/b_plus_tree.h \ 14 | src/storage/index/b_plus_tree.cpp \ 15 | src/include/storage/index/index_iterator.h \ 16 | src/storage/index/index_iterator.cpp 17 | -------------------------------------------------------------------------------- /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) { max_size = num_pages; } 18 | 19 | LRUReplacer::~LRUReplacer() = default; // 在project2中,不需要修改折构函数 20 | 21 | /** 22 | * 使用LRU策略删除一个victim frame,这个函数能得到frame_id 23 | * @param[out] frame_id id of frame that was removed, nullptr if no victim was found 24 | * @return true if a victim frame was found, false otherwise 25 | */ 26 | bool LRUReplacer::Victim(frame_id_t *frame_id) { 27 | // C++17 std::scoped_lock 28 | // 它能够避免死锁发生,其构造函数能够自动进行上锁操作,析构函数会对互斥量进行解锁操作,保证线程安全。 29 | std::scoped_lock lock{mut}; 30 | if (LRUlist.empty()) { 31 | // frame_id = nullptr; 32 | return false; 33 | } 34 | // lista,那么a.back()取出的是int类型 35 | *frame_id = LRUlist.back(); // 取出最后一个给frame_id(对传入的参数进行修改) 36 | LRUhash.erase(*frame_id); // 哈希表中删除其映射关系 37 | // 以上均要加*,才能改变函数外调用时传入的参数 38 | LRUlist.pop_back(); // 链表中删除最后一个 39 | return true; 40 | } 41 | 42 | /** 43 | * 固定一个frame, 表明它不应该成为victim(即在replacer中移除该frame_id) 44 | * @param frame_id the id of the frame to pin 45 | */ 46 | void LRUReplacer::Pin(frame_id_t frame_id) { 47 | std::scoped_lock lock{mut}; 48 | // 哈希表中找不到该frame_id 49 | if (LRUhash.count(frame_id) == 0) { 50 | return; 51 | } 52 | auto iter = LRUhash[frame_id]; 53 | LRUlist.erase(iter); 54 | LRUhash.erase(frame_id); 55 | } 56 | 57 | /** 58 | * 取消固定一个frame, 表明它可以成为victim(即将该frame_id添加到replacer) 59 | * @param frame_id the id of the frame to unpin 60 | */ 61 | void LRUReplacer::Unpin(frame_id_t frame_id) { 62 | std::scoped_lock lock{mut}; 63 | // 哈希表中已有该frame_id,直接退出,避免重复添加到replacer 64 | if (LRUhash.count(frame_id) != 0) { 65 | return; 66 | } 67 | // 已达最大容量,无法添加到replacer 68 | if (LRUlist.size() == max_size) { 69 | return; 70 | } 71 | // 正常添加到replacer 72 | LRUlist.push_front(frame_id); // 注意是添加到首部还是尾部呢? 73 | // 首部是最近被使用,尾部是最久未被使用 74 | LRUhash.emplace(frame_id, LRUlist.begin()); 75 | } 76 | 77 | /** @return replacer中能够victim的数量 */ 78 | size_t LRUReplacer::Size() { return LRUlist.size(); } 79 | 80 | } // namespace bustub 81 | -------------------------------------------------------------------------------- /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 | void LockManager::AddEdge(txn_id_t t1, txn_id_t t2) {} 43 | 44 | void LockManager::RemoveEdge(txn_id_t t1, txn_id_t t2) {} 45 | 46 | bool LockManager::HasCycle(txn_id_t *txn_id) { return false; } 47 | 48 | std::vector> LockManager::GetEdgeList() { return {}; } 49 | 50 | void LockManager::RunCycleDetection() { 51 | while (enable_cycle_detection_) { 52 | std::this_thread::sleep_for(cycle_detection_interval); 53 | { 54 | std::unique_lock l(latch_); 55 | // TODO(student): remove the continue and add your cycle detection and abort code here 56 | continue; 57 | } 58 | } 59 | } 60 | 61 | } // namespace bustub 62 | -------------------------------------------------------------------------------- /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-19, 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 | 23 | const AbstractExecutor *AggregationExecutor::GetChildExecutor() const { return child_.get(); } 24 | 25 | void AggregationExecutor::Init() {} 26 | 27 | bool AggregationExecutor::Next(Tuple *tuple, RID *rid) { return false; } 28 | 29 | } // namespace bustub 30 | -------------------------------------------------------------------------------- /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-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include 13 | 14 | #include "execution/executors/delete_executor.h" 15 | 16 | namespace bustub { 17 | 18 | DeleteExecutor::DeleteExecutor(ExecutorContext *exec_ctx, const DeletePlanNode *plan, 19 | std::unique_ptr &&child_executor) 20 | : AbstractExecutor(exec_ctx) {} 21 | 22 | void DeleteExecutor::Init() {} 23 | 24 | bool DeleteExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { return false; } 25 | 26 | } // namespace bustub 27 | -------------------------------------------------------------------------------- /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-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include 13 | 14 | #include "execution/executors/insert_executor.h" 15 | 16 | namespace bustub { 17 | 18 | InsertExecutor::InsertExecutor(ExecutorContext *exec_ctx, const InsertPlanNode *plan, 19 | std::unique_ptr &&child_executor) 20 | : AbstractExecutor(exec_ctx) {} 21 | 22 | void InsertExecutor::Init() {} 23 | 24 | bool InsertExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { return false; } 25 | 26 | } // namespace bustub 27 | -------------------------------------------------------------------------------- /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-19, 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 | 21 | void LimitExecutor::Init() {} 22 | 23 | bool LimitExecutor::Next(Tuple *tuple, RID *rid) { return false; } 24 | 25 | } // namespace bustub 26 | -------------------------------------------------------------------------------- /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-19, 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 | 22 | void NestedLoopJoinExecutor::Init() {} 23 | 24 | bool NestedLoopJoinExecutor::Next(Tuple *tuple, RID *rid) { return false; } 25 | 26 | } // namespace bustub 27 | -------------------------------------------------------------------------------- /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-19, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | #include "execution/executors/seq_scan_executor.h" 13 | 14 | namespace bustub { 15 | 16 | SeqScanExecutor::SeqScanExecutor(ExecutorContext *exec_ctx, const SeqScanPlanNode *plan) : AbstractExecutor(exec_ctx) {} 17 | 18 | void SeqScanExecutor::Init() {} 19 | 20 | bool SeqScanExecutor::Next(Tuple *tuple, RID *rid) { return false; } 21 | 22 | } // namespace bustub 23 | -------------------------------------------------------------------------------- /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-20, 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 | 22 | void UpdateExecutor::Init() {} 23 | 24 | bool UpdateExecutor::Next([[maybe_unused]] Tuple *tuple, RID *rid) { return false; } 25 | } // namespace bustub 26 | -------------------------------------------------------------------------------- /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-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #include 16 | #include // NOLINT 包含std::mutex、std::scoped_lock 17 | #include 18 | 19 | #include "buffer/replacer.h" 20 | #include "common/config.h" 21 | #include "unordered_map" 22 | 23 | /* PROJECT #1 - BUFFER POOL | TASK #1 - LRU REPLACEMENT POLICY 24 | LRUReplacer的大小与缓冲池相同,因为它包含BufferPoolManager中所有帧的占位符。 25 | LRUReplacer被初始化为没有frame。在LRUReplacer中只会考虑新取消固定的frame。 26 | 实现课程中讨论的LRU策略,实现以下方法: 27 | 1. Victim(T*): Replacer跟踪与所有元素相比最近最少访问的对象并删除,将其页号存储在输出参数中并返回True,为空则返回False。 28 | 2. Pin(T):在将page固定到BufferPoolManager中的frame后,应调用此方法。它应该从LRUReplacer中删除包含固定page的frame。 29 | 3. Unpin(T):当page的pin_count变为0时应调用此方法。此方法应将包含未固定page的frame添加到LRUReplacer。 30 | 4. Size():此方法返回当前在LRUReplacer中的frame数量。 31 | 实现细节由您决定。您可以使用内置的STL容器。您可以假设不会耗尽内存,但必须确保操作是线程安全的。 32 | */ 33 | 34 | namespace bustub { 35 | 36 | /** 37 | * LRUReplacer implements the lru replacement policy, which approximates the Least Recently Used policy. 38 | */ 39 | class LRUReplacer : public Replacer { 40 | public: 41 | /** 42 | * Create a new LRUReplacer. 43 | * @param num_pages the maximum number of pages the LRUReplacer will be required to store 44 | */ 45 | explicit LRUReplacer(size_t num_pages); 46 | // explicit关键字只能用来修饰类内部的构造函数声明,作用于单个参数的构造函数;被修饰的构造函数的类,不能发生相应的隐式类型转换。 47 | 48 | /** 49 | * Destroys the LRUReplacer. 50 | */ 51 | ~LRUReplacer() override; 52 | 53 | bool Victim(frame_id_t *frame_id) override; 54 | 55 | void Pin(frame_id_t frame_id) override; 56 | 57 | void Unpin(frame_id_t frame_id) override; 58 | 59 | size_t Size() override; 60 | 61 | private: 62 | // TODO(student): implement me! 63 | std::mutex mut; // 信号量 64 | std::list LRUlist; // 双向链表,存放frame_id_t 65 | std::unordered_map::iterator> LRUhash; // 哈希表,frame_id_t->链表迭代器 66 | size_t max_size; // 最大容量 67 | }; 68 | 69 | } // namespace bustub 70 | -------------------------------------------------------------------------------- /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/catalog/table_generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "catalog/catalog.h" 7 | #include "execution/executor_context.h" 8 | #include "storage/table/table_heap.h" 9 | 10 | namespace bustub { 11 | 12 | static constexpr uint32_t TEST1_SIZE = 1000; 13 | static constexpr uint32_t TEST2_SIZE = 100; 14 | static constexpr uint32_t TEST_VARLEN_SIZE = 10; 15 | 16 | class TableGenerator { 17 | public: 18 | /** 19 | * Constructor 20 | */ 21 | explicit TableGenerator(ExecutorContext *exec_ctx) : exec_ctx_{exec_ctx} {} 22 | 23 | /** 24 | * Generate test tables. 25 | */ 26 | void GenerateTestTables(); 27 | 28 | private: 29 | /** 30 | * Enumeration to characterize the distribution of values in a given column 31 | */ 32 | enum class Dist : uint8_t { Uniform, Zipf_50, Zipf_75, Zipf_95, Zipf_99, Serial }; 33 | 34 | /** 35 | * Metadata about the data for a given column. Specifically, the type of the 36 | * column, the distribution of values, a min and max if appropriate. 37 | */ 38 | struct ColumnInsertMeta { 39 | /** 40 | * Name of the column 41 | */ 42 | const char *name_; 43 | /** 44 | * Type of the column 45 | */ 46 | const TypeId type_; 47 | /** 48 | * Whether the column is nullable 49 | */ 50 | bool nullable_; 51 | /** 52 | * Distribution of values 53 | */ 54 | Dist dist_; 55 | /** 56 | * Min value of the column 57 | */ 58 | uint64_t min_; 59 | /** 60 | * Max value of the column 61 | */ 62 | uint64_t max_; 63 | /** 64 | * Counter to generate serial data 65 | */ 66 | uint64_t serial_counter_{0}; 67 | 68 | /** 69 | * Constructor 70 | */ 71 | ColumnInsertMeta(const char *name, const TypeId type, bool nullable, Dist dist, uint64_t min, uint64_t max) 72 | : name_(name), type_(type), nullable_(nullable), dist_(dist), min_(min), max_(max) {} 73 | }; 74 | 75 | /** 76 | * Metadata about a table. Specifically, the schema and number of 77 | * rows in the table. 78 | */ 79 | struct TableInsertMeta { 80 | /** 81 | * Name of the table 82 | */ 83 | const char *name_; 84 | /** 85 | * Number of rows 86 | */ 87 | uint32_t num_rows_; 88 | /** 89 | * Columns 90 | */ 91 | std::vector col_meta_; 92 | 93 | /** 94 | * Constructor 95 | */ 96 | TableInsertMeta(const char *name, uint32_t num_rows, std::vector col_meta) 97 | : name_(name), num_rows_(num_rows), col_meta_(std::move(col_meta)) {} 98 | }; 99 | 100 | void FillTable(TableMetadata *info, TableInsertMeta *table_meta); 101 | 102 | std::vector MakeValues(ColumnInsertMeta *col_meta, uint32_t count); 103 | 104 | template 105 | std::vector GenNumericValues(ColumnInsertMeta *col_meta, uint32_t count); 106 | 107 | private: 108 | ExecutorContext *exec_ctx_; 109 | }; 110 | } // namespace bustub 111 | -------------------------------------------------------------------------------- /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.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 BufferPoolManager(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-2019, 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 | class ExecutionEngine { 26 | public: 27 | ExecutionEngine(BufferPoolManager *bpm, TransactionManager *txn_mgr, Catalog *catalog) 28 | : bpm_(bpm), txn_mgr_(txn_mgr), catalog_(catalog) {} 29 | 30 | DISALLOW_COPY_AND_MOVE(ExecutionEngine); 31 | 32 | bool Execute(const AbstractPlanNode *plan, std::vector *result_set, Transaction *txn, 33 | ExecutorContext *exec_ctx) { 34 | // construct executor 35 | auto executor = ExecutorFactory::CreateExecutor(exec_ctx, plan); 36 | 37 | // prepare 38 | executor->Init(); 39 | 40 | // execute 41 | try { 42 | Tuple tuple; 43 | RID rid; 44 | while (executor->Next(&tuple, &rid)) { 45 | if (result_set != nullptr) { 46 | result_set->push_back(tuple); 47 | } 48 | } 49 | } catch (Exception &e) { 50 | // TODO(student): handle exceptions 51 | } 52 | 53 | return true; 54 | } 55 | 56 | private: 57 | [[maybe_unused]] BufferPoolManager *bpm_; 58 | [[maybe_unused]] TransactionManager *txn_mgr_; 59 | [[maybe_unused]] Catalog *catalog_; 60 | }; 61 | 62 | } // namespace bustub 63 | -------------------------------------------------------------------------------- /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-2019, 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 should use 33 | * @param bpm the buffer pool manager that the executor should use 34 | * @param txn_mgr the transaction manager that the executor should use 35 | * @param lock_mgr the lock manager that the executor should use 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 | DISALLOW_COPY_AND_MOVE(ExecutorContext); 42 | 43 | ~ExecutorContext() = default; 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 | Transaction *transaction_; 65 | Catalog *catalog_; 66 | BufferPoolManager *bpm_; 67 | TransactionManager *txn_mgr_; 68 | LockManager *lock_mgr_; 69 | }; 70 | 71 | } // namespace bustub 72 | -------------------------------------------------------------------------------- /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-2019, 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 and 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-19, 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 | * AbstractExecutor implements the Volcano tuple-at-a-time iterator model. 21 | */ 22 | class AbstractExecutor { 23 | public: 24 | /** 25 | * Constructs a new AbstractExecutor. 26 | * @param exec_ctx the executor context that the executor runs with 27 | */ 28 | explicit AbstractExecutor(ExecutorContext *exec_ctx) : exec_ctx_{exec_ctx} {} 29 | 30 | /** Virtual destructor. */ 31 | virtual ~AbstractExecutor() = default; 32 | 33 | /** 34 | * Initializes this executor. 35 | * @warning This function must be called before Next() is called! 36 | */ 37 | virtual void Init() = 0; 38 | 39 | /** 40 | * Produces the next tuple from this executor. 41 | * @param[out] tuple the next tuple produced by this executor 42 | * @param[out] rid the next tuple rid produced by this executor 43 | * @return true if a tuple was produced, false if there are no more tuples 44 | */ 45 | virtual bool Next(Tuple *tuple, RID *rid) = 0; 46 | 47 | /** @return the schema of the tuples that this executor produces */ 48 | virtual const Schema *GetOutputSchema() = 0; 49 | 50 | /** @return the executor context in which this executor runs */ 51 | ExecutorContext *GetExecutorContext() { return exec_ctx_; } 52 | 53 | protected: 54 | ExecutorContext *exec_ctx_; 55 | }; 56 | } // namespace bustub 57 | -------------------------------------------------------------------------------- /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 | * Delete executes a delete from a table. 27 | * Deleted tuple info come from a child executor. 28 | */ 29 | class DeleteExecutor : public AbstractExecutor { 30 | public: 31 | /** 32 | * Creates a new delete executor. 33 | * @param exec_ctx the executor context 34 | * @param plan the delete plan to be executed 35 | * @param child_executor the child executor (either sequential scan or index scan) to obtain tuple info 36 | */ 37 | DeleteExecutor(ExecutorContext *exec_ctx, const DeletePlanNode *plan, 38 | std::unique_ptr &&child_executor); 39 | 40 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 41 | 42 | void Init() override; 43 | 44 | // Note that Delete does not make use of the tuple pointer being passed in. 45 | // We throw exception if the delete failed for any reason, and return false if all delete succeeded. 46 | // Delete from indexes if necessary. 47 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 48 | 49 | private: 50 | /** The delete plan node to be executed. */ 51 | const DeletePlanNode *plan_; 52 | /** The child executor to obtain rid from. */ 53 | std::unique_ptr child_executor_; 54 | }; 55 | } // namespace bustub 56 | -------------------------------------------------------------------------------- /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-19, 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 | * InsertExecutor executes an insert into a table. 26 | * Inserted values can either be embedded in the plan itself ("raw insert") or come from a child executor. 27 | */ 28 | class InsertExecutor : public AbstractExecutor { 29 | public: 30 | /** 31 | * Creates a new insert executor. 32 | * @param exec_ctx the executor context 33 | * @param plan the insert plan to be executed 34 | * @param child_executor the child executor to obtain insert values from, can be nullptr 35 | */ 36 | InsertExecutor(ExecutorContext *exec_ctx, const InsertPlanNode *plan, 37 | std::unique_ptr &&child_executor); 38 | 39 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 40 | 41 | void Init() override; 42 | 43 | // Note that Insert does not make use of the tuple pointer being passed in. 44 | // We return false if the insert failed for any reason, and return true if all inserts succeeded. 45 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 46 | 47 | private: 48 | /** The insert plan node to be executed. */ 49 | const InsertPlanNode *plan_; 50 | }; 51 | } // namespace bustub 52 | -------------------------------------------------------------------------------- /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-19, 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 | * LimitExecutor limits the number of output tuples with an optional offset. 24 | */ 25 | class LimitExecutor : public AbstractExecutor { 26 | public: 27 | /** 28 | * Creates a new limit executor. 29 | * @param exec_ctx the executor context 30 | * @param plan the limit plan to be executed 31 | * @param child_executor the child executor that produces tuple 32 | */ 33 | LimitExecutor(ExecutorContext *exec_ctx, const LimitPlanNode *plan, 34 | std::unique_ptr &&child_executor); 35 | 36 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 37 | 38 | void Init() override; 39 | 40 | bool Next(Tuple *tuple, RID *rid) override; 41 | 42 | private: 43 | /** The limit plan node to be executed. */ 44 | const LimitPlanNode *plan_; 45 | /** The child executor to obtain value from. */ 46 | std::unique_ptr child_executor_; 47 | }; 48 | } // namespace bustub 49 | -------------------------------------------------------------------------------- /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-19, 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 | * NestedLoopJoinExecutor joins two tables using nested loop. 26 | * The child executor can either be a sequential scan 27 | */ 28 | class NestedLoopJoinExecutor : public AbstractExecutor { 29 | public: 30 | /** 31 | * Creates a new NestedLoop join executor. 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 | */ 38 | NestedLoopJoinExecutor(ExecutorContext *exec_ctx, const NestedLoopJoinPlanNode *plan, 39 | std::unique_ptr &&left_executor, 40 | std::unique_ptr &&right_executor); 41 | 42 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 43 | 44 | void Init() override; 45 | 46 | bool Next(Tuple *tuple, RID *rid) override; 47 | 48 | private: 49 | /** The NestedLoop plan node to be executed. */ 50 | const NestedLoopJoinPlanNode *plan_; 51 | }; 52 | } // namespace bustub 53 | -------------------------------------------------------------------------------- /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-19, 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 | * SeqScanExecutor executes a sequential scan over a table. 26 | */ 27 | class SeqScanExecutor : public AbstractExecutor { 28 | public: 29 | /** 30 | * Creates a new sequential scan executor. 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 | void Init() override; 37 | 38 | bool Next(Tuple *tuple, RID *rid) override; 39 | 40 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); } 41 | 42 | private: 43 | /** The sequential scan plan node to be executed. */ 44 | const SeqScanPlanNode *plan_; 45 | }; 46 | } // namespace bustub 47 | -------------------------------------------------------------------------------- /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-20, 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 in a table. 29 | * Updated values from a child executor. 30 | */ 31 | class UpdateExecutor : public AbstractExecutor { 32 | friend class UpdatePlanNode; 33 | 34 | public: 35 | /** 36 | * Creates a new update executor. 37 | * @param exec_ctx the executor context 38 | * @param plan the update plan to be executed 39 | */ 40 | UpdateExecutor(ExecutorContext *exec_ctx, const UpdatePlanNode *plan, 41 | std::unique_ptr &&child_executor); 42 | 43 | const Schema *GetOutputSchema() override { return plan_->OutputSchema(); }; 44 | 45 | void Init() override; 46 | 47 | bool Next([[maybe_unused]] Tuple *tuple, RID *rid) override; 48 | 49 | /* 50 | * Given an old tuple, creates a new updated tuple based on the updateinfo given in the plan 51 | * @param old_tup the tuple to be updated 52 | */ 53 | Tuple GenerateUpdatedTuple(const Tuple &old_tup) { 54 | auto update_attrs = plan_->GetUpdateAttr(); 55 | Schema schema = table_info_->schema_; 56 | uint32_t col_count = schema.GetColumnCount(); 57 | std::vector values; 58 | for (uint32_t idx = 0; idx < col_count; idx++) { 59 | if (update_attrs->find(idx) == update_attrs->end()) { 60 | values.emplace_back(old_tup.GetValue(&schema, idx)); 61 | } else { 62 | UpdateInfo info = update_attrs->at(idx); 63 | Value val = old_tup.GetValue(&schema, idx); 64 | switch (info.type_) { 65 | case UpdateType::Add: 66 | values.emplace_back(val.Add(ValueFactory::GetIntegerValue(info.update_val_))); 67 | break; 68 | 69 | case UpdateType::Set: 70 | values.emplace_back(ValueFactory::GetIntegerValue(info.update_val_)); 71 | break; 72 | } 73 | } 74 | } 75 | return Tuple(values, &schema); 76 | } 77 | 78 | private: 79 | /** The update plan node to be executed. */ 80 | const UpdatePlanNode *plan_; 81 | /** Metadata identifying the table that should be updated. */ 82 | const TableMetadata *table_info_; 83 | /** The child executor to obtain value from. */ 84 | std::unique_ptr child_executor_; 85 | }; 86 | } // namespace bustub 87 | -------------------------------------------------------------------------------- /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-19, 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-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 | 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 | Value Evaluate(const Tuple *tuple, const Schema *schema) const override { 37 | BUSTUB_ASSERT(false, "Aggregation should only refer to group-by and aggregates."); 38 | } 39 | 40 | Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 41 | const Schema *right_schema) const override { 42 | BUSTUB_ASSERT(false, "Aggregation should only refer to group-by and aggregates."); 43 | } 44 | 45 | Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const override { 46 | return is_group_by_term_ ? group_bys[term_idx_] : aggregates[term_idx_]; 47 | } 48 | 49 | private: 50 | bool is_group_by_term_; 51 | uint32_t term_idx_; 52 | }; 53 | } // namespace bustub 54 | -------------------------------------------------------------------------------- /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 | namespace bustub { 22 | /** 23 | * ColumnValueExpression maintains the tuple index and column index relative to a particular schema or join. 24 | */ 25 | class ColumnValueExpression : public AbstractExpression { 26 | public: 27 | /** 28 | * ColumnValueExpression is an abstraction around "Table.member" in terms of indexes. 29 | * @param tuple_idx {tuple index 0 = left side of join, tuple index 1 = right side of join} 30 | * @param col_idx the index of the column in the schema 31 | * @param ret_type the return type of the expression 32 | */ 33 | ColumnValueExpression(uint32_t tuple_idx, uint32_t col_idx, TypeId ret_type) 34 | : AbstractExpression({}, ret_type), tuple_idx_{tuple_idx}, col_idx_{col_idx} {} 35 | 36 | Value Evaluate(const Tuple *tuple, const Schema *schema) const override { return tuple->GetValue(schema, col_idx_); } 37 | 38 | Value EvaluateJoin(const Tuple *left_tuple, const Schema *left_schema, const Tuple *right_tuple, 39 | const Schema *right_schema) const override { 40 | return tuple_idx_ == 0 ? left_tuple->GetValue(left_schema, col_idx_) 41 | : right_tuple->GetValue(right_schema, col_idx_); 42 | } 43 | 44 | Value EvaluateAggregate(const std::vector &group_bys, const std::vector &aggregates) const override { 45 | BUSTUB_ASSERT(false, "Aggregation should only refer to group-by and aggregates."); 46 | } 47 | 48 | uint32_t GetTupleIdx() const { return tuple_idx_; } 49 | uint32_t GetColIdx() const { return col_idx_; } 50 | 51 | private: 52 | /** Tuple index 0 = left side of join, tuple index 1 = right side of join */ 53 | uint32_t tuple_idx_; 54 | /** Column index refers to the index within the schema of the tuple, e.g. schema {A,B,C} has indexes {0,1,2} */ 55 | uint32_t col_idx_; 56 | }; 57 | } // namespace bustub 58 | -------------------------------------------------------------------------------- /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 { SeqScan, IndexScan, Insert, Update, Delete, Aggregation, Limit, NestedLoopJoin, NestedIndexJoin }; 24 | 25 | /** 26 | * AbstractPlanNode represents all the possible types of plan nodes in our system. 27 | * Plan nodes are modeled as trees, so each plan node can have a variable number of children. 28 | * Per the Volcano model, the plan node receives the tuples of its children. 29 | * The ordering of the children may matter. 30 | */ 31 | class AbstractPlanNode { 32 | public: 33 | /** 34 | * Create a new AbstractPlanNode with the specified output schema and children. 35 | * @param output_schema the schema for the output of this plan node 36 | * @param children the children of this plan node 37 | */ 38 | AbstractPlanNode(const Schema *output_schema, std::vector &&children) 39 | : output_schema_(output_schema), children_(std::move(children)) {} 40 | 41 | /** Virtual destructor. */ 42 | virtual ~AbstractPlanNode() = default; 43 | 44 | /** @return the schema for the output of this plan node */ 45 | const Schema *OutputSchema() const { return output_schema_; } 46 | 47 | /** @return the child of this plan node at index child_idx */ 48 | const AbstractPlanNode *GetChildAt(uint32_t child_idx) const { return children_[child_idx]; } 49 | 50 | /** @return the children of this plan node */ 51 | const std::vector &GetChildren() const { return children_; } 52 | 53 | /** @return the type of this plan node */ 54 | virtual PlanType GetType() const = 0; 55 | 56 | private: 57 | /** 58 | * The schema for the output of this plan node. In the volcano model, every plan node will spit out tuples, 59 | * and this tells you what schema this plan node's tuples will have. 60 | */ 61 | const Schema *output_schema_; 62 | /** The children of this plan node. */ 63 | std::vector children_; 64 | }; 65 | } // namespace bustub 66 | -------------------------------------------------------------------------------- /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-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 | * DeletePlanNode identifies a table that should be deleted from. 22 | * The tuple/tuples to be deleted come from the child of the DeletedPlanNode. The child could either be an index scan 23 | * or a seq scan. To simplify the assignment, DeletePlanNode has at most one child. 24 | */ 25 | class DeletePlanNode : public AbstractPlanNode { 26 | public: 27 | /** 28 | * Creates a new delete plan node that has a child plan. 29 | * @param child the child plan to obtain tuple from 30 | * @param table_oid the identifier of the table that should be deleted from 31 | */ 32 | DeletePlanNode(const AbstractPlanNode *child, table_oid_t table_oid) 33 | : AbstractPlanNode(nullptr, {child}), table_oid_(table_oid) {} 34 | 35 | PlanType GetType() const override { return PlanType::Delete; } 36 | 37 | /** @return the identifier of the table that should be deleted from */ 38 | table_oid_t TableOid() const { return table_oid_; } 39 | 40 | /** @return the child plan providing tuples to be inserted */ 41 | const AbstractPlanNode *GetChildPlan() const { 42 | BUSTUB_ASSERT(GetChildren().size() == 1, "delete should have at most one child plan."); 43 | return GetChildAt(0); 44 | } 45 | 46 | private: 47 | /** The table to be deleted from. */ 48 | table_oid_t table_oid_; 49 | }; 50 | } // namespace bustub 51 | -------------------------------------------------------------------------------- /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-19, 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 | * Limit constraints the number of output tuples produced by its child executor. The offset indicates the number 20 | * of rows to be skipped before returning. 21 | */ 22 | class LimitPlanNode : public AbstractPlanNode { 23 | public: 24 | /** 25 | * Creates a new limit plan node that has a child plan. 26 | * @param child the child plan to obtain tuple from 27 | * @param limit the number of output tuples 28 | * @param offset the number of rows to be skipped 29 | */ 30 | LimitPlanNode(const Schema *output_schema, const AbstractPlanNode *child, size_t limit, size_t offset) 31 | : AbstractPlanNode(output_schema, {child}), limit_(limit), offset_(offset) {} 32 | 33 | PlanType GetType() const override { return PlanType::Limit; } 34 | 35 | size_t GetLimit() const { return limit_; } 36 | 37 | size_t GetOffset() const { return offset_; } 38 | 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 | size_t limit_; 46 | size_t offset_; 47 | }; 48 | } // namespace bustub 49 | -------------------------------------------------------------------------------- /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-19, 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 | * NestedLoopJoinPlanNode joins tuples that come from two sequential scan 25 | */ 26 | class NestedLoopJoinPlanNode : public AbstractPlanNode { 27 | public: 28 | /** 29 | * Creates a new nested loop join plan node. 30 | * @param output the output format of this nested loop join node 31 | * @param children two sequential scan children plans 32 | * @param predicate the predicate to join with, the tuples are joined if predicate(tuple) = true or predicate = 33 | * nullptr 34 | */ 35 | NestedLoopJoinPlanNode(const Schema *output_schema, std::vector &&children, 36 | const AbstractExpression *predicate) 37 | : AbstractPlanNode(output_schema, std::move(children)), predicate_(predicate) {} 38 | 39 | PlanType GetType() const override { return PlanType::NestedLoopJoin; } 40 | 41 | /** @return the predicate to be used in the nested loop join */ 42 | const AbstractExpression *Predicate() const { return predicate_; } 43 | 44 | /** @return the left plan node of the nested loop join, by convention it should be the smaller table*/ 45 | const AbstractPlanNode *GetLeftPlan() const { 46 | BUSTUB_ASSERT(GetChildren().size() == 2, "Nested loop joins should have exactly two children plans."); 47 | return GetChildAt(0); 48 | } 49 | 50 | /** @return the right plan node of the nested loop join */ 51 | const AbstractPlanNode *GetRightPlan() const { 52 | BUSTUB_ASSERT(GetChildren().size() == 2, "Nested loop joins should have exactly two children plans."); 53 | return GetChildAt(1); 54 | } 55 | 56 | private: 57 | /** The join predicate. */ 58 | const AbstractExpression *predicate_; 59 | }; 60 | 61 | } // namespace bustub 62 | -------------------------------------------------------------------------------- /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-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 | * SeqScanPlanNode identifies a table that should be scanned with an optional predicate. 22 | */ 23 | class SeqScanPlanNode : public AbstractPlanNode { 24 | public: 25 | /** 26 | * Creates a new sequential 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 = nullptr 29 | * @param table_oid the identifier of table to be scanned 30 | */ 31 | SeqScanPlanNode(const Schema *output, const AbstractExpression *predicate, table_oid_t table_oid) 32 | : AbstractPlanNode(output, {}), predicate_{predicate}, table_oid_(table_oid) {} 33 | 34 | PlanType GetType() const override { return PlanType::SeqScan; } 35 | 36 | /** @return the predicate to test tuples against; tuples should only be returned if they evaluate to true */ 37 | const AbstractExpression *GetPredicate() const { return predicate_; } 38 | 39 | /** @return the identifier of the table that should be scanned */ 40 | table_oid_t GetTableOid() const { return table_oid_; } 41 | 42 | private: 43 | /** The predicate that all returned tuples must satisfy. */ 44 | const AbstractExpression *predicate_; 45 | /** The table whose tuples should be scanned. */ 46 | table_oid_t table_oid_; 47 | }; 48 | 49 | } // namespace bustub 50 | -------------------------------------------------------------------------------- /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-20, 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 | enum class UpdateType { Add, Set }; 24 | 25 | /** 26 | * Metadata about an Update. 27 | */ 28 | struct UpdateInfo { 29 | UpdateInfo(UpdateType type, int update_val) : type_(type), update_val_(update_val) {} 30 | UpdateType type_; 31 | int update_val_; 32 | }; 33 | 34 | /** 35 | * UpdatePlannode identifies a table that should be updated. 36 | * The tuple/tuples to be updated come from the child of the UpdatePlanNode. The child could either be an index scan 37 | * or a seq scan. To simplify the assignment, UpdatePlannode has at most one child. 38 | */ 39 | class UpdatePlanNode : public AbstractPlanNode { 40 | public: 41 | /** 42 | * Creates a new update plan node that has a child plan. 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 | const std::unordered_map &update_attrs) 48 | : AbstractPlanNode(nullptr, {child}), table_oid_(table_oid), update_attrs_(&update_attrs) {} 49 | 50 | PlanType GetType() const override { return PlanType::Update; } 51 | 52 | /** @return the identifier of the table that should be updated */ 53 | table_oid_t TableOid() const { return table_oid_; } 54 | 55 | /** @return the child plan providing tuples to be inserted */ 56 | const AbstractPlanNode *GetChildPlan() const { 57 | BUSTUB_ASSERT(GetChildren().size() == 1, "update should have at most one child plan."); 58 | return GetChildAt(0); 59 | } 60 | 61 | const std::unordered_map *GetUpdateAttr() const { return update_attrs_; } 62 | 63 | private: 64 | /** The table to be updated. */ 65 | table_oid_t table_oid_; 66 | const std::unordered_map *update_attrs_; 67 | }; 68 | } // namespace bustub 69 | -------------------------------------------------------------------------------- /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 | 18 | #include "storage/index/b_plus_tree.h" 19 | #include "storage/index/index.h" 20 | 21 | namespace bustub { 22 | 23 | #define BPLUSTREE_INDEX_TYPE BPlusTreeIndex 24 | 25 | INDEX_TEMPLATE_ARGUMENTS 26 | class BPlusTreeIndex : public Index { 27 | public: 28 | BPlusTreeIndex(IndexMetadata *metadata, BufferPoolManager *buffer_pool_manager); 29 | 30 | void InsertEntry(const Tuple &key, RID rid, Transaction *transaction) override; 31 | 32 | void DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) override; 33 | 34 | void ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) override; 35 | 36 | INDEXITERATOR_TYPE GetBeginIterator(); 37 | 38 | INDEXITERATOR_TYPE GetBeginIterator(const KeyType &key); 39 | 40 | INDEXITERATOR_TYPE GetEndIterator(); 41 | 42 | protected: 43 | // comparator for key 44 | KeyComparator comparator_; 45 | // container 46 | BPlusTree 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 | using LeafPage = BPlusTreeLeafPage; 25 | 26 | public: 27 | // you may define your own constructor based on your member variables 28 | IndexIterator(BufferPoolManager *bpm, Page *page, int index); 29 | ~IndexIterator(); 30 | 31 | bool isEnd(); 32 | 33 | const MappingType &operator*(); 34 | 35 | IndexIterator &operator++(); 36 | 37 | bool operator==(const IndexIterator &itr) const; 38 | 39 | bool operator!=(const IndexIterator &itr) const; 40 | 41 | private: 42 | // add your own private member variables here 43 | // 注意:确保成员出现在构造函数的初始化列表中的顺序与它们在类中出现的顺序相同 44 | BufferPoolManager *buffer_pool_manager_; 45 | Page *page_; 46 | int index_; 47 | LeafPage *leaf_; 48 | }; 49 | 50 | } // namespace bustub 51 | -------------------------------------------------------------------------------- /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) { return lhs - rhs; } 24 | }; 25 | } // namespace bustub 26 | -------------------------------------------------------------------------------- /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 | 19 | #include "container/hash/hash_function.h" 20 | #include "container/hash/linear_probe_hash_table.h" 21 | #include "storage/index/index.h" 22 | 23 | namespace bustub { 24 | 25 | #define HASH_TABLE_INDEX_TYPE LinearProbeHashTableIndex 26 | 27 | template 28 | class LinearProbeHashTableIndex : public Index { 29 | public: 30 | LinearProbeHashTableIndex(IndexMetadata *metadata, BufferPoolManager *buffer_pool_manager, size_t num_buckets, 31 | const HashFunction &hash_fn); 32 | 33 | ~LinearProbeHashTableIndex() override = default; 34 | 35 | void InsertEntry(const Tuple &key, RID rid, Transaction *transaction) override; 36 | 37 | void DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) override; 38 | 39 | void ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) override; 40 | 41 | protected: 42 | // comparator for key 43 | KeyComparator comparator_; 44 | // container 45 | LinearProbeHashTable container_; 46 | }; 47 | 48 | } // namespace bustub 49 | -------------------------------------------------------------------------------- /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 | // 这是内部页(Internal Page)和叶页(Leaf Page)都继承的父类,它只包含两个子类共享的信息。 44 | class BPlusTreePage { 45 | public: 46 | bool IsLeafPage() const; 47 | bool IsRootPage() const; 48 | void SetPageType(IndexPageType page_type); 49 | 50 | int GetSize() const; 51 | void SetSize(int size); 52 | void IncreaseSize(int amount); 53 | 54 | int GetMaxSize() const; 55 | void SetMaxSize(int max_size); 56 | int GetMinSize() const; 57 | 58 | page_id_t GetParentPageId() const; 59 | void SetParentPageId(page_id_t parent_page_id); 60 | 61 | page_id_t GetPageId() const; 62 | void SetPageId(page_id_t page_id); 63 | 64 | void SetLSN(lsn_t lsn = INVALID_LSN); 65 | 66 | IndexPageType GetPageType() const { return page_type_; } // DEBUG 67 | 68 | private: 69 | // member variable, attributes that both internal and leaf page share 70 | IndexPageType page_type_ __attribute__((__unused__)); 71 | lsn_t lsn_ __attribute__((__unused__)); 72 | int size_ __attribute__((__unused__)); 73 | int max_size_ __attribute__((__unused__)); 74 | page_id_t parent_page_id_ __attribute__((__unused__)); 75 | page_id_t page_id_ __attribute__((__unused__)); 76 | }; 77 | 78 | } // namespace bustub 79 | -------------------------------------------------------------------------------- /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-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #pragma once 14 | 15 | #define MappingType std::pair 16 | 17 | /** BLOCK_ARRAY_SIZE is the number of (key, value) pairs that can be stored in * a block page. It is an approximate 18 | * calculation based on the size of MappingType (which is a std::pair of KeyType and ValueType). For each key/value 19 | * pair, we need two additional bits for occupied_ and readable_. 4 * PAGE_SIZE / (4 * sizeof (MappingType) + 1) = 20 | * PAGE_SIZE/(sizeof (MappingType) + 0.25) because 0.25 bytes = 2 bits is the space required to maintain the occupied 21 | * and readable flags for a key value pair.*/ 22 | #define BLOCK_ARRAY_SIZE (4 * PAGE_SIZE / (4 * sizeof(MappingType) + 1)) 23 | 24 | #define HASH_TABLE_BLOCK_TYPE HashTableBlockPage 25 | -------------------------------------------------------------------------------- /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(IndexMetadata *metadata, BufferPoolManager *buffer_pool_manager) 20 | : Index(metadata), 21 | comparator_(metadata->GetKeySchema()), 22 | container_(metadata->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/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(BufferPoolManager *bpm, Page *page, int index) 16 | : buffer_pool_manager_(bpm), page_(page), index_(index) { 17 | leaf_ = reinterpret_cast(page_->GetData()); 18 | // LOG_INFO("ENTER IndexIterator()"); 19 | // LOG_INFO("LEAVE IndexIterator()"); 20 | } 21 | 22 | INDEX_TEMPLATE_ARGUMENTS 23 | INDEXITERATOR_TYPE::~IndexIterator() { 24 | // LOG_INFO("ENTER ~IndexIterator()"); 25 | // assert(leaf_ != nullptr); 26 | // assert(leaf_->GetPageId()); 27 | page_->RUnlatch(); 28 | buffer_pool_manager_->UnpinPage(page_->GetPageId(), false); 29 | // LOG_INFO("LEAVE ~IndexIterator()"); 30 | } // 记得unpin leaf 31 | 32 | INDEX_TEMPLATE_ARGUMENTS 33 | bool INDEXITERATOR_TYPE::isEnd() { return leaf_->GetNextPageId() == INVALID_PAGE_ID && index_ == leaf_->GetSize(); } 34 | 35 | // 取出leaf中的array[index],为pair类型 36 | INDEX_TEMPLATE_ARGUMENTS 37 | const MappingType &INDEXITERATOR_TYPE::operator*() { return leaf_->GetItem(index_); } 38 | 39 | /** 40 | * index++,如果增加到当前leaf node末尾,则进入next leaf node且index置0 41 | * @return IndexIterator 42 | */ 43 | INDEX_TEMPLATE_ARGUMENTS 44 | INDEXITERATOR_TYPE &INDEXITERATOR_TYPE::operator++() { 45 | // 若index加1后指向当前leaf末尾(但不是整个叶子层的末尾),则进入下一个leaf且index置0 46 | index_++; 47 | if (index_ == leaf_->GetSize() && leaf_->GetNextPageId() != INVALID_PAGE_ID) { 48 | Page *next_page = buffer_pool_manager_->FetchPage(leaf_->GetNextPageId()); // pin next leaf page 49 | next_page->RLatch(); 50 | 51 | page_->RUnlatch(); 52 | buffer_pool_manager_->UnpinPage(page_->GetPageId(), false); // unpin current leaf page 53 | 54 | page_ = next_page; 55 | leaf_ = reinterpret_cast(page_->GetData()); // update leaf page to next page 56 | index_ = 0; // reset index to zero 57 | } 58 | return *this; 59 | } 60 | 61 | INDEX_TEMPLATE_ARGUMENTS 62 | bool INDEXITERATOR_TYPE::operator==(const IndexIterator &itr) const { 63 | return leaf_->GetPageId() == itr.leaf_->GetPageId() && index_ == itr.index_; // leaf page和index均相同 64 | } 65 | 66 | INDEX_TEMPLATE_ARGUMENTS 67 | bool INDEXITERATOR_TYPE::operator!=(const IndexIterator &itr) const { return !(*this == itr); } // 此处可用之前重载的== 68 | 69 | template class IndexIterator, RID, GenericComparator<4>>; 70 | 71 | template class IndexIterator, RID, GenericComparator<8>>; 72 | 73 | template class IndexIterator, RID, GenericComparator<16>>; 74 | 75 | template class IndexIterator, RID, GenericComparator<32>>; 76 | 77 | template class IndexIterator, RID, GenericComparator<64>>; 78 | 79 | } // namespace bustub 80 | -------------------------------------------------------------------------------- /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(IndexMetadata *metadata, BufferPoolManager *buffer_pool_manager, 11 | size_t num_buckets, const HashFunction &hash_fn) 12 | : Index(metadata), 13 | comparator_(metadata->GetKeySchema()), 14 | container_(metadata->GetName(), buffer_pool_manager, comparator_, num_buckets, hash_fn) {} 15 | 16 | template 17 | void HASH_TABLE_INDEX_TYPE::InsertEntry(const Tuple &key, RID rid, Transaction *transaction) { 18 | // construct insert index key 19 | KeyType index_key; 20 | index_key.SetFromKey(key); 21 | 22 | container_.Insert(transaction, index_key, rid); 23 | } 24 | 25 | template 26 | void HASH_TABLE_INDEX_TYPE::DeleteEntry(const Tuple &key, RID rid, Transaction *transaction) { 27 | // construct delete index key 28 | KeyType index_key; 29 | index_key.SetFromKey(key); 30 | 31 | container_.Remove(transaction, index_key, rid); 32 | } 33 | 34 | template 35 | void HASH_TABLE_INDEX_TYPE::ScanKey(const Tuple &key, std::vector *result, Transaction *transaction) { 36 | // construct scan index key 37 | KeyType index_key; 38 | index_key.SetFromKey(key); 39 | 40 | container_.GetValue(transaction, index_key, result); 41 | } 42 | template class LinearProbeHashTableIndex, RID, GenericComparator<4>>; 43 | template class LinearProbeHashTableIndex, RID, GenericComparator<8>>; 44 | template class LinearProbeHashTableIndex, RID, GenericComparator<16>>; 45 | template class LinearProbeHashTableIndex, RID, GenericComparator<32>>; 46 | template class LinearProbeHashTableIndex, RID, GenericComparator<64>>; 47 | 48 | } // namespace bustub 49 | -------------------------------------------------------------------------------- /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 page_type_ == IndexPageType::LEAF_PAGE; } 21 | // 若父节点page id不存在,则为RootPage 22 | bool BPlusTreePage::IsRootPage() const { return parent_page_id_ == INVALID_PAGE_ID; } 23 | void BPlusTreePage::SetPageType(IndexPageType page_type) { page_type_ = page_type; } 24 | 25 | /* 26 | * Helper methods to get/set size (number of key/value pairs stored in that 27 | * page) 28 | */ 29 | int BPlusTreePage::GetSize() const { return size_; } 30 | void BPlusTreePage::SetSize(int size) { size_ = size; } 31 | void BPlusTreePage::IncreaseSize(int amount) { size_ += amount; } // size增加amount 32 | 33 | /* 34 | * Helper methods to get/set max size (capacity) of the page 35 | */ 36 | int BPlusTreePage::GetMaxSize() const { 37 | // return IsLeafPage() ? max_size_ : max_size_ - 1; 38 | return max_size_; 39 | } // 叶页面和内部页面的max_size不同(疑问:此处不用体现?) 40 | void BPlusTreePage::SetMaxSize(int size) { max_size_ = size; } 41 | 42 | /* 43 | * Helper method to get min page size 44 | * Generally, min page size == max page size / 2 45 | */ 46 | int BPlusTreePage::GetMinSize() const { return max_size_ / 2; } // 疑问:此处要修改吗? 47 | 48 | /* 49 | * Helper methods to get/set parent page id 50 | */ 51 | page_id_t BPlusTreePage::GetParentPageId() const { return parent_page_id_; } 52 | void BPlusTreePage::SetParentPageId(page_id_t parent_page_id) { parent_page_id_ = parent_page_id; } 53 | 54 | /* 55 | * Helper methods to get/set self page id 56 | */ 57 | page_id_t BPlusTreePage::GetPageId() const { return page_id_; } 58 | void BPlusTreePage::SetPageId(page_id_t page_id) { page_id_ = page_id; } 59 | 60 | /* 61 | * Helper methods to set lsn 62 | */ 63 | void BPlusTreePage::SetLSN(lsn_t lsn) { lsn_ = lsn; } 64 | 65 | } // namespace bustub 66 | -------------------------------------------------------------------------------- /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/grading_leaderboard_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * grading_leaderboard_test.cpp 3 | * 4 | * THIS TEST WILL NOT BE RUN ON GRADESCOPE 5 | * 6 | * Test for calculating the milliseconds time for running 7 | * NewPage, UnpinPage, FetchPage, DeletePage in Buffer Pool Manager. 8 | */ 9 | 10 | //===----------------------------------------------------------------------===// 11 | // 12 | // BusTub 13 | // 14 | // clock_replacer_test.cpp 15 | // 16 | // Identification: test/buffer/leaderboard_test.cpp 17 | // 18 | // Copyright (c) 2015-2020, Carnegie Mellon University Database Group 19 | // 20 | //===----------------------------------------------------------------------===// 21 | 22 | #include 23 | #include // NOLINT 24 | #include 25 | 26 | #include "buffer/buffer_pool_manager.h" 27 | #include "gtest/gtest.h" 28 | #include "storage/disk/disk_manager.h" 29 | // #include "storage/disk/disk_manager_memory.h" 30 | 31 | namespace bustub { 32 | 33 | TEST(LeaderboardTest, Time) { 34 | const size_t buffer_pool_size = 1000000; 35 | 36 | // DiskManagerMemory *dm = new DiskManagerMemory(); 37 | DiskManager *dm = new DiskManager("test.db"); 38 | BufferPoolManager *bpm = new BufferPoolManager(buffer_pool_size, dm); 39 | page_id_t temp; 40 | for (size_t i = 0; i < buffer_pool_size; i++) { 41 | bpm->NewPage(&temp); 42 | } 43 | for (size_t i = 0; i < buffer_pool_size; i++) { 44 | bpm->UnpinPage(i, false); 45 | bpm->FetchPage(i); 46 | bpm->UnpinPage(i, false); 47 | } 48 | for (size_t i = buffer_pool_size - 1; i != 0; i--) { 49 | bpm->DeletePage(i); 50 | bpm->NewPage(&temp); 51 | bpm->UnpinPage(temp, false); 52 | bpm->DeletePage(temp); 53 | bpm->NewPage(&temp); 54 | } 55 | 56 | // Shutdown the disk manager and remove the temporary file we created. 57 | dm->ShutDown(); 58 | remove("test.db"); 59 | remove("test.log"); 60 | 61 | delete bpm; 62 | delete dm; 63 | } 64 | 65 | } // namespace bustub 66 | -------------------------------------------------------------------------------- /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, DISABLED_SampleTest) { 23 | TEST(LRUReplacerTest, SampleTest) { 24 | LRUReplacer lru_replacer(7); 25 | 26 | // Scenario: unpin six elements, i.e. add them to the replacer. 27 | lru_replacer.Unpin(1); 28 | lru_replacer.Unpin(2); 29 | lru_replacer.Unpin(3); 30 | lru_replacer.Unpin(4); 31 | lru_replacer.Unpin(5); 32 | lru_replacer.Unpin(6); 33 | lru_replacer.Unpin(1); 34 | EXPECT_EQ(6, lru_replacer.Size()); // 此刻还有6 5 4 3 2 1 35 | 36 | // Scenario: get three victims from the lru. 37 | int value; 38 | lru_replacer.Victim(&value); 39 | EXPECT_EQ(1, value); // 此刻还有6 5 4 3 2 40 | lru_replacer.Victim(&value); 41 | EXPECT_EQ(2, value); // 此刻还有6 5 4 3 42 | lru_replacer.Victim(&value); 43 | EXPECT_EQ(3, value); // 此刻还有6 5 4 44 | 45 | // Scenario: pin elements in the replacer. 46 | // Note that 3 has already been victimized, so pinning 3 should have no effect. 47 | lru_replacer.Pin(3); // 此刻还有6 5 4(该操作无效) 48 | lru_replacer.Pin(4); // 此刻还有6 5 49 | EXPECT_EQ(2, lru_replacer.Size()); 50 | 51 | // Scenario: unpin 4. We expect that the reference bit of 4 will be set to 1. 52 | lru_replacer.Unpin(4); // 此刻还有4 6 5 53 | 54 | EXPECT_EQ(3, lru_replacer.Size()); 55 | 56 | // Scenario: continue looking for victims. We expect these victims. 57 | lru_replacer.Victim(&value); // 此刻还有4 6(淘汰5) 58 | EXPECT_EQ(5, value); 59 | lru_replacer.Victim(&value); // 此刻还有4(淘汰6) 60 | EXPECT_EQ(6, value); 61 | 62 | EXPECT_EQ(1, lru_replacer.Size()); 63 | 64 | lru_replacer.Victim(&value); // 此刻为空(淘汰4) 65 | EXPECT_EQ(4, value); 66 | } 67 | 68 | } // namespace bustub 69 | -------------------------------------------------------------------------------- /test/catalog/catalog_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // catalog_test.cpp 6 | // 7 | // Identification: test/catalog/catalog_test.cpp 8 | // 9 | // Copyright (c) 2015-2019, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "buffer/buffer_pool_manager.h" 18 | #include "catalog/catalog.h" 19 | #include "gtest/gtest.h" 20 | #include "type/value_factory.h" 21 | 22 | namespace bustub { 23 | 24 | // NOLINTNEXTLINE 25 | TEST(CatalogTest, DISABLED_CreateTableTest) { 26 | auto disk_manager = new DiskManager("catalog_test.db"); 27 | auto bpm = new BufferPoolManager(32, disk_manager); 28 | auto catalog = new Catalog(bpm, nullptr, nullptr); 29 | std::string table_name = "potato"; 30 | 31 | // The table shouldn't exist in the catalog yet. 32 | EXPECT_THROW(catalog->GetTable(table_name), std::out_of_range); 33 | 34 | // Put the table into the catalog. 35 | std::vector columns; 36 | columns.emplace_back("A", TypeId::INTEGER); 37 | columns.emplace_back("B", TypeId::BOOLEAN); 38 | 39 | Schema schema(columns); 40 | auto *table_metadata = catalog->CreateTable(nullptr, table_name, schema); 41 | (void)table_metadata; 42 | 43 | // Notice that this test case doesn't check anything! :( 44 | // It is up to you to extend it 45 | 46 | delete catalog; 47 | delete bpm; 48 | delete disk_manager; 49 | } 50 | 51 | } // namespace bustub 52 | -------------------------------------------------------------------------------- /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/storage/b_plus_tree_test_util.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // schema.h 6 | // 7 | // Identification: src/include/catalog/schema.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 | #include 20 | #include 21 | 22 | #include "catalog/schema.h" 23 | #include "common/exception.h" 24 | #include "common/logger.h" 25 | #include "common/util/string_util.h" 26 | #include "storage/page/header_page.h" 27 | 28 | namespace bustub { 29 | 30 | /* Helpers */ 31 | Schema *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 | // create a copy of the sql query 39 | std::string sql = sql_base; 40 | // prepocess, transform sql string into lower case 41 | std::transform(sql.begin(), sql.end(), sql.begin(), ::tolower); 42 | std::vector tok = StringUtil::Split(sql, ','); 43 | // iterate through returned result 44 | for (std::string &t : tok) { 45 | type = INVALID; 46 | column_length = 0; 47 | // whitespace seperate column name and type 48 | n = t.find_first_of(' '); 49 | column_name = t.substr(0, n); 50 | column_type = t.substr(n + 1); 51 | // deal with varchar(size) situation 52 | n = column_type.find_first_of('('); 53 | if (n != std::string::npos) { 54 | column_length = std::stoi(column_type.substr(n + 1)); 55 | column_type = column_type.substr(0, n); 56 | } 57 | if (column_type == "bool" || column_type == "boolean") { 58 | type = BOOLEAN; 59 | } else if (column_type == "tinyint") { 60 | type = TINYINT; 61 | } else if (column_type == "smallint") { 62 | type = SMALLINT; 63 | } else if (column_type == "int" || column_type == "integer") { 64 | type = INTEGER; 65 | } else if (column_type == "bigint") { 66 | type = BIGINT; 67 | } else if (column_type == "double" || column_type == "float") { 68 | type = DECIMAL; 69 | } else if (column_type == "varchar" || column_type == "char") { 70 | type = VARCHAR; 71 | column_length = (column_length == 0) ? 32 : column_length; 72 | } 73 | // construct each column 74 | if (type != INVALID) { 75 | if (type == VARCHAR) { 76 | Column col(column_name, type, column_length); 77 | v.emplace_back(col); 78 | } else { 79 | Column col(column_name, type); 80 | v.emplace_back(col); 81 | } 82 | } else { 83 | throw Exception(ExceptionType::UNKNOWN_TYPE, "unknown type for create table"); 84 | } 85 | } 86 | Schema *schema = new Schema(v); 87 | // LOG_DEBUG("%s", schema->ToString().c_str()); 88 | 89 | return schema; 90 | } 91 | 92 | } // namespace bustub 93 | -------------------------------------------------------------------------------- /test/primer/starter_test.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // starter_test.cpp 6 | // 7 | // Identification: test/include/starter_test.cpp 8 | // 9 | // Copyright (c) 2015-2020, Carnegie Mellon University Database Group 10 | // 11 | //===----------------------------------------------------------------------===// 12 | 13 | #include 14 | 15 | #include "gtest/gtest.h" 16 | #include "primer/p0_starter.h" 17 | 18 | namespace bustub { 19 | 20 | TEST(StarterTest, SampleTest) { 21 | int a = 1; 22 | EXPECT_EQ(a, 1); 23 | } 24 | 25 | // TEST(StarterTest, DISABLED_AddMatricesTest) { 26 | TEST(StarterTest, AddMatricesTest) { 27 | std::unique_ptr> mat1_ptr{new RowMatrix(3, 3)}; 28 | int arr1[9] = {1, 4, 2, 5, 2, -1, 0, 3, 1}; 29 | mat1_ptr->MatImport(&arr1[0]); 30 | for (int i = 0; i < 3; i++) { 31 | for (int j = 0; j < 3; j++) { 32 | EXPECT_EQ(arr1[i * 3 + j], mat1_ptr->GetElem(i, j)); 33 | } 34 | } 35 | 36 | int arr2[9] = {2, -3, 1, 4, 6, 7, 0, 5, -2}; 37 | std::unique_ptr> mat2_ptr{new RowMatrix(3, 3)}; 38 | mat2_ptr->MatImport(&arr2[0]); 39 | for (int i = 0; i < 3; i++) { 40 | for (int j = 0; j < 3; j++) { 41 | EXPECT_EQ(arr2[i * 3 + j], mat2_ptr->GetElem(i, j)); 42 | } 43 | } 44 | 45 | int arr3[9] = {3, 1, 3, 9, 8, 6, 0, 8, -1}; 46 | std::unique_ptr> sum_ptr = 47 | RowMatrixOperations::AddMatrices(std::move(mat1_ptr), std::move(mat2_ptr)); 48 | for (int i = 0; i < 3; i++) { 49 | for (int j = 0; j < 3; j++) { 50 | EXPECT_EQ(arr3[i * 3 + j], sum_ptr->GetElem(i, j)); 51 | } 52 | } 53 | } 54 | 55 | // TEST(StarterTest, DISABLED_MultiplyMatricesTest) { 56 | TEST(StarterTest, MultiplyMatricesTest) { 57 | // Multiply 58 | int arr1[6] = {1, 2, 3, 4, 5, 6}; 59 | std::unique_ptr> mat1_ptr{new RowMatrix(2, 3)}; 60 | mat1_ptr->MatImport(&arr1[0]); 61 | for (int i = 0; i < 2; i++) { 62 | for (int j = 0; j < 3; j++) { 63 | EXPECT_EQ(arr1[i * 3 + j], mat1_ptr->GetElem(i, j)); 64 | } 65 | } 66 | 67 | int arr2[6] = {-2, 1, -2, 2, 2, 3}; 68 | std::unique_ptr> mat2_ptr{new RowMatrix(3, 2)}; 69 | mat2_ptr->MatImport(&arr2[0]); 70 | for (int i = 0; i < 3; i++) { 71 | for (int j = 0; j < 2; j++) { 72 | EXPECT_EQ(arr2[i * 2 + j], mat2_ptr->GetElem(i, j)); 73 | } 74 | } 75 | 76 | int arr3[4] = {0, 14, -6, 32}; 77 | std::unique_ptr> product_ptr = 78 | RowMatrixOperations::MultiplyMatrices(std::move(mat1_ptr), std::move(mat2_ptr)); 79 | for (int i = 0; i < 2; i++) { 80 | for (int j = 0; j < 2; j++) { 81 | EXPECT_EQ(arr3[i * 2 + j], product_ptr->GetElem(i, j)); 82 | } 83 | } 84 | } 85 | } // namespace bustub 86 | -------------------------------------------------------------------------------- /test/storage/b_plus_tree_test_util.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // BusTub 4 | // 5 | // schema.h 6 | // 7 | // Identification: src/include/catalog/schema.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 | #include 20 | #include 21 | 22 | #include "catalog/schema.h" 23 | #include "common/exception.h" 24 | #include "common/logger.h" 25 | #include "common/util/string_util.h" 26 | #include "storage/page/header_page.h" 27 | 28 | namespace bustub { 29 | 30 | /* Helpers */ 31 | Schema *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 | // create a copy of the sql query 39 | std::string sql = sql_base; 40 | // prepocess, transform sql string into lower case 41 | std::transform(sql.begin(), sql.end(), sql.begin(), ::tolower); 42 | std::vector tok = StringUtil::Split(sql, ','); 43 | // iterate through returned result 44 | for (std::string &t : tok) { 45 | type = INVALID; 46 | column_length = 0; 47 | // whitespace seperate column name and type 48 | n = t.find_first_of(' '); 49 | column_name = t.substr(0, n); 50 | column_type = t.substr(n + 1); 51 | // deal with varchar(size) situation 52 | n = column_type.find_first_of('('); 53 | if (n != std::string::npos) { 54 | column_length = std::stoi(column_type.substr(n + 1)); 55 | column_type = column_type.substr(0, n); 56 | } 57 | if (column_type == "bool" || column_type == "boolean") { 58 | type = BOOLEAN; 59 | } else if (column_type == "tinyint") { 60 | type = TINYINT; 61 | } else if (column_type == "smallint") { 62 | type = SMALLINT; 63 | } else if (column_type == "int" || column_type == "integer") { 64 | type = INTEGER; 65 | } else if (column_type == "bigint") { 66 | type = BIGINT; 67 | } else if (column_type == "double" || column_type == "float") { 68 | type = DECIMAL; 69 | } else if (column_type == "varchar" || column_type == "char") { 70 | type = VARCHAR; 71 | column_length = (column_length == 0) ? 32 : column_length; 72 | } 73 | // construct each column 74 | if (type == INVALID) { 75 | throw Exception(ExceptionType::UNKNOWN_TYPE, "unknown type for create table"); 76 | } else if (type == VARCHAR) { 77 | Column col(column_name, type, column_length); 78 | v.emplace_back(col); 79 | } else { 80 | Column col(column_name, type); 81 | v.emplace_back(col); 82 | } 83 | } 84 | Schema *schema = new Schema(v); 85 | // LOG_DEBUG("%s", schema->ToString().c_str()); 86 | 87 | return schema; 88 | } 89 | 90 | } // namespace bustub 91 | -------------------------------------------------------------------------------- /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.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 BufferPoolManager(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 | --------------------------------------------------------------------------------