Merge pull request #18501 from taosdata/fix/TS-2149
fix(query): handle countAlwaysReturnValue behavior
This commit is contained in:
commit
45cf5acc32
|
@ -57,7 +57,7 @@ typedef struct SFuncExecFuncs {
|
||||||
#define MAX_INTERVAL_TIME_WINDOW 10000000 // maximum allowed time windows in final results
|
#define MAX_INTERVAL_TIME_WINDOW 10000000 // maximum allowed time windows in final results
|
||||||
|
|
||||||
#define TOP_BOTTOM_QUERY_LIMIT 100
|
#define TOP_BOTTOM_QUERY_LIMIT 100
|
||||||
#define FUNCTIONS_NAME_MAX_LENGTH 16
|
#define FUNCTIONS_NAME_MAX_LENGTH 32
|
||||||
|
|
||||||
typedef struct SResultRowEntryInfo {
|
typedef struct SResultRowEntryInfo {
|
||||||
bool initialized : 1; // output buffer has been initialized
|
bool initialized : 1; // output buffer has been initialized
|
||||||
|
|
|
@ -332,6 +332,7 @@ typedef struct STableScanInfo {
|
||||||
int32_t currentTable;
|
int32_t currentTable;
|
||||||
int8_t scanMode;
|
int8_t scanMode;
|
||||||
int8_t assignBlockUid;
|
int8_t assignBlockUid;
|
||||||
|
bool hasGroupByTag;
|
||||||
} STableScanInfo;
|
} STableScanInfo;
|
||||||
|
|
||||||
typedef struct STableMergeScanInfo {
|
typedef struct STableMergeScanInfo {
|
||||||
|
|
|
@ -1419,6 +1419,78 @@ int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBlock **ppBlock) {
|
||||||
|
if (!tsCountAlwaysReturnValue) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||||
|
if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_PARTITION ||
|
||||||
|
(downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN &&
|
||||||
|
((STableScanInfo *)downstream->info)->hasGroupByTag == true)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx;
|
||||||
|
bool hasCountFunc = false;
|
||||||
|
for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) {
|
||||||
|
if ((strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "count") == 0) ||
|
||||||
|
(strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "hyperloglog") == 0) ||
|
||||||
|
(strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_hyperloglog_partial") == 0) ||
|
||||||
|
(strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_hyperloglog_merge") == 0)) {
|
||||||
|
hasCountFunc = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasCountFunc) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSDataBlock* pBlock = createDataBlock();
|
||||||
|
pBlock->info.rows = 1;
|
||||||
|
pBlock->info.capacity = 0;
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) {
|
||||||
|
SColumnInfoData colInfo = {0};
|
||||||
|
colInfo.hasNull = true;
|
||||||
|
colInfo.info.type = TSDB_DATA_TYPE_NULL;
|
||||||
|
colInfo.info.bytes = 1;
|
||||||
|
|
||||||
|
SExprInfo* pOneExpr = &pOperator->exprSupp.pExprInfo[i];
|
||||||
|
for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) {
|
||||||
|
SFunctParam* pFuncParam = &pOneExpr->base.pParam[j];
|
||||||
|
if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) {
|
||||||
|
int32_t slotId = pFuncParam->pCol->slotId;
|
||||||
|
int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock);
|
||||||
|
if (slotId >= numOfCols) {
|
||||||
|
taosArrayEnsureCap(pBlock->pDataBlock, slotId + 1);
|
||||||
|
for (int32_t k = numOfCols; k < slotId + 1; ++k) {
|
||||||
|
taosArrayPush(pBlock->pDataBlock, &colInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blockDataEnsureCapacity(pBlock, pBlock->info.rows);
|
||||||
|
*ppBlock = pBlock;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyDataBlockForEmptyInput(bool blockAllocated, SSDataBlock **ppBlock) {
|
||||||
|
if (!blockAllocated) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockDataDestroy(*ppBlock);
|
||||||
|
*ppBlock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// this is a blocking operator
|
// this is a blocking operator
|
||||||
static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
||||||
if (OPTR_IS_OPENED(pOperator)) {
|
if (OPTR_IS_OPENED(pOperator)) {
|
||||||
|
@ -1436,22 +1508,36 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
||||||
int32_t order = TSDB_ORDER_ASC;
|
int32_t order = TSDB_ORDER_ASC;
|
||||||
int32_t scanFlag = MAIN_SCAN;
|
int32_t scanFlag = MAIN_SCAN;
|
||||||
|
|
||||||
|
bool hasValidBlock = false;
|
||||||
|
bool blockAllocated = false;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
|
SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
|
||||||
|
if (pBlock == NULL) {
|
||||||
|
if (!hasValidBlock) {
|
||||||
|
createDataBlockForEmptyInput(pOperator, &pBlock);
|
||||||
if (pBlock == NULL) {
|
if (pBlock == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
blockAllocated = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasValidBlock = true;
|
||||||
|
|
||||||
int32_t code = getTableScanInfo(pOperator, &order, &scanFlag);
|
int32_t code = getTableScanInfo(pOperator, &order, &scanFlag);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
|
||||||
T_LONG_JMP(pTaskInfo->env, code);
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is an scalar expression that needs to be calculated before apply the group aggregation.
|
// there is an scalar expression that needs to be calculated before apply the group aggregation.
|
||||||
if (pAggInfo->scalarExprSup.pExprInfo != NULL) {
|
if (pAggInfo->scalarExprSup.pExprInfo != NULL && !blockAllocated) {
|
||||||
SExprSupp* pSup1 = &pAggInfo->scalarExprSup;
|
SExprSupp* pSup1 = &pAggInfo->scalarExprSup;
|
||||||
code = projectApplyFunctions(pSup1->pExprInfo, pBlock, pBlock, pSup1->pCtx, pSup1->numOfExprs, NULL);
|
code = projectApplyFunctions(pSup1->pExprInfo, pBlock, pBlock, pSup1->pCtx, pSup1->numOfExprs, NULL);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
|
||||||
T_LONG_JMP(pTaskInfo->env, code);
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1461,8 +1547,12 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
||||||
setInputDataBlock(pSup, pBlock, order, scanFlag, true);
|
setInputDataBlock(pSup, pBlock, order, scanFlag, true);
|
||||||
code = doAggregateImpl(pOperator, pSup->pCtx);
|
code = doAggregateImpl(pOperator, pSup->pCtx);
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
|
destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
|
||||||
T_LONG_JMP(pTaskInfo->env, code);
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the downstream operator may return with error code, so let's check the code before generating results.
|
// the downstream operator may return with error code, so let's check the code before generating results.
|
||||||
|
|
|
@ -895,6 +895,7 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
|
||||||
|
|
||||||
pInfo->currentGroupId = -1;
|
pInfo->currentGroupId = -1;
|
||||||
pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
|
pInfo->assignBlockUid = pTableScanNode->assignBlockUid;
|
||||||
|
pInfo->hasGroupByTag = pTableScanNode->pGroupTags ? true : false;
|
||||||
|
|
||||||
setOperatorInfo(pOperator, "TableScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
|
setOperatorInfo(pOperator, "TableScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, false, OP_NOT_OPENED, pInfo,
|
||||||
pTaskInfo);
|
pTaskInfo);
|
||||||
|
|
|
@ -526,7 +526,7 @@ static int32_t getNumOfElems(SqlFunctionCtx* pCtx) {
|
||||||
* count function does not use the pCtx->interResBuf to keep the intermediate buffer
|
* count function does not use the pCtx->interResBuf to keep the intermediate buffer
|
||||||
*/
|
*/
|
||||||
int32_t countFunction(SqlFunctionCtx* pCtx) {
|
int32_t countFunction(SqlFunctionCtx* pCtx) {
|
||||||
int32_t numOfElem = getNumOfElems(pCtx);
|
int32_t numOfElem = 0;
|
||||||
|
|
||||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
||||||
SInputColumnInfoData* pInput = &pCtx->input;
|
SInputColumnInfoData* pInput = &pCtx->input;
|
||||||
|
@ -539,6 +539,7 @@ int32_t countFunction(SqlFunctionCtx* pCtx) {
|
||||||
numOfElem = 1;
|
numOfElem = 1;
|
||||||
*((int64_t*)buf) = 0;
|
*((int64_t*)buf) = 0;
|
||||||
} else {
|
} else {
|
||||||
|
numOfElem = getNumOfElems(pCtx);
|
||||||
*((int64_t*)buf) += numOfElem;
|
*((int64_t*)buf) += numOfElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2043,12 +2044,16 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) {
|
||||||
|
|
||||||
pInfo->bytes = pInputCol->info.bytes;
|
pInfo->bytes = pInputCol->info.bytes;
|
||||||
|
|
||||||
|
if (IS_NULL_TYPE(pInputCol->info.type)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// All null data column, return directly.
|
// All null data column, return directly.
|
||||||
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows)) {
|
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows)) {
|
||||||
ASSERT(pInputCol->hasNull == true);
|
ASSERT(pInputCol->hasNull == true);
|
||||||
// save selectivity value for column consisted of all null values
|
// save selectivity value for column consisted of all null values
|
||||||
firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
|
firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
|
||||||
return 0;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
|
SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
|
||||||
|
@ -2147,12 +2152,16 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
|
||||||
int32_t bytes = pInputCol->info.bytes;
|
int32_t bytes = pInputCol->info.bytes;
|
||||||
pInfo->bytes = bytes;
|
pInfo->bytes = bytes;
|
||||||
|
|
||||||
|
if (IS_NULL_TYPE(type)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// All null data column, return directly.
|
// All null data column, return directly.
|
||||||
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows)) {
|
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows)) {
|
||||||
ASSERT(pInputCol->hasNull == true);
|
ASSERT(pInputCol->hasNull == true);
|
||||||
// save selectivity value for column consisted of all null values
|
// save selectivity value for column consisted of all null values
|
||||||
firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
|
firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
|
||||||
return 0;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
|
SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
|
||||||
|
@ -2417,9 +2426,14 @@ int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
|
||||||
SInputColumnInfoData* pInput = &pCtx->input;
|
SInputColumnInfoData* pInput = &pCtx->input;
|
||||||
SColumnInfoData* pInputCol = pInput->pData[0];
|
SColumnInfoData* pInputCol = pInput->pData[0];
|
||||||
|
|
||||||
|
int32_t type = pInputCol->info.type;
|
||||||
int32_t bytes = pInputCol->info.bytes;
|
int32_t bytes = pInputCol->info.bytes;
|
||||||
pInfo->bytes = bytes;
|
pInfo->bytes = bytes;
|
||||||
|
|
||||||
|
if (IS_NULL_TYPE(type)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
TSKEY startKey = getRowPTs(pInput->pPTS, 0);
|
TSKEY startKey = getRowPTs(pInput->pPTS, 0);
|
||||||
TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
|
TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
|
||||||
|
|
||||||
|
@ -3869,6 +3883,10 @@ int32_t hllFunction(SqlFunctionCtx* pCtx) {
|
||||||
int32_t numOfRows = pInput->numOfRows;
|
int32_t numOfRows = pInput->numOfRows;
|
||||||
|
|
||||||
int32_t numOfElems = 0;
|
int32_t numOfElems = 0;
|
||||||
|
if (IS_NULL_TYPE(type)) {
|
||||||
|
goto _hll_over;
|
||||||
|
}
|
||||||
|
|
||||||
for (int32_t i = start; i < numOfRows + start; ++i) {
|
for (int32_t i = start; i < numOfRows + start; ++i) {
|
||||||
if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
|
if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -3890,6 +3908,7 @@ int32_t hllFunction(SqlFunctionCtx* pCtx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hll_over:
|
||||||
pInfo->totalCount += numOfElems;
|
pInfo->totalCount += numOfElems;
|
||||||
|
|
||||||
if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
|
if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
|
||||||
|
@ -3913,12 +3932,16 @@ static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
|
||||||
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
|
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
|
||||||
SInputColumnInfoData* pInput = &pCtx->input;
|
SInputColumnInfoData* pInput = &pCtx->input;
|
||||||
SColumnInfoData* pCol = pInput->pData[0];
|
SColumnInfoData* pCol = pInput->pData[0];
|
||||||
ASSERT(pCol->info.type == TSDB_DATA_TYPE_BINARY);
|
|
||||||
|
if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||||
|
|
||||||
int32_t start = pInput->startRowIndex;
|
int32_t start = pInput->startRowIndex;
|
||||||
|
|
||||||
|
|
||||||
for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
|
for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
|
||||||
char* data = colDataGetData(pCol, i);
|
char* data = colDataGetData(pCol, i);
|
||||||
SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
|
SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
|
||||||
|
|
|
@ -471,7 +471,6 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
||||||
int32_t type = pInput->pData[0]->info.type;
|
int32_t type = pInput->pData[0]->info.type;
|
||||||
|
|
||||||
SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
|
||||||
pAvgRes->type = type;
|
|
||||||
|
|
||||||
// computing based on the true data block
|
// computing based on the true data block
|
||||||
SColumnInfoData* pCol = pInput->pData[0];
|
SColumnInfoData* pCol = pInput->pData[0];
|
||||||
|
@ -483,6 +482,8 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) {
|
||||||
goto _over;
|
goto _over;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pAvgRes->type = type;
|
||||||
|
|
||||||
if (pInput->colDataSMAIsSet) { // try to use SMA if available
|
if (pInput->colDataSMAIsSet) { // try to use SMA if available
|
||||||
numOfElem = calculateAvgBySMAInfo(pAvgRes, numOfRows, type, pAgg);
|
numOfElem = calculateAvgBySMAInfo(pAvgRes, numOfRows, type, pAgg);
|
||||||
} else if (!pCol->hasNull) { // try to employ the simd instructions to speed up the loop
|
} else if (!pCol->hasNull) { // try to employ the simd instructions to speed up the loop
|
||||||
|
@ -592,6 +593,10 @@ _over:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) {
|
static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) {
|
||||||
|
if (IS_NULL_TYPE(pInput->type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pOutput->type = pInput->type;
|
pOutput->type = pInput->type;
|
||||||
if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
|
if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
|
||||||
pOutput->sum.isum += pInput->sum.isum;
|
pOutput->sum.isum += pInput->sum.isum;
|
||||||
|
|
|
@ -496,18 +496,18 @@ sql create table tm0 using m1 tags('abc', 1);
|
||||||
sql create table m2(ts timestamp, k int) tags(a int, b binary(12));
|
sql create table m2(ts timestamp, k int) tags(a int, b binary(12));
|
||||||
|
|
||||||
sql select count(*) from m1, m2 where m1.ts=m2.ts and m1.b=m2.a;
|
sql select count(*) from m1, m2 where m1.ts=m2.ts and m1.b=m2.a;
|
||||||
if $rows != 0 then
|
if $rows != 1 then
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
|
||||||
sql create table tm2 using m2 tags(2, 'abc');
|
sql create table tm2 using m2 tags(2, 'abc');
|
||||||
sql select count(*) from tm0, tm2 where tm0.ts=tm2.ts;
|
sql select count(*) from tm0, tm2 where tm0.ts=tm2.ts;
|
||||||
if $rows != 0 then
|
if $rows != 1 then
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
|
||||||
sql select count(*) from m1, m2 where m1.ts=m2.ts and m1.b=m2.a;
|
sql select count(*) from m1, m2 where m1.ts=m2.ts and m1.b=m2.a;
|
||||||
if $rows != 0 then
|
if $rows != 1 then
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ endi
|
||||||
|
|
||||||
# regression test case 1
|
# regression test case 1
|
||||||
sql select count(*) from lr_tb1 where ts>'2018-09-18 08:45:00.1' and ts<'2018-09-18 08:45:00.2'
|
sql select count(*) from lr_tb1 where ts>'2018-09-18 08:45:00.1' and ts<'2018-09-18 08:45:00.2'
|
||||||
if $row != 0 then
|
if $row != 1 then
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
|
||||||
|
|
|
@ -245,12 +245,12 @@ endi
|
||||||
|
|
||||||
# first subclause are empty
|
# first subclause are empty
|
||||||
sql (select count(*) as c from union_tb0 where ts > now + 3650d) union all (select sum(c1) as c from union_tb1);
|
sql (select count(*) as c from union_tb0 where ts > now + 3650d) union all (select sum(c1) as c from union_tb1);
|
||||||
if $rows != 1 then
|
if $rows != 2 then
|
||||||
return -1
|
|
||||||
endi
|
|
||||||
if $data00 != 495000 then
|
|
||||||
return -1
|
return -1
|
||||||
endi
|
endi
|
||||||
|
#if $data00 != 495000 then
|
||||||
|
# return -1
|
||||||
|
#endi
|
||||||
|
|
||||||
# all subclause are empty
|
# all subclause are empty
|
||||||
sql (select c1 from union_tb0 limit 0) union all (select c1 from union_tb1 where ts>'2021-1-1 0:0:0')
|
sql (select c1 from union_tb0 limit 0) union all (select c1 from union_tb1 where ts>'2021-1-1 0:0:0')
|
||||||
|
|
|
@ -121,7 +121,7 @@ class TDTestCase:
|
||||||
tdSql.checkRows(0)
|
tdSql.checkRows(0)
|
||||||
tdSql.query(f'select count(*) from {stbname}')
|
tdSql.query(f'select count(*) from {stbname}')
|
||||||
if tb_num <= 1:
|
if tb_num <= 1:
|
||||||
if len(tdSql.queryResult) != 0:
|
if len(tdSql.queryResult) != 1 and tdSql.queryResult[0][0] != 0:
|
||||||
tdLog.exit('delete case failure!')
|
tdLog.exit('delete case failure!')
|
||||||
else:
|
else:
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],(tb_num-1)*row_num)
|
tdSql.checkEqual(tdSql.queryResult[0][0],(tb_num-1)*row_num)
|
||||||
|
|
|
@ -51,6 +51,129 @@ class TDTestCase:
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],rownum)
|
tdSql.checkEqual(tdSql.queryResult[0][0],rownum)
|
||||||
tdSql.query(f'select count({k}) from {ntbname} where ts <={self.ts+self.rowNum-2}')
|
tdSql.query(f'select count({k}) from {ntbname} where ts <={self.ts+self.rowNum-2}')
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],rownum-1)
|
tdSql.checkEqual(tdSql.queryResult[0][0],rownum-1)
|
||||||
|
def query_empty_stb(self):
|
||||||
|
tdSql.query(f'select count(*) from (select distinct tbname from {self.stbname})')
|
||||||
|
tdSql.checkEqual(tdSql.queryResult[0][0],self.tbnum)
|
||||||
|
tdSql.query(f'select count(*) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
function_names = ['count', 'hyperloglog']
|
||||||
|
for function_name in function_names:
|
||||||
|
tdSql.query(f'select {function_name}(tbname) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(ts) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(1) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c2),max(1) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(3)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.query(f'select sum(1),{function_name}(1),max(c2) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(3)
|
||||||
|
tdSql.checkData(0, 0, None)
|
||||||
|
tdSql.checkData(0, 1, 0)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.query(f'select {function_name}(1),sum(1),max(c2),min(1),min(2),min(3),min(4),min(5),min(6),min(7),min(8) from {self.stbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(11)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.checkData(0, 10, None)
|
||||||
|
tdSql.query(f'select sum(1),max(c2),min(1),leastsquares(c1,1,1) from {self.stbname}')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} group by tbname')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} group by c1')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} group by t0')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} partition by tbname')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} partition by c1')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} partition by t0')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(1) from (select {function_name}(c1),sum(c1) from {self.stbname} group by c1)')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} partition by tbname interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.stbname} partition by c1 interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(1),sum(1) from (select {function_name}(1) from {self.stbname} group by tbname)')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
|
|
||||||
|
def query_empty_ntb(self):
|
||||||
|
tdSql.query(f'select count(*) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
function_names = ['count', 'hyperloglog']
|
||||||
|
for function_name in function_names:
|
||||||
|
tdSql.query(f'select {function_name}(tbname) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(ts) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(1) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c2),max(1) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(3)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.query(f'select sum(1),{function_name}(1),max(c2) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(3)
|
||||||
|
tdSql.checkData(0, 0, None)
|
||||||
|
tdSql.checkData(0, 1, 0)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.query(f'select {function_name}(1),sum(1),max(c2),min(1),min(2),min(3),min(4),min(5),min(6),min(7),min(8) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkCols(11)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
|
tdSql.checkData(0, 2, None)
|
||||||
|
tdSql.checkData(0, 10, None)
|
||||||
|
tdSql.query(f'select sum(1),max(c2),min(1),leastsquares(c1,1,1) from {self.ntbname}')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.ntbname} group by tbname')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.ntbname} group by c1')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(1) from (select {function_name}(c1),sum(c1) from {self.ntbname} group by c1)')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.ntbname} interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.ntbname} partition by tbname interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select {function_name}(c1),sum(c1) from {self.ntbname} partition by c1 interval(1s)')
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
tdSql.query(f'select count(1),sum(1) from (select count(1) from {self.ntbname} group by tbname)')
|
||||||
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
|
tdSql.checkData(0, 1, None)
|
||||||
def count_query_stb(self,column_dict,tag_dict,stbname,tbnum,rownum):
|
def count_query_stb(self,column_dict,tag_dict,stbname,tbnum,rownum):
|
||||||
tdSql.query(f'select count(tbname) from {stbname}')
|
tdSql.query(f'select count(tbname) from {stbname}')
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],tbnum*rownum)
|
tdSql.checkEqual(tdSql.queryResult[0][0],tbnum*rownum)
|
||||||
|
@ -81,11 +204,11 @@ class TDTestCase:
|
||||||
def check_ntb(self):
|
def check_ntb(self):
|
||||||
tdSql.prepare()
|
tdSql.prepare()
|
||||||
tdSql.execute(self.setsql.set_create_normaltable_sql(self.ntbname,self.column_dict))
|
tdSql.execute(self.setsql.set_create_normaltable_sql(self.ntbname,self.column_dict))
|
||||||
tdSql.query(f'select count(tbname) from {self.ntbname}')
|
self.query_empty_ntb()
|
||||||
tdSql.checkRows(0)
|
|
||||||
tdSql.execute('flush database db')
|
tdSql.execute('flush database db')
|
||||||
tdSql.query(f'select count(tbname) from {self.ntbname}')
|
tdSql.query(f'select count(tbname) from {self.ntbname}')
|
||||||
tdSql.checkRows(0)
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
self.insert_data(self.column_dict,self.ntbname,self.rowNum)
|
self.insert_data(self.column_dict,self.ntbname,self.rowNum)
|
||||||
self.count_query_ntb(self.column_dict,self.ntbname,self.rowNum)
|
self.count_query_ntb(self.column_dict,self.ntbname,self.rowNum)
|
||||||
tdSql.execute('flush database db')
|
tdSql.execute('flush database db')
|
||||||
|
@ -96,13 +219,11 @@ class TDTestCase:
|
||||||
tdSql.execute(self.setsql.set_create_stable_sql(self.stbname,self.column_dict,self.tag_dict))
|
tdSql.execute(self.setsql.set_create_stable_sql(self.stbname,self.column_dict,self.tag_dict))
|
||||||
for i in range(self.tbnum):
|
for i in range(self.tbnum):
|
||||||
tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags({self.tag_values[i]})')
|
tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags({self.tag_values[i]})')
|
||||||
tdSql.query(f'SELECT count(*) from (select distinct tbname from {self.stbname})')
|
self.query_empty_stb()
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],self.tbnum)
|
|
||||||
tdSql.query(f'select count(tbname) from {self.stbname}')
|
|
||||||
tdSql.checkRows(0)
|
|
||||||
tdSql.execute('flush database db')
|
tdSql.execute('flush database db')
|
||||||
tdSql.query(f'select count(tbname) from {self.stbname}')
|
tdSql.query(f'select count(tbname) from {self.stbname}')
|
||||||
tdSql.checkRows(0)
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0, 0, 0)
|
||||||
tdSql.query(f'SELECT count(*) from (select distinct tbname from {self.stbname})')
|
tdSql.query(f'SELECT count(*) from (select distinct tbname from {self.stbname})')
|
||||||
tdSql.checkEqual(tdSql.queryResult[0][0],self.tbnum)
|
tdSql.checkEqual(tdSql.queryResult[0][0],self.tbnum)
|
||||||
for i in range(self.tbnum):
|
for i in range(self.tbnum):
|
||||||
|
|
|
@ -33,6 +33,19 @@ class TDTestCase:
|
||||||
f"create table {dbname}.ctb2 using {dbname}.stb tags (2)"
|
f"create table {dbname}.ctb2 using {dbname}.stb tags (2)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tdSql.execute(
|
||||||
|
f"create table {dbname}.tb_empty (ts timestamp, c0 int)"
|
||||||
|
)
|
||||||
|
tdSql.execute(
|
||||||
|
f"create table {dbname}.stb_empty (ts timestamp, c0 int) tags (t0 int)"
|
||||||
|
)
|
||||||
|
tdSql.execute(
|
||||||
|
f"create table {dbname}.ctb1_empty using {dbname}.stb tags (1)"
|
||||||
|
)
|
||||||
|
tdSql.execute(
|
||||||
|
f"create table {dbname}.ctb2_empty using {dbname}.stb tags (2)"
|
||||||
|
)
|
||||||
|
|
||||||
tdSql.execute(
|
tdSql.execute(
|
||||||
f"insert into {dbname}.tb values (now(), NULL)")
|
f"insert into {dbname}.tb values (now(), NULL)")
|
||||||
|
|
||||||
|
@ -94,6 +107,61 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
tdSql.checkData(0, 0, 0)
|
tdSql.checkData(0, 0, 0)
|
||||||
|
|
||||||
|
# test empty table/input
|
||||||
|
tdSql.query(f"select count(*) from {dbname}.tb where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(ts) from {dbname}.stb where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(c0) from {dbname}.ctb1 where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(1) from {dbname}.ctb2 where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(*) from {dbname}.tb_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(ts) from {dbname}.stb_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(c0) from {dbname}.ctb1_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(1) from {dbname}.ctb2_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(c0) from {dbname}.tb where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(ts) from {dbname}.stb where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(1) from {dbname}.ctb1 where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(1) from {dbname}.ctb2 where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(c0) from {dbname}.tb_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(ts) from {dbname}.stb_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(1) from {dbname}.ctb1_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select hyperloglog(1) from {dbname}.ctb2_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(*), hyperloglog(c0), sum(1), max(c0) from {dbname}.tb where ts > now + 1h")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
|
tdSql.query(f"select count(*), hyperloglog(c0), sum(1), max(c0) from {dbname}.tb_empty")
|
||||||
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
tdSql.prepare()
|
tdSql.prepare()
|
||||||
|
|
||||||
|
|
|
@ -402,7 +402,8 @@ class TDTestCase:
|
||||||
tdSql.checkRows(0)
|
tdSql.checkRows(0)
|
||||||
|
|
||||||
tdSql.query(f"select count(c1) from {dbname}.ct4 where t1 = 1 ")
|
tdSql.query(f"select count(c1) from {dbname}.ct4 where t1 = 1 ")
|
||||||
tdSql.checkRows(0)
|
tdSql.checkRows(1)
|
||||||
|
tdSql.checkData(0,0,0)
|
||||||
|
|
||||||
tdSql.query(f"select last_row(c1) ,last(c1) from {dbname}.stb1 where c1 is null")
|
tdSql.query(f"select last_row(c1) ,last(c1) from {dbname}.stb1 where c1 is null")
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
|
|
|
@ -298,7 +298,7 @@ class TDTestCase:
|
||||||
if (platform.system().lower() == 'windows' and pre_result.dtype == 'int32'):
|
if (platform.system().lower() == 'windows' and pre_result.dtype == 'int32'):
|
||||||
pre_result = np.array(pre_result, dtype = 'int64')
|
pre_result = np.array(pre_result, dtype = 'int64')
|
||||||
|
|
||||||
pre_mavg = pre_mavg = np.convolve(pre_result, np.ones(k), "valid")[offset_val:]/k
|
#pre_mavg = pre_mavg = np.convolve(pre_result, np.ones(k), "valid")[offset_val:]/k
|
||||||
tdSql.query(self.mavg_query_form(
|
tdSql.query(self.mavg_query_form(
|
||||||
sel=sel, func=func, col=col, m_comm=m_comm, k=k, r_comm=r_comm, alias=alias, fr=fr,
|
sel=sel, func=func, col=col, m_comm=m_comm, k=k, r_comm=r_comm, alias=alias, fr=fr,
|
||||||
table_expr=table_expr, condition=condition
|
table_expr=table_expr, condition=condition
|
||||||
|
|
Loading…
Reference in New Issue