diff options
author | Olivier Bertrand <bertrandop@gmail.com> | 2014-03-22 08:57:32 +0100 |
---|---|---|
committer | Olivier Bertrand <bertrandop@gmail.com> | 2014-03-22 08:57:32 +0100 |
commit | 81ce7da7a72e483b8f9d491c2d937d8ccc8c7b6e (patch) | |
tree | 6f076508d09cd50b09869ce00b5f5810133c3402 /storage/connect/value.cpp | |
parent | 7b400a088d049661b9a4dded385ac78923bb0017 (diff) | |
parent | 31560c448a62514f244b67d0925cd3837188e4c9 (diff) | |
download | mariadb-git-81ce7da7a72e483b8f9d491c2d937d8ccc8c7b6e.tar.gz |
- Resolving conflicts
modified:
storage/connect/block.h
storage/connect/colblk.cpp
storage/connect/connect.cc
storage/connect/csort.h
storage/connect/filamap.cpp
storage/connect/filamdbf.cpp
storage/connect/filamfix.cpp
storage/connect/filamtxt.cpp
storage/connect/filamzip.cpp
storage/connect/ha_connect.cc
storage/connect/mycat.cc
storage/connect/myconn.cpp
storage/connect/myutil.cpp
storage/connect/osutil.c
storage/connect/plgdbsem.h
storage/connect/plgdbutl.cpp
storage/connect/plugutil.c
storage/connect/reldef.cpp
storage/connect/tabcol.cpp
storage/connect/tabfmt.cpp
storage/connect/tabmysql.cpp
storage/connect/tabodbc.cpp
storage/connect/tabpivot.cpp
storage/connect/tabvct.cpp
storage/connect/user_connect.cc
storage/connect/valblk.cpp
storage/connect/value.cpp
storage/connect/xindex.cpp
Diffstat (limited to 'storage/connect/value.cpp')
-rw-r--r-- | storage/connect/value.cpp | 4410 |
1 files changed, 2205 insertions, 2205 deletions
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 5f89c1ac23c..654cf1d6907 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1,2205 +1,2205 @@ -/************* Value C++ Functions Source Code File (.CPP) *************/
-/* Name: VALUE.CPP Version 2.4 */
-/* */
-/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */
-/* */
-/* This file contains the VALUE and derived classes family functions. */
-/* These classes contain values of different types. They are used so */
-/* new object types can be defined and added to the processing simply */
-/* (hopefully) adding their specific functions in this file. */
-/* First family is VALUE that represent single typed objects. It is */
-/* used by columns (COLBLK), SELECT and FILTER (derived) objects. */
-/* Second family is VALBLK, representing simple suballocated arrays */
-/* of values treated sequentially by FIX, BIN and VCT tables and */
-/* columns, as well for min/max blocks as for VCT column blocks. */
-/* Q&A: why not using only one family ? Simple values are arrays that */
-/* have only one element and arrays could have functions for all kind */
-/* of processing. The answer is a-because historically it was simpler */
-/* to do that way, b-because of performance on single values, and c- */
-/* to avoid too complicated classes and unuseful duplication of many */
-/* functions used on one family only. The drawback is that for new */
-/* types of objects, we shall have more classes to update. */
-/* Currently the only implemented types are STRING, INT, SHORT, TINY, */
-/* DATE and LONGLONG. Recently we added some UNSIGNED types. */
-/***********************************************************************/
-
-/***********************************************************************/
-/* Include relevant MariaDB header file. */
-/***********************************************************************/
-#include "my_global.h"
-#include "sql_class.h"
-#include "sql_time.h"
-
-#if defined(WIN32)
-//#include <windows.h>
-#else // !WIN32
-#include <string.h>
-#endif // !WIN32
-
-#include <math.h>
-
-#undef DOMAIN // Was defined in math.h
-
-/***********************************************************************/
-/* Include required application header files */
-/* global.h is header containing all global Plug declarations. */
-/* plgdbsem.h is header containing the DB applic. declarations. */
-/***********************************************************************/
-#include "global.h"
-#include "plgdbsem.h"
-#include "preparse.h" // For DATPAR
-//#include "value.h"
-#include "valblk.h"
-#define NO_FUNC // Already defined in ODBConn
-#include "plgcnx.h" // For DB types
-#include "osutil.h"
-
-/***********************************************************************/
-/* Check macro's. */
-/***********************************************************************/
-#if defined(_DEBUG)
-#define CheckType(V) if (Type != V->GetType()) { \
- PGLOBAL& g = Global; \
- strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \
- longjmp(g->jumper[g->jump_level], Type); }
-#else
-#define CheckType(V)
-#endif
-
-#define FOURYEARS 126230400 // Four years in seconds (1 leap)
-
-/***********************************************************************/
-/* Static variables. */
-/***********************************************************************/
-
-extern "C" int trace;
-
-/***********************************************************************/
-/* Initialize the DTVAL static member. */
-/***********************************************************************/
-int DTVAL::Shift = 0;
-
-/***********************************************************************/
-/* Routines called externally. */
-/***********************************************************************/
-bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool);
-
-#if !defined(WIN32)
-extern "C" {
-PSZ strupr(PSZ s);
-PSZ strlwr(PSZ s);
-}
-#endif // !WIN32
-
-/***********************************************************************/
-/* Returns the bitmap representing the conditions that must not be */
-/* met when returning from TestValue for a given operator. */
-/* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */
-/***********************************************************************/
-BYTE OpBmp(PGLOBAL g, OPVAL opc)
- {
- BYTE bt;
-
- switch (opc) {
- case OP_IN:
- case OP_EQ: bt = 0x06; break;
- case OP_NE: bt = 0x01; break;
- case OP_GT: bt = 0x03; break;
- case OP_GE: bt = 0x02; break;
- case OP_LT: bt = 0x05; break;
- case OP_LE: bt = 0x04; break;
- case OP_EXIST: bt = 0x00; break;
- default:
- sprintf(g->Message, MSG(BAD_FILTER_OP), opc);
- longjmp(g->jumper[g->jump_level], TYPE_ARRAY);
- } // endswitch opc
-
- return bt;
- } // end of OpBmp
-
-/***********************************************************************/
-/* Get a long long number from its character representation. */
-/* IN p: Pointer to the numeric string */
-/* IN n: The string length */
-/* IN maxval: The number max value */
-/* IN un: True if the number must be unsigned */
-/* OUT rc: Set to TRUE for out of range value */
-/* OUT minus: Set to true if the number is negative */
-/* Returned val: The resulting number */
-/***********************************************************************/
-ulonglong CharToNumber(char *p, int n, ulonglong maxval,
- bool un, bool *minus, bool *rc)
-{
- char *p2;
- uchar c;
- ulonglong val;
-
- if (minus) *minus = false;
- if (rc) *rc = false;
-
- // Eliminate leading blanks or 0
- for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ;
-
- // Get an eventual sign character
- switch (*p) {
- case '-':
- if (un) {
- if (rc) *rc = true;
- return 0;
- } else {
- maxval++;
- if (minus) *minus = true;
- } // endif Unsigned
-
- case '+':
- p++;
- break;
- } // endswitch *p
-
- for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++)
- if (val > (maxval - c) / 10) {
- val = maxval;
- if (rc) *rc = true;
- break;
- } else
- val = val * 10 + c;
-
- return val;
-} // end of CharToNumber
-
-/***********************************************************************/
-/* GetTypeName: returns the PlugDB internal type name. */
-/***********************************************************************/
-PSZ GetTypeName(int type)
- {
- PSZ name;
-
- switch (type) {
- case TYPE_STRING: name = "CHAR"; break;
- case TYPE_SHORT: name = "SMALLINT"; break;
- case TYPE_INT: name = "INTEGER"; break;
- case TYPE_BIGINT: name = "BIGINT"; break;
- case TYPE_DATE: name = "DATE"; break;
- case TYPE_DOUBLE: name = "DOUBLE"; break;
- case TYPE_TINY: name = "TINY"; break;
- case TYPE_DECIM: name = "DECIMAL"; break;
- default: name = "UNKNOWN"; break;
- } // endswitch type
-
- return name;
- } // end of GetTypeName
-
-/***********************************************************************/
-/* GetTypeSize: returns the PlugDB internal type size. */
-/***********************************************************************/
-int GetTypeSize(int type, int len)
- {
- switch (type) {
- case TYPE_DECIM:
- case TYPE_STRING: len = len * sizeof(char); break;
- case TYPE_SHORT: len = sizeof(short); break;
- case TYPE_INT: len = sizeof(int); break;
- case TYPE_BIGINT: len = sizeof(longlong); break;
- case TYPE_DATE: len = sizeof(int); break;
- case TYPE_DOUBLE: len = sizeof(double); break;
- case TYPE_TINY: len = sizeof(char); break;
- default: len = 0;
- } // endswitch type
-
- return len;
- } // end of GetTypeSize
-
-/***********************************************************************/
-/* GetFormatType: returns the FORMAT character(s) according to type. */
-/***********************************************************************/
-char *GetFormatType(int type)
- {
- char *c = "X";
-
- switch (type) {
- case TYPE_STRING: c = "C"; break;
- case TYPE_SHORT: c = "S"; break;
- case TYPE_INT: c = "N"; break;
- case TYPE_BIGINT: c = "L"; break;
- case TYPE_DOUBLE: c = "F"; break;
- case TYPE_DATE: c = "D"; break;
- case TYPE_TINY: c = "T"; break;
- case TYPE_DECIM: c = "M"; break;
- } // endswitch type
-
- return c;
- } // end of GetFormatType
-
-/***********************************************************************/
-/* GetFormatType: returns the FORMAT type according to character. */
-/***********************************************************************/
-int GetFormatType(char c)
- {
- int type = TYPE_ERROR;
-
- switch (c) {
- case 'C': type = TYPE_STRING; break;
- case 'S': type = TYPE_SHORT; break;
- case 'N': type = TYPE_INT; break;
- case 'L': type = TYPE_BIGINT; break;
- case 'F': type = TYPE_DOUBLE; break;
- case 'D': type = TYPE_DATE; break;
- case 'T': type = TYPE_TINY; break;
- case 'M': type = TYPE_DECIM; break;
- } // endswitch type
-
- return type;
- } // end of GetFormatType
-
-/***********************************************************************/
-/* IsTypeChar: returns true for character type(s). */
-/***********************************************************************/
-bool IsTypeChar(int type)
- {
- switch (type) {
- case TYPE_STRING:
- case TYPE_DECIM:
- return true;
- } // endswitch type
-
- return false;
- } // end of IsTypeChar
-
-/***********************************************************************/
-/* IsTypeNum: returns true for numeric types. */
-/***********************************************************************/
-bool IsTypeNum(int type)
- {
- switch (type) {
- case TYPE_INT:
- case TYPE_BIGINT:
- case TYPE_DATE:
- case TYPE_DOUBLE:
- case TYPE_SHORT:
- case TYPE_NUM:
- case TYPE_TINY:
- case TYPE_DECIM:
- return true;
- } // endswitch type
-
- return false;
- } // end of IsTypeNum
-
-/***********************************************************************/
-/* GetFmt: returns the format to use with a typed value. */
-/***********************************************************************/
-const char *GetFmt(int type, bool un)
- {
- const char *fmt;
-
- switch (type) {
- case TYPE_DECIM:
- case TYPE_STRING: fmt = "%s"; break;
- case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break;
- case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
- case TYPE_DOUBLE: fmt = "%.*lf"; break;
- default: fmt = (un) ? "%u" : "%d"; break;
- } // endswitch Type
-
- return fmt;
- } // end of GetFmt
-
-/***********************************************************************/
-/* ConvertType: what this function does is to determine the type to */
-/* which should be converted a value so no precision would be lost. */
-/* This can be a numeric type if num is true or non numeric if false. */
-/* Note: this is an ultra simplified version of this function that */
-/* should become more and more complex as new types are added. */
-/* Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from */
-/* IsType... functions so match does not prevent correct setting. */
-/***********************************************************************/
-int ConvertType(int target, int type, CONV kind, bool match)
- {
- switch (kind) {
- case CNV_CHAR:
- if (match && (!IsTypeChar(target) || !IsTypeChar(type)))
- return TYPE_ERROR;
-
- return TYPE_STRING;
- case CNV_NUM:
- if (match && (!IsTypeNum(target) || !IsTypeNum(type)))
- return TYPE_ERROR;
-
- return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
- : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
- : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
- : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
- : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
- : TYPE_TINY;
- default:
- if (target == TYPE_ERROR || target == type)
- return type;
-
- if (match && ((IsTypeChar(target) && !IsTypeChar(type)) ||
- (IsTypeNum(target) && !IsTypeNum(type))))
- return TYPE_ERROR;
-
- return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE
- : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE
- : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT
- : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT
- : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT
- : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING
- : (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY
- : TYPE_ERROR;
- } // endswitch kind
-
- } // end of ConvertType
-
-/***********************************************************************/
-/* AllocateConstant: allocates a constant Value. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, void *value, short type)
- {
- PVAL valp;
-
- if (trace)
- htrc("AllocateConstant: value=%p type=%hd\n", value, type);
-
- switch (type) {
- case TYPE_STRING:
- valp = new(g) TYPVAL<PSZ>((PSZ)value);
- break;
- case TYPE_SHORT:
- valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT);
- break;
- case TYPE_INT:
- valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT);
- break;
- case TYPE_BIGINT:
- valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT);
- break;
- case TYPE_DOUBLE:
- valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2);
- break;
- case TYPE_TINY:
- valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY);
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
- return NULL;
- } // endswitch Type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-/***********************************************************************/
-/* Allocate a variable Value according to type, length and precision. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, int type, int len, int prec,
- bool uns, PSZ fmt)
- {
- PVAL valp;
-
- switch (type) {
- case TYPE_STRING:
- valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec);
- break;
- case TYPE_DATE:
- valp = new(g) DTVAL(g, len, prec, fmt);
- break;
- case TYPE_INT:
- if (uns)
- valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true);
- else
- valp = new(g) TYPVAL<int>((int)0, TYPE_INT);
-
- break;
- case TYPE_BIGINT:
- if (uns)
- valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true);
- else
- valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT);
-
- break;
- case TYPE_SHORT:
- if (uns)
- valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true);
- else
- valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT);
-
- break;
- case TYPE_DOUBLE:
- valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec);
- break;
- case TYPE_TINY:
- if (uns)
- valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true);
- else
- valp = new(g) TYPVAL<char>((char)0, TYPE_TINY);
-
- break;
- case TYPE_DECIM:
- valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns);
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), type);
- return NULL;
- } // endswitch type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-/***********************************************************************/
-/* Allocate a constant Value converted to newtype. */
-/* Can also be used to copy a Value eventually converted. */
-/***********************************************************************/
-PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns)
- {
- PSZ p, sp;
- bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned();
-
- if (newtype == TYPE_VOID) // Means allocate a value of the same type
- newtype = valp->GetType();
-
- switch (newtype) {
- case TYPE_STRING:
- p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen());
-
- if ((sp = valp->GetCharString(p)) != p)
- strcpy (p, sp);
-
- valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec());
- break;
- case TYPE_SHORT:
- if (un)
- valp = new(g) TYPVAL<ushort>(valp->GetUShortValue(),
- TYPE_SHORT, 0, true);
- else
- valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT);
-
- break;
- case TYPE_INT:
- if (un)
- valp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true);
- else
- valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT);
-
- break;
- case TYPE_BIGINT:
- if (un)
- valp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(),
- TYPE_BIGINT, 0, true);
- else
- valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT);
-
- break;
- case TYPE_DATE:
- valp = new(g) DTVAL(g, valp->GetIntValue());
- break;
- case TYPE_DOUBLE:
- valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE,
- valp->GetValPrec());
- break;
- case TYPE_TINY:
- if (un)
- valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(),
- TYPE_TINY, 0, true);
- else
- valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY);
-
- break;
- default:
- sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype);
- return NULL;
- } // endswitch type
-
- valp->SetGlobal(g);
- return valp;
- } // end of AllocateValue
-
-/* -------------------------- Class VALUE ---------------------------- */
-
-/***********************************************************************/
-/* Class VALUE protected constructor. */
-/***********************************************************************/
-VALUE::VALUE(int type, bool un) : Type(type)
- {
- Null = false;
- Nullable = false;
- Unsigned = un;
- Clen = 0;
- Prec = 0;
- Fmt = GetFmt(Type, Unsigned);
- Xfmt = GetXfmt();
- } // end of VALUE constructor
-
-/***********************************************************************/
-/* VALUE GetXfmt: returns the extended format to use with typed value. */
-/***********************************************************************/
-const char *VALUE::GetXfmt(void)
- {
- const char *fmt;
-
- switch (Type) {
- case TYPE_DECIM:
- case TYPE_STRING: fmt = "%*s"; break;
- case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break;
- case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
- case TYPE_DOUBLE: fmt = "%*.*lf"; break;
- default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
- } // endswitch Type
-
- return fmt;
- } // end of GetFmt
-
-/***********************************************************************/
-/* Returns a BYTE indicating the comparison between two values. */
-/* Bit 1 indicates equality, Bit 2 less than, and Bit3 greater than. */
-/* More than 1 bit can be set only in the case of TYPE_LIST. */
-/***********************************************************************/
-BYTE VALUE::TestValue(PVAL vp)
- {
- int n = CompareValue(vp);
-
- return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01;
- } // end of TestValue
-
-/* -------------------------- Class TYPVAL ---------------------------- */
-
-/***********************************************************************/
-/* TYPVAL public constructor from a constant typed value. */
-/***********************************************************************/
-template <class TYPE>
-TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un)
- : VALUE(type, un)
- {
- Tval = n;
- Clen = sizeof(TYPE);
- Prec = prec;
- } // end of TYPVAL constructor
-
-/***********************************************************************/
-/* Return unsigned max value for the type. */
-/***********************************************************************/
-template <class TYPE>
-ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;}
-
-template <>
-ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;}
-
-template <>
-ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;}
-
-template <>
-ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;}
-
-template <>
-ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;}
-
-template <>
-ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;}
-
-template <>
-ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;}
-
-template <>
-ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;}
-
-template <>
-ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;}
-
-/***********************************************************************/
-/* TYPVAL GetValLen: returns the print length of the typed object. */
-/***********************************************************************/
-template <class TYPE>
-int TYPVAL<TYPE>::GetValLen(void)
- {
- char c[32];
-
- return sprintf(c, Fmt, Tval);
- } // end of GetValLen
-
-template <>
-int TYPVAL<double>::GetValLen(void)
- {
- char c[32];
-
- return sprintf(c, Fmt, Prec, Tval);
- } // end of GetValLen
-
-/***********************************************************************/
-/* TYPVAL SetValue: copy the value of another Value object. */
-/* This function allows conversion if chktype is false. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && Type != valp->GetType())
- return true;
-
- if (!(Null = valp->IsNull() && Nullable))
- Tval = GetTypedValue(valp);
- else
- Reset();
-
- return false;
- } // end of SetValue
-
-template <>
-short TYPVAL<short>::GetTypedValue(PVAL valp)
- {return valp->GetShortValue();}
-
-template <>
-ushort TYPVAL<ushort>::GetTypedValue(PVAL valp)
- {return valp->GetUShortValue();}
-
-template <>
-int TYPVAL<int>::GetTypedValue(PVAL valp)
- {return valp->GetIntValue();}
-
-template <>
-uint TYPVAL<uint>::GetTypedValue(PVAL valp)
- {return valp->GetUIntValue();}
-
-template <>
-longlong TYPVAL<longlong>::GetTypedValue(PVAL valp)
- {return valp->GetBigintValue();}
-
-template <>
-ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp)
- {return valp->GetUBigintValue();}
-
-template <>
-double TYPVAL<double>::GetTypedValue(PVAL valp)
- {return valp->GetFloatValue();}
-
-template <>
-char TYPVAL<char>::GetTypedValue(PVAL valp)
- {return valp->GetTinyValue();}
-
-template <>
-uchar TYPVAL<uchar>::GetTypedValue(PVAL valp)
- {return valp->GetUTinyValue();}
-
-/***********************************************************************/
-/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::SetValue_char(char *p, int n)
- {
- bool rc, minus;
- ulonglong maxval = MaxVal();
- ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc);
-
- if (minus && val < maxval)
- Tval = (TYPE)(-(signed)val);
- else
- Tval = (TYPE)val;
-
- if (trace > 1) {
- char buf[64];
- htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"),
- GetTypeName(Type), Tval);
- } // endif trace
-
- Null = false;
- return rc;
- } // end of SetValue
-
-template <>
-bool TYPVAL<double>::SetValue_char(char *p, int n)
- {
- if (p) {
- char buf[32];
-
- for (; n > 0 && *p == ' '; p++)
- n--;
-
- memcpy(buf, p, min(n, 31));
- buf[n] = '\0';
- Tval = atof(buf);
-
- if (trace > 1)
- htrc(" setting double: '%s' -> %lf\n", buf, Tval);
-
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif p
-
- return false;
- } // end of SetValue
-
-/***********************************************************************/
-/* TYPVAL SetValue: fill a typed value from a string. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetValue_psz(PSZ s)
- {
- if (s) {
- SetValue_char(s, (int)strlen(s));
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif p
-
- } // end of SetValue
-
-/***********************************************************************/
-/* TYPVAL SetValue: set value with a TYPE extracted from a block. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n)
- {
- Tval = GetTypedValue(blk, n);
- Null = false;
- } // end of SetValue
-
-template <>
-int TYPVAL<int>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetIntValue(n);}
-
-template <>
-uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetUIntValue(n);}
-
-template <>
-short TYPVAL<short>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetShortValue(n);}
-
-template <>
-ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetUShortValue(n);}
-
-template <>
-longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetBigintValue(n);}
-
-template <>
-ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetUBigintValue(n);}
-
-template <>
-double TYPVAL<double>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetFloatValue(n);}
-
-template <>
-char TYPVAL<char>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetTinyValue(n);}
-
-template <>
-uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n)
- {return blk->GetUTinyValue(n);}
-
-/***********************************************************************/
-/* TYPVAL SetBinValue: with bytes extracted from a line. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::SetBinValue(void *p)
- {
- Tval = *(TYPE *)p;
- Null = false;
- } // end of SetBinValue
-
-/***********************************************************************/
-/* GetBinValue: fill a buffer with the internal binary value. */
-/* This function checks whether the buffer length is enough and */
-/* returns true if not. Actual filling occurs only if go is true. */
-/* Currently used by WriteColumn of binary files. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go)
- {
- // Test on length was removed here until a variable in column give the
- // real field length. For BIN files the field length logically cannot
- // be different from the variable length because no conversion is done.
- // Therefore this test is useless anyway.
-//#if defined(_DEBUG)
-// if (sizeof(TYPE) > buflen)
-// return true;
-//#endif
-
- if (go)
- *(TYPE *)buf = Tval;
-
- Null = false;
- return false;
- } // end of GetBinValue
-
-/***********************************************************************/
-/* TYPVAL ShowValue: get string representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::ShowValue(char *buf, int len)
- {
- sprintf(buf, Xfmt, len, Tval);
- return buf;
- } // end of ShowValue
-
-template <>
-char *TYPVAL<double>::ShowValue(char *buf, int len)
- {
- // TODO: use snprintf to avoid possible overflow
- sprintf(buf, Xfmt, len, Prec, Tval);
- return buf;
- } // end of ShowValue
-
-/***********************************************************************/
-/* TYPVAL GetCharString: get string representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetCharString(char *p)
- {
- sprintf(p, Fmt, Tval);
- return p;
- } // end of GetCharString
-
-template <>
-char *TYPVAL<double>::GetCharString(char *p)
- {
- sprintf(p, Fmt, Prec, Tval);
- return p;
- } // end of GetCharString
-
-#if 0
-/***********************************************************************/
-/* TYPVAL GetShortString: get short representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetShortString(char *p, int n)
- {
- sprintf(p, "%*hd", n, (short)Tval);
- return p;
- } // end of GetShortString
-
-/***********************************************************************/
-/* TYPVAL GetIntString: get int representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetIntString(char *p, int n)
- {
- sprintf(p, "%*d", n, (int)Tval);
- return p;
- } // end of GetIntString
-
-/***********************************************************************/
-/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetBigintString(char *p, int n)
- {
- sprintf(p, "%*lld", n, (longlong)Tval);
- return p;
- } // end of GetBigintString
-
-/***********************************************************************/
-/* TYPVAL GetFloatString: get double representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec)
- {
- sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval);
- return p;
- } // end of GetFloatString
-
-/***********************************************************************/
-/* TYPVAL GetTinyString: get char representation of a typed value. */
-/***********************************************************************/
-template <class TYPE>
-char *TYPVAL<TYPE>::GetTinyString(char *p, int n)
- {
- sprintf(p, "%*d", n, (int)(char)Tval);
- return p;
- } // end of GetIntString
-#endif // 0
-
-/***********************************************************************/
-/* TYPVAL compare value with another Value. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype)
- {
- if (this == vp)
- return true;
- else if (chktype && Type != vp->GetType())
- return false;
- else if (chktype && Unsigned != vp->IsUnsigned())
- return false;
- else if (Null || vp->IsNull())
- return false;
- else
- return (Tval == GetTypedValue(vp));
-
- } // end of IsEqual
-
-/***********************************************************************/
-/* Compare values and returns 1, 0 or -1 according to comparison. */
-/* This function is used for evaluation of numeric filters. */
-/***********************************************************************/
-template <class TYPE>
-int TYPVAL<TYPE>::CompareValue(PVAL vp)
- {
-//assert(vp->GetType() == Type);
-
- // Process filtering on numeric values.
- TYPE n = GetTypedValue(vp);
-
-//if (trace)
-// htrc(" Comparing: val=%d,%d\n", Tval, n);
-
- return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
- } // end of CompareValue
-
-/***********************************************************************/
-/* FormatValue: This function set vp (a STRING value) to the string */
-/* constructed from its own value formated using the fmt format. */
-/* This function assumes that the format matches the value type. */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- int n = sprintf(buf, fmt, Tval);
-
- return (n > vp->GetValLen());
- } // end of FormatValue
-
-/***********************************************************************/
-/* TYPVAL SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-template <class TYPE>
-bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- char c[32];
-
- fmt.Type[0] = *GetFormatType(Type);
- fmt.Length = sprintf(c, Fmt, Tval);
- fmt.Prec = Prec;
- return false;
- } // end of SetConstFormat
-
-/***********************************************************************/
-/* Make file output of a typed object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, FILE *f, uint n)
- {
- char m[64], buf[12];
-
- memset(m, ' ', n); /* Make margin string */
- m[n] = '\0';
-
- if (Null)
- fprintf(f, "%s<null>\n", m);
- else
- fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval);
-
- } /* end of Print */
-
-/***********************************************************************/
-/* Make string output of a int object. */
-/***********************************************************************/
-template <class TYPE>
-void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z)
- {
- if (Null)
- strcpy(ps, "<null>");
- else
- sprintf(ps, Fmt, Tval);
-
- } /* end of Print */
-
-/* -------------------------- Class STRING --------------------------- */
-
-/***********************************************************************/
-/* STRING public constructor from a constant string. */
-/***********************************************************************/
-TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING)
- {
- Strp = s;
- Len = strlen(s);
- Clen = Len;
- Ci = false;
- } // end of STRING constructor
-
-/***********************************************************************/
-/* STRING public constructor from char. */
-/***********************************************************************/
-TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c)
- : VALUE(TYPE_STRING)
- {
- Len = (g) ? n : strlen(s);
-
- if (!s) {
- if (g) {
- Strp = (char *)PlugSubAlloc(g, NULL, Len + 1);
- Strp[Len] = '\0';
- } else
- assert(false);
-
- } else
- Strp = s;
-
- Clen = Len;
- Ci = (c != 0);
- } // end of STRING constructor
-
-/***********************************************************************/
-/* Get the tiny value represented by the Strp string. */
-/***********************************************************************/
-char TYPVAL<PSZ>::GetTinyValue(void)
- {
- bool m;
- ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m);
-
- return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val;
- } // end of GetTinyValue
-
-/***********************************************************************/
-/* Get the unsigned tiny value represented by the Strp string. */
-/***********************************************************************/
-uchar TYPVAL<PSZ>::GetUTinyValue(void)
- {
- return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true);
- } // end of GetUTinyValue
-
-/***********************************************************************/
-/* Get the short value represented by the Strp string. */
-/***********************************************************************/
-short TYPVAL<PSZ>::GetShortValue(void)
- {
- bool m;
- ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m);
-
- return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val;
- } // end of GetShortValue
-
-/***********************************************************************/
-/* Get the unsigned short value represented by the Strp string. */
-/***********************************************************************/
-ushort TYPVAL<PSZ>::GetUShortValue(void)
- {
- return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true);
- } // end of GetUshortValue
-
-/***********************************************************************/
-/* Get the integer value represented by the Strp string. */
-/***********************************************************************/
-int TYPVAL<PSZ>::GetIntValue(void)
- {
- bool m;
- ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m);
-
- return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val;
- } // end of GetIntValue
-
-/***********************************************************************/
-/* Get the unsigned integer value represented by the Strp string. */
-/***********************************************************************/
-uint TYPVAL<PSZ>::GetUIntValue(void)
- {
- return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true);
- } // end of GetUintValue
-
-/***********************************************************************/
-/* Get the big integer value represented by the Strp string. */
-/***********************************************************************/
-longlong TYPVAL<PSZ>::GetBigintValue(void)
- {
- bool m;
- ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m);
-
- return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val;
- } // end of GetBigintValue
-
-/***********************************************************************/
-/* Get the unsigned big integer value represented by the Strp string. */
-/***********************************************************************/
-ulonglong TYPVAL<PSZ>::GetUBigintValue(void)
- {
- return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true);
- } // end of GetUBigintValue
-
-/***********************************************************************/
-/* STRING SetValue: copy the value of another Value object. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
- return true;
-
- char buf[32];
-
- if (!(Null = valp->IsNull() && Nullable))
- strncpy(Strp, valp->GetCharString(buf), Len);
- else
- Reset();
-
- return false;
- } // end of SetValue_pval
-
-/***********************************************************************/
-/* STRING SetValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::SetValue_char(char *p, int n)
- {
- bool rc;
-
- if (p) {
- rc = n > Len;
-
- if ((n = min(n, Len))) {
- strncpy(Strp, p, n);
-
-// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
- for (p = Strp + n - 1; p >= Strp; p--)
- if (*p && *p != ' ')
- break;
-
- *(++p) = '\0';
-
- if (trace > 1)
- htrc(" Setting string to: '%s'\n", Strp);
-
- } else
- Reset();
-
- Null = false;
- } else {
- rc = false;
- Reset();
- Null = Nullable;
- } // endif p
-
- return rc;
- } // end of SetValue_char
-
-/***********************************************************************/
-/* STRING SetValue: fill string with another string. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_psz(PSZ s)
- {
- if (s) {
- strncpy(Strp, s, Len);
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif s
-
- } // end of SetValue_psz
-
-/***********************************************************************/
-/* STRING SetValue: fill string with a string extracted from a block. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
- {
- // STRBLK's can return a NULL pointer
- PSZ vp = blk->GetCharString(Strp, n);
-
- if (vp != Strp)
- SetValue_psz(vp);
-
- } // end of SetValue_pvblk
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of an integer. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(int n)
- {
- char buf[16];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%d", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of an uint. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(uint n)
- {
- char buf[16];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%u", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a short int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(short i)
- {
- SetValue((int)i);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a ushort int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(ushort i)
- {
- SetValue((uint)i);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a big integer.*/
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(longlong n)
- {
- char buf[24];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%lld", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a big integer.*/
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(ulonglong n)
- {
- char buf[24];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%llu", n);
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a double. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(double f)
- {
- char *p, buf[32];
- PGLOBAL& g = Global;
- int k = sprintf(buf, "%lf", f);
-
- for (p = buf + k - 1; p >= buf; p--)
- if (*p == '0') {
- *p = 0;
- k--;
- } else
- break;
-
- if (k > Len) {
- sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len);
- longjmp(g->jumper[g->jump_level], 138);
- } else
- SetValue_psz(buf);
-
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a tiny int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(char c)
- {
- SetValue((int)c);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetValue: get the character representation of a tiny int. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetValue(uchar c)
- {
- SetValue((uint)c);
- Null = false;
- } // end of SetValue
-
-/***********************************************************************/
-/* STRING SetBinValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-void TYPVAL<PSZ>::SetBinValue(void *p)
- {
- SetValue_char((char *)p, Len);
- } // end of SetBinValue
-
-/***********************************************************************/
-/* GetBinValue: fill a buffer with the internal binary value. */
-/* This function checks whether the buffer length is enough and */
-/* returns true if not. Actual filling occurs only if go is true. */
-/* Currently used by WriteColumn of binary files. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go)
- {
- int len = (Null) ? 0 : strlen(Strp);
-
- if (len > buflen)
- return true;
- else if (go) {
- memset(buf, ' ', buflen);
- memcpy(buf, Strp, len);
- } // endif go
-
- return false;
- } // end of GetBinValue
-
-/***********************************************************************/
-/* STRING ShowValue: get string representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::ShowValue(char *buf, int len)
- {
- return Strp;
- } // end of ShowValue
-
-/***********************************************************************/
-/* STRING GetCharString: get string representation of a char value. */
-/***********************************************************************/
-char *TYPVAL<PSZ>::GetCharString(char *p)
- {
- return Strp;
- } // end of GetCharString
-
-/***********************************************************************/
-/* STRING compare value with another Value. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
- {
- if (this == vp)
- return true;
- else if (chktype && Type != vp->GetType())
- return false;
- else if (Null || vp->IsNull())
- return false;
-
- char buf[32];
-
- if (Ci || vp->IsCi())
- return !stricmp(Strp, vp->GetCharString(buf));
- else // (!Ci)
- return !strcmp(Strp, vp->GetCharString(buf));
-
- } // end of IsEqual
-
-/***********************************************************************/
-/* Compare values and returns 1, 0 or -1 according to comparison. */
-/* This function is used for evaluation of numeric filters. */
-/***********************************************************************/
-int TYPVAL<PSZ>::CompareValue(PVAL vp)
- {
- int n;
-//assert(vp->GetType() == Type);
-
- if (trace)
- htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue());
-
- // Process filtering on character strings.
- if (Ci || vp->IsCi())
- n = stricmp(Strp, vp->GetCharValue());
- else
- n = strcmp(Strp, vp->GetCharValue());
-
-#if defined(WIN32)
- if (n == _NLSCMPERROR)
- return n; // Here we should raise an error
-#endif // WIN32
-
- return (n > 0) ? 1 : (n < 0) ? -1 : 0;
- } // end of CompareValue
-
-/***********************************************************************/
-/* FormatValue: This function set vp (a STRING value) to the string */
-/* constructed from its own value formated using the fmt format. */
-/* This function assumes that the format matches the value type. */
-/***********************************************************************/
-bool TYPVAL<PSZ>::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- int n = sprintf(buf, fmt, Strp);
-
- return (n > vp->GetValLen());
- } // end of FormatValue
-
-/***********************************************************************/
-/* STRING SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- fmt.Type[0] = 'C';
- fmt.Length = Len;
- fmt.Prec = 0;
- return false;
- } // end of SetConstFormat
-
-/* -------------------------- Class DECIMAL -------------------------- */
-
-/***********************************************************************/
-/* DECIMAL public constructor from a constant string. */
-/***********************************************************************/
-DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
- {
- if (s) {
- char *p = strchr(Strp, '.');
-
- Prec = (p) ? Len - (p - Strp) : 0;
- } // endif s
-
- Type = TYPE_DECIM;
- } // end of DECVAL constructor
-
-/***********************************************************************/
-/* DECIMAL public constructor from char. */
-/***********************************************************************/
-DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns)
- : TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0)
- {
- Prec = prec;
- Unsigned = uns;
- Type = TYPE_DECIM;
- } // end of DECVAL constructor
-
-/***********************************************************************/
-/* DECIMAL: Check whether the numerica value is equal to 0. */
-/***********************************************************************/
-bool DECVAL::IsZero(void)
- {
- for (int i = 0; Strp[i]; i++)
- if (!strchr("0 +-.", Strp[i]))
- return false;
-
- return true;
- } // end of IsZero
-
-/***********************************************************************/
-/* DECIMAL: Reset value to zero. */
-/***********************************************************************/
-void DECVAL::Reset(void)
-{
- int i = 0;
-
- Strp[i++] = '0';
-
- if (Prec) {
- Strp[i++] = '.';
-
- do {
- Strp[i++] = '0';
- } while (i < Prec + 2);
-
- } // endif Prec
-
- Strp[i] = 0;
-} // end of Reset
-
-/***********************************************************************/
-/* DECIMAL ShowValue: get string representation right justified. */
-/***********************************************************************/
-char *DECVAL::ShowValue(char *buf, int len)
- {
- sprintf(buf, Xfmt, len, Strp);
- return buf;
- } // end of ShowValue
-
-/***********************************************************************/
-/* GetBinValue: fill a buffer with the internal binary value. */
-/* This function checks whether the buffer length is enough and */
-/* returns true if not. Actual filling occurs only if go is true. */
-/* Currently used by WriteColumn of binary files. */
-/***********************************************************************/
-bool DECVAL::GetBinValue(void *buf, int buflen, bool go)
- {
- int len = (Null) ? 0 : strlen(Strp);
-
- if (len > buflen)
- return true;
- else if (go) {
- memset(buf, ' ', buflen - len);
- memcpy((char*)buf + buflen - len, Strp, len);
- } // endif go
-
- return false;
- } // end of GetBinValue
-
-#if 0
-/***********************************************************************/
-/* DECIMAL SetValue: copy the value of another Value object. */
-/***********************************************************************/
-bool DECVAL::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && (valp->GetType() != Type || valp->GetSize() > Len))
- return true;
-
- char buf[32];
-
- if (!(Null = valp->IsNull() && Nullable))
- strncpy(Strp, valp->GetCharString(buf), Len);
- else
- Reset();
-
- return false;
- } // end of SetValue_pval
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-bool DECVAL::SetValue_char(char *p, int n)
- {
- bool rc;
-
- if (p) {
- rc = n > Len;
-
- if ((n = min(n, Len))) {
- strncpy(Strp, p, n);
-
-// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ;
- for (p = Strp + n - 1; p >= Strp; p--)
- if (*p && *p != ' ')
- break;
-
- *(++p) = '\0';
-
- if (trace > 1)
- htrc(" Setting string to: '%s'\n", Strp);
-
- } else
- Reset();
-
- Null = false;
- } else {
- rc = false;
- Reset();
- Null = Nullable;
- } // endif p
-
- return rc;
- } // end of SetValue_char
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with another string. */
-/***********************************************************************/
-void DECVAL::SetValue_psz(PSZ s)
- {
- if (s) {
- strncpy(Strp, s, Len);
- Null = false;
- } else {
- Reset();
- Null = Nullable;
- } // endif s
-
- } // end of SetValue_psz
-
-/***********************************************************************/
-/* DECIMAL SetValue: fill string with a string extracted from a block.*/
-/***********************************************************************/
-void DECVAL::SetValue_pvblk(PVBLK blk, int n)
- {
- // STRBLK's can return a NULL pointer
- SetValue_psz(blk->GetCharValue(n));
- } // end of SetValue_pvblk
-
-/***********************************************************************/
-/* DECIMAL SetBinValue: fill string with chars extracted from a line. */
-/***********************************************************************/
-void DECVAL::SetBinValue(void *p)
- {
- SetValue_char((char *)p, Len);
- } // end of SetBinValue
-
-/***********************************************************************/
-/* DECIMAL GetCharString: get string representation of a char value. */
-/***********************************************************************/
-char *DECVAL::GetCharString(char *p)
- {
- return Strp;
- } // end of GetCharString
-#endif // 0
-
-/***********************************************************************/
-/* DECIMAL compare value with another Value. */
-/***********************************************************************/
-bool DECVAL::IsEqual(PVAL vp, bool chktype)
- {
- if (this == vp)
- return true;
- else if (chktype && Type != vp->GetType())
- return false;
- else if (Null || vp->IsNull())
- return false;
-
- char buf[32];
-
- return !strcmp(Strp, vp->GetCharString(buf));
- } // end of IsEqual
-
-/***********************************************************************/
-/* Compare values and returns 1, 0 or -1 according to comparison. */
-/* This function is used for evaluation of numeric filters. */
-/***********************************************************************/
-int DECVAL::CompareValue(PVAL vp)
- {
-//assert(vp->GetType() == Type);
-
- // Process filtering on numeric values.
- double f = atof(Strp), n = vp->GetFloatValue();
-
-//if (trace)
-// htrc(" Comparing: val=%d,%d\n", f, n);
-
- return (f > n) ? 1 : (f < n) ? (-1) : 0;
- } // end of CompareValue
-
-#if 0
-/***********************************************************************/
-/* FormatValue: This function set vp (a STRING value) to the string */
-/* constructed from its own value formated using the fmt format. */
-/* This function assumes that the format matches the value type. */
-/***********************************************************************/
-bool DECVAL::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- int n = sprintf(buf, fmt, Strp);
-
- return (n > vp->GetValLen());
- } // end of FormatValue
-
-/***********************************************************************/
-/* DECIMAL SetFormat function (used to set SELECT output format). */
-/***********************************************************************/
-bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt)
- {
- fmt.Type[0] = 'C';
- fmt.Length = Len;
- fmt.Prec = 0;
- return false;
- } // end of SetConstFormat
-#endif // 0
-
-/* -------------------------- Class DTVAL ---------------------------- */
-
-/***********************************************************************/
-/* DTVAL public constructor for new void values. */
-/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt)
- : TYPVAL<int>((int)0, TYPE_DATE)
- {
- if (!fmt) {
- Pdtp = NULL;
- Sdate = NULL;
- DefYear = 0;
- Len = n;
- } else
- SetFormat(g, fmt, n, prec);
-
-//Type = TYPE_DATE;
- } // end of DTVAL constructor
-
-/***********************************************************************/
-/* DTVAL public constructor from int. */
-/***********************************************************************/
-DTVAL::DTVAL(PGLOBAL g, int n) : TYPVAL<int>(n, TYPE_DATE)
- {
- Pdtp = NULL;
- Len = 19;
-//Type = TYPE_DATE;
- Sdate = NULL;
- DefYear = 0;
- } // end of DTVAL constructor
-
-/***********************************************************************/
-/* Set format so formatted dates can be converted on input/output. */
-/***********************************************************************/
-bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
- {
- Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0);
- Sdate = (char*)PlugSubAlloc(g, NULL, len + 1);
- DefYear = (int)((year > 9999) ? (year - 10000) : year);
- Len = len;
- return false;
- } // end of SetFormat
-
-/***********************************************************************/
-/* Set format from the format of another date value. */
-/***********************************************************************/
-bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
- {
- DTVAL *vp;
-
- if (valp->GetType() != TYPE_DATE) {
- sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType());
- return true;
- } else
- vp = (DTVAL*)valp;
-
- Len = vp->Len;
- Pdtp = vp->Pdtp;
- Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
- DefYear = vp->DefYear;
- return false;
- } // end of SetFormat
-
-/***********************************************************************/
-/* We need TimeShift because the mktime C function does a correction */
-/* for local time zone that we want to override for DB operations. */
-/***********************************************************************/
-void DTVAL::SetTimeShift(void)
- {
- struct tm dtm;
- memset(&dtm, 0, sizeof(dtm));
- dtm.tm_mday=2;
- dtm.tm_mon=0;
- dtm.tm_year=70;
-
- Shift = (int)mktime(&dtm) - 86400;
-
- if (trace)
- htrc("DTVAL Shift=%d\n", Shift);
-
- } // end of SetTimeShift
-
-// Added by Alexander Barkov
-static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime)
-{
- bzero(tm, sizeof(*tm));
- tm->tm_year= ltime->year - 1900;
- tm->tm_mon= ltime->month - 1;
- tm->tm_mday= ltime->day;
- tm->tm_hour= ltime->hour;
- tm->tm_min= ltime->minute;
- tm->tm_sec= ltime->second;
-}
-
-// Added by Alexander Barkov
-static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm)
-{
- MYSQL_TIME ltime;
- thd_gmt_sec_to_TIME(current_thd, <ime, (my_time_t) *timep);
- TIME_to_localtime(tm, <ime);
- return tm;
-}
-
-/***********************************************************************/
-/* GetGmTime: returns a pointer to a static tm structure obtained */
-/* though the gmtime C function. The purpose of this function is to */
-/* extend the range of valid dates by accepting negative time values. */
-/***********************************************************************/
-struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
- {
- struct tm *datm;
- time_t t = (time_t)Tval;
-
- if (Tval < 0) {
- int n;
-
- for (n = 0; t < 0; n += 4)
- t += FOURYEARS;
-
- datm = gmtime_mysql(&t, tm_buffer);
-
- if (datm)
- datm->tm_year -= n;
-
- } else
- datm = gmtime_mysql(&t, tm_buffer);
-
- return datm;
- } // end of GetGmTime
-
-// Added by Alexander Barkov
-static time_t mktime_mysql(struct tm *ptm)
-{
- MYSQL_TIME ltime;
- localtime_to_TIME(<ime, ptm);
- ltime.time_type= MYSQL_TIMESTAMP_DATETIME;
- uint error_code;
- time_t t= TIME_to_timestamp(current_thd, <ime, &error_code);
- return error_code ? (time_t) -1 : t;
-}
-
-/***********************************************************************/
-/* MakeTime: calculates a date value from a tm structures using the */
-/* mktime C function. The purpose of this function is to extend the */
-/* range of valid dates by accepting to set negative time values. */
-/***********************************************************************/
-bool DTVAL::MakeTime(struct tm *ptm)
- {
- int n, y = ptm->tm_year;
- time_t t = mktime_mysql(ptm);
-
- if (trace > 1)
- htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n",
- ptm->tm_year, ptm->tm_mon, ptm->tm_mday,
- ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-
- if (t == -1) {
- if (y < 1 || y > 71)
- return true;
-
- for (n = 0; t == -1 && n < 20; n++) {
- ptm->tm_year += 4;
- t = mktime_mysql(ptm);
- } // endfor t
-
- if (t == -1)
- return true;
-
- if ((t -= (n * FOURYEARS)) > 2000000000)
- return true;
-
- }
- Tval= (int) t;
-
- if (trace > 1)
- htrc("MakeTime Ival=%d\n", Tval);
-
- return false;
- } // end of MakeTime
-
-/***********************************************************************/
-/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */
-/***********************************************************************/
-bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
- {
- int i, m;
- int n;
- bool rc = false;
- struct tm datm;
- bzero(&datm, sizeof(datm));
- datm.tm_mday=1;
- datm.tm_mon=0;
- datm.tm_year=70;
-
- if (trace > 1)
- htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n",
- val[0], val[1], val[2], val[3], val[4], val[5], nval);
-
- for (i = 0; i < nval; i++) {
- n = val[i];
-
-// if (trace > 1)
-// htrc("i=%d n=%d\n", i, n);
-
- switch (i) {
- case 0:
- if (n >= 1900)
- n -= 1900;
-
- datm.tm_year = n;
-
-// if (trace > 1)
-// htrc("n=%d tm_year=%d\n", n, datm.tm_year);
-
- break;
- case 1:
- // If mktime handles apparently correctly large or negative
- // day values, it is not the same for months. Therefore we
- // do the ajustment here, thus mktime has not to do it.
- if (n > 0) {
- m = (n - 1) % 12;
- n = (n - 1) / 12;
- } else {
- m = 11 + n % 12;
- n = n / 12 - 1;
- } // endfi n
-
- datm.tm_mon = m;
- datm.tm_year += n;
-
-// if (trace > 1)
-// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
-
- break;
- case 2:
- // For days, big or negative values may also cause problems
- m = n % 1461;
- n = 4 * (n / 1461);
-
- if (m < 0) {
- m += 1461;
- n -= 4;
- } // endif m
-
- datm.tm_mday = m;
- datm.tm_year += n;
-
-// if (trace > 1)
-// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
-
- break;
- case 3: datm.tm_hour = n; break;
- case 4: datm.tm_min = n; break;
- case 5: datm.tm_sec = n; break;
- } // endswitch i
-
- } // endfor i
-
- if (trace > 1)
- htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n",
- datm.tm_year, datm.tm_mon, datm.tm_mday,
- datm.tm_hour, datm.tm_min, datm.tm_sec);
-
- // Pass g to have an error return or NULL to set invalid dates to 0
- if (MakeTime(&datm))
- if (g) {
- strcpy(g->Message, MSG(BAD_DATETIME));
- rc = true;
- } else
- Tval = 0;
-
- return rc;
- } // end of MakeDate
-
-/***********************************************************************/
-/* DTVAL SetValue: copy the value of another Value object. */
-/* This function allows conversion if chktype is false. */
-/***********************************************************************/
-bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
- {
- if (chktype && Type != valp->GetType())
- return true;
-
- if (!(Null = valp->IsNull() && Nullable)) {
- if (Pdtp && !valp->IsTypeNum()) {
- int ndv;
- int dval[6];
-
- ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
- } else
- Tval = valp->GetIntValue();
-
- } else
- Reset();
-
- return false;
- } // end of SetValue
-
-/***********************************************************************/
-/* SetValue: convert chars extracted from a line to date value. */
-/***********************************************************************/
-bool DTVAL::SetValue_char(char *p, int n)
- {
- bool rc;
-
- if (Pdtp) {
- char *p2;
- int ndv;
- int dval[6];
-
- // Trim trailing blanks
- for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--) ;
-
- if ((rc = (n = p2 - p + 1) > Len))
- n = Len;
-
- memcpy(Sdate, p, n);
- Sdate[n] = '\0';
-
- ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
-
- if (trace > 1)
- htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
-
- Null = false;
- } else
- rc = TYPVAL<int>::SetValue_char(p, n);
-
- return rc;
- } // end of SetValue
-
-/***********************************************************************/
-/* SetValue: convert a char string to date value. */
-/***********************************************************************/
-void DTVAL::SetValue_psz(PSZ p)
- {
- if (Pdtp) {
- int ndv;
- int dval[6];
-
- strncpy(Sdate, p, Len);
- Sdate[Len] = '\0';
-
- ndv = ExtractDate(Sdate, Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
-
- if (trace > 1)
- htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
-
- Null = false;
- } else
- TYPVAL<int>::SetValue_psz(p);
-
- } // end of SetValue
-
-/***********************************************************************/
-/* DTVAL SetValue: set value with a value extracted from a block. */
-/***********************************************************************/
-void DTVAL::SetValue_pvblk(PVBLK blk, int n)
- {
- if (Pdtp && !::IsTypeNum(blk->GetType())) {
- int ndv;
- int dval[6];
-
- ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval);
- MakeDate(NULL, dval, ndv);
- } else
- Tval = blk->GetIntValue(n);
-
- } // end of SetValue
-
-/***********************************************************************/
-/* DTVAL GetCharString: get string representation of a date value. */
-/***********************************************************************/
-char *DTVAL::GetCharString(char *p)
- {
- if (Pdtp) {
- size_t n = 0;
- struct tm tm, *ptm= GetGmTime(&tm);
-
- if (ptm)
- n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm);
-
- if (!n) {
- *Sdate = '\0';
- strncat(Sdate, "Error", Len + 1);
- } // endif n
-
- return Sdate;
- } else
- sprintf(p, "%d", Tval);
-
- Null = false;
- return p;
- } // end of GetCharString
-
-/***********************************************************************/
-/* DTVAL ShowValue: get string representation of a date value. */
-/***********************************************************************/
-char *DTVAL::ShowValue(char *buf, int len)
- {
- if (Pdtp) {
- char *p;
- size_t m, n = 0;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- if (Len < len) {
- p = buf;
- m = len;
- } else {
- p = Sdate;
- m = Len + 1;
- } // endif Len
-
- if (ptm)
- n = strftime(p, m, Pdtp->OutFmt, ptm);
-
- if (!n) {
- *p = '\0';
- strncat(p, "Error", m);
- } // endif n
-
- return p;
- } else
- return TYPVAL<int>::ShowValue(buf, len);
-
- } // end of ShowValue
-
-#if 0 // Not used by CONNECT
-/***********************************************************************/
-/* Returns a member of the struct tm representation of the date. */
-/***********************************************************************/
-bool DTVAL::GetTmMember(OPVAL op, int& mval)
- {
- bool rc = false;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- switch (op) {
- case OP_MDAY: mval = ptm->tm_mday; break;
- case OP_MONTH: mval = ptm->tm_mon + 1; break;
- case OP_YEAR: mval = ptm->tm_year + 1900; break;
- case OP_WDAY: mval = ptm->tm_wday + 1; break;
- case OP_YDAY: mval = ptm->tm_yday + 1; break;
- case OP_QUART: mval = ptm->tm_mon / 3 + 1; break;
- default:
- rc = true;
- } // endswitch op
-
- return rc;
- } // end of GetTmMember
-
-/***********************************************************************/
-/* Calculates the week number of the year for the internal date value.*/
-/* The International Standard ISO 8601 has decreed that Monday shall */
-/* be the first day of the week. A week that lies partly in one year */
-/* and partly in another is assigned a number in the year in which */
-/* most of its days lie. That means that week number 1 of any year is */
-/* the week that contains the January 4th. */
-/***********************************************************************/
-bool DTVAL::WeekNum(PGLOBAL g, int& nval)
- {
- // w is the start of the week SUN=0, MON=1, etc.
- int m, n, w = nval % 7;
- struct tm tm, *ptm = GetGmTime(&tm);
-
- // Which day is January 4th of this year?
- m = (367 + ptm->tm_wday - ptm->tm_yday) % 7;
-
- // When does the first week begins?
- n = 3 - (7 + m - w) % 7;
-
- // Now calculate the week number
- if (!(nval = (7 + ptm->tm_yday - n) / 7))
- nval = 52;
-
- // Everything should be Ok
- return false;
- } // end of WeekNum
-#endif // 0
-
-/***********************************************************************/
-/* FormatValue: This function set vp (a STRING value) to the string */
-/* constructed from its own value formated using the fmt format. */
-/* This function assumes that the format matches the value type. */
-/***********************************************************************/
-bool DTVAL::FormatValue(PVAL vp, char *fmt)
- {
- char *buf = (char*)vp->GetTo_Val(); // Should be big enough
- struct tm tm, *ptm = GetGmTime(&tm);
-
- if (trace > 1)
- htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
-
- if (ptm) {
- size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
-
- if (trace > 1)
- htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
-
- return (n == 0);
- } else
- return true;
-
- } // end of FormatValue
-
-/* -------------------------- End of Value --------------------------- */
+/************* Value C++ Functions Source Code File (.CPP) *************/ +/* Name: VALUE.CPP Version 2.4 */ +/* */ +/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */ +/* */ +/* This file contains the VALUE and derived classes family functions. */ +/* These classes contain values of different types. They are used so */ +/* new object types can be defined and added to the processing simply */ +/* (hopefully) adding their specific functions in this file. */ +/* First family is VALUE that represent single typed objects. It is */ +/* used by columns (COLBLK), SELECT and FILTER (derived) objects. */ +/* Second family is VALBLK, representing simple suballocated arrays */ +/* of values treated sequentially by FIX, BIN and VCT tables and */ +/* columns, as well for min/max blocks as for VCT column blocks. */ +/* Q&A: why not using only one family ? Simple values are arrays that */ +/* have only one element and arrays could have functions for all kind */ +/* of processing. The answer is a-because historically it was simpler */ +/* to do that way, b-because of performance on single values, and c- */ +/* to avoid too complicated classes and unuseful duplication of many */ +/* functions used on one family only. The drawback is that for new */ +/* types of objects, we shall have more classes to update. */ +/* Currently the only implemented types are STRING, INT, SHORT, TINY, */ +/* DATE and LONGLONG. Recently we added some UNSIGNED types. */ +/***********************************************************************/ + +/***********************************************************************/ +/* Include relevant MariaDB header file. */ +/***********************************************************************/ +#include "my_global.h" +#include "sql_class.h" +#include "sql_time.h" + +#if defined(WIN32) +//#include <windows.h> +#else // !WIN32 +#include <string.h> +#endif // !WIN32 + +#include <math.h> + +#undef DOMAIN // Was defined in math.h + +/***********************************************************************/ +/* Include required application header files */ +/* global.h is header containing all global Plug declarations. */ +/* plgdbsem.h is header containing the DB applic. declarations. */ +/***********************************************************************/ +#include "global.h" +#include "plgdbsem.h" +#include "preparse.h" // For DATPAR +//#include "value.h" +#include "valblk.h" +#define NO_FUNC // Already defined in ODBConn +#include "plgcnx.h" // For DB types +#include "osutil.h" + +/***********************************************************************/ +/* Check macro's. */ +/***********************************************************************/ +#if defined(_DEBUG) +#define CheckType(V) if (Type != V->GetType()) { \ + PGLOBAL& g = Global; \ + strcpy(g->Message, MSG(VALTYPE_NOMATCH)); \ + longjmp(g->jumper[g->jump_level], Type); } +#else +#define CheckType(V) +#endif + +#define FOURYEARS 126230400 // Four years in seconds (1 leap) + +/***********************************************************************/ +/* Static variables. */ +/***********************************************************************/ + +extern "C" int trace; + +/***********************************************************************/ +/* Initialize the DTVAL static member. */ +/***********************************************************************/ +int DTVAL::Shift = 0; + +/***********************************************************************/ +/* Routines called externally. */ +/***********************************************************************/ +bool PlugEvalLike(PGLOBAL, LPCSTR, LPCSTR, bool); + +#if !defined(WIN32) +extern "C" { +PSZ strupr(PSZ s); +PSZ strlwr(PSZ s); +} +#endif // !WIN32 + +/***********************************************************************/ +/* Returns the bitmap representing the conditions that must not be */ +/* met when returning from TestValue for a given operator. */ +/* Bit one is EQ, bit 2 is LT, and bit 3 is GT. */ +/***********************************************************************/ +BYTE OpBmp(PGLOBAL g, OPVAL opc) + { + BYTE bt; + + switch (opc) { + case OP_IN: + case OP_EQ: bt = 0x06; break; + case OP_NE: bt = 0x01; break; + case OP_GT: bt = 0x03; break; + case OP_GE: bt = 0x02; break; + case OP_LT: bt = 0x05; break; + case OP_LE: bt = 0x04; break; + case OP_EXIST: bt = 0x00; break; + default: + sprintf(g->Message, MSG(BAD_FILTER_OP), opc); + longjmp(g->jumper[g->jump_level], TYPE_ARRAY); + } // endswitch opc + + return bt; + } // end of OpBmp + +/***********************************************************************/ +/* Get a long long number from its character representation. */ +/* IN p: Pointer to the numeric string */ +/* IN n: The string length */ +/* IN maxval: The number max value */ +/* IN un: True if the number must be unsigned */ +/* OUT rc: Set to TRUE for out of range value */ +/* OUT minus: Set to true if the number is negative */ +/* Returned val: The resulting number */ +/***********************************************************************/ +ulonglong CharToNumber(char *p, int n, ulonglong maxval, + bool un, bool *minus, bool *rc) +{ + char *p2; + uchar c; + ulonglong val; + + if (minus) *minus = false; + if (rc) *rc = false; + + // Eliminate leading blanks or 0 + for (p2 = p + n; p < p2 && (*p == ' ' || *p == '0'); p++) ; + + // Get an eventual sign character + switch (*p) { + case '-': + if (un) { + if (rc) *rc = true; + return 0; + } else { + maxval++; + if (minus) *minus = true; + } // endif Unsigned + + case '+': + p++; + break; + } // endswitch *p + + for (val = 0; p < p2 && (c = (uchar)(*p - '0')) < 10; p++) + if (val > (maxval - c) / 10) { + val = maxval; + if (rc) *rc = true; + break; + } else + val = val * 10 + c; + + return val; +} // end of CharToNumber + +/***********************************************************************/ +/* GetTypeName: returns the PlugDB internal type name. */ +/***********************************************************************/ +PSZ GetTypeName(int type) + { + PSZ name; + + switch (type) { + case TYPE_STRING: name = "CHAR"; break; + case TYPE_SHORT: name = "SMALLINT"; break; + case TYPE_INT: name = "INTEGER"; break; + case TYPE_BIGINT: name = "BIGINT"; break; + case TYPE_DATE: name = "DATE"; break; + case TYPE_DOUBLE: name = "DOUBLE"; break; + case TYPE_TINY: name = "TINY"; break; + case TYPE_DECIM: name = "DECIMAL"; break; + default: name = "UNKNOWN"; break; + } // endswitch type + + return name; + } // end of GetTypeName + +/***********************************************************************/ +/* GetTypeSize: returns the PlugDB internal type size. */ +/***********************************************************************/ +int GetTypeSize(int type, int len) + { + switch (type) { + case TYPE_DECIM: + case TYPE_STRING: len = len * sizeof(char); break; + case TYPE_SHORT: len = sizeof(short); break; + case TYPE_INT: len = sizeof(int); break; + case TYPE_BIGINT: len = sizeof(longlong); break; + case TYPE_DATE: len = sizeof(int); break; + case TYPE_DOUBLE: len = sizeof(double); break; + case TYPE_TINY: len = sizeof(char); break; + default: len = 0; + } // endswitch type + + return len; + } // end of GetTypeSize + +/***********************************************************************/ +/* GetFormatType: returns the FORMAT character(s) according to type. */ +/***********************************************************************/ +char *GetFormatType(int type) + { + char *c = "X"; + + switch (type) { + case TYPE_STRING: c = "C"; break; + case TYPE_SHORT: c = "S"; break; + case TYPE_INT: c = "N"; break; + case TYPE_BIGINT: c = "L"; break; + case TYPE_DOUBLE: c = "F"; break; + case TYPE_DATE: c = "D"; break; + case TYPE_TINY: c = "T"; break; + case TYPE_DECIM: c = "M"; break; + } // endswitch type + + return c; + } // end of GetFormatType + +/***********************************************************************/ +/* GetFormatType: returns the FORMAT type according to character. */ +/***********************************************************************/ +int GetFormatType(char c) + { + int type = TYPE_ERROR; + + switch (c) { + case 'C': type = TYPE_STRING; break; + case 'S': type = TYPE_SHORT; break; + case 'N': type = TYPE_INT; break; + case 'L': type = TYPE_BIGINT; break; + case 'F': type = TYPE_DOUBLE; break; + case 'D': type = TYPE_DATE; break; + case 'T': type = TYPE_TINY; break; + case 'M': type = TYPE_DECIM; break; + } // endswitch type + + return type; + } // end of GetFormatType + +/***********************************************************************/ +/* IsTypeChar: returns true for character type(s). */ +/***********************************************************************/ +bool IsTypeChar(int type) + { + switch (type) { + case TYPE_STRING: + case TYPE_DECIM: + return true; + } // endswitch type + + return false; + } // end of IsTypeChar + +/***********************************************************************/ +/* IsTypeNum: returns true for numeric types. */ +/***********************************************************************/ +bool IsTypeNum(int type) + { + switch (type) { + case TYPE_INT: + case TYPE_BIGINT: + case TYPE_DATE: + case TYPE_DOUBLE: + case TYPE_SHORT: + case TYPE_NUM: + case TYPE_TINY: + case TYPE_DECIM: + return true; + } // endswitch type + + return false; + } // end of IsTypeNum + +/***********************************************************************/ +/* GetFmt: returns the format to use with a typed value. */ +/***********************************************************************/ +const char *GetFmt(int type, bool un) + { + const char *fmt; + + switch (type) { + case TYPE_DECIM: + case TYPE_STRING: fmt = "%s"; break; + case TYPE_SHORT: fmt = (un) ? "%hu" : "%hd"; break; + case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break; + case TYPE_DOUBLE: fmt = "%.*lf"; break; + default: fmt = (un) ? "%u" : "%d"; break; + } // endswitch Type + + return fmt; + } // end of GetFmt + +/***********************************************************************/ +/* ConvertType: what this function does is to determine the type to */ +/* which should be converted a value so no precision would be lost. */ +/* This can be a numeric type if num is true or non numeric if false. */ +/* Note: this is an ultra simplified version of this function that */ +/* should become more and more complex as new types are added. */ +/* Not evaluated types (TYPE_VOID or TYPE_UNDEF) return false from */ +/* IsType... functions so match does not prevent correct setting. */ +/***********************************************************************/ +int ConvertType(int target, int type, CONV kind, bool match) + { + switch (kind) { + case CNV_CHAR: + if (match && (!IsTypeChar(target) || !IsTypeChar(type))) + return TYPE_ERROR; + + return TYPE_STRING; + case CNV_NUM: + if (match && (!IsTypeNum(target) || !IsTypeNum(type))) + return TYPE_ERROR; + + return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE + : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE + : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT + : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT + : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT + : TYPE_TINY; + default: + if (target == TYPE_ERROR || target == type) + return type; + + if (match && ((IsTypeChar(target) && !IsTypeChar(type)) || + (IsTypeNum(target) && !IsTypeNum(type)))) + return TYPE_ERROR; + + return (target == TYPE_DOUBLE || type == TYPE_DOUBLE) ? TYPE_DOUBLE + : (target == TYPE_DATE || type == TYPE_DATE) ? TYPE_DATE + : (target == TYPE_BIGINT || type == TYPE_BIGINT) ? TYPE_BIGINT + : (target == TYPE_INT || type == TYPE_INT) ? TYPE_INT + : (target == TYPE_SHORT || type == TYPE_SHORT) ? TYPE_SHORT + : (target == TYPE_STRING || type == TYPE_STRING) ? TYPE_STRING + : (target == TYPE_TINY || type == TYPE_TINY) ? TYPE_TINY + : TYPE_ERROR; + } // endswitch kind + + } // end of ConvertType + +/***********************************************************************/ +/* AllocateConstant: allocates a constant Value. */ +/***********************************************************************/ +PVAL AllocateValue(PGLOBAL g, void *value, short type) + { + PVAL valp; + + if (trace) + htrc("AllocateConstant: value=%p type=%hd\n", value, type); + + switch (type) { + case TYPE_STRING: + valp = new(g) TYPVAL<PSZ>((PSZ)value); + break; + case TYPE_SHORT: + valp = new(g) TYPVAL<short>(*(short*)value, TYPE_SHORT); + break; + case TYPE_INT: + valp = new(g) TYPVAL<int>(*(int*)value, TYPE_INT); + break; + case TYPE_BIGINT: + valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT); + break; + case TYPE_DOUBLE: + valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2); + break; + case TYPE_TINY: + valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); + break; + default: + sprintf(g->Message, MSG(BAD_VALUE_TYPE), type); + return NULL; + } // endswitch Type + + valp->SetGlobal(g); + return valp; + } // end of AllocateValue + +/***********************************************************************/ +/* Allocate a variable Value according to type, length and precision. */ +/***********************************************************************/ +PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, + bool uns, PSZ fmt) + { + PVAL valp; + + switch (type) { + case TYPE_STRING: + valp = new(g) TYPVAL<PSZ>(g, (PSZ)NULL, len, prec); + break; + case TYPE_DATE: + valp = new(g) DTVAL(g, len, prec, fmt); + break; + case TYPE_INT: + if (uns) + valp = new(g) TYPVAL<uint>((uint)0, TYPE_INT, 0, true); + else + valp = new(g) TYPVAL<int>((int)0, TYPE_INT); + + break; + case TYPE_BIGINT: + if (uns) + valp = new(g) TYPVAL<ulonglong>((ulonglong)0, TYPE_BIGINT, 0, true); + else + valp = new(g) TYPVAL<longlong>((longlong)0, TYPE_BIGINT); + + break; + case TYPE_SHORT: + if (uns) + valp = new(g) TYPVAL<ushort>((ushort)0, TYPE_SHORT, 0, true); + else + valp = new(g) TYPVAL<short>((short)0, TYPE_SHORT); + + break; + case TYPE_DOUBLE: + valp = new(g) TYPVAL<double>(0.0, TYPE_DOUBLE, prec); + break; + case TYPE_TINY: + if (uns) + valp = new(g) TYPVAL<uchar>((uchar)0, TYPE_TINY, 0, true); + else + valp = new(g) TYPVAL<char>((char)0, TYPE_TINY); + + break; + case TYPE_DECIM: + valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns); + break; + default: + sprintf(g->Message, MSG(BAD_VALUE_TYPE), type); + return NULL; + } // endswitch type + + valp->SetGlobal(g); + return valp; + } // end of AllocateValue + +/***********************************************************************/ +/* Allocate a constant Value converted to newtype. */ +/* Can also be used to copy a Value eventually converted. */ +/***********************************************************************/ +PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns) + { + PSZ p, sp; + bool un = (uns < 0) ? false : (uns > 0) ? true : valp->IsUnsigned(); + + if (newtype == TYPE_VOID) // Means allocate a value of the same type + newtype = valp->GetType(); + + switch (newtype) { + case TYPE_STRING: + p = (PSZ)PlugSubAlloc(g, NULL, 1 + valp->GetValLen()); + + if ((sp = valp->GetCharString(p)) != p) + strcpy (p, sp); + + valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec()); + break; + case TYPE_SHORT: + if (un) + valp = new(g) TYPVAL<ushort>(valp->GetUShortValue(), + TYPE_SHORT, 0, true); + else + valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT); + + break; + case TYPE_INT: + if (un) + valp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true); + else + valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT); + + break; + case TYPE_BIGINT: + if (un) + valp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(), + TYPE_BIGINT, 0, true); + else + valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT); + + break; + case TYPE_DATE: + valp = new(g) DTVAL(g, valp->GetIntValue()); + break; + case TYPE_DOUBLE: + valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE, + valp->GetValPrec()); + break; + case TYPE_TINY: + if (un) + valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(), + TYPE_TINY, 0, true); + else + valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY); + + break; + default: + sprintf(g->Message, MSG(BAD_VALUE_TYPE), newtype); + return NULL; + } // endswitch type + + valp->SetGlobal(g); + return valp; + } // end of AllocateValue + +/* -------------------------- Class VALUE ---------------------------- */ + +/***********************************************************************/ +/* Class VALUE protected constructor. */ +/***********************************************************************/ +VALUE::VALUE(int type, bool un) : Type(type) + { + Null = false; + Nullable = false; + Unsigned = un; + Clen = 0; + Prec = 0; + Fmt = GetFmt(Type, Unsigned); + Xfmt = GetXfmt(); + } // end of VALUE constructor + +/***********************************************************************/ +/* VALUE GetXfmt: returns the extended format to use with typed value. */ +/***********************************************************************/ +const char *VALUE::GetXfmt(void) + { + const char *fmt; + + switch (Type) { + case TYPE_DECIM: + case TYPE_STRING: fmt = "%*s"; break; + case TYPE_SHORT: fmt = (Unsigned) ? "%*hu" : "%*hd"; break; + case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break; + case TYPE_DOUBLE: fmt = "%*.*lf"; break; + default: fmt = (Unsigned) ? "%*u" : "%*d"; break; + } // endswitch Type + + return fmt; + } // end of GetFmt + +/***********************************************************************/ +/* Returns a BYTE indicating the comparison between two values. */ +/* Bit 1 indicates equality, Bit 2 less than, and Bit3 greater than. */ +/* More than 1 bit can be set only in the case of TYPE_LIST. */ +/***********************************************************************/ +BYTE VALUE::TestValue(PVAL vp) + { + int n = CompareValue(vp); + + return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01; + } // end of TestValue + +/* -------------------------- Class TYPVAL ---------------------------- */ + +/***********************************************************************/ +/* TYPVAL public constructor from a constant typed value. */ +/***********************************************************************/ +template <class TYPE> +TYPVAL<TYPE>::TYPVAL(TYPE n, int type, int prec, bool un) + : VALUE(type, un) + { + Tval = n; + Clen = sizeof(TYPE); + Prec = prec; + } // end of TYPVAL constructor + +/***********************************************************************/ +/* Return unsigned max value for the type. */ +/***********************************************************************/ +template <class TYPE> +ulonglong TYPVAL<TYPE>::MaxVal(void) {DBUG_ASSERT(false); return 0;} + +template <> +ulonglong TYPVAL<short>::MaxVal(void) {return INT_MAX16;} + +template <> +ulonglong TYPVAL<ushort>::MaxVal(void) {return UINT_MAX16;} + +template <> +ulonglong TYPVAL<int>::MaxVal(void) {return INT_MAX32;} + +template <> +ulonglong TYPVAL<uint>::MaxVal(void) {return UINT_MAX32;} + +template <> +ulonglong TYPVAL<char>::MaxVal(void) {return INT_MAX8;} + +template <> +ulonglong TYPVAL<uchar>::MaxVal(void) {return UINT_MAX8;} + +template <> +ulonglong TYPVAL<longlong>::MaxVal(void) {return INT_MAX64;} + +template <> +ulonglong TYPVAL<ulonglong>::MaxVal(void) {return ULONGLONG_MAX;} + +/***********************************************************************/ +/* TYPVAL GetValLen: returns the print length of the typed object. */ +/***********************************************************************/ +template <class TYPE> +int TYPVAL<TYPE>::GetValLen(void) + { + char c[32]; + + return sprintf(c, Fmt, Tval); + } // end of GetValLen + +template <> +int TYPVAL<double>::GetValLen(void) + { + char c[32]; + + return sprintf(c, Fmt, Prec, Tval); + } // end of GetValLen + +/***********************************************************************/ +/* TYPVAL SetValue: copy the value of another Value object. */ +/* This function allows conversion if chktype is false. */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::SetValue_pval(PVAL valp, bool chktype) + { + if (chktype && Type != valp->GetType()) + return true; + + if (!(Null = valp->IsNull() && Nullable)) + Tval = GetTypedValue(valp); + else + Reset(); + + return false; + } // end of SetValue + +template <> +short TYPVAL<short>::GetTypedValue(PVAL valp) + {return valp->GetShortValue();} + +template <> +ushort TYPVAL<ushort>::GetTypedValue(PVAL valp) + {return valp->GetUShortValue();} + +template <> +int TYPVAL<int>::GetTypedValue(PVAL valp) + {return valp->GetIntValue();} + +template <> +uint TYPVAL<uint>::GetTypedValue(PVAL valp) + {return valp->GetUIntValue();} + +template <> +longlong TYPVAL<longlong>::GetTypedValue(PVAL valp) + {return valp->GetBigintValue();} + +template <> +ulonglong TYPVAL<ulonglong>::GetTypedValue(PVAL valp) + {return valp->GetUBigintValue();} + +template <> +double TYPVAL<double>::GetTypedValue(PVAL valp) + {return valp->GetFloatValue();} + +template <> +char TYPVAL<char>::GetTypedValue(PVAL valp) + {return valp->GetTinyValue();} + +template <> +uchar TYPVAL<uchar>::GetTypedValue(PVAL valp) + {return valp->GetUTinyValue();} + +/***********************************************************************/ +/* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::SetValue_char(char *p, int n) + { + bool rc, minus; + ulonglong maxval = MaxVal(); + ulonglong val = CharToNumber(p, n, maxval, Unsigned, &minus, &rc); + + if (minus && val < maxval) + Tval = (TYPE)(-(signed)val); + else + Tval = (TYPE)val; + + if (trace > 1) { + char buf[64]; + htrc(strcat(strcat(strcpy(buf, " setting %s to: "), Fmt), "\n"), + GetTypeName(Type), Tval); + } // endif trace + + Null = false; + return rc; + } // end of SetValue + +template <> +bool TYPVAL<double>::SetValue_char(char *p, int n) + { + if (p) { + char buf[64]; + + for (; n > 0 && *p == ' '; p++) + n--; + + memcpy(buf, p, min(n, 31)); + buf[n] = '\0'; + Tval = atof(buf); + + if (trace > 1) + htrc(" setting double: '%s' -> %lf\n", buf, Tval); + + Null = false; + } else { + Reset(); + Null = Nullable; + } // endif p + + return false; + } // end of SetValue + +/***********************************************************************/ +/* TYPVAL SetValue: fill a typed value from a string. */ +/***********************************************************************/ +template <class TYPE> +void TYPVAL<TYPE>::SetValue_psz(PSZ s) + { + if (s) { + SetValue_char(s, (int)strlen(s)); + Null = false; + } else { + Reset(); + Null = Nullable; + } // endif p + + } // end of SetValue + +/***********************************************************************/ +/* TYPVAL SetValue: set value with a TYPE extracted from a block. */ +/***********************************************************************/ +template <class TYPE> +void TYPVAL<TYPE>::SetValue_pvblk(PVBLK blk, int n) + { + Tval = GetTypedValue(blk, n); + Null = false; + } // end of SetValue + +template <> +int TYPVAL<int>::GetTypedValue(PVBLK blk, int n) + {return blk->GetIntValue(n);} + +template <> +uint TYPVAL<uint>::GetTypedValue(PVBLK blk, int n) + {return blk->GetUIntValue(n);} + +template <> +short TYPVAL<short>::GetTypedValue(PVBLK blk, int n) + {return blk->GetShortValue(n);} + +template <> +ushort TYPVAL<ushort>::GetTypedValue(PVBLK blk, int n) + {return blk->GetUShortValue(n);} + +template <> +longlong TYPVAL<longlong>::GetTypedValue(PVBLK blk, int n) + {return blk->GetBigintValue(n);} + +template <> +ulonglong TYPVAL<ulonglong>::GetTypedValue(PVBLK blk, int n) + {return blk->GetUBigintValue(n);} + +template <> +double TYPVAL<double>::GetTypedValue(PVBLK blk, int n) + {return blk->GetFloatValue(n);} + +template <> +char TYPVAL<char>::GetTypedValue(PVBLK blk, int n) + {return blk->GetTinyValue(n);} + +template <> +uchar TYPVAL<uchar>::GetTypedValue(PVBLK blk, int n) + {return blk->GetUTinyValue(n);} + +/***********************************************************************/ +/* TYPVAL SetBinValue: with bytes extracted from a line. */ +/***********************************************************************/ +template <class TYPE> +void TYPVAL<TYPE>::SetBinValue(void *p) + { + Tval = *(TYPE *)p; + Null = false; + } // end of SetBinValue + +/***********************************************************************/ +/* GetBinValue: fill a buffer with the internal binary value. */ +/* This function checks whether the buffer length is enough and */ +/* returns true if not. Actual filling occurs only if go is true. */ +/* Currently used by WriteColumn of binary files. */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::GetBinValue(void *buf, int buflen, bool go) + { + // Test on length was removed here until a variable in column give the + // real field length. For BIN files the field length logically cannot + // be different from the variable length because no conversion is done. + // Therefore this test is useless anyway. +//#if defined(_DEBUG) +// if (sizeof(TYPE) > buflen) +// return true; +//#endif + + if (go) + *(TYPE *)buf = Tval; + + Null = false; + return false; + } // end of GetBinValue + +/***********************************************************************/ +/* TYPVAL ShowValue: get string representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::ShowValue(char *buf, int len) + { + sprintf(buf, Xfmt, len, Tval); + return buf; + } // end of ShowValue + +template <> +char *TYPVAL<double>::ShowValue(char *buf, int len) + { + // TODO: use snprintf to avoid possible overflow + sprintf(buf, Xfmt, len, Prec, Tval); + return buf; + } // end of ShowValue + +/***********************************************************************/ +/* TYPVAL GetCharString: get string representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetCharString(char *p) + { + sprintf(p, Fmt, Tval); + return p; + } // end of GetCharString + +template <> +char *TYPVAL<double>::GetCharString(char *p) + { + sprintf(p, Fmt, Prec, Tval); + return p; + } // end of GetCharString + +#if 0 +/***********************************************************************/ +/* TYPVAL GetShortString: get short representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetShortString(char *p, int n) + { + sprintf(p, "%*hd", n, (short)Tval); + return p; + } // end of GetShortString + +/***********************************************************************/ +/* TYPVAL GetIntString: get int representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetIntString(char *p, int n) + { + sprintf(p, "%*d", n, (int)Tval); + return p; + } // end of GetIntString + +/***********************************************************************/ +/* TYPVAL GetBigintString: get big int representation of a TYPE value.*/ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetBigintString(char *p, int n) + { + sprintf(p, "%*lld", n, (longlong)Tval); + return p; + } // end of GetBigintString + +/***********************************************************************/ +/* TYPVAL GetFloatString: get double representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetFloatString(char *p, int n, int prec) + { + sprintf(p, "%*.*lf", n, (prec < 0) ? 2 : prec, (double)Tval); + return p; + } // end of GetFloatString + +/***********************************************************************/ +/* TYPVAL GetTinyString: get char representation of a typed value. */ +/***********************************************************************/ +template <class TYPE> +char *TYPVAL<TYPE>::GetTinyString(char *p, int n) + { + sprintf(p, "%*d", n, (int)(char)Tval); + return p; + } // end of GetIntString +#endif // 0 + +/***********************************************************************/ +/* TYPVAL compare value with another Value. */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::IsEqual(PVAL vp, bool chktype) + { + if (this == vp) + return true; + else if (chktype && Type != vp->GetType()) + return false; + else if (chktype && Unsigned != vp->IsUnsigned()) + return false; + else if (Null || vp->IsNull()) + return false; + else + return (Tval == GetTypedValue(vp)); + + } // end of IsEqual + +/***********************************************************************/ +/* Compare values and returns 1, 0 or -1 according to comparison. */ +/* This function is used for evaluation of numeric filters. */ +/***********************************************************************/ +template <class TYPE> +int TYPVAL<TYPE>::CompareValue(PVAL vp) + { +//assert(vp->GetType() == Type); + + // Process filtering on numeric values. + TYPE n = GetTypedValue(vp); + +//if (trace) +// htrc(" Comparing: val=%d,%d\n", Tval, n); + + return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0; + } // end of CompareValue + +/***********************************************************************/ +/* FormatValue: This function set vp (a STRING value) to the string */ +/* constructed from its own value formated using the fmt format. */ +/* This function assumes that the format matches the value type. */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::FormatValue(PVAL vp, char *fmt) + { + char *buf = (char*)vp->GetTo_Val(); // Should be big enough + int n = sprintf(buf, fmt, Tval); + + return (n > vp->GetValLen()); + } // end of FormatValue + +/***********************************************************************/ +/* TYPVAL SetFormat function (used to set SELECT output format). */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::SetConstFormat(PGLOBAL g, FORMAT& fmt) + { + char c[32]; + + fmt.Type[0] = *GetFormatType(Type); + fmt.Length = sprintf(c, Fmt, Tval); + fmt.Prec = Prec; + return false; + } // end of SetConstFormat + +/***********************************************************************/ +/* Make file output of a typed object. */ +/***********************************************************************/ +template <class TYPE> +void TYPVAL<TYPE>::Print(PGLOBAL g, FILE *f, uint n) + { + char m[64], buf[12]; + + memset(m, ' ', n); /* Make margin string */ + m[n] = '\0'; + + if (Null) + fprintf(f, "%s<null>\n", m); + else + fprintf(f, strcat(strcat(strcpy(buf, "%s"), Fmt), "\n"), m, Tval); + + } /* end of Print */ + +/***********************************************************************/ +/* Make string output of a int object. */ +/***********************************************************************/ +template <class TYPE> +void TYPVAL<TYPE>::Print(PGLOBAL g, char *ps, uint z) + { + if (Null) + strcpy(ps, "<null>"); + else + sprintf(ps, Fmt, Tval); + + } /* end of Print */ + +/* -------------------------- Class STRING --------------------------- */ + +/***********************************************************************/ +/* STRING public constructor from a constant string. */ +/***********************************************************************/ +TYPVAL<PSZ>::TYPVAL(PSZ s) : VALUE(TYPE_STRING) + { + Strp = s; + Len = strlen(s); + Clen = Len; + Ci = false; + } // end of STRING constructor + +/***********************************************************************/ +/* STRING public constructor from char. */ +/***********************************************************************/ +TYPVAL<PSZ>::TYPVAL(PGLOBAL g, PSZ s, int n, int c) + : VALUE(TYPE_STRING) + { + Len = (g) ? n : strlen(s); + + if (!s) { + if (g) { + Strp = (char *)PlugSubAlloc(g, NULL, Len + 1); + Strp[Len] = '\0'; + } else + assert(false); + + } else + Strp = s; + + Clen = Len; + Ci = (c != 0); + } // end of STRING constructor + +/***********************************************************************/ +/* Get the tiny value represented by the Strp string. */ +/***********************************************************************/ +char TYPVAL<PSZ>::GetTinyValue(void) + { + bool m; + ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX8, false, &m); + + return (m && val < INT_MAX8) ? (char)(-(signed)val) : (char)val; + } // end of GetTinyValue + +/***********************************************************************/ +/* Get the unsigned tiny value represented by the Strp string. */ +/***********************************************************************/ +uchar TYPVAL<PSZ>::GetUTinyValue(void) + { + return (uchar)CharToNumber(Strp, strlen(Strp), UINT_MAX8, true); + } // end of GetUTinyValue + +/***********************************************************************/ +/* Get the short value represented by the Strp string. */ +/***********************************************************************/ +short TYPVAL<PSZ>::GetShortValue(void) + { + bool m; + ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX16, false, &m); + + return (m && val < INT_MAX16) ? (short)(-(signed)val) : (short)val; + } // end of GetShortValue + +/***********************************************************************/ +/* Get the unsigned short value represented by the Strp string. */ +/***********************************************************************/ +ushort TYPVAL<PSZ>::GetUShortValue(void) + { + return (ushort)CharToNumber(Strp, strlen(Strp), UINT_MAX16, true); + } // end of GetUshortValue + +/***********************************************************************/ +/* Get the integer value represented by the Strp string. */ +/***********************************************************************/ +int TYPVAL<PSZ>::GetIntValue(void) + { + bool m; + ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX32, false, &m); + + return (m && val < INT_MAX32) ? (int)(-(signed)val) : (int)val; + } // end of GetIntValue + +/***********************************************************************/ +/* Get the unsigned integer value represented by the Strp string. */ +/***********************************************************************/ +uint TYPVAL<PSZ>::GetUIntValue(void) + { + return (uint)CharToNumber(Strp, strlen(Strp), UINT_MAX32, true); + } // end of GetUintValue + +/***********************************************************************/ +/* Get the big integer value represented by the Strp string. */ +/***********************************************************************/ +longlong TYPVAL<PSZ>::GetBigintValue(void) + { + bool m; + ulonglong val = CharToNumber(Strp, strlen(Strp), INT_MAX64, false, &m); + + return (m && val < INT_MAX64) ? (-(signed)val) : (longlong)val; + } // end of GetBigintValue + +/***********************************************************************/ +/* Get the unsigned big integer value represented by the Strp string. */ +/***********************************************************************/ +ulonglong TYPVAL<PSZ>::GetUBigintValue(void) + { + return CharToNumber(Strp, strlen(Strp), ULONGLONG_MAX, true); + } // end of GetUBigintValue + +/***********************************************************************/ +/* STRING SetValue: copy the value of another Value object. */ +/***********************************************************************/ +bool TYPVAL<PSZ>::SetValue_pval(PVAL valp, bool chktype) + { + if (chktype && (valp->GetType() != Type || valp->GetSize() > Len)) + return true; + + char buf[64]; + + if (!(Null = valp->IsNull() && Nullable)) + strncpy(Strp, valp->GetCharString(buf), Len); + else + Reset(); + + return false; + } // end of SetValue_pval + +/***********************************************************************/ +/* STRING SetValue: fill string with chars extracted from a line. */ +/***********************************************************************/ +bool TYPVAL<PSZ>::SetValue_char(char *p, int n) + { + bool rc; + + if (p) { + rc = n > Len; + + if ((n = min(n, Len))) { + strncpy(Strp, p, n); + +// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ; + for (p = Strp + n - 1; p >= Strp; p--) + if (*p && *p != ' ') + break; + + *(++p) = '\0'; + + if (trace > 1) + htrc(" Setting string to: '%s'\n", Strp); + + } else + Reset(); + + Null = false; + } else { + rc = false; + Reset(); + Null = Nullable; + } // endif p + + return rc; + } // end of SetValue_char + +/***********************************************************************/ +/* STRING SetValue: fill string with another string. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue_psz(PSZ s) + { + if (s) { + strncpy(Strp, s, Len); + Null = false; + } else { + Reset(); + Null = Nullable; + } // endif s + + } // end of SetValue_psz + +/***********************************************************************/ +/* STRING SetValue: fill string with a string extracted from a block. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n) + { + // STRBLK's can return a NULL pointer + PSZ vp = blk->GetCharString(Strp, n); + + if (vp != Strp) + SetValue_psz(vp); + + } // end of SetValue_pvblk + +/***********************************************************************/ +/* STRING SetValue: get the character representation of an integer. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(int n) + { + char buf[16]; + PGLOBAL& g = Global; + int k = sprintf(buf, "%d", n); + + if (k > Len) { + sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); + longjmp(g->jumper[g->jump_level], 138); + } else + SetValue_psz(buf); + + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of an uint. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(uint n) + { + char buf[16]; + PGLOBAL& g = Global; + int k = sprintf(buf, "%u", n); + + if (k > Len) { + sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); + longjmp(g->jumper[g->jump_level], 138); + } else + SetValue_psz(buf); + + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a short int. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(short i) + { + SetValue((int)i); + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a ushort int. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(ushort i) + { + SetValue((uint)i); + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a big integer.*/ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(longlong n) + { + char buf[24]; + PGLOBAL& g = Global; + int k = sprintf(buf, "%lld", n); + + if (k > Len) { + sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); + longjmp(g->jumper[g->jump_level], 138); + } else + SetValue_psz(buf); + + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a big integer.*/ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(ulonglong n) + { + char buf[24]; + PGLOBAL& g = Global; + int k = sprintf(buf, "%llu", n); + + if (k > Len) { + sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); + longjmp(g->jumper[g->jump_level], 138); + } else + SetValue_psz(buf); + + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a double. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(double f) + { + char *p, buf[64]; + PGLOBAL& g = Global; + int k = sprintf(buf, "%lf", f); + + for (p = buf + k - 1; p >= buf; p--) + if (*p == '0') { + *p = 0; + k--; + } else + break; + + if (k > Len) { + sprintf(g->Message, MSG(VALSTR_TOO_LONG), buf, Len); + longjmp(g->jumper[g->jump_level], 138); + } else + SetValue_psz(buf); + + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a tiny int. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(char c) + { + SetValue((int)c); + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetValue: get the character representation of a tiny int. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetValue(uchar c) + { + SetValue((uint)c); + Null = false; + } // end of SetValue + +/***********************************************************************/ +/* STRING SetBinValue: fill string with chars extracted from a line. */ +/***********************************************************************/ +void TYPVAL<PSZ>::SetBinValue(void *p) + { + SetValue_char((char *)p, Len); + } // end of SetBinValue + +/***********************************************************************/ +/* GetBinValue: fill a buffer with the internal binary value. */ +/* This function checks whether the buffer length is enough and */ +/* returns true if not. Actual filling occurs only if go is true. */ +/* Currently used by WriteColumn of binary files. */ +/***********************************************************************/ +bool TYPVAL<PSZ>::GetBinValue(void *buf, int buflen, bool go) + { + int len = (Null) ? 0 : strlen(Strp); + + if (len > buflen) + return true; + else if (go) { + memset(buf, ' ', buflen); + memcpy(buf, Strp, len); + } // endif go + + return false; + } // end of GetBinValue + +/***********************************************************************/ +/* STRING ShowValue: get string representation of a char value. */ +/***********************************************************************/ +char *TYPVAL<PSZ>::ShowValue(char *buf, int len) + { + return Strp; + } // end of ShowValue + +/***********************************************************************/ +/* STRING GetCharString: get string representation of a char value. */ +/***********************************************************************/ +char *TYPVAL<PSZ>::GetCharString(char *p) + { + return Strp; + } // end of GetCharString + +/***********************************************************************/ +/* STRING compare value with another Value. */ +/***********************************************************************/ +bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype) + { + if (this == vp) + return true; + else if (chktype && Type != vp->GetType()) + return false; + else if (Null || vp->IsNull()) + return false; + + char buf[64]; + + if (Ci || vp->IsCi()) + return !stricmp(Strp, vp->GetCharString(buf)); + else // (!Ci) + return !strcmp(Strp, vp->GetCharString(buf)); + + } // end of IsEqual + +/***********************************************************************/ +/* Compare values and returns 1, 0 or -1 according to comparison. */ +/* This function is used for evaluation of numeric filters. */ +/***********************************************************************/ +int TYPVAL<PSZ>::CompareValue(PVAL vp) + { + int n; +//assert(vp->GetType() == Type); + + if (trace) + htrc(" Comparing: val='%s','%s'\n", Strp, vp->GetCharValue()); + + // Process filtering on character strings. + if (Ci || vp->IsCi()) + n = stricmp(Strp, vp->GetCharValue()); + else + n = strcmp(Strp, vp->GetCharValue()); + +#if defined(WIN32) + if (n == _NLSCMPERROR) + return n; // Here we should raise an error +#endif // WIN32 + + return (n > 0) ? 1 : (n < 0) ? -1 : 0; + } // end of CompareValue + +/***********************************************************************/ +/* FormatValue: This function set vp (a STRING value) to the string */ +/* constructed from its own value formated using the fmt format. */ +/* This function assumes that the format matches the value type. */ +/***********************************************************************/ +bool TYPVAL<PSZ>::FormatValue(PVAL vp, char *fmt) + { + char *buf = (char*)vp->GetTo_Val(); // Should be big enough + int n = sprintf(buf, fmt, Strp); + + return (n > vp->GetValLen()); + } // end of FormatValue + +/***********************************************************************/ +/* STRING SetFormat function (used to set SELECT output format). */ +/***********************************************************************/ +bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL g, FORMAT& fmt) + { + fmt.Type[0] = 'C'; + fmt.Length = Len; + fmt.Prec = 0; + return false; + } // end of SetConstFormat + +/* -------------------------- Class DECIMAL -------------------------- */ + +/***********************************************************************/ +/* DECIMAL public constructor from a constant string. */ +/***********************************************************************/ +DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s) + { + if (s) { + char *p = strchr(Strp, '.'); + + Prec = (p) ? Len - (p - Strp) : 0; + } // endif s + + Type = TYPE_DECIM; + } // end of DECVAL constructor + +/***********************************************************************/ +/* DECIMAL public constructor from char. */ +/***********************************************************************/ +DECVAL::DECVAL(PGLOBAL g, PSZ s, int n, int prec, bool uns) + : TYPVAL<PSZ>(g, s, n + (prec ? 1 : 0) + (uns ? 0 : 1), 0) + { + Prec = prec; + Unsigned = uns; + Type = TYPE_DECIM; + } // end of DECVAL constructor + +/***********************************************************************/ +/* DECIMAL: Check whether the numerica value is equal to 0. */ +/***********************************************************************/ +bool DECVAL::IsZero(void) + { + for (int i = 0; Strp[i]; i++) + if (!strchr("0 +-.", Strp[i])) + return false; + + return true; + } // end of IsZero + +/***********************************************************************/ +/* DECIMAL: Reset value to zero. */ +/***********************************************************************/ +void DECVAL::Reset(void) +{ + int i = 0; + + Strp[i++] = '0'; + + if (Prec) { + Strp[i++] = '.'; + + do { + Strp[i++] = '0'; + } while (i < Prec + 2); + + } // endif Prec + + Strp[i] = 0; +} // end of Reset + +/***********************************************************************/ +/* DECIMAL ShowValue: get string representation right justified. */ +/***********************************************************************/ +char *DECVAL::ShowValue(char *buf, int len) + { + sprintf(buf, Xfmt, len, Strp); + return buf; + } // end of ShowValue + +/***********************************************************************/ +/* GetBinValue: fill a buffer with the internal binary value. */ +/* This function checks whether the buffer length is enough and */ +/* returns true if not. Actual filling occurs only if go is true. */ +/* Currently used by WriteColumn of binary files. */ +/***********************************************************************/ +bool DECVAL::GetBinValue(void *buf, int buflen, bool go) + { + int len = (Null) ? 0 : strlen(Strp); + + if (len > buflen) + return true; + else if (go) { + memset(buf, ' ', buflen - len); + memcpy((char*)buf + buflen - len, Strp, len); + } // endif go + + return false; + } // end of GetBinValue + +#if 0 +/***********************************************************************/ +/* DECIMAL SetValue: copy the value of another Value object. */ +/***********************************************************************/ +bool DECVAL::SetValue_pval(PVAL valp, bool chktype) + { + if (chktype && (valp->GetType() != Type || valp->GetSize() > Len)) + return true; + + char buf[64]; + + if (!(Null = valp->IsNull() && Nullable)) + strncpy(Strp, valp->GetCharString(buf), Len); + else + Reset(); + + return false; + } // end of SetValue_pval + +/***********************************************************************/ +/* DECIMAL SetValue: fill string with chars extracted from a line. */ +/***********************************************************************/ +bool DECVAL::SetValue_char(char *p, int n) + { + bool rc; + + if (p) { + rc = n > Len; + + if ((n = min(n, Len))) { + strncpy(Strp, p, n); + +// for (p = Strp + n - 1; p >= Strp && (*p == ' ' || *p == '\0'); p--) ; + for (p = Strp + n - 1; p >= Strp; p--) + if (*p && *p != ' ') + break; + + *(++p) = '\0'; + + if (trace > 1) + htrc(" Setting string to: '%s'\n", Strp); + + } else + Reset(); + + Null = false; + } else { + rc = false; + Reset(); + Null = Nullable; + } // endif p + + return rc; + } // end of SetValue_char + +/***********************************************************************/ +/* DECIMAL SetValue: fill string with another string. */ +/***********************************************************************/ +void DECVAL::SetValue_psz(PSZ s) + { + if (s) { + strncpy(Strp, s, Len); + Null = false; + } else { + Reset(); + Null = Nullable; + } // endif s + + } // end of SetValue_psz + +/***********************************************************************/ +/* DECIMAL SetValue: fill string with a string extracted from a block.*/ +/***********************************************************************/ +void DECVAL::SetValue_pvblk(PVBLK blk, int n) + { + // STRBLK's can return a NULL pointer + SetValue_psz(blk->GetCharValue(n)); + } // end of SetValue_pvblk + +/***********************************************************************/ +/* DECIMAL SetBinValue: fill string with chars extracted from a line. */ +/***********************************************************************/ +void DECVAL::SetBinValue(void *p) + { + SetValue_char((char *)p, Len); + } // end of SetBinValue + +/***********************************************************************/ +/* DECIMAL GetCharString: get string representation of a char value. */ +/***********************************************************************/ +char *DECVAL::GetCharString(char *p) + { + return Strp; + } // end of GetCharString +#endif // 0 + +/***********************************************************************/ +/* DECIMAL compare value with another Value. */ +/***********************************************************************/ +bool DECVAL::IsEqual(PVAL vp, bool chktype) + { + if (this == vp) + return true; + else if (chktype && Type != vp->GetType()) + return false; + else if (Null || vp->IsNull()) + return false; + + char buf[64]; + + return !strcmp(Strp, vp->GetCharString(buf)); + } // end of IsEqual + +/***********************************************************************/ +/* Compare values and returns 1, 0 or -1 according to comparison. */ +/* This function is used for evaluation of numeric filters. */ +/***********************************************************************/ +int DECVAL::CompareValue(PVAL vp) + { +//assert(vp->GetType() == Type); + + // Process filtering on numeric values. + double f = atof(Strp), n = vp->GetFloatValue(); + +//if (trace) +// htrc(" Comparing: val=%d,%d\n", f, n); + + return (f > n) ? 1 : (f < n) ? (-1) : 0; + } // end of CompareValue + +#if 0 +/***********************************************************************/ +/* FormatValue: This function set vp (a STRING value) to the string */ +/* constructed from its own value formated using the fmt format. */ +/* This function assumes that the format matches the value type. */ +/***********************************************************************/ +bool DECVAL::FormatValue(PVAL vp, char *fmt) + { + char *buf = (char*)vp->GetTo_Val(); // Should be big enough + int n = sprintf(buf, fmt, Strp); + + return (n > vp->GetValLen()); + } // end of FormatValue + +/***********************************************************************/ +/* DECIMAL SetFormat function (used to set SELECT output format). */ +/***********************************************************************/ +bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt) + { + fmt.Type[0] = 'C'; + fmt.Length = Len; + fmt.Prec = 0; + return false; + } // end of SetConstFormat +#endif // 0 + +/* -------------------------- Class DTVAL ---------------------------- */ + +/***********************************************************************/ +/* DTVAL public constructor for new void values. */ +/***********************************************************************/ +DTVAL::DTVAL(PGLOBAL g, int n, int prec, PSZ fmt) + : TYPVAL<int>((int)0, TYPE_DATE) + { + if (!fmt) { + Pdtp = NULL; + Sdate = NULL; + DefYear = 0; + Len = n; + } else + SetFormat(g, fmt, n, prec); + +//Type = TYPE_DATE; + } // end of DTVAL constructor + +/***********************************************************************/ +/* DTVAL public constructor from int. */ +/***********************************************************************/ +DTVAL::DTVAL(PGLOBAL g, int n) : TYPVAL<int>(n, TYPE_DATE) + { + Pdtp = NULL; + Len = 19; +//Type = TYPE_DATE; + Sdate = NULL; + DefYear = 0; + } // end of DTVAL constructor + +/***********************************************************************/ +/* Set format so formatted dates can be converted on input/output. */ +/***********************************************************************/ +bool DTVAL::SetFormat(PGLOBAL g, PSZ fmt, int len, int year) + { + Pdtp = MakeDateFormat(g, fmt, true, true, (year > 9999) ? 1 : 0); + Sdate = (char*)PlugSubAlloc(g, NULL, len + 1); + DefYear = (int)((year > 9999) ? (year - 10000) : year); + Len = len; + return false; + } // end of SetFormat + +/***********************************************************************/ +/* Set format from the format of another date value. */ +/***********************************************************************/ +bool DTVAL::SetFormat(PGLOBAL g, PVAL valp) + { + DTVAL *vp; + + if (valp->GetType() != TYPE_DATE) { + sprintf(g->Message, MSG(NO_FORMAT_TYPE), valp->GetType()); + return true; + } else + vp = (DTVAL*)valp; + + Len = vp->Len; + Pdtp = vp->Pdtp; + Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1); + DefYear = vp->DefYear; + return false; + } // end of SetFormat + +/***********************************************************************/ +/* We need TimeShift because the mktime C function does a correction */ +/* for local time zone that we want to override for DB operations. */ +/***********************************************************************/ +void DTVAL::SetTimeShift(void) + { + struct tm dtm; + memset(&dtm, 0, sizeof(dtm)); + dtm.tm_mday=2; + dtm.tm_mon=0; + dtm.tm_year=70; + + Shift = (int)mktime(&dtm) - 86400; + + if (trace) + htrc("DTVAL Shift=%d\n", Shift); + + } // end of SetTimeShift + +// Added by Alexander Barkov +static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime) +{ + bzero(tm, sizeof(*tm)); + tm->tm_year= ltime->year - 1900; + tm->tm_mon= ltime->month - 1; + tm->tm_mday= ltime->day; + tm->tm_hour= ltime->hour; + tm->tm_min= ltime->minute; + tm->tm_sec= ltime->second; +} + +// Added by Alexander Barkov +static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) +{ + MYSQL_TIME ltime; + thd_gmt_sec_to_TIME(current_thd, <ime, (my_time_t) *timep); + TIME_to_localtime(tm, <ime); + return tm; +} + +/***********************************************************************/ +/* GetGmTime: returns a pointer to a static tm structure obtained */ +/* though the gmtime C function. The purpose of this function is to */ +/* extend the range of valid dates by accepting negative time values. */ +/***********************************************************************/ +struct tm *DTVAL::GetGmTime(struct tm *tm_buffer) + { + struct tm *datm; + time_t t = (time_t)Tval; + + if (Tval < 0) { + int n; + + for (n = 0; t < 0; n += 4) + t += FOURYEARS; + + datm = gmtime_mysql(&t, tm_buffer); + + if (datm) + datm->tm_year -= n; + + } else + datm = gmtime_mysql(&t, tm_buffer); + + return datm; + } // end of GetGmTime + +// Added by Alexander Barkov +static time_t mktime_mysql(struct tm *ptm) +{ + MYSQL_TIME ltime; + localtime_to_TIME(<ime, ptm); + ltime.time_type= MYSQL_TIMESTAMP_DATETIME; + uint error_code; + time_t t= TIME_to_timestamp(current_thd, <ime, &error_code); + return error_code ? (time_t) -1 : t; +} + +/***********************************************************************/ +/* MakeTime: calculates a date value from a tm structures using the */ +/* mktime C function. The purpose of this function is to extend the */ +/* range of valid dates by accepting to set negative time values. */ +/***********************************************************************/ +bool DTVAL::MakeTime(struct tm *ptm) + { + int n, y = ptm->tm_year; + time_t t = mktime_mysql(ptm); + + if (trace > 1) + htrc("MakeTime from (%d,%d,%d,%d,%d,%d)\n", + ptm->tm_year, ptm->tm_mon, ptm->tm_mday, + ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + + if (t == -1) { + if (y < 1 || y > 71) + return true; + + for (n = 0; t == -1 && n < 20; n++) { + ptm->tm_year += 4; + t = mktime_mysql(ptm); + } // endfor t + + if (t == -1) + return true; + + if ((t -= (n * FOURYEARS)) > 2000000000) + return true; + + } + Tval= (int) t; + + if (trace > 1) + htrc("MakeTime Ival=%d\n", Tval); + + return false; + } // end of MakeTime + +/***********************************************************************/ +/* Make a time_t datetime from its components (YY, MM, DD, hh, mm, ss) */ +/***********************************************************************/ +bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval) + { + int i, m; + int n; + bool rc = false; + struct tm datm; + bzero(&datm, sizeof(datm)); + datm.tm_mday=1; + datm.tm_mon=0; + datm.tm_year=70; + + if (trace > 1) + htrc("MakeDate from(%d,%d,%d,%d,%d,%d) nval=%d\n", + val[0], val[1], val[2], val[3], val[4], val[5], nval); + + for (i = 0; i < nval; i++) { + n = val[i]; + +// if (trace > 1) +// htrc("i=%d n=%d\n", i, n); + + switch (i) { + case 0: + if (n >= 1900) + n -= 1900; + + datm.tm_year = n; + +// if (trace > 1) +// htrc("n=%d tm_year=%d\n", n, datm.tm_year); + + break; + case 1: + // If mktime handles apparently correctly large or negative + // day values, it is not the same for months. Therefore we + // do the ajustment here, thus mktime has not to do it. + if (n > 0) { + m = (n - 1) % 12; + n = (n - 1) / 12; + } else { + m = 11 + n % 12; + n = n / 12 - 1; + } // endfi n + + datm.tm_mon = m; + datm.tm_year += n; + +// if (trace > 1) +// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon); + + break; + case 2: + // For days, big or negative values may also cause problems + m = n % 1461; + n = 4 * (n / 1461); + + if (m < 0) { + m += 1461; + n -= 4; + } // endif m + + datm.tm_mday = m; + datm.tm_year += n; + +// if (trace > 1) +// htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon); + + break; + case 3: datm.tm_hour = n; break; + case 4: datm.tm_min = n; break; + case 5: datm.tm_sec = n; break; + } // endswitch i + + } // endfor i + + if (trace > 1) + htrc("MakeDate datm=(%d,%d,%d,%d,%d,%d)\n", + datm.tm_year, datm.tm_mon, datm.tm_mday, + datm.tm_hour, datm.tm_min, datm.tm_sec); + + // Pass g to have an error return or NULL to set invalid dates to 0 + if (MakeTime(&datm)) + if (g) { + strcpy(g->Message, MSG(BAD_DATETIME)); + rc = true; + } else + Tval = 0; + + return rc; + } // end of MakeDate + +/***********************************************************************/ +/* DTVAL SetValue: copy the value of another Value object. */ +/* This function allows conversion if chktype is false. */ +/***********************************************************************/ +bool DTVAL::SetValue_pval(PVAL valp, bool chktype) + { + if (chktype && Type != valp->GetType()) + return true; + + if (!(Null = valp->IsNull() && Nullable)) { + if (Pdtp && !valp->IsTypeNum()) { + int ndv; + int dval[6]; + + ndv = ExtractDate(valp->GetCharValue(), Pdtp, DefYear, dval); + MakeDate(NULL, dval, ndv); + } else + Tval = valp->GetIntValue(); + + } else + Reset(); + + return false; + } // end of SetValue + +/***********************************************************************/ +/* SetValue: convert chars extracted from a line to date value. */ +/***********************************************************************/ +bool DTVAL::SetValue_char(char *p, int n) + { + bool rc; + + if (Pdtp) { + char *p2; + int ndv; + int dval[6]; + + // Trim trailing blanks + for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--) ; + + if ((rc = (n = p2 - p + 1) > Len)) + n = Len; + + memcpy(Sdate, p, n); + Sdate[n] = '\0'; + + ndv = ExtractDate(Sdate, Pdtp, DefYear, dval); + MakeDate(NULL, dval, ndv); + + if (trace > 1) + htrc(" setting date: '%s' -> %d\n", Sdate, Tval); + + Null = false; + } else + rc = TYPVAL<int>::SetValue_char(p, n); + + return rc; + } // end of SetValue + +/***********************************************************************/ +/* SetValue: convert a char string to date value. */ +/***********************************************************************/ +void DTVAL::SetValue_psz(PSZ p) + { + if (Pdtp) { + int ndv; + int dval[6]; + + strncpy(Sdate, p, Len); + Sdate[Len] = '\0'; + + ndv = ExtractDate(Sdate, Pdtp, DefYear, dval); + MakeDate(NULL, dval, ndv); + + if (trace > 1) + htrc(" setting date: '%s' -> %d\n", Sdate, Tval); + + Null = false; + } else + TYPVAL<int>::SetValue_psz(p); + + } // end of SetValue + +/***********************************************************************/ +/* DTVAL SetValue: set value with a value extracted from a block. */ +/***********************************************************************/ +void DTVAL::SetValue_pvblk(PVBLK blk, int n) + { + if (Pdtp && !::IsTypeNum(blk->GetType())) { + int ndv; + int dval[6]; + + ndv = ExtractDate(blk->GetCharValue(n), Pdtp, DefYear, dval); + MakeDate(NULL, dval, ndv); + } else + Tval = blk->GetIntValue(n); + + } // end of SetValue + +/***********************************************************************/ +/* DTVAL GetCharString: get string representation of a date value. */ +/***********************************************************************/ +char *DTVAL::GetCharString(char *p) + { + if (Pdtp) { + size_t n = 0; + struct tm tm, *ptm= GetGmTime(&tm); + + if (ptm) + n = strftime(Sdate, Len + 1, Pdtp->OutFmt, ptm); + + if (!n) { + *Sdate = '\0'; + strncat(Sdate, "Error", Len + 1); + } // endif n + + return Sdate; + } else + sprintf(p, "%d", Tval); + + Null = false; + return p; + } // end of GetCharString + +/***********************************************************************/ +/* DTVAL ShowValue: get string representation of a date value. */ +/***********************************************************************/ +char *DTVAL::ShowValue(char *buf, int len) + { + if (Pdtp) { + char *p; + size_t m, n = 0; + struct tm tm, *ptm = GetGmTime(&tm); + + if (Len < len) { + p = buf; + m = len; + } else { + p = Sdate; + m = Len + 1; + } // endif Len + + if (ptm) + n = strftime(p, m, Pdtp->OutFmt, ptm); + + if (!n) { + *p = '\0'; + strncat(p, "Error", m); + } // endif n + + return p; + } else + return TYPVAL<int>::ShowValue(buf, len); + + } // end of ShowValue + +#if 0 // Not used by CONNECT +/***********************************************************************/ +/* Returns a member of the struct tm representation of the date. */ +/***********************************************************************/ +bool DTVAL::GetTmMember(OPVAL op, int& mval) + { + bool rc = false; + struct tm tm, *ptm = GetGmTime(&tm); + + switch (op) { + case OP_MDAY: mval = ptm->tm_mday; break; + case OP_MONTH: mval = ptm->tm_mon + 1; break; + case OP_YEAR: mval = ptm->tm_year + 1900; break; + case OP_WDAY: mval = ptm->tm_wday + 1; break; + case OP_YDAY: mval = ptm->tm_yday + 1; break; + case OP_QUART: mval = ptm->tm_mon / 3 + 1; break; + default: + rc = true; + } // endswitch op + + return rc; + } // end of GetTmMember + +/***********************************************************************/ +/* Calculates the week number of the year for the internal date value.*/ +/* The International Standard ISO 8601 has decreed that Monday shall */ +/* be the first day of the week. A week that lies partly in one year */ +/* and partly in another is assigned a number in the year in which */ +/* most of its days lie. That means that week number 1 of any year is */ +/* the week that contains the January 4th. */ +/***********************************************************************/ +bool DTVAL::WeekNum(PGLOBAL g, int& nval) + { + // w is the start of the week SUN=0, MON=1, etc. + int m, n, w = nval % 7; + struct tm tm, *ptm = GetGmTime(&tm); + + // Which day is January 4th of this year? + m = (367 + ptm->tm_wday - ptm->tm_yday) % 7; + + // When does the first week begins? + n = 3 - (7 + m - w) % 7; + + // Now calculate the week number + if (!(nval = (7 + ptm->tm_yday - n) / 7)) + nval = 52; + + // Everything should be Ok + return false; + } // end of WeekNum +#endif // 0 + +/***********************************************************************/ +/* FormatValue: This function set vp (a STRING value) to the string */ +/* constructed from its own value formated using the fmt format. */ +/* This function assumes that the format matches the value type. */ +/***********************************************************************/ +bool DTVAL::FormatValue(PVAL vp, char *fmt) + { + char *buf = (char*)vp->GetTo_Val(); // Should be big enough + struct tm tm, *ptm = GetGmTime(&tm); + + if (trace > 1) + htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen()); + + if (ptm) { + size_t n = strftime(buf, vp->GetValLen(), fmt, ptm); + + if (trace > 1) + htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???"); + + return (n == 0); + } else + return true; + + } // end of FormatValue + +/* -------------------------- End of Value --------------------------- */ |