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 | |
27 | bool IsNum(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 | /***********************************************************************/ |
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 && !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 | /***********************************************************************/ |
105 | JMgoConn::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 | /***********************************************************************/ |
122 | void 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 | /***********************************************************************/ |
143 | bool 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 | /***********************************************************************/ |
219 | int 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 | /***********************************************************************/ |
233 | bool 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 | /***********************************************************************/ |
408 | bool 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 | /***********************************************************************/ |
444 | bool 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 | /***********************************************************************/ |
471 | int 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 | /***********************************************************************/ |
515 | PSZ 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 | /***********************************************************************/ |
535 | void 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 | /***********************************************************************/ |
548 | bool 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 | /***********************************************************************/ |
588 | jobject 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 | /***********************************************************************/ |
643 | jobject 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 | /***********************************************************************/ |
699 | int 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 | /***********************************************************************/ |
721 | int 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 | /***********************************************************************/ |
768 | int 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 | /***********************************************************************/ |
787 | bool 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 | /***********************************************************************/ |
795 | PSZ 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 | |