summaryrefslogtreecommitdiff
path: root/storage/connect/jmgoconn.cpp
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2017-07-02 22:29:31 +0200
committerOlivier Bertrand <bertrandop@gmail.com>2017-07-02 22:41:11 +0200
commit94e5d7de85a2964e7dd9a02e91a71522ccc66f94 (patch)
tree45164d08bff5a905f88da27762fcf3c089299cd7 /storage/connect/jmgoconn.cpp
parentc51548d6b4234d1b9bf7548125f63c5975f37d35 (diff)
downloadmariadb-git-94e5d7de85a2964e7dd9a02e91a71522ccc66f94.tar.gz
- Add Support of the MongoDB Java Driver.
modified: storage/connect/CMakeLists.txt modified: storage/connect/JavaWrappers.jar modified: storage/connect/colblk.h modified: storage/connect/filter.cpp modified: storage/connect/filter.h modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/jdbccat.h modified: storage/connect/jdbconn.cpp modified: storage/connect/jdbconn.h modified: storage/connect/mongofam.cpp modified: storage/connect/mongofam.h modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/tabext.h modified: storage/connect/tabjdbc.cpp modified: storage/connect/tabjdbc.h modified: storage/connect/tabjson.cpp modified: storage/connect/tabjson.h modified: storage/connect/tabmgo.cpp modified: storage/connect/tabmgo.h created: storage/connect/Mongo2Interface.java created: storage/connect/Mongo3Interface.java created: storage/connect/cmgoconn.cpp created: storage/connect/cmgoconn.h created: storage/connect/javaconn.cpp created: storage/connect/javaconn.h created: storage/connect/jmgfam.cpp created: storage/connect/jmgfam.h created: storage/connect/jmgoconn.cpp created: storage/connect/jmgoconn.h created: storage/connect/mongo.cpp created: storage/connect/mongo.h created: storage/connect/tabjmg.cpp created: storage/connect/tabjmg.h - tdbp not initialized when catched exception in CntGetTDB (connect.cc line 188) modified: storage/connect/connect.h - CheckCleanup should sometimes doing cleanup on pure info Sometimes MariaDB loops on info to get the size of all tables in a database. This can sometimes fail by exhausted memory. CheckCleanup now have a force boolean parameter (defaulting to false) modified: storage/connect/ha_connect.cc modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h Change the copyright of some source files modified: storage/connect/connect.cc modified: storage/connect/connect.h modified: storage/connect/engmsg.h modified: storage/connect/global.h modified: storage/connect/ha_connect.cc modified: storage/connect/ha_connect.h modified: storage/connect/msgid.h modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/os.h modified: storage/connect/osutil.c modified: storage/connect/osutil.h modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h
Diffstat (limited to 'storage/connect/jmgoconn.cpp')
-rw-r--r--storage/connect/jmgoconn.cpp811
1 files changed, 811 insertions, 0 deletions
diff --git a/storage/connect/jmgoconn.cpp b/storage/connect/jmgoconn.cpp
new file mode 100644
index 00000000000..cb0729ed1f7
--- /dev/null
+++ b/storage/connect/jmgoconn.cpp
@@ -0,0 +1,811 @@
+/************ JMgoConn C++ Functions Source Code File (.CPP) ***********/
+/* Name: JMgoConn.CPP Version 1.1 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2017 */
+/* */
+/* This file contains the MongoDB Java connection classes functions. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+
+/***********************************************************************/
+/* Required objects includes. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "colblk.h"
+#include "xobject.h"
+#include "xtable.h"
+#include "filter.h"
+#include "jmgoconn.h"
+
+#define nullptr 0
+
+bool IsNum(PSZ s);
+
+/* --------------------------- Class JNCOL --------------------------- */
+
+/***********************************************************************/
+/* Add a column in the column list. */
+/***********************************************************************/
+void JNCOL::AddCol(PGLOBAL g, PCOL colp, PSZ jp)
+{
+ char *p;
+ PJKC kp, kcp;
+
+ if ((p = strchr(jp, '.'))) {
+ PJNCOL icp;
+
+ *p++ = 0;
+
+ for (kp = Klist; kp; kp = kp->Next)
+ if (kp->Jncolp && !strcmp(jp, kp->Key))
+ break;
+
+ if (!kp) {
+ icp = new(g) JNCOL(IsNum(p));
+ kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
+ kcp->Next = NULL;
+ kcp->Jncolp = icp;
+ kcp->Colp = NULL;
+
+ if (Array) {
+ kcp->Key = NULL;
+ kcp->N = atoi(p);
+ } else {
+ kcp->Key = PlugDup(g, jp);
+ kcp->N = 0;
+ } // endif Array
+
+ if (Klist) {
+ for (kp = Klist; kp->Next; kp = kp->Next);
+
+ kp->Next = kcp;
+ } else
+ Klist = kcp;
+
+ } else
+ icp = kp->Jncolp;
+
+ *(p - 1) = '.';
+ icp->AddCol(g, colp, p);
+ } else {
+ kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
+
+ kcp->Next = NULL;
+ kcp->Jncolp = NULL;
+ kcp->Colp = colp;
+
+ if (Array) {
+ kcp->Key = NULL;
+ kcp->N = atoi(jp);
+ } else {
+ kcp->Key = jp;
+ kcp->N = 0;
+ } // endif Array
+
+ if (Klist) {
+ for (kp = Klist; kp->Next; kp = kp->Next);
+
+ kp->Next = kcp;
+ } else
+ Klist = kcp;
+
+ } // endif jp
+
+} // end of AddCol
+
+/***********************************************************************/
+/* JMgoConn construction/destruction. */
+/***********************************************************************/
+JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper)
+ : JAVAConn(g, wrapper)
+{
+ CollName = collname;
+ readid = fetchid = getdocid = objfldid = fcollid = acollid =
+ mkdocid = docaddid = mkarid = araddid = insertid = updateid =
+ deleteid = gcollid = countid = rewindid = nullptr;
+ DiscFunc = "MongoDisconnect";
+ Fpc = NULL;
+ m_Version = 0;
+ m_Fetch = 0;
+ m_Version = 0;
+} // end of JMgoConn
+
+/***********************************************************************/
+/* AddJars: add some jar file to the Class path. */
+/***********************************************************************/
+void JMgoConn::AddJars(PSTRG jpop, char sep)
+{
+#if defined(DEVELOPMENT)
+ if (m_Version == 2) {
+ //jpop->Append(sep);
+ //jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin");
+ jpop->Append(sep);
+ jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar");
+ } else {
+ //jpop->Append(sep);
+ //jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin");
+ jpop->Append(sep);
+ jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar");
+ } // endif m_Version
+#endif // DEVELOPMENT
+} // end of AddJars
+
+/***********************************************************************/
+/* Connect: connect to a data source. */
+/***********************************************************************/
+bool JMgoConn::Connect(PJPARM sop)
+{
+ bool err = false;
+ jint rc;
+ jboolean brc;
+ jstring cln;
+ PGLOBAL& g = m_G;
+
+ m_Version = sop->Version;
+
+ /*******************************************************************/
+ /* Create or attach a JVM. */
+ /*******************************************************************/
+ if (Open(g))
+ return true;
+
+ /*******************************************************************/
+ /* Connect to MongoDB. */
+ /*******************************************************************/
+ jmethodID cid = nullptr;
+
+ if (gmID(g, cid, "MongoConnect", "([Ljava/lang/String;)I"))
+ return true;
+
+ // Build the java string array
+ jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
+ env->FindClass("java/lang/String"), NULL); // Strings
+
+ //m_Scrollable = sop->Scrollable;
+ //m_RowsetSize = sop->Fsize;
+
+ // change some elements
+ if (sop->Driver)
+ env->SetObjectArrayElement(parms, 0, env->NewStringUTF(sop->Url));
+
+ if (sop->Url)
+ env->SetObjectArrayElement(parms, 1, env->NewStringUTF(sop->Driver));
+
+ if (sop->User)
+ env->SetObjectArrayElement(parms, 2, env->NewStringUTF(sop->User));
+
+ if (sop->Pwd)
+ env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
+
+ // call method
+ rc = env->CallIntMethod(job, cid, parms);
+ err = Check(rc);
+ env->DeleteLocalRef(parms); // Not used anymore
+
+ if (err) {
+ sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
+ return true;
+ } // endif Msg
+
+ /*********************************************************************/
+ /* Get the collection. */
+ /*********************************************************************/
+ if (gmID(g, gcollid, "GetCollection", "(Ljava/lang/String;)Z"))
+ return true;
+
+ cln = env->NewStringUTF(CollName);
+ brc = env->CallBooleanMethod(job, gcollid, cln);
+ env->DeleteLocalRef(cln);
+
+ if (Check(brc ? -1 : 0)) {
+ sprintf(g->Message, "GetCollection: %s", Msg);
+ return true;
+ } // endif Msg
+
+ m_Connected = true;
+ return false;
+} // end of Connect
+
+/***********************************************************************/
+/* CollSize: returns the number of documents in the collection. */
+/***********************************************************************/
+int JMgoConn::CollSize(PGLOBAL g)
+{
+ if (!gmID(g, countid, "GetCollSize", "()J")) {
+ jlong card = env->CallLongMethod(job, countid);
+
+ return (int)card;
+ } else
+ return 2; // Make MariaDB happy
+
+} // end of CollSize
+
+/***********************************************************************/
+/* OpenDB: Data Base open routine for MONGO access method. */
+/***********************************************************************/
+bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
+ PCSZ filter, bool pipe)
+{
+ const char *p;
+ bool b = false, id = (tdbp->GetMode() != MODE_READ), all = false;
+ uint len;
+ PCOL cp;
+ PSZ jp;
+ PCSZ op = NULL, sf = NULL, Options = options;
+ PSTRG s = NULL;
+
+ if (Options && !stricmp(Options, "all")) {
+ Options = NULL;
+ all = true;
+ } // endif Options
+
+ for (cp = tdbp->GetColumns(); cp; cp = cp->GetNext())
+ if (!strcmp(cp->GetName(), "_id"))
+ id = true;
+ else if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && (!Options || pipe))
+ all = true;
+
+ if (pipe && Options) {
+ if (trace)
+ htrc("Pipeline: %s\n", Options);
+
+ p = strrchr(Options, ']');
+
+ if (!p) {
+ strcpy(g->Message, "Missing ] in pipeline");
+ return true;
+ } else
+ *(char*)p = 0;
+
+ s = new(g) STRING(g, 1023, (PSZ)Options);
+
+ if (tdbp->GetFilter()) {
+ s->Append(",{\"$match\":");
+
+ if (tdbp->GetFilter()->MakeSelector(g, s)) {
+ strcpy(g->Message, "Failed making selector");
+ return NULL;
+ } else
+ s->Append('}');
+
+ tdbp->SetFilter(NULL); // Not needed anymore
+ } // endif To_Filter
+
+ if (!all && tdbp->GetColumns()) {
+ // Project list
+ len = s->GetLength();
+ s->Append(",{\"$project\":{\"");
+
+ if (!id)
+ s->Append("_id\":0,\"");
+
+ for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
+ if (b)
+ s->Append(",\"");
+ else
+ b = true;
+
+ if ((jp = cp->GetJpath(g, true)))
+ s->Append(jp);
+ else {
+ s->Truncate(len);
+ goto nop;
+ } // endif Jpath
+
+ s->Append("\":1");
+ } // endfor cp
+
+ s->Append("}}");
+ } // endif all
+
+ nop:
+ s->Append("]}");
+ s->Resize(s->GetLength() + 1);
+ *(char*)p = ']'; // Restore Colist for discovery
+ p = s->GetStr();
+
+ if (trace)
+ htrc("New Pipeline: %s\n", p);
+
+ return AggregateCollection(p);
+ } else {
+ if (filter || tdbp->GetFilter()) {
+ if (trace) {
+ if (filter)
+ htrc("Filter: %s\n", filter);
+
+ if (tdbp->GetFilter()) {
+ char buf[512];
+
+ tdbp->GetFilter()->Prints(g, buf, 511);
+ htrc("To_Filter: %s\n", buf);
+ } // endif To_Filter
+
+ } // endif trace
+
+ s = new(g) STRING(g, 1023, (PSZ)filter);
+ len = s->GetLength();
+
+ if (tdbp->GetFilter()) {
+ if (filter)
+ s->Append(',');
+
+ if (tdbp->GetFilter()->MakeSelector(g, s)) {
+ strcpy(g->Message, "Failed making selector");
+ return NULL;
+ } // endif Selector
+
+ tdbp->SetFilter(NULL); // Not needed anymore
+ } // endif To_Filter
+
+ if (trace)
+ htrc("selector: %s\n", s->GetStr());
+
+ s->Resize(s->GetLength() + 1);
+ sf = PlugDup(g, s->GetStr());
+ } // endif Filter
+
+ if (!all) {
+ if (Options && *Options) {
+ if (trace)
+ htrc("options=%s\n", Options);
+
+ op = Options;
+ } else if (tdbp->GetColumns()) {
+ // Projection list
+ if (s)
+ s->Set("{\"");
+ else
+ s = new(g) STRING(g, 511, "{\"");
+
+ if (!id)
+ s->Append("_id\":0,\"");
+
+ for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
+ if (b)
+ s->Append(",\"");
+ else
+ b = true;
+
+ if ((jp = cp->GetJpath(g, true)))
+ s->Append(jp);
+ else {
+ // Can this happen?
+ htrc("Fail getting projection path of %s\n", cp->GetName());
+ goto nope;
+ } // endif Jpath
+
+ s->Append("\":1");
+ } // endfor cp
+
+ s->Append("}");
+ s->Resize(s->GetLength() + 1);
+ op = s->GetStr();
+ } else {
+ // count(*) ?
+ op = "{\"_id\":1}";
+ } // endif Options
+
+ } // endif all
+
+ nope:
+ return FindCollection(sf, op);
+ } // endif Pipe
+
+} // end of MakeCursor
+
+/***********************************************************************/
+/* Find a collection and make cursor. */
+/***********************************************************************/
+bool JMgoConn::FindCollection(PCSZ query, PCSZ proj)
+{
+ bool rc = true;
+ jboolean brc;
+ jstring qry = nullptr, prj = nullptr;
+ PGLOBAL& g = m_G;
+
+ // Get the methods used to execute a query and get the result
+ if (!gmID(g, fcollid, "FindColl", "(Ljava/lang/String;Ljava/lang/String;)Z")) {
+ if (query)
+ qry = env->NewStringUTF(query);
+
+ if (proj)
+ prj = env->NewStringUTF(proj);
+
+ brc = env->CallBooleanMethod(job, fcollid, qry, prj);
+
+ if (!Check(brc ? -1 : 0)) {
+ rc = false;
+ } else
+ sprintf(g->Message, "FindColl: %s", Msg);
+
+ if (query)
+ env->DeleteLocalRef(qry);
+
+ if (proj)
+ env->DeleteLocalRef(prj);
+
+ } // endif xqid
+
+ return rc;
+} // end of FindCollection
+
+/***********************************************************************/
+/* Find a collection and make cursor. */
+/***********************************************************************/
+bool JMgoConn::AggregateCollection(PCSZ pipeline)
+{
+ bool rc = true;
+ jboolean brc;
+ jstring pip = nullptr;
+ PGLOBAL& g = m_G;
+
+ // Get the methods used to execute a query and get the result
+ if (!gmID(g, acollid, "AggregateColl", "(Ljava/lang/String;)Z")) {
+ pip = env->NewStringUTF(pipeline);
+
+ brc = env->CallBooleanMethod(job, acollid, pip);
+
+ if (!Check(brc ? -1 : 0)) {
+ rc = false;
+ } else
+ sprintf(g->Message, "AggregateColl: %s", Msg);
+
+ env->DeleteLocalRef(pip);
+ } // endif acollid
+
+ return rc;
+} // end of AggregateCollection
+
+/***********************************************************************/
+/* Fetch next row. */
+/***********************************************************************/
+int JMgoConn::Fetch(int pos)
+{
+ jint rc = JNI_ERR;
+ PGLOBAL& g = m_G;
+
+ //if (m_Full) // Result set has one row
+ // return 1;
+
+ //if (pos) {
+ // if (!m_Scrollable) {
+ // strcpy(g->Message, "Cannot fetch(pos) if FORWARD ONLY");
+ // return rc;
+ // } else if (gmID(m_G, fetchid, "Fetch", "(I)Z"))
+ // return rc;
+
+ // if (env->CallBooleanMethod(job, fetchid, pos))
+ // rc = m_Rows;
+
+ //} else {
+ if (gmID(g, readid, "ReadNext", "()I"))
+ return (int)rc;
+
+ rc = env->CallIntMethod(job, readid);
+
+ if (!Check(rc)) {
+ //if (rc == 0)
+ // m_Full = (m_Fetch == 1);
+ //else
+ // m_Fetch++;
+
+ m_Rows += (int)rc;
+ } else
+ sprintf(g->Message, "Fetch: %s", Msg);
+
+ //} // endif pos
+
+ return (int)rc;
+} // end of Fetch
+
+/***********************************************************************/
+/* Get the Json string of the current document. */
+/***********************************************************************/
+PSZ JMgoConn::GetDocument(void)
+{
+ PGLOBAL& g = m_G;
+ PSZ doc = NULL;
+ jstring jdc;
+
+ if (!gmID(g, getdocid, "GetDoc", "()Ljava/lang/String;")) {
+ jdc = (jstring)env->CallObjectMethod(job, getdocid);
+
+ if (jdc)
+ doc = (PSZ)env->GetStringUTFChars(jdc, (jboolean)false);
+
+ } // endif getdocid
+
+ return doc;
+ } // end of GetDocument
+
+/***********************************************************************/
+/* Group columns for inserting or updating. */
+/***********************************************************************/
+void JMgoConn::MakeColumnGroups(PGLOBAL g, PTDB tdbp)
+{
+ Fpc = new(g) JNCOL(false);
+
+ for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
+ if (!colp->IsSpecial())
+ Fpc->AddCol(g, colp, colp->GetJpath(g, false));
+
+} // end of MakeColumnGroups
+
+/***********************************************************************/
+/* Get additional method ID. */
+/***********************************************************************/
+bool JMgoConn::GetMethodId(PGLOBAL g, MODE mode)
+{
+ if (mode == MODE_UPDATE) {
+ if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
+ return true;
+
+ if (gmID(g, docaddid, "DocAdd",
+ "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"))
+ return true;
+
+ if (gmID(g, updateid, "CollUpdate", "(Ljava/lang/Object;)J"))
+ return true;
+
+ } else if (mode == MODE_INSERT) {
+ if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
+ return true;
+
+ if (gmID(g, docaddid, "DocAdd",
+ "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z"))
+ return true;
+
+ if (gmID(g, mkarid, "MakeArray", "()Ljava/lang/Object;"))
+ return true;
+
+ if (gmID(g, araddid, "ArrayAdd", "(Ljava/lang/Object;ILjava/lang/Object;)Z"))
+ return true;
+
+ if (gmID(g, insertid, "CollInsert", "(Ljava/lang/Object;)Z"))
+ return true;
+
+ } else if (mode == MODE_DELETE)
+ if (gmID(g, deleteid, "CollDelete", "(Z)J"))
+ return true;
+
+ return gmID(g, rewindid, "Rewind", "()Z");
+} // end of GetMethodId
+
+/***********************************************************************/
+/* MakeObject. */
+/***********************************************************************/
+jobject JMgoConn::MakeObject(PGLOBAL g, PCOL colp, bool&error )
+{
+ jclass cls;
+ jmethodID cns = nullptr; // Constructor
+ jobject val = nullptr;
+ PVAL valp = colp->GetValue();
+
+ error = false;
+
+ if (valp->IsNull())
+ return NULL;
+
+ try {
+ switch (valp->GetType()) {
+ case TYPE_STRING:
+ val = env->NewStringUTF(valp->GetCharValue());
+ break;
+ case TYPE_INT:
+ case TYPE_SHORT:
+ cls = env->FindClass("java/lang/Integer");
+ cns = env->GetMethodID(cls, "<init>", "(I)V");
+ val = env->NewObject(cls, cns, valp->GetIntValue());
+ break;
+ case TYPE_TINY:
+ cls = env->FindClass("java/lang/Boolean");
+ cns = env->GetMethodID(cls, "<init>", "(Z)V");
+ val = env->NewObject(cls, cns, (valp->GetIntValue() != 0));
+ break;
+ case TYPE_BIGINT:
+ cls = env->FindClass("java/lang/Long");
+ cns = env->GetMethodID(cls, "<init>", "(J)V");
+ val = env->NewObject(cls, cns, valp->GetBigintValue());
+ break;
+ case TYPE_DOUBLE:
+ cls = env->FindClass("java/lang/Double");
+ cns = env->GetMethodID(cls, "<init>", "(D)V");
+ val = env->NewObject(cls, cns, valp->GetFloatValue());
+ break;
+ default:
+ sprintf(g->Message, "Cannot make object from %d type", valp->GetType());
+ error = true;
+ break;
+ } // endswitch Type
+
+ } catch (...) {
+ sprintf(g->Message, "Cannot make object from %s value", colp->GetName());
+ error = true;
+ } // end try/catch
+
+ return val;
+} // end of MakeObject
+
+/***********************************************************************/
+/* MakeDoc. */
+/***********************************************************************/
+jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp)
+{
+ bool error = false;
+ jobject parent, child, val;
+ jstring jkey;
+
+ if (jcp->Array)
+ parent = env->CallObjectMethod(job, mkarid);
+ else
+ parent = env->CallObjectMethod(job, mkdocid);
+
+ for (PJKC kp = jcp->Klist; kp; kp = kp->Next)
+ if (kp->Jncolp) {
+ if (!(child = MakeDoc(g, kp->Jncolp)))
+ return NULL;
+
+ if (!jcp->Array) {
+ jkey = env->NewStringUTF(kp->Key);
+
+ if (env->CallBooleanMethod(job, docaddid, parent, jkey, child))
+ return NULL;
+
+ env->DeleteLocalRef(jkey);
+ } else
+ if (env->CallBooleanMethod(job, araddid, parent, kp->N, child))
+ return NULL;
+
+ } else {
+ if (!(val = MakeObject(g, kp->Colp, error))) {
+ if (error)
+ return NULL;
+
+ } else if (!jcp->Array) {
+ jkey = env->NewStringUTF(kp->Key);
+
+ if (env->CallBooleanMethod(job, docaddid, parent, jkey, val))
+ return NULL;
+
+ env->DeleteLocalRef(jkey);
+ } else if (env->CallBooleanMethod(job, araddid, parent, kp->N, val)) {
+ if (Check(-1))
+ sprintf(g->Message, "ArrayAdd: %s", Msg);
+ else
+ sprintf(g->Message, "ArrayAdd: unknown error");
+
+ return NULL;
+ } // endif ArrayAdd
+
+ } // endif Jncolp
+
+ return parent;
+} // end of MakeDoc
+
+/***********************************************************************/
+/* Insert a new document in the collation. */
+/***********************************************************************/
+int JMgoConn::DocWrite(PGLOBAL g)
+{
+ jobject doc;
+
+ if (!Fpc || !(doc = MakeDoc(g, Fpc)))
+ return RC_FX;
+
+ if (env->CallBooleanMethod(job, insertid, doc)) {
+ if (Check(-1))
+ sprintf(g->Message, "CollInsert: %s", Msg);
+ else
+ sprintf(g->Message, "CollInsert: unknown error");
+
+ return RC_FX;
+ } // endif Insert
+
+ return RC_OK;
+} // end of DocWrite
+
+/***********************************************************************/
+/* Update the current document from the collection. */
+/***********************************************************************/
+int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp)
+{
+ int rc = RC_OK;
+ bool error;
+ PCOL colp;
+ jstring jkey;
+ jobject val, upd, updlist = env->CallObjectMethod(job, mkdocid);
+
+ // Make the list of changes to do
+ for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext()) {
+ jkey = env->NewStringUTF(colp->GetJpath(g, false));
+ val = MakeObject(g, colp, error);
+
+ if (error)
+ return RC_FX;
+
+ if (env->CallBooleanMethod(job, docaddid, updlist, jkey, val))
+ return NULL;
+
+ env->DeleteLocalRef(jkey);
+ } // endfor colp
+
+ // Make the update parameter
+ upd = env->CallObjectMethod(job, mkdocid);
+ jkey = env->NewStringUTF("$set");
+
+ if (env->CallBooleanMethod(job, docaddid, upd, jkey, updlist))
+ return NULL;
+
+ env->DeleteLocalRef(jkey);
+
+ jlong ar = env->CallLongMethod(job, updateid, upd);
+
+ if (trace)
+ htrc("DocUpdate: ar = %ld\n", ar);
+
+ if (Check((int)ar)) {
+ sprintf(g->Message, "CollUpdate: %s", Msg);
+ rc = RC_FX;
+ } // endif ar
+
+ return rc;
+} // end of DocUpdate
+
+/***********************************************************************/
+/* Remove all or only the current document from the collection. */
+/***********************************************************************/
+int JMgoConn::DocDelete(PGLOBAL g, bool all)
+{
+ int rc = RC_OK;
+ jlong ar = env->CallLongMethod(job, deleteid, all);
+
+ if (trace)
+ htrc("DocDelete: ar = %ld\n", ar);
+
+ if (Check((int)ar)) {
+ sprintf(g->Message, "CollDelete: %s", Msg);
+ rc = RC_FX;
+ } // endif ar
+
+ return rc;
+} // end of DocDelete
+
+/***********************************************************************/
+/* Rewind the collection. */
+/***********************************************************************/
+bool JMgoConn::Rewind(void)
+{
+ return env->CallBooleanMethod(job, rewindid);
+} // end of Rewind
+
+/***********************************************************************/
+/* Retrieve the column string value from the document. */
+/***********************************************************************/
+PSZ JMgoConn::GetColumnValue(PSZ path)
+{
+ PGLOBAL& g = m_G;
+ PSZ fld = NULL;
+ jstring fn, jn = nullptr;
+
+ if (!path || (jn = env->NewStringUTF(path)) == nullptr) {
+ sprintf(g->Message, "Fail to allocate jstring %s", SVP(path));
+ throw (int)TYPE_AM_MGO;
+ } // endif name
+
+ if (!gmID(g, objfldid, "GetField", "(Ljava/lang/String;)Ljava/lang/String;")) {
+ fn = (jstring)env->CallObjectMethod(job, objfldid, jn);
+
+ if (fn)
+ fld = (PSZ)env->GetStringUTFChars(fn, (jboolean)false);
+
+ } // endif objfldid
+
+ return fld;
+} // end of GetColumnValue
+