diff --git a/include/libs/function/tudf.h b/include/libs/function/tudf.h index 0000972f5e..d59a7c23f7 100644 --- a/include/libs/function/tudf.h +++ b/include/libs/function/tudf.h @@ -29,7 +29,11 @@ extern "C" { #endif #define UDF_LISTEN_PIPE_NAME_LEN 32 -#define UDF_LISTEN_PIPE_NAME_PREFIX "udfd.sock." +#ifdef _WIN32 +#define UDF_LISTEN_PIPE_NAME_PREFIX "\\\\?\\pipe\\udfd.sock" +#else +#define UDF_LISTEN_PIPE_NAME_PREFIX ".udfd.sock." +#endif #define UDF_DNODE_ID_ENV_NAME "DNODE_ID" //====================================================================================== @@ -129,8 +133,8 @@ int32_t udfAggFinalize(struct SqlFunctionCtx *pCtx, SSDataBlock* pBlock); // begin API to UDF writer. // dynamic lib init and destroy -typedef int32_t (*TUdfSetupFunc)(); -typedef int32_t (*TUdfTeardownFunc)(); +typedef int32_t (*TUdfInitFunc)(); +typedef int32_t (*TUdfDestroyFunc)(); //TODO: add API to check function arguments type, number etc. @@ -242,7 +246,6 @@ static FORCE_INLINE int32_t udfColSetRow(SUdfColumn* pColumn, uint32_t currentRo return 0; } -typedef int32_t (*TUdfFreeUdfColumnFunc)(SUdfColumn* column); typedef int32_t (*TUdfScalarProcFunc)(SUdfDataBlock* block, SUdfColumn *resultCol); typedef int32_t (*TUdfAggStartFunc)(SUdfInterBuf *buf); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index abc752955d..441e87eff7 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -621,6 +621,14 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_INVALID_TOPIC_QUERY TAOS_DEF_ERROR_CODE(0, 0x2639) #define TSDB_CODE_PAR_INVALID_DROP_STABLE TAOS_DEF_ERROR_CODE(0, 0x263A) #define TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE TAOS_DEF_ERROR_CODE(0, 0x263B) +#define TSDB_CODE_PAR_DUPLICATED_COLUMN TAOS_DEF_ERROR_CODE(0, 0x263C) +#define TSDB_CODE_PAR_INVALID_TAGS_LENGTH TAOS_DEF_ERROR_CODE(0, 0x263D) +#define TSDB_CODE_PAR_INVALID_ROW_LENGTH TAOS_DEF_ERROR_CODE(0, 0x263E) +#define TSDB_CODE_PAR_INVALID_COLUMNS_NUM TAOS_DEF_ERROR_CODE(0, 0x263F) +#define TSDB_CODE_PAR_TOO_MANY_COLUMNS TAOS_DEF_ERROR_CODE(0, 0x2640) +#define TSDB_CODE_PAR_INVALID_FIRST_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2641) +#define TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN TAOS_DEF_ERROR_CODE(0, 0x2642) +#define TSDB_CODE_PAR_INVALID_TAGS_NUM TAOS_DEF_ERROR_CODE(0, 0x2643) //planner #define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700) diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index 06da3b0e1d..8460400b59 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -339,7 +339,7 @@ static int vnodeProcessCreateTbReq(SVnode *pVnode, int64_t version, void *pReq, goto _exit; } - rsp.pArray = taosArrayInit(sizeof(cRsp), req.nReqs); + rsp.pArray = taosArrayInit(req.nReqs, sizeof(cRsp)); if (rsp.pArray == NULL) { rcode = -1; terrno = TSDB_CODE_OUT_OF_MEMORY; diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index 87cd3e24a8..abb9525cc5 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -73,6 +73,11 @@ bool spreadFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) int32_t spreadFunction(SqlFunctionCtx* pCtx); int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); +bool getHistogramFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv); +bool histogramFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo); +int32_t histogramFunction(SqlFunctionCtx* pCtx); +int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); + #ifdef __cplusplus } #endif diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 734136b296..8fa4bd0c4d 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -225,6 +225,26 @@ static int32_t translateSpread(SFunctionNode* pFunc, char* pErrBuf, int32_t len) return TSDB_CODE_SUCCESS; } +static int32_t translateHistogram(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + if (4 != LIST_LENGTH(pFunc->pParameterList)) { + return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); + } + + uint8_t colType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; + if (!IS_NUMERIC_TYPE(colType)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } + + if (((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type != TSDB_DATA_TYPE_BINARY || + ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type != TSDB_DATA_TYPE_BINARY || + ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type != TSDB_DATA_TYPE_BIGINT) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } + + pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE }; + return TSDB_CODE_SUCCESS; +} + static int32_t translateLastRow(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { // todo return TSDB_CODE_SUCCESS; @@ -599,6 +619,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .processFunc = diffFunction, .finalizeFunc = functionFinalize }, + { + .name = "histogram", + .type = FUNCTION_TYPE_HISTOGRAM, + .classification = FUNC_MGT_AGG_FUNC, + .translateFunc = translateHistogram, + .getEnvFunc = getHistogramFuncEnv, + .initFunc = histogramFunctionSetup, + .processFunc = histogramFunction, + .finalizeFunc = histogramFinalize + }, { .name = "abs", .type = FUNCTION_TYPE_ABS, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 0eba442e66..3c9eca85dd 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -20,6 +20,8 @@ #include "tdatablock.h" #include "tpercentile.h" +#define HISTOGRAM_MAX_BINS_NUM 100 + typedef struct SSumRes { union { int64_t isum; @@ -89,6 +91,22 @@ typedef struct SSpreadInfo { double max; } SSpreadInfo; +typedef struct SHistoFuncBin { + double lower; + double upper; + union { + int64_t count; + double percentage; + }; +} SHistoFuncBin; + +typedef struct SHistoFuncInfo { + int32_t numOfBins; + bool normalized; + SHistoFuncBin bins[]; +} SHistoFuncInfo; + + #define SET_VAL(_info, numOfElem, res) \ do { \ if ((numOfElem) <= 0) { \ @@ -1777,3 +1795,34 @@ int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { } return functionFinalize(pCtx, pBlock); } + +bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { + pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin); + return true; +} + +bool histogramFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { + if (!functionSetup(pCtx, pResultInfo)) { + return false; + } + + SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo); + char* binType = pCtx->param[1].param.pz; + char* binDesc = pCtx->param[2].param.pz; + int64_t nornalized = pCtx->param[3].param.i; + + + return true; +} + +int32_t histogramFunction(SqlFunctionCtx *pCtx) { + return TSDB_CODE_SUCCESS; +} + +int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { + SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + //if (pInfo->hasResult == true) { + // SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min); + //} + return functionFinalize(pCtx, pBlock); +} diff --git a/source/libs/function/src/tudf.c b/source/libs/function/src/tudf.c index 5b1573c88f..0a99ef61ce 100644 --- a/source/libs/function/src/tudf.c +++ b/source/libs/function/src/tudf.c @@ -594,7 +594,9 @@ int32_t convertScalarParamToDataBlock(SScalarParam *input, int32_t numOfCols, SS //TODO: free the array output->pDataBlock output->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); - taosArrayPush(output->pDataBlock, input->columnData); + for (int32_t i = 0; i < numOfCols; ++i) { + taosArrayPush(output->pDataBlock, (input + i)->columnData); + } return 0; } diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c index ba9fca2969..f5e4a9c6e6 100644 --- a/source/libs/function/src/udfd.c +++ b/source/libs/function/src/udfd.c @@ -81,6 +81,9 @@ typedef struct SUdf { TUdfAggStartFunc aggStartFunc; TUdfAggProcessFunc aggProcFunc; TUdfAggFinishFunc aggFinishFunc; + + TUdfInitFunc initFunc; + TUdfDestroyFunc destroyFunc; } SUdf; // TODO: low priority: change name onxxx to xxxCb, and udfc or udfd as prefix @@ -101,7 +104,19 @@ int32_t udfdLoadUdf(char *udfName, SUdf *udf) { fnError("can not load library %s. error: %s", udf->path, uv_strerror(err)); return UDFC_CODE_LOAD_UDF_FAILURE; } - //TODO: init and destroy function + + char initFuncName[TSDB_FUNC_NAME_LEN+5] = {0}; + char *initSuffix = "_init"; + strcpy(initFuncName, udfName); + strncat(initFuncName, initSuffix, strlen(initSuffix)); + uv_dlsym(&udf->lib, initFuncName, (void**)(&udf->initFunc)); + + char destroyFuncName[TSDB_FUNC_NAME_LEN+5] = {0}; + char *destroySuffix = "_destroy"; + strcpy(destroyFuncName, udfName); + strncat(destroyFuncName, destroySuffix, strlen(destroySuffix)); + uv_dlsym(&udf->lib, destroyFuncName, (void**)(&udf->destroyFunc)); + if (udf->funcType == TSDB_FUNC_TYPE_SCALAR) { char processFuncName[TSDB_FUNC_NAME_LEN] = {0}; strcpy(processFuncName, udfName); @@ -159,6 +174,9 @@ void udfdProcessRequest(uv_work_t *req) { if (udf->state == UDF_STATE_INIT) { udf->state = UDF_STATE_LOADING; udfdLoadUdf(setup->udfName, udf); + if (udf->initFunc) { + udf->initFunc(); + } udf->state = UDF_STATE_READY; uv_cond_broadcast(&udf->condReady); uv_mutex_unlock(&udf->lock); @@ -170,7 +188,6 @@ void udfdProcessRequest(uv_work_t *req) { } SUdfcFuncHandle *handle = taosMemoryMalloc(sizeof(SUdfcFuncHandle)); handle->udf = udf; - // TODO: allocate private structure and call init function and set it to handle SUdfResponse rsp; rsp.seqNum = request.seqNum; rsp.type = request.type; @@ -275,10 +292,12 @@ void udfdProcessRequest(uv_work_t *req) { if (unloadUdf) { uv_cond_destroy(&udf->condReady); uv_mutex_destroy(&udf->lock); + if (udf->destroyFunc) { + (udf->destroyFunc)(); + } uv_dlclose(&udf->lib); taosMemoryFree(udf); } - // TODO: call destroy and free udf private taosMemoryFree(handle); SUdfResponse response; diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index fbb1f34217..6874b5b7d4 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -2174,17 +2174,6 @@ static int32_t checkTableSmaOption(STranslateContext* pCxt, SCreateTableStmt* pS return TSDB_CODE_SUCCESS; } -static int32_t checkTableTags(STranslateContext* pCxt, SCreateTableStmt* pStmt) { - SNode* pNode; - FOREACH(pNode, pStmt->pTags) { - SColumnDefNode* pCol = (SColumnDefNode*)pNode; - if (pCol->dataType.type == TSDB_DATA_TYPE_JSON && LIST_LENGTH(pStmt->pTags) > 1) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG); - } - } - return TSDB_CODE_SUCCESS; -} - static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs) { if (NULL == pFuncs) { return TSDB_CODE_SUCCESS; @@ -2196,6 +2185,113 @@ static int32_t checkTableRollupOption(STranslateContext* pCxt, SNodeList* pFuncs return TSDB_CODE_SUCCESS; } +static int32_t checkTableTagsSchema(STranslateContext* pCxt, SHashObj* pHash, SNodeList* pTags) { + int32_t ntags = LIST_LENGTH(pTags); + if (0 == ntags) { + return TSDB_CODE_SUCCESS; + } else if (ntags > TSDB_MAX_TAGS) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_NUM); + } + + int32_t code = TSDB_CODE_SUCCESS; + int32_t tagsSize = 0; + SNode* pNode = NULL; + FOREACH(pNode, pTags) { + SColumnDefNode* pTag = (SColumnDefNode*)pNode; + int32_t len = strlen(pTag->colName); + if (NULL != taosHashGet(pHash, pTag->colName, len)) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DUPLICATED_COLUMN); + } + if (TSDB_CODE_SUCCESS == code && pTag->dataType.type == TSDB_DATA_TYPE_JSON && ntags > 1) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG); + } + if (TSDB_CODE_SUCCESS == code) { + if ((TSDB_DATA_TYPE_VARCHAR == pTag->dataType.type && pTag->dataType.bytes > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pTag->dataType.type && pTag->dataType.bytes > TSDB_MAX_NCHAR_LEN)) { + code = code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + } + if (TSDB_CODE_SUCCESS == code) { + code = taosHashPut(pHash, pTag->colName, len, &pTag, POINTER_BYTES); + } + if (TSDB_CODE_SUCCESS == code) { + tagsSize += pTag->dataType.bytes; + } else { + break; + } + } + + if (TSDB_CODE_SUCCESS == code && tagsSize > TSDB_MAX_TAGS_LEN) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_LENGTH, TSDB_MAX_TAGS_LEN); + } + + return code; +} + +static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, SNodeList* pCols) { + int32_t ncols = LIST_LENGTH(pCols); + if (ncols < TSDB_MIN_COLUMNS) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); + } else if (ncols > TSDB_MAX_COLUMNS) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TOO_MANY_COLUMNS); + } + + int32_t code = TSDB_CODE_SUCCESS; + + bool first = true; + int32_t rowSize = 0; + SNode* pNode = NULL; + FOREACH(pNode, pCols) { + SColumnDefNode* pCol = (SColumnDefNode*)pNode; + if (first) { + first = false; + if (TSDB_DATA_TYPE_TIMESTAMP != pCol->dataType.type) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FIRST_COLUMN); + } + } + int32_t len = strlen(pCol->colName); + if (TSDB_CODE_SUCCESS == code && NULL != taosHashGet(pHash, pCol->colName, len)) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DUPLICATED_COLUMN); + } + if (TSDB_CODE_SUCCESS == code) { + if ((TSDB_DATA_TYPE_VARCHAR == pCol->dataType.type && pCol->dataType.bytes > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pCol->dataType.type && pCol->dataType.bytes > TSDB_MAX_NCHAR_LEN)) { + code = code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + } + if (TSDB_CODE_SUCCESS == code) { + code = taosHashPut(pHash, pCol->colName, len, &pCol, POINTER_BYTES); + } + if (TSDB_CODE_SUCCESS == code) { + rowSize += pCol->dataType.bytes; + } else { + break; + } + } + + if (TSDB_CODE_SUCCESS == code && rowSize > TSDB_MAX_BYTES_PER_ROW) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); + } + + return code; +} + +static int32_t checkTableSchema(STranslateContext* pCxt, SCreateTableStmt* pStmt) { + SHashObj* pHash = taosHashInit(LIST_LENGTH(pStmt->pTags) + LIST_LENGTH(pStmt->pCols), + taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (NULL == pHash) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t code = checkTableTagsSchema(pCxt, pHash, pStmt->pTags); + if (TSDB_CODE_SUCCESS == code) { + code = checkTableColsSchema(pCxt, pHash, pStmt->pCols); + } + + taosHashCleanup(pHash); + return code; +} + static int32_t checkCreateTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) { int32_t code = checkRangeOption(pCxt, "delay", pStmt->pOptions->delay, TSDB_MIN_ROLLUP_DELAY, TSDB_MAX_ROLLUP_DELAY); if (TSDB_CODE_SUCCESS == code) { @@ -2211,7 +2307,7 @@ static int32_t checkCreateTable(STranslateContext* pCxt, SCreateTableStmt* pStmt code = checkTableSmaOption(pCxt, pStmt); } if (TSDB_CODE_SUCCESS == code) { - code = checkTableTags(pCxt, pStmt); + code = checkTableSchema(pCxt, pStmt); } return code; } @@ -3838,6 +3934,10 @@ static int32_t buildDropTableVgroupHashmap(STranslateContext* pCxt, SDropTableCl goto over; } + if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code && pClause->ignoreNotExists) { + code = TSDB_CODE_SUCCESS; + } + *pIsSuperTable = false; SVgroupInfo info = {0}; diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index e839536218..e37dbd1edd 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -129,7 +129,23 @@ static char* getSyntaxErrFormat(int32_t errCode) { case TSDB_CODE_PAR_INVALID_DROP_STABLE: return "Cannot drop super table in batch"; case TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE: - return "start(end) time of query range required or time range too large"; + return "Start(end) time of query range required or time range too large"; + case TSDB_CODE_PAR_DUPLICATED_COLUMN: + return "Duplicated column names"; + case TSDB_CODE_PAR_INVALID_TAGS_LENGTH: + return "Tags length exceeds max length %d"; + case TSDB_CODE_PAR_INVALID_ROW_LENGTH: + return "Row length exceeds max length %d"; + case TSDB_CODE_PAR_INVALID_COLUMNS_NUM: + return "Illegal number of columns"; + case TSDB_CODE_PAR_TOO_MANY_COLUMNS: + return "Too many columns"; + case TSDB_CODE_PAR_INVALID_FIRST_COLUMN: + return "First column must be timestamp"; + case TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN: + return "Invalid binary/nchar column length"; + case TSDB_CODE_PAR_INVALID_TAGS_NUM: + return "Invalid number of tag columns"; case TSDB_CODE_OUT_OF_MEMORY: return "Out of memory"; default: diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index 0bc700696b..3e19ccbd82 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -277,6 +277,11 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect code = nodesCollectFuncs(pSelect, SQL_CLAUSE_FROM, fmIsScanPseudoColumnFunc, &pScan->pScanPseudoCols); } + // rewrite the expression in subsequent clauses + if (TSDB_CODE_SUCCESS == code) { + code = rewriteExprForSelect(pScan->pScanPseudoCols, pSelect, SQL_CLAUSE_FROM); + } + pScan->scanType = getScanType(pCxt, pScan->pScanPseudoCols, pScan->pScanCols, pScan->pMeta); if (TSDB_CODE_SUCCESS == code) { diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 67609355d7..dbce9abf36 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -123,14 +123,40 @@ static SNodeList* osdGetAllFuncs(SLogicNode* pNode) { return NULL; } +static bool needOptimizeDataRequire(const SFunctionNode* pFunc) { + if (!fmIsSpecialDataRequiredFunc(pFunc->funcId)) { + return false; + } + SNode* pPara = NULL; + FOREACH(pPara, pFunc->pParameterList) { + if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) { + return false; + } + } + return true; +} + +static bool needOptimizeDynamicScan(const SFunctionNode* pFunc) { + if (!fmIsDynamicScanOptimizedFunc(pFunc->funcId)) { + return false; + } + SNode* pPara = NULL; + FOREACH(pPara, pFunc->pParameterList) { + if (QUERY_NODE_COLUMN != nodeType(pPara) && QUERY_NODE_VALUE != nodeType(pPara)) { + return false; + } + } + return true; +} + static int32_t osdGetRelatedFuncs(SScanLogicNode* pScan, SNodeList** pSdrFuncs, SNodeList** pDsoFuncs) { SNodeList* pAllFuncs = osdGetAllFuncs(pScan->node.pParent); SNode* pFunc = NULL; FOREACH(pFunc, pAllFuncs) { int32_t code = TSDB_CODE_SUCCESS; - if (fmIsSpecialDataRequiredFunc(((SFunctionNode*)pFunc)->funcId)) { + if (needOptimizeDataRequire((SFunctionNode*)pFunc)) { code = nodesListMakeStrictAppend(pSdrFuncs, nodesCloneNode(pFunc)); - } else if (fmIsDynamicScanOptimizedFunc(((SFunctionNode*)pFunc)->funcId)) { + } else if (needOptimizeDynamicScan((SFunctionNode*)pFunc)) { code = nodesListMakeStrictAppend(pDsoFuncs, nodesCloneNode(pFunc)); } if (TSDB_CODE_SUCCESS != code) { @@ -541,9 +567,14 @@ static bool cpdIsPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) { if (QUERY_NODE_OPERATOR != nodeType(pCond)) { return false; } - SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets; - SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets; + SOperatorNode* pOper = (SOperatorNode*)pJoin->pOnConditions; + if (OP_TYPE_EQUAL != pOper->opType) { + return false; + } + + SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets; + SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets; if (cpdIsPrimaryKey(pOper->pLeft, pLeftCols)) { return cpdIsPrimaryKey(pOper->pRight, pRightCols); } else if (cpdIsPrimaryKey(pOper->pLeft, pRightCols)) { diff --git a/source/libs/planner/test/planOptimizeTest.cpp b/source/libs/planner/test/planOptimizeTest.cpp index deb20c65a4..4938618db6 100644 --- a/source/libs/planner/test/planOptimizeTest.cpp +++ b/source/libs/planner/test/planOptimizeTest.cpp @@ -20,11 +20,21 @@ using namespace std; class PlanOptimizeTest : public PlannerTestBase {}; +TEST_F(PlanOptimizeTest, optimizeScanData) { + useDb("root", "test"); + + run("SELECT COUNT(*) FROM t1"); + + run("SELECT COUNT(c1) FROM t1"); + + run("SELECT COUNT(CAST(c1 AS BIGINT)) FROM t1"); +} + TEST_F(PlanOptimizeTest, orderByPrimaryKey) { useDb("root", "test"); - run("select * from t1 order by ts"); - run("select * from t1 order by ts desc"); - run("select c1 from t1 order by ts"); - run("select c1 from t1 order by ts desc"); + run("SELECT * FROM t1 ORDER BY ts"); + run("SELECT * FROM t1 ORDER BY ts DESC"); + run("SELECT c1 FROM t1 ORDER BY ts"); + run("SELECT c1 FROM t1 ORDER BY ts DESC"); } diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index a70d366e9b..53772601ca 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -22,7 +22,7 @@ #include "trpc.h" SSchedulerMgmt schMgmt = { - .jobRef = -1, + .jobRef = -1, }; FORCE_INLINE SSchJob *schAcquireJob(int64_t refId) { return (SSchJob *)taosAcquireRef(schMgmt.jobRef, refId); } @@ -72,7 +72,7 @@ int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel * int32_t schInitJob(SSchJob **pSchJob, SQueryPlan *pDag, void *transport, SArray *pNodeList, const char *sql, int64_t startTs, bool syncSchedule) { int32_t code = 0; - int64_t refId = -1; + int64_t refId = -1; SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); if (NULL == pJob) { qError("QID:%" PRIx64 " calloc %d failed", pDag->queryId, (int32_t)sizeof(SSchJob)); @@ -124,7 +124,7 @@ int32_t schInitJob(SSchJob **pSchJob, SQueryPlan *pDag, void *transport, SArray } atomic_add_fetch_32(&schMgmt.jobNum, 1); - + if (NULL == schAcquireJob(refId)) { SCH_JOB_ELOG("schAcquireJob job failed, refId:%" PRIx64, refId); SCH_ERR_JRET(TSDB_CODE_SCH_STATUS_ERROR); @@ -1085,19 +1085,22 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch case TDMT_VND_CREATE_TABLE_RSP: { SVCreateTbBatchRsp batchRsp = {0}; if (msg) { - SCH_ERR_JRET(tDeserializeSVCreateTbBatchRsp(msg, msgSize, &batchRsp)); - if (batchRsp.pArray) { - int32_t num = taosArrayGetSize(batchRsp.pArray); - for (int32_t i = 0; i < num; ++i) { - SVCreateTbRsp *rsp = taosArrayGet(batchRsp.pArray, i); + SCoder coder = {0}; + tCoderInit(&coder, TD_LITTLE_ENDIAN, msg, msgSize, TD_DECODER); + code = tDecodeSVCreateTbBatchRsp(&coder, &batchRsp); + if (TSDB_CODE_SUCCESS == code && batchRsp.nRsps > 0) { + for (int32_t i = 0; i < batchRsp.nRsps; ++i) { + SVCreateTbRsp *rsp = batchRsp.pRsps + i; if (NEED_CLIENT_HANDLE_ERROR(rsp->code)) { - taosArrayDestroy(batchRsp.pArray); + tCoderClear(&coder); SCH_ERR_JRET(rsp->code); + } else if (TSDB_CODE_SUCCESS != rsp->code) { + code = rsp->code; } } - - taosArrayDestroy(batchRsp.pArray); } + tCoderClear(&coder); + SCH_ERR_JRET(code); } SCH_ERR_JRET(rspCode); @@ -1110,13 +1113,14 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t msgType, ch SCoder coder = {0}; tCoderInit(&coder, TD_LITTLE_ENDIAN, msg, msgSize, TD_DECODER); code = tDecodeSVDropTbBatchRsp(&coder, &batchRsp); - if (TSDB_CODE_SUCCESS == code && batchRsp.pArray) { - int32_t num = taosArrayGetSize(batchRsp.pArray); - for (int32_t i = 0; i < num; ++i) { - SVDropTbRsp *rsp = taosArrayGet(batchRsp.pArray, i); + if (TSDB_CODE_SUCCESS == code && batchRsp.nRsps > 0) { + for (int32_t i = 0; i < batchRsp.nRsps; ++i) { + SVDropTbRsp *rsp = batchRsp.pRsps + i; if (NEED_CLIENT_HANDLE_ERROR(rsp->code)) { tCoderClear(&coder); SCH_ERR_JRET(rsp->code); + } else if (TSDB_CODE_SUCCESS != rsp->code) { + code = rsp->code; } } } @@ -2282,10 +2286,10 @@ int32_t schCancelJob(SSchJob *pJob) { } void schCloseJobRef(void) { - if (!atomic_load_8((int8_t*)&schMgmt.exit)) { + if (!atomic_load_8((int8_t *)&schMgmt.exit)) { return; } - + SCH_LOCK(SCH_WRITE, &schMgmt.lock); if (atomic_load_32(&schMgmt.jobNum) <= 0 && schMgmt.jobRef >= 0) { taosCloseRef(schMgmt.jobRef); @@ -2791,8 +2795,8 @@ void schedulerFreeTaskList(SArray *taskList) { } void schedulerDestroy(void) { - atomic_store_8((int8_t*)&schMgmt.exit, 1); - + atomic_store_8((int8_t *)&schMgmt.exit, 1); + if (schMgmt.jobRef >= 0) { SSchJob *pJob = taosIterateRef(schMgmt.jobRef, 0); int64_t refId = 0; diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 00fe8bd0e9..1470496c68 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -443,6 +443,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SCH_STATUS_ERROR, "scheduler status erro TAOS_DEFINE_ERROR(TSDB_CODE_SCH_INTERNAL_ERROR, "scheduler internal error") TAOS_DEFINE_ERROR(TSDB_CODE_QW_MSG_ERROR, "Invalid msg order") +// parser +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TABLE_NOT_EXIST, "Table does not exist") + //planner TAOS_DEFINE_ERROR(TSDB_CODE_PLAN_INTERNAL_ERROR, "planner internal error") diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000000..ce459414c4 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,5 @@ +taospy +numpy +fabric2 +psutil +pandas diff --git a/tests/script/tsim/query/explain.sim b/tests/script/tsim/query/explain.sim index 66d3c48f5d..71f7969c83 100644 --- a/tests/script/tsim/query/explain.sim +++ b/tests/script/tsim/query/explain.sim @@ -25,15 +25,15 @@ sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=2 sql create table tb4 using st1 tags(4); sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); -sql create table tb1 using st2 tags(1); -sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); +#sql create table tb1 using st2 tags(1); +#sql insert into tb1 values (now, 1, "Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)"); -sql create table tb2 using st2 tags(2); -sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); -sql create table tb3 using st2 tags(3); -sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); -sql create table tb4 using st2 tags(4); -sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); +#sql create table tb2 using st2 tags(2); +#sql insert into tb2 values (now, 2, "Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)"); +#sql create table tb3 using st2 tags(3); +#sql insert into tb3 values (now, 3, "Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)"); +#sql create table tb4 using st2 tags(4); +#sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); print ======== step2 diff --git a/tests/script/tsim/query/session.sim b/tests/script/tsim/query/session.sim index a69b6249fc..c39956c0df 100644 --- a/tests/script/tsim/query/session.sim +++ b/tests/script/tsim/query/session.sim @@ -65,6 +65,15 @@ sql INSERT INTO dev_002 VALUES('2020-05-13 10:00:00.031', 5) sql INSERT INTO dev_002 VALUES('2020-05-13 10:00:00.036', 6) sql INSERT INTO dev_002 VALUES('2020-05-13 10:00:00.51', 7) +# vnode does not return the precision of the table +print ====> create database d1 precision 'us' +sql create database d1 precision 'us' +sql use d1 +sql create table dev_001 (ts timestamp ,i timestamp ,j int) +sql insert into dev_001 values(1623046993681000,now,1)(1623046993681001,now+1s,2)(1623046993681002,now+2s,3)(1623046993681004,now+5s,4) +sql create table secondts(ts timestamp,t2 timestamp,i int) +sql insert into secondts values(1623046993681000,now,1)(1623046993681001,now+1s,2)(1623046993681002,now+2s,3)(1623046993681004,now+5s,4) + $loop_test = 0 loop_test_pos: @@ -288,15 +297,6 @@ sql_error sql select count(*) from dev_001 session(ts,0s) sql_error select count(*) from dev_001 session(i,1y) sql_error select count(*) from dev_001 session(ts,1d) where ts <'2020-05-20 0:0:0' -# vnode does not return the precision of the table -print ====> create database d1 precision 'us' -sql create database d1 precision 'us' -sql use d1 -sql create table dev_001 (ts timestamp ,i timestamp ,j int) -sql insert into dev_001 values(1623046993681000,now,1)(1623046993681001,now+1s,2)(1623046993681002,now+2s,3)(1623046993681004,now+5s,4) -sql create table secondts(ts timestamp,t2 timestamp,i int) -sql insert into secondts values(1623046993681000,now,1)(1623046993681001,now+1s,2)(1623046993681002,now+2s,3)(1623046993681004,now+5s,4) - #print ====> select count(*) from dev_001 session(ts,1u) #sql select _wstartts, count(*) from dev_001 session(ts,1u) #print rows: $rows diff --git a/tests/script/tsim/query/udf.sim b/tests/script/tsim/query/udf.sim index 8acd07cfe4..c76569b40f 100644 --- a/tests/script/tsim/query/udf.sim +++ b/tests/script/tsim/query/udf.sim @@ -43,6 +43,27 @@ if $data00 != 2.236067977 then return -1 endi +sql create table t2 (ts timestamp, f1 int, f2 int); +sql insert into t2 values(now, 0, 0)(now+1s, 1, 1); +sql select udf1(f1, f2) from t2; +if $rows != 2 then + return -1 +endi +if $data00 != 88 then + return -1 +endi +if $data10 != 88 then + return -1 +endi + +sql select udf2(f1, f2) from t2; +if $rows != 1 then + return -1 +endi +if $data00 != 1.414213562 then + return -1 +endi + #sql drop function udf1; #sql drop function udf2; system sh/exec.sh -n dnode1 -s stop -x SIGKILL diff --git a/tests/script/tsim/table/basic1.sim b/tests/script/tsim/table/basic1.sim index be3b718fae..913ced74aa 100644 --- a/tests/script/tsim/table/basic1.sim +++ b/tests/script/tsim/table/basic1.sim @@ -91,9 +91,9 @@ print =============== create normal table sql create database ndb sql use ndb sql create table nt0 (ts timestamp, i int) -sql create table if not exists nt0 (ts timestamp, i int) +# sql create table if not exists nt0 (ts timestamp, i int) sql create table nt1 (ts timestamp, i int) -sql create table if not exists nt1 (ts timestamp, i int) +# sql create table if not exists nt1 (ts timestamp, i int) sql create table if not exists nt3 (ts timestamp, i int) sql show tables diff --git a/tests/system-test/2-query/join.py b/tests/system-test/2-query/join.py index b4878e42c9..a39bc21946 100644 --- a/tests/system-test/2-query/join.py +++ b/tests/system-test/2-query/join.py @@ -5,6 +5,7 @@ from util.sql import * from util.cases import * from util.dnodes import * +PRIMARY_COL = "ts" INT_COL = "c1" BINT_COL = "c2" @@ -18,9 +19,10 @@ BINARY_COL = "c8" NCHAR_COL = "c9" TS_COL = "c10" -UN_CHAR_COL = [INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, BOOL_COL, ] +NUM_COL = [ INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, ] CHAR_COL = [ BINARY_COL, NCHAR_COL, ] -TS_TYPE_COL = [TS_COL] +BOOLEAN_COL = [ BOOL_COL, ] +TS_TYPE_COL = [ TS_COL, ] class TDTestCase: @@ -28,88 +30,171 @@ class TDTestCase: tdLog.debug(f"start to excute {__file__}") tdSql.init(conn.cursor()) - def __length_condition(self): - length_condition = [] + def __query_condition(self,tbname): + query_condition = [] for char_col in CHAR_COL: - length_condition.extend( + query_condition.extend( ( - char_col, - f"upper( {char_col} )", + f"{tbname}.{char_col}", + f"upper( {tbname}.{char_col} )", ) ) - length_condition.extend( f"cast( {un_char_col} as binary(16) ) " for un_char_col in UN_CHAR_COL) - length_condition.extend( f"cast( {char_col} + {char_col_2} as binary(32) ) " for char_col_2 in CHAR_COL ) - length_condition.extend( f"cast( {char_col} + {un_char_col} as binary(32) ) " for un_char_col in UN_CHAR_COL ) + query_condition.extend( f"cast( {tbname}.{un_char_col} as binary(16) ) " for un_char_col in NUM_COL) + query_condition.extend( f"cast( {tbname}.{char_col} + {tbname}.{char_col_2} as binary(32) ) " for char_col_2 in CHAR_COL ) + query_condition.extend( f"cast( {tbname}.{char_col} + {tbname}.{un_char_col} as binary(32) ) " for un_char_col in NUM_COL ) + for num_col in NUM_COL: + query_condition.extend( + ( + f"{tbname}.{num_col}", + f"sin( {tbname}.{num_col} )" + ) + ) + query_condition.extend( f"{tbname}.{num_col} + {tbname}.{num_col_1} " for num_col_1 in NUM_COL ) - length_condition.append('''"test1234!@#$%^&*():'> 0 " - return "" + def __join_condition(self, tb_list, filter=PRIMARY_COL): + # sourcery skip: flip-comparison + if 1 == len(tb_list): + join_filter = f"{tb_list[0]}.{filter} = {tb_list[0]}.{filter} " + elif 2 == len(tb_list): + join_filter = f"{tb_list[0]}.{filter} = {tb_list[1]}.{filter} " + else: + join_filter = f"{tb_list[0]}.{filter} = {tb_list[1]}.{filter} " + for i in range(1, len(tb_list)-1 ): + join_filter += f"and {tb_list[i]}.{filter} = {tb_list[i+1]}.{filter}" - def __group_condition(self, col, having = ""): + return join_filter + + def __where_condition(self, col, tbname): + if col in NUM_COL: + return f" abs( {tbname}.{col} ) >= 0" + elif col in CHAR_COL: + return f" lower( {tbname}.{col} ) like 'bina%' or lower( {tbname}.{col} ) like '_cha%' " + elif col in BOOLEAN_COL: + return f" {tbname}.{col} in (false, true) " + elif col in TS_TYPE_COL or col in PRIMARY_COL: + return f" cast( {tbname}.{col} as binary(16) ) is not null " + else: + return "" + + def __group_condition(self, tbname, col, having = ""): return f" group by {col} having {having}" if having else f" group by {col} " - def __length_current_check(self, tbname): - length_condition = self.__length_condition() - for condition in length_condition: - where_condition = self.__where_condition(condition) - group_having = self.__group_condition(condition, having=f"{condition} is not null " ) - group_no_having= self.__group_condition(condition ) + def __join_check(self, tblist, checkrows, join_flag=True): + query_conditions = self.__query_condition(tblist[0]) + join_condition = self.__join_condition(tb_list=tblist) if join_flag else " " + for condition in query_conditions: + where_condition = self.__where_condition(col=condition, tbname=tblist[0]) + group_having = self.__group_condition(tbname=tblist[0], col=condition, having=f"{condition} is not null " ) + group_no_having= self.__group_condition(tbname=tblist[0], col=condition ) groups = ["", group_having, group_no_having] - for group_condition in groups: - tdSql.query(f"select {condition} from {tbname} {where_condition} {group_condition} ") - datas = [tdSql.getData(i,0) for i in range(tdSql.queryRows)] - length_data = [ len(str(data)) if data else None for data in datas ] - tdSql.query(f"select length( {condition} ) from {tbname} {where_condition} {group_condition}") - for i in range(len(length_data)): - tdSql.checkData(i, 0, length_data[i] ) if length_data[i] else tdSql.checkData(i, 0, None) + if where_condition: + sql = f" select {condition} from {tblist[0]},{tblist[1]} where {join_condition} and {where_condition} {group_condition} " + else: + sql = f" select {condition} from {tblist[0]},{tblist[1]} where {join_condition} {group_condition} " - def __length_err_check(self,tbname): - sqls = [] + if not join_flag : + tdSql.error(sql=sql) + if len(tblist) == 2: + if "ct1" in tblist or "t1" in tblist: + self.__join_current(sql, checkrows) + elif where_condition or "not null" in group_condition: + self.__join_current(sql, checkrows + 2 ) + elif group_condition: + self.__join_current(sql, checkrows + 3 ) + else: + self.__join_current(sql, checkrows + 5 ) + if len(tblist) > 2 or len(tblist) < 1: + tdSql.error(sql=sql) - for un_char_col in UN_CHAR_COL: - sqls.extend( - ( - f"select length( {un_char_col} ) from {tbname} ", - f"select length(ceil( {un_char_col} )) from {tbname} ", - f"select {un_char_col} from {tbname} group by length( {un_char_col} ) ", - ) - ) + # def __join_err_check(self,tbname): + # sqls = [] - sqls.extend( f"select length( {un_char_col} + {un_char_col_2} ) from {tbname} " for un_char_col_2 in UN_CHAR_COL ) - sqls.extend( f"select length( {un_char_col} + {ts_col} ) from {tbname} " for ts_col in TS_TYPE_COL ) + # for un_char_col in NUM_COL: + # sqls.extend( + # ( + # f"select length( {un_char_col} ) from {tbname} ", + # f"select length(ceil( {un_char_col} )) from {tbname} ", + # f"select {un_char_col} from {tbname} group by length( {un_char_col} ) ", + # ) + # ) - sqls.extend( f"select {char_col} from {tbname} group by length( {char_col} ) " for char_col in CHAR_COL) - sqls.extend( f"select length( {ts_col} ) from {tbname} " for ts_col in TS_TYPE_COL ) - sqls.extend( f"select length( {char_col} + {ts_col} ) from {tbname} " for char_col in UN_CHAR_COL for ts_col in TS_TYPE_COL) - sqls.extend( f"select length( {char_col} + {char_col_2} ) from {tbname} " for char_col in CHAR_COL for char_col_2 in CHAR_COL ) - sqls.extend( f"select upper({char_col}, 11) from {tbname} " for char_col in CHAR_COL ) - sqls.extend( f"select upper({char_col}) from {tbname} interval(2d) sliding(1d)" for char_col in CHAR_COL ) - sqls.extend( - ( - f"select length() from {tbname} ", - f"select length(*) from {tbname} ", - f"select length(ccccccc) from {tbname} ", - f"select length(111) from {tbname} ", - f"select length(c8, 11) from {tbname} ", - ) - ) + # sqls.extend( f"select length( {un_char_col} + {un_char_col_2} ) from {tbname} " for un_char_col_2 in NUM_COL ) + # sqls.extend( f"select length( {un_char_col} + {ts_col} ) from {tbname} " for ts_col in TS_TYPE_COL ) + + # sqls.extend( f"select {char_col} from {tbname} group by length( {char_col} ) " for char_col in CHAR_COL) + # sqls.extend( f"select length( {ts_col} ) from {tbname} " for ts_col in TS_TYPE_COL ) + # sqls.extend( f"select length( {char_col} + {ts_col} ) from {tbname} " for char_col in NUM_COL for ts_col in TS_TYPE_COL) + # sqls.extend( f"select length( {char_col} + {char_col_2} ) from {tbname} " for char_col in CHAR_COL for char_col_2 in CHAR_COL ) + # sqls.extend( f"select upper({char_col}, 11) from {tbname} " for char_col in CHAR_COL ) + # sqls.extend( f"select upper({char_col}) from {tbname} interval(2d) sliding(1d)" for char_col in CHAR_COL ) + # sqls.extend( + # ( + # f"select length() from {tbname} ", + # f"select length(*) from {tbname} ", + # f"select length(ccccccc) from {tbname} ", + # f"select length(111) from {tbname} ", + # f"select length(c8, 11) from {tbname} ", + # ) + # ) + + # return sqls + + def __join_current(self, sql, checkrows): + tdSql.query(sql=sql) + tdSql.checkRows(checkrows) - return sqls def __test_current(self): + # sourcery skip: extract-duplicate-method, inline-immediately-returned-variable tdLog.printNoPrefix("==========current sql condition check , must return query ok==========") - tbname = ["ct1", "ct2", "ct4", "t1"] - for tb in tbname: - self.__length_current_check(tb) - tdLog.printNoPrefix(f"==========current sql condition check in {tb} over==========") + tblist_1 = ["ct1", "ct2"] + self.__join_check(tblist_1, 1) + tdLog.printNoPrefix(f"==========current sql condition check in {tblist_1} over==========") + tblist_2 = ["ct2", "ct4"] + self.__join_check(tblist_2, self.rows) + tdLog.printNoPrefix(f"==========current sql condition check in {tblist_2} over==========") + tblist_3 = ["t1", "ct4"] + self.__join_check(tblist_3, 1) + tdLog.printNoPrefix(f"==========current sql condition check in {tblist_3} over==========") + tblist_4 = ["t1", "ct1"] + self.__join_check(tblist_4, 1) + tdLog.printNoPrefix(f"==========current sql condition check in {tblist_4} over==========") def __test_error(self): + # sourcery skip: extract-duplicate-method, move-assign-in-block tdLog.printNoPrefix("==========err sql condition check , must return error==========") + err_list_1 = ["ct1","ct2", "ct4"] + err_list_2 = ["ct1","ct2", "t1"] + err_list_3 = ["ct1","ct4", "t1"] + err_list_4 = ["ct2","ct4", "t1"] + err_list_5 = ["ct1", "ct2","ct4", "t1"] + self.__join_check(err_list_1, -1) + tdLog.printNoPrefix(f"==========err sql condition check in {err_list_1} over==========") + self.__join_check(err_list_2, -1) + tdLog.printNoPrefix(f"==========err sql condition check in {err_list_2} over==========") + self.__join_check(err_list_3, -1) + tdLog.printNoPrefix(f"==========err sql condition check in {err_list_3} over==========") + self.__join_check(err_list_4, -1) + tdLog.printNoPrefix(f"==========err sql condition check in {err_list_4} over==========") + self.__join_check(err_list_5, -1) + tdLog.printNoPrefix(f"==========err sql condition check in {err_list_5} over==========") + self.__join_check(["ct2", "ct4"], -1, join_flag=False) + tdLog.printNoPrefix("==========err sql condition check in has no join condition over==========") + + tdSql.error( f"select c1, c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL}" ) + tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{INT_COL}=ct4.{INT_COL}" ) + tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{TS_COL}=ct4.{TS_COL}" ) + tdSql.error( f"select ct2.c1, ct2.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{TS_COL}" ) + tdSql.error( f"select ct2.c1, ct1.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL}" ) + tdSql.error( f"select ct2.c1, ct4.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL} and c1 is not null " ) + tdSql.error( f"select ct2.c1, ct4.c2 from ct2, ct4 where ct2.{PRIMARY_COL}=ct4.{PRIMARY_COL} and ct1.c1 is not null " ) + + tbname = ["ct1", "ct2", "ct4", "t1"] for tb in tbname: @@ -150,33 +235,33 @@ class TDTestCase: now_time = int(datetime.datetime.timestamp(datetime.datetime.now()) * 1000) for i in range(rows): tdSql.execute( - f"insert into ct1 values ( { now_time - i * 1000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar{i}', { now_time + 1 * i } )" + f"insert into ct1 values ( { now_time - i * 1000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" ) tdSql.execute( - f"insert into ct4 values ( { now_time - i * 7776000000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar{i}', { now_time + 1 * i } )" + f"insert into ct4 values ( { now_time - i * 7776000000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" ) tdSql.execute( - f"insert into ct2 values ( { now_time - i * 7776000000 }, {-i}, {-11111 * i}, {-111 * i % 32767 }, {-11 * i % 127}, {-1.11*i}, {-1100.0011*i}, {i%2}, 'binary{i}', 'nchar{i}', { now_time + 1 * i } )" + f"insert into ct2 values ( { now_time - i * 7776000000 }, {-i}, {-11111 * i}, {-111 * i % 32767 }, {-11 * i % 127}, {-1.11*i}, {-1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" ) tdSql.execute( f'''insert into ct1 values - ( { now_time - rows * 5 }, 0, 0, 0, 0, 0, 0, 0, 'binary0', 'nchar0', { now_time + 8 } ) - ( { now_time + 10000 }, { rows }, -99999, -999, -99, -9.99, -99.99, 1, 'binary9', 'nchar9', { now_time + 9 } ) + ( { now_time - rows * 5 }, 0, 0, 0, 0, 0, 0, 0, 'binary0', 'nchar_测试_0', { now_time + 8 } ) + ( { now_time + 10000 }, { rows }, -99999, -999, -99, -9.99, -99.99, 1, 'binary9', 'nchar_测试_9', { now_time + 9 } ) ''' ) tdSql.execute( f'''insert into ct4 values ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - rows * 3888000000+ 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 5184000000}, {pow(2,31)-pow(2,15)}, {pow(2,63)-pow(2,30)}, 32767, 127, - { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_limit-1", { now_time - 86400000} + { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000} ) ( { now_time + 2592000000 }, {pow(2,31)-pow(2,16)}, {pow(2,63)-pow(2,31)}, 32766, 126, - { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_limit-2", { now_time - 172800000} + { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000} ) ''' ) @@ -184,15 +269,15 @@ class TDTestCase: tdSql.execute( f'''insert into ct2 values ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - rows * 3888000000+ 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 5184000000 }, { -1 * pow(2,31) + pow(2,15) }, { -1 * pow(2,63) + pow(2,30) }, -32766, -126, - { -1 * 3.2 * pow(10,38) }, { -1.2 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_limit-1", { now_time - 86400000 } + { -1 * 3.2 * pow(10,38) }, { -1.2 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 } ) ( { now_time + 2592000000 }, { -1 * pow(2,31) + pow(2,16) }, { -1 * pow(2,63) + pow(2,31) }, -32767, -127, - { - 3.3 * pow(10,38) }, { -1.3 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_limit-2", { now_time - 172800000 } + { - 3.3 * pow(10,38) }, { -1.3 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 } ) ''' ) @@ -200,7 +285,7 @@ class TDTestCase: for i in range(rows): insert_data = f'''insert into t1 values ( { now_time - i * 3600000 }, {i}, {i * 11111}, { i % 32767 }, { i % 127}, { i * 1.11111 }, { i * 1000.1111 }, { i % 2}, - "binary_{i}", "nchar_{i}", { now_time - 1000 * i } ) + "binary_{i}", "nchar_测试_{i}", { now_time - 1000 * i } ) ''' tdSql.execute(insert_data) tdSql.execute( @@ -210,12 +295,12 @@ class TDTestCase: ( { now_time - rows * 3600000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 7200000 }, { pow(2,31) - pow(2,15) }, { pow(2,63) - pow(2,30) }, 32767, 127, { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, - "binary_limit-1", "nchar_limit-1", { now_time - 86400000 } + "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 } ) ( { now_time + 3600000 } , { pow(2,31) - pow(2,16) }, { pow(2,63) - pow(2,31) }, 32766, 126, { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, - "binary_limit-2", "nchar_limit-2", { now_time - 172800000 } + "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 } ) ''' ) @@ -228,7 +313,8 @@ class TDTestCase: self.__create_tb() tdLog.printNoPrefix("==========step2:insert data") - self.__insert_data(10) + self.rows = 10 + self.__insert_data(self.rows) tdLog.printNoPrefix("==========step3:all check") self.all_test() diff --git a/tests/system-test/2-query/sqrt.py b/tests/system-test/2-query/sqrt.py new file mode 100644 index 0000000000..28e869e044 --- /dev/null +++ b/tests/system-test/2-query/sqrt.py @@ -0,0 +1,551 @@ +import taos +import sys +import datetime +import inspect +import math +from util.log import * +from util.sql import * +from util.cases import * + + +class TDTestCase: + updatecfgDict = {'debugFlag': 143 ,"cDebugFlag":143,"uDebugFlag":143 ,"rpcDebugFlag":143 , "tmrDebugFlag":143 , + "jniDebugFlag":143 ,"simDebugFlag":143,"dDebugFlag":143, "dDebugFlag":143,"vDebugFlag":143,"mDebugFlag":143,"qDebugFlag":143, + "wDebugFlag":143,"sDebugFlag":143,"tsdbDebugFlag":143,"tqDebugFlag":143 ,"fsDebugFlag":143 ,"fnDebugFlag":143} + def init(self, conn, powSql): + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + + def prepare_datas(self): + tdSql.execute( + '''create table stb1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + tags (t1 int) + ''' + ) + + tdSql.execute( + ''' + create table t1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + ''' + ) + for i in range(4): + tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + + for i in range(9): + tdSql.execute( + f"insert into ct1 values ( now()-{i*10}s, {1*i}, {11111*i}, {111*i}, {11*i}, {1.11*i}, {11.11*i}, {i%2}, 'binary{i}', 'nchar{i}', now()+{1*i}a )" + ) + tdSql.execute( + f"insert into ct4 values ( now()-{i*90}d, {1*i}, {11111*i}, {111*i}, {11*i}, {1.11*i}, {11.11*i}, {i%2}, 'binary{i}', 'nchar{i}', now()+{1*i}a )" + ) + tdSql.execute("insert into ct1 values (now()-45s, 0, 0, 0, 0, 0, 0, 0, 'binary0', 'nchar0', now()+8a )") + tdSql.execute("insert into ct1 values (now()+10s, 9, -99999, -999, -99, -9.99, -99.99, 1, 'binary9', 'nchar9', now()+9a )") + tdSql.execute("insert into ct1 values (now()+15s, 9, -99999, -999, -99, -9.99, NULL, 1, 'binary9', 'nchar9', now()+9a )") + tdSql.execute("insert into ct1 values (now()+20s, 9, -99999, -999, NULL, -9.99, -99.99, 1, 'binary9', 'nchar9', now()+9a )") + + tdSql.execute("insert into ct4 values (now()-810d, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ") + tdSql.execute("insert into ct4 values (now()-400d, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ") + tdSql.execute("insert into ct4 values (now()+90d, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ") + + tdSql.execute( + f'''insert into t1 values + ( '2020-04-21 01:01:01.000', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( '2020-10-21 01:01:01.000', 1, 11111, 111, 11, 1.11, 11.11, 1, "binary1", "nchar1", now()+1a ) + ( '2020-12-31 01:01:01.000', 2, 22222, 222, 22, 2.22, 22.22, 0, "binary2", "nchar2", now()+2a ) + ( '2021-01-01 01:01:06.000', 3, 33333, 333, 33, 3.33, 33.33, 0, "binary3", "nchar3", now()+3a ) + ( '2021-05-07 01:01:10.000', 4, 44444, 444, 44, 4.44, 44.44, 1, "binary4", "nchar4", now()+4a ) + ( '2021-07-21 01:01:01.000', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( '2021-09-30 01:01:16.000', 5, 55555, 555, 55, 5.55, 55.55, 0, "binary5", "nchar5", now()+5a ) + ( '2022-02-01 01:01:20.000', 6, 66666, 666, 66, 6.66, 66.66, 1, "binary6", "nchar6", now()+6a ) + ( '2022-10-28 01:01:26.000', 7, 00000, 000, 00, 0.00, 00.00, 1, "binary7", "nchar7", "1970-01-01 08:00:00.000" ) + ( '2022-12-01 01:01:30.000', 8, -88888, -888, -88, -8.88, -88.88, 0, "binary8", "nchar8", "1969-01-01 01:00:00.000" ) + ( '2022-12-31 01:01:36.000', 9, -99999999999999999, -999, -99, -9.99, -999999999999999999999.99, 1, "binary9", "nchar9", "1900-01-01 00:00:00.000" ) + ( '2023-02-21 01:01:01.000', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ''' + ) + + def check_result_auto_sqrt(self ,origin_query , pow_query): + + pow_result = tdSql.getResult(pow_query) + origin_result = tdSql.getResult(origin_query) + + auto_result =[] + + for row in origin_result: + row_check = [] + for elem in row: + if elem == None: + elem = None + elif elem < 0: + elem = None + else: + elem = math.sqrt(elem) + row_check.append(elem) + auto_result.append(row_check) + + check_status = True + + for row_index , row in enumerate(pow_result): + for col_index , elem in enumerate(row): + if auto_result[row_index][col_index] == None and not (auto_result[row_index][col_index] == None and elem == None): + check_status = False + elif auto_result[row_index][col_index] != None and (auto_result[row_index][col_index] - elem > 0.00000001): + check_status = False + else: + pass + if not check_status: + tdLog.notice("sqrt function value has not as expected , sql is \"%s\" "%pow_query ) + sys.exit(1) + else: + tdLog.info("sqrt value check pass , it work as expected ,sql is \"%s\" "%pow_query ) + + def test_errors(self): + error_sql_lists = [ + "select sqrt from t1", + # "select sqrt(-+--+c1 ) from t1", + # "select +-sqrt(c1) from t1", + # "select ++-sqrt(c1) from t1", + # "select ++--sqrt(c1) from t1", + # "select - -sqrt(c1)*0 from t1", + # "select sqrt(tbname+1) from t1 ", + "select sqrt(123--123)==1 from t1", + "select sqrt(c1) as 'd1' from t1", + "select sqrt(c1 ,c2) from t1", + "select sqrt(c1 ,NULL ) from t1", + "select sqrt(,) from t1;", + "select sqrt(sqrt(c1) ab from t1)", + "select sqrt(c1 ) as int from t1", + "select sqrt from stb1", + # "select sqrt(-+--+c1) from stb1", + # "select +-sqrt(c1) from stb1", + # "select ++-sqrt(c1) from stb1", + # "select ++--sqrt(c1) from stb1", + # "select - -sqrt(c1)*0 from stb1", + # "select sqrt(tbname+1) from stb1 ", + "select sqrt(123--123)==1 from stb1", + "select sqrt(c1) as 'd1' from stb1", + "select sqrt(c1 ,c2 ) from stb1", + "select sqrt(c1 ,NULL) from stb1", + "select sqrt(,) from stb1;", + "select sqrt(sqrt(c1) ab from stb1)", + "select sqrt(c1) as int from stb1" + ] + for error_sql in error_sql_lists: + tdSql.error(error_sql) + + def support_types(self): + type_error_sql_lists = [ + "select sqrt(ts) from t1" , + "select sqrt(c7) from t1", + "select sqrt(c8) from t1", + "select sqrt(c9) from t1", + "select sqrt(ts) from ct1" , + "select sqrt(c7) from ct1", + "select sqrt(c8) from ct1", + "select sqrt(c9) from ct1", + "select sqrt(ts) from ct3" , + "select sqrt(c7) from ct3", + "select sqrt(c8) from ct3", + "select sqrt(c9) from ct3", + "select sqrt(ts) from ct4" , + "select sqrt(c7) from ct4", + "select sqrt(c8) from ct4", + "select sqrt(c9) from ct4", + "select sqrt(ts) from stb1" , + "select sqrt(c7) from stb1", + "select sqrt(c8) from stb1", + "select sqrt(c9) from stb1" , + + "select sqrt(ts) from stbbb1" , + "select sqrt(c7) from stbbb1", + + "select sqrt(ts) from tbname", + "select sqrt(c9) from tbname" + + ] + + for type_sql in type_error_sql_lists: + tdSql.error(type_sql) + + + type_sql_lists = [ + "select sqrt(c1) from t1", + "select sqrt(c2) from t1", + "select sqrt(c3) from t1", + "select sqrt(c4) from t1", + "select sqrt(c5) from t1", + "select sqrt(c6) from t1", + + "select sqrt(c1) from ct1", + "select sqrt(c2) from ct1", + "select sqrt(c3) from ct1", + "select sqrt(c4) from ct1", + "select sqrt(c5) from ct1", + "select sqrt(c6) from ct1", + + "select sqrt(c1) from ct3", + "select sqrt(c2) from ct3", + "select sqrt(c3) from ct3", + "select sqrt(c4) from ct3", + "select sqrt(c5) from ct3", + "select sqrt(c6) from ct3", + + "select sqrt(c1) from stb1", + "select sqrt(c2) from stb1", + "select sqrt(c3) from stb1", + "select sqrt(c4) from stb1", + "select sqrt(c5) from stb1", + "select sqrt(c6) from stb1", + + "select sqrt(c6) as alisb from stb1", + "select sqrt(c6) alisb from stb1", + ] + + for type_sql in type_sql_lists: + tdSql.query(type_sql) + + def basic_sqrt_function(self): + + # basic query + tdSql.query("select c1 from ct3") + tdSql.checkRows(0) + tdSql.query("select c1 from t1") + tdSql.checkRows(12) + tdSql.query("select c1 from stb1") + tdSql.checkRows(25) + + # used for empty table , ct3 is empty + tdSql.query("select sqrt(c1) from ct3") + tdSql.checkRows(0) + tdSql.query("select sqrt(c2) from ct3") + tdSql.checkRows(0) + tdSql.query("select sqrt(c3) from ct3") + tdSql.checkRows(0) + tdSql.query("select sqrt(c4) from ct3") + tdSql.checkRows(0) + tdSql.query("select sqrt(c5) from ct3") + tdSql.checkRows(0) + tdSql.query("select sqrt(c6) from ct3") + tdSql.checkRows(0) + + + # # used for regular table + tdSql.query("select sqrt(c1) from t1") + tdSql.checkData(0, 0, None) + tdSql.checkData(1 , 0, 1.000000000) + tdSql.checkData(3 , 0, 1.732050808) + tdSql.checkData(5 , 0, None) + + tdSql.query("select c1, c2, c3 , c4, c5 from t1") + tdSql.checkData(1, 4, 1.11000) + tdSql.checkData(3, 3, 33) + tdSql.checkData(5, 4, None) + + tdSql.query("select ts,c1, c2, c3 , c4, c5 from t1") + tdSql.checkData(1, 5, 1.11000) + tdSql.checkData(3, 4, 33) + tdSql.checkData(5, 5, None) + + self.check_result_auto_sqrt( "select abs(c1), abs(c2), abs(c3) , abs(c4), abs(c5) from t1", "select sqrt(abs(c1)), sqrt(abs(c2)) ,sqrt(abs(c3)), sqrt(abs(c4)), sqrt(abs(c5)) from t1") + + # used for sub table + tdSql.query("select c2 ,sqrt(c2) from ct1") + tdSql.checkData(0, 1, 298.140906284) + tdSql.checkData(1 , 1, 278.885281074) + tdSql.checkData(3 , 1, 235.701081881) + tdSql.checkData(4 , 1, 0.000000000) + + tdSql.query("select c1, c5 ,sqrt(c5) from ct4") + tdSql.checkData(0 , 2, None) + tdSql.checkData(1 , 2, 2.979932904) + tdSql.checkData(2 , 2, 2.787471970) + tdSql.checkData(3 , 2, 2.580697551) + tdSql.checkData(5 , 2, None) + + self.check_result_auto_sqrt( "select c1, c2, c3 , c4, c5 from ct1", "select sqrt(c1), sqrt(c2) ,sqrt(c3), sqrt(c4), sqrt(c5) from ct1") + + # nest query for sqrt functions + tdSql.query("select c4 , sqrt(c4) ,sqrt(sqrt(c4)) , sqrt(sqrt(sqrt(c4))) from ct1;") + tdSql.checkData(0 , 0 , 88) + tdSql.checkData(0 , 1 , 9.380831520) + tdSql.checkData(0 , 2 , 3.062814314) + tdSql.checkData(0 , 3 , 1.750089802) + + tdSql.checkData(1 , 0 , 77) + tdSql.checkData(1 , 1 , 8.774964387) + tdSql.checkData(1 , 2 , 2.962256638) + tdSql.checkData(1 , 3 , 1.721120750) + + tdSql.checkData(11 , 0 , -99) + tdSql.checkData(11 , 1 , None) + tdSql.checkData(11 , 2 , None) + tdSql.checkData(11 , 3 , None) + + # used for stable table + + tdSql.query("select sqrt(c1) from stb1") + tdSql.checkRows(25) + + + # used for not exists table + tdSql.error("select sqrt(c1) from stbbb1") + tdSql.error("select sqrt(c1) from tbname") + tdSql.error("select sqrt(c1) from ct5") + + # mix with common col + tdSql.query("select c1, sqrt(c1) from ct1") + tdSql.checkData(0 , 0 ,8) + tdSql.checkData(0 , 1 ,2.828427125) + tdSql.checkData(4 , 0 ,0) + tdSql.checkData(4 , 1 ,0.000000000) + tdSql.query("select c2, sqrt(c2) from ct4") + tdSql.checkData(0 , 0 , None) + tdSql.checkData(0 , 1 ,None) + tdSql.checkData(4 , 0 ,55555) + tdSql.checkData(4 , 1 ,235.701081881) + tdSql.checkData(5 , 0 ,None) + tdSql.checkData(5 , 1 ,None) + + # mix with common functions + tdSql.query("select c1, sqrt(c1),sqrt(c1), sqrt(sqrt(c1)) from ct4 ") + tdSql.checkData(0 , 0 ,None) + tdSql.checkData(0 , 1 ,None) + tdSql.checkData(0 , 2 ,None) + tdSql.checkData(0 , 3 ,None) + + tdSql.checkData(3 , 0 , 6) + tdSql.checkData(3 , 1 ,2.449489743) + tdSql.checkData(3 , 2 ,2.449489743) + tdSql.checkData(3 , 3 ,1.565084580) + + tdSql.query("select c1, sqrt(c1),c5, floor(c5) from stb1 ") + + # # mix with agg functions , not support + tdSql.error("select c1, sqrt(c1),c5, count(c5) from stb1 ") + tdSql.error("select c1, sqrt(c1),c5, count(c5) from ct1 ") + tdSql.error("select sqrt(c1), count(c5) from stb1 ") + tdSql.error("select sqrt(c1), count(c5) from ct1 ") + tdSql.error("select c1, count(c5) from ct1 ") + tdSql.error("select c1, count(c5) from stb1 ") + + # agg functions mix with agg functions + + tdSql.query("select max(c5), count(c5) from stb1") + tdSql.query("select max(c5), count(c5) from ct1") + + + # bug fix for count + tdSql.query("select count(c1) from ct4 ") + tdSql.checkData(0,0,9) + tdSql.query("select count(*) from ct4 ") + tdSql.checkData(0,0,12) + tdSql.query("select count(c1) from stb1 ") + tdSql.checkData(0,0,22) + tdSql.query("select count(*) from stb1 ") + tdSql.checkData(0,0,25) + + # # bug fix for compute + tdSql.query("select c1, sqrt(c1) -0 ,sqrt(c1-4)-0 from ct4 ") + tdSql.checkData(0, 0, None) + tdSql.checkData(0, 1, None) + tdSql.checkData(0, 2, None) + tdSql.checkData(1, 0, 8) + tdSql.checkData(1, 1, 2.828427125) + tdSql.checkData(1, 2, 2.000000000) + + tdSql.query(" select c1, sqrt(c1) -0 ,sqrt(c1-0.1)-0.1 from ct4") + tdSql.checkData(0, 0, None) + tdSql.checkData(0, 1, None) + tdSql.checkData(0, 2, None) + tdSql.checkData(1, 0, 8) + tdSql.checkData(1, 1, 2.828427125) + tdSql.checkData(1, 2, 2.710693865) + + tdSql.query("select c1, sqrt(c1), c2, sqrt(c2), c3, sqrt(c3) from ct1") + + def test_big_number(self): + + tdSql.query("select c1, sqrt(100000000) from ct1") # bigint to double data overflow + tdSql.checkData(4, 1, 10000.000000000) + + + tdSql.query("select c1, sqrt(10000000000000) from ct1") # bigint to double data overflow + tdSql.checkData(4, 1, 3162277.660168380) + + tdSql.query("select c1, sqrt(c1) + sqrt(10000000000000000000000000) from ct1") # bigint to double data overflow + tdSql.query("select c1, sqrt(c1) + sqrt(10000000000000000000000000.0) from ct1") # 10000000000000000000000000.0 is a double value + tdSql.checkData(1, 1, 3162277660171.025390625) + + tdSql.query("select c1, sqrt(10000000000000000000000000000000000) from ct1") # bigint to double data overflow + tdSql.query("select c1, sqrt(10000000000000000000000000000000000.0) from ct1") # 10000000000000000000000000.0 is a double value + tdSql.checkData(4, 1, 100000000000000000.000000000) + + tdSql.query("select c1, sqrt(10000000000000000000000000000000000000000) from ct1") # bigint to double data overflow + tdSql.query("select c1, sqrt(10000000000000000000000000000000000000000.0) from ct1") # 10000000000000000000000000.0 is a double value + + tdSql.checkData(4, 1, 100000000000000000000.000000000) + + tdSql.query("select c1, sqrt(10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) from ct1") # bigint to double data overflow + + def pow_base_test(self): + + # base is an regular number ,int or double + tdSql.query("select c1, sqrt(c1) from ct1") + tdSql.checkData(0, 1,2.828427125) + tdSql.checkRows(13) + + # # bug for compute in functions + # tdSql.query("select c1, abs(1/0) from ct1") + # tdSql.checkData(0, 0, 8) + # tdSql.checkData(0, 1, 1) + + tdSql.query("select c1, sqrt(1) from ct1") + tdSql.checkData(0, 1, 1.000000000) + tdSql.checkRows(13) + + # two cols start sqrt(x,y) + tdSql.query("select c1,c2, sqrt(c2) from ct1") + tdSql.checkData(0, 2, 298.140906284) + tdSql.checkData(1, 2, 278.885281074) + tdSql.checkData(4, 2, 0.000000000) + + def abs_func_filter(self): + tdSql.execute("use db") + tdSql.query("select c1, abs(c1) -0 ,ceil(c1-0.1)-0 ,floor(c1+0.1)-0.1 ,ceil(sqrt(c1)-0.5) from ct4 where c1>5 ") + tdSql.checkRows(3) + tdSql.checkData(0,0,8) + tdSql.checkData(0,1,8.000000000) + tdSql.checkData(0,2,8.000000000) + tdSql.checkData(0,3,7.900000000) + tdSql.checkData(0,4,3.000000000) + + tdSql.query("select c1, abs(c1) -0 ,ceil(c1-0.1)-0 ,floor(c1+0.1)-0.1 ,ceil(sqrt(c1)-0.5) from ct4 where c1=5 ") + tdSql.checkRows(1) + tdSql.checkData(0,0,5) + tdSql.checkData(0,1,5.000000000) + tdSql.checkData(0,2,5.000000000) + tdSql.checkData(0,3,4.900000000) + tdSql.checkData(0,4,2.000000000) + + tdSql.query("select c1, abs(c1) -0 ,ceil(c1-0.1)-0 ,floor(c1+0.1)-0.1 ,ceil(sqrt(c1)-0.5) from ct4 where c1=5 ") + tdSql.checkRows(1) + tdSql.checkData(0,0,5) + tdSql.checkData(0,1,5.000000000) + tdSql.checkData(0,2,5.000000000) + tdSql.checkData(0,3,4.900000000) + tdSql.checkData(0,4,2.000000000) + + tdSql.query("select c1,c2 , abs(c1) -0 ,ceil(c1-0.1)-0 ,floor(c1+0.1)-0.1 ,ceil(sqrt(c1)-0.5) from ct4 where c1=sqrt(c1) limit 1 ") + tdSql.checkRows(1) + tdSql.checkData(0,0,1) + tdSql.checkData(0,1,11111) + tdSql.checkData(0,2,1.000000000) + tdSql.checkData(0,3,1.000000000) + tdSql.checkData(0,4,0.900000000) + tdSql.checkData(0,5,1.000000000) + + def pow_Arithmetic(self): + pass + + def check_boundary_values(self): + + tdSql.execute("drop database if exists bound_test") + tdSql.execute("create database if not exists bound_test") + time.sleep(3) + tdSql.execute("use bound_test") + tdSql.execute( + "create table stb_bound (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(32),c9 nchar(32), c10 timestamp) tags (t1 int);" + ) + tdSql.execute(f'create table sub1_bound using stb_bound tags ( 1 )') + tdSql.execute( + f"insert into sub1_bound values ( now()-1s, 2147483647, 9223372036854775807, 32767, 127, 3.40E+38, 1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )" + ) + tdSql.execute( + f"insert into sub1_bound values ( now()-1s, -2147483647, -9223372036854775807, -32767, -127, -3.40E+38, -1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )" + ) + tdSql.execute( + f"insert into sub1_bound values ( now(), 2147483646, 9223372036854775806, 32766, 126, 3.40E+38, 1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )" + ) + tdSql.execute( + f"insert into sub1_bound values ( now(), -2147483646, -9223372036854775806, -32766, -126, -3.40E+38, -1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )" + ) + tdSql.error( + f"insert into sub1_bound values ( now()+1s, 2147483648, 9223372036854775808, 32768, 128, 3.40E+38, 1.7e+308, True, 'binary_tb1', 'nchar_tb1', now() )" + ) + self.check_result_auto_sqrt( "select abs(c1), abs(c2), abs(c3) , abs(c4), abs(c5) from sub1_bound ", "select sqrt(abs(c1)), sqrt(abs(c2)) ,sqrt(abs(c3)), sqrt(abs(c4)), sqrt(abs(c5)) from sub1_bound") + + self.check_result_auto_sqrt( "select c1, c2, c3 , c3, c2 ,c1 from sub1_bound ", "select sqrt(c1), sqrt(c2) ,sqrt(c3), sqrt(c3), sqrt(c2) ,sqrt(c1) from sub1_bound") + + self.check_result_auto_sqrt("select abs(abs(abs(abs(abs(abs(abs(abs(abs(c1))))))))) nest_col_func from sub1_bound" , "select sqrt(abs(c1)) from sub1_bound" ) + + # check basic elem for table per row + tdSql.query("select sqrt(abs(c1)) ,sqrt(abs(c2)) , sqrt(abs(c3)) , sqrt(abs(c4)), sqrt(abs(c5)), sqrt(abs(c6)) from sub1_bound ") + tdSql.checkData(0,0,math.sqrt(2147483647)) + tdSql.checkData(0,1,math.sqrt(9223372036854775807)) + tdSql.checkData(0,2,math.sqrt(32767)) + tdSql.checkData(0,3,math.sqrt(127)) + tdSql.checkData(0,4,math.sqrt(339999995214436424907732413799364296704.00000)) + tdSql.checkData(1,0,math.sqrt(2147483647)) + tdSql.checkData(1,1,math.sqrt(9223372036854775807)) + tdSql.checkData(1,2,math.sqrt(32767)) + tdSql.checkData(1,3,math.sqrt(127)) + tdSql.checkData(1,4,math.sqrt(339999995214436424907732413799364296704.00000)) + tdSql.checkData(3,0,math.sqrt(2147483646)) + tdSql.checkData(3,1,math.sqrt(9223372036854775806)) + tdSql.checkData(3,2,math.sqrt(32766)) + tdSql.checkData(3,3,math.sqrt(126)) + tdSql.checkData(3,4,math.sqrt(339999995214436424907732413799364296704.00000)) + + # check + - * / in functions + tdSql.query("select sqrt(abs(c1+1)) ,sqrt(abs(c2)) , sqrt(abs(c3*1)) , sqrt(abs(c4/2)), sqrt(abs(c5))/2, sqrt(abs(c6)) from sub1_bound ") + tdSql.checkData(0,0,math.sqrt(2147483648.000000000)) + tdSql.checkData(0,1,math.sqrt(9223372036854775807)) + tdSql.checkData(0,2,math.sqrt(32767.000000000)) + tdSql.checkData(0,3,math.sqrt(63.500000000)) + + + def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring + tdSql.prepare() + + tdLog.printNoPrefix("==========step1:create table ==============") + + self.prepare_datas() + + tdLog.printNoPrefix("==========step2:test errors ==============") + + self.test_errors() + + tdLog.printNoPrefix("==========step3:support types ============") + + self.support_types() + + tdLog.printNoPrefix("==========step4: sqrt basic query ============") + + self.basic_sqrt_function() + + tdLog.printNoPrefix("==========step5: big number sqrt query ============") + + self.test_big_number() + + tdLog.printNoPrefix("==========step6: base number for sqrt query ============") + + self.pow_base_test() + + tdLog.printNoPrefix("==========step7: sqrt boundary query ============") + + self.check_boundary_values() + + tdLog.printNoPrefix("==========step8: sqrt filter query ============") + + self.abs_func_filter() + + + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/fulltest.sh b/tests/system-test/fulltest.sh index 1dfb160987..51f1649cc8 100755 --- a/tests/system-test/fulltest.sh +++ b/tests/system-test/fulltest.sh @@ -24,3 +24,4 @@ python3 ./test.py -f 2-query/floor.py python3 ./test.py -f 2-query/round.py python3 ./test.py -f 2-query/log.py python3 ./test.py -f 2-query/pow.py +python3 ./test.py -f 2-query/sqrt.py diff --git a/tools/taos-tools b/tools/taos-tools index 2f3dfddd4d..59e0ebaf49 160000 --- a/tools/taos-tools +++ b/tools/taos-tools @@ -1 +1 @@ -Subproject commit 2f3dfddd4d9a869e706ba3cf98fb6d769404cd7c +Subproject commit 59e0ebaf4905e4cb6d95a01c58b3fa507abc5a20