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/***********************************************************************/
29COLBLK::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/***********************************************************************/
69COLBLK::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
89 colp->Next = this;
90 } // endelse
91
92 } // end of COLBLK copy constructor
93
94/***********************************************************************/
95/* Reset the column descriptor to non evaluated yet. */
96/***********************************************************************/
97void 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/***********************************************************************/
106bool 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/***********************************************************************/
114bool 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/***********************************************************************/
129bool 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/***********************************************************************/
155bool 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/***********************************************************************/
178bool 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/***********************************************************************/
187int 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/***********************************************************************/
197void 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/***********************************************************************/
208void 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/***********************************************************************/
217void 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/***********************************************************************/
240void 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/***********************************************************************/
249SPCBLK::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/***********************************************************************/
262void 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/***********************************************************************/
271RIDBLK::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/***********************************************************************/
285void 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/***********************************************************************/
293FIDBLK::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(__WIN__)
301 Format.Prec = 1; // Case insensitive
302#endif // __WIN__
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/***********************************************************************/
313void 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/***********************************************************************/
335TIDBLK::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/***********************************************************************/
350void 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/***********************************************************************/
362PRTBLK::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/***********************************************************************/
377void 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/***********************************************************************/
392SIDBLK::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/***********************************************************************/
407void 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