mirror of
https://github.com/YuhangQ/InvoDB.git
synced 2025-01-27 15:10:57 +00:00
适配 nodejs
This commit is contained in:
parent
c49cb450ce
commit
458ab0649a
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
test.invodb
|
package-lock.json
|
||||||
/cmake-build-debug/
|
*.invodb
|
||||||
.idea
|
.vscode
|
||||||
|
node_modules
|
||||||
|
build
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
1
.idea/.name
generated
1
.idea/.name
generated
@ -1 +0,0 @@
|
|||||||
InvoDB
|
|
2
.idea/InvoDB.iml
generated
2
.idea/InvoDB.iml
generated
@ -1,2 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
|
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
|
||||||
</project>
|
|
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/InvoDB.iml" filepath="$PROJECT_DIR$/.idea/InvoDB.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,14 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.16.3)
|
|
||||||
project(InvoDB)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
|
|
||||||
|
|
||||||
include_directories(.)
|
|
||||||
include_directories(./invodb)
|
|
||||||
|
|
||||||
add_executable(InvoDB
|
|
||||||
invodb/main.cpp
|
|
||||||
invodb/main.h invodb/file/page_manager.cpp invodb/file/page_manager.h invodb/collection/collection.cpp invodb/collection/collection.h invodb/file/storage_page.cpp invodb/file/storage_page.h invodb/utils/logger.h invodb/utils/uuid.h invodb/btree/node.h invodb/btree/btree.h invodb/btree/list.h invodb/collection/query.cpp invodb/utils/cache.h invodb/collection/index.cpp)
|
|
27
binding.gyp
Normal file
27
binding.gyp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"target_name": "core",
|
||||||
|
"sources": [
|
||||||
|
"./src/collection/collection.cpp",
|
||||||
|
"./src/collection/index.cpp",
|
||||||
|
"./src/collection/query.cpp",
|
||||||
|
"./src/file/page_manager.cpp",
|
||||||
|
"./src/file/storage_page.cpp",
|
||||||
|
"./src/main.cpp",
|
||||||
|
],
|
||||||
|
"include_dirs": [
|
||||||
|
"<!@(node -p \"require('node-addon-api').include\")"
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"<!(node -p \"require('node-addon-api').gyp\")"
|
||||||
|
],
|
||||||
|
"cflags!": ["-fno-exceptions"],
|
||||||
|
"cflags_cc!": ["-fno-exceptions"],
|
||||||
|
"defines": ["NAPI_CPP_EXCEPTIONS"],
|
||||||
|
"xcode_settings": {
|
||||||
|
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
21
demo/test.js
Normal file
21
demo/test.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const invodb = require('..')
|
||||||
|
|
||||||
|
invodb.database('zzz.invodb')
|
||||||
|
|
||||||
|
let col = invodb.colection('blog')
|
||||||
|
if(!col.exist()) col.create();
|
||||||
|
|
||||||
|
col.insert({ id: 1, title: "第一篇文章", author: "YuhangQ"})
|
||||||
|
col.insert({ id: 2, title: "第二篇文章", author: "Ciel"})
|
||||||
|
col.insert({ id: 3, title: "第三篇文章", author: "YuhangQ"})
|
||||||
|
col.insert({ id: 4, title: "第四篇文章", author: "By"})
|
||||||
|
|
||||||
|
let result = col.query({
|
||||||
|
id: {
|
||||||
|
$gte: 2,
|
||||||
|
$lte: 3
|
||||||
|
},
|
||||||
|
author: "YuhangQ"
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(result)
|
38
index.js
Normal file
38
index.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
const core = require("./build/Release/core.node");
|
||||||
|
|
||||||
|
function database(filename) {
|
||||||
|
core.database(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
function colection(collectionName) {
|
||||||
|
function exist() { return core.exists(collectionName); }
|
||||||
|
function create() { core.create(collectionName); }
|
||||||
|
function insert(object) {
|
||||||
|
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
|
||||||
|
let json = JSON.stringify(object);
|
||||||
|
core.insert(collectionName, json);
|
||||||
|
}
|
||||||
|
function remove(object) {
|
||||||
|
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
|
||||||
|
let json = JSON.stringify(object);
|
||||||
|
core.remove(collectionName, json);
|
||||||
|
}
|
||||||
|
function query(object) {
|
||||||
|
if(!core.exists(collectionName)) throw `Collection ${collectionName} doesn't exists!`;
|
||||||
|
let json = JSON.stringify(object);
|
||||||
|
return core.query(collectionName, json);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
exist: exist,
|
||||||
|
create: create,
|
||||||
|
insert: insert,
|
||||||
|
remove: remove,
|
||||||
|
query: query
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
database: database,
|
||||||
|
colection: colection
|
||||||
|
};
|
||||||
|
|
24
package.json
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "invodb",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "a nosql json document database",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"install": "node-gyp rebuild"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/YuhangQ/InvoDB.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"gypfile": true,
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/YuhangQ/InvoDB/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/YuhangQ/InvoDB#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"node-addon-api": "^4.2.0"
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,8 @@
|
|||||||
#ifndef INVODB_BTREE_H
|
#ifndef INVODB_BTREE_H
|
||||||
#define INVODB_BTREE_H
|
#define INVODB_BTREE_H
|
||||||
|
|
||||||
#include "btree/node.h"
|
#include "node.h"
|
||||||
#include "utils/uuid.h"
|
#include "../utils/uuid.h"
|
||||||
|
|
||||||
#define M_SIZE 1000 / (K_SIZE + 4)
|
#define M_SIZE 1000 / (K_SIZE + 4)
|
||||||
|
|
@ -13,8 +13,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "file/page_manager.h"
|
#include "../file/page_manager.h"
|
||||||
#include "invodb/utils/cache.h"
|
#include "../utils/cache.h"
|
||||||
|
|
||||||
template<int M_SIZE, typename KT, int K_SIZE>
|
template<int M_SIZE, typename KT, int K_SIZE>
|
||||||
class BTreeNode {
|
class BTreeNode {
|
@ -27,6 +27,10 @@ Collection& Collection::createCollection(const std::string &name) {
|
|||||||
return *col;
|
return *col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Collection::existsCollection(const std::string& name) {
|
||||||
|
return map.count(name) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
Collection &Collection::getCollection(const std::string &name) {
|
Collection &Collection::getCollection(const std::string &name) {
|
||||||
if(map.count(name) == 0) {
|
if(map.count(name) == 0) {
|
||||||
throw "no such collection";
|
throw "no such collection";
|
||||||
@ -55,7 +59,7 @@ void Collection::insert(nlohmann::json &json) {
|
|||||||
int add = PageManager::Instance().saveJSONToFile(json);
|
int add = PageManager::Instance().saveJSONToFile(json);
|
||||||
uuid->insert(id, add);
|
uuid->insert(id, add);
|
||||||
|
|
||||||
//Logger::info<std::string, std::string>("INSERT ", json.dump());
|
Logger::info<std::string, std::string>("INSERT ", json.dump());
|
||||||
|
|
||||||
// add index
|
// add index
|
||||||
indexJSON("", json, add);
|
indexJSON("", json, add);
|
@ -5,16 +5,16 @@
|
|||||||
#ifndef INVODB_COLLECTION_H
|
#ifndef INVODB_COLLECTION_H
|
||||||
#define INVODB_COLLECTION_H
|
#define INVODB_COLLECTION_H
|
||||||
|
|
||||||
#include "file/page_manager.h"
|
#include "../file/page_manager.h"
|
||||||
#include "utils/logger.h"
|
#include "../utils/logger.h"
|
||||||
#include "btree/btree.h"
|
#include "../btree/btree.h"
|
||||||
#include "json/json.hpp"
|
#include "../json/json.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "utils/uuid.h"
|
#include "../utils/uuid.h"
|
||||||
#include "btree/list.h"
|
#include "../btree/list.h"
|
||||||
|
|
||||||
class Collection {
|
class Collection {
|
||||||
public:
|
public:
|
||||||
@ -23,6 +23,7 @@ public:
|
|||||||
std::vector<nlohmann::json> query(const nlohmann::json &json);
|
std::vector<nlohmann::json> query(const nlohmann::json &json);
|
||||||
static void loadCollections();
|
static void loadCollections();
|
||||||
static Collection& getCollection(const std::string& name);
|
static Collection& getCollection(const std::string& name);
|
||||||
|
static bool existsCollection(const std::string& name);
|
||||||
static Collection& createCollection(const std::string& name);
|
static Collection& createCollection(const std::string& name);
|
||||||
|
|
||||||
void test();
|
void test();
|
@ -152,11 +152,11 @@ std::set<nlohmann::json> Collection::innerQuery(const std::string &prefix, const
|
|||||||
|
|
||||||
auto str = json.dump();
|
auto str = json.dump();
|
||||||
|
|
||||||
printf("query: %s prefix: %s\n", str.c_str(), prefix.c_str());
|
// printf("query: %s prefix: %s\n", str.c_str(), prefix.c_str());
|
||||||
printf("result: \n");
|
// printf("result: \n");
|
||||||
for(auto it=res.begin(); it!=res.end(); it++) {
|
// for(auto it=res.begin(); it!=res.end(); it++) {
|
||||||
printf(" - %s\n", it->dump().c_str());
|
// printf(" - %s\n", it->dump().c_str());
|
||||||
}
|
// }
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ std::set<nlohmann::json>
|
|||||||
Collection::queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod) {
|
Collection::queryNumber(const std::string &prefix, const double &minValue, const double &maxValue, const int &mod) {
|
||||||
std::set<nlohmann::json> res;
|
std::set<nlohmann::json> res;
|
||||||
auto treeName = prefix + "$number";
|
auto treeName = prefix + "$number";
|
||||||
printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue);
|
//printf(">>>> %s %f %f\n", prefix.c_str(), minValue, maxValue);
|
||||||
|
|
||||||
if(!index->exists(treeName)) {
|
if(!index->exists(treeName)) {
|
||||||
return res;
|
return res;
|
@ -3,10 +3,10 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "page_manager.h"
|
#include "page_manager.h"
|
||||||
#include "btree/list.h"
|
|
||||||
|
|
||||||
|
|
||||||
int PageManager::loadDatabase(const char *filename) {
|
int PageManager::loadDatabase(const char *filename) {
|
||||||
|
std::ofstream file(filename, std::fstream::out);
|
||||||
|
file.close();
|
||||||
Instance().stream.open(filename);
|
Instance().stream.open(filename);
|
||||||
Instance().stream.seekp(0, std::ios::end);
|
Instance().stream.seekp(0, std::ios::end);
|
||||||
int index = Instance().stream.tellp() / 1024;
|
int index = Instance().stream.tellp() / 1024;
|
@ -9,12 +9,9 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include "../json/json.hpp"
|
||||||
|
#include "../utils/cache.h"
|
||||||
#include "storage_page.h"
|
#include "storage_page.h"
|
||||||
#include "json/json.hpp"
|
|
||||||
#include "invodb/utils/cache.h"
|
|
||||||
|
|
||||||
template<typename T, int T_SIZE>
|
|
||||||
class List;
|
|
||||||
|
|
||||||
class PageManager {
|
class PageManager {
|
||||||
public:
|
public:
|
@ -62,6 +62,8 @@ int StoragePage::getAddress() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StoragePage::StoragePage() {
|
StoragePage::StoragePage() {
|
||||||
|
|
||||||
|
printf("aha!\n");
|
||||||
memset(page, 0, sizeof(page));
|
memset(page, 0, sizeof(page));
|
||||||
}
|
}
|
||||||
|
|
69
src/main.cpp
Normal file
69
src/main.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Created by YuhangQ on 2021/9/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include <napi.h>
|
||||||
|
|
||||||
|
using namespace Napi;
|
||||||
|
|
||||||
|
|
||||||
|
void database(const CallbackInfo& info) {
|
||||||
|
std::string filename = info[0].As<String>();
|
||||||
|
PageManager::loadDatabase(filename.c_str());
|
||||||
|
Collection::loadCollections();
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean exists(const CallbackInfo& info) {
|
||||||
|
std::string colName = info[0].As<String>();
|
||||||
|
return Boolean::New(info.Env(), Collection::existsCollection(colName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void create(const CallbackInfo& info) {
|
||||||
|
std::string colName = info[0].As<String>();
|
||||||
|
Collection::createCollection(colName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(const CallbackInfo& info) {
|
||||||
|
std::string colName = info[0].As<String>();
|
||||||
|
std::string json = info[1].As<String>();
|
||||||
|
|
||||||
|
auto j = nlohmann::json::parse(json);
|
||||||
|
Collection::getCollection(colName).insert(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array query(const CallbackInfo& info) {
|
||||||
|
std::string colName = info[0].As<String>();
|
||||||
|
std::string json = info[1].As<String>();
|
||||||
|
|
||||||
|
auto j = nlohmann::json::parse(json);
|
||||||
|
auto result = Collection::getCollection(colName).query(j);
|
||||||
|
|
||||||
|
auto res = Array::New(info.Env(), result.size());
|
||||||
|
for(int i=0; i<result.size(); i++) {
|
||||||
|
res.Set(i, String::New(info.Env(), result[i].dump()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _remove(const CallbackInfo& info) {
|
||||||
|
std::string colName = info[0].As<String>();
|
||||||
|
std::string json = info[1].As<String>();
|
||||||
|
|
||||||
|
auto j = nlohmann::json::parse(json);
|
||||||
|
Collection::getCollection(colName).remove(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object Init(Env env, Object exports) {
|
||||||
|
srand(time(0));
|
||||||
|
exports.Set("database", Function::New(env, database));
|
||||||
|
exports.Set("exists", Function::New(env, exists));
|
||||||
|
exports.Set("create", Function::New(env, create));
|
||||||
|
exports.Set("insert", Function::New(env, insert));
|
||||||
|
exports.Set("query", Function::New(env, query));
|
||||||
|
exports.Set("remove", Function::New(env, _remove));
|
||||||
|
return exports;
|
||||||
|
}
|
||||||
|
NODE_API_MODULE(core, Init)
|
@ -1,11 +1,9 @@
|
|||||||
//
|
#include <iostream>
|
||||||
// Created by YuhangQ on 2021/9/24.
|
#include <cstdlib>
|
||||||
//
|
#include <ctime>
|
||||||
|
#include <vector>
|
||||||
#include "main.h"
|
#include "../collection/collection.h"
|
||||||
|
#include "../btree/list.h"
|
||||||
|
|
||||||
void testAndBenchmark(int n);
|
|
||||||
|
|
||||||
Collection *col;
|
Collection *col;
|
||||||
|
|
||||||
@ -53,84 +51,6 @@ void terminal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
|
||||||
int t = time(0);
|
|
||||||
srand(1635418590);
|
|
||||||
//srand(t);
|
|
||||||
printf("seed: %d\n", t);
|
|
||||||
|
|
||||||
system("rm -rf test.invodb && touch test.invodb");
|
|
||||||
|
|
||||||
PageManager::loadDatabase("test.invodb");
|
|
||||||
|
|
||||||
Collection::loadCollections();
|
|
||||||
|
|
||||||
PageManager& manager = PageManager::Instance();
|
|
||||||
|
|
||||||
try {
|
|
||||||
col = &Collection::getCollection("hello");
|
|
||||||
} catch(const char *error) {
|
|
||||||
Collection::createCollection("hello");
|
|
||||||
col = &Collection::getCollection("hello");
|
|
||||||
}
|
|
||||||
|
|
||||||
// nlohmann::json j = nlohmann::json::parse(R"(
|
|
||||||
//{
|
|
||||||
// "title" : "MongoDB 教程",
|
|
||||||
// "description" : "MongoDB 是一个 Nosql 数据库",
|
|
||||||
// "by" : "菜鸟教程",
|
|
||||||
// "url" : "http://www.runoob.com",
|
|
||||||
// "tags" : [
|
|
||||||
// "mongodb",
|
|
||||||
// "database",
|
|
||||||
// "NoSQL"
|
|
||||||
// ],
|
|
||||||
// "likes" : 100
|
|
||||||
//}
|
|
||||||
// )");
|
|
||||||
//
|
|
||||||
// col->insert(j);
|
|
||||||
//
|
|
||||||
// col->query(nlohmann::json::parse(R"(
|
|
||||||
//{
|
|
||||||
// "likes": {"$gt":50},
|
|
||||||
// "$or": [
|
|
||||||
// {"by": "菜鸟教程"},
|
|
||||||
// {"title": "MongoDB 教程"}
|
|
||||||
// ]
|
|
||||||
//}
|
|
||||||
// )"));
|
|
||||||
|
|
||||||
terminal();
|
|
||||||
|
|
||||||
|
|
||||||
// freopen("qq.txt", "r", stdin);
|
|
||||||
// const int n = 1000000;
|
|
||||||
// char qq[100], phone[100];
|
|
||||||
//
|
|
||||||
// clock_t start = clock();
|
|
||||||
// for(int i=0; i<n; i++) {
|
|
||||||
// scanf("%s%s", qq, phone);
|
|
||||||
// nlohmann::json json;
|
|
||||||
// json["qq"] = qq;
|
|
||||||
// json["phone"] = phone;
|
|
||||||
// col->insert(json);
|
|
||||||
//
|
|
||||||
// if(i % (n/1000) == 0) {
|
|
||||||
// printf("[%d/%d] time=%fs!\n", i, n, (double)(clock() - start) / CLOCKS_PER_SEC);
|
|
||||||
// start = clock();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//col->test();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//testAndBenchmark(20000);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void testAndBenchmark(int n) {
|
void testAndBenchmark(int n) {
|
||||||
|
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "invodb/file/storage_page.h"
|
#include "../file/storage_page.h"
|
||||||
|
|
||||||
template<typename KT, typename VT>
|
template<typename KT, typename VT>
|
||||||
class LRUCache {
|
class LRUCache {
|
Loading…
x
Reference in New Issue
Block a user