From 3f361af7ce4937f02b939e19b0e17dd942045f99 Mon Sep 17 00:00:00 2001 From: Olivier Bertrand Date: Tue, 1 Apr 2014 18:14:57 +0200 Subject: [PATCH] - FIX MDEV-5989 (max(indexed) doesn't work) By implementing index_last modified: storage/connect/ha_connect.cc storage/connect/ha_connect.h storage/connect/xindex.cpp - Adding the TYPE_BIN Connect internal type (not tested and not used yet) modified: storage/connect/global.h storage/connect/value.cpp storage/connect/value.h --- storage/connect/global.h | 1 + storage/connect/ha_connect.cc | 13 +- storage/connect/ha_connect.h | 5 +- storage/connect/value.cpp | 431 +++++++++++++++++++++++++++++++++- storage/connect/value.h | 60 ++++- storage/connect/xindex.cpp | 11 + 6 files changed, 512 insertions(+), 9 deletions(-) diff --git a/storage/connect/global.h b/storage/connect/global.h index 8bccd742a64..c0746e37db7 100644 --- a/storage/connect/global.h +++ b/storage/connect/global.h @@ -84,6 +84,7 @@ #define TYPE_LIST 6 #define TYPE_INT 7 #define TYPE_DECIM 9 +#define TYPE_BIN 10 #if defined(OS32) #define SYS_STAMP "OS32" diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 2dd90b99240..160080fd5e0 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2482,7 +2482,6 @@ int ha_connect::index_first(uchar *buf) } // end of index_first -#ifdef NOT_USED /** @brief index_last() asks for the last key in the index. @@ -2496,9 +2495,15 @@ int ha_connect::index_first(uchar *buf) int ha_connect::index_last(uchar *buf) { DBUG_ENTER("ha_connect::index_last"); - DBUG_RETURN(HA_ERR_WRONG_COMMAND); -} -#endif // NOT_USED + int rc; + + if (indexing <= 0) { + rc= HA_ERR_INTERNAL_ERROR; + } else + rc= ReadIndexed(buf, OP_LAST); + + DBUG_RETURN(rc); +} // end of index_last /****************************************************************************/ diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h index f277209a78c..79f4a2e734a 100644 --- a/storage/connect/ha_connect.h +++ b/storage/connect/ha_connect.h @@ -241,7 +241,8 @@ public: */ ulong index_flags(uint inx, uint part, bool all_parts) const { - return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER | HA_KEYREAD_ONLY; + return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER + | HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR; } // end of index_flags /** @brief @@ -416,7 +417,7 @@ const char *GetValStr(OPVAL vop, bool neg); We implement this in ha_connect.cc. It's not an obligatory method; skip it and and MySQL will treat it as not implemented. */ -//int index_last(uchar *buf); + int index_last(uchar *buf); /* Index condition pushdown implementation */ //Item *idx_cond_push(uint keyno, Item* idx_cond); diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp index 0c93fed520a..f915f9e9c98 100644 --- a/storage/connect/value.cpp +++ b/storage/connect/value.cpp @@ -1,5 +1,5 @@ /************* Value C++ Functions Source Code File (.CPP) *************/ -/* Name: VALUE.CPP Version 2.4 */ +/* Name: VALUE.CPP Version 2.5 */ /* */ /* (C) Copyright to the author Olivier BERTRAND 2001-2014 */ /* */ @@ -157,6 +157,7 @@ PSZ GetTypeName(int type) case TYPE_DOUBLE: name = "DOUBLE"; break; case TYPE_TINY: name = "TINY"; break; case TYPE_DECIM: name = "DECIMAL"; break; + case TYPE_BIN: name = "BINARY"; break; default: name = "UNKNOWN"; break; } // endswitch type @@ -170,6 +171,7 @@ int GetTypeSize(int type, int 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; @@ -199,6 +201,7 @@ char *GetFormatType(int type) case TYPE_DATE: c = "D"; break; case TYPE_TINY: c = "T"; break; case TYPE_DECIM: c = "M"; break; + case TYPE_BIN: c = "B"; break; } // endswitch type return c; @@ -220,6 +223,7 @@ int GetFormatType(char c) case 'D': type = TYPE_DATE; break; case 'T': type = TYPE_TINY; break; case 'M': type = TYPE_DECIM; break; + case 'B': type = TYPE_BIN; break; } // endswitch type return type; @@ -272,6 +276,7 @@ const char *GetFmt(int type, bool un) 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; default: fmt = (un) ? "%u" : "%d"; break; } // endswitch Type @@ -365,6 +370,9 @@ PVAL AllocateValue(PGLOBAL g, int type, int len, int prec, case TYPE_DECIM: valp = new(g) DECVAL(g, (PSZ)NULL, len, prec, uns); break; + case TYPE_BIN: + valp = new(g) BINVAL(g, (void*)NULL, len, prec); + break; default: sprintf(g->Message, MSG(BAD_VALUE_TYPE), type); return NULL; @@ -403,6 +411,7 @@ const char *VALUE::GetXfmt(void) 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; default: fmt = (Unsigned) ? "%*u" : "%*d"; break; } // endswitch Type @@ -1481,6 +1490,426 @@ bool DECVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt) } // end of SetConstFormat #endif // 0 +/* -------------------------- 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, Len); + + 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) + return false; + + return true; + } // 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; + else if (Len >= 4) + return (double)(*(float*)Binp); + else + return 0.0; + +} // end of GetFloatValue + +/***********************************************************************/ +/* BINVAL SetValue: copy the value of another Value object. */ +/***********************************************************************/ +bool BINVAL::SetValue_pval(PVAL valp, bool chktype) + { + if (chktype && (valp->GetType() != Type || valp->GetSize() > Clen)) + return true; + + bool rc = false; + + if (!(Null = valp->IsNull() && Nullable)) { + if ((rc = (Len = valp->GetSize()) > Clen)) + Len = Clen; + + memcpy(Binp, valp->GetTo_Val(), Len); + } else + Reset(); + + return rc; + } // end of SetValue_pval + +/***********************************************************************/ +/* BINVAL SetValue: fill value with chars extracted from a line. */ +/***********************************************************************/ +bool BINVAL::SetValue_char(char *p, int n) + { + bool rc; + + if (p) { + rc = n > Clen; + Len = min(n, Clen); + memcpy(Binp, p, Len); + Null = false; + } else { + rc = false; + Reset(); + Null = Nullable; + } // endif p + + return rc; + } // end of SetValue_char + +/***********************************************************************/ +/* BINVAL SetValue: fill value with another string. */ +/***********************************************************************/ +void BINVAL::SetValue_psz(PSZ s) + { + if (s) { + Len = min(Clen, (signed)strlen(s)); + memcpy(Binp, s, Len); + Null = false; + } else { + Reset(); + Null = Nullable; + } // endif s + + } // end of SetValue_psz + +/***********************************************************************/ +/* 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; + } else if (vp != Binp) { + if (blk->GetType() == TYPE_STRING) + Len = strlen((char*)vp); + else + Len = blk->GetVlen(); + + Len = min(Clen, Len); + memcpy(Binp, vp, Len); + Null = false; + } // endif vp + + } // end of SetValue_pvblk + +/***********************************************************************/ +/* BINVAL SetValue: get the binary representation of an integer. */ +/***********************************************************************/ +void BINVAL::SetValue(int n) + { + if (Clen >= 4) { + *((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) { + *((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) { + *((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) { + *((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) { + *((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) { + *((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 (Clen >= 8) { + *((double*)Binp) = n; + Len = 8; + } else if (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) + { + *((char*)Binp) = c; + Len = 1; + } // end of SetValue + +/***********************************************************************/ +/* BINVAL SetValue: get the binary representation of a tiny int. */ +/***********************************************************************/ +void BINVAL::SetValue(uchar c) + { + *((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); + } // 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) + return true; + else if (go) { + memset(buf, 0, buflen); + memcpy(buf, Binp, Len); + } // endif go + + return false; + } // end of GetBinValue + +/***********************************************************************/ +/* BINVAL ShowValue: get string representation of a binary value. */ +/***********************************************************************/ +char *BINVAL::ShowValue(char *buf, int len) + { + int n = min(Len, len / 2); + + sprintf(buf, GetXfmt(), n, Binp); + return buf; + } // end of ShowValue + +/***********************************************************************/ +/* BINVAL GetCharString: get string representation of a binary value. */ +/***********************************************************************/ +char *BINVAL::GetCharString(char *p) + { + if (!Chrp) + Chrp = (char*)PlugSubAlloc(Global, NULL, Clen * 2 + 1); + + sprintf(Chrp, GetXfmt(), Len, Binp); + return Chrp; + } // end of GetCharString + +/***********************************************************************/ +/* BINVAL compare value with another Value. */ +/***********************************************************************/ +bool BINVAL::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; + else if (Len != vp->GetSize()) + return false; + + char *v1 = (char*)Binp; + char *v2 = (char*)vp->GetTo_Val(); + + for (int i = 0; i < Len; i++) + if (v1[i] != v2[i]) + return false; + + return true; + } // end of IsEqual + +/***********************************************************************/ +/* 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 BINVAL::FormatValue(PVAL vp, char *fmt) + { + char *buf = (char*)vp->GetTo_Val(); // Should be big enough + int n = sprintf(buf, fmt, Len, Binp); + + return (n > vp->GetValLen()); + } // end of FormatValue + +/***********************************************************************/ +/* BINVAL SetFormat function (used to set SELECT output format). */ +/***********************************************************************/ +bool BINVAL::SetConstFormat(PGLOBAL g, FORMAT& fmt) + { + fmt.Type[0] = 'B'; + fmt.Length = Clen; + fmt.Prec = 0; + return false; + } // end of SetConstFormat + /* -------------------------- Class DTVAL ---------------------------- */ /***********************************************************************/ diff --git a/storage/connect/value.h b/storage/connect/value.h index a5eb2c886cf..56992d5bc26 100644 --- a/storage/connect/value.h +++ b/storage/connect/value.h @@ -1,7 +1,7 @@ /**************** Value H Declares Source Code File (.H) ***************/ -/* Name: VALUE.H Version 2.0 */ +/* Name: VALUE.H Version 2.1 */ /* */ -/* (C) Copyright to the author Olivier BERTRAND 2001-2013 */ +/* (C) Copyright to the author Olivier BERTRAND 2001-2014 */ /* */ /* This file contains the VALUE and derived classes declares. */ /***********************************************************************/ @@ -276,6 +276,62 @@ class DllExport DECVAL: public TYPVAL { // Members }; // end of class DECVAL +/***********************************************************************/ +/* Specific BINARY class. */ +/***********************************************************************/ +class DllExport BINVAL: public VALUE { + public: + // Constructors +//BINVAL(void *p); + BINVAL(PGLOBAL g, void *p, int cl, int n); + + // Implementation + virtual bool IsTypeNum(void) {return false;} + virtual bool IsZero(void); + virtual void Reset(void); + virtual int GetValLen(void) {return Clen;}; + virtual int GetValPrec() {return 0;} + virtual int GetSize(void) {return Len;} + virtual PSZ GetCharValue(void) {return (PSZ)Binp;} + virtual char GetTinyValue(void); + virtual uchar GetUTinyValue(void); + virtual short GetShortValue(void); + virtual ushort GetUShortValue(void); + virtual int GetIntValue(void); + virtual uint GetUIntValue(void); + virtual longlong GetBigintValue(void); + virtual ulonglong GetUBigintValue(void); + virtual double GetFloatValue(void); + virtual void *GetTo_Val(void) {return Binp;} + + // Methods + virtual bool SetValue_pval(PVAL valp, bool chktype); + virtual bool SetValue_char(char *p, int n); + virtual void SetValue_psz(PSZ s); + virtual void SetValue_pvblk(PVBLK blk, int n); + virtual void SetValue(char c); + virtual void SetValue(uchar c); + virtual void SetValue(short i); + virtual void SetValue(ushort i); + virtual void SetValue(int n); + virtual void SetValue(uint n); + virtual void SetValue(longlong n); + virtual void SetValue(ulonglong n); + virtual void SetValue(double f); + virtual void SetBinValue(void *p); + virtual bool GetBinValue(void *buf, int buflen, bool go); + virtual char *ShowValue(char *buf, int); + virtual char *GetCharString(char *p); + virtual bool IsEqual(PVAL vp, bool chktype); + virtual bool FormatValue(PVAL vp, char *fmt); + virtual bool SetConstFormat(PGLOBAL, FORMAT&); + + // Members + void *Binp; + char *Chrp; + int Len; + }; // end of class BINVAL + /***********************************************************************/ /* Class DTVAL: represents a time stamp value. */ /***********************************************************************/ diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp index e3321fd14a9..133f4546a56 100755 --- a/storage/connect/xindex.cpp +++ b/storage/connect/xindex.cpp @@ -1627,6 +1627,12 @@ int XINDEX::Fetch(PGLOBAL g) Op = (Mul || Nval < Nk) ? OP_NXTDIF : OP_NEXT; break; + case OP_LAST: // Read last key + for (Cur_K = Num_K - 1, kp = To_KeyCol; kp; kp = kp->Next) + kp->Val_K = kp->Kblp->GetNval() - 1; + + Op = OP_NEXT; + break; default: // Should be OP_EQ // if (Tbxp->Key_Rank < 0) { /***************************************************************/ @@ -1938,6 +1944,11 @@ int XINDXS::Fetch(PGLOBAL g) To_KeyCol->Val_K = Cur_K = 0; Op = (Mul) ? OP_NXTDIF : OP_NEXT; break; + case OP_LAST: // Read first + Cur_K = Num_K - 1; + To_KeyCol->Val_K = To_KeyCol->Kblp->GetNval() - 1; + Op = OP_NEXT; + break; default: // Should OP_EQ /*****************************************************************/ /* Look for the first key equal to the link column values */