├── .gitignore ├── unittest ├── build_and_run.sh └── TestShadowDB.cpp ├── tutorial ├── makeTutorial.sh ├── tutorial_debug_3.cpp ├── tutorial_orderby_5.cpp ├── tutorial_warning_callback_6.cpp ├── tutorial_fork_merge_2.cpp ├── tutorial_function_4.cpp ├── tutorial_simple_1.cpp └── tutorial_oneof_7.cpp ├── README.md └── ShadowDB.h /.gitignore: -------------------------------------------------------------------------------- 1 | unittest/TestShadowDB 2 | tutorial/simple_1 3 | tutorial/fork_merge_2 4 | tutorial/debug_3 5 | tutorial/function_4 6 | tutorial/orderby_5 7 | tutorial/warning_callback_6 8 | -------------------------------------------------------------------------------- /unittest/build_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | #g++ -g -O2 -std=c++11 TestShadowDB.cpp -I../ -lgtest_main -lgtest -lpthread -o TestShadowDB 2>/tmp/log && ./TestShadowDB || vim /tmp/log 6 | g++ -g -O2 -std=c++11 TestShadowDB.cpp -I../ -lgtest_main -lgtest -lpthread -o TestShadowDB && ./TestShadowDB 7 | -------------------------------------------------------------------------------- /tutorial/makeTutorial.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | # tutorial 6 | g++ -g -O2 -std=c++11 -I../ tutorial_simple_1.cpp -o simple_1 7 | g++ -g -O2 -std=c++11 -I../ tutorial_fork_merge_2.cpp -o fork_merge_2 8 | g++ -g -O2 -std=c++11 -I../ tutorial_debug_3.cpp -o debug_3 9 | g++ -g -O2 -std=c++11 -I../ tutorial_function_4.cpp -o function_4 10 | g++ -g -O2 -std=c++11 -I../ tutorial_orderby_5.cpp -o orderby_5 11 | g++ -g -O2 -std=c++11 -I../ tutorial_warning_callback_6.cpp -o warning_callback_6 12 | g++ -g -O2 -std=c++11 -I../ tutorial_oneof_7.cpp -o oneof_7 13 | -------------------------------------------------------------------------------- /tutorial/tutorial_debug_3.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB ::debug 2 | #include "ShadowDB.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | // 重载operator<即可作为索引字段 20 | friend bool operator<(Id const& lhs, Id const& rhs) 21 | { 22 | if (lhs.v1 != rhs.v1) 23 | return lhs.v1 < rhs.v1; 24 | return lhs.v2 < rhs.v2; 25 | } 26 | }; 27 | 28 | struct ProcessInfo { 29 | Id id; 30 | string processUUID; 31 | string scriptName; 32 | int64_t scriptVersion; 33 | string scriptKey; 34 | string nodeName; 35 | }; 36 | 37 | std::vector gData = { 38 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 39 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 40 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 41 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 42 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 43 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 44 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 45 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 46 | }; 47 | 48 | // 下面这个宏, 可以在debug信息中展示具体的字段名 49 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptVersion); 50 | 51 | int main() 52 | { 53 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 54 | typedef ::shadow::DB db_t; 55 | db_t db; 56 | 57 | // 创建索引 58 | db.createIndex({&ProcessInfo::scriptVersion}); 59 | 60 | // 写入数据 61 | for (ProcessInfo & pi : gData) { 62 | db.set(pi.processUUID, pi); 63 | } 64 | 65 | // 查询追踪器 66 | // 注意:当使用迭代器模式查询时, Debugger的生命期必须长于迭代器 67 | ::shadow::Debugger dbg; 68 | 69 | // 条件查询 70 | std::vector result = db.selectVectorCopy( 71 | Cond(&ProcessInfo::scriptVersion) >= 3, &dbg); 72 | 73 | cout << result[0].processUUID << endl; 74 | cout << result[1].processUUID << endl; 75 | 76 | // 打印查询细节 77 | cout << dbg.toString() << endl; 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /tutorial/tutorial_orderby_5.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB ::支持order by对查询结果进行排序 2 | #include "ShadowDB.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | // 重载operator<即可作为索引字段 20 | friend bool operator<(Id const& lhs, Id const& rhs) 21 | { 22 | if (lhs.v1 != rhs.v1) 23 | return lhs.v1 < rhs.v1; 24 | return lhs.v2 < rhs.v2; 25 | } 26 | }; 27 | 28 | struct ProcessInfo { 29 | Id id; 30 | string processUUID; 31 | string scriptName; 32 | int64_t scriptVersion; 33 | string scriptKey; 34 | string nodeName; 35 | }; 36 | 37 | std::vector gData = { 38 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 39 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 40 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 41 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 42 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 43 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 44 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 45 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 46 | }; 47 | 48 | int main() 49 | { 50 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 51 | typedef ::shadow::DB db_t; 52 | db_t db; 53 | 54 | // 创建联合索引 55 | db.createIndex({&ProcessInfo::scriptKey, &ProcessInfo::nodeName}); 56 | 57 | // 写入数据 58 | for (ProcessInfo & pi : gData) { 59 | db.set(pi.processUUID, pi); 60 | } 61 | 62 | // 条件查询的第二个参数可以传入一个order by语句 63 | // 注意:order by排序字段要尽量匹配索引最左前缀, 64 | // 才能用迭代器逐个取数据, 否则会把所有数据取完排序再返回. 65 | std::vector result = db.selectVector( 66 | Cond(&ProcessInfo::nodeName) >= "192.168.0.3", OrderBy(&ProcessInfo::scriptKey)); 67 | 68 | cout << result.size() << endl; 69 | int i = 0; 70 | for (auto pi : result) 71 | cout << "[" << i++ << "]" << pi->scriptKey << ", " << pi->nodeName << endl; 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /tutorial/tutorial_warning_callback_6.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB ::一些特殊情况的回调 2 | #include "ShadowDB.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | // 重载operator<即可作为索引字段 20 | friend bool operator<(Id const& lhs, Id const& rhs) 21 | { 22 | if (lhs.v1 != rhs.v1) 23 | return lhs.v1 < rhs.v1; 24 | return lhs.v2 < rhs.v2; 25 | } 26 | }; 27 | 28 | struct ProcessInfo { 29 | Id id; 30 | string processUUID; 31 | string scriptName; 32 | int64_t scriptVersion; 33 | string scriptKey; 34 | string nodeName; 35 | }; 36 | 37 | std::vector gData = { 38 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 39 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 40 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 41 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 42 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 43 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 44 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 45 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 46 | }; 47 | 48 | int main() 49 | { 50 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 51 | typedef ::shadow::DB db_t; 52 | db_t db; 53 | 54 | // 创建联合索引 55 | db.createIndex({&ProcessInfo::scriptKey, &ProcessInfo::nodeName}); 56 | 57 | // 写入数据 58 | for (ProcessInfo & pi : gData) { 59 | db.set(pi.processUUID, pi); 60 | } 61 | 62 | // 设置回调:查询未命中索引时被通知 63 | db.setSelectNotMatchIndexNotify([]{ 64 | cout << "warn:查询未命中索引" << endl; 65 | 66 | // 除了打印日志, 还可以在这个回调中抛出异常终止本次查询 67 | throw std::runtime_error("no index"); 68 | }); 69 | 70 | try { 71 | std::vector result = db.selectVector( 72 | Cond(&ProcessInfo::scriptVersion) >= 3); 73 | } catch (std::exception & e) { 74 | cout << "selectVector throw ex:" << e.what() << endl; 75 | } 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /tutorial/tutorial_fork_merge_2.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB ::fork ::merge 2 | #include "ShadowDB.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | // 重载operator<即可作为索引字段 20 | friend bool operator<(Id const& lhs, Id const& rhs) 21 | { 22 | if (lhs.v1 != rhs.v1) 23 | return lhs.v1 < rhs.v1; 24 | return lhs.v2 < rhs.v2; 25 | } 26 | }; 27 | 28 | struct ProcessInfo { 29 | Id id; 30 | string processUUID; 31 | string scriptName; 32 | int64_t scriptVersion; 33 | string scriptKey; 34 | string nodeName; 35 | }; 36 | 37 | std::vector gData = { 38 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 39 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 40 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 41 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 42 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 43 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 44 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 45 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 46 | }; 47 | 48 | int main() 49 | { 50 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 51 | typedef ::shadow::DB db_t; 52 | db_t db; 53 | 54 | // 创建索引 55 | db.createIndex({&ProcessInfo::scriptVersion}); 56 | 57 | // 写入数据 58 | for (ProcessInfo & pi : gData) { 59 | db.set(pi.processUUID, pi); 60 | } 61 | 62 | // fork创建一个数据分支 63 | // db2和db会共享原有db中的数据层, 并设置为只读 64 | // db2和db都会变为2层结构的数据库(索引也会同步变为2层) 65 | // 后续新的数据修改会保存在各自的新层上 66 | db_t db2; 67 | db.fork(db2); 68 | 69 | // 支持多次fork 70 | // 随着fork次数越来越多, 数据层数也会越来越多(无修改的连续fork不会增加额外层数). 71 | // 层数多了以后, CURD的性能都会有小幅度下降 72 | db_t db3; 73 | db2.fork(db3); 74 | cout << "db3 level:" << db3.forkLevel() << endl; 75 | 76 | // 每个fork的数据库都是独立的、互不影响的 77 | // 对db3的数据修改, 不会影响db和db2 78 | db3.del("11becf19-97fe-4683-9b8e-fc52c933c7bc"); 79 | 80 | // 使用merge, 可以把数据库变回单层数据结构, 但这可能带来很多拷贝, 请谨慎使用! 81 | db3.merge(); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /tutorial/tutorial_function_4.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB ::自定义虚拟列做索引\查询条件 2 | #include "ShadowDB.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | // 重载operator<即可作为索引字段 20 | friend bool operator<(Id const& lhs, Id const& rhs) 21 | { 22 | if (lhs.v1 != rhs.v1) 23 | return lhs.v1 < rhs.v1; 24 | return lhs.v2 < rhs.v2; 25 | } 26 | }; 27 | 28 | struct ProcessInfo { 29 | Id id; 30 | string processUUID; 31 | string scriptName; 32 | int64_t scriptVersion; 33 | string scriptKey; 34 | string nodeName; 35 | }; 36 | 37 | std::vector gData = { 38 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 39 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 40 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 41 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 42 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 43 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 44 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 45 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 46 | }; 47 | 48 | int main() 49 | { 50 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 51 | typedef ::shadow::DB db_t; 52 | db_t db; 53 | 54 | // 创建一个虚拟列 (nodeName的最后一个字符) 55 | ::shadow::VirtualColumn nodeLastChar = db.makeVirtualColumn( 56 | [](ProcessInfo const& pi) { 57 | return pi.nodeName.empty() ? '0' : pi.nodeName.back(); 58 | }); 59 | 60 | // 用虚拟列创建索引 61 | db.createIndex({nodeLastChar}); 62 | 63 | // 写入数据 64 | for (ProcessInfo & pi : gData) { 65 | db.set(pi.processUUID, pi); 66 | } 67 | 68 | // 用虚拟列做条件查询 69 | // 注意:查询用的虚拟列对象, 必须和创建索引用同一个对象, 查询时才能命中索引 70 | std::vector result = db.selectVectorCopy( 71 | Cond(nodeLastChar) >= '4'); 72 | 73 | cout << result[0].processUUID << endl; 74 | cout << result[1].processUUID << endl; 75 | 76 | // 再创建一个虚拟列, 不做索引, 仅用于查询 77 | ::shadow::VirtualColumn scriptVersionMod3 = db.makeVirtualColumn( 78 | [](ProcessInfo const& pi) { 79 | return pi.scriptVersion % 3; 80 | }); 81 | 82 | // 不命中索引的虚拟列查询 83 | std::vector r2 = db.selectVectorCopy( 84 | Cond(scriptVersionMod3) == 2); 85 | cout << r2[0].processUUID << endl; 86 | cout << r2[1].processUUID << endl; 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /tutorial/tutorial_simple_1.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB简单示例 2 | // ShadowDB是一个可以创建索引、能够快速fork出一份数据分支的C++内存数据库 3 | #include "ShadowDB.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | struct Id 13 | { 14 | int v1; 15 | int v2; 16 | 17 | Id() = default; 18 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 19 | 20 | // 重载operator<即可作为索引字段 21 | friend bool operator<(Id const& lhs, Id const& rhs) 22 | { 23 | if (lhs.v1 != rhs.v1) 24 | return lhs.v1 < rhs.v1; 25 | return lhs.v2 < rhs.v2; 26 | } 27 | }; 28 | 29 | struct ProcessInfo { 30 | Id id; 31 | string processUUID; 32 | string scriptName; 33 | int64_t scriptVersion; 34 | string scriptKey; 35 | string nodeName; 36 | }; 37 | 38 | std::vector gData = { 39 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 40 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 41 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 42 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 43 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 44 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 45 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 46 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 47 | }; 48 | 49 | int main() 50 | { 51 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 52 | typedef ::shadow::DB db_t; 53 | db_t db; 54 | 55 | // 创建普通索引 56 | db.createIndex({&ProcessInfo::scriptVersion}); 57 | // 创建自定义类索引 58 | db.createIndex({&ProcessInfo::id}); 59 | // 创建联合索引 60 | db.createIndex({&ProcessInfo::scriptKey, &ProcessInfo::nodeName}); 61 | 62 | // 写入数据 63 | for (ProcessInfo & pi : gData) { 64 | db.set(pi.processUUID, pi); 65 | } 66 | 67 | // 删除数据 68 | bool deleteSuccess = db.del("11becf19-97fe-4683-9b8e-fc52c933c7bc"); 69 | 70 | // 主键查询 71 | ProcessInfo pi; 72 | bool success = db.get("11becf19-97fe-4683-9b8e-fc52c933c7bc", pi); 73 | cout << "mainkey get success=" << success << endl; 74 | 75 | // 条件查询 76 | // 注意:返回的数据指针, 在数据库中的数据被修改后, 极有可能失效. 77 | // 需要长期使用时, 可以copy一份保存下来, 或使用selectVectorCopy接口查询 78 | std::vector result = db.selectVector( 79 | Cond(&ProcessInfo::scriptVersion) >= 3); 80 | 81 | cout << result[0]->processUUID << endl; 82 | cout << result[1]->processUUID << endl; 83 | 84 | // 复合条件查询 (支持操作符: < <= == >= > ! !=) 85 | std::map result2 = db.selectMap( 86 | Cond(&ProcessInfo::scriptVersion) >= 3 87 | && Cond(&ProcessInfo::scriptVersion) < 9 88 | || Cond(&ProcessInfo::id) == Id{0, 2} 89 | ); 90 | 91 | // 查询迭代器, 支持只取部分结果 92 | // 注意: 任何对数据库的修改, 都会导致迭代器失效 93 | db_t::condition_iterator it = db.select(Cond(&ProcessInfo::scriptVersion) > 1); 94 | for (; it; ++it) { 95 | string const* processUUID = it->first; 96 | ProcessInfo const* pi = it->second; 97 | cout << "select iterator -> processUUID=" << *processUUID << endl; 98 | } 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /tutorial/tutorial_oneof_7.cpp: -------------------------------------------------------------------------------- 1 | // ShadowDB简单示例 2 | // ShadowDB是一个可以创建索引、能够快速fork出一份数据分支的C++内存数据库 3 | #include "ShadowDB.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | struct Id 13 | { 14 | int v1; 15 | int v2; 16 | 17 | Id() = default; 18 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 19 | 20 | // 重载operator<即可作为索引字段 21 | friend bool operator<(Id const& lhs, Id const& rhs) 22 | { 23 | if (lhs.v1 != rhs.v1) 24 | return lhs.v1 < rhs.v1; 25 | return lhs.v2 < rhs.v2; 26 | } 27 | }; 28 | 29 | struct ProcessInfo { 30 | Id id; 31 | string processUUID; 32 | string scriptName; 33 | int64_t scriptVersion; 34 | string scriptKey; 35 | string nodeName; 36 | vector keys; 37 | }; 38 | 39 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, id); 40 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, processUUID); 41 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptName); 42 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptVersion); 43 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptKey); 44 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, nodeName); 45 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, keys); 46 | 47 | std::vector gData = { 48 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1", {0, 1}}, 49 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2", {1, 3, 5}}, 50 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3", {2, 4, 6}}, 51 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4", {2, 3}}, 52 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2", {8, 3}}, 53 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3", {8, 4}}, 54 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4", {1, 4}}, 55 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1", {2, 5}}, 56 | }; 57 | 58 | int main() 59 | { 60 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 61 | typedef ::shadow::DB db_t; 62 | db_t db; 63 | 64 | // 创建普通索引 65 | db.createIndex({&ProcessInfo::scriptVersion}); 66 | 67 | // 创建OneOf普通索引 68 | db.createIndex({OneOf(&ProcessInfo::scriptName)}); 69 | db.createIndex({OneOf(&ProcessInfo::keys)}); 70 | 71 | // 创建一个OneOf虚拟列 72 | ::shadow::VirtualColumn virtualOneOf = db.makeVirtualColumn( 73 | [](ProcessInfo const& pi) { 74 | vector vec; 75 | for (char ch : pi.nodeName) 76 | vec.push_back(ch); 77 | return vec; 78 | }, "OneOf(nodeName)"); 79 | db.createIndex({virtualOneOf}); 80 | 81 | // 写入数据 82 | for (ProcessInfo & pi : gData) { 83 | db.set(pi.processUUID, pi); 84 | } 85 | 86 | cout << db.toString() << endl; 87 | 88 | { 89 | // OneOf条件查询 90 | ::shadow::Debugger dbg; 91 | db_t::condition_iterator it = db.select(OneOf(&ProcessInfo::keys) == 4, &dbg); 92 | for (; it; ++it) { 93 | string const* processUUID = it->first; 94 | ProcessInfo const* pi = it->second; 95 | cout << "select iterator -> processUUID=" << *processUUID << endl; 96 | } 97 | 98 | cout << dbg.toString() << endl; 99 | } 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShadowDB 2 | 一个C++嵌入式内存数据库 3 | 4 | * 语法极简风 5 | * 支持自定义索引、复合条件查询('<','<=','==','>=','>','!=',&&,||) 6 | * 能够快速fork出一份数据副本 7 | 8 | ```cpp 9 | // ShadowDB简单示例 10 | // ShadowDB是一个可以创建索引、能够快速fork出一份数据分支的C++内存数据库 11 | #include "ShadowDB.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | struct Id 21 | { 22 | int v1; 23 | int v2; 24 | 25 | Id() = default; 26 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 27 | 28 | // 重载operator<即可作为索引字段 29 | friend bool operator<(Id const& lhs, Id const& rhs) 30 | { 31 | if (lhs.v1 != rhs.v1) 32 | return lhs.v1 < rhs.v1; 33 | return lhs.v2 < rhs.v2; 34 | } 35 | }; 36 | 37 | struct ProcessInfo { 38 | Id id; 39 | string processUUID; 40 | string scriptName; 41 | int64_t scriptVersion; 42 | string scriptKey; 43 | string nodeName; 44 | }; 45 | 46 | std::vector gData = { 47 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 48 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 49 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 50 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 51 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 52 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 53 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 54 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 55 | }; 56 | 57 | int main() 58 | { 59 | // 创建ShadowDB类, 第一个模板参数是主键类型, 第二个模板参数是存储的数据结构体 60 | typedef ::shadow::DB db_t; 61 | db_t db; 62 | 63 | // 创建普通索引 64 | db.createIndex({&ProcessInfo::scriptVersion}); 65 | // 创建自定义类索引 66 | db.createIndex({&ProcessInfo::id}); 67 | // 创建联合索引 68 | db.createIndex({&ProcessInfo::scriptKey, &ProcessInfo::nodeName}); 69 | 70 | // 写入数据 71 | for (ProcessInfo & pi : gData) { 72 | db.set(pi.processUUID, pi); 73 | } 74 | 75 | // 删除数据 76 | bool deleteSuccess = db.del("11becf19-97fe-4683-9b8e-fc52c933c7bc"); 77 | 78 | // 主键查询 79 | ProcessInfo pi; 80 | bool success = db.get("11becf19-97fe-4683-9b8e-fc52c933c7bc", pi); 81 | cout << "mainkey get success=" << success << endl; 82 | 83 | // 条件查询 84 | // 注意:返回的数据指针, 在数据库中的数据被修改后, 极有可能失效. 85 | // 需要长期使用时, 可以copy一份保存下来, 或使用selectVectorCopy接口查询 86 | std::vector result = db.selectVector( 87 | Cond(&ProcessInfo::scriptVersion) >= 3); 88 | 89 | cout << result[0]->processUUID << endl; 90 | cout << result[1]->processUUID << endl; 91 | 92 | // 复合条件查询 93 | std::map result2 = db.selectMap( 94 | Cond(&ProcessInfo::scriptVersion) >= 3 95 | && Cond(&ProcessInfo::scriptVersion) < 9 96 | || Cond(&ProcessInfo::id) == Id{0, 2} 97 | ); 98 | 99 | // 查询迭代器, 支持只取部分结果 100 | // 注意: 任何对数据库的修改, 都会导致迭代器失效 101 | db_t::condition_iterator it = db.select(Cond(&ProcessInfo::scriptVersion) > 1); 102 | for (; it; ++it) { 103 | string const* processUUID = it->first; 104 | ProcessInfo const* pi = it->second; 105 | cout << "select iterator -> processUUID=" << *processUUID << endl; 106 | } 107 | 108 | return 0; 109 | } 110 | ``` 111 | -------------------------------------------------------------------------------- /unittest/TestShadowDB.cpp: -------------------------------------------------------------------------------- 1 | #include "ShadowDB.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "gtest/gtest.h" 8 | 9 | using namespace std; 10 | 11 | struct Id 12 | { 13 | int v1; 14 | int v2; 15 | 16 | Id() = default; 17 | Id(int _v1, int _v2) : v1(_v1), v2(_v2) {} 18 | 19 | friend bool operator<(Id const& lhs, Id const& rhs) 20 | { 21 | if (lhs.v1 != rhs.v1) 22 | return lhs.v1 < rhs.v1; 23 | return lhs.v2 < rhs.v2; 24 | } 25 | 26 | friend bool operator>=(Id const& lhs, Id const& rhs) 27 | { 28 | return !(rhs < lhs); 29 | } 30 | 31 | string toString() const 32 | { 33 | return shadow::fmt("{%d,%d}", v1, v2); 34 | } 35 | }; 36 | 37 | struct IdGroup 38 | { 39 | std::set ids; 40 | 41 | IdGroup() = default; 42 | IdGroup(std::initializer_list il) : ids(il) {} 43 | 44 | void insert(Id id) { 45 | ids.insert(id); 46 | } 47 | 48 | friend bool operator==(IdGroup const& lhs, IdGroup const& rhs) 49 | { 50 | if (lhs.ids.size() != rhs.ids.size()) return false; 51 | for (Id const& id : lhs.ids) { 52 | if (!rhs.ids.count(id)) 53 | return false; 54 | } 55 | return true; 56 | } 57 | }; 58 | 59 | struct ProcessInfo { 60 | Id id; 61 | string processUUID; 62 | string scriptName; 63 | int64_t scriptVersion; 64 | string scriptKey; 65 | string nodeName; 66 | 67 | bool check(ProcessInfo const& other) const { 68 | return id.v1 == other.id.v1 && id.v2 == other.id.v2 && 69 | processUUID == other.processUUID && 70 | scriptName == other.scriptName && 71 | scriptVersion == other.scriptVersion && 72 | scriptKey == other.scriptKey && 73 | nodeName == other.nodeName; 74 | } 75 | 76 | string toString() const 77 | { 78 | return ::shadow::fmt("id=%s,script=\"%s\",version=%ld,key=\"%s\",node=\"%s\"", 79 | id.toString().c_str(), scriptName.c_str(), scriptVersion, 80 | scriptKey.c_str(), nodeName.c_str()); 81 | } 82 | 83 | string toStringAll() const 84 | { 85 | return ::shadow::fmt("id=%s,uuid=\"%s\",script=\"%s\",version=%ld,key=\"%s\",node=\"%s\"", 86 | id.toString().c_str(), processUUID.c_str(), scriptName.c_str(), 87 | scriptVersion, scriptKey.c_str(), nodeName.c_str()); 88 | } 89 | }; 90 | 91 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, id); 92 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, processUUID); 93 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptName); 94 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptVersion); 95 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, scriptKey); 96 | SHADOW_DB_DEBUG_FIELD(ProcessInfo, nodeName); 97 | 98 | struct ProcessInfoDrived : public ProcessInfo 99 | { 100 | int drived; 101 | }; 102 | 103 | void dump(std::vector const& r); 104 | size_t find(std::vector const& data, ProcessInfo const* ppi); 105 | void dumpFind(std::vector const& data, std::vector const& r); 106 | 107 | std::vector data1 = { 108 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.cc", 1, "mips-b-1", "192.168.0.1"}, 109 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.cc", 3, "mips-b-1", "192.168.0.2"}, 110 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.cc", 1, "mips-a-1", "192.168.0.3"}, 111 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.cc", 8, "mips-a-2", "192.168.0.4"}, 112 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.cc", 1, "mips-c-1", "192.168.0.2"}, 113 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.cc", 2, "mips-a-1", "192.168.0.3"}, 114 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.cc", 1, "mips-a-1", "192.168.0.4"}, 115 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.cc", 1, "mips-a-1", "192.168.0.1"}, 116 | }; 117 | 118 | // overlapped data1 119 | std::vector data2 = { 120 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.js", 0, "mips", "10.0.3.3"}, 121 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.js", 0, "mips", "10.0.3.4"}, 122 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.js", 0, "mips", "10.0.3.5"}, 123 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.js", 0, "mips", "10.0.3.6"}, 124 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.js", 0, "mips", "10.0.3.7"}, 125 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.js", 0, "mips", "10.0.3.8"}, 126 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.js", 0, "mips", "10.0.3.9"}, 127 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.js", 0, "mips", "10.0.3.0"}, 128 | }; 129 | 130 | // overlapped data1 131 | std::vector data3 = { 132 | {{0, 0}, "11becf19-97fe-4683-9b8e-fc52c933c7bc", "b.js", 1, "mips", "10.0.3.3"}, 133 | {{0, 1}, "521e60b5-f636-4c8e-af51-860ef7771adc", "b.js", 2, "mips", "10.0.3.4"}, 134 | {{0, 2}, "88b91109-2514-47c2-a0d1-1c73bc6b37dc", "a.js", 4, "mips", "10.0.3.5"}, 135 | {{1, 0}, "e4e730ae-e7e2-4f70-a1ba-1d3733459932", "a.js", 6, "mips", "10.0.3.6"}, 136 | {{1, 1}, "9df40b2d-d1db-4c83-819b-259686a21f31", "c.js", 3, "mips", "10.0.3.7"}, 137 | {{1, 2}, "3038fc64-19fc-4212-9a46-cdb248104e9c", "d.js", 3, "mips", "10.0.3.8"}, 138 | {{2, 0}, "59d11ac7-425a-42e9-b83d-c61e21a79d88", "d.js", 4, "mips", "10.0.3.9"}, 139 | {{2, 1}, "9e146f96-dff1-427e-9aca-fee5f81fbbb3", "d.js", 1, "mips", "10.0.3.0"}, 140 | }; 141 | 142 | // alone data 143 | std::vector g1 = { 144 | {{10, 0}, "df25c488-06b0-4cda-b457-5f2f611db76a", "b.py", 11, "g1-mips", "10.1.3.3"}, 145 | {{10, 1}, "9b0445e0-b906-4114-ae17-a04e0c972041", "b.py", 12, "g1-mips", "10.1.3.4"}, 146 | {{10, 2}, "6c67d8f0-fda3-41dc-b331-da9662e40e3d", "a.py", 14, "g1-mips", "10.1.3.5"}, 147 | {{11, 0}, "b4e388a4-49b7-4cbe-896c-d18219c734dc", "a.py", 16, "g1-mips", "10.1.3.6"}, 148 | {{11, 1}, "35e14652-674d-44b4-92ef-cfd7a9b4ad81", "c.py", 13, "g1-mips", "10.1.3.7"}, 149 | {{11, 2}, "d94a1ddc-e2ff-4c51-b5e6-283101544c7a", "d.py", 13, "g1-mips", "10.1.3.8"}, 150 | {{12, 0}, "835f8f94-198d-46ee-8a01-89fdabd69385", "d.py", 14, "g1-mips", "10.1.3.9"}, 151 | {{12, 1}, "8db669c3-2c71-4dd6-8e08-284c87497d84", "d.py", 11, "g1-mips", "10.1.3.0"}, 152 | }; 153 | 154 | // alone data 155 | std::vector g2 = { 156 | {{20, 0}, "3629e775-6bf8-4f36-902f-aa5cbcab0651", "b.java", 21, "g1-mips", "10.2.3.3"}, 157 | {{20, 1}, "1ce9bd3e-5096-4357-9285-7191916e991f", "b.java", 22, "g1-mips", "10.2.3.4"}, 158 | {{20, 2}, "f0b2d958-99b7-4a91-83e4-cd33807c34c0", "a.java", 24, "g1-mips", "10.2.3.5"}, 159 | {{21, 0}, "4475ac30-658e-41e5-af94-98494a17cb76", "a.java", 26, "g1-mips", "10.2.3.6"}, 160 | {{21, 1}, "59eb87e1-fc6b-4a32-b593-9b2c46dcf63b", "c.java", 23, "g1-mips", "10.2.3.7"}, 161 | {{21, 2}, "8eeb7ac3-49d5-41f2-86ec-abfcc0d403de", "d.java", 23, "g1-mips", "10.2.3.8"}, 162 | {{22, 0}, "336ee556-4c79-4124-86a3-92eac22e608d", "d.java", 24, "g1-mips", "10.2.3.9"}, 163 | {{22, 1}, "92c31973-49d3-4ee5-9e83-039adde8975b", "d.java", 21, "g1-mips", "10.2.3.0"}, 164 | }; 165 | 166 | int64_t us() 167 | { 168 | return std::chrono::duration_cast( 169 | std::chrono::system_clock::now().time_since_epoch()).count(); 170 | } 171 | 172 | int64_t ns() 173 | { 174 | return std::chrono::duration_cast( 175 | std::chrono::system_clock::now().time_since_epoch()).count(); 176 | } 177 | 178 | using db_t = shadow::DB; 179 | using id_db_t = shadow::DB; 180 | 181 | // 简单用例 182 | TEST(shadowdb, simple) 183 | { 184 | db_t db; 185 | 186 | // 创建索引, 重复创建返回false 187 | EXPECT_TRUE(db.createIndex({&ProcessInfo::scriptVersion})); 188 | EXPECT_FALSE(db.createIndex({&ProcessInfo::scriptVersion})); 189 | EXPECT_TRUE(db.createIndex({&ProcessInfo::nodeName})); 190 | EXPECT_FALSE(db.createIndex({&ProcessInfo::nodeName})); 191 | 192 | // 创建复合索引, 重复创建返回false 193 | EXPECT_TRUE(db.createIndex({&ProcessInfo::id, &ProcessInfo::scriptVersion})); 194 | EXPECT_FALSE(db.createIndex({&ProcessInfo::id, &ProcessInfo::scriptVersion})); 195 | 196 | // 导入数据 (move) 197 | for (ProcessInfo const& pi : data1) { 198 | ProcessInfo pic = pi; 199 | EXPECT_TRUE(db.set(pi.processUUID, std::move(pic))); 200 | } 201 | // 有数据的情况下创建索引 202 | EXPECT_TRUE(db.createIndex({&ProcessInfo::id})); 203 | 204 | // cout << db.toString() << endl; 205 | 206 | // 重复导入, 更新 207 | for (ProcessInfo const& pi : data2) { 208 | EXPECT_FALSE(db.set(pi.processUUID, pi)); 209 | } 210 | 211 | // cout << db.toString() << endl; 212 | 213 | // 只更新部分字段 214 | for (ProcessInfo pi : data3) { 215 | pi.nodeName = "fatal"; 216 | EXPECT_TRUE(db.update(pi.processUUID, {&ProcessInfo::scriptVersion}, pi)); 217 | } 218 | 219 | // cout << db.toString() << endl; 220 | 221 | // 主键查询 222 | size_t idx = 5; 223 | ProcessInfo const& pi = data3[idx]; 224 | db_t::VRefPtr ref = db.get(pi.processUUID); 225 | EXPECT_TRUE(ref); 226 | EXPECT_TRUE(pi.check(*ref)); 227 | 228 | ProcessInfo out; 229 | EXPECT_TRUE(db.get(pi.processUUID, out)); 230 | EXPECT_TRUE(pi.check(out)); 231 | 232 | EXPECT_FALSE(db.get("ced7cb19-cf04-4b0e-8314-3399d7bb2b96")); 233 | EXPECT_FALSE(db.get("ced7cb19-cf04-4b0e-8314-3399d7bb2b96", out)); 234 | EXPECT_FALSE(db.get("4e375371-53d4-4dbf-bd11-2fa608e73a83", out)); 235 | 236 | // 索引查询 237 | shadow::Debugger dbg1; 238 | std::vector r1 = db.selectVector(Cond(&ProcessInfo::id) == pi.id, &dbg1); 239 | EXPECT_EQ(r1.size(), 1); 240 | if (!r1.empty()) { 241 | EXPECT_TRUE(pi.check(*r1[0])); 242 | } 243 | // cout << "Debugger1:\n" << dbg1.toString() << endl; 244 | 245 | shadow::Debugger dbg2; 246 | 247 | std::vector r2 = db.selectVector(Cond(&ProcessInfo::scriptVersion) >= 3 && Cond(&ProcessInfo::scriptVersion) < 5, &dbg2); 248 | EXPECT_EQ(r2.size(), 4); 249 | IdGroup expectIds { 250 | {0, 2}, 251 | {1, 1}, 252 | {1, 2}, 253 | {2, 0} 254 | }; 255 | IdGroup r2ids; 256 | for (ProcessInfo const* ppi : r2) { 257 | r2ids.insert(ppi->id); 258 | } 259 | EXPECT_TRUE(r2ids == expectIds); 260 | cout << "db:\n" << db.toString() << endl; 261 | cout << "Debugger2:\n" << dbg2.toString() << endl; 262 | 263 | // 空条件查询 (基本等同于foreach) 264 | { 265 | shadow::Debugger dbg; 266 | std::vector r = db.selectVector({}, &dbg); 267 | EXPECT_EQ(r.size(), 8); 268 | // cout << "select({}) dbg:\n" << dbg.toString() << endl; 269 | // dump(r); 270 | } 271 | 272 | // // range 273 | // { 274 | // db_t::condition_range range = db.selectRange(Cond(&ProcessInfo::scriptVersion) >= 3 && Cond(&ProcessInfo::scriptVersion) < 5); 275 | // IdGroup expectIds { 276 | // {0, 2}, 277 | // {1, 1}, 278 | // {1, 2}, 279 | // {2, 0} 280 | // }; 281 | // IdGroup r2ids; 282 | // for (auto kv : range) { 283 | // ProcessInfo const* ppi = kv.second; 284 | // r2ids.insert(ppi->id); 285 | // } 286 | // EXPECT_TRUE(r2ids == expectIds); 287 | // } 288 | } 289 | 290 | // 继承 291 | TEST(shadowdb, drived) 292 | { 293 | using db_drived_t = shadow::DB; 294 | db_drived_t db; 295 | EXPECT_TRUE(db.createIndex({&ProcessInfoDrived::scriptVersion})); 296 | 297 | ::shadow::column_t colx(&ProcessInfoDrived::drived); 298 | 299 | ::shadow::column_t col(&ProcessInfoDrived::scriptVersion); 300 | ::shadow::column_t dcol(col); 301 | 302 | Cond(&ProcessInfoDrived::scriptVersion) > 1; 303 | db.select(Cond(&ProcessInfoDrived::scriptVersion) > 1); 304 | db.select(Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::scriptVersion) < 3); 305 | db.select(Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::scriptVersion) < 3 306 | || Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::scriptVersion) < 3); 307 | 308 | // db.select(Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::drived) < 3); 309 | db.select(Cond(&ProcessInfoDrived::drived) > 1 && Cond(&ProcessInfoDrived::scriptVersion) < 3); 310 | 311 | // db.select(Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::drived) < 3 312 | // || Cond(&ProcessInfoDrived::scriptVersion) > 1 && Cond(&ProcessInfoDrived::scriptVersion) < 3); 313 | } 314 | 315 | // VRefPtr: selectVectorRef/selectMapRef/VRefPtr(shared_ptr) 316 | TEST(shadowdb, ref) 317 | { 318 | db_t db; 319 | 320 | // 创建索引, 重复创建返回false 321 | EXPECT_TRUE(db.createIndex({&ProcessInfo::scriptVersion})); 322 | EXPECT_FALSE(db.createIndex({&ProcessInfo::scriptVersion})); 323 | EXPECT_TRUE(db.createIndex({&ProcessInfo::nodeName})); 324 | EXPECT_FALSE(db.createIndex({&ProcessInfo::nodeName})); 325 | 326 | // 创建复合索引, 重复创建返回false 327 | EXPECT_TRUE(db.createIndex({&ProcessInfo::id, &ProcessInfo::scriptVersion})); 328 | EXPECT_FALSE(db.createIndex({&ProcessInfo::id, &ProcessInfo::scriptVersion})); 329 | 330 | // 导入数据 331 | for (ProcessInfo const& pi : data1) { 332 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 333 | } 334 | // 有数据的情况下创建索引 335 | EXPECT_TRUE(db.createIndex({&ProcessInfo::id})); 336 | 337 | cout << db.toString() << endl; 338 | 339 | // 索引查询 340 | shadow::Debugger dbg1; 341 | std::vector r1 = db.selectVectorRef( 342 | Cond(&ProcessInfo::scriptVersion) > 1 && Cond(&ProcessInfo::scriptVersion) < 4, 343 | &dbg1); 344 | EXPECT_EQ(r1.size(), 2); 345 | EXPECT_TRUE(data1[5].check(*r1[0])); 346 | EXPECT_TRUE(data1[1].check(*r1[1])); 347 | cout << "*r1[0]: " << r1[0]->toStringAll() << endl; 348 | cout << "*r1[1]: " << r1[1]->toStringAll() << endl; 349 | // cout << "Debugger1:\n" << dbg1.toString() << endl; 350 | 351 | // 只更新部分字段 352 | for (ProcessInfo pi : data3) { 353 | EXPECT_TRUE(db.update(pi.processUUID, pi)); 354 | } 355 | 356 | cout << db.toString() << endl; 357 | EXPECT_TRUE(data3[5].check(*r1[0])); 358 | EXPECT_TRUE(data3[1].check(*r1[1])); 359 | cout << "*r1[0]: " << r1[0]->toStringAll() << endl; 360 | cout << "*r1[1]: " << r1[1]->toStringAll() << endl; 361 | 362 | std::shared_ptr myPi(new ProcessInfo{data1[0]}); 363 | db_t::VRefPtr selfHolder(myPi); 364 | EXPECT_EQ(selfHolder.get(), myPi.get()); 365 | EXPECT_TRUE(selfHolder->check(*myPi)); 366 | } 367 | 368 | // 测试无索引场景 369 | TEST(shadowdb, no_index) 370 | { 371 | db_t db; 372 | 373 | // 导入数据 374 | for (ProcessInfo const& pi : data1) { 375 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 376 | } 377 | 378 | ::shadow::Debugger dbg; 379 | std::vector r = db.selectVector(Cond(&ProcessInfo::scriptVersion) > 1 && Cond(&ProcessInfo::scriptVersion) < 4, &dbg); 380 | EXPECT_EQ(r.size(), 2); 381 | std::set uuidSet; 382 | for (auto ppi : r) { 383 | uuidSet.insert(ppi->processUUID); 384 | } 385 | EXPECT_TRUE(uuidSet.count(data1[1].processUUID)); 386 | EXPECT_TRUE(uuidSet.count(data1[5].processUUID)); 387 | 388 | EXPECT_EQ(dbg.queryTrace.querys.size(), 1); 389 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 390 | EXPECT_EQ(dbg.queryTrace.getResultRows(), r.size()); 391 | 392 | cout << dbg.toString() << endl; 393 | } 394 | 395 | // 或条件查询 / 复杂的复合条件查询 396 | TEST(shadowdb, or_condition) 397 | { 398 | db_t db; 399 | 400 | // 导入数据 401 | for (ProcessInfo const& pi : data1) { 402 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 403 | } 404 | 405 | // && and || 406 | { 407 | ::shadow::Debugger dbg; 408 | std::vector r = db.selectVector( 409 | Cond(&ProcessInfo::scriptVersion) > 1 410 | && Cond(&ProcessInfo::scriptVersion) < 4 411 | || Cond(&ProcessInfo::nodeName) >= "192.168.0.3" 412 | , 413 | &dbg); 414 | EXPECT_EQ(r.size(), 5); 415 | 416 | std::set uuidSet; 417 | for (auto ppi : r) { 418 | uuidSet.insert(ppi->processUUID); 419 | } 420 | EXPECT_TRUE(uuidSet.count(data1[1].processUUID)); 421 | EXPECT_TRUE(uuidSet.count(data1[2].processUUID)); 422 | EXPECT_TRUE(uuidSet.count(data1[3].processUUID)); 423 | EXPECT_TRUE(uuidSet.count(data1[5].processUUID)); 424 | EXPECT_TRUE(uuidSet.count(data1[6].processUUID)); 425 | EXPECT_EQ(dbg.queryTrace.querys.size(), 2); 426 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 427 | EXPECT_EQ(dbg.queryTrace.getResultRows(), 5); 428 | 429 | cout << "Result:" << endl; 430 | int i = 0; 431 | for (auto ppi : r) { 432 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 433 | } 434 | 435 | cout << dbg.toString() << endl; 436 | } 437 | 438 | // ( && and || ) && cond 439 | { 440 | ::shadow::Debugger dbg; 441 | std::vector r = db.selectVector( 442 | (Cond(&ProcessInfo::scriptVersion) > 1 443 | && Cond(&ProcessInfo::scriptVersion) < 4 444 | || Cond(&ProcessInfo::nodeName) >= "192.168.0.3") 445 | && Cond(&ProcessInfo::nodeName) < "192.168.0.4" 446 | , 447 | &dbg); 448 | EXPECT_EQ(r.size(), 3); 449 | std::set uuidSet; 450 | for (auto ppi : r) { 451 | uuidSet.insert(ppi->processUUID); 452 | } 453 | EXPECT_TRUE(uuidSet.count(data1[1].processUUID)); 454 | EXPECT_TRUE(uuidSet.count(data1[2].processUUID)); 455 | EXPECT_TRUE(uuidSet.count(data1[5].processUUID)); 456 | EXPECT_EQ(dbg.queryTrace.querys.size(), 2); 457 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 458 | EXPECT_EQ(dbg.queryTrace.getResultRows(), 3); 459 | 460 | cout << "Result:" << endl; 461 | int i = 0; 462 | for (auto ppi : r) { 463 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 464 | } 465 | 466 | cout << dbg.toString() << endl; 467 | } 468 | 469 | // ( && and || ) && ( && ) 470 | { 471 | ::shadow::Debugger dbg; 472 | std::vector r = db.selectVector( 473 | ( 474 | Cond(&ProcessInfo::scriptVersion) > 1 475 | && Cond(&ProcessInfo::scriptVersion) < 4 476 | || Cond(&ProcessInfo::nodeName) >= "192.168.0.3" 477 | ) && ( 478 | Cond(&ProcessInfo::nodeName) < "192.168.0.4" 479 | && Cond(&ProcessInfo::nodeName) < "192.168.0.4" 480 | ) 481 | , 482 | &dbg); 483 | EXPECT_EQ(r.size(), 3); 484 | std::set uuidSet; 485 | for (auto ppi : r) { 486 | uuidSet.insert(ppi->processUUID); 487 | } 488 | EXPECT_TRUE(uuidSet.count(data1[1].processUUID)); 489 | EXPECT_TRUE(uuidSet.count(data1[2].processUUID)); 490 | EXPECT_TRUE(uuidSet.count(data1[5].processUUID)); 491 | EXPECT_EQ(dbg.queryTrace.querys.size(), 2); 492 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 493 | EXPECT_EQ(dbg.queryTrace.getResultRows(), 3); 494 | 495 | cout << "Result:" << endl; 496 | int i = 0; 497 | for (auto ppi : r) { 498 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 499 | } 500 | 501 | cout << dbg.toString() << endl; 502 | } 503 | } 504 | 505 | // != 506 | TEST(shadowdb, ne) 507 | { 508 | db_t db; 509 | 510 | // 导入数据 511 | for (ProcessInfo const& pi : data3) { 512 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 513 | } 514 | 515 | // 无索引 516 | { 517 | ::shadow::Debugger dbg; 518 | std::vector r = db.selectVector( 519 | Cond(&ProcessInfo::scriptVersion) != 3 520 | && Cond(&ProcessInfo::scriptVersion) != 4, 521 | &dbg); 522 | EXPECT_EQ(r.size(), 4); 523 | std::set uuidSet; 524 | for (auto ppi : r) { 525 | uuidSet.insert(ppi->processUUID); 526 | } 527 | EXPECT_TRUE(uuidSet.count(data3[0].processUUID)); 528 | EXPECT_TRUE(uuidSet.count(data3[1].processUUID)); 529 | EXPECT_TRUE(uuidSet.count(data3[3].processUUID)); 530 | EXPECT_TRUE(uuidSet.count(data3[7].processUUID)); 531 | EXPECT_EQ(dbg.queryTrace.querys.size(), 1); 532 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 533 | EXPECT_EQ(dbg.queryTrace.getResultRows(), 4); 534 | 535 | cout << "Result:" << endl; 536 | int i = 0; 537 | for (auto ppi : r) { 538 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 539 | } 540 | 541 | cout << dbg.toString() << endl; 542 | } 543 | 544 | db.createIndex({&ProcessInfo::scriptVersion}); 545 | 546 | // 有索引 (1) 547 | { 548 | ::shadow::Debugger dbg; 549 | std::vector r = db.selectVector( 550 | Cond(&ProcessInfo::scriptVersion) != 3 551 | && Cond(&ProcessInfo::scriptVersion) != 4, 552 | &dbg); 553 | EXPECT_EQ(r.size(), 4); 554 | std::set uuidSet; 555 | for (auto ppi : r) { 556 | uuidSet.insert(ppi->processUUID); 557 | } 558 | EXPECT_TRUE(uuidSet.count(data3[0].processUUID)); 559 | EXPECT_TRUE(uuidSet.count(data3[1].processUUID)); 560 | EXPECT_TRUE(uuidSet.count(data3[3].processUUID)); 561 | EXPECT_TRUE(uuidSet.count(data3[7].processUUID)); 562 | EXPECT_EQ(dbg.queryTrace.querys.size(), 1); 563 | EXPECT_EQ(dbg.queryTrace.getScanRows(), r.size()); 564 | EXPECT_EQ(dbg.queryTrace.getResultRows(), r.size()); 565 | 566 | cout << "Result:" << endl; 567 | int i = 0; 568 | for (auto ppi : r) { 569 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 570 | } 571 | 572 | cout << dbg.toString() << endl; 573 | 574 | cout << db.toString() << endl; 575 | } 576 | 577 | // 有索引 (2) 578 | { 579 | db.createIndex({&ProcessInfo::scriptVersion}); 580 | 581 | ::shadow::Debugger dbg; 582 | std::vector r = db.selectVector( 583 | Cond(&ProcessInfo::scriptVersion) != 3 584 | && Cond(&ProcessInfo::scriptVersion) != 4 585 | && Cond(&ProcessInfo::scriptVersion) > 1 586 | && Cond(&ProcessInfo::scriptVersion) <= 6, 587 | &dbg); 588 | EXPECT_EQ(r.size(), 2); 589 | std::set uuidSet; 590 | for (auto ppi : r) { 591 | uuidSet.insert(ppi->processUUID); 592 | } 593 | EXPECT_TRUE(uuidSet.count(data3[1].processUUID)); 594 | EXPECT_TRUE(uuidSet.count(data3[3].processUUID)); 595 | EXPECT_EQ(dbg.queryTrace.querys.size(), 1); 596 | EXPECT_EQ(dbg.queryTrace.getScanRows(), r.size()); 597 | EXPECT_EQ(dbg.queryTrace.getResultRows(), r.size()); 598 | 599 | cout << "Result:" << endl; 600 | int i = 0; 601 | for (auto ppi : r) { 602 | cout << " " << ::shadow::fmt("[%d] %s", i++, ppi->toString().c_str()) << endl; 603 | } 604 | 605 | cout << dbg.toString() << endl; 606 | 607 | cout << db.toString() << endl; 608 | } 609 | } 610 | 611 | // 验证fork正确性 fork(data + index) * CURD 612 | TEST(shadowdb, fork_simple) 613 | { 614 | db_t db; 615 | EXPECT_TRUE(db.createIndex({&ProcessInfo::scriptKey})); 616 | 617 | // 导入数据 618 | for (ProcessInfo const& pi : data1) { 619 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 620 | } 621 | 622 | EXPECT_EQ(db.forkLevel(), 1); 623 | 624 | db_t forked; 625 | db.fork(forked); 626 | EXPECT_EQ(db.forkLevel(), 2); 627 | EXPECT_EQ(forked.forkLevel(), 2); 628 | 629 | EXPECT_EQ(db.size(), data1.size()); 630 | EXPECT_EQ(forked.size(), data1.size()); 631 | 632 | // 修改旧数据 633 | ProcessInfo const& newPi = data2[0]; 634 | forked.update(newPi.processUUID, newPi); 635 | db_t::VRefPtr dbDataPtr = db.get(newPi.processUUID); 636 | db_t::VRefPtr forkedDataPtr = forked.get(newPi.processUUID); 637 | EXPECT_TRUE(dbDataPtr->check(data1[0])); 638 | EXPECT_FALSE(dbDataPtr->check(data2[0])); 639 | EXPECT_TRUE(forkedDataPtr->check(data2[0])); 640 | 641 | // cout << "db:\n" << db.toString() << endl; 642 | // cout << "forked:\n" << forked.toString() << endl; 643 | 644 | // 写入新数据 645 | for (ProcessInfo const& pi : g1) { 646 | EXPECT_TRUE(forked.set(pi.processUUID, pi)); 647 | } 648 | 649 | EXPECT_EQ(db.size(), data1.size()); 650 | EXPECT_EQ(forked.size(), data1.size() + g1.size()); 651 | 652 | // 检验 653 | ProcessInfo const& pi = g1[3]; 654 | EXPECT_FALSE(!!db.get(pi.processUUID)); 655 | EXPECT_TRUE(!!forked.get(pi.processUUID)); 656 | 657 | // cout << "db:\n" << db.toString() << endl; 658 | // cout << "forked:\n" << forked.toString() << endl; 659 | 660 | // -------- 多次fork 661 | db_t f2; 662 | forked.fork(f2); 663 | EXPECT_EQ(db.forkLevel(), 2); 664 | EXPECT_EQ(forked.forkLevel(), 3); 665 | EXPECT_EQ(f2.forkLevel(), 3); 666 | 667 | db_t f3; // 还未写入数据, forkLevel不增加 668 | f2.fork(f3); 669 | EXPECT_EQ(db.forkLevel(), 2); 670 | EXPECT_EQ(forked.forkLevel(), 3); 671 | EXPECT_EQ(f2.forkLevel(), 3); 672 | EXPECT_EQ(f3.forkLevel(), 3); 673 | 674 | // cout << "db:\n" << db.toString() << endl; 675 | // cout << "forked:\n" << forked.toString() << endl; 676 | // cout << "f2:\n" << f2.toString() << endl; 677 | // cout << "f3:\n" << f3.toString() << endl; 678 | 679 | // 写入新数据 680 | for (ProcessInfo const& pi : g2) { 681 | EXPECT_TRUE(f2.set(pi.processUUID, pi)); 682 | } 683 | 684 | EXPECT_TRUE(f2.createIndex({&ProcessInfo::id})); 685 | 686 | EXPECT_EQ(db.size(), data1.size()); 687 | EXPECT_EQ(forked.size(), data1.size() + g1.size()); 688 | EXPECT_EQ(f2.size(), data1.size() + g1.size() + g2.size()); 689 | EXPECT_EQ(f3.size(), data1.size() + g1.size()); 690 | 691 | // 删除顶层数据 692 | EXPECT_TRUE(forked.del(g1[0].processUUID)); 693 | EXPECT_FALSE(forked.del(g1[0].processUUID)); 694 | EXPECT_FALSE(forked.get(g1[0].processUUID)); 695 | EXPECT_FALSE(db.get(g1[0].processUUID)); 696 | EXPECT_TRUE(f3.get(g1[0].processUUID)); 697 | 698 | // 删除底层数据 699 | EXPECT_TRUE(forked.del(data1[0].processUUID)); 700 | EXPECT_FALSE(forked.get(data1[0].processUUID)); 701 | EXPECT_TRUE(db.get(data1[0].processUUID)); 702 | EXPECT_TRUE(f3.get(data1[0].processUUID)); 703 | 704 | // cout << "db:\n" << db.toString() << endl; 705 | // cout << "forked:\n" << forked.toString() << endl; 706 | // cout << "f2:\n" << f2.toString() << endl; 707 | } 708 | 709 | // 验证fork正确性 (hash碰撞) 710 | TEST(shadowdb, fork_hashpong) 711 | { 712 | shadow::Config conf; 713 | conf.minBucketCount = 1; 714 | 715 | db_t db(conf); 716 | EXPECT_TRUE(db.createIndex({&ProcessInfo::scriptKey})); 717 | EXPECT_TRUE(db.createIndex({&ProcessInfo::scriptVersion, &ProcessInfo::id})); 718 | 719 | // 导入数据 720 | for (ProcessInfo const& pi : data1) { 721 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 722 | } 723 | 724 | EXPECT_EQ(db.forkLevel(), 1); 725 | 726 | db_t forked; 727 | db.fork(forked); 728 | EXPECT_EQ(db.forkLevel(), 2); 729 | EXPECT_EQ(forked.forkLevel(), 2); 730 | 731 | EXPECT_EQ(db.size(), data1.size()); 732 | EXPECT_EQ(forked.size(), data1.size()); 733 | 734 | // 写入新数据 735 | for (ProcessInfo const& pi : g1) { 736 | EXPECT_TRUE(forked.set(pi.processUUID, pi)); 737 | } 738 | 739 | // 删除顶层数据 740 | EXPECT_TRUE(forked.del(g1[0].processUUID)); 741 | EXPECT_FALSE(forked.get(g1[0].processUUID)); 742 | EXPECT_FALSE(db.get(g1[0].processUUID)); 743 | 744 | // 删除底层数据 745 | EXPECT_TRUE(forked.del(data1[0].processUUID)); 746 | EXPECT_FALSE(forked.get(data1[0].processUUID)); 747 | EXPECT_TRUE(db.get(data1[0].processUUID)); 748 | 749 | // cout << "db:\n" << db.toString() << endl; 750 | // cout << "forked:\n" << forked.toString() << endl; 751 | 752 | // merge 753 | string uuid = data1[1].processUUID; 754 | db_t::VRefPtr ref = forked.get(uuid); 755 | EXPECT_TRUE(ref); 756 | if (ref) { 757 | EXPECT_EQ(uuid, ref->processUUID); 758 | } 759 | // cout << ref.toString() << endl; 760 | 761 | forked.merge(); 762 | EXPECT_TRUE(ref); 763 | if (ref) { 764 | EXPECT_EQ(uuid, ref->processUUID); 765 | } 766 | // cout << ref.toString() << endl; 767 | 768 | // cout << "merged forked:\n" << forked.toString() << endl; 769 | 770 | ::shadow::Debugger dbg1; 771 | std::vector r1 = forked.selectVector(Cond(&ProcessInfo::scriptKey) == "g1-mips", &dbg1); 772 | EXPECT_EQ(r1.size(), 7); 773 | for (auto ppi : r1) { 774 | EXPECT_EQ(ppi->scriptKey, "g1-mips"); 775 | } 776 | // cout << dbg1.toString() << endl; 777 | // 778 | // cout << "flushed index forked:\n" << forked.toString() << endl; 779 | } 780 | 781 | // 底层无引用时merge 782 | TEST(shadowdb, fastMerge) 783 | { 784 | db_t db; 785 | db.createIndex({&ProcessInfo::id}); 786 | 787 | // 导入数据 788 | for (ProcessInfo const& pi : data1) { 789 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 790 | } 791 | 792 | EXPECT_EQ(db.forkLevel(), 1); 793 | 794 | { 795 | db_t forked; 796 | db.fork(forked); 797 | EXPECT_EQ(db.forkLevel(), 2); 798 | EXPECT_EQ(forked.forkLevel(), 2); 799 | 800 | EXPECT_EQ(db.size(), data1.size()); 801 | EXPECT_EQ(forked.size(), data1.size()); 802 | } 803 | 804 | // 写入新数据 805 | for (ProcessInfo const& pi : g1) { 806 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 807 | } 808 | 809 | // cout << "db:\n" << db.toString() << endl; 810 | db.merge(); 811 | EXPECT_EQ(db.forkLevel(), 1); 812 | // cout << "merged db:\n" << db.toString() << endl; 813 | } 814 | 815 | // 自定义function列索引、查询 816 | // 命中索引查询、不命中索引查询 817 | TEST(shadowdb, VirtualColumn_Index_Select) 818 | { 819 | db_t db; 820 | ::shadow::VirtualColumn scriptVersionMod3 = 821 | db.makeVirtualColumn([](ProcessInfo const& pi) { return pi.scriptVersion % 3; }, "scriptVersionMod3"); 822 | db.createIndex({scriptVersionMod3}); 823 | 824 | ::shadow::VirtualColumn scriptVersionMod2 = 825 | db.makeVirtualColumn([](ProcessInfo const& pi) { return pi.scriptVersion % 2; }, "scriptVersionMod2"); 826 | 827 | // 导入数据 828 | for (ProcessInfo const& pi : data1) { 829 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 830 | } 831 | 832 | EXPECT_EQ(db.forkLevel(), 1); 833 | 834 | { 835 | db_t forked; 836 | db.fork(forked); 837 | EXPECT_EQ(db.forkLevel(), 2); 838 | EXPECT_EQ(forked.forkLevel(), 2); 839 | 840 | EXPECT_EQ(db.size(), data1.size()); 841 | EXPECT_EQ(forked.size(), data1.size()); 842 | } 843 | 844 | // simple 845 | { 846 | ::shadow::Debugger dbg; 847 | std::vector r = db.selectVector(Cond(scriptVersionMod3) > 1, &dbg); 848 | EXPECT_EQ(r.size(), 2); 849 | 850 | cout << "--------------------------- simple" << endl; 851 | cout << db.toString() << endl; 852 | cout << dbg.toString() << endl; 853 | cout << "--------------------------- simple" << endl; 854 | } 855 | 856 | // not 857 | { 858 | ::shadow::Debugger dbg; 859 | std::vector r = db.selectVector(!(Cond(scriptVersionMod3) > 1), &dbg); 860 | EXPECT_EQ(r.size(), 6); 861 | 862 | cout << "--------------------------- not" << endl; 863 | cout << db.toString() << endl; 864 | cout << dbg.toString() << endl; 865 | cout << "--------------------------- not" << endl; 866 | } 867 | 868 | // ! && 869 | { 870 | ::shadow::Debugger dbg; 871 | std::vector r = db.selectVector( 872 | !(Cond(scriptVersionMod3) > 1) && (Cond(scriptVersionMod2) == 1) 873 | , &dbg); 874 | EXPECT_EQ(r.size(), 6); 875 | 876 | cout << "--------------------------- ! and &&" << endl; 877 | cout << db.toString() << endl; 878 | cout << dbg.toString() << endl; 879 | cout << "--------------------------- ! and &&" << endl; 880 | } 881 | 882 | // && || 883 | { 884 | ::shadow::Debugger dbg; 885 | std::vector r = db.selectVector( 886 | !(Cond(scriptVersionMod3) > 1) && (Cond(scriptVersionMod2) == 1) 887 | || (Cond(&ProcessInfo::scriptVersion) == 8) 888 | , &dbg); 889 | EXPECT_EQ(r.size(), 7); 890 | 891 | cout << "--------------------------- && and ||" << endl; 892 | cout << db.toString() << endl; 893 | cout << dbg.toString() << endl; 894 | cout << "--------------------------- && and ||" << endl; 895 | } 896 | } 897 | 898 | // OneOf 899 | TEST(shadowdb, one_of) 900 | { 901 | db_t db; 902 | db.createIndex({OneOf(&ProcessInfo::scriptName)}); 903 | 904 | ::shadow::VirtualColumn oneOfScriptName = 905 | db.makeVirtualColumn([](ProcessInfo const& pi) 906 | { 907 | vector vec; 908 | for (char ch : pi.scriptName) 909 | vec.push_back(ch); 910 | return vec; 911 | }, "oneOfScriptName"); 912 | db.createIndex({oneOfScriptName}); 913 | 914 | // 导入数据 915 | for (ProcessInfo const& pi : data1) { 916 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 917 | } 918 | 919 | /// -------------- OneOf keywards 920 | // simple 921 | { 922 | ::shadow::Debugger dbg; 923 | std::vector r = db.selectVector(OneOf(&ProcessInfo::scriptName) == 'a', &dbg); 924 | EXPECT_EQ(r.size(), 2); 925 | 926 | cout << "--------------------------- simple" << endl; 927 | cout << db.toString() << endl; 928 | cout << dbg.toString() << endl; 929 | cout << "--------------------------- simple" << endl; 930 | } 931 | 932 | // simple2 (去重) 933 | { 934 | ::shadow::Debugger dbg; 935 | std::vector r = db.selectVector(OneOf(&ProcessInfo::scriptName) == 'c', &dbg); 936 | EXPECT_EQ(r.size(), 8); 937 | 938 | cout << "--------------------------- simple2" << endl; 939 | cout << db.toString() << endl; 940 | cout << dbg.toString() << endl; 941 | cout << "--------------------------- simple2" << endl; 942 | } 943 | 944 | /// ----------- one_of virtual column 945 | // simple 946 | { 947 | ::shadow::Debugger dbg; 948 | std::vector r = db.selectVector(Cond(oneOfScriptName) == 'a', &dbg); 949 | EXPECT_EQ(r.size(), 2); 950 | 951 | cout << "--------------------------- simple" << endl; 952 | cout << db.toString() << endl; 953 | cout << dbg.toString() << endl; 954 | cout << "--------------------------- simple" << endl; 955 | } 956 | 957 | // simple2 (去重) 958 | { 959 | ::shadow::Debugger dbg; 960 | std::vector r = db.selectVector(Cond(oneOfScriptName) == 'c', &dbg); 961 | EXPECT_EQ(r.size(), 8); 962 | 963 | cout << "--------------------------- simple2" << endl; 964 | cout << db.toString() << endl; 965 | cout << dbg.toString() << endl; 966 | cout << "--------------------------- simple2" << endl; 967 | } 968 | } 969 | 970 | // order by 971 | TEST(shadowdb, order_by) 972 | { 973 | db_t db; 974 | ::shadow::VirtualColumn scriptVersionMod3 = 975 | db.makeVirtualColumn([](ProcessInfo const& pi) { return pi.scriptVersion % 3; }, "scriptVersionMod3"); 976 | db.createIndex({scriptVersionMod3}); 977 | 978 | db.createIndex({&ProcessInfo::scriptName, &ProcessInfo::scriptVersion}); 979 | db.createIndex({&ProcessInfo::scriptName, scriptVersionMod3}); 980 | db.createIndex({&ProcessInfo::nodeName}); 981 | 982 | // 导入数据 983 | for (ProcessInfo const& pi : data1) { 984 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 985 | } 986 | 987 | // 1.order by命中索引 988 | // 1.1 simple索引 989 | { 990 | cout << "------------------- 1.1" << endl; 991 | ::shadow::Debugger dbg; 992 | std::vector r = db.selectVector( 993 | Cond(&ProcessInfo::nodeName) > "192.168.0.2", 994 | OrderBy(&ProcessInfo::nodeName), &dbg); 995 | EXPECT_EQ(r.size(), 4); 996 | EXPECT_EQ(r[0]->nodeName, "192.168.0.3"); 997 | EXPECT_EQ(r[1]->nodeName, "192.168.0.3"); 998 | EXPECT_EQ(r[2]->nodeName, "192.168.0.4"); 999 | EXPECT_EQ(r[3]->nodeName, "192.168.0.4"); 1000 | 1001 | // cout << dbg.toString() << endl; 1002 | // dump(r); 1003 | } 1004 | 1005 | // 1.2 function索引 1006 | { 1007 | cout << "------------------- 1.2" << endl; 1008 | ::shadow::Debugger dbg; 1009 | std::vector r = db.selectVector( 1010 | Cond(scriptVersionMod3) >= 1, 1011 | OrderBy(scriptVersionMod3), &dbg); 1012 | EXPECT_EQ(r.size(), 7); 1013 | EXPECT_EQ(r[0]->scriptVersion % 3, 1); 1014 | EXPECT_EQ(r[1]->scriptVersion % 3, 1); 1015 | EXPECT_EQ(r[2]->scriptVersion % 3, 1); 1016 | EXPECT_EQ(r[3]->scriptVersion % 3, 1); 1017 | EXPECT_EQ(r[4]->scriptVersion % 3, 1); 1018 | EXPECT_EQ(r[5]->scriptVersion % 3, 2); 1019 | EXPECT_EQ(r[6]->scriptVersion % 3, 2); 1020 | 1021 | // cout << dbg.toString() << endl; 1022 | // dump(r); 1023 | } 1024 | 1025 | // 1.3 命中索引的最左前缀 1026 | { 1027 | cout << "------------------- 1.3" << endl; 1028 | ::shadow::Debugger dbg; 1029 | std::vector r = db.selectVector( 1030 | {}, 1031 | OrderBy(&ProcessInfo::scriptName), &dbg); 1032 | EXPECT_EQ(r.size(), 8); 1033 | // EXPECT_EQ(r[0]->nodeName, "192.168.0.3"); 1034 | 1035 | // cout << db.toString() << endl; 1036 | // cout << dbg.toString() << endl; 1037 | // dump(r); 1038 | } 1039 | 1040 | // 1.4 复合order by 1041 | { 1042 | cout << "------------------- 1.4" << endl; 1043 | ::shadow::Debugger dbg; 1044 | std::vector r = db.selectVector( 1045 | {}, 1046 | OrderBy(&ProcessInfo::scriptName, &ProcessInfo::scriptVersion), &dbg); 1047 | EXPECT_EQ(r.size(), 8); 1048 | // EXPECT_EQ(r[0]->nodeName, "192.168.0.3"); 1049 | 1050 | // cout << db.toString() << endl; 1051 | // cout << dbg.toString() << endl; 1052 | // dump(r); 1053 | } 1054 | 1055 | // 1.5 (memptr + function)复合order by 1056 | { 1057 | cout << "------------------- 1.5" << endl; 1058 | ::shadow::Debugger dbg; 1059 | std::vector r = db.selectVector( 1060 | {}, 1061 | OrderBy(&ProcessInfo::scriptName, scriptVersionMod3), &dbg); 1062 | EXPECT_EQ(r.size(), 8); 1063 | EXPECT_TRUE(r[0]->check(data1[2])); 1064 | EXPECT_TRUE(r[1]->check(data1[3])); 1065 | EXPECT_TRUE(r[2]->check(data1[1])); 1066 | EXPECT_TRUE(r[3]->check(data1[0])); 1067 | EXPECT_TRUE(r[4]->check(data1[4])); 1068 | EXPECT_TRUE(r[5]->check(data1[6])); 1069 | EXPECT_TRUE(r[6]->check(data1[7])); 1070 | EXPECT_TRUE(r[7]->check(data1[5])); 1071 | 1072 | // cout << db.toString() << endl; 1073 | // cout << dbg.toString() << endl; 1074 | // dump(r); 1075 | } 1076 | 1077 | // 1.6 order by未匹配, 但查询条件有一定匹配度 1078 | { 1079 | cout << "------------------- 1.6" << endl; 1080 | ::shadow::Debugger dbg; 1081 | std::vector r = db.selectVector( 1082 | Cond(scriptVersionMod3) >= 1, 1083 | OrderBy(&ProcessInfo::scriptKey), &dbg); 1084 | EXPECT_EQ(r.size(), 7); 1085 | EXPECT_TRUE(r[0]->check(data1[6])); 1086 | EXPECT_TRUE(r[1]->check(data1[2])); 1087 | EXPECT_TRUE(r[2]->check(data1[7])); 1088 | EXPECT_TRUE(r[3]->check(data1[5])); 1089 | EXPECT_TRUE(r[4]->check(data1[3])); 1090 | EXPECT_TRUE(r[5]->check(data1[0])); 1091 | EXPECT_TRUE(r[6]->check(data1[4])); 1092 | 1093 | // cout << db.toString() << endl; 1094 | // cout << dbg.toString() << endl; 1095 | // dump(r); 1096 | // dumpFind(data1, r); 1097 | } 1098 | 1099 | // 1.7 索引匹配, 但顺序不对 1100 | { 1101 | cout << "------------------- 1.7" << endl; 1102 | ::shadow::Debugger dbg; 1103 | std::vector r = db.selectVector( 1104 | Cond(scriptVersionMod3) >= 1, 1105 | OrderBy(&ProcessInfo::scriptVersion, &ProcessInfo::scriptName), &dbg); 1106 | EXPECT_EQ(r.size(), 7); 1107 | EXPECT_TRUE(r[0]->check(data1[2])); 1108 | EXPECT_TRUE(r[1]->check(data1[0])); 1109 | EXPECT_TRUE(r[2]->check(data1[4])); 1110 | EXPECT_TRUE(r[3]->check(data1[6])); 1111 | EXPECT_TRUE(r[4]->check(data1[7])); 1112 | EXPECT_TRUE(r[5]->check(data1[5])); 1113 | EXPECT_TRUE(r[6]->check(data1[3])); 1114 | 1115 | // cout << db.toString() << endl; 1116 | // cout << dbg.toString() << endl; 1117 | // dump(r); 1118 | // dumpFind(data1, r); 1119 | } 1120 | 1121 | // 2.order by未命中索引 1122 | 1123 | // 2.1 无索引 1124 | { 1125 | cout << "------------------- 2.1" << endl; 1126 | ::shadow::Debugger dbg; 1127 | std::vector r = db.selectVector( 1128 | Cond(&ProcessInfo::scriptKey) >= "mips-a-2", 1129 | OrderBy(&ProcessInfo::scriptKey), &dbg); 1130 | EXPECT_EQ(r.size(), 4); 1131 | EXPECT_TRUE(r[0]->check(data1[3])); 1132 | EXPECT_TRUE(r[1]->check(data1[1])); 1133 | EXPECT_TRUE(r[2]->check(data1[0])); 1134 | EXPECT_TRUE(r[3]->check(data1[4])); 1135 | 1136 | // cout << db.toString() << endl; 1137 | // cout << dbg.toString() << endl; 1138 | // dump(r); 1139 | // dumpFind(data1, r); 1140 | } 1141 | 1142 | // 2.2 在索引中,但不是最左前缀 1143 | { 1144 | cout << "------------------- 2.2" << endl; 1145 | ::shadow::Debugger dbg; 1146 | std::vector r = db.selectVector( 1147 | {}, 1148 | OrderBy(&ProcessInfo::scriptVersion), &dbg); 1149 | EXPECT_EQ(r.size(), 8); 1150 | EXPECT_TRUE(r[0]->check(data1[0])); 1151 | EXPECT_TRUE(r[1]->check(data1[7])); 1152 | EXPECT_TRUE(r[2]->check(data1[2])); 1153 | EXPECT_TRUE(r[3]->check(data1[6])); 1154 | EXPECT_TRUE(r[4]->check(data1[4])); 1155 | EXPECT_TRUE(r[5]->check(data1[5])); 1156 | EXPECT_TRUE(r[6]->check(data1[1])); 1157 | EXPECT_TRUE(r[7]->check(data1[3])); 1158 | 1159 | // cout << db.toString() << endl; 1160 | // cout << dbg.toString() << endl; 1161 | // dump(r); 1162 | // dumpFind(data1, r); 1163 | } 1164 | 1165 | // 2.3 索引匹配, 但顺序不对 1166 | { 1167 | cout << "------------------- 2.3" << endl; 1168 | ::shadow::Debugger dbg; 1169 | std::vector r = db.selectVector( 1170 | {}, 1171 | OrderBy(&ProcessInfo::scriptVersion, &ProcessInfo::scriptName), &dbg); 1172 | EXPECT_EQ(r.size(), 8); 1173 | EXPECT_TRUE(r[0]->check(data1[2])); 1174 | EXPECT_TRUE(r[1]->check(data1[0])); 1175 | EXPECT_TRUE(r[2]->check(data1[4])); 1176 | EXPECT_TRUE(r[3]->check(data1[7])); 1177 | EXPECT_TRUE(r[4]->check(data1[6])); 1178 | EXPECT_TRUE(r[5]->check(data1[5])); 1179 | EXPECT_TRUE(r[6]->check(data1[1])); 1180 | EXPECT_TRUE(r[7]->check(data1[3])); 1181 | 1182 | // cout << db.toString() << endl; 1183 | // cout << dbg.toString() << endl; 1184 | // dump(r); 1185 | // dumpFind(data1, r); 1186 | } 1187 | } 1188 | 1189 | void dump(std::vector const& r) 1190 | { 1191 | cout << "->r:" << endl; 1192 | int i = 0; 1193 | for (auto ppi : r) 1194 | { 1195 | cout << ::shadow::fmt("[%d] %s", i++, ppi->toStringAll().c_str()) << endl; 1196 | } 1197 | } 1198 | 1199 | size_t find(std::vector const& data, ProcessInfo const* ppi) 1200 | { 1201 | for (size_t i = 0; i < data.size(); ++i) 1202 | { 1203 | if (data[i].check(*ppi)) 1204 | return i; 1205 | } 1206 | return -1; 1207 | } 1208 | 1209 | void dumpFind(std::vector const& data, std::vector const& r) 1210 | { 1211 | cout << "->find:" << endl; 1212 | int i = 0; 1213 | for (auto ppi : r) 1214 | { 1215 | cout << ::shadow::fmt("[%d] %d", i++, (int)find(data, ppi)) << endl; 1216 | } 1217 | } 1218 | 1219 | void initDB(db_t & db, int nRows, bool bCreateIndex = true, int nLevel = 1) 1220 | { 1221 | for (int i = 0; i < nRows; ++i) { 1222 | ProcessInfo pi; 1223 | pi.id = {0, i}; 1224 | pi.processUUID = std::to_string(i); 1225 | pi.scriptName = std::to_string(i) + ".cc"; 1226 | pi.scriptVersion = i; 1227 | pi.scriptKey = ""; 1228 | pi.nodeName = "10." + std::to_string(i); 1229 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 1230 | } 1231 | 1232 | if (bCreateIndex) { 1233 | db.createIndex({&ProcessInfo::id}); 1234 | db.createIndex({&ProcessInfo::nodeName}); 1235 | db.createIndex({&ProcessInfo::scriptName, &ProcessInfo::scriptVersion}); 1236 | } 1237 | 1238 | nLevel = (std::max)(nLevel, 1); 1239 | for (int lv = 1; lv < nLevel; ++lv) { 1240 | db_t temp; 1241 | db.fork(temp); 1242 | 1243 | int i = nRows + lv; 1244 | ProcessInfo pi; 1245 | pi.id = {0, i}; 1246 | pi.processUUID = std::to_string(i); 1247 | pi.scriptName = std::to_string(i) + ".cc"; 1248 | pi.scriptVersion = i; 1249 | pi.scriptKey = ""; 1250 | pi.nodeName = "10." + std::to_string(i); 1251 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 1252 | } 1253 | 1254 | EXPECT_EQ(db.forkLevel(), nLevel); 1255 | } 1256 | 1257 | // 大量数据, 校验fork时长 1258 | TEST(shadowdb_bench, fork_large) 1259 | { 1260 | vector cs = { 1261 | 1000, 1262 | 10 * 1000, 1263 | 100 * 1000, 1264 | // 1000 * 1000, 1265 | }; 1266 | 1267 | cout << "benchmark: DB with 3 indexes" << endl; 1268 | for (int c : cs) { 1269 | cout << "====================================" << endl; 1270 | int64_t t1, t2, t3; 1271 | int64_t beforeDestory, afterDestroy; 1272 | { 1273 | db_t db; 1274 | db.createIndex({&ProcessInfo::id}); 1275 | db.createIndex({&ProcessInfo::nodeName}); 1276 | db.createIndex({&ProcessInfo::scriptName, &ProcessInfo::scriptVersion}); 1277 | 1278 | t1 = us(); 1279 | for (int i = 0; i < c; ++i) { 1280 | ProcessInfo pi; 1281 | pi.id = {0, i}; 1282 | pi.processUUID = std::to_string(i); 1283 | pi.scriptName = std::to_string(i) + ".cc"; 1284 | pi.scriptVersion = i; 1285 | pi.scriptKey = ""; 1286 | pi.nodeName = "10." + std::to_string(i); 1287 | EXPECT_TRUE(db.set(pi.processUUID, pi)); 1288 | } 1289 | EXPECT_EQ(db.size(), c); 1290 | t2 = us(); 1291 | cout << "insert " << c << " rows. cost: " << t2 - t1 << "us" << endl; 1292 | 1293 | // cout << "db(simple):\n" << db.toString(true) << endl; 1294 | 1295 | t1 = us(); 1296 | { 1297 | db_t forked; 1298 | db.fork(forked); 1299 | t2 = us(); 1300 | } 1301 | t3 = us(); 1302 | 1303 | // cout << "db(simple):\n" << db.toString(true) << endl; 1304 | 1305 | cout << "fork " << c << " rows. cost: " << t2 - t1 << "us" << endl; 1306 | cout << "destroy forked db. cost: " << t3 - t2 << "us" << endl; 1307 | beforeDestory = us(); 1308 | } 1309 | afterDestroy = us(); 1310 | cout << "destroy db. cost: " << afterDestroy - beforeDestory << "us" << endl; 1311 | cout << "====================================" << endl; 1312 | } 1313 | } 1314 | 1315 | // 大量数据, 多层fork 1316 | TEST(shadowdb_bench, fork_multi_large) 1317 | { 1318 | db_t db; 1319 | initDB(db, 100 * 1000, true, 10); 1320 | 1321 | int64_t t1 = us(); 1322 | db_t forked; 1323 | db.fork(forked); 1324 | int64_t t2 = us(); 1325 | EXPECT_TRUE(t2 - t1 < 10 * 1000); // 小于10ms 1326 | cout << "fork 10 levels, 100 * 1000 rows db. cost:" << t2 - t1 << "us" << endl; 1327 | } 1328 | 1329 | // 测试无索引场景 1330 | TEST(shadowdb_bench, index_yes_or_no) 1331 | { 1332 | vector levels = { 1333 | 1, 1334 | 2, 1335 | 3, 1336 | 5, 1337 | 10, 1338 | 20 1339 | }; 1340 | 1341 | int64_t t1, t2, rows; 1342 | for (int indexY = 0; indexY < 2; ++indexY) { 1343 | bool useIndex = !!indexY; 1344 | for (int lv : levels) { 1345 | db_t db; 1346 | initDB(db, 100 * 1000, useIndex, lv); 1347 | 1348 | { 1349 | ::shadow::Debugger dbg; 1350 | std::vector r = db.selectVector( 1351 | Cond(&ProcessInfo::id) >= Id{0, 1000} 1352 | && Cond(&ProcessInfo::id) < Id{0, 1010} 1353 | , &dbg); 1354 | EXPECT_EQ(r.size(), 10); 1355 | if (!useIndex) { 1356 | EXPECT_EQ(dbg.queryTrace.getScanRows(), db.size()); 1357 | } 1358 | } 1359 | 1360 | t1 = us(); 1361 | for (int i = 0; i < 10; ++i) { 1362 | std::vector r = db.selectVector( 1363 | Cond(&ProcessInfo::id) >= Id{0, 1000} 1364 | && Cond(&ProcessInfo::id) < Id{0, 1010}); 1365 | rows += r.size(); 1366 | } 1367 | t2 = us(); 1368 | cout << "[Index=" << useIndex << "]fork.level=" << lv 1369 | << " select by scan 100 * 1000 rows return 10 rows. cost:" 1370 | << (t2 - t1) / 10 << "us" << endl; 1371 | 1372 | if (!useIndex) { 1373 | t1 = us(); 1374 | for (int i = 0; i < 10; ++i) { 1375 | db.foreach([&](string const&, ProcessInfo const& pi){ 1376 | if (pi.id >= Id{0, 1000} && pi.id < Id{0, 1010}) 1377 | ++rows; 1378 | return true; 1379 | }); 1380 | } 1381 | t2 = us(); 1382 | cout << "fork.level=" << lv 1383 | << " foreach 100 * 1000 rows return 10 rows. cost:" 1384 | << (t2 - t1) / 10 << "us" << endl; 1385 | } 1386 | } 1387 | } 1388 | 1389 | cout << "----------------------------------" << endl; 1390 | cout << "ignore optimized output:" << rows << endl; 1391 | } 1392 | 1393 | // 测试主键查询 1394 | TEST(shadowdb_bench, mainkey) 1395 | { 1396 | vector levels = { 1397 | 1, 1398 | 2, 1399 | 3, 1400 | 5, 1401 | 10, 1402 | 20 1403 | }; 1404 | 1405 | int64_t t1, t2, rows = 0; 1406 | for (int lv : levels) { 1407 | db_t db; 1408 | initDB(db, 100 * 1000, false, lv); 1409 | 1410 | { 1411 | ProcessInfo pi; 1412 | EXPECT_TRUE(db.get(std::to_string(1000), pi)); 1413 | EXPECT_TRUE(db.get(std::to_string(1000))); 1414 | } 1415 | 1416 | t1 = ns(); 1417 | for (int i = 0; i < 1000; ++i) { 1418 | ProcessInfo pi; 1419 | rows += (int)db.get(std::to_string(1000), pi); 1420 | } 1421 | t2 = ns(); 1422 | cout << "fork.level=" << lv 1423 | << " mainkey select in 100 * 1000 rows. cost:" 1424 | << (t2 - t1) / 1000 << " ns" << endl; 1425 | } 1426 | 1427 | cout << "----------------------------------" << endl; 1428 | cout << "ignore optimized output:" << rows << endl; 1429 | } 1430 | -------------------------------------------------------------------------------- /ShadowDB.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace shadow { 21 | 22 | using namespace std; 23 | 24 | namespace adl { 25 | template 26 | struct HasToString 27 | { 28 | template 29 | static char foo(U*, decltype(((U*)0)->toString())*); 30 | 31 | template 32 | static short foo(U*, ...); 33 | 34 | static const bool value = sizeof(foo((T*)0, nullptr)) == sizeof(char); 35 | }; 36 | 37 | template 38 | struct StdToString 39 | { 40 | template 41 | static char foo(U*, decltype(std::to_string(*((U*)0)))*); 42 | 43 | template 44 | static short foo(U*, ...); 45 | 46 | static const bool value = sizeof(foo((T*)0, nullptr)) == sizeof(char); 47 | }; 48 | 49 | template 50 | struct IsString 51 | { 52 | static const bool value = std::is_same::type, std::string>::value 53 | || std::is_same::type, char*>::value 54 | || std::is_same::type, const char*>::value; 55 | }; 56 | 57 | template 58 | static typename std::enable_if::value, string>::type 59 | to_string(T const& t) 60 | { 61 | return std::to_string(t); 62 | } 63 | 64 | template 65 | static typename std::enable_if::value, string>::type 66 | to_string(T const& t) 67 | { 68 | return const_cast(t).toString(); 69 | } 70 | 71 | template 72 | static typename std::enable_if::value, string>::type 73 | to_string(T const& t) 74 | { 75 | return string{t}; 76 | } 77 | 78 | template 79 | static typename std::enable_if< 80 | !HasToString::value && !StdToString::value && !IsString::value, 81 | string 82 | >::type 83 | to_string(T const& t) 84 | { 85 | return "Unsupport-type"; 86 | } 87 | 88 | template 89 | map & field_maps() 90 | { 91 | static map m; 92 | return m; 93 | } 94 | 95 | template 96 | void register_to_string(F V::* memptr, string fieldname) 97 | { 98 | size_t offset = reinterpret_cast(&(((V*)0) ->* memptr)); 99 | map & m = field_maps(); 100 | m[offset] = fieldname; 101 | } 102 | 103 | #define SHADOW_DB_DEBUG_FIELD(V, F) \ 104 | struct SHADOW_DB_DEBUG_FIELD__ ## V ## F \ 105 | { \ 106 | SHADOW_DB_DEBUG_FIELD__ ## V ## F () { \ 107 | ::shadow::adl::register_to_string(&V::F, #V "::" #F);\ 108 | } \ 109 | } gShadowDBDebugRegister_ ## V ## F 110 | 111 | template 112 | string field_to_string(size_t offset) 113 | { 114 | map & m = field_maps(); 115 | auto it = m.find(offset); 116 | return (m.end() == it) ? "" : it->second; 117 | } 118 | } 119 | 120 | string P(const char* fmt = "", ...) __attribute__((format(printf,1,2))); 121 | string fmt(const char* fmt = "", ...) __attribute__((format(printf,1,2))); 122 | 123 | inline size_t & tlsTab() { 124 | static thread_local size_t t = 0; 125 | return t; 126 | } 127 | 128 | inline string P(const char* fmt, ...) 129 | { 130 | va_list ap; 131 | va_start(ap, fmt); 132 | char buf[4096]; 133 | size_t tt = tlsTab(); 134 | if (tt) { 135 | memset(buf, ' ', tt); 136 | } 137 | 138 | int len = vsnprintf((char*)buf + tt, sizeof(buf) - tt - 1, fmt, ap) + tt; 139 | buf[len] = '\n'; 140 | va_end(ap); 141 | return std::string(buf, len + 1); 142 | } 143 | 144 | inline string fmt(const char* fmt, ...) 145 | { 146 | va_list ap; 147 | va_start(ap, fmt); 148 | char buf[4096]; 149 | int len = vsnprintf((char*)buf, sizeof(buf) - 1, fmt, ap); 150 | va_end(ap); 151 | return std::string(buf, len); 152 | } 153 | 154 | // 条件 155 | enum class e_cond_op : char 156 | { 157 | none = 0, 158 | lt = 1, // < 159 | le = 2, // <= 160 | eq = 3, // == 161 | ge = 4, // >= 162 | gt = 5, // > 163 | ne = 6, // != 164 | }; 165 | 166 | inline const char* e_cond_op_2_str(e_cond_op op) 167 | { 168 | switch ((int)op) 169 | { 170 | case (int)e_cond_op::lt: 171 | return "<"; 172 | 173 | case (int)e_cond_op::le: 174 | return "<="; 175 | 176 | case (int)e_cond_op::eq: 177 | return "=="; 178 | 179 | case (int)e_cond_op::ge: 180 | return ">="; 181 | 182 | case (int)e_cond_op::gt: 183 | return ">"; 184 | 185 | case (int)e_cond_op::ne: 186 | return "!="; 187 | } 188 | return ""; 189 | } 190 | 191 | struct Debugger 192 | { 193 | struct IndexHintInfo 194 | { 195 | string indexName; 196 | size_t nLeftMatched = 0; // 最左匹配 197 | size_t nMatchedCond = 0; // 匹配到的条件数量 198 | bool bOrderByMatched = false; // orderby是否最左前缀匹配 199 | size_t nForkLevels = 0; // 数据层数 200 | size_t nScanIndexKeys = 0; // 遍历过的索引key 201 | size_t nScanRows = 0; // 遍历过的数据行 202 | size_t nResultRows = 0; // 返回的结果行数 203 | 204 | string toString(bool matched = false) const 205 | { 206 | string s; 207 | s += P("[%s]", indexName.c_str()); 208 | ++tlsTab(); 209 | s += P("left-matched: %d", (int)nLeftMatched); 210 | s += P("matched-cond: %d", (int)nMatchedCond); 211 | s += P("order-by-matched: %d", (int)bOrderByMatched); 212 | if (matched) { 213 | s += P("fork-levels: %d", (int)nForkLevels); 214 | s += P("scan-index-k: %d", (int)nScanIndexKeys); 215 | s += P("scan-rows: %d", (int)nScanRows); 216 | s += P("result-rows: %d", (int)nResultRows); 217 | } 218 | --tlsTab(); 219 | return s; 220 | } 221 | }; 222 | 223 | // 追踪单次索引使用 224 | struct OnceIndexQueryTrace 225 | { 226 | string cond; 227 | std::vector tryMatchIndexes; 228 | IndexHintInfo matched; 229 | 230 | string toString() const 231 | { 232 | string s; 233 | s += P("cond: %s", cond.c_str()); 234 | s += P("tryMatchIndexes:"); 235 | ++tlsTab(); 236 | for (size_t i = 0; i < tryMatchIndexes.size(); ++i) { 237 | s += P("[%d]", (int)i); 238 | ++tlsTab(); 239 | s += tryMatchIndexes[i].toString(false); 240 | --tlsTab(); 241 | } 242 | --tlsTab(); 243 | s += P("matched-index:"); 244 | ++tlsTab(); 245 | s += matched.toString(true); 246 | --tlsTab(); 247 | return s; 248 | } 249 | }; 250 | 251 | struct QueryTrace 252 | { 253 | string or_cond; 254 | string optimizedCond; 255 | std::list querys; 256 | int64_t beginTimestampUS = 0; 257 | int64_t endTimestampUS = 0; 258 | 259 | static int64_t us() 260 | { 261 | return std::chrono::duration_cast( 262 | std::chrono::system_clock::now().time_since_epoch()).count(); 263 | } 264 | 265 | // 遍历过的索引key 266 | size_t getScanIndexKeys() const { 267 | size_t n = 0; 268 | for (auto const& q : querys) 269 | n += q.matched.nScanIndexKeys; 270 | return n; 271 | } 272 | 273 | // 遍历过的数据行 274 | size_t getScanRows() const { 275 | size_t n = 0; 276 | for (auto const& q : querys) 277 | n += q.matched.nScanRows; 278 | return n; 279 | } 280 | 281 | 282 | // 返回的结果行数 283 | size_t getResultRows() const { 284 | size_t n = 0; 285 | for (auto const& q : querys) 286 | n += q.matched.nResultRows; 287 | return n; 288 | } 289 | 290 | // 查询耗时(us) 291 | int64_t queryCostUS() const 292 | { 293 | return (endTimestampUS ? endTimestampUS : us()) - beginTimestampUS; 294 | } 295 | 296 | OnceIndexQueryTrace* newQuery() 297 | { 298 | querys.push_back(OnceIndexQueryTrace{}); 299 | return &querys.back(); 300 | } 301 | 302 | string toString() const 303 | { 304 | string s; 305 | s += P("time: %ld us", queryCostUS()); 306 | s += P("cond: %s", or_cond.c_str()); 307 | s += P("optimized-cond: %s", optimizedCond.c_str()); 308 | s += P("scan-index-k: %d", (int)getScanIndexKeys()); 309 | s += P("scan-rows: %d", (int)getScanRows()); 310 | s += P("result-rows: %d", (int)getResultRows()); 311 | s += P("querys (size=%d):", (int)querys.size()); 312 | ++tlsTab(); 313 | int i = 0; 314 | for (auto & q : querys) { 315 | s += P("[%d]", (int)i++); 316 | ++tlsTab(); 317 | s += q.toString(); 318 | --tlsTab(); 319 | } 320 | --tlsTab(); 321 | return s; 322 | } 323 | }; 324 | 325 | QueryTrace queryTrace; 326 | 327 | string toString() 328 | { 329 | string s; 330 | s += P("[Debugger]"); 331 | ++tlsTab(); 332 | s += P("query-trace:"); 333 | ++tlsTab(); 334 | s += queryTrace.toString(); 335 | --tlsTab(); 336 | --tlsTab(); 337 | return s; 338 | } 339 | }; 340 | 341 | // 多层结构 342 | // 最上面一层当做logs使用, 可修改, 底层不可变更 343 | template < 344 | typename K, 345 | typename V, 346 | template class Table 347 | > 348 | struct ShadowBase 349 | { 350 | public: 351 | struct VStorage : public V 352 | { 353 | VStorage() = default; 354 | VStorage(VStorage const&) = default; 355 | VStorage(VStorage &&) = default; 356 | VStorage& operator=(VStorage const&) = default; 357 | VStorage& operator=(VStorage &&) = default; 358 | 359 | VStorage(V const& v) : V(v) {} 360 | VStorage(V && v) : V(std::move(v)) {} 361 | VStorage& operator=(V const& v) { 362 | static_cast(*this) = v; 363 | return *this; 364 | } 365 | VStorage& operator=(V && v) { 366 | static_cast(*this) = std::move(v); 367 | return *this; 368 | } 369 | 370 | string toString() const 371 | { 372 | string s; 373 | s = fmt("%s{%s}", deleted ? "(D)" : "", 374 | adl::to_string(static_cast(*this)).c_str()); 375 | return s; 376 | } 377 | 378 | bool deleted = false; 379 | }; 380 | 381 | typedef Table table_t; 382 | typedef shared_ptr table_ptr; 383 | 384 | ShadowBase() = default; 385 | ShadowBase(ShadowBase const&) = delete; 386 | ShadowBase& operator=(ShadowBase const&) = delete; 387 | 388 | virtual table_ptr makeTable() = 0; 389 | virtual void forUniqueTable(table_t & table) {} // 初始化成单层table(不清理数据) 390 | virtual void forBaseTable(table_t & table) {} // 初始化成底层table, 上层还有logs(不清理数据) 391 | virtual void forLogsTable(table_t & table) {} // 初始化成顶层table(不清理数据) 392 | virtual void mergeTable(table_t & from, table_t & to) = 0; // 覆盖合并 393 | virtual string tableToString(table_t & table, bool simple) const = 0; 394 | 395 | void reset() { 396 | levels_.clear(); 397 | levels_.push_back(makeTable()); 398 | forUniqueTable(*logs()); 399 | } 400 | 401 | void fork(ShadowBase & other) 402 | { 403 | if (logs()->empty() && level() == 1) { 404 | // 空的 405 | other.reset(); 406 | return ; 407 | } 408 | 409 | other.levels_.clear(); 410 | 411 | if (logs()->empty()) { 412 | // 没有logs, 顶层不需要共享 413 | for (size_t i = 0; i + 1 < level(); ++i) { 414 | other.levels_.push_back(levels_[i]); 415 | } 416 | } else { 417 | // 所有层共享 418 | for (auto & ht : levels_) { 419 | other.levels_.push_back(ht); 420 | } 421 | 422 | addLevel(); 423 | } 424 | 425 | other.addLevel(); 426 | } 427 | 428 | void merge() 429 | { 430 | size_t mergeStartLevel = 0; 431 | table_ptr htp; 432 | table_ptr & base = levels_.front(); 433 | if (base.unique()) { 434 | // 没有别的共享了, 可以直接merge到最底层 435 | mergeStartLevel = 1; 436 | htp = base; 437 | } else { 438 | // 最底层有共享的, 需要创建一个新的hashtable 439 | htp = makeTable(); 440 | } 441 | 442 | forUniqueTable(*htp); 443 | 444 | // 逐层合并 445 | for (size_t i = mergeStartLevel; i < levels_.size(); ++i) 446 | { 447 | table_t & ht = *levels_[i]; 448 | mergeTable(ht, *htp); 449 | } 450 | 451 | levels_.clear(); 452 | levels_.push_back(htp); 453 | } 454 | 455 | size_t level() const { 456 | return levels_.size(); 457 | } 458 | 459 | string toString(bool simple = false) const 460 | { 461 | string s; 462 | s += P("[Shadow-Table] (level=%d)", (int)level()); 463 | ++tlsTab(); 464 | for (size_t i = 0; i < level(); ++i) { 465 | table_ptr const& tp = table(i); 466 | s += P("[%d](ref=%d)(0x%p) %s", 467 | (int)i, (int)tp.use_count(), (void*)tp.get(), 468 | (i == 0) ? "-> top" : ""); 469 | ++tlsTab(); 470 | s += tableToString(*tp, simple); 471 | --tlsTab(); 472 | } 473 | --tlsTab(); 474 | return s; 475 | } 476 | 477 | protected: 478 | inline table_ptr & logs() 479 | { 480 | return levels_.back(); 481 | } 482 | 483 | inline table_ptr & table(size_t lv) 484 | { 485 | assert(lv < levels_.size()); 486 | return levels_[levels_.size() - lv - 1]; 487 | } 488 | 489 | inline table_ptr const& table(size_t lv) const 490 | { 491 | assert(lv < levels_.size()); 492 | return levels_[levels_.size() - lv - 1]; 493 | } 494 | 495 | void addLevel() 496 | { 497 | // 冻结上一层的rehash 498 | if (level() == 1) { 499 | forBaseTable(*logs()); 500 | } 501 | 502 | // 新增一层, bucket_count和上一层保持一致, 并冻结rehash 503 | table_ptr ht = makeTable(); 504 | forLogsTable(*ht); 505 | levels_.push_back(ht); 506 | } 507 | 508 | protected: 509 | vector levels_; 510 | }; 511 | 512 | template 513 | using hashtable = std::unordered_map; 514 | 515 | template 516 | struct ShadowHashTable : public ShadowBase 517 | { 518 | public: 519 | typedef ShadowHashTable this_t; 520 | typedef ShadowBase base_t; 521 | typedef typename base_t::VStorage VStorage; 522 | typedef typename base_t::table_t table_t; 523 | typedef typename base_t::table_ptr table_ptr; 524 | 525 | using base_t::reset; 526 | using base_t::logs; 527 | using base_t::level; 528 | using base_t::table; 529 | 530 | struct ref_t 531 | { 532 | K key; 533 | size_t bucket_count = 0; 534 | size_t bucket_index = 0; 535 | 536 | ref_t() = default; 537 | explicit ref_t(K const& k) : key(k) {} 538 | 539 | friend bool operator<(ref_t const& lhs, ref_t const& rhs) { 540 | return lhs.key < rhs.key; 541 | } 542 | 543 | friend bool operator==(ref_t const& lhs, ref_t const& rhs) { 544 | return lhs.key == rhs.key; 545 | } 546 | 547 | string toString() const 548 | { 549 | string s; 550 | s += fmt("{key=%s, bc=%d, bi=%d}", 551 | adl::to_string(key).c_str(), 552 | (int)bucket_count, (int)bucket_index); 553 | return s; 554 | } 555 | }; 556 | 557 | struct iterator 558 | { 559 | public: 560 | iterator() = default; 561 | explicit iterator(this_t * hashtable) : ht(hashtable) {} 562 | 563 | iterator(iterator &&) = default; 564 | iterator& operator=(iterator &&) = default; 565 | 566 | iterator(iterator const&) = delete; 567 | iterator& operator=(iterator const&) = delete; 568 | 569 | bool isEnd() const { return bEnd; } 570 | explicit operator bool() const { return !isEnd(); } 571 | 572 | typename table_t::value_type & operator*() { return *it; } 573 | typename table_t::value_type const& operator*() const { return *it; } 574 | typename table_t::value_type * operator->() { return &*it; } 575 | typename table_t::value_type const* operator->() const { return &*it; } 576 | 577 | ref_t & getRef() { return ref; } 578 | ref_t const& getRef() const { return ref; } 579 | 580 | iterator & operator++() 581 | { 582 | next(); 583 | return *this; 584 | } 585 | 586 | void setBegin() 587 | { 588 | bucket = 0; 589 | level = 0; 590 | bucketUnique.clear(); 591 | bEnd = false; 592 | it = ht->table(level)->begin(bucket); 593 | if (!begin()) { 594 | setEnd(); 595 | } 596 | } 597 | 598 | void setEnd() { bEnd = true; } 599 | 600 | friend bool operator==(iterator const& lhs, iterator const& rhs) 601 | { 602 | if (lhs.isEnd() && rhs.isEnd()) return true; 603 | 604 | if (lhs.ht != rhs.ht) return false; 605 | return lhs.bucket == rhs.bucket && lhs.level == rhs.level 606 | && lhs.it == rhs.it; 607 | } 608 | 609 | friend bool operator!=(iterator const& lhs, iterator const& rhs) 610 | { 611 | return !(lhs == rhs); 612 | } 613 | 614 | private: 615 | void next() 616 | { 617 | ++it; 618 | if (!begin()) { 619 | setEnd(); 620 | } 621 | } 622 | 623 | bool begin() 624 | { 625 | while (bucket < ht->logs()->bucket_count()) { 626 | while (level < ht->level()) { 627 | if (ht->table(level)->end(bucket) == it) { 628 | ++level; 629 | if (level == ht->level()) 630 | break; 631 | 632 | it = ht->table(level)->begin(bucket); 633 | continue; 634 | } 635 | 636 | if (!bucketUnique.insert(it->first).second) { 637 | ++it; 638 | continue; 639 | } 640 | 641 | if (it->second.deleted) { 642 | ++it; 643 | continue; 644 | } 645 | 646 | ref.key = it->first; 647 | ref.bucket_count = ht->logs()->bucket_count(); 648 | ref.bucket_index = bucket; 649 | return true; 650 | } 651 | 652 | level = 0; 653 | bucketUnique.clear(); 654 | ++bucket; 655 | if (bucket == ht->logs()->bucket_count()) 656 | break; 657 | 658 | it = ht->table(level)->begin(bucket); 659 | } 660 | 661 | return false; 662 | } 663 | 664 | private: 665 | this_t * ht; 666 | size_t bucket = 0; 667 | size_t level = 0; 668 | typename table_t::local_iterator it; 669 | std::set bucketUnique; 670 | bool bEnd = true; 671 | ref_t ref; 672 | }; 673 | 674 | bool foreach(std::function pred) 675 | { 676 | iterator it(this); 677 | it.setBegin(); 678 | for (; it; ++it) { 679 | if (!pred(it->first, it.getRef(), static_cast(&it->second))) 680 | return false; 681 | } 682 | 683 | return true; 684 | } 685 | 686 | explicit ShadowHashTable(size_t minBucketCount = 1024) 687 | : minBucketCount_(minBucketCount) 688 | { 689 | reset(); 690 | } 691 | 692 | iterator begin() 693 | { 694 | iterator it(this); 695 | it.setBegin(); 696 | return std::move(it); 697 | } 698 | 699 | void fork(ShadowHashTable & other) 700 | { 701 | other.minBucketCount_ = minBucketCount_; 702 | base_t::fork(other); 703 | } 704 | 705 | void set(K const& key, V const& value) 706 | { 707 | VStorage & vs = (*logs())[key]; 708 | static_cast(vs) = value; 709 | vs.deleted = false; 710 | } 711 | 712 | void set(K const& key, V && value) 713 | { 714 | VStorage & vs = (*logs())[key]; 715 | static_cast(vs) = std::move(value); 716 | vs.deleted = false; 717 | } 718 | 719 | void del(K const& key) 720 | { 721 | if (level() == 1) { 722 | logs()->erase(key); 723 | return ; 724 | } 725 | 726 | // 查看logs以下的层中是否有key 727 | ref_t keyRef(key); 728 | ref_t out; 729 | for (size_t i = 1; i < level(); ++i) { 730 | table_ptr & htp = table(i); 731 | std::pair res = get(htp, keyRef, out); 732 | if (res.first) { 733 | // 底层有, logs追加一个deleted记录 734 | VStorage & vs = (*logs())[key]; 735 | vs.deleted = true; 736 | return ; 737 | } 738 | 739 | if (res.second) { // 顶层已删除, 底层无需再看 740 | break; 741 | } 742 | } 743 | 744 | // 底层没有or已删除, logs里直接删除即可 745 | logs()->erase(key); 746 | } 747 | 748 | V* get(K const& key) 749 | { 750 | ref_t out; 751 | return get(key, out); 752 | } 753 | 754 | V* get(K const& key, ref_t & out) 755 | { 756 | ref_t keyRef; 757 | keyRef.key = key; 758 | return get(keyRef, out); 759 | } 760 | 761 | V* get(ref_t const& keyRef, ref_t & out) 762 | { 763 | // 自顶向下, 逐层查找 764 | for (size_t i = 0; i < level(); ++i) { 765 | table_ptr & htp = table(i); 766 | std::pair res = get(htp, keyRef, out); 767 | if (res.first) { 768 | return res.first; 769 | } 770 | 771 | if (res.second) { // 顶层已删除, 底层无需再看 772 | return nullptr; 773 | } 774 | } 775 | 776 | return nullptr; 777 | } 778 | 779 | static float& default_load_factor() 780 | { 781 | static float load_factor = 0.5; 782 | return load_factor; 783 | } 784 | 785 | protected: 786 | virtual table_ptr makeTable() override 787 | { 788 | return std::make_shared(); 789 | } 790 | 791 | virtual void forUniqueTable(table_t & table) override 792 | { 793 | // 打开rehash 794 | table.max_load_factor(default_load_factor()); 795 | table.reserve(minBucketCount_ * default_load_factor()); 796 | } 797 | 798 | virtual void forBaseTable(table_t & table) override 799 | { 800 | // 冻结rehash 801 | table.max_load_factor(std::numeric_limits::max()); 802 | } 803 | 804 | virtual void forLogsTable(table_t & table) override 805 | { 806 | // 和上一层保持相同bucket_count & 冻结rehash 807 | table.max_load_factor(1); 808 | table.reserve(logs()->bucket_count()); 809 | table.max_load_factor(std::numeric_limits::max()); 810 | } 811 | 812 | virtual void mergeTable(table_t & from, table_t & to) override 813 | { 814 | for (auto const& kv : from) 815 | { 816 | if (kv.second.deleted) { 817 | to.erase(kv.first); 818 | } else { 819 | to[kv.first] = kv.second; 820 | } 821 | } 822 | } 823 | 824 | virtual string tableToString(table_t & table, bool simple) const override 825 | { 826 | string s; 827 | s += P("Hashtable[size=%d bucket=%d load_factor=%.3f max_load_factor=%.3f]", 828 | (int)table.size(), (int)table.bucket_count(), 829 | (float)table.load_factor(), (float)table.max_load_factor()); 830 | if (simple) 831 | return s; 832 | 833 | ++tlsTab(); 834 | for (size_t i = 0; i < table.bucket_count(); ++i) 835 | { 836 | for (auto it = table.begin(i); it != table.end(i); ++it) 837 | { 838 | s += P("[%d] K=%s V=%s", (int)i, 839 | adl::to_string(it->first).c_str(), 840 | adl::to_string(it->second).c_str()); 841 | } 842 | } 843 | --tlsTab(); 844 | return s; 845 | } 846 | 847 | // @return: 848 | std::pair get(table_ptr & htp, ref_t const& keyRef, ref_t & out) 849 | { 850 | size_t bucket_index = keyRef.bucket_index; 851 | if (htp->bucket_count() != keyRef.bucket_count) { 852 | // bucket index失效, 重新hash 853 | bucket_index = htp->bucket(keyRef.key); 854 | } 855 | 856 | for (auto it = htp->begin(bucket_index); 857 | it != htp->end(bucket_index); ++it) 858 | { 859 | if (it->first != keyRef.key) 860 | continue; 861 | 862 | VStorage & vs = it->second; 863 | if (vs.deleted) { 864 | return {nullptr, true}; 865 | } 866 | 867 | out.key = it->first; 868 | out.bucket_count = htp->bucket_count(); 869 | out.bucket_index = bucket_index; 870 | return {static_cast(&vs), false}; 871 | } 872 | 873 | return {nullptr, false}; 874 | } 875 | 876 | private: 877 | size_t minBucketCount_; 878 | }; 879 | 880 | // 备选结构:rbtree 881 | // 优点: 遍历有序, fork快 882 | // 缺点: 查询慢, fork多层以后更慢 883 | //template 884 | //using rbtree = std::map; 885 | // 886 | //template 887 | //struct ShadowRBTree : public ShadowBase; 888 | 889 | // 递归map-set结构 890 | // map->map->map->...->set 891 | template 892 | struct RecursiveMapSet 893 | { 894 | public: 895 | typedef RecursiveMapSet this_t; 896 | typedef std::set set_t; 897 | typedef typename set_t::iterator set_iterator; 898 | typedef void* map_value_type; 899 | typedef std::map map_t; 900 | typedef typename map_t::iterator map_iterator; 901 | typedef std::vector keys_t; 902 | typedef std::pair cond_t; 903 | typedef std::vector condition_vec_t; 904 | typedef std::vector condition_vec2_t; 905 | 906 | typedef std::pair map_iterator_range_t; 907 | typedef std::vector map_iterator_range_list_t; 908 | 909 | struct map_range_iterator 910 | { 911 | public: 912 | map_iterator & get() { return it; } 913 | map_iterator const& get() const { return it; } 914 | 915 | map_range_iterator& operator++() 916 | { 917 | next(); 918 | return *this; 919 | } 920 | 921 | bool next() 922 | { 923 | if (isEnd()) return false; 924 | ++it; 925 | if (it == range[idx].second) { 926 | if (idx == range.size() - 1) { 927 | return false; 928 | } 929 | 930 | ++idx; 931 | it = range[idx].first; 932 | } 933 | return true; 934 | } 935 | 936 | bool isEnd() const { 937 | if (range.empty()) return true; 938 | return idx == range.size() - 1 && it == range[idx].second; 939 | } 940 | 941 | explicit operator bool() const { return !isEnd(); } 942 | 943 | public: 944 | map_iterator it; 945 | map_iterator_range_list_t range; 946 | size_t idx = 0; 947 | }; 948 | 949 | struct iterator 950 | { 951 | public: 952 | iterator() = default; 953 | explicit iterator(this_t * t) : self(t) {} 954 | 955 | keys_t keys() 956 | { 957 | keys_t ks; 958 | ks.reserve(mapItrs.size()); 959 | for (map_iterator & it : mapItrs) 960 | ks.push_back(it->first); 961 | return ks; 962 | } 963 | 964 | V const& get() { return *setItr; } 965 | 966 | iterator & operator++() 967 | { 968 | if (isEnd()) 969 | return *this; 970 | 971 | assert(mapItrs.size() == self->depth_ + 1); 972 | set_t * s = reinterpret_cast(mapItrs.back()->second); 973 | ++setItr; 974 | if (s->end() != setItr) 975 | return *this; 976 | 977 | // 逐层回退, ++ 978 | while (!mapItrs.empty()) { 979 | map_iterator & it = mapItrs.back(); 980 | map_t* parent = (mapItrs.size() == 1) ? root() 981 | : reinterpret_cast(mapItrs[mapItrs.size() - 2]->second); 982 | map_iterator last = parent->end(); 983 | 984 | ++it; 985 | for (; it != last; ++it) { 986 | if (begin(reinterpret_cast(it->second), mapItrs.size())) 987 | // next完成 988 | return *this; 989 | } 990 | 991 | // 本层遍历到底了, 需要回退 992 | mapItrs.pop_back(); 993 | } 994 | 995 | setEnd(); 996 | return *this; 997 | } 998 | 999 | iterator operator++(int) 1000 | { 1001 | iterator it = *this; 1002 | ++(*this); 1003 | return it; 1004 | } 1005 | 1006 | explicit operator bool() const { return !isEnd(); } 1007 | 1008 | bool isEnd() const 1009 | { 1010 | return !self || mapItrs.empty(); 1011 | } 1012 | 1013 | friend bool operator==(iterator const& lhs, iterator const& rhs) 1014 | { 1015 | if (lhs.isEnd() && rhs.isEnd()) return true; 1016 | 1017 | if (lhs.self != rhs.self) return false; 1018 | if (lhs.mapItrs.size() != rhs.mapItrs.size()) return false; 1019 | for (size_t i = 0; i < lhs.mapItrs.size(); ++i) 1020 | if (lhs.mapItrs[i] != rhs.mapItrs[i]) 1021 | return false; 1022 | 1023 | return lhs.setItr == rhs.setItr; 1024 | } 1025 | 1026 | friend bool operator!=(iterator const& lhs, iterator const& rhs) 1027 | { 1028 | return !(lhs == rhs); 1029 | } 1030 | 1031 | virtual void setBegin() 1032 | { 1033 | if (!self) return ; 1034 | 1035 | mapItrs.clear(); 1036 | mapItrs.reserve(self->depth_ + 1); 1037 | 1038 | if (!begin(root(), 0)) { 1039 | setEnd(); 1040 | } 1041 | } 1042 | 1043 | virtual void setEnd() 1044 | { 1045 | if (!self) return ; 1046 | 1047 | mapItrs.clear(); 1048 | setItr = set_iterator{}; 1049 | } 1050 | 1051 | protected: 1052 | inline map_t* root() const { return &self->m_; } 1053 | 1054 | private: 1055 | virtual bool begin(map_t* m, size_t depth) 1056 | { 1057 | if (depth < self->depth_ + 1) { 1058 | // 补全未命中索引 1059 | map_iterator it = m->begin(); 1060 | if (m->end() == it) 1061 | return false; 1062 | 1063 | mapItrs.push_back(it); 1064 | 1065 | map_t * next = reinterpret_cast(it->second); 1066 | if (begin(next, depth + 1)) 1067 | return true; 1068 | 1069 | mapItrs.pop_back(); 1070 | return false; 1071 | } 1072 | 1073 | // set 1074 | // if (depth == self->depth_ + 1) 1075 | set_t * s = reinterpret_cast(m); 1076 | setItr = s->begin(); 1077 | return true; 1078 | } 1079 | 1080 | private: 1081 | friend struct RecursiveMapSet; 1082 | this_t * self = nullptr; 1083 | vector mapItrs; 1084 | set_iterator setItr; 1085 | }; 1086 | 1087 | struct condition_iterator 1088 | { 1089 | public: 1090 | condition_iterator() = default; 1091 | explicit condition_iterator(this_t * t, 1092 | std::shared_ptr cv2, 1093 | Debugger::IndexHintInfo* pIndexHintInfo) 1094 | : self(t), indexHintInfo(pIndexHintInfo), condv2(cv2) {} 1095 | 1096 | condition_iterator(condition_iterator && other) = default; 1097 | condition_iterator& operator=(condition_iterator && other) = default; 1098 | 1099 | // condition_iterator(condition_iterator && other) { 1100 | // *this = std::move(other); 1101 | // } 1102 | // condition_iterator& operator=(condition_iterator && other) { 1103 | // self = other.self; 1104 | // setItr = other.setItr; 1105 | // condv2 = other.condv2; 1106 | // std::swap(mapRangeItrs, other.mapRangeItrs); 1107 | // other.setEnd(); 1108 | // return *this; 1109 | // } 1110 | 1111 | condition_iterator(condition_iterator const&) = delete; 1112 | condition_iterator& operator=(condition_iterator const&) = delete; 1113 | 1114 | V & get() { return const_cast(*setItr); } 1115 | V const& get() const { return *setItr; } 1116 | 1117 | condition_iterator & operator++() 1118 | { 1119 | next(); 1120 | return *this; 1121 | } 1122 | 1123 | condition_iterator operator++(int) 1124 | { 1125 | condition_iterator it = *this; 1126 | ++(*this); 1127 | return it; 1128 | } 1129 | 1130 | explicit operator bool() const { return !isEnd(); } 1131 | 1132 | bool isEnd() const 1133 | { 1134 | return !self || mapRangeItrs.empty(); 1135 | } 1136 | 1137 | friend bool operator==(condition_iterator const& lhs, condition_iterator const& rhs) 1138 | { 1139 | if (lhs.isEnd() && rhs.isEnd()) return true; 1140 | 1141 | if (lhs.self != rhs.self) return false; 1142 | if (lhs.mapRangeItrs.size() != rhs.mapRangeItrs.size()) return false; 1143 | for (size_t i = 0; i < lhs.mapRangeItrs.size(); ++i) 1144 | if (lhs.mapRangeItrs[i].get() != rhs.mapRangeItrs[i].get()) 1145 | return false; 1146 | 1147 | return lhs.setItr == rhs.setItr; 1148 | } 1149 | 1150 | friend bool operator!=(condition_iterator const& lhs, condition_iterator const& rhs) 1151 | { 1152 | return !(lhs == rhs); 1153 | } 1154 | 1155 | virtual void setBegin() 1156 | { 1157 | if (!self) return ; 1158 | 1159 | mapRangeItrs.clear(); 1160 | mapRangeItrs.reserve(self->depth_ + 1); 1161 | 1162 | if (!begin(root(), 0)) { 1163 | setEnd(); 1164 | } 1165 | } 1166 | 1167 | virtual void setEnd() 1168 | { 1169 | if (!self) return ; 1170 | 1171 | mapRangeItrs.clear(); 1172 | setItr = set_iterator{}; 1173 | } 1174 | 1175 | protected: 1176 | map_t* root() const { return &self->m_; } 1177 | 1178 | private: 1179 | // range交集 1180 | void crossRange(map_t* m, 1181 | map_iterator_range_list_t & rangeList, 1182 | map_iterator_range_t const& range) 1183 | { 1184 | auto lt = [m](map_iterator const& lhs, map_iterator const& rhs){ 1185 | if (lhs == rhs) return false; 1186 | if (lhs == m->end()) return false; 1187 | if (rhs == m->end()) return true; 1188 | return lhs->first < rhs->first; 1189 | }; 1190 | auto le = [m](map_iterator const& lhs, map_iterator const& rhs){ 1191 | if (lhs == rhs) return false; 1192 | if (lhs == m->end()) return false; 1193 | if (rhs == m->end()) return true; 1194 | return !(rhs->first < lhs->first); 1195 | }; 1196 | 1197 | auto pos = rangeList.begin(); 1198 | while (pos != rangeList.end()) { 1199 | map_iterator_range_t & r = *pos; 1200 | if (le(r.second, range.first) || le(range.second, r.first)) { 1201 | // 超出范围 1202 | pos = rangeList.erase(pos); 1203 | continue; 1204 | } 1205 | 1206 | // 有交集 1207 | if (lt(r.first, range.first)) { 1208 | r.first = range.first; 1209 | } 1210 | 1211 | if (lt(range.second, r.second)) { 1212 | r.second = range.second; 1213 | } 1214 | 1215 | if (r.first == r.second) { // 切空了 1216 | pos = rangeList.erase(pos); 1217 | continue; 1218 | } 1219 | 1220 | ++pos; 1221 | } 1222 | } 1223 | 1224 | // ne(!=) 1225 | void expectRange(map_t* m, 1226 | map_iterator_range_list_t & rangeList, 1227 | map_iterator const& neIter) 1228 | { 1229 | auto lt = [m](map_iterator const& lhs, map_iterator const& rhs){ 1230 | if (lhs == rhs) return false; 1231 | if (lhs == m->end()) return false; 1232 | if (rhs == m->end()) return true; 1233 | return lhs->first < rhs->first; 1234 | }; 1235 | auto cmp = [m, lt](map_iterator_range_t const& lhs, map_iterator const& rhs) { 1236 | return lt(lhs.first, rhs); 1237 | }; 1238 | 1239 | // [left, right]两边剪枝 1240 | typename map_iterator_range_list_t::iterator pos = std::lower_bound( 1241 | rangeList.begin(), rangeList.end(), neIter, cmp); 1242 | if (pos->first == neIter) { // 命中在首端 1243 | ++pos->first; 1244 | return ; 1245 | } 1246 | 1247 | if (pos == rangeList.begin()) // pos前面没有了 1248 | return ; 1249 | 1250 | --pos; 1251 | assert(lt(pos->first, neIter)); 1252 | if (lt(neIter, pos->second)) { // 命中在中间, 需要切分  1253 | map_iterator_range_t right{neIter, pos->second}; 1254 | ++right.first; 1255 | 1256 | pos->second = neIter; 1257 | ++pos; 1258 | rangeList.insert(pos, right); 1259 | } 1260 | } 1261 | 1262 | // @cond: {A > 1 && A < 3 && A != 2} 1263 | // (-, +) + {A > 1} = (1, +) 1264 | map_iterator_range_list_t makeRanges(map_t* m, condition_vec_t const& cond) 1265 | { 1266 | map_iterator_range_list_t rangeList{{m->begin(), m->end()}}; 1267 | 1268 | for (auto const& kv : cond) 1269 | { 1270 | K const& key = kv.first; 1271 | e_cond_op op = kv.second; 1272 | map_iterator_range_t range; 1273 | 1274 | switch ((int)op) 1275 | { 1276 | case (int)e_cond_op::lt: 1277 | range.first = m->begin(); 1278 | range.second = m->lower_bound(key); 1279 | crossRange(m, rangeList, range); 1280 | break; 1281 | 1282 | case (int)e_cond_op::le: 1283 | range.first = m->begin(); 1284 | range.second = m->upper_bound(key); 1285 | crossRange(m, rangeList, range); 1286 | break; 1287 | 1288 | case (int)e_cond_op::eq: 1289 | range.second = range.first = m->find(key); 1290 | if (range.first != m->end()) { 1291 | ++range.second; 1292 | } 1293 | crossRange(m, rangeList, range); 1294 | break; 1295 | 1296 | case (int)e_cond_op::ge: 1297 | range.first = m->lower_bound(key); 1298 | range.second = m->end(); 1299 | crossRange(m, rangeList, range); 1300 | break; 1301 | 1302 | case (int)e_cond_op::gt: 1303 | range.first = m->upper_bound(key); 1304 | range.second = m->end(); 1305 | crossRange(m, rangeList, range); 1306 | break; 1307 | 1308 | case (int)e_cond_op::ne: 1309 | // lt && gt 1310 | auto it = m->find(key); 1311 | if (it != m->end()) { 1312 | expectRange(m, rangeList, it); 1313 | } 1314 | break; 1315 | } 1316 | 1317 | if (rangeList.empty()) { 1318 | // 交集已为空 1319 | break; 1320 | } 1321 | } 1322 | 1323 | return rangeList; 1324 | } 1325 | 1326 | virtual bool begin(map_t* m, size_t depth) 1327 | { 1328 | if (depth < condv2->size()) { 1329 | // 命中索引 1330 | condition_vec_t const& cond = (*condv2)[depth]; 1331 | 1332 | map_iterator_range_list_t range = makeRanges(m, cond); 1333 | 1334 | if (range.empty()) { 1335 | // 条件未命中索引, 回退上级索引向后迭代 1336 | return false; 1337 | } 1338 | 1339 | mapRangeItrs.resize(mapRangeItrs.size() + 1); 1340 | map_range_iterator & mrIter = mapRangeItrs.back(); 1341 | mrIter.range.swap(range); 1342 | mrIter.it = mrIter.range[0].first; 1343 | 1344 | for (; mrIter; ++mrIter) { 1345 | // 最后一次递归中, next其实是一个set_t* 1346 | onScan(); 1347 | map_t * next = reinterpret_cast(mrIter.get()->second); 1348 | if (begin(next, depth + 1)) { 1349 | return true; 1350 | } 1351 | } 1352 | 1353 | mapRangeItrs.pop_back(); 1354 | return false; 1355 | } else if (depth < self->depth_ + 1) { 1356 | // 补全未命中索引 1357 | assert(!m->empty()); 1358 | 1359 | mapRangeItrs.resize(mapRangeItrs.size() + 1); 1360 | map_range_iterator & mrIter = mapRangeItrs.back(); 1361 | mrIter.range.push_back({m->begin(), m->end()}); 1362 | mrIter.it = mrIter.range[0].first; 1363 | onScan(); 1364 | 1365 | map_t * next = reinterpret_cast(mrIter.get()->second); 1366 | if (begin(next, depth + 1)) 1367 | return true; 1368 | 1369 | mapRangeItrs.pop_back(); 1370 | return false; 1371 | } 1372 | 1373 | // set 1374 | // if (depth == self->depth_ + 1) 1375 | set_t * s = reinterpret_cast(m); 1376 | setItr = s->begin(); 1377 | return true; 1378 | } 1379 | 1380 | void next() 1381 | { 1382 | if (isEnd()) 1383 | return ; 1384 | 1385 | assert(mapRangeItrs.size() == self->depth_ + 1); 1386 | set_t * s = reinterpret_cast(mapRangeItrs.back().get()->second); 1387 | ++setItr; 1388 | if (s->end() != setItr) { 1389 | return ; 1390 | } 1391 | 1392 | // 逐层回退, ++ 1393 | while (!mapRangeItrs.empty()) { 1394 | map_range_iterator & mrIter = mapRangeItrs.back(); 1395 | 1396 | assert(!!mrIter); 1397 | ++mrIter; 1398 | for (; mrIter; ++mrIter) { 1399 | onScan(); 1400 | if (begin(reinterpret_cast(mrIter.get()->second), mapRangeItrs.size())) 1401 | return ; 1402 | } 1403 | 1404 | // 本层遍历到底了, 需要回退 1405 | mapRangeItrs.pop_back(); 1406 | continue; 1407 | } 1408 | 1409 | setEnd(); 1410 | } 1411 | 1412 | inline void onScan() 1413 | { 1414 | if (indexHintInfo) { 1415 | ++indexHintInfo->nScanIndexKeys; 1416 | } 1417 | } 1418 | 1419 | private: 1420 | this_t * self = nullptr; 1421 | Debugger::IndexHintInfo* indexHintInfo = nullptr; 1422 | set_iterator setItr; 1423 | std::shared_ptr condv2; // size <= self->depth_ + 1 1424 | std::vector mapRangeItrs; 1425 | }; 1426 | 1427 | explicit RecursiveMapSet(size_t depth) : depth_(depth) {} 1428 | ~RecursiveMapSet() { clear(); } 1429 | 1430 | iterator begin() 1431 | { 1432 | if (m_.empty()) { 1433 | return end(); 1434 | } 1435 | 1436 | iterator it(this); 1437 | it.setBegin(); 1438 | return it; 1439 | } 1440 | 1441 | iterator end() 1442 | { 1443 | iterator it(this); 1444 | it.setEnd(); 1445 | return it; 1446 | } 1447 | 1448 | void set(keys_t const& keys, V const& value) 1449 | { 1450 | assert(keys.size() == depth_ + 1); 1451 | if (keys.size() != depth_ + 1) { 1452 | throw std::logic_error("RecursiveMapSet::set keys size not equal depth_+1"); 1453 | } 1454 | 1455 | map_iterator mapItr; 1456 | void* pos = &m_; 1457 | for (size_t i = 0; i < depth_ + 1; ++i) { 1458 | map_t * m = reinterpret_cast(pos); 1459 | mapItr = m->find(keys[i]); 1460 | if (m->end() == mapItr) { 1461 | void * p = (i == depth_) ? (void*)new set_t : (void*)new map_t; 1462 | mapItr = m->insert({keys[i], p}).first; 1463 | } 1464 | pos = reinterpret_cast(mapItr->second); 1465 | } 1466 | 1467 | // set 1468 | set_t* s = reinterpret_cast(pos); 1469 | if (s->erase(value)) { 1470 | --size_; 1471 | } 1472 | s->insert(value); 1473 | ++size_; 1474 | } 1475 | 1476 | bool erase(keys_t const& keys, V const& value) 1477 | { 1478 | iterator it = find(keys, value); 1479 | if (end() == it) { 1480 | return false; 1481 | } 1482 | 1483 | erase(it); 1484 | return true; 1485 | } 1486 | 1487 | iterator find(keys_t const& keys, V const& value) 1488 | { 1489 | assert(keys.size() == depth_ + 1); 1490 | if (keys.size() != depth_ + 1) { 1491 | throw std::logic_error("RecursiveMapSet::find keys size not equal depth_+1"); 1492 | } 1493 | 1494 | iterator it(this); 1495 | void* pos = &m_; 1496 | for (size_t i = 0; i < depth_ + 1; ++i) { 1497 | map_t * m = reinterpret_cast(pos); 1498 | map_iterator mapItr = m->find(keys[i]); 1499 | if (m->end() == mapItr) { 1500 | return end(); 1501 | } 1502 | it.mapItrs.push_back(mapItr); 1503 | pos = reinterpret_cast(mapItr->second); 1504 | } 1505 | 1506 | // set 1507 | set_t* s = reinterpret_cast(pos); 1508 | it.setItr = s->find(value); 1509 | if (s->end() == it.setItr) { 1510 | return end(); 1511 | } 1512 | 1513 | return it; 1514 | } 1515 | 1516 | void erase(iterator it) 1517 | { 1518 | assert(it.self == this); 1519 | assert(it.mapItrs.size() == depth_ + 1); 1520 | if (it.mapItrs.size() != depth_ + 1) { 1521 | throw std::logic_error("RecursiveMapSet::erase it.mapItrs size not equal depth_+1"); 1522 | } 1523 | 1524 | for (size_t i = 0; i < depth_ + 1; ++i) { 1525 | size_t ri = depth_ - i; 1526 | map_iterator & mapItr = it.mapItrs[ri]; 1527 | map_t * parent = (ri == 0) ? &m_ : 1528 | reinterpret_cast(it.mapItrs[ri - 1]->second); 1529 | 1530 | if (i == 0) { // 最后一个 1531 | set_t* s = reinterpret_cast(mapItr->second); 1532 | s->erase(it.setItr); 1533 | --size_; 1534 | if (s->empty()) { 1535 | delete s; 1536 | parent->erase(mapItr); 1537 | } 1538 | } else { 1539 | map_t* m = reinterpret_cast(mapItr->second); 1540 | if (m->empty()) { 1541 | delete m; 1542 | parent->erase(mapItr); 1543 | } 1544 | } 1545 | } 1546 | } 1547 | 1548 | bool empty() const 1549 | { 1550 | return m_.empty(); 1551 | } 1552 | 1553 | size_t size() const 1554 | { 1555 | return size_; 1556 | } 1557 | 1558 | void clear() 1559 | { 1560 | clear(&m_, 0); 1561 | } 1562 | 1563 | condition_iterator select(std::shared_ptr condv2, 1564 | Debugger::IndexHintInfo* indexHintInfo) 1565 | { 1566 | assert(condv2->size() <= depth_ + 1); 1567 | if (condv2->size() > depth_ + 1) { 1568 | throw std::logic_error("RecursiveMapSet::begin too many conditions"); 1569 | } 1570 | 1571 | condition_iterator it(this, condv2, indexHintInfo); 1572 | it.setBegin(); 1573 | return std::move(it); 1574 | } 1575 | 1576 | string toString(bool simple = false) const 1577 | { 1578 | string s; 1579 | s += P("RecursiveMapSet [depth=%d keys.depth=%d size=%d]", 1580 | (int)depth_, (int)depth_ + 1, (int)size()); 1581 | if (simple) 1582 | return s; 1583 | 1584 | ++tlsTab(); 1585 | s += toString(&m_, 0); 1586 | --tlsTab(); 1587 | return s; 1588 | } 1589 | 1590 | string toString(map_t const* m, size_t depth) const 1591 | { 1592 | string s; 1593 | if (depth < depth_ + 1) { 1594 | // map 1595 | // s += P("map[%d] [size=%d]", (int)depth, (int)m->size()); 1596 | ++tlsTab(); 1597 | int i = 0; 1598 | for (auto it = m->begin(); it != m->end(); ++it, ++i) 1599 | { 1600 | s += P("[%d] -> K[%d]=%s", i, (int)depth, adl::to_string(it->first).c_str()); 1601 | ++tlsTab(); 1602 | map_t* next = reinterpret_cast(it->second); 1603 | s += toString(next, depth + 1); 1604 | --tlsTab(); 1605 | } 1606 | --tlsTab(); 1607 | return s; 1608 | } 1609 | 1610 | // set 1611 | set_t const* sp = reinterpret_cast(m); 1612 | // s += P("set[%d] [size=%d]", (int)depth, (int)sp->size()); 1613 | ++tlsTab(); 1614 | int i = 0; 1615 | for (auto it = sp->begin(); it != sp->end(); ++it, ++i) 1616 | { 1617 | s += P("[%d] V=%s", i, adl::to_string(*it).c_str()); 1618 | } 1619 | --tlsTab(); 1620 | return s; 1621 | } 1622 | 1623 | private: 1624 | void clear(map_t* m, size_t depth) 1625 | { 1626 | if (depth == depth_) { 1627 | for (auto & kv : *m) { 1628 | set_t * s = reinterpret_cast(kv.second); 1629 | delete s; 1630 | } 1631 | m->clear(); 1632 | return ; 1633 | } 1634 | 1635 | for (auto & kv : *m) 1636 | { 1637 | map_t * next = reinterpret_cast(kv.second); 1638 | clear(next, depth + 1); 1639 | delete next; 1640 | } 1641 | m->clear(); 1642 | } 1643 | 1644 | private: 1645 | size_t size_ = 0; 1646 | size_t depth_ = 0; 1647 | map_t m_; 1648 | }; 1649 | 1650 | // 索引结构 1651 | template 1652 | struct ShadowRecursiveMapSet : public ShadowBase 1653 | { 1654 | public: 1655 | typedef ShadowBase base_t; 1656 | typedef typename base_t::VStorage VStorage; 1657 | typedef typename base_t::table_t table_t; 1658 | typedef typename base_t::table_ptr table_ptr; 1659 | typedef typename base_t::table_t::cond_t cond_t; 1660 | typedef typename base_t::table_t::condition_vec_t condition_vec_t; 1661 | typedef typename base_t::table_t::condition_vec2_t condition_vec2_t; 1662 | typedef typename base_t::table_t::keys_t keys_t; 1663 | 1664 | typedef std::pair range_t; 1666 | 1667 | using base_t::reset; 1668 | using base_t::logs; 1669 | using base_t::level; 1670 | using base_t::table; 1671 | 1672 | struct ordered_range_t 1673 | { 1674 | size_t level; 1675 | range_t range; 1676 | 1677 | ordered_range_t() = default; 1678 | 1679 | VStorage & vs() { return range.first.get(); } 1680 | VStorage const& vs() const { return range.first.get(); } 1681 | 1682 | friend bool operator<(ordered_range_t const& lhs, ordered_range_t const& rhs) 1683 | { 1684 | // VStorage < VStorage 1685 | if (lhs.vs() < rhs.vs()) 1686 | return true; 1687 | 1688 | if (rhs.vs() < lhs.vs()) 1689 | return false; 1690 | 1691 | // 让底层的先弹出, 最后一个弹出的即为有效数据 1692 | return rhs.level < lhs.level; 1693 | } 1694 | }; 1695 | 1696 | struct ordered_range_ref 1697 | { 1698 | std::shared_ptr> ranges; 1699 | size_t index; 1700 | 1701 | ordered_range_t & ort() { return (*ranges)[index]; } 1702 | ordered_range_t const& ort() const { return (*ranges)[index]; } 1703 | 1704 | friend bool operator<(ordered_range_ref const& lhs, ordered_range_ref const& rhs) 1705 | { 1706 | return lhs.ort() < rhs.ort(); 1707 | } 1708 | }; 1709 | 1710 | struct condition_iterator 1711 | { 1712 | public: 1713 | condition_iterator() = default; 1714 | condition_iterator(condition_iterator &&) = default; 1715 | condition_iterator& operator=(condition_iterator &&) = default; 1716 | 1717 | condition_iterator(condition_iterator const&) = delete; 1718 | condition_iterator& operator=(condition_iterator const&) = delete; 1719 | 1720 | // V == ref_t 1721 | V& operator*() { return *value; } 1722 | V* operator->() { return value; } 1723 | 1724 | condition_iterator & operator++() 1725 | { 1726 | next(); 1727 | return *this; 1728 | } 1729 | 1730 | explicit operator bool() const { return !isEnd(); } 1731 | 1732 | bool isEnd() const 1733 | { 1734 | return q.empty() && !value; 1735 | } 1736 | 1737 | void init() 1738 | { 1739 | for (size_t i = 0; i < ranges->size(); ++i) 1740 | { 1741 | ordered_range_ref orr; 1742 | orr.ranges = ranges; 1743 | orr.index = i; 1744 | q.push(orr); 1745 | } 1746 | 1747 | // 定位到第一个有效数据 1748 | next(); 1749 | } 1750 | 1751 | void next() 1752 | { 1753 | bool succ = false; 1754 | while (!q.empty() && !succ) { 1755 | ordered_range_ref orr = q.top(); 1756 | q.pop(); 1757 | 1758 | ordered_range_t & ort = orr.ort(); 1759 | 1760 | VStorage & vs = ort.vs(); 1761 | 1762 | if (!posV || *posV == static_cast(vs)) { 1763 | // 相同或首次遍历, 覆盖 1764 | posV = &vs; 1765 | deleted = vs.deleted; 1766 | } else { 1767 | // 新数据, 保存旧数据 1768 | if (!deleted) { // 数据有效, 完成一步next 1769 | value = posV; 1770 | succ = true; 1771 | } 1772 | 1773 | // 数据无效, 继续探索 1774 | posV = &vs; 1775 | deleted = vs.deleted; 1776 | } 1777 | 1778 | // 步进, 重新放回堆 1779 | ++ort.range.first; 1780 | if (ort.range.first != ort.range.second) { 1781 | q.push(orr); 1782 | } 1783 | } 1784 | 1785 | if (succ) { 1786 | return ; 1787 | } 1788 | 1789 | // 队列排空, 还未发现新数据, posV即为新数据 1790 | value = !deleted ? posV : nullptr; 1791 | posV = nullptr; 1792 | deleted = false; 1793 | } 1794 | 1795 | public: 1796 | std::shared_ptr> ranges; 1797 | std::priority_queue q; 1798 | V *value = nullptr; 1799 | V *posV = nullptr; 1800 | bool deleted = false; 1801 | }; 1802 | 1803 | explicit ShadowRecursiveMapSet(size_t depth) : depth_(depth) 1804 | { 1805 | reset(); 1806 | } 1807 | 1808 | void fork(ShadowRecursiveMapSet & other) 1809 | { 1810 | assert(other.depth_ == depth_); 1811 | base_t::fork(static_cast(other)); 1812 | } 1813 | 1814 | void set(keys_t const& keys, V const& value) 1815 | { 1816 | VStorage vs{value}; 1817 | logs()->set(keys, vs); 1818 | } 1819 | 1820 | void del(keys_t const& keys, V const& value) 1821 | { 1822 | if (level() == 1) { 1823 | logs()->erase(keys, value); 1824 | return ; 1825 | } 1826 | 1827 | // 查看logs以下的层中是否有key 1828 | for (size_t i = 1; i < level(); ++i) { 1829 | table_ptr & htp = table(i); 1830 | auto it = htp->find(keys, value); 1831 | if (it == htp->end()) 1832 | continue; 1833 | 1834 | VStorage const& vs = it.get(); 1835 | if (vs.deleted) { // 上层已删除, 底层无需再看 1836 | break; 1837 | } 1838 | 1839 | // 底层有, logs追加一个deleted记录 1840 | VStorage dvs{value}; 1841 | dvs.deleted = true; 1842 | logs()->set(keys, dvs); 1843 | return ; 1844 | } 1845 | 1846 | // 底层没有or已删除, logs里直接删除即可 1847 | logs()->erase(keys, value); 1848 | } 1849 | 1850 | condition_iterator select(std::shared_ptr condv2, 1851 | Debugger::IndexHintInfo* indexHintInfo) 1852 | { 1853 | condition_iterator it; 1854 | it.ranges = std::make_shared>(); 1855 | 1856 | if (indexHintInfo) { 1857 | indexHintInfo->nForkLevels = level(); 1858 | } 1859 | 1860 | // 自顶向下, 逐层查找 1861 | for (size_t i = 0; i < level(); ++i) { 1862 | table_ptr & htp = table(i); 1863 | ordered_range_t ort; 1864 | ort.level = i; 1865 | ort.range.first = htp->select(condv2, indexHintInfo); 1866 | ort.range.second.setEnd(); 1867 | if (ort.range.first == ort.range.second) 1868 | continue; 1869 | 1870 | it.ranges->emplace_back(std::move(ort)); 1871 | } 1872 | 1873 | it.init(); 1874 | return std::move(it); 1875 | } 1876 | 1877 | protected: 1878 | virtual table_ptr makeTable() override 1879 | { 1880 | return std::make_shared(depth_); 1881 | } 1882 | 1883 | virtual void mergeTable(table_t & from, table_t & to) override // 覆盖合并 1884 | { 1885 | for (auto it = from.begin(); it != from.end(); ++it) 1886 | { 1887 | VStorage const& vs = it.get(); 1888 | if (vs.deleted) { 1889 | to.erase(it.keys(), vs); 1890 | } else { 1891 | to.set(it.keys(), vs); 1892 | } 1893 | } 1894 | } 1895 | 1896 | virtual string tableToString(table_t & table, bool simple) const override 1897 | { 1898 | string s; 1899 | s = table.toString(simple); 1900 | return s; 1901 | } 1902 | 1903 | private: 1904 | size_t depth_; 1905 | }; 1906 | 1907 | // 可以operator<的any 1908 | class LessAny 1909 | { 1910 | public: 1911 | enum class e_simple_types : char 1912 | { 1913 | e_unseted = 0, 1914 | e_any = 1, 1915 | e_signed_integer_64 = 2, 1916 | e_unsigned_integer_64 = 3, 1917 | e_string = 4, 1918 | e_max = 5, 1919 | }; 1920 | 1921 | struct min_t {}; 1922 | struct max_t {}; 1923 | 1924 | LessAny() : type_(e_simple_types::e_unseted) {} 1925 | explicit LessAny(min_t) : type_(e_simple_types::e_unseted) {} 1926 | explicit LessAny(max_t) : type_(e_simple_types::e_max) {} 1927 | 1928 | LessAny(LessAny const& other) { 1929 | *this = other; 1930 | } 1931 | 1932 | LessAny& operator=(LessAny const& other) { 1933 | if (this == &other) return *this; 1934 | 1935 | type_ = other.type_; 1936 | if (type_ == e_simple_types::e_any) { 1937 | u_.p = other.u_.p->clone(); 1938 | } else if (type_ == e_simple_types::e_string) { 1939 | str_ = other.str_; 1940 | } else { 1941 | u_ = other.u_; 1942 | } 1943 | return *this; 1944 | } 1945 | 1946 | LessAny(LessAny && other) { 1947 | *this = std::move(other); 1948 | } 1949 | 1950 | LessAny& operator=(LessAny && other) { 1951 | if (this == &other) return *this; 1952 | 1953 | type_ = other.type_; 1954 | if (type_ == e_simple_types::e_any) { 1955 | std::swap(u_.p, other.u_.p); 1956 | } else if (type_ == e_simple_types::e_string) { 1957 | swap(str_, other.str_); 1958 | } else { 1959 | std::swap(u_, other.u_); 1960 | } 1961 | 1962 | other.type_ = e_simple_types::e_unseted; 1963 | return *this; 1964 | } 1965 | 1966 | ~LessAny() { 1967 | reset(); 1968 | } 1969 | 1970 | friend bool operator<(LessAny const& lhs, LessAny const& rhs) 1971 | { 1972 | if (lhs.type_ != rhs.type_) 1973 | return lhs.type_ < rhs.type_; 1974 | 1975 | switch ((char)lhs.type_) { 1976 | case (char)e_simple_types::e_unseted: 1977 | return &lhs < &rhs; 1978 | 1979 | case (char)e_simple_types::e_any: 1980 | return lhs.u_.p->less(rhs.u_.p); 1981 | 1982 | case (char)e_simple_types::e_signed_integer_64: 1983 | return lhs.u_.i64 < rhs.u_.i64; 1984 | 1985 | case (char)e_simple_types::e_unsigned_integer_64: 1986 | return lhs.u_.u64 < rhs.u_.u64; 1987 | 1988 | case (char)e_simple_types::e_string: 1989 | default: 1990 | return lhs.str_ < rhs.str_; 1991 | } 1992 | } 1993 | 1994 | string toString() const 1995 | { 1996 | switch ((char)type_) { 1997 | case (char)e_simple_types::e_unseted: 1998 | return "e_unseted"; 1999 | 2000 | case (char)e_simple_types::e_any: 2001 | return u_.p->toString(); 2002 | 2003 | case (char)e_simple_types::e_signed_integer_64: 2004 | return std::to_string(u_.i64); 2005 | 2006 | case (char)e_simple_types::e_unsigned_integer_64: 2007 | return std::to_string(u_.u64); 2008 | 2009 | case (char)e_simple_types::e_string: 2010 | return "\"" + str_ + "\""; 2011 | 2012 | case (char)e_simple_types::e_max: 2013 | return "e_max"; 2014 | } 2015 | 2016 | return "Unknown LessAny"; 2017 | } 2018 | 2019 | void reset() 2020 | { 2021 | if (type_ == e_simple_types::e_any) { 2022 | delete u_.p; 2023 | } 2024 | str_.clear(); 2025 | type_ = e_simple_types::e_unseted; 2026 | } 2027 | 2028 | template 2029 | void set(T const& t) 2030 | { 2031 | reset(); 2032 | setData(t, NULL); 2033 | } 2034 | 2035 | private: 2036 | template 2037 | typename std::enable_if::value, void>::type 2038 | setData(T i64, int*) 2039 | { 2040 | u_.i64 = i64; 2041 | type_ = e_simple_types::e_signed_integer_64; 2042 | } 2043 | 2044 | template 2045 | typename std::enable_if::value, void>::type 2046 | setData(T u64, int*) 2047 | { 2048 | u_.u64 = u64; 2049 | type_ = e_simple_types::e_unsigned_integer_64; 2050 | } 2051 | 2052 | template 2053 | typename std::enable_if::value, void>::type 2054 | setData(T str, int*) 2055 | { 2056 | str_ = str; 2057 | type_ = e_simple_types::e_string; 2058 | } 2059 | 2060 | template 2061 | void setData(T any_t, ...) 2062 | { 2063 | u_.p = new storage(any_t); 2064 | type_ = e_simple_types::e_any; 2065 | } 2066 | 2067 | private: 2068 | struct base_t 2069 | { 2070 | virtual ~base_t() {} 2071 | virtual bool less(base_t* other) const = 0; 2072 | virtual base_t* clone() const = 0; 2073 | virtual string toString() const = 0; 2074 | }; 2075 | 2076 | template 2077 | struct storage : public base_t 2078 | { 2079 | storage(T const& v) : value_(v) {} 2080 | 2081 | bool less(base_t* other) const override 2082 | { 2083 | storage* o = reinterpret_cast*>(other); 2084 | return value_ < o->value_; 2085 | } 2086 | 2087 | base_t* clone() const override 2088 | { 2089 | return new storage(value_); 2090 | } 2091 | 2092 | string toString() const override 2093 | { 2094 | return adl::to_string(value_); 2095 | } 2096 | 2097 | T value_; 2098 | }; 2099 | 2100 | private: 2101 | union { 2102 | int64_t i64; 2103 | uint64_t u64; 2104 | base_t* p; 2105 | } u_; 2106 | e_simple_types type_; 2107 | string str_; 2108 | }; 2109 | 2110 | // 存储只增不删、支持resetTop的小顶堆 2111 | template 2112 | struct Heap 2113 | { 2114 | public: 2115 | T& top() 2116 | { 2117 | return storage_[heap_[0]]; 2118 | } 2119 | 2120 | bool empty() const 2121 | { 2122 | return heap_.empty(); 2123 | } 2124 | 2125 | size_t size() const 2126 | { 2127 | return heap_.size(); 2128 | } 2129 | 2130 | template 2131 | void push(Args && ... args) 2132 | { 2133 | storage_.emplace_back(std::forward(args)...); 2134 | heap_.push_back(storage_.size() - 1); 2135 | std::push_heap(heap_.begin(), heap_.end(), [this](size_t lhs, size_t rhs){ return greater(lhs, rhs); }); 2136 | } 2137 | 2138 | void pop() 2139 | { 2140 | std::pop_heap(heap_.begin(), heap_.end(), [this](size_t lhs, size_t rhs){ return greater(lhs, rhs); }); 2141 | heap_.resize(heap_.size() - 1); 2142 | } 2143 | 2144 | void resetTop() 2145 | { 2146 | std::pop_heap(heap_.begin(), heap_.end(), [this](size_t lhs, size_t rhs){ return greater(lhs, rhs); }); 2147 | std::push_heap(heap_.begin(), heap_.end(), [this](size_t lhs, size_t rhs){ return greater(lhs, rhs); }); 2148 | } 2149 | 2150 | private: 2151 | bool greater(size_t lhs, size_t rhs) 2152 | { 2153 | return storage_[rhs] < storage_[lhs]; 2154 | } 2155 | 2156 | private: 2157 | std::vector storage_; 2158 | std::vector heap_; 2159 | }; 2160 | 2161 | // 单列:值 2162 | typedef LessAny column_value_t; 2163 | 2164 | // 单列:元信息 2165 | template 2166 | struct column_t 2167 | { 2168 | static const size_t kInvalidOffset = -1; 2169 | 2170 | typedef std::function GetFn; 2171 | typedef std::function GetterHandler; 2172 | typedef std::function AssignFn; 2173 | 2174 | column_t() = default; 2175 | column_t(column_t const&) = default; 2176 | column_t(column_t &&) = default; 2177 | column_t& operator=(column_t const&) = default; 2178 | column_t& operator=(column_t &&) = default; 2179 | 2180 | template 2181 | column_t(FieldType V::* memptr) 2182 | { 2183 | offset = reinterpret_cast(&(((V*)0) ->* memptr)); 2184 | getF = [memptr](V const& v) { 2185 | LessAny la; 2186 | la.set(v.*memptr); 2187 | return la; 2188 | }; 2189 | assignF = [memptr](V const& from, V & to) { 2190 | to.*memptr = from.*memptr; 2191 | }; 2192 | } 2193 | 2194 | template 2195 | column_t(FieldType VBase::* memptr) 2196 | : column_t(static_cast(memptr)) 2197 | { 2198 | } 2199 | 2200 | template 2201 | column_t(column_t const& other) 2202 | { 2203 | static_assert(std::is_base_of::value, ""); 2204 | 2205 | offset = other.offset + offsetVBase(); 2206 | getF = [other](V const& v) { 2207 | return other.getF(static_cast(v)); 2208 | }; 2209 | assignF = [other](V const& from, V & to) { 2210 | other.assignF(static_cast(from), static_cast(to)); 2211 | }; 2212 | } 2213 | 2214 | bool get(V const& value, GetterHandler const& handler) const 2215 | { 2216 | if (!getF) 2217 | return false; 2218 | 2219 | return handler(getF(value)); 2220 | } 2221 | 2222 | bool assign(V const& from, V& to) const 2223 | { 2224 | if (!assignF) 2225 | return false; 2226 | 2227 | assignF(from, to); 2228 | return true; 2229 | } 2230 | 2231 | template 2232 | static size_t offsetVBase() 2233 | { 2234 | return (size_t)static_cast((V*)0x1) - 1; 2235 | } 2236 | 2237 | bool isValid() const { 2238 | return offset != kInvalidOffset && getF && assignF; 2239 | } 2240 | 2241 | friend bool operator<(column_t const& lhs, column_t const& rhs) { 2242 | return lhs.offset < rhs.offset; 2243 | } 2244 | 2245 | friend bool operator==(column_t const& lhs, column_t const& rhs) { 2246 | return lhs.offset == rhs.offset; 2247 | } 2248 | 2249 | friend bool operator!=(column_t const& lhs, column_t const& rhs) { 2250 | return !(lhs.offset == rhs.offset); 2251 | } 2252 | 2253 | string toString() const 2254 | { 2255 | string name = adl::field_to_string(offset); 2256 | return name.empty() ? fmt("offset=%d", (int)offset) : fmt("&%s", name.c_str()); 2257 | } 2258 | 2259 | public: 2260 | size_t offset = kInvalidOffset; 2261 | GetFn getF; 2262 | AssignFn assignF; 2263 | }; 2264 | 2265 | enum class column_category : uint8_t { 2266 | native, 2267 | function, 2268 | native_one_of, 2269 | function_one_of 2270 | }; 2271 | 2272 | // 虚拟列:元信息 2273 | template 2274 | struct virtual_column_t : public column_t 2275 | { 2276 | typedef column_t base_t; 2277 | 2278 | typedef typename base_t::GetterHandler GetterHandler; 2279 | typedef std::function ForeachGetterFn; 2280 | 2281 | virtual_column_t() = default; 2282 | 2283 | virtual_column_t(column_t const& base) : column_t(base), category(column_category::native) {} 2284 | virtual_column_t(column_t && base) : column_t(std::move(base)), category(column_category::native) {} 2285 | 2286 | template 2287 | virtual_column_t(FieldType V::* memptr) : column_t(memptr), category(column_category::native) {} 2288 | 2289 | template 2290 | virtual_column_t(FieldType VBase::* memptr) : column_t(memptr), category(column_category::native) {} 2291 | 2292 | template 2293 | virtual_column_t(virtual_column_t const& ct) : column_t(ct), category(ct.category) {} 2294 | 2295 | template 2296 | virtual_column_t(column_t const& ct) : column_t(ct), category(column_category::native) {} 2297 | 2298 | bool get(V const& value, GetterHandler const& handler) const 2299 | { 2300 | if (column_category::native == category || column_category::function == category) 2301 | return base_t::get(value, handler); 2302 | 2303 | return foreachGetter(value, handler); 2304 | } 2305 | 2306 | template 2307 | static virtual_column_t make(std::function const& fn, 2308 | string const& name = "") 2309 | { 2310 | virtual_column_t vct; 2311 | vct.category = column_category::function; 2312 | vct.id.reset(new int(0xf)); 2313 | vct.getF = [fn](V const& v) { 2314 | LessAny la; 2315 | la.set(fn(v)); 2316 | return la; 2317 | }; 2318 | vct.name = name; 2319 | return vct; 2320 | } 2321 | 2322 | static virtual_column_t makeOneOf(ForeachGetterFn const& foreachG, 2323 | string const& name = "") 2324 | { 2325 | virtual_column_t vct; 2326 | vct.category = column_category::function_one_of; 2327 | vct.id.reset(new int(0xf)); 2328 | vct.foreachGetter = foreachG; 2329 | vct.name = name; 2330 | return vct; 2331 | } 2332 | 2333 | template 2334 | static virtual_column_t makeOneOf(FieldType V::* memptr) 2335 | { 2336 | virtual_column_t vct(memptr); 2337 | vct.category = column_category::native_one_of; 2338 | vct.foreachGetter = [memptr](V const& v, GetterHandler const& handler) -> bool { 2339 | for (auto & val : v.*memptr) { 2340 | LessAny la; 2341 | la.set(val); 2342 | if (!handler(la)) 2343 | return false; 2344 | } 2345 | return true; 2346 | }; 2347 | return vct; 2348 | } 2349 | 2350 | template 2351 | static virtual_column_t makeOneOf(FieldType VBase::* memptr) 2352 | { 2353 | static_assert(std::is_base_of::value, ""); 2354 | return makeOneOf(static_cast(memptr)); 2355 | } 2356 | 2357 | bool isValid() const { 2358 | return !!id || base_t::isValid(); 2359 | } 2360 | 2361 | bool isMatchedIndex() const { 2362 | return base_t::isValid(); 2363 | } 2364 | 2365 | friend bool operator<(virtual_column_t const& lhs, virtual_column_t const& rhs) { 2366 | if (lhs.offset != rhs.offset) 2367 | return lhs.offset < rhs.offset; 2368 | return lhs.id < rhs.id; 2369 | } 2370 | 2371 | friend bool operator==(virtual_column_t const& lhs, virtual_column_t const& rhs) { 2372 | return lhs.offset == rhs.offset && lhs.id == rhs.id; 2373 | } 2374 | 2375 | string toString() const 2376 | { 2377 | if (column_category::native == category) { 2378 | return base_t::toString(); 2379 | } else if (column_category::function == category || column_category::function_one_of == category) { 2380 | return name; 2381 | } else if (column_category::native_one_of == category) { 2382 | return "OneOf(" + base_t::toString() + ")"; 2383 | } 2384 | 2385 | return name; 2386 | } 2387 | 2388 | public: 2389 | column_category category; 2390 | ForeachGetterFn foreachGetter; 2391 | std::shared_ptr id; 2392 | string name; 2393 | }; 2394 | 2395 | // ------------------ 查询条件 2396 | // 查询条件(单个) 2397 | template 2398 | struct condition_t 2399 | { 2400 | virtual_column_t col_; 2401 | e_cond_op op_; 2402 | column_value_t colValue_; 2403 | 2404 | condition_t() = default; 2405 | condition_t(condition_t const&) = default; 2406 | condition_t(condition_t &&) = default; 2407 | condition_t& operator=(condition_t const&) = default; 2408 | condition_t& operator=(condition_t &&) = default; 2409 | 2410 | condition_t(virtual_column_t && col, e_cond_op op, column_value_t && value) 2411 | : col_(std::move(col)), op_(op), colValue_(std::move(value)) 2412 | { 2413 | } 2414 | 2415 | template 2416 | condition_t(condition_t const& cond) 2417 | : col_(cond.col_), op_(cond.op_), colValue_(cond.colValue_) 2418 | { 2419 | static_assert(std::is_base_of::value, ""); 2420 | } 2421 | 2422 | string toString() const 2423 | { 2424 | return fmt("Cond(%s) %s %s", 2425 | col_.toString().c_str(), e_cond_op_2_str(op_), 2426 | colValue_.toString().c_str()); 2427 | } 2428 | 2429 | friend bool operator<(condition_t const& lhs, condition_t const& rhs) { 2430 | return lhs.col_ < rhs.col_; 2431 | } 2432 | 2433 | condition_t operator!() 2434 | { 2435 | condition_t ct(*this); 2436 | switch ((int)ct.op_) { 2437 | case (int)e_cond_op::lt: 2438 | ct.op_ = e_cond_op::ge; 2439 | break; 2440 | 2441 | case (int)e_cond_op::le: 2442 | ct.op_ = e_cond_op::gt; 2443 | break; 2444 | 2445 | case (int)e_cond_op::eq: 2446 | ct.op_ = e_cond_op::ne; 2447 | break; 2448 | 2449 | case (int)e_cond_op::ge: 2450 | ct.op_ = e_cond_op::lt; 2451 | break; 2452 | 2453 | case (int)e_cond_op::gt: 2454 | ct.op_ = e_cond_op::le; 2455 | break; 2456 | 2457 | case (int)e_cond_op::ne: 2458 | ct.op_ = e_cond_op::eq; 2459 | break; 2460 | } 2461 | 2462 | return ct; 2463 | } 2464 | 2465 | bool check(V const& value) 2466 | { 2467 | bool succ = false; 2468 | col_.get(value, [&, this](column_value_t const& colValue) -> bool { 2469 | if (check(colValue)) { 2470 | succ = true; 2471 | return false; 2472 | } 2473 | 2474 | return true; 2475 | }); 2476 | return succ; 2477 | } 2478 | 2479 | bool check(column_value_t const& colValue) 2480 | { 2481 | // 处理多结果索引时,按照oneOf的方式check, 有任意一个符合条件即可 2482 | // todo: 优化成指针形式的getter 2483 | switch ((int)op_) { 2484 | case (int)e_cond_op::lt: 2485 | return colValue < colValue_; 2486 | 2487 | case (int)e_cond_op::le: 2488 | return !(colValue_ < colValue); 2489 | 2490 | case (int)e_cond_op::eq: 2491 | return !(colValue_ < colValue) && !(colValue < colValue_); 2492 | 2493 | case (int)e_cond_op::ge: 2494 | return !(colValue < colValue_); 2495 | 2496 | case (int)e_cond_op::gt: 2497 | return colValue_ < colValue; 2498 | 2499 | default: 2500 | case (int)e_cond_op::ne: 2501 | return (colValue_ < colValue) || (colValue < colValue_); 2502 | } 2503 | } 2504 | }; 2505 | 2506 | // 语法糖辅助类 2507 | template 2508 | struct field_t 2509 | { 2510 | virtual_column_t col_; 2511 | 2512 | explicit field_t(FieldType V::* memptr) : col_(memptr) {} 2513 | 2514 | // 这里要copy一次, 以免VirtualColumn的内容被move改写 2515 | explicit field_t(virtual_column_t const& col) : col_(col) {} 2516 | 2517 | operator virtual_column_t() { return col_; } 2518 | 2519 | friend condition_t operator<(field_t field, FieldType value) 2520 | { 2521 | column_value_t la; 2522 | la.set(value); 2523 | return condition_t{std::move(field.col_), e_cond_op::lt, std::move(la)}; 2524 | } 2525 | 2526 | friend condition_t operator<=(field_t field, FieldType value) 2527 | { 2528 | column_value_t la; 2529 | la.set(value); 2530 | return condition_t{std::move(field.col_), e_cond_op::le, std::move(la)}; 2531 | } 2532 | 2533 | friend condition_t operator==(field_t field, FieldType value) 2534 | { 2535 | column_value_t la; 2536 | la.set(value); 2537 | return condition_t{std::move(field.col_), e_cond_op::eq, std::move(la)}; 2538 | } 2539 | 2540 | friend condition_t operator>=(field_t field, FieldType value) 2541 | { 2542 | column_value_t la; 2543 | la.set(value); 2544 | return condition_t{std::move(field.col_), e_cond_op::ge, std::move(la)}; 2545 | } 2546 | 2547 | friend condition_t operator>(field_t field, FieldType value) 2548 | { 2549 | column_value_t la; 2550 | la.set(value); 2551 | return condition_t{std::move(field.col_), e_cond_op::gt, std::move(la)}; 2552 | } 2553 | 2554 | friend condition_t operator!=(field_t field, FieldType value) 2555 | { 2556 | column_value_t la; 2557 | la.set(value); 2558 | return condition_t{std::move(field.col_), e_cond_op::ne, std::move(la)}; 2559 | } 2560 | }; 2561 | 2562 | // 一组&&查询条件 2563 | // {&A::a == 1 && &A::b < 2} 2564 | // {Cond(&A::a) == 1 && Cond(&A::b) < 2} 2565 | template 2566 | struct condition_and_group 2567 | { 2568 | vector> and_; 2569 | 2570 | condition_and_group() = default; 2571 | condition_and_group(condition_and_group const&) = default; 2572 | condition_and_group(condition_and_group &&) = default; 2573 | condition_and_group& operator=(condition_and_group const&) = default; 2574 | condition_and_group& operator=(condition_and_group &&) = default; 2575 | 2576 | condition_and_group(condition_t const& c1) 2577 | : and_{c1} {} 2578 | 2579 | condition_and_group(condition_t const& c1, condition_t const& c2) 2580 | : and_{c1, c2} {} 2581 | 2582 | template 2583 | condition_and_group(condition_t const& other) 2584 | : and_{other} 2585 | { 2586 | static_assert(std::is_base_of::value, ""); 2587 | } 2588 | 2589 | template 2590 | condition_and_group(condition_and_group const& other) 2591 | : and_(other.and_.begin(), other.and_.end()) 2592 | { 2593 | static_assert(std::is_base_of::value, ""); 2594 | } 2595 | 2596 | string toString() const 2597 | { 2598 | string s; 2599 | size_t i = 0; 2600 | for (condition_t const& cond : and_) { 2601 | ++i; 2602 | s += cond.toString(); 2603 | if (i != and_.size()) 2604 | s += " && "; 2605 | } 2606 | return s; 2607 | } 2608 | 2609 | bool check(V const& value) 2610 | { 2611 | for (condition_t & cond : and_) { 2612 | if (!cond.check(value)) 2613 | return false; 2614 | } 2615 | return true; 2616 | } 2617 | }; 2618 | 2619 | // && ||复合查询条件 2620 | // {&A::a == 1 && &A::b < 2 || &A::c > 3} 2621 | // {Cond(&A::a) == 1 && Cond(&A::b) < 2 || Cond(&A::c) > 3} 2622 | template 2623 | struct condition_or_group 2624 | { 2625 | vector> or_; 2626 | 2627 | condition_or_group() = default; 2628 | condition_or_group(condition_or_group const&) = default; 2629 | condition_or_group(condition_or_group &&) = default; 2630 | condition_or_group& operator=(condition_or_group const&) = default; 2631 | condition_or_group& operator=(condition_or_group &&) = default; 2632 | 2633 | condition_or_group(condition_t const& c1) 2634 | : or_{condition_and_group{c1}} {} 2635 | 2636 | condition_or_group(condition_and_group const& g1) 2637 | : or_{g1} {} 2638 | 2639 | condition_or_group(condition_and_group const& g1, condition_and_group const& g2) 2640 | : or_{g1, g2}{} 2641 | 2642 | template 2643 | condition_or_group(condition_t const& cond) 2644 | : or_{cond} 2645 | { 2646 | static_assert(std::is_base_of::value, ""); 2647 | } 2648 | 2649 | template 2650 | condition_or_group(condition_and_group const& and_group) 2651 | : or_{and_group} 2652 | { 2653 | static_assert(std::is_base_of::value, ""); 2654 | } 2655 | 2656 | template 2657 | condition_or_group(condition_or_group const& other) 2658 | : or_(other.or_.begin(), other.or_.end()) 2659 | { 2660 | static_assert(std::is_base_of::value, ""); 2661 | } 2662 | 2663 | string toString() const 2664 | { 2665 | string s; 2666 | size_t i = 0; 2667 | for (condition_and_group const& and_group : or_) { 2668 | ++i; 2669 | s += and_group.toString(); 2670 | if (i != or_.size()) 2671 | s += " || "; 2672 | } 2673 | return s; 2674 | } 2675 | }; 2676 | 2677 | namespace detail { 2678 | 2679 | template 2680 | struct drived_type_helper; 2681 | 2682 | template 2683 | struct drived_type_helper : public std::enable_if {}; 2684 | 2685 | template 2686 | struct drived_type_helper 2687 | { 2688 | typedef T1 type; 2689 | }; 2690 | 2691 | template 2692 | struct drived_type_helper 2693 | { 2694 | typedef T2 type; 2695 | }; 2696 | 2697 | template 2698 | struct one_of_type 2699 | { 2700 | typedef typename std::remove_cv< 2701 | typename std::remove_reference< 2702 | decltype(*std::begin(std::declval())) 2703 | >::type 2704 | >::type 2705 | type; 2706 | }; 2707 | 2708 | } // namespace detail 2709 | 2710 | template 2711 | struct drived_type 2712 | { 2713 | static const int value = std::is_base_of::value ? 2 2714 | : (std::is_base_of::value ? 1 : 0); 2715 | typedef typename detail::drived_type_helper::type type; 2716 | }; 2717 | 2718 | // -------- cond 2719 | // cond && cond 2720 | template 2721 | condition_and_group::type> operator&&(condition_t c1, condition_t c2) 2722 | { 2723 | typedef typename drived_type::type T; 2724 | return condition_and_group(c1, c2); 2725 | } 2726 | 2727 | // cond && and_group 2728 | template 2729 | condition_and_group::type> operator&&(condition_t c1, condition_and_group c2) 2730 | { 2731 | return c2 && c1; 2732 | } 2733 | 2734 | // cond && or_group 2735 | template 2736 | condition_and_group::type> operator&&(condition_t c1, condition_or_group c2) 2737 | { 2738 | return c2 && c1; 2739 | } 2740 | 2741 | // cond || cond 2742 | template 2743 | condition_or_group::type> operator||(condition_t c1, condition_t c2) 2744 | { 2745 | typedef typename drived_type::type T; 2746 | return condition_or_group(c1, c2); 2747 | } 2748 | 2749 | // cond || and_group 2750 | template 2751 | condition_or_group::type> operator||(condition_t c1, condition_and_group c2) 2752 | { 2753 | return c2 || c1; 2754 | } 2755 | 2756 | // cond || or_group 2757 | template 2758 | condition_or_group::type> operator||(condition_t c1, condition_or_group c2) 2759 | { 2760 | return c2 || c1; 2761 | } 2762 | 2763 | // -------- and_group 2764 | template 2765 | inline condition_or_group operator!(condition_and_group c1) 2766 | { 2767 | condition_or_group or_group; 2768 | for (condition_t & cond : c1.and_) { 2769 | or_group.or_.emplace_back(!cond); 2770 | } 2771 | return or_group; 2772 | } 2773 | 2774 | // and_group && cond 2775 | template 2776 | inline condition_and_group::type> operator&&(condition_and_group c1, condition_t c2) 2777 | { 2778 | typedef typename drived_type::type T; 2779 | condition_and_group c(c1); 2780 | c.and_.emplace_back(c2); 2781 | return c; 2782 | } 2783 | 2784 | // and_group && and_group 2785 | template 2786 | inline condition_and_group::type> operator&&(condition_and_group c1, condition_and_group c2) 2787 | { 2788 | typedef typename drived_type::type T; 2789 | condition_and_group c(c1); 2790 | 2791 | for (condition_t & ct : c2.and_) { 2792 | c.and_.emplace_back(ct); 2793 | } 2794 | c2.and_.clear(); 2795 | return c; 2796 | } 2797 | 2798 | // and_group && or_group 2799 | template 2800 | inline condition_or_group::type> operator&&(condition_and_group c1, condition_or_group c2) 2801 | { 2802 | return c2 && c1; 2803 | } 2804 | 2805 | // and_group || cond 2806 | template 2807 | inline condition_or_group::type> operator||(condition_and_group c1, condition_t c2) 2808 | { 2809 | typedef typename drived_type::type T; 2810 | return condition_or_group(c1, c2); 2811 | } 2812 | 2813 | // and_group || and_group 2814 | template 2815 | inline condition_or_group::type> operator||(condition_and_group c1, condition_and_group c2) 2816 | { 2817 | typedef typename drived_type::type T; 2818 | return condition_or_group(c1, c2); 2819 | } 2820 | 2821 | // and_group || or_group 2822 | template 2823 | inline condition_or_group::type> operator||(condition_and_group && c1, condition_or_group && c2) 2824 | { 2825 | return c2 || c1; 2826 | } 2827 | 2828 | // -------- or_group 2829 | template 2830 | inline condition_or_group operator!(condition_or_group const& c1) 2831 | { 2832 | condition_or_group or_group; 2833 | for (condition_and_group const& and_group : c1.or_) { 2834 | or_group = or_group && !and_group; 2835 | } 2836 | return or_group; 2837 | } 2838 | 2839 | // or_group && cond 2840 | template 2841 | inline condition_or_group::type> operator&&(condition_or_group c1, condition_t c2) 2842 | { 2843 | typedef typename drived_type::type T; 2844 | condition_or_group c(c1); 2845 | for (condition_and_group & ag : c.or_) { 2846 | ag = ag && c2; 2847 | } 2848 | return c; 2849 | } 2850 | 2851 | // or_group && and_group 2852 | template 2853 | inline condition_or_group::type> operator&&(condition_or_group c1, condition_and_group c2) 2854 | { 2855 | typedef typename drived_type::type T; 2856 | condition_or_group c(c1); 2857 | for (condition_and_group & ag : c.or_) { 2858 | ag = ag && c2; 2859 | } 2860 | return c; 2861 | } 2862 | 2863 | // or_group && or_group 2864 | // todo: test it! 2865 | template 2866 | inline condition_or_group::type> && operator&&(condition_or_group c1, condition_or_group c2) 2867 | { 2868 | typedef typename drived_type::type T; 2869 | 2870 | if (c2.or_.empty()) 2871 | return condition_or_group(c1); 2872 | 2873 | if (c1.or_.empty()) 2874 | return condition_or_group(c2); 2875 | 2876 | condition_or_group r; 2877 | for (condition_and_group & a1 : c1.or_) { 2878 | for (condition_and_group & a2 : c2.or_) { 2879 | r.or_.emplace_back(a1 && a2); 2880 | } 2881 | } 2882 | return r; 2883 | } 2884 | 2885 | // or_group || cond 2886 | template 2887 | inline condition_or_group::type> && operator||(condition_or_group c1, condition_t c2) 2888 | { 2889 | typedef typename drived_type::type T; 2890 | condition_or_group c(c1); 2891 | c.or_.emplace_back(c2); 2892 | return c; 2893 | } 2894 | 2895 | // or_group || and_group 2896 | template 2897 | inline condition_or_group::type> && operator||(condition_or_group c1, condition_and_group c2) 2898 | { 2899 | typedef typename drived_type::type T; 2900 | condition_or_group c(c1); 2901 | c.or_.emplace_back(c2); 2902 | return c; 2903 | } 2904 | 2905 | // or_group || or_group 2906 | template 2907 | inline condition_or_group::type> && operator||(condition_or_group c1, condition_or_group c2) 2908 | { 2909 | typedef typename drived_type::type T; 2910 | condition_or_group c(c1); 2911 | c.or_.emplace(c2.or_.begin(), c2.or_.end()); 2912 | return c; 2913 | } 2914 | // ------------------ 查询条件 2915 | 2916 | // ------------------ 索引 2917 | // 索引:元信息 2918 | template 2919 | struct index_meta_t 2920 | { 2921 | vector> cols; 2922 | 2923 | index_meta_t() = default; 2924 | index_meta_t(index_meta_t const&) = default; 2925 | index_meta_t(index_meta_t &&) = default; 2926 | index_meta_t& operator=(index_meta_t const&) = default; 2927 | index_meta_t& operator=(index_meta_t &&) = default; 2928 | 2929 | template 2930 | index_meta_t(index_meta_t const& other) 2931 | : cols(other.cols.begin(), other.cols.end()) 2932 | { 2933 | static_assert(std::is_base_of::value, ""); 2934 | } 2935 | 2936 | friend bool operator<(index_meta_t const& lhs, index_meta_t const& rhs) 2937 | { 2938 | for (size_t i = 0; i < (std::min)(lhs.cols.size(), rhs.cols.size()); ++i) 2939 | { 2940 | if (lhs.cols[i] < rhs.cols[i]) return true; 2941 | if (rhs.cols[i] < lhs.cols[i]) return false; 2942 | } 2943 | return lhs.cols.size() < rhs.cols.size(); 2944 | } 2945 | 2946 | friend bool operator==(index_meta_t const& lhs, index_meta_t const& rhs) 2947 | { 2948 | return !(lhs < rhs) && !(rhs < lhs); 2949 | } 2950 | 2951 | void push_back(virtual_column_t const& col) { 2952 | cols.push_back(col); 2953 | } 2954 | 2955 | template 2956 | void push_back(FieldType V::* memptr) { 2957 | cols.push_back(virtual_column_t(memptr)); 2958 | } 2959 | 2960 | template 2961 | void push_back(Arg1 && arg1, Args && ... args) 2962 | { 2963 | push_back(std::forward(arg1)); 2964 | push_back(std::forward(args)...); 2965 | } 2966 | 2967 | 2968 | string toString() const 2969 | { 2970 | string s("{"); 2971 | for (size_t i = 0; i < cols.size(); ++i) { 2972 | virtual_column_t const& col = cols[i]; 2973 | s += col.toString(); 2974 | if (i + 1 < cols.size()) 2975 | s += ", "; 2976 | } 2977 | s += "}"; 2978 | return s; 2979 | } 2980 | }; 2981 | 2982 | // 索引:值 2983 | struct index_value_t 2984 | { 2985 | vector values; 2986 | 2987 | static index_value_t min(size_t n) 2988 | { 2989 | index_value_t ivt; 2990 | ivt.values.resize(n, column_value_t(LessAny::min_t{})); 2991 | return ivt; 2992 | } 2993 | 2994 | static index_value_t max(size_t n) 2995 | { 2996 | index_value_t ivt; 2997 | ivt.values.resize(n, column_value_t(LessAny::max_t{})); 2998 | return ivt; 2999 | } 3000 | 3001 | friend bool operator<(index_value_t const& lhs, index_value_t const& rhs) 3002 | { 3003 | for (size_t i = 0; i < (std::min)(lhs.values.size(), rhs.values.size()); ++i) 3004 | { 3005 | if (lhs.values[i] < rhs.values[i]) return true; 3006 | if (rhs.values[i] < lhs.values[i]) return false; 3007 | } 3008 | return lhs.values.size() < rhs.values.size(); 3009 | } 3010 | 3011 | friend bool operator==(index_value_t const& lhs, index_value_t const& rhs) 3012 | { 3013 | return !(lhs < rhs) && !(rhs < lhs); 3014 | } 3015 | }; 3016 | 3017 | typedef std::vector multi_index_value_t; 3018 | 3019 | // ------------------ order by 3020 | // order by信息 3021 | template 3022 | using order_by_t = index_meta_t; 3023 | 3024 | using order_by_value_t = index_value_t; 3025 | 3026 | // order by语法糖 3027 | // ex: 3028 | // OrderBy(&A::a, &A::b); 3029 | template 3030 | inline void makeOrderBy(order_by_t & ob, FieldType V::* memptr) 3031 | { 3032 | ob.push_back(memptr); 3033 | } 3034 | 3035 | template 3036 | inline void makeOrderBy(order_by_t & ob, virtual_column_t const& vct) 3037 | { 3038 | ob.push_back(vct); 3039 | } 3040 | 3041 | template 3042 | inline void makeOrderBy(order_by_t & ob, FieldType V::* memptr, Args && ... args) 3043 | { 3044 | ob.push_back(memptr); 3045 | makeOrderBy(ob, std::forward(args)...); 3046 | } 3047 | 3048 | template 3049 | inline void makeOrderBy(order_by_t & ob, virtual_column_t const& vct, Args && ... args) 3050 | { 3051 | ob.push_back(vct); 3052 | makeOrderBy(ob, std::forward(args)...); 3053 | } 3054 | // ------------------ order by 3055 | 3056 | template 3057 | struct VirtualColumn : public virtual_column_t 3058 | { 3059 | typedef virtual_column_t base_t; 3060 | 3061 | VirtualColumn() = default; 3062 | 3063 | VirtualColumn(base_t const& vct) : base_t(vct) {} 3064 | VirtualColumn(base_t && vct) : base_t(std::move(vct)) {} 3065 | 3066 | template 3067 | VirtualColumn(T && vct) : base_t(std::forward(vct)) {} 3068 | 3069 | using base_t::base_t; 3070 | }; 3071 | 3072 | struct Config 3073 | { 3074 | size_t minBucketCount = 1024; 3075 | }; 3076 | 3077 | template 3078 | struct DB 3079 | { 3080 | public: 3081 | DB() : DB(Config{}) {} 3082 | explicit DB(Config const& conf) : data_(conf.minBucketCount) {} 3083 | 3084 | DB(const DB&) = delete; 3085 | DB& operator=(const DB&) = delete; 3086 | 3087 | // 存储引擎 3088 | typedef ShadowHashTable data_table_t; 3089 | typedef DB this_t; 3090 | typedef typename data_table_t::ref_t ref_t; 3091 | 3092 | // V* 3093 | class VRefPtr 3094 | { 3095 | public: 3096 | VRefPtr() = default; 3097 | VRefPtr(this_t* db, ref_t ref, V const* debugPtr = nullptr) : db_(db), ref_(ref), ptr_(debugPtr) {} 3098 | VRefPtr(std::shared_ptr holder) : db_(nullptr), holder_(holder), ptr_(holder.get()) {} 3099 | 3100 | V const& operator*() const 3101 | { 3102 | return *p(); 3103 | } 3104 | 3105 | V const* operator->() const 3106 | { 3107 | return p(); 3108 | } 3109 | 3110 | explicit operator bool() const 3111 | { 3112 | return !!p(); 3113 | } 3114 | 3115 | V const* get() const 3116 | { 3117 | return p(); 3118 | } 3119 | 3120 | string toString() const 3121 | { 3122 | if (db_) { 3123 | return fmt("VRefPtr{db:0x%p, ref:%s}", 3124 | (void*)db_, ref_.toString().c_str()); 3125 | } else { 3126 | return fmt("VRefPtr{holder:0x%p}", (void*)holder_.get()); 3127 | } 3128 | } 3129 | 3130 | private: 3131 | V* p() const 3132 | { 3133 | if (!db_) return holder_.get(); 3134 | 3135 | ref_t newRef; 3136 | V* ptr = db_->data_.get(ref_, newRef); 3137 | if (ptr) { 3138 | ref_ = newRef; 3139 | } 3140 | ptr_ = ptr; // 用于调试 3141 | return ptr; 3142 | } 3143 | 3144 | private: 3145 | this_t* db_ = nullptr; 3146 | mutable ref_t ref_; 3147 | std::shared_ptr holder_; 3148 | mutable V const* ptr_ = nullptr; // 最近一次查询结果, 方便调试用 3149 | }; 3150 | 3151 | struct IndexMatchInfo 3152 | { 3153 | size_t nLeftMatched = 0; // 最左匹配 3154 | size_t nMatchedCond = 0; // 匹配到的条件数量 3155 | bool bOrderByMatched = false; // 能否逐个取结果 (orderby未命中最左前缀时,需要取所有结果排序后才能返回第一个结果) 3156 | 3157 | friend bool operator<(IndexMatchInfo const& lhs, IndexMatchInfo const& rhs) 3158 | { 3159 | if (lhs.bOrderByMatched != rhs.bOrderByMatched) { 3160 | return lhs.bOrderByMatched < rhs.bOrderByMatched; 3161 | } 3162 | 3163 | if (lhs.nLeftMatched != rhs.nLeftMatched) { 3164 | return lhs.nLeftMatched < rhs.nLeftMatched; 3165 | } 3166 | 3167 | return lhs.nMatchedCond < rhs.nMatchedCond; 3168 | } 3169 | }; 3170 | 3171 | // 索引: 元信息+值+数据 3172 | struct index_t 3173 | { 3174 | typedef ShadowRecursiveMapSet map_t; 3175 | index_meta_t meta; 3176 | map_t data; 3177 | 3178 | index_t(index_meta_t const& mt) : meta(mt), data(mt.cols.size() - 1) { 3179 | assert(!mt.cols.empty()); 3180 | } 3181 | 3182 | struct condition_iterator 3183 | { 3184 | public: 3185 | condition_iterator() = default; 3186 | condition_iterator(condition_iterator &&) = default; 3187 | condition_iterator(condition_iterator const&) = delete; 3188 | condition_iterator& operator=(condition_iterator const&) = delete; 3189 | 3190 | ref_t & operator*() { return *it; } 3191 | ref_t * operator->() { return &*it; } 3192 | 3193 | V* getValue() 3194 | { 3195 | return value; 3196 | } 3197 | 3198 | condition_iterator & operator++() 3199 | { 3200 | next(); 3201 | return *this; 3202 | } 3203 | 3204 | bool isEnd() const 3205 | { 3206 | return it.isEnd(); 3207 | } 3208 | 3209 | explicit operator bool() const { return !isEnd(); } 3210 | 3211 | void init() 3212 | { 3213 | while (!isEnd() && !checkAndRef()) { 3214 | ++it; 3215 | value = nullptr; 3216 | } 3217 | 3218 | if (indexHintInfo && !isEnd()) { 3219 | ++indexHintInfo->nResultRows; 3220 | } 3221 | } 3222 | 3223 | private: 3224 | bool checkAndRef() 3225 | { 3226 | ref_t & ref = *it; 3227 | ref_t out; 3228 | value = table->get(ref, out); 3229 | assert(!!value); 3230 | 3231 | // bugfix: ref可能是底层数据, 修改会影响多个db对象, 多线程场景下可能crash 3232 | // if (value) { 3233 | // // 更新ref 3234 | // std::swap(ref, out); 3235 | // } 3236 | 3237 | if (indexHintInfo) { 3238 | ++indexHintInfo->nScanRows; 3239 | } 3240 | return and_group.check(*value); 3241 | } 3242 | 3243 | void next() 3244 | { 3245 | if (isEnd()) 3246 | return ; 3247 | 3248 | ++it; 3249 | value = nullptr; 3250 | init(); 3251 | } 3252 | 3253 | public: 3254 | data_table_t* table; 3255 | Debugger::IndexHintInfo* indexHintInfo = nullptr; 3256 | typename map_t::condition_iterator it; 3257 | condition_and_group and_group; // 未命中的索引, 遍历搜索 3258 | V* value; 3259 | }; 3260 | 3261 | void fork(index_t & other) 3262 | { 3263 | assert(other.meta == meta); 3264 | data.fork(other.data); 3265 | } 3266 | 3267 | void merge() 3268 | { 3269 | data.merge(); 3270 | } 3271 | 3272 | template 3273 | void foreachIndexValue(V const& value, F const& f) 3274 | { 3275 | vector> values(meta.cols.size()); 3276 | size_t n = 1; 3277 | for (size_t i = 0; i < meta.cols.size(); ++i) 3278 | { 3279 | auto & col = meta.cols[i]; 3280 | meta.cols[i].get(value, [&](column_value_t const& colValue) -> bool { 3281 | values[i].emplace_back(colValue); 3282 | return true; 3283 | }); 3284 | n *= values[i].size(); 3285 | } 3286 | 3287 | if (!n) 3288 | return ; 3289 | 3290 | // 交叉组合出多个index_value_t 3291 | vector indexes(values.size(), 0); 3292 | indexes[0] = -1; 3293 | 3294 | index_value_t ivt; 3295 | ivt.values.resize(values.size()); 3296 | for (size_t i = 1; i < values.size(); ++i) 3297 | { 3298 | ivt.values[i] = values[i][0]; 3299 | } 3300 | 3301 | for (size_t k = 0; k < n; ++k) 3302 | { 3303 | for (size_t i = 0; i < indexes.size(); ++i) 3304 | { 3305 | if (indexes[i] + 1 < int(values[i].size())) { 3306 | indexes[i]++; 3307 | ivt.values[i] = values[i][indexes[i]]; 3308 | break; 3309 | } 3310 | 3311 | if (!indexes[i]) { 3312 | // 不等于0, 回环, 进位 3313 | indexes[i] = 0; 3314 | ivt.values[i] = values[i][indexes[i]]; 3315 | continue; 3316 | } 3317 | } 3318 | 3319 | f(ivt); 3320 | } 3321 | } 3322 | 3323 | // @return: <最左连续匹配长度, 总匹配cond数量> 3324 | IndexMatchInfo match(condition_and_group const& and_group, 3325 | order_by_t const& ob) 3326 | { 3327 | bool isLeftMatchedStop = false; 3328 | IndexMatchInfo matchInfo; 3329 | vector> & cols = meta.cols; 3330 | 3331 | // 有order by时, 仅能匹配到order by的索引也要能用 3332 | if (ob.cols.size()) { 3333 | matchInfo.bOrderByMatched = true; 3334 | if (cols.size() < ob.cols.size()) { 3335 | matchInfo.bOrderByMatched = false; 3336 | } else { 3337 | for (size_t i = 0; i < ob.cols.size(); ++i) { 3338 | if (ob.cols[i] != cols[i]) { 3339 | matchInfo.bOrderByMatched = false; 3340 | break; 3341 | } 3342 | } 3343 | } 3344 | } 3345 | 3346 | for (virtual_column_t & col : cols) { 3347 | bool matched = false; 3348 | for (condition_t const& cond : and_group.and_) { 3349 | if (cond.col_ == col) 3350 | { 3351 | matchInfo.nMatchedCond++; 3352 | matched = true; 3353 | } 3354 | } 3355 | 3356 | if (!matched) { 3357 | isLeftMatchedStop = true; 3358 | } 3359 | 3360 | if (!isLeftMatchedStop) { 3361 | ++matchInfo.nLeftMatched; 3362 | } 3363 | } 3364 | 3365 | return matchInfo; 3366 | } 3367 | 3368 | void setIndex(V const& value, ref_t const& ref) 3369 | { 3370 | foreachIndexValue(value, [&](index_value_t & ivt){ 3371 | data.set(ivt.values, ref); 3372 | }); 3373 | } 3374 | 3375 | void delIndex(V const& value, ref_t const& ref) 3376 | { 3377 | foreachIndexValue(value, [&](index_value_t & ivt){ 3378 | data.del(ivt.values, ref); 3379 | }); 3380 | } 3381 | 3382 | void updateIndex(V const& oldValue, V const& newValue, ref_t const& ref) 3383 | { 3384 | // 优化TODO: index没变化时不操作 3385 | delIndex(oldValue, ref); 3386 | setIndex(newValue, ref); 3387 | } 3388 | 3389 | condition_iterator select(data_table_t* table, 3390 | condition_and_group const& and_group, 3391 | Debugger::IndexHintInfo* indexHintInfo) 3392 | { 3393 | std::vector mask(and_group.and_.size()); 3394 | 3395 | vector> & cols = meta.cols; 3396 | 3397 | typedef typename map_t::cond_t cond_t; 3398 | typedef typename map_t::condition_vec2_t condv2_t; 3399 | typedef std::shared_ptr condv2_ptr; 3400 | condv2_ptr condv2 = std::make_shared(); 3401 | condv2->resize(cols.size()); 3402 | 3403 | // and_group按字段聚合, 转为便于查询的结构: condv2 3404 | for (size_t i = 0; i < cols.size(); ++i) { 3405 | virtual_column_t & col = cols[i]; 3406 | for (size_t j = 0; j < and_group.and_.size(); ++j) { 3407 | condition_t const& cond = and_group.and_[j]; 3408 | if (cond.col_ == col) { 3409 | // matched 3410 | (*condv2)[i].emplace_back(cond_t{cond.colValue_, cond.op_}); 3411 | mask[j] = true; 3412 | } 3413 | } 3414 | } 3415 | 3416 | condition_iterator iter; 3417 | iter.it = data.select(condv2, indexHintInfo); 3418 | iter.table = table; 3419 | iter.indexHintInfo = indexHintInfo; 3420 | for (size_t j = 0; j < mask.size(); ++j) { 3421 | if (mask[j]) 3422 | continue; 3423 | 3424 | iter.and_group.and_.push_back(and_group.and_[j]); 3425 | } 3426 | iter.init(); 3427 | return std::move(iter); 3428 | } 3429 | 3430 | string toString(bool simple = false) const 3431 | { 3432 | string s; 3433 | s += P("index [cols.size()=%d]", (int)meta.cols.size()); 3434 | ++tlsTab(); 3435 | 3436 | { 3437 | s += P("cols:"); 3438 | ++tlsTab(); 3439 | for (size_t i = 0; i < meta.cols.size(); ++i) { 3440 | virtual_column_t const& col = meta.cols[i]; 3441 | s += P("[%d] %s", (int)i, col.toString().c_str()); 3442 | } 3443 | --tlsTab(); 3444 | } 3445 | 3446 | { 3447 | s += P("index-data:"); 3448 | ++tlsTab(); 3449 | s += data.toString(simple); 3450 | --tlsTab(); 3451 | } 3452 | 3453 | --tlsTab(); 3454 | return s; 3455 | } 3456 | }; 3457 | typedef std::shared_ptr index_ptr_t; 3458 | 3459 | // 索引搜索树 3460 | struct index_tree_t 3461 | { 3462 | map, index_ptr_t> indexes; 3463 | 3464 | index_ptr_t insert(index_meta_t meta) 3465 | { 3466 | index_ptr_t index = std::make_shared(meta); 3467 | auto kv = indexes.insert({index->meta, index}); 3468 | if (!kv.second) 3469 | return index_ptr_t{}; 3470 | 3471 | return index; 3472 | } 3473 | 3474 | void fork(index_tree_t & other) 3475 | { 3476 | other.indexes.clear(); 3477 | for (auto & kv : indexes) { 3478 | index_ptr_t & self = kv.second; 3479 | index_ptr_t index = std::make_shared(self->meta); 3480 | self->fork(*index); 3481 | other.indexes[kv.first] = index; 3482 | } 3483 | } 3484 | 3485 | void merge() 3486 | { 3487 | for (auto & kv : indexes) { 3488 | kv.second->merge(); 3489 | } 3490 | } 3491 | 3492 | // 匹配一个最佳索引 3493 | std::pair match(condition_and_group const& and_group, 3494 | order_by_t const& ob, 3495 | Debugger::OnceIndexQueryTrace* onceQueryTrace) 3496 | { 3497 | index_ptr_t bestIndex = nullptr; 3498 | IndexMatchInfo bestMatched; 3499 | 3500 | for (auto & kv : indexes) { 3501 | index_ptr_t & index = kv.second; 3502 | auto matched = index->match(and_group, ob); 3503 | 3504 | if (onceQueryTrace) { 3505 | onceQueryTrace->tryMatchIndexes.resize(onceQueryTrace->tryMatchIndexes.size() + 1); 3506 | Debugger::IndexHintInfo & indexHintInfo = onceQueryTrace->tryMatchIndexes.back(); 3507 | indexHintInfo.indexName = index->meta.toString(); 3508 | indexHintInfo.nLeftMatched = matched.nLeftMatched; 3509 | indexHintInfo.nMatchedCond = matched.nMatchedCond; 3510 | indexHintInfo.bOrderByMatched = matched.bOrderByMatched; 3511 | indexHintInfo.nForkLevels = index->data.level(); 3512 | } 3513 | 3514 | if (bestMatched < matched) { 3515 | bestMatched = matched; 3516 | bestIndex = index; 3517 | 3518 | if (onceQueryTrace) { 3519 | onceQueryTrace->matched = onceQueryTrace->tryMatchIndexes.back(); 3520 | } 3521 | } 3522 | } 3523 | 3524 | return {bestIndex, bestMatched}; 3525 | } 3526 | 3527 | void foreach(std::function pred) 3528 | { 3529 | for (auto & kv : indexes) 3530 | pred(kv.second); 3531 | } 3532 | 3533 | void setIndex(V const& value, ref_t const& ref) 3534 | { 3535 | foreach([&](index_ptr_t index){ 3536 | index->setIndex(value, ref); 3537 | }); 3538 | } 3539 | 3540 | void delIndex(V const& value, ref_t const& ref) 3541 | { 3542 | foreach([&](index_ptr_t index){ 3543 | index->delIndex(value, ref); 3544 | }); 3545 | } 3546 | 3547 | void updateIndex(V const& oldValue, V const& newValue, ref_t const& ref) 3548 | { 3549 | foreach([&](index_ptr_t index){ 3550 | index->updateIndex(oldValue, newValue, ref); 3551 | }); 3552 | } 3553 | 3554 | string toString(bool simple = false) const 3555 | { 3556 | string s; 3557 | int i = 0; 3558 | const_cast(this)->foreach([&](index_ptr_t index){ 3559 | s += P("[%d]", i++); 3560 | ++tlsTab(); 3561 | s += index->toString(simple); 3562 | --tlsTab(); 3563 | }); 3564 | return s; 3565 | } 3566 | }; 3567 | // ------------------ 索引 3568 | 3569 | public: 3570 | // 创建虚拟列, 用于创建索引、条件查询 3571 | // *注意*:仅当创建索引和条件查询用同一个虚拟列对象时, 查询才能命中索引! 3572 | // 3573 | // 虚拟列信息不局限于单个DB对象, 类型V相同的DB对象间可以通用 3574 | // @getter: 用于计算索引值的function 3575 | // @name: 仅用于debug时输出文字信息, 没有其他作用. 3576 | // @return: 返回一个虚拟列, 用于创建索引\条件查询 3577 | template 3578 | VirtualColumn makeVirtualColumn( 3579 | std::function const& getter, 3580 | string const& name = "") 3581 | { 3582 | return VirtualColumn(virtual_column_t::make(getter, name)); 3583 | } 3584 | 3585 | // one_of模式的索引 3586 | template 3587 | VirtualColumn makeVirtualColumn( 3588 | std::function(V const&)> const& getter, 3589 | string const& name = "") 3590 | { 3591 | typename virtual_column_t::ForeachGetterFn foreachGF = 3592 | [getter](V const& v, typename virtual_column_t::GetterHandler const& handler) -> bool { 3593 | vector vec = getter(v); 3594 | for (auto & val : vec) { 3595 | LessAny la; 3596 | la.set(val); 3597 | if (!handler(la)) 3598 | return false; 3599 | } 3600 | return true; 3601 | }; 3602 | return VirtualColumn(virtual_column_t::makeOneOf(foreachGF, name)); 3603 | } 3604 | 3605 | // 传入成员指针列表 / 虚拟列信息列表 3606 | // 例如: 3607 | // DB db; 3608 | // db.createIndex({&A::a}); 3609 | // db.createIndex({&A::a, &A::b}); 3610 | // 或: 3611 | // VirtualColumn vcol = db.makeVirtualColumn([](A const& v) { return v.a % 100; }); 3612 | // db.createIndex({vcol}); 3613 | // db.createIndex({vcol, &A::b}); 3614 | bool createIndex(vector> const& cols) { 3615 | std::set> unique; 3616 | 3617 | index_meta_t meta; 3618 | 3619 | for (virtual_column_t const& col : cols) { 3620 | if (unique.insert(col).second) 3621 | meta.cols.push_back(col); 3622 | } 3623 | 3624 | index_ptr_t index = indexes_.insert(meta); 3625 | if (!index) { 3626 | // 索引已存在 3627 | return false; 3628 | } 3629 | 3630 | for (virtual_column_t const& col : meta.cols) { 3631 | if (col.isMatchedIndex()) 3632 | indexedColumns_.insert({col, index}); 3633 | else 3634 | hasVirtualColumns_.push_back(index); 3635 | } 3636 | 3637 | data_.foreach([index](K const& key, ref_t const& ref, V* ptr){ 3638 | index->setIndex(*ptr, ref); 3639 | return true; 3640 | }); 3641 | 3642 | return true; 3643 | } 3644 | 3645 | // CRUD 3646 | bool insert(K const& key, V const& value) { 3647 | if (data_.get(key)) { 3648 | return false; 3649 | } 3650 | 3651 | data_.set(key, value); 3652 | ref_t ref {key}; 3653 | indexes_.setIndex(value, ref); 3654 | ++size_; 3655 | return true; 3656 | } 3657 | 3658 | bool update(K const& key, V const& value) { 3659 | ref_t ref; 3660 | V* oldValue = data_.get(key, ref); 3661 | if (!oldValue) { 3662 | return false; 3663 | } 3664 | 3665 | indexes_.updateIndex(*oldValue, value, ref); 3666 | data_.set(key, value); // 先更新索引后set, 避免set改变oldValue指向的值 3667 | return true; 3668 | } 3669 | 3670 | // 只更新部分字段, 在索引比较多的场景下可以有效减少索引重置 3671 | bool update(K const& key, vector> const& cols, V const& value) { 3672 | ref_t ref; 3673 | V* oldValue = data_.get(key, ref); 3674 | if (!oldValue) { 3675 | return false; 3676 | } 3677 | 3678 | std::set indexes; 3679 | for (column_t const& col : cols) { 3680 | auto range = indexedColumns_.equal_range(col); 3681 | for (auto it = range.first; it != range.second; ++it) 3682 | indexes.insert(it->second); 3683 | } 3684 | 3685 | for (index_ptr_t index : hasVirtualColumns_) 3686 | indexes.insert(index); 3687 | 3688 | V newValue = *oldValue; 3689 | for (column_t const& col : cols) { 3690 | col.assign(value, newValue); 3691 | } 3692 | 3693 | for (index_ptr_t index : indexes) 3694 | index->updateIndex(*oldValue, newValue, ref); 3695 | 3696 | data_.set(key, newValue); // 先更新索引后set, 避免set改变oldValue指向的值 3697 | return true; 3698 | } 3699 | 3700 | // @return: true:首次插入, false:数据已存在,执行变更操作 3701 | bool set(K const& key, V const& value) 3702 | { 3703 | ref_t ref; 3704 | V* oldValue = data_.get(key, ref); 3705 | if (!oldValue) { 3706 | ref_t newRef {key}; 3707 | indexes_.setIndex(value, newRef); 3708 | data_.set(key, value); 3709 | ++size_; 3710 | return true; 3711 | } 3712 | 3713 | indexes_.updateIndex(*oldValue, value, ref); 3714 | data_.set(key, value); 3715 | return false; 3716 | } 3717 | 3718 | // @return: true:首次插入, false:数据已存在,执行变更操作 3719 | bool set(K const& key, V && value) 3720 | { 3721 | ref_t ref; 3722 | V* oldValue = data_.get(key, ref); 3723 | if (!oldValue) { 3724 | ref_t newRef {key}; 3725 | indexes_.setIndex(value, newRef); 3726 | data_.set(key, std::move(value)); 3727 | ++size_; 3728 | return true; 3729 | } 3730 | 3731 | indexes_.updateIndex(*oldValue, value, ref); 3732 | data_.set(key, std::move(value)); 3733 | return false; 3734 | } 3735 | 3736 | size_t size() const { 3737 | return size_; 3738 | } 3739 | 3740 | bool empty() const { 3741 | return !size(); 3742 | } 3743 | 3744 | VRefPtr get(K const& key) 3745 | { 3746 | ref_t ref{key}; 3747 | return VRefPtr(this, ref); 3748 | } 3749 | 3750 | bool get(K const& key, V & out) 3751 | { 3752 | V* p = data_.get(key); 3753 | if (!p) { 3754 | return false; 3755 | } 3756 | 3757 | out = *p; 3758 | return true; 3759 | } 3760 | 3761 | bool del(K const& key) 3762 | { 3763 | ref_t ref; 3764 | V* oldValue = data_.get(key, ref); 3765 | if (!oldValue) { 3766 | return false; 3767 | } 3768 | 3769 | indexes_.delIndex(*oldValue, ref); 3770 | data_.del(key); 3771 | --size_; 3772 | return true; 3773 | } 3774 | 3775 | // 兼容 3776 | // void forEach(const std::function &cb) { 3777 | // foreach([&](K const& key, V const& value){ 3778 | // cb(key, value); 3779 | // return true; 3780 | // }); 3781 | // } 3782 | 3783 | // 无序遍历所有数据 3784 | // @return: 是否遍历完所有数据 3785 | // @cb: return-是否继续遍历, 返回false可以提前结束 3786 | bool foreach(const std::function &cb) { 3787 | return data_.foreach([cb](K const& key, ref_t const& ref, V* ptr){ 3788 | return cb(key, *ptr); 3789 | }); 3790 | } 3791 | bool foreachRef(const std::function &cb) { 3792 | return data_.foreach([this, cb](K const& key, ref_t const& ref, V* ptr){ 3793 | return cb(key, VRefPtr(this, ref, ptr), *ptr); 3794 | }); 3795 | } 3796 | 3797 | // 逐个取出select结果的迭代器 3798 | // 注意: 数据有修改时, 迭代器很可能会失效. 3799 | // Debugger的生命期要长于condition_iterator 3800 | struct condition_iterator 3801 | { 3802 | public: 3803 | condition_iterator() = default; 3804 | explicit condition_iterator(this_t * db, order_by_t const& ob) : db(db) 3805 | { 3806 | if (!ob.cols.empty()) { 3807 | obp = std::make_shared>(ob); 3808 | } 3809 | } 3810 | 3811 | condition_iterator(condition_iterator &&) = default; 3812 | condition_iterator& operator=(condition_iterator &&) = default; 3813 | 3814 | condition_iterator(condition_iterator const&) = delete; 3815 | condition_iterator& operator=(condition_iterator const&) = delete; 3816 | 3817 | std::pair & operator*() 3818 | { 3819 | return v.value; 3820 | } 3821 | 3822 | std::pair * operator->() 3823 | { 3824 | return &v.value; 3825 | } 3826 | 3827 | ref_t const& ref() 3828 | { 3829 | return v.ref; 3830 | } 3831 | 3832 | condition_iterator & operator++() 3833 | { 3834 | next(); 3835 | return *this; 3836 | } 3837 | 3838 | bool isEnd() const { return bEnd; } 3839 | 3840 | explicit operator bool() const { return !isEnd(); } 3841 | 3842 | private: 3843 | struct value_type 3844 | { 3845 | std::pair value; 3846 | ref_t ref; 3847 | }; 3848 | 3849 | struct order_iterator_t 3850 | { 3851 | enum class iterator_type { none, index, foreach }; 3852 | 3853 | order_iterator_t() = default; 3854 | order_iterator_t(order_iterator_t &&) = default; 3855 | order_iterator_t& operator=(order_iterator_t &&) = default; 3856 | 3857 | explicit order_iterator_t(typename index_t::condition_iterator && it, 3858 | std::shared_ptr> const& _obp, size_t _idx) 3859 | : type(iterator_type::index), indexIter(std::move(it)), obp(_obp), idx(_idx) 3860 | { 3861 | resetValue(); 3862 | } 3863 | 3864 | explicit order_iterator_t(typename data_table_t::iterator && it, 3865 | std::shared_ptr> const& _obp, size_t _idx) 3866 | : type(iterator_type::foreach), foreachIter(std::move(it)), obp(_obp), idx(_idx) 3867 | { 3868 | resetValue(); 3869 | } 3870 | 3871 | bool isForeach() 3872 | { 3873 | return iterator_type::foreach == type; 3874 | } 3875 | 3876 | friend bool operator<(order_iterator_t const& lhs, order_iterator_t const& rhs) 3877 | { 3878 | if (lhs.isEnd() && rhs.isEnd()) return false; 3879 | if (lhs.isEnd()) return true; 3880 | if (rhs.isEnd()) return false; 3881 | 3882 | if (lhs.obp) return lhs.obv < rhs.obv; // 使用了order by 3883 | if (lhs.type != rhs.type) return lhs.type < rhs.type; // index优先 3884 | return lhs.idx < rhs.idx; // ||左边的条件先处理 3885 | } 3886 | 3887 | value_type & value() { return v; } 3888 | 3889 | void next() { 3890 | switch ((int)type) { 3891 | case (int)iterator_type::index: 3892 | ++indexIter; 3893 | break; 3894 | 3895 | case (int)iterator_type::foreach: 3896 | ++foreachIter; 3897 | break; 3898 | 3899 | default: 3900 | return ; 3901 | } 3902 | 3903 | resetValue(); 3904 | } 3905 | 3906 | bool isEnd() const { 3907 | switch ((int)type) { 3908 | case (int)iterator_type::index: 3909 | return indexIter.isEnd(); 3910 | 3911 | case (int)iterator_type::foreach: 3912 | return foreachIter.isEnd(); 3913 | 3914 | default: 3915 | return true; 3916 | } 3917 | } 3918 | 3919 | void resetValue() 3920 | { 3921 | if (isEnd()) 3922 | return ; 3923 | 3924 | switch ((int)type) { 3925 | case (int)iterator_type::index: 3926 | v.value.first = &indexIter->key; 3927 | v.value.second = indexIter.getValue(); 3928 | v.ref = *indexIter; 3929 | break; 3930 | 3931 | case (int)iterator_type::foreach: 3932 | v.value.first = &foreachIter->first; 3933 | v.value.second = static_cast(&foreachIter->second); 3934 | v.ref = foreachIter.getRef(); 3935 | break; 3936 | 3937 | default: 3938 | return ; 3939 | } 3940 | 3941 | resetObv(); 3942 | } 3943 | 3944 | void resetObv() 3945 | { 3946 | if (isEnd()) 3947 | return ; 3948 | 3949 | if (obp) { 3950 | obv.values.clear(); 3951 | for (auto & col : obp->cols) { 3952 | // todo: order by OneOf怎么支持? 3953 | column_value_t cv; 3954 | col.get(*v.value.second, [&](column_value_t const& colValue) -> bool { 3955 | cv = colValue; 3956 | return false; 3957 | }); 3958 | obv.values.emplace_back(std::move(cv)); 3959 | } 3960 | } 3961 | } 3962 | 3963 | iterator_type type = iterator_type::none; 3964 | typename index_t::condition_iterator indexIter; 3965 | typename data_table_t::iterator foreachIter; 3966 | value_type v; 3967 | std::shared_ptr> obp; 3968 | order_by_value_t obv; 3969 | size_t idx = 0; 3970 | }; 3971 | 3972 | void setBegin() 3973 | { 3974 | bEnd = false; 3975 | 3976 | if (!canStepByStep()) { 3977 | // order by + foreach: 取出所有数据排序后返回 3978 | orderM.clear(); 3979 | order_by_value_t obv; 3980 | while (loopNextWhenInvalidInOrderQ(&obv)) { 3981 | orderM.insert({std::move(obv), v}); 3982 | nextInOrderQ(); 3983 | } 3984 | 3985 | mIter = orderM.begin(); 3986 | } 3987 | 3988 | if (!loopNextWhenInvalid()) 3989 | setEnd(); 3990 | } 3991 | 3992 | void setEnd() { 3993 | bEnd = true; 3994 | 3995 | if (queryTrace && !queryTrace->endTimestampUS) { 3996 | queryTrace->endTimestampUS = Debugger::QueryTrace::us(); 3997 | } 3998 | } 3999 | 4000 | bool loopNextWhenInvalid(order_by_value_t * obv = nullptr) 4001 | { 4002 | if (!canStepByStep()) { 4003 | if (mIter == orderM.end()) 4004 | return false; 4005 | 4006 | this->v = mIter->second; 4007 | if (obv) { 4008 | *obv = mIter->first; 4009 | } 4010 | return true; 4011 | } 4012 | 4013 | return loopNextWhenInvalidInOrderQ(obv); 4014 | } 4015 | 4016 | bool loopNextWhenInvalidInOrderQ(order_by_value_t * obv = nullptr) 4017 | { 4018 | while (!orderQ.empty()) { 4019 | order_iterator_t & oit = orderQ.top(); 4020 | 4021 | value_type & v = oit.value(); 4022 | 4023 | if (oit.isForeach()) { 4024 | if (foreachHintInfo) { 4025 | ++foreachHintInfo->nScanRows; 4026 | } 4027 | 4028 | if (!checkForeachConds(v)) { 4029 | // 条件不满足 4030 | oit.next(); 4031 | if (!oit.isEnd()) { 4032 | orderQ.resetTop(); 4033 | } else { 4034 | orderQ.pop(); 4035 | } 4036 | continue; 4037 | } 4038 | 4039 | if (foreachHintInfo) { 4040 | ++foreachHintInfo->nResultRows; 4041 | } 4042 | } 4043 | 4044 | if (!unique.insert(*v.value.first).second) { 4045 | // 重复的结果 4046 | oit.next(); 4047 | if (!oit.isEnd()) { 4048 | orderQ.resetTop(); 4049 | } else { 4050 | orderQ.pop(); 4051 | } 4052 | continue; 4053 | } 4054 | 4055 | // 可用 4056 | this->v = oit.value(); 4057 | if (obv) { 4058 | *obv = oit.obv; 4059 | } 4060 | return true; 4061 | } 4062 | 4063 | return false; 4064 | } 4065 | 4066 | bool checkForeachConds(value_type const& v) 4067 | { 4068 | for (condition_and_group & and_group : foreachConds.or_) { 4069 | if (and_group.check(*v.value.second)) 4070 | return true; 4071 | } 4072 | 4073 | return false; 4074 | } 4075 | 4076 | void next() 4077 | { 4078 | if (isEnd()) 4079 | return ; 4080 | 4081 | if (!canStepByStep()) { 4082 | ++mIter; 4083 | } else { 4084 | nextInOrderQ(); 4085 | } 4086 | 4087 | if (!loopNextWhenInvalid()) 4088 | setEnd(); 4089 | } 4090 | 4091 | void nextInOrderQ() 4092 | { 4093 | while (!orderQ.empty()) { 4094 | order_iterator_t & oit = orderQ.top(); 4095 | 4096 | oit.next(); 4097 | if (oit.isEnd()) { 4098 | orderQ.pop(); 4099 | continue; 4100 | } 4101 | 4102 | orderQ.resetTop(); 4103 | break; 4104 | } 4105 | } 4106 | 4107 | void push(typename index_t::condition_iterator && it, bool orderByMatched) 4108 | { 4109 | if (!it) return ; 4110 | 4111 | orderQ.push(std::move(it), obp, orderQ.size()); 4112 | if (!orderByMatched) { 4113 | bOrderByMatched = false; 4114 | } 4115 | } 4116 | 4117 | void push(typename data_table_t::iterator && it, condition_and_group const& and_group) 4118 | { 4119 | if (foreachConds.or_.empty() && it) { 4120 | orderQ.push(std::move(it), obp, orderQ.size()); 4121 | } 4122 | 4123 | foreachConds.or_.push_back(and_group); 4124 | bOrderByMatched = false; 4125 | } 4126 | 4127 | bool canStepByStep() 4128 | { 4129 | return !(obp && !bOrderByMatched); 4130 | } 4131 | 4132 | private: 4133 | friend this_t; 4134 | this_t * db = nullptr; 4135 | Debugger::QueryTrace* queryTrace = nullptr; 4136 | Debugger::IndexHintInfo* foreachHintInfo = nullptr; 4137 | condition_or_group foreachConds; 4138 | bool bOrderByMatched = true; 4139 | 4140 | std::shared_ptr> obp; 4141 | Heap orderQ; 4142 | std::multimap orderM; 4143 | typename std::multimap::iterator mIter; 4144 | std::set unique; 4145 | 4146 | value_type v; 4147 | bool bEnd = true; 4148 | }; 4149 | 4150 | condition_iterator select(condition_or_group const& cond, Debugger * dbg = nullptr) 4151 | { 4152 | order_by_t ob; 4153 | return select(cond, ob, dbg); 4154 | } 4155 | 4156 | condition_iterator select(condition_or_group cond, 4157 | order_by_t const& ob, Debugger * dbg = nullptr) 4158 | { 4159 | Debugger::QueryTrace* queryTrace = dbg ? &dbg->queryTrace : nullptr; 4160 | if (queryTrace) { 4161 | queryTrace->or_cond = cond.toString(); 4162 | queryTrace->beginTimestampUS = Debugger::QueryTrace::us(); 4163 | } 4164 | 4165 | optimize(cond); 4166 | 4167 | if (queryTrace) { 4168 | queryTrace->optimizedCond = cond.toString(); 4169 | } 4170 | 4171 | Debugger::OnceIndexQueryTrace* lastForeachQueryTrace = nullptr; 4172 | 4173 | condition_iterator condIter(this, ob); 4174 | condIter.queryTrace = queryTrace; 4175 | if (cond.or_.empty()) { 4176 | cond.or_.push_back(condition_and_group{}); 4177 | } 4178 | 4179 | for (size_t i = 0; i < cond.or_.size(); ++i) 4180 | { 4181 | condition_and_group const& and_group = cond.or_[i]; 4182 | 4183 | Debugger::OnceIndexQueryTrace* onceQueryTrace = nullptr; 4184 | Debugger::IndexHintInfo* matchedIndexHintInfo = nullptr; 4185 | if (queryTrace) { 4186 | onceQueryTrace = queryTrace->newQuery(); 4187 | onceQueryTrace->cond = and_group.toString(); 4188 | matchedIndexHintInfo = &onceQueryTrace->matched; 4189 | } 4190 | 4191 | // 选索引 4192 | std::pair matched = indexes_.match(and_group, ob, onceQueryTrace); 4193 | index_ptr_t index = matched.first; 4194 | if (index) { 4195 | // 在索引上搜索 4196 | typename index_t::condition_iterator it = index->select( 4197 | &data_, and_group, matchedIndexHintInfo); 4198 | if (it) { 4199 | condIter.push(std::move(it), matched.second.bOrderByMatched); 4200 | } 4201 | continue; 4202 | } 4203 | 4204 | // 后续遍历搜索 4205 | lastForeachQueryTrace = onceQueryTrace; 4206 | condIter.push(data_.begin(), and_group); 4207 | } 4208 | 4209 | if (!condIter.foreachConds.or_.empty()) { 4210 | if (queryTrace) { 4211 | lastForeachQueryTrace->cond = condIter.foreachConds.toString(); 4212 | lastForeachQueryTrace->matched.indexName = "foreach"; 4213 | condIter.foreachHintInfo = &lastForeachQueryTrace->matched; 4214 | } 4215 | 4216 | if (selectNotMatchIndexNotify_) { 4217 | selectNotMatchIndexNotify_(); 4218 | } 4219 | } 4220 | 4221 | condIter.setBegin(); 4222 | return std::move(condIter); 4223 | } 4224 | 4225 | // 迭代器不方便copy, 暂时不做range了 4226 | // struct condition_range 4227 | // { 4228 | // condition_range() { 4229 | // it.setEnd(); 4230 | // empty.setEnd(); 4231 | // } 4232 | // 4233 | // condition_range(condition_iterator && cit) : it(std::move(cit)) { 4234 | // empty.setEnd(); 4235 | // } 4236 | // 4237 | // condition_iterator & begin() 4238 | // { 4239 | // return it; 4240 | // } 4241 | // 4242 | // condition_iterator & end() 4243 | // { 4244 | // return empty; 4245 | // } 4246 | // 4247 | // condition_iterator it; 4248 | // condition_iterator empty; 4249 | // }; 4250 | // 4251 | // condition_range selectRange(condition_or_group cond, Debugger * dbg = nullptr) 4252 | // { 4253 | // return condition_range(select(cond, dbg)); 4254 | // } 4255 | 4256 | std::vector selectVector(condition_or_group const& cond, Debugger * dbg = nullptr) 4257 | { 4258 | order_by_t ob; 4259 | return selectVector(cond, ob, dbg); 4260 | } 4261 | 4262 | std::vector selectVector(condition_or_group const& cond, 4263 | order_by_t const& ob, Debugger * dbg = nullptr) 4264 | { 4265 | std::vector result; 4266 | condition_iterator it = select(cond, ob, dbg); 4267 | for (; it; ++it) { 4268 | V const* p = it->second; 4269 | result.push_back(p); 4270 | } 4271 | return result; 4272 | } 4273 | 4274 | std::vector selectVectorRef(condition_or_group const& cond, Debugger * dbg = nullptr) 4275 | { 4276 | order_by_t ob; 4277 | return selectVectorRef(cond, ob, dbg); 4278 | } 4279 | 4280 | std::vector selectVectorRef(condition_or_group const& cond, 4281 | order_by_t const& ob, Debugger * dbg = nullptr) 4282 | { 4283 | std::vector result; 4284 | condition_iterator it = select(cond, ob, dbg); 4285 | for (; it; ++it) { 4286 | result.push_back(VRefPtr(this, it.ref(), it->second)); 4287 | } 4288 | return result; 4289 | } 4290 | 4291 | std::vector selectVectorCopy(condition_or_group const& cond, Debugger * dbg = nullptr) 4292 | { 4293 | order_by_t ob; 4294 | return selectVectorCopy(cond, ob, dbg); 4295 | } 4296 | 4297 | std::vector selectVectorCopy(condition_or_group const& cond, 4298 | order_by_t const& ob, Debugger * dbg = nullptr) 4299 | { 4300 | std::vector result; 4301 | condition_iterator it = select(cond, ob, dbg); 4302 | for (; it; ++it) { 4303 | V const* p = it->second; 4304 | result.push_back(*p); 4305 | } 4306 | return result; 4307 | } 4308 | 4309 | std::map selectMap(condition_or_group const& cond, Debugger * dbg = nullptr) 4310 | { 4311 | order_by_t ob; 4312 | return selectMap(cond, ob, dbg); 4313 | } 4314 | 4315 | std::map selectMap(condition_or_group const& cond, 4316 | order_by_t const& ob, Debugger * dbg = nullptr) 4317 | { 4318 | std::map result; 4319 | condition_iterator it = select(cond, ob, dbg); 4320 | for (; it; ++it) { 4321 | result[*it->first] = it->second; 4322 | } 4323 | return result; 4324 | } 4325 | 4326 | std::map selectMapRef(condition_or_group const& cond, Debugger * dbg = nullptr) 4327 | { 4328 | order_by_t ob; 4329 | return selectMapRef(cond, ob, dbg); 4330 | } 4331 | 4332 | std::map selectMapRef(condition_or_group const& cond, 4333 | order_by_t const& ob, Debugger * dbg = nullptr) 4334 | { 4335 | std::map result; 4336 | condition_iterator it = select(cond, ob, dbg); 4337 | for (; it; ++it) { 4338 | result[*it->first] = VRefPtr(this, it.ref(), it->second); 4339 | } 4340 | return result; 4341 | } 4342 | 4343 | std::map selectMapCopy(condition_or_group const& cond, Debugger * dbg = nullptr) 4344 | { 4345 | order_by_t ob; 4346 | return selectMapCopy(cond, ob, dbg); 4347 | } 4348 | 4349 | std::map selectMapCopy(condition_or_group const& cond, 4350 | order_by_t const& ob, Debugger * dbg = nullptr) 4351 | { 4352 | std::map result; 4353 | condition_iterator it = select(cond, ob, dbg); 4354 | for (; it; ++it) { 4355 | result[*it->first] = *it->second; 4356 | } 4357 | return result; 4358 | } 4359 | 4360 | // todo:查询条件优化 4361 | // case1: (A > 1 && A < 3) 4362 | // case2: (A > 2 || A < 2) 4363 | // case3: (A > 2 || B == 3) && (A < 3 || B == 3) 4364 | // case4: (A > 1 && A < 3 && A > 2) 4365 | // other cases... 4366 | void optimize(condition_or_group & cond) 4367 | { 4368 | } 4369 | 4370 | void fork(DB & other) 4371 | { 4372 | other.size_ = size_; 4373 | other.selectNotMatchIndexNotify_ = selectNotMatchIndexNotify_; 4374 | data_.fork(other.data_); 4375 | indexes_.fork(other.indexes_); 4376 | other.initIndexedColumns(); 4377 | } 4378 | 4379 | size_t forkLevel() 4380 | { 4381 | return data_.level(); 4382 | } 4383 | 4384 | void merge() 4385 | { 4386 | data_.merge(); 4387 | indexes_.merge(); 4388 | } 4389 | 4390 | // 查询未命中索引时通知callback (foreach执行前) 4391 | // 可以在callback做'爬堆栈'、'输出日志'、'抛出异常终止本次查询'等等操作 4392 | void setSelectNotMatchIndexNotify(std::function const& selectNotMatchIndexNotify) 4393 | { 4394 | selectNotMatchIndexNotify_ = selectNotMatchIndexNotify; 4395 | } 4396 | 4397 | string toString(bool simple = false) const 4398 | { 4399 | string s; 4400 | s += P("[ShadowDB](0x%p)", (void*)this); 4401 | ++tlsTab(); 4402 | 4403 | { 4404 | s += P("data:"); 4405 | ++tlsTab(); 4406 | s += data_.toString(simple); 4407 | --tlsTab(); 4408 | } 4409 | 4410 | { 4411 | s += P("indexes:"); 4412 | ++tlsTab(); 4413 | s += indexes_.toString(simple); 4414 | --tlsTab(); 4415 | } 4416 | 4417 | --tlsTab(); 4418 | return s; 4419 | } 4420 | 4421 | private: 4422 | void initIndexedColumns() 4423 | { 4424 | indexedColumns_.clear(); 4425 | hasVirtualColumns_.clear(); 4426 | indexes_.foreach([this](index_ptr_t index) { 4427 | for (virtual_column_t const& col : index->meta.cols) { 4428 | if (col.isMatchedIndex()) { 4429 | indexedColumns_.insert({col, index}); 4430 | } else { 4431 | hasVirtualColumns_.push_back(index); 4432 | } 4433 | } 4434 | }); 4435 | } 4436 | 4437 | private: 4438 | data_table_t data_; // 原始数据 4439 | index_tree_t indexes_; // 索引 4440 | multimap, index_ptr_t> indexedColumns_; // 索引涉及的列 4441 | vector hasVirtualColumns_; // 包含虚拟列的索引信息 4442 | size_t size_ = 0; 4443 | std::function selectNotMatchIndexNotify_; // 查询未命中索引时通知 4444 | }; 4445 | 4446 | // condition语法糖 4447 | // ex: 4448 | // Cond(&A::a) < 1 4449 | // Cond(&A::a) < 1 && Cond(&A::b) == 2 4450 | // 4451 | // cond-&A::a < 1 4452 | template 4453 | inline field_t Cond(FieldType V::* memptr) 4454 | { 4455 | return field_t(memptr); 4456 | } 4457 | 4458 | // condition语法糖(自定义VirtualColumn重载) 4459 | // 注意:用于Cond查找的VirtualColumn, 必须和用于创建索引的VirtualColumn是同一个对象, 才能命中索引查询. 4460 | // ex: 4461 | // VirtualColumn col = VirtualColumn::make([](A const& v){ return v.a % 10; }); 4462 | // Cond(col) < 1 4463 | // 4464 | // cond-col < 1 4465 | template 4466 | inline field_t Cond(VirtualColumn & col) 4467 | { 4468 | if (!col.isValid()) { 4469 | throw std::logic_error("Invalid column parameter for call ::shadow::Cond"); 4470 | } 4471 | 4472 | return field_t(col); 4473 | } 4474 | 4475 | // oneof语法糖 4476 | // ex: 4477 | // Cond(&A::a) < 1 4478 | // Cond(&A::a) < 1 && Cond(&A::b) == 2 4479 | // 4480 | // cond-&A::a < 1 4481 | template 4482 | inline field_t::type> OneOf(ContainerType V::* memptr) 4483 | { 4484 | typedef typename detail::one_of_type::type ValueType; 4485 | return field_t(virtual_column_t::makeOneOf(memptr)); 4486 | } 4487 | 4488 | struct CondHelper 4489 | { 4490 | template 4491 | inline field_t operator-(FieldType V::* memptr) 4492 | { 4493 | return Cond(memptr); 4494 | } 4495 | 4496 | template 4497 | inline field_t operator-(VirtualColumn & col) 4498 | { 4499 | return Cond(col); 4500 | } 4501 | }; 4502 | 4503 | static CondHelper cond; 4504 | 4505 | // order by语法糖 4506 | // ex: 4507 | // OrderBy(&A::a, &A::b); 4508 | template 4509 | inline order_by_t OrderBy(FieldType V::* memptr, Args && ... args) 4510 | { 4511 | order_by_t ob; 4512 | makeOrderBy(ob, memptr, std::forward(args)...); 4513 | return ob; 4514 | } 4515 | 4516 | template 4517 | inline order_by_t OrderBy(VirtualColumn & col, Args && ... args) 4518 | { 4519 | order_by_t ob; 4520 | makeOrderBy(ob, col, std::forward(args)...); 4521 | return ob; 4522 | } 4523 | 4524 | } // namespace shadow 4525 | 4526 | #ifndef SHADOW_DB_NOT_EXPORT_COND 4527 | using shadow::Cond; 4528 | using shadow::cond; 4529 | using shadow::OneOf; 4530 | using shadow::OrderBy; 4531 | #endif 4532 | --------------------------------------------------------------------------------