1 /************* Value C++ Functions Source Code File (.CPP) *************/
2 /*  Name: VALUE.CPP  Version 2.9                                       */
3 /*                                                                     */
4 /*  (C) Copyright to the author Olivier BERTRAND          2001-2019    */
5 /*                                                                     */
6 /*  This file contains the VALUE and derived classes family functions. */
7 /*  These classes contain values of different types. They are used so  */
8 /*  new object types can be defined and added to the processing simply */
9 /*  (hopefully) adding their specific functions in this file.          */
10 /*  First family is VALUE that represent single typed objects. It is   */
11 /*  used by columns (COLBLK), SELECT and FILTER (derived) objects.     */
12 /*  Second family is VALBLK, representing simple suballocated arrays   */
13 /*  of values treated sequentially by FIX, BIN and VCT tables and      */
14 /*  columns, as well for min/max blocks as for VCT column blocks.      */
15 /*  Q&A: why not using only one family ? Simple values are arrays that */
16 /*  have only one element and arrays could have functions for all kind */
17 /*  of processing. The answer is a-because historically it was simpler */
18 /*  to do that way, b-because of performance on single values, and c-  */
19 /*  to avoid too complicated classes and unuseful duplication of many  */
20 /*  functions used on one family only. The drawback is that for new    */
21 /*  types of objects, we shall have more classes to update.            */
22 /*  Currently the only implemented types are STRING, INT, SHORT, TINY, */
23 /*  DATE and LONGLONG. Recently we added some UNSIGNED types.          */
24 /***********************************************************************/
25 
26 /***********************************************************************/
27 /*  Include relevant MariaDB header file.                              */
28 /***********************************************************************/
29 #include "my_global.h"
30 #include "sql_class.h"
31 #include "sql_time.h"
32 
33 #if defined(_WIN32)
34 //#include <windows.h>
35 #else   // !_WIN32
36 #include <string.h>
37 #endif  // !_WIN32
38 
39 #include <math.h>
40 
41 #undef DOMAIN                           // Was defined in math.h
42 
43 /***********************************************************************/
44 /*  Include required application header files                          */
45 /*  global.h    is header containing all global Plug declarations.     */
46 /*  plgdbsem.h  is header containing the DB applic. declarations.      */
47 /***********************************************************************/
48 #include "global.h"
49 #include "plgdbsem.h"
50 #include "preparse.h"                     // For DATPAR
51 #include "valblk.h"
52 #define NO_FUNC                           // Already defined in ODBConn
53 #include "plgcnx.h"                       // For DB types
54 #include "osutil.h"
55 
56 /***********************************************************************/
57 /*  Check macro's.                                                     */
58 /***********************************************************************/
59 #if defined(_DEBUG)
60 #define CheckType(V)    if (Type != V->GetType()) { \
61     PGLOBAL& g = Global; \
62     strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
63     throw Type;
64 #else
65 #define CheckType(V)
66 #endif
67 
68 #define FOURYEARS    126230400    // Four years in seconds (1 leap)
69 
70 /***********************************************************************/
71 /*  Initialize the DTVAL static member.                                */
72 /***********************************************************************/
73 int DTVAL::Shift = 0;
74 
75 /***********************************************************************/
76 /*  Routines called externally.                                        */
77 /***********************************************************************/
78 bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
79 
80 #if !defined(_WIN32)
81 extern "C" {
82 PSZ strupr(PSZ s);
83 PSZ strlwr(PSZ s);
84 }
85 #endif   // !_WIN32
86 
87 /***********************************************************************/
88 /*  Get a long long number from its character representation.          */
89 /*  IN  p: Pointer to the numeric string                               */
90 /*  IN  n: The string length                                           */
91 /*  IN  maxval: The number max value                                   */
92 /*  IN  un: True if the number must be unsigned                        */
93 /*  OUT rc: Set to TRUE for out of range value                         */
94 /*  OUT minus: Set to true if the number is negative                   */
95 /*  Returned val: The resulting number                                 */
96 /***********************************************************************/
CharToNumber(const char * p,int n,ulonglong maxval,bool un,bool * minus,bool * rc)97 ulonglong CharToNumber(const char *p, int n, ulonglong maxval,
98                        bool un, bool *minus, bool *rc)
99 {
100   const char *p2;
101   uchar       c;
102   ulonglong   val;
103 
104   if (minus) *minus = false;
105   if (rc) *rc = false;
106 	if (n <= 0) return 0LL;
107 
108   // Eliminate leading blanks or 0
109   for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ;
110 
111   // Get an eventual sign character
112   switch (*p) {
113     case '-':
114       if (un) {
115         if (rc) *rc = true;
116         return 0;
117       } else {
118         maxval++;
119         if (minus) *minus = true;
120       } // endif Unsigned
121 
122 			// Fall through
123     case '+':
124       p++;
125       break;
126   } // endswitch *p
127 
128   for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++)
129     if (val > (maxval - c) / 10) {
130       val = maxval;
131       if (rc) *rc = true;
132       break;
133     } else
134       val = val * 10 + c;
135 
136   return val;
137 } // end of CharToNumber
138 
139 /***********************************************************************/
140 /*  GetTypeName: returns the PlugDB internal type name.                */
141 /***********************************************************************/
GetTypeName(int type)142 PCSZ GetTypeName(int type)
143 {
144   PCSZ name;
145 
146   switch (type) {
147     case TYPE_STRING: name = "CHAR";     break;
148     case TYPE_SHORT:  name = "SMALLINT"; break;
149     case TYPE_INT:    name = "INTEGER";  break;
150     case TYPE_BIGINT: name = "BIGINT";   break;
151     case TYPE_DATE:   name = "DATE";     break;
152     case TYPE_DOUBLE: name = "DOUBLE";   break;
153     case TYPE_TINY:   name = "TINY";     break;
154     case TYPE_DECIM:  name = "DECIMAL";  break;
155     case TYPE_BIN:    name = "BINARY";   break;
156     case TYPE_PCHAR:  name = "PCHAR";    break;
157     default:          name = "UNKNOWN";  break;
158   } // endswitch type
159 
160   return name;
161 } // end of GetTypeName
162 
163 /***********************************************************************/
164 /*  GetTypeSize: returns the PlugDB internal type size.                */
165 /***********************************************************************/
GetTypeSize(int type,int len)166 int GetTypeSize(int type, int len)
167   {
168 	switch (type) {
169     case TYPE_DECIM:
170     case TYPE_BIN:
171     case TYPE_STRING: len = len * sizeof(char); break;
172     case TYPE_SHORT:  len = sizeof(short);      break;
173     case TYPE_INT:    len = sizeof(int);        break;
174     case TYPE_BIGINT: len = sizeof(longlong);   break;
175     case TYPE_DATE:   len = sizeof(int);        break;
176     case TYPE_DOUBLE: len = sizeof(double);     break;
177     case TYPE_TINY:   len = sizeof(char);       break;
178     case TYPE_PCHAR:  len = sizeof(char*);      break;
179     default:          len = -1;
180   } // endswitch type
181 
182   return len;
183 } // end of GetTypeSize
184 
185 /***********************************************************************/
186 /*  GetFormatType: returns the FORMAT character(s) according to type.  */
187 /***********************************************************************/
GetFormatType(int type)188 const char *GetFormatType(int type)
189 {
190   const char *c = "X";
191 
192   switch (type) {
193     case TYPE_STRING: c = "C"; break;
194     case TYPE_SHORT:  c = "S"; break;
195     case TYPE_INT:    c = "N"; break;
196     case TYPE_BIGINT: c = "L"; break;
197     case TYPE_DOUBLE: c = "F"; break;
198     case TYPE_DATE:   c = "D"; break;
199     case TYPE_TINY:   c = "T"; break;
200     case TYPE_DECIM:  c = "F"; break;
201     case TYPE_BIN:    c = "B"; break;
202     case TYPE_PCHAR:  c = "P"; break;
203   } // endswitch type
204 
205   return c;
206 } // end of GetFormatType
207 
208 /***********************************************************************/
209 /*  GetFormatType: returns the FORMAT type according to character.     */
210 /***********************************************************************/
GetFormatType(char c)211 int GetFormatType(char c)
212 {
213   int type = TYPE_ERROR;
214 
215   switch (c) {
216     case 'C': type = TYPE_STRING; break;
217     case 'S': type = TYPE_SHORT;  break;
218     case 'N': type = TYPE_INT;    break;
219     case 'L': type = TYPE_BIGINT; break;
220     case 'F': type = TYPE_DOUBLE; break;
221     case 'D': type = TYPE_DATE;   break;
222     case 'T': type = TYPE_TINY;   break;
223     case 'M': type = TYPE_DECIM;  break;
224     case 'B': type = TYPE_BIN;    break;
225     case 'P': type = TYPE_PCHAR;  break;
226   } // endswitch type
227 
228   return type;
229 } // end of GetFormatType
230 
231 /***********************************************************************/
232 /*  IsTypeChar: returns true for character type(s).                    */
233 /***********************************************************************/
IsTypeChar(int type)234 bool IsTypeChar(int type)
235 {
236   switch (type) {
237     case TYPE_STRING:
238     case TYPE_DECIM:
239 		case TYPE_BIN:
240       return true;
241   } // endswitch type
242 
243   return false;
244 } // end of IsTypeChar
245 
246 /***********************************************************************/
247 /*  IsTypeNum: returns true for numeric types.                         */
248 /***********************************************************************/
IsTypeNum(int type)249 bool IsTypeNum(int type)
250 {
251   switch (type) {
252     case TYPE_INT:
253     case TYPE_BIGINT:
254     case TYPE_DATE:
255     case TYPE_DOUBLE:
256     case TYPE_SHORT:
257     case TYPE_NUM:
258     case TYPE_TINY:
259     case TYPE_DECIM:
260       return true;
261   } // endswitch type
262 
263   return false;
264 } // end of IsTypeNum
265 
266 /***********************************************************************/
267 /*  GetFmt: returns the format to use with a typed value.              */
268 /***********************************************************************/
GetFmt(int type,bool un)269 const char *GetFmt(int type, bool un)
270 {
271   const char *fmt;
272 
273   switch (type) {
274     case TYPE_DECIM:
275     case TYPE_STRING: fmt = "%s";                   break;
276     case TYPE_SHORT:  fmt = (un) ? "%hu" : "%hd";   break;
277     case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
278     case TYPE_DOUBLE: fmt = "%.*lf";                break;
279     case TYPE_BIN:    fmt = "%*x";                  break;
280     default:          fmt = (un) ? "%u" : "%d";     break;
281   } // endswitch Type
282 
283   return fmt;
284 } // end of GetFmt
285 
286 /***********************************************************************/
287 /*  ConvertType: what this function does is to determine the type to   */
288 /*  which should be converted a value so no precision would be lost.   */
289 /*  This can be a numeric type if num is true or non numeric if false. */
290 /*  Note: this is an ultra simplified version of this function that    */
291 /*  should become more and more complex as new types are added.        */
292 /*  Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from    */
293 /*  IsType... functions so match does not prevent correct setting.     */
294 /***********************************************************************/
ConvertType(int target,int type,CONV kind,bool match)295 int ConvertType(int target, int type, CONV kind, bool match)
296 {
297   switch (kind) {
298     case CNV_CHAR:
299       if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
300         return TYPE_ERROR;
301 
302       return TYPE_STRING;
303     case CNV_NUM:
304       if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
305         return TYPE_ERROR;
306 
307       return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
308            : (target == TYPE_DATE   || type == TYPE_DATE)   ? TYPE_DATE
309            : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
310            : (target == TYPE_INT    || type == TYPE_INT)    ? TYPE_INT
311            : (target == TYPE_SHORT  || type == TYPE_SHORT)  ? TYPE_SHORT
312                                                             : TYPE_TINY;
313     default:
314       if (target == TYPE_ERROR || target == type)
315         return type;
316 
317       if (match && ((IsTypeChar(target) && !IsTypeChar(type)) ||
318                     (IsTypeNum(target) && !IsTypeNum(type))))
319         return TYPE_ERROR;
320 
321       return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
322            : (target == TYPE_DATE   || type == TYPE_DATE)   ? TYPE_DATE
323            : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
324            : (target == TYPE_INT    || type == TYPE_INT)    ? TYPE_INT
325            : (target == TYPE_SHORT  || type == TYPE_SHORT)  ? TYPE_SHORT
326            : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
327            : (target == TYPE_TINY   || type == TYPE_TINY)   ? TYPE_TINY
328                                                             : TYPE_ERROR;
329   } // endswitch kind
330 
331 } // end of ConvertType
332 
333 /***********************************************************************/
334 /*  AllocateConstant: allocates a constant Value.                      */
335 /***********************************************************************/
AllocateValue(PGLOBAL g,void * value,short type,short prec)336 PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
337 {
338   PVAL valp;
339 
340   if (trace(1))
341     htrc("AllocateConstant: value=%p type=%hd\n", value, type);
342 
343   switch (type) {
344     case TYPE_STRING:
345       valp = new(g) TYPVAL<PSZ>((PSZ)value, prec);
346       break;
347     case TYPE_SHORT:
348       valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
349       break;
350     case TYPE_INT:
351       valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT);
352       break;
353     case TYPE_BIGINT:
354       valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
355       break;
356     case TYPE_DOUBLE:
357       valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, prec);
358       break;
359     case TYPE_TINY:
360       valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
361       break;
362     default:
363       sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
364       return NULL;
365   } // endswitch Type
366 
367   valp->SetGlobal(g);
368   return valp;
369 } // end of AllocateValue
370 
371 /***********************************************************************/
372 /*  Allocate a variable Value according to type, length and precision. */
373 /***********************************************************************/
AllocateValue(PGLOBAL g,int type,int len,int prec,bool uns,PCSZ fmt)374 PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
375                    bool uns, PCSZ fmt)
376 {
377   PVAL valp;
378 
379   switch (type) {
380     case TYPE_STRING:
381       valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
382       break;
383 		case TYPE_DATE:
384 			valp = new(g) DTVAL(g, len, prec, fmt);
385       break;
386     case TYPE_INT:
387       if (uns)
388         valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
389       else
390         valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
391 
392       break;
393     case TYPE_BIGINT:
394       if (uns)
395         valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
396       else
397         valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
398 
399       break;
400     case TYPE_SHORT:
401       if (uns)
402         valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
403       else
404         valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
405 
406       break;
407     case TYPE_DOUBLE:
408       valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec);
409       break;
410     case TYPE_TINY:
411       if (uns)
412         valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
413       else
414         valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
415 
416       break;
417     case TYPE_DECIM:
418       valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
419       break;
420     case TYPE_BIN:
421       valp = new(g) BINVAL(g, (void*)NULL, len, prec);
422       break;
423     default:
424       sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
425       return NULL;
426   } // endswitch type
427 
428   valp->SetGlobal(g);
429   return valp;
430 } // end of AllocateValue
431 
432 /***********************************************************************/
433 /*  Allocate a constant Value converted to newtype.                    */
434 /*  Can also be used to copy a Value eventually converted.             */
435 /***********************************************************************/
AllocateValue(PGLOBAL g,PVAL valp,int newtype,int uns)436 PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
437 {
438   PSZ  p, sp;
439   bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
440   PVAL vp;
441 
442   if (!valp)
443     return NULL;
444 
445   if (newtype == TYPE_VOID)  // Means allocate a value of the same type
446     newtype = valp->GetType();
447 
448   switch (newtype) {
449     case TYPE_STRING:
450       p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
451 
452       if ((sp = valp->GetCharString(p)) != p && sp)
453         strcpy(p, sp);
454 
455       vp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
456       break;
457     case TYPE_SHORT:
458       if (un)
459         vp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
460                                    TYPE_SHORT, 0, true);
461       else
462         vp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
463 
464       break;
465     case TYPE_INT:
466       if (un)
467         vp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
468       else
469         vp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
470 
471       break;
472     case TYPE_BIGINT:
473       if (un)
474         vp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
475                                       TYPE_BIGINT, 0, true);
476       else
477         vp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
478 
479       break;
480     case TYPE_DATE:
481       vp = new(g) DTVAL(valp->GetIntValue());
482       break;
483     case TYPE_DOUBLE:
484       vp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
485                    (uns) ? uns : valp->GetValPrec());
486       break;
487     case TYPE_TINY:
488       if (un)
489         vp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
490                                     TYPE_TINY, 0, true);
491       else
492         vp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
493 
494       break;
495     default:
496       sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
497       return NULL;
498   } // endswitch type
499 
500   vp->SetNullable(valp->GetNullable());
501   vp->SetNull(valp->IsNull());
502   vp->SetGlobal(g);
503   return vp;
504 } // end of AllocateValue
505 
506 /* -------------------------- Class VALUE ---------------------------- */
507 
508 /***********************************************************************/
509 /*  Class VALUE protected constructor.                                 */
510 /***********************************************************************/
VALUE(int type,bool un)511 VALUE::VALUE(int type, bool un) : Type(type)
512 {
513   Null = false;
514   Nullable = false;
515   Unsigned = un;
516   Clen = 0;
517   Prec = 0;
518   Fmt = GetFmt(Type, Unsigned);
519   Xfmt = GetXfmt();
520 } // end of VALUE constructor
521 
522 /***********************************************************************/
523 /* VALUE GetXfmt: returns the extended format to use with typed value. */
524 /***********************************************************************/
GetXfmt(void)525 const char *VALUE::GetXfmt(void)
526 {
527   const char *fmt;
528 
529   switch (Type) {
530     case TYPE_DECIM:
531     case TYPE_STRING: fmt = "%*s";                          break;
532     case TYPE_SHORT:  fmt = (Unsigned) ? "%*hu" : "%*hd";   break;
533     case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
534     case TYPE_DOUBLE: fmt = "%*.*lf";                       break;
535     case TYPE_BIN:    fmt = "%*x";                          break;
536     default:          fmt = (Unsigned) ? "%*u" : "%*d";     break;
537     } // endswitch Type
538 
539   return fmt;
540 } // end of GetXFmt
541 
542 /***********************************************************************/
543 /*  Returns a BYTE indicating the comparison between two values.       */
544 /*  Bit 1 indicates equality, Bit 2 less than, and Bit3 greater than.  */
545 /*  More than 1 bit can be set only in the case of TYPE_LIST.          */
546 /***********************************************************************/
TestValue(PVAL vp)547 BYTE VALUE::TestValue(PVAL vp)
548 {
549   int n = CompareValue(vp);
550 
551   return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
552 } // end of TestValue
553 
554 /***********************************************************************/
555 /*  Compute a function on a string.                                    */
556 /***********************************************************************/
Compute(PGLOBAL g,PVAL *,int,OPVAL)557 bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
558 {
559   strcpy(g->Message, "Compute not implemented for this value type");
560   return true;
561 } // end of Compute
562 
563 /***********************************************************************/
564 /*  Make file output of an object value.                               */
565 /***********************************************************************/
Printf(PGLOBAL g,FILE * f,uint n)566 void VALUE::Printf(PGLOBAL g, FILE *f, uint n)
567 {
568 	char m[64], buf[64];
569 
570 	memset(m, ' ', n);                             /* Make margin string */
571 	m[n] = '\0';
572 
573 	if (Null)
574 		fprintf(f, "%s<null>\n", m);
575 	else
576 		fprintf(f, "%s%s\n", m, GetCharString(buf));
577 
578 } /* end of Printf */
579 
580 /***********************************************************************/
581 /*  Make string output of an object value.                             */
582 /***********************************************************************/
Prints(PGLOBAL g,char * ps,uint z)583 void VALUE::Prints(PGLOBAL g, char *ps, uint z)
584 {
585 	char *p, buf[64];
586 
587 	if (Null)
588 		p = strcpy(buf, "<null>");
589 	else
590 		p = GetCharString(buf);
591 
592   strncpy(ps, p, z);
593 } // end of Prints
594 
595 /* -------------------------- Class TYPVAL ---------------------------- */
596 
597 /***********************************************************************/
598 /*  TYPVAL  public constructor from a constant typed value.            */
599 /***********************************************************************/
600 template <class TYPE>
TYPVAL(TYPE n,int type,int prec,bool un)601 TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
602             : VALUE(type, un)
603 {
604   Tval = n;
605   Clen = sizeof(TYPE);
606   Prec = prec;
607 } // end of TYPVAL constructor
608 
609 /***********************************************************************/
610 /*  Return unsigned max value for the type.                            */
611 /***********************************************************************/
612 template <class TYPE>
MaxVal(void)613 ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
614 
615 template <>
MaxVal(void)616 ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;}
617 
618 template <>
MaxVal(void)619 ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;}
620 
621 template <>
MaxVal(void)622 ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;}
623 
624 template <>
MaxVal(void)625 ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;}
626 
627 template <>
MaxVal(void)628 ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;}
629 
630 template <>
MaxVal(void)631 ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;}
632 
633 template <>
MaxVal(void)634 ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;}
635 
636 template <>
MaxVal(void)637 ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
638 
639 /***********************************************************************/
640 /*  TYPVAL GetValLen: returns the print length of the typed object.    */
641 /***********************************************************************/
642 template <class TYPE>
GetValLen(void)643 int TYPVAL<TYPE>::GetValLen(void)
644 {
645   char c[32];
646 
647   return snprintf(c, 32, Fmt, Tval);
648 } // end of GetValLen
649 
650 template <>
GetValLen(void)651 int TYPVAL<double>::GetValLen(void)
652 {
653   char c[32];
654 
655   return snprintf(c, 32, Fmt, Prec, Tval);
656 } // end of GetValLen
657 
658 /***********************************************************************/
659 /*  TYPVAL SetValue: copy the value of another Value object.           */
660 /*  This function allows conversion if chktype is false.               */
661 /***********************************************************************/
662 template <class TYPE>
SetValue_pval(PVAL valp,bool chktype)663 bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
664 {
665   if (valp != this) {
666     if (chktype && Type != valp->GetType())
667       return true;
668 
669     if (!(Null = (valp->IsNull() && Nullable)))
670       Tval = GetTypedValue(valp);
671     else
672       Reset();
673 
674   } // endif valp
675 
676   return false;
677 } // end of SetValue
678 
679 template <>
GetTypedValue(PVAL valp)680 short TYPVAL<short>::GetTypedValue(PVAL valp)
681   {return valp->GetShortValue();}
682 
683 template <>
GetTypedValue(PVAL valp)684 ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
685   {return valp->GetUShortValue();}
686 
687 template <>
GetTypedValue(PVAL valp)688 int TYPVAL<int>::GetTypedValue(PVAL valp)
689   {return valp->GetIntValue();}
690 
691 template <>
GetTypedValue(PVAL valp)692 uint TYPVAL<uint>::GetTypedValue(PVAL valp)
693   {return valp->GetUIntValue();}
694 
695 template <>
GetTypedValue(PVAL valp)696 longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
697   {return valp->GetBigintValue();}
698 
699 template <>
GetTypedValue(PVAL valp)700 ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
701   {return valp->GetUBigintValue();}
702 
703 template <>
GetTypedValue(PVAL valp)704 double TYPVAL<double>::GetTypedValue(PVAL valp)
705   {return valp->GetFloatValue();}
706 
707 template <>
GetTypedValue(PVAL valp)708 char TYPVAL<char>::GetTypedValue(PVAL valp)
709   {return valp->GetTinyValue();}
710 
711 template <>
GetTypedValue(PVAL valp)712 uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
713   {return valp->GetUTinyValue();}
714 
715 /***********************************************************************/
716 /*  TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
717 /***********************************************************************/
718 template <class TYPE>
SetValue_char(const char * p,int n)719 bool TYPVAL<TYPE>::SetValue_char(const char *p, int n)
720 {
721   bool      rc, minus;
722   ulonglong maxval = MaxVal();
723   ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc);
724 
725   if (minus && val < maxval)
726     Tval = (TYPE)(-(signed)val);
727   else
728     Tval = (TYPE)val;
729 
730   if (trace(2)) {
731     char buf[64];
732     htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
733                               GetTypeName(Type), Tval);
734   } // endif trace
735 
736   Null = false;
737   return rc;
738 } // end of SetValue
739 
740 template <>
SetValue_char(const char * p,int n)741 bool TYPVAL<double>::SetValue_char(const char *p, int n)
742 {
743   if (p && n > 0) {
744     char buf[64];
745 
746     for (; n > 0 && *p == ' '; p++)
747       n--;
748 
749     memcpy(buf, p, MY_MIN(n, 31));
750     buf[n] = '\0';
751     Tval = atof(buf);
752 
753     if (trace(2))
754       htrc(" setting double: '%s' -> %lf\n", buf, Tval);
755 
756     Null = false;
757   } else {
758     Reset();
759     Null = Nullable;
760   } // endif p
761 
762   return false;
763 } // end of SetValue
764 
765 /***********************************************************************/
766 /*  TYPVAL SetValue: fill a typed value from a string.                 */
767 /***********************************************************************/
768 template <class TYPE>
SetValue_psz(PCSZ s)769 void TYPVAL<TYPE>::SetValue_psz(PCSZ s)
770 {
771   if (s) {
772     SetValue_char(s, (int)strlen(s));
773     Null = false;
774   } else {
775     Reset();
776     Null = Nullable;
777   } // endif p
778 
779 } // end of SetValue
780 
781 /***********************************************************************/
782 /*  TYPVAL SetValue: set value with a TYPE extracted from a block.     */
783 /***********************************************************************/
784 template <class TYPE>
SetValue_pvblk(PVBLK blk,int n)785 void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
786 {
787   Tval = GetTypedValue(blk, n);
788   Null = false;
789 } // end of SetValue
790 
791 template <>
GetTypedValue(PVBLK blk,int n)792 int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
793   {return blk->GetIntValue(n);}
794 
795 template <>
GetTypedValue(PVBLK blk,int n)796 uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
797   {return blk->GetUIntValue(n);}
798 
799 template <>
GetTypedValue(PVBLK blk,int n)800 short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
801   {return blk->GetShortValue(n);}
802 
803 template <>
GetTypedValue(PVBLK blk,int n)804 ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
805   {return blk->GetUShortValue(n);}
806 
807 template <>
GetTypedValue(PVBLK blk,int n)808 longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
809   {return blk->GetBigintValue(n);}
810 
811 template <>
GetTypedValue(PVBLK blk,int n)812 ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
813   {return blk->GetUBigintValue(n);}
814 
815 template <>
GetTypedValue(PVBLK blk,int n)816 double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
817   {return blk->GetFloatValue(n);}
818 
819 template <>
GetTypedValue(PVBLK blk,int n)820 char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
821   {return blk->GetTinyValue(n);}
822 
823 template <>
GetTypedValue(PVBLK blk,int n)824 uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
825   {return blk->GetUTinyValue(n);}
826 
827 /***********************************************************************/
828 /*  TYPVAL SetBinValue: with bytes extracted from a line.              */
829 /*  Currently only used reading column of binary files.                */
830 /***********************************************************************/
831 template <class TYPE>
SetBinValue(void * p)832 void TYPVAL<TYPE>::SetBinValue(void *p)
833 {
834 #if defined(UNALIGNED_OK)
835 	// x86 can cast non-aligned memory directly
836 	Tval = *(TYPE *)p;
837 #else
838 	// Prevent unaligned memory access on MIPS and ArmHF platforms.
839 	// Make use of memcpy instead of straight pointer dereferencing.
840 	// Currently only used by WriteColumn of binary files.
841 	// From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
842 	memcpy(&Tval, p, sizeof(TYPE));
843 #endif
844 	Null = false;
845 } // end of SetBinValue
846 
847 /***********************************************************************/
848 /*  GetBinValue: fill a buffer with the internal binary value.         */
849 /*  This function checks whether the buffer length is enough and       */
850 /*  returns true if not. Actual filling occurs only if go is true.     */
851 /*  Currently only used writing column of binary files.                */
852 /***********************************************************************/
853 template <class TYPE>
GetBinValue(void * buf,int buflen,bool go)854 bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
855 {
856   // Test on length was removed here until a variable in column give the
857   // real field length. For BIN files the field length logically cannot
858   // be different from the variable length because no conversion is done.
859   // Therefore this test is useless anyway.
860 //#if defined(_DEBUG)
861 //  if (sizeof(TYPE) > buflen)
862 //    return true;
863 //#endif
864 
865   if (go)
866 #if defined(UNALIGNED_OK)
867 		// x86 can cast non-aligned memory directly
868 		*(TYPE *)buf = Tval;
869 #else
870 		// Prevent unaligned memory access on MIPS and ArmHF platforms.
871 		// Make use of memcpy instead of straight pointer dereferencing.
872 		// Currently only used by WriteColumn of binary files.
873 		// From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
874 		memcpy(buf, &Tval, sizeof(TYPE));
875 #endif
876 
877   Null = false;
878   return false;
879 } // end of GetBinValue
880 
881 /***********************************************************************/
882 /*  TYPVAL ShowValue: get string representation of a typed value.      */
883 /***********************************************************************/
884 template <class TYPE>
ShowValue(char * buf,int len)885 int TYPVAL<TYPE>::ShowValue(char *buf, int len)
886 {
887   return snprintf(buf, len + 1, Xfmt, len, Tval);
888 } // end of ShowValue
889 
890 template <>
ShowValue(char * buf,int len)891 int TYPVAL<double>::ShowValue(char *buf, int len)
892 {
893   // TODO: use a more appropriate format to avoid possible truncation
894   return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
895 } // end of ShowValue
896 
897 /***********************************************************************/
898 /*  TYPVAL GetCharString: get string representation of a typed value.  */
899 /***********************************************************************/
900 template <class TYPE>
GetCharString(char * p)901 char *TYPVAL<TYPE>::GetCharString(char *p)
902 {
903   sprintf(p, Fmt, Tval);
904   return p;
905 } // end of GetCharString
906 
907 template <>
GetCharString(char * p)908 char *TYPVAL<double>::GetCharString(char *p)
909 {
910 	// Most callers use a 32 long buffer
911   snprintf(p, 32, Fmt, Prec, Tval);
912   return p;
913 } // end of GetCharString
914 
915 #if 0
916 /***********************************************************************/
917 /*  TYPVAL GetShortString: get short representation of a typed value.  */
918 /***********************************************************************/
919 template <class TYPE>
920 char *TYPVAL<TYPE>::GetShortString(char *p, int n)
921 {
922   sprintf(p, "%*hd", n, (short)Tval);
923   return p;
924 } // end of GetShortString
925 
926 /***********************************************************************/
927 /*  TYPVAL GetIntString: get int representation of a typed value.      */
928 /***********************************************************************/
929 template <class TYPE>
930 char *TYPVAL<TYPE>::GetIntString(char *p, int n)
931 {
932   sprintf(p, "%*d", n, (int)Tval);
933   return p;
934 } // end of GetIntString
935 
936 /***********************************************************************/
937 /*  TYPVAL GetBigintString: get big int representation of a TYPE value.*/
938 /***********************************************************************/
939 template <class TYPE>
940 char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
941 {
942   sprintf(p, "%*lld", n, (longlong)Tval);
943   return p;
944 } // end of GetBigintString
945 
946 /***********************************************************************/
947 /*  TYPVAL GetFloatString: get double representation of a typed value. */
948 /***********************************************************************/
949 template <class TYPE>
950 char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
951 {
952   sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
953   return p;
954 } // end of GetFloatString
955 
956 /***********************************************************************/
957 /*  TYPVAL GetTinyString: get char representation of a typed value.    */
958 /***********************************************************************/
959 template <class TYPE>
960 char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
961 {
962   sprintf(p, "%*d", n, (int)(char)Tval);
963   return p;
964 } // end of GetIntString
965 #endif // 0
966 
967 /***********************************************************************/
968 /*  TYPVAL compare value with another Value.                           */
969 /***********************************************************************/
970 template <class TYPE>
IsEqual(PVAL vp,bool chktype)971 bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
972 {
973   if (this == vp)
974     return true;
975   else if (chktype && Type != vp->GetType())
976     return false;
977   else if (chktype && Unsigned != vp->IsUnsigned())
978     return false;
979   else if (Null || vp->IsNull())
980     return false;
981   else
982     return (Tval == GetTypedValue(vp));
983 
984 } // end of IsEqual
985 
986 /***********************************************************************/
987 /*  Compare values and returns 1, 0 or -1 according to comparison.     */
988 /*  This function is used for evaluation of numeric filters.           */
989 /***********************************************************************/
990 template <class TYPE>
CompareValue(PVAL vp)991 int TYPVAL<TYPE>::CompareValue(PVAL vp)
992 {
993 //assert(vp->GetType() == Type);
994 
995   // Process filtering on numeric values.
996   TYPE n = GetTypedValue(vp);
997 
998 //if (trace(1))
999 //  htrc(" Comparing: val=%d,%d\n", Tval, n);
1000 
1001   return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
1002 } // end of CompareValue
1003 
1004 /***********************************************************************/
1005 /*  Return max type value if b is true, else min type value.           */
1006 /***********************************************************************/
1007 template <>
MinMaxVal(bool b)1008 short TYPVAL<short>::MinMaxVal(bool b)
1009   {return (b) ? INT_MAX16 : INT_MIN16;}
1010 
1011 template <>
MinMaxVal(bool b)1012 ushort TYPVAL<ushort>::MinMaxVal(bool b)
1013   {return (b) ? UINT_MAX16 : 0;}
1014 
1015 template <>
MinMaxVal(bool b)1016 int TYPVAL<int>::MinMaxVal(bool b)
1017   {return (b) ? INT_MAX32 : INT_MIN32;}
1018 
1019 template <>
MinMaxVal(bool b)1020 uint TYPVAL<uint>::MinMaxVal(bool b)
1021   {return (b) ? UINT_MAX32 : 0;}
1022 
1023 template <>
MinMaxVal(bool b)1024 longlong TYPVAL<longlong>::MinMaxVal(bool b)
1025   {return (b) ? INT_MAX64 : INT_MIN64;}
1026 
1027 template <>
MinMaxVal(bool b)1028 ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b)
1029   {return (b) ? 0xFFFFFFFFFFFFFFFFLL : 0;}
1030 
1031 template <>
MinMaxVal(bool)1032 double TYPVAL<double>::MinMaxVal(bool)
1033   {assert(false); return 0.0;}
1034 
1035 template <>
MinMaxVal(bool b)1036 char TYPVAL<char>::MinMaxVal(bool b)
1037   {return (b) ? INT_MAX8 : INT_MIN8;}
1038 
1039 template <>
MinMaxVal(bool b)1040 uchar TYPVAL<uchar>::MinMaxVal(bool b)
1041   {return (b) ? UINT_MAX8 : 0;}
1042 
1043 /***********************************************************************/
1044 /*  SafeAdd: adds a value and test whether overflow/underflow occurred. */
1045 /***********************************************************************/
1046 template <class TYPE>
SafeAdd(TYPE n1,TYPE n2)1047 TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
1048 {
1049   PGLOBAL& g = Global;
1050   TYPE     n = n1 + n2;
1051 
1052   if ((n2 > 0) && (n < n1)) {
1053     // Overflow
1054     strcpy(g->Message, MSG(FIX_OVFLW_ADD));
1055 		throw 138;
1056 	} else if ((n2 < 0) && (n > n1)) {
1057     // Underflow
1058     strcpy(g->Message, MSG(FIX_UNFLW_ADD));
1059 		throw 138;
1060 	} // endif's n2
1061 
1062   return n;
1063 } // end of SafeAdd
1064 
1065 template <>
SafeAdd(double n1,double n2)1066 inline double TYPVAL<double>::SafeAdd(double n1, double n2)
1067 {
1068   return n1 + n2;
1069 } // end of SafeAdd
1070 
1071 /***********************************************************************/
1072 /*  SafeMult: multiply values and test whether overflow occurred.       */
1073 /***********************************************************************/
1074 template <class TYPE>
SafeMult(TYPE n1,TYPE n2)1075 TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
1076 {
1077   PGLOBAL& g = Global;
1078   double   n = (double)n1 * (double)n2;
1079 
1080   if (n > MinMaxVal(true)) {
1081     // Overflow
1082     strcpy(g->Message, MSG(FIX_OVFLW_TIMES));
1083 		throw 138;
1084 	} else if (n < MinMaxVal(false)) {
1085     // Underflow
1086     strcpy(g->Message, MSG(FIX_UNFLW_TIMES));
1087 		throw 138;
1088 	} // endif's n2
1089 
1090   return (TYPE)n;
1091 } // end of SafeMult
1092 
1093 template <>
SafeMult(double n1,double n2)1094 inline double TYPVAL<double>::SafeMult(double n1, double n2)
1095 {
1096   return n1 * n2;
1097 } // end of SafeMult
1098 
1099 /***********************************************************************/
1100 /*  Compute defined functions for the type.                            */
1101 /***********************************************************************/
1102 template <class TYPE>
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1103 bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1104 {
1105   bool rc = false;
1106   TYPE val[2];
1107 
1108   assert(np == 2);
1109 
1110   for (int i = 0; i < np; i++)
1111     val[i] = GetTypedValue(vp[i]);
1112 
1113   switch (op) {
1114     case OP_ADD:
1115       Tval = SafeAdd(val[0], val[1]);
1116       break;
1117     case OP_MULT:
1118       Tval = SafeMult(val[0], val[1]);
1119       break;
1120     case OP_DIV:
1121       if (!val[1]) {
1122         strcpy(g->Message, MSG(ZERO_DIVIDE));
1123         return true;
1124         } // endif
1125 
1126       Tval = val[0] / val[1];
1127       break;
1128     default:
1129       rc = Compall(g, vp, np, op);
1130       break;
1131   } // endswitch op
1132 
1133   return rc;
1134 } // end of Compute
1135 
1136 template <>
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1137 bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1138 {
1139   bool   rc = false;
1140   double val[2];
1141 
1142   assert(np == 2);
1143 
1144   for (int i = 0; i < np; i++)
1145     val[i] = vp[i]->GetFloatValue();
1146 
1147   switch (op) {
1148     case OP_ADD:
1149       Tval = val[0] + val[1];
1150       break;
1151     case OP_MULT:
1152       Tval = val[0] * val[1];
1153       break;
1154     default:
1155       rc = Compall(g, vp, np, op);
1156   } // endswitch op
1157 
1158   return rc;
1159 } // end of Compute
1160 
1161 /***********************************************************************/
1162 /*  Compute a function for all types.                                  */
1163 /***********************************************************************/
1164 template <class TYPE>
Compall(PGLOBAL g,PVAL * vp,int np,OPVAL op)1165 bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1166 {
1167   TYPE val[2];
1168 
1169   for (int i = 0; i < np; i++)
1170     val[i] = GetTypedValue(vp[i]);
1171 
1172   switch (op) {
1173     case OP_DIV:
1174       if (val[0]) {
1175         if (!val[1]) {
1176           strcpy(g->Message, MSG(ZERO_DIVIDE));
1177           return true;
1178           } // endif
1179 
1180         Tval = val[0] / val[1];
1181       } else
1182         Tval = 0;
1183 
1184       break;
1185     case OP_MIN:
1186       Tval = MY_MIN(val[0], val[1]);
1187       break;
1188     case OP_MAX:
1189       Tval = MY_MAX(val[0], val[1]);
1190       break;
1191     default:
1192 //    sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1193       strcpy(g->Message, "Function not supported");
1194       return true;
1195   } // endswitch op
1196 
1197   return false;
1198 } // end of Compall
1199 
1200 /***********************************************************************/
1201 /*  FormatValue: This function set vp (a STRING value) to the string   */
1202 /*  constructed from its own value formated using the fmt format.      */
1203 /*  This function assumes that the format matches the value type.      */
1204 /***********************************************************************/
1205 template <class TYPE>
FormatValue(PVAL vp,PCSZ fmt)1206 bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
1207 {
1208 	// This function is wrong and should never be called
1209 	assert(false);
1210   char *buf = (char*)vp->GetTo_Val();        // Not big enough
1211   int   n = sprintf(buf, fmt, Tval);
1212 
1213   return (n > vp->GetValLen());
1214 } // end of FormatValue
1215 
1216 /***********************************************************************/
1217 /*  TYPVAL  SetFormat function (used to set SELECT output format).     */
1218 /***********************************************************************/
1219 template <class TYPE>
SetConstFormat(PGLOBAL g,FORMAT & fmt)1220 bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
1221 {
1222   char c[32];
1223 
1224   fmt.Type[0] = *GetFormatType(Type);
1225   fmt.Length = sprintf(c, Fmt, Tval);
1226   fmt.Prec = Prec;
1227   return false;
1228 } // end of SetConstFormat
1229 
1230 /* -------------------------- Class STRING --------------------------- */
1231 
1232 /***********************************************************************/
1233 /*  STRING  public constructor from a constant string.                 */
1234 /***********************************************************************/
TYPVAL(PSZ s,short c)1235 TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
1236 {
1237   Strp = s;
1238   Len = strlen(s);
1239   Clen = Len;
1240   Ci = (c == 1);
1241 } // end of STRING constructor
1242 
1243 /***********************************************************************/
1244 /*  STRING public constructor from char.                               */
1245 /***********************************************************************/
TYPVAL(PGLOBAL g,PSZ s,int n,int c)1246 TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
1247            : VALUE(TYPE_STRING)
1248 {
1249   Len = (g) ? n : (s) ? strlen(s) : 0;
1250 
1251   if (!s) {
1252     if (g) {
1253       if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
1254         memset(Strp, 0, Len + 1);
1255       else
1256         Len = 0;
1257 
1258     } else
1259       assert(false);
1260 
1261   } else
1262     Strp = s;
1263 
1264   Clen = Len;
1265   Ci = (c != 0);
1266 } // end of STRING constructor
1267 
1268 /***********************************************************************/
1269 /*  Get the tiny value represented by the Strp string.                 */
1270 /***********************************************************************/
GetTinyValue(void)1271 char TYPVAL<PSZ>::GetTinyValue(void)
1272 {
1273   bool      m;
1274   ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
1275 
1276   return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
1277 } // end of GetTinyValue
1278 
1279 /***********************************************************************/
1280 /*  Get the unsigned tiny value represented by the Strp string.        */
1281 /***********************************************************************/
GetUTinyValue(void)1282 uchar TYPVAL<PSZ>::GetUTinyValue(void)
1283 {
1284   return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
1285 } // end of GetUTinyValue
1286 
1287 /***********************************************************************/
1288 /*  Get the short value represented by the Strp string.                */
1289 /***********************************************************************/
GetShortValue(void)1290 short TYPVAL<PSZ>::GetShortValue(void)
1291 {
1292   bool      m;
1293   ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
1294 
1295   return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
1296 } // end of GetShortValue
1297 
1298 /***********************************************************************/
1299 /*  Get the unsigned short value represented by the Strp string.       */
1300 /***********************************************************************/
GetUShortValue(void)1301 ushort TYPVAL<PSZ>::GetUShortValue(void)
1302 {
1303   return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
1304 } // end of GetUshortValue
1305 
1306 /***********************************************************************/
1307 /*  Get the integer value represented by the Strp string.              */
1308 /***********************************************************************/
GetIntValue(void)1309 int TYPVAL<PSZ>::GetIntValue(void)
1310 {
1311   bool      m;
1312   ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
1313 
1314   return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
1315 } // end of GetIntValue
1316 
1317 /***********************************************************************/
1318 /*  Get the unsigned integer value represented by the Strp string.     */
1319 /***********************************************************************/
GetUIntValue(void)1320 uint TYPVAL<PSZ>::GetUIntValue(void)
1321 {
1322   return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
1323 } // end of GetUintValue
1324 
1325 /***********************************************************************/
1326 /*  Get the big integer value represented by the Strp string.          */
1327 /***********************************************************************/
GetBigintValue(void)1328 longlong TYPVAL<PSZ>::GetBigintValue(void)
1329 {
1330   bool      m;
1331   ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
1332 
1333   return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
1334 } // end of GetBigintValue
1335 
1336 /***********************************************************************/
1337 /*  Get the unsigned big integer value represented by the Strp string. */
1338 /***********************************************************************/
GetUBigintValue(void)1339 ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
1340 {
1341   return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
1342 } // end of GetUBigintValue
1343 
1344 /***********************************************************************/
1345 /*  STRING SetValue: copy the value of another Value object.           */
1346 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)1347 bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
1348 {
1349   if (valp != this) {
1350     if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
1351       return true;
1352 
1353     char buf[64];
1354 
1355     if (!(Null = (valp->IsNull() && Nullable)))
1356       strncpy(Strp, valp->GetCharString(buf), Len);
1357     else
1358       Reset();
1359 
1360   } // endif valp
1361 
1362   return false;
1363 } // end of SetValue_pval
1364 
1365 /***********************************************************************/
1366 /*  STRING SetValue: fill string with chars extracted from a line.     */
1367 /***********************************************************************/
SetValue_char(const char * cp,int n)1368 bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
1369 {
1370   bool rc = false;
1371 
1372   if (!cp || n == 0) {
1373 		Reset();
1374 		Null = (cp) ? false : Nullable;
1375 	} else if (cp != Strp) {
1376 		const char *p = cp + n - 1;
1377 
1378 		for (; p >= cp; p--, n--)
1379 			if (*p && *p != ' ')
1380 				break;
1381 
1382 		rc = n > Len;
1383 
1384     if ((n = MY_MIN(n, Len))) {
1385     	strncpy(Strp, cp, n);
1386 	    Strp[n] = '\0';
1387 
1388       if (trace(2))
1389         htrc(" Setting string to: '%s'\n", Strp);
1390 
1391     } else
1392       Reset();
1393 
1394     Null = false;
1395   } // endif cp
1396 
1397   return rc;
1398 } // end of SetValue_char
1399 
1400 /***********************************************************************/
1401 /*  STRING SetValue: fill string with another string.                  */
1402 /***********************************************************************/
SetValue_psz(PCSZ s)1403 void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
1404 {
1405   if (!s) {
1406 		Reset();
1407 		Null = Nullable;
1408 	} else if (s != Strp) {
1409 		strncpy(Strp, s, Len);
1410     Null = false;
1411   } // endif s
1412 
1413 } // end of SetValue_psz
1414 
1415 /***********************************************************************/
1416 /*  STRING SetValue: fill string with a string extracted from a block. */
1417 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)1418 void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
1419 {
1420   // STRBLK's can return a NULL pointer
1421   PSZ vp = blk->GetCharString(Strp, n);
1422 
1423   if (vp != Strp)
1424     SetValue_psz(vp);
1425 
1426 } // end of SetValue_pvblk
1427 
1428 /***********************************************************************/
1429 /*  STRING SetValue: get the character representation of an integer.   */
1430 /***********************************************************************/
SetValue(int n)1431 void TYPVAL<PSZ>::SetValue(int n)
1432 {
1433   char     buf[16];
1434   PGLOBAL& g = Global;
1435   int      k = sprintf(buf, "%d", n);
1436 
1437   if (k > Len) {
1438     sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1439 		throw 138;
1440 	} else
1441     SetValue_psz(buf);
1442 
1443   Null = false;
1444 } // end of SetValue
1445 
1446 /***********************************************************************/
1447 /*  STRING SetValue: get the character representation of an uint.      */
1448 /***********************************************************************/
SetValue(uint n)1449 void TYPVAL<PSZ>::SetValue(uint n)
1450 {
1451   char     buf[16];
1452   PGLOBAL& g = Global;
1453   int      k = sprintf(buf, "%u", n);
1454 
1455   if (k > Len) {
1456     sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1457     throw 138;
1458   } else
1459     SetValue_psz(buf);
1460 
1461   Null = false;
1462 } // end of SetValue
1463 
1464 /***********************************************************************/
1465 /*  STRING SetValue: get the character representation of a short int.  */
1466 /***********************************************************************/
SetValue(short i)1467 void TYPVAL<PSZ>::SetValue(short i)
1468 {
1469   SetValue((int)i);
1470   Null = false;
1471 } // end of SetValue
1472 
1473 /***********************************************************************/
1474 /*  STRING SetValue: get the character representation of a ushort int. */
1475 /***********************************************************************/
SetValue(ushort i)1476 void TYPVAL<PSZ>::SetValue(ushort i)
1477 {
1478   SetValue((uint)i);
1479   Null = false;
1480 } // end of SetValue
1481 
1482 /***********************************************************************/
1483 /*  STRING SetValue: get the character representation of a big integer.*/
1484 /***********************************************************************/
SetValue(longlong n)1485 void TYPVAL<PSZ>::SetValue(longlong n)
1486 {
1487   char     buf[24];
1488   PGLOBAL& g = Global;
1489   int      k = sprintf(buf, "%lld", n);
1490 
1491   if (k > Len) {
1492     sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1493 		throw 138;
1494 	} else
1495     SetValue_psz(buf);
1496 
1497   Null = false;
1498 } // end of SetValue
1499 
1500 /***********************************************************************/
1501 /*  STRING SetValue: get the character representation of a big integer.*/
1502 /***********************************************************************/
SetValue(ulonglong n)1503 void TYPVAL<PSZ>::SetValue(ulonglong n)
1504 {
1505   char     buf[24];
1506   PGLOBAL& g = Global;
1507   int      k = sprintf(buf, "%llu", n);
1508 
1509   if (k > Len) {
1510     sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1511     throw 138;
1512   } else
1513     SetValue_psz(buf);
1514 
1515   Null = false;
1516 } // end of SetValue
1517 
1518 /***********************************************************************/
1519 /*  STRING SetValue: get the character representation of a double.     */
1520 /***********************************************************************/
SetValue(double f)1521 void TYPVAL<PSZ>::SetValue(double f)
1522 {
1523   char    *p, buf[64];
1524   PGLOBAL& g = Global;
1525   int      k = sprintf(buf, "%lf", f);
1526 
1527   for (p = buf + k - 1; p >= buf; p--)
1528     if (*p == '0') {
1529       *p = 0;
1530       k--;
1531     } else
1532       break;
1533 
1534   if (k > Len) {
1535     sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1536 		throw 138;
1537 	} else
1538     SetValue_psz(buf);
1539 
1540   Null = false;
1541 } // end of SetValue
1542 
1543 /***********************************************************************/
1544 /*  STRING SetValue: get the character representation of a tiny int.   */
1545 /***********************************************************************/
SetValue(char c)1546 void TYPVAL<PSZ>::SetValue(char c)
1547 {
1548   SetValue((int)c);
1549   Null = false;
1550 } // end of SetValue
1551 
1552 /***********************************************************************/
1553 /*  STRING SetValue: get the character representation of a tiny int.   */
1554 /***********************************************************************/
SetValue(uchar c)1555 void TYPVAL<PSZ>::SetValue(uchar c)
1556 {
1557   SetValue((uint)c);
1558   Null = false;
1559 } // end of SetValue
1560 
1561 /***********************************************************************/
1562 /*  STRING SetBinValue: fill string with chars extracted from a line.  */
1563 /***********************************************************************/
SetBinValue(void * p)1564 void TYPVAL<PSZ>::SetBinValue(void *p)
1565 {
1566   SetValue_char((const char *)p, Len);
1567 } // end of SetBinValue
1568 
1569 /***********************************************************************/
1570 /*  GetBinValue: fill a buffer with the internal binary value.         */
1571 /*  This function checks whether the buffer length is enough and       */
1572 /*  returns true if not. Actual filling occurs only if go is true.     */
1573 /*  Currently used by WriteColumn of binary files.                     */
1574 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)1575 bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
1576 {
1577   int len = (Null) ? 0 : strlen(Strp);
1578 
1579   if (len > buflen)
1580     return true;
1581   else if (go) {
1582     memset(buf, ' ', buflen);
1583     memcpy(buf, Strp, len);
1584     } // endif go
1585 
1586   return false;
1587 } // end of GetBinValue
1588 
1589 /***********************************************************************/
1590 /*  STRING ShowValue: get string representation of a char value.       */
1591 /***********************************************************************/
ShowValue(char * buf,int buflen)1592 int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
1593 {
1594 	int len = (Null) ? 0 : strlen(Strp);
1595 
1596 	if (buf && buf != Strp) {
1597 		memset(buf, ' ', (size_t)buflen + 1);
1598 		memcpy(buf, Strp, MY_MIN(len, buflen));
1599 	} // endif buf
1600 
1601 	return len;
1602 } // end of ShowValue
1603 
1604 /***********************************************************************/
1605 /*  STRING GetCharString: get string representation of a char value.   */
1606 /***********************************************************************/
GetCharString(char *)1607 char *TYPVAL<PSZ>::GetCharString(char *)
1608 {
1609   return Strp;
1610 } // end of GetCharString
1611 
1612 /***********************************************************************/
1613 /*  STRING compare value with another Value.                           */
1614 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)1615 bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
1616 {
1617   if (this == vp)
1618     return true;
1619   else if (chktype && Type != vp->GetType())
1620     return false;
1621   else if (Null || vp->IsNull())
1622     return false;
1623 
1624   char buf[64];
1625 
1626   if (Ci || vp->IsCi())
1627     return !stricmp(Strp, vp->GetCharString(buf));
1628   else // (!Ci)
1629     return !strcmp(Strp, vp->GetCharString(buf));
1630 
1631 } // end of IsEqual
1632 
1633 /***********************************************************************/
1634 /*  Compare values and returns 1, 0 or -1 according to comparison.     */
1635 /*  This function is used for evaluation of numeric filters.           */
1636 /***********************************************************************/
CompareValue(PVAL vp)1637 int TYPVAL<PSZ>::CompareValue(PVAL vp)
1638 {
1639   int n;
1640 //assert(vp->GetType() == Type);
1641 
1642   if (trace(1))
1643     htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue());
1644 
1645   // Process filtering on character strings.
1646   if (Ci || vp->IsCi())
1647     n = stricmp(Strp, vp->GetCharValue());
1648   else
1649     n = strcmp(Strp, vp->GetCharValue());
1650 
1651 #if defined(_WIN32)
1652   if (n == _NLSCMPERROR)
1653     return n;                        // Here we should raise an error
1654 #endif   // _WIN32
1655 
1656   return (n > 0) ? 1 : (n < 0) ? -1 : 0;
1657 } // end of CompareValue
1658 
1659 /***********************************************************************/
1660 /*  Compute a function on a string.                                    */
1661 /***********************************************************************/
Compute(PGLOBAL g,PVAL * vp,int np,OPVAL op)1662 bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1663 {
1664   char *p[2], val[2][32];
1665   int   i;
1666 
1667 	if (trace(1))
1668 		htrc("Compute: np=%d op=%d\n", np, op);
1669 
1670 	for (i = 0; i < np; i++)
1671 		if (!vp[i]->IsNull()) {
1672 			p[i] = vp[i]->GetCharString(val[i]);
1673 
1674 			if (trace(1))
1675 				htrc("p[%d]=%s\n", i, p[i]);
1676 
1677 		} else
1678 			return false;
1679 
1680 	switch (op) {
1681 		case OP_CNC:
1682 			assert(np == 1 || np == 2);
1683 
1684 			if (np == 2)
1685 				SetValue_psz(p[0]);
1686 
1687 			if ((i = Len - (signed)strlen(Strp)) > 0)
1688 				strncat(Strp, p[np - 1], i);
1689 
1690 			if (trace(1))
1691 				htrc("Strp=%s\n", Strp);
1692 
1693 			break;
1694 		case OP_MIN:
1695 			assert(np == 2);
1696 			SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
1697 			break;
1698 		case OP_MAX:
1699 			assert(np == 2);
1700 			SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
1701 			break;
1702 		default:
1703 			//    sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1704 			strcpy(g->Message, "Function not supported");
1705 			return true;
1706 	} // endswitch op
1707 
1708 	Null = false;
1709   return false;
1710 } // end of Compute
1711 
1712 /***********************************************************************/
1713 /*  FormatValue: This function set vp (a STRING value) to the string   */
1714 /*  constructed from its own value formated using the fmt format.      */
1715 /*  This function assumes that the format matches the value type.      */
1716 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)1717 bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
1718 {
1719   char *buf = (char*)vp->GetTo_Val();        // Should be big enough
1720   int   n = sprintf(buf, fmt, Strp);
1721 
1722   return (n > vp->GetValLen());
1723 } // end of FormatValue
1724 
1725 /***********************************************************************/
1726 /*  STRING SetFormat function (used to set SELECT output format).      */
1727 /***********************************************************************/
SetConstFormat(PGLOBAL,FORMAT & fmt)1728 bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
1729 {
1730   fmt.Type[0] = 'C';
1731   fmt.Length = Len;
1732   fmt.Prec = 0;
1733   return false;
1734 } // end of SetConstFormat
1735 
1736 /***********************************************************************/
1737 /*  Make string output of an object value.                             */
1738 /***********************************************************************/
Prints(PGLOBAL g,char * ps,uint z)1739 void TYPVAL<PSZ>::Prints(PGLOBAL g, char *ps, uint z)
1740 {
1741 	if (Null)
1742 		strncpy(ps, "null", z);
1743 	else
1744 		strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
1745 
1746 } // end of Prints
1747 
1748 /* -------------------------- Class DECIMAL -------------------------- */
1749 
1750 /***********************************************************************/
1751 /*  DECIMAL public constructor from a constant string.                 */
1752 /***********************************************************************/
DECVAL(PSZ s)1753 DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
1754 {
1755   if (s) {
1756     char *p = strchr(Strp, '.');
1757 
1758     Prec = (p) ? (int)(Len - (p - Strp)) : 0;
1759   } // endif s
1760 
1761   Type = TYPE_DECIM;
1762 } // end of DECVAL constructor
1763 
1764 /***********************************************************************/
1765 /*  DECIMAL public constructor from char.                              */
1766 /***********************************************************************/
DECVAL(PGLOBAL g,PSZ s,int n,int prec,bool uns)1767 DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
1768       : TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
1769 {
1770   Prec = prec;
1771   Unsigned = uns;
1772   Type = TYPE_DECIM;
1773 } // end of DECVAL constructor
1774 
1775 /***********************************************************************/
1776 /*  DECIMAL: Check whether the numerica value is equal to 0.           */
1777 /***********************************************************************/
IsZero(void)1778 bool DECVAL::IsZero(void)
1779 {
1780   for (int i = 0; Strp[i]; i++)
1781     if (!strchr("0 +-.", Strp[i]))
1782       return false;
1783 
1784   return true;
1785 } // end of IsZero
1786 
1787 /***********************************************************************/
1788 /*  DECIMAL: Reset value to zero.                                      */
1789 /***********************************************************************/
Reset(void)1790 void DECVAL::Reset(void)
1791 {
1792   int i = 0;
1793 
1794   Strp[i++] = '0';
1795 
1796   if (Prec) {
1797     Strp[i++] = '.';
1798 
1799     do {
1800       Strp[i++] = '0';
1801       } while (i < Prec + 2);
1802 
1803   } // endif Prec
1804 
1805   Strp[i] = 0;
1806 } // end of Reset
1807 
1808 /***********************************************************************/
1809 /*  DECIMAL ShowValue: get string representation right justified.      */
1810 /***********************************************************************/
ShowValue(char * buf,int len)1811 int DECVAL::ShowValue(char *buf, int len)
1812 {
1813   return snprintf(buf, len + 1, Xfmt, len, Strp);
1814 } // end of ShowValue
1815 
1816 /***********************************************************************/
1817 /*  GetBinValue: fill a buffer with the internal binary value.         */
1818 /*  This function checks whether the buffer length is enough and       */
1819 /*  returns true if not. Actual filling occurs only if go is true.     */
1820 /*  Currently used by WriteColumn of binary files.                     */
1821 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)1822 bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
1823 {
1824   int len = (Null) ? 0 : strlen(Strp);
1825 
1826   if (len > buflen)
1827     return true;
1828   else if (go) {
1829     memset(buf, ' ', buflen - len);
1830     memcpy((char*)buf + buflen - len, Strp, len);
1831   } // endif go
1832 
1833   return false;
1834 } // end of GetBinValue
1835 
1836 /***********************************************************************/
1837 /*  DECIMAL compare value with another Value.                          */
1838 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)1839 bool DECVAL::IsEqual(PVAL vp, bool chktype)
1840 {
1841   if (this == vp)
1842     return true;
1843   else if (chktype && Type != vp->GetType())
1844     return false;
1845   else if (Null || vp->IsNull())
1846     return false;
1847 
1848   char buf[64];
1849 
1850   return !strcmp(Strp, vp->GetCharString(buf));
1851 } // end of IsEqual
1852 
1853 /***********************************************************************/
1854 /*  Compare values and returns 1, 0 or -1 according to comparison.     */
1855 /*  This function is used for evaluation of numeric filters.           */
1856 /***********************************************************************/
CompareValue(PVAL vp)1857 int DECVAL::CompareValue(PVAL vp)
1858 {
1859 //assert(vp->GetType() == Type);
1860 
1861   // Process filtering on numeric values.
1862   double f = atof(Strp), n = vp->GetFloatValue();
1863 
1864 //if (trace(1))
1865 //  htrc(" Comparing: val=%d,%d\n", f, n);
1866 
1867   return (f > n) ? 1 : (f < n) ? (-1) : 0;
1868 } // end of CompareValue
1869 
1870 /* -------------------------- Class BINVAL --------------------------- */
1871 
1872 /***********************************************************************/
1873 /*  BINVAL public constructor from bytes.                              */
1874 /***********************************************************************/
BINVAL(PGLOBAL g,void * p,int cl,int n)1875 BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
1876 {
1877   assert(g);
1878 	Len = n;
1879 	Clen = cl;
1880 	Binp = PlugSubAlloc(g, NULL, Clen + 1);
1881   memset(Binp, 0, Clen + 1);
1882 
1883   if (p)
1884     memcpy(Binp, p, MY_MIN(Len,Clen));
1885 
1886   Chrp = NULL;
1887 } // end of BINVAL constructor
1888 
1889 /***********************************************************************/
1890 /*  BINVAL: Check whether the hexadecimal value is equal to 0.         */
1891 /***********************************************************************/
IsZero(void)1892 bool BINVAL::IsZero(void)
1893 {
1894   for (int i = 0; i < Len; i++)
1895     if (((char*)Binp)[i] != 0)
1896       return false;
1897 
1898   return true;
1899 } // end of IsZero
1900 
1901 /***********************************************************************/
1902 /*  BINVAL: Reset value to zero.                                       */
1903 /***********************************************************************/
Reset(void)1904 void BINVAL::Reset(void)
1905 {
1906   memset(Binp, 0, Clen);
1907   Len = 0;
1908 } // end of Reset
1909 
1910 /***********************************************************************/
1911 /*  Get the tiny value pointed by Binp.                                */
1912 /***********************************************************************/
GetTinyValue(void)1913 char BINVAL::GetTinyValue(void)
1914 {
1915   return *(char*)Binp;
1916 } // end of GetTinyValue
1917 
1918 /***********************************************************************/
1919 /*  Get the unsigned tiny value pointed by Binp.                       */
1920 /***********************************************************************/
GetUTinyValue(void)1921 uchar BINVAL::GetUTinyValue(void)
1922 {
1923   return *(uchar*)Binp;
1924 } // end of GetUTinyValue
1925 
1926 /***********************************************************************/
1927 /*  Get the short value pointed by Binp.                               */
1928 /***********************************************************************/
GetShortValue(void)1929 short BINVAL::GetShortValue(void)
1930 {
1931   if (Len >= 2)
1932     return *(short*)Binp;
1933   else
1934     return (short)GetTinyValue();
1935 
1936 } // end of GetShortValue
1937 
1938 /***********************************************************************/
1939 /*  Get the unsigned short value pointed by Binp.                      */
1940 /***********************************************************************/
GetUShortValue(void)1941 ushort BINVAL::GetUShortValue(void)
1942 {
1943   return (ushort)GetShortValue();
1944 } // end of GetUshortValue
1945 
1946 /***********************************************************************/
1947 /*  Get the integer value pointed by Binp.                             */
1948 /***********************************************************************/
GetIntValue(void)1949 int BINVAL::GetIntValue(void)
1950 {
1951   if (Len >= 4)
1952     return *(int*)Binp;
1953   else
1954     return (int)GetShortValue();
1955 
1956 } // end of GetIntValue
1957 
1958 /***********************************************************************/
1959 /*  Get the unsigned integer value pointed by Binp.                    */
1960 /***********************************************************************/
GetUIntValue(void)1961 uint BINVAL::GetUIntValue(void)
1962 {
1963   return (uint)GetIntValue();
1964 } // end of GetUintValue
1965 
1966 /***********************************************************************/
1967 /*  Get the big integer value pointed by Binp.                         */
1968 /***********************************************************************/
GetBigintValue(void)1969 longlong BINVAL::GetBigintValue(void)
1970 {
1971   if (Len >= 8)
1972     return *(longlong*)Binp;
1973   else
1974     return (longlong)GetIntValue();
1975 
1976 } // end of GetBigintValue
1977 
1978 /***********************************************************************/
1979 /*  Get the unsigned big integer value pointed by Binp.                */
1980 /***********************************************************************/
GetUBigintValue(void)1981 ulonglong BINVAL::GetUBigintValue(void)
1982 {
1983   return (ulonglong)GetBigintValue();
1984 } // end of GetUBigintValue
1985 
1986 /***********************************************************************/
1987 /*  Get the double value pointed by Binp.                              */
1988 /***********************************************************************/
GetFloatValue(void)1989 double BINVAL::GetFloatValue(void)
1990 {
1991   if (Len >= 8)
1992     return *(double*)Binp;
1993   else if (Len >= 4)
1994     return (double)(*(float*)Binp);
1995   else
1996     return 0.0;
1997 
1998 } // end of GetFloatValue
1999 
2000 /***********************************************************************/
2001 /*  BINVAL SetValue: copy the value of another Value object.           */
2002 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)2003 bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
2004 {
2005   bool rc = false;
2006 
2007   if (valp != this) {
2008     if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
2009       return true;
2010 
2011     if (!(Null = valp->IsNull() && Nullable)) {
2012 			int len = Len;
2013 
2014 			if ((rc = (Len = valp->GetSize()) > Clen))
2015         Len = Clen;
2016 			else if (len > Len)
2017 				memset(Binp, 0, len);
2018 
2019       memcpy(Binp, valp->GetTo_Val(), Len);
2020 			((char*)Binp)[Len] = 0;
2021     } else
2022       Reset();
2023 
2024   } // endif valp
2025 
2026   return rc;
2027 } // end of SetValue_pval
2028 
2029 /***********************************************************************/
2030 /*  BINVAL SetValue: fill value with chars extracted from a line.      */
2031 /***********************************************************************/
SetValue_char(const char * p,int n)2032 bool BINVAL::SetValue_char(const char *p, int n)
2033 {
2034   bool rc;
2035 
2036   if (p && n > 0) {
2037 		int len = Len;
2038 
2039     if (len > (Len = MY_MIN(n, Clen)))
2040 			memset(Binp, 0, len);
2041 
2042 		memcpy(Binp, p, Len);
2043 		((char*)Binp)[Len] = 0;
2044 		rc = n > Clen;
2045 		Null = false;
2046   } else {
2047     rc = false;
2048     Reset();
2049     Null = Nullable;
2050   } // endif p
2051 
2052   return rc;
2053 } // end of SetValue_char
2054 
2055 /***********************************************************************/
2056 /*  BINVAL SetValue: fill value with another string.                   */
2057 /***********************************************************************/
SetValue_psz(PCSZ s)2058 void BINVAL::SetValue_psz(PCSZ s)
2059 {
2060   if (s) {
2061 		int len = Len;
2062 
2063 		if (len > (Len = MY_MIN(Clen, (signed)strlen(s))))
2064 			memset(Binp, 0, len);
2065 
2066 		memcpy(Binp, s, Len);
2067 		((char*)Binp)[Len] = 0;
2068 		Null = false;
2069   } else {
2070     Reset();
2071     Null = Nullable;
2072   } // endif s
2073 
2074 } // end of SetValue_psz
2075 
2076 /***********************************************************************/
2077 /*  BINVAL SetValue: fill value with bytes extracted from a block.     */
2078 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)2079 void BINVAL::SetValue_pvblk(PVBLK blk, int n)
2080 {
2081   // STRBLK's can return a NULL pointer
2082   void *vp = blk->GetValPtrEx(n);
2083 
2084   if (!vp || blk->IsNull(n)) {
2085     Reset();
2086     Null = Nullable;
2087   } else if (vp != Binp) {
2088 		int len = Len;
2089 
2090     if (blk->GetType() == TYPE_STRING)
2091       Len = strlen((char*)vp);
2092     else
2093       Len = blk->GetVlen();
2094 
2095     if (len > (Len = MY_MIN(Clen, Len)))
2096 			memset(Binp, 0, len);
2097 
2098     memcpy(Binp, vp, Len);
2099 		((char*)Binp)[Len] = 0;
2100 		Null = false;
2101   } // endif vp
2102 
2103 } // end of SetValue_pvblk
2104 
2105 /***********************************************************************/
2106 /*  BINVAL SetValue: get the binary representation of an integer.      */
2107 /***********************************************************************/
SetValue(int n)2108 void BINVAL::SetValue(int n)
2109 {
2110   if (Clen >= 4) {
2111 		if (Len > 4)
2112 			memset(Binp, 0, Len);
2113 
2114 		*((int*)Binp) = n;
2115     Len = 4;
2116   } else
2117     SetValue((short)n);
2118 
2119 } // end of SetValue
2120 
2121 /***********************************************************************/
2122 /*  BINVAL SetValue: get the binary representation of an uint.         */
2123 /***********************************************************************/
SetValue(uint n)2124 void BINVAL::SetValue(uint n)
2125 {
2126   if (Clen >= 4) {
2127 		if (Len > 4)
2128 			memset(Binp, 0, Len);
2129 
2130 		*((uint*)Binp) = n;
2131     Len = 4;
2132   } else
2133     SetValue((ushort)n);
2134 
2135 } // end of SetValue
2136 
2137 /***********************************************************************/
2138 /*  BINVAL SetValue: get the binary representation of a short int.     */
2139 /***********************************************************************/
SetValue(short i)2140 void BINVAL::SetValue(short i)
2141 {
2142   if (Clen >= 2) {
2143 		if (Len > 2)
2144 			memset(Binp, 0, Len);
2145 
2146 		*((int*)Binp) = i;
2147     Len = 2;
2148   } else
2149     SetValue((char)i);
2150 
2151 } // end of SetValue
2152 
2153 /***********************************************************************/
2154 /*  BINVAL SetValue: get the binary representation of a ushort int.    */
2155 /***********************************************************************/
SetValue(ushort i)2156 void BINVAL::SetValue(ushort i)
2157 {
2158   if (Clen >= 2) {
2159 		if (Len > 2)
2160 			memset(Binp, 0, Len);
2161 
2162 		*((uint*)Binp) = i;
2163     Len = 2;
2164   } else
2165     SetValue((uchar)i);
2166 
2167 } // end of SetValue
2168 
2169 /***********************************************************************/
2170 /*  BINVAL SetValue: get the binary representation of a big integer.   */
2171 /***********************************************************************/
SetValue(longlong n)2172 void BINVAL::SetValue(longlong n)
2173 {
2174   if (Clen >= 8) {
2175 		if (Len > 8)
2176 			memset(Binp, 0, Len);
2177 
2178 		*((longlong*)Binp) = n;
2179     Len = 8;
2180   } else
2181     SetValue((int)n);
2182 
2183 } // end of SetValue
2184 
2185 /***********************************************************************/
2186 /*  BINVAL SetValue: get the binary representation of a big integer.   */
2187 /***********************************************************************/
SetValue(ulonglong n)2188 void BINVAL::SetValue(ulonglong n)
2189 {
2190   if (Clen >= 8) {
2191 		if (Len > 8)
2192 			memset(Binp, 0, Len);
2193 
2194 		*((ulonglong*)Binp) = n;
2195     Len = 8;
2196   } else
2197     SetValue((uint)n);
2198 
2199 } // end of SetValue
2200 
2201 /***********************************************************************/
2202 /*  BINVAL SetValue: get the binary representation of a double.        */
2203 /***********************************************************************/
SetValue(double n)2204 void BINVAL::SetValue(double n)
2205 {
2206 	if (Len > 8)
2207 	  memset(Binp, 0, Len);
2208 
2209   if (Clen >= 8) {
2210     *((double*)Binp) = n;
2211     Len = 8;
2212   } else if (Clen >= 4) {
2213     *((float*)Binp) = (float)n;
2214     Len = 4;
2215   } else
2216     Len = 0;
2217 
2218 } // end of SetValue
2219 
2220 /***********************************************************************/
2221 /*  BINVAL SetValue: get the character binary of a tiny int.           */
2222 /***********************************************************************/
SetValue(char c)2223 void BINVAL::SetValue(char c)
2224 {
2225 	if (Len > 1)
2226 		memset(Binp, 0, Len);
2227 
2228 	*((char*)Binp) = c;
2229   Len = 1;
2230 } // end of SetValue
2231 
2232 /***********************************************************************/
2233 /*  BINVAL SetValue: get the binary representation of a tiny int.      */
2234 /***********************************************************************/
SetValue(uchar c)2235 void BINVAL::SetValue(uchar c)
2236 {
2237 	if (Len > 1)
2238 		memset(Binp, 0, Len);
2239 
2240 	*((uchar*)Binp) = c;
2241   Len = 1;
2242 } // end of SetValue
2243 
2244 /***********************************************************************/
2245 /*  BINVAL SetBinValue: fill string with bytes extracted from a line.  */
2246 /***********************************************************************/
SetBinValue(void * p)2247 void BINVAL::SetBinValue(void *p)
2248 {
2249   memcpy(Binp, p, Clen);
2250 	Len = Clen;
2251 } // end of SetBinValue
2252 
2253 /***********************************************************************/
2254 /*  BINVAL SetBinValue: fill string with len bytes.                    */
2255 /***********************************************************************/
SetBinValue(void * p,ulong len)2256 void BINVAL::SetBinValue(void* p, ulong len)
2257 {
2258 	memcpy(Binp, p, len);
2259 	Len = len;
2260 } // end of SetBinValue
2261 
2262 /***********************************************************************/
2263 /*  GetBinValue: fill a buffer with the internal binary value.         */
2264 /*  This function checks whether the buffer length is enough and       */
2265 /*  returns true if not. Actual filling occurs only if go is true.     */
2266 /*  Currently used by WriteColumn of binary files.                     */
2267 /***********************************************************************/
GetBinValue(void * buf,int buflen,bool go)2268 bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
2269 {
2270   if (Len > buflen)
2271     return true;
2272   else if (go) {
2273     memset(buf, 0, buflen);
2274     memcpy(buf, Binp, Len);
2275   } // endif go
2276 
2277   return false;
2278 } // end of GetBinValue
2279 
2280 /***********************************************************************/
2281 /*  BINVAL ShowValue: get string representation of a binary value.     */
2282 /***********************************************************************/
ShowValue(char * buf,int len)2283 int BINVAL::ShowValue(char *buf, int len)
2284 {
2285 	memset(buf, 0, len + 1);
2286 	memcpy(buf, Binp, MY_MIN(len, Len));
2287 	return Len;
2288 } // end of ShowValue
2289 
2290 /***********************************************************************/
2291 /*  BINVAL GetCharString: get string representation of a binary value. */
2292 /***********************************************************************/
GetCharString(char *)2293 char *BINVAL::GetCharString(char *)
2294 {
2295   if (!Chrp)
2296     Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
2297 
2298   sprintf(Chrp, GetXfmt(), Len, Binp);
2299   return Chrp;
2300 } // end of GetCharString
2301 
2302 /***********************************************************************/
2303 /*  BINVAL compare value with another Value.                           */
2304 /***********************************************************************/
IsEqual(PVAL vp,bool chktype)2305 bool BINVAL::IsEqual(PVAL vp, bool chktype)
2306 {
2307   if (this == vp)
2308     return true;
2309   else if (chktype && Type != vp->GetType())
2310     return false;
2311   else if (Null || vp->IsNull())
2312     return false;
2313   else if (Len != vp->GetSize())
2314     return false;
2315 
2316   char *v1 = (char*)Binp;
2317   char *v2 = (char*)vp->GetTo_Val();
2318 
2319   for (int i = 0; i < Len; i++)
2320     if (v1[i] != v2[i])
2321       return false;
2322 
2323   return true;
2324 } // end of IsEqual
2325 
2326 /***********************************************************************/
2327 /*  FormatValue: This function set vp (a STRING value) to the string   */
2328 /*  constructed from its own value formated using the fmt format.      */
2329 /*  This function assumes that the format matches the value type.      */
2330 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)2331 bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
2332 {
2333   char *buf = (char*)vp->GetTo_Val();        // Should be big enough
2334   int   n = sprintf(buf, fmt, Len, Binp);
2335 
2336   return (n > vp->GetValLen());
2337 } // end of FormatValue
2338 
2339 /***********************************************************************/
2340 /*  BINVAL SetFormat function (used to set SELECT output format).      */
2341 /***********************************************************************/
SetConstFormat(PGLOBAL,FORMAT & fmt)2342 bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
2343 {
2344   fmt.Type[0] = 'B';
2345   fmt.Length = Clen;
2346   fmt.Prec = 0;
2347   return false;
2348 } // end of SetConstFormat
2349 
2350 /* -------------------------- Class DTVAL ---------------------------- */
2351 
2352 /***********************************************************************/
2353 /*  DTVAL  public constructor for new void values.                     */
2354 /***********************************************************************/
DTVAL(PGLOBAL g,int n,int prec,PCSZ fmt)2355 DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
2356      : TYPVAL<int>((int)0, TYPE_DATE)
2357 {
2358   if (!fmt) {
2359     Pdtp = NULL;
2360     Sdate = NULL;
2361     DefYear = 0;
2362     Len = n;
2363   } else
2364     SetFormat(g, fmt, n, prec);
2365 
2366 //Type = TYPE_DATE;
2367 } // end of DTVAL constructor
2368 
2369 /***********************************************************************/
2370 /*  DTVAL  public constructor from int.                                */
2371 /***********************************************************************/
DTVAL(int n)2372 DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
2373 {
2374   Pdtp = NULL;
2375   Len = 19;
2376 //Type = TYPE_DATE;
2377   Sdate = NULL;
2378   DefYear = 0;
2379 } // end of DTVAL constructor
2380 
2381 /***********************************************************************/
2382 /*  Set format so formatted dates can be converted on input/output.    */
2383 /***********************************************************************/
SetFormat(PGLOBAL g,PCSZ fmt,int len,int year)2384 bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
2385 {
2386   Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
2387   Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
2388   DefYear = (int)((year > 9999) ? (year - 10000) : year);
2389   Len = len;
2390   return false;
2391 } // end of SetFormat
2392 
2393 /***********************************************************************/
2394 /*  Set format from the format of another date value.                  */
2395 /***********************************************************************/
SetFormat(PGLOBAL g,PVAL valp)2396 bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
2397 {
2398   DTVAL *vp;
2399 
2400   if (valp->GetType() != TYPE_DATE) {
2401     sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
2402     return true;
2403   } else
2404     vp = (DTVAL*)valp;
2405 
2406   Len = vp->Len;
2407   Pdtp = vp->Pdtp;
2408   Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
2409   DefYear = vp->DefYear;
2410   return false;
2411 } // end of SetFormat
2412 
2413 /***********************************************************************/
2414 /*  We need TimeShift because the mktime C function does a correction  */
2415 /*  for local time zone that we want to override for DB operations.    */
2416 /***********************************************************************/
SetTimeShift(void)2417 void DTVAL::SetTimeShift(void)
2418 {
2419   struct tm dtm;
2420   memset(&dtm, 0, sizeof(dtm));
2421   dtm.tm_mday=2;
2422   dtm.tm_mon=0;
2423   dtm.tm_year=70;
2424 
2425   Shift = (int)mktime(&dtm) - 86400;
2426 
2427   if (trace(1))
2428     htrc("DTVAL Shift=%d\n", Shift);
2429 
2430 } // end of SetTimeShift
2431 
2432 // Added by Alexander Barkov
TIME_to_localtime(struct tm * tm,const MYSQL_TIME * ltime)2433 static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
2434 {
2435   bzero(tm, sizeof(*tm));
2436   tm->tm_year= ltime->year - 1900;
2437   tm->tm_mon=  ltime->month - 1;
2438   tm->tm_mday= ltime->day;
2439   mktime(tm);  // set tm->tm_wday tm->yday fields to get proper day name (OB)
2440   tm->tm_hour= ltime->hour;
2441   tm->tm_min=  ltime->minute;
2442   tm->tm_sec=  ltime->second;
2443 } // end of TIME_to_localtime
2444 
2445 // Added by Alexander Barkov
gmtime_mysql(const time_t * timep,struct tm * tm)2446 static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
2447 {
2448   MYSQL_TIME ltime;
2449   thd_gmt_sec_to_TIME(current_thd, &ltime, (my_time_t) *timep);
2450   TIME_to_localtime(tm, &ltime);
2451   return tm;
2452 } // end of gmtime_mysql
2453 
2454 /***********************************************************************/
2455 /*  GetGmTime: returns a pointer to a static tm structure obtained     */
2456 /*  though the gmtime C function. The purpose of this function is to   */
2457 /*  extend the range of valid dates by accepting negative time values. */
2458 /***********************************************************************/
GetGmTime(struct tm * tm_buffer)2459 struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
2460 {
2461   struct tm *datm;
2462   time_t t = (time_t)Tval;
2463 
2464   if (Tval < 0) {
2465     int    n;
2466 
2467     for (n = 0; t < 0; n += 4)
2468       t += FOURYEARS;
2469 
2470     datm = gmtime_mysql(&t, tm_buffer);
2471 
2472     if (datm)
2473       datm->tm_year -= n;
2474 
2475   } else
2476     datm = gmtime_mysql(&t, tm_buffer);
2477 
2478   return datm;
2479 } // end of GetGmTime
2480 
2481 // Added by Alexander Barkov
mktime_mysql(struct tm * ptm)2482 static time_t mktime_mysql(struct tm *ptm)
2483 {
2484   MYSQL_TIME ltime;
2485   localtime_to_TIME(&ltime, ptm);
2486   ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
2487   uint error_code;
2488   time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
2489   return error_code ? (time_t) -1 : t;
2490 }
2491 
2492 /***********************************************************************/
2493 /*  MakeTime: calculates a date value from a tm structures using the   */
2494 /*  mktime C function. The purpose of this function is to extend the   */
2495 /*  range of valid dates by accepting to set negative time values.     */
2496 /***********************************************************************/
MakeTime(struct tm * ptm)2497 bool DTVAL::MakeTime(struct tm *ptm)
2498 {
2499   int    n, y = ptm->tm_year;
2500   time_t t = mktime_mysql(ptm);
2501 
2502   if (trace(2))
2503     htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
2504           ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
2505           ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
2506 
2507   if (t == -1) {
2508     if (y < 1 || y > 71)
2509       return true;
2510 
2511     for (n = 0; t == -1 && n < 20; n++) {
2512       ptm->tm_year += 4;
2513       t = mktime_mysql(ptm);
2514     } // endfor t
2515 
2516     if (t == -1)
2517       return true;
2518 
2519     if ((t -= (n * FOURYEARS)) > 2000000000)
2520       return true;
2521 
2522   } // endif t
2523 
2524   Tval= (int) t;
2525 
2526   if (trace(2))
2527     htrc("MakeTime Ival=%d\n", Tval);
2528 
2529   return false;
2530 } // end of MakeTime
2531 
2532 /***********************************************************************/
2533 /* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
2534 /***********************************************************************/
MakeDate(PGLOBAL g,int * val,int nval)2535 bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
2536 {
2537   int       i, m;
2538   int       n;
2539   bool      rc = false;
2540   struct tm datm;
2541   bzero(&datm, sizeof(datm));
2542   datm.tm_mday=1;
2543   datm.tm_mon=0;
2544   datm.tm_year=70;
2545 
2546   if (trace(2))
2547     htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
2548     val[0], val[1], val[2], val[3], val[4], val[5], nval);
2549 
2550   for (i = 0; i < nval; i++) {
2551     n = val[i];
2552 
2553 //    if (trace(2))
2554 //      htrc("i=%d n=%d\n", i, n);
2555 
2556     switch (i) {
2557       case 0:
2558         if (n >= 1900)
2559           n -= 1900;
2560 
2561         datm.tm_year = n;
2562 
2563 //        if (trace(2))
2564 //          htrc("n=%d tm_year=%d\n", n, datm.tm_year);
2565 
2566         break;
2567       case 1:
2568         // If mktime handles apparently correctly large or negative
2569         // day values, it is not the same for months. Therefore we
2570         // do the ajustment here, thus mktime has not to do it.
2571         if (n > 0) {
2572           m = (n - 1) % 12;
2573           n = (n - 1) / 12;
2574         } else {
2575           m = 11 + n % 12;
2576           n = n / 12 - 1;
2577         } // endfi n
2578 
2579         datm.tm_mon = m;
2580         datm.tm_year += n;
2581 
2582 //        if (trace(2))
2583 //          htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2584 
2585         break;
2586       case 2:
2587         // For days, big or negative values may also cause problems
2588         m = n % 1461;
2589         n = 4 * (n / 1461);
2590 
2591         if (m < 0) {
2592           m += 1461;
2593           n -= 4;
2594           } // endif m
2595 
2596         datm.tm_mday = m;
2597         datm.tm_year += n;
2598 
2599 //        if (trace(2))
2600 //          htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2601 
2602        break;
2603       case 3: datm.tm_hour = n; break;
2604       case 4: datm.tm_min  = n; break;
2605       case 5: datm.tm_sec  = n; break;
2606     } // endswitch i
2607 
2608   } // endfor i
2609 
2610   if (trace(2))
2611     htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
2612     datm.tm_year, datm.tm_mon, datm.tm_mday,
2613     datm.tm_hour, datm.tm_min, datm.tm_sec);
2614 
2615   // Pass g to have an error return or NULL to set invalid dates to 0
2616   if (MakeTime(&datm))
2617   {
2618     if (g) {
2619       strcpy(g->Message, MSG(BAD_DATETIME));
2620       rc = true;
2621     } else
2622       Tval = 0;
2623   }
2624   return rc;
2625 } // end of MakeDate
2626 
2627 /***********************************************************************/
2628 /*  DTVAL SetValue: copy the value of another Value object.            */
2629 /*  This function allows conversion if chktype is false.               */
2630 /***********************************************************************/
SetValue_pval(PVAL valp,bool chktype)2631 bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
2632 {
2633   if (valp != this) {
2634     if (chktype && Type != valp->GetType())
2635       return true;
2636 
2637     if (!(Null = valp->IsNull() && Nullable)) {
2638       if (Pdtp && !valp->IsTypeNum()) {
2639         int   ndv;
2640         int  dval[6];
2641 
2642         ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
2643         MakeDate(NULL, dval, ndv);
2644 			} else if (valp->GetType() == TYPE_BIGINT &&
2645 				       !(valp->GetBigintValue() % 1000)) {
2646 				// Assuming that this timestamp is in milliseconds
2647 				SetValue((int)(valp->GetBigintValue() / 1000));
2648 			}	else
2649         SetValue(valp->GetIntValue());
2650 
2651     } else
2652       Reset();
2653 
2654   } // endif valp
2655 
2656   return false;
2657 } // end of SetValue
2658 
2659 /***********************************************************************/
2660 /*  SetValue: convert chars extracted from a line to date value.       */
2661 /***********************************************************************/
SetValue_char(const char * p,int n)2662 bool DTVAL::SetValue_char(const char *p, int n)
2663 {
2664   bool rc= 0;
2665 
2666   if (Pdtp) {
2667     const char *p2;
2668     int ndv;
2669     int dval[6];
2670 
2671 		if (n > 0) {
2672 			// Trim trailing blanks
2673 			for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--);
2674 
2675 			if ((rc = (n = (int)(p2 - p + 1)) > Len))
2676 				n = Len;
2677 
2678 			memcpy(Sdate, p, n);
2679 		} // endif n
2680 
2681     Sdate[n] = '\0';
2682 
2683     ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2684     MakeDate(NULL, dval, ndv);
2685 
2686     if (trace(2))
2687       htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2688 
2689     Null = (Nullable && ndv == 0);
2690   } else {
2691     rc = TYPVAL<int>::SetValue_char(p, n);
2692     Null = (Nullable && Tval == 0);
2693   } // endif Pdtp
2694 
2695   return rc;
2696 } // end of SetValue
2697 
2698 /***********************************************************************/
2699 /*  SetValue: convert a char string to date value.                     */
2700 /***********************************************************************/
SetValue_psz(PCSZ p)2701 void DTVAL::SetValue_psz(PCSZ p)
2702 {
2703   if (Pdtp) {
2704     int ndv;
2705     int dval[6];
2706 
2707     strncpy(Sdate, p, Len);
2708     Sdate[Len] = '\0';
2709 
2710     ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2711     MakeDate(NULL, dval, ndv);
2712 
2713     if (trace(2))
2714       htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2715 
2716     Null = (Nullable && ndv == 0);
2717   } else {
2718     TYPVAL<int>::SetValue_psz(p);
2719     Null = (Nullable && Tval == 0);
2720   } // endif Pdtp
2721 
2722 } // end of SetValue
2723 
2724 /***********************************************************************/
2725 /*  DTVAL SetValue: set value with a value extracted from a block.     */
2726 /***********************************************************************/
SetValue_pvblk(PVBLK blk,int n)2727 void DTVAL::SetValue_pvblk(PVBLK blk, int n)
2728 {
2729   if (Pdtp && !::IsTypeNum(blk->GetType())) {
2730     int   ndv;
2731     int  dval[6];
2732 
2733     ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
2734     MakeDate(NULL, dval, ndv);
2735   } else
2736     Tval = blk->GetIntValue(n);
2737 
2738 } // end of SetValue
2739 
2740 /***********************************************************************/
2741 /*  DTVAL SetValue: get date as an integer.                            */
2742 /***********************************************************************/
SetValue(int n)2743 void DTVAL::SetValue(int n)
2744 {
2745   Tval = n;
2746 
2747   if (Pdtp) {
2748     size_t slen = (size_t)Len + 1;
2749     struct tm tm, *ptm= GetGmTime(&tm);
2750 
2751     if (ptm)
2752       strftime(Sdate, slen, Pdtp->OutFmt, ptm);
2753 
2754   } // endif Pdtp
2755 
2756 } // end of SetValue
2757 
2758 /***********************************************************************/
2759 /*  DTVAL GetCharString: get string representation of a date value.    */
2760 /***********************************************************************/
GetCharString(char * p)2761 char *DTVAL::GetCharString(char *p)
2762 {
2763   if (Pdtp) {
2764     size_t n = 0, slen = (size_t)Len + 1;
2765     struct tm tm, *ptm= GetGmTime(&tm);
2766 
2767     if (ptm)
2768       n = strftime(Sdate, slen, Pdtp->OutFmt, ptm);
2769 
2770     if (!n) {
2771       *Sdate = '\0';
2772       strncat(Sdate, "Error", slen);
2773       } // endif n
2774 
2775     return Sdate;
2776   } else
2777     sprintf(p, "%d", Tval);
2778 
2779 //Null = false;                      ??????????????
2780   return p;
2781 } // end of GetCharString
2782 
2783 /***********************************************************************/
2784 /*  DTVAL ShowValue: get string representation of a date value.        */
2785 /***********************************************************************/
ShowValue(char * buf,int len)2786 int DTVAL::ShowValue(char *buf, int len)
2787 {
2788 	int rv = 0;
2789 
2790   if (Pdtp) {
2791     if (!Null) {
2792       size_t n = 0, m = len + 1;
2793       struct tm tm, *ptm = GetGmTime(&tm);
2794 
2795       if (ptm)
2796         n = strftime(buf, m, Pdtp->OutFmt, ptm);
2797 
2798       if (!n) {
2799         *buf = '\0';
2800         strncat(buf, "Error", m);
2801 				rv = 5;
2802 			} else
2803 				rv = (int)n;
2804 
2805 		} else
2806 			*buf = '\0';               // DEFAULT VALUE ???
2807 
2808   } else
2809     rv = TYPVAL<int>::ShowValue(buf, len);
2810 
2811 	return rv;
2812 } // end of ShowValue
2813 
2814 #if 0           // Not used by CONNECT
2815 /***********************************************************************/
2816 /*  Returns a member of the struct tm representation of the date.      */
2817 /***********************************************************************/
2818 bool DTVAL::GetTmMember(OPVAL op, int& mval)
2819 {
2820   bool       rc = false;
2821   struct tm tm, *ptm = GetGmTime(&tm);
2822 
2823   switch (op) {
2824     case OP_MDAY:  mval = ptm->tm_mday;        break;
2825     case OP_MONTH: mval = ptm->tm_mon  + 1;    break;
2826     case OP_YEAR:  mval = ptm->tm_year + 1900; break;
2827     case OP_WDAY:  mval = ptm->tm_wday + 1;    break;
2828     case OP_YDAY:  mval = ptm->tm_yday + 1;    break;
2829     case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
2830     default:
2831       rc = true;
2832   } // endswitch op
2833 
2834   return rc;
2835 } // end of GetTmMember
2836 
2837 /***********************************************************************/
2838 /*  Calculates the week number of the year for the internal date value.*/
2839 /*  The International Standard ISO 8601 has decreed that Monday shall  */
2840 /*  be the first day of the week. A week that lies partly in one year  */
2841 /*  and partly in another is assigned a number in the year in which    */
2842 /*  most of its days lie. That means that week number 1 of any year is */
2843 /*  the week that contains the January 4th.                            */
2844 /***********************************************************************/
2845 bool DTVAL::WeekNum(PGLOBAL g, int& nval)
2846 {
2847   // w is the start of the week SUN=0, MON=1, etc.
2848   int        m, n, w = nval % 7;
2849   struct tm tm, *ptm = GetGmTime(&tm);
2850 
2851   // Which day is January 4th of this year?
2852   m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
2853 
2854   // When does the first week begins?
2855   n = 3 - (7 + m - w) % 7;
2856 
2857   // Now calculate the week number
2858   if (!(nval = (7 + ptm->tm_yday - n) / 7))
2859     nval = 52;
2860 
2861   // Everything should be Ok
2862   return false;
2863 } // end of WeekNum
2864 #endif // 0
2865 
2866 /***********************************************************************/
2867 /*  FormatValue: This function set vp (a STRING value) to the string   */
2868 /*  constructed from its own value formated using the fmt format.      */
2869 /*  This function assumes that the format matches the value type.      */
2870 /***********************************************************************/
FormatValue(PVAL vp,PCSZ fmt)2871 bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
2872 {
2873   char     *buf = (char*)vp->GetTo_Val();       // Should be big enough
2874   struct tm tm, *ptm = GetGmTime(&tm);
2875 
2876   if (trace(2))
2877     htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
2878 
2879   if (ptm) {
2880     size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
2881 
2882     if (trace(2))
2883       htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
2884 
2885     return (n == 0);
2886   } else
2887     return true;
2888 
2889 } // end of FormatValue
2890 
2891 /* -------------------------- End of Value --------------------------- */
2892