mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
e4797a991f
In addition to files and Mongo collections, JSON as well as XML and CSV data can be retrieved from the net as answers from REST queries. Because it uses and external package (cpprestsdk) this is currently available only to MariaDB servers compiled from source. -- Add the REST support when Microsoft Casablanca package (cpprestsdk) is installed. -- Also include some changes specific to MariaDB 10.3. modified: storage/connect/CMakeLists.txt -- Add conditional REST support -- Added string options HTTP and URI. -- Added added internal table type TAB_REST. modified: storage/connect/ha_connect.cc modified: storage/connect/mycat.cc modified: storage/connect/mycat.h modified: storage/connect/plgdbsem.h -- Fix MDEV-19648 Variable connect_conv_size doesn't change -- Change Variable wrong block parameter from 8169 to 1. -- Also change connect_conv_size default value to 1024. modified: storage/connect/ha_connect.cc -- Avoid possible buffer overflow -- In particular by the function ShowValue. modified: storage/connect/tabdos.cpp modified: storage/connect/tabfmt.cpp modified: storage/connect/value.cpp modified: storage/connect/value.h -- Add some cast to avoid some compiler warnings modified: storage/connect/filamdbf.cpp -- Fix some C++ error modified: storage/connect/javaconn.cpp modified: storage/connect/jmgoconn.cpp modified: storage/connect/plugutil.cpp -- Miscellaneous Typo and warning suppressing changes modified: storage/connect/connect.cpp modified: storage/connect/connect.h modified: storage/connect/filamvct.cpp modified: storage/connect/inihandl.cpp modified: storage/connect/jsonudf.cpp modified: storage/connect/libdoc.cpp modified: storage/connect/tabjson.cpp modified: storage/connect/tabtbl.cpp modified: storage/connect/tabxml.cpp modified: storage/connect/user_connect.cc modified: storage/connect/user_connect.h -- Update failing test results and disbling modified: storage/connect/mysql-test/connect/disabled.def modified: storage/connect/mysql-test/connect/r/dir.result modified: storage/connect/mysql-test/connect/r/grant.result modified: storage/connect/mysql-test/connect/r/jdbc.result modified: storage/connect/mysql-test/connect/r/jdbc_postgresql.result modified: storage/connect/mysql-test/connect/r/xml.result modified: storage/connect/mysql-test/connect/r/xml2.result modified: storage/connect/mysql-test/connect/r/xml2_mult.result modified: storage/connect/mysql-test/connect/r/xml_mult.result -- Add an option modified: storage/connect/mysql-test/connect/t/grant.test
815 lines
22 KiB
C++
815 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 true;
|
|
} 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 true;
|
|
} // 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
|