diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-01-31 21:48:47 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-01-31 21:48:47 +0100 |
commit | 4b21cd21fef2763d757aa15681c9c9a7ed5db3c9 (patch) | |
tree | e9e233392b47f93de12cecce1f7f403ce26057b0 /storage/connect/value.cpp | |
parent | 0b049b40124d72d77c008d4441e4db2e77f0f127 (diff) | |
parent | a06624d61f36c70edd63adcfe2803bb7a8564de5 (diff) | |
download | mariadb-git-4b21cd21fef2763d757aa15681c9c9a7ed5db3c9.tar.gz |
Merge branch '10.0' into merge-wip
Diffstat (limited to 'storage/connect/value.cpp')
-rw-r--r-- | storage/connect/value.cpp | 294 |
1 files changed, 272 insertions, 22 deletions
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 81d00862703..1cc40473433 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -330,7 +330,7 @@ int ConvertType(int target, int type, CONV kind, bool match) /***********************************************************************/ /* AllocateConstant: allocates a constant Value. */ /***********************************************************************/ -PVAL AllocateValue(PGLOBAL g, void *value, short type) +PVAL AllocateValue(PGLOBAL g, void *value, short type, short prec) { PVAL valp; @@ -351,7 +351,7 @@ PVAL AllocateValue(PGLOBAL g, void *value, short type) valp = new(g) TYPVAL<longlong>(*(longlong*)value, TYPE_BIGINT); break; case TYPE_DOUBLE: - valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, 2); + valp = new(g) TYPVAL<double>(*(double *)value, TYPE_DOUBLE, prec); break; case TYPE_TINY: valp = new(g) TYPVAL<char>(*(char *)value, TYPE_TINY); @@ -434,6 +434,7 @@ 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 (newtype == TYPE_VOID) // Means allocate a value of the same type newtype = valp->GetType(); @@ -445,53 +446,55 @@ PVAL AllocateValue(PGLOBAL g, PVAL valp, int newtype, int uns) if ((sp = valp->GetCharString(p)) != p) strcpy (p, sp); - valp = new(g) TYPVAL<PSZ>(g, p, valp->GetValLen(), valp->GetValPrec()); + vp = 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); + vp = new(g) TYPVAL<ushort>(valp->GetUShortValue(), + TYPE_SHORT, 0, true); else - valp = new(g) TYPVAL<short>(valp->GetShortValue(), TYPE_SHORT); + vp = 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); + vp = new(g) TYPVAL<uint>(valp->GetUIntValue(), TYPE_INT, 0, true); else - valp = new(g) TYPVAL<int>(valp->GetIntValue(), TYPE_INT); + vp = 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); + vp = new(g) TYPVAL<ulonglong>(valp->GetUBigintValue(), + TYPE_BIGINT, 0, true); else - valp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT); + vp = new(g) TYPVAL<longlong>(valp->GetBigintValue(), TYPE_BIGINT); break; case TYPE_DATE: - valp = new(g) DTVAL(g, valp->GetIntValue()); + vp = new(g) DTVAL(g, valp->GetIntValue()); break; case TYPE_DOUBLE: - valp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE, - valp->GetValPrec()); + vp = new(g) TYPVAL<double>(valp->GetFloatValue(), TYPE_DOUBLE, + (uns) ? uns : valp->GetValPrec()); break; case TYPE_TINY: if (un) - valp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(), + vp = new(g) TYPVAL<uchar>(valp->GetUTinyValue(), TYPE_TINY, 0, true); else - valp = new(g) TYPVAL<char>(valp->GetTinyValue(), TYPE_TINY); + vp = 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; + + vp->SetNullable(valp->GetNullable()); + vp->SetNull(valp->IsNull()); + vp->SetGlobal(g); + return vp; } // end of AllocateValue /* -------------------------- Class VALUE ---------------------------- */ @@ -542,6 +545,15 @@ BYTE VALUE::TestValue(PVAL vp) return (n > 0) ? 0x04 : (n < 0) ? 0x02 : 0x01; } // end of TestValue +/***********************************************************************/ +/* Compute a function on a string. */ +/***********************************************************************/ +bool VALUE::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) + { + strcpy(g->Message, "Compute not implemented for this value type"); + return true; + } // end of Compute + /* -------------------------- Class TYPVAL ---------------------------- */ /***********************************************************************/ @@ -931,6 +943,202 @@ int TYPVAL<TYPE>::CompareValue(PVAL vp) } // 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;} + +template <> +ushort TYPVAL<ushort>::MinMaxVal(bool b) + {return (b) ? UINT_MAX16 : 0;} + +template <> +int TYPVAL<int>::MinMaxVal(bool b) + {return (b) ? INT_MAX32 : INT_MIN32;} + +template <> +uint TYPVAL<uint>::MinMaxVal(bool b) + {return (b) ? UINT_MAX32 : 0;} + +template <> +longlong TYPVAL<longlong>::MinMaxVal(bool b) + {return (b) ? INT_MAX64 : INT_MIN64;} + +template <> +ulonglong TYPVAL<ulonglong>::MinMaxVal(bool b) + {return (b) ? 0xFFFFFFFFFFFFFFFFLL : 0;} + +template <> +double TYPVAL<double>::MinMaxVal(bool b) + {assert(false); return 0.0;} + +template <> +char TYPVAL<char>::MinMaxVal(bool b) + {return (b) ? INT_MAX8 : INT_MIN8;} + +template <> +uchar TYPVAL<uchar>::MinMaxVal(bool b) + {return (b) ? UINT_MAX8 : 0;} + +/***********************************************************************/ +/* SafeAdd: adds a value and test whether overflow/underflow occured. */ +/***********************************************************************/ +template <class TYPE> +TYPE TYPVAL<TYPE>::SafeAdd(TYPE n1, TYPE n2) + { + PGLOBAL& g = Global; + TYPE n = n1 + n2; + + if ((n2 > 0) && (n < n1)) { + // Overflow + strcpy(g->Message, MSG(FIX_OVFLW_ADD)); + longjmp(g->jumper[g->jump_level], 138); + } else if ((n2 < 0) && (n > n1)) { + // Underflow + strcpy(g->Message, MSG(FIX_UNFLW_ADD)); + longjmp(g->jumper[g->jump_level], 138); + } // endif's n2 + + return n; + } // end of SafeAdd + +template <> +inline double TYPVAL<double>::SafeAdd(double n1, double n2) + { + return n1 + n2; + } // end of SafeAdd + +/***********************************************************************/ +/* SafeMult: multiply values and test whether overflow occured. */ +/***********************************************************************/ +template <class TYPE> +TYPE TYPVAL<TYPE>::SafeMult(TYPE n1, TYPE n2) + { + PGLOBAL& g = Global; + double n = (double)n1 * (double)n2; + + if (n > MinMaxVal(true)) { + // Overflow + strcpy(g->Message, MSG(FIX_OVFLW_TIMES)); + longjmp(g->jumper[g->jump_level], 138); + } else if (n < MinMaxVal(false)) { + // Underflow + strcpy(g->Message, MSG(FIX_UNFLW_TIMES)); + longjmp(g->jumper[g->jump_level], 138); + } // endif's n2 + + return (TYPE)n; + } // end of SafeMult + +template <> +inline double TYPVAL<double>::SafeMult(double n1, double n2) + { + return n1 * n2; + } // end of SafeMult + +/***********************************************************************/ +/* Compute defined functions for the type. */ +/***********************************************************************/ +template <class TYPE> +bool TYPVAL<TYPE>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) + { + bool rc = false; + TYPE val[2]; + + assert(np == 2); + + for (int i = 0; i < np; i++) + val[i] = GetTypedValue(vp[i]); + + switch (op) { + case OP_ADD: + Tval = SafeAdd(val[0], val[1]); + break; + case OP_MULT: + Tval = SafeMult(val[0], val[1]); + break; + case OP_DIV: + if (!val[1]) { + strcpy(g->Message, MSG(ZERO_DIVIDE)); + return true; + } // endif + + Tval = val[0] / val[1]; + break; + default: + rc = Compall(g, vp, np, op); + break; + } // endswitch op + + return rc; + } // end of Compute + +template <> +bool TYPVAL<double>::Compute(PGLOBAL g, PVAL *vp, int np, OPVAL op) + { + bool rc = false; + double val[2]; + + assert(np == 2); + + 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]) { + strcpy(g->Message, MSG(ZERO_DIVIDE)); + return true; + } // 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: +// sprintf(g->Message, MSG(BAD_EXP_OPER), op); + strcpy(g->Message, "Function not supported"); + return true; + } // endswitch op + + return false; + } // end of Compall + +/***********************************************************************/ /* 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. */ @@ -1410,6 +1618,45 @@ int TYPVAL<PSZ>::CompareValue(PVAL vp) } // 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; + + for (i = 0; i < np; i++) + p[i] = vp[i]->GetCharString(val[i]); + + switch (op) { + case OP_CNC: + assert(np == 1 || np == 2); + + if (np == 2) + strncpy(Strp, p[0], Len); + + if ((i = Len - (signed)strlen(Strp)) > 0) + strncat(Strp, p[np - 1], i); + + break; + case OP_MIN: + assert(np == 2); + strcpy(Strp, (strcmp(p[0], p[1]) < 0) ? p[0] : p[1]); + break; + case OP_MAX: + assert(np == 2); + strcpy(Strp, (strcmp(p[0], p[1]) > 0) ? p[0] : p[1]); + break; + default: +// sprintf(g->Message, MSG(BAD_EXP_OPER), op); + strcpy(g->Message, "Function not supported"); + return true; + } // endswitch op + + return false; + } // end of Compute + +/***********************************************************************/ /* 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. */ @@ -2187,10 +2434,11 @@ static void TIME_to_localtime(struct tm *tm, const MYSQL_TIME *ltime) 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 static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) @@ -2199,7 +2447,7 @@ static struct tm *gmtime_mysql(const time_t *timep, struct tm *tm) 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 */ @@ -2511,6 +2759,8 @@ char *DTVAL::ShowValue(char *buf, int len) if (!Null) { size_t m, n = 0; struct tm tm, *ptm = GetGmTime(&tm); + + if (Len < len) { p = buf; @@ -2596,7 +2846,7 @@ bool DTVAL::WeekNum(PGLOBAL g, int& nval) /***********************************************************************/ bool DTVAL::FormatValue(PVAL vp, char *fmt) { - char *buf = (char*)vp->GetTo_Val(); // Should be big enough + char *buf = (char*)vp->GetTo_Val(); // Should be big enough struct tm tm, *ptm = GetGmTime(&tm); if (trace > 1) |