美文网首页
Node-Sqlite3 的修改详解

Node-Sqlite3 的修改详解

作者: l蓝色梦幻 | 来源:发表于2018-11-19 16:13 被阅读70次

由于我们需要使用静态库连接, 尽可能少的使用 dll .因此我们需要对 Node-Sqlite3 的源代码做出对应的修改. 代码相对于 4.0.3
做出的修改

关于 Gyp 的修改.

由于 Node-Sqlite3 使用 Gyp 作为配置, 因此我们从本地编译代码, 就需要添加, 修改对应的代码块才可能. 如下:

原来的 bingding.gyp.

下面是我们修改的 gyp 文件. 注意, 修改部分我会加上注释表明是为什么修改, 但是该注释在使用的时候需要删除.

{
  "includes": [ "deps/common-sqlite.gypi" ],
  "variables": {
      "sqlite%":"sqlcipher_lib",
      "sqlite_libname%":"sqlcipher",
      "openssl_libname%":"crypto" // 添加新的配置项, 支持 openssl 静态库编译
  },
  "targets": [
    {
      "target_name": "<(module_name)",
      "include_dirs": ["<!(node -e \"require('nan')\")"],
      "conditions": [
        ["sqlite != 'internal'", {
            "include_dirs": [ "<(module_root_dir)/<(sqlite)/include", "<(module_root_dir)/<(sqlite)/include/sqlcipher", "<(module_root_dir)/<(sqlite)/include/openssl" ], // 添加 openssl 静态库支持
            "libraries": [
               "-l<(sqlite_libname)",
           "-l<(openssl_libname)" // 添加 openssl 静态库支持
            ],
            "conditions": [ [ "OS=='linux'", {"libraries+":["-Wl,-rpath=<(module_root_dir)/<@(sqlite)/lib"]} ] ],
            "conditions": [ [ "OS!='win'", {"libraries+":["-l<(openssl_libname)", "-L<(module_root_dir)/<@(sqlite)/lib"]} ] ], // 添加 openssl 静态库支持
        "conditions": [ [ "OS=='win'", {"libraries+":[ "-lmsvcrt", "crypt32.lib", "ws2_32.lib" ] } ] ], // windows 上, 我们需要添加 openssl 静态库支持, 同时需要加入openssl 的依赖
            'msvs_settings': {
              'VCLinkerTool': {
                'AdditionalLibraryDirectories': [
                  '<(module_root_dir)/<(sqlite)/lib'
                ],
        'IgnoreDefaultLibraryNames': [ // 由于在 Windows 上, Node.lib 中本身有 openssl 的代码, 因此我们如果要用 SQLCipher ,就需要智能忽略 openssl 库.
                  '<(openssl_libname).lib',
                  'crypt32.lib',
                  'ws2_32.lib'
        ],
              },
            }
        },
        {
            "dependencies": [
              "deps/sqlite3.gyp:sqlite3"
            ]
        }
        ]
      ],
      "sources": [
        "src/database.cc",
        "src/node_sqlite3.cc",
        "src/statement.cc"
      ]
    },
    {
      "target_name": "action_after_build",
      "type": "none",
      "dependencies": [ "<(module_name)" ],
      "copies": [
          {
            "files": [ "<(PRODUCT_DIR)/<(module_name).node" ],
            "destination": "<(module_path)"
          }
      ]
    }
  ]
}

添加 lib 库到 sqlcipher_lib 目录下. 这样, 我们就不需要再指定代码库了.

package.json 的修改

将 binary 中的 host 修改成一个无法访问的地址, 这样就无法从这里下载预编译好的 dll .这时候就只能从本地编译了.

添加 Backup 方法.

SQLite 支持 backup 方法. 但是在 Node-Sqlite3 中并不支持. 因此我们需要自己加入该方法. 在 database.cc 中加入如下代码:

NAN_METHOD(Database::Backup) {
    Database* db = Nan::ObjectWrap::Unwrap<Database>(info.This());
    REQUIRE_ARGUMENT_STRING(0, filename);
    REQUIRE_ARGUMENT_STRING(1, passcode);
    OPTIONAL_ARGUMENT_FUNCTION(2, callback);
    
    Local<Function> completed;
    int last = info.Length();

    if (last >= 3 && info[last - 1]->IsFunction() && info[last - 2]->IsFunction()) {
        completed = Local<Function>::Cast(info[--last]);
    }
    
    info.GetReturnValue().Set(info.This());
    
    Nan::ForceSet(info.This(), Nan::New("filename").ToLocalChecked(), info[0].As<String>(), ReadOnly);
    Nan::ForceSet(info.This(), Nan::New("passcode").ToLocalChecked(), info[0].As<String>(), ReadOnly);
//    Nan::ForceSet(info.This(), Nan::New("mode").ToLocalChecked(), Nan::New(mode), ReadOnly);
    
    // Start opening the database.
    BackupBaton* baton = new BackupBaton(db, callback, *filename, *passcode);
    baton->progress.Reset(completed);
    db->Schedule(Work_Backup, baton, true);

    info.GetReturnValue().Set(info.This());
}

