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 | /***********************************************************************/ |
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 | |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | |
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 | /***********************************************************************/ |
296 | bool TDB::SetRecpos(PGLOBAL g, int) |
297 | { |
298 | strcpy(g->Message, MSG(SETRECPOS_NIY)); |
299 | return true; |
300 | } // end of SetRecpos |
301 | |
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 | |
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 | /***********************************************************************/ |
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 | |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | |