├── lib └── unqlite.js ├── .gitignore ├── .npmignore ├── .shipit.json ├── .travis.yml ├── package.json ├── typings └── index.d.ts ├── binding.gyp ├── LICENSE ├── unqlite ├── license.txt └── unqlite.h ├── History.md ├── src ├── macro.h ├── node_unqlite.h ├── node_unqlite_async.h ├── node_unqlite_async.cc └── node_unqlite.cc ├── test └── test.js └── README.md /lib/unqlite.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./node_unqlite'); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | .lock-wscript 4 | build 5 | lib/node_unqlite.node 6 | node_modules 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | .gitignore 4 | .lock-wscript 5 | .shipit.json 6 | .travis.yml 7 | .git/ 8 | build/ 9 | npm_modules/ 10 | 11 | -------------------------------------------------------------------------------- /.shipit.json: -------------------------------------------------------------------------------- 1 | { 2 | "steps": ["FindVersion", "ChangeVersion", "CheckChangeLog", "Commit", "Tag", "Publish"], 3 | "CheckChangeLog": { 4 | "files": ["History.md"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - "0.10" 4 | - "0.12" 5 | - "4.0" 6 | - "6.10" 7 | - "8.0" 8 | addons: 9 | apt: 10 | sources: 11 | - ubuntu-toolchain-r-test 12 | packages: 13 | - g++-4.8 14 | before_install: 15 | - export CXX="g++-4.8" 16 | sudo: false 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unqlite", 3 | "version": "0.3.5", 4 | "description": "Node.js binding of UnQLite", 5 | "main": "lib/unqlite.js", 6 | "types": "typings/index.d.ts", 7 | "scripts": { 8 | "test": "mocha -R spec test/test.js" 9 | }, 10 | "engines": { 11 | "node": ">=0.12.0" 12 | }, 13 | "dependencies": { 14 | "nan": "^2.4.0" 15 | }, 16 | "devDependencies": { 17 | "mocha": "3.2.0", 18 | "temp": "" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git://github.com/hideo55/node-unqlite.git" 23 | }, 24 | "keywords": [ 25 | "UnQLite" 26 | ], 27 | "author": "Hideaki Ohno ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/hideo55/node-unqlite/issues" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /typings/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'unqlite' { 2 | 3 | export const enum OpenMode { 4 | OPEN_READONLY = 0x00000001, 5 | OPEN_READWRITE = 0x00000002, 6 | OPEN_CREATE = 0x00000004, 7 | OPEN_EXCLUSIVE = 0x00000008, 8 | OPEN_TEMP_DB = 0x00000010, 9 | OPEN_NOMUTEX = 0x00000020, 10 | OPEN_OMIT_JOURNALING = 0x00000040, 11 | OPEN_IN_MEMORY = 0x00000080, 12 | OPEN_MMAP = 0x00000100 13 | } 14 | 15 | export class Database { 16 | constructor(filename: string); 17 | open(openMode: OpenMode, callback: (err: any) => void); 18 | close(callback: (err: any) => void); 19 | store(key: string, value: string, callback: (err: any, key: string, value: string) => void); 20 | append(key: string, value: string, callback: (err: any, key: string, value: string) => void); 21 | fetch(key: string, callback: (err: any, key: string, value: string) => void); 22 | delete(key: string, callback: (err: any, key: string) => void); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | 'target_name': 'node_unqlite', 5 | 'include_dirs': ['unqlite', "]. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SYMISC SYSTEMS ``AS IS'' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 17 | * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SYMISC SYSTEMS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 21 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 23 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | # Revision history for unqlite 2 | 3 | 0.3.5 / 2017-06-01 4 | ================== 5 | 6 | * Add workaround for gyp issue: nodejs/node-gyp#1151 7 | * Use Nan::ForceSet() instead of v8::Object::ForceSet() 8 | 9 | 0.3.4 / 2016-06-29 10 | ================== 11 | 12 | * Update version of NAN 13 | 14 | 0.3.3 / 2015-08-20 15 | ================== 16 | 17 | * Add support for io.js v3 18 | 19 | 0.3.2 / 2015-07-10 20 | ================== 21 | 22 | * Update document 23 | 24 | 0.3.1 / 2015-05-09 25 | ================== 26 | 27 | * Update version of NAN 28 | 29 | 0.3.0 / 2015-02-07 30 | ================== 31 | 32 | * Change way to make constant values. 33 | * io.js ready 34 | 35 | 0.2.4 / 2014-06-12 36 | ================== 37 | 38 | * Update docs 39 | 40 | 0.2.3 / 2014-05-25 41 | ================== 42 | 43 | * Change version of nan(1.10) 44 | 45 | 0.2.2 / 2014-05-08 46 | ================== 47 | 48 | * Change version of nan(Exact match with 1.0.0) 49 | 50 | 0.2.1 / 2014-05-06 51 | ================== 52 | 53 | * Support Node.js v0.11.13(V8 3.25)) 54 | 55 | 0.2.0 / 2014-05-05 56 | ================== 57 | 58 | * [Incompatible change] Change constant var name. 59 | 60 | 0.1.2 / 2014-05-05 61 | ================== 62 | 63 | * Delete unimplemented constants 64 | * Improved document 65 | 66 | 0.1.1 / 2014-04-30 67 | ================== 68 | 69 | * Fixed error message handling 70 | * Improved document 71 | 72 | 0.1.0 / 2014-04-30 73 | ================== 74 | 75 | * [Incompatible change] Change API 76 | * Support Node.js v0.12 77 | 78 | 0.0.1 / 2013-07-14 79 | ================== 80 | 81 | * Initial release 82 | 83 | -------------------------------------------------------------------------------- /src/macro.h: -------------------------------------------------------------------------------- 1 | #if !defined(NODE_UNQLITE_MACRO_H) 2 | #define NODE_UNQLITE_MACRO_H 3 | 4 | #include "nan.h" 5 | #include 6 | 7 | #define REQ_ARG_COUNT_AND_TYPE(I, TYPE) \ 8 | if (info.Length() < (I + 1) ) { \ 9 | std::stringstream __ss; \ 10 | __ss << "A least " << I + 1 << " arguments are required"; \ 11 | return Nan::ThrowRangeError(__ss.str().c_str()); \ 12 | } else if (!info[I]->Is##TYPE()) { \ 13 | std::stringstream __ss; \ 14 | __ss << "Argument " << I + 1 << " must be a " #TYPE; \ 15 | return Nan::ThrowTypeError(__ss.str().c_str()); \ 16 | } 17 | 18 | // validate the argument type is 'function' or not. 19 | #define REQ_FUN_ARG(I, VAR) \ 20 | REQ_ARG_COUNT_AND_TYPE(I, Function) \ 21 | Local VAR = info[I].As(); 22 | 23 | // validate the argument type is 'string' or not. 24 | #define REQ_STR_ARG(I) REQ_ARG_COUNT_AND_TYPE(I, String) 25 | 26 | #define TRY_CATCH_CALL(context, callback, argc, argv) \ 27 | TryCatch try_catch; \ 28 | (callback)->Call((context), (argc), (argv)); \ 29 | if (try_catch.HasCaught()) { \ 30 | FatalException(try_catch); \ 31 | } 32 | 33 | #define DEFINE_CONSTANT_INTEGER(target, constant, name) \ 34 | Nan::ForceSet(target, \ 35 | Nan::New(#name).ToLocalChecked(), \ 36 | Nan::New(constant), \ 37 | static_cast(ReadOnly | DontDelete) \ 38 | ); 39 | 40 | 41 | #endif /* NODE_UNQLITE_MACRO_H */ 42 | -------------------------------------------------------------------------------- /src/node_unqlite.h: -------------------------------------------------------------------------------- 1 | #if !defined(NODE_UNQLITE_H) 2 | #define NODE_UNQLITE_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include "macro.h" 9 | #include 10 | 11 | extern "C" { 12 | #include "unqlite.h" 13 | } 14 | 15 | namespace node_unqlite { 16 | 17 | class NodeUnQLite: public node::ObjectWrap { 18 | public: 19 | 20 | /** 21 | * @brief Constructor 22 | */ 23 | NodeUnQLite(); 24 | 25 | /** 26 | * @brief Destructor 27 | */ 28 | virtual ~NodeUnQLite(); 29 | 30 | /** 31 | * @brief Initialize NodeUnQLite class as Node.js addon 32 | */ 33 | static void Init(v8::Handle exports); 34 | 35 | static NAN_METHOD (New); 36 | 37 | static NAN_METHOD (Open); 38 | 39 | static NAN_METHOD (Close); 40 | 41 | static NAN_METHOD (StoreKV); 42 | 43 | static NAN_METHOD (AppendKV); 44 | 45 | static NAN_METHOD (DeleteKV); 46 | 47 | static NAN_METHOD (FetchKV); 48 | 49 | /** 50 | * @brief Open database 51 | * @param[in] filename 52 | * @param[in] mode 53 | * @return status code 54 | */ 55 | int open_db(const char* filename, int mode); 56 | 57 | /** 58 | * @brief Close database 59 | * @return status code 60 | */ 61 | int close_db(); 62 | 63 | /** 64 | * @brief Return whether the database is opened. 65 | * @retval true Database is opend. 66 | * @retval false Database is closed. 67 | */ 68 | bool is_opened(); 69 | 70 | /** 71 | * @brief Fetch value from the database. 72 | * @param key[in] 73 | * @param value[out] 74 | * @return status code 75 | */ 76 | int fetch_kv(std::string& key, std::string& value); 77 | 78 | /** 79 | * @brief Store key and value to the database. 80 | * @param key[in] 81 | * @param value[in] 82 | * @return status code 83 | */ 84 | int store_kv(std::string& key, std::string& value); 85 | 86 | /** 87 | * @brief Append value to the database. 88 | * @param key[in] 89 | * @param value[in] 90 | * @return status code 91 | */ 92 | int append_kv(std::string& key, std::string& value); 93 | 94 | /** 95 | * @brief Delete key from the database. 96 | * @param key[in] 97 | * @return status code 98 | */ 99 | int delete_kv(std::string& key); 100 | 101 | /** 102 | * @brief Get error message of status code. 103 | * @param[in] status Status code 104 | * @param[out] Error message 105 | */ 106 | void get_error_message(std::string& message); 107 | 108 | 109 | private: 110 | static Nan::Persistent constructor_template; 111 | unqlite* db_; 112 | bool open_; 113 | }; 114 | 115 | } // namespace node_unqlite 116 | 117 | #endif /* NODE_UNQLITE_H */ 118 | -------------------------------------------------------------------------------- /src/node_unqlite_async.h: -------------------------------------------------------------------------------- 1 | #if !defined(NODE_UNQLITE_ASYNC_H) 2 | #define NODE_UNQLITE_ASYNC_H 3 | 4 | #include "node_unqlite.h" 5 | 6 | namespace node_unqlite { 7 | 8 | typedef enum { 9 | T_UNQLITE_FETCH, T_UNQLITE_STORE, T_UNQLITE_APPEND, T_UNQLITE_DELETE 10 | } UnQLiteAccessType; 11 | 12 | 13 | /** 14 | * @brief Base class of UnQLite asynchronous worker 15 | */ 16 | class UnQLiteAsyncWorker : public Nan::AsyncWorker { 17 | public: 18 | /** 19 | * @brief Constructor 20 | * @param callback[in] Callback functio object 21 | * @param uql[in] NodeUnQLite instance 22 | */ 23 | UnQLiteAsyncWorker(Nan::Callback *callback, NodeUnQLite* uql); 24 | 25 | 26 | protected: 27 | NodeUnQLite* unqlite_; /// NodeUnQLite instance 28 | int status_; /// File open status 29 | 30 | /** 31 | * Set error message for async worker 32 | * @param message[in] Error message 33 | */ 34 | void SetErrorMessage(const char* message); 35 | }; 36 | 37 | /** 38 | * @brief Asynchronous worker for open database 39 | */ 40 | class OpenWorker: public UnQLiteAsyncWorker { 41 | public: 42 | /** 43 | * @brief Constructor 44 | * @param callback[in] Callback functio object 45 | * @param uql[in] NodeUnQLite instance 46 | * @param filename[in] Name of the file to open 47 | * @param mode[in] UnQLite open mode 48 | */ 49 | OpenWorker(Nan::Callback *callback, NodeUnQLite* uql, std::string& filename, int mode); 50 | 51 | /** 52 | * @brief Open UnQLite file 53 | */ 54 | void Execute(); 55 | 56 | /** 57 | * @brief Invoke callback function 58 | */ 59 | void HandleOKCallback(); 60 | 61 | private: 62 | std::string filename_; /// File name 63 | int mode_; /// Open mode 64 | }; 65 | 66 | /** 67 | * @brief Asynchronous worker for close database 68 | */ 69 | class CloseWorker: public UnQLiteAsyncWorker { 70 | public: 71 | /** 72 | * @brief Constructor 73 | * @param callback[in] Callback functio object 74 | * @param uql[in] NodeUnQLite instance 75 | */ 76 | CloseWorker(Nan::Callback *callback, NodeUnQLite* uql); 77 | 78 | /** 79 | * @brief Open UnQLite file 80 | */ 81 | void Execute(); 82 | 83 | /** 84 | * @brief Invoke callback function 85 | */ 86 | void HandleOKCallback(); 87 | }; 88 | 89 | // Asyncronous worker for database access 90 | class AccessWorker: public UnQLiteAsyncWorker { 91 | public: 92 | /** 93 | * @brief Constructor 94 | * @param callback[in] Callback functio object 95 | * @param uql[in] NodeUnQLite instance 96 | * @param type[in] Access type 97 | * @param key[in] Key 98 | */ 99 | AccessWorker(Nan::Callback *callback, NodeUnQLite* uql, UnQLiteAccessType type, std::string key); 100 | 101 | /** 102 | * @brief Constructor 103 | * @param callback[in] Callback functio object 104 | * @param uql[in] NodeUnQLite instance 105 | * @param type[in] Access type 106 | * @param key[in] Key 107 | * @param value[in] Value 108 | */ 109 | AccessWorker(Nan::Callback *callback, NodeUnQLite* uql, UnQLiteAccessType type, std::string key, std::string value); 110 | 111 | /** 112 | * @brief Access to the UnQLite DB 113 | */ 114 | void Execute(); 115 | 116 | /** 117 | * @brief Invoke callback function 118 | */ 119 | void HandleOKCallback(); 120 | 121 | private: 122 | UnQLiteAccessType type_; 123 | std::string key_; 124 | std::string value_; 125 | }; 126 | 127 | } // namespace node_unqlite 128 | 129 | #endif // NODE_UNQLITE_ASYNC_H 130 | -------------------------------------------------------------------------------- /src/node_unqlite_async.cc: -------------------------------------------------------------------------------- 1 | #include "node_unqlite_async.h" 2 | #include "unqlite.h" 3 | 4 | namespace node_unqlite { 5 | 6 | UnQLiteAsyncWorker::UnQLiteAsyncWorker(Nan::Callback *callback, NodeUnQLite* uql) : 7 | Nan::AsyncWorker(callback), unqlite_(uql), status_(UNQLITE_OK) { 8 | } 9 | 10 | void UnQLiteAsyncWorker::SetErrorMessage(const char* message) { 11 | if (status_ != UNQLITE_OK) { 12 | std::string errLog; 13 | unqlite_->get_error_message(errLog); 14 | std::stringstream ss; 15 | ss << message << " : "; 16 | if (errLog.size() > 0) { 17 | ss << errLog; 18 | } else { 19 | ss << status_; 20 | } 21 | Nan::AsyncWorker::SetErrorMessage(ss.str().c_str()); 22 | } 23 | } 24 | 25 | // OpenWorker 26 | OpenWorker::OpenWorker(Nan::Callback *callback, NodeUnQLite* uql, std::string& filename, int mode) : 27 | UnQLiteAsyncWorker(callback, uql), filename_(filename), mode_(mode) { 28 | } 29 | 30 | void OpenWorker::Execute() { 31 | status_ = unqlite_->open_db(filename_.c_str(), mode_); 32 | SetErrorMessage("Failed to open"); 33 | } 34 | 35 | void OpenWorker::HandleOKCallback() { 36 | Nan::HandleScope scope; 37 | v8::Local argv[] = {Nan::Null()}; 38 | callback->Call(1, argv); 39 | } 40 | 41 | // CloseWorker 42 | CloseWorker::CloseWorker(Nan::Callback *callback, NodeUnQLite* uql) : 43 | UnQLiteAsyncWorker(callback, uql) { 44 | } 45 | 46 | void CloseWorker::Execute() { 47 | status_ = unqlite_->close_db(); 48 | SetErrorMessage("Failed to close"); 49 | } 50 | 51 | void CloseWorker::HandleOKCallback() { 52 | Nan::HandleScope scope; 53 | v8::Local argv[] = {Nan::Null()}; 54 | callback->Call(1, argv); 55 | } 56 | 57 | // AccessWorker 58 | 59 | AccessWorker::AccessWorker(Nan::Callback *callback, NodeUnQLite* uql, UnQLiteAccessType type, std::string key) : 60 | UnQLiteAsyncWorker(callback, uql), type_(type), key_(key), value_() { 61 | } 62 | 63 | AccessWorker::AccessWorker(Nan::Callback *callback, NodeUnQLite* uql, UnQLiteAccessType type, std::string key, 64 | std::string value) : 65 | UnQLiteAsyncWorker(callback, uql), type_(type), key_(key), value_(value) { 66 | } 67 | 68 | void AccessWorker::Execute() { 69 | if (!unqlite_->is_opened()) { 70 | std::string err = "Database not opened."; 71 | Nan::AsyncWorker::SetErrorMessage(err.c_str()); 72 | return; 73 | } 74 | 75 | switch (type_) { 76 | case T_UNQLITE_FETCH: 77 | status_ = unqlite_->fetch_kv(key_, value_); 78 | SetErrorMessage("Failed to fetch"); 79 | break; 80 | case T_UNQLITE_STORE: 81 | status_ = unqlite_->store_kv(key_, value_); 82 | SetErrorMessage("Failed to store"); 83 | break; 84 | case T_UNQLITE_APPEND: 85 | status_ = unqlite_->append_kv(key_, value_); 86 | SetErrorMessage("Failed to append"); 87 | break; 88 | case T_UNQLITE_DELETE: 89 | status_ = unqlite_->delete_kv(key_); 90 | SetErrorMessage("Failed to delete"); 91 | break; 92 | default: 93 | break; 94 | }; 95 | } 96 | 97 | void AccessWorker::HandleOKCallback() { 98 | Nan::HandleScope scope; 99 | v8::Local argv[] = { 100 | Nan::Null(), 101 | Nan::New(key_.c_str(), key_.size()).ToLocalChecked(), 102 | Nan::New(value_.c_str(), value_.size()).ToLocalChecked() 103 | }; 104 | callback->Call(3, argv); 105 | } 106 | 107 | } // namespace node_unqlite 108 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var unqlite = require('../lib/unqlite'); 2 | var DB = unqlite.Database; 3 | 4 | var assert = require('assert'); 5 | 6 | describe('open', function() { 7 | var temp = require('temp'); 8 | var path = require('path'); 9 | 10 | var dbFile; 11 | 12 | beforeEach(function(cb) { 13 | temp.mkdir(null, function(err, tempPath) { 14 | if (err) { 15 | cb(err); 16 | } 17 | dbFile = path.join(tempPath, 'test_open.db'); 18 | cb(); 19 | }); 20 | }); 21 | 22 | it('default', function(done) { 23 | var uql = new DB(dbFile); 24 | uql.open(function(err) { 25 | assert.equal(err, null); 26 | done(); 27 | }); 28 | }); 29 | 30 | describe('mode', function() { 31 | it('with READONLY', function(done) { 32 | var uql = new DB(dbFile); 33 | uql.open(unqlite.OPEN_READONLY, function() { 34 | assert.equal(uql.mode, unqlite.OPEN_READONLY); 35 | done(); 36 | }); 37 | }); 38 | 39 | it('with READWRITE', function(done) { 40 | var uql = new DB(dbFile); 41 | uql.open(unqlite.OPEN_READWRITE, function() { 42 | assert.equal(uql.mode, unqlite.OPEN_READWRITE); 43 | done(); 44 | }); 45 | }); 46 | 47 | it('with MMAP', function(done) { 48 | var uql = new DB(dbFile); 49 | uql.open(unqlite.OPEN_MMAP, function() { 50 | assert.equal(uql.mode, unqlite.OPEN_MMAP); 51 | done(); 52 | }); 53 | }); 54 | 55 | it('with IN_MEMORY', function(done) { 56 | var uql = new DB(dbFile); 57 | uql.open(unqlite.OPEN_IN_MEMORY, function() { 58 | assert.equal(uql.mode, unqlite.OPEN_IN_MEMORY); 59 | done(); 60 | }); 61 | }); 62 | }); 63 | 64 | it('close', function(done) { 65 | var uql = new DB(dbFile); 66 | uql.open(function() { 67 | uql.close(function(err) { 68 | assert.equal(err, null); 69 | done(); 70 | }); 71 | }); 72 | }); 73 | }); 74 | 75 | describe('Key/Value API', function() { 76 | it('store API', function(done) { 77 | var uql = new DB('test/test.db'); 78 | uql.open(unqlite.OPEN_IN_MEMORY, function() { 79 | uql.store('foo', 'bar', function(err, key, value) { 80 | assert.equal(key, 'foo'); 81 | assert.equal(value, 'bar'); 82 | done(); 83 | }); 84 | }); 85 | }); 86 | 87 | it('fetch API', function(done) { 88 | var uql = new DB('test/test.db'); 89 | uql.open(unqlite.OPEN_IN_MEMORY, function() { 90 | uql.store('foo', 'bar', function(err, key, value) { 91 | uql.fetch(key, function(err, key, value) { 92 | assert.equal(value, 'bar'); 93 | done(); 94 | }); 95 | }); 96 | }); 97 | }); 98 | 99 | it('append API', function(done) { 100 | var uql = new DB('test/test.db'); 101 | uql.open(unqlite.OPEN_IN_MEMORY, function() { 102 | uql.store('foo', 'bar', function() { 103 | uql.append('foo', 'baz', function(err, key, value) { 104 | uql.fetch(key, function(err, key, value) { 105 | assert.equal(value, 'barbaz'); 106 | done(); 107 | }); 108 | }); 109 | }); 110 | }); 111 | }); 112 | 113 | it('delete API', function(done) { 114 | var uql = new DB('test/test.db'); 115 | uql.open(unqlite.OPEN_IN_MEMORY, function() { 116 | uql.store('foo', 'bar', function(err, key, value) { 117 | uql. 118 | delete ('foo', 119 | function(err, key) { 120 | uql.fetch(key, function(err, key, value) { 121 | assert.notEqual(err, null); 122 | assert.ok(err.message.match(/^Failed to fetch/)); 123 | done(); 124 | }); 125 | }); 126 | }); 127 | }); 128 | }); 129 | }); 130 | 131 | describe('exceptions', function() { 132 | describe('new', function() { 133 | it('argument missing', function(done) { 134 | try { 135 | var uql = new DB(); 136 | assert.fail(); 137 | } catch(e) { 138 | assert.ok( e instanceof RangeError); 139 | assert.ok(e.message.match(/A least 1 arguments are required/)); 140 | done(); 141 | } 142 | }); 143 | it('argument is not string', function(done) { 144 | try { 145 | var uql = new DB(1); 146 | assert.fail(); 147 | } catch(e) { 148 | assert.ok( e instanceof TypeError); 149 | assert.ok(e.message.match(/Argument 1 must be a String/)); 150 | done(); 151 | } 152 | }); 153 | }); 154 | describe('open', function() { 155 | it('callback missing', function(done) { 156 | try { 157 | var uql = new DB(''); 158 | uql.open(); 159 | assert.fail('Must be fail'); 160 | } catch(e) { 161 | assert.ok( e instanceof RangeError); 162 | assert.ok(e.message.match(/A least 1 arguments are required/)); 163 | done(); 164 | }; 165 | }); 166 | 167 | it('callback is not function', function(done) { 168 | try { 169 | var uql = new DB(''); 170 | uql.open(0, 0); 171 | assert.fail('Must be fail'); 172 | } catch(e) { 173 | assert.ok( e instanceof TypeError); 174 | assert.ok(e.message.match(/Argument 2 must be a Function/)); 175 | done(); 176 | }; 177 | }); 178 | 179 | }); 180 | }); 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unqlite 2 | 3 | Node.js binding for [UnQLite](http://unqlite.org/). 4 | This module provides simple Key/Value store functions of UnQLite. 5 | 6 | [![Build Status](https://travis-ci.org/hideo55/node-unqlite.svg?branch=master)](http://travis-ci.org/hideo55/node-unqlite) 7 | [![npm](https://img.shields.io/npm/v/unqlite.svg)](https://www.npmjs.com/package/unqlite) 8 | 9 | ## Installation 10 | 11 | $ npm install unqlite 12 | 13 | or 14 | 15 | $ git clone https://github.com/hideo55/node-unqlite.git 16 | $ npm install ./node-unqlite 17 | 18 | ## Usage 19 | 20 | ```JavaScript 21 | var unqlite = require('unqlite'); 22 | 23 | var db = new unqlite.Database('/path/to/db'); 24 | db.open(unqlite.OPEN_CREATE, function(err){ 25 | if(err) throw err; 26 | db.store('example key', 'example value', function(err, key, value){ 27 | db.close(function(err){// commit change to the database 28 | ... 29 | }); 30 | }); 31 | }); 32 | ``` 33 | 34 | ## API 35 | 36 | ### new Database(filename) 37 | 38 | Create new instance. 39 | 40 | - `filename` is file-path of UnQLite database. 41 | 42 | ### open([mode,] callback) 43 | 44 | Opening a new database handle and start transaction. 45 | 46 | - `mode` is database access mode. See Constants section. 47 | - If the `mode` parameter is omitted, the database is opened in `OPEN_CREATE` mode. 48 | - `callback` will called with a sigle argument `error`. 49 | 50 | ### close(callback) 51 | 52 | Closing a database handle and commit all changes to the database. 53 | 54 | - `callback` will called with a sigle argument `error`. 55 | 56 | ### store(key, value, callback) 57 | 58 | Store records in the database. 59 | 60 | - `key` is record key. 61 | - `value` is record data. 62 | - `callback` will called with a three arguments `(error, key, value)`. 63 | 64 | ### append(key, value, callback) 65 | 66 | Append data to a database record. 67 | 68 | - `key` is record key. 69 | - `value` is record data. 70 | - `callback` will called with a three arguments `(error, key, value)`. 71 | 72 | ### fetch(key, callback) 73 | 74 | Fetch a record from the database. 75 | 76 | - `key` is record key. 77 | - `callback` will called with a three arguments `(error, key, value)`. 78 | 79 | ### delete(key, callback) 80 | 81 | Remove a record from the database. 82 | 83 | - `key` is record key. 84 | - `callback` will called with a two arguments `(error, key)`. 85 | 86 | 87 | ## Constants 88 | 89 | See also [http://unqlite.org/c_api/unqlite_open.html](http://unqlite.org/c_api/unqlite_open.html) 90 | 91 | - **OPEN_CREATE** 92 | - If the database does not exists, it is created. Otherwise, it is opened with read+write privileges. 93 | - **OPEN_READWRITE** 94 | - Open the database with read+write privileges. 95 | - **OPEN_READONLY** 96 | - Open the database in a read-only mode. 97 | - **OPEN_MMAP** 98 | - Obtain a read-only memory view of the whole database. 99 | - **OPEN_EXCLUSIVE** 100 | - Creates a new file, only if it does not already exist. If the file exists, it fails. 101 | - **OPEN_TEMP** 102 | - A private, temporary on-disk database will be created. This private database will be automatically deleted as soon as the database connection is closed. 103 | - **OPEN_IN_MEMORY** 104 | - A private, in-memory database will be created. The in-memory database will vanish when the database connection is closed. 105 | - **OPEN_OMIT_JOURNALING** 106 | - (Not recommended) Disable journaling for this database. In other words, you will not be able to rollback your database after a crash or power failure. This flag is automatically set for temporary database. 107 | - **OPEN_NOMUTEX** 108 | - (Not recommended) Disable the private recursive mutex associated with each database handle. When set, you should not share this handle between multiple threads. Otherwise, the result is undefined. 109 | 110 | 111 | ## Unsupported features 112 | 113 | - Cursor 114 | - Document Store (JSON via Jx9) 115 | - Manual Transaction Manager 116 | 117 | ## Version of UnQLite 118 | 119 | 1.1.7 120 | 121 | ## Requirement 122 | 123 | Node v0.12 or later 124 | 125 | ## Author 126 | 127 | Hideaki Ohno <hide.o.j55{at}gmail.com> 128 | 129 | ## License 130 | 131 | (The MIT License) 132 | 133 | Copyright (c) 2013-2017 Hideaki Ohno <hide.o.j55{at}gmail.com> 134 | 135 | Permission is hereby granted, free of charge, to any person obtaining 136 | a copy of this software and associated documentation files (the 137 | 'Software'), to deal in the Software without restriction, including 138 | without limitation the rights to use, copy, modify, merge, publish, 139 | distribute, sublicense, and/or sell copies of the Software, and to 140 | permit persons to whom the Software is furnished to do so, subject to 141 | the following conditions: 142 | 143 | The above copyright notice and this permission notice shall be 144 | included in all copies or substantial portions of the Software. 145 | 146 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 147 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 148 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 149 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 150 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 151 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 152 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 153 | 154 | -------------------------------------------------------------------------------- /src/node_unqlite.cc: -------------------------------------------------------------------------------- 1 | /*! 2 | * node-unqlite 3 | * Copyright(c) 2013 Hideaki Ohno 4 | * MIT Licensed 5 | */ 6 | #ifndef BUILDING_NODE_EXTENSION 7 | #define BUILDING_NODE_EXTENSION 8 | #endif 9 | 10 | #include "node_unqlite.h" 11 | #include "node_unqlite_async.h" 12 | #include 13 | 14 | using namespace v8; 15 | using namespace node; 16 | 17 | namespace node_unqlite { 18 | 19 | Nan::Persistent NodeUnQLite::constructor_template; 20 | 21 | void NodeUnQLite::Init(Handle exports) { 22 | Nan::HandleScope scope; 23 | 24 | Local < FunctionTemplate > t = Nan::New(NodeUnQLite::New); 25 | constructor_template.Reset(t); 26 | t->InstanceTemplate()->SetInternalFieldCount(1); 27 | t->SetClassName(Nan::New("Database").ToLocalChecked()); 28 | 29 | Nan::SetPrototypeMethod(t, "open", Open); 30 | Nan::SetPrototypeMethod(t, "close", Close); 31 | Nan::SetPrototypeMethod(t, "fetch", FetchKV); 32 | Nan::SetPrototypeMethod(t, "store", StoreKV); 33 | Nan::SetPrototypeMethod(t, "append", AppendKV); 34 | Nan::SetPrototypeMethod(t, "delete", DeleteKV); 35 | 36 | exports->Set(Nan::New("Database").ToLocalChecked(), t->GetFunction()); 37 | } 38 | 39 | NodeUnQLite::NodeUnQLite() : 40 | db_(NULL), open_(false) { 41 | } 42 | 43 | NodeUnQLite::~NodeUnQLite() { 44 | if (db_ != NULL) { 45 | close_db(); 46 | } 47 | } 48 | 49 | NAN_METHOD(NodeUnQLite::New){ 50 | Nan::HandleScope scope; 51 | 52 | REQ_STR_ARG(0) 53 | std::string filename = *String::Utf8Value(info[0]->ToString()); 54 | 55 | NodeUnQLite* uql = new NodeUnQLite(); 56 | uql->Wrap(info.Holder()); 57 | Nan::ForceSet(info.This(), Nan::New("filename").ToLocalChecked(), info[0]->ToString(), ReadOnly); 58 | 59 | info.GetReturnValue().Set(info.Holder()); 60 | } 61 | 62 | NAN_METHOD(NodeUnQLite::Open){ 63 | Nan::HandleScope scope; 64 | 65 | int pos = 0; 66 | 67 | int mode; 68 | if (info.Length() >= pos && info[pos]->IsInt32()) { 69 | mode = info[pos++]->Int32Value(); 70 | } else { 71 | mode = UNQLITE_OPEN_CREATE; 72 | } 73 | 74 | REQ_FUN_ARG(pos, cb); 75 | 76 | NodeUnQLite* uql = Unwrap(info.Holder()); 77 | Nan::ForceSet(info.This(), Nan::New("mode").ToLocalChecked(), Nan::New(mode), ReadOnly); 78 | std::string filename = *String::Utf8Value(info.This()->Get(Nan::New("filename").ToLocalChecked())); 79 | 80 | Nan::Callback *callback = new Nan::Callback(cb); 81 | Nan::AsyncQueueWorker(new OpenWorker(callback, uql, filename, mode)); 82 | info.GetReturnValue().SetUndefined(); 83 | } 84 | 85 | NAN_METHOD(NodeUnQLite::Close) { 86 | Nan::HandleScope scope; 87 | REQ_FUN_ARG(0, cb); 88 | NodeUnQLite* uql = Unwrap(info.Holder()); 89 | Nan::Callback *callback = new Nan::Callback(cb); 90 | Nan::AsyncQueueWorker(new CloseWorker(callback, uql)); 91 | info.GetReturnValue().SetUndefined(); 92 | } 93 | 94 | NAN_METHOD(NodeUnQLite::FetchKV){ 95 | Nan::HandleScope scope; 96 | 97 | REQ_STR_ARG(0) 98 | std::string key = *String::Utf8Value(info[0]->ToString()); 99 | REQ_FUN_ARG(1, cb); 100 | 101 | NodeUnQLite* uql = Unwrap(info.Holder()); 102 | 103 | Nan::Callback *callback = new Nan::Callback(cb); 104 | Nan::AsyncQueueWorker(new AccessWorker(callback, uql, T_UNQLITE_FETCH, key)); 105 | 106 | info.GetReturnValue().SetUndefined(); 107 | } 108 | 109 | NAN_METHOD(NodeUnQLite::StoreKV){ 110 | Nan::HandleScope scope; 111 | REQ_STR_ARG(0) 112 | std::string key = *String::Utf8Value(info[0]->ToString()); 113 | REQ_STR_ARG(1) 114 | std::string value = *String::Utf8Value(info[1]->ToString()); 115 | 116 | REQ_FUN_ARG(2, cb); 117 | 118 | NodeUnQLite* uql = Unwrap(info.Holder()); 119 | 120 | Nan::Callback *callback = new Nan::Callback(cb); 121 | Nan::AsyncQueueWorker(new AccessWorker(callback, uql, T_UNQLITE_STORE, key, value)); 122 | 123 | info.GetReturnValue().SetUndefined(); 124 | } 125 | 126 | NAN_METHOD(NodeUnQLite::AppendKV){ 127 | Nan::HandleScope scope; 128 | 129 | REQ_STR_ARG(0) 130 | std::string key = *String::Utf8Value(info[0]->ToString()); 131 | REQ_STR_ARG(1) 132 | std::string value = *String::Utf8Value(info[1]->ToString()); 133 | 134 | REQ_FUN_ARG(2, cb); 135 | 136 | NodeUnQLite* uql = Unwrap(info.Holder()); 137 | 138 | Nan::Callback *callback = new Nan::Callback(cb); 139 | Nan::AsyncQueueWorker(new AccessWorker(callback, uql, T_UNQLITE_APPEND, key, value)); 140 | 141 | info.GetReturnValue().SetUndefined(); 142 | } 143 | 144 | NAN_METHOD(NodeUnQLite::DeleteKV){ 145 | Nan::HandleScope scope; 146 | 147 | REQ_STR_ARG(0) 148 | std::string key = *String::Utf8Value(info[0]->ToString()); 149 | 150 | REQ_FUN_ARG(1, cb); 151 | 152 | NodeUnQLite* uql = Unwrap(info.Holder()); 153 | 154 | Nan::Callback *callback = new Nan::Callback(cb); 155 | Nan::AsyncQueueWorker(new AccessWorker(callback, uql, T_UNQLITE_DELETE, key)); 156 | 157 | info.GetReturnValue().SetUndefined(); 158 | } 159 | 160 | int NodeUnQLite::open_db(const char* filename, int mode) { 161 | int status = unqlite_open(&(db_), filename, mode); 162 | if (status != UNQLITE_OK) { 163 | close_db(); 164 | open_ = false; 165 | } else { 166 | open_ = true; 167 | } 168 | return status; 169 | } 170 | 171 | int NodeUnQLite::close_db() { 172 | if(!open_){ 173 | return UNQLITE_OK; 174 | } 175 | int status = unqlite_close(db_); 176 | if (status == UNQLITE_OK) { 177 | db_ = NULL; 178 | open_ = false; 179 | } 180 | return status; 181 | } 182 | 183 | bool NodeUnQLite::is_opened() { 184 | return open_; 185 | } 186 | 187 | int NodeUnQLite::fetch_kv(std::string& key, std::string& value) { 188 | unqlite_int64 val_size; 189 | int status = unqlite_kv_fetch(db_, key.c_str(), key.size(), NULL, &val_size); 190 | if (status == UNQLITE_OK) { 191 | char* buf = new char[val_size]; 192 | status = unqlite_kv_fetch(db_, key.c_str(), key.size(), buf, &val_size); 193 | value.assign(buf, val_size); 194 | delete[] buf; 195 | } 196 | return status; 197 | } 198 | 199 | int NodeUnQLite::store_kv(std::string& key, std::string& value) { 200 | return unqlite_kv_store(db_, key.c_str(), key.size(), value.c_str(), value.size()); 201 | } 202 | 203 | int NodeUnQLite::append_kv(std::string& key, std::string& value) { 204 | return unqlite_kv_append(db_, key.c_str(), key.size(), value.c_str(), value.size()); 205 | } 206 | 207 | int NodeUnQLite::delete_kv(std::string& key) { 208 | return unqlite_kv_delete(db_, key.c_str(), key.size()); 209 | } 210 | 211 | void NodeUnQLite::get_error_message(std::string& message) { 212 | const char* buf; 213 | int bufLen; 214 | unqlite_config(db_, UNQLITE_CONFIG_ERR_LOG, &buf, &bufLen); 215 | if(bufLen > 0){ 216 | message.assign(buf, bufLen); 217 | } 218 | } 219 | 220 | } // namespace node_unqlite 221 | 222 | void Initialize(Handle exports) { 223 | node_unqlite::NodeUnQLite::Init(exports); 224 | 225 | // define constants 226 | // status code 227 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OK, OK); 228 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_NOMEM, NOMEM); 229 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_ABORT, ABORT); 230 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_IOERR, IOERR); 231 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_CORRUPT, CORRUPT); 232 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_LOCKED, LOCKED); 233 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_BUSY, BUSY); 234 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_DONE, DONE); 235 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_PERM, PERM); 236 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_NOTIMPLEMENTED, NOTIMPLEMENTED); 237 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_NOTFOUND, NOTFOUND); 238 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_NOOP, NOOP); 239 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_INVALID, INVALID); 240 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_EOF, EOF); 241 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_UNKNOWN, UNKNOWN); 242 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_LIMIT, LIMIT); 243 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_EXISTS, EXISTS); 244 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_EMPTY, EMPTY); 245 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_COMPILE_ERR, COMPILE_ERR); 246 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_VM_ERR, VM_ERR); 247 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_FULL, FULL); 248 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_CANTOPEN, CANTOPEN); 249 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_READ_ONLY, READ_ONLY); 250 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_LOCKERR, LOCKERR); 251 | 252 | // Cursor seek position 253 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_CURSOR_MATCH_EXACT, CURSOR_MATCH_EXACT); 254 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_CURSOR_MATCH_LE, CURSOR_MATCH_LE); 255 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_CURSOR_MATCH_GE, CURSOR_MATCH_GE); 256 | 257 | // open mode 258 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_CREATE, OPEN_CREATE); 259 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_READWRITE, OPEN_READWRITE); 260 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_READONLY, OPEN_READONLY); 261 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_MMAP, OPEN_MMAP); 262 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_EXCLUSIVE, OPEN_EXCLUSIVE); 263 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_TEMP_DB, OPEN_TEMP); 264 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_IN_MEMORY, OPEN_IN_MEMORY); 265 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_OMIT_JOURNALING, OPEN_OMIT_JOURNALING); 266 | DEFINE_CONSTANT_INTEGER(exports, UNQLITE_OPEN_NOMUTEX, OPEN_NOMUTEX); 267 | } 268 | 269 | NODE_MODULE(node_unqlite, Initialize) 270 | -------------------------------------------------------------------------------- /unqlite/unqlite.h: -------------------------------------------------------------------------------- 1 | /* This file was automatically generated. Do not edit (Except for compile time directives)! */ 2 | #ifndef _UNQLITE_H_ 3 | #define _UNQLITE_H_ 4 | /* 5 | * Symisc UnQLite: An Embeddable NoSQL (Post Modern) Database Engine. 6 | * Copyright (C) 2012-2016, Symisc Systems http://unqlite.org/ 7 | * Version 1.1.7 8 | * For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES 9 | * please contact Symisc Systems via: 10 | * legal@symisc.net 11 | * licensing@symisc.net 12 | * contact@symisc.net 13 | * or visit: 14 | * http://unqlite.org/licensing.html 15 | */ 16 | /* 17 | * Copyright (C) 2012, 2016 Symisc Systems, S.U.A.R.L [M.I.A.G Mrad Chems Eddine ]. 18 | * All rights reserved. 19 | * 20 | * Redistribution and use in source and binary forms, with or without 21 | * modification, are permitted provided that the following conditions 22 | * are met: 23 | * 1. Redistributions of source code must retain the above copyright 24 | * notice, this list of conditions and the following disclaimer. 25 | * 2. Redistributions in binary form must reproduce the above copyright 26 | * notice, this list of conditions and the following disclaimer in the 27 | * documentation and/or other materials provided with the distribution. 28 | * 29 | * THIS SOFTWARE IS PROVIDED BY SYMISC SYSTEMS ``AS IS'' AND ANY EXPRESS 30 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 31 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 32 | * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SYMISC SYSTEMS 33 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 36 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 37 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 38 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 39 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | */ 41 | /* $SymiscID: unqlite.h v1.2 Win10 2106-12-02 00:04:12 stable $ */ 42 | #include /* needed for the definition of va_list */ 43 | /* 44 | * Compile time engine version, signature, identification in the symisc source tree 45 | * and copyright notice. 46 | * Each macro have an equivalent C interface associated with it that provide the same 47 | * information but are associated with the library instead of the header file. 48 | * Refer to [unqlite_lib_version()], [unqlite_lib_signature()], [unqlite_lib_ident()] and 49 | * [unqlite_lib_copyright()] for more information. 50 | */ 51 | /* 52 | * The UNQLITE_VERSION C preprocessor macroevaluates to a string literal 53 | * that is the unqlite version in the format "X.Y.Z" where X is the major 54 | * version number and Y is the minor version number and Z is the release 55 | * number. 56 | */ 57 | #define UNQLITE_VERSION "1.1.7" 58 | /* 59 | * The UNQLITE_VERSION_NUMBER C preprocessor macro resolves to an integer 60 | * with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same 61 | * numbers used in [UNQLITE_VERSION]. 62 | */ 63 | #define UNQLITE_VERSION_NUMBER 1001007 64 | /* 65 | * The UNQLITE_SIG C preprocessor macro evaluates to a string 66 | * literal which is the public signature of the unqlite engine. 67 | * This signature could be included for example in a host-application 68 | * generated Server MIME header as follows: 69 | * Server: YourWebServer/x.x unqlite/x.x.x \r\n 70 | */ 71 | #define UNQLITE_SIG "unqlite/1.1.7" 72 | /* 73 | * UnQLite identification in the Symisc source tree: 74 | * Each particular check-in of a particular software released 75 | * by symisc systems have an unique identifier associated with it. 76 | * This macro hold the one associated with unqlite. 77 | */ 78 | #define UNQLITE_IDENT "unqlite:b172a1e2c3f62fb35c8e1fb2795121f82356cad6" 79 | /* 80 | * Copyright notice. 81 | * If you have any questions about the licensing situation, please 82 | * visit http://unqlite.org/licensing.html 83 | * or contact Symisc Systems via: 84 | * legal@symisc.net 85 | * licensing@symisc.net 86 | * contact@symisc.net 87 | */ 88 | #define UNQLITE_COPYRIGHT "Copyright (C) Symisc Systems, S.U.A.R.L [Mrad Chems Eddine ] 2012-2016, http://unqlite.org/" 89 | 90 | /* Forward declaration to public objects */ 91 | typedef struct unqlite_io_methods unqlite_io_methods; 92 | typedef struct unqlite_kv_methods unqlite_kv_methods; 93 | typedef struct unqlite_kv_engine unqlite_kv_engine; 94 | typedef struct jx9_io_stream unqlite_io_stream; 95 | typedef struct jx9_context unqlite_context; 96 | typedef struct jx9_value unqlite_value; 97 | typedef struct unqlite_vfs unqlite_vfs; 98 | typedef struct unqlite_vm unqlite_vm; 99 | typedef struct unqlite unqlite; 100 | /* 101 | * ------------------------------ 102 | * Compile time directives 103 | * ------------------------------ 104 | * For most purposes, UnQLite can be built just fine using the default compilation options. 105 | * However, if required, the compile-time options documented below can be used to omit UnQLite 106 | * features (resulting in a smaller compiled library size) or to change the default values 107 | * of some parameters. 108 | * Every effort has been made to ensure that the various combinations of compilation options 109 | * work harmoniously and produce a working library. 110 | * 111 | * UNQLITE_ENABLE_THREADS 112 | * This option controls whether or not code is included in UnQLite to enable it to operate 113 | * safely in a multithreaded environment. The default is not. All mutexing code is omitted 114 | * and it is unsafe to use UnQLite in a multithreaded program. When compiled with the 115 | * UNQLITE_ENABLE_THREADS directive enabled, UnQLite can be used in a multithreaded program 116 | * and it is safe to share the same virtual machine and engine handle between two or more threads. 117 | * The value of UNQLITE_ENABLE_THREADS can be determined at run-time using the unqlite_lib_is_threadsafe() 118 | * interface. 119 | * When UnQLite has been compiled with threading support then the threading mode can be altered 120 | * at run-time using the unqlite_lib_config() interface together with one of these verbs: 121 | * UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE 122 | * UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI 123 | * Platforms others than Windows and UNIX systems must install their own mutex subsystem via 124 | * unqlite_lib_config() with a configuration verb set to UNQLITE_LIB_CONFIG_USER_MUTEX. 125 | * Otherwise the library is not threadsafe. 126 | * Note that you must link UnQLite with the POSIX threads library under UNIX systems (i.e: -lpthread). 127 | * 128 | * Options To Omit/Enable Features 129 | * 130 | * The following options can be used to reduce the size of the compiled library by omitting optional 131 | * features. This is probably only useful in embedded systems where space is especially tight, as even 132 | * with all features included the UnQLite library is relatively small. Don't forget to tell your 133 | * compiler to optimize for binary size! (the -Os option if using GCC). Telling your compiler 134 | * to optimize for size usually has a much larger impact on library footprint than employing 135 | * any of these compile-time options. 136 | * 137 | * JX9_DISABLE_BUILTIN_FUNC 138 | * Jx9 is shipped with more than 312 built-in functions suitable for most purposes like 139 | * string and INI processing, ZIP extracting, Base64 encoding/decoding, JSON encoding/decoding 140 | * and so forth. 141 | * If this directive is enabled, then all built-in Jx9 functions are omitted from the build. 142 | * Note that special functions such as db_create(), db_store(), db_fetch(), etc. are not omitted 143 | * from the build and are not affected by this directive. 144 | * 145 | * JX9_ENABLE_MATH_FUNC 146 | * If this directive is enabled, built-in math functions such as sqrt(), abs(), log(), ceil(), etc. 147 | * are included in the build. Note that you may need to link UnQLite with the math library in same 148 | * Linux/BSD flavor (i.e: -lm). 149 | * 150 | * JX9_DISABLE_DISK_IO 151 | * If this directive is enabled, built-in VFS functions such as chdir(), mkdir(), chroot(), unlink(), 152 | * sleep(), etc. are omitted from the build. 153 | * 154 | * UNQLITE_ENABLE_JX9_HASH_IO 155 | * If this directive is enabled, built-in hash functions such as md5(), sha1(), md5_file(), crc32(), etc. 156 | * are included in the build. 157 | */ 158 | /* Symisc public definitions */ 159 | #if !defined(SYMISC_STANDARD_DEFS) 160 | #define SYMISC_STANDARD_DEFS 161 | #if defined (_WIN32) || defined (WIN32) || defined(__MINGW32__) || defined (_MSC_VER) || defined (_WIN32_WCE) 162 | /* Windows Systems */ 163 | #if !defined(__WINNT__) 164 | #define __WINNT__ 165 | #endif 166 | /* 167 | * Determine if we are dealing with WindowsCE - which has a much 168 | * reduced API. 169 | */ 170 | #if defined(_WIN32_WCE) 171 | #ifndef __WIN_CE__ 172 | #define __WIN_CE__ 173 | #endif /* __WIN_CE__ */ 174 | #endif /* _WIN32_WCE */ 175 | #else 176 | /* 177 | * By default we will assume that we are compiling on a UNIX systems. 178 | * Otherwise the OS_OTHER directive must be defined. 179 | */ 180 | #if !defined(OS_OTHER) 181 | #if !defined(__UNIXES__) 182 | #define __UNIXES__ 183 | #endif /* __UNIXES__ */ 184 | #else 185 | #endif /* OS_OTHER */ 186 | #endif /* __WINNT__/__UNIXES__ */ 187 | #if defined(_MSC_VER) || defined(__BORLANDC__) 188 | typedef signed __int64 sxi64; /* 64 bits(8 bytes) signed int64 */ 189 | typedef unsigned __int64 sxu64; /* 64 bits(8 bytes) unsigned int64 */ 190 | #else 191 | typedef signed long long int sxi64; /* 64 bits(8 bytes) signed int64 */ 192 | typedef unsigned long long int sxu64; /* 64 bits(8 bytes) unsigned int64 */ 193 | #endif /* _MSC_VER */ 194 | /* Signature of the consumer routine */ 195 | typedef int (*ProcConsumer)(const void *, unsigned int, void *); 196 | /* Forward reference */ 197 | typedef struct SyMutexMethods SyMutexMethods; 198 | typedef struct SyMemMethods SyMemMethods; 199 | typedef struct SyString SyString; 200 | typedef struct syiovec syiovec; 201 | typedef struct SyMutex SyMutex; 202 | typedef struct Sytm Sytm; 203 | /* Scatter and gather array. */ 204 | struct syiovec 205 | { 206 | #if defined (__WINNT__) 207 | /* Same fields type and offset as WSABUF structure defined one winsock2 header */ 208 | unsigned long nLen; 209 | char *pBase; 210 | #else 211 | void *pBase; 212 | unsigned long nLen; 213 | #endif 214 | }; 215 | struct SyString 216 | { 217 | const char *zString; /* Raw string (may not be null terminated) */ 218 | unsigned int nByte; /* Raw string length */ 219 | }; 220 | /* Time structure. */ 221 | struct Sytm 222 | { 223 | int tm_sec; /* seconds (0 - 60) */ 224 | int tm_min; /* minutes (0 - 59) */ 225 | int tm_hour; /* hours (0 - 23) */ 226 | int tm_mday; /* day of month (1 - 31) */ 227 | int tm_mon; /* month of year (0 - 11) */ 228 | int tm_year; /* year + 1900 */ 229 | int tm_wday; /* day of week (Sunday = 0) */ 230 | int tm_yday; /* day of year (0 - 365) */ 231 | int tm_isdst; /* is summer time in effect? */ 232 | char *tm_zone; /* abbreviation of timezone name */ 233 | long tm_gmtoff; /* offset from UTC in seconds */ 234 | }; 235 | /* Convert a tm structure (struct tm *) found in to a Sytm structure */ 236 | #define STRUCT_TM_TO_SYTM(pTM, pSYTM) \ 237 | (pSYTM)->tm_hour = (pTM)->tm_hour;\ 238 | (pSYTM)->tm_min = (pTM)->tm_min;\ 239 | (pSYTM)->tm_sec = (pTM)->tm_sec;\ 240 | (pSYTM)->tm_mon = (pTM)->tm_mon;\ 241 | (pSYTM)->tm_mday = (pTM)->tm_mday;\ 242 | (pSYTM)->tm_year = (pTM)->tm_year + 1900;\ 243 | (pSYTM)->tm_yday = (pTM)->tm_yday;\ 244 | (pSYTM)->tm_wday = (pTM)->tm_wday;\ 245 | (pSYTM)->tm_isdst = (pTM)->tm_isdst;\ 246 | (pSYTM)->tm_gmtoff = 0;\ 247 | (pSYTM)->tm_zone = 0; 248 | 249 | /* Convert a SYSTEMTIME structure (LPSYSTEMTIME: Windows Systems only ) to a Sytm structure */ 250 | #define SYSTEMTIME_TO_SYTM(pSYSTIME, pSYTM) \ 251 | (pSYTM)->tm_hour = (pSYSTIME)->wHour;\ 252 | (pSYTM)->tm_min = (pSYSTIME)->wMinute;\ 253 | (pSYTM)->tm_sec = (pSYSTIME)->wSecond;\ 254 | (pSYTM)->tm_mon = (pSYSTIME)->wMonth - 1;\ 255 | (pSYTM)->tm_mday = (pSYSTIME)->wDay;\ 256 | (pSYTM)->tm_year = (pSYSTIME)->wYear;\ 257 | (pSYTM)->tm_yday = 0;\ 258 | (pSYTM)->tm_wday = (pSYSTIME)->wDayOfWeek;\ 259 | (pSYTM)->tm_gmtoff = 0;\ 260 | (pSYTM)->tm_isdst = -1;\ 261 | (pSYTM)->tm_zone = 0; 262 | 263 | /* Dynamic memory allocation methods. */ 264 | struct SyMemMethods 265 | { 266 | void * (*xAlloc)(unsigned int); /* [Required:] Allocate a memory chunk */ 267 | void * (*xRealloc)(void *, unsigned int); /* [Required:] Re-allocate a memory chunk */ 268 | void (*xFree)(void *); /* [Required:] Release a memory chunk */ 269 | unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */ 270 | int (*xInit)(void *); /* [Optional:] Initialization callback */ 271 | void (*xRelease)(void *); /* [Optional:] Release callback */ 272 | void *pUserData; /* [Optional:] First argument to xInit() and xRelease() */ 273 | }; 274 | /* Out of memory callback signature. */ 275 | typedef int (*ProcMemError)(void *); 276 | /* Mutex methods. */ 277 | struct SyMutexMethods 278 | { 279 | int (*xGlobalInit)(void); /* [Optional:] Global mutex initialization */ 280 | void (*xGlobalRelease)(void); /* [Optional:] Global Release callback () */ 281 | SyMutex * (*xNew)(int); /* [Required:] Request a new mutex */ 282 | void (*xRelease)(SyMutex *); /* [Optional:] Release a mutex */ 283 | void (*xEnter)(SyMutex *); /* [Required:] Enter mutex */ 284 | int (*xTryEnter)(SyMutex *); /* [Optional:] Try to enter a mutex */ 285 | void (*xLeave)(SyMutex *); /* [Required:] Leave a locked mutex */ 286 | }; 287 | #if defined (_MSC_VER) || defined (__MINGW32__) || defined (__GNUC__) && defined (__declspec) 288 | #define SX_APIIMPORT __declspec(dllimport) 289 | #define SX_APIEXPORT __declspec(dllexport) 290 | #else 291 | #define SX_APIIMPORT 292 | #define SX_APIEXPORT 293 | #endif 294 | /* Standard return values from Symisc public interfaces */ 295 | #define SXRET_OK 0 /* Not an error */ 296 | #define SXERR_MEM (-1) /* Out of memory */ 297 | #define SXERR_IO (-2) /* IO error */ 298 | #define SXERR_EMPTY (-3) /* Empty field */ 299 | #define SXERR_LOCKED (-4) /* Locked operation */ 300 | #define SXERR_ORANGE (-5) /* Out of range value */ 301 | #define SXERR_NOTFOUND (-6) /* Item not found */ 302 | #define SXERR_LIMIT (-7) /* Limit reached */ 303 | #define SXERR_MORE (-8) /* Need more input */ 304 | #define SXERR_INVALID (-9) /* Invalid parameter */ 305 | #define SXERR_ABORT (-10) /* User callback request an operation abort */ 306 | #define SXERR_EXISTS (-11) /* Item exists */ 307 | #define SXERR_SYNTAX (-12) /* Syntax error */ 308 | #define SXERR_UNKNOWN (-13) /* Unknown error */ 309 | #define SXERR_BUSY (-14) /* Busy operation */ 310 | #define SXERR_OVERFLOW (-15) /* Stack or buffer overflow */ 311 | #define SXERR_WILLBLOCK (-16) /* Operation will block */ 312 | #define SXERR_NOTIMPLEMENTED (-17) /* Operation not implemented */ 313 | #define SXERR_EOF (-18) /* End of input */ 314 | #define SXERR_PERM (-19) /* Permission error */ 315 | #define SXERR_NOOP (-20) /* No-op */ 316 | #define SXERR_FORMAT (-21) /* Invalid format */ 317 | #define SXERR_NEXT (-22) /* Not an error */ 318 | #define SXERR_OS (-23) /* System call return an error */ 319 | #define SXERR_CORRUPT (-24) /* Corrupted pointer */ 320 | #define SXERR_CONTINUE (-25) /* Not an error: Operation in progress */ 321 | #define SXERR_NOMATCH (-26) /* No match */ 322 | #define SXERR_RESET (-27) /* Operation reset */ 323 | #define SXERR_DONE (-28) /* Not an error */ 324 | #define SXERR_SHORT (-29) /* Buffer too short */ 325 | #define SXERR_PATH (-30) /* Path error */ 326 | #define SXERR_TIMEOUT (-31) /* Timeout */ 327 | #define SXERR_BIG (-32) /* Too big for processing */ 328 | #define SXERR_RETRY (-33) /* Retry your call */ 329 | #define SXERR_IGNORE (-63) /* Ignore */ 330 | #endif /* SYMISC_PUBLIC_DEFS */ 331 | /* 332 | * Marker for exported interfaces. 333 | */ 334 | #define UNQLITE_APIEXPORT SX_APIEXPORT 335 | /* 336 | * If compiling for a processor that lacks floating point 337 | * support, substitute integer for floating-point. 338 | */ 339 | #ifdef UNQLITE_OMIT_FLOATING_POINT 340 | typedef sxi64 uqlite_real; 341 | #else 342 | typedef double unqlite_real; 343 | #endif 344 | typedef sxi64 unqlite_int64; 345 | /* Standard UnQLite return values */ 346 | #define UNQLITE_OK SXRET_OK /* Successful result */ 347 | /* Beginning of error codes */ 348 | #define UNQLITE_NOMEM SXERR_MEM /* Out of memory */ 349 | #define UNQLITE_ABORT SXERR_ABORT /* Another thread have released this instance */ 350 | #define UNQLITE_IOERR SXERR_IO /* IO error */ 351 | #define UNQLITE_CORRUPT SXERR_CORRUPT /* Corrupt pointer */ 352 | #define UNQLITE_LOCKED SXERR_LOCKED /* Forbidden Operation */ 353 | #define UNQLITE_BUSY SXERR_BUSY /* The database file is locked */ 354 | #define UNQLITE_DONE SXERR_DONE /* Operation done */ 355 | #define UNQLITE_PERM SXERR_PERM /* Permission error */ 356 | #define UNQLITE_NOTIMPLEMENTED SXERR_NOTIMPLEMENTED /* Method not implemented by the underlying Key/Value storage engine */ 357 | #define UNQLITE_NOTFOUND SXERR_NOTFOUND /* No such record */ 358 | #define UNQLITE_NOOP SXERR_NOOP /* No such method */ 359 | #define UNQLITE_INVALID SXERR_INVALID /* Invalid parameter */ 360 | #define UNQLITE_EOF SXERR_EOF /* End Of Input */ 361 | #define UNQLITE_UNKNOWN SXERR_UNKNOWN /* Unknown configuration option */ 362 | #define UNQLITE_LIMIT SXERR_LIMIT /* Database limit reached */ 363 | #define UNQLITE_EXISTS SXERR_EXISTS /* Record exists */ 364 | #define UNQLITE_EMPTY SXERR_EMPTY /* Empty record */ 365 | #define UNQLITE_COMPILE_ERR (-70) /* Compilation error */ 366 | #define UNQLITE_VM_ERR (-71) /* Virtual machine error */ 367 | #define UNQLITE_FULL (-73) /* Full database (unlikely) */ 368 | #define UNQLITE_CANTOPEN (-74) /* Unable to open the database file */ 369 | #define UNQLITE_READ_ONLY (-75) /* Read only Key/Value storage engine */ 370 | #define UNQLITE_LOCKERR (-76) /* Locking protocol error */ 371 | /* end-of-error-codes */ 372 | /* 373 | * Database Handle Configuration Commands. 374 | * 375 | * The following set of constants are the available configuration verbs that can 376 | * be used by the host-application to configure an UnQLite database handle. 377 | * These constants must be passed as the second argument to [unqlite_config()]. 378 | * 379 | * Each options require a variable number of arguments. 380 | * The [unqlite_config()] interface will return UNQLITE_OK on success, any other 381 | * return value indicates failure. 382 | * For a full discussion on the configuration verbs and their expected 383 | * parameters, please refer to this page: 384 | * http://unqlite.org/c_api/unqlite_config.html 385 | */ 386 | #define UNQLITE_CONFIG_JX9_ERR_LOG 1 /* TWO ARGUMENTS: const char **pzBuf, int *pLen */ 387 | #define UNQLITE_CONFIG_MAX_PAGE_CACHE 2 /* ONE ARGUMENT: int nMaxPage */ 388 | #define UNQLITE_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf, int *pLen */ 389 | #define UNQLITE_CONFIG_KV_ENGINE 4 /* ONE ARGUMENT: const char *zKvName */ 390 | #define UNQLITE_CONFIG_DISABLE_AUTO_COMMIT 5 /* NO ARGUMENTS */ 391 | #define UNQLITE_CONFIG_GET_KV_NAME 6 /* ONE ARGUMENT: const char **pzPtr */ 392 | /* 393 | * UnQLite/Jx9 Virtual Machine Configuration Commands. 394 | * 395 | * The following set of constants are the available configuration verbs that can 396 | * be used by the host-application to configure the Jx9 (Via UnQLite) Virtual machine. 397 | * These constants must be passed as the second argument to the [unqlite_vm_config()] 398 | * interface. 399 | * Each options require a variable number of arguments. 400 | * The [unqlite_vm_config()] interface will return UNQLITE_OK on success, any other return 401 | * value indicates failure. 402 | * There are many options but the most importants are: UNQLITE_VM_CONFIG_OUTPUT which install 403 | * a VM output consumer callback, UNQLITE_VM_CONFIG_HTTP_REQUEST which parse and register 404 | * a HTTP request and UNQLITE_VM_CONFIG_ARGV_ENTRY which populate the $argv array. 405 | * For a full discussion on the configuration verbs and their expected parameters, please 406 | * refer to this page: 407 | * http://unqlite.org/c_api/unqlite_vm_config.html 408 | */ 409 | #define UNQLITE_VM_CONFIG_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut, unsigned int nLen, void *pUserData), void *pUserData */ 410 | #define UNQLITE_VM_CONFIG_IMPORT_PATH 2 /* ONE ARGUMENT: const char *zIncludePath */ 411 | #define UNQLITE_VM_CONFIG_ERR_REPORT 3 /* NO ARGUMENTS: Report all run-time errors in the VM output */ 412 | #define UNQLITE_VM_CONFIG_RECURSION_DEPTH 4 /* ONE ARGUMENT: int nMaxDepth */ 413 | #define UNQLITE_VM_OUTPUT_LENGTH 5 /* ONE ARGUMENT: unsigned int *pLength */ 414 | #define UNQLITE_VM_CONFIG_CREATE_VAR 6 /* TWO ARGUMENTS: const char *zName, unqlite_value *pValue */ 415 | #define UNQLITE_VM_CONFIG_HTTP_REQUEST 7 /* TWO ARGUMENTS: const char *zRawRequest, int nRequestLength */ 416 | #define UNQLITE_VM_CONFIG_SERVER_ATTR 8 /* THREE ARGUMENTS: const char *zKey, const char *zValue, int nLen */ 417 | #define UNQLITE_VM_CONFIG_ENV_ATTR 9 /* THREE ARGUMENTS: const char *zKey, const char *zValue, int nLen */ 418 | #define UNQLITE_VM_CONFIG_EXEC_VALUE 10 /* ONE ARGUMENT: unqlite_value **ppValue */ 419 | #define UNQLITE_VM_CONFIG_IO_STREAM 11 /* ONE ARGUMENT: const unqlite_io_stream *pStream */ 420 | #define UNQLITE_VM_CONFIG_ARGV_ENTRY 12 /* ONE ARGUMENT: const char *zValue */ 421 | #define UNQLITE_VM_CONFIG_EXTRACT_OUTPUT 13 /* TWO ARGUMENTS: const void **ppOut, unsigned int *pOutputLen */ 422 | /* 423 | * Storage engine configuration commands. 424 | * 425 | * The following set of constants are the available configuration verbs that can 426 | * be used by the host-application to configure the underlying storage engine (i.e Hash, B+tree, R+tree). 427 | * These constants must be passed as the first argument to [unqlite_kv_config()]. 428 | * Each options require a variable number of arguments. 429 | * The [unqlite_kv_config()] interface will return UNQLITE_OK on success, any other return 430 | * value indicates failure. 431 | * For a full discussion on the configuration verbs and their expected parameters, please 432 | * refer to this page: 433 | * http://unqlite.org/c_api/unqlite_kv_config.html 434 | */ 435 | #define UNQLITE_KV_CONFIG_HASH_FUNC 1 /* ONE ARGUMENT: unsigned int (*xHash)(const void *,unsigned int) */ 436 | #define UNQLITE_KV_CONFIG_CMP_FUNC 2 /* ONE ARGUMENT: int (*xCmp)(const void *,const void *,unsigned int) */ 437 | /* 438 | * Global Library Configuration Commands. 439 | * 440 | * The following set of constants are the available configuration verbs that can 441 | * be used by the host-application to configure the whole library. 442 | * These constants must be passed as the first argument to [unqlite_lib_config()]. 443 | * 444 | * Each options require a variable number of arguments. 445 | * The [unqlite_lib_config()] interface will return UNQLITE_OK on success, any other return 446 | * value indicates failure. 447 | * Notes: 448 | * The default configuration is recommended for most applications and so the call to 449 | * [unqlite_lib_config()] is usually not necessary. It is provided to support rare 450 | * applications with unusual needs. 451 | * The [unqlite_lib_config()] interface is not threadsafe. The application must insure that 452 | * no other [unqlite_*()] interfaces are invoked by other threads while [unqlite_lib_config()] 453 | * is running. Furthermore, [unqlite_lib_config()] may only be invoked prior to library 454 | * initialization using [unqlite_lib_init()] or [unqlite_init()] or after shutdown 455 | * by [unqlite_lib_shutdown()]. If [unqlite_lib_config()] is called after [unqlite_lib_init()] 456 | * or [unqlite_init()] and before [unqlite_lib_shutdown()] then it will return UNQLITE_LOCKED. 457 | * For a full discussion on the configuration verbs and their expected parameters, please 458 | * refer to this page: 459 | * http://unqlite.org/c_api/unqlite_lib.html 460 | */ 461 | #define UNQLITE_LIB_CONFIG_USER_MALLOC 1 /* ONE ARGUMENT: const SyMemMethods *pMemMethods */ 462 | #define UNQLITE_LIB_CONFIG_MEM_ERR_CALLBACK 2 /* TWO ARGUMENTS: int (*xMemError)(void *), void *pUserData */ 463 | #define UNQLITE_LIB_CONFIG_USER_MUTEX 3 /* ONE ARGUMENT: const SyMutexMethods *pMutexMethods */ 464 | #define UNQLITE_LIB_CONFIG_THREAD_LEVEL_SINGLE 4 /* NO ARGUMENTS */ 465 | #define UNQLITE_LIB_CONFIG_THREAD_LEVEL_MULTI 5 /* NO ARGUMENTS */ 466 | #define UNQLITE_LIB_CONFIG_VFS 6 /* ONE ARGUMENT: const unqlite_vfs *pVfs */ 467 | #define UNQLITE_LIB_CONFIG_STORAGE_ENGINE 7 /* ONE ARGUMENT: unqlite_kv_methods *pStorage */ 468 | #define UNQLITE_LIB_CONFIG_PAGE_SIZE 8 /* ONE ARGUMENT: int iPageSize */ 469 | /* 470 | * These bit values are intended for use in the 3rd parameter to the [unqlite_open()] interface 471 | * and in the 4th parameter to the xOpen method of the [unqlite_vfs] object. 472 | */ 473 | #define UNQLITE_OPEN_READONLY 0x00000001 /* Read only mode. Ok for [unqlite_open] */ 474 | #define UNQLITE_OPEN_READWRITE 0x00000002 /* Ok for [unqlite_open] */ 475 | #define UNQLITE_OPEN_CREATE 0x00000004 /* Ok for [unqlite_open] */ 476 | #define UNQLITE_OPEN_EXCLUSIVE 0x00000008 /* VFS only */ 477 | #define UNQLITE_OPEN_TEMP_DB 0x00000010 /* VFS only */ 478 | #define UNQLITE_OPEN_NOMUTEX 0x00000020 /* Ok for [unqlite_open] */ 479 | #define UNQLITE_OPEN_OMIT_JOURNALING 0x00000040 /* Omit journaling for this database. Ok for [unqlite_open] */ 480 | #define UNQLITE_OPEN_IN_MEMORY 0x00000080 /* An in memory database. Ok for [unqlite_open]*/ 481 | #define UNQLITE_OPEN_MMAP 0x00000100 /* Obtain a memory view of the whole file. Ok for [unqlite_open] */ 482 | /* 483 | * Synchronization Type Flags 484 | * 485 | * When UnQLite invokes the xSync() method of an [unqlite_io_methods] object it uses 486 | * a combination of these integer values as the second argument. 487 | * 488 | * When the UNQLITE_SYNC_DATAONLY flag is used, it means that the sync operation only 489 | * needs to flush data to mass storage. Inode information need not be flushed. 490 | * If the lower four bits of the flag equal UNQLITE_SYNC_NORMAL, that means to use normal 491 | * fsync() semantics. If the lower four bits equal UNQLITE_SYNC_FULL, that means to use 492 | * Mac OS X style fullsync instead of fsync(). 493 | */ 494 | #define UNQLITE_SYNC_NORMAL 0x00002 495 | #define UNQLITE_SYNC_FULL 0x00003 496 | #define UNQLITE_SYNC_DATAONLY 0x00010 497 | /* 498 | * File Locking Levels 499 | * 500 | * UnQLite uses one of these integer values as the second 501 | * argument to calls it makes to the xLock() and xUnlock() methods 502 | * of an [unqlite_io_methods] object. 503 | */ 504 | #define UNQLITE_LOCK_NONE 0 505 | #define UNQLITE_LOCK_SHARED 1 506 | #define UNQLITE_LOCK_RESERVED 2 507 | #define UNQLITE_LOCK_PENDING 3 508 | #define UNQLITE_LOCK_EXCLUSIVE 4 509 | /* 510 | * CAPIREF: OS Interface: Open File Handle 511 | * 512 | * An [unqlite_file] object represents an open file in the [unqlite_vfs] OS interface 513 | * layer. 514 | * Individual OS interface implementations will want to subclass this object by appending 515 | * additional fields for their own use. The pMethods entry is a pointer to an 516 | * [unqlite_io_methods] object that defines methods for performing 517 | * I/O operations on the open file. 518 | */ 519 | typedef struct unqlite_file unqlite_file; 520 | struct unqlite_file { 521 | const unqlite_io_methods *pMethods; /* Methods for an open file. MUST BE FIRST */ 522 | }; 523 | /* 524 | * CAPIREF: OS Interface: File Methods Object 525 | * 526 | * Every file opened by the [unqlite_vfs] xOpen method populates an 527 | * [unqlite_file] object (or, more commonly, a subclass of the 528 | * [unqlite_file] object) with a pointer to an instance of this object. 529 | * This object defines the methods used to perform various operations 530 | * against the open file represented by the [unqlite_file] object. 531 | * 532 | * If the xOpen method sets the unqlite_file.pMethods element 533 | * to a non-NULL pointer, then the unqlite_io_methods.xClose method 534 | * may be invoked even if the xOpen reported that it failed. The 535 | * only way to prevent a call to xClose following a failed xOpen 536 | * is for the xOpen to set the unqlite_file.pMethods element to NULL. 537 | * 538 | * The flags argument to xSync may be one of [UNQLITE_SYNC_NORMAL] or 539 | * [UNQLITE_SYNC_FULL]. The first choice is the normal fsync(). 540 | * The second choice is a Mac OS X style fullsync. The [UNQLITE_SYNC_DATAONLY] 541 | * flag may be ORed in to indicate that only the data of the file 542 | * and not its inode needs to be synced. 543 | * 544 | * The integer values to xLock() and xUnlock() are one of 545 | * 546 | * UNQLITE_LOCK_NONE 547 | * UNQLITE_LOCK_SHARED 548 | * UNQLITE_LOCK_RESERVED 549 | * UNQLITE_LOCK_PENDING 550 | * UNQLITE_LOCK_EXCLUSIVE 551 | * 552 | * xLock() increases the lock. xUnlock() decreases the lock. 553 | * The xCheckReservedLock() method checks whether any database connection, 554 | * either in this process or in some other process, is holding a RESERVED, 555 | * PENDING, or EXCLUSIVE lock on the file. It returns true if such a lock exists 556 | * and false otherwise. 557 | * 558 | * The xSectorSize() method returns the sector size of the device that underlies 559 | * the file. The sector size is the minimum write that can be performed without 560 | * disturbing other bytes in the file. 561 | * 562 | */ 563 | struct unqlite_io_methods { 564 | int iVersion; /* Structure version number (currently 1) */ 565 | int (*xClose)(unqlite_file*); 566 | int (*xRead)(unqlite_file*, void*, unqlite_int64 iAmt, unqlite_int64 iOfst); 567 | int (*xWrite)(unqlite_file*, const void*, unqlite_int64 iAmt, unqlite_int64 iOfst); 568 | int (*xTruncate)(unqlite_file*, unqlite_int64 size); 569 | int (*xSync)(unqlite_file*, int flags); 570 | int (*xFileSize)(unqlite_file*, unqlite_int64 *pSize); 571 | int (*xLock)(unqlite_file*, int); 572 | int (*xUnlock)(unqlite_file*, int); 573 | int (*xCheckReservedLock)(unqlite_file*, int *pResOut); 574 | int (*xSectorSize)(unqlite_file*); 575 | }; 576 | /* 577 | * CAPIREF: OS Interface Object 578 | * 579 | * An instance of the unqlite_vfs object defines the interface between 580 | * the UnQLite core and the underlying operating system. The "vfs" 581 | * in the name of the object stands for "Virtual File System". 582 | * 583 | * Only a single vfs can be registered within the UnQLite core. 584 | * Vfs registration is done using the [unqlite_lib_config()] interface 585 | * with a configuration verb set to UNQLITE_LIB_CONFIG_VFS. 586 | * Note that Windows and UNIX (Linux, FreeBSD, Solaris, Mac OS X, etc.) users 587 | * does not have to worry about registering and installing a vfs since UnQLite 588 | * come with a built-in vfs for these platforms that implements most the methods 589 | * defined below. 590 | * 591 | * Clients running on exotic systems (ie: Other than Windows and UNIX systems) 592 | * must register their own vfs in order to be able to use the UnQLite library. 593 | * 594 | * The value of the iVersion field is initially 1 but may be larger in 595 | * future versions of UnQLite. 596 | * 597 | * The szOsFile field is the size of the subclassed [unqlite_file] structure 598 | * used by this VFS. mxPathname is the maximum length of a pathname in this VFS. 599 | * 600 | * At least szOsFile bytes of memory are allocated by UnQLite to hold the [unqlite_file] 601 | * structure passed as the third argument to xOpen. The xOpen method does not have to 602 | * allocate the structure; it should just fill it in. Note that the xOpen method must 603 | * set the unqlite_file.pMethods to either a valid [unqlite_io_methods] object or to NULL. 604 | * xOpen must do this even if the open fails. UnQLite expects that the unqlite_file.pMethods 605 | * element will be valid after xOpen returns regardless of the success or failure of the 606 | * xOpen call. 607 | * 608 | */ 609 | struct unqlite_vfs { 610 | const char *zName; /* Name of this virtual file system [i.e: Windows, UNIX, etc.] */ 611 | int iVersion; /* Structure version number (currently 1) */ 612 | int szOsFile; /* Size of subclassed unqlite_file */ 613 | int mxPathname; /* Maximum file pathname length */ 614 | int (*xOpen)(unqlite_vfs*, const char *zName, unqlite_file*,unsigned int flags); 615 | int (*xDelete)(unqlite_vfs*, const char *zName, int syncDir); 616 | int (*xAccess)(unqlite_vfs*, const char *zName, int flags, int *pResOut); 617 | int (*xFullPathname)(unqlite_vfs*, const char *zName,int buf_len,char *zBuf); 618 | int (*xTmpDir)(unqlite_vfs*,char *zBuf,int buf_len); 619 | int (*xSleep)(unqlite_vfs*, int microseconds); 620 | int (*xCurrentTime)(unqlite_vfs*,Sytm *pOut); 621 | int (*xGetLastError)(unqlite_vfs*, int, char *); 622 | }; 623 | /* 624 | * Flags for the xAccess VFS method 625 | * 626 | * These integer constants can be used as the third parameter to 627 | * the xAccess method of an [unqlite_vfs] object. They determine 628 | * what kind of permissions the xAccess method is looking for. 629 | * With UNQLITE_ACCESS_EXISTS, the xAccess method 630 | * simply checks whether the file exists. 631 | * With UNQLITE_ACCESS_READWRITE, the xAccess method 632 | * checks whether the named directory is both readable and writable 633 | * (in other words, if files can be added, removed, and renamed within 634 | * the directory). 635 | * The UNQLITE_ACCESS_READWRITE constant is currently used only by the 636 | * [temp_store_directory pragma], though this could change in a future 637 | * release of UnQLite. 638 | * With UNQLITE_ACCESS_READ, the xAccess method 639 | * checks whether the file is readable. The UNQLITE_ACCESS_READ constant is 640 | * currently unused, though it might be used in a future release of 641 | * UnQLite. 642 | */ 643 | #define UNQLITE_ACCESS_EXISTS 0 644 | #define UNQLITE_ACCESS_READWRITE 1 645 | #define UNQLITE_ACCESS_READ 2 646 | /* 647 | * The type used to represent a page number. The first page in a file 648 | * is called page 1. 0 is used to represent "not a page". 649 | * A page number is an unsigned 64-bit integer. 650 | */ 651 | typedef sxu64 pgno; 652 | /* 653 | * A database disk page is represented by an instance 654 | * of the follwoing structure. 655 | */ 656 | typedef struct unqlite_page unqlite_page; 657 | struct unqlite_page 658 | { 659 | unsigned char *zData; /* Content of this page */ 660 | void *pUserData; /* Extra content */ 661 | pgno pgno; /* Page number for this page */ 662 | }; 663 | /* 664 | * UnQLite handle to the underlying Key/Value Storage Engine (See below). 665 | */ 666 | typedef void * unqlite_kv_handle; 667 | /* 668 | * UnQLite pager IO methods. 669 | * 670 | * An instance of the following structure define the exported methods of the UnQLite pager 671 | * to the underlying Key/Value storage engine. 672 | */ 673 | typedef struct unqlite_kv_io unqlite_kv_io; 674 | struct unqlite_kv_io 675 | { 676 | unqlite_kv_handle pHandle; /* UnQLite handle passed as the first parameter to the 677 | * method defined below. 678 | */ 679 | unqlite_kv_methods *pMethods; /* Underlying storage engine */ 680 | /* Pager methods */ 681 | int (*xGet)(unqlite_kv_handle,pgno,unqlite_page **); 682 | int (*xLookup)(unqlite_kv_handle,pgno,unqlite_page **); 683 | int (*xNew)(unqlite_kv_handle,unqlite_page **); 684 | int (*xWrite)(unqlite_page *); 685 | int (*xDontWrite)(unqlite_page *); 686 | int (*xDontJournal)(unqlite_page *); 687 | int (*xDontMkHot)(unqlite_page *); 688 | int (*xPageRef)(unqlite_page *); 689 | int (*xPageUnref)(unqlite_page *); 690 | int (*xPageSize)(unqlite_kv_handle); 691 | int (*xReadOnly)(unqlite_kv_handle); 692 | unsigned char * (*xTmpPage)(unqlite_kv_handle); 693 | void (*xSetUnpin)(unqlite_kv_handle,void (*xPageUnpin)(void *)); 694 | void (*xSetReload)(unqlite_kv_handle,void (*xPageReload)(void *)); 695 | void (*xErr)(unqlite_kv_handle,const char *); 696 | }; 697 | /* 698 | * Key/Value Storage Engine Cursor Object 699 | * 700 | * An instance of a subclass of the following object defines a cursor 701 | * used to scan through a key-value storage engine. 702 | */ 703 | typedef struct unqlite_kv_cursor unqlite_kv_cursor; 704 | struct unqlite_kv_cursor 705 | { 706 | unqlite_kv_engine *pStore; /* Must be first */ 707 | /* Subclasses will typically add additional fields */ 708 | }; 709 | /* 710 | * Possible seek positions. 711 | */ 712 | #define UNQLITE_CURSOR_MATCH_EXACT 1 713 | #define UNQLITE_CURSOR_MATCH_LE 2 714 | #define UNQLITE_CURSOR_MATCH_GE 3 715 | /* 716 | * Key/Value Storage Engine. 717 | * 718 | * A Key-Value storage engine is defined by an instance of the following 719 | * object. 720 | * UnQLite works with run-time interchangeable storage engines (i.e. Hash, B+Tree, R+Tree, LSM, etc.). 721 | * The storage engine works with key/value pairs where both the key 722 | * and the value are byte arrays of arbitrary length and with no restrictions on content. 723 | * UnQLite come with two built-in KV storage engine: A Virtual Linear Hash (VLH) storage 724 | * engine is used for persistent on-disk databases with O(1) lookup time and an in-memory 725 | * hash-table or Red-black tree storage engine is used for in-memory databases. 726 | * Future versions of UnQLite might add other built-in storage engines (i.e. LSM). 727 | * Registration of a Key/Value storage engine at run-time is done via [unqlite_lib_config()] 728 | * with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE. 729 | */ 730 | struct unqlite_kv_engine 731 | { 732 | const unqlite_kv_io *pIo; /* IO methods: MUST be first */ 733 | /* Subclasses will typically add additional fields */ 734 | }; 735 | /* 736 | * Key/Value Storage Engine Virtual Method Table. 737 | * 738 | * Key/Value storage engine methods is defined by an instance of the following 739 | * object. 740 | * Registration of a Key/Value storage engine at run-time is done via [unqlite_lib_config()] 741 | * with a configuration verb set to UNQLITE_LIB_CONFIG_STORAGE_ENGINE. 742 | */ 743 | struct unqlite_kv_methods 744 | { 745 | const char *zName; /* Storage engine name [i.e. Hash, B+tree, LSM, R-tree, Mem, etc.]*/ 746 | int szKv; /* 'unqlite_kv_engine' subclass size */ 747 | int szCursor; /* 'unqlite_kv_cursor' subclass size */ 748 | int iVersion; /* Structure version, currently 1 */ 749 | /* Storage engine methods */ 750 | int (*xInit)(unqlite_kv_engine *,int iPageSize); 751 | void (*xRelease)(unqlite_kv_engine *); 752 | int (*xConfig)(unqlite_kv_engine *,int op,va_list ap); 753 | int (*xOpen)(unqlite_kv_engine *,pgno); 754 | int (*xReplace)( 755 | unqlite_kv_engine *, 756 | const void *pKey,int nKeyLen, 757 | const void *pData,unqlite_int64 nDataLen 758 | ); 759 | int (*xAppend)( 760 | unqlite_kv_engine *, 761 | const void *pKey,int nKeyLen, 762 | const void *pData,unqlite_int64 nDataLen 763 | ); 764 | void (*xCursorInit)(unqlite_kv_cursor *); 765 | int (*xSeek)(unqlite_kv_cursor *,const void *pKey,int nByte,int iPos); /* Mandatory */ 766 | int (*xFirst)(unqlite_kv_cursor *); 767 | int (*xLast)(unqlite_kv_cursor *); 768 | int (*xValid)(unqlite_kv_cursor *); 769 | int (*xNext)(unqlite_kv_cursor *); 770 | int (*xPrev)(unqlite_kv_cursor *); 771 | int (*xDelete)(unqlite_kv_cursor *); 772 | int (*xKeyLength)(unqlite_kv_cursor *,int *); 773 | int (*xKey)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData); 774 | int (*xDataLength)(unqlite_kv_cursor *,unqlite_int64 *); 775 | int (*xData)(unqlite_kv_cursor *,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData); 776 | void (*xReset)(unqlite_kv_cursor *); 777 | void (*xCursorRelease)(unqlite_kv_cursor *); 778 | }; 779 | /* 780 | * UnQLite journal file suffix. 781 | */ 782 | #ifndef UNQLITE_JOURNAL_FILE_SUFFIX 783 | #define UNQLITE_JOURNAL_FILE_SUFFIX "_unqlite_journal" 784 | #endif 785 | /* 786 | * Call Context - Error Message Serverity Level. 787 | * 788 | * The following constans are the allowed severity level that can 789 | * passed as the second argument to the [unqlite_context_throw_error()] or 790 | * [unqlite_context_throw_error_format()] interfaces. 791 | * Refer to the official documentation for additional information. 792 | */ 793 | #define UNQLITE_CTX_ERR 1 /* Call context error such as unexpected number of arguments, invalid types and so on. */ 794 | #define UNQLITE_CTX_WARNING 2 /* Call context Warning */ 795 | #define UNQLITE_CTX_NOTICE 3 /* Call context Notice */ 796 | /* 797 | * C-API-REF: Please refer to the official documentation for interfaces 798 | * purpose and expected parameters. 799 | */ 800 | 801 | /* Database Engine Handle */ 802 | UNQLITE_APIEXPORT int unqlite_open(unqlite **ppDB,const char *zFilename,unsigned int iMode); 803 | UNQLITE_APIEXPORT int unqlite_config(unqlite *pDb,int nOp,...); 804 | UNQLITE_APIEXPORT int unqlite_close(unqlite *pDb); 805 | 806 | 807 | /* Key/Value (KV) Store Interfaces */ 808 | UNQLITE_APIEXPORT int unqlite_kv_store(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen); 809 | UNQLITE_APIEXPORT int unqlite_kv_append(unqlite *pDb,const void *pKey,int nKeyLen,const void *pData,unqlite_int64 nDataLen); 810 | UNQLITE_APIEXPORT int unqlite_kv_store_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...); 811 | UNQLITE_APIEXPORT int unqlite_kv_append_fmt(unqlite *pDb,const void *pKey,int nKeyLen,const char *zFormat,...); 812 | UNQLITE_APIEXPORT int unqlite_kv_fetch(unqlite *pDb,const void *pKey,int nKeyLen,void *pBuf,unqlite_int64 /* in|out */*pBufLen); 813 | UNQLITE_APIEXPORT int unqlite_kv_fetch_callback(unqlite *pDb,const void *pKey, 814 | int nKeyLen,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData); 815 | UNQLITE_APIEXPORT int unqlite_kv_delete(unqlite *pDb,const void *pKey,int nKeyLen); 816 | UNQLITE_APIEXPORT int unqlite_kv_config(unqlite *pDb,int iOp,...); 817 | 818 | /* Document (JSON) Store Interfaces powered by the Jx9 Scripting Language */ 819 | UNQLITE_APIEXPORT int unqlite_compile(unqlite *pDb,const char *zJx9,int nByte,unqlite_vm **ppOut); 820 | UNQLITE_APIEXPORT int unqlite_compile_file(unqlite *pDb,const char *zPath,unqlite_vm **ppOut); 821 | UNQLITE_APIEXPORT int unqlite_vm_config(unqlite_vm *pVm,int iOp,...); 822 | UNQLITE_APIEXPORT int unqlite_vm_exec(unqlite_vm *pVm); 823 | UNQLITE_APIEXPORT int unqlite_vm_reset(unqlite_vm *pVm); 824 | UNQLITE_APIEXPORT int unqlite_vm_release(unqlite_vm *pVm); 825 | UNQLITE_APIEXPORT int unqlite_vm_dump(unqlite_vm *pVm, int (*xConsumer)(const void *, unsigned int, void *), void *pUserData); 826 | UNQLITE_APIEXPORT unqlite_value * unqlite_vm_extract_variable(unqlite_vm *pVm,const char *zVarname); 827 | 828 | /* Cursor Iterator Interfaces */ 829 | UNQLITE_APIEXPORT int unqlite_kv_cursor_init(unqlite *pDb,unqlite_kv_cursor **ppOut); 830 | UNQLITE_APIEXPORT int unqlite_kv_cursor_release(unqlite *pDb,unqlite_kv_cursor *pCur); 831 | UNQLITE_APIEXPORT int unqlite_kv_cursor_seek(unqlite_kv_cursor *pCursor,const void *pKey,int nKeyLen,int iPos); 832 | UNQLITE_APIEXPORT int unqlite_kv_cursor_first_entry(unqlite_kv_cursor *pCursor); 833 | UNQLITE_APIEXPORT int unqlite_kv_cursor_last_entry(unqlite_kv_cursor *pCursor); 834 | UNQLITE_APIEXPORT int unqlite_kv_cursor_valid_entry(unqlite_kv_cursor *pCursor); 835 | UNQLITE_APIEXPORT int unqlite_kv_cursor_next_entry(unqlite_kv_cursor *pCursor); 836 | UNQLITE_APIEXPORT int unqlite_kv_cursor_prev_entry(unqlite_kv_cursor *pCursor); 837 | UNQLITE_APIEXPORT int unqlite_kv_cursor_key(unqlite_kv_cursor *pCursor,void *pBuf,int *pnByte); 838 | UNQLITE_APIEXPORT int unqlite_kv_cursor_key_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData); 839 | UNQLITE_APIEXPORT int unqlite_kv_cursor_data(unqlite_kv_cursor *pCursor,void *pBuf,unqlite_int64 *pnData); 840 | UNQLITE_APIEXPORT int unqlite_kv_cursor_data_callback(unqlite_kv_cursor *pCursor,int (*xConsumer)(const void *,unsigned int,void *),void *pUserData); 841 | UNQLITE_APIEXPORT int unqlite_kv_cursor_delete_entry(unqlite_kv_cursor *pCursor); 842 | UNQLITE_APIEXPORT int unqlite_kv_cursor_reset(unqlite_kv_cursor *pCursor); 843 | 844 | /* Manual Transaction Manager */ 845 | UNQLITE_APIEXPORT int unqlite_begin(unqlite *pDb); 846 | UNQLITE_APIEXPORT int unqlite_commit(unqlite *pDb); 847 | UNQLITE_APIEXPORT int unqlite_rollback(unqlite *pDb); 848 | 849 | /* Utility interfaces */ 850 | UNQLITE_APIEXPORT int unqlite_util_load_mmaped_file(const char *zFile,void **ppMap,unqlite_int64 *pFileSize); 851 | UNQLITE_APIEXPORT int unqlite_util_release_mmaped_file(void *pMap,unqlite_int64 iFileSize); 852 | UNQLITE_APIEXPORT int unqlite_util_random_string(unqlite *pDb,char *zBuf,unsigned int buf_size); 853 | UNQLITE_APIEXPORT unsigned int unqlite_util_random_num(unqlite *pDb); 854 | 855 | /* In-process extending interfaces */ 856 | UNQLITE_APIEXPORT int unqlite_create_function(unqlite_vm *pVm,const char *zName,int (*xFunc)(unqlite_context *,int,unqlite_value **),void *pUserData); 857 | UNQLITE_APIEXPORT int unqlite_delete_function(unqlite_vm *pVm, const char *zName); 858 | UNQLITE_APIEXPORT int unqlite_create_constant(unqlite_vm *pVm,const char *zName,void (*xExpand)(unqlite_value *, void *),void *pUserData); 859 | UNQLITE_APIEXPORT int unqlite_delete_constant(unqlite_vm *pVm, const char *zName); 860 | 861 | /* On Demand Object allocation interfaces */ 862 | UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_scalar(unqlite_vm *pVm); 863 | UNQLITE_APIEXPORT unqlite_value * unqlite_vm_new_array(unqlite_vm *pVm); 864 | UNQLITE_APIEXPORT int unqlite_vm_release_value(unqlite_vm *pVm,unqlite_value *pValue); 865 | UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_scalar(unqlite_context *pCtx); 866 | UNQLITE_APIEXPORT unqlite_value * unqlite_context_new_array(unqlite_context *pCtx); 867 | UNQLITE_APIEXPORT void unqlite_context_release_value(unqlite_context *pCtx,unqlite_value *pValue); 868 | 869 | /* Dynamically Typed Value Object Management Interfaces */ 870 | UNQLITE_APIEXPORT int unqlite_value_int(unqlite_value *pVal, int iValue); 871 | UNQLITE_APIEXPORT int unqlite_value_int64(unqlite_value *pVal, unqlite_int64 iValue); 872 | UNQLITE_APIEXPORT int unqlite_value_bool(unqlite_value *pVal, int iBool); 873 | UNQLITE_APIEXPORT int unqlite_value_null(unqlite_value *pVal); 874 | UNQLITE_APIEXPORT int unqlite_value_double(unqlite_value *pVal, double Value); 875 | UNQLITE_APIEXPORT int unqlite_value_string(unqlite_value *pVal, const char *zString, int nLen); 876 | UNQLITE_APIEXPORT int unqlite_value_string_format(unqlite_value *pVal, const char *zFormat,...); 877 | UNQLITE_APIEXPORT int unqlite_value_reset_string_cursor(unqlite_value *pVal); 878 | UNQLITE_APIEXPORT int unqlite_value_resource(unqlite_value *pVal, void *pUserData); 879 | UNQLITE_APIEXPORT int unqlite_value_release(unqlite_value *pVal); 880 | 881 | /* Foreign Function Parameter Values */ 882 | UNQLITE_APIEXPORT int unqlite_value_to_int(unqlite_value *pValue); 883 | UNQLITE_APIEXPORT int unqlite_value_to_bool(unqlite_value *pValue); 884 | UNQLITE_APIEXPORT unqlite_int64 unqlite_value_to_int64(unqlite_value *pValue); 885 | UNQLITE_APIEXPORT double unqlite_value_to_double(unqlite_value *pValue); 886 | UNQLITE_APIEXPORT const char * unqlite_value_to_string(unqlite_value *pValue, int *pLen); 887 | UNQLITE_APIEXPORT void * unqlite_value_to_resource(unqlite_value *pValue); 888 | UNQLITE_APIEXPORT int unqlite_value_compare(unqlite_value *pLeft, unqlite_value *pRight, int bStrict); 889 | 890 | /* Setting The Result Of A Foreign Function */ 891 | UNQLITE_APIEXPORT int unqlite_result_int(unqlite_context *pCtx, int iValue); 892 | UNQLITE_APIEXPORT int unqlite_result_int64(unqlite_context *pCtx, unqlite_int64 iValue); 893 | UNQLITE_APIEXPORT int unqlite_result_bool(unqlite_context *pCtx, int iBool); 894 | UNQLITE_APIEXPORT int unqlite_result_double(unqlite_context *pCtx, double Value); 895 | UNQLITE_APIEXPORT int unqlite_result_null(unqlite_context *pCtx); 896 | UNQLITE_APIEXPORT int unqlite_result_string(unqlite_context *pCtx, const char *zString, int nLen); 897 | UNQLITE_APIEXPORT int unqlite_result_string_format(unqlite_context *pCtx, const char *zFormat, ...); 898 | UNQLITE_APIEXPORT int unqlite_result_value(unqlite_context *pCtx, unqlite_value *pValue); 899 | UNQLITE_APIEXPORT int unqlite_result_resource(unqlite_context *pCtx, void *pUserData); 900 | 901 | /* Dynamically Typed Value Object Query Interfaces */ 902 | UNQLITE_APIEXPORT int unqlite_value_is_int(unqlite_value *pVal); 903 | UNQLITE_APIEXPORT int unqlite_value_is_float(unqlite_value *pVal); 904 | UNQLITE_APIEXPORT int unqlite_value_is_bool(unqlite_value *pVal); 905 | UNQLITE_APIEXPORT int unqlite_value_is_string(unqlite_value *pVal); 906 | UNQLITE_APIEXPORT int unqlite_value_is_null(unqlite_value *pVal); 907 | UNQLITE_APIEXPORT int unqlite_value_is_numeric(unqlite_value *pVal); 908 | UNQLITE_APIEXPORT int unqlite_value_is_callable(unqlite_value *pVal); 909 | UNQLITE_APIEXPORT int unqlite_value_is_scalar(unqlite_value *pVal); 910 | UNQLITE_APIEXPORT int unqlite_value_is_json_array(unqlite_value *pVal); 911 | UNQLITE_APIEXPORT int unqlite_value_is_json_object(unqlite_value *pVal); 912 | UNQLITE_APIEXPORT int unqlite_value_is_resource(unqlite_value *pVal); 913 | UNQLITE_APIEXPORT int unqlite_value_is_empty(unqlite_value *pVal); 914 | 915 | /* JSON Array/Object Management Interfaces */ 916 | UNQLITE_APIEXPORT unqlite_value * unqlite_array_fetch(unqlite_value *pArray, const char *zKey, int nByte); 917 | UNQLITE_APIEXPORT int unqlite_array_walk(unqlite_value *pArray, int (*xWalk)(unqlite_value *, unqlite_value *, void *), void *pUserData); 918 | UNQLITE_APIEXPORT int unqlite_array_add_elem(unqlite_value *pArray, unqlite_value *pKey, unqlite_value *pValue); 919 | UNQLITE_APIEXPORT int unqlite_array_add_strkey_elem(unqlite_value *pArray, const char *zKey, unqlite_value *pValue); 920 | UNQLITE_APIEXPORT int unqlite_array_count(unqlite_value *pArray); 921 | 922 | /* Call Context Handling Interfaces */ 923 | UNQLITE_APIEXPORT int unqlite_context_output(unqlite_context *pCtx, const char *zString, int nLen); 924 | UNQLITE_APIEXPORT int unqlite_context_output_format(unqlite_context *pCtx,const char *zFormat, ...); 925 | UNQLITE_APIEXPORT int unqlite_context_throw_error(unqlite_context *pCtx, int iErr, const char *zErr); 926 | UNQLITE_APIEXPORT int unqlite_context_throw_error_format(unqlite_context *pCtx, int iErr, const char *zFormat, ...); 927 | UNQLITE_APIEXPORT unsigned int unqlite_context_random_num(unqlite_context *pCtx); 928 | UNQLITE_APIEXPORT int unqlite_context_random_string(unqlite_context *pCtx, char *zBuf, int nBuflen); 929 | UNQLITE_APIEXPORT void * unqlite_context_user_data(unqlite_context *pCtx); 930 | UNQLITE_APIEXPORT int unqlite_context_push_aux_data(unqlite_context *pCtx, void *pUserData); 931 | UNQLITE_APIEXPORT void * unqlite_context_peek_aux_data(unqlite_context *pCtx); 932 | UNQLITE_APIEXPORT unsigned int unqlite_context_result_buf_length(unqlite_context *pCtx); 933 | UNQLITE_APIEXPORT const char * unqlite_function_name(unqlite_context *pCtx); 934 | 935 | /* Call Context Memory Management Interfaces */ 936 | UNQLITE_APIEXPORT void * unqlite_context_alloc_chunk(unqlite_context *pCtx,unsigned int nByte,int ZeroChunk,int AutoRelease); 937 | UNQLITE_APIEXPORT void * unqlite_context_realloc_chunk(unqlite_context *pCtx,void *pChunk,unsigned int nByte); 938 | UNQLITE_APIEXPORT void unqlite_context_free_chunk(unqlite_context *pCtx,void *pChunk); 939 | 940 | /* Global Library Management Interfaces */ 941 | UNQLITE_APIEXPORT int unqlite_lib_config(int nConfigOp,...); 942 | UNQLITE_APIEXPORT int unqlite_lib_init(void); 943 | UNQLITE_APIEXPORT int unqlite_lib_shutdown(void); 944 | UNQLITE_APIEXPORT int unqlite_lib_is_threadsafe(void); 945 | UNQLITE_APIEXPORT const char * unqlite_lib_version(void); 946 | UNQLITE_APIEXPORT const char * unqlite_lib_signature(void); 947 | UNQLITE_APIEXPORT const char * unqlite_lib_ident(void); 948 | UNQLITE_APIEXPORT const char * unqlite_lib_copyright(void); 949 | 950 | #endif /* _UNQLITE_H_ */ 951 | --------------------------------------------------------------------------------