/*
 https://www.sqlite.org/backup.html
 */
void Database::Work_Backup(Baton* b) {
    Nan::HandleScope scope;
    BackupBaton* baton = static_cast<BackupBaton*>(b);
    Database* db = baton->db;
    
    int rc;
    sqlite3 *pFile;
    sqlite3_backup *pBackup;

    assert(baton->db->locked);
    assert(baton->db->open);
    assert(baton->db->_handle);
    assert(baton->db->pending == 0);

    rc = sqlite3_open(baton->filename.c_str(), &pFile);
    // pKey 是密钥,nKey 是密钥长度
    sqlite3_key(pFile, baton->passcode.c_str(), strlen(baton->passcode.c_str()));
    if(rc==SQLITE_OK) {
        pBackup = sqlite3_backup_init(pFile, "main", baton->db->_handle, "main");
        if( pBackup ) {
            do {
                rc = sqlite3_backup_step(pBackup, 5);

                int remaining = sqlite3_backup_remaining(pBackup);
                int pagecount = sqlite3_backup_pagecount(pBackup);

                if (remaining > 0 && pagecount > 0) {
                    // Completion = 100% * (pagecount() - remaining()) / pagecount()
                    Local<Value> argv[] = {
                        Nan::Null(),
                        Nan::New((int)remaining),
                        Nan::New((int)pagecount)
                    };

                    Local<Function> cb = Nan::New(baton->progress);

                    if (!cb.IsEmpty() && cb->IsFunction()) {
                        TRY_CATCH_CALL(db->handle(), cb, 3, argv);
                    }
                }

                if( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
                    sqlite3_sleep(250);
                }
            } while( rc==SQLITE_OK || rc==SQLITE_BUSY || rc==SQLITE_LOCKED );
            (void)sqlite3_backup_finish(pBackup);
        }
        rc = sqlite3_errcode(pFile);
    }

    (void)sqlite3_close(pFile);
    
    // 2. 返回参数
    Local<Value> argv[1];
    if (baton->status != SQLITE_OK) {
        EXCEPTION(Nan::New(baton->message.c_str()).ToLocalChecked(), baton->status, exception);
        argv[0] = exception;
    } else {
        argv[0] = Nan::Null();
    }
    
    Local<Function> cb = Nan::New(baton->callback);
    
    if (!cb.IsEmpty() && cb->IsFunction()) {
        TRY_CATCH_CALL(db->handle(), cb, 1, argv);
    }
    
    delete baton;
}

其他的地方仿照其他部分修改一下即可. 这时候我们就加入了 backup 功能.

参考

Node-Sqlite3

SQLite Backup

GYP Setting 参数

相关文章

  • Node-Sqlite3 的修改详解

    由于我们需要使用静态库连接, 尽可能少的使用 dll .因此我们需要对 Node-Sqlite3 的源代码做出对应...

  • Mathtype与LaTeX公式

    A、Mathtype 快捷键 详解 MathType 使用快捷键输入常见符号 详解 MathType 批量修改公式...

  • linux文件访问权限

    参考 Linux 简单修改权限命令 Linux权限详解 命令之 chmod:修改权限 Linux命令:修改文件权限...

  • 大连滕泰科技学习笔记2020-05-06

    1,@AutoWired 的详解 2,@Value的详解 3,@一个接口多个实现的情况 4,案例讲解 将这项目修改...

  • iOS开发证书要点详解

    转自 iOS开发证书要点详解,ios证书详解 有细节修改。 首先,假设你使用过Apple设备(iMac/iPad/...

  • Django web框架-----url path name详解

    Django web框架-----url path name详解 quicktool/view.py文件修改视图函...

  • Android模拟器修改hosts文件详解

    Android模拟器修改hosts文件详解 引:通过修改android模拟器hosts文件实现访问本地局域网域名服...

  • 饭店流量预测

    lightgbm 模型 修改参数 交叉验证 【机器学习】Cross-Validation(交叉验证)详解. 在机器...

  • mongoose基本使用

    package.js详解 参考 mongoose基本使用 安装 连接 定义模型 新增 查询 修改 删除 [更多其它...

  • C++ STL alg

    四类:STL算法原文详解 1、非可变序列算法:指不直接修改其所操作的容器内容的算法。 2、可变序列算法:指可以修改...

网友评论

      本文标题:Node-Sqlite3 的修改详解

      本文链接:https://www.haomeiwen.com/subject/dtdafqtx.html