├── .DS_Store ├── BTree ├── BTree.cpp ├── BTree.hpp ├── Base.cpp ├── Base.hpp ├── CMakeLists.txt ├── Hash.cpp └── Hash.hpp ├── CMake ├── FindFLEX.cmake ├── FindLEMON.cmake └── Utils.cmake ├── CMakeLists.txt ├── Exception ├── CMakeLists.txt ├── Exception.cpp └── Exception.hpp ├── IndexFile └── IndexFile.hpp ├── PageDB ├── .DS_Store ├── CMakeLists.txt ├── file.cpp ├── file.hpp ├── iterator.hpp ├── lru_scheduler.cpp ├── lru_scheduler.hpp ├── page.hpp ├── scheduler.cpp └── scheduler.hpp ├── README ├── README.md ├── Stmt ├── CMakeLists.txt ├── createDBStmt.cpp ├── createDBStmt.hpp ├── createTableStmt.cpp ├── createTableStmt.hpp ├── deleteStmt.cpp ├── deleteStmt.hpp ├── descStmt.cpp ├── descStmt.hpp ├── dropDBStmt.cpp ├── dropDBStmt.hpp ├── dropTableStmt.cpp ├── dropTableStmt.hpp ├── filter.cpp ├── filter.hpp ├── insertStmt.cpp ├── insertStmt.hpp ├── selectStmt.cpp ├── selectStmt.hpp ├── showTablesStmt.cpp ├── showTablesStmt.hpp ├── stmt.cpp ├── stmt.hpp ├── updateStmt.cpp ├── updateStmt.hpp ├── useDBStmt.cpp └── useDBStmt.hpp ├── TypeDB ├── .DS_Store ├── CMakeLists.txt ├── expr.cpp ├── expr.hpp ├── object.cpp ├── object.hpp ├── table.cpp ├── table.hpp ├── tblExpr.cpp ├── tblExpr.hpp ├── tblSelector.cpp ├── tblSelector.hpp ├── type.cpp └── type.hpp ├── context ├── CMakeLists.txt ├── context.cpp └── context.hpp ├── frontend ├── .DS_Store ├── CMakeLists.txt ├── Lexer.l ├── Parser.hpp ├── Parser.y └── ParserDef.h ├── main ├── CMakeLists.txt └── main.cpp ├── test ├── CMakeLists.txt ├── testBTree.cpp ├── testContext.cpp ├── testPageDB.cpp └── testParser.cpp └── utils ├── bufOp.hpp └── writeFile.hpp /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewdy/mymymysql/ecb881b1b048dc908b033dbfd95b6455b17ba331/.DS_Store -------------------------------------------------------------------------------- /BTree/BTree.cpp: -------------------------------------------------------------------------------- 1 | #include "BTree.hpp" 2 | #include 3 | #include "Utils/writeFile.hpp" 4 | #include "Utils/bufOp.hpp" 5 | 6 | namespace BTree { 7 | 8 | 9 | BTree::BTree(PageDB::Scheduler* _pgdb, const std::string& fn) 10 | : pgdb(_pgdb), file(pgdb->OpenFile(fn)), 11 | entrySession(pgdb->GetWriteSession(file, file->entryPageID)) { 12 | if (magicNumber() != MagicNumber) { 13 | initBTree(); 14 | } 15 | } 16 | std::pair BTree::find(const Key& key) { 17 | std::pair ret; 18 | bool found; 19 | PageDB::Location loc; 20 | trace(key, nullptr, found, loc); 21 | ret.first = found; 22 | if (found) { 23 | PageDB::PageSession session = pgdb->GetSession(file, loc.Page); 24 | const Information* x; 25 | x = reinterpret_cast(session.buf() + loc.Offset); 26 | ret.second = x->value; 27 | } 28 | return ret; 29 | } 30 | bool BTree::set(const Key& key, Value value, bool force) { 31 | std::vector tr; 32 | bool found; 33 | PageDB::Location loc; 34 | trace(key, &tr, found, loc); 35 | if (!found && !force) 36 | return false; 37 | Information* info; 38 | if (found) { 39 | PageDB::PageWriteSession session = pgdb->GetWriteSession(file, loc.Page); 40 | info = reinterpret_cast(session.buf() + loc.Offset); 41 | info->key = key; 42 | info->value = value; 43 | return true; 44 | } 45 | auto next = writable_end(); 46 | auto prev = BTreeIterator(pgdb, file, next.Info().prev); 47 | char buf[sizeof(Information)]; 48 | info = reinterpret_cast(buf); 49 | info->key = key; 50 | info->value = value; 51 | info->next = next.loc; 52 | info->prev = prev.loc; 53 | auto locX = Utils::writeFile(pgdb, file, buf, sizeof(Information)); 54 | next.Info().prev = locX; 55 | prev.Info().next = locX; 56 | insertCore(key, tr, locX); 57 | return true; 58 | } 59 | bool BTree::remove(const Key& key) { 60 | std::vector tr; 61 | bool found; 62 | PageDB::Location loc; 63 | trace(key, &tr, found, loc); 64 | if (!found) 65 | return false; 66 | auto me = BTreeConstIterator(pgdb, file, loc); 67 | auto next = BTreeIterator(pgdb, file, me.Info().next); 68 | auto prev = BTreeIterator(pgdb, file, me.Info().prev); 69 | prev.Info().next = next.loc; 70 | next.Info().prev = prev.loc; 71 | removeCore(key, tr); 72 | return true; 73 | } 74 | void BTree::trace(const Key& key, std::vector* tr, bool& found, PageDB::Location& loc) { 75 | const Node* node; 76 | int currentPage = rootPage(); 77 | while (true) { 78 | if (tr) 79 | tr->push_back(currentPage); 80 | PageDB::PageSession session = pgdb->GetSession(file, currentPage); 81 | node = reinterpret_cast(session.buf()); 82 | if (node->size == 0) { 83 | found = false; 84 | break; 85 | } 86 | int idx = node->findIndex(key); 87 | auto locX = node->children[idx].loc; 88 | if (locX.Page != 0) { 89 | if (node->children[idx].less == key) { 90 | found = true; 91 | loc = locX; 92 | break; 93 | } else { 94 | found = false; 95 | break; 96 | } 97 | } else { 98 | currentPage = locX.Offset; 99 | } 100 | } 101 | } 102 | void BTree::initBTree() { 103 | magicNumber() = MagicNumber; 104 | int rtPage = file->newPage(); 105 | int infoPage = file->newPage(); 106 | file->eof.Page = infoPage; 107 | file->eof.Offset = sizeof(Information); 108 | file->writebackFileHeaderCore(); 109 | rootPage() = rtPage; 110 | usedRecord() = 0; 111 | avalibleRecord() = 0; 112 | linkHeadPage() = infoPage; 113 | linkHeadOffset() = 0; 114 | PageDB::PageWriteSession s = pgdb->GetWriteSession(file, infoPage); 115 | Information* info = reinterpret_cast(s.buf()); 116 | info->next = info->prev = PageDB::Location(infoPage, 0); 117 | entrySession.flush(); 118 | } 119 | void BTree::insertCore(Key key, std::vector& trace, PageDB::Location loc) { 120 | Node *currentNode, *splitNode; 121 | int sp = trace.size() - 1; 122 | for(; sp > -1; sp--) { 123 | PageDB::PageWriteSession session1 = pgdb->GetWriteSession(file, trace[sp]); 124 | currentNode = reinterpret_cast(session1.buf()); 125 | if (currentNode->size != MinChild * 2) { 126 | currentNode->Insert(key, loc); 127 | break; 128 | } 129 | int newPage = file->newPage(); 130 | PageDB::PageWriteSession session2 = pgdb->GetWriteSession(file, newPage); 131 | splitNode = reinterpret_cast(session2.buf()); 132 | currentNode->InsertAndSplit(key, loc, *splitNode); 133 | loc.Page = 0; 134 | loc.Offset = newPage; 135 | key = splitNode->children[0].less; 136 | } 137 | if (sp == -1) { 138 | int newPage = file->newPage(); 139 | PageDB::PageWriteSession session = pgdb->GetWriteSession(file, newPage); 140 | currentNode = reinterpret_cast(session.buf()); 141 | currentNode->size = 2; 142 | currentNode->children[0].less = Key(INT_MIN, INT_MIN, INT_MIN); 143 | currentNode->children[0].loc = PageDB::Location(0, trace[0]); 144 | currentNode->children[1].less = key; 145 | currentNode->children[1].loc = loc; 146 | rootPage() = newPage; 147 | entrySession.flush(); 148 | } 149 | } 150 | void BTree::removeCore(Key key, std::vector& trace) { 151 | Node *parent; 152 | PageDB::PageWriteSession parentSession = pgdb->GetWriteSession(file, trace.back()); 153 | parent = reinterpret_cast(parentSession.buf()); 154 | int sp; 155 | int idx = parent->findIndex(key); 156 | for (sp = trace.size() - 1; sp > 0; sp--) { 157 | Node* child = parent; 158 | child->Remove(idx); 159 | if (child->size >= MinChild) { 160 | break; 161 | } 162 | PageDB::PageWriteSession childSession = std::move(parentSession); 163 | parentSession = pgdb->GetWriteSession(file, trace[sp - 1]); 164 | parent = reinterpret_cast(parentSession.buf()); 165 | idx = parent->findIndex(child->children[0].less); 166 | if (idx > 0) { 167 | //Left 168 | PageDB::PageWriteSession siblingSession = pgdb->GetWriteSession(file, parent->children[idx - 1].loc.Offset); 169 | Node* sibling = reinterpret_cast(siblingSession.buf()); 170 | if (sibling->size > MinChild) { 171 | auto item = sibling->children[sibling->size - 1]; 172 | child->Insert(item.less, item.loc); 173 | sibling->Remove(sibling->size - 1); 174 | parent->children[idx].less = child->children[0].less; 175 | break; 176 | } 177 | //Merge 178 | sibling->Merge(*child); 179 | childSession.Release(); 180 | pgdb->RemovePage(file, trace[sp]); 181 | } else { 182 | //Right 183 | PageDB::PageWriteSession siblingSession = pgdb->GetWriteSession(file, parent->children[idx + 1].loc.Offset); 184 | Node* sibling = reinterpret_cast(siblingSession.buf()); 185 | if (sibling->size > MinChild) { 186 | auto item = sibling->children[0]; 187 | child->Insert(item.less, item.loc); 188 | sibling->Remove(0); 189 | parent->children[idx + 1].less = sibling->children[0].less; 190 | break; 191 | } 192 | //Merge 193 | child->Merge(*sibling); 194 | siblingSession.Release(); 195 | pgdb->RemovePage(file, parent->children[idx + 1].loc.Offset); 196 | idx++; 197 | } 198 | } 199 | if (sp == 0) { 200 | parent->Remove(idx); 201 | if (parent->size == 1 && parent->children[0].loc.Page == 0) { 202 | rootPage() = parent->children[0].loc.Offset; 203 | parentSession.Release(); 204 | entrySession.flush(); 205 | } 206 | } 207 | } 208 | BTreeIterator BTree::writable_begin() { 209 | auto x = end(); 210 | auto loc = x.NextLocation(); 211 | return BTreeIterator(pgdb, file, loc.Page, loc.Offset); 212 | } 213 | BTreeIterator BTree::writable_end() { 214 | return BTreeIterator(pgdb, file, linkHeadPage(), linkHeadOffset()); 215 | } 216 | BTreeConstIterator BTree::begin() { 217 | auto x = end(); 218 | auto loc = x.NextLocation(); 219 | return BTreeConstIterator(pgdb, file, loc.Page, loc.Offset); 220 | } 221 | BTreeConstIterator BTree::end() { 222 | return BTreeConstIterator(pgdb, file, linkHeadPage(), linkHeadOffset()); 223 | } 224 | const Information& BTreeConstIterator::Info() { 225 | const Information* info = reinterpret_cast(Get()); 226 | return *info; 227 | } 228 | Information& BTreeIterator::Info() { 229 | Information* info = reinterpret_cast(Get()); 230 | return *info; 231 | } 232 | Value BTreeConstIterator::value() { 233 | return Info().value; 234 | } 235 | Value& BTreeIterator::value() { 236 | return Info().value; 237 | } 238 | PageDB::Location BTreeConstIterator::NextLocation() { 239 | return Info().next; 240 | } 241 | PageDB::Location BTreeIterator::NextLocation() { 242 | return Info().next; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /BTree/BTree.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9123193456_BTREE 2 | #define WDY_9123193456_BTREE 3 | 4 | #include "PageDB/scheduler.hpp" 5 | #include "PageDB/iterator.hpp" 6 | #include "Base.hpp" 7 | #include 8 | 9 | namespace BTree { 10 | struct BTreeIterator : public PageDB::Iterator { 11 | BTreeIterator(PageDB::Scheduler* _pgdb, PageDB::File* _file, int _pageid, int _offset) 12 | : PageDB::Iterator(_pgdb, _file, _pageid, _offset) {} 13 | BTreeIterator(PageDB::Scheduler* _pgdb, PageDB::File* _file, PageDB::Location _loc) 14 | : PageDB::Iterator(_pgdb, _file, _loc) {} 15 | Information& Info(); 16 | Value& value(); 17 | virtual PageDB::Location NextLocation(); 18 | }; 19 | struct BTreeConstIterator : public PageDB::ConstIterator { 20 | BTreeConstIterator(PageDB::Scheduler* _pgdb, PageDB::File* _file, int _pageid, int _offset) 21 | : PageDB::ConstIterator(_pgdb, _file, _pageid, _offset) {} 22 | BTreeConstIterator(PageDB::Scheduler* _pgdb, PageDB::File* _file, PageDB::Location _loc) 23 | : PageDB::ConstIterator(_pgdb, _file, _loc) {} 24 | const Information& Info(); 25 | Value value(); 26 | virtual PageDB::Location NextLocation(); 27 | BTreeIterator toWritable() { 28 | return BTreeIterator(pgdb, file, loc); 29 | } 30 | }; 31 | const int MagicNumber = 0x19940319; 32 | const int MagicNumberOffset = 0; 33 | const int rootPageOffset = MagicNumberOffset + 4; 34 | const int usedRecordOffset = rootPageOffset + 4; 35 | const int avaliableRecordOffset = usedRecordOffset + 4; 36 | const int LinkHeadPageOffset = avaliableRecordOffset + 4; 37 | const int LinkHeadPageOffOffset = LinkHeadPageOffset + 2; 38 | struct BTree { 39 | PageDB::Scheduler* pgdb; 40 | PageDB::File* file; 41 | PageDB::PageWriteSession entrySession; 42 | BTree(PageDB::Scheduler* _pgdb, const std::string& fn); 43 | std::pair find(int key) { 44 | return find(Key(key)); 45 | } 46 | std::pair find(const std::string& key) { 47 | return find(Key(key)); 48 | } 49 | bool set(int key, Value value, bool force = false) { 50 | return set(Key(key), value, force); 51 | } 52 | bool set(const std::string& key, Value value, bool force = false) { 53 | return set(Key(key), value, force); 54 | } 55 | bool remove(int key) { 56 | return remove(Key(key)); 57 | } 58 | bool remove(const std::string& key) { 59 | return remove(Key(key)); 60 | } 61 | BTreeIterator writable_begin(); 62 | BTreeIterator writable_end(); 63 | BTreeConstIterator begin(); 64 | BTreeConstIterator end(); 65 | std::pair find(const Key& key); 66 | bool set(const Key& key, Value value, bool force = false); 67 | bool remove(const Key& key); 68 | private: 69 | void trace(const Key& key, std::vector* tr, bool& found, PageDB::Location& loc); 70 | void initBTree(); 71 | void insertCore(Key key, std::vector& trace, PageDB::Location loc); 72 | void removeCore(Key key, std::vector& trace); 73 | int& magicNumber() { 74 | return *(int*)(entrySession.page().buf + MagicNumberOffset); 75 | } 76 | int& rootPage() { 77 | return *(int*)(entrySession.page().buf + rootPageOffset); 78 | } 79 | int& usedRecord() { 80 | return *(int*)(entrySession.page().buf + usedRecordOffset); 81 | } 82 | int& avalibleRecord() { 83 | return *(int*)(entrySession.page().buf + avaliableRecordOffset); 84 | } 85 | int& linkHeadPage() { 86 | return *(int*)(entrySession.page().buf + LinkHeadPageOffset); 87 | } 88 | int& linkHeadOffset() { 89 | return *(int*)(entrySession.page().buf + LinkHeadPageOffOffset); 90 | } 91 | }; 92 | } 93 | #endif 94 | -------------------------------------------------------------------------------- /BTree/Base.cpp: -------------------------------------------------------------------------------- 1 | #include "Base.hpp" 2 | 3 | namespace BTree { 4 | int Node::findIndex(const Key& key) const { 5 | int sb = 0, se = size - 1; 6 | while (sb < se) { 7 | int sm = (sb + se) / 2 + 1; 8 | if (key < children[sm].less) 9 | se = sm - 1; 10 | else 11 | sb = sm; 12 | } 13 | return sb; 14 | } 15 | bool Node::InsertAndSplit(Key key, PageDB::Location loc, Node& splitNode) { 16 | if (size == MinChild * 2) { 17 | size = MinChild; 18 | splitNode.size = MinChild; 19 | for (int i = 0; i < MinChild; i++) 20 | splitNode.children[i] = children[i + MinChild]; 21 | if (key < splitNode.children[0].less) 22 | Insert(key, loc); 23 | else 24 | splitNode.Insert(key, loc); 25 | return true; 26 | } 27 | Insert(key, loc); 28 | return false; 29 | } 30 | void Node::Insert(Key key, PageDB::Location loc) { 31 | int i; 32 | for (i = size; i > 0; i--) { 33 | if (key < children[i - 1].less) 34 | children[i] = children[i - 1]; 35 | else 36 | break; 37 | } 38 | children[i].less = key; 39 | children[i].loc = loc; 40 | size++; 41 | } 42 | void Node::Remove(int idx) { 43 | int p = idx; 44 | size--; 45 | for (int i = p; i < size; i++) 46 | children[i] = children[i + 1]; 47 | } 48 | void Node::Merge(const Node& right) { 49 | for (int i = 0; i < right.size; i++) 50 | children[size + i] = right.children[i]; 51 | size += right.size; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /BTree/Base.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0192103485_BTREE_BASE 2 | #define WDY_0192103485_BTREE_BASE 3 | #include "PageDB/file.hpp" 4 | #include "Hash.hpp" 5 | namespace BTree { 6 | typedef PageDB::Location Value; 7 | const int MinChild = PageDB::PAGE_SIZE / 16 / 2 - 1; 8 | struct Node { 9 | int size; 10 | struct Child { 11 | Key less; 12 | PageDB::Location loc; 13 | } children[MinChild * 2]; 14 | int findIndex(const Key& key) const; 15 | bool InsertAndSplit(Key key, PageDB::Location loc, Node& splitNode); 16 | void Insert(Key key, PageDB::Location loc); 17 | void Remove(int idx); 18 | void Merge(const Node& right); 19 | }; 20 | struct Information { 21 | Key key; 22 | Value value; 23 | PageDB::Location next, prev; 24 | }; 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /BTree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(BTree) 2 | -------------------------------------------------------------------------------- /BTree/Hash.cpp: -------------------------------------------------------------------------------- 1 | #include "Hash.hpp" 2 | namespace BTree { 3 | static const int p1 = 98765431, p2 = 10016957, p3 = 57885161; 4 | Key::Key(const std::string& _key) { 5 | hash1 = hash2 = hash3 = 0; 6 | for (auto c : _key) { 7 | hash1 = hash1 * p1 + c; 8 | hash2 = hash2 * p2 + c; 9 | hash3 = hash3 * p3 + c; 10 | } 11 | } 12 | Key::Key(int _key) { 13 | hash1 = hash2 = hash3 = _key; 14 | } 15 | Key::Key(int _hash1, int _hash2, int _hash3) : 16 | hash1(_hash1), hash2(_hash2), hash3(_hash3) {} 17 | } 18 | -------------------------------------------------------------------------------- /BTree/Hash.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0129109765_BTREE_HASH 2 | #define WDY_0129109765_BTREE_HASH 3 | #include 4 | namespace BTree { 5 | struct Key { 6 | int hash1, hash2, hash3; 7 | Key(const std::string& _key); 8 | Key(int _key); 9 | Key(int _hash1, int _hash2, int _hash3); 10 | Key(){} 11 | }; 12 | inline bool operator<(const Key& lhs, const Key& rhs) { 13 | if (lhs.hash1 == rhs.hash1 && lhs.hash2 == rhs.hash2) 14 | return lhs.hash3 < rhs.hash3; 15 | if (lhs.hash1 == rhs.hash1) 16 | return lhs.hash2 < rhs.hash2; 17 | return lhs.hash1 < rhs.hash1; 18 | }; 19 | inline bool operator>(const Key& lhs, const Key& rhs) { 20 | return rhs < lhs; 21 | } 22 | inline bool operator<=(const Key& lhs, const Key& rhs) { 23 | return !(rhs > lhs); 24 | } 25 | inline bool operator>=(const Key& lhs, const Key& rhs) { 26 | return !(rhs < lhs); 27 | } 28 | inline bool operator==(const Key& lhs, const Key& rhs) { 29 | return lhs.hash1 == rhs.hash1 && lhs.hash2 == rhs.hash2 && lhs.hash3 == rhs.hash3; 30 | } 31 | inline bool operator!=(const Key& lhs, const Key& rhs) { 32 | return !(rhs == lhs); 33 | } 34 | } 35 | #endif 36 | -------------------------------------------------------------------------------- /CMake/FindFLEX.cmake: -------------------------------------------------------------------------------- 1 | FIND_PROGRAM(FLEX_EXECUTABLE flex) 2 | 3 | IF (FLEX_EXECUTABLE) 4 | SET(FLEX_FOUND TRUE) 5 | ENDIF () 6 | 7 | IF (FLEX_FOUND) 8 | IF (NOT FLEX_FIND_QUIETLY) 9 | MESSAGE(STATUS "Found flex: ${FLEX_EXECUTABLE}") 10 | ENDIF () 11 | ELSE () 12 | IF (FLEX_FIND_REQUIRED) 13 | MESSAGE(FATAL_ERROR "Could not find flex") 14 | ENDIF () 15 | ENDIF () 16 | 17 | -------------------------------------------------------------------------------- /CMake/FindLEMON.cmake: -------------------------------------------------------------------------------- 1 | FIND_PROGRAM(LEMON_EXECUTABLE lemon) 2 | 3 | IF (LEMON_EXECUTABLE) 4 | SET(LEMON_FOUND TRUE) 5 | ENDIF () 6 | 7 | IF (LEMON_FOUND) 8 | IF (NOT LEMON_FIND_QUIETLY) 9 | MESSAGE(STATUS "Found lemon: ${LEMON_EXECUTABLE}") 10 | ENDIF () 11 | ELSE () 12 | IF (LEMON_FIND_REQUIRED) 13 | MESSAGE(FATAL_ERROR "Could not find lemon") 14 | ENDIF () 15 | ENDIF () 16 | 17 | -------------------------------------------------------------------------------- /CMake/Utils.cmake: -------------------------------------------------------------------------------- 1 | MACRO (new_executable project) 2 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 3 | ADD_EXECUTABLE(${project} ${SRC_LIST}) 4 | ENDMACRO () 5 | 6 | MACRO (new_static_library project) 7 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 8 | ADD_LIBRARY(${project} STATIC ${SRC_LIST}) 9 | ENDMACRO () 10 | 11 | MACRO (new_shared_library project) 12 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 13 | ADD_LIBRARY(${project} SHARED ${SRC_LIST}) 14 | ENDMACRO () 15 | 16 | MACRO (new_module_library project) 17 | AUX_SOURCE_DIRECTORY(. SRC_LIST) 18 | ADD_LIBRARY(${project} MODULE ${SRC_LIST}) 19 | ENDMACRO () 20 | 21 | IF (${UNIX}) 22 | SET(CMD_MV mv) 23 | SET(CMD_CP cp) 24 | SET(CMD_RM rm) 25 | SET(CMD_IG cat) 26 | ELSE () 27 | SET(CMD_MV move /y) 28 | SET(CMD_CP copy /y) 29 | SET(CMD_RM del) 30 | SET(CMD_IG echo off) 31 | ENDIF() 32 | 33 | MACRO (new_copy_only dst file) 34 | IF (NOT ("${EXECUTABLE_OUTPUT_PATH}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")) 35 | ADD_CUSTOM_COMMAND(OUTPUT "${EXECUTABLE_OUTPUT_PATH}/${file}" 36 | COMMAND ${CMD_CP} ${file} "${EXECUTABLE_OUTPUT_PATH}/${file}" 37 | MAIN_DEPENDENCY ${file} 38 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 39 | ) 40 | ADD_CUSTOM_TARGET(${dst} SOURCES "${EXECUTABLE_OUTPUT_PATH}/${file}") 41 | ENDIF() 42 | ENDMACRO() 43 | 44 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | PROJECT(ST) 3 | 4 | SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMake") 5 | INCLUDE(Utils) 6 | 7 | INCLUDE_DIRECTORIES(".") 8 | IF (DEBUG) 9 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -g -DDEBUG") 10 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -g -DDEBUG") 11 | ELSE() 12 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -DNDEBUG -O2") 13 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DNDEBUG -O2") 14 | ENDIF() 15 | 16 | FIND_PACKAGE(FLEX) 17 | FIND_PACKAGE(LEMON) 18 | 19 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-register") 20 | 21 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 22 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}) 23 | 24 | ADD_SUBDIRECTORY(frontend) 25 | ADD_SUBDIRECTORY(PageDB) 26 | ADD_SUBDIRECTORY(BTree) 27 | ADD_SUBDIRECTORY(TypeDB) 28 | ADD_SUBDIRECTORY(Context) 29 | ADD_SUBDIRECTORY(Exception) 30 | ADD_SUBDIRECTORY(Stmt) 31 | ADD_SUBDIRECTORY(test) 32 | ADD_SUBDIRECTORY(main) 33 | 34 | -------------------------------------------------------------------------------- /Exception/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(Exception) 2 | -------------------------------------------------------------------------------- /Exception/Exception.cpp: -------------------------------------------------------------------------------- 1 | #include "Exception.hpp" 2 | 3 | namespace Exception { 4 | std::string SyntaxException::msg() { 5 | return "Syntax Error!"; 6 | } 7 | std::string ColumnNotFoundException::msg() { 8 | return "Column " + column + " Not Found!"; 9 | } 10 | std::string ColumnMultiFoundException::msg() { 11 | return "Column " + column + " Multi Found!"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Exception/Exception.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_8976509898_EXCEPTION 2 | #define WDY_8976509898_EXCEPTION 3 | 4 | #include 5 | #include 6 | 7 | namespace Exception { 8 | struct Exception { 9 | virtual std::string msg() = 0; 10 | }; 11 | struct SyntaxException { 12 | SyntaxException() {} 13 | virtual std::string msg(); 14 | }; 15 | struct ColumnNotFoundException { 16 | std::string column; 17 | ColumnNotFoundException(const std::string& _column) : column(_column) {} 18 | virtual std::string msg(); 19 | }; 20 | struct ColumnMultiFoundException { 21 | std::string column; 22 | ColumnMultiFoundException(const std::string& _column) : column(_column) {} 23 | virtual std::string msg(); 24 | }; 25 | } 26 | 27 | 28 | #ifdef DEBUG 29 | #define RAISE(TYPE, ...) do{\ 30 | Exception::TYPE##Exception* ex = new Exception::TYPE##Exception(__VA_ARGS__);\ 31 | std::cerr << "Exception[" << #TYPE << "Exception] Raise At " << __FILE__ << ":" << __LINE__ << std::endl;\ 32 | throw ex;\ 33 | }while(0) 34 | #else 35 | #define RAISE(TYPE, ...) do{\ 36 | Exception::TYPE##Exception* ex = new Exception::TYPE##Exception(__VA_ARGS__);\ 37 | throw ex;\ 38 | }while(0) 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /IndexFile/IndexFile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9281209011_INDEXFILE 2 | #define WDY_9281209011_INDEXFILE 3 | namespace IndexFile { 4 | struct 5 | } 6 | #endif 7 | -------------------------------------------------------------------------------- /PageDB/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewdy/mymymysql/ecb881b1b048dc908b033dbfd95b6455b17ba331/PageDB/.DS_Store -------------------------------------------------------------------------------- /PageDB/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(PageDB) 2 | -------------------------------------------------------------------------------- /PageDB/file.cpp: -------------------------------------------------------------------------------- 1 | #include "file.hpp" 2 | #include "page.hpp" 3 | #include 4 | 5 | namespace PageDB { 6 | static char zeroPage[PAGE_SIZE] = {0}; 7 | static inline void writeZeroPage(std::ostream& out, int paddr) { 8 | out.seekp(paddr * PAGE_SIZE); 9 | out.write(zeroPage, PAGE_SIZE); 10 | } 11 | int File::pageOffset(int vaddr) { 12 | auto iter = pageMap.find(vaddr); 13 | if (iter == pageMap.end()) { 14 | throw "Page Not Found"; 15 | } 16 | //first page to save the file informations 17 | return (iter->second + 1) * PAGE_SIZE; 18 | } 19 | int File::newPage() { 20 | if (pageMap.size() >= MaxPage) { 21 | //TODO 22 | throw "Page Overflow"; 23 | } 24 | std::unordered_set Vs; 25 | for (auto& item : pageMap) { 26 | Vs.insert(item.second); 27 | } 28 | int vaddr = -1, paddr = -1; 29 | for (int i = 0; i < MaxPage + 10; i++) 30 | if (pageMap.find(i) == pageMap.end()) { 31 | vaddr = i; 32 | break; 33 | } 34 | for (int i = 0; i < MaxPage + 10; i++) 35 | if (Vs.find(i) == Vs.end()) { 36 | paddr = i; 37 | break; 38 | } 39 | pageMap[vaddr] = paddr; 40 | raw_mutex.lock(); 41 | writeZeroPage(raw, paddr + 1); 42 | raw_mutex.unlock(); 43 | writebackFileHeader(); 44 | return vaddr; 45 | } 46 | void File::removePage(int pageid) { 47 | std::size_t count = pageMap.erase(pageid); 48 | if (count == 0) { 49 | //TODO 50 | throw "Page Not Found"; 51 | } 52 | writebackFileHeader(); 53 | } 54 | void File::initFile() { 55 | entryPageID = 0; 56 | eof.Page = 0; 57 | eof.Offset = 0; 58 | pageMap.clear(); 59 | pageMap[0] = 0; 60 | raw_mutex.lock(); 61 | writeZeroPage(raw, 0); 62 | writeZeroPage(raw, 1); 63 | raw_mutex.unlock(); 64 | writebackFileHeader(); 65 | } 66 | void File::writebackFileHeaderCore(bool lock) { 67 | assert(raw); 68 | if (lock) 69 | raw_mutex.lock(); 70 | raw.seekp(0); 71 | raw.write((const char*)&MagicNumber, 4); 72 | raw.write((const char*)&entryPageID, 2); 73 | raw.write((const char*)&eof.Page, 2); 74 | raw.write((const char*)&eof.Offset, 2); 75 | if (lock) 76 | raw_mutex.unlock(); 77 | } 78 | void File::writebackFileHeader() { 79 | raw_mutex.lock(); 80 | writebackFileHeaderCore(false); 81 | unsigned short tmp; 82 | tmp = pageMap.size(); 83 | raw.write((const char*)&tmp, 2); 84 | for (auto& item : pageMap) { 85 | raw.write((const char*)&item.first, 2); 86 | raw.write((const char*)&item.second, 2); 87 | } 88 | raw_mutex.unlock(); 89 | } 90 | void File::readFile() { 91 | raw_mutex.lock(); 92 | raw.seekg(0); 93 | int magic; 94 | unsigned short tmp = 0; 95 | raw.read((char*)&magic, 4); 96 | if (magic != MagicNumber) { 97 | raw_mutex.unlock(); 98 | initFile(); 99 | return; 100 | } 101 | raw.read((char*)&tmp, 2); 102 | entryPageID = tmp; 103 | raw.read((char*)&tmp, 2); 104 | eof.Page = tmp; 105 | raw.read((char*)&tmp, 2); 106 | eof.Offset = tmp; 107 | raw.read((char*)&tmp, 2); 108 | int size = tmp; 109 | for (int i = 0; i < size; i++) { 110 | unsigned short vaddr, paddr; 111 | raw.read((char*)&vaddr, 2); 112 | raw.read((char*)&paddr, 2); 113 | pageMap[vaddr] = paddr; 114 | } 115 | raw_mutex.unlock(); 116 | } 117 | File::File(const std::string& fn) : raw(fn, std::ios::in | std::ios::out | std::ios::binary) { 118 | if (!raw) { 119 | raw_mutex.lock(); 120 | raw.open(fn, std::ios::out | std::ios::binary | std::ios::trunc); 121 | raw.close(); 122 | raw.open(fn, std::ios::in | std::ios::out | std::ios::binary); 123 | raw_mutex.unlock(); 124 | initFile(); 125 | } else { 126 | readFile(); 127 | } 128 | }; 129 | Page* File::loadPage(int page_id) { 130 | assert(raw); 131 | int offset = pageOffset(page_id); 132 | Page* ret = new Page; 133 | raw_mutex.lock(); 134 | raw.seekg(offset); 135 | raw.read(ret->buf, PAGE_SIZE); 136 | raw_mutex.unlock(); 137 | return ret; 138 | } 139 | void File::writePage(int page_id, Page* pg) { 140 | assert(raw); 141 | int offset = pageOffset(page_id); 142 | raw_mutex.lock(); 143 | raw.seekp(offset); 144 | raw.write(pg->buf, PAGE_SIZE); 145 | raw_mutex.unlock(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /PageDB/file.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1920382934_FILE 2 | #define WDY_1920382934_FILE 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace PageDB { 10 | struct Location { 11 | unsigned short Page, Offset; 12 | Location() {} 13 | Location(unsigned short _Page, unsigned short _Offset) 14 | : Page(_Page), Offset(_Offset) {} 15 | }; 16 | inline bool operator==(Location lhs, Location rhs) { 17 | return lhs.Page == rhs.Page && lhs.Offset == rhs.Offset; 18 | } 19 | inline bool operator!=(Location lhs, Location rhs) { 20 | return !(lhs == rhs); 21 | } 22 | struct Page; 23 | const int PAGE_SIZE = 8192; 24 | const int MaxPage = 2045; 25 | const int MagicNumber = 0x19941102; 26 | const int MagicNumberOffset = 0; 27 | const int EntryPageOffset = MagicNumberOffset + 4; 28 | const int EofPageOffset = EntryPageOffset + 2; 29 | const int EofOffOffset = EofPageOffset + 2; 30 | const int PageCountOffset = EofOffOffset + 2; 31 | const int PageMapOffset = PageCountOffset + 2; 32 | struct File { 33 | std::fstream raw; 34 | std::mutex raw_mutex; 35 | int entryPageID; 36 | Location eof; 37 | std::unordered_map pageMap; 38 | int pageOffset(int vaddr); 39 | int newPage(); 40 | void removePage(int pageid); 41 | void writebackFileHeaderCore(bool lock = true); 42 | void writebackFileHeader(); 43 | File(const std::string&); 44 | Page* loadPage(int page_id); 45 | void writePage(int page_id, Page* pg); 46 | ~File() { 47 | raw.close(); 48 | } 49 | void initFile(); 50 | void readFile(); 51 | }; 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /PageDB/iterator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0192102912_PAGEDB_ITERATOR 2 | #define WDY_0192102912_PAGEDB_ITERATOR 3 | #include "file.hpp" 4 | #include "page.hpp" 5 | #include "scheduler.hpp" 6 | namespace PageDB { 7 | struct Iterator { 8 | Scheduler* pgdb; 9 | File* file; 10 | PageDB::Location loc; 11 | PageWriteSession session; 12 | Iterator(Scheduler* _pgdb, File* _file, int _pageid = -1, int _offset = 0) 13 | : pgdb(_pgdb), file(_file), 14 | loc(_pageid, _offset), session(pgdb->GetWriteSession(file, _pageid)) 15 | {} 16 | Iterator(Scheduler* _pgdb, File* _file, Location _loc) 17 | : pgdb(_pgdb), file(_file), 18 | loc(_loc), session(pgdb->GetWriteSession(file, _loc.Page)) 19 | {} 20 | void Goto(unsigned short page, unsigned short offset) { 21 | Goto(PageDB::Location(page, offset)); 22 | } 23 | void Goto(Location _loc) { 24 | if (loc.Page != _loc.Page) { 25 | session = pgdb->GetWriteSession(file, _loc.Page); 26 | } 27 | loc = _loc; 28 | } 29 | char* Get() { 30 | return session.buf() + loc.Offset; 31 | } 32 | void Next() { 33 | auto nxt = NextLocation(); 34 | Goto(nxt); 35 | } 36 | virtual Location NextLocation() { 37 | //TODO: Not Imp 38 | throw "Internal Error"; 39 | } 40 | char& operator[](int idx) { 41 | return Get()[idx]; 42 | } 43 | }; 44 | struct ConstIterator { 45 | Scheduler* pgdb; 46 | File* file; 47 | Location loc; 48 | PageSession session; 49 | ConstIterator(Scheduler* _pgdb, File* _file, int _pageid = -1, int _offset = 0) 50 | : pgdb(_pgdb), file(_file), 51 | loc(_pageid, _offset), session(pgdb->GetSession(file, _pageid)) 52 | {} 53 | ConstIterator(Scheduler* _pgdb, File* _file, Location _loc) 54 | : pgdb(_pgdb), file(_file), 55 | loc(_loc), session(pgdb->GetSession(file, _loc.Page)) 56 | {} 57 | void Goto(unsigned short page, unsigned short offset) { 58 | Goto(PageDB::Location(page, offset)); 59 | } 60 | void Goto(Location _loc) { 61 | if (loc.Page != _loc.Page) { 62 | session = pgdb->GetSession(file, _loc.Page); 63 | } 64 | loc = _loc; 65 | } 66 | const char* Get() { 67 | return session.buf() + loc.Offset; 68 | } 69 | void Next() { 70 | auto nxt = NextLocation(); 71 | Goto(nxt); 72 | } 73 | virtual Location NextLocation() { 74 | //TODO: Not Imp 75 | throw "Internal Error"; 76 | } 77 | const char& operator[](int idx) { 78 | return Get()[idx]; 79 | } 80 | }; 81 | inline bool operator==(const Iterator& lhs, const Iterator& rhs) { 82 | return lhs.file == rhs.file && lhs.loc == rhs.loc; 83 | } 84 | inline bool operator!=(const Iterator& lhs, const Iterator& rhs) { 85 | return !(lhs == rhs); 86 | } 87 | inline bool operator==(const ConstIterator& lhs, const ConstIterator& rhs) { 88 | return lhs.file == rhs.file && lhs.loc == rhs.loc; 89 | } 90 | inline bool operator!=(const ConstIterator& lhs, const ConstIterator& rhs) { 91 | return !(lhs == rhs); 92 | } 93 | inline bool operator==(const Iterator& lhs, const ConstIterator& rhs) { 94 | return lhs.file == rhs.file && lhs.loc == rhs.loc; 95 | } 96 | inline bool operator!=(const Iterator& lhs, const ConstIterator& rhs) { 97 | return !(lhs == rhs); 98 | } 99 | inline bool operator==(const ConstIterator& lhs, const Iterator& rhs) { 100 | return lhs.file == rhs.file && lhs.loc == rhs.loc; 101 | } 102 | inline bool operator!=(const ConstIterator& lhs, const Iterator& rhs) { 103 | return !(lhs == rhs); 104 | } 105 | } 106 | #endif 107 | -------------------------------------------------------------------------------- /PageDB/lru_scheduler.cpp: -------------------------------------------------------------------------------- 1 | #include "lru_scheduler.hpp" 2 | 3 | namespace PageDB { 4 | void LRU_Scheduler::Schedule() { 5 | for (auto iter = pageIndex.begin(); iter != pageIndex.end(); iter++) { 6 | PageDesc* desc = iter->second; 7 | desc->WriteBack(); 8 | int& count = lruIndex[desc]; 9 | if (desc->used) { 10 | count++; 11 | desc->used = desc->ref; 12 | } else { 13 | if (count) { 14 | count--; 15 | } else { 16 | desc->Release(false); 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /PageDB/lru_scheduler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1829373821_LRU_SCHEDULER 2 | #define WDY_1829373821_LRU_SCHEDULER 3 | #include "scheduler.hpp" 4 | #include 5 | 6 | namespace PageDB { 7 | class LRU_Scheduler : public Scheduler { 8 | std::map lruIndex; 9 | virtual void Schedule(); 10 | }; 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /PageDB/page.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_8320182910_PAGE 2 | #define WDY_8320182910_PAGE 3 | #include "file.hpp" 4 | #include 5 | 6 | namespace PageDB { 7 | struct Page { 8 | char buf[PAGE_SIZE]; 9 | }; 10 | 11 | struct PageDesc { 12 | File* file; 13 | int page_id; 14 | Page* page; 15 | std::mutex ref_mutex; 16 | int ref; 17 | bool dirty; 18 | bool used; 19 | PageDesc(File* _file, int _page_id) 20 | : file(_file), page_id(_page_id), 21 | page(nullptr), ref_mutex(), ref(0), dirty(false), used(false) 22 | {} 23 | void incRef() { 24 | used = true; 25 | ref_mutex.lock(); 26 | ref++; 27 | if (page == nullptr) { 28 | page = file->loadPage(page_id); 29 | } 30 | ref_mutex.unlock(); 31 | } 32 | void decRef() { 33 | ref_mutex.lock(); 34 | ref--; 35 | ref_mutex.unlock(); 36 | } 37 | void write() { 38 | dirty = true; 39 | } 40 | void WriteBack() { 41 | if (dirty) { 42 | dirty = false; 43 | file->writePage(page_id, page); 44 | } 45 | } 46 | void Release(bool force = true) { 47 | if (force) { 48 | ref_mutex.lock(); 49 | } else { 50 | if (!ref_mutex.try_lock()) { 51 | return; 52 | } 53 | } 54 | if (force || ref == 0) { 55 | WriteBack(); 56 | delete page; 57 | page = nullptr; 58 | } 59 | ref_mutex.unlock(); 60 | } 61 | void Useless() { 62 | ref_mutex.lock(); 63 | delete page; 64 | page = nullptr; 65 | dirty = false; 66 | ref_mutex.unlock(); 67 | } 68 | ~PageDesc() { 69 | Release(); 70 | } 71 | void Remove() { 72 | ref_mutex.lock(); 73 | dirty = false; 74 | ref = 0; 75 | delete page; 76 | page = nullptr; 77 | ref_mutex.unlock(); 78 | } 79 | }; 80 | 81 | struct PageSession { 82 | PageDesc* desc; 83 | PageSession(PageDesc* _desc = nullptr) : desc(_desc) { 84 | incRef(); 85 | } 86 | PageSession(PageSession&& pgs) : desc(pgs.desc) {pgs.desc = nullptr;} 87 | PageSession(const PageSession& pgs) : desc(pgs.desc) {incRef();} 88 | PageSession& operator=(PageSession&& pgs) { 89 | decRef(); 90 | desc = pgs.desc; 91 | pgs.desc = nullptr; 92 | return * this; 93 | } 94 | PageSession& operator=(const PageSession& pgs) { 95 | decRef(); 96 | desc = pgs.desc; 97 | incRef(); 98 | return * this; 99 | } 100 | void decRef() { 101 | if (desc) 102 | desc->decRef(); 103 | } 104 | void incRef() { 105 | if (desc) 106 | desc->incRef(); 107 | } 108 | ~PageSession() { 109 | decRef(); 110 | desc = nullptr; 111 | } 112 | const Page& page() { 113 | return *(desc->page); 114 | } 115 | const char* buf() { 116 | return page().buf; 117 | } 118 | }; 119 | 120 | struct PageWriteSession { 121 | PageDesc* desc; 122 | PageWriteSession(PageDesc* _desc = nullptr) : desc(_desc) { 123 | incRef(); 124 | } 125 | PageWriteSession(PageWriteSession&& pgs) : desc(pgs.desc) {pgs.desc = nullptr;} 126 | PageWriteSession(const PageWriteSession& pgs) : desc(pgs.desc) {incRef();} 127 | PageWriteSession& operator=(PageWriteSession&& pgs) { 128 | decRef(); 129 | desc = pgs.desc; 130 | pgs.desc = nullptr; 131 | return * this; 132 | } 133 | PageWriteSession& operator=(const PageWriteSession& pgs) { 134 | decRef(); 135 | desc = pgs.desc; 136 | incRef(); 137 | return * this; 138 | } 139 | void flush() { 140 | if (desc) { 141 | desc->write(); 142 | } 143 | } 144 | void decRef() { 145 | if (desc) { 146 | desc->write(); 147 | desc->decRef(); 148 | } 149 | } 150 | void incRef() { 151 | if (desc) 152 | desc->incRef(); 153 | } 154 | void Release() { 155 | decRef(); 156 | desc = nullptr; 157 | } 158 | ~PageWriteSession() { 159 | Release(); 160 | } 161 | Page& page() { 162 | return *(desc->page); 163 | } 164 | char* buf() { 165 | return page().buf; 166 | } 167 | }; 168 | } 169 | #endif 170 | -------------------------------------------------------------------------------- /PageDB/scheduler.cpp: -------------------------------------------------------------------------------- 1 | #include "scheduler.hpp" 2 | #include 3 | #include 4 | 5 | namespace PageDB { 6 | void Scheduler::ScheduleLoop() { 7 | while (running) { 8 | std::this_thread::sleep_for(SCHEDULE_LOOP_DELAY); 9 | Schedule(); 10 | } 11 | } 12 | void Scheduler::StartSchedule() { 13 | if (!running) { 14 | running = true; 15 | ScheduleThread = std::thread([=](){this->ScheduleLoop();}); 16 | } 17 | } 18 | void Scheduler::StopSchedule() { 19 | if (running) { 20 | running = false; 21 | ScheduleThread.join(); 22 | } 23 | } 24 | File* Scheduler::OpenFile(const std::string& fn) { 25 | File*& file = fileIndex[fn]; 26 | if (file == nullptr) { 27 | file = new File(fn); 28 | } 29 | return file; 30 | } 31 | File* Scheduler::InitFile(const std::string& fn) { 32 | File*& file = fileIndex[fn]; 33 | if (file == nullptr) { 34 | file = new File(fn); 35 | } else { 36 | auto beg = pageIndex.lower_bound(std::make_pair(file, 0)); 37 | auto end = pageIndex.upper_bound(std::make_pair(file, 0x3FFFFFFF)); 38 | for (auto iter = beg; iter != end; iter++) 39 | iter->second->Useless(); 40 | } 41 | file->initFile(); 42 | return file; 43 | } 44 | PageDesc* Scheduler::GetPage(File* file, int page_id) { 45 | if (page_id < 0) 46 | return nullptr; 47 | PageDesc*& desc = pageIndex[std::make_pair(file, page_id)]; 48 | if (desc == nullptr) { 49 | desc = new PageDesc(file, page_id); 50 | } 51 | return desc; 52 | } 53 | void Scheduler::RemovePage(File* file, int page_id) { 54 | PageDesc*& desc = pageIndex[std::make_pair(file, page_id)]; 55 | if (desc) { 56 | desc->Remove(); 57 | } 58 | file->removePage(page_id); 59 | } 60 | PageSession Scheduler::GetSession(File* file, int page_id) { 61 | return PageSession(GetPage(file, page_id)); 62 | } 63 | PageWriteSession Scheduler::GetWriteSession(File* file, int page_id) { 64 | return PageWriteSession(GetPage(file, page_id)); 65 | } 66 | Scheduler::~Scheduler() { 67 | StopSchedule(); 68 | for (auto& item : pageIndex) 69 | delete item.second; 70 | for (auto& item : fileIndex) 71 | delete item.second; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /PageDB/scheduler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9282100293_SCHEDULER 2 | #define WDY_9282100293_SCHEDULER 3 | #include "file.hpp" 4 | #include "page.hpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace PageDB { 11 | //Sleep Seconds 12 | const auto SCHEDULE_LOOP_DELAY = std::chrono::milliseconds(100); 13 | class Scheduler { 14 | std::thread ScheduleThread; 15 | void ScheduleLoop(); 16 | bool running; 17 | protected: 18 | std::map fileIndex; 19 | std::map, PageDesc*> pageIndex; 20 | virtual void Schedule() = 0; 21 | public: 22 | Scheduler() : running(false) {} 23 | void StartSchedule(); 24 | void StopSchedule(); 25 | bool Running() { 26 | return running; 27 | } 28 | File* OpenFile(const std::string& fn); 29 | File* InitFile(const std::string& fn); 30 | PageDesc* GetPage(File* file, int page_id); 31 | void RemovePage(File* file, int page_id); 32 | PageSession GetSession(File* file, int page_id); 33 | PageWriteSession GetWriteSession(File* file, int page_id); 34 | virtual ~Scheduler(); 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewdy/mymymysql/ecb881b1b048dc908b033dbfd95b6455b17ba331/README -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mymymysql 2 | ========= 3 | A simple SQL Server... 4 | -------------------------------------------------------------------------------- /Stmt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(Stmt) 2 | -------------------------------------------------------------------------------- /Stmt/createDBStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "createDBStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void CreateDBStmt::Run(Context::Context& ctx) { 6 | ctx.CreateDB(db); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/createDBStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1923791823_CREATE_DB_STMT 2 | #define WDY_1923791823_CREATE_DB_STMT 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct CreateDBStmt : public Stmt { 6 | std::string db; 7 | virtual void Run(Context::Context& ctx); 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /Stmt/createTableStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "createTableStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void CreateTableStmt::Run(Context::Context& ctx) { 6 | ctx.InitTable(tbl, desc); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/createTableStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1923187232_CREATETABLESTMT 2 | #define WDY_1923187232_CREATETABLESTMT 3 | #include "stmt.hpp" 4 | #include 5 | #include "TypeDB/expr.hpp" 6 | namespace Stmt { 7 | struct CreateTableStmt : public Stmt { 8 | std::string tbl; 9 | TypeDB::TableDesc desc; 10 | virtual void Run(Context::Context& ctx); 11 | }; 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /Stmt/deleteStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "deleteStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void DeleteStmt::Run(Context::Context& ctx) { 6 | ctx.AssertTable(tbl); 7 | TypeDB::Table table = filter(ctx, tbl, where); 8 | ctx.Delete(tbl, table); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Stmt/deleteStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_8916271829_DELETESTMT 2 | #define WDY_8916271829_DELETESTMT 3 | #include "stmt.hpp" 4 | #include 5 | #include "TypeDB/expr.hpp" 6 | namespace Stmt { 7 | struct DeleteStmt : public Stmt { 8 | std::string tbl; 9 | TypeDB::Expr* where; 10 | virtual void Run(Context::Context& ctx); 11 | }; 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /Stmt/descStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "descStmt.hpp" 2 | 3 | namespace Stmt { 4 | void descStmt::Run(Context::Context& ctx) { 5 | auto tbls = ctx.GetTableDesc(tbl); 6 | for (auto desc : tbls.descs) { 7 | std::cout << desc.name << " " << desc.type->toString() << std::endl; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Stmt/descStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1829367129_DESC_STMT 2 | #define WDY_1829367129_DESC_STMT 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct descStmt : public Stmt { 6 | std::string tbl; 7 | virtual void Run(Context::Context& ctx); 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /Stmt/dropDBStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "dropDBStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void DropDBStmt::Run(Context::Context& ctx) { 6 | ctx.DropDB(db); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/dropDBStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1278936123_DROP_DB_STMT 2 | #define WDY_1278936123_DROP_DB_STMT 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct DropDBStmt : public Stmt { 6 | std::string db; 7 | virtual void Run(Context::Context& ctx); 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /Stmt/dropTableStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "dropTableStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void DropTableStmt::Run(Context::Context& ctx) { 6 | ctx.DropTable(tbl); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/dropTableStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1287312763_DROP_TABLE_STMT 2 | #define WDY_1287312763_DROP_TABLE_STMT 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct DropTableStmt : public Stmt { 6 | std::string tbl; 7 | virtual void Run(Context::Context& ctx); 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /Stmt/filter.cpp: -------------------------------------------------------------------------------- 1 | #include "filter.hpp" 2 | 3 | namespace Stmt { 4 | TypeDB::Table filter(const Context::Context& ctx, const std::vector& tbls, TypeDB::Expr* cond, bool force) { 5 | auto ret = filter(ctx, tbls[0], cond, true); 6 | for (std::size_t i = 1; i < tbls.size(); i++) { 7 | auto new_tbl = filter(ctx, tbls[i], cond, true); 8 | auto desc = TypeDB::TableDesc::merge(ret.desc, new_tbl.desc); 9 | ret.desc = desc; 10 | std::vector rows; 11 | for (auto& row1 : ret.rows) 12 | for (auto& row2 : new_tbl.rows) { 13 | auto row = TypeDB::Row::merge(row1, row2); 14 | if (cond) { 15 | auto x = cond->CalcBool(desc, row); 16 | if (!x.first || x.second) 17 | rows.push_back(row); 18 | } else { 19 | rows.push_back(row); 20 | } 21 | } 22 | ret.rows.swap(rows); 23 | } 24 | if (cond && !force) { 25 | for (auto& row : ret.rows) 26 | if (!cond->CalcBool(ret.desc, row).first) { 27 | throw "Column Not Found"; 28 | } 29 | } 30 | return std::move(ret); 31 | } 32 | TypeDB::Table filter(const Context::Context& ctx, TypeDB::TableSelector* tbl, TypeDB::Expr* cond, bool force) { 33 | TypeDB::Table ret = tbl->getTable(ctx); 34 | if (cond) { 35 | std::vector rows; 36 | for (auto& row : ret.rows) { 37 | auto x = cond->CalcBool(ret.desc, row); 38 | if (!force && !x.first) { 39 | throw "Column Not Found"; 40 | } 41 | if (!x.first || x.second) 42 | rows.push_back(std::move(row)); 43 | } 44 | ret.rows.swap(rows); 45 | } 46 | return std::move(ret); 47 | } 48 | TypeDB::Table filter(const Context::Context& ctx, const std::string& tblName, TypeDB::Expr* cond, bool force) { 49 | TypeDB::Table ret = ctx.GetTable(tblName); 50 | if (cond) { 51 | std::vector rows; 52 | for (auto& row : ret.rows) { 53 | auto x = cond->CalcBool(ret.desc, row); 54 | if (force && !x.first) { 55 | throw "Column Not Found"; 56 | } 57 | if (!x.first || x.second) 58 | rows.push_back(std::move(row)); 59 | } 60 | ret.rows.swap(rows); 61 | } 62 | return std::move(ret); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Stmt/filter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9102392182_STMT_FILTER 2 | #define WDY_9102392182_STMT_FILTER 3 | #include "TypeDB/table.hpp" 4 | #include "TypeDB/tblSelector.hpp" 5 | #include "TypeDB/expr.hpp" 6 | #include "context/context.hpp" 7 | namespace Stmt { 8 | TypeDB::Table filter(const Context::Context& ctx, const std::vector& tbls, TypeDB::Expr* cond = nullptr, bool force = false); 9 | TypeDB::Table filter(const Context::Context& ctx, TypeDB::TableSelector* tbl, TypeDB::Expr* cond = nullptr, bool force = false); 10 | TypeDB::Table filter(const Context::Context& ctx, const std::string& tblName, TypeDB::Expr* cond = nullptr, bool force = false); 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /Stmt/insertStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "insertStmt.hpp" 2 | 3 | namespace Stmt { 4 | void InsertStmt::Run(Context::Context& ctx) { 5 | ctx.AssertTable(tbl_name); 6 | ctx.Insert(tbl_name, tbl); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/insertStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9281293742_INSERTSTMT 2 | #define WDY_9281293742_INSERTSTMT 3 | #include "stmt.hpp" 4 | #include "TypeDB/tblExpr.hpp" 5 | #include "TypeDB/tblSelector.hpp" 6 | #include "TypeDB/expr.hpp" 7 | #include 8 | namespace Stmt { 9 | struct InsertStmt : public Stmt { 10 | virtual void Run(Context::Context& ctx); 11 | std::string tbl_name; 12 | TypeDB::Table tbl; 13 | }; 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /Stmt/selectStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "SelectStmt.hpp" 2 | #include "filter.hpp" 3 | #include 4 | 5 | namespace Stmt { 6 | void SelectStmt::Run(Context::Context& ctx) { 7 | auto tbl = filter(ctx, from, where); 8 | if (groupby == nullptr) 9 | Output(tbl); 10 | else { 11 | std::map> tbls; 12 | for (auto& row : tbl.rows) { 13 | tbls[groupby->Calc(tbl.desc, row).second->hash()].push_back(std::move(row)); 14 | } 15 | for (auto& item : tbls) { 16 | tbl.rows = std::move(item.second); 17 | Output(tbl); 18 | } 19 | } 20 | } 21 | void SelectStmt::Output(const TypeDB::Table& tbl) { 22 | if (selectAll) { 23 | for (auto& row : tbl.rows) { 24 | for (auto& item : row.objs) 25 | std::cout << item->toString() << " "; 26 | std::cout << std::endl; 27 | } 28 | } else { 29 | std::vector> objects; 30 | for (auto& item : select) 31 | objects.push_back(item->Calc(tbl)); 32 | std::size_t size = 0xFFFFFFFF; 33 | for (auto& item : objects) 34 | size = size < item.size() ? size : item.size(); 35 | for (std::size_t i = 0; i < size; i++) { 36 | for (auto& item : objects) 37 | std::cout << item[i]->toString() << " "; 38 | std::cout << std::endl; 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Stmt/selectStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0392129210_SELECTSTMT 2 | #define WDY_0392129210_SELECTSTMT 3 | #include "stmt.hpp" 4 | #include "TypeDB/tblExpr.hpp" 5 | #include "TypeDB/tblSelector.hpp" 6 | #include "TypeDB/expr.hpp" 7 | #include 8 | namespace Stmt { 9 | struct SelectStmt : public Stmt { 10 | virtual void Run(Context::Context& ctx); 11 | void Output(const TypeDB::Table& tbl); 12 | std::vector select; 13 | bool selectAll; 14 | TypeDB::Expr* groupby; 15 | std::vector from; 16 | TypeDB::Expr* where; 17 | SelectStmt() : selectAll(false), groupby(nullptr), where(nullptr) {} 18 | }; 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /Stmt/showTablesStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "showTablesStmt.hpp" 2 | 3 | namespace Stmt { 4 | void ShowTablesStmt::Run(Context::Context& ctx) { 5 | auto tbls = ctx.ReadDB(); 6 | for (auto& tbl : tbls) 7 | std::cout << tbl << std::endl; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Stmt/showTablesStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1231782392_SHOW_TABLES 2 | #define WDY_1231782392_SHOW_TABLES 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct ShowTablesStmt : public Stmt { 6 | virtual void Run(Context::Context& ctx); 7 | }; 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /Stmt/stmt.cpp: -------------------------------------------------------------------------------- 1 | #include "stmt.hpp" 2 | 3 | namespace Stmt { 4 | void Stmt::Run(Context::Context& ctx) { 5 | //TODO 6 | throw "Internal Error"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/stmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0293192102_STMT 2 | #define WDY_0293192102_STMT 3 | #include "context/context.hpp" 4 | namespace Stmt { 5 | struct Stmt { 6 | virtual void Run(Context::Context& ctx); 7 | virtual ~Stmt() {} 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /Stmt/updateStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "updateStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void UpdateStmt::Run(Context::Context& ctx) { 6 | ctx.AssertTable(tbl); 7 | TypeDB::Table table = filter(ctx, tbl, where); 8 | for (auto& rule : rules) { 9 | int idx = table.desc.getIndex("", rule.first); 10 | if (idx == table.desc.primaryIndex) { 11 | throw "Cannot Update Primary Key"; 12 | } 13 | for (auto& row : table.rows) { 14 | auto rst = rule.second->Calc(table.desc, row); 15 | if (!table.desc.descs[idx].type->Test(rst.second.obj)) { 16 | throw "Type Check Error"; 17 | } 18 | row.objs[idx] = rst.second; 19 | } 20 | } 21 | ctx.Update(tbl, table); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Stmt/updateStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_7321273921_UPDATESTMT 2 | #define WDY_7321273921_UPDATESTMT 3 | #include "stmt.hpp" 4 | #include 5 | #include "TypeDB/expr.hpp" 6 | namespace Stmt { 7 | struct UpdateStmt : public Stmt { 8 | std::string tbl; 9 | std::unordered_map rules; 10 | TypeDB::Expr* where; 11 | virtual void Run(Context::Context& ctx); 12 | }; 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /Stmt/useDBStmt.cpp: -------------------------------------------------------------------------------- 1 | #include "useDBStmt.hpp" 2 | #include "filter.hpp" 3 | 4 | namespace Stmt { 5 | void UseDBStmt::Run(Context::Context& ctx) { 6 | ctx.UseDB(db); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Stmt/useDBStmt.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_8718762328_USE_DB_STMT 2 | #define WDY_8718762328_USE_DB_STMT 3 | #include "stmt.hpp" 4 | namespace Stmt { 5 | struct UseDBStmt : public Stmt { 6 | std::string db; 7 | virtual void Run(Context::Context& ctx); 8 | }; 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /TypeDB/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewdy/mymymysql/ecb881b1b048dc908b033dbfd95b6455b17ba331/TypeDB/.DS_Store -------------------------------------------------------------------------------- /TypeDB/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(TypeDB) 2 | -------------------------------------------------------------------------------- /TypeDB/expr.cpp: -------------------------------------------------------------------------------- 1 | #include "expr.hpp" 2 | #include "Exception/Exception.hpp" 3 | 4 | namespace TypeDB { 5 | std::pair Expr::Calc(const TableDesc& desc, const Row& row) { 6 | throw "Syntax Error"; 7 | } 8 | 9 | std::pair Expr::CalcBool(const TableDesc& desc, const Row& row) { 10 | throw "Syntax Error"; 11 | } 12 | 13 | Expr::~Expr() {} 14 | 15 | std::pair LiteralExpr::Calc(const TableDesc& desc, const Row& row) { 16 | return std::make_pair(true, Literal); 17 | } 18 | 19 | std::pair ReadExpr::Calc(const TableDesc& desc, const Row& row) { 20 | auto ret = desc.getObject(row, tbl, name, true); 21 | if (ret.obj == nullptr) 22 | return std::make_pair(false, ret); 23 | else 24 | return std::make_pair(true, ret); 25 | } 26 | 27 | std::pair UnaryExpr::CalcBool(const TableDesc& desc, const Row& row) { 28 | switch (op) { 29 | case Not: 30 | { 31 | auto X = l->CalcBool(desc, row); 32 | X.second = !X.second; 33 | return X; 34 | } 35 | case IsNull: 36 | { 37 | auto X = l->Calc(desc, row); 38 | Null* ptr = dynamic_cast(X.second.obj); 39 | return std::make_pair(X.first, ptr != nullptr); 40 | } 41 | } 42 | } 43 | 44 | UnaryExpr::~UnaryExpr() {delete l;} 45 | 46 | #define CALC2BOOL(op, def) \ 47 | {\ 48 | auto lhs = l->CalcBool(desc, row), rhs = r->CalcBool(desc, row);\ 49 | if (lhs.first && rhs.first)\ 50 | return std::make_pair(true, lhs.second op rhs.second);\ 51 | else\ 52 | return std::make_pair(false, def);\ 53 | } 54 | #define CALC2OBJ(op, def) \ 55 | {\ 56 | auto lhs = l->Calc(desc, row), rhs = r->Calc(desc, row);\ 57 | if (lhs.first && rhs.first)\ 58 | return std::make_pair(true, lhs.second->op_##op(rhs.second));\ 59 | else\ 60 | return std::make_pair(false, def);\ 61 | } 62 | std::pair BinaryExpr::Calc(const TableDesc& desc, const Row& row) { 63 | switch (op) { 64 | case Plus: 65 | CALC2OBJ(add, nullptr); 66 | case Minus: 67 | CALC2OBJ(minus, nullptr); 68 | break; 69 | default: 70 | throw "Syntax Error"; 71 | } 72 | } 73 | 74 | std::pair BinaryExpr::CalcBool(const TableDesc& desc, const Row& row) { 75 | switch (op) { 76 | case Equal: 77 | CALC2OBJ(eq, false); 78 | case NotEqual: 79 | CALC2OBJ(ne, false); 80 | case LessThan: 81 | CALC2OBJ(lt, false); 82 | case GreaterThan: 83 | CALC2OBJ(gt, false); 84 | case LessEqual: 85 | CALC2OBJ(le, false); 86 | case GreaterEqual: 87 | CALC2OBJ(ge, false); 88 | case Like: 89 | CALC2OBJ(like, false); 90 | case And: 91 | { 92 | auto lhs = l->CalcBool(desc, row), rhs = r->CalcBool(desc, row); 93 | if (lhs.first && rhs.first) 94 | return std::make_pair(true, lhs.second && rhs.second); 95 | if (!lhs.first && !rhs.first) 96 | return std::make_pair(false, false); 97 | if (lhs.first) 98 | return std::make_pair(!lhs.second, lhs.second); 99 | if (rhs.first) 100 | return std::make_pair(!rhs.second, rhs.second); 101 | } 102 | case Or: 103 | { 104 | auto lhs = l->CalcBool(desc, row), rhs = r->CalcBool(desc, row); 105 | if (lhs.first && rhs.first) 106 | return std::make_pair(true, lhs.second || rhs.second); 107 | if (!lhs.first && !rhs.first) 108 | return std::make_pair(false, false); 109 | if (lhs.first) 110 | return std::make_pair(lhs.second, lhs.second); 111 | if (rhs.first) 112 | return std::make_pair(rhs.second, rhs.second); 113 | } 114 | default: 115 | throw "Syntax Error"; 116 | } 117 | } 118 | 119 | BinaryExpr::~BinaryExpr() {delete l; delete r;} 120 | } 121 | -------------------------------------------------------------------------------- /TypeDB/expr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0293812012_EXPR 2 | #define WDY_0293812012_EXPR 3 | #include "table.hpp" 4 | 5 | namespace TypeDB { 6 | struct Expr { 7 | virtual std::pair Calc(const TableDesc& desc, const Row& row); 8 | virtual std::pair CalcBool(const TableDesc& desc, const Row& row); 9 | virtual ~Expr(); 10 | }; 11 | struct LiteralExpr : public Expr { 12 | pObject Literal; 13 | LiteralExpr(const pObject& l) : Literal(l) {} 14 | LiteralExpr(pObject&& l) : Literal(std::move(l)) {} 15 | virtual std::pair Calc(const TableDesc& desc, const Row& row); 16 | }; 17 | struct ReadExpr : public Expr { 18 | std::string tbl, name; 19 | ReadExpr(const std::string& _tbl, const std::string& _name) : tbl(_tbl), name(_name) {} 20 | ReadExpr(const std::string& _name) : tbl(""), name(_name) {} 21 | virtual std::pair Calc(const TableDesc& desc, const Row& row); 22 | }; 23 | struct UnaryExpr : public Expr { 24 | Expr *l; 25 | enum OpCode { 26 | Not, 27 | IsNull, 28 | } op; 29 | UnaryExpr(Expr* _l, OpCode _op) : l(_l), op(_op) {} 30 | virtual std::pair CalcBool(const TableDesc& desc, const Row& row); 31 | virtual ~UnaryExpr(); 32 | }; 33 | struct BinaryExpr : public Expr { 34 | Expr *l, *r; 35 | enum OpCode { 36 | Plus, 37 | Minus, 38 | Equal, 39 | NotEqual, 40 | LessThan, 41 | GreaterThan, 42 | LessEqual, 43 | GreaterEqual, 44 | And, 45 | Or, 46 | Like, 47 | } op; 48 | BinaryExpr(Expr* _l, Expr* _r, OpCode _op) : l(_l), r(_r), op(_op) {} 49 | virtual std::pair Calc(const TableDesc& desc, const Row& row); 50 | virtual std::pair CalcBool(const TableDesc& desc, const Row& row); 51 | virtual ~BinaryExpr(); 52 | }; 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /TypeDB/object.cpp: -------------------------------------------------------------------------------- 1 | #include "Object.hpp" 2 | #include "Exception/Exception.hpp" 3 | #include "Utils/bufOp.hpp" 4 | #include 5 | 6 | namespace TypeDB { 7 | 8 | Object::~Object() {} 9 | bool Object::op_eq(Object* rhs) {throw "Syntax Error";} 10 | bool Object::op_ne(Object* rhs) {throw "Syntax Error";} 11 | bool Object::op_lt(Object* rhs) {throw "Syntax Error";} 12 | bool Object::op_gt(Object* rhs) {throw "Syntax Error";} 13 | bool Object::op_le(Object* rhs) {throw "Syntax Error";} 14 | bool Object::op_ge(Object* rhs) {throw "Syntax Error";} 15 | bool Object::op_like(Object* rhs) {throw "Syntax Error";} 16 | bool Object::op_is_null(Object* rhs) {return false;} 17 | Object* Object::op_add(Object* rhs) {throw "Syntax Error";} 18 | Object* Object::op_minus(Object* rhs) {throw "Syntax Error";} 19 | 20 | #define DEF_NULL_BOOL_OP(op) \ 21 | bool Null::op_##op(Object* rhs) {return false;} 22 | 23 | DEF_NULL_BOOL_OP(eq); 24 | DEF_NULL_BOOL_OP(ne); 25 | DEF_NULL_BOOL_OP(lt); 26 | DEF_NULL_BOOL_OP(gt); 27 | DEF_NULL_BOOL_OP(le); 28 | DEF_NULL_BOOL_OP(ge); 29 | DEF_NULL_BOOL_OP(like); 30 | 31 | 32 | #define DEF_BOOL_OP(type, op, opc) \ 33 | bool type::op_##op(Object* rhs) {\ 34 | type* _rhs = dynamic_cast(rhs);\ 35 | if (_rhs == nullptr) {\ 36 | if (dynamic_cast(rhs) == nullptr)\ 37 | throw "Syntax Error";\ 38 | else\ 39 | return false;\ 40 | }\ 41 | return raw opc _rhs->raw;\ 42 | } 43 | 44 | #define DEF_OBJ_OP(type, op, opc) \ 45 | Object* type::op_##op(Object* rhs) {\ 46 | type* _rhs = dynamic_cast(rhs);\ 47 | if (_rhs == nullptr) {\ 48 | throw "Syntax Error";\ 49 | }\ 50 | return new type(raw opc _rhs->raw);\ 51 | } 52 | 53 | DEF_BOOL_OP(Int, eq, ==); 54 | DEF_BOOL_OP(Int, ne, !=); 55 | DEF_BOOL_OP(Int, lt, <); 56 | DEF_BOOL_OP(Int, gt, >); 57 | DEF_BOOL_OP(Int, le, <=); 58 | DEF_BOOL_OP(Int, ge, >=); 59 | DEF_OBJ_OP(Int, add, +); 60 | DEF_OBJ_OP(Int, minus, -); 61 | 62 | DEF_BOOL_OP(String, eq, ==); 63 | DEF_BOOL_OP(String, ne, !=); 64 | DEF_BOOL_OP(String, lt, <); 65 | DEF_BOOL_OP(String, gt, >); 66 | DEF_BOOL_OP(String, le, <=); 67 | DEF_BOOL_OP(String, ge, >=); 68 | DEF_OBJ_OP(String, add, +); 69 | 70 | bool Null::op_is_null(Object* rhs) {return true;} 71 | 72 | bool String::op_like(Object* rhs) { 73 | String* _rhs = dynamic_cast(rhs); 74 | if (_rhs == nullptr) { 75 | throw "Type Check Error"; 76 | } 77 | std::string& r = _rhs->raw; 78 | std::vector loc; 79 | loc.push_back(0); 80 | for (char x : r) { 81 | if (loc.empty()) 82 | break; 83 | std::vector locX; 84 | if (x == '%') { 85 | for (int i = loc[0]; i <= raw.size(); i++) 86 | locX.push_back(i); 87 | } else { 88 | for (auto i : loc) 89 | if (i < raw.size() && (raw[i] == x || x == '_')) 90 | locX.push_back(i + 1); 91 | } 92 | loc = std::move(locX); 93 | } 94 | return !loc.empty() && loc.back() == raw.size(); 95 | } 96 | 97 | BTree::Key Object::hash() { 98 | throw "Syntax Error"; 99 | } 100 | BTree::Key Null::hash() { 101 | return BTree::Key(0x19940319, 0x65766f6c, 0x19941102); 102 | } 103 | BTree::Key Int::hash() { 104 | return BTree::Key(raw); 105 | } 106 | BTree::Key String::hash() { 107 | return BTree::Key(raw); 108 | } 109 | void Object::write(char*& buf) { 110 | throw "Syntax Error"; 111 | } 112 | void Null::write(char*& buf) { 113 | Utils::writeInt(buf, 0x80000000); 114 | } 115 | void Int::write(char*& buf) { 116 | Utils::writeInt(buf, raw); 117 | } 118 | void String::write(char*& buf) { 119 | Utils::writeString(buf, raw); 120 | } 121 | std::string Object::toString() { 122 | throw "Syntax Error"; 123 | } 124 | std::string Null::toString() { 125 | return "NULL"; 126 | } 127 | std::string Int::toString() { 128 | return std::to_string(raw); 129 | } 130 | std::string Double::toString() { 131 | return std::to_string(raw); 132 | } 133 | std::string String::toString() { 134 | return raw; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /TypeDB/object.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1293829183_OBJECT 2 | #define WDY_1293829183_OBJECT 3 | #include 4 | #include 5 | #include "BTree/Hash.hpp" 6 | 7 | namespace TypeDB { 8 | struct Object { 9 | virtual ~Object(); 10 | virtual bool op_eq(Object* rhs); 11 | virtual bool op_ne(Object* rhs); 12 | virtual bool op_lt(Object* rhs); 13 | virtual bool op_gt(Object* rhs); 14 | virtual bool op_le(Object* rhs); 15 | virtual bool op_ge(Object* rhs); 16 | virtual bool op_like(Object* rhs); 17 | virtual bool op_is_null(Object* rhs); 18 | virtual Object* op_add(Object* rhs); 19 | virtual Object* op_minus(Object* rhs); 20 | virtual BTree::Key hash(); 21 | virtual void write(char*& buf); 22 | virtual std::string toString(); 23 | }; 24 | struct Null : public Object { 25 | virtual bool op_eq(Object* rhs); 26 | virtual bool op_ne(Object* rhs); 27 | virtual bool op_lt(Object* rhs); 28 | virtual bool op_gt(Object* rhs); 29 | virtual bool op_le(Object* rhs); 30 | virtual bool op_ge(Object* rhs); 31 | virtual bool op_like(Object* rhs); 32 | virtual void write(char*& buf); 33 | virtual bool op_is_null(Object* rhs); 34 | virtual BTree::Key hash(); 35 | virtual std::string toString(); 36 | }; 37 | struct Int : public Object { 38 | int raw; 39 | Int(int _raw) : raw(_raw) {} 40 | virtual bool op_eq(Object* rhs); 41 | virtual bool op_ne(Object* rhs); 42 | virtual bool op_lt(Object* rhs); 43 | virtual bool op_gt(Object* rhs); 44 | virtual bool op_le(Object* rhs); 45 | virtual bool op_ge(Object* rhs); 46 | virtual Object* op_add(Object* rhs); 47 | virtual Object* op_minus(Object* rhs); 48 | virtual BTree::Key hash(); 49 | virtual void write(char*& buf); 50 | virtual std::string toString(); 51 | }; 52 | struct Double : public Object { 53 | double raw; 54 | Double(double _raw) : raw(_raw) {} 55 | virtual std::string toString(); 56 | }; 57 | struct String : public Object { 58 | std::string raw; 59 | String(const std::string& _raw) : raw(_raw) {} 60 | String(std::string&& _raw) : raw(std::move(_raw)) {} 61 | virtual bool op_eq(Object* rhs); 62 | virtual bool op_ne(Object* rhs); 63 | virtual bool op_lt(Object* rhs); 64 | virtual bool op_gt(Object* rhs); 65 | virtual bool op_le(Object* rhs); 66 | virtual bool op_ge(Object* rhs); 67 | virtual bool op_like(Object* rhs); 68 | virtual Object* op_add(Object* rhs); 69 | virtual BTree::Key hash(); 70 | virtual void write(char*& buf); 71 | virtual std::string toString(); 72 | }; 73 | struct pObject { 74 | Object* obj; 75 | int* ref; 76 | void Reduce() {if (obj) {(*ref)--;}} 77 | void Increase() {if (obj) {(*ref)++;}} 78 | pObject() : obj(nullptr), ref(nullptr) {} 79 | pObject(Object* _obj) : obj(_obj), ref(new int(1)) {} 80 | pObject(const pObject& pobj) : obj(pobj.obj), ref(pobj.ref) {Increase();} 81 | pObject(pObject&& pobj) : obj(pobj.obj), ref(pobj.ref) {pobj.obj = nullptr; pobj.ref = nullptr;} 82 | pObject& operator=(const pObject& rhs) { 83 | Reduce(); 84 | obj = rhs.obj; 85 | ref = rhs.ref; 86 | Increase(); 87 | return *this; 88 | } 89 | pObject& operator=(pObject&& rhs) { 90 | Reduce(); 91 | obj = rhs.obj; 92 | ref = rhs.ref; 93 | rhs.obj = nullptr; 94 | rhs.ref = nullptr; 95 | return *this; 96 | } 97 | Object* operator->() const {return obj;} 98 | operator Object*() const {return obj;} 99 | }; 100 | } 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /TypeDB/table.cpp: -------------------------------------------------------------------------------- 1 | #include "table.hpp" 2 | #include "Exception/Exception.hpp" 3 | 4 | namespace TypeDB { 5 | Row Row::merge(const Row& lhs, const Row& rhs) { 6 | Row ret; 7 | ret.objs.reserve(lhs.objs.size() + rhs.objs.size()); 8 | ret.objs.insert(ret.objs.end(), lhs.objs.begin(), lhs.objs.end()); 9 | ret.objs.insert(ret.objs.end(), rhs.objs.begin(), rhs.objs.end()); 10 | return std::move(ret); 11 | } 12 | int TableDesc::getIndex(const std::string& tbl, const std::string& name, bool force) const { 13 | int result = -1; 14 | if (tbl == "") { 15 | for (std::size_t i = 0; i < descs.size(); i++) { 16 | if (descs[i].name == name) { 17 | if (result == -1) 18 | result = i; 19 | else 20 | throw "ColumnMultiFound"; 21 | } 22 | } 23 | } else { 24 | for (std::size_t i = 0; i < descs.size(); i++) { 25 | if (descs[i].tbl == tbl && descs[i].name == name) { 26 | result = i; 27 | break; 28 | } 29 | } 30 | } 31 | if (result == -1) { 32 | if (force) 33 | return -1; 34 | else 35 | throw "ColumnNotFound"; 36 | } 37 | return result; 38 | } 39 | pObject TableDesc::getObject(const std::vector& rows, const std::string& tbl, const std::string& name, bool force) const { 40 | auto idx = getIndex(tbl, name, force); 41 | if (idx == -1) 42 | return nullptr; 43 | for (auto& row : rows) 44 | if (idx < (int)row->objs.size()) 45 | return row->objs[idx]; 46 | else 47 | idx -= row->objs.size(); 48 | throw "Column Not Found"; 49 | } 50 | pObject TableDesc::getObject(const Row& row, const std::string& tbl, const std::string& name, bool force) const { 51 | auto idx = getIndex(tbl, name, force); 52 | if (idx == -1) 53 | return nullptr; 54 | return row.objs[idx]; 55 | } 56 | void TableDesc::setForeign(const std::string& name, const std::string& fT, const std::string& fK) { 57 | for (std::size_t i = 0; i < descs.size(); i++) { 58 | if (descs[i].name == name) { 59 | descs[i].type->foreignTable = fT; 60 | descs[i].type->foreignKey = fK; 61 | return; 62 | } 63 | } 64 | throw "Column Not Found"; 65 | } 66 | void TableDesc::setPrimary(const std::string& name) { 67 | for (std::size_t i = 0; i < descs.size(); i++) { 68 | if (descs[i].name == name) { 69 | primaryIndex = i; 70 | return; 71 | } 72 | } 73 | //TODO 74 | throw "Column Not Found"; 75 | } 76 | pObject TableDesc::getPrimary(const Row& row) const { 77 | return row.objs[primaryIndex]; 78 | } 79 | TableDesc TableDesc::merge(const TableDesc& lhs, const TableDesc& rhs) { 80 | TableDesc ret; 81 | ret.primaryIndex = lhs.primaryIndex; 82 | ret.descs.reserve(lhs.descs.size() + rhs.descs.size()); 83 | ret.descs.insert(ret.descs.end(), lhs.descs.begin(), lhs.descs.end()); 84 | ret.descs.insert(ret.descs.end(), rhs.descs.begin(), rhs.descs.end()); 85 | return std::move(ret); 86 | } 87 | bool TableDesc::Test(const Row& row) const { 88 | if (row.objs.size() != descs.size()) 89 | return false; 90 | for (std::size_t i = 0; i < descs.size(); i++) { 91 | if (!descs[i].type->Test(row.objs[i])) 92 | return false; 93 | } 94 | return true; 95 | } 96 | std::vector Table::getVec(const std::string& tbl, const std::string& name) const { 97 | std::size_t index = desc.getIndex(tbl, name); 98 | std::vector ret; 99 | for (auto row : rows) 100 | ret.push_back(row.objs[index]); 101 | return std::move(ret); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /TypeDB/table.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9218312393_TABLE 2 | #define WDY_9218312393_TABLE 3 | #include "type.hpp" 4 | #include 5 | #include 6 | #include "Exception/Exception.hpp" 7 | 8 | namespace TypeDB { 9 | struct ColDesc { 10 | std::string tbl, name; 11 | Type* type; 12 | ColDesc() {} 13 | ColDesc(const std::string& _name, Type* _type) : name(_name), type(_type) {} 14 | std::string toString() { 15 | if (tbl.empty()) 16 | return name; 17 | else 18 | return tbl + '.' + name; 19 | } 20 | }; 21 | struct Row { 22 | std::vector objs; 23 | static Row merge(const Row& lhs, const Row& rhs); 24 | }; 25 | struct TableDesc { 26 | std::vector descs; 27 | std::size_t primaryIndex; 28 | TableDesc() : primaryIndex(0) {} 29 | void setPrimary(const std::string& name); 30 | void setForeign(const std::string& name, const std::string& fT, const std::string& fK); 31 | int getIndex(const std::string& tbl, const std::string& name, bool force = false) const; 32 | pObject getObject(const std::vector& rows, const std::string& tbl, const std::string& name, bool force = false) const; 33 | pObject getObject(const Row& rows, const std::string& tbl, const std::string& name, bool force = false) const; 34 | pObject getPrimary(const Row& row) const; 35 | static TableDesc merge(const TableDesc& lhs, const TableDesc& rhs); 36 | bool Test(const Row& row) const; 37 | }; 38 | struct Table { 39 | TableDesc desc; 40 | std::vector rows; 41 | std::vector getVec(const std::string& tbl, const std::string& name) const; 42 | }; 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /TypeDB/tblExpr.cpp: -------------------------------------------------------------------------------- 1 | #include "tblExpr.hpp" 2 | #include "Exception/Exception.hpp" 3 | 4 | namespace TypeDB { 5 | TblExpr::~TblExpr() {} 6 | std::vector ReadTblExpr::Calc(const Table& table) { 7 | return table.getVec(tbl, name); 8 | } 9 | std::vector UnaryTblExpr::Calc(const Table& table) { 10 | std::vector org = l->Calc(table); 11 | auto beg = org.begin(), end = org.end(); 12 | pObject retX = *beg++; 13 | switch (op) { 14 | case Sum: 15 | { 16 | for (auto iter = beg; iter != end; iter++) 17 | retX = retX->op_add(*iter); 18 | break; 19 | } 20 | case Avg: 21 | { 22 | for (auto iter = beg; iter != end; iter++) 23 | retX = retX->op_add(*iter); 24 | Object* raw = retX; 25 | Int* i = dynamic_cast(raw); 26 | int r = i->raw; 27 | retX = new Double((double)r / org.size()); 28 | break; 29 | } 30 | case Min: 31 | { 32 | for (auto iter = beg; iter != end; iter++) 33 | retX = retX->op_lt(*iter) ? retX : *iter; 34 | break; 35 | } 36 | case Max: 37 | for (auto iter = beg; iter != end; iter++) 38 | retX = retX->op_gt(*iter) ? retX : *iter; 39 | break; 40 | } 41 | return std::vector(1, std::move(retX)); 42 | } 43 | UnaryTblExpr::~UnaryTblExpr() {delete l;} 44 | } 45 | -------------------------------------------------------------------------------- /TypeDB/tblExpr.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_1823162721_TBLEXPR 2 | #define WDY_1823162721_TBLEXPR 3 | #include "table.hpp" 4 | #include 5 | 6 | namespace TypeDB { 7 | struct TblExpr { 8 | virtual std::vector Calc(const Table& table) = 0; 9 | virtual ~TblExpr(); 10 | }; 11 | struct ReadTblExpr : public TblExpr { 12 | std::string tbl; 13 | std::string name; 14 | ReadTblExpr(const std::string& _tbl, const std::string& _name) : tbl(_tbl), name(_name) {} 15 | ReadTblExpr(const std::string& _name) : tbl(""), name(_name) {} 16 | virtual std::vector Calc(const Table& table); 17 | }; 18 | struct UnaryTblExpr : public TblExpr { 19 | TblExpr* l; 20 | enum OpCode { 21 | Sum, 22 | Avg, 23 | Min, 24 | Max, 25 | } op; 26 | UnaryTblExpr(TblExpr* _l, OpCode _op) : l(_l), op(_op) {} 27 | virtual std::vector Calc(const Table& table); 28 | virtual ~UnaryTblExpr(); 29 | }; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /TypeDB/tblSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "tblSelector.hpp" 2 | 3 | namespace TypeDB { 4 | Table RawTableSelector::getTable(const Context::Context& ctx) { 5 | ctx.AssertTable(tblname); 6 | return ctx.GetTable(tblname); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /TypeDB/tblSelector.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9182102932_TBLSELECTOR 2 | #define WDY_9182102932_TBLSELECTOR 3 | #include "table.hpp" 4 | #include "context/context.hpp" 5 | 6 | namespace TypeDB { 7 | struct TableSelector { 8 | virtual Table getTable(const Context::Context& ctx) = 0; 9 | virtual ~TableSelector() {} 10 | }; 11 | struct RawTableSelector : TableSelector{ 12 | std::string tblname; 13 | RawTableSelector(std::string _tblname) : tblname(_tblname) {} 14 | virtual Table getTable(const Context::Context& ctx); 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /TypeDB/type.cpp: -------------------------------------------------------------------------------- 1 | #include "type.hpp" 2 | #include "utils/bufOp.hpp" 3 | 4 | namespace TypeDB { 5 | void IntType::Jump(const char*& buf) { 6 | Utils::jumpInt(buf); 7 | } 8 | Object* IntType::CreateAndJump(const char*& buf) { 9 | int ret = Utils::readInt(buf); 10 | if (ret == 0x80000000) 11 | return NullType::none; 12 | return Create(ret); 13 | } 14 | void StringType::Jump(const char*& buf) { 15 | Utils::jumpString(buf); 16 | } 17 | Object* StringType::CreateAndJump(const char*& buf) { 18 | int size = Utils::readInt(buf); 19 | if (size == 0x80000000) 20 | return NullType::none; 21 | std::string ret(buf, buf + size); 22 | buf += size; 23 | return Create(ret); 24 | } 25 | bool Type::Test(Object* obj) { 26 | //TODO 27 | throw "Internal Error"; 28 | } 29 | bool StringType::Test(Object* obj) { 30 | if (obj == NullType::none) 31 | return null_; 32 | auto r = dynamic_cast(obj); 33 | return r; 34 | } 35 | bool IntType::Test(Object* obj) { 36 | if (obj == NullType::none) 37 | return null_; 38 | auto r = dynamic_cast(obj); 39 | return r; 40 | } 41 | std::string Type::toString() { 42 | //TODO 43 | throw "Internal Error"; 44 | } 45 | std::string IntType::toString() { 46 | return "INT(" + std::to_string(desc) + ")"; 47 | } 48 | std::string StringType::toString() { 49 | return "STRING(" + std::to_string(desc) + ")"; 50 | } 51 | static Null null; 52 | Null* NullType::none = &null; 53 | Type* createIntType(int _desc, bool _null_) {return new IntType(_desc, _null_);} 54 | Type* createStringType(int _desc, bool _null_) {return new StringType(_desc, _null_);} 55 | TypeCreator typeCreators[ErrorTypeEnum] = {createIntType, createStringType}; 56 | } 57 | -------------------------------------------------------------------------------- /TypeDB/type.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9812310210_TYPE 2 | #define WDY_9812310210_TYPE 3 | #include 4 | #include "object.hpp" 5 | 6 | namespace TypeDB { 7 | enum TypeEnum : unsigned char { 8 | IntEnum, 9 | StringEnum, 10 | NullEnum, 11 | ErrorTypeEnum, 12 | }; 13 | struct Type { 14 | int desc; 15 | bool null_; 16 | std::string foreignTable; 17 | std::string foreignKey; 18 | TypeEnum type; 19 | Type(int _desc = 0, bool _null_ = true, TypeEnum _type = ErrorTypeEnum) : desc(_desc), null_(_null_), type(_type) {} 20 | virtual void Jump(const char*& buf) = 0; 21 | virtual Object* CreateAndJump(const char*& buf) = 0; 22 | virtual bool Test(Object* obj); 23 | virtual std::string toString(); 24 | virtual ~Type(){} 25 | }; 26 | struct NullType { 27 | static Null* none; 28 | static Null* Create() { 29 | return none; 30 | } 31 | }; 32 | struct IntType : public Type { 33 | static Int* Create(int x) { 34 | return new Int(x); 35 | } 36 | IntType(int _desc, bool _null_ = true) : Type(_desc, _null_, IntEnum) {} 37 | virtual void Jump(const char*& buf); 38 | virtual Object* CreateAndJump(const char*& buf); 39 | virtual std::string toString(); 40 | virtual bool Test(Object* obj); 41 | }; 42 | struct StringType : public Type { 43 | static String* Create(const std::string& x) { 44 | return new String(x); 45 | } 46 | StringType(int _desc, bool _null_ = true) : Type(_desc, _null_, StringEnum) {} 47 | virtual void Jump(const char*& buf); 48 | virtual Object* CreateAndJump(const char*& buf); 49 | virtual std::string toString(); 50 | virtual bool Test(Object* obj); 51 | }; 52 | void initTypes(); 53 | typedef Type* (*TypeCreator)(int _desc, bool _null_); 54 | extern TypeCreator typeCreators[ErrorTypeEnum]; 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /context/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | new_static_library(Context) 2 | -------------------------------------------------------------------------------- /context/context.cpp: -------------------------------------------------------------------------------- 1 | #include "context.hpp" 2 | #include "utils/bufOp.hpp" 3 | #include "BTree/BTree.hpp" 4 | #include "Utils/writeFile.hpp" 5 | 6 | namespace Context { 7 | typedef std::pair colTypeDesc; 8 | static TypeDB::Type* readType(const char*& buf) { 9 | TypeDB::TypeEnum type = (TypeDB::TypeEnum)Utils::readByte(buf); 10 | int desc = Utils::readInt(buf); 11 | bool null_ = desc & 0x80000000; 12 | desc = desc & 0x3FFFFFFF; 13 | auto ret = TypeDB::typeCreators[type](desc, null_); 14 | ret->foreignTable = Utils::readString(buf); 15 | ret->foreignKey = Utils::readString(buf); 16 | return ret; 17 | } 18 | static void writeType(char*& buf, TypeDB::Type* desc) { 19 | Utils::writeByte(buf, desc->type); 20 | Utils::writeInt(buf, desc->desc | ((int)desc->null_ << 31)); 21 | Utils::writeString(buf, desc->foreignTable); 22 | Utils::writeString(buf, desc->foreignKey); 23 | } 24 | void Context::InitTable(const std::string& tblName, const TypeDB::TableDesc& desc) const { 25 | if (!dbNewTable(tblName)) { 26 | throw "Table Already Exist"; 27 | } 28 | pgdb->InitFile(tblidxFileName(tblName)); 29 | auto file = pgdb->InitFile(tblFileName(tblName)); 30 | auto x = pgdb->GetWriteSession(file, file->entryPageID); 31 | auto buf = x.buf(); 32 | Utils::writeInt(buf, 1); 33 | Utils::writeInt(buf, 0); 34 | Utils::writeWord(buf, desc.descs.size()); 35 | Utils::writeWord(buf, desc.primaryIndex); 36 | for (std::size_t i = 0; i < desc.descs.size(); i++) { 37 | writeType(buf, desc.descs[i].type); 38 | Utils::writeString(buf, desc.descs[i].name); 39 | } 40 | file->eof = PageDB::Location(file->newPage(), 0); 41 | file->writebackFileHeaderCore(); 42 | } 43 | TypeDB::TableDesc Context::GetTableDesc(const std::string& tblName) const { 44 | auto file = pgdb->OpenFile(tblFileName(tblName)); 45 | auto x = pgdb->GetSession(file, file->entryPageID); 46 | auto buf = x.buf(); 47 | Utils::jumpInt(buf); 48 | Utils::jumpInt(buf); 49 | auto sz = Utils::readWord(buf); 50 | TypeDB::TableDesc ret; 51 | ret.primaryIndex = Utils::readWord(buf); 52 | ret.descs.resize(sz); 53 | for (int i = 0; i < sz; i++) { 54 | ret.descs[i].type = readType(buf); 55 | ret.descs[i].tbl = tblName; 56 | ret.descs[i].name = Utils::readString(buf); 57 | } 58 | return std::move(ret); 59 | } 60 | void Context::DropTable(const std::string& tblName) const { 61 | if (!dbRemoveTable(tblName)) { 62 | //TODO: throw a exception 63 | throw "Table Not Found"; 64 | } 65 | } 66 | TypeDB::Table Context::GetTable(const std::string& tblName) const { 67 | TypeDB::Table ret; 68 | ret.desc = GetTableDesc(tblName); 69 | BTree::BTree btree(pgdb, tblidxFileName(tblName)); 70 | PageDB::ConstIterator pgiter(pgdb, pgdb->OpenFile(tblFileName(tblName))); 71 | auto iter = btree.begin(), end = btree.end(); 72 | for (; iter != end; iter.Next()) { 73 | auto v = iter.value(); 74 | pgiter.Goto(v); 75 | auto buf = pgiter.Get(); 76 | TypeDB::Row row; 77 | row.objs.resize(ret.desc.descs.size()); 78 | Utils::jumpWord(buf); 79 | for (std::size_t i = 0; i < ret.desc.descs.size(); i++) 80 | row.objs[i] = ret.desc.descs[i].type->CreateAndJump(buf); 81 | ret.rows.push_back(std::move(row)); 82 | } 83 | return ret; 84 | } 85 | static char* WriteRow(char* buf, const TypeDB::Row& row) { 86 | char* org_buf = buf; 87 | Utils::jumpWord(buf); 88 | for (auto& item : row.objs) 89 | item->write(buf); 90 | Utils::writeWord(org_buf, buf - org_buf); 91 | return buf; 92 | } 93 | void Context::AssertTable(const std::string& tblName) const { 94 | auto tbls = ReadDB(); 95 | for (auto& tbl : tbls) 96 | if (tbl == tblName) 97 | return; 98 | throw "Table Not Found"; 99 | } 100 | void Context::Insert(const std::string& tblName, const TypeDB::Table& tbl) const { 101 | PageDB::File* tblFile = pgdb->OpenFile(tblFileName(tblName)); 102 | BTree::BTree btree(pgdb, tblidxFileName(tblName)); 103 | auto desc = GetTableDesc(tblName); 104 | //Test 105 | for (auto& row : tbl.rows) { 106 | if (!desc.Test(row)) { 107 | throw "Type Check Error"; 108 | } 109 | if (btree.find(desc.getPrimary(row)->hash()).first) { 110 | throw "Primary Key Conflict"; 111 | } 112 | } 113 | for (std::size_t i = 0; i < desc.descs.size(); i++) { 114 | auto& descX = desc.descs[i]; 115 | if (descX.type->foreignTable != "") { 116 | AssertTable(descX.type->foreignTable); 117 | BTree::BTree btreeX(pgdb, tblidxFileName(descX.type->foreignTable)); 118 | for (auto& row : tbl.rows) 119 | if (!btreeX.find(row.objs[i]->hash()).first) { 120 | throw "Foriegn Key Check Error"; 121 | } 122 | } 123 | } 124 | //Begin 125 | PageDB::Iterator iter(pgdb, tblFile); 126 | char* writeBuf = new char[PageDB::PAGE_SIZE]; 127 | for (const TypeDB::Row& row : tbl.rows) { 128 | char* eob = WriteRow(writeBuf, row); 129 | auto loc = Utils::writeFile(pgdb, tblFile, writeBuf, eob - writeBuf); 130 | btree.set(desc.getPrimary(row)->hash(), loc, true); 131 | } 132 | delete [] writeBuf; 133 | } 134 | void Context::Update(const std::string& tblName, const TypeDB::Table& tbl) const { 135 | //Test 136 | auto desc = tbl.desc; 137 | for (auto& row : tbl.rows) { 138 | if (!desc.Test(row)) { 139 | throw "Type Check Error"; 140 | } 141 | } 142 | for (std::size_t i = 0; i < desc.descs.size(); i++) { 143 | auto& descX = desc.descs[i]; 144 | if (descX.type->foreignTable != "") { 145 | AssertTable(descX.type->foreignTable); 146 | BTree::BTree btreeX(pgdb, tblidxFileName(descX.type->foreignTable)); 147 | for (auto& row : tbl.rows) 148 | if (!btreeX.find(row.objs[i]->hash()).first) { 149 | throw "Foriegn Key Check Error"; 150 | } 151 | } 152 | } 153 | PageDB::File* tblFile = pgdb->OpenFile(tblFileName(tblName)); 154 | BTree::BTree btree(pgdb, tblidxFileName(tblName)); 155 | PageDB::Iterator iter(pgdb, tblFile); 156 | char* writeBuf = new char[PageDB::PAGE_SIZE]; 157 | for (const TypeDB::Row& row : tbl.rows) { 158 | auto loc = btree.find(tbl.desc.getPrimary(row)->hash()); 159 | if (!loc.first) { 160 | throw "Cannnot Update Primary Key"; 161 | } 162 | iter.Goto(loc.second); 163 | char* buf = iter.Get(); 164 | int size = Utils::readWord(buf); 165 | char* eob = WriteRow(writeBuf, row); 166 | if (eob - writeBuf > size) { 167 | auto new_loc = Utils::writeFile(pgdb, tblFile, writeBuf, eob - writeBuf); 168 | btree.set(tbl.desc.getPrimary(row)->hash(), new_loc, true); 169 | } else { 170 | memcpy(buf, writeBuf + 2, eob - writeBuf - 2); 171 | } 172 | } 173 | delete [] writeBuf; 174 | } 175 | void Context::Delete(const std::string& tblName, const TypeDB::Table& tbl) const { 176 | BTree::BTree btree(pgdb, tblidxFileName(tblName)); 177 | for (const TypeDB::Row& row : tbl.rows) { 178 | btree.remove(tbl.desc.getPrimary(row)->hash()); 179 | } 180 | } 181 | std::vector Context::ReadDB(const std::string& fn) const { 182 | PageDB::File* dbFile = pgdb->OpenFile(fn); 183 | PageDB::PageSession session = pgdb->GetSession(dbFile, dbFile->entryPageID); 184 | const char* buf = session.buf(); 185 | int size = Utils::readInt(buf); 186 | std::vector ret; 187 | for (int i = 0; i < size; i++) 188 | ret.push_back(Utils::readString(buf)); 189 | return ret; 190 | } 191 | void Context::WriteDB(const std::string& fn, const std::vector& info) const { 192 | PageDB::File* dbFile = pgdb->OpenFile(fn); 193 | PageDB::PageWriteSession session = pgdb->GetWriteSession(dbFile, dbFile->entryPageID); 194 | char* buf = session.buf(); 195 | Utils::writeInt(buf, info.size()); 196 | for (auto& item : info) 197 | Utils::writeString(buf, item); 198 | } 199 | std::vector Context::ReadDB() const { 200 | return ReadDB(dbFileName()); 201 | } 202 | void Context::WriteDB(const std::vector& info) const { 203 | return WriteDB(dbFileName(), info); 204 | } 205 | bool Context::dbNewTable(const std::string& tblName) const { 206 | auto x = ReadDB(); 207 | for (std::size_t i = 0; i < x.size(); i++) { 208 | if (x[i] == tblName) { 209 | return false; 210 | } 211 | } 212 | x.push_back(tblName); 213 | WriteDB(x); 214 | return true; 215 | } 216 | bool Context::dbRemoveTable(const std::string& tblName) const { 217 | auto x = ReadDB(); 218 | std::size_t p; 219 | for (p = 0; p < x.size(); p++) { 220 | if (x[p] == tblName) { 221 | break; 222 | } 223 | } 224 | if (p == x.size()) { 225 | return false; 226 | } 227 | for (std::size_t i = p; i + 1 < x.size(); i++) 228 | x[i] = x[i + 1]; 229 | x.pop_back(); 230 | WriteDB(x); 231 | return true; 232 | } 233 | void Context::UseDB(const std::string& _dbName) { 234 | auto tbls = ReadDB(DBFilename); 235 | for (auto& tbl : tbls) 236 | if (_dbName == tbl) { 237 | dbName = _dbName; 238 | return; 239 | } 240 | throw "DB Not Found"; 241 | } 242 | void Context::CreateDB(const std::string& _dbName) { 243 | auto tbls = ReadDB(DBFilename); 244 | for (auto& tbl : tbls) 245 | if (_dbName == tbl) { 246 | //TODO 247 | throw "Table Already Exist"; 248 | } 249 | pgdb->InitFile(_dbName + ".db"); 250 | tbls.push_back(_dbName); 251 | WriteDB(DBFilename, tbls); 252 | } 253 | void Context::DropDB(const std::string& _dbName) { 254 | if (_dbName == DefaultDB) { 255 | //TODO 256 | throw "Permission Denined"; 257 | } 258 | if (_dbName == dbName) { 259 | //TODO 260 | throw "Cannot Drop Self"; 261 | } 262 | auto tbls = ReadDB(DBFilename); 263 | for (auto& tbl : tbls) 264 | if (_dbName == tbl) { 265 | tbl = tbls.back(); 266 | tbls.pop_back(); 267 | WriteDB(DBFilename, tbls); 268 | return; 269 | } 270 | //TODO 271 | throw "DB Not Found"; 272 | } 273 | void Context::Init() { 274 | auto tbls = ReadDB(DBFilename); 275 | for (auto& tbl : tbls) 276 | if (tbl == DefaultDB) { 277 | return; 278 | } 279 | pgdb->InitFile(DefaultDB + ".db"); 280 | tbls.push_back(DefaultDB); 281 | WriteDB(DBFilename, tbls); 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /context/context.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_9203812930_CONTEXT 2 | #define WDY_9203812930_CONTEXT 3 | 4 | #include "TypeDB/object.hpp" 5 | #include "TypeDB/table.hpp" 6 | #include "PageDB/lru_scheduler.hpp" 7 | #include "PageDB/scheduler.hpp" 8 | 9 | namespace Context { 10 | static const std::string DefaultDB = "test"; 11 | static const std::string DBFilename = "DB.DBX"; 12 | struct Context { 13 | PageDB::Scheduler* pgdb; 14 | std::string dbName; 15 | std::string tblFileName(const std::string& tblName) const { 16 | return dbName + ":" + tblName + ".db"; 17 | } 18 | std::string tblidxFileName(const std::string& tblName) const { 19 | return dbName + ":" + tblName + ".idx"; 20 | } 21 | std::string dbFileName() const { 22 | return dbName + ".db"; 23 | } 24 | Context(PageDB::Scheduler* _pgdb) : pgdb(_pgdb), dbName(DefaultDB) {Init();} 25 | void InitTable(const std::string& tblName, const TypeDB::TableDesc& desc) const; 26 | TypeDB::TableDesc GetTableDesc(const std::string& tblName) const; 27 | void DropTable(const std::string& tblName) const; 28 | TypeDB::Table GetTable(const std::string& tblName) const; 29 | void AssertTable(const std::string& tblName) const; 30 | void Insert(const std::string& tblName, const TypeDB::Table& tbl) const; 31 | void Update(const std::string& tblName, const TypeDB::Table& tbl) const; 32 | void Delete(const std::string& tblName, const TypeDB::Table& tbl) const; 33 | std::vector ReadDB() const; 34 | void WriteDB(const std::vector& info) const; 35 | std::vector ReadDB(const std::string& fn) const; 36 | void WriteDB(const std::string& fn, const std::vector& info) const; 37 | bool dbNewTable(const std::string& tblName) const; 38 | bool dbRemoveTable(const std::string& tblName) const; 39 | void UseDB(const std::string& _dbName); 40 | void CreateDB(const std::string& _dbName); 41 | void DropDB(const std::string& _dbName); 42 | void Init(); 43 | }; 44 | } 45 | #endif 46 | -------------------------------------------------------------------------------- /frontend/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codewdy/mymymysql/ecb881b1b048dc908b033dbfd95b6455b17ba331/frontend/.DS_Store -------------------------------------------------------------------------------- /frontend/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Parser.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Parser.h" 2 | COMMAND ${LEMON_EXECUTABLE} Parser.y | cat 3 | COMMAND ${CMD_MV} Parser.c "${CMAKE_CURRENT_BINARY_DIR}/Parser.cpp" 4 | COMMAND ${CMD_MV} Parser.h "${CMAKE_CURRENT_BINARY_DIR}/Parser.h" 5 | COMMAND ${CMD_RM} Parser.out 6 | MAIN_DEPENDENCY Parser.y 7 | WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 8 | ) 9 | 10 | ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Lexer.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Lexer.h" 11 | COMMAND "${FLEX_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/Lexer.l" 12 | MAIN_DEPENDENCY Lexer.l 13 | WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 14 | ) 15 | 16 | INCLUDE_DIRECTORIES(".") 17 | ADD_LIBRARY(Parser STATIC "${CMAKE_CURRENT_BINARY_DIR}/Parser.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Lexer.cpp") 18 | 19 | -------------------------------------------------------------------------------- /frontend/Lexer.l: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "Exception/Exception.hpp" 3 | #include 4 | #include 5 | #include "Parser.h" 6 | #include "ParserDef.h" 7 | std::vector sb; 8 | Lex curLex; 9 | 10 | #define BuildOpX(X, str) do {curLex.type = X; curLex.raw = str; return 1;} while(0) 11 | #define BuildLex(X) do {\ 12 | BuildOpX(X, new std::string(yytext));\ 13 | }while(0) 14 | #define BuildOp(X) do {\ 15 | BuildOpX(X, nullptr);\ 16 | }while(0) 17 | #define BuildStr(X) do {\ 18 | BuildOpX(X, new std::string(sb.begin(), sb.end()));\ 19 | }while(0) 20 | %} 21 | 22 | DIGIT ([0-9]) 23 | INTEGER ({DIGIT}+) 24 | IDENTIFIER ([_A-Za-z][_0-9A-Za-z]*) 25 | WHITESPACE ([ \t\n\r]+) 26 | 27 | %option outfile="Lexer.cpp" HEADER-FILE="Lexer.h" 28 | %option c++ 29 | %x S 30 | %x S2 31 | 32 | %% 33 | {WHITESPACE} {} 34 | 35 | "+" {BuildOp(PLUS);} 36 | "-" {BuildOp(MINUS);} 37 | "*" {BuildOp(STAR);} 38 | "," {BuildOp(COMMA);} 39 | ">" {BuildOp(GT);} 40 | "<" {BuildOp(LT);} 41 | ">=" {BuildOp(GE);} 42 | "<=" {BuildOp(LE);} 43 | "=" {BuildOp(EQ);} 44 | "<>" {BuildOp(NE);} 45 | "(" {BuildOp(LLC);} 46 | ")" {BuildOp(RLC);} 47 | "." {BuildOp(DOT);} 48 | (?i:not) {BuildOp(NOT);} 49 | (?i:and) {BuildOp(AND);} 50 | (?i:or) {BuildOp(OR);} 51 | (?i:select) {BuildOp(SELECT);} 52 | (?i:from) {BuildOp(FROM);} 53 | (?i:where) {BuildOp(WHERE);} 54 | (?i:sum) {BuildOp(SUM);} 55 | (?i:avg) {BuildOp(AVG);} 56 | (?i:min) {BuildOp(MIN);} 57 | (?i:max) {BuildOp(MAX);} 58 | (?i:group) {BuildOp(GROUP);} 59 | (?i:by) {BuildOp(BY);} 60 | (?i:insert) {BuildOp(INSERT);} 61 | (?i:into) {BuildOp(INTO);} 62 | (?i:values) {BuildOp(VALUES);} 63 | (?i:update) {BuildOp(UPDATE);} 64 | (?i:set) {BuildOp(SET);} 65 | (?i:delete) {BuildOp(DELETE);} 66 | (?i:null) {BuildOp(NULL_);} 67 | (?i:int) {BuildOp(INT);} 68 | (?i:varchar) {BuildOp(VARCHAR);} 69 | (?i:create) {BuildOp(CREATE);} 70 | (?i:table) {BuildOp(TABLE);} 71 | (?i:primary) {BuildOp(PRIMARY);} 72 | (?i:key) {BuildOp(KEY);} 73 | (?i:drop) {BuildOp(DROP);} 74 | (?i:show) {BuildOp(SHOW);} 75 | (?i:tables) {BuildOp(TABLES);} 76 | (?i:database) {BuildOp(DATABASE);} 77 | (?i:use) {BuildOp(USE);} 78 | (?i:foreign) {BuildOp(FOREIGN);} 79 | (?i:references) {BuildOp(REFERENCES);} 80 | (?i:desc) {BuildOp(DESC);} 81 | (?i:is) {BuildOp(IS);} 82 | (?i:like) {BuildOp(LIKE);} 83 | 84 | {INTEGER} {BuildLex(INTEGER);} 85 | 86 | \" {BEGIN S; sb.clear();} 87 | <> {throw "Syntax Error";} 88 | \" {BEGIN INITIAL; BuildStr(STRING);} 89 | "\\n" {sb.push_back('\n');} 90 | "\\t" {sb.push_back('\t');} 91 | "\\\"" {sb.push_back('\"');} 92 | "\\\\" {sb.push_back('\\');} 93 | . {sb.push_back(YYText()[0]);} 94 | 95 | ' {BEGIN S2; sb.clear();} 96 | <> {throw "Syntax Error";} 97 | ' {BEGIN INITIAL; BuildStr(STRING);} 98 | "\\n" {sb.push_back('\n');} 99 | "\\t" {sb.push_back('\t');} 100 | "\\'" {sb.push_back('\'');} 101 | "\\\\" {sb.push_back('\\');} 102 | . {sb.push_back(YYText()[0]);} 103 | 104 | {IDENTIFIER} {BuildLex(IDENTIFIER);} 105 | 106 | <> {return 0;} 107 | . {throw "Syntax Error";} 108 | %% 109 | 110 | int yyFlexLexer::yywrap() { return 1; } 111 | -------------------------------------------------------------------------------- /frontend/Parser.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_2923819213_FRONTEND_PARSER 2 | #define WDY_2923819213_FRONTEND_PARSER 3 | #include "Stmt/stmt.hpp" 4 | #include 5 | namespace Parser { 6 | Stmt::Stmt* CreateAST(std::string st); 7 | } 8 | #endif 9 | -------------------------------------------------------------------------------- /frontend/Parser.y: -------------------------------------------------------------------------------- 1 | %syntax_error { 2 | throw "Syntax Error"; 3 | } 4 | 5 | %include { 6 | #include 7 | #include "ParserDef.h" 8 | #include "Exception/Exception.hpp" 9 | #include 10 | #include "TypeDB/expr.hpp" 11 | #include "TypeDB/tblSelector.hpp" 12 | #include "TypeDB/tblExpr.hpp" 13 | #include "Stmt/updateStmt.hpp" 14 | #include "Stmt/selectStmt.hpp" 15 | #include "Stmt/insertStmt.hpp" 16 | #include "Stmt/deleteStmt.hpp" 17 | #include "Stmt/createTableStmt.hpp" 18 | #include "Stmt/dropTableStmt.hpp" 19 | #include "Stmt/showTablesStmt.hpp" 20 | #include "Stmt/createDBStmt.hpp" 21 | #include "Stmt/dropDBStmt.hpp" 22 | #include "Stmt/useDBStmt.hpp" 23 | #include "Stmt/descStmt.hpp" 24 | extern Lex curLex; 25 | } 26 | 27 | %code { 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "Lexer.h" 33 | namespace Parser { 34 | Stmt::Stmt* CreateAST(std::string st) { 35 | std::vector strs; 36 | void *parser = ParseAlloc(malloc); 37 | std::stringstream stream(st); 38 | try { 39 | yyFlexLexer lexer(&stream); 40 | while (lexer.yylex()) { 41 | if (curLex.raw) 42 | strs.push_back(curLex.raw); 43 | Parse(parser, curLex.type, curLex.raw, 0); 44 | } 45 | Stmt::Stmt* ret; 46 | Parse(parser, 0, 0, &ret); 47 | return ret; 48 | } catch(Exception::Exception *e) { 49 | ParseFree(parser, free); 50 | for (auto p : strs) 51 | delete p; 52 | throw e; 53 | } 54 | for (auto p : strs) 55 | delete p; 56 | } 57 | } 58 | } 59 | 60 | %left OR . 61 | %left AND . 62 | %left EQ NE . 63 | %left LE GE LT GT . 64 | %left PLUS MINUS . 65 | %nonassoc NOT . 66 | %nonassoc RLC . 67 | 68 | %extra_argument {Stmt::Stmt** ret} 69 | 70 | %start_symbol stmt 71 | 72 | %token_type {std::string*} 73 | %token_destructor {delete $$;} 74 | 75 | %type stmt {Stmt::Stmt*} 76 | stmt(A) ::= selectStmt(B). {*ret = A = B;} 77 | stmt(A) ::= insertStmt(B). {*ret = A = B;} 78 | stmt(A) ::= updateStmt(B). {*ret = A = B;} 79 | stmt(A) ::= deleteStmt(B). {*ret = A = B;} 80 | stmt(A) ::= createTableStmt(B). {*ret = A = B;} 81 | stmt(A) ::= dropTableStmt(B). {*ret = A = B;} 82 | stmt(A) ::= showTablesStmt(B). {*ret = A = B;} 83 | stmt(A) ::= useStmt(B). {*ret = A = B;} 84 | stmt(A) ::= createDBStmt(B). {*ret = A = B;} 85 | stmt(A) ::= dropDBStmt(B). {*ret = A = B;} 86 | stmt(A) ::= descStmt(B). {*ret = A = B;} 87 | 88 | %type selectStmt {Stmt::SelectStmt*} 89 | %destructor selectStmt {delete $$;} 90 | selectStmt(A) ::= selectClause(B) fromClause(C) . {A = B; A->from.swap(*C); delete C;} 91 | selectStmt(A) ::= selectStmt(B) whereClause(C) . {A = B; A->where = C;} 92 | selectStmt(A) ::= selectStmt(B) groupbyClause(C) . {A = B; A->groupby = C;} 93 | 94 | %type updateStmt {Stmt::UpdateStmt*} 95 | %destructor updateStmt {delete $$;} 96 | updateStmt(A) ::= updateClause(B) whereClause(C) . {A = B; A->where = C;} 97 | updateStmt(A) ::= updateClause(B) . {A = B; A->where = nullptr;} 98 | 99 | %type insertStmt {Stmt::InsertStmt*} 100 | %destructor insertStmt {delete $$;} 101 | insertStmt(A) ::= INSERT INTO IDENTIFIER(B) VALUES rows(C) . {A = new Stmt::InsertStmt; A->tbl.rows.swap(*C); A->tbl_name = *B; delete C;} 102 | 103 | %type deleteStmt {Stmt::DeleteStmt*} 104 | %destructor deleteStmt {delete $$;} 105 | deleteStmt(A) ::= DELETE FROM IDENTIFIER(B) . {A = new Stmt::DeleteStmt; A->tbl = *B; A->where = nullptr;} 106 | deleteStmt(A) ::= DELETE FROM IDENTIFIER(B) whereClause(C) . {A = new Stmt::DeleteStmt; A->tbl = *B; A->where = C;} 107 | 108 | %type createTableStmt {Stmt::CreateTableStmt*} 109 | %destructor createTableStmt {delete $$;} 110 | createTableStmt(A) ::= CREATE TABLE IDENTIFIER(B) LLC tblDesc(C) RLC . {A = new Stmt::CreateTableStmt; A->tbl = *B; A->desc = std::move(*C); delete C;} 111 | 112 | %type dropTableStmt {Stmt::DropTableStmt*} 113 | %destructor dropTableStmt {delete $$;} 114 | dropTableStmt(A) ::= DROP TABLE IDENTIFIER(B) . {A = new Stmt::DropTableStmt; A->tbl = *B;} 115 | 116 | %type showTablesStmt {Stmt::ShowTablesStmt*} 117 | %destructor showTablesStmt {delete $$;} 118 | showTablesStmt(A) ::= SHOW TABLES . {A = new Stmt::ShowTablesStmt;} 119 | 120 | %type useStmt {Stmt::UseDBStmt*} 121 | %destructor useStmt {delete $$;} 122 | useStmt(A) ::= USE IDENTIFIER(B) . {A = new Stmt::UseDBStmt(); A->db = *B;} 123 | 124 | %type createDBStmt {Stmt::CreateDBStmt*} 125 | %destructor createDBStmt {delete $$;} 126 | createDBStmt(A) ::= CREATE DATABASE IDENTIFIER(B) . {A = new Stmt::CreateDBStmt(); A->db = *B;} 127 | 128 | %type dropDBStmt {Stmt::DropDBStmt*} 129 | %destructor dropDBStmt {delete $$;} 130 | dropDBStmt(A) ::= DROP DATABASE IDENTIFIER(B) . {A = new Stmt::DropDBStmt(); A->db = *B;} 131 | 132 | %type descStmt {Stmt::descStmt*} 133 | %destructor descStmt {delete $$;} 134 | descStmt(A) ::= DESC IDENTIFIER(B) . {A = new Stmt::descStmt(); A->tbl = *B;} 135 | 136 | %type selectClause {Stmt::SelectStmt*} 137 | %destructor selectClause {delete $$;} 138 | selectClause(A) ::= SELECT tblExprList(B) . {A = new Stmt::SelectStmt; A->select.swap(*B); delete B;} 139 | selectClause(A) ::= SELECT STAR . {A = new Stmt::SelectStmt; A->selectAll = true;} 140 | 141 | %type tblExprList {std::vector*} 142 | %destructor tblExprList {delete $$;} 143 | tblExprList(A) ::= tblExprList(B) COMMA tblExpr(C) . {A = B; A->push_back(C);} 144 | tblExprList(A) ::= tblExpr(C) . {A = new std::vector; A->push_back(C);} 145 | 146 | %type tblExpr {TypeDB::TblExpr*} 147 | %destructor tblExpr{delete $$;} 148 | tblExpr(A) ::= IDENTIFIER(B) DOT IDENTIFIER(C) . {A = new TypeDB::ReadTblExpr(*B, *C);} 149 | tblExpr(A) ::= IDENTIFIER(B) . {A = new TypeDB::ReadTblExpr(*B);} 150 | tblExpr(A) ::= SUM LLC tblExpr(B) RLC . {A = new TypeDB::UnaryTblExpr(B, TypeDB::UnaryTblExpr::Sum);} 151 | tblExpr(A) ::= AVG LLC tblExpr(B) RLC . {A = new TypeDB::UnaryTblExpr(B, TypeDB::UnaryTblExpr::Avg);} 152 | tblExpr(A) ::= MIN LLC tblExpr(B) RLC . {A = new TypeDB::UnaryTblExpr(B, TypeDB::UnaryTblExpr::Min);} 153 | tblExpr(A) ::= MAX LLC tblExpr(B) RLC . {A = new TypeDB::UnaryTblExpr(B, TypeDB::UnaryTblExpr::Max);} 154 | 155 | %type fromClause {std::vector*} 156 | %destructor fromClause {delete $$;} 157 | fromClause(A) ::= FROM tables(B) . {A = B;} 158 | 159 | %type groupbyClause {TypeDB::Expr*} 160 | %destructor groupbyClause {delete $$;} 161 | groupbyClause(A) ::= GROUP BY expr(B) . {A = B;} 162 | 163 | %type tables {std::vector*} 164 | %destructor tables {delete $$;} 165 | tables(A) ::= tables(B) COMMA table(C) . {A = B; A->push_back(C);} 166 | tables(A) ::= table(C) . {A = new std::vector; A->push_back(C);} 167 | 168 | %type table {TypeDB::TableSelector*} 169 | %destructor table {delete $$;} 170 | table(A) ::= IDENTIFIER(B) . {A = new TypeDB::RawTableSelector(*B);} 171 | 172 | %type whereClause {TypeDB::Expr*} 173 | %destructor whereClause {delete $$;} 174 | whereClause(A) ::= WHERE expr(B) . {A = B;} 175 | 176 | %type updateClause {Stmt::UpdateStmt*} 177 | %destructor updateClause {delete $$;} 178 | updateClause(A) ::= UPDATE IDENTIFIER(B) SET updateRules(C) . {A = new Stmt::UpdateStmt; A->tbl = *B; A->rules.swap(*C); delete C;} 179 | 180 | %type updateRules {std::unordered_map*} 181 | %destructor updateRules {delete $$;} 182 | updateRules(A) ::= updateRules(B) COMMA updateRule(C) . {A = B; (*A)[C->first] = C->second; delete C;} 183 | updateRules(A) ::= updateRule(C) . {A = new std::unordered_map; (*A)[C->first] = C->second; delete C;} 184 | 185 | %type updateRule {std::pair*} 186 | %destructor updateRule {delete $$;} 187 | updateRule(A) ::= IDENTIFIER(B) EQ expr(C) . {A = new std::pair(*B, C);} 188 | 189 | %type expr {TypeDB::Expr*} 190 | %destructor expr {delete $$;} 191 | //Literal Expr 192 | expr(A) ::= literal(B) . {A = new TypeDB::LiteralExpr(B);} 193 | expr(A) ::= IDENTIFIER(B) . {A = new TypeDB::ReadExpr(*B);} 194 | expr(A) ::= IDENTIFIER(B) DOT IDENTIFIER(C) . {A = new TypeDB::ReadExpr(*B, *C);} 195 | //Simple Expr 196 | expr(A) ::= LLC expr(B) RLC . {A = B;} 197 | expr(A) ::= expr(B) PLUS expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::Plus);} 198 | expr(A) ::= expr(B) MINUS expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::Minus);} 199 | expr(A) ::= expr(B) EQ expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::Equal);} 200 | expr(A) ::= expr(B) NE expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::NotEqual);} 201 | expr(A) ::= expr(B) LT expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::LessThan);} 202 | expr(A) ::= expr(B) GT expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::GreaterThan);} 203 | expr(A) ::= expr(B) LE expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::LessEqual);} 204 | expr(A) ::= expr(B) GE expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::GreaterEqual);} 205 | expr(A) ::= expr(B) LIKE expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::Like);} 206 | expr(A) ::= expr(B) AND expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::And);} 207 | expr(A) ::= expr(B) OR expr(C) . {A = new TypeDB::BinaryExpr(B, C, TypeDB::BinaryExpr::Or);} 208 | expr(A) ::= NOT expr(B) . {A = new TypeDB::UnaryExpr(B, TypeDB::UnaryExpr::Not);} 209 | expr(A) ::= expr(B) IS NULL_ . {A = new TypeDB::UnaryExpr(B, TypeDB::UnaryExpr::IsNull);} 210 | 211 | %type rows {std::vector*} 212 | %destructor row {delete $$;} 213 | rows(A) ::= LLC row(C) RLC . {A = new std::vector; A->push_back(std::move(*C)); delete C;} 214 | rows(A) ::= rows(B) COMMA LLC row(C) RLC . {A = B; A->push_back(std::move(*C)); delete C;} 215 | 216 | %type row {TypeDB::Row*} 217 | row(A) ::= literal(C) . {A = new TypeDB::Row; A->objs.push_back(C);} 218 | row(A) ::= row(B) COMMA literal(C) . {A = B; A->objs.push_back(C);} 219 | 220 | %type literal {TypeDB::Object*} 221 | %destructor literal {delete $$;} 222 | literal(A) ::= STRING(B) . {A = TypeDB::StringType::Create(*B);} 223 | literal(A) ::= INTEGER(B) . {A = TypeDB::IntType::Create(std::stoi(*B));} 224 | literal(A) ::= NULL_ . {A = TypeDB::NullType::Create();} 225 | 226 | %type type {TypeDB::Type*} 227 | %destructor type {delete $$;} 228 | type(A) ::= INT LLC INTEGER(B) RLC . {A = new TypeDB::IntType(std::stoi(*B));} 229 | type(A) ::= VARCHAR LLC INTEGER(B) RLC . {A = new TypeDB::StringType(std::stoi(*B));} 230 | type(A) ::= type(B) NOT NULL_ . {A = B; A->null_ = false;} 231 | 232 | %type tblDesc {TypeDB::TableDesc*} 233 | %destructor tblDesc {delete $$;} 234 | tblDesc(A) ::= IDENTIFIER(C) type(D) . {A = new TypeDB::TableDesc; A->descs.push_back(TypeDB::ColDesc(*C, D));} 235 | tblDesc(A) ::= tblDesc(B) COMMA IDENTIFIER(C) type(D) . {A = B; A->descs.push_back(TypeDB::ColDesc(*C, D));} 236 | tblDesc(A) ::= tblDesc(B) COMMA PRIMARY KEY LLC IDENTIFIER(C) RLC . {A = B; A->setPrimary(*C);} 237 | tblDesc(A) ::= tblDesc(B) COMMA FOREIGN KEY LLC IDENTIFIER(C) RLC REFERENCES IDENTIFIER(D) LLC IDENTIFIER(E) RLC . {A = B; A->setForeign(*C, *D, *E);} 238 | -------------------------------------------------------------------------------- /frontend/ParserDef.h: -------------------------------------------------------------------------------- 1 | #ifndef FRONTEND_PARSERDEF 2 | #define FRONTEND_PARSERDEF 3 | #include 4 | struct Lex { 5 | int type; 6 | std::string* raw; 7 | }; 8 | #endif 9 | 10 | -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE(mymymysql main.cpp) 2 | TARGET_LINK_LIBRARIES(mymymysql Parser TypeDB Stmt BTree TypeDB Context Exception PageDB) 3 | -------------------------------------------------------------------------------- /main/main.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/parser.hpp" 2 | #include 3 | #include 4 | #include 5 | 6 | void RunStmt(const std::string& sql, Context::Context& ctx) { 7 | #ifndef DEBUG 8 | try { 9 | #endif 10 | auto X = Parser::CreateAST(sql); 11 | X->Run(ctx); 12 | #ifndef DEBUG 13 | } catch (const char* ex) { 14 | std::cout << ex << std::endl; 15 | } 16 | #endif 17 | } 18 | 19 | int main(int argc, char** argv) { 20 | PageDB::Scheduler* pgdb = new PageDB::LRU_Scheduler; 21 | pgdb->StartSchedule(); 22 | Context::Context ctx(pgdb); 23 | if (argc == 2) { 24 | std::ifstream input(argv[1]); 25 | if (!input) { 26 | std::cout << "File Not Found" << std::endl; 27 | return 0; 28 | } 29 | std::vector sql; 30 | char c = '\0'; 31 | while (input) { 32 | int x = input.get(); 33 | if (x == -1) 34 | break; 35 | if (c == '\0' && x == ';') { 36 | RunStmt(std::string(sql.begin(), sql.end()), ctx); 37 | sql.clear(); 38 | } else { 39 | if (c == '\0' && x == '\'') 40 | c = '\''; 41 | else if (c == '\0' && x == '"') 42 | c = '"'; 43 | else if (c == '\'' && x == '\'') 44 | c = '\0'; 45 | else if (c == '"' && x == '"') 46 | c = '\0'; 47 | sql.push_back(x); 48 | } 49 | } 50 | } else { 51 | while (true) { 52 | std::string sql; 53 | std::cout << ctx.dbName << " >> "; 54 | std::getline(std::cin, sql); 55 | if (!std::cin) 56 | break; 57 | if (sql.substr(0, 4) == "exit") 58 | break; 59 | RunStmt(sql, ctx); 60 | } 61 | } 62 | pgdb->StopSchedule(); 63 | delete pgdb; 64 | } 65 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE(testPageDB testPageDB.cpp) 2 | TARGET_LINK_LIBRARIES(testPageDB PageDB) 3 | 4 | ADD_EXECUTABLE(testBTree testBTree.cpp) 5 | TARGET_LINK_LIBRARIES(testBTree BTree PageDB) 6 | 7 | ADD_EXECUTABLE(testContext testContext.cpp) 8 | TARGET_LINK_LIBRARIES(testContext BTree PageDB TypeDB Context Exception) 9 | 10 | ADD_EXECUTABLE(testParser testParser.cpp) 11 | TARGET_LINK_LIBRARIES(testParser Parser TypeDB Stmt BTree TypeDB Context Exception PageDB) 12 | -------------------------------------------------------------------------------- /test/testBTree.cpp: -------------------------------------------------------------------------------- 1 | #include "BTree/BTree.hpp" 2 | #include "PageDB/lru_scheduler.hpp" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void test(PageDB::Scheduler* pgdb) { 10 | int ALL = 10000, DEL = 5000; 11 | std::srand((unsigned int)time(NULL)); 12 | std::remove("testBTree.txt"); 13 | BTree::BTree bt(pgdb, "testBTree.txt"); 14 | for (int t = 0; t < 10; t++) { 15 | std::vector ava, removed; 16 | bt.set("test", BTree::Value(0, 0), true); 17 | bt.remove("test"); 18 | auto X = bt.find("test"); 19 | if (X.first) 20 | std::cout << "ERROR" << std::endl; 21 | for (int i = 0; i < ALL; i++) { 22 | bt.set(std::to_string(i), BTree::Value(i * 2, i), true); 23 | ava.push_back(i); 24 | } 25 | for (int i = 0; i < DEL; i++) { 26 | int pos = rand() % ava.size(); 27 | bt.remove(std::to_string(ava[pos])); 28 | removed.push_back(ava[pos]); 29 | ava[pos] = ava.back(); 30 | ava.pop_back(); 31 | } 32 | sort(ava.begin(), ava.end()); 33 | auto iter = bt.begin(), end = bt.end(); 34 | for (int i : ava) { 35 | auto V = bt.find(std::to_string(i)); 36 | auto X = V.second; 37 | if (!V.first) 38 | std::cout << "ERROR1!" << i << std::endl; 39 | if (X.Page != i * 2) 40 | std::cout << "ERROR2!" << i << std::endl; 41 | if (X.Offset != i) 42 | std::cout << "ERROR3!" << i << std::endl; 43 | if (iter.value() != X) 44 | std::cout << "ERROR4!" << i << iter.value().Offset << std::endl; 45 | iter.Next(); 46 | } 47 | if (iter != end) 48 | std::cout << "ERROR5!" << std::endl; 49 | iter.Next(); 50 | for (int i : removed) { 51 | auto V = bt.find(std::to_string(i)); 52 | if (V.first) 53 | std::cout << "ERROR0!" << i << std::endl; 54 | } 55 | for (int i = 0; i < ALL - DEL; i++) { 56 | int pos = rand() % ava.size(); 57 | bt.remove(std::to_string(ava[pos])); 58 | removed.push_back(ava[pos]); 59 | ava[pos] = ava.back(); 60 | ava.pop_back(); 61 | } 62 | } 63 | } 64 | 65 | int main() { 66 | PageDB::Scheduler* pgdb = new PageDB::LRU_Scheduler; 67 | pgdb->StartSchedule(); 68 | test(pgdb); 69 | pgdb->StopSchedule(); 70 | delete pgdb; 71 | } 72 | -------------------------------------------------------------------------------- /test/testContext.cpp: -------------------------------------------------------------------------------- 1 | #include "context/context.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | void Print(Context::Context& ctx, std::string tbName) { 10 | TypeDB::Table tbl_rst = ctx.GetTable(tbName); 11 | for (auto& row : tbl_rst.rows) { 12 | for (auto& item : row.objs) 13 | std::cout << item->toString() << " "; 14 | std::cout << std::endl; 15 | } 16 | std::cout << std::endl; 17 | } 18 | 19 | void test(PageDB::Scheduler* pgdb) { 20 | std::srand((unsigned int)time(NULL)); 21 | std::remove("test.db"); 22 | std::remove("test:wdy.db"); 23 | std::remove("test:wdy.idx"); 24 | Context::Context ctx(pgdb); 25 | TypeDB::TableDesc desc; 26 | TypeDB::ColDesc col_desc1, col_desc2, col_desc3; 27 | col_desc1.type = new TypeDB::IntType(3); 28 | col_desc2.type = new TypeDB::StringType(3); 29 | col_desc3.type = new TypeDB::StringType(3); 30 | col_desc1.name = "W"; 31 | col_desc2.name = "D"; 32 | col_desc3.name = "Y"; 33 | desc.descs.push_back(col_desc1); 34 | desc.descs.push_back(col_desc2); 35 | desc.descs.push_back(col_desc3); 36 | desc.primaryIndex = 0; 37 | ctx.InitTable("wdy", desc); 38 | TypeDB::Table tbl; 39 | tbl.desc = desc; 40 | TypeDB::Row row1, row2, row3; 41 | row1.objs.push_back(new TypeDB::Int(1)); 42 | row1.objs.push_back(new TypeDB::String("wdy")); 43 | row1.objs.push_back(new TypeDB::String("abc")); 44 | row2.objs.push_back(new TypeDB::Int(2)); 45 | row2.objs.push_back(new TypeDB::String("wy")); 46 | row2.objs.push_back(new TypeDB::String("lo")); 47 | row3.objs.push_back(new TypeDB::Int(3)); 48 | row3.objs.push_back(new TypeDB::String("XYZ")); 49 | row3.objs.push_back(new TypeDB::String("ve")); 50 | tbl.rows.push_back(row1); 51 | tbl.rows.push_back(row2); 52 | tbl.rows.push_back(row3); 53 | ctx.Insert("wdy", tbl); 54 | Print(ctx, "wdy"); 55 | tbl.rows.clear(); 56 | tbl.rows.push_back(row2); 57 | ctx.Delete("wdy", tbl); 58 | Print(ctx, "wdy"); 59 | tbl.rows.clear(); 60 | tbl.rows.push_back(row1); 61 | ctx.Delete("wdy", tbl); 62 | Print(ctx, "wdy"); 63 | row3.objs[2] = new TypeDB::String("wdy"); 64 | tbl.rows[0] = row3; 65 | ctx.Update("wdy", tbl); 66 | Print(ctx, "wdy"); 67 | } 68 | 69 | int main() { 70 | PageDB::Scheduler* pgdb = new PageDB::LRU_Scheduler; 71 | pgdb->StartSchedule(); 72 | test(pgdb); 73 | pgdb->StopSchedule(); 74 | delete pgdb; 75 | } 76 | -------------------------------------------------------------------------------- /test/testPageDB.cpp: -------------------------------------------------------------------------------- 1 | #include "PageDB/lru_scheduler.hpp" 2 | #include "PageDB/iterator.hpp" 3 | #include 4 | 5 | void test(PageDB::Scheduler* pgdb) { 6 | PageDB::Iterator X(pgdb, pgdb->OpenFile("testPageDB.txt")); 7 | PageDB::ConstIterator Y(pgdb, pgdb->OpenFile("testPageDB.txt")); 8 | int newPage = X.file->newPage(); 9 | Y.Goto(newPage - 1, 0); 10 | int ans = Y[0]; 11 | std::cout << newPage << std::endl; 12 | std::cout << ans << std::endl; 13 | X.Goto(newPage, 0); 14 | X[0] = ans + 1; 15 | } 16 | 17 | int main() { 18 | PageDB::LRU_Scheduler* pgdb = new PageDB::LRU_Scheduler; 19 | pgdb->StartSchedule(); 20 | test(pgdb); 21 | pgdb->StopSchedule(); 22 | delete pgdb; 23 | } 24 | -------------------------------------------------------------------------------- /test/testParser.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/Parser.hpp" 2 | #include "context/context.hpp" 3 | 4 | int main() { 5 | PageDB::Scheduler* pgdb = new PageDB::LRU_Scheduler; 6 | pgdb->StartSchedule(); 7 | Context::Context ctx(pgdb); 8 | std::remove(Context::DBFilename.c_str()); 9 | Parser::CreateAST("Create Table wdy (W int(10), D Varchar(10), Y Varchar(10) Not Null, Primary Key (W))")->Run(ctx); 10 | Parser::CreateAST("Create Table wy (W int(10), D Varchar(10), Y Varchar(10) Not Null, Primary Key (W))")->Run(ctx); 11 | Parser::CreateAST("Create Table happy (W int(10), D Varchar(10), Y Varchar(10) Not Null, Primary Key (W))")->Run(ctx); 12 | Parser::CreateAST("insert into wdy values (1, 'wdy', 'abc'), (2, 'wy', 'lo'), (3, 'XYZ', 've')")->Run(ctx); 13 | Parser::CreateAST("insert into wy values (1, 'wdy', 'abc'), (2, 'wy', 'lo'), (3, 'XYZ', 've')")->Run(ctx); 14 | Parser::CreateAST("insert into happy values (1, 'wdy', 'abc'), (2, 'wy', 'lo'), (3, 'XYZ', 've')")->Run(ctx); 15 | Parser::CreateAST("select wdy.W, D from wdy")->Run(ctx); 16 | std::cout << std::endl; 17 | Parser::CreateAST("Select * from wdy")->Run(ctx); 18 | std::cout << std::endl; 19 | Parser::CreateAST("select SUM(wdy.W), avg(W), min(W), max(W), sum(D) from wdy")->Run(ctx); 20 | std::cout << std::endl; 21 | Parser::CreateAST("select * from wdy where wdy.W = 1 or wdy.D = \"wy\"")->Run(ctx); 22 | std::cout << std::endl; 23 | Parser::CreateAST("select * from wdy, wy where wdy.W = wy.W")->Run(ctx); 24 | std::cout << std::endl; 25 | Parser::CreateAST("select * from wdy, wy where wdy.W = wy.W and wdy.W = 1")->Run(ctx); 26 | std::cout << std::endl; 27 | Parser::CreateAST("select * from wdy, wy, happy where wdy.W = wy.W and wdy.W = happy.W")->Run(ctx); 28 | std::cout << std::endl; 29 | Parser::CreateAST("insert into wdy values (0, NULL, \"ABC\")")->Run(ctx); 30 | std::cout << std::endl; 31 | Parser::CreateAST("Select * from wdy")->Run(ctx); 32 | std::cout << std::endl; 33 | Parser::CreateAST("update wdy set D = D + \"...\" where W = 1")->Run(ctx); 34 | Parser::CreateAST("Select * from wdy")->Run(ctx); 35 | std::cout << std::endl; 36 | Parser::CreateAST("delete from wdy where W = 1")->Run(ctx); 37 | Parser::CreateAST("Select * from wdy")->Run(ctx); 38 | std::cout << std::endl; 39 | Parser::CreateAST("Drop Table happy")->Run(ctx); 40 | Parser::CreateAST("Create Table happy (W int(10), D Varchar(10), Y Varchar(10) Not Null, Primary Key (W))")->Run(ctx); 41 | Parser::CreateAST("insert into happy values (0, NULL, \"ABC\")")->Run(ctx); 42 | Parser::CreateAST("Select * from happy")->Run(ctx); 43 | std::cout << std::endl; 44 | Parser::CreateAST("Show Tables")->Run(ctx); 45 | std::cout << std::endl; 46 | Parser::CreateAST("Create Database X")->Run(ctx); 47 | Parser::CreateAST("Use X")->Run(ctx); 48 | Parser::CreateAST("Create Table happy (W int(10), D Varchar(10), Y Varchar(10) Not Null, Primary Key (W))")->Run(ctx); 49 | Parser::CreateAST("insert into happy values (1, NULL, \"ABC\")")->Run(ctx); 50 | Parser::CreateAST("insert into happy values (2, NULL, \"CBD\")")->Run(ctx); 51 | Parser::CreateAST("insert into happy values (3, 'AB', \"ABC\")")->Run(ctx); 52 | Parser::CreateAST("Select * from happy")->Run(ctx); 53 | std::cout << std::endl; 54 | Parser::CreateAST("Show Tables")->Run(ctx); 55 | std::cout << std::endl; 56 | Parser::CreateAST("create table fori (WX int(10), foreign key (WX) references happy(W))")->Run(ctx); 57 | Parser::CreateAST("insert into fori values (1)")->Run(ctx); 58 | Parser::CreateAST("Select * from fori")->Run(ctx); 59 | std::cout << std::endl; 60 | Parser::CreateAST("desc happy")->Run(ctx); 61 | std::cout << std::endl; 62 | Parser::CreateAST("Select * from happy")->Run(ctx); 63 | std::cout << std::endl; 64 | Parser::CreateAST("Select Y, sum(W) from happy group by Y")->Run(ctx); 65 | std::cout << std::endl; 66 | Parser::CreateAST("Select * from happy where Y like '%C'")->Run(ctx); 67 | std::cout << std::endl; 68 | Parser::CreateAST("Select * from happy where D is null")->Run(ctx); 69 | std::cout << std::endl; 70 | try { 71 | Parser::CreateAST("insert into fori values (0)")->Run(ctx); 72 | std::cout << "ERROR" << std::endl; 73 | } catch (const char* str) { 74 | std::cout << str << std::endl; 75 | } 76 | try { 77 | Parser::CreateAST("insert into wdy values (0, \"XYZ\", \"ABC\")")->Run(ctx); 78 | std::cout << "ERROR" << std::endl; 79 | } catch (const char* str) { 80 | std::cout << str << std::endl; 81 | } 82 | try { 83 | Parser::CreateAST("insert into wdy values (0, 1, \"XYZ\", \"ABC\")")->Run(ctx); 84 | std::cout << "ERROR" << std::endl; 85 | } catch (const char* str) { 86 | std::cout << str << std::endl; 87 | } 88 | try { 89 | Parser::CreateAST("insert into wdy values (0, 1, \"ABC\")")->Run(ctx); 90 | std::cout << "ERROR" << std::endl; 91 | } catch (const char* str) { 92 | std::cout << str << std::endl; 93 | } 94 | try { 95 | Parser::CreateAST("insert into wdy values (5, \"ABC\", NULL)")->Run(ctx); 96 | std::cout << "ERROR" << std::endl; 97 | } catch (const char* str) { 98 | std::cout << str << std::endl; 99 | } 100 | try { 101 | Parser::CreateAST("update wdy set D = 1")->Run(ctx); 102 | std::cout << "ERROR" << std::endl; 103 | } catch (const char* str) { 104 | std::cout << str << std::endl; 105 | } 106 | try { 107 | Parser::CreateAST("update wdy set W = 1")->Run(ctx); 108 | std::cout << "ERROR" << std::endl; 109 | } catch (const char* str) { 110 | std::cout << str << std::endl; 111 | } 112 | try { 113 | Parser::CreateAST("select * from happyC")->Run(ctx); 114 | std::cout << "ERROR" << std::endl; 115 | } catch (const char* str) { 116 | std::cout << str << std::endl; 117 | } 118 | try { 119 | Parser::CreateAST("update happyCC set D = 2")->Run(ctx); 120 | std::cout << "ERROR" << std::endl; 121 | } catch (const char* str) { 122 | std::cout << str << std::endl; 123 | } 124 | try { 125 | Parser::CreateAST("Drop Table ha")->Run(ctx); 126 | std::cout << "ERROR" << std::endl; 127 | } catch (const char* str) { 128 | std::cout << str << std::endl; 129 | } 130 | pgdb->StopSchedule(); 131 | delete pgdb; 132 | } 133 | -------------------------------------------------------------------------------- /utils/bufOp.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Utils { 4 | typedef unsigned char byte; 5 | typedef unsigned short word; 6 | 7 | 8 | inline byte readByte(const char*& buf) { 9 | byte ret = *(byte*)buf; 10 | buf += 1; 11 | return ret; 12 | } 13 | inline byte readByte(char*& buf) { 14 | byte ret = *(byte*)buf; 15 | buf += 1; 16 | return ret; 17 | } 18 | inline void jumpByte(const char*& buf) { 19 | buf += 1; 20 | } 21 | inline void jumpByte(char*& buf) { 22 | buf += 1; 23 | } 24 | inline void writeByte(char*& buf, byte v) { 25 | *(byte*)buf = v; 26 | buf += 1; 27 | } 28 | 29 | 30 | inline word readWord(const char*& buf) { 31 | word ret = *(word*)buf; 32 | buf += 2; 33 | return ret; 34 | } 35 | inline word readWord(char*& buf) { 36 | word ret = *(word*)buf; 37 | buf += 2; 38 | return ret; 39 | } 40 | inline void jumpWord(const char*& buf) { 41 | buf += 2; 42 | } 43 | inline void jumpWord(char*& buf) { 44 | buf += 2; 45 | } 46 | inline void writeWord(char*& buf, word v) { 47 | *(word*)buf = v; 48 | buf += 2; 49 | } 50 | 51 | 52 | inline int readInt(const char*& buf) { 53 | int ret = *(int*)buf; 54 | buf += 4; 55 | return ret; 56 | } 57 | inline int readInt(char*& buf) { 58 | int ret = *(int*)buf; 59 | buf += 4; 60 | return ret; 61 | } 62 | inline void jumpInt(const char*& buf) { 63 | buf += 4; 64 | } 65 | inline void jumpInt(char*& buf) { 66 | buf += 4; 67 | } 68 | inline void writeInt(char*& buf, int v) { 69 | *(int*)buf = v; 70 | buf += 4; 71 | } 72 | 73 | 74 | inline std::string readString(const char*& buf) { 75 | word len = readInt(buf); 76 | std::string ret(buf, buf + len); 77 | buf += len; 78 | return ret; 79 | } 80 | inline std::string readString(char*& buf) { 81 | word len = readInt(buf); 82 | std::string ret(buf, buf + len); 83 | buf += len; 84 | return ret; 85 | } 86 | inline void jumpString(const char*& buf) { 87 | word len = readInt(buf); 88 | buf += len; 89 | } 90 | inline void jumpString(char*& buf) { 91 | word len = readInt(buf); 92 | buf += len; 93 | } 94 | inline void writeString(char*& buf, const std::string& v) { 95 | writeInt(buf, v.size()); 96 | memcpy(buf, v.data(), v.size()); 97 | buf += v.size(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /utils/writeFile.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WDY_0192310212_UTILS_WRITEFILE 2 | #define WDY_0192310212_UTILS_WRITEFILE 3 | #include 4 | #include 5 | #include "PageDB/scheduler.hpp" 6 | 7 | namespace Utils { 8 | inline PageDB::Location writeFile(PageDB::Scheduler* pgdb, PageDB::File* file, const char* buf, int size) { 9 | if (file->eof.Offset + size > PageDB::PAGE_SIZE) { 10 | file->eof.Page = file->newPage(); 11 | file->eof.Offset = 0; 12 | } 13 | PageDB::PageWriteSession session = pgdb->GetWriteSession(file, file->eof.Page); 14 | memcpy(session.buf() + file->eof.Offset, buf, size); 15 | PageDB::Location ret = file->eof; 16 | file->eof.Offset += size; 17 | file->writebackFileHeaderCore(); 18 | return ret; 19 | } 20 | } 21 | 22 | #endif 23 | --------------------------------------------------------------------------------