1 /************* Colblk C++ Functions Source Code File (.CPP) ************/
2 /*  Name: COLBLK.CPP  Version 2.2                                      */
3 /*                                                                     */
4 /*  (C) Copyright to the author Olivier BERTRAND          1998-2017    */
5 /*                                                                     */
6 /*  This file contains the COLBLK class functions.                     */
7 /***********************************************************************/
8 
9 /***********************************************************************/
10 /*  Include relevant MariaDB header file.                  */
11 /***********************************************************************/
12 #include "my_global.h"
13 
14 /***********************************************************************/
15 /*  Include required application header files                          */
16 /*  global.h    is header containing all global Plug declarations.     */
17 /*  plgdbsem.h  is header containing the DB applic. declarations.      */
18 /***********************************************************************/
19 #include "global.h"
20 #include "plgdbsem.h"
21 #include "tabcol.h"
22 #include "colblk.h"
23 #include "xindex.h"
24 #include "xtable.h"
25 
26 /***********************************************************************/
27 /*  COLBLK protected constructor.                                      */
28 /***********************************************************************/
COLBLK(PCOLDEF cdp,PTDB tdbp,int i)29 COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
30   {
31   Next = NULL;
32   Index = i;
33 //Number = 0;
34   ColUse = 0;
35 
36   if ((Cdp = cdp)) {
37     Name = cdp->Name;
38     Format = cdp->F;
39     Opt = cdp->Opt;
40     Long = cdp->Long;
41     Precision = cdp->Precision;
42     Freq = cdp->Freq;
43     Buf_Type = cdp->Buf_Type;
44     ColUse |= cdp->Flags;       // Used by CONNECT
45     Nullable = !!(cdp->Flags & U_NULLS);
46     Unsigned = !!(cdp->Flags & U_UNSIGNED);
47   } else {
48     Name = NULL;
49     memset(&Format, 0, sizeof(FORMAT));
50     Opt = 0;
51     Long = 0;
52     Precision = 0;
53     Freq = 0;
54     Buf_Type = TYPE_ERROR;
55     Nullable = false;
56     Unsigned = false;
57   } // endif cdp
58 
59   To_Tdb = tdbp;
60   Status = BUF_NO;
61 //Value = NULL;                  done in XOBJECT constructor
62   To_Kcol = NULL;
63   } // end of COLBLK constructor
64 
65 /***********************************************************************/
66 /*  COLBLK constructor used for copying columns.                       */
67 /*  tdbp is the pointer to the new table descriptor.                   */
68 /***********************************************************************/
COLBLK(PCOL col1,PTDB tdbp)69 COLBLK::COLBLK(PCOL col1, PTDB tdbp)
70   {
71   PCOL colp;
72 
73   // Copy the old column block to the new one
74   *this = *col1;
75   Next = NULL;
76 //To_Orig = col1;
77   To_Tdb = tdbp;
78 
79   if (trace(2))
80     htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);
81 
82   if (tdbp) {
83     // Attach the new column to the table block
84     if (!tdbp->GetColumns()) {
85       tdbp->SetColumns(this);
86     } else {
87       for (colp = tdbp->GetColumns(); colp->Next; colp = colp->Next) ;
88       colp->Next = this;
89     } // endelse
90   }
91 
92   } // end of COLBLK copy constructor
93 
94 /***********************************************************************/
95 /*  Reset the column descriptor to non evaluated yet.                  */
96 /***********************************************************************/
Reset(void)97 void COLBLK::Reset(void)
98   {
99   Status &= ~BUF_READ;
100   } // end of Reset
101 
102 /***********************************************************************/
103 /*  Compare: compares itself to an (expression) object and returns     */
104 /*  true if it is equivalent.                                          */
105 /***********************************************************************/
Compare(PXOB xp)106 bool COLBLK::Compare(PXOB xp)
107   {
108   return (this == xp);
109   } // end of Compare
110 
111 /***********************************************************************/
112 /*  SetFormat: function used to set SELECT output format.              */
113 /***********************************************************************/
SetFormat(PGLOBAL,FORMAT & fmt)114 bool COLBLK::SetFormat(PGLOBAL, FORMAT& fmt)
115   {
116   fmt = Format;
117 
118   if (trace(2))
119     htrc("COLBLK: %p format=%c(%d,%d)\n",
120          this, *fmt.Type, fmt.Length, fmt.Prec);
121 
122   return false;
123   } // end of SetFormat
124 
125 /***********************************************************************/
126 /*  Eval:  get the column value from the last read record or from a    */
127 /*  matching Index column if there is one.                             */
128 /***********************************************************************/
Eval(PGLOBAL g)129 bool COLBLK::Eval(PGLOBAL g)
130   {
131   if (trace(2))
132     htrc("Col Eval: %s status=%.4X\n", Name, Status);
133 
134   if (!GetStatus(BUF_READ)) {
135 //  if (To_Tdb->IsNull())
136 //    Value->Reset();
137     if (To_Kcol)
138       To_Kcol->FillValue(Value);
139     else
140       ReadColumn(g);
141 
142     AddStatus(BUF_READ);
143     } // endif
144 
145   return false;
146   } // end of Eval
147 
148 /***********************************************************************/
149 /*  InitValue: prepare a column block for read operation.              */
150 /*  Now we use Format.Length for the len parameter to avoid strings    */
151 /*  to be truncated when converting from string to coded string.       */
152 /*  Added in version 1.5 is the arguments GetScale() and Domain        */
153 /*  in calling AllocateValue. Domain is used for TYPE_DATE only.       */
154 /***********************************************************************/
InitValue(PGLOBAL g)155 bool COLBLK::InitValue(PGLOBAL g)
156   {
157   if (Value)
158     return false;                       // Already done
159 
160   // Allocate a Value object
161   if (!(Value = AllocateValue(g, Buf_Type, Precision,
162                               GetScale(), Unsigned, GetDomain())))
163     return true;
164 
165   AddStatus(BUF_READY);
166   Value->SetNullable(Nullable);
167 
168   if (trace(2))
169     htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n",
170          this, Buf_Type, Value, ColUse, Status);
171 
172   return false;
173   } // end of InitValue
174 
175 /***********************************************************************/
176 /*  SetBuffer: prepare a column block for write operation.             */
177 /***********************************************************************/
SetBuffer(PGLOBAL g,PVAL,bool,bool)178 bool COLBLK::SetBuffer(PGLOBAL g, PVAL, bool, bool)
179   {
180   sprintf(g->Message, MSG(UNDEFINED_AM), "SetBuffer");
181   return true;
182   } // end of SetBuffer
183 
184 /***********************************************************************/
185 /*  GetLength: returns an evaluation of the column string length.      */
186 /***********************************************************************/
GetLengthEx(void)187 int COLBLK::GetLengthEx(void)
188   {
189   return Long;
190   } // end of GetLengthEx
191 
192 /***********************************************************************/
193 /*  ReadColumn: what this routine does is to access the last line      */
194 /*  read from the corresponding table, extract from it the field       */
195 /*  corresponding to this column and convert it to buffer type.        */
196 /***********************************************************************/
ReadColumn(PGLOBAL g)197 void COLBLK::ReadColumn(PGLOBAL g)
198 {
199   sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
200 	throw (int)TYPE_COLBLK;
201 } // end of ReadColumn
202 
203 /***********************************************************************/
204 /*  WriteColumn: what this routine does is to access the last line     */
205 /*  read from the corresponding table, and rewrite the field           */
206 /*  corresponding to this column from the column buffer and type.      */
207 /***********************************************************************/
WriteColumn(PGLOBAL g)208 void COLBLK::WriteColumn(PGLOBAL g)
209 {
210   sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
211 	throw (int)TYPE_COLBLK;
212 } // end of WriteColumn
213 
214 /***********************************************************************/
215 /*  Make file output of a column descriptor block.                     */
216 /***********************************************************************/
Printf(PGLOBAL,FILE * f,uint n)217 void COLBLK::Printf(PGLOBAL, FILE *f, uint n)
218   {
219   char m[64];
220   int  i;
221   PCOL colp;
222 
223   memset(m, ' ', n);        // Make margin string
224   m[n] = '\0';
225 
226   for (colp = To_Tdb->GetColumns(), i = 1; colp; colp = colp->Next, i++)
227     if (colp == this)
228       break;
229 
230   fprintf(f, "%sR%dC%d type=%d F=%.2s(%d,%d)", m, To_Tdb->GetTdb_No(),
231           i, GetAmType(), Format.Type, Format.Length, Format.Prec);
232   fprintf(f,
233     " coluse=%04X status=%04X buftyp=%d value=%p name=%s\n",
234           ColUse, Status, Buf_Type, Value, Name);
235   } // end of Printf
236 
237 /***********************************************************************/
238 /*  Make string output of a column descriptor block.                   */
239 /***********************************************************************/
Prints(PGLOBAL,char * ps,uint)240 void COLBLK::Prints(PGLOBAL, char *ps, uint)
241   {
242   sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
243   } // end of Prints
244 
245 
246 /***********************************************************************/
247 /*  SPCBLK constructor.                                                */
248 /***********************************************************************/
SPCBLK(PCOLUMN cp)249 SPCBLK::SPCBLK(PCOLUMN cp)
250        : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
251   {
252   Name = (char*)cp->GetName();
253   Precision = Long = 0;
254   Buf_Type = TYPE_ERROR;
255   } // end of SPCBLK constructor
256 
257 /***********************************************************************/
258 /*  WriteColumn: what this routine does is to access the last line     */
259 /*  read from the corresponding table, and rewrite the field           */
260 /*  corresponding to this column from the column buffer and type.      */
261 /***********************************************************************/
WriteColumn(PGLOBAL g)262 void SPCBLK::WriteColumn(PGLOBAL g)
263 {
264   sprintf(g->Message, MSG(SPCOL_READONLY), Name);
265 	throw (int)TYPE_COLBLK;
266 } // end of WriteColumn
267 
268 /***********************************************************************/
269 /*  RIDBLK constructor for the ROWID special column.                   */
270 /***********************************************************************/
RIDBLK(PCOLUMN cp,bool rnm)271 RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
272   {
273   Precision = Long = 10;
274   Buf_Type = TYPE_INT;
275   Rnm = rnm;
276   *Format.Type = 'N';
277   Format.Length = 10;
278   } // end of RIDBLK constructor
279 
280 /***********************************************************************/
281 /*  ReadColumn: what this routine does is to return the ordinal        */
282 /*  number of the current row in the table (if Rnm is true) or in the  */
283 /*  current file (if Rnm is false) the same except for multiple tables.*/
284 /***********************************************************************/
ReadColumn(PGLOBAL g)285 void RIDBLK::ReadColumn(PGLOBAL g)
286   {
287   Value->SetValue(To_Tdb->RowNumber(g, Rnm));
288   } // end of ReadColumn
289 
290 /***********************************************************************/
291 /*  FIDBLK constructor for the FILEID special column.                  */
292 /***********************************************************************/
FIDBLK(PCOLUMN cp,OPVAL op)293 FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op)
294   {
295 //Is_Key = 2; for when the MUL table indexed reading will be implemented.
296   Precision = Long = _MAX_PATH;
297   Buf_Type = TYPE_STRING;
298   *Format.Type = 'C';
299   Format.Length = Long;
300 #if defined(_WIN32)
301   Format.Prec = 1;          // Case insensitive
302 #endif   // _WIN32
303   Constant = (!To_Tdb->GetDef()->GetMultiple() &&
304               To_Tdb->GetAmType() != TYPE_AM_PLG &&
305               To_Tdb->GetAmType() != TYPE_AM_PLM);
306   Fn = NULL;
307   } // end of FIDBLK constructor
308 
309 /***********************************************************************/
310 /*  ReadColumn: what this routine does is to return the current        */
311 /*  file ID of the table (can change for Multiple tables).             */
312 /***********************************************************************/
ReadColumn(PGLOBAL g)313 void FIDBLK::ReadColumn(PGLOBAL g)
314   {
315   if (Fn != To_Tdb->GetFile(g)) {
316     char filename[_MAX_PATH];
317 
318     Fn = To_Tdb->GetFile(g);
319     PlugSetPath(filename, Fn, To_Tdb->GetPath());
320 
321     if (Op != OP_XX) {
322       char buff[_MAX_PATH];
323 
324       Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
325     } else
326       Value->SetValue_psz(filename);
327 
328     } // endif Fn
329 
330   } // end of ReadColumn
331 
332 /***********************************************************************/
333 /*  TIDBLK constructor for the TABID special column.                   */
334 /***********************************************************************/
TIDBLK(PCOLUMN cp)335 TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
336   {
337 //Is_Key = 2; for when the MUL table indexed reading will be implemented.
338   Precision = Long = 64;
339   Buf_Type = TYPE_STRING;
340   *Format.Type = 'C';
341   Format.Length = Long;
342   Format.Prec = 1;          // Case insensitive
343   Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
344   Tname = NULL;
345   } // end of TIDBLK constructor
346 
347 /***********************************************************************/
348 /*  ReadColumn: what this routine does is to return the table ID.      */
349 /***********************************************************************/
ReadColumn(PGLOBAL)350 void TIDBLK::ReadColumn(PGLOBAL)
351   {
352   if (Tname == NULL) {
353     Tname = (char*)To_Tdb->GetName();
354     Value->SetValue_psz(Tname);
355     } // endif Tname
356 
357   } // end of ReadColumn
358 
359 /***********************************************************************/
360 /*  PRTBLK constructor for the PARTID special column.                  */
361 /***********************************************************************/
PRTBLK(PCOLUMN cp)362 PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
363   {
364 //Is_Key = 2; for when the MUL table indexed reading will be implemented.
365   Precision = Long = 64;
366   Buf_Type = TYPE_STRING;
367   *Format.Type = 'C';
368   Format.Length = Long;
369   Format.Prec = 1;          // Case insensitive
370   Constant = true;          // TODO: check whether this is true indeed
371   Pname = NULL;
372   } // end of PRTBLK constructor
373 
374 /***********************************************************************/
375 /*  ReadColumn: what this routine does is to return the partition ID.  */
376 /***********************************************************************/
ReadColumn(PGLOBAL g)377 void PRTBLK::ReadColumn(PGLOBAL g)
378   {
379   if (Pname == NULL) {
380     const char *p;
381 
382     Pname = To_Tdb->GetDef()->GetStringCatInfo(g, "partname", "?");
383     p = strrchr(Pname, '#');
384     Value->SetValue_psz((p) ? p + 1 : Pname);
385     } // endif Pname
386 
387   } // end of ReadColumn
388 
389 /***********************************************************************/
390 /*  SIDBLK constructor for the SERVID special column.                  */
391 /***********************************************************************/
SIDBLK(PCOLUMN cp)392 SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
393   {
394 //Is_Key = 2; for when the MUL table indexed reading will be implemented.
395   Precision = Long = 64;
396   Buf_Type = TYPE_STRING;
397   *Format.Type = 'C';
398   Format.Length = Long;
399   Format.Prec = 1;          // Case insensitive
400   Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
401   Sname = NULL;
402   } // end of TIDBLK constructor
403 
404 /***********************************************************************/
405 /*  ReadColumn: what this routine does is to return the server ID.     */
406 /***********************************************************************/
ReadColumn(PGLOBAL)407 void SIDBLK::ReadColumn(PGLOBAL)
408   {
409 //if (Sname == NULL) {
410     Sname = To_Tdb->GetServer();
411     Value->SetValue_psz(Sname);
412 //  } // endif Sname
413 
414   } // end of ReadColumn
415