1 /************ JMgoConn C++ Functions Source Code File (.CPP) ***********/
2 /* Name: JMgoConn.CPP Version 1.2 */
3 /* */
4 /* (C) Copyright to the author Olivier BERTRAND 2017 - 2021 */
5 /* */
6 /* This file contains the MongoDB Java connection classes functions. */
7 /***********************************************************************/
8
9 /***********************************************************************/
10 /* Include relevant MariaDB header file. */
11 /***********************************************************************/
12 #include <my_global.h>
13
14 /***********************************************************************/
15 /* Required objects includes. */
16 /***********************************************************************/
17 #include "global.h"
18 #include "plgdbsem.h"
19 #include "colblk.h"
20 #include "xobject.h"
21 #include "xtable.h"
22 #include "filter.h"
23 #include "jmgoconn.h"
24
25 #define nullptr 0
26
27 bool IsArray(PSZ s);
28 bool MakeSelector(PGLOBAL g, PFIL fp, PSTRG s);
29
30 /* --------------------------- Class JNCOL --------------------------- */
31
32 /***********************************************************************/
33 /* Add a column in the column list. */
34 /***********************************************************************/
AddCol(PGLOBAL g,PCOL colp,PSZ jp)35 void JNCOL::AddCol(PGLOBAL g, PCOL colp, PSZ jp)
36 {
37 char *p;
38 PJKC kp, kcp;
39
40 if ((p = strchr(jp, '.'))) {
41 PJNCOL icp;
42
43 *p++ = 0;
44
45 for (kp = Klist; kp; kp = kp->Next)
46 if (kp->Jncolp && ((kp->Key && !strcmp(jp, kp->Key))
47 || (!kp->Key && IsArray(jp) && kp->N == atoi(jp))))
48 break;
49
50 if (!kp) {
51 icp = new(g) JNCOL();
52 kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
53 kcp->Next = NULL;
54 kcp->Jncolp = icp;
55 kcp->Colp = NULL;
56 kcp->Array = IsArray(jp);
57
58 if (kcp->Array) {
59 kcp->Key = NULL;
60 kcp->N = atoi(jp);
61 } else {
62 kcp->Key = PlugDup(g, jp);
63 kcp->N = 0;
64 } // endif Array
65
66 if (Klist) {
67 for (kp = Klist; kp->Next; kp = kp->Next);
68
69 kp->Next = kcp;
70 } else
71 Klist = kcp;
72
73 } else
74 icp = kp->Jncolp;
75
76 *(p - 1) = '.';
77 icp->AddCol(g, colp, p);
78 } else {
79 kcp = (PJKC)PlugSubAlloc(g, NULL, sizeof(JKCOL));
80 kcp->Next = NULL;
81 kcp->Jncolp = NULL;
82 kcp->Colp = colp;
83 kcp->Array = IsArray(jp);
84
85 if (kcp->Array) {
86 kcp->Key = NULL;
87 kcp->N = atoi(jp);
88 } else {
89 kcp->Key = jp;
90 kcp->N = 0;
91 } // endif Array
92
93 if (Klist) {
94 for (kp = Klist; kp->Next; kp = kp->Next);
95
96 kp->Next = kcp;
97 } else
98 Klist = kcp;
99
100 } // endif jp
101
102 } // end of AddCol
103
104 /***********************************************************************/
105 /* JMgoConn construction/destruction. */
106 /***********************************************************************/
JMgoConn(PGLOBAL g,PCSZ collname,PCSZ wrapper)107 JMgoConn::JMgoConn(PGLOBAL g, PCSZ collname, PCSZ wrapper)
108 : JAVAConn(g, wrapper)
109 {
110 CollName = collname;
111 readid = fetchid = getdocid = objfldid = fcollid = acollid =
112 mkdocid = docaddid = mkarid = araddid = insertid = updateid =
113 deleteid = gcollid = countid = rewindid = mkbsonid = nullptr;
114 DiscFunc = "MongoDisconnect";
115 Fpc = NULL;
116 m_Fetch = 0;
117 m_Ncol = 0;
118 m_Version = 0;
119 } // end of JMgoConn
120
121 /***********************************************************************/
122 /* AddJars: add some jar file to the Class path. */
123 /***********************************************************************/
AddJars(PSTRG jpop,char sep)124 void JMgoConn::AddJars(PSTRG jpop, char sep)
125 {
126 #if defined(DEVELOPMENT)
127 if (m_Version == 2) {
128 jpop->Append(sep);
129 // jpop->Append("C:/Eclipse/workspace/MongoWrap2/bin");
130 // jpop->Append(sep);
131 jpop->Append("C:/mongo-java-driver/mongo-java-driver-2.13.3.jar");
132 } else {
133 jpop->Append(sep);
134 // jpop->Append("C:/Eclipse/workspace/MongoWrap3/bin");
135 // jpop->Append(sep);
136 // jpop->Append("C:/Program Files/MariaDB 10.1/lib/plugin/JavaWrappers.jar");
137 // jpop->Append(sep);
138 jpop->Append("C:/mongo-java-driver/mongo-java-driver-3.4.2.jar");
139 } // endif m_Version
140 #endif // DEVELOPMENT
141 } // end of AddJars
142
143 /***********************************************************************/
144 /* Connect: connect to a data source. */
145 /***********************************************************************/
Connect(PJPARM sop)146 bool JMgoConn::Connect(PJPARM sop)
147 {
148 bool err = false;
149 jint rc;
150 jboolean brc;
151 jstring cln;
152 PGLOBAL& g = m_G;
153
154 m_Version = sop->Version;
155
156 /*******************************************************************/
157 /* Create or attach a JVM. */
158 /*******************************************************************/
159 if (Open(g))
160 return true;
161
162 /*******************************************************************/
163 /* Connect to MongoDB. */
164 /*******************************************************************/
165 jmethodID cid = nullptr;
166
167 if (gmID(g, cid, "MongoConnect", "([Ljava/lang/String;)I"))
168 return true;
169
170 // Build the java string array
171 jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
172 env->FindClass("java/lang/String"), NULL); // Strings
173
174 //m_Scrollable = sop->Scrollable;
175 //m_RowsetSize = sop->Fsize;
176
177 // change some elements
178 if (sop->Driver)
179 env->SetObjectArrayElement(parms, 0, env->NewStringUTF(sop->Url));
180
181 if (sop->Url)
182 env->SetObjectArrayElement(parms, 1, env->NewStringUTF(sop->Driver));
183
184 if (sop->User)
185 env->SetObjectArrayElement(parms, 2, env->NewStringUTF(sop->User));
186
187 if (sop->Pwd)
188 env->SetObjectArrayElement(parms, 3, env->NewStringUTF(sop->Pwd));
189
190 // call method
191 rc = env->CallIntMethod(job, cid, parms);
192 err = Check(rc);
193 env->DeleteLocalRef(parms); // Not used anymore
194
195 if (err) {
196 sprintf(g->Message, "Connecting: %s rc=%d", Msg, (int)rc);
197 return true;
198 } // endif Msg
199
200 /*********************************************************************/
201 /* Get the collection. */
202 /*********************************************************************/
203 if (gmID(g, gcollid, "GetCollection", "(Ljava/lang/String;)Z"))
204 return true;
205
206 cln = env->NewStringUTF(CollName);
207 brc = env->CallBooleanMethod(job, gcollid, cln);
208 env->DeleteLocalRef(cln);
209
210 if (Check(brc ? -1 : 0)) {
211 sprintf(g->Message, "GetCollection: %s", Msg);
212 return true;
213 } // endif Msg
214
215 m_Connected = true;
216 return false;
217 } // end of Connect
218
219 /***********************************************************************/
220 /* CollSize: returns the number of documents in the collection. */
221 /***********************************************************************/
CollSize(PGLOBAL g)222 int JMgoConn::CollSize(PGLOBAL g)
223 {
224 if (!gmID(g, countid, "GetCollSize", "()J")) {
225 jlong card = env->CallLongMethod(job, countid);
226
227 return (int)card;
228 } else
229 return 2; // Make MariaDB happy
230
231 } // end of CollSize
232
233 /***********************************************************************/
234 /* OpenDB: Data Base open routine for MONGO access method. */
235 /***********************************************************************/
MakeCursor(PGLOBAL g,PTDB tdbp,PCSZ options,PCSZ filter,bool pipe)236 bool JMgoConn::MakeCursor(PGLOBAL g, PTDB tdbp, PCSZ options,
237 PCSZ filter, bool pipe)
238 {
239 const char *p;
240 bool id, b = false, all = false;
241 uint len;
242 PCOL cp;
243 PSZ jp;
244 PCSZ op = NULL, sf = NULL, Options = options;
245 PSTRG s = NULL;
246 PFIL filp = tdbp->GetFilter();
247
248 if (Options && !stricmp(Options, "all")) {
249 Options = NULL;
250 all = true;
251 } else
252 id = (tdbp->GetMode() == MODE_UPDATE || tdbp->GetMode() == MODE_DELETE);
253
254 for (cp = tdbp->GetColumns(); cp && !all; cp = cp->GetNext())
255 if (cp->GetFmt() && !strcmp(cp->GetFmt(), "*") && (!Options || pipe))
256 all = true;
257 else if (!id)
258 id = !strcmp(cp->GetJpath(g, false), "_id");
259
260 if (pipe && Options) {
261 if (trace(1))
262 htrc("Pipeline: %s\n", Options);
263
264 p = strrchr(Options, ']');
265
266 if (!p) {
267 strcpy(g->Message, "Missing ] in pipeline");
268 return true;
269 } else
270 *(char*)p = 0;
271
272 s = new(g) STRING(g, 1023, (PSZ)Options);
273
274 if (filp) {
275 s->Append(",{\"$match\":");
276
277 if (MakeSelector(g, filp, s)) {
278 strcpy(g->Message, "Failed making selector");
279 return true;
280 } else
281 s->Append('}');
282
283 tdbp->SetFilter(NULL); // Not needed anymore
284 } // endif To_Filter
285
286 if (!all && tdbp->GetColumns()) {
287 // Project list
288 len = s->GetLength();
289 s->Append(",{\"$project\":{\"");
290
291 if (!id)
292 s->Append("_id\":0,\"");
293
294 for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
295 if (b)
296 s->Append(",\"");
297 else
298 b = true;
299
300 if ((jp = cp->GetJpath(g, true)))
301 s->Append(jp);
302 else {
303 s->Truncate(len);
304 goto nop;
305 } // endif Jpath
306
307 s->Append("\":1");
308 } // endfor cp
309
310 s->Append("}}");
311 } // endif all
312
313 nop:
314 s->Append("]}");
315 s->Resize(s->GetLength() + 1);
316 *(char*)p = ']'; // Restore Colist for discovery
317 p = s->GetStr();
318
319 if (trace(33))
320 htrc("New Pipeline: %s\n", p);
321
322 return AggregateCollection(p);
323 } else {
324 if (filter || filp) {
325 if (trace(1)) {
326 if (filter)
327 htrc("Filter: %s\n", filter);
328
329 if (filp) {
330 char buf[512];
331
332 filp->Prints(g, buf, 511);
333 htrc("To_Filter: %s\n", buf);
334 } // endif To_Filter
335
336 } // endif trace
337
338 s = new(g) STRING(g, 1023, (PSZ)filter);
339 len = s->GetLength();
340
341 if (filp) {
342 if (filter)
343 s->Append(',');
344
345 if (MakeSelector(g, filp, s)) {
346 strcpy(g->Message, "Failed making selector");
347 return true;
348 } // endif Selector
349
350 tdbp->SetFilter(NULL); // Not needed anymore
351 } // endif To_Filter
352
353 if (trace(33))
354 htrc("selector: %s\n", s->GetStr());
355
356 s->Resize(s->GetLength() + 1);
357 sf = PlugDup(g, s->GetStr());
358 } // endif Filter
359
360 if (!all) {
361 if (Options && *Options) {
362 if (trace(1))
363 htrc("options=%s\n", Options);
364
365 op = Options;
366 } else if (tdbp->GetColumns()) {
367 // Projection list
368 if (s)
369 s->Set("{\"");
370 else
371 s = new(g) STRING(g, 511, "{\"");
372
373 if (!id)
374 s->Append("_id\":0,\"");
375
376 for (PCOL cp = tdbp->GetColumns(); cp; cp = cp->GetNext()) {
377 if (b)
378 s->Append(",\"");
379 else
380 b = true;
381
382 if ((jp = cp->GetJpath(g, true)))
383 s->Append(jp);
384 else {
385 // Can this happen?
386 htrc("Fail getting projection path of %s\n", cp->GetName());
387 goto nope;
388 } // endif Jpath
389
390 s->Append("\":1");
391 } // endfor cp
392
393 s->Append("}");
394 s->Resize(s->GetLength() + 1);
395 op = s->GetStr();
396 } else {
397 // count(*) ?
398 op = "{\"_id\":1}";
399 } // endif Options
400
401 } // endif all
402
403 nope:
404 return FindCollection(sf, op);
405 } // endif Pipe
406
407 } // end of MakeCursor
408
409 /***********************************************************************/
410 /* Find a collection and make cursor. */
411 /***********************************************************************/
FindCollection(PCSZ query,PCSZ proj)412 bool JMgoConn::FindCollection(PCSZ query, PCSZ proj)
413 {
414 bool rc = true;
415 jboolean brc;
416 jstring qry = nullptr, prj = nullptr;
417 PGLOBAL& g = m_G;
418
419 // Get the methods used to execute a query and get the result
420 if (!gmID(g, fcollid, "FindColl", "(Ljava/lang/String;Ljava/lang/String;)Z")) {
421 if (query)
422 qry = env->NewStringUTF(query);
423
424 if (proj)
425 prj = env->NewStringUTF(proj);
426
427 brc = env->CallBooleanMethod(job, fcollid, qry, prj);
428
429 if (!Check(brc ? -1 : 0)) {
430 rc = false;
431 } else
432 sprintf(g->Message, "FindColl: %s", Msg);
433
434 if (query)
435 env->DeleteLocalRef(qry);
436
437 if (proj)
438 env->DeleteLocalRef(prj);
439
440 } // endif xqid
441
442 return rc;
443 } // end of FindCollection
444
445 /***********************************************************************/
446 /* Find a collection and make cursor. */
447 /***********************************************************************/
AggregateCollection(PCSZ pipeline)448 bool JMgoConn::AggregateCollection(PCSZ pipeline)
449 {
450 bool rc = true;
451 jboolean brc;
452 jstring pip = nullptr;
453 PGLOBAL& g = m_G;
454
455 // Get the methods used to execute a query and get the result
456 if (!gmID(g, acollid, "AggregateColl", "(Ljava/lang/String;)Z")) {
457 pip = env->NewStringUTF(pipeline);
458
459 brc = env->CallBooleanMethod(job, acollid, pip);
460
461 if (!Check(brc ? -1 : 0)) {
462 rc = false;
463 } else
464 sprintf(g->Message, "AggregateColl: %s", Msg);
465
466 env->DeleteLocalRef(pip);
467 } // endif acollid
468
469 return rc;
470 } // end of AggregateCollection
471
472 /***********************************************************************/
473 /* Fetch next row. */
474 /***********************************************************************/
Fetch(int pos)475 int JMgoConn::Fetch(int pos)
476 {
477 jint rc = JNI_ERR;
478 PGLOBAL& g = m_G;
479
480 //if (m_Full) // Result set has one row
481 // return 1;
482
483 //if (pos) {
484 // if (!m_Scrollable) {
485 // strcpy(g->Message, "Cannot fetch(pos) if FORWARD ONLY");
486 // return rc;
487 // } else if (gmID(m_G, fetchid, "Fetch", "(I)Z"))
488 // return rc;
489
490 // if (env->CallBooleanMethod(job, fetchid, pos))
491 // rc = m_Rows;
492
493 //} else {
494 if (gmID(g, readid, "ReadNext", "()I"))
495 return (int)rc;
496
497 rc = env->CallIntMethod(job, readid);
498
499 if (!Check(rc)) {
500 //if (rc == 0)
501 // m_Full = (m_Fetch == 1);
502 //else
503 // m_Fetch++;
504
505 m_Ncol = (int)rc;
506 rc = MY_MIN(rc, 1);
507 m_Rows += rc;
508 } else
509 sprintf(g->Message, "Fetch: %s", Msg);
510
511 //} // endif pos
512
513 return rc;
514 } // end of Fetch
515
516 /***********************************************************************/
517 /* Get the Json string of the current document. */
518 /***********************************************************************/
GetDocument(void)519 PSZ JMgoConn::GetDocument(void)
520 {
521 PGLOBAL& g = m_G;
522 PSZ doc = NULL;
523 jstring jdc;
524
525 if (!gmID(g, getdocid, "GetDoc", "()Ljava/lang/String;")) {
526 jdc = (jstring)env->CallObjectMethod(job, getdocid);
527
528 if (jdc)
529 doc = (PSZ)GetUTFString(jdc);
530
531 } // endif getdocid
532
533 return doc;
534 } // end of GetDocument
535
536 /***********************************************************************/
537 /* Group columns for inserting or updating. */
538 /***********************************************************************/
MakeColumnGroups(PGLOBAL g,PTDB tdbp)539 void JMgoConn::MakeColumnGroups(PGLOBAL g, PTDB tdbp)
540 {
541 Fpc = new(g) JNCOL();
542
543 for (PCOL colp = tdbp->GetColumns(); colp; colp = colp->GetNext())
544 if (!colp->IsSpecial())
545 Fpc->AddCol(g, colp, colp->GetJpath(g, false));
546
547 } // end of MakeColumnGroups
548
549 /***********************************************************************/
550 /* Get additional method ID. */
551 /***********************************************************************/
GetMethodId(PGLOBAL g,MODE mode)552 bool JMgoConn::GetMethodId(PGLOBAL g, MODE mode)
553 {
554 if (mode == MODE_UPDATE) {
555 if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
556 return true;
557
558 if (gmID(g, docaddid, "DocAdd",
559 "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;I)Z"))
560 return true;
561
562 if (gmID(g, updateid, "CollUpdate", "(Ljava/lang/Object;)J"))
563 return true;
564
565 } else if (mode == MODE_INSERT) {
566 if (gmID(g, mkdocid, "MakeDocument", "()Ljava/lang/Object;"))
567 return true;
568
569 if (gmID(g, mkbsonid, "MakeBson",
570 "(Ljava/lang/String;I)Ljava/lang/Object;"))
571 return true;
572
573 if (gmID(g, docaddid, "DocAdd",
574 "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;I)Z"))
575 return true;
576
577 if (gmID(g, mkarid, "MakeArray", "()Ljava/lang/Object;"))
578 return true;
579
580 if (gmID(g, araddid, "ArrayAdd",
581 "(Ljava/lang/Object;ILjava/lang/Object;I)Z"))
582 return true;
583
584 if (gmID(g, insertid, "CollInsert", "(Ljava/lang/Object;)Z"))
585 return true;
586
587 } else if (mode == MODE_DELETE)
588 if (gmID(g, deleteid, "CollDelete", "(Z)J"))
589 return true;
590
591 return gmID(g, rewindid, "Rewind", "()Z");
592 } // end of GetMethodId
593
594 /***********************************************************************/
595 /* MakeObject. */
596 /***********************************************************************/
MakeObject(PGLOBAL g,PCOL colp,bool & error)597 jobject JMgoConn::MakeObject(PGLOBAL g, PCOL colp, bool&error )
598 {
599 jclass cls;
600 jmethodID cns = nullptr; // Constructor
601 jobject val = nullptr;
602 PVAL valp = colp->GetValue();
603
604 error = false;
605
606 if (valp->IsNull())
607 return NULL;
608
609 try {
610 switch (valp->GetType()) {
611 case TYPE_STRING:
612 val = env->NewStringUTF(valp->GetCharValue());
613 break;
614 case TYPE_INT:
615 case TYPE_SHORT:
616 cls = env->FindClass("java/lang/Integer");
617 cns = env->GetMethodID(cls, "<init>", "(I)V");
618 val = env->NewObject(cls, cns, valp->GetIntValue());
619 break;
620 case TYPE_TINY:
621 cls = env->FindClass("java/lang/Boolean");
622 cns = env->GetMethodID(cls, "<init>", "(Z)V");
623 val = env->NewObject(cls, cns, (valp->GetIntValue() != 0));
624 break;
625 case TYPE_BIGINT:
626 cls = env->FindClass("java/lang/Long");
627 cns = env->GetMethodID(cls, "<init>", "(J)V");
628 val = env->NewObject(cls, cns, valp->GetBigintValue());
629 break;
630 case TYPE_DOUBLE:
631 cls = env->FindClass("java/lang/Double");
632 cns = env->GetMethodID(cls, "<init>", "(D)V");
633 val = env->NewObject(cls, cns, valp->GetFloatValue());
634 break;
635 default:
636 sprintf(g->Message, "Cannot make object from %d type", valp->GetType());
637 error = true;
638 break;
639 } // endswitch Type
640
641 } catch (...) {
642 sprintf(g->Message, "Cannot make object from %s value", colp->GetName());
643 error = true;
644 } // end try/catch
645
646 return val;
647 } // end of MakeObject
648
649 /***********************************************************************/
650 /* Stringify. */
651 /***********************************************************************/
Stringify(PCOL colp)652 bool JMgoConn::Stringify(PCOL colp)
653 {
654 bool b = false;
655
656 if (colp)
657 b = (colp->Stringify() && colp->GetResultType() == TYPE_STRING);
658
659 return b;
660 } // end of Stringify
661
662 /***********************************************************************/
663 /* MakeDoc. */
664 /***********************************************************************/
MakeDoc(PGLOBAL g,PJNCOL jcp)665 jobject JMgoConn::MakeDoc(PGLOBAL g, PJNCOL jcp)
666 {
667 int j;
668 bool b, error = false;
669 jobject parent, child, val;
670 jstring jkey;
671 PJKC kp = jcp->Klist;
672
673 if (kp->Array)
674 parent = env->CallObjectMethod(job, mkarid);
675 else
676 parent = env->CallObjectMethod(job, mkdocid);
677
678 for (j = 0; kp; j = 0, kp = kp->Next) {
679 if (Stringify(kp->Colp)) {
680 switch (*kp->Colp->GetCharValue()) {
681 case '{': j = 1; break;
682 case '[': j = 2; break;
683 default: break;
684 } // endswitch
685
686 b = (!kp->Key || !*kp->Key || *kp->Key == '*');
687 } else
688 b = false;
689
690 if (kp->Jncolp) {
691 if (!(child = MakeDoc(g, kp->Jncolp)))
692 return NULL;
693
694 if (!kp->Array) {
695 jkey = env->NewStringUTF(kp->Key);
696
697 if (env->CallBooleanMethod(job, docaddid, parent, jkey, child, j))
698 return NULL;
699
700 env->DeleteLocalRef(jkey);
701 } else
702 if (env->CallBooleanMethod(job, araddid, parent, kp->N, child, j))
703 return NULL;
704
705 env->DeleteLocalRef(child);
706 } else {
707 if (!(val = MakeObject(g, kp->Colp, error))) {
708 if (error)
709 return NULL;
710
711 } else if (!kp->Array) {
712 if (!b) {
713 jkey = env->NewStringUTF(kp->Key);
714
715 if (env->CallBooleanMethod(job, docaddid, parent, jkey, val, j))
716 return NULL;
717
718 env->DeleteLocalRef(jkey);
719 } else {
720 env->DeleteLocalRef(parent);
721 parent = env->CallObjectMethod(job, mkbsonid, val, j);
722 } // endif b
723
724 } else if (env->CallBooleanMethod(job, araddid, parent, kp->N, val, j)) {
725 if (Check(-1))
726 sprintf(g->Message, "ArrayAdd: %s", Msg);
727 else
728 sprintf(g->Message, "ArrayAdd: unknown error");
729
730 return NULL;
731 } // endif ArrayAdd
732
733 env->DeleteLocalRef(val);
734 } // endif Jncolp
735
736 } // endfor kp
737
738 return parent;
739 } // end of MakeDoc
740
741 /***********************************************************************/
742 /* Insert a new document in the collation. */
743 /***********************************************************************/
DocWrite(PGLOBAL g,PCSZ line)744 int JMgoConn::DocWrite(PGLOBAL g, PCSZ line)
745 {
746 int rc = RC_OK;
747 jobject doc = nullptr;
748
749 if (line) {
750 int j;
751 jobject val = env->NewStringUTF(line);
752
753 switch (*line) {
754 case '{': j = 1; break;
755 case '[': j = 2; break;
756 default: j = 0; break;
757 } // endswitch line
758
759 doc = env->CallObjectMethod(job, mkbsonid, val, j);
760 env->DeleteLocalRef(val);
761 } else if (Fpc)
762 doc = MakeDoc(g, Fpc);
763
764 if (!doc)
765 return RC_FX;
766
767 if (env->CallBooleanMethod(job, insertid, doc)) {
768 if (Check(-1))
769 sprintf(g->Message, "CollInsert: %s", Msg);
770 else
771 sprintf(g->Message, "CollInsert: unknown error");
772
773 rc = RC_FX;
774 } // endif Insert
775
776 env->DeleteLocalRef(doc);
777 return rc;
778 } // end of DocWrite
779
780 /***********************************************************************/
781 /* Update the current document from the collection. */
782 /***********************************************************************/
DocUpdate(PGLOBAL g,PTDB tdbp)783 int JMgoConn::DocUpdate(PGLOBAL g, PTDB tdbp)
784 {
785 int j = 0, rc = RC_OK;
786 bool error;
787 PCOL colp;
788 jstring jkey;
789 jobject val, upd, updlist = env->CallObjectMethod(job, mkdocid);
790
791 // Make the list of changes to do
792 for (colp = tdbp->GetSetCols(); colp; colp = colp->GetNext()) {
793 jkey = env->NewStringUTF(colp->GetJpath(g, false));
794 val = MakeObject(g, colp, error);
795
796 if (error)
797 return RC_FX;
798 else if (Stringify(colp))
799 switch (*colp->GetCharValue()) {
800 case '{': j = 1; break;
801 case '[': j = 2; break;
802 default: break;
803 } // endswitch
804
805 if (env->CallBooleanMethod(job, docaddid, updlist, jkey, val, j))
806 return RC_OK;
807
808 env->DeleteLocalRef(jkey);
809 } // endfor colp
810
811 // Make the update parameter
812 upd = env->CallObjectMethod(job, mkdocid);
813 jkey = env->NewStringUTF("$set");
814
815 if (env->CallBooleanMethod(job, docaddid, upd, jkey, updlist, 0))
816 return RC_OK;
817
818 env->DeleteLocalRef(jkey);
819
820 jlong ar = env->CallLongMethod(job, updateid, upd);
821
822 if (trace(1))
823 htrc("DocUpdate: ar = %ld\n", ar);
824
825 if (Check((int)ar)) {
826 sprintf(g->Message, "CollUpdate: %s", Msg);
827 rc = RC_FX;
828 } // endif ar
829
830 return rc;
831 } // end of DocUpdate
832
833 /***********************************************************************/
834 /* Remove all or only the current document from the collection. */
835 /***********************************************************************/
DocDelete(PGLOBAL g,bool all)836 int JMgoConn::DocDelete(PGLOBAL g, bool all)
837 {
838 int rc = RC_OK;
839 jlong ar = env->CallLongMethod(job, deleteid, all);
840
841 if (trace(1))
842 htrc("DocDelete: ar = %ld\n", ar);
843
844 if (Check((int)ar)) {
845 sprintf(g->Message, "CollDelete: %s", Msg);
846 rc = RC_FX;
847 } // endif ar
848
849 return rc;
850 } // end of DocDelete
851
852 /***********************************************************************/
853 /* Rewind the collection. */
854 /***********************************************************************/
Rewind(void)855 bool JMgoConn::Rewind(void)
856 {
857 return env->CallBooleanMethod(job, rewindid);
858 } // end of Rewind
859
860 /***********************************************************************/
861 /* Retrieve the column string value from the document. */
862 /***********************************************************************/
GetColumnValue(PSZ path)863 PSZ JMgoConn::GetColumnValue(PSZ path)
864 {
865 PGLOBAL& g = m_G;
866 PSZ fld = NULL;
867 jstring fn, jn = nullptr;
868
869 if (!path || (jn = env->NewStringUTF(path)) == nullptr) {
870 sprintf(g->Message, "Fail to allocate jstring %s", SVP(path));
871 throw (int)TYPE_AM_MGO;
872 } // endif name
873
874 if (!gmID(g, objfldid, "GetField", "(Ljava/lang/String;)Ljava/lang/String;")) {
875 fn = (jstring)env->CallObjectMethod(job, objfldid, jn);
876
877 if (fn)
878 fld = (PSZ)GetUTFString(fn);
879
880 } // endif objfldid
881
882 return fld;
883 } // end of GetColumnValue
884