static PyObject *tc_TDBQuery_keys(tc_TDBQuery *self) { log_trace("ENTER"); TCLIST *res; PyObject *pylist, *key; const char *pkbuf; int pksiz, i; res = tctdbqrysearch(self->qry); if ( (pylist = PyList_New( (Py_ssize_t)TCLISTNUM(res) )) == NULL ) { tclistdel(res); return NULL; } for(i = 0; i < TCLISTNUM(res); i++){ pkbuf = tclistval(res, i, &pksiz); if ( (key = PyBytes_FromStringAndSize(pkbuf, pksiz)) == NULL ) { Py_CLEAR(pylist); break; } PyList_SET_ITEM(pylist, i, key); } tclistdel(res); return pylist; }
/* * Class: org_ejdb_driver_EJDBResultSet * Method: length * Signature: ()I */ JNIEXPORT jint JNICALL Java_org_ejdb_driver_EJDBResultSet_length (JNIEnv *env, jobject obj) { TCLIST *rs = get_rs_from_object(env, obj); if (!rs) { return 0; } return TCLISTNUM(rs); };
/* * Class: org_ejdb_driver_EJDB * Method: updateMeta * Signature: ()V */ JNIEXPORT void JNICALL Java_org_ejdb_driver_EJDB_updateMeta (JNIEnv *env, jobject obj) { jclass clazz = (*env)->GetObjectClass(env, obj); EJDB *db = get_ejdb_from_object(env, obj); jfieldID pathID = (*env)->GetFieldID(env, clazz, "path", "Ljava/lang/String;"); (*env)->SetObjectField(env, obj, pathID, db ? (*env)->NewStringUTF(env, db->metadb->hdb->path) : NULL); jfieldID collectionMapID = (*env)->GetFieldID(env, clazz, "collections", "Ljava/util/Map;"); jobject collmapold = (*env)->GetObjectField(env, obj, collectionMapID); jclass mapClazz = (*env)->GetObjectClass(env, collmapold); jmethodID getFromMap = (*env)->GetMethodID(env, mapClazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); jclass hashMapClazz = (*env)->FindClass(env, "java/util/HashMap"); jmethodID initHashMap = (*env)->GetMethodID(env, hashMapClazz, "<init>", "(I)V"); jmethodID putIntoMap = (*env)->GetMethodID(env, hashMapClazz, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); jobject collmapnew = (*env)->NewObject(env, hashMapClazz, initHashMap, !db ? 0 : db->cdbsnum); if (!db) { (*env)->SetObjectField(env, obj, collectionMapID, collmapnew); return; } TCLIST *colls = ejdbgetcolls(db); if (!colls) { set_ejdb_error(env, db); return; } jclass collectionClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBCollection"); jmethodID initCollection = (*env)->GetMethodID(env, collectionClazz, "<init>", "(Lorg/ejdb/driver/EJDB;Ljava/lang/String;)V"); for (int i = 0; i < TCLISTNUM(colls); ++i) { EJCOLL *coll = (EJCOLL*) TCLISTVALPTR(colls, i); jstring cname = (*env)->NewStringUTF(env, coll->cname);//, coll->cnamesz); jobject cobj = (*env)->CallObjectMethod(env, collmapold, getFromMap, cname); if (!cobj) { cobj = (*env)->NewObject(env, collectionClazz, initCollection, obj, cname); } update_coll_meta(env, cobj, coll); (*env)->CallObjectMethod(env, collmapnew, putIntoMap, cname, cobj); } (*env)->SetObjectField(env, obj, collectionMapID, collmapnew); };
/* * Class: org_ejdb_driver_EJDBResultSet * Method: _get * Signature: (I)Lorg/ejdb/bson/BSONObject; */ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBResultSet__1get (JNIEnv *env, jobject obj, jint indx) { TCLIST *rs = get_rs_from_object(env, obj); if (!rs) { set_error(env, 0, "Cursor closed"); return NULL; } if (indx < 0 || indx >= TCLISTNUM(rs)) { set_error(env, 0, "Invalid cursor position"); return NULL; } int bdatasz; void *bdata; TCLISTVAL(bdata, rs, indx, bdatasz); return decode_bson_from_buffer(env, bdata, bdatasz); };
int _tmain(int argc, _TCHAR* argv[]) { setlocale(LC_ALL, "en_US.UTF-8"); jb = ejdbnew(); if (!ejdbopen(jb, "addressbook", JBOWRITER | JBOCREAT | JBOTRUNC)) { return 1; } //Get or create collection 'contacts' EJCOLL *coll = ejdbcreatecoll(jb, "contacts", NULL); bson bsrec; bson_oid_t oid; //One record bson_init(&bsrec); bson_append_string(&bsrec, "name", "John Travolta"); bson_append_string(&bsrec, "phone", "333-222-333"); bson_append_int(&bsrec, "age", 58); bson_finish(&bsrec); ejdbsavebson(coll, &bsrec, &oid); fprintf(stderr, "\nSaved Travolta"); bson_destroy(&bsrec); //Another record bson_init(&bsrec); bson_append_string(&bsrec, "name", "Bruce Willis"); bson_append_string(&bsrec, "phone", "222-333-222"); bson_append_int(&bsrec, "age", 57); bson_finish(&bsrec); ejdbsavebson(coll, &bsrec, &oid); fprintf(stderr, "\nSaved Bruce Willis"); bson_destroy(&bsrec); //Now select one record. //Query: {'name' : {'$begin' : 'Bru'}} //Name starts with 'Bru' string bson bq1; bson_init_as_query(&bq1); bson_append_start_object(&bq1, "name"); bson_append_string(&bq1, "$begin", "Bru"); bson_append_finish_object(&bq1); bson_finish(&bq1); EJQ *q1 = ejdbcreatequery(jb, &bq1, NULL, 0, NULL); uint32_t count; TCLIST *res = ejdbqryexecute(coll, q1, &count, 0, NULL); fprintf(stderr, "\n\nRecords found: %d\n", count); for (int i = 0; i < TCLISTNUM(res); ++i) { void *bsdata = TCLISTVALPTR(res, i); bson_print_raw((char*) bsdata, 0); } fprintf(stderr, "\n"); //Dispose result set tclistdel(res); //Dispose query ejdbquerydel(q1); bson_destroy(&bq1); //Close database ejdbclose(jb); ejdbdel(jb); getc(stdin); return 0; }
void testBuildQuery1() { CU_ASSERT_PTR_NOT_NULL_FATAL(jb); /* Query = { "name" : Петров Петр, "age" : 33, "family" : { "wife" : { "name" : "Jeniffer", "age" : {"$gt" : 25}, "phone" : "444-111" }, "children" : [ { "name" : "Dasha", "age" : {"$in" : [1, 4, 10]} } ] } */ bson q1; bson_init_as_query(&q1); bson_append_string(&q1, "name", "Петров Петр"); bson_append_int(&q1, "age", 33); bson q1family_wife; bson_init_as_query(&q1family_wife); bson_append_string(&q1family_wife, "name", "Jeniffer"); bson_append_start_object(&q1family_wife, "age"); bson_append_int(&q1family_wife, "$gt", 25); bson_append_finish_object(&q1family_wife); bson_append_string(&q1family_wife, "phone", "444-111"); bson_finish(&q1family_wife); bson q1family_child; bson_init_as_query(&q1family_child); bson_append_string(&q1family_child, "name", "Dasha"); //"age" : {"$in" : [1, 4, 10]} bson q1family_child_age_IN; bson_init_as_query(&q1family_child_age_IN); bson_append_start_array(&q1family_child_age_IN, "$in"); bson_append_int(&q1family_child_age_IN, "0", 1); bson_append_int(&q1family_child_age_IN, "1", 4); bson_append_int(&q1family_child_age_IN, "2", 10); bson_append_finish_array(&q1family_child_age_IN); bson_finish(&q1family_child_age_IN); bson_append_bson(&q1family_child, "age", &q1family_child_age_IN); bson_finish(&q1family_child); bson q1family; bson_init_as_query(&q1family); bson_append_bson(&q1family, "wife", &q1family_wife); bson_append_start_array(&q1family, "children"); bson_append_bson(&q1family, "0", &q1family_child); bson_append_finish_array(&q1family); bson_finish(&q1family); bson_append_bson(&q1, "family", &q1family); bson_finish(&q1); CU_ASSERT_FALSE_FATAL(q1.err); CU_ASSERT_FALSE_FATAL(q1family.err); CU_ASSERT_FALSE_FATAL(q1family_wife.err); CU_ASSERT_FALSE_FATAL(q1family_child.err); CU_ASSERT_FALSE_FATAL(q1family_child_age_IN.err); EJQ *ejq = ejdbcreatequery(jb, &q1, NULL, 0, NULL); CU_ASSERT_PTR_NOT_NULL_FATAL(ejq); bson_destroy(&q1); bson_destroy(&q1family); bson_destroy(&q1family_wife); bson_destroy(&q1family_child); bson_destroy(&q1family_child_age_IN); CU_ASSERT_PTR_NOT_NULL_FATAL(ejq->qobjlist); TCLIST *qmap = ejq->qobjlist; CU_ASSERT_EQUAL(qmap->num, 7); for (int i = 0; i < TCLISTNUM(qmap); ++i) { const EJQF *qf = TCLISTVALPTR(qmap, i); CU_ASSERT_PTR_NOT_NULL_FATAL(qf); const char* key = qf->fpath; switch (i) { case 0: { CU_ASSERT_STRING_EQUAL(key, "name"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "Петров Петр"); CU_ASSERT_EQUAL(qf->tcop, TDBQCSTREQ); break; } case 1: { CU_ASSERT_STRING_EQUAL(key, "age"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "33"); CU_ASSERT_EQUAL(qf->tcop, TDBQCNUMEQ); break; } case 2: { CU_ASSERT_STRING_EQUAL(key, "family.wife.name"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "Jeniffer"); CU_ASSERT_EQUAL(qf->tcop, TDBQCSTREQ); break; } case 3: { CU_ASSERT_STRING_EQUAL(key, "family.wife.age"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "25"); CU_ASSERT_EQUAL(qf->tcop, TDBQCNUMGT); break; } case 4: { CU_ASSERT_STRING_EQUAL(key, "family.wife.phone"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "444-111"); CU_ASSERT_EQUAL(qf->tcop, TDBQCSTREQ); break; } case 5: { CU_ASSERT_STRING_EQUAL(key, "family.children.0.name"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_STRING_EQUAL(qf->expr, "Dasha"); CU_ASSERT_EQUAL(qf->tcop, TDBQCSTREQ); break; } case 6: { CU_ASSERT_STRING_EQUAL(key, "family.children.0.age"); CU_ASSERT_PTR_NOT_NULL(qf); CU_ASSERT_EQUAL(qf->ftype, BSON_ARRAY); TCLIST *al = tclistload(qf->expr, qf->exprsz); char* als = tcstrjoin(al, ','); CU_ASSERT_STRING_EQUAL(als, "1,4,10"); TCFREE(als); tclistdel(al); CU_ASSERT_EQUAL(qf->tcop, TDBQCNUMOREQ); break; } } } ejdbquerydel(ejq); }
static void lua_val_to_bson(lua_State *L, const char *key, int vpos, bson *bs, int tref) { int vtype = lua_type(L, vpos); char nbuf[TCNUMBUFSIZ]; if (key == NULL && vtype != LUA_TTABLE) { luaL_error(L, "lua_val_to_bson: Table must be on top of lua stack"); return; } switch (vtype) { case LUA_TTABLE: { if (vpos < 0) { vpos = lua_gettop(L) + vpos + 1; } lua_checkstack(L, 3); int bsontype_found = luaL_getmetafield(L, vpos, "__bsontype"); if (!bsontype_found) { lua_rawgeti(L, LUA_REGISTRYINDEX, tref); //+ reg table lua_pushvalue(L, vpos); //+ val lua_rawget(L, -2); //-val +reg table val if (lua_toboolean(L, -1)) { //already traversed lua_pop(L, 2); break; } lua_pop(L, 1); //-reg table val lua_pushvalue(L, vpos); lua_pushboolean(L, 1); lua_rawset(L, -3); lua_pop(L, 1); //-reg table int len = 0; bool query = false; bool array = true; if (luaL_getmetafield(L, vpos, "__query")) { lua_pop(L, 1); query = true; array = false; } if (array) { for (lua_pushnil(L); lua_next(L, vpos); lua_pop(L, 1)) { ++len; if ((lua_type(L, -2) != LUA_TNUMBER) || (lua_tointeger(L, -2) != len)) { lua_pop(L, 2); array = false; break; } } } if (array) { if (key) bson_append_start_array(bs, key); int i; for (i = 1; i <= len; ++i, lua_pop(L, 1)) { lua_rawgeti(L, vpos, i); bson_numstrn(nbuf, TCNUMBUFSIZ, (int64_t) i); lua_val_to_bson(L, nbuf, -1, bs, tref); } if (key) bson_append_finish_array(bs); } else if (query) { //special query builder case //oarr format: //{ {fname1, v1, v2...}, {fname2, v21, v22,..}, ... } //where: vN: {op, val} OR {val} with '__bval' metafield //Eg: {fname : {$inc : {...}, $dec : {...}}} -> {fname, {$inc, {}}, {$dec, {}}} lua_getfield(L, vpos, "_oarr"); //+oarr if (!lua_istable(L, -1)) { //it is not array lua_pop(L, 1); break; } if (key) bson_append_start_object(bs, key); //iterate over _oarr int ipos = lua_gettop(L); size_t ilen = lua_objlen(L, ipos); lua_checkstack(L, 2); size_t i; for (i = 1; i <= ilen; ++i, lua_pop(L, 1)) { lua_rawgeti(L, ipos, i); //gettop == 3 if (!lua_istable(L, -1)) continue; char *fname = NULL; int jpos = lua_gettop(L); size_t jlen = lua_objlen(L, jpos); lua_checkstack(L, 3); bool wrapped = false; size_t j; for (j = 1; j <= jlen; ++j, lua_pop(L, 1)) { lua_rawgeti(L, jpos, j); if (j == 1) { fname = strdup(lua_tostring(L, -1)); continue; } if (!fname || !lua_istable(L, -1)) { //invalid state lua_pop(L, 1); //pop val break; } int vblkpos = lua_gettop(L); if (j == 2 && luaL_getmetafield(L, -1, "__bval")) { //{val} single value +metafield lua_pop(L, 1); //-metafield lua_rawgeti(L, vblkpos, 1); //+val lua_val_to_bson(L, fname, lua_gettop(L), bs, tref); lua_pop(L, 2); //-val -lua_rawgeti break; //Terminate due single val } else { //{op, val} value if (!wrapped) { bson_append_start_object(bs, fname); wrapped = true; } lua_rawgeti(L, vblkpos, 1); //+op const char *op = lua_tostring(L, -1); if (op) { lua_rawgeti(L, vblkpos, 2); //+val lua_val_to_bson(L, op, lua_gettop(L), bs, tref); lua_pop(L, 1); //-val } lua_pop(L, 1); //-op } } if (wrapped) { bson_append_finish_object(bs); } if (fname) { free(fname); fname = NULL; } } if (key) bson_append_finish_object(bs); lua_pop(L, 1); //-oarr } else { if (key) bson_append_start_object(bs, key); 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); int i; for (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 int bson_type = lua_tointeger(L, -1); if (!key && bson_type != BSON_OBJECT && bson_type != BSON_ARRAY) { lua_pop(L, 1); luaL_error(L, "Invalid object structure"); } lua_pop(L, 1); //-metafield __bsontype lua_rawgeti(L, -1, 1); //get first value switch (bson_type) { case BSON_OID: { const char* boid = lua_tostring(L, -1); if (boid && strlen(boid) == 24) { bson_oid_t oid; bson_oid_from_string(&oid, boid); bson_append_oid(bs, key, &oid); } break; } case BSON_DATE: bson_append_date(bs, key, (bson_date_t) lua_tonumber(L, -1)); break; case BSON_REGEX: { const char* regex = lua_tostring(L, -1); lua_rawgeti(L, -2, 2); // re opts const char* options = lua_tostring(L, -1); if (regex && options) { bson_append_regex(bs, key, regex, options); } lua_pop(L, 1); break; } case BSON_BINDATA: { size_t len; const char* cbuf = lua_tolstring(L, -1, &len); bson_append_binary(bs, key, BSON_BIN_BINARY, cbuf, len); break; } case BSON_NULL: bson_append_null(bs, key); break; case BSON_UNDEFINED: bson_append_undefined(bs, key); break; case BSON_OBJECT: if (key) bson_append_start_object(bs, key); lua_val_to_bson(L, NULL, vpos, bs, tref); if (key) bson_append_finish_object(bs); break; case BSON_ARRAY: if (key) bson_append_start_array(bs, key); lua_val_to_bson(L, NULL, vpos, bs, tref); if (key) bson_append_finish_array(bs); break; case BSON_DOUBLE: bson_append_double(bs, key, (double) lua_tonumber(L, -1)); break; case BSON_INT: bson_append_int(bs, key, (int32_t) lua_tonumber(L, -1)); break; case BSON_LONG: bson_append_long(bs, key, (int64_t) lua_tonumber(L, -1)); break; case BSON_BOOL: bson_append_bool(bs, key, lua_toboolean(L, -1)); break; default: break; } lua_pop(L, 1); //-1 first value } break; } case LUA_TNIL: bson_append_null(bs, key); break; case LUA_TNUMBER: { lua_Number numval = lua_tonumber(L, vpos); if (numval == floor(numval)) { int64_t iv = (int64_t) numval; if (-(1LL << 31) <= iv && iv <= (1LL << 31)) { bson_append_int(bs, key, iv); } else { bson_append_long(bs, key, iv); } } else { bson_append_double(bs, key, numval); } break; } case LUA_TBOOLEAN: bson_append_bool(bs, key, lua_toboolean(L, vpos)); break; case LUA_TSTRING: bson_append_string(bs, key, lua_tostring(L, vpos)); break; } }