1/************ JMONGO FAM C++ Program Source Code File (.CPP) ***********/
2/* PROGRAM NAME: jmgfam.cpp */
3/* ------------- */
4/* Version 1.0 */
5/* */
6/* COPYRIGHT: */
7/* ---------- */
8/* (C) Copyright to the author Olivier BERTRAND 20017 */
9/* */
10/* WHAT THIS PROGRAM DOES: */
11/* ----------------------- */
12/* This program are the Java MongoDB access method classes. */
13/* */
14/***********************************************************************/
15
16/***********************************************************************/
17/* Include relevant sections of the System header files. */
18/***********************************************************************/
19#include "my_global.h"
20#if defined(__WIN__)
21//#include <io.h>
22//#include <fcntl.h>
23//#include <errno.h>
24#if defined(__BORLANDC__)
25#define __MFC_COMPAT__ // To define min/max as macro
26#endif // __BORLANDC__
27//#include <windows.h>
28#else // !__WIN__
29#if defined(UNIX) || defined(UNIV_LINUX)
30//#include <errno.h>
31#include <unistd.h>
32//#if !defined(sun) // Sun has the ftruncate fnc.
33//#define USETEMP // Force copy mode for DELETE
34//#endif // !sun
35#else // !UNIX
36//#include <io.h>
37#endif // !UNIX
38//#include <fcntl.h>
39#endif // !__WIN__
40
41/***********************************************************************/
42/* Include application header files: */
43/* global.h is header containing all global declarations. */
44/* plgdbsem.h is header containing the DB application declarations. */
45/* filamtxt.h is header containing the file AM classes declarations. */
46/***********************************************************************/
47#include "global.h"
48#include "plgdbsem.h"
49#include "reldef.h"
50#include "filamtxt.h"
51#include "tabdos.h"
52#include "tabjson.h"
53#include "jmgfam.h"
54
55#if defined(UNIX) || defined(UNIV_LINUX)
56#include "osutil.h"
57//#define _fileno fileno
58//#define _O_RDONLY O_RDONLY
59#endif
60
61/* --------------------------- Class JMGFAM -------------------------- */
62
63/***********************************************************************/
64/* Constructors. */
65/***********************************************************************/
66JMGFAM::JMGFAM(PJDEF tdp) : DOSFAM((PDOSDEF)NULL)
67{
68 Jcp = NULL;
69 //Client = NULL;
70 //Database = NULL;
71 //Collection = NULL;
72 //Cursor = NULL;
73 //Query = NULL;
74 //Opts = NULL;
75 Ops.Driver = tdp->Schema;
76 Ops.Url = tdp->Uri;
77 Ops.User = NULL;
78 Ops.Pwd = NULL;
79 Ops.Scrollable = false;
80 Ops.Fsize = 0;
81 Ops.Version = tdp->Version;
82 To_Fbt = NULL;
83 Mode = MODE_ANY;
84 Uristr = tdp->Uri;
85 Db_name = tdp->Schema;
86 Coll_name = tdp->Collname;
87 Options = tdp->Options;
88 Filter = tdp->Filter;
89 Wrapname = tdp->Wrapname;
90 Done = false;
91 Pipe = tdp->Pipe;
92 Version = tdp->Version;
93 Lrecl = tdp->Lrecl + tdp->Ending;
94 Curpos = 0;
95} // end of JMGFAM standard constructor
96
97JMGFAM::JMGFAM(PJMGFAM tdfp) : DOSFAM(tdfp)
98{
99 //Client = tdfp->Client;
100 //Database = NULL;
101 //Collection = tdfp->Collection;
102 //Cursor = tdfp->Cursor;
103 //Query = tdfp->Query;
104 //Opts = tdfp->Opts;
105 Ops = tdfp->Ops;
106 To_Fbt = tdfp->To_Fbt;
107 Mode = tdfp->Mode;
108 Uristr = tdfp->Uristr;
109 Db_name = tdfp->Db_name;
110 Coll_name = tdfp->Coll_name;
111 Options = tdfp->Options;
112 Filter = NULL;
113 Wrapname = tdfp->Wrapname;
114 Done = tdfp->Done;
115 Pipe = tdfp->Pipe;
116 Version = tdfp->Version;
117} // end of JMGFAM copy constructor
118
119/***********************************************************************/
120/* Reset: reset position values at the beginning of file. */
121/***********************************************************************/
122void JMGFAM::Reset(void)
123{
124 TXTFAM::Reset();
125 Fpos = Tpos = Spos = 0;
126} // end of Reset
127
128/***********************************************************************/
129/* MGO GetFileLength: returns file size in number of bytes. */
130/***********************************************************************/
131int JMGFAM::GetFileLength(PGLOBAL g)
132{
133 return 0;
134} // end of GetFileLength
135
136/***********************************************************************/
137/* Cardinality: returns table cardinality in number of rows. */
138/* This function can be called with a null argument to test the */
139/* availability of Cardinality implementation (1 yes, 0 no). */
140/***********************************************************************/
141int JMGFAM::Cardinality(PGLOBAL g)
142{
143 if (!g)
144 return 1;
145
146 return (!Init(g)) ? Jcp->CollSize(g) : 0;
147} // end of Cardinality
148
149/***********************************************************************/
150/* Note: This function is not really implemented yet. */
151/***********************************************************************/
152int JMGFAM::MaxBlkSize(PGLOBAL, int s)
153{
154 return s;
155} // end of MaxBlkSize
156
157/***********************************************************************/
158/* Init: initialize MongoDB processing. */
159/***********************************************************************/
160bool JMGFAM::Init(PGLOBAL g)
161{
162 if (Done)
163 return false;
164
165 /*********************************************************************/
166 /* Open an JDBC connection for this table. */
167 /* Note: this may not be the proper way to do. Perhaps it is better */
168 /* to test whether a connection is already open for this datasource */
169 /* and if so to allocate just a new result set. But this only for */
170 /* drivers allowing concurency in getting results ??? */
171 /*********************************************************************/
172 if (!Jcp)
173 Jcp = new(g) JMgoConn(g, Coll_name, Wrapname);
174 else if (Jcp->IsOpen())
175 Jcp->Close();
176
177 if (Jcp->Connect(&Ops))
178 return true;
179
180 Done = true;
181 return false;
182} // end of Init
183
184/***********************************************************************/
185/* OpenTableFile: Open a MongoDB table. */
186/***********************************************************************/
187bool JMGFAM::OpenTableFile(PGLOBAL g)
188{
189 Mode = Tdbp->GetMode();
190
191 if (Pipe && Mode != MODE_READ) {
192 strcpy(g->Message, "Pipeline tables are read only");
193 return true;
194 } // endif Pipe
195
196 if (Init(g))
197 return true;
198
199 if (Jcp->GetMethodId(g, Mode))
200 return true;
201
202 if (Mode == MODE_DELETE && !Tdbp->GetNext()) {
203 // Delete all documents
204 if (!Jcp->MakeCursor(g, Tdbp, "all", Filter, false))
205 if (Jcp->DocDelete(g, true) == RC_OK)
206 return false;
207
208 return true;
209 } // endif Mode
210
211 if (Mode == MODE_INSERT)
212 Jcp->MakeColumnGroups(g, Tdbp);
213
214 if (Mode != MODE_UPDATE)
215 return Jcp->MakeCursor(g, Tdbp, Options, Filter, Pipe);
216
217 return false;
218 } // end of OpenTableFile
219
220/***********************************************************************/
221/* GetRowID: return the RowID of last read record. */
222/***********************************************************************/
223int JMGFAM::GetRowID(void)
224{
225 return Rows;
226} // end of GetRowID
227
228/***********************************************************************/
229/* GetPos: return the position of last read record. */
230/***********************************************************************/
231int JMGFAM::GetPos(void)
232{
233 return Fpos;
234} // end of GetPos
235
236/***********************************************************************/
237/* GetNextPos: return the position of next record. */
238/***********************************************************************/
239int JMGFAM::GetNextPos(void)
240{
241 return Fpos; // TODO
242} // end of GetNextPos
243
244/***********************************************************************/
245/* SetPos: Replace the table at the specified position. */
246/***********************************************************************/
247bool JMGFAM::SetPos(PGLOBAL g, int pos)
248{
249 Fpos = pos;
250 Placed = true;
251 return false;
252} // end of SetPos
253
254/***********************************************************************/
255/* Record file position in case of UPDATE or DELETE. */
256/***********************************************************************/
257bool JMGFAM::RecordPos(PGLOBAL g)
258{
259 strcpy(g->Message, "JMGFAM::RecordPos NIY");
260 return true;
261} // end of RecordPos
262
263/***********************************************************************/
264/* Initialize Fpos and the current position for indexed DELETE. */
265/***********************************************************************/
266int JMGFAM::InitDelete(PGLOBAL g, int fpos, int spos)
267{
268 strcpy(g->Message, "JMGFAM::InitDelete NIY");
269 return RC_FX;
270} // end of InitDelete
271
272/***********************************************************************/
273/* Skip one record in file. */
274/***********************************************************************/
275int JMGFAM::SkipRecord(PGLOBAL g, bool header)
276{
277 return RC_OK; // Dummy
278} // end of SkipRecord
279
280/***********************************************************************/
281/* ReadBuffer: Get next document from a collection. */
282/***********************************************************************/
283int JMGFAM::ReadBuffer(PGLOBAL g)
284{
285 int rc = RC_FX;
286
287 if (!Curpos && Mode == MODE_UPDATE)
288 if (Jcp->MakeCursor(g, Tdbp, Options, Filter, Pipe))
289 return RC_FX;
290
291 if (++CurNum >= Rbuf) {
292 Rbuf = Jcp->Fetch();
293 Curpos++;
294 CurNum = 0;
295 } // endif CurNum
296
297 if (Rbuf > 0) {
298 PSZ str = Jcp->GetDocument();
299
300 if (str) {
301 if (trace(1))
302 htrc("%s\n", str);
303
304 strncpy(Tdbp->GetLine(), str, Lrecl);
305 rc = RC_OK;
306 } else
307 strcpy(g->Message, "Null document");
308
309 } else if (!Rbuf)
310 rc = RC_EF;
311
312 return rc;
313} // end of ReadBuffer
314
315/***********************************************************************/
316/* WriteBuffer: File write routine for MGO access method. */
317/***********************************************************************/
318int JMGFAM::WriteBuffer(PGLOBAL g)
319{
320 int rc = RC_OK;
321
322 if (Mode == MODE_INSERT) {
323 rc = Jcp->DocWrite(g);
324 } else if (Mode == MODE_DELETE) {
325 rc = Jcp->DocDelete(g, false);
326 } else if (Mode == MODE_UPDATE) {
327 rc = Jcp->DocUpdate(g, Tdbp);
328 } // endif Mode
329
330 return rc;
331} // end of WriteBuffer
332
333/***********************************************************************/
334/* Data Base delete line routine for MGO and BLK access methods. */
335/***********************************************************************/
336int JMGFAM::DeleteRecords(PGLOBAL g, int irc)
337{
338 return (irc == RC_OK) ? WriteBuffer(g) : RC_OK;
339} // end of DeleteRecords
340
341/***********************************************************************/
342/* Table file close routine for MGO access method. */
343/***********************************************************************/
344void JMGFAM::CloseTableFile(PGLOBAL g, bool)
345{
346 Jcp->Close();
347 Done = false;
348} // end of CloseTableFile
349
350/***********************************************************************/
351/* Rewind routine for MGO access method. */
352/***********************************************************************/
353void JMGFAM::Rewind(void)
354{
355 Jcp->Rewind();
356} // end of Rewind
357
358