#51
authoradam <adamansky@gmail.com>
Fri, 15 Mar 2013 07:06:21 +0000 (14:06 +0700)
committeradam <adamansky@gmail.com>
Fri, 15 Mar 2013 07:06:21 +0000 (14:06 +0700)
luaejdb/ejdb.lua
luaejdb/luabson.c
luaejdb/luabson.h
luaejdb/luaejdb.c
luaejdb/test/t1.lua
tcejdb/tcutil.h

index 97ad63d..ca08940 100644 (file)
@@ -69,7 +69,7 @@ local mtBSON_BOOL = {
 
 
 function luaejdb.toOID(val)
-  assert(type(val) == "string" and #val == 24)
+  luaejdb.check_valid_oid_string(val)
   return setmetatable({ val }, mtBSON_OID);
 end
 
index f6308ab..d66643c 100644 (file)
@@ -4,10 +4,9 @@
 #include <lauxlib.h>
 #include <math.h>
 #include <string.h>
-#include <tcejdb/tcutil.h>
+#include <tcejdb/ejdb.h>
 
 static void lua_push_bson_value(lua_State *L, bson_iterator *it);
-static void lua_push_bson_table(lua_State *L, bson_iterator *it);
 static void lua_push_bson_array(lua_State *L, bson_iterator *it);
 static void lua_to_bson_impl(lua_State *L, int spos, bson *bs);
 static void bson_print_xstr(TCXSTR* xstr, const char *data, int depth);
@@ -26,6 +25,19 @@ void lua_init_bson(lua_State *L) {
     lua_pushcfunction(L, print_bson);
     lua_setfield(L, -2, "print_bson");
 
+    lua_pushcfunction(L, check_valid_oid_string);
+    lua_setfield(L, -2, "check_valid_oid_string");
+}
+
+int check_valid_oid_string(lua_State *L) {
+    bool ret = false;
+    if (lua_type(L, 1) == LUA_TSTRING) {
+        ret = ejdbisvalidoidstr(lua_tostring(L, -1));
+    }
+    if (!ret) {
+        return luaL_error(L, "OID is not valid");
+    }
+    return 0;
 }
 
 int print_bson(lua_State *L) {
@@ -121,7 +133,7 @@ static void lua_push_bson_value(lua_State *L, bson_iterator *it) {
     }
 }
 
-static void lua_push_bson_table(lua_State *L, bson_iterator *it) {
+void lua_push_bson_table(lua_State *L, bson_iterator *it) {
     bson_type bt;
     lua_push_bsontype_table(L, BSON_OBJECT);
     while ((bt = bson_iterator_next(it)) != BSON_EOO) {
@@ -298,24 +310,41 @@ static void lua_val_to_bson(lua_State *L, const char *key, int vpos, bson *bs, i
                     lua_pop(L, 1); //-oarr
                 } else {
                     if (key) bson_append_start_object(bs, key);
-                    for (lua_pushnil(L); lua_next(L, vpos); lua_pop(L, 1)) {
-                        int ktype = lua_type(L, -2);
-                        if (ktype == LUA_TNUMBER) {
-                            char vkey[TCNUMBUFSIZ];
-                            bson_numstrn(vkey, TCNUMBUFSIZ, (int64_t) lua_tointeger(L, -2));
-                            lua_val_to_bson(L, vkey, lua_gettop(L), bs, tref);
-                        } else if (ktype == LUA_TSTRING) {
-                            size_t klen = 0;
-                            const char *vkey = lua_tolstring(L, -2, &klen);
-                            if (key == NULL && klen == JDBIDKEYNAMEL && !strcmp(JDBIDKEYNAME, vkey)) { //root level OID as string
-                                //pack OID as type table
-                                lua_push_bsontype_table(L, BSON_OID); //+type table
-                                lua_pushvalue(L, -2); //dup oid on stack
-                                lua_rawseti(L, -2, 1); //pop oid val
+                    TCLIST *keys = tclistnew();
+                    //we need to sort keys due to unordered nature of lua tables
+                    for (lua_pushnil(L); lua_next(L, vpos);) {
+                        lua_pop(L, 1); //-val
+                        size_t ksize = 0;
+                        int ktype = lua_type(L, -1);
+                        if (ktype == LUA_TSTRING) { //accept only string keys
+                            const char* key = lua_tolstring(L, -1, &ksize);
+                            tclistpush(keys, key, ksize);
+                        }
+                    }
+                    tclistsort(keys);
+                    for (int i = 0; i < TCLISTNUM(keys); ++i) {
+                        int vkeysz = TCLISTVALSIZ(keys, i);
+                        const char *vkey = TCLISTVALPTR(keys, i);
+                        lua_pushlstring(L, vkey, vkeysz);
+                        lua_rawget(L, vpos); //+val
+                        if (key == NULL && lua_type(L, -1) == LUA_TSTRING &&
+                                vkeysz == JDBIDKEYNAMEL && !strcmp(JDBIDKEYNAME, vkey)) { //root level OID as string
+                            //pack OID as type table
+                            lua_push_bsontype_table(L, BSON_OID); //+type table
+                            lua_pushvalue(L, -2); //dup oid(val) on stack
+                            lua_rawseti(L, -2, 1); //pop oid val
+                            if (ejdbisvalidoidstr(lua_tostring(L, -2))) {
+                                lua_val_to_bson(L, vkey, lua_gettop(L), bs, tref);
+                            } else {
+                                luaL_error(L, "OID _id='%s' is not valid", lua_tostring(L, -2));
                             }
+                            lua_pop(L, 1); //-type table
+                        } else {
                             lua_val_to_bson(L, vkey, lua_gettop(L), bs, tref);
                         }
+                        lua_pop(L, 1); //-val
                     }
+                    tclistdel(keys);
                     if (key) bson_append_finish_object(bs);
                 }
             } else { //metafield __bsontype on top
index 5c87490..f63e48c 100644 (file)
@@ -19,7 +19,9 @@ extern "C" {
     int lua_from_bson(lua_State *L);
     int lua_to_bson(lua_State *L);
     int print_bson(lua_State *L);
+    int check_valid_oid_string(lua_State *L);
     void lua_push_bsontype_table(lua_State* L, int bsontype);
+    void lua_push_bson_table(lua_State *L, bson_iterator *it);
 
 #ifdef __cplusplus
 }
index c644f81..8ab2a37 100644 (file)
@@ -131,8 +131,8 @@ static int db_save(lua_State *L) {
     int argc = lua_gettop(L);
     luaL_checktype(L, 1, LUA_TTABLE); //self
     lua_getfield(L, 1, EJDBUDATAKEY);
-    EJDBDATA *data = luaL_checkudata(L, -1, EJDBUDATAMT);
-    EJDB *jb = data->db;
+    EJDB *jb = ((EJDBDATA*) luaL_checkudata(L, -1, EJDBUDATAMT))->db;
+    lua_pop(L, 1);
     const char *cname = luaL_checkstring(L, 2); //collections name
     bson bsonval;
     const char *bsonbuf = luaL_checkstring(L, 3); //Object to save
@@ -156,7 +156,57 @@ static int db_save(lua_State *L) {
     lua_pushstring(L, xoid);
 
     bson_destroy(&bsonval);
-    if (lua_gettop(L) - argc != 2) { //got +lua_getfield(L, 1, EJDBUDATAKEY)
+    if (lua_gettop(L) - argc != 1) { //got +lua_getfield(L, 1, EJDBUDATAKEY)
+        return luaL_error(L, "db_save: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
+    }
+    return 1;
+}
+
+static int db_load(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;
+    lua_pop(L, 1);
+
+    const char *cname = luaL_checkstring(L, 2);
+    bson_oid_t oid;
+    memset(&oid, 0, sizeof(oid));
+
+    if (lua_type(L, 3) == LUA_TSTRING) {
+        const char *soid = lua_tostring(L, 3);
+        if (ejdbisvalidoidstr(soid)) {
+            bson_oid_from_string(&oid, soid);
+        }
+    } else if (luaL_getmetafield(L, 3, "__bsontype") && lua_tointeger(L, -1) == BSON_OID) {
+        lua_pop(L, 1);
+        lua_rawgeti(L, 3, 1);
+        const char *soid = lua_tostring(L, -1);
+        if (ejdbisvalidoidstr(soid)) {
+            bson_oid_from_string(&oid, soid);
+        }
+        lua_pop(L, 1);
+    }
+    if (!oid.ints[0] && !oid.ints[1] && !oid.ints[2]) {
+        return luaL_error(L, "Invalid OID arg #2");
+    }
+    EJCOLL *coll = ejdbgetcoll(jb, cname);
+    if (!coll) {
+        lua_pushnil(L);
+        goto finish;
+    }
+    bson *bs = ejdbloadbson(coll, &oid);
+    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_save: Invalid stack size: %d should be: %d", (lua_gettop(L) - argc), 1);
     }
     return 1;
@@ -166,12 +216,13 @@ static int db_find(lua_State *L) {
     //cname, q.toBSON(), orBsons, q.toHintsBSON(), flags
     luaL_checktype(L, 1, LUA_TTABLE); //self
     lua_getfield(L, 1, EJDBUDATAKEY);
-    EJDBDATA *data = luaL_checkudata(L, -1, EJDBUDATAMT);
+    EJDB *jb = ((EJDBDATA*) luaL_checkudata(L, -1, EJDBUDATAMT))->db;
+    lua_pop(L, 1);
     const char *cname = luaL_checkstring(L, 2); //collections name
     const char *qbsonbuf = luaL_checkstring(L, 3); //Query bson
     luaL_checktype(L, 4, LUA_TTABLE); //or joined
     const char *hbsonbuf = luaL_checkstring(L, 5); //Hints bson
-    if (!data || !data->db || !qbsonbuf || !hbsonbuf) {
+    if (!jb || !qbsonbuf || !hbsonbuf) {
         return luaL_error(L, "Illegal arguments");
     }
     bson oqarrstack[8]; //max 8 $or bsons on stack
@@ -179,7 +230,6 @@ static int db_find(lua_State *L) {
     bson qbson = {NULL};
     bson hbson = {NULL};
     EJQ *q = NULL;
-    EJDB *jb = data->db;
     EJCOLL *coll = NULL;
     uint32_t count = 0;
 
@@ -245,6 +295,9 @@ static int db_open(lua_State *L) {
     lua_pushcfunction(L, db_save);
     lua_setfield(L, -2, "_save");
 
+    lua_pushcfunction(L, db_load);
+    lua_setfield(L, -2, "load");
+
     lua_pushcfunction(L, db_find);
     lua_setfield(L, -2, "_find");
 
index f66b7db..f15a0b3 100644 (file)
@@ -6,6 +6,9 @@ local inspect = require("inspect")
 local ejdb = require("ejdb")
 assert(type(ejdb) == "table")
 
+assert(not pcall(function() ejdb.check_valid_oid_string("sss") end));
+assert(pcall(function() ejdb.check_valid_oid_string("510f7fa91ad6270a00000000") end));
+
 local Q = ejdb.Q
 local B = ejdb.B
 
@@ -58,15 +61,29 @@ assert(type(obj.bdate) == "table" and getmetatable(obj.bdate).__bsontype == db.B
 assert(obj.bdate[1] == 1362835380447)
 assert(type(obj.dst) == "table" and getmetatable(obj.dst).__bsontype == db.BSON_NULL)
 
+assert([[._id(7)=510f7fa91ad6270a00000000
+.a(16)=2
+.c(2)=d
+.dd(3)=
+..c(16)=1
+..f(2)=v1
+..gt(8)=true
+
+.ee(2)=t
+]] == ejdb.print_bson(ejdb.to_bson({ c = "d", a = 2, _id = "510f7fa91ad6270a00000000", dd = { f = "v1", gt = true, c = 1 }, ee = "t" })))
+
 
 -- Test save
 --
-local oid = db:save("mycoll", {foo="bar"});
+local oid = db:save("mycoll", { foo = "bar" });
 assert(oid and #oid == 24)
 
-oid = db:save("mycoll", B("foo2","bar2"));
+oid = db:save("mycoll", B("foo2", "bar2"):KV("g", "d"):KV("e", 1):KV("a", "g"));
 assert(oid and #oid == 24)
 
+obj = db:load("mycoll", oid)
+print(inspect(obj));
+
 
 db:close()
 
index 6c01ab0..b35ac05 100644 (file)
@@ -3719,7 +3719,7 @@ typedef unsigned char TCBITMAP;          /* type of a bit map object */
 
 #include <stdio.h>
 
-#define _TC_VERSION    "1.0.65"
+#define _TC_VERSION    "1.0.66"
 #define _TC_LIBVER     911
 #define _TC_FORMATVER  "1.0"