/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include "function.h" #include "os.h" #include "texception.h" #include "taosdef.h" #include "tmsg.h" #include "tarray.h" #include "tbuffer.h" #include "tcompare.h" #include "thash.h" #include "texpr.h" #include "tvariant.h" #include "tdef.h" static void doExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)); void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)) { if (pNode == NULL) { return; } if (pNode->nodeType == TEXPR_BINARYEXPR_NODE || pNode->nodeType == TEXPR_UNARYEXPR_NODE) { doExprTreeDestroy(&pNode, fp); } taosMemoryFree(pNode); } static void doExprTreeDestroy(tExprNode **pExpr, void (*fp)(void *)) { if (*pExpr == NULL) { return; } taosMemoryFree(*pExpr); *pExpr = NULL; } bool exprTreeApplyFilter(tExprNode *pExpr, const void *pItem, SExprTraverseSupp *param) { #if 0 //non-leaf nodes, recursively traverse the expression tree in the post-root order if (pLeft->nodeType == TEXPR_BINARYEXPR_NODE && pRight->nodeType == TEXPR_BINARYEXPR_NODE) { if (pExpr->_node.optr == LOGIC_COND_TYPE_OR) { // or if (exprTreeApplyFilter(pLeft, pItem, param)) { return true; } // left child does not satisfy the query condition, try right child return exprTreeApplyFilter(pRight, pItem, param); } else { // and if (!exprTreeApplyFilter(pLeft, pItem, param)) { return false; } return exprTreeApplyFilter(pRight, pItem, param); } } // handle the leaf node param->setupInfoFn(pExpr, param->pExtInfo); return param->nodeFilterFn(pItem, pExpr->_node.info); #endif return 0; } // TODO: these three functions should be made global static void* exception_calloc(size_t nmemb, size_t size) { void* p = taosMemoryCalloc(nmemb, size); if (p == NULL) { THROW(TSDB_CODE_QRY_OUT_OF_MEMORY); } return p; } static void* exception_malloc(size_t size) { void* p = taosMemoryMalloc(size); if (p == NULL) { THROW(TSDB_CODE_QRY_OUT_OF_MEMORY); } return p; } static UNUSED_FUNC char* exception_strdup(const char* str) { char* p = strdup(str); if (p == NULL) { THROW(TSDB_CODE_QRY_OUT_OF_MEMORY); } return p; } 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++) { if (type == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(type)) { int64_t val = tbufReadInt64(&br); taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy)); } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { uint64_t val = tbufReadUint64(&br); taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy)); } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { int64_t val = tbufReadInt64(&br); taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy)); } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) { double val = tbufReadDouble(&br); taosHashPut(pObj, (char *)&val, sizeof(val), &dummy, sizeof(dummy)); } else if (type == TSDB_DATA_TYPE_BINARY) { size_t t = 0; const char *val = tbufReadBinary(&br, &t); taosHashPut(pObj, (char *)val, t, &dummy, sizeof(dummy)); } else if (type == TSDB_DATA_TYPE_NCHAR) { size_t t = 0; const char *val = tbufReadBinary(&br, &t); taosHashPut(pObj, (char *)val, t, &dummy, sizeof(dummy)); } } *q = (void *)pObj; } void convertFilterSetFromBinary(void **q, const char *buf, int32_t len, uint32_t tType) { SBufferReader br = tbufInitReader(buf, len, false); uint32_t sType = tbufReadUint32(&br); SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(tType), true, false); // taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(tType)); int dummy = -1; SVariant tmpVar = {0}; size_t t = 0; int32_t sz = tbufReadInt32(&br); void *pvar = NULL; int64_t val = 0; int32_t bufLen = 0; if (IS_NUMERIC_TYPE(sType)) { bufLen = 60; // The maximum length of string that a number is converted to. } else { bufLen = 128; } char *tmp = taosMemoryCalloc(1, bufLen * TSDB_NCHAR_SIZE); for (int32_t i = 0; i < sz; i++) { switch (sType) { case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_TINYINT: { *(uint8_t *)&val = (uint8_t)tbufReadInt64(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_SMALLINT: { *(uint16_t *)&val = (uint16_t)tbufReadInt64(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_INT: { *(uint32_t *)&val = (uint32_t)tbufReadInt64(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_UBIGINT: case TSDB_DATA_TYPE_BIGINT: { *(uint64_t *)&val = (uint64_t)tbufReadInt64(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_DOUBLE: { *(double *)&val = tbufReadDouble(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_FLOAT: { *(float *)&val = (float)tbufReadDouble(&br); t = sizeof(val); pvar = &val; break; } case TSDB_DATA_TYPE_BINARY: { pvar = (char *)tbufReadBinary(&br, &t); break; } case TSDB_DATA_TYPE_NCHAR: { pvar = (char *)tbufReadBinary(&br, &t); break; } default: taosHashCleanup(pObj); *q = NULL; return; } taosVariantCreateFromBinary(&tmpVar, (char *)pvar, t, sType); if (bufLen < t) { tmp = taosMemoryRealloc(tmp, t * TSDB_NCHAR_SIZE); bufLen = (int32_t)t; } switch (tType) { case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_TINYINT: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_SMALLINT: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_INT: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_UBIGINT: case TSDB_DATA_TYPE_BIGINT: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_DOUBLE: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_FLOAT: { if (taosVariantDump(&tmpVar, (char *)&val, tType, false)) { goto err_ret; } pvar = &val; t = sizeof(val); break; } case TSDB_DATA_TYPE_BINARY: { if (taosVariantDump(&tmpVar, tmp, tType, true)) { goto err_ret; } t = varDataLen(tmp); pvar = varDataVal(tmp); break; } case TSDB_DATA_TYPE_NCHAR: { if (taosVariantDump(&tmpVar, tmp, tType, true)) { goto err_ret; } t = varDataLen(tmp); pvar = varDataVal(tmp); break; } default: goto err_ret; } taosHashPut(pObj, (char *)pvar, t, &dummy, sizeof(dummy)); taosVariantDestroy(&tmpVar); memset(&tmpVar, 0, sizeof(tmpVar)); } *q = (void *)pObj; pObj = NULL; err_ret: taosVariantDestroy(&tmpVar); taosHashCleanup(pObj); taosMemoryFreeClear(tmp); }