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