mariadb/storage/connect/jmgoconn.cpp
Olivier Bertrand 70e567f576 Squashed commit of connect/10.0:
commit 02d8c21380f
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Sat Oct 6 16:27:13 2018 +0200

    - Fix truncating error messages on first unrecognized latin1 character
      modified:   storage/connect/ha_connect.cc

    - Fix MDEV-17343
      Reject multi-table UPDATE/DELETE commands that crash on some systems
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/tabext.cpp

    - Try to fix failing tests (MariaDB version 10.0 only)
      modified:   storage/connect/mysql-test/connect/disabled.def

    - Typo
      modified:   storage/connect/global.h

commit f83caed8569
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Sep 25 15:49:26 2018 +0200

    - Try to fix failing tests (MariaDB version 10.0 only)
      modified:   storage/connect/mysql-test/connect/disabled.def
      modified:   storage/connect/mysql-test/connect/r/grant2.result
      modified:   storage/connect/mysql-test/connect/r/infoschema2-9739.result
      modified:   storage/connect/mysql-test/connect/r/mysql_exec.result

commit 9fd6f178846
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Sun Sep 23 19:45:59 2018 +0200

    - Implement the CHECK TABLE statement and accept REPAIR and ANALYZE
      modified:   storage/connect/connect.cc
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/ha_connect.h
      modified:   storage/connect/tabjdbc.cpp
      modified:   storage/connect/tabmysql.cpp
      modified:   storage/connect/tabodbc.cpp

    - MDEV-17212: Test if NumResultCols is implemented by the data source
      modified:   storage/connect/odbconn.cpp

    - Change error type in Optimize
      modified:   storage/connect/ha_connect.cc

    - Update version date
      modified:   storage/connect/ha_connect.cc

    - Record new result from odbc_postgresql.test
      modified:   storage/connect/mysql-test/connect/r/odbc_postgresql.result

commit d8cf51319e1
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Wed Aug 8 12:18:52 2018 +0200

    - Comment out failing Cyrillic test in xml2.test
      modified:   storage/connect/mysql-test/connect/r/xml2.result
      modified:   storage/connect/mysql-test/connect/t/xml2.test

commit 9df49e21f9e
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Tue Aug 7 15:01:06 2018 +0200

    - Fix MDEV-16672 Connect: Warnings with 10.0
      filamtxt.cpp: DOSFAM::RenameTempFile: Change sprintf to snprintf.
      filamvct.cpp: VECFAM::RenameTempFile: Change sprintf to snprintf.
      javaconn.cpp:
        Add JAVAConn::GetUTFString function.
        Use it instead of env->GetStringUTFChars.
        Fix wrong identation.
      javaconn.h: Add GetUTFString declaration.
      jdbconn.cpp:
        Use GetUTFString function instead of env->GetStringUTFChars.
      jmgoconn.cpp:
        Use GetUTFString function instead of env->GetStringUTFChars.
        Fix wrong identation.
      jsonudf.cpp: change 139 to BMX line 4631.
      tabjmg.cpp:
        Add ReleaseStringUTF.
        Fix wrong identation.
      tabpivot.cpp: Fix wrong identation.
      tabutil.cpp: TDBPRX::GetSubTable: Change sprintf to snprintf.
      modified:   storage/connect/filamtxt.cpp
      modified:   storage/connect/filamvct.cpp
      modified:   storage/connect/javaconn.cpp
      modified:   storage/connect/javaconn.h
      modified:   storage/connect/jdbconn.cpp
      modified:   storage/connect/jmgoconn.cpp
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/tabjmg.cpp
      modified:   storage/connect/tabpivot.cpp
      modified:   storage/connect/tabutil.cpp

    - Fix MDEV-16895 CONNECT engine's get_error_message can cause buffer
                     overflow and server crash with long queries
      ha_connect_cc: Update version.
        get_error_message: Remove charset conversion.
      modified:   storage/connect/ha_connect.cc

    - Fix a server crash on inserting bigint to a JDBC table
      JDBConn::SetUUID:
        Suppress check on ctyp that causes a server crash because ctyp
        can be negative and this triggers an DEBUG_ASSERT on return.
      modified:   storage/connect/jdbconn.cpp

    - Delete an assert(qrp) from JCATPARM *AllocCatInfo that is called with
      qrp=NULL from JDBConn::SetUUID. Also delete a clone of this function
      that was duplicated in javaconn.cpp.
      modified:   storage/connect/javaconn.cpp
      modified:   storage/connect/jdbconn.cpp

    - Update some disabled tests and results to avoid failure
      modified:   storage/connect/mysql-test/connect/r/jdbc.result
      modified:   storage/connect/mysql-test/connect/r/json_java_2.result
      modified:   storage/connect/mysql-test/connect/r/json_java_3.result
      modified:   storage/connect/mysql-test/connect/r/mongo_java_2.result
      modified:   storage/connect/mysql-test/connect/r/mongo_java_3.result
      modified:   storage/connect/mysql-test/connect/t/json_java_2.test
      modified:   storage/connect/mysql-test/connect/t/json_java_3.test
      modified:   storage/connect/mysql-test/connect/t/mongo_java_2.test
      modified:   storage/connect/mysql-test/connect/t/mongo_java_3.test

