#59 #72
authoradam <adamansky@gmail.com>
Thu, 18 Jul 2013 11:03:18 +0000 (18:03 +0700)
committeradam <adamansky@gmail.com>
Thu, 18 Jul 2013 11:03:18 +0000 (18:03 +0700)
29 files changed:
Changelog
luaejdb/debian/changelog
luaejdb/debian/control
luaejdb/doc/index.html
luaejdb/ejdb.lua
luaejdb/ejdb.luadoc
luaejdb/luaejdb-1.0.5-1.rockspec [moved from luaejdb/luaejdb-1.0.4-1.rockspec with 97% similarity]
luaejdb/luaejdb.c
luaejdb/test/t1.lua
node/ejdb.js
node/ejdb_native.cc
node/tests/t2.js
package.json
pyejdb/debian/changelog
pyejdb/debian/control
pyejdb/pyejdb.iml
pyejdb/pyejdb/__init__.py
pyejdb/setup.py [changed mode: 0755->0644]
pyejdb/src/pejdb.c
pyejdb/test/test_one.py
tcejdb/Changelog
tcejdb/Makefile.in
tcejdb/configure
tcejdb/configure.ac
tcejdb/debian/changelog
tcejdb/debian/libtcejdb9.symbols
tcejdb/ejdb.c
tcejdb/ejdb.h
tcejdb/tcutil.h

index 2db1ca3..2754184 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,10 @@
+libtcejdb (1.1.14) testing; urgency=low
+
+  * Supports generic ejdb commands interface
+  * Export/Import database data implemented
+
+ -- Anton Adamansky <adamansky@gmail.com>  Thu, 18 Jul 2013 15:44:31 +0700
+
 libtcejdb (1.1.13) testing; urgency=low
 
   * .Net binding
index d18536a..1c93d1f 100644 (file)
@@ -1,3 +1,9 @@
+lua-ejdb (1.0.5-1) testing; urgency=low
+
+  * EJDB 1.1.14
+
+ -- Anton Adamansky <adamansky@gmail.com>  Thu, 18 Jul 2013 17:59:41 +0700
+
 lua-ejdb (1.0.4-1) testing; urgency=low
 
   * EJDB 1.1.13 
index 9106a54..6c86414 100644 (file)
@@ -4,7 +4,7 @@ Priority: optional
 Maintainer: Anton Adamansky <adamansky@gmail.com>
 Build-Depends:
  debhelper (>= 9),
- libtcejdb9-dev (>= 1.1.13),
+ libtcejdb9-dev (>= 1.1.14),
  luarocks (>= 2.0),
  lua-penlight,
  lua-filesystem
@@ -18,7 +18,7 @@ Architecture: any
 Depends:
  ${misc:Depends},
  ${shlibs:Depends},
- libtcejdb9 (>= 1.1.13)
+ libtcejdb9 (>= 1.1.14)
 Recommends: lua5.1
 Description: Lua binding for EJDB
  EJDB aims to be a fast MongoDB-like library which can be embedded into C/C++/NodeJS/Python/Lua
index b21654f..4cc4551 100644 (file)
        <td class="summary">Builds BSON_UNDEFINED value .</td>
        </tr>
        <tr>
+       <td class="name" nowrap><a href="#DB.version">DB.version&nbsp;()</a></td>
+       <td class="summary">Returns EJDB version string eg: "1.1.14"</td>
+       </tr>
+       <tr>
        <td class="name" nowrap><a href="#DB:save">DB:save&nbsp;(cname, obj, ...)</a></td>
        <td class="summary">Save/update specified JSON objects in the collection.</td>
        </tr>
        <tr>
+       <td class="name" nowrap><a href="#DB:load">DB:load&nbsp;(cname, oid)</a></td>
+       <td class="summary">Loads JSON object identified by OID from the collection.</td>
+       </tr>
+       <tr>
+       <td class="name" nowrap><a href="#DB:command">DB:command&nbsp;(cmd)</a></td>
+       <td class="summary">Executes ejdb command.</td>
+       </tr>
+       <tr>
        <td class="name" nowrap><a href="#DB:find">DB:find&nbsp;(cname, q, flags)</a></td>
        <td class="summary">Execute query on collection.</td>
        </tr>
 
 </dd>
     <dt>
+    <a name = "DB.version"></a>
+    <strong>DB.version&nbsp;()</strong>
+    </dt>
+    <dd>
+    Returns EJDB version string eg: "1.1.14"
+
+
+
+
+
+
+</dd>
+    <dt>
     <a name = "DB:save"></a>
     <strong>DB:save&nbsp;(cname, obj, ...)</strong>
     </dt>
 
 </dd>
     <dt>
