未验证 提交 06076c57 编写于 作者: S shenglian-zhou 提交者: GitHub

Merge pull request #10615 from taosdata/feature/TD-11210

stateCount/stateDuration function
......@@ -1113,7 +1113,7 @@ static int32_t addPrimaryTsColumnForTimeWindowQuery(SQueryInfo* pQueryInfo, SSql
static int32_t checkInvalidExprForTimeWindow(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
const char* msg1 = "invalid query expression";
const char* msg2 = "top/bottom query does not support order by value in time window query";
const char* msg3 = "unique function does not supportted in time window query";
const char* msg3 = "unique/state function does not supportted in time window query";
/*
* invalid sql:
......@@ -1125,7 +1125,8 @@ static int32_t checkInvalidExprForTimeWindow(SSqlCmd* pCmd, SQueryInfo* pQueryIn
if (pExpr->base.functionId == TSDB_FUNC_COUNT && TSDB_COL_IS_TAG(pExpr->base.colInfo.flag)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
if (pExpr->base.functionId == TSDB_FUNC_UNIQUE) {
if (pExpr->base.functionId == TSDB_FUNC_UNIQUE || pExpr->base.functionId == TSDB_FUNC_STATE_COUNT ||
pExpr->base.functionId == TSDB_FUNC_STATE_DURATION) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
}
}
......@@ -2695,6 +2696,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
const char* msg28 = "the second paramter of diff should be 0 or 1";
const char* msg29 = "key timestamp column cannot be used to unique/mode/tail function";
const char* msg30 = "offset is out of range [0, 100]";
const char* msg31 = "state function can not be used in subquery";
switch (functionId) {
case TSDB_FUNC_COUNT: {
......@@ -2793,7 +2795,9 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
case TSDB_FUNC_STDDEV:
case TSDB_FUNC_LEASTSQR:
case TSDB_FUNC_ELAPSED:
case TSDB_FUNC_MODE: {
case TSDB_FUNC_MODE:
case TSDB_FUNC_STATE_COUNT:
case TSDB_FUNC_STATE_DURATION:{
// 1. valid the number of parameters
int32_t numOfParams =
(pItem->pNode->Expr.paramList == NULL) ? 0 : (int32_t)taosArrayGetSize(pItem->pNode->Expr.paramList);
......@@ -2801,10 +2805,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
// no parameters or more than one parameter for function
if (pItem->pNode->Expr.paramList == NULL ||
(functionId != TSDB_FUNC_LEASTSQR && functionId != TSDB_FUNC_DERIVATIVE && functionId != TSDB_FUNC_ELAPSED &&
functionId != TSDB_FUNC_DIFF && numOfParams != 1) ||
functionId != TSDB_FUNC_DIFF && functionId != TSDB_FUNC_STATE_COUNT && functionId != TSDB_FUNC_STATE_DURATION && numOfParams != 1) ||
((functionId == TSDB_FUNC_LEASTSQR || functionId == TSDB_FUNC_DERIVATIVE) && numOfParams != 3) ||
(functionId == TSDB_FUNC_ELAPSED && numOfParams != 1 && numOfParams != 2) ||
(functionId == TSDB_FUNC_DIFF && numOfParams != 1 && numOfParams != 2)) {
(functionId == TSDB_FUNC_DIFF && numOfParams != 1 && numOfParams != 2) ||
(functionId == TSDB_FUNC_STATE_COUNT && numOfParams != 3) ||
(functionId == TSDB_FUNC_STATE_DURATION && numOfParams != 3 && numOfParams != 4)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
......@@ -2843,6 +2849,11 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
}
if ((functionId == TSDB_FUNC_STATE_COUNT || functionId == TSDB_FUNC_STATE_DURATION) &&
pQueryInfo->pUpstream != NULL && taosArrayGetSize(pQueryInfo->pUpstream) > 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg31);
}
STableComInfo info = tscGetTableInfo(pTableMetaInfo->pTableMeta);
// functions can not be applied to tags
......@@ -2885,6 +2896,24 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
aAggs[TSDB_FUNC_TS_DUMMY].name, pExpr);
}
if (functionId == TSDB_FUNC_STATE_COUNT || functionId == TSDB_FUNC_STATE_DURATION) {
SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0};
SExprInfo* pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_PRJ, &indexTS, TSDB_DATA_TYPE_TIMESTAMP,
TSDB_KEYSIZE, 0, TSDB_KEYSIZE, false);
tstrncpy(pExpr->base.aliasName, aAggs[TSDB_FUNC_TS_DUMMY].name, sizeof(pExpr->base.aliasName));
SColumnList ids = createColumnList(1, 0, 0);
insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
aAggs[TSDB_FUNC_TS].name, pExpr);
pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_PRJ, &index, pSchema->type,
pSchema->bytes, getNewResColId(pCmd), 0, false);
tstrncpy(pExpr->base.aliasName, pParamElem->pNode->columnName.z, pParamElem->pNode->columnName.n+1);
ids = createColumnList(1, index.tableIndex, index.columnIndex);
insertResultField(pQueryInfo, colIndex + 1, &ids, pExpr->base.resBytes, (int32_t)pExpr->base.resType,
pExpr->base.aliasName, pExpr);
}
SExprInfo* pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd),
intermediateResSize, false);
......@@ -2963,6 +2992,41 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
}
}
tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t));
} else if (functionId == TSDB_FUNC_STATE_COUNT || functionId == TSDB_FUNC_STATE_DURATION) {
if (pParamElem[1].pNode->tokenId != TK_ID || !isValidStateOper(pParamElem[1].pNode->columnName.z, pParamElem[1].pNode->columnName.n)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
tscExprAddParams(&pExpr->base, pParamElem[1].pNode->columnName.z, TSDB_DATA_TYPE_BINARY, pParamElem[1].pNode->columnName.n);
if (pParamElem[2].pNode->tokenId != TK_INTEGER && pParamElem[2].pNode->tokenId != TK_FLOAT) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
tVariantAssign(&pExpr->base.param[pExpr->base.numOfParams++], &pParamElem[2].pNode->value);
if (functionId == TSDB_FUNC_STATE_DURATION){
if (numOfParams == 4) {
// unit must be 1s 1m 1h
if (pParamElem[3].pNode->tokenId != TK_TIMESTAMP || (pParamElem[3].pNode->value.i64 != MILLISECOND_PER_SECOND * 1000000L &&
pParamElem[3].pNode->value.i64 != MILLISECOND_PER_MINUTE * 1000000L && pParamElem[3].pNode->value.i64 != MILLISECOND_PER_HOUR * 1000000L)) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
}
if (info.precision == TSDB_TIME_PRECISION_MILLI) {
pParamElem[3].pNode->value.i64 /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MICRO);
} else if (info.precision == TSDB_TIME_PRECISION_MICRO) {
pParamElem[3].pNode->value.i64 /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MILLI);
}
tVariantAssign(&pExpr->base.param[pExpr->base.numOfParams++], &pParamElem[3].pNode->value);
}else{
int64_t tmp = TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_NANO);
if (info.precision == TSDB_TIME_PRECISION_MILLI) {
tmp /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MICRO);
} else if (info.precision == TSDB_TIME_PRECISION_MICRO) {
tmp /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MILLI);
}
tscExprAddParams(&pExpr->base, (char *)&tmp, TSDB_DATA_TYPE_BIGINT, sizeof(tmp));
}
}
}
SColumnList ids = createColumnList(1, index.tableIndex, index.columnIndex);
......@@ -6716,7 +6780,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
const char* msg8 = "only column in groupby clause allowed as order column";
const char* msg10 = "not support distinct mixed with order by";
const char* msg11 = "not support order with udf";
const char* msg12 = "order by tags not supported with diff/derivative/csum/mavg";
const char* msg12 = "order by tags not supported with diff/derivative/csum/mavg/stateCount/stateDuration";
const char* msg13 = "order by json tag, key is too long";
const char* msg14 = "order by json tag, must be json->'key'";
......@@ -7526,7 +7590,8 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQu
int32_t f = pExpr->base.functionId;
if ((f == TSDB_FUNC_PRJ && pExpr->base.numOfParams == 0) ||
f == TSDB_FUNC_DIFF || f == TSDB_FUNC_SCALAR_EXPR || f == TSDB_FUNC_DERIVATIVE ||
f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG)
f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG || f == TSDB_FUNC_STATE_COUNT ||
f == TSDB_FUNC_STATE_DURATION)
{
isProjectionFunction = true;
break;
......@@ -8162,7 +8227,8 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, char* msg) {
int16_t functionId = pExpr->base.functionId;
if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TS ||
functionId == TSDB_FUNC_SCALAR_EXPR || functionId == TSDB_FUNC_TS_DUMMY) {
functionId == TSDB_FUNC_SCALAR_EXPR || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_STATE_COUNT ||
functionId == TSDB_FUNC_STATE_DURATION) {
continue;
}
......@@ -8365,12 +8431,11 @@ static int32_t doTagFunctionCheck(SQueryInfo* pQueryInfo) {
int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char* msg) {
const char* msg1 = "functions/columns not allowed in group by query";
const char* msg2 = "projection query on columns not allowed";
const char* msg3 = "group by/session/state_window not allowed on projection query";
const char* msg4 = "retrieve tags not compatible with group by or interval query";
const char* msg5 = "functions can not be mixed up";
const char* msg6 = "TWA/Diff/Derivative/Irate/CSum/MAvg/Elapsed only support group by tbname";
const char* msg7 = "unique function does not supportted in state window query";
const char* msg6 = "TWA/Diff/Derivative/Irate/CSum/MAvg/Elapsed/stateCount/stateDuration only support group by tbname";
const char* msg7 = "unique/state function does not supportted in state window query";
// only retrieve tags, group by is not supportted
if (tscQueryTags(pQueryInfo)) {
......@@ -8403,31 +8468,11 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
int32_t f = pExpr->base.functionId;
/*
* group by normal columns.
* Check if the column projection is identical to the group by column or not
*/
if (f == TSDB_FUNC_PRJ && pExpr->base.colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
bool qualified = false;
for (int32_t j = 0; j < pQueryInfo->groupbyExpr.numOfGroupCols; ++j) {
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, j);
if (pColIndex->colId == pExpr->base.colInfo.colId) {
qualified = true;
break;
}
}
if (!qualified) {
return invalidOperationMsg(msg, msg2);
}
}
if (f < 0) {
SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * f - 1);
if (pUdfInfo->funcType == TSDB_UDF_TYPE_SCALAR) {
return invalidOperationMsg(msg, msg1);
}
continue;
}
......@@ -8437,7 +8482,8 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
}
if ((!pQueryInfo->stateWindow) && (f == TSDB_FUNC_DIFF || f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA ||
f == TSDB_FUNC_IRATE || f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG || f == TSDB_FUNC_ELAPSED)) {
f == TSDB_FUNC_IRATE || f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG || f == TSDB_FUNC_ELAPSED ||
f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION)) {
for (int32_t j = 0; j < pQueryInfo->groupbyExpr.numOfGroupCols; ++j) {
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, j);
if (j == 0) {
......@@ -8450,7 +8496,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
}
}
if (pQueryInfo->stateWindow && f == TSDB_FUNC_UNIQUE){
if (pQueryInfo->stateWindow && (f == TSDB_FUNC_UNIQUE || f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION)){
return invalidOperationMsg(msg, msg7);
}
......@@ -8460,11 +8506,6 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, char*
f != TSDB_FUNC_UNIQUE && f != TSDB_FUNC_TAIL) {
return invalidOperationMsg(msg, msg1);
}
if (f == TSDB_FUNC_COUNT && pExpr->base.colInfo.colIndex == TSDB_TBNAME_COLUMN_INDEX) {
return invalidOperationMsg(msg, msg1);
}
}
if (checkUpdateTagPrjFunctions(pQueryInfo, msg) != TSDB_CODE_SUCCESS) {
......@@ -8501,7 +8542,8 @@ int32_t validateFunctionFromUpstream(SQueryInfo* pQueryInfo, char* msg) {
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
int32_t f = pExpr->base.functionId;
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_ELAPSED) {
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_ELAPSED ||
f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION) {
for (int32_t j = 0; j < upNum; ++j) {
SQueryInfo* pUp = taosArrayGetP(pQueryInfo->pUpstream, j);
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pUp, 0);
......@@ -9498,12 +9540,23 @@ int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelectNode
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
pLeft->functionId = isValidFunction(pLeft->Expr.operand.z, pLeft->Expr.operand.n);
if (pLeft->functionId < 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
if (pLeft->Expr.paramList) {
size_t size = taosArrayGetSize(pLeft->Expr.paramList);
for (int32_t i = 0; i < size; i++) {
tSqlExprItem* pParamItem = taosArrayGet(pLeft->Expr.paramList, i);
tSqlExpr* pExpr1 = pParamItem->pNode;
if (pLeft->functionId == TSDB_FUNC_STATE_COUNT || pLeft->functionId == TSDB_FUNC_STATE_DURATION){
if (i == 1 && pExpr1->tokenId == TK_ID) continue;
if (pLeft->functionId == TSDB_FUNC_STATE_DURATION && i == 3 && pExpr1->tokenId == TK_TIMESTAMP)
continue;
}
if (pExpr1->tokenId != TK_ALL &&
pExpr1->tokenId != TK_ID &&
pExpr1->tokenId != TK_STRING &&
......@@ -9533,11 +9586,6 @@ int32_t getHavingExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelectNode
}
}
pLeft->functionId = isValidFunction(pLeft->Expr.operand.z, pLeft->Expr.operand.n);
if (pLeft->functionId < 0) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
}
return handleExprInHavingClause(pCmd, pQueryInfo, pSelectNodeList, pExpr, parentOptr);
}
......@@ -10061,7 +10109,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
const char* msg4 = "interval query not supported, since the result of sub query not include valid timestamp column";
const char* msg5 = "only tag query not compatible with normal column filter";
const char* msg6 = "not support stddev/percentile in the outer query yet";
const char* msg7 = "derivative/twa/rate/irate/diff/tail requires timestamp column exists in subquery";
const char* msg7 = "derivative/twa/rate/irate/diff/tail/stateCount/stateDuration requires timestamp column exists in subquery";
const char* msg8 = "condition missing for join query";
const char* msg9 = "not support 3 level select";
......@@ -10143,7 +10191,8 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
int32_t f = pExpr->base.functionId;
if (f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_TWA || f == TSDB_FUNC_IRATE ||
f == TSDB_FUNC_RATE || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_TAIL) {
f == TSDB_FUNC_RATE || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_TAIL ||
f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION) {
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
}
}
......
......@@ -1184,7 +1184,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
tlv->len = htonl(sizeof(int16_t) * 2);
*(int16_t*)tlv->value = htons(pTableMeta->sversion);
*(int16_t*)(tlv->value+sizeof(int16_t)) = htons(pTableMeta->tversion);
pMsg += sizeof(*tlv) + ntohl(tlv->len);
pMsg += sizeof(*tlv) + sizeof(int16_t) * 2;
tlv = (STLV *)pMsg;
tlv->type = htons(TLV_TYPE_END_MARK);
......
......@@ -328,7 +328,8 @@ bool tscIsProjectionQuery(SQueryInfo* pQueryInfo) {
if (f != TSDB_FUNC_PRJ && f != TSDB_FUNC_TAGPRJ && f != TSDB_FUNC_TAG &&
f != TSDB_FUNC_TS && f != TSDB_FUNC_SCALAR_EXPR && f != TSDB_FUNC_DIFF &&
f != TSDB_FUNC_DERIVATIVE && !TSDB_FUNC_IS_SCALAR(f)) {
f != TSDB_FUNC_DERIVATIVE && !TSDB_FUNC_IS_SCALAR(f) &&
f != TSDB_FUNC_STATE_COUNT && f != TSDB_FUNC_STATE_DURATION) {
return false;
}
}
......@@ -347,8 +348,8 @@ bool tscIsDiffDerivLikeQuery(SQueryInfo* pQueryInfo) {
continue;
}
if (f == TSDB_FUNC_DIFF || f == TSDB_FUNC_DERIVATIVE ||
f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG) {
if (f == TSDB_FUNC_DIFF || f == TSDB_FUNC_DERIVATIVE || f == TSDB_FUNC_CSUM || f == TSDB_FUNC_MAVG ||
f == TSDB_FUNC_STATE_COUNT || f == TSDB_FUNC_STATE_DURATION) {
return true;
}
}
......@@ -356,7 +357,6 @@ bool tscIsDiffDerivLikeQuery(SQueryInfo* pQueryInfo) {
return false;
}
bool tscHasColumnFilter(SQueryInfo* pQueryInfo) {
// filter on primary timestamp column
if (pQueryInfo->window.skey != INT64_MIN || pQueryInfo->window.ekey != INT64_MAX) {
......@@ -5088,7 +5088,6 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt
pQueryAttr->pUdfInfo = pQueryInfo->pUdfInfo;
pQueryAttr->range = pQueryInfo->range;
if (pQueryInfo->order.order == TSDB_ORDER_ASC) { // TODO refactor
pQueryAttr->window = pQueryInfo->window;
} else {
......
......@@ -565,6 +565,9 @@ static void shellPrintNChar(const char *str, int length, int width) {
if (bytes <= 0) {
break;
}
if (pos + bytes > length) {
break;
}
int w = 0;
#ifdef WINDOWS
w = bytes;
......@@ -575,15 +578,11 @@ static void shellPrintNChar(const char *str, int length, int width) {
w = wcwidth(wc);
}
#endif
pos += bytes;
if (w <= 0) {
continue;
}
pos += bytes;
if (pos > length) {
break;
}
if (width <= 0) {
printf("%lc", wc);
continue;
......
......@@ -81,8 +81,10 @@ extern "C" {
#define TSDB_FUNC_UNIQUE 39
#define TSDB_FUNC_MODE 40
#define TSDB_FUNC_TAIL 41
#define TSDB_FUNC_STATE_COUNT 42
#define TSDB_FUNC_STATE_DURATION 43
#define TSDB_FUNC_MAX_NUM 42
#define TSDB_FUNC_MAX_NUM 44
#define TSDB_FUNCSTATE_SO 0x1u // single output
#define TSDB_FUNCSTATE_MO 0x2u // dynamic number of output, not multinumber of output e.g., TOP/BOTTOM
......@@ -230,6 +232,8 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
int32_t *len, int32_t *interBytes, int16_t extLength, bool isSuperTable, SUdfInfo* pUdfInfo);
int32_t isValidFunction(const char* name, int32_t len);
bool isValidStateOper(char *oper, int32_t len);
#define IS_STREAM_QUERY_VALID(x) (((x)&TSDB_FUNCSTATE_STREAM) != 0)
#define IS_MULTIOUTPUT(x) (((x)&TSDB_FUNCSTATE_MO) != 0)
#define IS_SINGLEOUTPUT(x) (((x)&TSDB_FUNCSTATE_SO) != 0)
......
......@@ -230,6 +230,7 @@ typedef struct SQueryAttr {
bool stabledev; // super table stddev query
bool tsCompQuery; // is tscomp query
bool diffQuery; // is diff query
bool stateQuery; // is state query
bool simpleAgg;
bool pointInterpQuery; // point interpolation query
bool needTableSeqScan; // need scan table by table
......
......@@ -211,6 +211,14 @@ typedef struct {
};
} SDiffFuncInfo;
typedef struct {
union {
int64_t countPrev;
int64_t durationStart;
};
} SStateInfo;
typedef struct {
double lower; // >lower
double upper; // <=upper
......@@ -319,6 +327,13 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
return TSDB_CODE_SUCCESS;
}
if (functionId == TSDB_FUNC_STATE_COUNT || functionId == TSDB_FUNC_STATE_DURATION) {
*type = TSDB_DATA_TYPE_BIGINT;
*bytes = sizeof(int64_t);
*interBytes = sizeof(SStateInfo);
return TSDB_CODE_SUCCESS;
}
if (functionId == TSDB_FUNC_CSUM) {
if (IS_SIGNED_NUMERIC_TYPE(dataType)) {
*type = TSDB_DATA_TYPE_BIGINT;
......@@ -625,6 +640,76 @@ int32_t isValidFunction(const char* name, int32_t len) {
return -1;
}
bool isValidStateOper(char *oper, int32_t len){
return strncmp(oper, "lt", len) == 0 || strncmp(oper, "gt", len) == 0 || strncmp(oper, "le", len) == 0 ||
strncmp(oper, "ge", len) == 0 || strncmp(oper, "ne", len) == 0 || strncmp(oper, "eq", len) == 0;
}
#define STATEOPER(OPER, COMP, TYPE) if (strncmp(oper->pz, OPER, oper->nLen) == 0) {\
if (pVar->nType == TSDB_DATA_TYPE_BIGINT && *(TYPE)data COMP pVar->i64) return true;\
else if(pVar->nType == TSDB_DATA_TYPE_DOUBLE && *(TYPE)data COMP pVar->dKey) return true;\
else return false;}
#define STATEJUDGE(TYPE) STATEOPER("lt", <, TYPE)\
STATEOPER("gt", >, TYPE)\
STATEOPER("le", <=, TYPE)\
STATEOPER("ge", >=, TYPE)\
STATEOPER("ne", !=, TYPE)\
STATEOPER("eq", ==, TYPE)
static bool isStateOperTrue(void *data, int16_t type, tVariant *oper, tVariant *pVar){
switch (type) {
case TSDB_DATA_TYPE_INT: {
STATEJUDGE(int32_t *)
break;
}
case TSDB_DATA_TYPE_UINT: {
STATEJUDGE(uint32_t *)
break;
}
case TSDB_DATA_TYPE_BIGINT: {
STATEJUDGE(int64_t *)
break;
}case TSDB_DATA_TYPE_UBIGINT: {
STATEJUDGE(uint64_t *)
break;
}
case TSDB_DATA_TYPE_DOUBLE: {
STATEJUDGE(double *)
break;
}
case TSDB_DATA_TYPE_FLOAT: {
STATEJUDGE(float *)
break;
}
case TSDB_DATA_TYPE_SMALLINT: {
STATEJUDGE(int16_t *)
break;
}
case TSDB_DATA_TYPE_USMALLINT: {
STATEJUDGE(uint16_t *)
break;
}
case TSDB_DATA_TYPE_TINYINT: {
STATEJUDGE(int8_t *)
break;
}
case TSDB_DATA_TYPE_UTINYINT: {
STATEJUDGE(uint8_t *)
break;
}
default:
qError("error input type");
}
return false;
}
static bool function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) {
if (pResultInfo->initialized) {
return false;
......@@ -5317,7 +5402,7 @@ static void unique_func_finalizer(SQLFunctionCtx *pCtx) {
}
SortSupporter support = {0};
// user specify the order of output by sort the result according to timestamp
if (pCtx->param[2].i64 == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
if (pCtx->param[2].i64 == PRIMARYKEY_TIMESTAMP_COL_INDEX || pCtx->param[2].i64 == TSDB_RES_COL_ID) {
support.dataOffset = 0;
support.comparFn = compareInt64Val;
} else{
......@@ -5616,7 +5701,7 @@ static void tail_func_finalizer(SQLFunctionCtx *pCtx) {
SortSupporter support = {0};
// user specify the order of output by sort the result according to timestamp
if (pCtx->param[2].i64 != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
if (pCtx->param[2].i64 != PRIMARYKEY_TIMESTAMP_COL_INDEX && pCtx->param[2].i64 != TSDB_RES_COL_ID) {
support.dataOffset = sizeof(int64_t);
support.comparFn = getComparFunc(type, 0);
taosqsort(data, (size_t)GET_RES_INFO(pCtx)->numOfRes, size, &support, sortCompareFn);
......@@ -5627,6 +5712,69 @@ static void tail_func_finalizer(SQLFunctionCtx *pCtx) {
doFinalizer(pCtx);
}
static void state_count_function(SQLFunctionCtx *pCtx) {
SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
SStateInfo *pStateInfo = GET_ROWCELL_INTERBUF(pResInfo);
void *data = GET_INPUT_DATA_LIST(pCtx);
int64_t *pOutput = (int64_t *)pCtx->pOutput;
for (int32_t i = 0; i < pCtx->size; i++,pOutput++,data += pCtx->inputBytes) {
if (pCtx->hasNull && isNull(data, pCtx->inputType)) {
setNull(pOutput, TSDB_DATA_TYPE_BIGINT, 0);
continue;
}
if (isStateOperTrue(data, pCtx->inputType, &pCtx->param[0], &pCtx->param[1])){
*pOutput = ++pStateInfo->countPrev;
}else{
*pOutput = -1;
pStateInfo->countPrev = 0;
}
}
for (int t = 0; t < pCtx->tagInfo.numOfTagCols; ++t) {
SQLFunctionCtx* tagCtx = pCtx->tagInfo.pTagCtxList[t];
if (tagCtx->functionId == TSDB_FUNC_TAG_DUMMY) {
aAggs[TSDB_FUNC_TAGPRJ].xFunction(tagCtx);
}
}
pResInfo->numOfRes += pCtx->size;
}
static void state_duration_function(SQLFunctionCtx *pCtx) {
SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx);
SStateInfo *pStateInfo = GET_ROWCELL_INTERBUF(pResInfo);
void *data = GET_INPUT_DATA_LIST(pCtx);
TSKEY* tsList = GET_TS_LIST(pCtx);
int64_t *pOutput = (int64_t *)pCtx->pOutput;
for (int32_t i = 0; i < pCtx->size; i++,pOutput++,data += pCtx->inputBytes) {
if (pCtx->hasNull && isNull(data, pCtx->inputType)) {
setNull(pOutput, TSDB_DATA_TYPE_BIGINT, 0);
continue;
}
if (isStateOperTrue(data, pCtx->inputType, &pCtx->param[0], &pCtx->param[1])){
if (pStateInfo->durationStart == 0) {
*pOutput = 0;
pStateInfo->durationStart = tsList[i];
} else {
*pOutput = (tsList[i] - pStateInfo->durationStart)/pCtx->param[2].i64;
}
} else{
*pOutput = -1;
pStateInfo->durationStart = 0;
}
}
for (int t = 0; t < pCtx->tagInfo.numOfTagCols; ++t) {
SQLFunctionCtx* tagCtx = pCtx->tagInfo.pTagCtxList[t];
if (tagCtx->functionId == TSDB_FUNC_TAG_DUMMY) {
aAggs[TSDB_FUNC_TAGPRJ].xFunction(tagCtx);
}
}
pResInfo->numOfRes += pCtx->size;
}
/////////////////////////////////////////////////////////////////////////////////////////////
/*
* function compatible list.
......@@ -5647,8 +5795,8 @@ int32_t functionCompatList[] = {
1, 1, 1, 1, -1, 1, 1, 1, 5, 1, 1,
// tid_tag, deriv, csum, mavg, sample,
6, 8, -1, -1, -1,
// block_info,elapsed,histogram,unique,mode,tail
7, 1, -1, -1, 1, -1
// block_info,elapsed,histogram,unique,mode,tail, stateCount, stateDuration
7, 1, -1, -1, 1, -1, 1, 1,
};
SAggFunctionInfo aAggs[TSDB_FUNC_MAX_NUM] = {{
......@@ -6157,5 +6305,29 @@ SAggFunctionInfo aAggs[TSDB_FUNC_MAX_NUM] = {{
tail_func_finalizer,
tail_func_merge,
tailFuncRequired,
},
{
// 42
"stateCount",
TSDB_FUNC_STATE_COUNT,
TSDB_FUNC_INVALID_ID,
TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS,
function_setup,
state_count_function,
doFinalizer,
noop1,
dataBlockRequired,
},
{
// 43
"stateDuration",
TSDB_FUNC_STATE_DURATION,
TSDB_FUNC_INVALID_ID,
TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS,
function_setup,
state_duration_function,
doFinalizer,
noop1,
dataBlockRequired,
}
};
......@@ -2042,7 +2042,6 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
pRuntimeEnv->prevGroupId = INT32_MIN;
pRuntimeEnv->pQueryAttr = pQueryAttr;
pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
pRuntimeEnv->pResultRowListSet = taosHashInit(numOfTables * 10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
......@@ -2661,7 +2660,7 @@ static void updateDataCheckOrder(SQInfo *pQInfo, SQueryTableMsg* pQueryMsg, bool
return;
}
if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) {
if ((pQueryAttr->groupbyColumn || pQueryAttr->stateQuery) && pQueryAttr->order.order == TSDB_ORDER_DESC) {
pQueryAttr->order.order = TSDB_ORDER_ASC;
if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
SWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey, TSKEY);
......@@ -3174,7 +3173,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa
pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
} else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery) && (!pQueryAttr->diffQuery) && (!pQueryAttr->pointInterpQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
} else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery) && (!pQueryAttr->pointInterpQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
pRuntimeEnv->current->groupIndex);
......@@ -9585,6 +9584,9 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S
if (pExprs[col].base.flist.filterInfo) {
++pQueryAttr->havingNum;
}
if (pExprs[col].base.functionId == TSDB_FUNC_STATE_COUNT || pExprs[col].base.functionId == TSDB_FUNC_STATE_DURATION){
pQueryAttr->stateQuery = true;
}
}
doUpdateExprColumnIndex(pQueryAttr);
......
......@@ -48,8 +48,6 @@ static SKeyword keywordTable[] = {
{"OR", TK_OR},
{"AND", TK_AND},
{"NOT", TK_NOT},
{"EQ", TK_EQ},
{"NE", TK_NE},
{"ISNULL", TK_ISNULL},
{"NOTNULL", TK_NOTNULL},
{"IS", TK_IS},
......@@ -58,10 +56,6 @@ static SKeyword keywordTable[] = {
{"GLOB", TK_GLOB},
{"BETWEEN", TK_BETWEEN},
{"IN", TK_IN},
{"GT", TK_GT},
{"GE", TK_GE},
{"LT", TK_LT},
{"LE", TK_LE},
{"BITAND", TK_BITAND},
{"BITOR", TK_BITOR},
{"LSHIFT", TK_LSHIFT},
......
###################################################################
# Copyright (c) 2021 by TAOS Technologies, Inc.
# All rights reserved.
#
# This file is proprietary and confidential to TAOS Technologies.
# No part of this file may be reproduced, stored, transmitted,
# disclosed or used in any form or by any means other than as
# expressly provided by the written permission from Jianhui Tao
#
###################################################################
# -*- coding: utf-8 -*-
import sys
from util.log import *
from util.cases import *
from util.sql import *
class TDTestCase:
def caseDescription(self):
'''
case1<markwang>: [TD-11210] function stateCount stateDuration
'''
return
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
self._conn = conn
def run(self):
print("running {}".format(__file__))
tdSql.execute("drop database if exists statef")
tdSql.execute("create database if not exists statef PRECISION 'ns'")
tdSql.execute('use statef')
tdSql.execute('create table sstatef (ts timestamp, dbig bigint, dsmall smallint, dbool bool, dtiny tinyint unsigned, dfloat float, ddouble double, dnchar nchar(4093), dbinary binary(64), dtime timestamp) tags (tbinary nchar(4093), tint int)')
tdSql.execute('create table statef1 using sstatef tags ("t1", 1)')
tdSql.execute('create table statef2 using sstatef tags ("t2", 2)')
tdSql.execute('insert into statef1 values("2021-10-17 00:31:31", 1, -3276, true, 253, 3.32333, 4.984392323, "你好", "sddd", 333) ("2022-01-24 00:31:32", 1, -32767, false, 254, NULL, 4.982392323, "你好吗", "sdf",2323)')
tdSql.execute('insert into statef2 values("2021-10-15 00:31:33", 1, NULL, true, 23, 3.4, 4.982392323, "你好吗", "sdf", 333) ("2021-12-24 00:31:34", 2, 32767, NULL, NULL, NULL, 4.982392323, NULL, "sddd", NULL) ("2022-01-01 08:00:05", 19, 3276, true, 2, 3.323222, 4.92323, "试试", "sddd", 1645434434000)')
tdSql.execute('insert into statef2 values("2021-10-17 00:31:31", NULL, 32767, true, 123, 3.323232333, 4.2, NULL, NULL, NULL) ("2022-01-01 08:00:06", NULL, NULL, NULL, 35, 3.323232333, NULL, "试试", NULL, 1645434434000) ("2022-01-01 08:00:07", 9, 54, true, 25, 3.32333, NULL, "试试", NULL, 1645434434001)')
# error
tdSql.error("select stateCount(ts,LE,4.923230000) from statef2")
tdSql.error("select stateCount(dbool,LE,4.923230000) from statef2")
tdSql.error("select stateCount(dnchar,LE,4.923230000) from statef2")
tdSql.error("select stateCount(dbinary,LE,4.923230000) from statef2")
tdSql.error("select stateCount(dtime,LE,4.923230000) from statef2")
tdSql.error("select stateCount(tint,LE,4.923230000) from statef2")
tdSql.error("select stateCount(tbinary,LE,4.923230000) from statef2")
tdSql.error("select stateCount(tbinary,ew,4.923230000) from statef2")
tdSql.error("select stateCount(tbinary,23,4.923230000) from statef2")
tdSql.query("select stateCount(dtiny,le,1e3) from statef2")
tdSql.error("select stateCount(dtiny,le,1e3) from statef")
tdSql.error("select stateDuration(dtiny,le,1e3) from statef")
tdSql.query("select stateDuration(dtiny,le,1e3) from statef2")
tdSql.error("select stateCount(dtiny,le,'1e3') from statef2")
tdSql.error("select stateCount(dtiny,le,le) from statef2")
tdSql.error("select stateDuration(dtiny,le,le) from statef2")
tdSql.error("select stateCount(dtiny,le,2,1s) from statef2")
tdSql.error("select stateDuration(dtiny,le,2,1) from statef2")
tdSql.error("select stateDuration(dtiny,le,2,'1s') from statef2")
tdSql.error("select stateDuration(dtiny,le,2,2s) from statef2")
tdSql.error("select stateCount(dtiny,le,1e3),top(dtiny,1) from statef2")
tdSql.error("select stateCount(dtiny,le,1e3),first(dbig) from statef2")
tdSql.error("select stateCount(dtiny,le,1e3),ceil(dsmall) from statef2")
#interval
tdSql.error('select stateCount(dtiny,ne,9.0) from statef2 interval(1s)')
tdSql.error('select stateDuration(dtiny,ne,9.0,1s) from statef2 interval(1s)')
#state_window
tdSql.error('select stateCount(dtiny,ne,9.0) from statef2 state_window(dbool)')
tdSql.error('select stateDuration(dtiny,ne,9.0,1s) from statef2 state_window(dbool)')
#session
tdSql.error('select stateCount(dtiny,ne,9.0) from statef2 session(ts,1w)')
tdSql.error('select stateDuration(dtiny,ne,9.0,1s) from statef2 session(ts,1w)')
tdSql.error('select stateDuration(dfloat,Ge,3.32323) from (select dfloat from statef2)')
tdSql.error('select stateCount(dfloat,Ge,3.32323) from (select dfloat from statef2)')
## test normal table
tdSql.query('select stateCount(dtiny,GT,10) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 0, "2021-10-15 00:31:33")
tdSql.checkData(0, 1, 23)
tdSql.checkData(0, 2, 1)
tdSql.checkData(1, 0, "2021-10-17 00:31:31")
tdSql.checkData(1, 1, 123)
tdSql.checkData(1, 2, 2)
tdSql.checkData(2, 0, "2021-12-24 00:31:34")
tdSql.checkData(2, 1, None)
tdSql.checkData(2, 2, None)
tdSql.checkData(3, 0, "2022-01-01 08:00:05")
tdSql.checkData(3, 1, 2)
tdSql.checkData(3, 2, -1)
tdSql.checkData(4, 0, "2022-01-01 08:00:06")
tdSql.checkData(4, 1, 35)
tdSql.checkData(4, 2, 1)
tdSql.checkData(5, 0, "2022-01-01 08:00:07")
tdSql.checkData(5, 1, 25)
tdSql.checkData(5, 2, 2)
tdSql.query('select dtiny,ts,stateCount(dtiny,GT,10),*,tbinary from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 1, "2021-10-15 00:31:33")
tdSql.checkData(1, 2, 123)
tdSql.checkData(2, 6, 2)
tdSql.checkData(3, 15, "t2")
tdSql.query('select stateCount(dtiny,LT,10) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, -1)
tdSql.checkData(1, 2, -1)
tdSql.checkData(3, 2, 1)
tdSql.checkData(4, 2, -1)
tdSql.query('select stateCount(ddouble,LE,4.923230000) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, -1)
tdSql.checkData(1, 2, 1)
tdSql.checkData(2, 2, -1)
tdSql.checkData(3, 2, 1)
tdSql.checkData(4, 2, None)
tdSql.checkData(5, 2, None)
tdSql.query('select stateCount(dfloat,Ge,3.32323) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, 1)
tdSql.checkData(1, 2, 2)
tdSql.checkData(2, 2, None)
tdSql.checkData(3, 2, -1)
tdSql.checkData(4, 2, 1)
tdSql.checkData(5, 2, 2)
tdSql.query('select stateCount(dsmall,eq,3276.0) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, None)
tdSql.checkData(1, 2, -1)
tdSql.checkData(2, 2, -1)
tdSql.checkData(3, 2, 1)
tdSql.checkData(4, 2, None)
tdSql.checkData(5, 2, -1)
tdSql.query('select stateCount(dbig,ne,9.0) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, 1)
tdSql.checkData(1, 2, None)
tdSql.checkData(2, 2, 2)
tdSql.checkData(3, 2, 3)
tdSql.checkData(4, 2, None)
tdSql.checkData(5, 2, -1)
tdSql.query('select stateDuration(dtiny,ne,9.0) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, 0)
tdSql.checkData(1, 2, 172798)
tdSql.checkData(2, 2, None)
tdSql.checkData(3, 2, 6766112)
tdSql.checkData(4, 2, 6766113)
tdSql.checkData(5, 2, 6766114)
tdSql.query('select stateDuration(dtiny,ne,9.0,1h) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, 0)
tdSql.checkData(1, 2, 47)
tdSql.checkData(2, 2, None)
tdSql.checkData(3, 2, 1879)
tdSql.checkData(4, 2, 1879)
tdSql.checkData(5, 2, 1879)
tdSql.query('select stateDuration(dtiny,ne,9.0,1m) from statef2')
tdSql.checkRows(6)
tdSql.checkData(0, 2, 0)
tdSql.checkData(1, 2, 2879)
tdSql.checkData(2, 2, None)
tdSql.checkData(3, 2, 112768)
tdSql.checkData(4, 2, 112768)
tdSql.checkData(5, 2, 112768)
## test super table
tdSql.query('select stateDuration(dtiny,ne,9.0,1s) from sstatef group by tbname')
tdSql.checkRows(8)
tdSql.checkData(0, 2, 0)
tdSql.checkData(1, 2, 8553601)
#where
tdSql.query('select stateCount(dfloat,Ge,3.32323) from statef2 where dfloat >3.32323')
tdSql.checkRows(4)
tdSql.checkData(0, 2, 1)
tdSql.checkData(1, 2, 2)
tdSql.checkData(2, 2, 3)
tdSql.checkData(3, 2, 4)
tdSql.query('select stateDuration(dfloat,Ge,3.32323) from statef2 where dfloat <3.4')
tdSql.checkRows(4)
tdSql.checkData(0, 2, 0)
tdSql.checkData(1, 2, -1)
tdSql.checkData(2, 2, 0)
tdSql.checkData(3, 2, 1)
tdSql.query('select stateDuration(dfloat,Ge,3.32323,1m) from statef2 where dfloat <3.4')
tdSql.checkRows(4)
tdSql.checkData(3, 2, 0)
#slimit/soffset
tdSql.query('select stateDuration(dtiny,ne,9.0,1s) from sstatef group by tbname slimit 2 soffset 1')
tdSql.checkRows(6)
#limit/offset
tdSql.query('select stateCount(dfloat,Ge,3.32323) from statef2 limit 1,2')
tdSql.checkRows(2)
tdSql.checkData(0, 0, "2021-10-17 00:31:31")
tdSql.checkData(0, 2, 2)
tdSql.checkData(1, 2, None)
#having
tdSql.query('select stateDuration(dtiny,ne,9.0,1s) from sstatef group by tbname having stateDuration(dtiny,ne,9.0,1s) > 0')
#subquery
tdSql.error('select stateDuration(dfloat,Ge,3.32323) from (select ts,dfloat from statef2)')
#union
tdSql.query('select stateCount(dfloat,Ge,3.32323) from statef1 union all select stateCount(dfloat,Ge,3.32323) from statef2')
tdSql.checkRows(8)
tdSql.checkData(0, 2, 1)
tdSql.checkData(3, 2, 2)
#join
tdSql.execute('create table sstatef1 (ts timestamp, dbig bigint, dsmall smallint, dbool bool, dtiny tinyint unsigned, dfloat float, ddouble double, dnchar nchar(4093), dbinary binary(64), dtime timestamp) tags (tbinary nchar(4093), tint int)')
tdSql.execute('create table statef11 using sstatef1 tags ("t1", 1)')
tdSql.execute('insert into statef11 values("2021-10-17 00:31:31", 1, -3276, true, 253, 3.32333, 4.984392323, "你好", "sddd", 333) ("2022-01-24 00:31:32", 1, -32767, false, 254, NULL, 4.982392323, "你好吗", "sdf",2323)')
tdSql.error('select stateCount(sstatef.dsmall,eq,3276.0) from sstatef, sstatef1 where sstatef.ts=sstatef1.ts and sstatef.tint=sstatef1.tint')
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
......@@ -321,6 +321,20 @@ class TDTestCase:
tdSql.checkData(1, 0, "2022-01-01 08:00:07")
tdSql.checkData(1, 1, "试试")
tdSql.query('select tail(dbig, 3) from (select * from stail) order by ts')
tdSql.checkRows(3)
tdSql.checkData(0, 0, "2022-01-01 08:00:06")
tdSql.checkData(0, 1, None)
tdSql.checkData(1, 0, "2022-01-01 08:00:07")
tdSql.checkData(1, 1, 9)
tdSql.query('select tail(dbig, 3) from (select * from stail) order by ts desc')
tdSql.checkRows(3)
tdSql.checkData(0, 0, "2022-01-24 00:31:32")
tdSql.checkData(0, 1, 1)
tdSql.checkData(1, 0, "2022-01-01 08:00:07")
tdSql.checkData(1, 1, 9)
#union
tdSql.query('select tail(dtiny,2) from tail1 union all select tail(dtiny,2) from tail2')
tdSql.checkRows(4)
......
......@@ -256,6 +256,20 @@ class TDTestCase:
tdSql.query('select unique(num) from (select * from unique where voltage > 1)')
tdSql.checkRows(2)
tdSql.query('select unique(num) from (select * from unique) order by ts')
tdSql.checkRows(2)
tdSql.checkData(0, 0, "2021-10-15 00:00:01")
tdSql.checkData(0, 1, 2)
tdSql.checkData(1, 0, "2021-12-25 01:31:31")
tdSql.checkData(1, 1, 4)
tdSql.query('select unique(num) from (select * from unique) order by ts desc')
tdSql.checkRows(2)
tdSql.checkData(0, 0, "2021-12-25 01:31:31")
tdSql.checkData(0, 1, 4)
tdSql.checkData(1, 0, "2021-10-15 00:00:01")
tdSql.checkData(1, 1, 2)
#union
tdSql.query('select unique(voltage) from d002 union all select unique(voltage) from d003')
tdSql.checkRows(5)
......
......@@ -790,4 +790,5 @@
3,,script,./test.sh -f general/compute/scalar_str_concat_len.sim
3,,develop-test,python3 ./test.py -f 2-query/function_tail.py
2,,develop-test,python3 ./test.py -f 2-query/function_unique.py
1,,develop-test,python3 ./test.py -f 2-query/function_state.py
1,,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/demo.py
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册