Exemple #1
0
void testTransactions1() {
    EJCOLL *coll = ejdbcreatecoll(jb, "trans1", NULL);
    bson bs;
    bson_init(&bs);
    bson_append_string(&bs, "foo", "bar");
    bson_finish(&bs);

    bson_oid_t oid;
    CU_ASSERT_TRUE(ejdbtranbegin(coll));
    ejdbsavebson(coll, &bs, &oid);
    CU_ASSERT_TRUE(ejdbtrancommit(coll));

    bson *bres = ejdbloadbson(coll, &oid);
    CU_ASSERT_PTR_NOT_NULL(bres);
    if (bres) {
        bson_del(bres);
    }

    CU_ASSERT_TRUE(ejdbtranbegin(coll));
    ejdbsavebson(coll, &bs, &oid);
    CU_ASSERT_TRUE(ejdbtranabort(coll));

    bres = ejdbloadbson(coll, &oid);
    CU_ASSERT_PTR_NULL(bres);
    if (bres) {
        bson_del(bres);
    }

    bson_destroy(&bs);
}
Exemple #2
0
/*
 * Class:     org_ejdb_driver_EJDBCollection
 * Method:    load
 * Signature: (Lorg/ejdb/bson/types/ObjectId;)Lorg/ejdb/bson/BSONObject;
 */
JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBCollection_load (JNIEnv *env, jobject obj, jobject joid) {
	EJDB* db = get_ejdb_from_object(env, obj);		
	if (!ejdbisopen(db)) {
		set_error(env, 0, "EJDB not opened");
		return NULL;
	}

	jstring colname = get_coll_name(env, obj);

	const char *cname = (*env)->GetStringUTFChars(env, colname, NULL);
	EJCOLL * coll = ejdbgetcoll(db, cname);
	(*env)->ReleaseStringUTFChars(env, colname, cname);

	if (!coll) {
		return NULL;
	}

	jclass jObjectIdClazz = (*env)->FindClass(env, "org/ejdb/bson/types/ObjectId");
	jmethodID encodeMethodID = (*env)->GetMethodID(env, jObjectIdClazz, "toByteArray", "()[B");
	jbyteArray joiddata = (*env)->CallObjectMethod(env, joid, encodeMethodID);
	bson_oid_t *oid = (bson_oid_t*)(*env)->GetByteArrayElements(env, joiddata, NULL);
	bson* bson = ejdbloadbson(coll, oid);
	(*env)->ReleaseByteArrayElements(env, joiddata, (jbyte*)oid, 0);
	(*env)->DeleteLocalRef(env, joiddata);

	if (!bson) {
		return NULL;
	}

	jobject result = decode_bson(env, bson);
	bson_del(bson);

	return result;
}
Exemple #3
0
/*
 * Class:     org_ejdb_driver_EJDB
 * Method:    executeCommand
 * Signature: (Lorg/ejdb/bson/BSONObject;)Lorg/ejdb/bson/BSONObject;
 */
JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDB_executeCommand
  (JNIEnv *env, jobject obj, jobject jcommand) {
	EJDB* db = get_ejdb_from_object(env, obj);
	if (!ejdbisopen(db)) {
		set_error(env, 0, "EJDB not opened");
		return NULL;
	}

    bson *cmdret = NULL;

	bson *cmd = encode_bson(env, jcommand, NULL);
    cmdret = ejdbcommand(db, cmd);
	bson_del(cmd);

    jobject result = decode_bson(env, cmdret);
    bson_del(cmdret);

    return result;
};
Exemple #4
0
/*
 * Class:     org_ejdb_driver_EJDBCollection
 * Method:    save
 * Signature: (Lorg/ejdb/bson/BSONObject;)Lorg/ejdb/bson/types/ObjectId;
 */
JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBCollection_save (JNIEnv *env, jobject obj, jobject jdata) {
    if (NULL == jdata) {
        return NULL;
    }

	EJDB* db = get_ejdb_from_object(env, obj);
	if (!ejdbisopen(db)) {
		set_error(env, 0, "EJDB not opened");
		return NULL;
	}

	jstring colname = get_coll_name(env, obj);

	const char *cname = (*env)->GetStringUTFChars(env, colname, NULL);
	// todo: check
	EJCOLL * coll = ejdbcreatecoll(db, cname, NULL);
	(*env)->ReleaseStringUTFChars(env, colname, cname);

	if (!coll) {
		set_ejdb_error(env, db);
		return NULL;
	}

	bson_oid_t oid;

	bson *bson = encode_bson(env, jdata, NULL);
	bool status = ejdbsavebson(coll, bson, &oid);
	bson_del(bson);

	if (!status) {
		set_ejdb_error(env, db);
		return NULL;
	}

	jclass jObjectIdClazz = (*env)->FindClass(env, "org/ejdb/bson/types/ObjectId");
	jmethodID initMethodID = (*env)->GetMethodID(env, jObjectIdClazz, "<init>", "([B)V");

	jbyteArray joiddata = (*env)->NewByteArray(env, sizeof(oid));
	(*env)->SetByteArrayRegion(env, joiddata, 0, sizeof(oid), (jbyte*)&oid);
	jobject result = (*env)->NewObject(env, jObjectIdClazz, initMethodID, joiddata);

	(*env)->DeleteLocalRef(env, joiddata);

	jclass clazz = (*env)->GetObjectClass(env, jdata);
	jmethodID putMethodID = (*env)->GetMethodID(env, clazz, "put", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
	jfieldID idKeyID = (*env)->GetStaticFieldID(env, clazz, "ID_KEY", "Ljava/lang/String;");
	jstring	oidField = (*env)->GetStaticObjectField(env, clazz, idKeyID);

	(*env)->CallObjectMethod(env, jdata, putMethodID, oidField, result);

	update_coll_meta(env, obj, coll);

	return result;
}
Exemple #5
0
void testSaveLoad() {
    CU_ASSERT_PTR_NOT_NULL_FATAL(jb);
    bson_oid_t oid;
    EJCOLL *ccoll = ejdbcreatecoll(jb, "contacts", NULL);
    CU_ASSERT_PTR_NOT_NULL(ccoll);

    //Save record
    bson a1;
    bson_init(&a1);

    bson_append_string(&a1, "name", "Петров Петр");
    bson_append_string(&a1, "phone", "333-222-333");
    bson_append_int(&a1, "age", 33);
    bson_append_long(&a1, "longage", 0xFFFFFFFFFF01LL);
    bson_append_double(&a1, "doubleage", 0.333333);
    bson_finish(&a1);
    ejdbsavebson(ccoll, &a1, &oid);
    bson_destroy(&a1);


    bson *lbson = ejdbloadbson(ccoll, &oid);
    CU_ASSERT_PTR_NOT_NULL(lbson);
    bson_iterator it1;
    bson_iterator_init(&it1, lbson);

    int btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_OID);
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_STRING);
    CU_ASSERT(!strcmp("name", bson_iterator_key(&it1)));
    CU_ASSERT(!strcmp("Петров Петр", bson_iterator_string(&it1)));
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_STRING);
    CU_ASSERT(!strcmp("phone", bson_iterator_key(&it1)));
    CU_ASSERT(!strcmp("333-222-333", bson_iterator_string(&it1)));
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_INT);
    CU_ASSERT(!strcmp("age", bson_iterator_key(&it1)));
    CU_ASSERT(33 == bson_iterator_int(&it1));
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_LONG);
    CU_ASSERT(!strcmp("longage", bson_iterator_key(&it1)));
    CU_ASSERT(0xFFFFFFFFFF01LL == bson_iterator_long(&it1));
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_DOUBLE);
    CU_ASSERT(!strcmp("doubleage", bson_iterator_key(&it1)));
    CU_ASSERT_DOUBLE_EQUAL(bson_iterator_double(&it1), 0.3, 0.1);
    btype = bson_iterator_next(&it1);
    CU_ASSERT(btype == BSON_EOO);
    bson_del(lbson);
}
Exemple #6
0
void testBSONExportImport(void) {
    EJDB *jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT | JBOTRUNC));
    EJCOLL *coll = ejdbcreatecoll(jb, "col1", NULL);
    if (!coll) {
        eprint(jb, __LINE__, "testBSONExportImport");
    }
    CU_ASSERT_TRUE(coll != NULL);
    bson_oid_t oid;

    bson bv1;
    bson_init(&bv1);
    bson_append_int(&bv1, "a", 1);
    bson_append_string(&bv1, "c", "d");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    EJCOLLOPTS copts = {0};
    copts.large = true;
    copts.records = 200000;
    coll = ejdbcreatecoll(jb, "col2", &copts);
    if (!coll) {
        eprint(jb, __LINE__, "testBSONExportImport");
    }
    CU_ASSERT_TRUE(coll != NULL);
    CU_ASSERT_TRUE(ejdbsetindex(coll, "f", JBIDXSTR | JBIDXNUM));
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 1);
    bson_append_string(&bv1, "f", "g");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_append_string(&bv1, "f", "g2");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    TCXSTR *log = tcxstrnew();
    TCLIST *cnames = tclistnew();
    tclistpush2(cnames, "col1");
    tclistpush2(cnames, "col2");


    bool rv = ejdbexport(jb, "testBSONExportImport", NULL, 0, log);
    if (!rv) {
        eprint(jb, __LINE__, "testBSONExportImport");
    }
    CU_ASSERT_TRUE(rv);

    bson *ometa = ejdbmeta(jb);
    CU_ASSERT_TRUE_FATAL(ometa != NULL);

    ejdbclose(jb);
    ejdbdel(jb);

    //Restore data:

    jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT));

    coll = ejdbgetcoll(jb, "col1");
    CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_finish(&bv1);
    CU_ASSERT_TRUE(ejdbsavebson(coll, &bv1, &oid));
    bson_destroy(&bv1);

    rv = ejdbimport(jb, "testBSONExportImport", cnames, JBIMPORTREPLACE, log);
    CU_ASSERT_TRUE(rv);
    //fprintf(stderr, "\n\n%s", TCXSTRPTR(log));

    CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "Replacing all data in 'col1'"));
    CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "1 objects imported into 'col1'"));
    CU_ASSERT_PTR_NOT_NULL(strstr(TCXSTRPTR(log), "2 objects imported into 'col2'"));

    bson *nmeta = ejdbmeta(jb);
    CU_ASSERT_TRUE_FATAL(nmeta != NULL);

    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.0.name", strlen("collections.0.name")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.0.records", strlen("collections.0.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.name", strlen("collections.1.name")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.records", strlen("collections.1.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.options.buckets", strlen("collections.1.options.buckets")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.options.large", strlen("collections.1.options.large")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.field", strlen("collections.1.indexes.0.field")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.type", strlen("collections.1.indexes.0.type")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.records", strlen("collections.1.indexes.0.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.field", strlen("collections.1.indexes.1.field")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.type", strlen("collections.1.indexes.1.type")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.records", strlen("collections.1.indexes.1.records")) == 0);

    ejdbclose(jb);
    ejdbdel(jb);

    jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT | JBOTRUNC));

    coll = ejdbcreatecoll(jb, "col1", NULL);
    CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_finish(&bv1);
    CU_ASSERT_TRUE(ejdbsavebson(coll, &bv1, &oid));

    EJQ *q = ejdbcreatequery(jb, &bv1, NULL, 0, NULL);
    CU_ASSERT_PTR_NOT_NULL_FATAL(q);
    uint32_t count = 0;
    ejdbqryexecute(coll, q, &count, JBQRYCOUNT, NULL);
    CU_ASSERT_EQUAL(count, 1);

    rv = ejdbimport(jb, "testBSONExportImport", NULL, JBIMPORTUPDATE, NULL);
    CU_ASSERT_TRUE(rv);

    coll = ejdbcreatecoll(jb, "col1", NULL);
    ejdbqryexecute(coll, q, &count, JBQRYCOUNT, NULL);
    CU_ASSERT_EQUAL(count, 1);

    ejdbquerydel(q);
    bson_destroy(&bv1);
    ejdbclose(jb);
    ejdbdel(jb);

    bson_del(ometa);
    bson_del(nmeta);
    tcxstrdel(log);
    tclistdel(cnames);
}
Exemple #7
0
void testBSONExportImport2(void) {
    EJDB *jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT | JBOTRUNC));
    EJCOLL *coll = ejdbcreatecoll(jb, "col1", NULL);
    if (!coll) {
        eprint(jb, __LINE__, "testBSONExportImport2");
    }
    CU_ASSERT_TRUE(coll != NULL);
    bson_oid_t oid;
    const char *log = NULL;

    bson bv1;
    bson_init(&bv1);
    bson_append_int(&bv1, "a", 1);
    bson_append_string(&bv1, "c", "d");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    EJCOLLOPTS copts = {0};
    copts.large = true;
    copts.records = 200000;
    coll = ejdbcreatecoll(jb, "col2", &copts);
    if (!coll) {
        eprint(jb, __LINE__, "testBSONExportImport2");
    }
    CU_ASSERT_TRUE(coll != NULL);
    CU_ASSERT_TRUE(ejdbsetindex(coll, "f", JBIDXSTR | JBIDXNUM));
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 1);
    bson_append_string(&bv1, "f", "g");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_append_string(&bv1, "f", "g2");
    bson_finish(&bv1);
    ejdbsavebson(coll, &bv1, &oid);
    bson_destroy(&bv1);

    bson cmd;
    bson_init(&cmd);
    bson_append_start_object(&cmd, "export");
    bson_append_string(&cmd, "path", "testBSONExportImport2");
    bson_append_start_array(&cmd, "cnames");
    bson_append_string(&cmd, "0", "col1");
    bson_append_string(&cmd, "1", "col2");
    bson_append_finish_array(&cmd);
    bson_append_finish_object(&cmd);
    bson_finish(&cmd);
    bson *bret = ejdbcommand(jb, &cmd);
    CU_ASSERT_PTR_NOT_NULL_FATAL(bret);
    bson_destroy(&cmd);

    bson_iterator it;
    bson_iterator_init(&it, bret);
    CU_ASSERT_TRUE(bson_find_fieldpath_value("error", &it) == BSON_EOO);
    bson_iterator_init(&it, bret);
    CU_ASSERT_TRUE(bson_compare_long(0, bson_data(bret), "errorCode") == 0);
    bson_iterator_init(&it, bret);
    CU_ASSERT_TRUE(bson_find_fieldpath_value("log", &it) == BSON_STRING);
    bson_del(bret);

    bson *ometa = ejdbmeta(jb);
    CU_ASSERT_TRUE_FATAL(ometa != NULL);

    ejdbclose(jb);
    ejdbdel(jb);

    //Restore data:
    jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT));

    coll = ejdbgetcoll(jb, "col1");
    CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_finish(&bv1);
    CU_ASSERT_TRUE(ejdbsavebson(coll, &bv1, &oid));
    bson_destroy(&bv1);

    bson_init(&cmd);
    bson_append_start_object(&cmd, "import");
    bson_append_string(&cmd, "path", "testBSONExportImport2");
    bson_append_int(&cmd, "mode", JBIMPORTREPLACE);
    bson_append_start_array(&cmd, "cnames");
    bson_append_string(&cmd, "0", "col1");
    bson_append_string(&cmd, "1", "col2");
    bson_append_finish_array(&cmd);
    bson_append_finish_object(&cmd);
    bson_finish(&cmd);
    bret = ejdbcommand(jb, &cmd);
    CU_ASSERT_PTR_NOT_NULL_FATAL(bret);
    bson_destroy(&cmd);

    bson_iterator_init(&it, bret);
    CU_ASSERT_TRUE_FATAL(bson_find_fieldpath_value("log", &it) == BSON_STRING);
    log = bson_iterator_string(&it);

    CU_ASSERT_PTR_NOT_NULL(strstr(log, "Replacing all data in 'col1'"));
    CU_ASSERT_PTR_NOT_NULL(strstr(log, "1 objects imported into 'col1'"));
    CU_ASSERT_PTR_NOT_NULL(strstr(log, "2 objects imported into 'col2'"));
    bson_del(bret);
    log = NULL;

    bson *nmeta = ejdbmeta(jb);
    CU_ASSERT_TRUE_FATAL(nmeta != NULL);

    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.0.name", strlen("collections.0.name")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.0.records", strlen("collections.0.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.name", strlen("collections.1.name")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.records", strlen("collections.1.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.options.buckets", strlen("collections.1.options.buckets")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.options.large", strlen("collections.1.options.large")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.field", strlen("collections.1.indexes.0.field")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.type", strlen("collections.1.indexes.0.type")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.0.records", strlen("collections.1.indexes.0.records")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.field", strlen("collections.1.indexes.1.field")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.type", strlen("collections.1.indexes.1.type")) == 0);
    CU_ASSERT_TRUE(bson_compare(bson_data(ometa), bson_data(nmeta), "collections.1.indexes.1.records", strlen("collections.1.indexes.1.records")) == 0);

    ejdbclose(jb);
    ejdbdel(jb);

    jb = ejdbnew();
    CU_ASSERT_TRUE_FATAL(ejdbopen(jb, "dbt4_export", JBOWRITER | JBOCREAT | JBOTRUNC));

    coll = ejdbcreatecoll(jb, "col1", NULL);
    CU_ASSERT_PTR_NOT_NULL_FATAL(coll);
    bson_init(&bv1);
    bson_append_int(&bv1, "e", 2);
    bson_finish(&bv1);
    CU_ASSERT_TRUE(ejdbsavebson(coll, &bv1, &oid));

    EJQ *q = ejdbcreatequery(jb, &bv1, NULL, 0, NULL);
    CU_ASSERT_PTR_NOT_NULL_FATAL(q);
    uint32_t count = 0;
    ejdbqryexecute(coll, q, &count, JBQRYCOUNT, NULL);
    CU_ASSERT_EQUAL(count, 1);

    bson_init(&cmd);
    bson_append_start_object(&cmd, "import");
    bson_append_string(&cmd, "path", "testBSONExportImport2");
    bson_append_int(&cmd, "mode", JBIMPORTUPDATE);
    bson_append_finish_object(&cmd);
    bson_finish(&cmd);
    bret = ejdbcommand(jb, &cmd);
    CU_ASSERT_PTR_NOT_NULL_FATAL(bret);
    bson_destroy(&cmd);
    bson_del(bret);

    coll = ejdbcreatecoll(jb, "col1", NULL);
    ejdbqryexecute(coll, q, &count, JBQRYCOUNT, NULL);
    CU_ASSERT_EQUAL(count, 1);

    ejdbquerydel(q);
    bson_destroy(&bv1);
    ejdbclose(jb);
    ejdbdel(jb);

    bson_del(ometa);
    bson_del(nmeta);
}
Exemple #8
0
/*
 * Class:     org_ejdb_driver_EJDBQuery
 * Method:    execute
 * Signature: (Lorg/ejdb/bson/BSONObject;[Lorg/ejdb/bson/BSONObject;Lorg/ejdb/bson/BSONObject;ILjava/io/OutputStream;)Lorg/ejdb/driver/EJDBQuery$QResult;
 */
JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBQuery_execute (JNIEnv *env, jobject obj, jobject qobj, jobjectArray qorarrobj, jobject hobj, jint flags, jobject logstream) {
	jclass jQResultClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBQuery$QResult");
	jmethodID initQResultMethodID = (*env)->GetMethodID(env, jQResultClazz, "<init>", "(IJ)V");

    TCXSTR *log = NULL;

	bson *qbson = NULL;
	bson *qorbsons = NULL;
	bson *qhbson = NULL;

	EJQ *q = NULL;

	jobject qresult = NULL;

	EJDB* db = get_ejdb_from_object(env, obj);
	if (!ejdbisopen(db)) {
		set_error(env, 0, "EJDB not opened");
		goto finish;
	}

	qbson = encode_bson(env, qobj, NULL);

	if (!qbson) {
		// TODO: ?
		goto finish;
	}

	jsize qorz = NULL != qorarrobj ? (*env)->GetArrayLength(env, qorarrobj) : 0;
	if (qorz > 0) {
		qorbsons = (bson*)malloc(qorz * sizeof(bson));
		if (!qorbsons) {
			set_error(env, 0, "Not enought memory");
			goto finish;
		}

		for (jsize i = 0; i < qorz; ++i) {
			jobject qorobj = (*env)->GetObjectArrayElement(env, qorarrobj, i);
			encode_bson(env, qorobj, &qorbsons[i]);
		}
	}

	if (NULL != hobj){
		qhbson = encode_bson(env, hobj, NULL);
	}

	q = ejdbcreatequery(db, qbson, qorz > 0 ? qorbsons : NULL, qorz, qhbson);
	if (!q) {
		set_ejdb_error(env, db);
		goto finish;
	}

	jstring colname = get_coll_name(env, obj);

	const char *cname = (*env)->GetStringUTFChars(env, colname, NULL);
	EJCOLL *coll = ejdbgetcoll(db, cname);

	if (!coll) {
		bson_iterator it;
		//If we are in $upsert mode a new collection will be created
		if (bson_find(&it, qbson, "$upsert") == BSON_OBJECT) {
			coll = ejdbcreatecoll(db, cname, NULL);
			(*env)->ReleaseStringUTFChars(env, colname, cname);
			if (!coll) {
				set_ejdb_error(env, db);
				goto finish;
			}
		}
	} else {
		(*env)->ReleaseStringUTFChars(env, colname, cname);
	}

	uint32_t count = 0;
	TCLIST *qres = NULL;
	if (!coll) { //No collection -> no results
		qres = (flags & JBQRYCOUNT) ? NULL : tclistnew2(1); //empty results
	} else {
        if (NULL != logstream) {
            log = tcxstrnew();
        }
		qres = ejdbqryexecute(coll, q, &count, flags, log);
		if (ejdbecode(db) != TCESUCCESS) {
			set_ejdb_error(env, db);
			goto finish;
		}
	}

	qresult = (*env)->NewObject(env, jQResultClazz, initQResultMethodID, (jint)count, (jlong)qres);

finish:
	// clear
    if (log) {
		jclass logstreamClazz = (*env)->GetObjectClass(env, logstream);
		jmethodID writeMethodID = (*env)->GetMethodID(env, logstreamClazz, "write", "([B)V");
		jmethodID flushMethodID = (*env)->GetMethodID(env, logstreamClazz, "flush", "()V");

		jsize logLength = TCXSTRSIZE(log);

		jbyteArray jlogdata = (*env)->NewByteArray(env, logLength);
		(*env)->SetByteArrayRegion(env, jlogdata, 0, logLength, (jbyte*)TCXSTRPTR(log));
		(*env)->CallVoidMethod(env, logstream, writeMethodID, jlogdata);
		(*env)->DeleteLocalRef(env, jlogdata);

		(*env)->CallVoidMethod(env, logstream, flushMethodID);

		tcxstrdel(log);
    }
	if (qbson) {
		bson_del(qbson);
	}
	if (qorbsons) {
		for (int i = 0; i < qorz; ++i) {
			bson_destroy(&qorbsons[i]);
		}
		free(qorbsons);
	}
	if (qhbson) {
		bson_del(qhbson);
	}
	if (q) {
		ejdbquerydel(q);
	}

	return qresult;
};