From 01f52f01fa674cda100f2a0f00720f086adb8506 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Wed, 9 Jun 2021 21:21:46 +0800 Subject: [PATCH] [TD-4614] add equal func to hashTable --- src/client/src/tscSQLParser.c | 6 ++-- src/common/src/texpr.c | 3 ++ src/query/src/qFilterfunc.c | 2 +- src/util/inc/hash.h | 10 +++++++ src/util/inc/hashfunc.h | 9 +++++- src/util/src/hash.c | 20 ++++++++----- src/util/src/thashutil.c | 56 +++++++++++++++++++++++++++++++---- 7 files changed, 88 insertions(+), 18 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index e7a821ddf4..0e2f4829e0 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -153,9 +153,9 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType) if (!pList || pList->size <= 0) { return ret; } - if (colType == TSDB_DATA_TYPE_DOUBLE || colType == TSDB_DATA_TYPE_FLOAT) { - return ret; - } + //if (colType == TSDB_DATA_TYPE_DOUBLE || colType == TSDB_DATA_TYPE_FLOAT) { + // return ret; + //} tSqlExprItem* item = (tSqlExprItem *)taosArrayGet(pList, 0); int32_t firstTokenType = item->pNode->token.type; diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index 6fa4d68734..0e9ec053cc 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -470,6 +470,9 @@ void buildFilterSetFromBinary(void **q, const char *buf, int32_t len) { SBufferReader br = tbufInitReader(buf, len, false); uint32_t type = tbufReadUint32(&br); SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false); + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(type)); + int dummy = -1; int32_t sz = tbufReadInt32(&br); for (int32_t i = 0; i < sz; i++) { diff --git a/src/query/src/qFilterfunc.c b/src/query/src/qFilterfunc.c index 663f8814a0..7e8dd66ed1 100644 --- a/src/query/src/qFilterfunc.c +++ b/src/query/src/qFilterfunc.c @@ -262,7 +262,7 @@ bool inOperator(SColumnFilterElem *pFilter, const char* minval, const char* maxv return NULL != taosHashGet((SHashObj *)pFilter->q, (char *)&minv, sizeof(minv)); } return true; - } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_DOUBLE) { + } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) { double v; GET_TYPED_DATA(v, double, type, minval); return NULL != taosHashGet((SHashObj *)pFilter->q, (char *)&v, sizeof(v)); diff --git a/src/util/inc/hash.h b/src/util/inc/hash.h index cd4850e47e..c37426069c 100644 --- a/src/util/inc/hash.h +++ b/src/util/inc/hash.h @@ -61,6 +61,7 @@ typedef struct SHashObj { size_t size; // number of elements in hash table _hash_fn_t hashFp; // hash function _hash_free_fn_t freeFp; // hash node free callback function + _equal_fn_t equalFp; // equal function SRWLatch lock; // read-write spin lock SHashLockTypeE type; // lock type @@ -78,6 +79,15 @@ typedef struct SHashObj { */ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type); + +/** + * set equal func of the hash table + * @param pHashObj + * @param equalFp + * @return + */ +void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp); + /** * return the size of hash table * @param pHashObj diff --git a/src/util/inc/hashfunc.h b/src/util/inc/hashfunc.h index 047f1889d7..a9563d0394 100644 --- a/src/util/inc/hashfunc.h +++ b/src/util/inc/hashfunc.h @@ -20,6 +20,8 @@ typedef uint32_t (*_hash_fn_t)(const char *, uint32_t); +typedef int32_t (*_equal_fn_t)(const void *a, const void *b, size_t sz); + /** * murmur hash algorithm * @key usually string @@ -36,9 +38,14 @@ uint32_t MurmurHash3_32(const char *key, uint32_t len); * @return */ uint32_t taosIntHash_32(const char *key, uint32_t len); - uint32_t taosIntHash_64(const char *key, uint32_t len); + +int32_t taosFloatEqual(const void *a, const void *b, size_t sz); +int32_t taosDoubleEqual(const void *a,const void *b, size_t sz); + _hash_fn_t taosGetDefaultHashFunction(int32_t type); +_equal_fn_t taosGetDefaultEqualFunction(int32_t type); + #endif //TDENGINE_HASHUTIL_H diff --git a/src/util/src/hash.c b/src/util/src/hash.c index ede3e1e4ce..5b3218382f 100644 --- a/src/util/src/hash.c +++ b/src/util/src/hash.c @@ -73,10 +73,10 @@ static FORCE_INLINE int32_t taosHashCapacity(int32_t length) { return i; } -static FORCE_INLINE SHashNode *doSearchInEntryList(SHashEntry *pe, const void *key, size_t keyLen, uint32_t hashVal) { +static FORCE_INLINE SHashNode *doSearchInEntryList(SHashObj *pHashObj, SHashEntry *pe, const void *key, size_t keyLen, uint32_t hashVal) { SHashNode *pNode = pe->next; while (pNode) { - if ((pNode->keyLen == keyLen) && (memcmp(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) { + if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) { assert(pNode->hashVal == hashVal); break; } @@ -165,8 +165,8 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTyp // the max slots is not defined by user pHashObj->capacity = taosHashCapacity((int32_t)capacity); assert((pHashObj->capacity & (pHashObj->capacity - 1)) == 0); - - pHashObj->hashFp = fn; + pHashObj->equalFp = memcmp; + pHashObj->hashFp = fn; pHashObj->type = type; pHashObj->enableUpdate = update; @@ -189,6 +189,12 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTyp return pHashObj; } +void taosHashSetEqualFp(SHashObj *pHashObj, _equal_fn_t fp) { + if (pHashObj != NULL && fp != NULL) { + pHashObj->equalFp = fp; + } +} + int32_t taosHashGetSize(const SHashObj *pHashObj) { return (int32_t)((pHashObj == NULL) ? 0 : pHashObj->size); } int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *data, size_t size) { @@ -223,7 +229,7 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, void *da SHashNode* prev = NULL; while (pNode) { - if ((pNode->keyLen == keyLen) && (memcmp(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) { + if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) { assert(pNode->hashVal == hashVal); break; } @@ -306,7 +312,7 @@ void* taosHashGetClone(SHashObj *pHashObj, const void *key, size_t keyLen, void assert(pe->next == NULL); } - SHashNode *pNode = doSearchInEntryList(pe, key, keyLen, hashVal); + SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal); if (pNode != NULL) { if (fp != NULL) { fp(GET_HASH_NODE_DATA(pNode)); @@ -362,7 +368,7 @@ int32_t taosHashRemoveWithData(SHashObj *pHashObj, const void *key, size_t keyLe SHashNode *prevNode = NULL; while (pNode) { - if ((pNode->keyLen == keyLen) && (memcmp(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) + if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) break; prevNode = pNode; diff --git a/src/util/src/thashutil.c b/src/util/src/thashutil.c index 3634dca4c0..a0f3e58577 100644 --- a/src/util/src/thashutil.c +++ b/src/util/src/thashutil.c @@ -16,6 +16,7 @@ #include "os.h" #include "hashfunc.h" #include "tutil.h" +#include "tcompare.h" #define ROTL32(x, r) ((x) << (r) | (x) >> (32u - (r))) @@ -78,7 +79,28 @@ uint32_t MurmurHash3_32(const char *key, uint32_t len) { uint32_t taosIntHash_32(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint32_t *)key; } uint32_t taosIntHash_16(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint16_t *)key; } uint32_t taosIntHash_8(const char *key, uint32_t UNUSED_PARAM(len)) { return *(uint8_t *)key; } - +uint32_t taosFloatHash(const char *key, uint32_t UNUSED_PARAM(len)) { + float f = GET_FLOAT_VAL(key); + if (isnan(f)) { + return 0x7fc00000; + } + if (fabs(f - 0.0) < FLT_EPSILON) { + return 0; + } + + return *(uint32_t *)(key); +} +uint32_t taosDoubleHash(const char *key, uint32_t UNUSED_PARAM(len)) { + double f = GET_DOUBLE_VAL(key); + if (isnan(f)) { + return 0x7fc00000; + } + if (fabs(f - 0.0) < FLT_EPSILON) { + return 0; + } + return *(uint32_t *)(key); + +} uint32_t taosIntHash_64(const char *key, uint32_t UNUSED_PARAM(len)) { uint64_t val = *(uint64_t *)key; @@ -92,13 +114,35 @@ _hash_fn_t taosGetDefaultHashFunction(int32_t type) { _hash_fn_t fn = NULL; switch(type) { case TSDB_DATA_TYPE_TIMESTAMP: - case TSDB_DATA_TYPE_BIGINT: fn = taosIntHash_64;break; - case TSDB_DATA_TYPE_BINARY: fn = MurmurHash3_32;break; - case TSDB_DATA_TYPE_INT: fn = taosIntHash_32; break; + case TSDB_DATA_TYPE_BIGINT: fn = taosIntHash_64;break; + case TSDB_DATA_TYPE_BINARY: fn = MurmurHash3_32;break; + case TSDB_DATA_TYPE_NCHAR: fn = MurmurHash3_32;break; + case TSDB_DATA_TYPE_INT: fn = taosIntHash_32; break; case TSDB_DATA_TYPE_SMALLINT: fn = taosIntHash_16; break; - case TSDB_DATA_TYPE_TINYINT: fn = taosIntHash_8; break; + case TSDB_DATA_TYPE_TINYINT: fn = taosIntHash_8; break; + case TSDB_DATA_TYPE_FLOAT: fn = taosFloatHash; break; + case TSDB_DATA_TYPE_DOUBLE: fn = taosDoubleHash; break; default: fn = taosIntHash_32;break; } return fn; -} \ No newline at end of file +} + +int32_t taosFloatEqual(const void *a, const void *b, size_t UNUSED_PARAM(sz)) { + return getComparFunc(TSDB_DATA_TYPE_FLOAT, -1)(a, b); +} + +int32_t taosDoubleEqual(const void *a, const void *b, size_t UNUSED_PARAM(sz)) { + return getComparFunc(TSDB_DATA_TYPE_DOUBLE, -1)(a, b); +} + +_equal_fn_t taosGetDefaultEqualFunction(int32_t type) { + _equal_fn_t fn = NULL; + switch (type) { + case TSDB_DATA_TYPE_FLOAT: fn = taosFloatEqual; break; + case TSDB_DATA_TYPE_DOUBLE: fn = taosDoubleEqual; break; + default: fn = memcmp; break; + } + return fn; + +} -- GitLab