Merge remote-tracking branch 'origin/3.0' into fix/valgrind
This commit is contained in:
commit
9423000143
|
@ -71,8 +71,8 @@ ELSE ()
|
|||
ENDIF ()
|
||||
|
||||
IF (${SANITIZER} MATCHES "true")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -static-libasan -g3")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -static-libasan -g3")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -static-libasan -g3")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -static-libasan -g3")
|
||||
MESSAGE(STATUS "Will compile with Address Sanitizer!")
|
||||
ELSE ()
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3")
|
||||
|
|
|
@ -1352,7 +1352,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
int32_t code;
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
char tbFName[TSDB_TABLE_FNAME_LEN];
|
||||
int32_t sversion;
|
||||
int32_t tversion;
|
||||
} SResReadyRsp;
|
||||
|
@ -2524,7 +2524,7 @@ static FORCE_INLINE void* tDecodeSMqDataBlkRsp(const void* buf, SMqDataBlkRsp* p
|
|||
buf = taosDecodeFixedI32(buf, &pRsp->skipLogNum);
|
||||
buf = taosDecodeFixedI32(buf, &pRsp->blockNum);
|
||||
pRsp->blockData = taosArrayInit(pRsp->blockNum, sizeof(void*));
|
||||
pRsp->blockDataLen = taosArrayInit(pRsp->blockNum, sizeof(void*));
|
||||
pRsp->blockDataLen = taosArrayInit(pRsp->blockNum, sizeof(int32_t));
|
||||
pRsp->blockTbName = taosArrayInit(pRsp->blockNum, sizeof(void*));
|
||||
pRsp->blockSchema = taosArrayInit(pRsp->blockNum, sizeof(void*));
|
||||
if (pRsp->blockNum != 0) {
|
||||
|
|
|
@ -228,23 +228,23 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
|
|||
taosPrintLog("QRY ", DEBUG_INFO, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define qDebug(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLog("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
#define qDebug(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLog("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define qTrace(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_TRACE) { \
|
||||
taosPrintLog("QRY ", DEBUG_TRACE, qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
#define qTrace(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_TRACE) { \
|
||||
taosPrintLog("QRY ", DEBUG_TRACE, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define qDebugL(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLongString("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
#define qDebugL(...) \
|
||||
do { \
|
||||
if (qDebugFlag & DEBUG_DEBUG) { \
|
||||
taosPrintLongString("QRY ", DEBUG_DEBUG, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define QRY_ERR_RET(c) \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -972,9 +972,10 @@ SOperatorInfo* createStreamScanOperatorInfo(void* streamReadHandle, void* pDataR
|
|||
}
|
||||
|
||||
pInfo->primaryTsIndex = 0; // TODO(liuyao) get it from physical plan
|
||||
pInfo->pUpdateInfo = updateInfoInitP(&pSTInfo->interval, 10000); // TODO(liuyao) get watermark from physical plan
|
||||
if (pInfo->pUpdateInfo == NULL) {
|
||||
goto _error;
|
||||
if (pSTInfo->interval.interval > 0) {
|
||||
pInfo->pUpdateInfo = updateInfoInitP(&pSTInfo->interval, 10000); // TODO(liuyao) get watermark from physical plan
|
||||
} else {
|
||||
pInfo->pUpdateInfo = NULL;
|
||||
}
|
||||
|
||||
pInfo->readHandle = *pHandle;
|
||||
|
|
|
@ -241,7 +241,7 @@ alter_table_clause(A) ::=
|
|||
alter_table_clause(A) ::=
|
||||
full_table_name(B) RENAME TAG column_name(C) column_name(D). { A = createAlterTableRenameCol(pCxt, B, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &C, &D); }
|
||||
alter_table_clause(A) ::=
|
||||
full_table_name(B) SET TAG column_name(C) NK_EQ literal(D). { A = createAlterTableSetTag(pCxt, B, &C, releaseRawExprNode(pCxt, D)); }
|
||||
full_table_name(B) SET TAG column_name(C) NK_EQ signed_literal(D). { A = createAlterTableSetTag(pCxt, B, &C, D); }
|
||||
|
||||
%type multi_create_clause { SNodeList* }
|
||||
%destructor multi_create_clause { nodesDestroyList($$); }
|
||||
|
@ -448,7 +448,7 @@ agg_func_opt(A) ::= AGGREGATE.
|
|||
%type bufsize_opt { int32_t }
|
||||
%destructor bufsize_opt { }
|
||||
bufsize_opt(A) ::= . { A = 0; }
|
||||
bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A = strtol(B.z, NULL, 10); }
|
||||
bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A = taosStr2Int32(B.z, NULL, 10); }
|
||||
|
||||
/************************************************ create/drop stream **************************************************/
|
||||
cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A)
|
||||
|
|
|
@ -694,66 +694,110 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
|||
return translateValueImpl(pCxt, pVal, pVal->node.resType);
|
||||
}
|
||||
|
||||
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
if (nodesIsUnaryOp(pOp)) {
|
||||
if (OP_TYPE_MINUS == pOp->opType) {
|
||||
if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
|
||||
} else {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
static bool isMultiResFunc(SNode* pNode) {
|
||||
if (NULL == pNode) {
|
||||
return false;
|
||||
}
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (nodesIsArithmeticOp(pOp)) {
|
||||
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type ||
|
||||
TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if (QUERY_NODE_FUNCTION != nodeType(pNode) || !fmIsMultiResFunc(((SFunctionNode*)pNode)->funcId)) {
|
||||
return false;
|
||||
}
|
||||
SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
|
||||
if (LIST_LENGTH(pParameterList) > 1) {
|
||||
return true;
|
||||
}
|
||||
SNode* pParam = nodesListGetNode(pParameterList, 0);
|
||||
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
|
||||
}
|
||||
|
||||
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
|
||||
} else {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
|
||||
}
|
||||
} else if (nodesIsComparisonOp(pOp)) {
|
||||
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
|
||||
((SExprNode*)pOp->pRight)->resType = ((SExprNode*)pOp->pLeft)->resType;
|
||||
}
|
||||
if (nodesIsRegularOp(pOp)) {
|
||||
if (!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
static EDealRes translateUnaryOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
if (OP_TYPE_MINUS == pOp->opType) {
|
||||
if (!IS_MATHABLE_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
|
||||
} else {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
||||
} else if (nodesIsJsonOp(pOp)) {
|
||||
if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) {
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateArithmeticOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type ||
|
||||
TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && (IS_VAR_DATA_TYPE(rdt.type) || IS_FLOAT_TYPE(rdt.type))) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && (IS_VAR_DATA_TYPE(ldt.type) || IS_FLOAT_TYPE(ldt.type)))) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
|
||||
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && IS_INTEGER_TYPE(rdt.type)) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && IS_INTEGER_TYPE(ldt.type)) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_BOOL == rdt.type) ||
|
||||
(TSDB_DATA_TYPE_TIMESTAMP == rdt.type && TSDB_DATA_TYPE_BOOL == ldt.type)) {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes;
|
||||
} else {
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateComparisonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
|
||||
((SExprNode*)pOp->pRight)->resType = ((SExprNode*)pOp->pLeft)->resType;
|
||||
}
|
||||
if (nodesIsRegularOp(pOp)) {
|
||||
if (!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_JSON].bytes;
|
||||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateJsonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_JSON != ldt.type || TSDB_DATA_TYPE_BINARY != rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
pOp->node.resType.type = TSDB_DATA_TYPE_JSON;
|
||||
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_JSON].bytes;
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
if (isMultiResFunc(pOp->pLeft)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
if (isMultiResFunc(pOp->pRight)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
|
||||
if (nodesIsUnaryOp(pOp)) {
|
||||
return translateUnaryOperator(pCxt, pOp);
|
||||
} else if (nodesIsArithmeticOp(pOp)) {
|
||||
return translateArithmeticOperator(pCxt, pOp);
|
||||
} else if (nodesIsComparisonOp(pOp)) {
|
||||
return translateComparisonOperator(pCxt, pOp);
|
||||
} else if (nodesIsJsonOp(pOp)) {
|
||||
return translateJsonOperator(pCxt, pOp);
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
@ -808,6 +852,13 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
|
|||
}
|
||||
|
||||
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
SNode* pParam = NULL;
|
||||
FOREACH(pParam, pFunc->pParameterList) {
|
||||
if (isMultiResFunc(pParam)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)pParam)->aliasName);
|
||||
}
|
||||
}
|
||||
|
||||
SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog,
|
||||
.pRpc = pCxt->pParseCxt->pTransporter,
|
||||
.pMgmtEps = &pCxt->pParseCxt->mgmtEpSet,
|
||||
|
@ -926,9 +977,10 @@ typedef struct SCheckExprForGroupByCxt {
|
|||
STranslateContext* pTranslateCxt;
|
||||
int32_t selectFuncNum;
|
||||
bool hasSelectValFunc;
|
||||
bool hasOtherAggFunc;
|
||||
} SCheckExprForGroupByCxt;
|
||||
|
||||
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSelectValFunc, SNode** pNode) {
|
||||
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
@ -942,9 +994,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSel
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
*pNode = (SNode*)pFunc;
|
||||
if (NULL != pHasSelectValFunc) {
|
||||
*pHasSelectValFunc = true;
|
||||
}
|
||||
} else {
|
||||
nodesDestroyNode(pFunc);
|
||||
}
|
||||
|
@ -956,8 +1005,12 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
pCxt->selectFuncNum += isSelectFunc(*pNode) ? 1 : 0;
|
||||
if (pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) {
|
||||
if (isSelectFunc(*pNode)) {
|
||||
++(pCxt->selectFuncNum);
|
||||
} else if (isAggFunc(*pNode)) {
|
||||
pCxt->hasOtherAggFunc = true;
|
||||
}
|
||||
if ((pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) || (pCxt->hasOtherAggFunc && pCxt->hasSelectValFunc)) {
|
||||
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
|
||||
}
|
||||
if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
|
@ -970,10 +1023,11 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
}
|
||||
}
|
||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
if (pCxt->selectFuncNum > 1) {
|
||||
if (pCxt->selectFuncNum > 1 || pCxt->hasOtherAggFunc) {
|
||||
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
|
||||
} else {
|
||||
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, &pCxt->hasSelectValFunc, pNode);
|
||||
pCxt->hasSelectValFunc = true;
|
||||
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, pNode);
|
||||
}
|
||||
}
|
||||
if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
|
@ -983,7 +1037,8 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
|||
}
|
||||
|
||||
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) {
|
||||
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false};
|
||||
SCheckExprForGroupByCxt cxt = {
|
||||
.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
|
||||
nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
|
@ -995,7 +1050,8 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
|
|||
if (NULL == getGroupByList(pCxt)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false};
|
||||
SCheckExprForGroupByCxt cxt = {
|
||||
.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false};
|
||||
nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
|
@ -1008,7 +1064,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
|
|||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
return rewriteColToSelectValFunc((STranslateContext*)pContext, NULL, pNode);
|
||||
return rewriteColToSelectValFunc((STranslateContext*)pContext, pNode);
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
@ -1027,11 +1083,16 @@ typedef struct CheckAggColCoexistCxt {
|
|||
bool existCol;
|
||||
bool existNonstdFunc;
|
||||
int32_t selectFuncNum;
|
||||
bool existOtherAggFunc;
|
||||
} CheckAggColCoexistCxt;
|
||||
|
||||
static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
|
||||
CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext;
|
||||
pCxt->selectFuncNum += isSelectFunc(pNode) ? 1 : 0;
|
||||
if (isSelectFunc(pNode)) {
|
||||
++(pCxt->selectFuncNum);
|
||||
} else if (isAggFunc(pNode)) {
|
||||
pCxt->existOtherAggFunc = true;
|
||||
}
|
||||
if (isAggFunc(pNode)) {
|
||||
pCxt->existAggFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
|
@ -1050,13 +1111,17 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
|
|||
if (NULL != pSelect->pGroupByList) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
CheckAggColCoexistCxt cxt = {
|
||||
.pTranslateCxt = pCxt, .existAggFunc = false, .existCol = false, .existNonstdFunc = false};
|
||||
CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt,
|
||||
.existAggFunc = false,
|
||||
.existCol = false,
|
||||
.existNonstdFunc = false,
|
||||
.selectFuncNum = 0,
|
||||
.existOtherAggFunc = false};
|
||||
nodesWalkExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt);
|
||||
if (!pSelect->isDistinct) {
|
||||
nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
|
||||
}
|
||||
if (1 == cxt.selectFuncNum) {
|
||||
if (1 == cxt.selectFuncNum && !cxt.existOtherAggFunc) {
|
||||
return rewriteColsToSelectValFunc(pCxt, pSelect);
|
||||
}
|
||||
if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
|
||||
|
@ -1230,18 +1295,6 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool isMultiResFunc(SNode* pNode) {
|
||||
if (QUERY_NODE_FUNCTION != nodeType(pNode) || !fmIsMultiResFunc(((SFunctionNode*)pNode)->funcId)) {
|
||||
return false;
|
||||
}
|
||||
SNodeList* pParameterList = ((SFunctionNode*)pNode)->pParameterList;
|
||||
if (LIST_LENGTH(pParameterList) > 1) {
|
||||
return true;
|
||||
}
|
||||
SNode* pParam = nodesListGetNode(pParameterList, 0);
|
||||
return (QUERY_NODE_COLUMN == nodeType(pParam) ? 0 == strcmp(((SColumnNode*)pParam)->colName, "*") : false);
|
||||
}
|
||||
|
||||
static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
|
@ -1872,7 +1925,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
|
|||
}
|
||||
|
||||
static bool dataTypeEqual(const SDataType* l, const SDataType* r) {
|
||||
return (l->type == r->type && l->bytes == l->bytes && l->precision == r->precision && l->scale == l->scale);
|
||||
return (l->type == r->type && l->bytes == r->bytes && l->precision == r->precision && l->scale == r->scale);
|
||||
}
|
||||
|
||||
static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType dt, SNode** pCast) {
|
||||
|
@ -2726,8 +2779,11 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm
|
|||
|
||||
SName tableName;
|
||||
tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), pReq->name);
|
||||
|
||||
return buildRollupAst(pCxt, pStmt, pReq);
|
||||
int32_t code = collectUseTable(&tableName, pCxt->pTables);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = buildRollupAst(pCxt, pStmt, pReq);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateCreateSuperTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
|
||||
|
@ -4032,13 +4088,18 @@ static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* p
|
|||
return scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal);
|
||||
}
|
||||
|
||||
static int32_t colDataBytesToValueDataBytes(uint8_t type, int32_t bytes) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == type || TSDB_DATA_TYPE_BINARY == type || TSDB_DATA_TYPE_VARBINARY == type) {
|
||||
return bytes - VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == type) {
|
||||
return (bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static SDataType schemaToDataType(SSchema* pSchema) {
|
||||
SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = 0, .scale = 0};
|
||||
if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_BINARY == dt.type || TSDB_DATA_TYPE_VARBINARY == dt.type) {
|
||||
dt.bytes -= VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
dt.bytes = (dt.bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
dt.bytes = colDataBytesToValueDataBytes(pSchema->type, pSchema->bytes);
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
@ -4440,7 +4501,8 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt
|
|||
SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName);
|
||||
if (NULL == pSchema) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName);
|
||||
} else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->bytes >= pReq->colModBytes) {
|
||||
} else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type ||
|
||||
pSchema->bytes >= pReq->colModBytes) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL);
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -239,6 +239,10 @@ TEST_F(ParserSelectTest, semanticError) {
|
|||
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
|
||||
run("SELECT timestamp '2010a' FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
|
||||
|
||||
run("SELECT LAST(*) + SUM(c1) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
|
||||
|
||||
run("SELECT CEIL(LAST(ts, c1)) FROM t1", TSDB_CODE_PAR_WRONG_VALUE_TYPE, PARSER_STAGE_TRANSLATE);
|
||||
|
||||
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
|
||||
run("SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0", TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION,
|
||||
PARSER_STAGE_TRANSLATE);
|
||||
|
|
|
@ -248,6 +248,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode)
|
|||
pSubplan->id.groupId = pCxt->groupId;
|
||||
pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
|
||||
pSubplan->pNode = pNode;
|
||||
pNode->pParent = NULL;
|
||||
return pSubplan;
|
||||
}
|
||||
|
||||
|
@ -408,17 +409,30 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc
|
|||
|
||||
static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule));
|
||||
|
||||
static void dumpLogicSubplan(const char* pRuleName, SLogicSubplan* pSubplan) {
|
||||
char* pStr = NULL;
|
||||
nodesNodeToString(pSubplan, false, &pStr, NULL);
|
||||
qDebugL("apply %s rule: %s", pRuleName, pStr);
|
||||
taosMemoryFree(pStr);
|
||||
}
|
||||
|
||||
static int32_t applySplitRule(SLogicSubplan* pSubplan) {
|
||||
SSplitContext cxt = {.queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false};
|
||||
bool split = false;
|
||||
do {
|
||||
cxt.split = false;
|
||||
split = false;
|
||||
for (int32_t i = 0; i < splitRuleNum; ++i) {
|
||||
cxt.split = false;
|
||||
int32_t code = splitRuleSet[i].splitFunc(&cxt, pSubplan);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
if (cxt.split) {
|
||||
split = true;
|
||||
dumpLogicSubplan(splitRuleSet[i].pName, pSubplan);
|
||||
}
|
||||
}
|
||||
} while (cxt.split);
|
||||
} while (split);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,12 @@ class PlanSetOpTest : public PlannerTestBase {};
|
|||
TEST_F(PlanSetOpTest, unionAll) {
|
||||
useDb("root", "test");
|
||||
|
||||
// sql 1: single UNION ALL operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20");
|
||||
// sql 2: multi UNION ALL operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 "
|
||||
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 "
|
||||
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 30");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionAllSubquery) {
|
||||
|
@ -44,7 +49,12 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) {
|
|||
TEST_F(PlanSetOpTest, union) {
|
||||
useDb("root", "test");
|
||||
|
||||
// single UNION operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20");
|
||||
// multi UNION operator
|
||||
run("SELECT c1, c2 FROM t1 WHERE c1 > 10 "
|
||||
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 20 "
|
||||
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 30");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, unionContainJoin) {
|
||||
|
@ -62,3 +72,12 @@ TEST_F(PlanSetOpTest, unionSubquery) {
|
|||
|
||||
run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)");
|
||||
}
|
||||
|
||||
TEST_F(PlanSetOpTest, bug001) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT c2 FROM t1 WHERE c1 IS NOT NULL GROUP BY c2 "
|
||||
"UNION "
|
||||
"SELECT 'abcdefghijklmnopqrstuvwxyz' FROM t1 "
|
||||
"WHERE 'abcdefghijklmnopqrstuvwxyz' IS NOT NULL GROUP BY 'abcdefghijklmnopqrstuvwxyz'");
|
||||
}
|
||||
|
|
|
@ -23,9 +23,7 @@ class PlanSubqeuryTest : public PlannerTestBase {};
|
|||
TEST_F(PlanSubqeuryTest, basic) {
|
||||
useDb("root", "test");
|
||||
|
||||
if (0 == g_skipSql) {
|
||||
run("SELECT * FROM (SELECT * FROM t1)");
|
||||
}
|
||||
run("SELECT * FROM (SELECT * FROM t1)");
|
||||
|
||||
run("SELECT LAST(c1) FROM (SELECT * FROM t1)");
|
||||
}
|
||||
|
|
|
@ -35,18 +35,19 @@ class PlannerEnv : public testing::Environment {
|
|||
|
||||
private:
|
||||
void initLog(const char* path) {
|
||||
dDebugFlag = 143;
|
||||
vDebugFlag = 0;
|
||||
mDebugFlag = 143;
|
||||
cDebugFlag = 0;
|
||||
jniDebugFlag = 0;
|
||||
tmrDebugFlag = 135;
|
||||
uDebugFlag = 135;
|
||||
rpcDebugFlag = 143;
|
||||
qDebugFlag = 143;
|
||||
wDebugFlag = 0;
|
||||
sDebugFlag = 0;
|
||||
tsdbDebugFlag = 0;
|
||||
int32_t logLevel = getLogLevel();
|
||||
dDebugFlag = logLevel;
|
||||
vDebugFlag = logLevel;
|
||||
mDebugFlag = logLevel;
|
||||
cDebugFlag = logLevel;
|
||||
jniDebugFlag = logLevel;
|
||||
tmrDebugFlag = logLevel;
|
||||
uDebugFlag = logLevel;
|
||||
rpcDebugFlag = logLevel;
|
||||
qDebugFlag = logLevel;
|
||||
wDebugFlag = logLevel;
|
||||
sDebugFlag = logLevel;
|
||||
tsdbDebugFlag = logLevel;
|
||||
tsLogEmbedded = 1;
|
||||
tsAsyncLog = 0;
|
||||
|
||||
|
@ -60,17 +61,26 @@ class PlannerEnv : public testing::Environment {
|
|||
};
|
||||
|
||||
static void parseArg(int argc, char* argv[]) {
|
||||
int opt = 0;
|
||||
const char* optstring = "";
|
||||
int opt = 0;
|
||||
const char* optstring = "";
|
||||
// clang-format off
|
||||
static struct option long_options[] = {
|
||||
{"dump", optional_argument, NULL, 'd'}, {"skipSql", optional_argument, NULL, 's'}, {0, 0, 0, 0}};
|
||||
{"dump", optional_argument, NULL, 'd'},
|
||||
{"skipSql", required_argument, NULL, 's'},
|
||||
{"log", required_argument, NULL, 'l'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
// clang-format on
|
||||
while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
setDumpModule(optarg);
|
||||
break;
|
||||
case 's':
|
||||
g_skipSql = 1;
|
||||
setSkipSqlNum(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
setLogLevel(optarg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -48,6 +48,7 @@ enum DumpModule {
|
|||
|
||||
DumpModule g_dumpModule = DUMP_MODULE_NOTHING;
|
||||
int32_t g_skipSql = 0;
|
||||
int32_t g_logLevel = 131;
|
||||
|
||||
void setDumpModule(const char* pModule) {
|
||||
if (NULL == pModule) {
|
||||
|
@ -71,14 +72,26 @@ void setDumpModule(const char* pModule) {
|
|||
}
|
||||
}
|
||||
|
||||
void setSkipSqlNum(const char* pNum) { g_skipSql = stoi(optarg); }
|
||||
|
||||
void setLogLevel(const char* pLogLevel) { g_logLevel = stoi(pLogLevel); }
|
||||
|
||||
int32_t getLogLevel() { return g_logLevel; }
|
||||
|
||||
class PlannerTestBaseImpl {
|
||||
public:
|
||||
void useDb(const string& acctId, const string& db) {
|
||||
caseEnv_.acctId_ = acctId;
|
||||
caseEnv_.db_ = db;
|
||||
caseEnv_.nsql_ = g_skipSql;
|
||||
}
|
||||
|
||||
void run(const string& sql) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
--(caseEnv_.nsql_);
|
||||
return;
|
||||
}
|
||||
|
||||
reset();
|
||||
try {
|
||||
SQuery* pQuery = nullptr;
|
||||
|
@ -109,6 +122,10 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void prepare(const string& sql) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
reset();
|
||||
try {
|
||||
doParseSql(sql, &stmtEnv_.pQuery_, true);
|
||||
|
@ -119,6 +136,10 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doBindParams(stmtEnv_.pQuery_, pParams, colIdx);
|
||||
} catch (...) {
|
||||
|
@ -128,6 +149,11 @@ class PlannerTestBaseImpl {
|
|||
}
|
||||
|
||||
void exec() {
|
||||
if (caseEnv_.nsql_ > 0) {
|
||||
--(caseEnv_.nsql_);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
doParseBoundSql(stmtEnv_.pQuery_);
|
||||
|
||||
|
@ -157,8 +183,9 @@ class PlannerTestBaseImpl {
|
|||
|
||||
private:
|
||||
struct caseEnv {
|
||||
string acctId_;
|
||||
string db_;
|
||||
string acctId_;
|
||||
string db_;
|
||||
int32_t nsql_;
|
||||
};
|
||||
|
||||
struct stmtEnv {
|
||||
|
|
|
@ -37,8 +37,9 @@ class PlannerTestBase : public testing::Test {
|
|||
std::unique_ptr<PlannerTestBaseImpl> impl_;
|
||||
};
|
||||
|
||||
extern int32_t g_skipSql;
|
||||
|
||||
extern void setDumpModule(const char* pModule);
|
||||
extern void setDumpModule(const char* pModule);
|
||||
extern void setSkipSqlNum(const char* pNum);
|
||||
extern void setLogLevel(const char* pLogLevel);
|
||||
extern int32_t getLogLevel();
|
||||
|
||||
#endif // PLAN_TEST_UTIL_H
|
||||
|
|
|
@ -76,8 +76,8 @@ int32_t syncRespMgrGetAndDel(SSyncRespMgr *pObj, uint64_t index, SRespStub *pStu
|
|||
void *pTmp = taosHashGet(pObj->pRespHash, &index, sizeof(index));
|
||||
if (pTmp != NULL) {
|
||||
memcpy(pStub, pTmp, sizeof(SRespStub));
|
||||
taosThreadMutexUnlock(&(pObj->mutex));
|
||||
taosHashRemove(pObj->pRespHash, &index, sizeof(index));
|
||||
taosThreadMutexUnlock(&(pObj->mutex));
|
||||
return 1; // get one object
|
||||
}
|
||||
taosThreadMutexUnlock(&(pObj->mutex));
|
||||
|
@ -90,4 +90,4 @@ void syncRespClean(SSyncRespMgr *pObj) {
|
|||
taosThreadMutexUnlock(&(pObj->mutex));
|
||||
}
|
||||
|
||||
void syncRespCleanByTTL(SSyncRespMgr *pObj, int64_t ttl) {}
|
||||
void syncRespCleanByTTL(SSyncRespMgr *pObj, int64_t ttl) {}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "thash.h"
|
||||
#include "taoserror.h"
|
||||
#include "os.h"
|
||||
#include "taoserror.h"
|
||||
#include "tlog.h"
|
||||
|
||||
// the add ref count operation may trigger the warning if the reference count is greater than the MAX_WARNING_REF_COUNT
|
||||
|
@ -27,36 +27,36 @@
|
|||
|
||||
#define HASH_NEED_RESIZE(_h) ((_h)->size >= (_h)->capacity * HASH_DEFAULT_LOAD_FACTOR)
|
||||
|
||||
#define GET_HASH_NODE_KEY(_n) ((char*)(_n) + sizeof(SHashNode) + (_n)->dataLen)
|
||||
#define GET_HASH_NODE_DATA(_n) ((char*)(_n) + sizeof(SHashNode))
|
||||
#define GET_HASH_PNODE(_n) ((SHashNode *)((char*)(_n) - sizeof(SHashNode)))
|
||||
#define GET_HASH_NODE_KEY(_n) ((char *)(_n) + sizeof(SHashNode) + (_n)->dataLen)
|
||||
#define GET_HASH_NODE_DATA(_n) ((char *)(_n) + sizeof(SHashNode))
|
||||
#define GET_HASH_PNODE(_n) ((SHashNode *)((char *)(_n) - sizeof(SHashNode)))
|
||||
|
||||
#define FREE_HASH_NODE(_fp, _n) \
|
||||
do { \
|
||||
/* if (_fp != NULL) { \
|
||||
(_fp)(_n); \
|
||||
}*/ \
|
||||
/* if (_fp != NULL) { \
|
||||
(_fp)(_n); \
|
||||
}*/ \
|
||||
taosMemoryFreeClear(_n); \
|
||||
} while (0);
|
||||
|
||||
struct SHashNode {
|
||||
SHashNode *next;
|
||||
uint32_t hashVal; // the hash value of key
|
||||
uint32_t dataLen; // length of data
|
||||
uint32_t keyLen; // length of the key
|
||||
uint16_t refCount; // reference count
|
||||
int8_t removed; // flag to indicate removed
|
||||
char data[];
|
||||
SHashNode *next;
|
||||
uint32_t hashVal; // the hash value of key
|
||||
uint32_t dataLen; // length of data
|
||||
uint32_t keyLen; // length of the key
|
||||
uint16_t refCount; // reference count
|
||||
int8_t removed; // flag to indicate removed
|
||||
char data[];
|
||||
};
|
||||
|
||||
typedef struct SHashEntry {
|
||||
int32_t num; // number of elements in current entry
|
||||
SRWLatch latch; // entry latch
|
||||
SHashNode *next;
|
||||
int32_t num; // number of elements in current entry
|
||||
SRWLatch latch; // entry latch
|
||||
SHashNode *next;
|
||||
} SHashEntry;
|
||||
|
||||
struct SHashObj {
|
||||
SHashEntry ** hashList;
|
||||
SHashEntry **hashList;
|
||||
size_t capacity; // number of slots
|
||||
int64_t size; // number of elements in hash table
|
||||
_hash_fn_t hashFp; // hash function
|
||||
|
@ -65,7 +65,7 @@ struct SHashObj {
|
|||
SRWLatch lock; // read-write spin lock
|
||||
SHashLockTypeE type; // lock type
|
||||
bool enableUpdate; // enable update
|
||||
SArray * pMemBlock; // memory block allocated for SHashEntry
|
||||
SArray *pMemBlock; // memory block allocated for SHashEntry
|
||||
_hash_before_fn_t callbackFp; // function invoked before return the value to caller
|
||||
};
|
||||
|
||||
|
@ -103,14 +103,14 @@ static FORCE_INLINE void taosHashRUnlock(SHashObj *pHashObj) {
|
|||
taosRUnLockLatch(&pHashObj->lock);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void taosHashEntryWLock(const SHashObj *pHashObj, SHashEntry* pe) {
|
||||
static FORCE_INLINE void taosHashEntryWLock(const SHashObj *pHashObj, SHashEntry *pe) {
|
||||
if (pHashObj->type == HASH_NO_LOCK) {
|
||||
return;
|
||||
}
|
||||
taosWLockLatch(&pe->latch);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void taosHashEntryWUnlock(const SHashObj *pHashObj, SHashEntry* pe) {
|
||||
static FORCE_INLINE void taosHashEntryWUnlock(const SHashObj *pHashObj, SHashEntry *pe) {
|
||||
if (pHashObj->type == HASH_NO_LOCK) {
|
||||
return;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ static FORCE_INLINE void taosHashEntryWUnlock(const SHashObj *pHashObj, SHashEnt
|
|||
taosWUnLockLatch(&pe->latch);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void taosHashEntryRLock(const SHashObj *pHashObj, SHashEntry* pe) {
|
||||
static FORCE_INLINE void taosHashEntryRLock(const SHashObj *pHashObj, SHashEntry *pe) {
|
||||
if (pHashObj->type == HASH_NO_LOCK) {
|
||||
return;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ static FORCE_INLINE void taosHashEntryRLock(const SHashObj *pHashObj, SHashEntry
|
|||
taosRLockLatch(&pe->latch);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void taosHashEntryRUnlock(const SHashObj *pHashObj, SHashEntry* pe) {
|
||||
static FORCE_INLINE void taosHashEntryRUnlock(const SHashObj *pHashObj, SHashEntry *pe) {
|
||||
if (pHashObj->type == HASH_NO_LOCK) {
|
||||
return;
|
||||
}
|
||||
|
@ -142,12 +142,11 @@ static FORCE_INLINE int32_t taosHashCapacity(int32_t length) {
|
|||
return i;
|
||||
}
|
||||
|
||||
static FORCE_INLINE SHashNode *
|
||||
doSearchInEntryList(SHashObj *pHashObj, 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) &&
|
||||
((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
|
||||
if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
|
||||
pNode->removed == 0) {
|
||||
assert(pNode->hashVal == hashVal);
|
||||
break;
|
||||
|
@ -186,18 +185,22 @@ static SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *p
|
|||
* @param pNode the old node with requested key
|
||||
* @param pNewNode the new node with requested key
|
||||
*/
|
||||
static FORCE_INLINE void doUpdateHashNode(SHashObj *pHashObj, SHashEntry* pe, SHashNode* prev, SHashNode *pNode, SHashNode *pNewNode) {
|
||||
static FORCE_INLINE void doUpdateHashNode(SHashObj *pHashObj, SHashEntry *pe, SHashNode *prev, SHashNode *pNode,
|
||||
SHashNode *pNewNode) {
|
||||
assert(pNode->keyLen == pNewNode->keyLen);
|
||||
|
||||
atomic_sub_fetch_16(&pNode->refCount, 1);
|
||||
if (prev != NULL) {
|
||||
prev->next = pNewNode;
|
||||
ASSERT(prev->next != prev);
|
||||
} else {
|
||||
pe->next = pNewNode;
|
||||
}
|
||||
|
||||
if (pNode->refCount <= 0) {
|
||||
pNewNode->next = pNode->next;
|
||||
ASSERT(pNewNode->next != pNewNode);
|
||||
|
||||
FREE_HASH_NODE(pHashObj->freeFp, pNode);
|
||||
} else {
|
||||
pNewNode->next = pNode;
|
||||
|
@ -227,9 +230,7 @@ static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj);
|
|||
* @param pHashObj
|
||||
* @return
|
||||
*/
|
||||
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) {
|
||||
return taosHashGetSize(pHashObj) == 0;
|
||||
}
|
||||
static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) { return taosHashGetSize(pHashObj) == 0; }
|
||||
|
||||
SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type) {
|
||||
if (fn == NULL) {
|
||||
|
@ -251,7 +252,7 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTyp
|
|||
pHashObj->capacity = taosHashCapacity((int32_t)capacity);
|
||||
|
||||
pHashObj->equalFp = memcmp;
|
||||
pHashObj->hashFp = fn;
|
||||
pHashObj->hashFp = fn;
|
||||
pHashObj->type = type;
|
||||
pHashObj->enableUpdate = update;
|
||||
|
||||
|
@ -305,7 +306,7 @@ int32_t taosHashGetSize(const SHashObj *pHashObj) {
|
|||
if (pHashObj == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return (int32_t)atomic_load_64((int64_t*)&pHashObj->size);
|
||||
return (int32_t)atomic_load_64((int64_t *)&pHashObj->size);
|
||||
}
|
||||
|
||||
int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const void *data, size_t size) {
|
||||
|
@ -340,10 +341,9 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo
|
|||
}
|
||||
#endif
|
||||
|
||||
SHashNode* prev = NULL;
|
||||
SHashNode *prev = NULL;
|
||||
while (pNode) {
|
||||
if ((pNode->keyLen == keyLen) &&
|
||||
(*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0 &&
|
||||
if ((pNode->keyLen == keyLen) && (*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0 &&
|
||||
pNode->removed == 0) {
|
||||
assert(pNode->hashVal == hashVal);
|
||||
break;
|
||||
|
@ -391,27 +391,27 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo
|
|||
}
|
||||
}
|
||||
|
||||
static void* taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void** d, int32_t* size, bool addRef);
|
||||
static void *taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void **d, int32_t *size, bool addRef);
|
||||
|
||||
void *taosHashGet(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
||||
void* p = NULL;
|
||||
void *p = NULL;
|
||||
return taosHashGetImpl(pHashObj, key, keyLen, &p, 0, false);
|
||||
}
|
||||
|
||||
int32_t taosHashGetDup(SHashObj *pHashObj, const void *key, size_t keyLen, void *destBuf) {
|
||||
terrno = 0;
|
||||
/*char* p = */taosHashGetImpl(pHashObj, key, keyLen, &destBuf, 0, false);
|
||||
/*char* p = */ taosHashGetImpl(pHashObj, key, keyLen, &destBuf, 0, false);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
int32_t taosHashGetDup_m(SHashObj *pHashObj, const void *key, size_t keyLen, void **destBuf, int32_t* size) {
|
||||
int32_t taosHashGetDup_m(SHashObj *pHashObj, const void *key, size_t keyLen, void **destBuf, int32_t *size) {
|
||||
terrno = 0;
|
||||
|
||||
/*char* p = */taosHashGetImpl(pHashObj, key, keyLen, destBuf, size, false);
|
||||
/*char* p = */ taosHashGetImpl(pHashObj, key, keyLen, destBuf, size, false);
|
||||
return terrno;
|
||||
}
|
||||
|
||||
void* taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void** d, int32_t* size, bool addRef) {
|
||||
void *taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void **d, int32_t *size, bool addRef) {
|
||||
if (pHashObj == NULL || taosHashTableEmpty(pHashObj) || keyLen == 0 || key == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -449,15 +449,15 @@ void* taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void**
|
|||
|
||||
if (size != NULL) {
|
||||
if (*d == NULL) {
|
||||
*size = pNode->dataLen;
|
||||
*size = pNode->dataLen;
|
||||
*d = taosMemoryCalloc(1, *size);
|
||||
if (*d == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
} else if (*size < pNode->dataLen) {
|
||||
*size = pNode->dataLen;
|
||||
char* tmp = taosMemoryRealloc(*d, *size);
|
||||
*size = pNode->dataLen;
|
||||
char *tmp = taosMemoryRealloc(*d, *size);
|
||||
if (tmp == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
|
@ -508,13 +508,12 @@ int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int code = -1;
|
||||
int code = -1;
|
||||
SHashNode *pNode = pe->next;
|
||||
SHashNode *prevNode = NULL;
|
||||
|
||||
while (pNode) {
|
||||
if ((pNode->keyLen == keyLen) &&
|
||||
((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
|
||||
if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) &&
|
||||
pNode->removed == 0) {
|
||||
code = 0; // it is found
|
||||
|
||||
|
@ -525,6 +524,7 @@ int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
|||
pe->next = pNode->next;
|
||||
} else {
|
||||
prevNode->next = pNode->next;
|
||||
ASSERT(prevNode->next != prevNode);
|
||||
}
|
||||
|
||||
pe->num--;
|
||||
|
@ -598,14 +598,14 @@ void taosHashCleanup(SHashObj *pHashObj) {
|
|||
}
|
||||
|
||||
// for profile only
|
||||
int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj){
|
||||
int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj) {
|
||||
if (pHashObj == NULL || taosHashTableEmpty(pHashObj)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t num = 0;
|
||||
|
||||
taosHashRLock((SHashObj*) pHashObj);
|
||||
taosHashRLock((SHashObj *)pHashObj);
|
||||
for (int32_t i = 0; i < pHashObj->size; ++i) {
|
||||
SHashEntry *pEntry = pHashObj->hashList[i];
|
||||
|
||||
|
@ -616,7 +616,7 @@ int32_t taosHashGetMaxOverflowLinkLength(const SHashObj *pHashObj){
|
|||
}
|
||||
}
|
||||
|
||||
taosHashRUnlock((SHashObj*) pHashObj);
|
||||
taosHashRUnlock((SHashObj *)pHashObj);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
@ -627,22 +627,22 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
|||
|
||||
int32_t newCapacity = (int32_t)(pHashObj->capacity << 1u);
|
||||
if (newCapacity > HASH_MAX_CAPACITY) {
|
||||
// uDebug("current capacity:%zu, maximum capacity:%d, no resize applied due to limitation is reached",
|
||||
// pHashObj->capacity, HASH_MAX_CAPACITY);
|
||||
// uDebug("current capacity:%zu, maximum capacity:%d, no resize applied due to limitation is reached",
|
||||
// pHashObj->capacity, HASH_MAX_CAPACITY);
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t st = taosGetTimestampUs();
|
||||
void *pNewEntryList = taosMemoryRealloc(pHashObj->hashList, sizeof(void *) * newCapacity);
|
||||
void *pNewEntryList = taosMemoryRealloc(pHashObj->hashList, sizeof(void *) * newCapacity);
|
||||
if (pNewEntryList == NULL) {
|
||||
// uDebug("cache resize failed due to out of memory, capacity remain:%zu", pHashObj->capacity);
|
||||
// uDebug("cache resize failed due to out of memory, capacity remain:%zu", pHashObj->capacity);
|
||||
return;
|
||||
}
|
||||
|
||||
pHashObj->hashList = pNewEntryList;
|
||||
|
||||
size_t inc = newCapacity - pHashObj->capacity;
|
||||
void * p = taosMemoryCalloc(inc, sizeof(SHashEntry));
|
||||
void *p = taosMemoryCalloc(inc, sizeof(SHashEntry));
|
||||
|
||||
for (int32_t i = 0; i < inc; ++i) {
|
||||
pHashObj->hashList[i + pHashObj->capacity] = (void *)((char *)p + i * sizeof(SHashEntry));
|
||||
|
@ -653,9 +653,9 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
|||
pHashObj->capacity = newCapacity;
|
||||
for (int32_t idx = 0; idx < pHashObj->capacity; ++idx) {
|
||||
SHashEntry *pe = pHashObj->hashList[idx];
|
||||
SHashNode *pNode;
|
||||
SHashNode *pNext;
|
||||
SHashNode *pPrev = NULL;
|
||||
SHashNode *pNode;
|
||||
SHashNode *pNext;
|
||||
SHashNode *pPrev = NULL;
|
||||
|
||||
if (pe->num == 0) {
|
||||
assert(pe->next == NULL);
|
||||
|
@ -688,24 +688,25 @@ void taosHashTableResize(SHashObj *pHashObj) {
|
|||
|
||||
int64_t et = taosGetTimestampUs();
|
||||
|
||||
// uDebug("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms", (int32_t)pHashObj->capacity,
|
||||
// ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
|
||||
// uDebug("hash table resize completed, new capacity:%d, load factor:%f, elapsed time:%fms",
|
||||
// (int32_t)pHashObj->capacity,
|
||||
// ((double)pHashObj->size) / pHashObj->capacity, (et - st) / 1000.0);
|
||||
}
|
||||
|
||||
SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, size_t dsize, uint32_t hashVal) {
|
||||
SHashNode *pNewNode = taosMemoryMalloc(sizeof(SHashNode) + keyLen + dsize);
|
||||
SHashNode *pNewNode = taosMemoryMalloc(sizeof(SHashNode) + keyLen + dsize + 1);
|
||||
|
||||
if (pNewNode == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNewNode->keyLen = (uint32_t)keyLen;
|
||||
pNewNode->keyLen = (uint32_t)keyLen;
|
||||
pNewNode->hashVal = hashVal;
|
||||
pNewNode->dataLen = (uint32_t)dsize;
|
||||
pNewNode->refCount= 1;
|
||||
pNewNode->refCount = 1;
|
||||
pNewNode->removed = 0;
|
||||
pNewNode->next = NULL;
|
||||
pNewNode->next = NULL;
|
||||
|
||||
memcpy(GET_HASH_NODE_DATA(pNewNode), pData, dsize);
|
||||
memcpy(GET_HASH_NODE_KEY(pNewNode), key, keyLen);
|
||||
|
@ -719,6 +720,7 @@ void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode) {
|
|||
pNode->next = pEntry->next;
|
||||
pEntry->next = pNode;
|
||||
|
||||
ASSERT(pNode->next != pNode);
|
||||
pEntry->num += 1;
|
||||
}
|
||||
|
||||
|
@ -727,11 +729,12 @@ size_t taosHashGetMemSize(const SHashObj *pHashObj) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return (pHashObj->capacity * (sizeof(SHashEntry) + sizeof(void*))) + sizeof(SHashNode) * taosHashGetSize(pHashObj) + sizeof(SHashObj);
|
||||
return (pHashObj->capacity * (sizeof(SHashEntry) + sizeof(void *))) + sizeof(SHashNode) * taosHashGetSize(pHashObj) +
|
||||
sizeof(SHashObj);
|
||||
}
|
||||
|
||||
void *taosHashGetKey(void *data, size_t* keyLen) {
|
||||
SHashNode * node = GET_HASH_PNODE(data);
|
||||
void *taosHashGetKey(void *data, size_t *keyLen) {
|
||||
SHashNode *node = GET_HASH_PNODE(data);
|
||||
if (keyLen != NULL) {
|
||||
*keyLen = node->keyLen;
|
||||
}
|
||||
|
@ -751,8 +754,7 @@ static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
|
|||
|
||||
SHashNode *pNode = pe->next;
|
||||
while (pNode) {
|
||||
if (pNode == pOld)
|
||||
break;
|
||||
if (pNode == pOld) break;
|
||||
|
||||
prevNode = pNode;
|
||||
pNode = pNode->next;
|
||||
|
@ -766,11 +768,16 @@ static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
|
|||
}
|
||||
|
||||
atomic_sub_fetch_16(&pOld->refCount, 1);
|
||||
if (pOld->refCount <=0) {
|
||||
if (pOld->refCount <= 0) {
|
||||
if (prevNode) {
|
||||
prevNode->next = pOld->next;
|
||||
ASSERT(prevNode->next != prevNode);
|
||||
} else {
|
||||
pe->next = pOld->next;
|
||||
SHashNode* x = pe->next;
|
||||
if (x != NULL) {
|
||||
ASSERT(x->next != x);
|
||||
}
|
||||
}
|
||||
|
||||
pe->num--;
|
||||
|
@ -778,7 +785,7 @@ static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
|
|||
FREE_HASH_NODE(pHashObj->freeFp, pOld);
|
||||
}
|
||||
} else {
|
||||
// uError("pNode:%p data:%p is not there!!!", pNode, p);
|
||||
// uError("pNode:%p data:%p is not there!!!", pNode, p);
|
||||
}
|
||||
|
||||
return pNode;
|
||||
|
@ -787,7 +794,7 @@ static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) {
|
|||
void *taosHashIterate(SHashObj *pHashObj, void *p) {
|
||||
if (pHashObj == NULL) return NULL;
|
||||
|
||||
int slot = 0;
|
||||
int slot = 0;
|
||||
char *data = NULL;
|
||||
|
||||
// only add the read lock to disable the resize process
|
||||
|
@ -865,9 +872,9 @@ void taosHashCancelIterate(SHashObj *pHashObj, void *p) {
|
|||
taosHashRUnlock(pHashObj);
|
||||
}
|
||||
|
||||
//TODO remove it
|
||||
// TODO remove it
|
||||
void *taosHashAcquire(SHashObj *pHashObj, const void *key, size_t keyLen) {
|
||||
void* p = NULL;
|
||||
void *p = NULL;
|
||||
return taosHashGetImpl(pHashObj, key, keyLen, &p, 0, true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue