/************* Value C++ Functions Source Code File (.CPP) *************/ /* Name: VALUE.CPP Version 2.9 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2001-2019 */ /* */ /* 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 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"valblk.h" #define NO_FUNC // Already defined in ODBConn #include"plgcnx.h"// For DB types #include"osutil.h"
/***********************************************************************/ /* 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(constchar *p, int n, ulonglong maxval, bool un, bool *minus, bool *rc)
{ constchar *p2;
uchar c;
ulonglong val;
if (minus) *minus = false; if (rc) *rc = false; if (n <= 0) return0LL;
// 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; return0;
} else {
maxval++; if (minus) *minus = true;
} // endif Unsigned
// Fall through 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. */ /***********************************************************************/
PCSZ GetTypeName(int type)
{
PCSZ 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; case TYPE_BIN: name = "BINARY"; break; case TYPE_PCHAR: name = "PCHAR"; break; default: name = "UNKNOWN"; break;
} // endswitch type
return name;
} // end of GetTypeName
/***********************************************************************/ /* GetTypeSize: returns the PlugDB internal type size. */ /***********************************************************************/ unsigned GetTypeSize(int type, unsigned len)
{ switch (type) { case TYPE_DECIM: case TYPE_BIN: 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; case TYPE_PCHAR: len = sizeof(char*); break; default: len = 0;
} // endswitch type
return len;
} // end of GetTypeSize
/***********************************************************************/ /* GetFormatType: returns the FORMAT character(s) according to type. */ /***********************************************************************/ constchar *GetFormatType(int type)
{ constchar *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 = "F"; break; case TYPE_BIN: c = "B"; break; case TYPE_PCHAR: c = "P"; 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; case'B': type = TYPE_BIN; break; case'P': type = TYPE_PCHAR; 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: case TYPE_BIN: returntrue;
} // endswitch type
returnfalse;
} // 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: returntrue;
} // endswitch type
returnfalse;
} // end of IsTypeNum
/***********************************************************************/ /* GetFmt: returns the format to use with a typed value. */ /***********************************************************************/ constchar *GetFmt(int type, bool un)
{ constchar *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; case TYPE_BIN: fmt = "%*x"; break; case TYPE_DATE: fmt = "%llu"; 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;
/***********************************************************************/ /* AllocateConstant: allocates a constant Value. */ /***********************************************************************/
PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec)
{
PVAL valp;
if (trace(1))
htrc("AllocateConstant: value=%p type=%hd\n", value, type);
switch (type) { case TYPE_STRING:
valp = new(g) TYPVAL<PSZ>((PSZ)value, prec); 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, prec); break; case TYPE_TINY:
valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); break; default:
snprintf(g->Message, sizeof(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, PCSZ 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);
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();
PVAL vp;
if (!valp) return NULL;
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 && sp)
strcpy(p, sp);
vp->SetNullable(valp->GetNullable());
vp->SetNull(valp->IsNull());
vp->SetGlobal(g); return vp;
} // 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. */ /***********************************************************************/ constchar *VALUE::GetXfmt(void)
{ constchar *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; case TYPE_BIN: fmt = "%*x"; break; case TYPE_DATE: fmt = "%*lld"; break; default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
} // endswitch Type
return fmt;
} // end of GetXFmt
/***********************************************************************/ /* 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
/***********************************************************************/ /* Compute a function on a string. */ /***********************************************************************/ bool VALUE::Compute(PGLOBAL g, PVAL *, int, OPVAL)
{
snprintf(g->Message, sizeof(g->Message), "Compute not implemented for this value type"); returntrue;
} // end of Compute
/***********************************************************************/ /* Make file output of an object value. */ /***********************************************************************/ void VALUE::Printf(PGLOBAL g, FILE *f, uint n)
{ char m[64], buf[64];
if (Null)
fprintf(f, "%s<null>\n", m); else
fprintf(f, "%s%s\n", m, GetCharString(buf));
} /* end of Printf */
/***********************************************************************/ /* Make string output of an object value. */ /***********************************************************************/ void VALUE::Prints(PGLOBAL g, char *ps, uint z)
{ char *p, buf[64];
if (Null)
p = strcpy(buf, "<null>"); else
p = GetCharString(buf);
strncpy(ps, p, z);
} // end of Prints
/* -------------------------- 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); return0;}
/***********************************************************************/ /* TYPVAL GetValLen: returns the print length of the typed object. */ /***********************************************************************/ template <class TYPE> int TYPVAL<TYPE>::GetValLen(void)
{ char c[32];
return snprintf(c, 32, Fmt, Tval);
} // end of GetValLen
template <> int TYPVAL<double>::GetValLen(void)
{ char c[32];
return snprintf(c, 32, 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 (valp != this) { if (chktype && Type != valp->GetType()) returntrue;
/***********************************************************************/ /* TYPVAL SetValue: convert chars extracted from a line to TYPE value.*/ /***********************************************************************/ template <class TYPE> bool TYPVAL<TYPE>::SetValue_char(constchar *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(2)) { 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(constchar *p, int n)
{ if (p && n > 0) { char buf[64];
/***********************************************************************/ /* TYPVAL SetValue: fill a typed value from a string. */ /***********************************************************************/ template <class TYPE> void TYPVAL<TYPE>::SetValue_psz(PCSZ 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. */ /* Currently only used reading column of binary files. */ /***********************************************************************/ template <class TYPE> void TYPVAL<TYPE>::SetBinValue(void *p)
{ #ifdefined(UNALIGNED_OK) // x86 can cast non-aligned memory directly
Tval = *(TYPE *)p; #else // Prevent unaligned memory access on MIPS and ArmHF platforms. // Make use of memcpy instead of straight pointer dereferencing. // Currently only used by WriteColumn of binary files. // From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
memcpy(&Tval, p, sizeof(TYPE)); #endif
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 only used writing column 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) #ifdefined(UNALIGNED_OK) // x86 can cast non-aligned memory directly
*(TYPE *)buf = Tval; #else // Prevent unaligned memory access on MIPS and ArmHF platforms. // Make use of memcpy instead of straight pointer dereferencing. // Currently only used by WriteColumn of binary files. // From original author: Vicentiu Ciorbaru <vicentiu@mariadb.org>
memcpy(buf, &Tval, sizeof(TYPE)); #endif
Null = false; returnfalse;
} // end of GetBinValue
/***********************************************************************/ /* TYPVAL ShowValue: get string representation of a typed value. */ /***********************************************************************/ template <class TYPE> int TYPVAL<TYPE>::ShowValue(char *buf, int len)
{ return snprintf(buf, len + 1, Xfmt, len, Tval);
} // end of ShowValue
template <> int TYPVAL<double>::ShowValue(char *buf, int len)
{ // TODO: use a more appropriate format to avoid possible truncation return snprintf(buf, len + 1, Xfmt, len, Prec, Tval);
} // end of ShowValue
/***********************************************************************/ /* TYPVAL GetCharString: get string representation of a typed value. */ /***********************************************************************/ template <class TYPE> char *TYPVAL<TYPE>::GetCharString(char *p)
{
snprintf(p, 32, Fmt, Tval); return p;
} // end of GetCharString
template <> char *TYPVAL<double>::GetCharString(char *p)
{ // Most callers use a 32 long buffer
snprintf(p, 32, Fmt, Prec, Tval); return p;
} // end of GetCharString
#if0 /***********************************************************************/ /* TYPVAL GetShortString: get short representation of a typed value. */ /***********************************************************************/ template <class TYPE> char *TYPVAL<TYPE>::GetShortString(char *p, int n)
{
snprintf(p, 32, "%*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)
{
snprintf(p, 32, "%*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)
{
snprintf(p, 32, "%*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)
{
snprintf(p, 32, "%*.*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)
{
snprintf(p, 32, "%*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) returntrue; elseif (chktype && Type != vp->GetType()) returnfalse; elseif (chktype && Unsigned != vp->IsUnsigned()) returnfalse; elseif (Null || vp->IsNull()) returnfalse; 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);
return (Tval > n) ? 1 : (Tval < n) ? (-1) : 0;
} // end of CompareValue
/***********************************************************************/ /* Return max type value if b is true, else min type value. */ /***********************************************************************/ template <> short TYPVAL<short>::MinMaxVal(bool b)
{return (b) ? INT_MAX16 : INT_MIN16;}
/***********************************************************************/ /* SafeAdd: adds a value and test whether overflow/underflow occurred. */ /***********************************************************************/ template <class TYPE>
TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2)
{
PGLOBAL& g = Global;
TYPE n = n1 + n2;
for (int i = 0; i < np; i++)
val[i] = vp[i]->GetFloatValue();
switch (op) { case OP_ADD:
Tval = val[0] + val[1]; break; case OP_MULT:
Tval = val[0] * val[1]; break; default:
rc = Compall(g, vp, np, op);
} // endswitch op
return rc;
} // end of Compute
/***********************************************************************/ /* Compute a function for all types. */ /***********************************************************************/ template <class TYPE> bool TYPVAL<TYPE>::Compall(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{
TYPE val[2];
for (int i = 0; i < np; i++)
val[i] = GetTypedValue(vp[i]);
switch (op) { case OP_DIV: if (val[0]) { if (!val[1]) {
snprintf(g->Message, sizeof(g->Message), MSG(ZERO_DIVIDE)); returntrue;
} // endif
Tval = val[0] / val[1];
} else
Tval = 0;
break; case OP_MIN:
Tval = MY_MIN(val[0], val[1]); break; case OP_MAX:
Tval = MY_MAX(val[0], val[1]); break; default: // snprintf(g->Message, sizeof(g->Message), MSG(BAD_EXP_OPER), op);
snprintf(g->Message, sizeof(g->Message), "Function not supported"); returntrue;
} // endswitch op
returnfalse;
} // end of Compall
/***********************************************************************/ /* FormatValue: This function set vp (a STRING value) to the string */ /* constructed from its own value formatted using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ template <class TYPE> bool TYPVAL<TYPE>::FormatValue(PVAL vp, PCSZ fmt)
{ // This function is wrong and should never be called
assert(false); char *buf = (char*)vp->GetTo_Val(); // Not big enough int n = snprintf(buf, vp->GetValLen() + 1, 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 = snprintf(c, sizeof(c), Fmt, Tval);
fmt.Prec = Prec; returnfalse;
} // end of SetConstFormat
/* -------------------------- Class STRING --------------------------- */
/***********************************************************************/ /* STRING public constructor from a constant string. */ /***********************************************************************/
TYPVAL<PSZ>::TYPVAL(PSZ s, short c) : VALUE(TYPE_STRING)
{
Strp = s;
Len = strlen(s);
Clen = Len;
Ci = (c == 1);
} // 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 : (s) ? strlen(s) : 0;
if (!s) { if (g) { if ((Strp = (char *)PlgDBSubAlloc(g, NULL, Len + 1)))
memset(Strp, 0, Len + 1); else
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 (valp != this) { if (chktype && (valp->GetType() != Type || valp->GetSize() > Len)) returntrue;
/***********************************************************************/ /* STRING SetValue: fill string with chars extracted from a line. */ /***********************************************************************/ bool TYPVAL<PSZ>::SetValue_char(constchar *cp, int n)
{ bool rc = false;
if (!cp || n == 0) {
Reset();
Null = (cp) ? false : Nullable;
} elseif (cp != Strp) { constchar *p = cp + n - 1;
for (; p >= cp; p--, n--) if (*p && *p != ' ') break;
if (trace(2))
htrc(" Setting string to: '%s'\n", Strp);
} else
Reset();
Null = false;
} // endif cp
return rc;
} // end of SetValue_char
/***********************************************************************/ /* STRING SetValue: fill string with another string. */ /***********************************************************************/ void TYPVAL<PSZ>::SetValue_psz(PCSZ s)
{ if (!s) {
Reset();
Null = Nullable;
} elseif (s != Strp) {
strncpy(Strp, s, Len);
Null = false;
} // 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 = snprintf(buf, sizeof(buf), "%d", n);
/***********************************************************************/ /* STRING SetValue: get the character representation of an uint. */ /***********************************************************************/ void TYPVAL<PSZ>::SetValue(uint n)
{ char buf[16];
PGLOBAL& g = Global; int k = snprintf(buf, sizeof(buf), "%u", n);
/***********************************************************************/ /* 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 = snprintf(buf, sizeof(buf), "%lld", n);
/***********************************************************************/ /* STRING SetValue: get the character representation of a big integer.*/ /***********************************************************************/ void TYPVAL<PSZ>::SetValue(ulonglong n)
{ char buf[24];
PGLOBAL& g = Global; int k = snprintf(buf, sizeof(buf), "%llu", n);
/***********************************************************************/ /* STRING SetValue: get the character representation of a double. */ /***********************************************************************/ void TYPVAL<PSZ>::SetValue(double f)
{ char *p, buf[64];
PGLOBAL& g = Global; int k = snprintf(buf, sizeof(buf), "%lf", f);
for (p = buf + k - 1; p >= buf; p--) if (*p == '0') {
*p = 0;
k--;
} else break;
/***********************************************************************/ /* 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((constchar *)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) returntrue; elseif (go) {
memset(buf, ' ', buflen);
memcpy(buf, Strp, len);
} // endif go
returnfalse;
} // end of GetBinValue
/***********************************************************************/ /* STRING ShowValue: get string representation of a char value. */ /***********************************************************************/ int TYPVAL<PSZ>::ShowValue(char *buf, int buflen)
{ int len = (Null) ? 0 : strlen(Strp);
/***********************************************************************/ /* STRING GetCharString: get string representation of a char value. */ /***********************************************************************/ char *TYPVAL<PSZ>::GetCharString(char *)
{ return Strp;
} // end of GetCharString
/***********************************************************************/ /* STRING compare value with another Value. */ /***********************************************************************/ bool TYPVAL<PSZ>::IsEqual(PVAL vp, bool chktype)
{ if (this == vp) returntrue; elseif (chktype && Type != vp->GetType()) returnfalse; elseif (Null || vp->IsNull()) returnfalse;
/***********************************************************************/ /* 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(1))
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());
#ifdefined(_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
/***********************************************************************/ /* Compute a function on a string. */ /***********************************************************************/ bool TYPVAL<PSZ>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op)
{ char *p[2], val[2][32]; int i;
if (trace(1))
htrc("Compute: np=%d op=%d\n", np, op);
for (i = 0; i < np; i++) if (!vp[i]->IsNull()) {
p[i] = vp[i]->GetCharString(val[i]);
/***********************************************************************/ /* FormatValue: This function set vp (a STRING value) to the string */ /* constructed from its own value formatted using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ bool TYPVAL<PSZ>::FormatValue(PVAL vp, PCSZ fmt)
{ char *buf = (char*)vp->GetTo_Val(); // Should be big enough int n = snprintf(buf, vp->GetValLen() + 1, fmt, Strp);
return (n > vp->GetValLen());
} // end of FormatValue
/***********************************************************************/ /* STRING SetFormat function (used to set SELECT output format). */ /***********************************************************************/ bool TYPVAL<PSZ>::SetConstFormat(PGLOBAL, FORMAT& fmt)
{
fmt.Type[0] = 'C';
fmt.Length = Len;
fmt.Prec = 0; returnfalse;
} // end of SetConstFormat
/***********************************************************************/ /* Make string output of an object value. */ /***********************************************************************/ void TYPVAL<PSZ>::Prints(PGLOBAL g, char *ps, uint z)
{ if (Null)
strncpy(ps, "null", z); else
strcat(strncat(strncpy(ps, "\"", z), Strp, z-2), "\"");
} // end of Prints
/* -------------------------- Class DECIMAL -------------------------- */
/***********************************************************************/ /* DECIMAL public constructor from a constant string. */ /***********************************************************************/
DECVAL::DECVAL(PSZ s) : TYPVAL<PSZ>(s)
{ if (s) { char *p = strchr(Strp, '.');
/***********************************************************************/ /* 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 numerical value is equal to 0. */ /***********************************************************************/ bool DECVAL::IsZero(void)
{ for (int i = 0; Strp[i]; i++) if (!strchr("0 +-.", Strp[i])) returnfalse;
returntrue;
} // 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. */ /***********************************************************************/ int DECVAL::ShowValue(char *buf, int len)
{ return snprintf(buf, len + 1, Xfmt, len, Strp);
} // 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);
/***********************************************************************/ /* DECIMAL compare value with another Value. */ /***********************************************************************/ bool DECVAL::IsEqual(PVAL vp, bool chktype)
{ if (this == vp) returntrue; elseif (chktype && Type != vp->GetType()) returnfalse; elseif (Null || vp->IsNull()) returnfalse;
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();
return (f > n) ? 1 : (f < n) ? (-1) : 0;
} // end of CompareValue
/* -------------------------- Class BINVAL --------------------------- */
/***********************************************************************/ /* BINVAL public constructor from bytes. */ /***********************************************************************/
BINVAL::BINVAL(PGLOBAL g, void *p, int cl, int n) : VALUE(TYPE_BIN)
{
assert(g);
Len = n;
Clen = cl;
Binp = PlugSubAlloc(g, NULL, Clen + 1);
memset(Binp, 0, Clen + 1);
if (p)
memcpy(Binp, p, MY_MIN(Len,Clen));
Chrp = NULL;
} // end of BINVAL constructor
/***********************************************************************/ /* BINVAL: Check whether the hexadecimal value is equal to 0. */ /***********************************************************************/ bool BINVAL::IsZero(void)
{ for (int i = 0; i < Len; i++) if (((char*)Binp)[i] != 0) returnfalse;
returntrue;
} // end of IsZero
/***********************************************************************/ /* BINVAL: Reset value to zero. */ /***********************************************************************/ void BINVAL::Reset(void)
{
memset(Binp, 0, Clen);
Len = 0;
} // end of Reset
/***********************************************************************/ /* Get the tiny value pointed by Binp. */ /***********************************************************************/ char BINVAL::GetTinyValue(void)
{ return *(char*)Binp;
} // end of GetTinyValue
/***********************************************************************/ /* Get the unsigned tiny value pointed by Binp. */ /***********************************************************************/
uchar BINVAL::GetUTinyValue(void)
{ return *(uchar*)Binp;
} // end of GetUTinyValue
/***********************************************************************/ /* Get the short value pointed by Binp. */ /***********************************************************************/ short BINVAL::GetShortValue(void)
{ if (Len >= 2) return *(short*)Binp; else return (short)GetTinyValue();
} // end of GetShortValue
/***********************************************************************/ /* Get the unsigned short value pointed by Binp. */ /***********************************************************************/
ushort BINVAL::GetUShortValue(void)
{ return (ushort)GetShortValue();
} // end of GetUshortValue
/***********************************************************************/ /* Get the integer value pointed by Binp. */ /***********************************************************************/ int BINVAL::GetIntValue(void)
{ if (Len >= 4) return *(int*)Binp; else return (int)GetShortValue();
} // end of GetIntValue
/***********************************************************************/ /* Get the unsigned integer value pointed by Binp. */ /***********************************************************************/
uint BINVAL::GetUIntValue(void)
{ return (uint)GetIntValue();
} // end of GetUintValue
/***********************************************************************/ /* Get the big integer value pointed by Binp. */ /***********************************************************************/
longlong BINVAL::GetBigintValue(void)
{ if (Len >= 8) return *(longlong*)Binp; else return (longlong)GetIntValue();
} // end of GetBigintValue
/***********************************************************************/ /* Get the unsigned big integer value pointed by Binp. */ /***********************************************************************/
ulonglong BINVAL::GetUBigintValue(void)
{ return (ulonglong)GetBigintValue();
} // end of GetUBigintValue
/***********************************************************************/ /* Get the double value pointed by Binp. */ /***********************************************************************/ double BINVAL::GetFloatValue(void)
{ if (Len >= 8) return *(double*)Binp; elseif (Len >= 4) return (double)(*(float*)Binp); else return0.0;
} // end of GetFloatValue
/***********************************************************************/ /* BINVAL SetValue: copy the value of another Value object. */ /***********************************************************************/ bool BINVAL::SetValue_pval(PVAL valp, bool chktype)
{ bool rc = false;
if (valp != this) { if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen)) returntrue;
if (!(Null = valp->IsNull() && Nullable)) { int len = Len;
if ((rc = (Len = valp->GetSize()) > Clen))
Len = Clen; elseif (len > Len)
memset(Binp, 0, len);
/***********************************************************************/ /* BINVAL SetValue: fill value with chars extracted from a line. */ /***********************************************************************/ bool BINVAL::SetValue_char(constchar *p, int n)
{ bool rc;
if (p && n > 0) { int len = Len;
if (len > (Len = MY_MIN(n, Clen)))
memset(Binp, 0, len);
/***********************************************************************/ /* BINVAL SetValue: fill value with another string. */ /***********************************************************************/ void BINVAL::SetValue_psz(PCSZ s)
{ if (s) { int len = Len;
if (len > (Len = MY_MIN(Clen, (signed)strlen(s))))
memset(Binp, 0, len);
/***********************************************************************/ /* BINVAL SetValue: fill value with bytes extracted from a block. */ /***********************************************************************/ void BINVAL::SetValue_pvblk(PVBLK blk, int n)
{ // STRBLK's can return a NULL pointer void *vp = blk->GetValPtrEx(n);
if (!vp || blk->IsNull(n)) {
Reset();
Null = Nullable;
} elseif (vp != Binp) { int len = Len;
if (blk->GetType() == TYPE_STRING)
Len = strlen((char*)vp); else
Len = blk->GetVlen();
if (len > (Len = MY_MIN(Clen, Len)))
memset(Binp, 0, len);
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of an integer. */ /***********************************************************************/ void BINVAL::SetValue(int n)
{ if (Clen >= 4) { if (Len > 4)
memset(Binp, 0, Len);
*((int*)Binp) = n;
Len = 4;
} else
SetValue((short)n);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of an uint. */ /***********************************************************************/ void BINVAL::SetValue(uint n)
{ if (Clen >= 4) { if (Len > 4)
memset(Binp, 0, Len);
*((uint*)Binp) = n;
Len = 4;
} else
SetValue((ushort)n);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a short int. */ /***********************************************************************/ void BINVAL::SetValue(short i)
{ if (Clen >= 2) { if (Len > 2)
memset(Binp, 0, Len);
*((int*)Binp) = i;
Len = 2;
} else
SetValue((char)i);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a ushort int. */ /***********************************************************************/ void BINVAL::SetValue(ushort i)
{ if (Clen >= 2) { if (Len > 2)
memset(Binp, 0, Len);
*((uint*)Binp) = i;
Len = 2;
} else
SetValue((uchar)i);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a big integer. */ /***********************************************************************/ void BINVAL::SetValue(longlong n)
{ if (Clen >= 8) { if (Len > 8)
memset(Binp, 0, Len);
*((longlong*)Binp) = n;
Len = 8;
} else
SetValue((int)n);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a big integer. */ /***********************************************************************/ void BINVAL::SetValue(ulonglong n)
{ if (Clen >= 8) { if (Len > 8)
memset(Binp, 0, Len);
*((ulonglong*)Binp) = n;
Len = 8;
} else
SetValue((uint)n);
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a double. */ /***********************************************************************/ void BINVAL::SetValue(double n)
{ if (Len > 8)
memset(Binp, 0, Len);
if (Clen >= 8) {
*((double*)Binp) = n;
Len = 8;
} elseif (Clen >= 4) {
*((float*)Binp) = (float)n;
Len = 4;
} else
Len = 0;
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the character binary of a tiny int. */ /***********************************************************************/ void BINVAL::SetValue(char c)
{ if (Len > 1)
memset(Binp, 0, Len);
*((char*)Binp) = c;
Len = 1;
} // end of SetValue
/***********************************************************************/ /* BINVAL SetValue: get the binary representation of a tiny int. */ /***********************************************************************/ void BINVAL::SetValue(uchar c)
{ if (Len > 1)
memset(Binp, 0, Len);
*((uchar*)Binp) = c;
Len = 1;
} // end of SetValue
/***********************************************************************/ /* BINVAL SetBinValue: fill string with bytes extracted from a line. */ /***********************************************************************/ void BINVAL::SetBinValue(void *p)
{
memcpy(Binp, p, Clen);
Len = Clen;
} // end of SetBinValue
/***********************************************************************/ /* BINVAL SetBinValue: fill string with len bytes. */ /***********************************************************************/ void BINVAL::SetBinValue(void* p, ulong len)
{
memcpy(Binp, p, len);
Len = 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 BINVAL::GetBinValue(void *buf, int buflen, bool go)
{ if (Len > buflen) returntrue; elseif (go) {
memset(buf, 0, buflen);
memcpy(buf, Binp, Len);
} // endif go
returnfalse;
} // end of GetBinValue
/***********************************************************************/ /* BINVAL ShowValue: get string representation of a binary value. */ /***********************************************************************/ int BINVAL::ShowValue(char *buf, int len)
{
memset(buf, 0, len + 1);
memcpy(buf, Binp, MY_MIN(len, Len)); return Len;
} // end of ShowValue
/***********************************************************************/ /* BINVAL GetCharString: get string representation of a binary value. */ /***********************************************************************/ char *BINVAL::GetCharString(char *)
{ if (!Chrp)
Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1);
snprintf(Chrp, Clen * 2 + 1, GetXfmt(), Len, Binp); return Chrp;
} // end of GetCharString
/***********************************************************************/ /* BINVAL compare value with another Value. */ /***********************************************************************/ bool BINVAL::IsEqual(PVAL vp, bool chktype)
{ if (this == vp) returntrue; elseif (chktype && Type != vp->GetType()) returnfalse; elseif (Null || vp->IsNull()) returnfalse; elseif (Len != vp->GetSize()) returnfalse;
for (int i = 0; i < Len; i++) if (v1[i] != v2[i]) returnfalse;
returntrue;
} // end of IsEqual
/***********************************************************************/ /* FormatValue: This function set vp (a STRING value) to the string */ /* constructed from its own value formatted using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ bool BINVAL::FormatValue(PVAL vp, PCSZ fmt)
{ char *buf = (char*)vp->GetTo_Val(); // Should be big enough int n = snprintf(buf, vp->GetValLen() + 1, fmt, Len, Binp);
return (n > vp->GetValLen());
} // end of FormatValue
/***********************************************************************/ /* BINVAL SetFormat function (used to set SELECT output format). */ /***********************************************************************/ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
{
fmt.Type[0] = 'B';
fmt.Length = Clen;
fmt.Prec = 0; returnfalse;
} // end of SetConstFormat
/* -------------------------- Class DTVAL ---------------------------- */
/***********************************************************************/ /* DTVAL public constructor for new void values. */ /***********************************************************************/
DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
: TYPVAL<dtval_timestamp_t>(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(int n) : TYPVAL<dtval_timestamp_t>(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, PCSZ 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; returnfalse;
} // end of SetFormat
/***********************************************************************/ /* Set format from the format of another date value. */ /***********************************************************************/ bool DTVAL::SetFormat(PGLOBAL g, PVAL valp)
{
DTVAL *vp;
Len = vp->Len;
Pdtp = vp->Pdtp;
Sdate = (char*)PlugSubAlloc(g, NULL, Len + 1);
DefYear = vp->DefYear; returnfalse;
} // 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(1))
htrc("DTVAL Shift=%d\n", Shift);
} // end of SetTimeShift
// Added by Alexander Barkov staticvoid 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;
mktime(tm); // set tm->tm_wday tm->yday fields to get proper day name (OB)
tm->tm_hour= ltime->hour;
tm->tm_min= ltime->minute;
tm->tm_sec= ltime->second;
} // end of TIME_to_localtime
// Added by Alexander Barkov staticstruct 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;
} // end of gmtime_mysql
/***********************************************************************/ /* 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) {
longlong n; for (n = 0; t < 0; n += 4)
t += FOURYEARS;
/***********************************************************************/ /* 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(2))
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) returntrue;
for (n = 0; t == -1 && n < 20; n++) {
ptm->tm_year += 4;
t = mktime_mysql(ptm);
} // endfor t
if (t == -1) returntrue;
if ((t -= (n * FOURYEARS)) > 2000000000) returntrue;
} // endif t
Tval= (dtval_timestamp_t) t;
if (trace(2))
htrc("MakeTime Ival=%lld\n", (longlong) Tval);
returnfalse;
} // 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(2)) // htrc("n=%d tm_year=%d\n", n, datm.tm_year);
break; case1: // 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(2)) // htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
break; case2: // 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(2)) // htrc("n=%d m=%d tm_year=%d tm_mon=%d\n", n, m, datm.tm_year, datm.tm_mon);
if (trace(2))
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) {
snprintf(g->Message, sizeof(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 (valp != this) { if (chktype && Type != valp->GetType()) returntrue;
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);
} elseif (valp->GetType() == TYPE_BIGINT &&
!(valp->GetBigintValue() % 1000)) { // Assuming that this timestamp is in milliseconds
SetValue((int)(valp->GetBigintValue() / 1000));
} else
SetValue(valp->GetBigintValue());
} else
Reset();
} // endif valp
returnfalse;
} // end of SetValue
/***********************************************************************/ /* SetValue: convert chars extracted from a line to date value. */ /***********************************************************************/ bool DTVAL::SetValue_char(constchar *p, int n)
{ bool rc= 0;
if (Pdtp) { constchar *p2; int ndv; int dval[6];
if (n > 0) { // Trim trailing blanks for (p2 = p + n -1; p < p2 && *p2 == ' '; p2--);
if ((rc = (n = (int)(p2 - p + 1)) > Len))
n = Len;
/***********************************************************************/ /* SetValue: convert a char string to date value. */ /***********************************************************************/ void DTVAL::SetValue_psz(PCSZ p)
{ if (Pdtp) { int ndv; int dval[6];
/***********************************************************************/ /* 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];
/***********************************************************************/ /* DTVAL SetValue: get date as an integer. */ /***********************************************************************/ void DTVAL::SetValue(dtval_timestamp_t n)
{
Tval = n;
//Null = false; ?????????????? return p;
} // end of GetCharString
/***********************************************************************/ /* DTVAL ShowValue: get string representation of a date value. */ /***********************************************************************/ int DTVAL::ShowValue(char *buf, int len)
{ int rv = 0;
if (Pdtp) { if (!Null) {
size_t n = 0, m = len + 1; struct tm tm, *ptm = GetGmTime(&tm);
#if0// 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 returnfalse;
} // end of WeekNum #endif// 0
/***********************************************************************/ /* FormatValue: This function set vp (a STRING value) to the string */ /* constructed from its own value formatted using the fmt format. */ /* This function assumes that the format matches the value type. */ /***********************************************************************/ bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
{ char *buf = (char*)vp->GetTo_Val(); // Should be big enough struct tm tm, *ptm = GetGmTime(&tm);
if (trace(2))
htrc("FormatValue: ptm=%p len=%d\n", ptm, vp->GetValLen());
if (ptm) {
size_t n = strftime(buf, vp->GetValLen(), fmt, ptm);
if (trace(2))
htrc("strftime: n=%d buf=%s\n", n, (n) ? buf : "???");
return (n == 0);
} else returntrue;
} // end of FormatValue
void DTVAL::SetBinValue(void* p)
{ #ifdefined(UNALIGNED_OK) // x86 can cast non-aligned memory directly
Tval = *(int *)p; #else int tmp;
memcpy(&tmp, p, sizeof(tmp));
Tval= tmp; #endif
Null = false;
} // end of SetBinValue
bool DTVAL::GetBinValue(void *buf, int buflen, bool go)
{ if (go) #ifdefined(UNALIGNED_OK) // x86 can cast non-aligned memory directly
*(int *)buf = (int) Tval; #else
{ int tmp= (int) Tval;
memcpy(buf, &tmp, sizeof(tmp));
} #endif
Null = false; returnfalse;
} // end of GetBinValue
/* -------------------------- End of Value --------------------------- */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.112 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.