summaryrefslogtreecommitdiff
path: root/storage/connect/colblk.cpp
blob: a9cf43f3d9678e4b4a94280f61c40c53e3bfc3b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/************* Colblk C++ Functions Source Code File (.CPP) ************/
/*  Name: COLBLK.CPP  Version 2.2                                      */
/*                                                                     */
/*  (C) Copyright to the author Olivier BERTRAND          1998-2017    */
/*                                                                     */
/*  This file contains the COLBLK class functions.                     */
/***********************************************************************/

/***********************************************************************/
/*  Include relevant MariaDB header file.                  */
/***********************************************************************/
#include "my_global.h"

/***********************************************************************/
/*  Include required application header files                          */
/*  global.h    is header containing all global Plug declarations.     */
/*  plgdbsem.h  is header containing the DB applic. declarations.      */
/***********************************************************************/
#include "global.h"
#include "plgdbsem.h"
#include "tabcol.h"
#include "colblk.h"
#include "xindex.h"
#include "xtable.h"

/***********************************************************************/
/*  COLBLK protected constructor.                                      */
/***********************************************************************/
COLBLK::COLBLK(PCOLDEF cdp, PTDB tdbp, int i)
  {
  Next = NULL;
  Index = i;
//Number = 0;
  ColUse = 0;

  if ((Cdp = cdp)) {
    Name = cdp->Name;
    Format = cdp->F;
    Opt = cdp->Opt;
    Long = cdp->Long;
    Precision = cdp->Precision;
    Freq = cdp->Freq;
    Buf_Type = cdp->Buf_Type;
    ColUse |= cdp->Flags;       // Used by CONNECT
    Nullable = !!(cdp->Flags & U_NULLS);
    Unsigned = !!(cdp->Flags & U_UNSIGNED);
  } else {
    Name = NULL;
    memset(&Format, 0, sizeof(FORMAT));
    Opt = 0;
    Long = 0;
    Precision = 0;
    Freq = 0;
    Buf_Type = TYPE_ERROR;
    Nullable = false;
    Unsigned = false;
  } // endif cdp

  To_Tdb = tdbp;
  Status = BUF_NO;
//Value = NULL;                  done in XOBJECT constructor
  To_Kcol = NULL;
  } // end of COLBLK constructor

/***********************************************************************/
/*  COLBLK constructor used for copying columns.                       */
/*  tdbp is the pointer to the new table descriptor.                   */
/***********************************************************************/
COLBLK::COLBLK(PCOL col1, PTDB tdbp)
  {
  PCOL colp;

  // Copy the old column block to the new one
  *this = *col1;
  Next = NULL;
//To_Orig = col1;
  To_Tdb = tdbp;

  if (trace(2))
    htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);

  if (tdbp)
    // Attach the new column to the table block
    if (!tdbp->GetColumns())
      tdbp->SetColumns(this);
    else {
      for (colp = tdbp->GetColumns(); colp->Next; colp = colp->Next) ;

      colp->Next = this;
      } // endelse

  } // end of COLBLK copy constructor

/***********************************************************************/
/*  Reset the column descriptor to non evaluated yet.                  */
/***********************************************************************/
void COLBLK::Reset(void)
  {
  Status &= ~BUF_READ;
  } // end of Reset

/***********************************************************************/
/*  Compare: compares itself to an (expression) object and returns     */
/*  true if it is equivalent.                                          */
/***********************************************************************/
bool COLBLK::Compare(PXOB xp)
  {
  return (this == xp);
  } // end of Compare

/***********************************************************************/
/*  SetFormat: function used to set SELECT output format.              */
/***********************************************************************/
bool COLBLK::SetFormat(PGLOBAL, FORMAT& fmt)
  {
  fmt = Format;

  if (trace(2))
    htrc("COLBLK: %p format=%c(%d,%d)\n",
         this, *fmt.Type, fmt.Length, fmt.Prec);

  return false;
  } // end of SetFormat

/***********************************************************************/
/*  Eval:  get the column value from the last read record or from a    */
/*  matching Index column if there is one.                             */
/***********************************************************************/
bool COLBLK::Eval(PGLOBAL g)
  {
  if (trace(2))
    htrc("Col Eval: %s status=%.4X\n", Name, Status);

  if (!GetStatus(BUF_READ)) {
//  if (To_Tdb->IsNull())
//    Value->Reset();
    if (To_Kcol)
      To_Kcol->FillValue(Value);
    else
      ReadColumn(g);

    AddStatus(BUF_READ);
    } // endif

  return false;
  } // end of Eval

