1 /************** Table C++ Functions Source Code File (.CPP) ************/
2 /* Name: TABLE.CPP Version 2.8 */
3 /* */
4 /* (C) Copyright to the author Olivier BERTRAND 1999-2017 */
5 /* */
6 /* This file contains the TBX, TDB and OPJOIN classes functions. */
7 /***********************************************************************/
8
9 /***********************************************************************/
10 /* Include relevant MariaDB header file. */
11 /***********************************************************************/
12 #include "my_global.h"
13 #include "sql_string.h"
14
15 /***********************************************************************/
16 /* Include required application header files */
17 /* global.h is header containing all global Plug declarations. */
18 /* plgdbsem.h is header containing the DB applic. declarations. */
19 /* xobject.h is header containing XOBJECT derived classes declares. */
20 /***********************************************************************/
21 #include "global.h"
22 #include "plgdbsem.h"
23 #include "xtable.h"
24 #include "tabcol.h"
25 #include "filamtxt.h"
26 #include "tabdos.h"
27 //#include "catalog.h"
28 #include "reldef.h"
29
30 int TDB::Tnum = 0;
31
32 /***********************************************************************/
33 /* Utility routines. */
34 /***********************************************************************/
35 void NewPointer(PTABS, void *, void *);
36 void AddPointer(PTABS, void *);
37
38 /* ---------------------------- class TDB ---------------------------- */
39
40 /***********************************************************************/
41 /* TDB public constructors. */
42 /***********************************************************************/
TDB(PTABDEF tdp)43 TDB::TDB(PTABDEF tdp) : Tdb_No(++Tnum)
44 {
45 To_Def = tdp;
46 Use = USE_NO;
47 To_Orig = NULL;
48 To_Filter = NULL;
49 To_CondFil = NULL;
50 Cond = NULL;
51 Next = NULL;
52 Name = (tdp) ? tdp->GetName() : NULL;
53 To_Table = NULL;
54 Columns = NULL;
55 To_SetCols = NULL;
56 Degree = (tdp) ? tdp->GetDegree() : 0;
57 Mode = MODE_ANY;
58 Cardinal = -1;
59 MaxSize = -1;
60 Read_Only = (tdp) ? tdp->IsReadOnly() : false;
61 m_data_charset = (tdp) ? tdp->data_charset() : NULL;
62 csname = (tdp) ? tdp->csname : NULL;
63 } // end of TDB standard constructor
64
TDB(PTDB tdbp)65 TDB::TDB(PTDB tdbp) : Tdb_No(++Tnum)
66 {
67 To_Def = tdbp->To_Def;
68 Use = tdbp->Use;
69 To_Orig = tdbp;
70 To_Filter = NULL;
71 To_CondFil = NULL;
72 Cond = NULL;
73 Next = NULL;
74 Name = tdbp->Name;
75 To_Table = tdbp->To_Table;
76 Columns = NULL;
77 To_SetCols = tdbp->To_SetCols; // ???
78 Degree = tdbp->Degree;
79 Mode = tdbp->Mode;
80 Cardinal = tdbp->Cardinal;
81 MaxSize = tdbp->MaxSize;
82 Read_Only = tdbp->IsReadOnly();
83 m_data_charset = tdbp->data_charset();
84 csname = tdbp->csname;
85 } // end of TDB copy constructor
86
87 // Methods
88 /***********************************************************************/
89 /* Return the pointer on the charset of this table. */
90 /***********************************************************************/
data_charset(void)91 CHARSET_INFO *TDB::data_charset(void)
92 {
93 // If no DATA_CHARSET is specified, we assume that character
94 // set of the remote data is the same with CHARACTER SET
95 // definition of the SQL column.
96 return m_data_charset ? m_data_charset : &my_charset_bin;
97 } // end of data_charset
98
99 /***********************************************************************/
100 /* Return the datapath of the DB this table belongs to. */
101 /***********************************************************************/
GetPath(void)102 PCSZ TDB::GetPath(void)
103 {
104 return To_Def->GetPath();
105 } // end of GetPath
106
107 /***********************************************************************/
108 /* Return true if name is a special column of this table. */
109 /***********************************************************************/
IsSpecial(PSZ name)110 bool TDB::IsSpecial(PSZ name)
111 {
112 for (PCOLDEF cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext())
113 if (!stricmp(cdp->GetName(), name) && (cdp->Flags & U_SPECIAL))
114 return true; // Special column to ignore while inserting
115
116 return false; // Not found or not special or not inserting
117 } // end of IsSpecial
118
119 /***********************************************************************/
120 /* Initialize TDB based column description block construction. */
121 /* name is used to call columns by name. */
122 /* num is used by TBL to construct columns by index number. */
123 /* Note: name=Null and num=0 for constructing all columns (select *) */
124 /***********************************************************************/
ColDB(PGLOBAL g,PSZ name,int num)125 PCOL TDB::ColDB(PGLOBAL g, PSZ name, int num)
126 {
127 int i;
128 PCOLDEF cdp;
129 PCOL cp, colp = NULL, cprec = NULL;
130
131 if (trace(1))
132 htrc("ColDB: am=%d colname=%s tabname=%s num=%d\n",
133 GetAmType(), SVP(name), Name, num);
134
135 for (cdp = To_Def->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
136 if ((!name && !num) ||
137 (name && !stricmp(cdp->GetName(), name)) || num == i) {
138 /*****************************************************************/
139 /* Check for existence of desired column. */
140 /* Also find where to insert the new block. */
141 /*****************************************************************/
142 for (cp = Columns; cp; cp = cp->GetNext())
143 if ((num && cp->GetIndex() == i) ||
144 (name && !stricmp(cp->GetName(), name)))
145 break; // Found
146 else if (cp->GetIndex() < i)
147 cprec = cp;
148
149 if (trace(1))
150 htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp);
151
152 /*****************************************************************/
153 /* Now take care of Column Description Block. */
154 /*****************************************************************/
155 if (cp)
156 colp = cp;
157 else if (!(cdp->Flags & U_SPECIAL))
158 colp = MakeCol(g, cdp, cprec, i);
159 else if (Mode != MODE_INSERT)
160 colp = InsertSpcBlk(g, cdp);
161
162 if (trace(1))
163 htrc("colp=%p\n", colp);
164
165 if (name || num)
166 break;
167 else if (colp && !colp->IsSpecial())
168 cprec = colp;
169
170 } // endif Name
171
172 return (colp);
173 } // end of ColDB
174
175 /***********************************************************************/
176 /* InsertSpecialColumn: Put a special column ahead of the column list.*/
177 /***********************************************************************/
InsertSpecialColumn(PCOL colp)178 PCOL TDB::InsertSpecialColumn(PCOL colp)
179 {
180 if (!colp->IsSpecial())
181 return NULL;
182
183 colp->SetNext(Columns);
184 Columns = colp;
185 return colp;
186 } // end of InsertSpecialColumn
187
188 /***********************************************************************/
189 /* Make a special COLBLK to insert in a table. */
190 /***********************************************************************/
InsertSpcBlk(PGLOBAL g,PCOLDEF cdp)191 PCOL TDB::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
192 {
193 //char *name = cdp->GetName();
194 char *name = cdp->GetFmt();
195 PCOLUMN cp;
196 PCOL colp;
197
198 cp = new(g)COLUMN(cdp->GetName());
199
200 if (!To_Table) {
201 strcpy(g->Message, "Cannot make special column: To_Table is NULL");
202 return NULL;
203 } else
204 cp->SetTo_Table(To_Table);
205
206 if (!stricmp(name, "FILEID") || !stricmp(name, "FDISK") ||
207 !stricmp(name, "FPATH") || !stricmp(name, "FNAME") ||
208 !stricmp(name, "FTYPE") || !stricmp(name, "SERVID")) {
209 if (!To_Def || !(To_Def->GetPseudo() & 2)) {
210 sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
211 return NULL;
212 } // endif Pseudo
213
214 if (!stricmp(name, "FILEID"))
215 colp = new(g)FIDBLK(cp, OP_XX);
216 else if (!stricmp(name, "FDISK"))
217 colp = new(g)FIDBLK(cp, OP_FDISK);
218 else if (!stricmp(name, "FPATH"))
219 colp = new(g)FIDBLK(cp, OP_FPATH);
220 else if (!stricmp(name, "FNAME"))
221 colp = new(g)FIDBLK(cp, OP_FNAME);
222 else if (!stricmp(name, "FTYPE"))
223 colp = new(g)FIDBLK(cp, OP_FTYPE);
224 else
225 colp = new(g)SIDBLK(cp);
226
227 } else if (!stricmp(name, "TABID")) {
228 colp = new(g)TIDBLK(cp);
229 } else if (!stricmp(name, "PARTID")) {
230 colp = new(g)PRTBLK(cp);
231 //} else if (!stricmp(name, "CONID")) {
232 // colp = new(g) CIDBLK(cp);
233 } else if (!stricmp(name, "ROWID")) {
234 colp = new(g)RIDBLK(cp, false);
235 } else if (!stricmp(name, "ROWNUM")) {
236 colp = new(g)RIDBLK(cp, true);
237 } else {
238 sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
239 return NULL;
240 } // endif's name
241
242 if (!(colp = InsertSpecialColumn(colp))) {
243 sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
244 return NULL;
245 } // endif Insert
246
247 return (colp);
248 } // end of InsertSpcBlk
249
250 /***********************************************************************/
251 /* Marks DOS/MAP table columns used in internal joins. */
252 /* tdb2 is the top of tree or first tdb in chained tdb's and tdbp */
253 /* points to the currently marked tdb. */
254 /* Two questions here: exact meaning of U_J_INT ? */
255 /* Why is the eventual reference to To_Key_Col not marked U_J_EXT ? */
256 /***********************************************************************/
MarkDB(PGLOBAL,PTDB tdb2)257 void TDB::MarkDB(PGLOBAL, PTDB tdb2)
258 {
259 if (trace(1))
260 htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
261
262 } // end of MarkDB
263
264 /***********************************************************************/
265 /* RowNumber: returns the current row ordinal number. */
266 /***********************************************************************/
RowNumber(PGLOBAL g,bool)267 int TDB::RowNumber(PGLOBAL g, bool)
268 {
269 sprintf(g->Message, MSG(ROWID_NOT_IMPL), GetAmName(g, GetAmType()));
270 return 0;
271 } // end of RowNumber
272
Copy(PTABS t)273 PTDB TDB::Copy(PTABS t)
274 {
275 PTDB tp, tdb1, tdb2 = NULL, outp = NULL;
276 //PGLOBAL g = t->G; // Is this really useful ???
277
278 for (tdb1 = this; tdb1; tdb1 = tdb1->Next) {
279 tp = tdb1->Clone(t);
280
281 if (!outp)
282 outp = tp;
283 else
284 tdb2->Next = tp;
285
286 tdb2 = tp;
287 NewPointer(t, tdb1, tdb2);
288 } // endfor tdb1
289
290 return outp;
291 } // end of Copy
292
293 /***********************************************************************/
294 /* SetRecpos: Replace the table at the specified position. */
295 /***********************************************************************/
SetRecpos(PGLOBAL g,int)296 bool TDB::SetRecpos(PGLOBAL g, int)
297 {
298 strcpy(g->Message, MSG(SETRECPOS_NIY));
299 return true;
300 } // end of SetRecpos
301
Printf(PGLOBAL g,FILE * f,uint n)302 void TDB::Printf(PGLOBAL g, FILE *f, uint n)
303 {
304 PCOL cp;
305 char m[64];
306
307 memset(m, ' ', n); // Make margin string
308 m[n] = '\0';
309
310 for (PTDB tp = this; tp; tp = tp->Next) {
311 fprintf(f, "%sTDB (%p) %s no=%d use=%d type=%d\n", m,
312 tp, tp->Name, tp->Tdb_No, tp->Use, tp->GetAmType());
313
314 tp->PrintAM(f, m);
315 fprintf(f, "%s Columns (deg=%d):\n", m, tp->Degree);
316
317 for (cp = tp->Columns; cp; cp = cp->GetNext())
318 cp->Printf(g, f, n);
319
320 } /* endfor tp */
321
322 } // end of Printf
323
Prints(PGLOBAL,char * ps,uint)324 void TDB::Prints(PGLOBAL, char *ps, uint)
325 {
326 sprintf(ps, "R%d.%s", Tdb_No, Name);
327 } // end of Prints
328
329 /* -------------------------- class TDBASE --------------------------- */
330
331 /***********************************************************************/
332 /* Implementation of the TDBASE class. This is the base class to all */
333 /* classes for tables that can be joined together. */
334 /***********************************************************************/
TDBASE(PTABDEF tdp)335 TDBASE::TDBASE(PTABDEF tdp) : TDB(tdp)
336 {
337 //To_Def = tdp;
338 To_Link = NULL;
339 To_Key_Col = NULL;
340 To_Kindex = NULL;
341 To_Xdp = NULL;
342 //To_SetCols = NULL;
343 Ftype = RECFM_NAF;
344 //MaxSize = -1;
345 Knum = 0;
346 //Read_Only = (tdp) ? tdp->IsReadOnly() : false;
347 //m_data_charset= (tdp) ? tdp->data_charset() : NULL;
348 //csname = (tdp) ? tdp->csname : NULL;
349 } // end of TDBASE constructor
350
TDBASE(PTDBASE tdbp)351 TDBASE::TDBASE(PTDBASE tdbp) : TDB(tdbp)
352 {
353 //To_Def = tdbp->To_Def;
354 To_Link = tdbp->To_Link;
355 To_Key_Col = tdbp->To_Key_Col;
356 To_Kindex = tdbp->To_Kindex;
357 To_Xdp = tdbp->To_Xdp;
358 //To_SetCols = tdbp->To_SetCols; // ???
359 Ftype = tdbp->Ftype;
360 //MaxSize = tdbp->MaxSize;
361 Knum = tdbp->Knum;
362 //Read_Only = tdbp->Read_Only;
363 //m_data_charset= tdbp->m_data_charset;
364 //csname = tdbp->csname;
365 } // end of TDBASE copy constructor
366
367 /***********************************************************************/
368 /* Return the pointer on the DB catalog this table belongs to. */
369 /***********************************************************************/
GetCat(void)370 PCATLG TDBASE::GetCat(void)
371 {
372 return (To_Def) ? To_Def->GetCat() : NULL;
373 } // end of GetCat
374
375 #if 0
376 /***********************************************************************/
377 /* Return the pointer on the charset of this table. */
378 /***********************************************************************/
379 CHARSET_INFO *TDBASE::data_charset(void)
380 {
381 // If no DATA_CHARSET is specified, we assume that character
382 // set of the remote data is the same with CHARACTER SET
383 // definition of the SQL column.
384 return m_data_charset ? m_data_charset : &my_charset_bin;
385 } // end of data_charset
386
387 /***********************************************************************/
388 /* Return the datapath of the DB this table belongs to. */
389 /***********************************************************************/
390 PSZ TDBASE::GetPath(void)
391 {
392 return To_Def->GetPath();
393 } // end of GetPath
394
395 /***********************************************************************/
396 /* Return true if name is a special column of this table. */
397 /***********************************************************************/
398 bool TDBASE::IsSpecial(PSZ name)
399 {
400 for (PCOLDEF cdp = To_Def->GetCols(); cdp; cdp = cdp->GetNext())
401 if (!stricmp(cdp->GetName(), name) && (cdp->Flags & U_SPECIAL))
402 return true; // Special column to ignore while inserting
403
404 return false; // Not found or not special or not inserting
405 } // end of IsSpecial
406
407 /***********************************************************************/
408 /* Initialize TDBASE based column description block construction. */
409 /* name is used to call columns by name. */
410 /* num is used by TBL to construct columns by index number. */
411 /* Note: name=Null and num=0 for constructing all columns (select *) */
412 /***********************************************************************/
413 PCOL TDBASE::ColDB(PGLOBAL g, PSZ name, int num)
414 {
415 int i;
416 PCOLDEF cdp;
417 PCOL cp, colp = NULL, cprec = NULL;
418
419 if (trace(1))
420 htrc("ColDB: am=%d colname=%s tabname=%s num=%d\n",
421 GetAmType(), SVP(name), Name, num);
422
423 for (cdp = To_Def->GetCols(), i = 1; cdp; cdp = cdp->GetNext(), i++)
424 if ((!name && !num) ||
425 (name && !stricmp(cdp->GetName(), name)) || num == i) {
426 /*****************************************************************/
427 /* Check for existence of desired column. */
428 /* Also find where to insert the new block. */
429 /*****************************************************************/
430 for (cp = Columns; cp; cp = cp->GetNext())
431 if ((num && cp->GetIndex() == i) ||
432 (name && !stricmp(cp->GetName(), name)))
433 break; // Found
434 else if (cp->GetIndex() < i)
435 cprec = cp;
436
437 if (trace(1))
438 htrc("cdp(%d).Name=%s cp=%p\n", i, cdp->GetName(), cp);
439
440 /*****************************************************************/
441 /* Now take care of Column Description Block. */
442 /*****************************************************************/
443 if (cp)
444 colp = cp;
445 else if (!(cdp->Flags & U_SPECIAL))
446 colp = MakeCol(g, cdp, cprec, i);
447 else if (Mode != MODE_INSERT)
448 colp = InsertSpcBlk(g, cdp);
449
450 if (trace(1))
451 htrc("colp=%p\n", colp);
452
453 if (name || num)
454 break;
455 else if (colp && !colp->IsSpecial())
456 cprec = colp;
457
458 } // endif Name
459
460 return (colp);
461 } // end of ColDB
462
463 /***********************************************************************/
464 /* InsertSpecialColumn: Put a special column ahead of the column list.*/
465 /***********************************************************************/
466 PCOL TDBASE::InsertSpecialColumn(PCOL colp)
467 {
468 if (!colp->IsSpecial())
469 return NULL;
470
471 colp->SetNext(Columns);
472 Columns = colp;
473 return colp;
474 } // end of InsertSpecialColumn
475
476 /***********************************************************************/
477 /* Make a special COLBLK to insert in a table. */
478 /***********************************************************************/
479 PCOL TDBASE::InsertSpcBlk(PGLOBAL g, PCOLDEF cdp)
480 {
481 //char *name = cdp->GetName();
482 char *name = cdp->GetFmt();
483 PCOLUMN cp;
484 PCOL colp;
485
486 cp= new(g) COLUMN(cdp->GetName());
487
488 if (! To_Table) {
489 strcpy(g->Message, "Cannot make special column: To_Table is NULL");
490 return NULL;
491 } else
492 cp->SetTo_Table(To_Table);
493
494 if (!stricmp(name, "FILEID") || !stricmp(name, "FDISK") ||
495 !stricmp(name, "FPATH") || !stricmp(name, "FNAME") ||
496 !stricmp(name, "FTYPE") || !stricmp(name, "SERVID")) {
497 if (!To_Def || !(To_Def->GetPseudo() & 2)) {
498 sprintf(g->Message, MSG(BAD_SPEC_COLUMN));
499 return NULL;
500 } // endif Pseudo
501
502 if (!stricmp(name, "FILEID"))
503 colp = new(g) FIDBLK(cp, OP_XX);
504 else if (!stricmp(name, "FDISK"))
505 colp = new(g) FIDBLK(cp, OP_FDISK);
506 else if (!stricmp(name, "FPATH"))
507 colp = new(g) FIDBLK(cp, OP_FPATH);
508 else if (!stricmp(name, "FNAME"))
509 colp = new(g) FIDBLK(cp, OP_FNAME);
510 else if (!stricmp(name, "FTYPE"))
511 colp = new(g) FIDBLK(cp, OP_FTYPE);
512 else
513 colp = new(g) SIDBLK(cp);
514
515 } else if (!stricmp(name, "TABID")) {
516 colp = new(g) TIDBLK(cp);
517 } else if (!stricmp(name, "PARTID")) {
518 colp = new(g) PRTBLK(cp);
519 //} else if (!stricmp(name, "CONID")) {
520 // colp = new(g) CIDBLK(cp);
521 } else if (!stricmp(name, "ROWID")) {
522 colp = new(g) RIDBLK(cp, false);
523 } else if (!stricmp(name, "ROWNUM")) {
524 colp = new(g) RIDBLK(cp, true);
525 } else {
526 sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
527 return NULL;
528 } // endif's name
529
530 if (!(colp = InsertSpecialColumn(colp))) {
531 sprintf(g->Message, MSG(BAD_SPECIAL_COL), name);
532 return NULL;
533 } // endif Insert
534
535 return (colp);
536 } // end of InsertSpcBlk
537 #endif // 0
538
539 /***********************************************************************/
540 /* ResetTableOpt: Wrong for this table type. */
541 /***********************************************************************/
ResetTableOpt(PGLOBAL g,bool,bool)542 int TDBASE::ResetTableOpt(PGLOBAL g, bool, bool)
543 {
544 strcpy(g->Message, "This table is not indexable");
545 return RC_INFO;
546 } // end of ResetTableOpt
547
548 /***********************************************************************/
549 /* ResetKindex: set or reset the index pointer. */
550 /***********************************************************************/
ResetKindex(PGLOBAL g,PKXBASE kxp)551 void TDBASE::ResetKindex(PGLOBAL g, PKXBASE kxp)
552 {
553 if (To_Kindex) {
554 int pos = GetRecpos(); // To be reset in Txfp
555
556 for (PCOL colp= Columns; colp; colp= colp->GetNext())
557 colp->SetKcol(NULL);
558
559 To_Kindex->Close(); // Discard old index
560 SetRecpos(g, pos); // Ignore return value
561 } // endif To_Kindex
562
563 To_Kindex = kxp;
564 } // end of ResetKindex
565
566 #if 0
567 /***********************************************************************/
568 /* SetRecpos: Replace the table at the specified position. */
569 /***********************************************************************/
570 bool TDBASE::SetRecpos(PGLOBAL g, int)
571 {
572 strcpy(g->Message, MSG(SETRECPOS_NIY));
573 return true;
574 } // end of SetRecpos
575 #endif // 0
576
577 /***********************************************************************/
578 /* Methods */
579 /***********************************************************************/
PrintAM(FILE * f,char * m)580 void TDBASE::PrintAM(FILE *f, char *m)
581 {
582 fprintf(f, "%s AM(%d): mode=%d\n", m, GetAmType(), Mode);
583 } // end of PrintAM
584
585 #if 0
586 /***********************************************************************/
587 /* Marks DOS/MAP table columns used in internal joins. */
588 /* tdb2 is the top of tree or first tdb in chained tdb's and tdbp */
589 /* points to the currently marked tdb. */
590 /* Two questions here: exact meaning of U_J_INT ? */
591 /* Why is the eventual reference to To_Key_Col not marked U_J_EXT ? */
592 /***********************************************************************/
593 void TDBASE::MarkDB(PGLOBAL, PTDB tdb2)
594 {
595 if (trace(1))
596 htrc("DOS MarkDB: tdbp=%p tdb2=%p\n", this, tdb2);
597
598 } // end of MarkDB
599 #endif // 0
600
601 /* ---------------------------TDBCAT class --------------------------- */
602
603 /***********************************************************************/
604 /* Implementation of the TDBCAT class. */
605 /***********************************************************************/
TDBCAT(PTABDEF tdp)606 TDBCAT::TDBCAT(PTABDEF tdp) : TDBASE(tdp)
607 {
608 Qrp = NULL;
609 Init = false;
610 N = -1;
611 } // end of TDBCAT constructor
612
613 /***********************************************************************/
614 /* Allocate CAT column description block. */
615 /***********************************************************************/
MakeCol(PGLOBAL g,PCOLDEF cdp,PCOL cprec,int n)616 PCOL TDBCAT::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
617 {
618 PCATCOL colp;
619
620 colp = (PCATCOL)new(g) CATCOL(cdp, this, n);
621
622 if (cprec) {
623 colp->SetNext(cprec->GetNext());
624 cprec->SetNext(colp);
625 } else {
626 colp->SetNext(Columns);
627 Columns = colp;
628 } // endif cprec
629
630 return colp;
631 } // end of MakeCol
632
633 /***********************************************************************/
634 /* Initialize: Get the result query block. */
635 /***********************************************************************/
Initialize(PGLOBAL g)636 bool TDBCAT::Initialize(PGLOBAL g)
637 {
638 if (Init)
639 return false;
640
641 if (!(Qrp = GetResult(g)))
642 return true;
643
644 if (Qrp->Truncated) {
645 sprintf(g->Message, "Result limited to %d lines", Qrp->Maxres);
646 PushWarning(g, this);
647 } // endif Truncated
648
649 if (Qrp->BadLines) {
650 sprintf(g->Message, "%d bad lines in result", Qrp->BadLines);
651 PushWarning(g, this);
652 } // endif Badlines
653
654 Init = true;
655 return false;
656 } // end of Initialize
657
658 /***********************************************************************/
659 /* CAT: Get the number of properties. */
660 /***********************************************************************/
GetMaxSize(PGLOBAL g)661 int TDBCAT::GetMaxSize(PGLOBAL g __attribute__((unused)))
662 {
663 if (MaxSize < 0) {
664 // if (Initialize(g))
665 // return -1;
666
667 // MaxSize = Qrp->Nblin;
668 MaxSize = 10; // To make MariaDB happy
669 } // endif MaxSize
670
671 return MaxSize;
672 } // end of GetMaxSize
673
674 /***********************************************************************/
675 /* CAT Access Method opening routine. */
676 /***********************************************************************/
OpenDB(PGLOBAL g)677 bool TDBCAT::OpenDB(PGLOBAL g)
678 {
679 if (Use == USE_OPEN) {
680 /*******************************************************************/
681 /* Table already open. */
682 /*******************************************************************/
683 N = -1;
684 return false;
685 } // endif use
686
687 if (Mode != MODE_READ) {
688 /*******************************************************************/
689 /* ODBC Info tables cannot be modified. */
690 /*******************************************************************/
691 strcpy(g->Message, "CAT tables are read only");
692 return true;
693 } // endif Mode
694
695 /*********************************************************************/
696 /* Initialize the ODBC processing. */
697 /*********************************************************************/
698 if (Initialize(g))
699 return true;
700
701 Use = USE_OPEN;
702 return InitCol(g);
703 } // end of OpenDB
704
705 /***********************************************************************/
706 /* Initialize columns. */
707 /***********************************************************************/
InitCol(PGLOBAL g)708 bool TDBCAT::InitCol(PGLOBAL g)
709 {
710 PCATCOL colp;
711 PCOLRES crp;
712
713 for (colp = (PCATCOL)Columns; colp; colp = (PCATCOL)colp->GetNext()) {
714 for (crp = Qrp->Colresp; crp; crp = crp->Next)
715 if ((colp->Flag && colp->Flag == crp->Fld) ||
716 (!colp->Flag && !stricmp(colp->Name, crp->Name))) {
717 colp->Crp = crp;
718 break;
719 } // endif Flag
720
721
722 if (!colp->Crp /*&& !colp->GetValue()->IsConstant()*/) {
723 sprintf(g->Message, "Invalid flag %d for column %s",
724 colp->Flag, colp->Name);
725 return true;
726 } else if (crp->Fld == FLD_SCALE || crp->Fld == FLD_RADIX)
727 colp->Value->SetNullable(true);
728
729 } // endfor colp
730
731 return false;
732 } // end of InitCol
733
734 /***********************************************************************/
735 /* SetRecpos: Replace the table at the specified position. */
736 /***********************************************************************/
SetRecpos(PGLOBAL,int recpos)737 bool TDBCAT::SetRecpos(PGLOBAL, int recpos)
738 {
739 N = recpos - 1;
740 return false;
741 } // end of SetRecpos
742
743 /***********************************************************************/
744 /* Data Base read routine for CAT access method. */
745 /***********************************************************************/
ReadDB(PGLOBAL)746 int TDBCAT::ReadDB(PGLOBAL)
747 {
748 return (++N < Qrp->Nblin) ? RC_OK : RC_EF;
749 } // end of ReadDB
750
751 /***********************************************************************/
752 /* WriteDB: Data Base write routine for CAT access methods. */
753 /***********************************************************************/
WriteDB(PGLOBAL g)754 int TDBCAT::WriteDB(PGLOBAL g)
755 {
756 strcpy(g->Message, "CAT tables are read only");
757 return RC_FX;
758 } // end of WriteDB
759
760 /***********************************************************************/
761 /* Data Base delete line routine for CAT access methods. */
762 /***********************************************************************/
DeleteDB(PGLOBAL g,int)763 int TDBCAT::DeleteDB(PGLOBAL g, int)
764 {
765 strcpy(g->Message, "Delete not enabled for CAT tables");
766 return RC_FX;
767 } // end of DeleteDB
768
769 /***********************************************************************/
770 /* Data Base close routine for WMI access method. */
771 /***********************************************************************/
CloseDB(PGLOBAL)772 void TDBCAT::CloseDB(PGLOBAL)
773 {
774 // Nothing to do
775 } // end of CloseDB
776
777 // ------------------------ CATCOL functions ----------------------------
778
779 /***********************************************************************/
780 /* CATCOL public constructor. */
781 /***********************************************************************/
CATCOL(PCOLDEF cdp,PTDB tdbp,int n)782 CATCOL::CATCOL(PCOLDEF cdp, PTDB tdbp, int n)
783 : COLBLK(cdp, tdbp, n)
784 {
785 Tdbp = (PTDBCAT)tdbp;
786 Crp = NULL;
787 Flag = cdp->GetOffset();
788 } // end of WMICOL constructor
789
790 /***********************************************************************/
791 /* Read the next Data Source elements. */
792 /***********************************************************************/
ReadColumn(PGLOBAL)793 void CATCOL::ReadColumn(PGLOBAL)
794 {
795 bool b = (!Crp->Kdata || Crp->Kdata->IsNull(Tdbp->N));
796
797 // Get the value of the Name or Description property
798 if (!b)
799 Value->SetValue_pvblk(Crp->Kdata, Tdbp->N);
800 else
801 Value->Reset();
802
803 Value->SetNull(b);
804 } // end of ReadColumn
805
806