+    <a name = "DB:load"></a>
+    <strong>DB:load&nbsp;(cname, oid)</strong>
+    </dt>
+    <dd>
+    Loads JSON object identified by OID from the collection.
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">cname</span>
+            <span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
+         Collection name</li>
+        <li><span class="parameter">oid</span>
+            <span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.4">string</a> or <a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
+         24 hex chars BSON_OID or BSON oid table</li>
+    </ul>
+
+
+
+
+
+</dd>
+    <dt>
+    <a name = "DB:command"></a>
+    <strong>DB:command&nbsp;(cmd)</strong>
+    </dt>
+    <dd>
+
+<p>Executes ejdb command.
+ Supported commands:</p>
+<pre><code>1) Exports database collections data. See ejdbexport() method.
+
+  "export" : {
+        "path" : string,                    //Exports database collections data
+        "cnames" : [string array]|null,     //List of collection names to export
+        "mode" : int|null                   //Values: null|`JBJSONEXPORT` See ejdbexport() method
+  }
+
+  Command response:
+     {
+        "log" : string,        //Diagnostic log about executing this command
+        "error" : string|null, //ejdb error message
+        "errorCode" : int|0,   //ejdb error code
+     }
+
+2) Imports previously exported collections data into ejdb.
+
+  "import" : {
+        "path" : string                     //The directory path in which data resides
+        "cnames" : [string array]|null,     //List of collection names to import
+        "mode" : int|null                //Values: null|`JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdbimport() method
+   }
+
+   Command response:
+     {
+        "log" : string,        //Diagnostic log about executing this command
+        "error" : string|null, //ejdb error message
+        "errorCode" : int|0,   //ejdb error code
+     }
+</code></pre>
+
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">cmd</span>
+            <span class="types"><a class="type" href="http://www.lua.org/manual/5.1/manual.html#5.5">table</a> or <a class="type" href="index.html#Q">Q</a></span>
+         Command object.</li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        Command response table
+    </ol>
+
+
+
+
+</dd>
+    <dt>
     <a name = "DB:find"></a>
     <strong>DB:find&nbsp;(cname, q, flags)</strong>
     </dt>
index 25be60f..145d703 100644 (file)
@@ -124,6 +124,18 @@ function luaejdb.open(path, omode, ...)
   return setmetatable(luaejdb_open(path, omode), mtDBObj)
 end
 
+
+function DB:command(cmd)
+  assert(cmd and type(cmd) == "table", "Invalid arg #1")
+  if getmetatable(cmd) == mtBObj then
+    cmd = cmd:toBSON()
+  else
+    cmd = luaejdb.to_bson(cmd)
+  end
+  return self:_command(cmd)
+end
+
+
 function DB:save(cname, obj, ...)
   assert(obj and type(obj) == "table", "Invalid arg #2")
   if getmetatable(obj) == mtBObj then
index 8b9b54c..e0067a8 100644 (file)
@@ -235,6 +235,9 @@ function DB.toNull() end
 -- @see ejdb.toUndefined
 function DB.toUndefined() end
 
+--- Returns EJDB version string eg: "1.1.14"
+function DB.version() end
+
 --- Save/update specified JSON objects in the collection.
 -- If collection with `cname` does not exists it will be created.
 -- Each persistent object has unique identifier (OID) placed in the `_id` property.
@@ -248,6 +251,46 @@ function DB.toUndefined() end
 -- @usage dQ:save("parrots2", Q("foo", "bar"), true) -- merge option is on
 function DB:save(cname, obj, ...) end
 
+--- Loads JSON object identified by OID from the collection.
+-- @tparam string cname Collection name
+-- @tparam string|table oid 24 hex chars BSON_OID or BSON oid table
+function DB:load(cname, oid) end
+
+--- Executes ejdb command.
+-- Supported commands:
+--    1) Exports database collections data. See ejdbexport() method.
+--
+--      "export" : {
+--            "path" : string,                    //Exports database collections data
+--            "cnames" : [string array]|null,     //List of collection names to export
+--            "mode" : int|null                   //Values: null|`JBJSONEXPORT` See ejdbexport() method
+--      }
+--
+--      Command response:
+--         {
+--            "log" : string,        //Diagnostic log about executing this command
+--            "error" : string|null, //ejdb error message
+--            "errorCode" : int|0,   //ejdb error code
+--         }
+--
+--    2) Imports previously exported collections data into ejdb.
+--
+--      "import" : {
+--            "path" : string                     //The directory path in which data resides
+--            "cnames" : [string array]|null,     //List of collection names to import
+--            "mode" : int|null                //Values: null|`JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdbimport() method
+--       }
+--
+--       Command response:
+--         {
+--            "log" : string,        //Diagnostic log about executing this command
+--            "error" : string|null, //ejdb error message
+--            "errorCode" : int|0,   //ejdb error code
+--         }
+-- @tparam table|Q cmd Command object.
+-- @return Command response table
+function DB:command(cmd) end
+
 --- Execute query on collection.
 --
 -- EJDB queries inspired by MongoDB (mongodb.org) and follows same philosophy.
similarity index 97%
rename from luaejdb/luaejdb-1.0.4-1.rockspec
rename to luaejdb/luaejdb-1.0.5-1.rockspec
index d423769..10e8641 100644 (file)
@@ -1,5 +1,5 @@
 package = "luaejdb"
-version = "1.0.4-1"
+version = "1.0.5-1"
 source = {
   url = "https://github.com/Softmotions/ejdb.git"
 }
