#21
authorVyacheslav Tyutyunkov <tyutyunkov@gmail.com>
Mon, 25 Mar 2013 05:08:52 +0000 (12:08 +0700)
committerVyacheslav Tyutyunkov <tyutyunkov@gmail.com>
Mon, 25 Mar 2013 05:08:52 +0000 (12:08 +0700)
28 files changed:
jejdb/Makefile
jejdb/build.properties
jejdb/build.xml
jejdb/build/classes/org/ejdb/driver/EJDB.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBCollection$Index.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBCollection$IndexType.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBCollection$Options.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBCollection.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBException.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBQuery$QResult.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBQuery.class [new file with mode: 0644]
jejdb/build/classes/org/ejdb/driver/EJDBResultSet.class [new file with mode: 0644]
jejdb/build/test-reports/TEST-org.ejdb.driver.test.EJDBTest.txt [new file with mode: 0644]
jejdb/build/tests/classes/org/ejdb/driver/test/EJDBTest.class [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test_bars [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test_birds [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test_birds.idx.sname.lex [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test_parrots [new file with mode: 0644]
jejdb/build/tests/data/jejdb-test_testcoll [new file with mode: 0644]
jejdb/src/cpp/jejdb.c
jejdb/src/cpp/org_ejdb_driver_EJDBCollection.h
jejdb/src/cpp/org_ejdb_driver_EJDBQuery.h
jejdb/src/java/org/ejdb/driver/EJDBCollection.java
jejdb/src/java/org/ejdb/driver/EJDBQuery.java
jejdb/src/test/org/ejdb/driver/test/EJDBTest.java
jejdb/src/test/org/ejdb/driver/test/Test.java [deleted file]
jejdb/src/test/org/ejdb/driver/test/Test2.java [deleted file]

index be03803..b2403f7 100644 (file)
@@ -6,63 +6,31 @@
 # Generic settings
 SHELL = /bin/bash
 
-# Package information
-PACKAGE = tcejdb
-VERSION = 1.0.65
-PACKAGEDIR = $(PACKAGE)-$(VERSION)
-PACKAGETGZ = $(PACKAGE)-$(VERSION).tar.gz
-LIBVER = 9
-LIBREV = 11
-FORMATVER = 1.0
-
-# Targets
-#HEADERFILES = tcutil.h tchdb.h tcbdb.h tcfdb.h tctdb.h tcadb.h ejdb.h ejdb_private.h bson.h myconf.h
-#LIBRARYFILES = libtcejdb.a libtcejdb.so.9.11.0 libtcejdb.so.9 libtcejdb.so
-#LIBOBJFILES = tcutil.o tchdb.o tcbdb.o tcfdb.o tctdb.o tcadb.o myconf.o md5.o ejdb.o bson.o numbers.o encoding.o utf8proc.o ejdbutl.o
-#COMMANDFILES = tcutest tcumttest tcucodec tchtest tchmttest tchmgr tcbtest tcbmttest tcbmgr tcftest tcfmttest tcfmgr tcttest tctmttest tctmgr tcatest tcamttest tcamgr
-#CGIFILES = tcawmgr.cgi
-#MAN1FILES =
-#MAN3FILES = libtcejdb.3
-#DOCUMENTFILES = COPYING Changelog
-#PCFILES = tcejdb.pc
-
-# Install destinations
-prefix = /usr/local
-exec_prefix = ${prefix}
-datarootdir = ${prefix}/share
-INCLUDEDIR = ${prefix}/include
-LIBDIR = ${exec_prefix}/lib
-BINDIR = ${exec_prefix}/bin
-LIBEXECDIR = ${exec_prefix}/libexec
-DATADIR = ${datarootdir}/$(PACKAGE)
-MAN1DIR = ${datarootdir}/man/man1
-MAN3DIR = ${datarootdir}/man/man3
-PCDIR = ${exec_prefix}/lib/pkgconfig
-
 SRCDIR = ./src/cpp/
-DESTDIR =
+DESTDIR = ./target/
 
 # Building configuration
 CC = gcc
-CPPFLAGS = -I. -I../tcejdb -I/usr/lib/jvm/java-6-oracle/include -I/usr/lib/jvm/java-6-oracle/include/linux
+CPPFLAGS = -I. -I../tcejdb -I$(JDK_HOME)/include -I$(JDK_HOME)/include/linux
 CFLAGS =  -std=c99 -Wall -fPIC -fsigned-char -O2
 LDFLAGS = -L. -L../tcejdb
 CMDLDFLAGS =
 LIBS = -lz -lrt -lpthread -lm -lc -shared -ltcejdb
-# LDENV = LD_RUN_PATH=/lib:/usr/lib:$(LIBDIR):$(HOME)/lib:/usr/local/lib:$(LIBDIR):.
 RUNENV = LD_LIBRARY_PATH=.
 POSTCMD = true
 
 
-all: jejdb
-
-tcejdb:
-       $(MAKE) -C ../ all
+all: jejdb tests
 
 jejdb:
+       mkdir -p $(DESTDIR)
        $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $(DESTDIR)libjejdb.so $(SRCDIR)jejdb.c  $(LIBS)
+       ant build
+
+tests:
+       ant build.and.test
 
 clean:
-       - $(MAKE) -C . clean
+       rm -rf  $(DESTDIR)libjejdb*
 
-.PHONY: all tcejdb jni-jejdb clean
+.PHONY: all jejdb tests clean
index 621970f..f07c583 100644 (file)
@@ -13,6 +13,7 @@ build.test.classes=${build.test.dir}/classes
 test.data.dir=${build.test.dir}/data
 
 source.dir=${basedir}/src/java
+source.native.dir=${basedir}/src/cpp
 source.test.dir=${basedir}/src/test
 
 test.reports.dir=${build.dir}/test-reports
index 0143bac..7e2edf6 100644 (file)
@@ -3,7 +3,7 @@
 
     <property file="build.properties"/>
 
-    <target name="compile.production" description="Compile module JEJDB; production classes">
+    <target name="compile.production" depends="init" description="Compile module JEJDB; production classes">
         <mkdir dir="${build.dir}"/>
         <mkdir dir="${build.classes}"/>
         <javac destdir="${build.classes}"
@@ -35,7 +35,7 @@
         </jar>
     </target>
 
-    <target name="compile.tests" depends="compile.production" description="compile module JEJDB; test classes" if="with.tests">
+    <target name="compile.tests" depends="compile.production" description="Compile module JEJDB; test classes" if="with.tests">
         <mkdir dir="${build.test.dir}"/>
         <mkdir dir="${build.test.classes}"/>
         <javac destdir="${build.test.classes}"
@@ -64,6 +64,7 @@
             <fileset refid="lib.bson.fileset"/>
         </copy>
 
+        <delete dir="${test.data.dir}"/>
         <mkdir dir="${test.data.dir}"/>
         <mkdir dir="${test.reports.dir}"/>
         <junit printsummary="on" showoutput="yes" haltonfailure="yes" haltonerror="yes" dir="${test.data.dir}" fork="true">
         </junit>
     </target>
 
-    <target name="compile" depends="init, compile.production, compile.tests"/>
+    <target name="compile.headers" depends="compile.production" description="Build JNI headers for JEJDB" if="build.native.headers">
+        <javah destdir="${source.native.dir}">
+            <class name="org.ejdb.driver.EJDB"/>
+            <class name="org.ejdb.driver.EJDBCollection"/>
+            <class name="org.ejdb.driver.EJDBQuery"/>
+            <class name="org.ejdb.driver.EJDBResultSet"/>
+            <classpath>
+                <path refid="lib.bson.classpath"/>
+                <path refid="jejdb.classpath"/>
+            </classpath>
+        </javah>
+    </target>
+
+    <target name="compile" depends="compile.production, compile.tests, compile.headers"/>
 
     <target name="init" description="Build initialization">
         <!-- Perform any build initialization in this target -->
         <delete file="${distr.home}/${distr.name}.jar"/>
     </target>
 
+    <target name="build.native.headers" depends="clean">
+        <property name="build.native.headers" value="true"/>
+        <ant target="compile" inheritall="true" inheritrefs="true"/>
+    </target>
+
     <target name="build" depends="clean" description="Build">
         <ant target="compile" inheritall="true" inheritrefs="true"/>
     </target>
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDB.class b/jejdb/build/classes/org/ejdb/driver/EJDB.class
new file mode 100644 (file)
index 0000000..18e481a
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDB.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Index.class b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Index.class
new file mode 100644 (file)
index 0000000..6defbc0
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Index.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBCollection$IndexType.class b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$IndexType.class
new file mode 100644 (file)
index 0000000..6e523d1
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$IndexType.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Options.class b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Options.class
new file mode 100644 (file)
index 0000000..68f2789
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBCollection$Options.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBCollection.class b/jejdb/build/classes/org/ejdb/driver/EJDBCollection.class
new file mode 100644 (file)
index 0000000..5632764
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBCollection.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBException.class b/jejdb/build/classes/org/ejdb/driver/EJDBException.class
new file mode 100644 (file)
index 0000000..3695d45
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBException.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBQuery$QResult.class b/jejdb/build/classes/org/ejdb/driver/EJDBQuery$QResult.class
new file mode 100644 (file)
index 0000000..464645a
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBQuery$QResult.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBQuery.class b/jejdb/build/classes/org/ejdb/driver/EJDBQuery.class
new file mode 100644 (file)
index 0000000..32f44e0
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBQuery.class differ
diff --git a/jejdb/build/classes/org/ejdb/driver/EJDBResultSet.class b/jejdb/build/classes/org/ejdb/driver/EJDBResultSet.class
new file mode 100644 (file)
index 0000000..359a4a5
Binary files /dev/null and b/jejdb/build/classes/org/ejdb/driver/EJDBResultSet.class differ
diff --git a/jejdb/build/test-reports/TEST-org.ejdb.driver.test.EJDBTest.txt b/jejdb/build/test-reports/TEST-org.ejdb.driver.test.EJDBTest.txt
new file mode 100644 (file)
index 0000000..770311d
--- /dev/null
@@ -0,0 +1,7 @@
+Testsuite: org.ejdb.driver.test.EJDBTest
+Tests run: 4, Failures: 0, Errors: 0, Time elapsed: 0.36 sec
+
+Testcase: testTransactions took 0.198 sec
+Testcase: testLowLevel took 0.076 sec
+Testcase: testQueries took 0.057 sec
+Testcase: testIndexes took 0.021 sec
diff --git a/jejdb/build/tests/classes/org/ejdb/driver/test/EJDBTest.class b/jejdb/build/tests/classes/org/ejdb/driver/test/EJDBTest.class
new file mode 100644 (file)
index 0000000..7fe5bc9
Binary files /dev/null and b/jejdb/build/tests/classes/org/ejdb/driver/test/EJDBTest.class differ
diff --git a/jejdb/build/tests/data/jejdb-test b/jejdb/build/tests/data/jejdb-test
new file mode 100644 (file)
index 0000000..dc7fc1f
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test differ
diff --git a/jejdb/build/tests/data/jejdb-test_bars b/jejdb/build/tests/data/jejdb-test_bars
new file mode 100644 (file)
index 0000000..e2223b8
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test_bars differ
diff --git a/jejdb/build/tests/data/jejdb-test_birds b/jejdb/build/tests/data/jejdb-test_birds
new file mode 100644 (file)
index 0000000..a984b20
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test_birds differ
diff --git a/jejdb/build/tests/data/jejdb-test_birds.idx.sname.lex b/jejdb/build/tests/data/jejdb-test_birds.idx.sname.lex
new file mode 100644 (file)
index 0000000..3eb680f
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test_birds.idx.sname.lex differ
diff --git a/jejdb/build/tests/data/jejdb-test_parrots b/jejdb/build/tests/data/jejdb-test_parrots
new file mode 100644 (file)
index 0000000..54b99a0
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test_parrots differ
diff --git a/jejdb/build/tests/data/jejdb-test_testcoll b/jejdb/build/tests/data/jejdb-test_testcoll
new file mode 100644 (file)
index 0000000..0517069
Binary files /dev/null and b/jejdb/build/tests/data/jejdb-test_testcoll differ
index 358620d..d899177 100755 (executable)
@@ -145,9 +145,17 @@ static void update_coll_meta(JNIEnv *env, jobject obj, EJCOLL *coll) {
        jfieldID existsID = (*env)->GetFieldID(env, clazz, "exists", "Z");
        (*env)->SetBooleanField(env, obj, existsID, coll ? JNI_TRUE : JNI_FALSE);
 
-       jclass optionsClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBCollection$Options");
        jfieldID optionsID = (*env)->GetFieldID(env, clazz, "options", "Lorg/ejdb/driver/EJDBCollection$Options;");
+       jfieldID indexesID = (*env)->GetFieldID(env, clazz, "indexes", "Ljava/util/Collection;");
+
+       jclass optionsClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBCollection$Options");
        jobject jopts = (*env)->GetObjectField(env, obj, optionsID);
+
+       if (!coll) {
+           (*env)->SetObjectField(env, obj, optionsID, NULL);
+           (*env)->SetObjectField(env, obj, indexesID, NULL);
+           return;
+       }
        
        if (!jopts) {
                jmethodID initOptions = (*env)->GetMethodID(env, optionsClazz, "<init>", "()V");
@@ -168,7 +176,6 @@ static void update_coll_meta(JNIEnv *env, jobject obj, EJCOLL *coll) {
        jclass indexClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBCollection$Index");
        jclass indexTypeClazz = (*env)->FindClass(env, "org/ejdb/driver/EJDBCollection$IndexType");
        jmethodID initIndex = (*env)->GetMethodID(env, indexClazz, "<init>", "()V");
-       jfieldID indexesID = (*env)->GetFieldID(env, clazz, "indexes", "Ljava/util/Collection;");
 
        jclass arrayListClazz = (*env)->FindClass(env, "Ljava/util/ArrayList;");
        jmethodID initArrayList = (*env)->GetMethodID(env, arrayListClazz, "<init>", "(I)V");
@@ -382,6 +389,8 @@ JNIEXPORT void JNICALL Java_org_ejdb_driver_EJDBCollection_ensureExists (JNIEnv
                set_ejdb_error(env, db);
                return;
        }
+
+       update_coll_meta(env, obj, coll);
 };
 
 /*
@@ -406,6 +415,8 @@ JNIEXPORT void JNICALL Java_org_ejdb_driver_EJDBCollection_drop (JNIEnv *env, jo
                set_ejdb_error(env, db);
                return;
        }
+
+       update_coll_meta(env, obj, NULL);
 };
 
 /*
@@ -503,6 +514,10 @@ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBCollection_load (JNIEnv *env,
  * Signature: (Lorg/bson/BSONObject;)Lorg/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");
@@ -541,6 +556,8 @@ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBCollection_save (JNIEnv *env,
 
        (*env)->DeleteLocalRef(env, joiddata);
 
+       update_coll_meta(env, obj, coll);
+
        return result;
 }
 
@@ -612,14 +629,16 @@ JNIEXPORT void JNICALL Java_org_ejdb_driver_EJDBCollection_setIndex (JNIEnv *env
 };
 
 /*
-* Class:     org_ejdb_driver_EJDBQuery
-* Method:    execute
-* Signature: (Lorg/bson/BSONObject;[Lorg/bson/BSONObject;Lorg/bson/BSONObject;I)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) {
+ * Class:     org_ejdb_driver_EJDBQuery
+ * Method:    execute
+ * Signature: (Lorg/bson/BSONObject;[Lorg/bson/BSONObject;Lorg/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;
@@ -691,7 +710,10 @@ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBQuery_execute (JNIEnv *env, j
        if (!coll) { //No collection -> no results
                qres = (flags & JBQRYCOUNT) ? NULL : tclistnew2(1); //empty results
        } else {
-               qres = ejdbqryexecute(coll, q, &count, flags, NULL);
+        if (NULL != logstream) {
+            log = tcxstrnew();
+        }
+               qres = ejdbqryexecute(coll, q, &count, flags, log);
                if (ejdbecode(db) != TCESUCCESS) {
                        set_ejdb_error(env, db);
                        goto finish;
@@ -702,6 +724,22 @@ JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBQuery_execute (JNIEnv *env, j
 
 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);
        }
index 4a23856..19eb70c 100755 (executable)
@@ -34,7 +34,7 @@ extern "C" {
 /*
  * Class:     org_ejdb_driver_EJDBCollection
  * Method:    ensureExists
- * Signature: (Lorg/ejdb/driver/EJDBCollection/Options;)V
+ * Signature: (Lorg/ejdb/driver/EJDBCollection$Options;)V
  */
 JNIEXPORT void JNICALL Java_org_ejdb_driver_EJDBCollection_ensureExists
   (JNIEnv *, jobject, jobject);
index 8d4576e..49ec7eb 100755 (executable)
@@ -12,10 +12,10 @@ extern "C" {
 /*
  * Class:     org_ejdb_driver_EJDBQuery
  * Method:    execute
- * Signature: (Lorg/bson/BSONObject;[Lorg/bson/BSONObject;Lorg/bson/BSONObject;I)Lorg/ejdb/driver/EJDBQuery/QResult;
+ * Signature: (Lorg/bson/BSONObject;[Lorg/bson/BSONObject;Lorg/bson/BSONObject;ILjava/io/OutputStream;)Lorg/ejdb/driver/EJDBQuery$QResult;
  */
 JNIEXPORT jobject JNICALL Java_org_ejdb_driver_EJDBQuery_execute
-  (JNIEnv *, jobject, jobject, jobjectArray, jobject, jint);
+  (JNIEnv *, jobject, jobject, jobjectArray, jobject, jint, jobject);
 
 #ifdef __cplusplus
 }
index 449ce58..c1f860e 100644 (file)
@@ -210,7 +210,133 @@ public class EJDBCollection {
      * @param flags
      * @throws EJDBException
      */
-    public native void setIndex(String path, int flags) throws EJDBException;
+    protected native void setIndex(String path, int flags) throws EJDBException;
+
+    /**
+     * Drops indexes of all types for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void dropIndexes(String path) throws EJDBException {
+        this.setIndex(path, JBIDXDROPALL);
+    }
+
+    /**
+     * Optimize indexes of all types for BSON field path
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void optimizeIndexes(String path) throws EJDBException {
+        this.setIndex(path, JBIDXOP);
+    }
+
+    /**
+     * Ensure index presence of String type for BSON field path
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void ensureStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXSTR);
+    }
+
+    /**
+     * Rebuild index of String type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void rebuildStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXSTR | JBIDXREBLD);
+    }
+
+    /**
+     * Drop index of String type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void dropStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXSTR | JBIDXDROP);
+    }
+
+    /**
+     * Ensure case insensitive String index for BSON field path
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void ensureIStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXISTR);
+    }
+
+    /**
+     * Rebuild case insensitive String index for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void rebuildIStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXISTR | JBIDXREBLD);
+    }
+
+    /**
+     * Drop case insensitive String index for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void dropIStringIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXISTR | JBIDXDROP);
+    }
+
+    /**
+     * Ensure index presence of Number type for BSON field path
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void ensureNumderIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXNUM);
+    }
+
+    /**
+     * Rebuild index of Number type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void rebuildNumderIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXNUM | JBIDXREBLD);
+    }
+
+    /**
+     * Drop index of Number type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void dropNumderIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXNUM | JBIDXDROP);
+    }
+
+    /**
+     * Ensure index presence of Array type for BSON field path
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void ensureArrayIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXARR);
+    }
+
+    /**
+     * Rebuild index of Array type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void rebuildArrayIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXARR | JBIDXREBLD);
+    }
+
+    /**
+     * Drop index of Array type for BSON field path.
+     * @param path    BSON field path
+     * @throws EJDBException
+     */
+    public void dropArrayIndex(String path) throws EJDBException {
+        this.setIndex(path, JBIDXARR | JBIDXDROP);
+    }
 
     /**
      * @see EJDBCollection#createQuery(org.bson.BSONObject, org.bson.BSONObject[], org.bson.BSONObject)
index 4900654..404a6ff 100644 (file)
@@ -3,6 +3,8 @@ package org.ejdb.driver;
 import org.bson.BSONObject;
 import org.bson.BasicBSONObject;
 
+import java.io.IOException;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -47,17 +49,41 @@ public class EJDBQuery {
      * Execute query
      */
     public EJDBResultSet find() throws EJDBException {
-        return this.execute(hints, 0).getResultSet();
+        try {
+            return this.find(null);
+        } catch (IOException ignored) {
+            // unpossible (log is null)
+        }
+
+        return null;
+    }
+    /**
+     * Execute query
+     */
+    public EJDBResultSet find(OutputStream log) throws EJDBException, IOException {
+        return this.execute(hints, 0, log).getResultSet();
     }
 
     /**
      * Same as  {@link org.ejdb.driver.EJDBQuery#find()} but retrieves only one matching JSON object.
      */
     public BSONObject findOne() throws EJDBException {
+        try {
+            return this.findOne(null);
+        } catch (IOException ignored) {
+            // unpossible (log is null)
+        }
+
+        return null;
+    }
+    /**
+     * Same as  {@link org.ejdb.driver.EJDBQuery#find()} but retrieves only one matching JSON object.
+     */
+    public BSONObject findOne(OutputStream log) throws EJDBException, IOException {
         Map hintsMap = hints != null ? hints.toMap() : new HashMap();
         hintsMap.put("$max", 1);
 
-        EJDBResultSet rs = this.execute(new BasicBSONObject(hintsMap), 0).getResultSet();
+        EJDBResultSet rs = this.execute(new BasicBSONObject(hintsMap), 0, null).getResultSet();
         BSONObject result = rs.hasNext() ? rs.next() : null;
         rs.close();
 
@@ -70,24 +96,51 @@ public class EJDBQuery {
      * @return count of affected objects
      */
     public int update() throws EJDBException {
-        return this.execute(hints, JBQRYCOUNT).getCount();
+        try {
+            return this.update(null);
+        } catch (IOException ignored) {
+            // unpossible (log is null)
+        }
+
+        return 0;
+    }
+    /**
+     * Executes update query
+     *
+     * @return count of affected objects
+     */
+    public int update(OutputStream log) throws EJDBException, IOException {
+        return this.execute(hints, JBQRYCOUNT, log).getCount();
     }
 
     /**
      * Convenient count(*) operation
      */
     public int count() throws EJDBException {
-        return this.execute(hints, JBQRYCOUNT).getCount();
+        try {
+            return this.count(null);
+        } catch (IOException ignored) {
+            // unpossible (log is null)
+        }
+
+        return 0;
+    }
+
+    /**
+     * Convenient count(*) operation
+     */
+    public int count(OutputStream log) throws EJDBException, IOException {
+        return this.execute(hints, JBQRYCOUNT, log).getCount();
     }
 
-    protected QResult execute(BSONObject hints, int flags) throws EJDBException {
+    protected QResult execute(BSONObject hints, int flags, OutputStream log) throws EJDBException, IOException {
         BSONObject[] qors = new BSONObject[this.qors.size()];
         this.qors.toArray(qors);
 
-        return this.execute(query, qors, hints, flags);
+        return this.execute(query, qors, hints, flags, log);
     }
 
-    protected native QResult execute(BSONObject query, BSONObject[] qors, BSONObject hints, int flags) throws EJDBException;
+    protected native QResult execute(BSONObject query, BSONObject[] qors, BSONObject hints, int flags, OutputStream log) throws EJDBException, IOException;
 
     private static class QResult {
         private int count;
index 0c2ff1b..680b9f0 100644 (file)
@@ -2,7 +2,19 @@ package org.ejdb.driver.test;
 
 import junit.framework.TestCase;
 
+import org.bson.BSONObject;
+import org.bson.BasicBSONObject;
+import org.bson.types.ObjectId;
 import org.ejdb.driver.EJDB;
+import org.ejdb.driver.EJDBCollection;
+import org.ejdb.driver.EJDBQuery;
+import org.ejdb.driver.EJDBResultSet;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * @author Tyutyunkov Vyacheslav (tve@softmotions.com)
@@ -32,6 +44,176 @@ public class EJDBTest extends TestCase {
         assertFalse(db.isOpen());
     }
 
-    public void testDBOpen() throws Exception {
+    public void testLowLevel() throws Exception {
+        assertTrue(db.isOpen());
+
+        EJDBCollection coll = db.getCollection("testcoll");
+
+        assertNotNull(coll);
+        assertFalse(coll.isExists());
+
+        coll.ensureExists();
+        assertTrue(coll.isExists());
+
+        BSONObject obj = new BasicBSONObject("test", "test").append("test2", 123);
+
+
+        ObjectId oid = coll.save(obj);
+        assertNotNull(oid);
+
+        BSONObject lobj = coll.load(oid);
+        assertNotNull(lobj);
+        assertEquals(lobj.get("_id"), oid);
+        assertEquals(obj.get("test"), lobj.get("test"));
+        assertEquals(obj.get("test2"), lobj.get("test2"));
+
+        EJDBQuery query = coll.createQuery(new BasicBSONObject());
+        EJDBResultSet rs = query.find();
+        assertEquals(rs.length(), 1);
+        for (BSONObject r : rs) {
+            assertNotNull(r);
+            assertEquals(r, lobj);
+        }
+        rs.close();
+
+        assertEquals(lobj, query.findOne());
+
+        EJDBQuery query2 = db.getCollection("test2").createQuery(new BasicBSONObject());
+        assertNull(query2.findOne());
+
+        assertEquals(query.count(), 1);
+        assertEquals(query2.count(), 0);
+
+        EJDBQuery query3 = coll.createQuery(new BasicBSONObject("test", "test"), new BasicBSONObject("$fields", new BasicBSONObject("test2", 0)));
+        assertEquals(query3.count(), 1);
+
+        rs = query3.find();
+        assertEquals(rs.length(), 1);
+        rs.close();
+
+        coll.remove(oid);
+        lobj = coll.load(oid);
+        assertNull(lobj);
+
+        db.sync();
+
+        db.ensureCollection("test2", new EJDBCollection.Options(false, false, 90000, 0));
+        db.dropCollection("test2", true);
+    }
+
+    public void testQueries() throws Exception {
+        assertTrue(db.isOpen());
+
+        BSONObject obj1 = new BasicBSONObject("name", "Grenny")
+                .append("type", "African Grey")
+                .append("male", true)
+                .append("age", 1)
+                .append("birthdate", new Date())
+                .append("likes", new String[]{"green color", "night", "toys"})
+                .append("extra1", null);
+
+        BSONObject obj2 = new BasicBSONObject("name", "Bounty")
+                .append("type", "Cockatoo")
+                .append("male", false)
+                .append("age", 15)
+                .append("birthdate", new Date())
+                .append("likes", new String[]{"sugar cane"})
+                .append("extra1", null);
+
+        EJDBCollection parrots = db.getCollection("parrots");
+
+        List<ObjectId> ss = parrots.save(Arrays.asList(obj1, null, obj2));
+        assertEquals(ss.size(), 3);
+        assertNotNull(ss.get(0));
+        assertNull(ss.get(1));
+        assertNotNull(ss.get(2));
+
+        BSONObject obj12 = parrots.load(ss.get(0));
+        assertEquals(ss.get(0), obj12.get("_id"));
+
+        EJDBQuery query = parrots.createQuery(new BasicBSONObject());
+        EJDBResultSet rs = query.find();
+        assertEquals(rs.length(), 2);
+        rs.close();
+
+
+        query = parrots.createQuery(new BasicBSONObject("name", Pattern.compile("(grenny|bounty)", Pattern.CASE_INSENSITIVE)),
+                                    new BasicBSONObject("$orderby", new BasicBSONObject("name", 1)));
+
+        rs = query.find();
+        assertEquals(rs.length(), 2);
+        BSONObject robj1 = rs.next();
+        assertEquals(robj1.get("name"), "Bounty");
+        assertEquals(robj1.get("age"), 15);
+        rs.close();
+
+        query = parrots.createQuery(new BasicBSONObject(),
+                                    new BSONObject[]{new BasicBSONObject("name", "Grenny"), new BasicBSONObject("name", "Bounty")},
+                                    new BasicBSONObject("$orderby", new BasicBSONObject("name", 1)));
+
+        rs = query.find();
+        assertEquals(rs.length(), 2);
+        rs.close();
+
+        query = parrots.createQuery(new BasicBSONObject(),
+                                    new BSONObject[]{new BasicBSONObject("name", "Grenny")},
+                                    new BasicBSONObject("$orderby", new BasicBSONObject("name", 1)));
+
+        assertEquals(query.count(), 1);
+    }
+
+    public void testIndexes() throws Exception {
+        assertTrue(db.isOpen());
+
+        BSONObject sally = new BasicBSONObject("name", "Sally").append("mood", "Angry");
+        BSONObject molly = new BasicBSONObject("name", "Molly").append("mood", "Very angry").append("secret", null);
+
+        EJDBCollection birds = db.getCollection("birds");
+        birds.save(Arrays.asList(sally, molly));
+
+        ByteArrayOutputStream log;
+
+        EJDBQuery query = birds.createQuery(new BasicBSONObject("name", "Molly"));
+
+        query.find(log = new ByteArrayOutputStream());
+        assertTrue(log.toString().contains("RUN FULLSCAN"));
+
+        birds.ensureStringIndex("name");
+
+        query.find(log = new ByteArrayOutputStream());
+        assertTrue(log.toString().contains("MAIN IDX: 'sname'"));
+        assertFalse(log.toString().contains("RUN FULLSCAN"));
+    }
+
+    public void testTransactions() throws Exception {
+        assertTrue(db.isOpen());
+
+        ObjectId boid;
+        BasicBSONObject bar = new BasicBSONObject("foo", "bar");
+
+        EJDBCollection bars = db.getCollection("bars");
+
+        assertFalse(bars.isTransactionActive());
+        bars.beginTransaction();
+        assertTrue(bars.isTransactionActive());
+        boid = bars.save(bar);
+        assertNotNull(boid);
+        assertNotNull(bars.load(boid));
+        bars.rollbackTransaction();
+        assertFalse(bars.isTransactionActive());
+        assertNull(bars.load(boid));
+
+        assertFalse(bars.isTransactionActive());
+        bars.beginTransaction();
+        assertTrue(bars.isTransactionActive());
+        boid = bars.save(bar);
+        assertNotNull(boid);
+        assertNotNull(bars.load(boid));
+        bars.commitTransaction();
+        assertFalse(bars.isTransactionActive());
+        BSONObject bar2 = bars.load(boid);
+        assertNotNull(bar2);
+        assertEquals(bar2.get("_id"), boid);
+        assertEquals(bar2.get("foo"), bar.get("foo"));
     }
 }
diff --git a/jejdb/src/test/org/ejdb/driver/test/Test.java b/jejdb/src/test/org/ejdb/driver/test/Test.java
deleted file mode 100644 (file)
index e760b8b..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-package org.ejdb.driver.test;
-
-import org.bson.BSONObject;
-import org.bson.BasicBSONObject;
-import org.bson.types.BasicBSONList;
-import org.bson.types.ObjectId;
-import org.ejdb.driver.EJDB;
-import org.ejdb.driver.EJDBCollection;
-import org.ejdb.driver.EJDBQuery;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-/**
- * @author Tyutyunkov Vyacheslav (tve@softmotions.com)
- * @version $Id$
- */
-public class Test {
-    public static void main(String[] args) throws Exception {
-        EJDB db = new EJDB();
-
-        try {
-            db.open("test");
-
-            System.out.println("DB opened");
-//            System.in.read();
-
-//            db.ensureCollection("test");
-//
-//            System.out.println("collection 'test' created");
-//            System.in.read();
-
-//            db.ensureCollection("test2");
-//
-//            System.out.println("collection 'test2' created");
-////            System.in.read();
-//
-            db.dropCollection("test");
-//
-//            System.out.println("collection 'test' dropped");
-////            System.in.read();
-//
-//            db.dropCollection("test2", true);
-//
-//            System.out.println("collection 'test2' dropped");
-//            System.in.read();
-
-
-            EJDBCollection coll = db.getCollection("test");
-            coll.ensureExists();
-            coll.drop();
-
-
-            BSONObject b = new BasicBSONObject("name", "name");
-            EJDBQuery query = coll.createQuery(b, new BSONObject[]{b,b,b,b}, b);
-
-//            if (true) {
-//                return;
-//            }
-
-
-//
-//            db.close();
-//
-//            db.isOpen();
-
-            coll.setIndex("test", EJDBCollection.JBIDXDROPALL | EJDBCollection.JBIDXISTR);
-
-//            if (true) {
-//                return;
-//            }
-//
-//            coll.createQuery(null);
-
-            BSONObject bson = coll.load(new ObjectId("513f04d563f08b6400000000"));
-            if (bson != null) {
-                System.out.println(bson);
-            }
-
-            Random rand = new Random();
-
-            List<ObjectId> oids = new ArrayList<ObjectId>(500);
-
-            int ri;
-
-            for (int i = 0; i < 5/*00*/; ++ i) {
-                ri = rand.nextInt();
-//                System.out.println("Random: " + ri);
-
-                ObjectId oid = coll.save(new BasicBSONObject("random", ri));
-                if (oid == null) {
-                    System.out.println("Error saving");
-                } else {
-                    bson = coll.load(oid);
-                    if (bson == null) {
-                        System.out.println("Error loading");
-                    } else {
-                        System.out.println(bson);
-                        oids.add(oid);
-                    }
-                }
-            }
-
-            List<ObjectId> roids = new ArrayList<ObjectId>(oids.size());
-            List<ObjectId> nroids = new ArrayList<ObjectId>(oids.size());
-
-            for (ObjectId oid : oids) {
-                coll.remove(oid);
-                System.out.println("Object removed #" + oid);
-                (true ? roids : nroids).add(oid);
-            }
-
-            System.out.println("Check removed (" + roids.size() + ")");
-            for (ObjectId oid : roids) {
-                bson = coll.load(oid);
-                if (bson != null) {
-                    System.out.println("Achtung! Object exists: " + bson);
-                } else {
-                    System.out.println("Ok! Object not loaded. (#" + oid + ")");
-                }
-            }
-
-            System.out.println("Check not removed (" + nroids.size() + ")");
-            for (ObjectId oid : nroids) {
-                bson = coll.load(oid);
-                if (bson != null) {
-                    System.out.println("Achtung! Object exists: " + bson);
-                } else {
-                    System.out.println("That ok! Object not loaded. (#" + oid + ")");
-                }
-            }
-
-//            int i = 0;
-
-//            while(true) {
-//                for (ObjectId oid : oids) {
-//                    bson = coll.load(oid);
-//                }
-//            }
-//
-            BasicBSONList list = new BasicBSONList();
-
-            list.add(new BasicBSONObject("random", rand.nextInt()));
-            list.add(new BasicBSONObject("random", rand.nextInt()));
-            list.add(new BasicBSONObject("random", rand.nextInt()));
-            list.add(new BasicBSONObject("random", rand.nextInt()));
-            list.add(new BasicBSONObject("random", rand.nextInt()));
-
-            ObjectId oid = coll.save(list);
-            if (oid == null) {
-                System.out.println("Error saving");
-            } else {
-                bson = coll.load(oid);
-                if (bson == null) {
-                    System.out.println("Error loading");
-                } else {
-                    System.out.println(bson.toString());
-                    oids.add(oid);
-                }
-            }
-
-            System.out.println("Collection sync: ");coll.sync();
-
-
-            List<BSONObject> objs = new ArrayList<BSONObject>(5);
-            for(int i=0; i < 5; ++i) {
-                objs.add(new BasicBSONObject("random", rand.nextBoolean()));
-            }
-
-            oids = coll.save(objs);
-            for (ObjectId oid2 : oids) {
-                if (oid2 == null) {
-                    System.out.println("Error saving");
-                } else {
-                    bson = coll.load(oid2);
-                    if (bson == null) {
-                        System.out.println("Error loading");
-                    } else {
-                        System.out.println(bson);
-                    }
-                }
-            }
-
-            System.out.println("DB sync: ");db.sync();
-
-        } finally {
-            db.close();
-            System.out.println("DB closed");
-        }
-    }
-}
-
diff --git a/jejdb/src/test/org/ejdb/driver/test/Test2.java b/jejdb/src/test/org/ejdb/driver/test/Test2.java
deleted file mode 100644 (file)
index 0cfc101..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package org.ejdb.driver.test;
-
-import org.bson.BSONObject;
-import org.bson.BasicBSONObject;
-import org.ejdb.driver.EJDB;
-import org.ejdb.driver.EJDBCollection;
-import org.ejdb.driver.EJDBQuery;
-import org.ejdb.driver.EJDBResultSet;
-
-import java.io.IOException;
-import java.util.Random;
-
-/**
- * @author Tyutyunkov Vyacheslav (tve@softmotions.com)
- * @version $Id$
- */
-public class Test2 {
-    public static int INDEX = -1;
-
-    public static final int TEST_COUNT = 15;
-    public static final Random random = new Random(System.currentTimeMillis());
-
-    public static void main(String[] args) throws Exception {
-        EJDB db = new EJDB();
-
-        try {
-            db.open("test5");
-            System.out.println("test EJDB opened: " + db);
-
-            EJDBCollection test = db.getCollection("test");
-
-            System.out.println(test);
-
-            test.setIndex("random", EJDBCollection.JBIDXNUM);
-
-            test.updateMeta();
-
-            System.out.println(test);
-
-            test.drop(true);
-            System.out.println("test collection dropped");
-            test.ensureExists();
-            System.out.println("test collection created");
-
-            for (int i = 0; i < TEST_COUNT; ++i) {
-                test.save(getTestObject());
-            }
-
-            System.out.println("test objects saved");
-
-            test.sync();
-            System.out.println("test collection synced");
-
-            EJDBQuery query = test.createQuery(new BasicBSONObject());
-
-            System.out.println("Objects matched: " + query.count());
-
-            EJDBResultSet rs = query.find();
-            for (BSONObject r : rs) {
-                System.out.println(r);
-            }
-            rs.close();
-
-            System.out.println();
-            System.out.println(query.findOne());
-            System.out.println();
-
-            query = test.createQuery(new BasicBSONObject("randomBoolean", true));
-            System.out.println("Objects with 'randomBoolean==true': " + query.count());
-            rs = query.find();
-            for (BSONObject r : rs) {
-                System.out.println(r);
-            }
-            rs.close();
-
-            query.getQueryObject().put("smallRandom", new BasicBSONObject("$lt", 6));
-            rs = query.find();
-            System.out.println("Objects with 'randomBoolean==true && smallRandom<6': " + rs.length());
-            for (BSONObject r : rs) {
-                System.out.println(r);
-            }
-            rs.close();
-        } finally {
-            db.close();
-        }
-    }
-
-    private static BSONObject getTestObject() {
-        BSONObject bsonObject = new BasicBSONObject();
-
-        ++INDEX;
-
-        bsonObject.put("name", "Object#" + INDEX);
-        bsonObject.put("time", System.currentTimeMillis());
-        bsonObject.put("index", INDEX);
-        bsonObject.put("random", (random.nextBoolean() ? -1 : 1) * random.nextInt(65536));
-        bsonObject.put("randomBoolean", random.nextBoolean());
-        bsonObject.put("randomDouble", random.nextDouble());
-        bsonObject.put("smallRandom", random.nextInt(10));
-
-        return bsonObject;
-    }
-}