/***********************************************************************/
/*  InitValue: prepare a column block for read operation.              */
/*  Now we use Format.Length for the len parameter to avoid strings    */
/*  to be truncated when converting from string to coded string.       */
/*  Added in version 1.5 is the arguments GetScale() and Domain        */
/*  in calling AllocateValue. Domain is used for TYPE_DATE only.       */
/***********************************************************************/
bool COLBLK::InitValue(PGLOBAL g)
  {
  if (Value)
    return false;                       // Already done

  // Allocate a Value object
  if (!(Value = AllocateValue(g, Buf_Type, Precision,
                              GetScale(), Unsigned, GetDomain())))
    return true;

  AddStatus(BUF_READY);
  Value->SetNullable(Nullable);

  if (trace(2))
    htrc(" colp=%p type=%d value=%p coluse=%.4X status=%.4X\n",
         this, Buf_Type, Value, ColUse, Status);

  return false;
  } // end of InitValue

/***********************************************************************/
/*  SetBuffer: prepare a column block for write operation.             */
/***********************************************************************/
bool COLBLK::SetBuffer(PGLOBAL g, PVAL, bool, bool)
  {
  sprintf(g->Message, MSG(UNDEFINED_AM), "SetBuffer");
  return true;
  } // end of SetBuffer

/***********************************************************************/
/*  GetLength: returns an evaluation of the column string length.      */
/***********************************************************************/
int COLBLK::GetLengthEx(void)
  {
  return Long;
  } // end of GetLengthEx

/***********************************************************************/
/*  ReadColumn: what this routine does is to access the last line      */
/*  read from the corresponding table, extract from it the field       */
/*  corresponding to this column and convert it to buffer type.        */
/***********************************************************************/
void COLBLK::ReadColumn(PGLOBAL g)
{
  sprintf(g->Message, MSG(UNDEFINED_AM), "ReadColumn");
	throw (int)TYPE_COLBLK;
} // end of ReadColumn

/***********************************************************************/
/*  WriteColumn: what this routine does is to access the last line     */
/*  read from the corresponding table, and rewrite the field           */
/*  corresponding to this column from the column buffer and type.      */
/***********************************************************************/
void COLBLK::WriteColumn(PGLOBAL g)
{
  sprintf(g->Message, MSG(UNDEFINED_AM), "WriteColumn");
	throw (int)TYPE_COLBLK;
} // end of WriteColumn

/***********************************************************************/
/*  Make file output of a column descriptor block.                     */
/***********************************************************************/
void COLBLK::Printf(PGLOBAL, FILE *f, uint n)
  {
  char m[64];
  int  i;
  PCOL colp;

  memset(m, ' ', n);        // Make margin string
  m[n] = '\0';

  for (colp = To_Tdb->GetColumns(), i = 1; colp; colp = colp->Next, i++)
    if (colp == this)
      break;

  fprintf(f, "%sR%dC%d type=%d F=%.2s(%d,%d)", m, To_Tdb->GetTdb_No(),
          i, GetAmType(), Format.Type, Format.Length, Format.Prec);
  fprintf(f,
    " coluse=%04X status=%04X buftyp=%d value=%p name=%s\n",
          ColUse, Status, Buf_Type, Value, Name);
  } // end of Printf

/***********************************************************************/
/*  Make string output of a column descriptor block.                   */
/***********************************************************************/
void COLBLK::Prints(PGLOBAL, char *ps, uint)
  {
  sprintf(ps, "R%d.%s", To_Tdb->GetTdb_No(), Name);
  } // end of Prints


/***********************************************************************/
/*  SPCBLK constructor.                                                */
/***********************************************************************/
SPCBLK::SPCBLK(PCOLUMN cp)
       : COLBLK((PCOLDEF)NULL, cp->GetTo_Table()->GetTo_Tdb(), 0)
  {
  Name = (char*)cp->GetName();
  Precision = Long = 0;
  Buf_Type = TYPE_ERROR;
  } // end of SPCBLK constructor

/***********************************************************************/
/*  WriteColumn: what this routine does is to access the last line     */
/*  read from the corresponding table, and rewrite the field           */
/*  corresponding to this column from the column buffer and type.      */
/***********************************************************************/
void SPCBLK::WriteColumn(PGLOBAL g)
{
  sprintf(g->Message, MSG(SPCOL_READONLY), Name);
	throw (int)TYPE_COLBLK;
} // end of WriteColumn

/***********************************************************************/
/*  RIDBLK constructor for the ROWID special column.                   */
/***********************************************************************/
RIDBLK::RIDBLK(PCOLUMN cp, bool rnm) : SPCBLK(cp)
  {
  Precision = Long = 10;
  Buf_Type = TYPE_INT;
  Rnm = rnm;
  *Format.Type = 'N';
  Format.Length = 10;
  } // end of RIDBLK constructor

