1/************* Value C++ Functions Source Code File (.CPP) *************/
2/* Name: VALUE.CPP Version 2.8 */
3/* */
4/* (C) Copyright to the author Olivier BERTRAND 2001-2017 */
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(__WIN__)
34//#include <windows.h>
35#else // !__WIN__
36#include <string.h>
37#endif // !__WIN__
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/***********************************************************************/
73int DTVAL::Shift = 0;
74
75/***********************************************************************/
76/* Routines called externally. */
77/***********************************************************************/
78bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
79
80#if !defined(__WIN__)
81extern "C" {
82PSZ strupr(PSZ s);
83PSZ strlwr(PSZ s);
84}
85#endif // !__WIN__
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/***********************************************************************/
97ulonglong 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/***********************************************************************/
142PCSZ 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/***********************************************************************/
166int 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/***********************************************************************/
188const 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 = "M"; 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/***********************************************************************/
211int 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/***********************************************************************/
234bool 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/***********************************************************************/
249bool 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/***********************************************************************/
269const 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/***********************************************************************/
295int 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/***********************************************************************/
336PVAL 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/***********************************************************************/
374PVAL 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/***********************************************************************/
436PVAL 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/***********************************************************************/
511VALUE::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/***********************************************************************/
525const 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 GetFmt
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/***********************************************************************/
547BYTE 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/***********************************************************************/
557bool 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/***********************************************************************/
566void 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/***********************************************************************/
583void 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/***********************************************************************/
600template <class TYPE>
601TYPVAL<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/***********************************************************************/
612template <class TYPE>
613ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
614
615template <>
616ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;}
617
618template <>
619ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;}
620
621template <>
622ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;}
623
624template <>
625ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;}
626
627template <>
628ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;}
629
630template <>
631ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;}
632
633template <>
634ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;}
635
636template <>
637ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
638
639/***********************************************************************/
640/* TYPVAL GetValLen: returns the print length of the typed object. */
641/***********************************************************************/
642template <class TYPE>
643int TYPVAL<TYPE>::GetValLen(void)
644 {
645 char c[32];
646
647 return sprintf(c, Fmt, Tval);
648 } // end of GetValLen
649
650template <>
651int TYPVAL<double>::GetValLen(void)
652 {
653 char c[32];
654
655 return sprintf(c, 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/***********************************************************************/
662template <class TYPE>
663bool 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
679template <>
680short TYPVAL<short>::GetTypedValue(PVAL valp)
681 {return valp->GetShortValue();}
682
683template <>
684ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
685 {return valp->GetUShortValue();}
686
687template <>
688int TYPVAL<int>::GetTypedValue(PVAL valp)
689 {return valp->GetIntValue();}
690
691template <>
692uint TYPVAL<uint>::GetTypedValue(PVAL valp)
693 {return valp->GetUIntValue();}
694
695template <>
696longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
697 {return valp->GetBigintValue();}
698
699template <>
700ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
701 {return valp->GetUBigintValue();}
702
703template <>
704double TYPVAL<double>::GetTypedValue(PVAL valp)
705 {return valp->GetFloatValue();}
706
707template <>
708char TYPVAL<char>::GetTypedValue(PVAL valp)
709 {return valp->GetTinyValue();}
710
711template <>
712uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
713 {return valp->GetUTinyValue();}
714
715/***********************************************************************/
716/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
717/***********************************************************************/
718template <class TYPE>
719bool 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
740template <>
741bool 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/***********************************************************************/
768template <class TYPE>
769void 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/***********************************************************************/
784template <class TYPE>
785void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
786 {
787 Tval = GetTypedValue(blk, n);
788 Null = false;
789 } // end of SetValue
790
791template <>
792int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
793 {return blk->GetIntValue(n);}
794
795template <>
796uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
797 {return blk->GetUIntValue(n);}
798
799template <>
800short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
801 {return blk->GetShortValue(n);}
802
803template <>
804ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
805 {return blk->GetUShortValue(n);}
806
807template <>
808longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
809 {return blk->GetBigintValue(n);}
810
811template <>
812ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
813 {return blk->GetUBigintValue(n);}
814
815template <>
816double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
817 {return blk->GetFloatValue(n);}
818
819template <>
820char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
821 {return blk->GetTinyValue(n);}
822
823template <>
824uchar 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/***********************************************************************/
831template <class TYPE>
832void 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/***********************************************************************/
853template <class TYPE>
854bool 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/***********************************************************************/
884template <class TYPE>
885char *TYPVAL<TYPE>::ShowValue(char *buf, int len)
886 {
887 sprintf(buf, Xfmt, len, Tval);
888 return buf;
889 } // end of ShowValue
890
891template <>
892char *TYPVAL<double>::ShowValue(char *buf, int len)
893 {
894 // TODO: use snprintf to avoid possible overflow
895 sprintf(buf, Xfmt, len, Prec, Tval);
896 return buf;
897 } // end of ShowValue
898
899/***********************************************************************/
900/* TYPVAL GetCharString: get string representation of a typed value. */
901/***********************************************************************/
902template <class TYPE>
903char *TYPVAL<TYPE>::GetCharString(char *p)
904 {
905 sprintf(p, Fmt, Tval);
906 return p;
907 } // end of GetCharString
908
909template <>
910char *TYPVAL<double>::GetCharString(char *p)
911 {
912 sprintf(p, Fmt, Prec, Tval);
913 return p;
914 } // end of GetCharString
915
916#if 0
917/***********************************************************************/
918/* TYPVAL GetShortString: get short representation of a typed value. */
919/***********************************************************************/
920template <class TYPE>
921char *TYPVAL<TYPE>::GetShortString(char *p, int n)
922 {
923 sprintf(p, "%*hd", n, (short)Tval);
924 return p;
925 } // end of GetShortString
926
927/***********************************************************************/
928/* TYPVAL GetIntString: get int representation of a typed value. */
929/***********************************************************************/
930template <class TYPE>
931char *TYPVAL<TYPE>::GetIntString(char *p, int n)
932 {
933 sprintf(p, "%*d", n, (int)Tval);
934 return p;
935 } // end of GetIntString
936
937/***********************************************************************/
938/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
939/***********************************************************************/
940template <class TYPE>
941char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
942 {
943 sprintf(p, "%*lld", n, (longlong)Tval);
944 return p;
945 } // end of GetBigintString
946
947/***********************************************************************/
948/* TYPVAL GetFloatString: get double representation of a typed value. */
949/***********************************************************************/
950template <class TYPE>
951char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
952 {
953 sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
954 return p;
955 } // end of GetFloatString
956
957/***********************************************************************/
958/* TYPVAL GetTinyString: get char representation of a typed value. */
959/***********************************************************************/
960template <class TYPE>
961char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
962 {
963 sprintf(p, "%*d", n, (int)(char)Tval);
964 return p;
965 } // end of GetIntString
966#endif // 0
967
968/***********************************************************************/
969/* TYPVAL compare value with another Value. */
970/***********************************************************************/
971template <class TYPE>
972bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
973 {
974 if (this == vp)
975 return true;
976 else if (chktype && Type != vp->GetType())
977 return false;
978 else if (chktype && Unsigned != vp->IsUnsigned())
979 return false;
980 else if (Null || vp->IsNull())
981 return false;
982 else
983 return (Tval == GetTypedValue(vp));
984
985 } // end of IsEqual
986
987/***********************************************************************/
988/* Compare values and returns 1, 0 or -1 according to comparison. */
989/* This function is used for evaluation of numeric filters. */
990/***********************************************************************/
991template <class TYPE>
992int TYPVAL<TYPE>::CompareValue(PVAL vp)
993 {
994//assert(vp->GetType() == Type);
995
996 // Process filtering on numeric values.
997 TYPE n = GetTypedValue(vp);
998
999//if (trace(1))
1000// htrc(" Comparing: val=%d,%d\n", Tval, n);
1001
1002 return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
1003 } // end of CompareValue
1004
1005/***********************************************************************/
1006/* Return max type value if b is true, else min type value. */
1007/***********************************************************************/
1008template <>
1009short TYPVAL<short>::MinMaxVal(bool b)
1010 {return (b) ? INT_MAX16 : INT_MIN16;}
1011
1012template <>
1013ushort TYPVAL<ushort>::MinMaxVal(bool b)
1014 {return (b) ? UINT_MAX16 : 0;}
1015
1016template <>
1017int TYPVAL<int>::MinMaxVal(bool b)
1018 {return (b) ? INT_MAX32 : INT_MIN32;}
1019
1020template <>
1021uint TYPVAL<uint>::MinMaxVal(bool b)
1022 {return (b) ? UINT_MAX32 : 0;}
1023
1024template <>
1025longlong TYPVAL<longlong>::MinMaxVal(bool b)
1026 {return (b) ? INT_MAX64 : INT_MIN64;}
1027
1028template <>
1029ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b)
1030 {return (b) ? 0xFFFFFFFFFFFFFFFFLL : 0;}
1031
1032template <>
1033double TYPVAL<double>::MinMaxVal(bool)
1034 {assert(false); return 0.0;}
1035
1036template <>
1037char TYPVAL<char>::MinMaxVal(bool b)
1038 {return (b) ? INT_MAX8 : INT_MIN8;}
1039
1040template <>
1041uchar TYPVAL<uchar>::MinMaxVal(bool b)
1042 {return (b) ? UINT_MAX8 : 0;}
1043
1044/***********************************************************************/
1045/* SafeAdd: adds a value and test whether overflow/underflow occurred. */
1046/***********************************************************************/
1047template <class TYPE>
1048TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
1049 {
1050 PGLOBAL& g = Global;
1051 TYPE n = n1 + n2;
1052
1053 if ((n2 > 0) && (n < n1)) {
1054 // Overflow
1055 strcpy(g->Message, MSG(FIX_OVFLW_ADD));
1056 throw 138;
1057 } else if ((n2 < 0) && (n > n1)) {
1058 // Underflow
1059 strcpy(g->Message, MSG(FIX_UNFLW_ADD));
1060 throw 138;
1061 } // endif's n2
1062
1063 return n;
1064 } // end of SafeAdd
1065
1066template <>
1067inline double TYPVAL<double>::SafeAdd(double n1, double n2)
1068 {
1069 return n1 + n2;
1070 } // end of SafeAdd
1071
1072/***********************************************************************/
1073/* SafeMult: multiply values and test whether overflow occurred. */
1074/***********************************************************************/
1075template <class TYPE>
1076TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2)
1077 {
1078 PGLOBAL& g = Global;
1079 double n = (double)n1 * (double)n2;
1080
1081 if (n > MinMaxVal(true)) {
1082 // Overflow
1083 strcpy(g->Message, MSG(FIX_OVFLW_TIMES));
1084 throw 138;
1085 } else if (n < MinMaxVal(false)) {
1086 // Underflow
1087 strcpy(g->Message, MSG(FIX_UNFLW_TIMES));
1088 throw 138;
1089 } // endif's n2
1090
1091 return (TYPE)n;
1092 } // end of SafeMult
1093
1094template <>
1095inline double TYPVAL<double>::SafeMult(double n1, double n2)
1096 {
1097 return n1 * n2;
1098 } // end of SafeMult
1099
1100/***********************************************************************/
1101/* Compute defined functions for the type. */
1102/***********************************************************************/
1103template <class TYPE>
1104bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1105 {
1106 bool rc = false;
1107 TYPE val[2];
1108
1109 assert(np == 2);
1110
1111 for (int i = 0; i < np; i++)
1112 val[i] = GetTypedValue(vp[i]);
1113
1114 switch (op) {
1115 case OP_ADD:
1116 Tval = SafeAdd(val[0], val[1]);
1117 break;
1118 case OP_MULT:
1119 Tval = SafeMult(val[0], val[1]);
1120 break;
1121 case OP_DIV:
1122 if (!val[1]) {
1123 strcpy(g->Message, MSG(ZERO_DIVIDE));
1124 return true;
1125 } // endif
1126
1127 Tval = val[0] / val[1];
1128 break;
1129 default:
1130 rc = Compall(g, vp, np, op);
1131 break;
1132 } // endswitch op
1133
1134 return rc;
1135 } // end of Compute
1136
1137template <>
1138bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1139 {
1140 bool rc = false;
1141 double val[2];
1142
1143 assert(np == 2);
1144
1145 for (int i = 0; i < np; i++)
1146 val[i] = vp[i]->GetFloatValue();
1147
1148 switch (op) {
1149 case OP_ADD:
1150 Tval = val[0] + val[1];
1151 break;
1152 case OP_MULT:
1153 Tval = val[0] * val[1];
1154 break;
1155 default:
1156 rc = Compall(g, vp, np, op);
1157 } // endswitch op
1158
1159 return rc;
1160 } // end of Compute
1161
1162/***********************************************************************/
1163/* Compute a function for all types. */
1164/***********************************************************************/
1165template <class TYPE>
1166bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1167 {
1168 TYPE val[2];
1169
1170 for (int i = 0; i < np; i++)
1171 val[i] = GetTypedValue(vp[i]);
1172
1173 switch (op) {
1174 case OP_DIV:
1175 if (val[0]) {
1176 if (!val[1]) {
1177 strcpy(g->Message, MSG(ZERO_DIVIDE));
1178 return true;
1179 } // endif
1180
1181 Tval = val[0] / val[1];
1182 } else
1183 Tval = 0;
1184
1185 break;
1186 case OP_MIN:
1187 Tval = MY_MIN(val[0], val[1]);
1188 break;
1189 case OP_MAX:
1190 Tval = MY_MAX(val[0], val[1]);
1191 break;
1192 default:
1193// sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1194 strcpy(g->Message, "Function not supported");
1195 return true;
1196 } // endswitch op
1197
1198 return false;
1199 } // end of Compall
1200
1201/***********************************************************************/
1202/* FormatValue: This function set vp (a STRING value) to the string */
1203/* constructed from its own value formated using the fmt format. */
1204/* This function assumes that the format matches the value type. */
1205/***********************************************************************/
1206template <class TYPE>
1207bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
1208 {
1209 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
1210 int n = sprintf(buf, fmt, Tval);
1211
1212 return (n > vp->GetValLen());
1213 } // end of FormatValue
1214
1215/***********************************************************************/
1216/* TYPVAL SetFormat function (used to set SELECT output format). */
1217/***********************************************************************/
1218template <class TYPE>
1219bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
1220 {
1221 char c[32];
1222
1223 fmt.Type[0] = *GetFormatType(Type);
1224 fmt.Length = sprintf(c, Fmt, Tval);
1225 fmt.Prec = Prec;
1226 return false;
1227 } // end of SetConstFormat
1228
1229/* -------------------------- Class STRING --------------------------- */
1230
1231/***********************************************************************/
1232/* STRING public constructor from a constant string. */
1233/***********************************************************************/
1234TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
1235 {
1236 Strp = s;
1237 Len = strlen(s);
1238 Clen = Len;
1239 Ci = (c == 1);
1240 } // end of STRING constructor
1241
1242/***********************************************************************/
1243/* STRING public constructor from char. */
1244/***********************************************************************/
1245TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
1246 : VALUE(TYPE_STRING)
1247 {
1248 Len = (g) ? n : (s) ? strlen(s) : 0;
1249
1250 if (!s) {
1251 if (g) {
1252 if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
1253 memset(Strp, 0, Len + 1);
1254 else
1255 Len = 0;
1256
1257 } else
1258 assert(false);
1259
1260 } else
1261 Strp = s;
1262
1263 Clen = Len;
1264 Ci = (c != 0);
1265 } // end of STRING constructor
1266
1267/***********************************************************************/
1268/* Get the tiny value represented by the Strp string. */
1269/***********************************************************************/
1270char TYPVAL<PSZ>::GetTinyValue(void)
1271 {
1272 bool m;
1273 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
1274
1275 return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
1276 } // end of GetTinyValue
1277
1278/***********************************************************************/
1279/* Get the unsigned tiny value represented by the Strp string. */
1280/***********************************************************************/
1281uchar TYPVAL<PSZ>::GetUTinyValue(void)
1282 {
1283 return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
1284 } // end of GetUTinyValue
1285
1286/***********************************************************************/
1287/* Get the short value represented by the Strp string. */
1288/***********************************************************************/
1289short TYPVAL<PSZ>::GetShortValue(void)
1290 {
1291 bool m;
1292 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
1293
1294 return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
1295 } // end of GetShortValue
1296
1297/***********************************************************************/
1298/* Get the unsigned short value represented by the Strp string. */
1299/***********************************************************************/
1300ushort TYPVAL<PSZ>::GetUShortValue(void)
1301 {
1302 return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
1303 } // end of GetUshortValue
1304
1305/***********************************************************************/
1306/* Get the integer value represented by the Strp string. */
1307/***********************************************************************/
1308int TYPVAL<PSZ>::GetIntValue(void)
1309 {
1310 bool m;
1311 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
1312
1313 return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
1314 } // end of GetIntValue
1315
1316/***********************************************************************/
1317/* Get the unsigned integer value represented by the Strp string. */
1318/***********************************************************************/
1319uint TYPVAL<PSZ>::GetUIntValue(void)
1320 {
1321 return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
1322 } // end of GetUintValue
1323
1324/***********************************************************************/
1325/* Get the big integer value represented by the Strp string. */
1326/***********************************************************************/
1327longlong TYPVAL<PSZ>::GetBigintValue(void)
1328 {
1329 bool m;
1330 ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
1331
1332 return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
1333 } // end of GetBigintValue
1334
1335/***********************************************************************/
1336/* Get the unsigned big integer value represented by the Strp string. */
1337/***********************************************************************/
1338ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
1339 {
1340 return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
1341 } // end of GetUBigintValue
1342
1343/***********************************************************************/
1344/* STRING SetValue: copy the value of another Value object. */
1345/***********************************************************************/
1346bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
1347 {
1348 if (valp != this) {
1349 if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
1350 return true;
1351
1352 char buf[64];
1353
1354 if (!(Null = (valp->IsNull() && Nullable)))
1355 strncpy(Strp, valp->GetCharString(buf), Len);
1356 else
1357 Reset();
1358
1359 } // endif valp
1360
1361 return false;
1362 } // end of SetValue_pval
1363
1364/***********************************************************************/
1365/* STRING SetValue: fill string with chars extracted from a line. */
1366/***********************************************************************/
1367bool TYPVAL<PSZ>::SetValue_char(const char *cp, int n)
1368 {
1369 bool rc = false;
1370
1371 if (!cp || n == 0) {
1372 Reset();
1373 Null = (cp) ? false : Nullable;
1374 } else if (cp != Strp) {
1375 const char *p = cp + n - 1;
1376
1377 for (; p >= cp; p--, n--)
1378 if (*p && *p != ' ')
1379 break;
1380
1381 rc = n > Len;
1382
1383 if ((n = MY_MIN(n, Len))) {
1384 strncpy(Strp, cp, n);
1385 Strp[n] = '\0';
1386
1387 if (trace(2))
1388 htrc(" Setting string to: '%s'\n", Strp);
1389
1390 } else
1391 Reset();
1392
1393 Null = false;
1394 } // endif p
1395
1396 return rc;
1397 } // end of SetValue_char
1398
1399/***********************************************************************/
1400/* STRING SetValue: fill string with another string. */
1401/***********************************************************************/
1402void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
1403 {
1404 if (!s) {
1405 Reset();
1406 Null = Nullable;
1407 } else if (s != Strp) {
1408 strncpy(Strp, s, Len);
1409 Null = false;
1410 } // endif s
1411
1412 } // end of SetValue_psz
1413
1414/***********************************************************************/
1415/* STRING SetValue: fill string with a string extracted from a block. */
1416/***********************************************************************/
1417void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
1418 {
1419 // STRBLK's can return a NULL pointer
1420 PSZ vp = blk->GetCharString(Strp, n);
1421
1422 if (vp != Strp)
1423 SetValue_psz(vp);
1424
1425 } // end of SetValue_pvblk
1426
1427/***********************************************************************/
1428/* STRING SetValue: get the character representation of an integer. */
1429/***********************************************************************/
1430void TYPVAL<PSZ>::SetValue(int n)
1431 {
1432 char buf[16];
1433 PGLOBAL& g = Global;
1434 int k = sprintf(buf, "%d", n);
1435
1436 if (k > Len) {
1437 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1438 throw 138;
1439 } else
1440 SetValue_psz(buf);
1441
1442 Null = false;
1443 } // end of SetValue
1444
1445/***********************************************************************/
1446/* STRING SetValue: get the character representation of an uint. */
1447/***********************************************************************/
1448void TYPVAL<PSZ>::SetValue(uint n)
1449 {
1450 char buf[16];
1451 PGLOBAL& g = Global;
1452 int k = sprintf(buf, "%u", n);
1453
1454 if (k > Len) {
1455 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1456 throw 138;
1457 } else
1458 SetValue_psz(buf);
1459
1460 Null = false;
1461 } // end of SetValue
1462
1463/***********************************************************************/
1464/* STRING SetValue: get the character representation of a short int. */
1465/***********************************************************************/
1466void TYPVAL<PSZ>::SetValue(short i)
1467 {
1468 SetValue((int)i);
1469 Null = false;
1470 } // end of SetValue
1471
1472/***********************************************************************/
1473/* STRING SetValue: get the character representation of a ushort int. */
1474/***********************************************************************/
1475void TYPVAL<PSZ>::SetValue(ushort i)
1476 {
1477 SetValue((uint)i);
1478 Null = false;
1479 } // end of SetValue
1480
1481/***********************************************************************/
1482/* STRING SetValue: get the character representation of a big integer.*/
1483/***********************************************************************/
1484void TYPVAL<PSZ>::SetValue(longlong n)
1485 {
1486 char buf[24];
1487 PGLOBAL& g = Global;
1488 int k = sprintf(buf, "%lld", n);
1489
1490 if (k > Len) {
1491 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1492 throw 138;
1493 } else
1494 SetValue_psz(buf);
1495
1496 Null = false;
1497 } // end of SetValue
1498
1499/***********************************************************************/
1500/* STRING SetValue: get the character representation of a big integer.*/
1501/***********************************************************************/
1502void TYPVAL<PSZ>::SetValue(ulonglong n)
1503 {
1504 char buf[24];
1505 PGLOBAL& g = Global;
1506 int k = sprintf(buf, "%llu", n);
1507
1508 if (k > Len) {
1509 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1510 throw 138;
1511 } else
1512 SetValue_psz(buf);
1513
1514 Null = false;
1515 } // end of SetValue
1516
1517/***********************************************************************/
1518/* STRING SetValue: get the character representation of a double. */
1519/***********************************************************************/
1520void TYPVAL<PSZ>::SetValue(double f)
1521 {
1522 char *p, buf[64];
1523 PGLOBAL& g = Global;
1524 int k = sprintf(buf, "%lf", f);
1525
1526 for (p = buf + k - 1; p >= buf; p--)
1527 if (*p == '0') {
1528 *p = 0;
1529 k--;
1530 } else
1531 break;
1532
1533 if (k > Len) {
1534 sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
1535 throw 138;
1536 } else
1537 SetValue_psz(buf);
1538
1539 Null = false;
1540 } // end of SetValue
1541
1542/***********************************************************************/
1543/* STRING SetValue: get the character representation of a tiny int. */
1544/***********************************************************************/
1545void TYPVAL<PSZ>::SetValue(char c)
1546 {
1547 SetValue((int)c);
1548 Null = false;
1549 } // end of SetValue
1550
1551/***********************************************************************/
1552/* STRING SetValue: get the character representation of a tiny int. */
1553/***********************************************************************/
1554void TYPVAL<PSZ>::SetValue(uchar c)
1555 {
1556 SetValue((uint)c);
1557 Null = false;
1558 } // end of SetValue
1559
1560/***********************************************************************/
1561/* STRING SetBinValue: fill string with chars extracted from a line. */
1562/***********************************************************************/
1563void TYPVAL<PSZ>::SetBinValue(void *p)
1564 {
1565 SetValue_char((const char *)p, Len);
1566 } // end of SetBinValue
1567
1568/***********************************************************************/
1569/* GetBinValue: fill a buffer with the internal binary value. */
1570/* This function checks whether the buffer length is enough and */
1571/* returns true if not. Actual filling occurs only if go is true. */
1572/* Currently used by WriteColumn of binary files. */
1573/***********************************************************************/
1574bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
1575 {
1576 int len = (Null) ? 0 : strlen(Strp);
1577
1578 if (len > buflen)
1579 return true;
1580 else if (go) {
1581 memset(buf, ' ', buflen);
1582 memcpy(buf, Strp, len);
1583 } // endif go
1584
1585 return false;
1586 } // end of GetBinValue
1587
1588/***********************************************************************/
1589/* STRING ShowValue: get string representation of a char value. */
1590/***********************************************************************/
1591char *TYPVAL<PSZ>::ShowValue(char *, int)
1592 {
1593 return Strp;
1594 } // end of ShowValue
1595
1596/***********************************************************************/
1597/* STRING GetCharString: get string representation of a char value. */
1598/***********************************************************************/
1599char *TYPVAL<PSZ>::GetCharString(char *)
1600 {
1601 return Strp;
1602 } // end of GetCharString
1603
1604/***********************************************************************/
1605/* STRING compare value with another Value. */
1606/***********************************************************************/
1607bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
1608 {
1609 if (this == vp)
1610 return true;
1611 else if (chktype && Type != vp->GetType())
1612 return false;
1613 else if (Null || vp->IsNull())
1614 return false;
1615
1616 char buf[64];
1617
1618 if (Ci || vp->IsCi())
1619 return !stricmp(Strp, vp->GetCharString(buf));
1620 else // (!Ci)
1621 return !strcmp(Strp, vp->GetCharString(buf));
1622
1623 } // end of IsEqual
1624
1625/***********************************************************************/
1626/* Compare values and returns 1, 0 or -1 according to comparison. */
1627/* This function is used for evaluation of numeric filters. */
1628/***********************************************************************/
1629int TYPVAL<PSZ>::CompareValue(PVAL vp)
1630 {
1631 int n;
1632//assert(vp->GetType() == Type);
1633
1634 if (trace(1))
1635 htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue());
1636
1637 // Process filtering on character strings.
1638 if (Ci || vp->IsCi())
1639 n = stricmp(Strp, vp->GetCharValue());
1640 else
1641 n = strcmp(Strp, vp->GetCharValue());
1642
1643#if defined(__WIN__)
1644 if (n == _NLSCMPERROR)
1645 return n; // Here we should raise an error
1646#endif // __WIN__
1647
1648 return (n > 0) ? 1 : (n < 0) ? -1 : 0;
1649 } // end of CompareValue
1650
1651/***********************************************************************/
1652/* Compute a function on a string. */
1653/***********************************************************************/
1654bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
1655 {
1656 char *p[2], val[2][32];
1657 int i;
1658
1659 if (trace(1))
1660 htrc("Compute: np=%d op=%d\n", np, op);
1661
1662 for (i = 0; i < np; i++)
1663 if (!vp[i]->IsNull()) {
1664 p[i] = vp[i]->GetCharString(val[i]);
1665
1666 if (trace(1))
1667 htrc("p[%d]=%s\n", i, p[i]);
1668
1669 } else
1670 return false;
1671
1672 switch (op) {
1673 case OP_CNC:
1674 assert(np == 1 || np == 2);
1675
1676 if (np == 2)
1677 SetValue_psz(p[0]);
1678
1679 if ((i = Len - (signed)strlen(Strp)) > 0)
1680 strncat(Strp, p[np - 1], i);
1681
1682 if (trace(1))
1683 htrc("Strp=%s\n", Strp);
1684
1685 break;
1686 case OP_MIN:
1687 assert(np == 2);
1688 SetValue_psz((strcmp(p[0], p[1]) < 0) ? p[0] : p[1]);
1689 break;
1690 case OP_MAX:
1691 assert(np == 2);
1692 SetValue_psz((strcmp(p[0], p[1]) > 0) ? p[0] : p[1]);
1693 break;
1694 default:
1695 // sprintf(g->Message, MSG(BAD_EXP_OPER), op);
1696 strcpy(g->Message, "Function not supported");
1697 return true;
1698 } // endswitch op
1699
1700 Null = false;
1701 return false;
1702 } // end of Compute
1703
1704/***********************************************************************/
1705/* FormatValue: This function set vp (a STRING value) to the string */
1706/* constructed from its own value formated using the fmt format. */
1707/* This function assumes that the format matches the value type. */
1708/***********************************************************************/
1709bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
1710 {
1711 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
1712 int n = sprintf(buf, fmt, Strp);
1713
1714 return (n > vp->GetValLen());
1715 } // end of FormatValue
1716
1717/***********************************************************************/
1718/* STRING SetFormat function (used to set SELECT output format). */
1719/***********************************************************************/
1720bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
1721 {
1722 fmt.Type[0] = 'C';
1723 fmt.Length = Len;
1724 fmt.Prec = 0;
1725 return false;
1726 } // end of SetConstFormat
1727
1728/***********************************************************************/
1729/* Make string output of an object value. */
1730/***********************************************************************/
1731void TYPVAL<PSZ>::Prints(PGLOBAL g, char *ps, uint z)
1732{
1733 if (Null)
1734 strncpy(ps, "null", z);
1735 else
1736 strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
1737
1738} // end of Prints
1739
1740/* -------------------------- Class DECIMAL -------------------------- */
1741
1742/***********************************************************************/
1743/* DECIMAL public constructor from a constant string. */
1744/***********************************************************************/
1745DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
1746 {
1747 if (s) {
1748 char *p = strchr(Strp, '.');
1749
1750 Prec = (p) ? (int)(Len - (p - Strp)) : 0;
1751 } // endif s
1752
1753 Type = TYPE_DECIM;
1754 } // end of DECVAL constructor
1755
1756/***********************************************************************/
1757/* DECIMAL public constructor from char. */
1758/***********************************************************************/
1759DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
1760 : TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
1761 {
1762 Prec = prec;
1763 Unsigned = uns;
1764 Type = TYPE_DECIM;
1765 } // end of DECVAL constructor
1766
1767/***********************************************************************/
1768/* DECIMAL: Check whether the numerica value is equal to 0. */
1769/***********************************************************************/
1770bool DECVAL::IsZero(void)
1771 {
1772 for (int i = 0; Strp[i]; i++)
1773 if (!strchr("0 +-.", Strp[i]))
1774 return false;
1775
1776 return true;
1777 } // end of IsZero
1778
1779/***********************************************************************/
1780/* DECIMAL: Reset value to zero. */
1781/***********************************************************************/
1782void DECVAL::Reset(void)
1783{
1784 int i = 0;
1785
1786 Strp[i++] = '0';
1787
1788 if (Prec) {
1789 Strp[i++] = '.';
1790
1791 do {
1792 Strp[i++] = '0';
1793 } while (i < Prec + 2);
1794
1795 } // endif Prec
1796
1797 Strp[i] = 0;
1798} // end of Reset
1799
1800/***********************************************************************/
1801/* DECIMAL ShowValue: get string representation right justified. */
1802/***********************************************************************/
1803char *DECVAL::ShowValue(char *buf, int len)
1804 {
1805 sprintf(buf, Xfmt, len, Strp);
1806 return buf;
1807 } // end of ShowValue
1808
1809/***********************************************************************/
1810/* GetBinValue: fill a buffer with the internal binary value. */
1811/* This function checks whether the buffer length is enough and */
1812/* returns true if not. Actual filling occurs only if go is true. */
1813/* Currently used by WriteColumn of binary files. */
1814/***********************************************************************/
1815bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
1816 {
1817 int len = (Null) ? 0 : strlen(Strp);
1818
1819 if (len > buflen)
1820 return true;
1821 else if (go) {
1822 memset(buf, ' ', buflen - len);
1823 memcpy((char*)buf + buflen - len, Strp, len);
1824 } // endif go
1825
1826 return false;
1827 } // end of GetBinValue
1828
1829/***********************************************************************/
1830/* DECIMAL compare value with another Value. */
1831/***********************************************************************/
1832bool DECVAL::IsEqual(PVAL vp, bool chktype)
1833 {
1834 if (this == vp)
1835 return true;
1836 else if (chktype && Type != vp->GetType())
1837 return false;
1838 else if (Null || vp->IsNull())
1839 return false;
1840
1841 char buf[64];
1842
1843 return !strcmp(Strp, vp->GetCharString(buf));
1844 } // end of IsEqual
1845
1846/***********************************************************************/
1847/* Compare values and returns 1, 0 or -1 according to comparison. */
1848/* This function is used for evaluation of numeric filters. */
1849/***********************************************************************/
1850int DECVAL::CompareValue(PVAL vp)
1851 {
1852//assert(vp->GetType() == Type);
1853
1854 // Process filtering on numeric values.
1855 double f = atof(Strp), n = vp->GetFloatValue();
1856
1857//if (trace(1))
1858// htrc(" Comparing: val=%d,%d\n", f, n);
1859
1860 return (f > n) ? 1 : (f < n) ? (-1) : 0;
1861 } // end of CompareValue
1862
1863/* -------------------------- Class BINVAL --------------------------- */
1864
1865/***********************************************************************/
1866/* BINVAL public constructor from bytes. */
1867/***********************************************************************/
1868BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
1869 {
1870 assert(g);
1871//Len = n;
1872 Len = (g) ? n : (p) ? strlen((char*)p) : 0;
1873 Clen = cl;
1874 Binp = PlugSubAlloc(g, NULL, Clen + 1);
1875 memset(Binp, 0, Clen + 1);
1876
1877 if (p)
1878 memcpy(Binp, p, Len);
1879
1880 Chrp = NULL;
1881 } // end of BINVAL constructor
1882
1883/***********************************************************************/
1884/* BINVAL: Check whether the hexadecimal value is equal to 0. */
1885/***********************************************************************/
1886bool BINVAL::IsZero(void)
1887 {
1888 for (int i = 0; i < Len; i++)
1889 if (((char*)Binp)[i] != 0)
1890 return false;
1891
1892 return true;
1893 } // end of IsZero
1894
1895/***********************************************************************/
1896/* BINVAL: Reset value to zero. */
1897/***********************************************************************/
1898void BINVAL::Reset(void)
1899{
1900 memset(Binp, 0, Clen);
1901 Len = 0;
1902} // end of Reset
1903
1904/***********************************************************************/
1905/* Get the tiny value pointed by Binp. */
1906/***********************************************************************/
1907char BINVAL::GetTinyValue(void)
1908 {
1909 return *(char*)Binp;
1910 } // end of GetTinyValue
1911
1912/***********************************************************************/
1913/* Get the unsigned tiny value pointed by Binp. */
1914/***********************************************************************/
1915uchar BINVAL::GetUTinyValue(void)
1916 {
1917 return *(uchar*)Binp;
1918 } // end of GetUTinyValue
1919
1920/***********************************************************************/
1921/* Get the short value pointed by Binp. */
1922/***********************************************************************/
1923short BINVAL::GetShortValue(void)
1924 {
1925 if (Len >= 2)
1926 return *(short*)Binp;
1927 else
1928 return (short)GetTinyValue();
1929
1930 } // end of GetShortValue
1931
1932/***********************************************************************/
1933/* Get the unsigned short value pointed by Binp. */
1934/***********************************************************************/
1935ushort BINVAL::GetUShortValue(void)
1936 {
1937 return (ushort)GetShortValue();
1938 } // end of GetUshortValue
1939
1940/***********************************************************************/
1941/* Get the integer value pointed by Binp. */
1942/***********************************************************************/
1943int BINVAL::GetIntValue(void)
1944 {
1945 if (Len >= 4)
1946 return *(int*)Binp;
1947 else
1948 return (int)GetShortValue();
1949
1950 } // end of GetIntValue
1951
1952/***********************************************************************/
1953/* Get the unsigned integer value pointed by Binp. */
1954/***********************************************************************/
1955uint BINVAL::GetUIntValue(void)
1956 {
1957 return (uint)GetIntValue();
1958 } // end of GetUintValue
1959
1960/***********************************************************************/
1961/* Get the big integer value pointed by Binp. */
1962/***********************************************************************/
1963longlong BINVAL::GetBigintValue(void)
1964 {
1965 if (Len >= 8)
1966 return *(longlong*)Binp;
1967 else
1968 return (longlong)GetIntValue();
1969
1970 } // end of GetBigintValue
1971
1972/***********************************************************************/
1973/* Get the unsigned big integer value pointed by Binp. */
1974/***********************************************************************/
1975ulonglong BINVAL::GetUBigintValue(void)
1976 {
1977 return (ulonglong)GetBigintValue();
1978 } // end of GetUBigintValue
1979
1980/***********************************************************************/
1981/* Get the double value pointed by Binp. */
1982/***********************************************************************/
1983double BINVAL::GetFloatValue(void)
1984{
1985 if (Len >= 8)
1986 return *(double*)Binp;
1987 else if (Len >= 4)
1988 return (double)(*(float*)Binp);
1989 else
1990 return 0.0;
1991
1992} // end of GetFloatValue
1993
1994/***********************************************************************/
1995/* BINVAL SetValue: copy the value of another Value object. */
1996/***********************************************************************/
1997bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
1998 {
1999 bool rc = false;
2000
2001 if (valp != this) {
2002 if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen))
2003 return true;
2004
2005 if (!(Null = valp->IsNull() && Nullable)) {
2006 int len = Len;
2007
2008 if ((rc = (Len = valp->GetSize()) > Clen))
2009 Len = Clen;
2010 else if (len > Len)
2011 memset(Binp, 0, len);
2012
2013 memcpy(Binp, valp->GetTo_Val(), Len);
2014 ((char*)Binp)[Len] = 0;
2015 } else
2016 Reset();
2017
2018 } // endif valp
2019
2020 return rc;
2021 } // end of SetValue_pval
2022
2023/***********************************************************************/
2024/* BINVAL SetValue: fill value with chars extracted from a line. */
2025/***********************************************************************/
2026bool BINVAL::SetValue_char(const char *p, int n)
2027 {
2028 bool rc;
2029
2030 if (p && n > 0) {
2031 int len = Len;
2032
2033 if (len > (Len = MY_MIN(n, Clen)))
2034 memset(Binp, 0, len);
2035
2036 memcpy(Binp, p, Len);
2037 ((char*)Binp)[Len] = 0;
2038 rc = n > Clen;
2039 Null = false;
2040 } else {
2041 rc = false;
2042 Reset();
2043 Null = Nullable;
2044 } // endif p
2045
2046 return rc;
2047 } // end of SetValue_char
2048
2049/***********************************************************************/
2050/* BINVAL SetValue: fill value with another string. */
2051/***********************************************************************/
2052void BINVAL::SetValue_psz(PCSZ s)
2053 {
2054 if (s) {
2055 int len = Len;
2056
2057 if (len > (Len = MY_MIN(Clen, (signed)strlen(s))))
2058 memset(Binp, 0, len);
2059
2060 memcpy(Binp, s, Len);
2061 ((char*)Binp)[Len] = 0;
2062 Null = false;
2063 } else {
2064 Reset();
2065 Null = Nullable;
2066 } // endif s
2067
2068 } // end of SetValue_psz
2069
2070/***********************************************************************/
2071/* BINVAL SetValue: fill value with bytes extracted from a block. */
2072/***********************************************************************/
2073void BINVAL::SetValue_pvblk(PVBLK blk, int n)
2074 {
2075 // STRBLK's can return a NULL pointer
2076 void *vp = blk->GetValPtrEx(n);
2077
2078 if (!vp || blk->IsNull(n)) {
2079 Reset();
2080 Null = Nullable;
2081 } else if (vp != Binp) {
2082 int len = Len;
2083
2084 if (blk->GetType() == TYPE_STRING)
2085 Len = strlen((char*)vp);
2086 else
2087 Len = blk->GetVlen();
2088
2089 if (len > (Len = MY_MIN(Clen, Len)))
2090 memset(Binp, 0, len);
2091
2092 memcpy(Binp, vp, Len);
2093 ((char*)Binp)[Len] = 0;
2094 Null = false;
2095 } // endif vp
2096
2097 } // end of SetValue_pvblk
2098
2099/***********************************************************************/
2100/* BINVAL SetValue: get the binary representation of an integer. */
2101/***********************************************************************/
2102void BINVAL::SetValue(int n)
2103 {
2104 if (Clen >= 4) {
2105 if (Len > 4)
2106 memset(Binp, 0, Len);
2107
2108 *((int*)Binp) = n;
2109 Len = 4;
2110 } else
2111 SetValue((short)n);
2112
2113 } // end of SetValue
2114
2115/***********************************************************************/
2116/* BINVAL SetValue: get the binary representation of an uint. */
2117/***********************************************************************/
2118void BINVAL::SetValue(uint n)
2119 {
2120 if (Clen >= 4) {
2121 if (Len > 4)
2122 memset(Binp, 0, Len);
2123
2124 *((uint*)Binp) = n;
2125 Len = 4;
2126 } else
2127 SetValue((ushort)n);
2128
2129 } // end of SetValue
2130
2131/***********************************************************************/
2132/* BINVAL SetValue: get the binary representation of a short int. */
2133/***********************************************************************/
2134void BINVAL::SetValue(short i)
2135 {
2136 if (Clen >= 2) {
2137 if (Len > 2)
2138 memset(Binp, 0, Len);
2139
2140 *((int*)Binp) = i;
2141 Len = 2;
2142 } else
2143 SetValue((char)i);
2144
2145 } // end of SetValue
2146
2147/***********************************************************************/
2148/* BINVAL SetValue: get the binary representation of a ushort int. */
2149/***********************************************************************/
2150void BINVAL::SetValue(ushort i)
2151 {
2152 if (Clen >= 2) {
2153 if (Len > 2)
2154 memset(Binp, 0, Len);
2155
2156 *((uint*)Binp) = i;
2157 Len = 2;
2158 } else
2159 SetValue((uchar)i);
2160
2161 } // end of SetValue
2162
2163/***********************************************************************/
2164/* BINVAL SetValue: get the binary representation of a big integer. */
2165/***********************************************************************/
2166void BINVAL::SetValue(longlong n)
2167 {
2168 if (Clen >= 8) {
2169 if (Len > 8)
2170 memset(Binp, 0, Len);
2171
2172 *((longlong*)Binp) = n;
2173 Len = 8;
2174 } else
2175 SetValue((int)n);
2176
2177 } // end of SetValue
2178
2179/***********************************************************************/
2180/* BINVAL SetValue: get the binary representation of a big integer. */
2181/***********************************************************************/
2182void BINVAL::SetValue(ulonglong n)
2183 {
2184 if (Clen >= 8) {
2185 if (Len > 8)
2186 memset(Binp, 0, Len);
2187
2188 *((ulonglong*)Binp) = n;
2189 Len = 8;
2190 } else
2191 SetValue((uint)n);
2192 } // end of SetValue
2193
2194/***********************************************************************/
2195/* BINVAL SetValue: get the binary representation of a double. */
2196/***********************************************************************/
2197void BINVAL::SetValue(double n)
2198 {
2199 if (Len > 8)
2200 memset(Binp, 0, Len);
2201
2202 if (Clen >= 8) {
2203 *((double*)Binp) = n;
2204 Len = 8;
2205 } else if (Clen >= 4) {
2206 *((float*)Binp) = (float)n;
2207 Len = 4;
2208 } else
2209 Len = 0;
2210
2211 } // end of SetValue
2212
2213/***********************************************************************/
2214/* BINVAL SetValue: get the character binary of a tiny int. */
2215/***********************************************************************/
2216void BINVAL::SetValue(char c)
2217 {
2218 if (Len > 1)
2219 memset(Binp, 0, Len);
2220
2221 *((char*)Binp) = c;
2222 Len = 1;
2223 } // end of SetValue
2224
2225/***********************************************************************/
2226/* BINVAL SetValue: get the binary representation of a tiny int. */
2227/***********************************************************************/
2228void BINVAL::SetValue(uchar c)
2229 {
2230 if (Len > 1)
2231 memset(Binp, 0, Len);
2232
2233 *((uchar*)Binp) = c;
2234 Len = 1;
2235 } // end of SetValue
2236
2237/***********************************************************************/
2238/* BINVAL SetBinValue: fill string with bytes extracted from a line. */
2239/***********************************************************************/
2240void BINVAL::SetBinValue(void *p)
2241 {
2242 memcpy(Binp, p, Clen);
2243 Len = Clen;
2244 } // end of SetBinValue
2245
2246/***********************************************************************/
2247/* GetBinValue: fill a buffer with the internal binary value. */
2248/* This function checks whether the buffer length is enough and */
2249/* returns true if not. Actual filling occurs only if go is true. */
2250/* Currently used by WriteColumn of binary files. */
2251/***********************************************************************/
2252bool BINVAL::GetBinValue(void *buf, int buflen, bool go)
2253 {
2254 if (Len > buflen)
2255 return true;
2256 else if (go) {
2257 memset(buf, 0, buflen);
2258 memcpy(buf, Binp, Len);
2259 } // endif go
2260
2261 return false;
2262 } // end of GetBinValue
2263
2264/***********************************************************************/
2265/* BINVAL ShowValue: get string representation of a binary value. */
2266/***********************************************************************/
2267char *BINVAL::ShowValue(char *buf, int len)
2268 {
2269 //int n = MY_MIN(Len, len / 2);
2270
2271 //sprintf(buf, GetXfmt(), n, Binp);
2272 //return buf;
2273 return (char*)Binp;
2274 } // end of ShowValue
2275
2276/***********************************************************************/
2277/* BINVAL GetCharString: get string representation of a binary value. */
2278/***********************************************************************/
2279char *BINVAL::GetCharString(char *)
2280 {
2281 if (!Chrp)
2282 Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
2283
2284 sprintf(Chrp, GetXfmt(), Len, Binp);
2285 return Chrp;
2286 } // end of GetCharString
2287
2288/***********************************************************************/
2289/* BINVAL compare value with another Value. */
2290/***********************************************************************/
2291bool BINVAL::IsEqual(PVAL vp, bool chktype)
2292 {
2293 if (this == vp)
2294 return true;
2295 else if (chktype && Type != vp->GetType())
2296 return false;
2297 else if (Null || vp->IsNull())
2298 return false;
2299 else if (Len != vp->GetSize())
2300 return false;
2301
2302 char *v1 = (char*)Binp;
2303 char *v2 = (char*)vp->GetTo_Val();
2304
2305 for (int i = 0; i < Len; i++)
2306 if (v1[i] != v2[i])
2307 return false;
2308
2309 return true;
2310 } // end of IsEqual
2311
2312/***********************************************************************/
2313/* FormatValue: This function set vp (a STRING value) to the string */
2314/* constructed from its own value formated using the fmt format. */
2315/* This function assumes that the format matches the value type. */
2316/***********************************************************************/
2317bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
2318 {
2319 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
2320 int n = sprintf(buf, fmt, Len, Binp);
2321
2322 return (n > vp->GetValLen());
2323 } // end of FormatValue
2324
2325/***********************************************************************/
2326/* BINVAL SetFormat function (used to set SELECT output format). */
2327/***********************************************************************/
2328bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
2329 {
2330 fmt.Type[0] = 'B';
2331 fmt.Length = Clen;
2332 fmt.Prec = 0;
2333 return false;
2334 } // end of SetConstFormat
2335
2336/* -------------------------- Class DTVAL ---------------------------- */
2337
2338/***********************************************************************/
2339/* DTVAL public constructor for new void values. */
2340/***********************************************************************/
2341DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
2342 : TYPVAL<int>((int)0, TYPE_DATE)
2343 {
2344 if (!fmt) {
2345 Pdtp = NULL;
2346 Sdate = NULL;
2347 DefYear = 0;
2348 Len = n;
2349 } else
2350 SetFormat(g, fmt, n, prec);
2351
2352//Type = TYPE_DATE;
2353 } // end of DTVAL constructor
2354
2355/***********************************************************************/
2356/* DTVAL public constructor from int. */
2357/***********************************************************************/
2358DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
2359 {
2360 Pdtp = NULL;
2361 Len = 19;
2362//Type = TYPE_DATE;
2363 Sdate = NULL;
2364 DefYear = 0;
2365 } // end of DTVAL constructor
2366
2367/***********************************************************************/
2368/* Set format so formatted dates can be converted on input/output. */
2369/***********************************************************************/
2370bool DTVAL::SetFormat(PGLOBAL g, PCSZ fmt, int len, int year)
2371 {
2372 Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
2373 Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
2374 DefYear = (int)((year > 9999) ? (year - 10000) : year);
2375 Len = len;
2376 return false;
2377 } // end of SetFormat
2378
2379/***********************************************************************/
2380/* Set format from the format of another date value. */
2381/***********************************************************************/
2382bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
2383 {
2384 DTVAL *vp;
2385
2386 if (valp->GetType() != TYPE_DATE) {
2387 sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
2388 return true;
2389 } else
2390 vp = (DTVAL*)valp;
2391
2392 Len = vp->Len;
2393 Pdtp = vp->Pdtp;
2394 Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
2395 DefYear = vp->DefYear;
2396 return false;
2397 } // end of SetFormat
2398
2399/***********************************************************************/
2400/* We need TimeShift because the mktime C function does a correction */
2401/* for local time zone that we want to override for DB operations. */
2402/***********************************************************************/
2403void DTVAL::SetTimeShift(void)
2404 {
2405 struct tm dtm;
2406 memset(&dtm, 0, sizeof(dtm));
2407 dtm.tm_mday=2;
2408 dtm.tm_mon=0;
2409 dtm.tm_year=70;
2410
2411 Shift = (int)mktime(&dtm) - 86400;
2412
2413 if (trace(1))
2414 htrc("DTVAL Shift=%d\n", Shift);
2415
2416 } // end of SetTimeShift
2417
2418// Added by Alexander Barkov
2419static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
2420{
2421 bzero(tm, sizeof(*tm));
2422 tm->tm_year= ltime->year - 1900;
2423 tm->tm_mon= ltime->month - 1;
2424 tm->tm_mday= ltime->day;
2425 mktime(tm); // set tm->tm_wday tm->yday fields to get proper day name (OB)
2426 tm->tm_hour= ltime->hour;
2427 tm->tm_min= ltime->minute;
2428 tm->tm_sec= ltime->second;
2429} // end of TIME_to_localtime
2430
2431// Added by Alexander Barkov
2432static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
2433{
2434 MYSQL_TIME ltime;
2435 thd_gmt_sec_to_TIME(current_thd, &ltime, (my_time_t) *timep);
2436 TIME_to_localtime(tm, &ltime);
2437 return tm;
2438} // end of gmtime_mysql
2439
2440/***********************************************************************/
2441/* GetGmTime: returns a pointer to a static tm structure obtained */
2442/* though the gmtime C function. The purpose of this function is to */
2443/* extend the range of valid dates by accepting negative time values. */
2444/***********************************************************************/
2445struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
2446 {
2447 struct tm *datm;
2448 time_t t = (time_t)Tval;
2449
2450 if (Tval < 0) {
2451 int n;
2452
2453 for (n = 0; t < 0; n += 4)
2454 t += FOURYEARS;
2455
2456 datm = gmtime_mysql(&t, tm_buffer);
2457
2458 if (datm)
2459 datm->tm_year -= n;
2460
2461 } else
2462 datm = gmtime_mysql(&t, tm_buffer);
2463
2464 return datm;
2465 } // end of GetGmTime
2466
2467// Added by Alexander Barkov
2468static time_t mktime_mysql(struct tm *ptm)
2469{
2470 MYSQL_TIME ltime;
2471 localtime_to_TIME(&ltime, ptm);
2472 ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
2473 uint error_code;
2474 time_t t= TIME_to_timestamp(current_thd, &ltime, &error_code);
2475 return error_code ? (time_t) -1 : t;
2476}
2477
2478/***********************************************************************/
2479/* MakeTime: calculates a date value from a tm structures using the */
2480/* mktime C function. The purpose of this function is to extend the */
2481/* range of valid dates by accepting to set negative time values. */
2482/***********************************************************************/
2483bool DTVAL::MakeTime(struct tm *ptm)
2484 {
2485 int n, y = ptm->tm_year;
2486 time_t t = mktime_mysql(ptm);
2487
2488 if (trace(2))
2489 htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
2490 ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
2491 ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
2492
2493 if (t == -1) {
2494 if (y < 1 || y > 71)
2495 return true;
2496
2497 for (n = 0; t == -1 && n < 20; n++) {
2498 ptm->tm_year += 4;
2499 t = mktime_mysql(ptm);
2500 } // endfor t
2501
2502 if (t == -1)
2503 return true;
2504
2505 if ((t -= (n * FOURYEARS)) > 2000000000)
2506 return true;
2507
2508 }
2509 Tval= (int) t;
2510
2511 if (trace(2))
2512 htrc("MakeTime Ival=%d\n", Tval);
2513
2514 return false;
2515 } // end of MakeTime
2516
2517/***********************************************************************/
2518/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
2519/***********************************************************************/
2520bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
2521 {
2522 int i, m;
2523 int n;
2524 bool rc = false;
2525 struct tm datm;
2526 bzero(&datm, sizeof(datm));
2527 datm.tm_mday=1;
2528 datm.tm_mon=0;
2529 datm.tm_year=70;
2530
2531 if (trace(2))
2532 htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
2533 val[0], val[1], val[2], val[3], val[4], val[5], nval);
2534
2535 for (i = 0; i < nval; i++) {
2536 n = val[i];
2537
2538// if (trace(2))
2539// htrc("i=%d n=%d\n", i, n);
2540
2541 switch (i) {
2542 case 0:
2543 if (n >= 1900)
2544 n -= 1900;
2545
2546 datm.tm_year = n;
2547
2548// if (trace(2))
2549// htrc("n=%d tm_year=%d\n", n, datm.tm_year);
2550
2551 break;
2552 case 1:
2553 // If mktime handles apparently correctly large or negative
2554 // day values, it is not the same for months. Therefore we
2555 // do the ajustment here, thus mktime has not to do it.
2556 if (n > 0) {
2557 m = (n - 1) % 12;
2558 n = (n - 1) / 12;
2559 } else {
2560 m = 11 + n % 12;
2561 n = n / 12 - 1;
2562 } // endfi n
2563
2564 datm.tm_mon = m;
2565 datm.tm_year += n;
2566
2567// if (trace(2))
2568// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2569
2570 break;
2571 case 2:
2572 // For days, big or negative values may also cause problems
2573 m = n % 1461;
2574 n = 4 * (n / 1461);
2575
2576 if (m < 0) {
2577 m += 1461;
2578 n -= 4;
2579 } // endif m
2580
2581 datm.tm_mday = m;
2582 datm.tm_year += n;
2583
2584// if (trace(2))
2585// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
2586
2587 break;
2588 case 3: datm.tm_hour = n; break;
2589 case 4: datm.tm_min = n; break;
2590 case 5: datm.tm_sec = n; break;
2591 } // endswitch i
2592
2593 } // endfor i
2594
2595 if (trace(2))
2596 htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
2597 datm.tm_year, datm.tm_mon, datm.tm_mday,
2598 datm.tm_hour, datm.tm_min, datm.tm_sec);
2599
2600 // Pass g to have an error return or NULL to set invalid dates to 0
2601 if (MakeTime(&datm))
2602 if (g) {
2603 strcpy(g->Message, MSG(BAD_DATETIME));
2604 rc = true;
2605 } else
2606 Tval = 0;
2607
2608 return rc;
2609 } // end of MakeDate
2610
2611/***********************************************************************/
2612/* DTVAL SetValue: copy the value of another Value object. */
2613/* This function allows conversion if chktype is false. */
2614/***********************************************************************/
2615bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
2616 {
2617 if (valp != this) {
2618 if (chktype && Type != valp->GetType())
2619 return true;
2620
2621 if (!(Null = valp->IsNull() && Nullable)) {
2622 if (Pdtp && !valp->IsTypeNum()) {
2623 int ndv;
2624 int dval[6];
2625
2626 ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
2627 MakeDate(NULL, dval, ndv);
2628 } else if (valp->GetType() == TYPE_BIGINT &&
2629 !(valp->GetBigintValue() % 1000)) {
2630 // Assuming that this timestamp is in milliseconds
2631 Tval = (int)(valp->GetBigintValue() / 1000);
2632 } else
2633 Tval = valp->GetIntValue();
2634
2635 } else
2636 Reset();
2637
2638 } // endif valp
2639
2640 return false;
2641 } // end of SetValue
2642
2643/***********************************************************************/
2644/* SetValue: convert chars extracted from a line to date value. */
2645/***********************************************************************/
2646bool DTVAL::SetValue_char(const char *p, int n)
2647 {
2648 bool rc= 0;
2649
2650 if (Pdtp) {
2651 const char *p2;
2652 int ndv;
2653 int dval[6];
2654
2655 if (n > 0) {
2656 // Trim trailing blanks
2657 for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--);
2658
2659 if ((rc = (n = (int)(p2 - p + 1)) > Len))
2660 n = Len;
2661
2662 memcpy(Sdate, p, n);
2663 } // endif n
2664
2665 Sdate[n] = '\0';
2666
2667 ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2668 MakeDate(NULL, dval, ndv);
2669
2670 if (trace(2))
2671 htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2672
2673 Null = (Nullable && ndv == 0);
2674 } else {
2675 rc = TYPVAL<int>::SetValue_char(p, n);
2676 Null = (Nullable && Tval == 0);
2677 } // endif Pdtp
2678
2679 return rc;
2680 } // end of SetValue
2681
2682/***********************************************************************/
2683/* SetValue: convert a char string to date value. */
2684/***********************************************************************/
2685void DTVAL::SetValue_psz(PCSZ p)
2686 {
2687 if (Pdtp) {
2688 int ndv;
2689 int dval[6];
2690
2691 strncpy(Sdate, p, Len);
2692 Sdate[Len] = '\0';
2693
2694 ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
2695 MakeDate(NULL, dval, ndv);
2696
2697 if (trace(2))
2698 htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
2699
2700 Null = (Nullable && ndv == 0);
2701 } else {
2702 TYPVAL<int>::SetValue_psz(p);
2703 Null = (Nullable && Tval == 0);
2704 } // endif Pdtp
2705
2706 } // end of SetValue
2707
2708/***********************************************************************/
2709/* DTVAL SetValue: set value with a value extracted from a block. */
2710/***********************************************************************/
2711void DTVAL::SetValue_pvblk(PVBLK blk, int n)
2712 {
2713 if (Pdtp && !::IsTypeNum(blk->GetType())) {
2714 int ndv;
2715 int dval[6];
2716
2717 ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
2718 MakeDate(NULL, dval, ndv);
2719 } else
2720 Tval = blk->GetIntValue(n);
2721
2722 } // end of SetValue
2723
2724/***********************************************************************/
2725/* DTVAL GetCharString: get string representation of a date value. */
2726/***********************************************************************/
2727char *DTVAL::GetCharString(char *p)
2728 {
2729 if (Pdtp) {
2730 size_t n = 0;
2731 struct tm tm, *ptm= GetGmTime(&tm);
2732
2733 if (ptm)
2734 n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm);
2735
2736 if (!n) {
2737 *Sdate = '\0';
2738 strncat(Sdate, "Error", Len + 1);
2739 } // endif n
2740
2741 return Sdate;
2742 } else
2743 sprintf(p, "%d", Tval);
2744
2745//Null = false; ??????????????
2746 return p;
2747 } // end of GetCharString
2748
2749/***********************************************************************/
2750/* DTVAL ShowValue: get string representation of a date value. */
2751/***********************************************************************/
2752char *DTVAL::ShowValue(char *buf, int len)
2753 {
2754 if (Pdtp) {
2755 char *p;
2756
2757 if (!Null) {
2758 size_t m, n = 0;
2759 struct tm tm, *ptm = GetGmTime(&tm);
2760
2761
2762
2763 if (Len < len) {
2764 p = buf;
2765 m = len;
2766 } else {
2767 p = Sdate;
2768 m = Len + 1;
2769 } // endif Len
2770
2771 if (ptm)
2772 n = strftime(p, m, Pdtp->OutFmt, ptm);
2773
2774 if (!n) {
2775 *p = '\0';
2776 strncat(p, "Error", m);
2777 } // endif n
2778
2779 } else {
2780 p = buf;
2781 *p = '\0'; // DEFAULT VALUE ???
2782 } // endif Null
2783
2784 return p;
2785 } else
2786 return TYPVAL<int>::ShowValue(buf, len);
2787
2788 } // end of ShowValue
2789
2790#if 0 // Not used by CONNECT
2791/***********************************************************************/
2792/* Returns a member of the struct tm representation of the date. */
2793/***********************************************************************/
2794bool DTVAL::GetTmMember(OPVAL op, int& mval)
2795 {
2796 bool rc = false;
2797 struct tm tm, *ptm = GetGmTime(&tm);
2798
2799 switch (op) {
2800 case OP_MDAY: mval = ptm->tm_mday; break;
2801 case OP_MONTH: mval = ptm->tm_mon + 1; break;
2802 case OP_YEAR: mval = ptm->tm_year + 1900; break;
2803 case OP_WDAY: mval = ptm->tm_wday + 1; break;
2804 case OP_YDAY: mval = ptm->tm_yday + 1; break;
2805 case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
2806 default:
2807 rc = true;
2808 } // endswitch op
2809
2810 return rc;
2811 } // end of GetTmMember
2812
2813/***********************************************************************/
2814/* Calculates the week number of the year for the internal date value.*/
2815/* The International Standard ISO 8601 has decreed that Monday shall */
2816/* be the first day of the week. A week that lies partly in one year */
2817/* and partly in another is assigned a number in the year in which */
2818/* most of its days lie. That means that week number 1 of any year is */
2819/* the week that contains the January 4th. */
2820/***********************************************************************/
2821bool DTVAL::WeekNum(PGLOBAL g, int& nval)
2822 {
2823 // w is the start of the week SUN=0, MON=1, etc.
2824 int m, n, w = nval % 7;
2825 struct tm tm, *ptm = GetGmTime(&tm);
2826
2827 // Which day is January 4th of this year?
2828 m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
2829
2830 // When does the first week begins?
2831 n = 3 - (7 + m - w) % 7;
2832
2833 // Now calculate the week number
2834 if (!(nval = (7 + ptm->tm_yday - n) / 7))
2835 nval = 52;
2836
2837 // Everything should be Ok
2838 return false;
2839 } // end of WeekNum
2840#endif // 0
2841
2842/***********************************************************************/
2843/* FormatValue: This function set vp (a STRING value) to the string */
2844/* constructed from its own value formated using the fmt format. */
2845/* This function assumes that the format matches the value type. */
2846/***********************************************************************/
2847bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
2848 {
2849 char *buf = (char*)vp->GetTo_Val(); // Should be big enough
2850 struct tm tm, *ptm = GetGmTime(&tm);
2851
2852 if (trace(2))
2853 htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
2854
2855 if (ptm) {
2856 size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
2857
2858 if (trace(2))
2859 htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
2860
2861 return (n == 0);
2862 } else
2863 return true;
2864
2865 } // end of FormatValue
2866
2867/* -------------------------- End of Value --------------------------- */
2868