index 4c41391..4d62236 100644 (file)
@@ -484,118 +484,32 @@ static int db_txctl(lua_State *L) {
 }
 
 static int db_meta(lua_State *L) {
-    lua_checkstack(L, 6);
     int argc = lua_gettop(L);
     luaL_checktype(L, 1, LUA_TTABLE); //self
     lua_getfield(L, 1, EJDBUDATAKEY);
     EJDB *jb = ((EJDBDATA*) luaL_checkudata(L, -1, EJDBUDATAMT))->db;
     check_ejdb(L, jb);
-    bool jbret = true;
     lua_pop(L, 1);
-
-    lua_newtable(L); //+root info
-
-    lua_pushstring(L, jb->metadb->hdb->path);
-    lua_setfield(L, -2, "file");
-
-    lua_newtable(L); //+collections
-    TCLIST *cols = ejdbgetcolls(jb);
-    if (!cols) {
-        return set_ejdb_error(L, jb);
-    }
-    int i;
-    for (i = 0; i < TCLISTNUM(cols); ++i) {
-        EJCOLL *coll = (EJCOLL*) TCLISTVALPTR(cols, i);
-        if (!ejcollockmethod(coll, false)) continue;
-
-        lua_pushlstring(L, coll->cname, coll->cnamesz); //coll key
-
-        lua_newtable(L); //+ coll table
-
-        lua_pushlstring(L, coll->cname, coll->cnamesz);
-        lua_setfield(L, -2, "name");
-
-        lua_pushstring(L, coll->tdb->hdb->path);
-        lua_setfield(L, -2, "file");
-
-        lua_pushinteger(L, coll->tdb->hdb->rnum);
-        lua_setfield(L, -2, "records");
-
-        lua_newtable(L); //+ coll options
-
-        lua_pushinteger(L, coll->tdb->hdb->bnum);
-        lua_setfield(L, -2, "buckets");
-
-        lua_pushinteger(L, coll->tdb->hdb->rcnum);
-        lua_setfield(L, -2, "cachedrecords");
-
-        lua_pushboolean(L, coll->tdb->opts & TDBTLARGE);
-        lua_setfield(L, -2, "large");
-
-        lua_pushboolean(L, coll->tdb->opts & TDBTDEFLATE);
-        lua_setfield(L, -2, "compressed");
-        lua_setfield(L, -2, "options");
-
-        lua_newtable(L); //+ coll indexes
-
-        int ic = 0;
-        int j;
-        for (j = 0; j < coll->tdb->inum; ++j) {
-            TDBIDX *idx = (coll->tdb->idxs + j);
-            if (idx->type != TDBITLEXICAL && idx->type != TDBITDECIMAL && idx->type != TDBITTOKEN) {
-                continue;
-            }
-            lua_newtable(L); //+ index details
-
-            lua_pushstring(L, idx->name + 1);
-            lua_setfield(L, -2, "field");
-
-            lua_pushstring(L, idx->name);
-            lua_setfield(L, -2, "iname");
-
-            switch (idx->type) {
-                case TDBITLEXICAL:
-                    lua_pushstring(L, "lexical");
-                    lua_setfield(L, -2, "type");
-                    break;
-                case TDBITDECIMAL:
-                    lua_pushstring(L, "decimal");
-                    lua_setfield(L, -2, "type");
-                    break;
-                case TDBITTOKEN:
-                    lua_pushstring(L, "token");
-                    lua_setfield(L, -2, "type");
-                    break;
-            }
-            TCBDB *idb = (TCBDB*) idx->db;
-            if (idb) {
-                lua_pushinteger(L, idb->rnum);
-                lua_setfield(L, -2, "records");
-
-                lua_pushstring(L, idb->hdb->path);
-                lua_setfield(L, -2, "file");
-            }
-            lua_rawseti(L, -2, ++ic);
-        }
-        lua_setfield(L, -2, "indexes");
-        lua_settable(L, -3);
-
-        ejcollunlockmethod(coll);
-    }
-    lua_setfield(L, -2, "collections");
-
-    if (cols) {
-        tclistdel(cols);
-    }
-    if (!jbret) {
-        return set_ejdb_error(L, jb);
+    bson *meta = ejdbmeta(jb);
+    if (meta == NULL) {
+        lua_pushnil(L);
+        return 1;
     }
+    bson_iterator it;
+    bson_iterator_init(&it, meta);
+    lua_push_bson_table(L, &it);
+    bson_del(meta);
     if (lua_gettop(L) - argc != 1) {
         return luaL_error(L, "db_meta: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
     }
     return 1;
 }
 
+static int db_version(lua_State *L) {
+    lua_pushstring(L, ejdbversion());
+    return 1;
+}
+
 static int db_save(lua_State *L) {
     int argc = lua_gettop(L);
     luaL_checktype(L, 1, LUA_TTABLE); //self
@@ -632,6 +546,36 @@ static int db_save(lua_State *L) {
     return 1;
 }
 
+static int db_command(lua_State *L) {
+    int argc = lua_gettop(L);
+    luaL_checktype(L, 1, LUA_TTABLE); //self
+    lua_getfield(L, 1, EJDBUDATAKEY);
+    EJDB *jb = ((EJDBDATA*) luaL_checkudata(L, -1, EJDBUDATAMT))->db;
+    check_ejdb(L, jb);
+    lua_pop(L, 1);
+    bson bsonval;
+    const char *bsonbuf = luaL_checkstring(L, 2); //Object to save
+    bson_init_finished_data(&bsonval, bsonbuf);
+    bsonval.flags |= BSON_FLAG_STACK_ALLOCATED;
+    bson *bs = ejdbcommand(jb, &bsonval);
+    if (!bs) {
+        lua_pushnil(L);
+        goto finish;
+    }
+    bson_iterator it;
+    bson_iterator_init(&it, bs);
+    lua_push_bson_table(L, &it);
+    bson_del(bs);
+
+finish:
+    if (lua_gettop(L) - argc != 1) { //got
+        return luaL_error(L, "db_command: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
+    }
+    bson_destroy(&bsonval);
+    return 1;
+}
+
+
 static int db_load(lua_State *L) {
     int argc = lua_gettop(L);
     luaL_checktype(L, 1, LUA_TTABLE); //self
@@ -678,7 +622,7 @@ static int db_load(lua_State *L) {
 
 finish:
     if (lua_gettop(L) - argc != 1) { //got
-        return luaL_error(L, "db_save: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
+        return luaL_error(L, "db_load: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
     }
     return 1;
 }
@@ -877,6 +821,9 @@ static int db_open(lua_State *L) {
     lua_pushcfunction(L, db_load);
     lua_setfield(L, -2, "load");
 
+    lua_pushcfunction(L, db_command);
+    lua_setfield(L, -2, "_command");
+
     lua_pushcfunction(L, db_find);
     lua_setfield(L, -2, "_find");
 
@@ -936,6 +883,9 @@ int luaopen_luaejdb(lua_State *L) {
     lua_pushcfunction(L, db_open);
     lua_setfield(L, -2, "open");
 
+    lua_pushcfunction(L, db_version);
+    lua_setfield(L, -2, "version");
+
     //Push cursor methods into metatable
     luaL_newmetatable(L, EJDBCURSORMT);
     luaL_register(L, NULL, ejdbcursor_m);
index 175e9dc..b3aad60 100644 (file)
@@ -214,6 +214,12 @@ db:dropCollection("ecoll", true);
 
 assert(db:count("ecoll", Q("k1", "v2")) == 0)
 
+local cret = db:command({ping = {}});
+assert(cret["log"] == "pong");
+
+
+--print(ejdb.version());
+
 assert(db:isOpen() == true)
 db:close()
 assert(db:isOpen() == false)
index ac55516..c5495f5 100644 (file)
@@ -471,6 +471,80 @@ EJDB.prototype.findOne = function() {
 
 
 /**
+ * Execute ejdb database command.
+ *
+ * Supported commands:
+ *
+ *
+ *  1) Exports database collections data. See ejdbexport() method.
+ *
+ *    "export" : {
+ *          "path" : string,                    //Exports database collections data
+ *          "cnames" : [string array]|null,     //List of collection names to export
+ *          "mode" : int|null                   //Values: null|`JBJSONEXPORT` See ejdbexport() method
+ *    }
+ *
+ *    Command response:
+ *       {
+ *          "log" : string,        //Diagnostic log about executing this command
+ *          "error" : string|null, //ejdb error message
+ *          "errorCode" : int|0,   //ejdb error code
+ *       }
+ *
+ *  2) Imports previously exported collections data into ejdb.
+ *
+ *    "import" : {
+ *          "path" : string                     //The directory path in which data resides
+ *          "cnames" : [string array]|null,     //List of collection names to import
+ *          "mode" : int|null                //Values: null|`JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdbimport() method
+ *     }
+ *
+ *     Command response:
+ *       {
+ *          "log" : string,        //Diagnostic log about executing this command
+ *          "error" : string|null, //ejdb error message
+ *          "errorCode" : int|0,   //ejdb error code
+ *       }
+ *
+ * If callback is not provided this function will be synchronous.
+ *
+ * @param {Object} cmd   BSON command spec.
+ * @param {Function} [cb] Callback function with arguments: (error, obj) where:
+ *          `obj`:  Command response JSON object.
+ * @return Command response JSON object if callback is not provided.
+ */
+EJDB.prototype.command = function(cmd, cb) {
+    if (cb) {
+        this._impl.command(cmd, function(err, cursor) {
+            if (err) {
+                cb(err);
+                return;
+            }
+            if (cursor.next()) {
+                try {
+                    cb(null, cursor.object());
+                } finally {
+                    cursor.close();
+                }
+            } else {
+                cb(null, null);
+            }
+        });
+    } else {
+        var ret = null;
+        var cursor = this._impl.command(cmd);
+        if (cursor && typeof cursor === "object") {
+            if (cursor.next()) {
+                ret = cursor.object();
+            }
+            cursor.close();
+        }
+        return ret;
+    }
+};
+
+
+/**
  * Convenient method to execute update queries.
  * If callback is not provided this function will be synchronous.
  *
index fd9b58a..2401a90 100644 (file)
@@ -509,7 +509,8 @@ namespace ejdb {
             cmdTxBegin = 8, //Begin collection transaction
             cmdTxAbort = 9, //Abort collection transaction
             cmdTxCommit = 10, //Commit collection transaction
-            cmdTxStatus = 11 //Get collection transaction status
+            cmdTxStatus = 11, //Get collection transaction status
+            cmdCmd = 12 //Execute EJDB command
         };
 
         struct BSONCmdData { //Any bson related cmd data
@@ -730,6 +731,37 @@ namespace ejdb {
             }
         }
 
+        static Handle<Value> s_cmd(const Arguments& args) {
+            HandleScope scope;
+            REQ_ARGS(1);
+            REQ_OBJ_ARG(0, cmdobj);
+
+            Local<Function> cb;
+            BSONQCmdData *cmdata = new BSONQCmdData("", 0);
+            bson *bs = bson_create();
+            bson_init_as_query(bs);
+            toBSON(cmdobj, bs, false);
+            if (bs->err) {
+                Local<String> msg = String::New(bson_first_errormsg(bs));
+                bson_del(bs);
+                delete cmdata;
+                return scope.Close(ThrowException(Exception::Error(msg)));
+            }
+            bson_finish(bs);
+            cmdata->bsons.push_back(bs);
+            NodeEJDB *njb = ObjectWrap::Unwrap< NodeEJDB > (args.This());
+            if (args[1]->IsFunction()) { //callback provided
+                cb = Local<Function>::Cast(args[1]);
+                BSONQCmdTask *task = new BSONQCmdTask(cb, njb, cmdCmd, cmdata, BSONQCmdTask::delete_val);
+                uv_queue_work(uv_default_loop(), &task->uv_work, s_exec_cmd_eio, (uv_after_work_cb)s_exec_cmd_eio_after);
+                return scope.Close(Undefined());
+            } else {
+                BSONQCmdTask task(cb, njb, cmdCmd, cmdata, BSONQCmdTask::delete_val);
+                njb->ejdbcmd(&task);
+                return scope.Close(njb->ejdbcmd_after(&task));
+            }
+        }
+
         static Handle<Value> s_query(const Arguments& args) {
             HandleScope scope;
             REQ_ARGS(3);
@@ -975,6 +1007,9 @@ namespace ejdb {
                 case cmdTxStatus:
                     txctl((TxCmdTask*) task);
                     break;
+                case cmdCmd:
+                    ejdbcmd((BSONQCmdTask*) task);
+                    break;
                 default:
                     assert(0);
             }
@@ -1010,6 +1045,9 @@ namespace ejdb {
                 case cmdTxStatus:
                     txctl_after((TxCmdTask*) task);
                     break;
+                case cmdCmd:
+                    ejdbcmd_after((BSONQCmdTask*) task);
+                    break;
                 default:
                     assert(0);
             }
@@ -1328,6 +1366,30 @@ namespace ejdb {
             }
         }
 
+
+        void ejdbcmd(BSONQCmdTask *task) {
+            if (!_check_state((EJBTask*) task)) {
+                return;
+            }
+            BSONQCmdData *cmdata = task->cmd_data;
+            std::vector<bson*> &bsons = cmdata->bsons;
+            bson *qbs = bsons.front();
+            assert(qbs);
+            TCLIST *res = tclistnew2(1);
+            bson *bret = ejdbcommand(m_jb, qbs);
+            assert(bret);
+            tclistpush(res, bson_data(bret), bson_size(bret));
+            bson_del(bret);
+            cmdata->res = res;
+            cmdata->count = TCLISTNUM(cmdata->res);
+            cmdata->qflags = 0;
+        }
+
+        Handle<Value> ejdbcmd_after(BSONQCmdTask *task) {
+            return query_after(task);
+        }
+
+
         void query(BSONQCmdTask *task) {
             if (!_check_state((EJBTask*) task)) {
                 return;
@@ -1495,6 +1557,7 @@ finish:
             NODE_SET_PROTOTYPE_METHOD(constructor_template, "setIndex", s_set_index);
             NODE_SET_PROTOTYPE_METHOD(constructor_template, "sync", s_sync);
             NODE_SET_PROTOTYPE_METHOD(constructor_template, "dbMeta", s_db_meta);
+            NODE_SET_PROTOTYPE_METHOD(constructor_template, "command", s_cmd);
             NODE_SET_PROTOTYPE_METHOD(constructor_template, "_txctl", s_coll_txctl);
 
             //Symbols
index 281cd55..5ec192e 100644 (file)
@@ -269,7 +269,7 @@ module.exports.testCMeta = function(test) {
     test.equal(dm["file"], "var/tdbt2");
     test.ok(dm["collections"]);
     test.ok(dm["collections"].constructor == Array);
-    var parrots = dm["collections"][0];
+    var parrots = dm["collections"][1];
     test.ok(parrots);
     test.equal(parrots["name"], "parrots");
     //todo...
@@ -446,6 +446,17 @@ module.exports.testFPIssue = function(test) {
     test.done();
 };
 
+module.exports.testEJDBCommand = function(test) {
+    jb.command({
+        "ping" : {}
+    }, function(err, pong) {
+        test.ifError(err);
+        test.ok(pong);
+        test.equal("pong", pong["log"]);
+        test.done();
+    })
+};
+
 
 module.exports.testClose = function(test) {
     test.ok(jb);
index b432d8f..285e372 100644 (file)
@@ -1,9 +1,9 @@
 {
     "name" : "ejdb",
-    "version" : "1.1.13-1",
+    "version" : "1.1.14-1",
     "config" : {
-        "windownloadurl_ia32" : "http://dl.dropboxusercontent.com/u/4709222/ejdb/tcejdb-1.1.13-mingw32-i686.zip",
-        "windownloadurl_x64" : "http://dl.dropboxusercontent.com/u/4709222/ejdb/tcejdb-1.1.13-mingw32-x86_64.zip"
+        "windownloadurl_ia32" : "http://dl.dropboxusercontent.com/u/4709222/ejdb/tcejdb-1.1.14-mingw32-i686.zip",
+        "windownloadurl_x64" : "http://dl.dropboxusercontent.com/u/4709222/ejdb/tcejdb-1.1.14-mingw32-x86_64.zip"
     },
     "main" : "node/ejdb.js",
     "homepage" : "http://ejdb.org",
index 5da7df7..18f7992 100644 (file)
@@ -1,3 +1,9 @@
+python-ejdb (1.0.15) testing; urgency=low
+
+  * EJDB 1.1.14
+
+ -- Anton Adamansky <adamansky@gmail.com>  Thu, 18 Jul 2013 18:00:55 +0700
+
 python-ejdb (1.0.14) testing; urgency=low
 
   * Critical bugfix: error on saving docs.
index d439761..78f039e 100644 (file)
@@ -4,7 +4,7 @@ Priority: optional
 Maintainer: Anton Adamansky <adamansky@gmail.com>
 Build-Depends:
  debhelper (>= 9),
- libtcejdb9-dev (>= 1.1.3),
+ libtcejdb9-dev (>= 1.1.14),
  python3-dev,
  python3-setuptools,
  python3-pkg-resources
@@ -21,7 +21,7 @@ Depends:
  ${misc:Depends},
  python3 (>= 3.2.0),
  ${shlibs:Depends},
- libtcejdb9 (>= 1.1.3)
+ libtcejdb9 (>= 1.1.14)
 Provides:
  ${python3:Provides}
 Description: Python3 binding for EJDB
index 25c0933..1b2905f 100644 (file)
@@ -19,7 +19,7 @@
       <excludeFolder url="file://$USER_HOME$/tmp/mongo-python-driver/doc" />
       <excludeFolder url="file://$USER_HOME$/tmp/mongo-python-driver/test" />
     </content>
-    <orderEntry type="jdk" jdkName="Python 3.3.1 (/usr/bin/python3m)" jdkType="Python SDK" />
+    <orderEntry type="jdk" jdkName="Python 3.2.3 (/usr/bin/python3mu)" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
 </module>
index 8f80df5..de7f9a5 100644 (file)
@@ -51,7 +51,7 @@ __all__ = [
     "libejdb_version"
 ]
 
-version_tuple = (1, 0, 11)
+version_tuple = (1, 0, 15)
 
 def get_version_string():
     return '.'.join(map(str, version_tuple))
@@ -185,6 +185,52 @@ class EJDB(object):
     def sync(self):
         return self.__ejdb.sync()
 
+    def command(self, cmd):
+        """ Executes ejdb database command.
+
+          Supported commands:
+
+           1) Exports database collections data. See ejdbexport() method.
+
+             "export" : {
+                   "path" : string,                    //Exports database collections data
+                   "cnames" : [string array]|null,     //List of collection names to export
+                   "mode" : int|null                   //Values: null|`JBJSONEXPORT` See ejdbexport() method
+             }
+
+             Command response:
+                {
+                   "log" : string,        //Diagnostic log about executing this command
+                   "error" : string|null, //ejdb error message
+                   "errorCode" : int|0,   //ejdb error code
+                }
+
+           2) Imports previously exported collections data into ejdb.
+
+             "import" : {
+                   "path" : string                     //The directory path in which data resides
+                   "cnames" : [string array]|null,     //List of collection names to import
+                   "mode" : int|null                //Values: null|`JBIMPORTUPDATE`|`JBIMPORTREPLACE` See ejdbimport() method
+              }
+
+              Command response:
+                {
+                   "log" : string,        //Diagnostic log about executing this command
+                   "error" : string|null, //ejdb error message
+                   "errorCode" : int|0,   //ejdb error code
+                }
+
+         :Parameters:
+            - `cmd`  Command object dictionary
+
+         :Returns:
+            Command response object dictionary
+        """
+        bret = self.__ejdb.command(bson.serialize_to_bytes(cmd))
+        if bret is not None:
+            return bson.parse_bytes(bret)
+        return None
+
     def save(self, cname, *jsarr, **kwargs):
         """ Save/update specified `dict` documents into collection `cname`.
 
old mode 100755 (executable)
new mode 100644 (file)
index 620193f..e5d8e0e
@@ -14,6 +14,7 @@ from distutils.core import setup, Extension, Command
 
 from ctypes.util import find_library
 from ctypes import cdll, c_char_p
+from distutils.version import StrictVersion
 
 import sys
 import os
@@ -81,11 +82,12 @@ def check_extension(ext):
         raise SystemExit(err_msg.format(ext.name, ext.min_ver, ext.url))
     elif lib:
         curr_ver = c_char_p.in_dll(cdll.LoadLibrary(lib), ext.ver_char_p).value
-        if curr_ver.decode() < ext.min_ver:
+        if StrictVersion(curr_ver.decode()) < StrictVersion(ext.min_ver):
             raise SystemExit(err_msg.format(ext.name, ext.min_ver, ext.url))
+
     return lib
 
-ejdb_ext = EJDBPythonExt(True, "tcejdb", "EJDB", "1.1",
+ejdb_ext = EJDBPythonExt(True, "tcejdb", "EJDB", "1.1.14",
                          "tcversion", "http://ejdb.org",
                          "_pyejdb", ["src/pyejdb.c"],
                          libraries=["tcejdb", "z", "pthread", "m", "c"],
@@ -99,7 +101,7 @@ class build_ext(_build_ext):
 
 setup(
     name="pyejdb",
-    version="1.0.14",
+    version="1.0.15",
     url="http://ejdb.org",
     keywords=["ejdb", "tokyocabinet", "nosql", "database", "storage", "embedded", "mongodb", "json"],
     description="Python 2.7/3.x binding for EJDB database engine.",
index e656c1a..ef02732 100644 (file)
@@ -119,6 +119,30 @@ static PyObject* EJDB_ensureCollection(PEJDB *self, PyObject *args, PyObject *kw
     Py_RETURN_NONE;
 }
 
+static PyObject* EJDB_command(PEJDB *self, PyObject *args) {
+    bson bscmd;
+    void *bsonbuf = NULL;
+    int bsonbufz;
+    PyObject *bsonbufpy;
+    bson *cmdret = NULL;
+    if (!PyArg_ParseTuple(args, "O:command", &bsonbufpy)) {
+        return NULL;
+    }
+    if (bytes_to_void(bsonbufpy, &bsonbuf, &bsonbufz)) {
+        return NULL;
+    }
+    bson_init_finished_data(&bscmd, bsonbuf);
+    bscmd.flags |= BSON_FLAG_STACK_ALLOCATED;
+    Py_BEGIN_ALLOW_THREADS
+    cmdret = ejdbcommand(self->ejdb, &bscmd);
+    Py_END_ALLOW_THREADS
+
+    bson_destroy(&bscmd);
+    PyObject *docbytes = PyBytes_FromStringAndSize(bson_data(cmdret), bson_size(cmdret));
+    bson_del(cmdret);
+    return docbytes;
+}
+
 static PyObject* EJDB_save(PEJDB *self, PyObject *args, PyObject *kwargs) {
     const char *cname;
     PyObject *merge = Py_False;
@@ -588,6 +612,7 @@ static PyMethodDef EJDB_tp_methods[] = {
     {"setIndex", (PyCFunction) EJDB_setIndex, METH_VARARGS, NULL},
     {"txcontrol", (PyCFunction) EJDB_txcontrol, METH_VARARGS, NULL},
     {"dbmeta", (PyCFunction) EJDB_dbmeta, METH_VARARGS, NULL},
+    {"command", (PyCFunction) EJDB_command, METH_VARARGS, NULL},
     {NULL}
 };
 
index d53a3a1..d3901f0 100644 (file)
@@ -186,6 +186,14 @@ class TestOne(unittest.TestCase):
         self.assertTrue(ejdb.findOne("upsertcoll", {"foo": "bar"}) is not None)
 
 
+        cmd = {
+            "ping" : {}
+        }
+        cmdret = ejdb.command(cmd)
+        self.assertIsNotNone(cmdret)
+        self.assertEquals(cmdret["log"], "pong")
+
+
     @classmethod
     def tearDownClass(cls):
         if cls._ejdb:
index 2db1ca3..2754184 100644 (file)
@@ -1,3 +1,10 @@
+libtcejdb (1.1.14) testing; urgency=low
+
+  * Supports generic ejdb commands interface
+  * Export/Import database data implemented
+
+ -- Anton Adamansky <adamansky@gmail.com>  Thu, 18 Jul 2013 15:44:31 +0700
+
 libtcejdb (1.1.13) testing; urgency=low
 
   * .Net binding
index a98d2f9..7de49f1 100644 (file)
@@ -126,7 +126,8 @@ install :
            mkdir -p `dirname $(DESTDIR)$(INCLUDEDIR)/$(PACKAGE)/$(HF)`; \
            $(INSTALL) -m 644 $(HF) $(DESTDIR)$(INCLUDEDIR)/$(PACKAGE)/$(HF); \
        )
-       $(INSTALL) -m 755 $(LIBRARYFILES) $(DESTDIR)$(LIBDIR)
+       chmod -R 755 $(LIBRARYFILES)
+       cp -Rf $(LIBRARYFILES) $(DESTDIR)$(LIBDIR)
        $(INSTALL) -m 644 $(DOCUMENTFILES) $(DESTDIR)$(DATADIR)
        $(INSTALL) -m 644 $(PCFILES) $(DESTDIR)$(PCDIR)
        ## mkdir -p $(DESTDIR)$(BINDIR)
index 5d50661..8778233 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tcejdb 1.1.13.
+# Generated by GNU Autoconf 2.69 for tcejdb 1.1.14.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='tcejdb'
 PACKAGE_TARNAME='tcejdb'
-PACKAGE_VERSION='1.1.13'
-PACKAGE_STRING='tcejdb 1.1.13'
+PACKAGE_VERSION='1.1.14'
+PACKAGE_STRING='tcejdb 1.1.14'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1268,7 +1268,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures tcejdb 1.1.13 to adapt to many kinds of systems.
+\`configure' configures tcejdb 1.1.14 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1333,7 +1333,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of tcejdb 1.1.13:";;
+     short | recursive ) echo "Configuration of tcejdb 1.1.14:";;
    esac
   cat <<\_ACEOF
 
@@ -1439,7 +1439,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-tcejdb configure 1.1.13
+tcejdb configure 1.1.14
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1737,7 +1737,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by tcejdb $as_me 1.1.13, which was
+It was created by tcejdb $as_me 1.1.14, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -5273,7 +5273,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by tcejdb $as_me 1.1.13, which was
+This file was extended by tcejdb $as_me 1.1.14, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5326,7 +5326,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-tcejdb config.status 1.1.13
+tcejdb config.status 1.1.14
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 28e23ab..91b53f1 100644 (file)
@@ -10,7 +10,7 @@ test -n "$CPPFLAGS" && MYCPPFLAGS="$CPPFLAGS $MYCPPFLAGS"
 test -n "$LDFLAGS" && MYLDFLAGS="$LDFLAGS $MYLDFLAGS"
 
 # Package name
-AC_INIT(tcejdb, 1.1.13)
+AC_INIT(tcejdb, 1.1.14)
 AC_CANONICAL_HOST
 
 # Package information
index 2db1ca3..2754184 100644 (file)
@@ -1,3 +1,10 @@
+libtcejdb (1.1.14) testing; urgency=low
+
+  * Supports generic ejdb commands interface
+  * Export/Import database data implemented
+
+ -- Anton Adamansky <adamansky@gmail.com>  Thu, 18 Jul 2013 15:44:31 +0700
+
 libtcejdb (1.1.13) testing; urgency=low
 
   * .Net binding
index 81e3024..63a468f 100644 (file)
@@ -12,6 +12,7 @@ libtcejdb.so.9 libtcejdb9 #MINVER#
  _tc_md5_init@Base 1.1.8
  _tc_recdecode@Base 1.1.8
  _tc_recencode@Base 1.1.8
+ bson2json@Base 1.1.14
  bson_append32@Base 1.1.8
  bson_append64@Base 1.1.8
  bson_append@Base 1.1.8
@@ -161,14 +162,17 @@ libtcejdb.so.9 libtcejdb9 #MINVER#
  ejcollockmethod@Base 1.1.8
  ejcollunlockmethod@Base 1.1.8
  ejdbclose@Base 1.1.8
+ ejdbcommand@Base 1.1.14
  ejdbcreatecoll@Base 1.1.8
  ejdbcreatequery2@Base 1.1.13
  ejdbcreatequery@Base 1.1.8
  ejdbdel@Base 1.1.8
  ejdbecode@Base 1.1.8
  ejdberrmsg@Base 1.1.8
+ ejdbexport@Base 1.1.14
  ejdbgetcoll@Base 1.1.8
  ejdbgetcolls@Base 1.1.8
+ ejdbimport@Base 1.1.14
  ejdbisopen@Base 1.1.8
  ejdbisvalidoidstr@Base 1.1.8
  ejdbloadbson@Base 1.1.8
@@ -201,6 +205,13 @@ libtcejdb.so.9 libtcejdb9 #MINVER#
  hashmurmur32@Base 1.1.8
  hashmurmur64@Base 1.1.8
  initialBufferSize@Base 1.1.8
+ json2bson@Base 1.1.14
+ nx_json_free@Base 1.1.14
+ nx_json_get@Base 1.1.14
+ nx_json_item@Base 1.1.14
+ nx_json_parse@Base 1.1.14
+ nx_json_parse_utf8@Base 1.1.14
+ nx_json_unicode_to_utf8@Base 1.1.14
  set_bson_err_handler@Base 1.1.8
  tcadbadddouble@Base 1.1.8
  tcadbaddint@Base 1.1.8
@@ -533,6 +544,7 @@ libtcejdb.so.9 libtcejdb9 #MINVER#
  tchdbsetcodecfunc@Base 1.1.8
  tchdbsetdbgfd@Base 1.1.8
  tchdbsetdfunit@Base 1.1.8
+ tchdbsetecode2@Base 1.1.14
  tchdbsetecode@Base 1.1.8
  tchdbsetmutex@Base 1.1.8
  tchdbsettype@Base 1.1.8
@@ -892,6 +904,7 @@ libtcejdb.so.9 libtcejdb9 #MINVER#
  tctdbsetcodecfunc@Base 1.1.8
  tctdbsetdbgfd@Base 1.1.8
  tctdbsetdfunit@Base 1.1.8
+ tctdbsetecode2@Base 1.1.14
  tctdbsetecode@Base 1.1.8
  tctdbsetindex@Base 1.1.8
  tctdbsetindexrldr@Base 1.1.8
index a2ec5b1..d54d1c9 100644 (file)
@@ -547,16 +547,16 @@ EJQRESULT ejdbqryexecute(EJCOLL *jcoll, const EJQ *q, uint32_t *count, int qflag
         _ejdbsetecode(jcoll->jb, TCEINVALID, __FILE__, __LINE__, __func__);
         return NULL;
     }
-    JBCLOCKMETHOD(jcoll, (q->flags & EJQUPDATING) ? true : false);
-    _ejdbsetecode(jcoll->jb, TCESUCCESS, __FILE__, __LINE__, __func__);
-    if (ejdbecode(jcoll->jb) != TCESUCCESS) { //we are not in fatal state
+        JBCLOCKMETHOD(jcoll, (q->flags & EJQUPDATING) ? true : false);
+        _ejdbsetecode(jcoll->jb, TCESUCCESS, __FILE__, __LINE__, __func__);
+        if (ejdbecode(jcoll->jb) != TCESUCCESS) { //we are not in fatal state
+            JBCUNLOCKMETHOD(jcoll);
+            return NULL;
+        }
+        TCLIST *res = _qryexecute(jcoll, q, count, qflags, log);
         JBCUNLOCKMETHOD(jcoll);
-        return NULL;
+        return res;
     }
-    TCLIST *res = _qryexecute(jcoll, q, count, qflags, log);
-    JBCUNLOCKMETHOD(jcoll);
-    return res;
-}
 
 int ejdbqresultnum(EJQRESULT qr) {
     return qr ? tclistnum(qr) : 0;
@@ -900,6 +900,9 @@ bson* ejdbcommand(EJDB *jb, bson *cmd) {
                 err = ejdberrmsg(ecode);
             }
             TCFREE(path);
+        } else if (!strcmp("ping", key)) {
+            xlog = tcxstrnew();
+            tcxstrprintf(xlog, "pong");
         } else {
             err = "Unknown command";
             ecode = JBEINVALIDCMD;
index 814f75d..d527f14 100644 (file)
@@ -436,8 +436,10 @@ EJDB_EXPORT bool ejdbsetindex(EJCOLL *coll, const char *ipath, int flags);
  * @param jcoll EJDB database
  * @param q Query handle created with ejdbcreatequery()
  * @param count Output count pointer. Result set size will be stored into it.
- * @param qflags Execution flag. If JBQRYCOUNT is set the only count of matching records will be computed
- *         without resultset, this operation is analog of count(*) in SQL and can be faster than operations with resultsets.
+ * @param qflags Execution flag.
+ *          * `JBQRYCOUNT` The only count of matching records will be computed
+ *                         without resultset, this operation is analog of count(*)
+ *                         in SQL and can be faster than operations with resultsets.
  * @param log Optional extended string to collect debug information during query execution, can be NULL.
  * @return TCLIST with matched bson records data.
  * If (qflags & JBQRYCOUNT) then NULL will be returned
index 6c40852..ec9acd6 100644 (file)
@@ -3733,7 +3733,7 @@ typedef unsigned char TCBITMAP; /* type of a bit map object */
 
 #include <stdio.h>
 
-#define _TC_VERSION    "1.1.13"
+#define _TC_VERSION    "1.1.14"
 #define _TC_LIBVER     911
 #define _TC_FORMATVER  "1.0"