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