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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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(__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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | /***********************************************************************/ |
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 | |