1/************* Tabutil cpp Declares Source Code File (.CPP) ************/
2/* Name: TABUTIL.CPP Version 1.2 */
3/* */
4/* (C) Copyright to the author Olivier BERTRAND 2013 - 2017 */
5/* */
6/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */
7/***********************************************************************/
8
9/***********************************************************************/
10/* Include relevant section of system dependant header files. */
11/***********************************************************************/
12#define MYSQL_SERVER 1
13#include <my_global.h>
14#include "sql_class.h"
15#include "table.h"
16#include "field.h"
17#if defined(__WIN__)
18#include <stdlib.h>
19#include <stdio.h>
20#if defined(__BORLANDC__)
21#define __MFC_COMPAT__ // To define min/max as macro
22#endif
23//#include <windows.h>
24#else
25#if defined(UNIX)
26#include <fnmatch.h>
27#include <errno.h>
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#include "osutil.h"
32#else
33//#include <io.h>
34#endif
35//#include <fcntl.h>
36#endif
37
38/***********************************************************************/
39/* Include application header files: */
40/***********************************************************************/
41#include "table.h" // MySQL table definitions
42#include "global.h"
43#include "plgdbsem.h"
44#include "plgcnx.h" // For DB types
45#include "myutil.h"
46#include "valblk.h"
47#include "resource.h"
48//#include "reldef.h"
49#include "xtable.h"
50#include "tabext.h"
51#include "tabmysql.h"
52#include "tabcol.h"
53#include "tabutil.h"
54#include "ha_connect.h"
55
56int GetConvSize(void);
57
58/************************************************************************/
59/* Used by MYSQL tables to get MySQL parameters from the calling proxy */
60/* table (PROXY, TBL, XCL, or OCCUR) when used by one of these. */
61/************************************************************************/
62void Remove_tshp(PCATLG cat)
63{
64 ((MYCAT*)cat)->GetHandler()->tshp = NULL;
65} // end of Remove_thsp
66
67/************************************************************************/
68/* GetTableShare: allocates and open a table share. */
69/************************************************************************/
70TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
71 const char *name, bool& mysql)
72{
73 char key[256];
74 uint k;
75 TABLE_SHARE *s;
76
77 k = sprintf(key, "%s", db) + 1;
78 k += sprintf(key + k, "%s", name);
79 key[++k] = 0;
80
81 if (!(s = alloc_table_share(db, name, key, ++k))) {
82 strcpy(g->Message, "Error allocating share\n");
83 return NULL;
84 } // endif s
85
86 if (!open_table_def(thd, s, GTS_TABLE | GTS_VIEW)) {
87 if (!s->is_view) {
88 if (stricmp(plugin_name(s->db_plugin)->str, "connect"))
89 mysql = true;
90 else
91 mysql = false;
92
93 } else
94 mysql = true;
95
96 } else {
97 if (thd->is_error())
98 thd->clear_error(); // Avoid stopping info commands
99
100 sprintf(g->Message, "Error %d opening share\n", s->error);
101 free_table_share(s);
102 return NULL;
103 } // endif open_table_def
104
105 return s;
106} // end of GetTableShare
107
108/************************************************************************/
109/* TabColumns: constructs the result blocks containing all the columns */
110/* description of the object table that will be retrieved by discovery.*/
111/************************************************************************/
112PQRYRES TabColumns(PGLOBAL g, THD *thd, const char *db,
113 const char *name, bool& info)
114 {
115 int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
116 TYPE_INT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
117 TYPE_STRING, TYPE_STRING, TYPE_STRING};
118 XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
119 FLD_LENGTH, FLD_SCALE, FLD_RADIX, FLD_NULL,
120 FLD_REM, FLD_NO, FLD_CHARSET};
121 unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 32, 32};
122 PCSZ fmt;
123 char *pn, *tn, *fld, *colname, v; // *chset
124 int i, n, ncol = sizeof(buftyp) / sizeof(int);
125 int prec, len, type, scale;
126 int zconv = GetConvSize();
127 bool mysql;
128 TABLE_SHARE *s = NULL;
129 Field* *field;
130 Field *fp;
131 PQRYRES qrp;
132 PCOLRES crp;
133
134 if (!info) {
135 // Analyze the table name, it may have the format: [dbname.]tabname
136 if (strchr((char*)name, '.')) {
137 tn = (char*)PlugDup(g, name);
138 pn = strchr(tn, '.');
139 *pn++ = 0;
140 db = tn;
141 name = pn;
142 } // endif pn
143
144 if (!(s = GetTableShare(g, thd, db, name, mysql))) {
145 return NULL;
146 } else if (s->is_view) {
147 strcpy(g->Message, "Use MYSQL type to see columns from a view");
148 info = true; // To tell caller name is a view
149 free_table_share(s);
150 return NULL;
151 } else
152 n = s->fieldnames.count;
153
154 } else {
155 n = 0;
156 length[0] = 128;
157 } // endif info
158
159 /**********************************************************************/
160 /* Allocate the structures used to refer to the result set. */
161 /**********************************************************************/
162 if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
163 buftyp, fldtyp, length, false, true)))
164 return NULL;
165
166 // Some columns must be renamed
167 for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
168 switch (++i) {
169 case 2: crp->Nulls = (char*)PlugSubAlloc(g, NULL, n); break;
170 case 10: crp->Name = "Date_fmt"; break;
171 case 11: crp->Name = "Collation"; break;
172 } // endswitch i
173
174 if (info)
175 return qrp;
176
177 /**********************************************************************/
178 /* Now get the results into blocks. */
179 /**********************************************************************/
180 for (i = 0, field= s->field; *field; field++) {
181 fp= *field;
182
183 // Get column name
184 crp = qrp->Colresp; // Column_Name
185 colname = (char *)fp->field_name.str;
186 crp->Kdata->SetValue(colname, i);
187
188// chset = (char *)fp->charset()->name;
189// v = (!strcmp(chset, "binary")) ? 'B' : 0;
190 v = 0;
191
192 if ((type = MYSQLtoPLG(fp->type(), &v)) == TYPE_ERROR) {
193 if (v == 'K') {
194 // Skip this column
195 sprintf(g->Message, "Column %s skipped (unsupported type)", colname);
196 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
197 continue;
198 } // endif v
199
200 sprintf(g->Message, "Column %s unsupported type", colname);
201 qrp = NULL;
202 break;
203 } // endif type
204
205 if (v == 'X') {
206 len = zconv;
207 sprintf(g->Message, "Column %s converted to varchar(%d)",
208 colname, len);
209 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
210 } // endif v
211
212 crp = crp->Next; // Data_Type
213 crp->Kdata->SetValue(type, i);
214
215 if (fp->flags & ZEROFILL_FLAG)
216 crp->Nulls[i] = 'Z';
217 else if (fp->flags & UNSIGNED_FLAG)
218 crp->Nulls[i] = 'U';
219 else // X means TEXT field
220 crp->Nulls[i] = (v == 'X') ? 'V' : v;
221
222 crp = crp->Next; // Type_Name
223 crp->Kdata->SetValue(GetTypeName(type), i);
224 fmt = NULL;
225
226 if (type == TYPE_DATE) {
227 // When creating tables we do need info about date columns
228 if (mysql) {
229 fmt = MyDateFmt(fp->type());
230 prec = len = strlen(fmt);
231 } else {
232 fmt = (PCSZ)fp->option_struct->dateformat;
233 prec = len = fp->field_length;
234 } // endif mysql
235
236 } else if (v != 'X') {
237 if (type == TYPE_DECIM)
238 prec = ((Field_new_decimal*)fp)->precision;
239 else
240 prec = fp->field_length;
241// prec = (prec(???) == NOT_FIXED_DEC) ? 0 : fp->field_length;
242
243 len = fp->char_length();
244 } else
245 prec = len = zconv;
246
247 crp = crp->Next; // Precision
248 crp->Kdata->SetValue(prec, i);
249
250 crp = crp->Next; // Length
251 crp->Kdata->SetValue(len, i);
252
253 crp = crp->Next; // Scale
254 scale = (type == TYPE_DOUBLE || type == TYPE_DECIM) ? fp->decimals()
255 : 0;
256 crp->Kdata->SetValue(scale, i);
257
258 crp = crp->Next; // Radix
259 crp->Kdata->SetValue(0, i);
260
261 crp = crp->Next; // Nullable
262 crp->Kdata->SetValue((fp->null_ptr != 0) ? 1 : 0, i);
263
264 crp = crp->Next; // Remark
265
266 // For Valgrind
267 if (fp->comment.length > 0 && (fld = (char*) fp->comment.str))
268 crp->Kdata->SetValue(fld, fp->comment.length, i);
269 else
270 crp->Kdata->Reset(i);
271
272 crp = crp->Next; // New (date format)
273 crp->Kdata->SetValue((fmt) ? fmt : (char*) "", i);
274
275 crp = crp->Next; // New (charset)
276 fld = (char *)fp->charset()->name;
277 crp->Kdata->SetValue(fld, i);
278
279 // Add this item
280 qrp->Nblin++;
281 i++; // Can be skipped
282 } // endfor field
283
284 /**********************************************************************/
285 /* Return the result pointer for use by GetData routines. */
286 /**********************************************************************/
287 if (s)
288 free_table_share(s);
289
290 return qrp;
291 } // end of TabColumns
292
293/* -------------- Implementation of the PROXY classes ---------------- */
294
295/***********************************************************************/
296/* PRXDEF constructor. */
297/***********************************************************************/
298PRXDEF::PRXDEF(void)
299 {
300 Tablep = NULL;
301 Pseudo = 3;
302} // end of PRXDEF constructor
303
304/***********************************************************************/
305/* DefineAM: define specific AM block values from XCOL file. */
306/***********************************************************************/
307bool PRXDEF::DefineAM(PGLOBAL g, LPCSTR, int)
308 {
309 char *pn, *db, *tab, *def = NULL;
310
311 db = GetStringCatInfo(g, "Dbname", "*");
312 def = GetStringCatInfo(g, "Srcdef", NULL);
313
314 if (!(tab = GetStringCatInfo(g, "Tabname", NULL))) {
315 if (!def) {
316 strcpy(g->Message, "Missing object table definition");
317 return true;
318 } else
319 tab = PlugDup(g, "Noname");
320
321 } else
322 // Analyze the table name, it may have the format: [dbname.]tabname
323 if ((pn = strchr(tab, '.'))) {
324 *pn++ = 0;
325 db = tab;
326 tab = pn;
327 } // endif pn
328
329 Tablep = new(g) XTAB(tab, def);
330 Tablep->SetSchema(db);
331 return false;
332 } // end of DefineAM
333
334/***********************************************************************/
335/* GetTable: makes a new TDB of the proper type. */
336/***********************************************************************/
337PTDB PRXDEF::GetTable(PGLOBAL g, MODE)
338 {
339 if (Catfunc == FNC_COL)
340 return new(g) TDBTBC(this);
341 else
342 return new(g) TDBPRX(this);
343
344 } // end of GetTable
345
346/* ------------------------------------------------------------------- */
347
348/***********************************************************************/
349/* Implementation of the TDBPRX class. */
350/***********************************************************************/
351TDBPRX::TDBPRX(PPRXDEF tdp) : TDBASE(tdp)
352 {
353 Tdbp = NULL; // The object table
354 } // end of TDBPRX constructor
355
356TDBPRX::TDBPRX(PTDBPRX tdbp) : TDBASE(tdbp)
357 {
358 Tdbp = tdbp->Tdbp;
359 } // end of TDBPRX copy constructor
360
361// Method
362PTDB TDBPRX::Clone(PTABS t)
363 {
364 PTDB tp;
365 PPRXCOL cp1, cp2;
366 PGLOBAL g = t->G;
367
368 tp = new(g) TDBPRX(this);
369
370 for (cp1 = (PPRXCOL)Columns; cp1; cp1 = (PPRXCOL)cp1->GetNext()) {
371 cp2 = new(g) PRXCOL(cp1, tp); // Make a copy
372 NewPointer(t, cp1, cp2);
373 } // endfor cp1
374
375 return tp;
376 } // end of Clone
377
378/***********************************************************************/
379/* Get the PTDB of the sub-table. */
380/***********************************************************************/
381PTDB TDBPRX::GetSubTable(PGLOBAL g, PTABLE tabp, bool b)
382 {
383 const char *sp = NULL;
384 char *db, *name;
385 bool mysql = true;
386 PTDB tdbp = NULL;
387 TABLE_SHARE *s = NULL;
388 Field* *fp = NULL;
389 PCATLG cat = To_Def->GetCat();
390 PHC hc = ((MYCAT*)cat)->GetHandler();
391 LPCSTR cdb, curdb = hc->GetDBName(NULL);
392 THD *thd = (hc->GetTable())->in_use;
393
394 db = (char*)(tabp->GetSchema() ? tabp->GetSchema() : curdb);
395 name = (char*)tabp->GetName();
396
397 // Check for eventual loop
398 for (PTABLE tp = To_Table; tp; tp = tp->Next) {
399 cdb = (tp->Schema) ? tp->Schema : curdb;
400
401 if (!stricmp(name, tp->Name) && !stricmp(db, cdb)) {
402 sprintf(g->Message, "Table %s.%s pointing on itself", db, name);
403 return NULL;
404 } // endif
405
406 } // endfor tp
407
408 if (!tabp->GetSrc()) {
409 if (!(s = GetTableShare(g, thd, db, name, mysql)))
410 return NULL;
411
412 if (s->is_view && !b)
413 s->field = hc->get_table()->s->field;
414
415 hc->tshp = s;
416 } else if (b) {
417 // Don't use caller's columns
418 fp = hc->get_table()->field;
419 hc->get_table()->field = NULL;
420
421 // Make caller use the source definition
422 sp = hc->get_table()->s->option_struct->srcdef;
423 hc->get_table()->s->option_struct->srcdef = tabp->GetSrc();
424 } // endif srcdef
425
426 if (mysql) {
427 // Access sub-table via MySQL API
428 if (!(tdbp= cat->GetTable(g, tabp, Mode, "MYPRX"))) {
429 char buf[MAX_STR];
430
431 strcpy(buf, g->Message);
432 sprintf(g->Message, "Error accessing %s.%s: %s", db, name, buf);
433 hc->tshp = NULL;
434 goto err;
435 } // endif Define
436
437 if (db)
438 ((PTDBMY)tdbp)->SetDatabase(tabp->GetSchema());
439
440 if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
441 tdbp->SetName(Name); // For Make_Command
442
443 } else {
444 // Sub-table is a CONNECT table
445 tabp->Next = To_Table; // For loop checking
446 tdbp = cat->GetTable(g, tabp, Mode);
447 } // endif mysql
448
449 if (s) {
450 if (s->is_view && !b)
451 s->field = NULL;
452
453 hc->tshp = NULL;
454 } else if (b) {
455 // Restore s structure that can be in cache
456 hc->get_table()->field = fp;
457 hc->get_table()->s->option_struct->srcdef = sp;
458 } // endif s
459
460 if (trace(1) && tdbp)
461 htrc("Subtable %s in %s\n",
462 name, SVP(tdbp->GetDef()->GetDB()));
463
464 err:
465 if (s)
466 free_table_share(s);
467
468 return tdbp;
469 } // end of GetSubTable
470
471/***********************************************************************/
472/* Initializes the table. */
473/***********************************************************************/
474bool TDBPRX::InitTable(PGLOBAL g)
475 {
476 if (!Tdbp) {
477 // Get the table description block of this table
478 if (!(Tdbp = GetSubTable(g, ((PPRXDEF)To_Def)->Tablep)))
479 return true;
480
481// Tdbp->SetMode(Mode);
482 } // endif Tdbp
483
484 return false;
485 } // end of InitTable
486
487/***********************************************************************/
488/* Allocate PRX column description block. */
489/***********************************************************************/
490PCOL TDBPRX::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
491 {
492 return new(g) PRXCOL(cdp, this, cprec, n);
493 } // end of MakeCol
494
495/***********************************************************************/
496/* PRX Cardinality: returns the number of rows in the table. */
497/***********************************************************************/
498int TDBPRX::Cardinality(PGLOBAL g)
499 {
500 if (Cardinal < 0) {
501 if (InitTable(g))
502 return 0;
503
504 Cardinal = Tdbp->Cardinality(g);
505 } // endif MaxSize
506
507 return Cardinal;
508 } // end of GetMaxSize
509
510/***********************************************************************/
511/* PRX GetMaxSize: returns the maximum number of rows in the table. */
512/***********************************************************************/
513int TDBPRX::GetMaxSize(PGLOBAL g)
514 {
515 if (MaxSize < 0) {
516 if (InitTable(g))
517 return 0;
518
519 MaxSize = Tdbp->GetMaxSize(g);
520 } // endif MaxSize
521
522 return MaxSize;
523 } // end of GetMaxSize
524
525/***********************************************************************/
526/* In this sample, ROWID will be the (virtual) row number, */
527/* while ROWNUM will be the occurence rank in the multiple column. */
528/***********************************************************************/
529int TDBPRX::RowNumber(PGLOBAL g, bool b)
530 {
531 return Tdbp->RowNumber(g, b);
532 } // end of RowNumber
533
534/***********************************************************************/
535/* PROXY Access Method opening routine. */
536/***********************************************************************/
537bool TDBPRX::OpenDB(PGLOBAL g)
538 {
539 if (Use == USE_OPEN) {
540 /*******************************************************************/
541 /* Table already open, just replace it at its beginning. */
542 /*******************************************************************/
543 return Tdbp->OpenDB(g);
544 } // endif use
545
546 if (InitTable(g))
547 return true;
548 else if (Mode != MODE_READ && (Read_Only || Tdbp->IsReadOnly())) {
549 strcpy(g->Message, "Cannot modify a read only table");
550 return true;
551 } // endif tp
552
553 /*********************************************************************/
554 /* Check and initialize the subtable columns. */
555 /*********************************************************************/
556 for (PCOL cp = Columns; cp; cp = cp->GetNext())
557 if (((PPRXCOL)cp)->Init(g, Tdbp))
558 return true;
559
560 /*********************************************************************/
561 /* In Update mode, the updated column blocks must be distinct from */
562 /* the read column blocks. So make a copy of the TDB and allocate */
563 /* its column blocks in mode write (required by XML tables). */
564 /*********************************************************************/
565 if (Mode == MODE_UPDATE) {
566 PTDB utp;
567
568 if (!(utp= Tdbp->Duplicate(g))) {
569 sprintf(g->Message, MSG(INV_UPDT_TABLE), Tdbp->GetName());
570 return true;
571 } // endif tp
572
573 for (PCOL cp = To_SetCols; cp; cp = cp->GetNext())
574 if (((PPRXCOL)cp)->Init(g, utp))
575 return true;
576
577 } else if (Mode == MODE_DELETE)
578 Tdbp->SetNext(Next);
579
580 /*********************************************************************/
581 /* Physically open the object table. */
582 /*********************************************************************/
583 if (Tdbp->OpenDB(g))
584 return true;
585
586 Tdbp->SetNext(NULL);
587 Use = USE_OPEN;
588 return false;
589 } // end of OpenDB
590
591/***********************************************************************/
592/* Data Base read routine for PROY access method. */
593/***********************************************************************/
594int TDBPRX::ReadDB(PGLOBAL g)
595 {
596 /*********************************************************************/
597 /* Now start the reading process. */
598 /*********************************************************************/
599 return Tdbp->ReadDB(g);
600 } // end of ReadDB
601
602/***********************************************************************/
603/* WriteDB: Data Base write routine for PROXY access methods. */
604/***********************************************************************/
605int TDBPRX::WriteDB(PGLOBAL g)
606 {
607 return Tdbp->WriteDB(g);
608 } // end of WriteDB
609
610/***********************************************************************/
611/* Data Base delete line routine for PROXY access methods. */
612/***********************************************************************/
613int TDBPRX::DeleteDB(PGLOBAL g, int irc)
614 {
615 return Tdbp->DeleteDB(g, irc);
616 } // end of DeleteDB
617
618/***********************************************************************/
619/* Used by the TBL tables. */
620/***********************************************************************/
621void TDBPRX::RemoveNext(PTABLE tp)
622 {
623 tp->Next = NULL;
624 } // end of RemoveNext
625
626/* ---------------------------- PRXCOL ------------------------------- */
627
628/***********************************************************************/
629/* PRXCOL public constructor. */
630/***********************************************************************/
631PRXCOL::PRXCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
632 : COLBLK(cdp, tdbp, i)
633 {
634 if (cprec) {
635 Next = cprec->GetNext();
636 cprec->SetNext(this);
637 } else {
638 Next = tdbp->GetColumns();
639 tdbp->SetColumns(this);
640 } // endif cprec
641
642 // Set additional Dos access method information for column.
643 Long = cdp->GetLong(); // Useful ???
644//strcpy(F_Date, cdp->F_Date);
645 Colp = NULL;
646 To_Val = NULL;
647 Pseudo = false;
648 Colnum = cdp->GetOffset(); // If columns are retrieved by number
649
650 if (trace(1))
651 htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
652
653 } // end of PRXCOL constructor
654
655/***********************************************************************/
656/* PRXCOL constructor used for copying columns. */
657/* tdbp is the pointer to the new table descriptor. */
658/***********************************************************************/
659PRXCOL::PRXCOL(PRXCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
660 {
661 Colp = col1->Colp;
662 To_Val = col1->To_Val;
663 Pseudo = col1->Pseudo;
664 Colnum = col1->Colnum;
665 } // end of PRXCOL copy constructor
666
667/***********************************************************************/
668/* Convert an UTF-8 name to latin characters. */
669/***********************************************************************/
670char *PRXCOL::Decode(PGLOBAL g, const char *cnm)
671 {
672 char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) + 1);
673 uint dummy_errors;
674 uint32 len= copy_and_convert(buf, strlen(cnm) + 1,
675 &my_charset_latin1,
676 cnm, strlen(cnm),
677 &my_charset_utf8_general_ci,
678 &dummy_errors);
679 buf[len]= '\0';
680 return buf;
681 } // end of Decode
682
683/***********************************************************************/
684/* PRXCOL initialization routine. */
685/* Look for the matching column in the object table. */
686/***********************************************************************/
687bool PRXCOL::Init(PGLOBAL g, PTDB tp)
688 {
689 if (!tp)
690 tp = ((PTDBPRX)To_Tdb)->Tdbp;
691
692 if (!(Colp = tp->ColDB(g, Name, 0)) && Colnum)
693 Colp = tp->ColDB(g, NULL, Colnum);
694
695 if (Colp) {
696 MODE mode = To_Tdb->GetMode();
697
698 // Needed for MYSQL subtables
699 ((XCOLBLK*)Colp)->Name = Decode(g, Colp->GetName());
700
701 // May not have been done elsewhere
702 Colp->InitValue(g);
703 To_Val = Colp->GetValue();
704
705 if (mode == MODE_INSERT || mode == MODE_UPDATE)
706 if (Colp->SetBuffer(g, Colp->GetValue(), true, false))
707 return true;
708
709 // this may be needed by some tables (which?)
710 Colp->SetColUse(ColUse);
711 } else {
712 sprintf(g->Message, MSG(NO_MATCHING_COL), Name, tp->GetName());
713 return true;
714 } // endif Colp
715
716 return false;
717 } // end of Init
718
719/***********************************************************************/
720/* Reset the column descriptor to non evaluated yet. */
721/***********************************************************************/
722void PRXCOL::Reset(void)
723 {
724 if (Colp)
725 Colp->Reset();
726
727 Status &= ~BUF_READ;
728 } // end of Reset
729
730/***********************************************************************/
731/* ReadColumn: */
732/***********************************************************************/
733void PRXCOL::ReadColumn(PGLOBAL g)
734 {
735 if (trace(2))
736 htrc("PRX ReadColumn: name=%s\n", Name);
737
738 if (Colp) {
739 Colp->Eval(g);
740 Value->SetValue_pval(To_Val);
741
742 // Set null when applicable
743 if (Nullable)
744 Value->SetNull(Value->IsNull());
745
746 } else {
747 Value->Reset();
748
749 // Set null when applicable
750 if (Nullable)
751 Value->SetNull(true);
752
753 } // endif Colp
754
755 } // end of ReadColumn
756
757/***********************************************************************/
758/* WriteColumn: */
759/***********************************************************************/
760void PRXCOL::WriteColumn(PGLOBAL g)
761 {
762 if (trace(2))
763 htrc("PRX WriteColumn: name=%s\n", Name);
764
765 if (Colp) {
766 To_Val->SetValue_pval(Value);
767 Colp->WriteColumn(g);
768 } // endif Colp
769
770 } // end of WriteColumn
771
772/* ---------------------------TDBTBC class --------------------------- */
773
774/***********************************************************************/
775/* TDBTBC class constructor. */
776/***********************************************************************/
777TDBTBC::TDBTBC(PPRXDEF tdp) : TDBCAT(tdp)
778 {
779 Db = (PSZ)tdp->Tablep->GetSchema();
780 Tab = (PSZ)tdp->Tablep->GetName();
781 } // end of TDBTBC constructor
782
783/***********************************************************************/
784/* GetResult: Get the list the MYSQL table columns. */
785/***********************************************************************/
786PQRYRES TDBTBC::GetResult(PGLOBAL g)
787 {
788 bool b = false;
789
790 return TabColumns(g, current_thd, Db, Tab, b);
791 } // end of GetResult
792
793