commit 415273eb193
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Thu Jun 28 19:37:49 2018 +0200

    - Fix MDEV-16167 Cannot insert unsigned values into a VEC table
      modified:   storage/connect/filamvct.cpp
      modified:   storage/connect/tabvct.cpp

commit 9ffcb68a9f2
Author: Olivier Bertrand <bertrandop@gmail.com>
Date:   Mon May 7 22:43:43 2018 +0200

    - Fix MDEV-15735 CONNECT [filamtxt.cpp:429]: Suspicious condition
      modified:   storage/connect/filamtxt.cpp

    - Fix compiler warnings
      modified:   storage/connect/domdoc.cpp
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/json.h
      modified:   storage/connect/jsonudf.cpp
      modified:   storage/connect/tabext.cpp
      modified:   storage/connect/tabjson.cpp
      modified:   storage/connect/tabjson.h

    - Miscelleanous from 10.3
      modified:   storage/connect/ha_connect.cc
      modified:   storage/connect/mycat.cc
      modified:   storage/connect/user_connect.cc
2018-10-28 10:41:31 +01:00

816 lines
22 KiB
C++

/************ 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);
bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG 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_Fetch = 0;
m_Ncol = 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("C:/Program Files/MariaDB 10.1/lib/plugin/JavaWrappers.jar");
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;
PFIL filp = tdbp->GetFilter();
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(1))
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 (filp) {
s->Append(",{\"$match\":");
if (MakeSelector(g, filp, 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(33))
htrc("New Pipeline: %s\n", p);
return AggregateCollection(p);
} else {
if (filter || filp) {
if (trace(1)) {
if (filter)
htrc("Filter: %s\n", filter);
if (filp) {
char buf[512];
filp->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 (filp) {
if (filter)
s->Append(',');
if (MakeSelector(g, filp, s)) {
strcpy(g->Message, "Failed making selector");
return NULL;
} // endif Selector
tdbp->SetFilter(NULL); // Not needed anymore
} // endif To_Filter
if (trace(33))
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(1))
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_Ncol = (int)rc;
rc = MY_MIN(rc, 1);
m_Rows += rc;
} else
sprintf(g->Message, "Fetch: %s", Msg);
//} // endif pos
return 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)GetUTFString(jdc);
} // 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 RC_OK;
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 RC_OK;
env->DeleteLocalRef(jkey);
jlong ar = env->CallLongMethod(job, updateid, upd);
if (trace(1))
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(1))
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)GetUTFString(fn);
} // endif objfldid
return fld;
} // end of GetColumnValue