/***********************************************************************/
/*  ReadColumn: what this routine does is to return the ordinal        */
/*  number of the current row in the table (if Rnm is true) or in the  */
/*  current file (if Rnm is false) the same except for multiple tables.*/
/***********************************************************************/
void RIDBLK::ReadColumn(PGLOBAL g)
  {
  Value->SetValue(To_Tdb->RowNumber(g, Rnm));
  } // end of ReadColumn

/***********************************************************************/
/*  FIDBLK constructor for the FILEID special column.                  */
/***********************************************************************/
FIDBLK::FIDBLK(PCOLUMN cp, OPVAL op) : SPCBLK(cp), Op(op)
  {
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
  Precision = Long = _MAX_PATH;
  Buf_Type = TYPE_STRING;
  *Format.Type = 'C';
  Format.Length = Long;
#if defined(__WIN__)
  Format.Prec = 1;          // Case insensitive
#endif   // __WIN__
  Constant = (!To_Tdb->GetDef()->GetMultiple() &&
              To_Tdb->GetAmType() != TYPE_AM_PLG &&
              To_Tdb->GetAmType() != TYPE_AM_PLM);
  Fn = NULL;
  } // end of FIDBLK constructor

/***********************************************************************/
/*  ReadColumn: what this routine does is to return the current        */
/*  file ID of the table (can change for Multiple tables).             */
/***********************************************************************/
void FIDBLK::ReadColumn(PGLOBAL g)
  {
  if (Fn != To_Tdb->GetFile(g)) {
    char filename[_MAX_PATH];

    Fn = To_Tdb->GetFile(g);
    PlugSetPath(filename, Fn, To_Tdb->GetPath());

    if (Op != OP_XX) {
      char buff[_MAX_PATH];

      Value->SetValue_psz(ExtractFromPath(g, buff, filename, Op));
    } else
      Value->SetValue_psz(filename);

    } // endif Fn

  } // end of ReadColumn

/***********************************************************************/
/*  TIDBLK constructor for the TABID special column.                   */
/***********************************************************************/
TIDBLK::TIDBLK(PCOLUMN cp) : SPCBLK(cp)
  {
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
  Precision = Long = 64;
  Buf_Type = TYPE_STRING;
  *Format.Type = 'C';
  Format.Length = Long;
  Format.Prec = 1;          // Case insensitive
  Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
  Tname = NULL;
  } // end of TIDBLK constructor

/***********************************************************************/
/*  ReadColumn: what this routine does is to return the table ID.      */
/***********************************************************************/
void TIDBLK::ReadColumn(PGLOBAL)
  {
  if (Tname == NULL) {
    Tname = (char*)To_Tdb->GetName();
    Value->SetValue_psz(Tname);
    } // endif Tname

  } // end of ReadColumn

/***********************************************************************/
/*  PRTBLK constructor for the PARTID special column.                  */
/***********************************************************************/
PRTBLK::PRTBLK(PCOLUMN cp) : SPCBLK(cp)
  {
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
  Precision = Long = 64;
  Buf_Type = TYPE_STRING;
  *Format.Type = 'C';
  Format.Length = Long;
  Format.Prec = 1;          // Case insensitive
  Constant = true;          // TODO: check whether this is true indeed
  Pname = NULL;
  } // end of PRTBLK constructor

/***********************************************************************/
/*  ReadColumn: what this routine does is to return the partition ID.  */
/***********************************************************************/
void PRTBLK::ReadColumn(PGLOBAL g)
  {
  if (Pname == NULL) {
    const char *p;

    Pname = To_Tdb->GetDef()->GetStringCatInfo(g, "partname", "?");
    p = strrchr(Pname, '#');
    Value->SetValue_psz((p) ? p + 1 : Pname);
    } // endif Pname

  } // end of ReadColumn

/***********************************************************************/
/*  SIDBLK constructor for the SERVID special column.                  */
/***********************************************************************/
SIDBLK::SIDBLK(PCOLUMN cp) : SPCBLK(cp)
  {
//Is_Key = 2; for when the MUL table indexed reading will be implemented.
  Precision = Long = 64;
  Buf_Type = TYPE_STRING;
  *Format.Type = 'C';
  Format.Length = Long;
  Format.Prec = 1;          // Case insensitive
  Constant = (To_Tdb->GetAmType() != TYPE_AM_TBL);
  Sname = NULL;
  } // end of TIDBLK constructor

/***********************************************************************/
/*  ReadColumn: what this routine does is to return the server ID.     */
/***********************************************************************/
void SIDBLK::ReadColumn(PGLOBAL)
  {
//if (Sname == NULL) {
    Sname = To_Tdb->GetServer();
    Value->SetValue_psz(Sname);
//  } // endif Sname

  } // end of ReadColumn