diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index b3674a7bf5..42550b3339 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -61,6 +61,7 @@ typedef struct SJoinSupporter { uint64_t uid; // query table uid SArray* colList; // previous query information, no need to use this attribute, and the corresponding attribution SArray* exprList; + SArray* colCond; SFieldInfo fieldsInfo; STagCond tagCond; SGroupbyExpr groupInfo; // group by info @@ -244,8 +245,9 @@ SCond* tsGetSTableQueryCond(STagCond* pCond, uint64_t uid); void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw); int32_t tscTagCondCopy(STagCond* dest, const STagCond* src); +int32_t tscColCondCopy(SArray** dest, const SArray* src, uint64_t uid, int16_t tidx); void tscTagCondRelease(STagCond* pCond); - +void tscColCondRelease(SArray** pCond); void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SQueryInfo* pQueryInfo); bool tscShouldBeFreed(SSqlObj* pSql); @@ -355,6 +357,7 @@ char* strdup_throw(const char* str); bool vgroupInfoIdentical(SNewVgroupInfo *pExisted, SVgroupMsg* src); SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg); +STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx); void tscRemoveTableMetaBuf(STableMetaInfo* pTableMetaInfo, uint64_t id); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 173c709545..32358659d6 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -39,6 +39,7 @@ #include "ttokendef.h" #include "qScript.h" #include "ttype.h" +#include "qFilter.h" #define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0" @@ -140,6 +141,7 @@ static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlE static bool validateDebugFlag(int32_t v); static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo); static int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo); +static tSqlExpr* extractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, int32_t tableIndex); static bool isTimeWindowQuery(SQueryInfo* pQueryInfo) { return pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0; @@ -183,6 +185,9 @@ bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, if (var->nType != TSDB_DATA_TYPE_BOOL && !IS_SIGNED_NUMERIC_TYPE(var->nType)) { break; } + if (colType == TSDB_DATA_TYPE_BOOL && (var->i64 > 1 ||var->i64 < 0)) { + break; + } tbufWriteInt64(&bw, var->i64); } else if (IS_UNSIGNED_NUMERIC_TYPE(colType)) { if (IS_SIGNED_NUMERIC_TYPE(var->nType) || IS_UNSIGNED_NUMERIC_TYPE(var->nType)) { @@ -3732,8 +3737,8 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false); } else if (colType == TSDB_DATA_TYPE_NCHAR) { - // pRight->value.nLen + 1 is larger than the actual nchar string length - pColumnFilter->pz = (int64_t)calloc(1, bufLen * TSDB_NCHAR_SIZE); + // bufLen + 1 is larger than the actual nchar string length + pColumnFilter->pz = (int64_t)calloc(1, (bufLen + 1) * TSDB_NCHAR_SIZE); retVal = tVariantDump(&pRight->value, (char*)pColumnFilter->pz, colType, false); size_t len = twcslen((wchar_t*)pColumnFilter->pz); pColumnFilter->len = len * TSDB_NCHAR_SIZE; @@ -3839,51 +3844,40 @@ static int32_t tablenameCondToString(tSqlExpr* pExpr, SStringBuilder* sb) { } enum { - TSQL_EXPR_TS = 0, - TSQL_EXPR_TAG = 1, - TSQL_EXPR_COLUMN = 2, - TSQL_EXPR_TBNAME = 3, + TSQL_EXPR_TS = 1, + TSQL_EXPR_TAG = 2, + TSQL_EXPR_COLUMN = 4, + TSQL_EXPR_TBNAME = 8, + TSQL_EXPR_JOIN = 16, }; -static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) { +#define GET_MIXED_TYPE(t) (((t) >= TSQL_EXPR_JOIN) || ((t) > TSQL_EXPR_COLUMN && (t) < TSQL_EXPR_TBNAME) || ((t) == (TSQL_EXPR_TS|TSQL_EXPR_TAG))) + +static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SColumnIndex* pIndex, tSqlExpr* pExpr, int32_t sqlOptr) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); - + int32_t ret = 0; const char* msg1 = "non binary column not support like operator"; const char* msg2 = "binary column not support this operator"; const char* msg3 = "bool column not support this operator"; const char* msg4 = "primary key not support this operator"; SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex->columnIndex, pTableMeta->id.uid, pSchema); - SColumnFilterInfo* pColFilter = NULL; + pColumn->info.flist.numOfFilters++; + /* * in case of TK_AND filter condition, we first find the corresponding column and build the query condition together * the already existed condition. */ - if (sqlOptr == TK_AND) { - // this is a new filter condition on this column - if (pColumn->info.flist.numOfFilters == 0) { - pColFilter = addColumnFilterInfo(&pColumn->info.flist); - } else { // update the existed column filter information, find the filter info here - pColFilter = &pColumn->info.flist.filterInfo[0]; - } - - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else if (sqlOptr == TK_OR) { - // TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2" - pColFilter = addColumnFilterInfo(&pColumn->info.flist); - if (pColFilter == NULL) { - return TSDB_CODE_TSC_OUT_OF_MEMORY; - } - } else { // error; + if (sqlOptr != TK_AND && sqlOptr != TK_OR) { return TSDB_CODE_TSC_INVALID_OPERATION; } + SColumnFilterInfo* pColFilter = calloc(1, sizeof(SColumnFilterInfo)); + pColFilter->filterstr = ((pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) ? 1 : 0); @@ -3894,17 +3888,20 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC && pExpr->tokenId != TK_NOTNULL && pExpr->tokenId != TK_LIKE && pExpr->tokenId != TK_IN) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + goto _err_ret; } } else { if (pExpr->tokenId == TK_LIKE) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + goto _err_ret; } if (pSchema->type == TSDB_DATA_TYPE_BOOL) { int32_t t = pExpr->tokenId; if (t != TK_EQ && t != TK_NE && t != TK_NOTNULL && t != TK_ISNULL && t != TK_IN) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); + goto _err_ret; } } } @@ -3916,7 +3913,12 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC } STableComInfo tinfo = tscGetTableInfo(pTableMeta); - return doExtractColumnFilterInfo(pCmd, pQueryInfo, tinfo.precision, pColFilter, pSchema->type, pExpr); + ret = doExtractColumnFilterInfo(pCmd, pQueryInfo, tinfo.precision, pColFilter, pSchema->type, pExpr); + +_err_ret: + freeColumnFilterInfo(pColFilter, 1); + + return ret; } static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pTableCond, SStringBuilder* sb) { @@ -3953,7 +3955,61 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* return ret; } -static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t relOptr) { +static int32_t getColQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr) { + int32_t ret = TSDB_CODE_SUCCESS; + + for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { + tSqlExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i); + if (p1 == NULL) { // no query condition on this table + continue; + } + + tExprNode* p = NULL; + + SArray* colList = taosArrayInit(10, sizeof(SColIndex)); + ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + taosArrayDestroy(colList); + + SBufferWriter bw = tbufInitWriter(NULL, false); + + TRY(0) { + exprTreeToBinary(&bw, p); + } CATCH(code) { + tbufCloseWriter(&bw); + UNUSED(code); + // TODO: more error handling + } END_TRY + + // add to required table column list + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i); + int64_t uid = pTableMetaInfo->pTableMeta->id.uid; + + STblCond cond = { + .uid = uid, + .idx = i, + .len = (int32_t)(tbufTell(&bw)), + .cond = tbufGetData(&bw, true) + }; + + if (pQueryInfo->colCond == NULL) { + pQueryInfo->colCond = taosArrayInit(2, sizeof(SCond)); + } + + taosArrayPush(pQueryInfo->colCond, &cond); + + tSqlExprDestroy(p1); + tExprTreeDestroy(p, NULL); + + if (ret) { + break; + } + } + + return ret; +} + + +static int32_t checkColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr, int32_t relOptr) { if (pExpr == NULL) { pQueryInfo->onlyHasTagCond &= true; return TSDB_CODE_SUCCESS; @@ -3961,19 +4017,19 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSq pQueryInfo->onlyHasTagCond &= false; if (!tSqlExprIsParentOfLeaf(pExpr)) { // internal node - int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); + int32_t ret = checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->tokenId); if (ret != TSDB_CODE_SUCCESS) { return ret; } - return getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); + return checkColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pRight, pExpr->tokenId); } else { // handle leaf node SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(&pExpr->pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; } - return extractColumnFilterInfo(pCmd, pQueryInfo, &index, pExpr, relOptr); + return checkColumnFilterInfo(pCmd, pQueryInfo, &index, pExpr, relOptr); } } @@ -4240,6 +4296,10 @@ static bool isValidExpr(tSqlExpr* pLeft, tSqlExpr* pRight, int32_t optr) { return false; } + if (pLeft->tokenId >= TK_BOOL && pLeft->tokenId <= TK_BINARY && (optr == TK_NOTNULL || optr == TK_ISNULL)) { + return false; + } + return true; } @@ -4359,7 +4419,18 @@ static int32_t setExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, const char* msg return TSDB_CODE_SUCCESS; } -static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) { +static int32_t setNormalExprToCond(tSqlExpr** parent, tSqlExpr* pExpr, int32_t parentOptr) { + if (*parent != NULL) { + *parent = tSqlExprCreate((*parent), pExpr, parentOptr); + } else { + *parent = pExpr; + } + + return TSDB_CODE_SUCCESS; +} + + +static int32_t validateNullExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) { const char* msg = "only support is [not] null"; tSqlExpr* pRight = pExpr->pRight; @@ -4367,13 +4438,34 @@ static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) { return invalidOperationMsg(msgBuf, msg); } + if (pRight->tokenId == TK_STRING) { + SSchema* pSchema = tscGetTableSchema(pTableMeta); + if (IS_VAR_DATA_TYPE(pSchema[index].type)) { + return TSDB_CODE_SUCCESS; + } + + char *v = strndup(pRight->exprToken.z, pRight->exprToken.n); + int32_t len = strRmquote(v, pRight->exprToken.n); + if (len > 0) { + uint32_t type = 0; + tGetToken(v, &type); + + if (type == TK_NULL) { + free(v); + return invalidOperationMsg(msgBuf, msg); + } + } + + free(v); + } + return TSDB_CODE_SUCCESS; } // check for like expression static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) { const char* msg1 = "wildcard string should be less than %d characters"; - const char* msg2 = "illegal column name"; + const char* msg2 = "illegal column type for like"; tSqlExpr* pLeft = pExpr->pLeft; tSqlExpr* pRight = pExpr->pRight; @@ -4394,11 +4486,23 @@ static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t return TSDB_CODE_SUCCESS; } +int32_t handleNeOptr(tSqlExpr** rexpr, tSqlExpr* expr) { + tSqlExpr* left = tSqlExprClone(expr); + tSqlExpr* right = expr; + + left->tokenId = TK_LT; + right->tokenId = TK_GT; + + *rexpr = tSqlExprCreate(left, right, TK_OR); + + return TSDB_CODE_SUCCESS; +} + + static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr) { + int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { const char* msg1 = "table query cannot use tags filter"; const char* msg2 = "illegal column name"; - const char* msg3 = "only one query time range allowed"; const char* msg4 = "too many join tables"; const char* msg5 = "not support ordinary column join"; const char* msg6 = "only one query condition on tbname allowed"; @@ -4414,13 +4518,15 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); } + *tbIdx = index.tableIndex; + assert(tSqlExprIsParentOfLeaf(*pExpr)); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; // validate the null expression - int32_t code = validateNullExpr(*pExpr, tscGetErrorMsgPayload(pCmd)); + int32_t code = validateNullExpr(*pExpr, pTableMeta, index.columnIndex, tscGetErrorMsgPayload(pCmd)); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -4487,12 +4593,24 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql * since this expression is used to set the join query type */ tSqlExprDestroy(*pExpr); + if (type) { + *type |= TSQL_EXPR_JOIN; + } } else { - ret = setExprToCond(&pCondExpr->pTimewindow, *pExpr, msg3, parentOptr, pQueryInfo->msg); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE) { + handleNeOptr(&rexpr, *pExpr); + } else { + rexpr = *pExpr; + } + + ret = setNormalExprToCond(tsExpr, rexpr, parentOptr); + if (type) { + *type |= TSQL_EXPR_TS; + } } *pExpr = NULL; // remove this expression - *type = TSQL_EXPR_TS; } else if (index.columnIndex >= tscGetNumOfColumns(pTableMeta) || index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) { // query on tags, check for tag query condition if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) { @@ -4517,7 +4635,9 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } - *type = TSQL_EXPR_TBNAME; + if (type) { + *type |= TSQL_EXPR_TAG; + } *pExpr = NULL; } else { if (pRight != NULL && pRight->tokenId == TK_ID) { // join on tag columns for stable query @@ -4528,23 +4648,41 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY; ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg); *pExpr = NULL; + if (type) { + *type |= TSQL_EXPR_JOIN; + } } else { // do nothing // ret = setExprToCond(pCmd, &pCondExpr->pTagCond, // *pExpr, NULL, parentOptr); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE && (pSchema->type != TSDB_DATA_TYPE_BINARY && pSchema->type != TSDB_DATA_TYPE_NCHAR && pSchema->type != TSDB_DATA_TYPE_BOOL)) { + handleNeOptr(&rexpr, *pExpr); + *pExpr = rexpr; + } + + if (type) { + *type |= TSQL_EXPR_TAG; + } } - - *type = TSQL_EXPR_TAG; } - } else { // query on other columns - *type = TSQL_EXPR_COLUMN; - + if (type) { + *type |= TSQL_EXPR_COLUMN; + } + if (pRight->tokenId == TK_ID) { // other column cannot be served as the join column return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } - ret = setExprToCond(&pCondExpr->pColumnCond, *pExpr, NULL, parentOptr, pQueryInfo->msg); + tSqlExpr *rexpr = NULL; + if ((*pExpr)->tokenId == TK_NE && (pSchema->type != TSDB_DATA_TYPE_BINARY && pSchema->type != TSDB_DATA_TYPE_NCHAR && pSchema->type != TSDB_DATA_TYPE_BOOL)) { + handleNeOptr(&rexpr, *pExpr); + } else { + rexpr = *pExpr; + } + + ret = setNormalExprToCond(columnExpr, rexpr, parentOptr); *pExpr = NULL; // remove it from expr tree } @@ -4552,12 +4690,20 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql } int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SCondExpr* pCondExpr, - int32_t* type, int32_t parentOptr) { + int32_t* type, int32_t* tbIdx, int32_t parentOptr, tSqlExpr** columnExpr, tSqlExpr** tsExpr) { if (pExpr == NULL) { return TSDB_CODE_SUCCESS; } - const char* msg1 = "query condition between different columns must use 'AND'"; + tSqlExpr *columnLeft = NULL; + tSqlExpr *columnRight = NULL; + tSqlExpr *tsLeft = NULL; + tSqlExpr *tsRight = NULL; + + int32_t ret = 0; + + const char* msg1 = "query condition between columns/tags/timestamp/join fields must use 'AND'"; + const char* msg2 = "query condition between tables must use 'AND'"; if ((*pExpr)->flags & (1 << EXPR_FLAG_TS_ERROR)) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -4570,48 +4716,94 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr return TSDB_CODE_TSC_INVALID_OPERATION; } - int32_t leftType = -1; - int32_t rightType = -1; + int32_t leftType = 0; + int32_t rightType = 0; + int32_t leftTbIdx = 0; + int32_t rightTbIdx = 0; if (!tSqlExprIsParentOfLeaf(*pExpr)) { - int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->tokenId); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, type ? &leftType : NULL, &leftTbIdx, (*pExpr)->tokenId, &columnLeft, &tsLeft); if (ret != TSDB_CODE_SUCCESS) { - return ret; + goto err_ret; } - ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, &rightType, (*pExpr)->tokenId); + ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pRight, pCondExpr, type ? &rightType : NULL, &rightTbIdx, (*pExpr)->tokenId, &columnRight, &tsRight); if (ret != TSDB_CODE_SUCCESS) { - return ret; + goto err_ret; } /* * if left child and right child do not belong to the same group, the sub * expression is not valid for parent node, it must be TK_AND operator. */ - if (leftType != rightType) { - if ((*pExpr)->tokenId == TK_OR && (leftType + rightType != TSQL_EXPR_TBNAME + TSQL_EXPR_TAG)) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - } + if (type != NULL && ((leftType != rightType) || GET_MIXED_TYPE(leftType)) && ((*pExpr)->tokenId == TK_OR)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + goto err_ret; } - *type = rightType; + if (((leftTbIdx != rightTbIdx) || (leftTbIdx == -1 || rightTbIdx == -1)) && ((*pExpr)->tokenId == TK_OR)) { + ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); + goto err_ret; + } + + if (columnLeft && columnRight) { + setNormalExprToCond(&columnLeft, columnRight, (*pExpr)->tokenId); + + *columnExpr = columnLeft; + } else { + *columnExpr = columnLeft ? columnLeft : columnRight; + } + + if (tsLeft && tsRight) { + setNormalExprToCond(&tsLeft, tsRight, (*pExpr)->tokenId); + + *tsExpr = tsLeft; + } else { + *tsExpr = tsLeft ? tsLeft : tsRight; + } + + if (type) { + *type = leftType|rightType; + } + *tbIdx = (leftTbIdx == rightTbIdx) ? leftTbIdx : -1; + return TSDB_CODE_SUCCESS; } exchangeExpr(*pExpr); if (pLeft->tokenId == TK_ID && pRight->tokenId == TK_TIMESTAMP && (pRight->flags & (1 << EXPR_FLAG_TIMESTAMP_VAR))) { - return TSDB_CODE_TSC_INVALID_OPERATION; + ret = TSDB_CODE_TSC_INVALID_OPERATION; + goto err_ret; } if ((pLeft->flags & (1 << EXPR_FLAG_TS_ERROR)) || (pRight->flags & (1 << EXPR_FLAG_TS_ERROR))) { - return TSDB_CODE_TSC_INVALID_OPERATION; + ret = TSDB_CODE_TSC_INVALID_OPERATION; + goto err_ret; } - return handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, parentOptr); + ret = handleExprInQueryCond(pCmd, pQueryInfo, pExpr, pCondExpr, type, tbIdx, parentOptr, columnExpr, tsExpr); + if (ret) { + goto err_ret; + } + + return TSDB_CODE_SUCCESS; + +err_ret: + + tSqlExprDestroy(columnLeft); + tSqlExprDestroy(columnRight); + tSqlExprDestroy(tsLeft); + tSqlExprDestroy(tsRight); + return ret; } static void doExtractExprForSTable(SSqlCmd* pCmd, tSqlExpr** pExpr, SQueryInfo* pQueryInfo, tSqlExpr** pOut, int32_t tableIndex) { + if (*pExpr == NULL) { + *pOut = NULL; + return; + } + if (tSqlExprIsParentOfLeaf(*pExpr)) { tSqlExpr* pLeft = (*pExpr)->pLeft; @@ -4733,38 +4925,73 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, return TSDB_CODE_SUCCESS; } -static bool validateFilterExpr(SQueryInfo* pQueryInfo) { - SArray* pColList = pQueryInfo->colList; +int32_t mergeTimeRange(SSqlCmd* pCmd, STimeWindow* res, STimeWindow* win, int32_t optr) { + const char* msg0 = "only one time stamp window allowed"; + +#define SET_EMPTY_RANGE(w) do { (w)->skey = INT64_MAX; (w)->ekey = INT64_MIN; } while (0) +#define IS_EMPTY_RANGE(w) ((w)->skey == INT64_MAX && (w)->ekey == INT64_MIN) - size_t num = taosArrayGetSize(pColList); - - for (int32_t i = 0; i < num; ++i) { - SColumn* pCol = taosArrayGetP(pColList, i); - - for (int32_t j = 0; j < pCol->info.flist.numOfFilters; ++j) { - SColumnFilterInfo* pColFilter = &pCol->info.flist.filterInfo[j]; - int32_t lowerOptr = pColFilter->lowerRelOptr; - int32_t upperOptr = pColFilter->upperRelOptr; - - if ((lowerOptr == TSDB_RELATION_GREATER_EQUAL || lowerOptr == TSDB_RELATION_GREATER) && - (upperOptr == TSDB_RELATION_LESS_EQUAL || upperOptr == TSDB_RELATION_LESS)) { - continue; - } - - // there must be at least two range, not support yet. - if (lowerOptr * upperOptr != TSDB_RELATION_INVALID) { - return false; - } + if (optr == TSDB_RELATION_AND) { + if (res->skey > win->ekey || win->skey > res->ekey) { + SET_EMPTY_RANGE(res); + return TSDB_CODE_SUCCESS; } + + if (res->skey < win->skey) { + res->skey = win->skey; + } + + if (res->ekey > win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; } - return true; + if (res->skey > win->ekey || win->skey > res->ekey) { + if (IS_EMPTY_RANGE(res)) { + res->skey = win->skey; + res->ekey = win->ekey; + return TSDB_CODE_SUCCESS; + } + + if (IS_EMPTY_RANGE(win)) { + return TSDB_CODE_SUCCESS; + } + + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); + } + + if (res->skey > win->skey) { + res->skey = win->skey; + } + + if (res->ekey < win->ekey) { + res->ekey = win->ekey; + } + + return TSDB_CODE_SUCCESS; } -static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { - const char* msg0 = "invalid timestamp"; - const char* msg1 = "only one time stamp window allowed"; +static int32_t createTimeRangeExpr(tSqlExpr** pExpr, STimeWindow* win, uint32_t tokenId) { + *pExpr = calloc(1, sizeof(tSqlExpr)); + + (*pExpr)->type = SQL_NODE_VALUE; + (*pExpr)->tokenId = tokenId; + (*pExpr)->value.nType = TSDB_DATA_TYPE_VALUE_ARRAY; + (*pExpr)->value.nLen = 2; + (*pExpr)->value.arr = taosArrayInit(2, sizeof(int64_t)); + + taosArrayPush((*pExpr)->value.arr, &win->skey); + taosArrayPush((*pExpr)->value.arr, &win->ekey); + + return TSDB_CODE_SUCCESS; +} + +static int32_t convertTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* pExpr) { + const char* msg0 = "invalid timestamp or operator for timestamp"; int32_t code = 0; + STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; if (pExpr == NULL) { pQueryInfo->onlyHasTagCond &= true; @@ -4774,16 +5001,15 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE if (!tSqlExprIsParentOfLeaf(pExpr)) { - if (pExpr->tokenId == TK_OR) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - } + code = convertTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); + if (code) { + return code; + } - code = getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pLeft); - if (code) { - return code; - } - - return getTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); + code = convertTimeRangeFromExpr(pCmd, pQueryInfo, pExpr->pRight); + if (code) { + return code; + } } else { SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (getColumnIndexByName(&pExpr->pLeft->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) { @@ -4795,19 +5021,13 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlE tSqlExpr* pRight = pExpr->pRight; - STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; if (getTimeRange(&win, pRight, pExpr->tokenId, tinfo.precision) != TSDB_CODE_SUCCESS) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0); } - // update the timestamp query range - if (pQueryInfo->window.skey < win.skey) { - pQueryInfo->window.skey = win.skey; - } + createTimeRangeExpr(&pExpr->pRight, &win, pRight->tokenId); - if (pQueryInfo->window.ekey > win.ekey) { - pQueryInfo->window.ekey = win.ekey; - } + tSqlExprDestroy(pRight); } return TSDB_CODE_SUCCESS; @@ -4973,7 +5193,7 @@ static int32_t validateTagCondExpr(SSqlCmd* pCmd, tExprNode *p) { return TSDB_CODE_SUCCESS; } -static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr, tSqlExpr** pExpr) { +static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondExpr* pCondExpr) { int32_t ret = TSDB_CODE_SUCCESS; if (pCondExpr->pTagCond == NULL) { @@ -4981,7 +5201,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE } for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { - tSqlExpr* p1 = extractExprForSTable(pCmd, pExpr, pQueryInfo, i); + tSqlExpr* p1 = extractExprForSTable(pCmd, &pCondExpr->pTagCond, pQueryInfo, i); if (p1 == NULL) { // no query condition on this table continue; } @@ -4990,6 +5210,10 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE SArray* colList = taosArrayInit(10, sizeof(SColIndex)); ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL); + //if (ret == TSDB_CODE_SUCCESS) { + // ret = filterInitFromTree(p, &pQueryInfo->tagFilter, (int32_t)taosArrayGetSize(colList)); + //} + SBufferWriter bw = tbufInitWriter(NULL, false); TRY(0) { @@ -5016,14 +5240,14 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE } tsSetSTableQueryCond(&pQueryInfo->tagCond, uid, &bw); - tSqlExprCompact(pExpr); + tSqlExprCompact(&pCondExpr->pTagCond); if (ret == TSDB_CODE_SUCCESS) { ret = validateTagCondExpr(pCmd, p); } tSqlExprDestroy(p1); - tExprTreeDestroy(p, NULL); + tExprTreeDestroy(p, NULL); //TODO taosArrayDestroy(colList); if (pQueryInfo->tagCond.pCond != NULL && taosArrayGetSize(pQueryInfo->tagCond.pCond) > 0 && !UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { @@ -5035,7 +5259,6 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE } } - pCondExpr->pTagCond = NULL; return ret; } @@ -5134,6 +5357,46 @@ int32_t mergeJoinNodes(SQueryInfo* pQueryInfo, SSqlObj* pSql) { return TSDB_CODE_SUCCESS; } +static int32_t getQueryTimeRange(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr** pExpr) { + int32_t ret = TSDB_CODE_SUCCESS; + + if (*pExpr == NULL) { + return ret; + } + + //multiple tables's query time range mixed together + + tExprNode* p = NULL; + SFilterInfo *filter = NULL; + + SArray* colList = taosArrayInit(10, sizeof(SColIndex)); + ret = exprTreeFromSqlExpr(pCmd, &p, *pExpr, pQueryInfo, colList, NULL); + taosArrayDestroy(colList); + + if (ret != TSDB_CODE_SUCCESS) { + goto _ret; + } + + ret = filterInitFromTree(p, &filter, FI_OPTION_NO_REWRITE|FI_OPTION_TIMESTAMP); + if (ret != TSDB_CODE_SUCCESS) { + goto _ret; + } + + ret = filterGetTimeRange(filter, &pQueryInfo->window); + + filterFreeInfo(filter); + +_ret: + tExprTreeDestroy(p, NULL); + + if (ret) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), tstrerror(ret)); + } + + return ret; +} + + int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSql) { if (pExpr == NULL) { @@ -5141,7 +5404,7 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } const char* msg1 = "invalid expression"; - const char* msg2 = "invalid filter expression"; +// const char* msg2 = "invalid filter expression"; int32_t ret = TSDB_CODE_SUCCESS; @@ -5154,14 +5417,30 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } int32_t type = 0; - if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, &type, (*pExpr)->tokenId)) != TSDB_CODE_SUCCESS) { + int32_t tbIdx = 0; + int32_t *etype = &type; + +#if 0 + //DISABLE PARENT CONDITION GROUP TYPE CHECK + if (taosArrayGetSize(pQueryInfo->pUpstream) > 0) { + etype = NULL; + } +#endif + + if ((ret = getQueryCondExpr(&pSql->cmd, pQueryInfo, pExpr, &condExpr, etype, &tbIdx, (*pExpr)->tokenId, &condExpr.pColumnCond, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; } + if (taosArrayGetSize(pQueryInfo->pUpstream) > 0 && condExpr.pTimewindow != NULL) { + setNormalExprToCond(&condExpr.pColumnCond, condExpr.pTimewindow, TK_AND); + condExpr.pTimewindow = NULL; + } + tSqlExprCompact(pExpr); // after expression compact, the expression tree is only include tag query condition condExpr.pTagCond = (*pExpr); + *pExpr = NULL; // 1. check if it is a join query if ((ret = validateJoinExpr(&pSql->cmd, pQueryInfo, &condExpr)) != TSDB_CODE_SUCCESS) { @@ -5169,14 +5448,18 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } // 2. get the query time range - if ((ret = getTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { - return ret; + if ((ret = convertTimeRangeFromExpr(&pSql->cmd, pQueryInfo, condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; + } + + if ((ret = getQueryTimeRange(&pSql->cmd, pQueryInfo, &condExpr.pTimewindow)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } // 3. get the tag query condition - if ((ret = getTagQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr, pExpr)) != TSDB_CODE_SUCCESS) { - return ret; + if ((ret = getTagQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } // 4. get the table name query condition @@ -5185,16 +5468,15 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq } // 5. other column query condition - if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) { + if ((ret = checkColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pColumnCond, TK_AND)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; } - if (taosArrayGetSize(pQueryInfo->pUpstream) > 0 ) { - if ((ret = getColumnQueryCondInfo(&pSql->cmd, pQueryInfo, condExpr.pTimewindow, TK_AND)) != TSDB_CODE_SUCCESS) { - goto PARSE_WHERE_EXIT; - } + if ((ret = getColQueryCondExpr(&pSql->cmd, pQueryInfo, &condExpr.pColumnCond)) != TSDB_CODE_SUCCESS) { + goto PARSE_WHERE_EXIT; } + // 6. join condition if ((ret = getJoinCondInfo(&pSql->cmd, pQueryInfo, condExpr.pJoinExpr)) != TSDB_CODE_SUCCESS) { goto PARSE_WHERE_EXIT; @@ -5209,10 +5491,10 @@ int32_t validateWhereNode(SQueryInfo* pQueryInfo, tSqlExpr** pExpr, SSqlObj* pSq goto PARSE_WHERE_EXIT; } - if (!validateFilterExpr(pQueryInfo)) { - ret = invalidOperationMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2); - goto PARSE_WHERE_EXIT; - } + //if (!validateFilterExpr(pQueryInfo)) { + // ret = invalidOperationMsg(tscGetErrorMsgPayload(&pSql->cmd), msg2); + // goto PARSE_WHERE_EXIT; + //} //doAddJoinTagsColumnsIntoTagList(&pSql->cmd, pQueryInfo, &condExpr); if (condExpr.tsJoin) { @@ -5243,7 +5525,7 @@ int32_t getTimeRange(STimeWindow* win, tSqlExpr* pRight, int32_t optr, int16_t t * filter primary ts filter expression like: * where ts in ('2015-12-12 4:8:12') */ - if (pRight->tokenId == TK_SET || optr == TK_IN) { + if (pRight->tokenId == TK_SET || optr == TK_IN || optr == TK_NE) { return TSDB_CODE_TSC_INVALID_OPERATION; } @@ -8671,12 +8953,8 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf SExprInfo* pExpr1 = tscExprGet(pQueryInfo, 0); if (pExpr1->base.functionId != TSDB_FUNC_TID_TAG) { - int32_t numOfCols = (int32_t)taosArrayGetSize(pQueryInfo->colList); - for (int32_t i = 0; i < numOfCols; ++i) { - SColumn* pCols = taosArrayGetP(pQueryInfo->colList, i); - if (pCols->info.flist.numOfFilters > 0) { - return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); - } + if ((pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0) || IS_TSWINDOW_SPECIFIED(pQueryInfo->window)) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } } } @@ -8778,6 +9056,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, uint64_t *uid) { tExprNode* pLeft = NULL; tExprNode* pRight= NULL; + SColumnIndex index = COLUMN_INDEX_INITIALIZER; if (pSqlExpr->pLeft != NULL) { int32_t ret = exprTreeFromSqlExpr(pCmd, &pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, uid); @@ -8845,13 +9124,13 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS } } } else if (pSqlExpr->type == SQL_NODE_TABLE_COLUMN) { // column name, normal column arithmetic expression - SColumnIndex index = COLUMN_INDEX_INITIALIZER; int32_t ret = getColumnIndexByName(&pSqlExpr->columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)); if (ret != TSDB_CODE_SUCCESS) { return ret; } - STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta; + pQueryInfo->curTableIdx = index.tableIndex; + STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, index.tableIndex)->pTableMeta; int32_t numOfColumns = tscGetNumOfColumns(pTableMeta); *pExpr = calloc(1, sizeof(tExprNode)); @@ -8874,12 +9153,16 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS return TSDB_CODE_SUCCESS; } else if (pSqlExpr->tokenId == TK_SET) { int32_t colType = -1; - STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta; - if (pCols != NULL && taosArrayGetSize(pCols) > 0) { - SColIndex* idx = taosArrayGet(pCols, taosArrayGetSize(pCols) - 1); - SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, idx->colIndex); - if (pSchema != NULL) { - colType = pSchema->type; + STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, pQueryInfo->curTableIdx)->pTableMeta; + if (pCols != NULL) { + size_t colSize = taosArrayGetSize(pCols); + + if (colSize > 0) { + SColIndex* idx = taosArrayGet(pCols, colSize - 1); + SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, idx->colIndex); + if (pSchema != NULL) { + colType = pSchema->type; + } } } tVariant *pVal; @@ -8888,7 +9171,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS } else if (colType == TSDB_DATA_TYPE_FLOAT || colType == TSDB_DATA_TYPE_DOUBLE) { colType = TSDB_DATA_TYPE_DOUBLE; } - STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pQueryInfo->curTableIdx); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); if (serializeExprListToVariant(pSqlExpr->Expr.paramList, &pVal, colType, tinfo.precision) == false) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "not support filter expression"); @@ -8927,7 +9210,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSqlExpr* pS // NOTE: binary|nchar data allows the >|< type filter if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { if (pRight != NULL && pRight->nodeType == TSQL_NODE_VALUE) { - if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL) { + if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL && pLeft->pSchema->type == TSDB_DATA_TYPE_BOOL) { return TSDB_CODE_TSC_INVALID_OPERATION; } } @@ -8982,3 +9265,4 @@ void normalizeSqlNode(SSqlNode* pSqlNode, const char* dbName) { #endif + diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 36cc212868..e05c8b562b 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -684,7 +684,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd); int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo)); - int32_t srcColFilterSize = tscGetColFilterSerializeLen(pQueryInfo); + int32_t srcColFilterSize = 0; int32_t srcTagFilterSize = tscGetTagFilterSerializeLen(pQueryInfo); size_t numOfExprs = tscNumOfExprs(pQueryInfo); @@ -695,6 +695,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { int32_t tableSerialize = 0; STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; if (pTableMetaInfo->pVgroupTables != NULL) { size_t numOfGroups = taosArrayGetSize(pTableMetaInfo->pVgroupTables); @@ -707,8 +708,15 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { tableSerialize = totalTables * sizeof(STableIdInfo); } - return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + - exprSize + tsBufSize + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; + if (pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0) { + STblCond *pCond = tsGetTableFilter(pQueryInfo->colCond, pTableMeta->id.uid, 0); + if (pCond != NULL && pCond->cond != NULL) { + srcColFilterSize = pCond->len; + } + } + + return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + exprSize + tsBufSize + + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; } static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, char *pMsg, @@ -966,10 +974,21 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->tableCols[i].colId = htons(pCol->colId); pQueryMsg->tableCols[i].bytes = htons(pCol->bytes); pQueryMsg->tableCols[i].type = htons(pCol->type); - pQueryMsg->tableCols[i].flist.numOfFilters = htons(pCol->flist.numOfFilters); + //pQueryMsg->tableCols[i].flist.numOfFilters = htons(pCol->flist.numOfFilters); + pQueryMsg->tableCols[i].flist.numOfFilters = 0; // append the filter information after the basic column information - serializeColFilterInfo(pCol->flist.filterInfo, pCol->flist.numOfFilters, &pMsg); + //serializeColFilterInfo(pCol->flist.filterInfo, pCol->flist.numOfFilters, &pMsg); + } + + if (pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0 && !onlyQueryTags(&query) ) { + STblCond *pCond = tsGetTableFilter(pQueryInfo->colCond, pTableMeta->id.uid, 0); + if (pCond != NULL && pCond->cond != NULL) { + pQueryMsg->colCondLen = htons(pCond->len); + memcpy(pMsg, pCond->cond, pCond->len); + + pMsg += pCond->len; + } } for (int32_t i = 0; i < query.numOfOutput; ++i) { @@ -1044,7 +1063,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SCond *pCond = tsGetSTableQueryCond(pTagCond, pTableMeta->id.uid); if (pCond != NULL && pCond->cond != NULL) { - pQueryMsg->tagCondLen = htonl(pCond->len); + pQueryMsg->tagCondLen = htons(pCond->len); memcpy(pMsg, pCond->cond, pCond->len); pMsg += pCond->len; diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 8c0d642ca6..3554b43ff6 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -796,6 +796,7 @@ static void issueTsCompQuery(SSqlObj* pSql, SJoinSupporter* pSupporter, SSqlObj* STimeWindow window = pQueryInfo->window; tscInitQueryInfo(pQueryInfo); + pQueryInfo->colCond = pSupporter->colCond; pQueryInfo->window = window; TSDB_QUERY_CLEAR_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_MULTITABLE_QUERY); @@ -1883,6 +1884,9 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // return the tableId & tag SColumnIndex colIndex = {0}; + pSupporter->colCond = pNewQueryInfo->colCond; + pNewQueryInfo->colCond = NULL; + STagCond* pTagCond = &pSupporter->tagCond; assert(pTagCond->joinInfo.hasJoin); @@ -2319,6 +2323,11 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) { goto _error; } + if (tscColCondCopy(&pNewQueryInfo->colCond, pQueryInfo->colCond, pTableMetaInfo->pTableMeta->id.uid, 0) != 0) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + pNewQueryInfo->window = pQueryInfo->window; pNewQueryInfo->interval = pQueryInfo->interval; pNewQueryInfo->sessionWindow = pQueryInfo->sessionWindow; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 5a724af7bf..82f6827909 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -62,11 +62,11 @@ int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *le break; case TSDB_DATA_TYPE_FLOAT: - n = sprintf(str, "%f", GET_FLOAT_VAL(buf)); + n = sprintf(str, "%e", GET_FLOAT_VAL(buf)); break; case TSDB_DATA_TYPE_DOUBLE: - n = sprintf(str, "%f", GET_DOUBLE_VAL(buf)); + n = sprintf(str, "%e", GET_DOUBLE_VAL(buf)); break; case TSDB_DATA_TYPE_BINARY: @@ -82,6 +82,22 @@ int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *le n = bufSize + 2; break; + case TSDB_DATA_TYPE_UTINYINT: + n = sprintf(str, "%d", *(uint8_t*)buf); + break; + + case TSDB_DATA_TYPE_USMALLINT: + n = sprintf(str, "%d", *(uint16_t*)buf); + break; + + case TSDB_DATA_TYPE_UINT: + n = sprintf(str, "%u", *(uint32_t*)buf); + break; + + case TSDB_DATA_TYPE_UBIGINT: + n = sprintf(str, "%" PRIu64, *(uint64_t*)buf); + break; + default: tscError("unsupported type:%d", type); return TSDB_CODE_TSC_INVALID_VALUE; @@ -118,6 +134,24 @@ SCond* tsGetSTableQueryCond(STagCond* pTagCond, uint64_t uid) { return NULL; } +STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx) { + if (filters == NULL) { + return NULL; + } + + size_t size = taosArrayGetSize(filters); + for (int32_t i = 0; i < size; ++i) { + STblCond* cond = taosArrayGet(filters, i); + + if (uid == cond->uid && (idx >= 0 && cond->idx == idx)) { + return cond; + } + } + + return NULL; +} + + void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) { if (tbufTell(bw) == 0) { return; @@ -753,8 +787,7 @@ typedef struct SDummyInputInfo { SSDataBlock *block; STableQueryInfo *pTableQueryInfo; SSqlObj *pSql; // refactor: remove it - int32_t numOfFilterCols; - SSingleColumnFilterInfo *pFilterInfo; + SFilterInfo *pFilterInfo; } SDummyInputInfo; typedef struct SJoinStatus { @@ -770,38 +803,7 @@ typedef struct SJoinOperatorInfo { SRspResultInfo resultInfo; // todo refactor, add this info for each operator } SJoinOperatorInfo; -static void converNcharFilterColumn(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t rows, bool *gotNchar) { - for (int32_t i = 0; i < numOfFilterCols; ++i) { - if (pFilterInfo[i].info.type == TSDB_DATA_TYPE_NCHAR) { - pFilterInfo[i].pData2 = pFilterInfo[i].pData; - pFilterInfo[i].pData = malloc(rows * pFilterInfo[i].info.bytes); - int32_t bufSize = pFilterInfo[i].info.bytes - VARSTR_HEADER_SIZE; - for (int32_t j = 0; j < rows; ++j) { - char* dst = (char *)pFilterInfo[i].pData + j * pFilterInfo[i].info.bytes; - char* src = (char *)pFilterInfo[i].pData2 + j * pFilterInfo[i].info.bytes; - int32_t len = 0; - taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); - varDataLen(dst) = len; - } - *gotNchar = true; - } - } -} - -static void freeNcharFilterColumn(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { - for (int32_t i = 0; i < numOfFilterCols; ++i) { - if (pFilterInfo[i].info.type == TSDB_DATA_TYPE_NCHAR) { - if (pFilterInfo[i].pData2) { - tfree(pFilterInfo[i].pData); - pFilterInfo[i].pData = pFilterInfo[i].pData2; - pFilterInfo[i].pData2 = NULL; - } - } - } -} - - -static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { +static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SFilterInfo* pFilterInfo) { int32_t offset = 0; char* pData = pRes->data; @@ -817,14 +819,16 @@ static void doSetupSDataBlock(SSqlRes* pRes, SSDataBlock* pBlock, SSingleColumnF } // filter data if needed - if (numOfFilterCols > 0) { - doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock); + if (pFilterInfo) { + //doSetFilterColumnInfo(pFilterInfo, numOfFilterCols, pBlock); + doSetFilterColInfo(pFilterInfo, pBlock); bool gotNchar = false; - converNcharFilterColumn(pFilterInfo, numOfFilterCols, pBlock->info.rows, &gotNchar); + filterConverNcharColumns(pFilterInfo, pBlock->info.rows, &gotNchar); int8_t* p = calloc(pBlock->info.rows, sizeof(int8_t)); - bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); + //bool all = doFilterDataBlock(pFilterInfo, numOfFilterCols, pBlock->info.rows, p); + bool all = filterExecute(pFilterInfo, pBlock->info.rows, p); if (gotNchar) { - freeNcharFilterColumn(pFilterInfo, numOfFilterCols); + filterFreeNcharColumns(pFilterInfo); } if (!all) { doCompactSDataBlock(pBlock, pBlock->info.rows, p); @@ -862,7 +866,7 @@ SSDataBlock* doGetDataBlock(void* param, bool* newgroup) { pBlock->info.rows = pRes->numOfRows; if (pRes->numOfRows != 0) { - doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo, pInput->numOfFilterCols); + doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo); *newgroup = false; return pBlock; } @@ -877,7 +881,7 @@ SSDataBlock* doGetDataBlock(void* param, bool* newgroup) { } pBlock->info.rows = pRes->numOfRows; - doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo, pInput->numOfFilterCols); + doSetupSDataBlock(pRes, pBlock, pInput->pFilterInfo); *newgroup = false; return pBlock; } @@ -920,25 +924,40 @@ SSDataBlock* doDataBlockJoin(void* param, bool* newgroup) { if (pOperator->status == OP_EXEC_DONE) { return pJoinInfo->pRes; } - + SJoinStatus* st0 = &pJoinInfo->status[0]; SColumnInfoData* p0 = taosArrayGet(st0->pBlock->pDataBlock, 0); int64_t* ts0 = (int64_t*) p0->pData; + if (st0->index >= st0->pBlock->info.rows) { + continue; + } + bool prefixEqual = true; while(1) { prefixEqual = true; for (int32_t i = 1; i < pJoinInfo->numOfUpstream; ++i) { SJoinStatus* st = &pJoinInfo->status[i]; + ts0 = (int64_t*) p0->pData; SColumnInfoData* p = taosArrayGet(st->pBlock->pDataBlock, 0); int64_t* ts = (int64_t*)p->pData; + if (st->index >= st->pBlock->info.rows || st0->index >= st0->pBlock->info.rows) { + fetchNextBlockIfCompleted(pOperator, newgroup); + if (pOperator->status == OP_EXEC_DONE) { + return pJoinInfo->pRes; + } + + prefixEqual = false; + break; + } + if (ts[st->index] < ts0[st0->index]) { // less than the first prefixEqual = false; - if ((++(st->index)) >= st->pBlock->info.rows) { + if ((++(st->index)) >= st->pBlock->info.rows) { fetchNextBlockIfCompleted(pOperator, newgroup); if (pOperator->status == OP_EXEC_DONE) { return pJoinInfo->pRes; @@ -1053,22 +1072,21 @@ static void destroyDummyInputOperator(void* param, int32_t numOfOutput) { pInfo->block = destroyOutputBuf(pInfo->block); pInfo->pSql = NULL; - doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols); + filterFreeInfo(pInfo->pFilterInfo); cleanupResultRowInfo(&pInfo->pTableQueryInfo->resInfo); tfree(pInfo->pTableQueryInfo); } // todo this operator servers as the adapter for Operator tree and SqlRes result, remove it later -SOperatorInfo* createDummyInputOperator(SSqlObj* pSql, SSchema* pSchema, int32_t numOfCols, SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols) { +SOperatorInfo* createDummyInputOperator(SSqlObj* pSql, SSchema* pSchema, int32_t numOfCols, SFilterInfo* pFilters) { assert(numOfCols > 0); STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; SDummyInputInfo* pInfo = calloc(1, sizeof(SDummyInputInfo)); pInfo->pSql = pSql; - pInfo->pFilterInfo = pFilterInfo; - pInfo->numOfFilterCols = numOfFilterCols; + pInfo->pFilterInfo = pFilters; pInfo->pTableQueryInfo = createTmpTableQueryInfo(win); pInfo->block = calloc(numOfCols, sizeof(SSDataBlock)); @@ -1156,6 +1174,7 @@ void convertQueryResult(SSqlRes* pRes, SQueryInfo* pQueryInfo, uint64_t objId, b pRes->completed = (pRes->numOfRows == 0); } +/* static void createInputDataFilterInfo(SQueryInfo* px, int32_t numOfCol1, int32_t* numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo) { SColumnInfo* tableCols = calloc(numOfCol1, sizeof(SColumnInfo)); for(int32_t i = 0; i < numOfCol1; ++i) { @@ -1173,6 +1192,7 @@ static void createInputDataFilterInfo(SQueryInfo* px, int32_t numOfCol1, int32_t tfree(tableCols); } +*/ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQueryInfo* px, SSqlObj* pSql) { SSqlRes* pOutput = &pSql->res; @@ -1201,11 +1221,17 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue // if it is a join query, create join operator here int32_t numOfCol1 = pTableMeta->tableInfo.numOfColumns; - int32_t numOfFilterCols = 0; - SSingleColumnFilterInfo* pFilterInfo = NULL; - createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo); + SFilterInfo *pFilters = NULL; + STblCond *pCond = NULL; + if (px->colCond) { + pCond = tsGetTableFilter(px->colCond, pTableMeta->id.uid, 0); + if (pCond && pCond->cond) { + createQueryFilter(pCond->cond, pCond->len, &pFilters); + } + //createInputDataFlterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo); + } - SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilterInfo, numOfFilterCols); + SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilters); pOutput->precision = pSqlObjList[0]->res.precision; @@ -1222,15 +1248,21 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue for(int32_t i = 1; i < px->numOfTables; ++i) { STableMeta* pTableMeta1 = tscGetMetaInfo(px, i)->pTableMeta; + numOfCol1 = pTableMeta1->tableInfo.numOfColumns; + SFilterInfo *pFilters1 = NULL; SSchema* pSchema1 = tscGetTableSchema(pTableMeta1); int32_t n = pTableMeta1->tableInfo.numOfColumns; - int32_t numOfFilterCols1 = 0; - SSingleColumnFilterInfo* pFilterInfo1 = NULL; - createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols1, &pFilterInfo1); + if (px->colCond) { + pCond = tsGetTableFilter(px->colCond, pTableMeta1->id.uid, i); + if (pCond && pCond->cond) { + createQueryFilter(pCond->cond, pCond->len, &pFilters1); + } + //createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols1, &pFilterInfo1); + } - p[i] = createDummyInputOperator(pSqlObjList[i], pSchema1, n, pFilterInfo1, numOfFilterCols1); + p[i] = createDummyInputOperator(pSqlObjList[i], pSchema1, n, pFilters1); memcpy(&schema[offset], pSchema1, n * sizeof(SSchema)); offset += n; } @@ -2268,6 +2300,11 @@ int32_t tscGetResRowLength(SArray* pExprList) { } static void destroyFilterInfo(SColumnFilterList* pFilterList) { + if (pFilterList->filterInfo == NULL) { + pFilterList->numOfFilters = 0; + return; + } + for(int32_t i = 0; i < pFilterList->numOfFilters; ++i) { if (pFilterList->filterInfo[i].filterstr) { tfree(pFilterList->filterInfo[i].pz); @@ -2970,6 +3007,64 @@ int32_t tscTagCondCopy(STagCond* dest, const STagCond* src) { return 0; } +int32_t tscColCondCopy(SArray** dest, const SArray* src, uint64_t uid, int16_t tidx) { + if (src == NULL) { + return 0; + } + + size_t s = taosArrayGetSize(src); + *dest = taosArrayInit(s, sizeof(SCond)); + + for (int32_t i = 0; i < s; ++i) { + STblCond* pCond = taosArrayGet(src, i); + STblCond c = {0}; + + if (tidx > 0) { + if (!(pCond->uid == uid && pCond->idx == tidx)) { + continue; + } + + c.idx = 0; + } else { + c.idx = pCond->idx; + } + + c.len = pCond->len; + c.uid = pCond->uid; + + if (pCond->len > 0) { + assert(pCond->cond != NULL); + c.cond = malloc(c.len); + if (c.cond == NULL) { + return -1; + } + + memcpy(c.cond, pCond->cond, c.len); + } + + taosArrayPush(*dest, &c); + } + + return 0; +} + +void tscColCondRelease(SArray** pCond) { + if (*pCond == NULL) { + return; + } + + size_t s = taosArrayGetSize(*pCond); + for (int32_t i = 0; i < s; ++i) { + STblCond* p = taosArrayGet(*pCond, i); + tfree(p->cond); + } + + taosArrayDestroy(*pCond); + + *pCond = NULL; +} + + void tscTagCondRelease(STagCond* pTagCond) { free(pTagCond->tbnameCond.cond); @@ -3162,6 +3257,7 @@ int32_t tscAddQueryInfo(SSqlCmd* pCmd) { static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) { tscTagCondRelease(&pQueryInfo->tagCond); + tscColCondRelease(&pQueryInfo->colCond); tscFieldInfoClear(&pQueryInfo->fieldsInfo); tscExprDestroy(pQueryInfo->exprList); @@ -3252,6 +3348,11 @@ int32_t tscQueryInfoCopy(SQueryInfo* pQueryInfo, const SQueryInfo* pSrc) { goto _error; } + if (tscColCondCopy(&pQueryInfo->colCond, pSrc->colCond, 0, -1) != 0) { + code = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + if (pSrc->fillType != TSDB_FILL_NONE) { pQueryInfo->fillVal = calloc(1, pSrc->fieldsInfo.numOfOutput * sizeof(int64_t)); if (pQueryInfo->fillVal == NULL) { @@ -3647,6 +3748,11 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t goto _error; } + if (tscColCondCopy(&pNewQueryInfo->colCond, pQueryInfo->colCond, pTableMetaInfo->pTableMeta->id.uid, tableIndex) != 0) { + terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; + goto _error; + } + if (pQueryInfo->fillType != TSDB_FILL_NONE) { //just make memory memory sanitizer happy //refactor later diff --git a/src/common/inc/tvariant.h b/src/common/inc/tvariant.h index 21b7fd8223..c69a662846 100644 --- a/src/common/inc/tvariant.h +++ b/src/common/inc/tvariant.h @@ -53,6 +53,8 @@ int32_t tVariantToString(tVariant *pVar, char *dst); int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix); +int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo); + int32_t tVariantTypeSetType(tVariant *pVariant, char type); #ifdef __cplusplus diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index 973b88fef9..ebdb33fd5b 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -118,7 +118,7 @@ void tExprTreeDestroy(tExprNode *pNode, void (*fp)(void *)) { } else if (pNode->nodeType == TSQL_NODE_VALUE) { tVariantDestroy(pNode->pVal); } else if (pNode->nodeType == TSQL_NODE_COL) { - free(pNode->pSchema); + tfree(pNode->pSchema); } free(pNode); @@ -435,7 +435,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { expr->_node.optr = TSDB_RELATION_IN; tVariant* pVal = exception_calloc(1, sizeof(tVariant)); right->pVal = pVal; - pVal->nType = TSDB_DATA_TYPE_ARRAY; + pVal->nType = TSDB_DATA_TYPE_POINTER_ARRAY; pVal->arr = taosArrayInit(2, POINTER_BYTES); const char* cond = tbnameCond + QUERY_COND_REL_PREFIX_IN_LEN; @@ -502,6 +502,183 @@ void buildFilterSetFromBinary(void **q, const char *buf, int32_t len) { *q = (void *)pObj; } +void convertFilterSetFromBinary(void **q, const char *buf, int32_t len, uint32_t tType) { + SBufferReader br = tbufInitReader(buf, len, false); + uint32_t sType = tbufReadUint32(&br); + SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(tType), true, false); + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(tType)); + + int dummy = -1; + tVariant tmpVar = {0}; + size_t t = 0; + int32_t sz = tbufReadInt32(&br); + void *pvar = NULL; + int64_t val = 0; + int32_t bufLen = 0; + if (IS_NUMERIC_TYPE(sType)) { + bufLen = 60; // The maximum length of string that a number is converted to. + } else { + bufLen = 128; + } + + char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE); + + for (int32_t i = 0; i < sz; i++) { + switch (sType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + *(uint8_t *)&val = (uint8_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + *(uint16_t *)&val = (uint16_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + *(uint32_t *)&val = (uint32_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + *(uint64_t *)&val = (uint64_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + *(double *)&val = tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_FLOAT: { + *(float *)&val = (float)tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_BINARY: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + default: + taosHashCleanup(pObj); + *q = NULL; + return; + } + + tVariantCreateFromBinary(&tmpVar, (char *)pvar, t, sType); + + if (bufLen < t) { + tmp = realloc(tmp, t * TSDB_NCHAR_SIZE); + bufLen = (int32_t)t; + } + + switch (tType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_FLOAT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto err_ret; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_BINARY: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto err_ret; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto err_ret; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + default: + goto err_ret; + } + + taosHashPut(pObj, (char *)pvar, t, &dummy, sizeof(dummy)); + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + } + + *q = (void *)pObj; + pObj = NULL; + +err_ret: + tVariantDestroy(&tmpVar); + taosHashCleanup(pObj); + tfree(tmp); +} + + tExprNode* exprdup(tExprNode* pNode) { if (pNode == NULL) { return NULL; diff --git a/src/common/src/tname.c b/src/common/src/tname.c index 5da48b2e9a..e92169f097 100644 --- a/src/common/src/tname.c +++ b/src/common/src/tname.c @@ -61,7 +61,7 @@ bool tscValidateTableNameLength(size_t len) { // TODO refactor SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFilters) { - if (numOfFilters == 0) { + if (numOfFilters == 0 || src == NULL) { assert(src == NULL); return NULL; } diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c index eeffe49adc..13c4160e7f 100644 --- a/src/common/src/ttypes.c +++ b/src/common/src/ttypes.c @@ -372,21 +372,21 @@ static void getStatics_nchr(const void *pData, int32_t numOfRow, int64_t *min, i } tDataTypeDescriptor tDataTypes[15] = { - {TSDB_DATA_TYPE_NULL, 6,1, "NOTYPE", NULL, NULL, NULL}, - {TSDB_DATA_TYPE_BOOL, 4, CHAR_BYTES, "BOOL", tsCompressBool, tsDecompressBool, getStatics_bool}, - {TSDB_DATA_TYPE_TINYINT, 7, CHAR_BYTES, "TINYINT", tsCompressTinyint, tsDecompressTinyint, getStatics_i8}, - {TSDB_DATA_TYPE_SMALLINT, 8, SHORT_BYTES, "SMALLINT", tsCompressSmallint, tsDecompressSmallint, getStatics_i16}, - {TSDB_DATA_TYPE_INT, 3, INT_BYTES, "INT", tsCompressInt, tsDecompressInt, getStatics_i32}, - {TSDB_DATA_TYPE_BIGINT, 6, LONG_BYTES, "BIGINT", tsCompressBigint, tsDecompressBigint, getStatics_i64}, - {TSDB_DATA_TYPE_FLOAT, 5, FLOAT_BYTES, "FLOAT", tsCompressFloat, tsDecompressFloat, getStatics_f}, - {TSDB_DATA_TYPE_DOUBLE, 6, DOUBLE_BYTES, "DOUBLE", tsCompressDouble, tsDecompressDouble, getStatics_d}, - {TSDB_DATA_TYPE_BINARY, 6, 0, "BINARY", tsCompressString, tsDecompressString, getStatics_bin}, - {TSDB_DATA_TYPE_TIMESTAMP, 9, LONG_BYTES, "TIMESTAMP", tsCompressTimestamp, tsDecompressTimestamp, getStatics_i64}, - {TSDB_DATA_TYPE_NCHAR, 5, 8, "NCHAR", tsCompressString, tsDecompressString, getStatics_nchr}, - {TSDB_DATA_TYPE_UTINYINT, 16, CHAR_BYTES, "TINYINT UNSIGNED", tsCompressTinyint, tsDecompressTinyint, getStatics_u8}, - {TSDB_DATA_TYPE_USMALLINT, 17, SHORT_BYTES, "SMALLINT UNSIGNED", tsCompressSmallint, tsDecompressSmallint, getStatics_u16}, - {TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", tsCompressInt, tsDecompressInt, getStatics_u32}, - {TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", tsCompressBigint, tsDecompressBigint, getStatics_u64}, + {TSDB_DATA_TYPE_NULL, 6, 1, "NOTYPE", 0, 0, NULL, NULL, NULL}, + {TSDB_DATA_TYPE_BOOL, 4, CHAR_BYTES, "BOOL", false, true, tsCompressBool, tsDecompressBool, getStatics_bool}, + {TSDB_DATA_TYPE_TINYINT, 7, CHAR_BYTES, "TINYINT", INT8_MIN, INT8_MAX, tsCompressTinyint, tsDecompressTinyint, getStatics_i8}, + {TSDB_DATA_TYPE_SMALLINT, 8, SHORT_BYTES, "SMALLINT", INT16_MIN, INT16_MAX, tsCompressSmallint, tsDecompressSmallint, getStatics_i16}, + {TSDB_DATA_TYPE_INT, 3, INT_BYTES, "INT", INT32_MIN, INT32_MAX, tsCompressInt, tsDecompressInt, getStatics_i32}, + {TSDB_DATA_TYPE_BIGINT, 6, LONG_BYTES, "BIGINT", INT64_MIN, INT64_MAX, tsCompressBigint, tsDecompressBigint, getStatics_i64}, + {TSDB_DATA_TYPE_FLOAT, 5, FLOAT_BYTES, "FLOAT", 0, 0, tsCompressFloat, tsDecompressFloat, getStatics_f}, + {TSDB_DATA_TYPE_DOUBLE, 6, DOUBLE_BYTES, "DOUBLE", 0, 0, tsCompressDouble, tsDecompressDouble, getStatics_d}, + {TSDB_DATA_TYPE_BINARY, 6, 0, "BINARY", 0, 0, tsCompressString, tsDecompressString, getStatics_bin}, + {TSDB_DATA_TYPE_TIMESTAMP, 9, LONG_BYTES, "TIMESTAMP", INT64_MIN, INT64_MAX, tsCompressTimestamp, tsDecompressTimestamp, getStatics_i64}, + {TSDB_DATA_TYPE_NCHAR, 5, 8, "NCHAR", 0, 0, tsCompressString, tsDecompressString, getStatics_nchr}, + {TSDB_DATA_TYPE_UTINYINT, 16, CHAR_BYTES, "TINYINT UNSIGNED", 0, UINT8_MAX, tsCompressTinyint, tsDecompressTinyint, getStatics_u8}, + {TSDB_DATA_TYPE_USMALLINT, 17, SHORT_BYTES, "SMALLINT UNSIGNED", 0, UINT16_MAX, tsCompressSmallint, tsDecompressSmallint, getStatics_u16}, + {TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", 0, UINT32_MAX, tsCompressInt, tsDecompressInt, getStatics_u32}, + {TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", 0, UINT64_MAX, tsCompressBigint, tsDecompressBigint, getStatics_u64}, }; char tTokenTypeSwitcher[13] = { @@ -405,6 +405,32 @@ char tTokenTypeSwitcher[13] = { TSDB_DATA_TYPE_NCHAR, // TK_NCHAR }; +float floatMin = -FLT_MAX, floatMax = FLT_MAX; +double doubleMin = -DBL_MAX, doubleMax = DBL_MAX; + +FORCE_INLINE void* getDataMin(int32_t type) { + switch (type) { + case TSDB_DATA_TYPE_FLOAT: + return &floatMin; + case TSDB_DATA_TYPE_DOUBLE: + return &doubleMin; + default: + return &tDataTypes[type].minValue; + } +} + +FORCE_INLINE void* getDataMax(int32_t type) { + switch (type) { + case TSDB_DATA_TYPE_FLOAT: + return &floatMax; + case TSDB_DATA_TYPE_DOUBLE: + return &doubleMax; + default: + return &tDataTypes[type].maxValue; + } +} + + bool isValidDataType(int32_t type) { return type >= TSDB_DATA_TYPE_NULL && type <= TSDB_DATA_TYPE_UBIGINT; } @@ -566,6 +592,53 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) { } } +void operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type) { + if (optr == TSDB_BINARY_OP_ADD) { + switch (type) { + case TSDB_DATA_TYPE_TINYINT: + *((int8_t *)dst) = GET_INT8_VAL(s1) + GET_INT8_VAL(s2); + break; + case TSDB_DATA_TYPE_UTINYINT: + *((uint8_t *)dst) = GET_UINT8_VAL(s1) + GET_UINT8_VAL(s2); + break; + case TSDB_DATA_TYPE_SMALLINT: + *((int16_t *)dst) = GET_INT16_VAL(s1) + GET_INT16_VAL(s2); + break; + case TSDB_DATA_TYPE_USMALLINT: + *((uint16_t *)dst) = GET_UINT16_VAL(s1) + GET_UINT16_VAL(s2); + break; + case TSDB_DATA_TYPE_INT: + *((int32_t *)dst) = GET_INT32_VAL(s1) + GET_INT32_VAL(s2); + break; + case TSDB_DATA_TYPE_UINT: + *((uint32_t *)dst) = GET_UINT32_VAL(s1) + GET_UINT32_VAL(s2); + break; + case TSDB_DATA_TYPE_BIGINT: + *((int64_t *)dst) = GET_INT64_VAL(s1) + GET_INT64_VAL(s2); + break; + case TSDB_DATA_TYPE_UBIGINT: + *((uint64_t *)dst) = GET_UINT64_VAL(s1) + GET_UINT64_VAL(s2); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + *((int64_t *)dst) = GET_INT64_VAL(s1) + GET_INT64_VAL(s2); + break; + case TSDB_DATA_TYPE_FLOAT: + SET_FLOAT_VAL(dst, GET_FLOAT_VAL(s1) + GET_FLOAT_VAL(s2)); + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_VAL(dst, GET_DOUBLE_VAL(s1) + GET_DOUBLE_VAL(s2)); + break; + default: { + assert(0); + break; + } + } + } else { + assert(0); + } +} + + void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf) { switch (type) { case TSDB_DATA_TYPE_INT: diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c index 9e0f7ffc74..a491df6f98 100644 --- a/src/common/src/tvariant.c +++ b/src/common/src/tvariant.c @@ -23,6 +23,13 @@ #include "tutil.h" #include "tvariant.h" +#define SET_EXT_INFO(converted, res, minv, maxv, exti) do { \ + if (converted == NULL || exti == NULL || *converted == false) { break; } \ + if ((res) < (minv)) { *exti = -1; break; } \ + if ((res) > (maxv)) { *exti = 1; break; } \ + assert(0); \ + } while (0) + void tVariantCreate(tVariant *pVar, SStrToken *token) { int32_t ret = 0; int32_t type = token->type; @@ -184,7 +191,7 @@ void tVariantDestroy(tVariant *pVar) { } // NOTE: this is only for string array - if (pVar->nType == TSDB_DATA_TYPE_ARRAY) { + if (pVar->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { size_t num = taosArrayGetSize(pVar->arr); for(size_t i = 0; i < num; i++) { void* p = taosArrayGetP(pVar->arr, i); @@ -192,6 +199,9 @@ void tVariantDestroy(tVariant *pVar) { } taosArrayDestroy(pVar->arr); pVar->arr = NULL; + } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + taosArrayDestroy(pVar->arr); + pVar->arr = NULL; } } @@ -220,7 +230,7 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) { if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) { pDst->i64 = pSrc->i64; - } else if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) { // this is only for string array + } else if (pSrc->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { // this is only for string array size_t num = taosArrayGetSize(pSrc->arr); pDst->arr = taosArrayInit(num, sizeof(char*)); for(size_t i = 0; i < num; i++) { @@ -228,9 +238,18 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) { char* n = strdup(p); taosArrayPush(pDst->arr, &n); } + } else if (pSrc->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + size_t num = taosArrayGetSize(pSrc->arr); + pDst->arr = taosArrayInit(num, sizeof(int64_t)); + pDst->nLen = pSrc->nLen; + assert(pSrc->nLen == num); + for(size_t i = 0; i < num; i++) { + int64_t *p = taosArrayGet(pSrc->arr, i); + taosArrayPush(pDst->arr, p); + } } - if (pDst->nType != TSDB_DATA_TYPE_ARRAY) { + if (pDst->nType != TSDB_DATA_TYPE_POINTER_ARRAY && pDst->nType != TSDB_DATA_TYPE_VALUE_ARRAY) { pDst->nLen = tDataTypes[pDst->nType].bytes; } } @@ -450,7 +469,7 @@ static FORCE_INLINE int32_t convertToDouble(char *pStr, int32_t len, double *val return 0; } -static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr) { +static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result, int32_t type, bool issigned, bool releaseVariantPtr, bool *converted) { if (pVariant->nType == TSDB_DATA_TYPE_NULL) { setNull((char *)result, type, tDataTypes[type].bytes); return 0; @@ -540,6 +559,10 @@ static FORCE_INLINE int32_t convertToInteger(tVariant *pVariant, int64_t *result } } + if (converted) { + *converted = true; + } + bool code = false; uint64_t ui = 0; @@ -602,6 +625,18 @@ static int32_t convertToBool(tVariant *pVariant, int64_t *pDest) { * to column type defined in schema */ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix) { + return tVariantDumpEx(pVariant, payload, type, includeLengthPrefix, NULL, NULL); +} + +/* + * transfer data from variant serve as the implicit data conversion: from input sql string pVariant->nType + * to column type defined in schema + */ +int32_t tVariantDumpEx(tVariant *pVariant, char *payload, int16_t type, bool includeLengthPrefix, bool *converted, char *extInfo) { + if (converted) { + *converted = false; + } + if (pVariant == NULL || (pVariant->nType != 0 && !isValidDataType(pVariant->nType))) { return -1; } @@ -620,7 +655,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_TINYINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT8_MIN + 1, INT8_MAX, extInfo); return -1; } *((int8_t *)payload) = (int8_t) result; @@ -628,7 +664,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UTINYINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT8_MAX - 1, extInfo); return -1; } *((uint8_t *)payload) = (uint8_t) result; @@ -636,7 +673,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_SMALLINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT16_MIN + 1, INT16_MAX, extInfo); return -1; } *((int16_t *)payload) = (int16_t)result; @@ -644,7 +682,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_USMALLINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT16_MAX - 1, extInfo); return -1; } *((uint16_t *)payload) = (uint16_t)result; @@ -652,7 +691,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_INT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, result, INT32_MIN + 1, INT32_MAX, extInfo); return -1; } *((int32_t *)payload) = (int32_t)result; @@ -660,7 +700,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, result, 0, UINT32_MAX - 1, extInfo); return -1; } *((uint32_t *)payload) = (uint32_t)result; @@ -668,7 +709,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_BIGINT: { - if (convertToInteger(pVariant, &result, type, true, false) < 0) { + if (convertToInteger(pVariant, &result, type, true, false, converted) < 0) { + SET_EXT_INFO(converted, (int64_t)result, INT64_MIN + 1, INT64_MAX, extInfo); return -1; } *((int64_t *)payload) = (int64_t)result; @@ -676,7 +718,8 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu } case TSDB_DATA_TYPE_UBIGINT: { - if (convertToInteger(pVariant, &result, type, false, false) < 0) { + if (convertToInteger(pVariant, &result, type, false, false, converted) < 0) { + SET_EXT_INFO(converted, (uint64_t)result, 0, UINT64_MAX - 1, extInfo); return -1; } *((uint64_t *)payload) = (uint64_t)result; @@ -696,11 +739,37 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu return -1; } + if (converted) { + *converted = true; + } + + if (value > FLT_MAX || value < -FLT_MAX) { + SET_EXT_INFO(converted, value, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } SET_FLOAT_VAL(payload, value); } } else if (pVariant->nType == TSDB_DATA_TYPE_BOOL || IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) { + if (converted) { + *converted = true; + } + + if (pVariant->i64 > FLT_MAX || pVariant->i64 < -FLT_MAX) { + SET_EXT_INFO(converted, pVariant->i64, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } + SET_FLOAT_VAL(payload, pVariant->i64); } else if (IS_FLOAT_TYPE(pVariant->nType)) { + if (converted) { + *converted = true; + } + + if (pVariant->dKey > FLT_MAX || pVariant->dKey < -FLT_MAX) { + SET_EXT_INFO(converted, pVariant->dKey, -FLT_MAX, FLT_MAX, extInfo); + return -1; + } + SET_FLOAT_VAL(payload, pVariant->dKey); } else if (pVariant->nType == TSDB_DATA_TYPE_NULL) { *((uint32_t *)payload) = TSDB_DATA_FLOAT_NULL; @@ -824,6 +893,7 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu return 0; } + /* * In variant, bool/smallint/tinyint/int/bigint share the same attribution of * structure, also ignore the convert the type required @@ -848,7 +918,7 @@ int32_t tVariantTypeSetType(tVariant *pVariant, char type) { case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: { - convertToInteger(pVariant, &(pVariant->i64), type, true, true); + convertToInteger(pVariant, &(pVariant->i64), type, true, true, NULL); pVariant->nType = TSDB_DATA_TYPE_BIGINT; break; } diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 5b96f0ebd9..fceeaea0ae 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -34,6 +34,7 @@ extern "C" { #define TSWINDOW_INITIALIZER ((STimeWindow) {INT64_MIN, INT64_MAX}) #define TSWINDOW_DESC_INITIALIZER ((STimeWindow) {INT64_MAX, INT64_MIN}) +#define IS_TSWINDOW_SPECIFIED(win) (((win).skey != INT64_MIN) || ((win).ekey != INT64_MAX)) #define TSKEY_INITIAL_VAL INT64_MIN diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 2214078f55..368658377c 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -272,7 +272,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW TAOS_DEF_ERROR_CODE(0, 0x070A) //"Too many time window in query") #define TSDB_CODE_QRY_NOT_ENOUGH_BUFFER TAOS_DEF_ERROR_CODE(0, 0x070B) //"Query buffer limit has reached") #define TSDB_CODE_QRY_INCONSISTAN TAOS_DEF_ERROR_CODE(0, 0x070C) //"File inconsistency in replica") -#define TSDB_CODE_QRY_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x070D) //"System error") +#define TSDB_CODE_QRY_INVALID_TIME_CONDITION TAOS_DEF_ERROR_CODE(0, 0x070D) //"invalid time condition") +#define TSDB_CODE_QRY_SYS_ERROR TAOS_DEF_ERROR_CODE(0, 0x070E) //"System error") // grant diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index c2918cfdf7..a74a531361 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -489,7 +489,8 @@ typedef struct { int16_t numOfCols; // the number of columns will be load from vnode SInterval interval; SSessionWindow sw; // session window - uint32_t tagCondLen; // tag length in current query + uint16_t tagCondLen; // tag length in current query + uint16_t colCondLen; // column length in current query uint32_t tbnameCondLen; // table name filter condition string length int16_t numOfGroupCols; // num of group by columns int16_t orderByIdx; diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 44e666106a..3f1606e957 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -47,7 +47,8 @@ typedef struct { // this data type is internally used only in 'in' query to hold the values -#define TSDB_DATA_TYPE_ARRAY (1000) +#define TSDB_DATA_TYPE_POINTER_ARRAY (1000) +#define TSDB_DATA_TYPE_VALUE_ARRAY (1001) #define GET_TYPED_DATA(_v, _finalType, _type, _data) \ do { \ @@ -181,6 +182,8 @@ typedef struct tDataTypeDescriptor { int16_t nameLen; int32_t bytes; char * name; + int64_t minValue; + int64_t maxValue; int (*compFunc)(const char *const input, int inputSize, const int nelements, char *const output, int outputSize, char algorithm, char *const buffer, int bufferSize); int (*decompFunc)(const char *const input, int compressedSize, const int nelements, char *const output, @@ -200,6 +203,9 @@ const void *getNullValue(int32_t type); void assignVal(char *val, const char *src, int32_t len, int32_t type); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf); +void operateVal(void *dst, void *s1, void *s2, int32_t optr, int32_t type); +void* getDataMin(int32_t type); +void* getDataMax(int32_t type); int32_t tStrToInteger(const char* z, int16_t type, int32_t n, int64_t* value, bool issigned); diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index ce70a9ba4a..996d925756 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -252,8 +252,10 @@ typedef struct SQueryAttr { int32_t numOfFilterCols; int64_t* fillVal; SOrderedPrjQueryInfo prjInfo; // limit value for each vgroup, only available in global order projection query. - SSingleColumnFilterInfo* pFilterInfo; + SSingleColumnFilterInfo* pFilterInfo; + SFilterInfo *pFilters; + void* tsdb; SMemRef memRef; STableGroupInfo tableGroupInfo; // table list SArray @@ -382,6 +384,7 @@ typedef struct SQInfo { typedef struct SQueryParam { char *sql; char *tagCond; + char *colCond; char *tbnameCond; char *prevResult; SArray *pTableIdList; @@ -390,6 +393,8 @@ typedef struct SQueryParam { SExprInfo *pExprs; SExprInfo *pSecExprs; + SFilterInfo *pFilters; + SColIndex *pGroupColIndex; SColumnInfo *pTagColumnInfo; SGroupbyExpr *pGroupbyExpr; @@ -573,6 +578,7 @@ SSDataBlock* doSLimit(void* param, bool* newgroup); int32_t doCreateFilterInfo(SColumnInfo* pCols, int32_t numOfCols, int32_t numOfFilterCols, SSingleColumnFilterInfo** pFilterInfo, uint64_t qId); void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, SSDataBlock* pBlock); +void doSetFilterColInfo(SFilterInfo *pFilters, SSDataBlock* pBlock); bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols, int32_t numOfRows, int8_t* p); void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p); @@ -594,9 +600,11 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg *pQueryMsg, int32_t numOfOutput, SExprInfo **pExprInfo, SSqlExpr **pExpr, SExprInfo *prevExpr, SUdfInfo *pUdfInfo); +int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters); + SGroupbyExpr *createGroupbyExprFromMsg(SQueryTableMsg *pQueryMsg, SColIndex *pColIndex, int32_t *code); SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SGroupbyExpr *pGroupbyExpr, SExprInfo *pExprs, - SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo); + SExprInfo *pSecExprs, STableGroupInfo *pTableGroupInfo, SColumnInfo* pTagCols, SFilterInfo* pFilters, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo); int32_t initQInfo(STsBufInfo* pTsBufInfo, void* tsdb, void* sourceOptr, SQInfo* pQInfo, SQueryParam* param, char* start, int32_t prevResultLen, void* merger); diff --git a/src/query/inc/qFilter.h b/src/query/inc/qFilter.h new file mode 100644 index 0000000000..7a7b3157ea --- /dev/null +++ b/src/query/inc/qFilter.h @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_QFILTER_H +#define TDENGINE_QFILTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "texpr.h" +#include "hash.h" +#include "tname.h" + +#define FILTER_DEFAULT_GROUP_SIZE 4 +#define FILTER_DEFAULT_UNIT_SIZE 4 +#define FILTER_DEFAULT_FIELD_SIZE 4 +#define FILTER_DEFAULT_VALUE_SIZE 4 +#define FILTER_DEFAULT_GROUP_UNIT_SIZE 2 + +#define FILTER_DUMMY_EMPTY_OPTR 127 +#define FILTER_DUMMY_RANGE_OPTR 126 + +#define MAX_NUM_STR_SIZE 40 + +enum { + FLD_TYPE_COLUMN = 1, + FLD_TYPE_VALUE = 2, + FLD_TYPE_MAX = 3, + FLD_DESC_NO_FREE = 4, + FLD_DATA_NO_FREE = 8, + FLD_DATA_IS_HASH = 16, +}; + +enum { + MR_ST_START = 1, + MR_ST_FIN = 2, + MR_ST_ALL = 4, + MR_ST_EMPTY = 8, +}; + +enum { + RANGE_FLG_EXCLUDE = 1, + RANGE_FLG_INCLUDE = 2, + RANGE_FLG_NULL = 4, +}; + +enum { + FI_OPTION_NO_REWRITE = 1, + FI_OPTION_TIMESTAMP = 2, + FI_OPTION_NEED_UNIQE = 4, +}; + +enum { + FI_STATUS_ALL = 1, + FI_STATUS_EMPTY = 2, + FI_STATUS_REWRITE = 4, + FI_STATUS_CLONED = 8, +}; + +enum { + RANGE_TYPE_UNIT = 1, + RANGE_TYPE_VAR_HASH = 2, + RANGE_TYPE_MR_CTX = 3, +}; + +typedef struct OptrStr { + uint16_t optr; + char *str; +} OptrStr; + +typedef struct SFilterRange { + int64_t s; + int64_t e; + char sflag; + char eflag; +} SFilterRange; + +typedef struct SFilterColRange { + uint16_t idx; //column field idx + bool isNull; + bool notNull; + bool isRange; + SFilterRange ra; +} SFilterColRange; + +typedef bool (*rangeCompFunc) (const void *, const void *, const void *, const void *, __compar_fn_t); +typedef int32_t(*filter_desc_compare_func)(const void *, const void *); +typedef bool(*filter_exec_func)(void *, int32_t, int8_t*); + +typedef struct SFilterRangeCompare { + int64_t s; + int64_t e; + rangeCompFunc func; +} SFilterRangeCompare; + +typedef struct SFilterRangeNode { + struct SFilterRangeNode* prev; + struct SFilterRangeNode* next; + union { + SFilterRange ra; + SFilterRangeCompare rc; + }; +} SFilterRangeNode; + +typedef struct SFilterRangeCtx { + int32_t type; + int32_t options; + int8_t status; + bool isnull; + bool notnull; + bool isrange; + int16_t colId; + __compar_fn_t pCompareFunc; + SFilterRangeNode *rf; //freed + SFilterRangeNode *rs; +} SFilterRangeCtx ; + +typedef struct SFilterVarCtx { + int32_t type; + int32_t options; + int8_t status; + bool isnull; + bool notnull; + bool isrange; + SHashObj *wild; + SHashObj *value; +} SFilterVarCtx; + +typedef struct SFilterField { + uint16_t flag; + void* desc; + void* data; +} SFilterField; + +typedef struct SFilterFields { + uint16_t size; + uint16_t num; + SFilterField *fields; +} SFilterFields; + +typedef struct SFilterFieldId { + uint16_t type; + uint16_t idx; +} SFilterFieldId; + +typedef struct SFilterGroup { + uint16_t unitSize; + uint16_t unitNum; + uint16_t *unitIdxs; + uint8_t *unitFlags; // !unit result +} SFilterGroup; + +typedef struct SFilterColInfo { + uint8_t type; + int32_t dataType; + void *info; +} SFilterColInfo; + +typedef struct SFilterGroupCtx { + uint16_t colNum; + uint16_t *colIdx; + SFilterColInfo *colInfo; +} SFilterGroupCtx; + +typedef struct SFilterColCtx { + uint16_t colIdx; + void* ctx; +} SFilterColCtx; + +typedef struct SFilterCompare { + uint8_t type; + uint8_t optr; + uint8_t optr2; +} SFilterCompare; + +typedef struct SFilterUnit { + SFilterCompare compare; + SFilterFieldId left; + SFilterFieldId right; + SFilterFieldId right2; +} SFilterUnit; + +typedef struct SFilterComUnit { + void *colData; + void *valData; + void *valData2; + uint16_t dataSize; + uint8_t dataType; + uint8_t optr; + int8_t func; + int8_t rfunc; +} SFilterComUnit; + +typedef struct SFilterPCtx { + SHashObj *valHash; + SHashObj *unitHash; +} SFilterPCtx; + +typedef struct SFilterInfo { + uint32_t options; + uint32_t status; + uint16_t unitSize; + uint16_t unitNum; + uint16_t groupNum; + uint16_t colRangeNum; + SFilterFields fields[FLD_TYPE_MAX]; + SFilterGroup *groups; + uint16_t *cgroups; + SFilterUnit *units; + SFilterComUnit *cunits; + uint8_t *unitRes; // result + uint8_t *unitFlags; // got result + SFilterRangeCtx **colRange; + filter_exec_func func; + + SFilterPCtx pctx; +} SFilterInfo; + +#define COL_FIELD_SIZE (sizeof(SFilterField) + 2 * sizeof(int64_t)) + +#define FILTER_NO_MERGE_DATA_TYPE(t) ((t) == TSDB_DATA_TYPE_BINARY || (t) == TSDB_DATA_TYPE_NCHAR) +#define FILTER_NO_MERGE_OPTR(o) ((o) == TSDB_RELATION_ISNULL || (o) == TSDB_RELATION_NOTNULL || (o) == FILTER_DUMMY_EMPTY_OPTR) + +#define MR_EMPTY_RES(ctx) (ctx->rs == NULL) + +#define SET_AND_OPTR(ctx, o) do {if (o == TSDB_RELATION_ISNULL) { (ctx)->isnull = true; } else if (o == TSDB_RELATION_NOTNULL) { if (!(ctx)->isrange) { (ctx)->notnull = true; } } else if (o != FILTER_DUMMY_EMPTY_OPTR) { (ctx)->isrange = true; (ctx)->notnull = false; } } while (0) +#define SET_OR_OPTR(ctx,o) do {if (o == TSDB_RELATION_ISNULL) { (ctx)->isnull = true; } else if (o == TSDB_RELATION_NOTNULL) { (ctx)->notnull = true; (ctx)->isrange = false; } else if (o != FILTER_DUMMY_EMPTY_OPTR) { if (!(ctx)->notnull) { (ctx)->isrange = true; } } } while (0) +#define CHK_OR_OPTR(ctx) ((ctx)->isnull == true && (ctx)->notnull == true) +#define CHK_AND_OPTR(ctx) ((ctx)->isnull == true && (((ctx)->notnull == true) || ((ctx)->isrange == true))) + + +#define FILTER_GET_FLAG(st, f) (st & f) +#define FILTER_SET_FLAG(st, f) st |= (f) +#define FILTER_CLR_FLAG(st, f) st &= (~f) + +#define SIMPLE_COPY_VALUES(dst, src) *((int64_t *)dst) = *((int64_t *)src) +#define FILTER_PACKAGE_UNIT_HASH_KEY(v, optr, idx1, idx2) do { char *_t = (char *)v; _t[0] = optr; *(uint16_t *)(_t + 1) = idx1; *(uint16_t *)(_t + 3) = idx2; } while (0) +#define FILTER_GREATER(cr,sflag,eflag) ((cr > 0) || ((cr == 0) && (FILTER_GET_FLAG(sflag,RANGE_FLG_EXCLUDE) || FILTER_GET_FLAG(eflag,RANGE_FLG_EXCLUDE)))) +#define FILTER_COPY_RA(dst, src) do { (dst)->sflag = (src)->sflag; (dst)->eflag = (src)->eflag; (dst)->s = (src)->s; (dst)->e = (src)->e; } while (0) + +#define RESET_RANGE(ctx, r) do { (r)->next = (ctx)->rf; (ctx)->rf = r; } while (0) +#define FREE_RANGE(ctx, r) do { if ((r)->prev) { (r)->prev->next = (r)->next; } else { (ctx)->rs = (r)->next;} if ((r)->next) { (r)->next->prev = (r)->prev; } RESET_RANGE(ctx, r); } while (0) +#define FREE_FROM_RANGE(ctx, r) do { SFilterRangeNode *_r = r; if ((_r)->prev) { (_r)->prev->next = NULL; } else { (ctx)->rs = NULL;} while (_r) {SFilterRangeNode *n = (_r)->next; RESET_RANGE(ctx, _r); _r = n; } } while (0) +#define INSERT_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r)->prev; if ((r)->prev) { (r)->prev->next = n; } else { (ctx)->rs = n; } (r)->prev = n; n->next = r; } while (0) +#define APPEND_RANGE(ctx, r, ra) do { SFilterRangeNode *n = filterNewRange(ctx, ra); n->prev = (r); if (r) { (r)->next = n; } else { (ctx)->rs = n; } } while (0) + +#define ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { return _code; } } while (0) +#define ERR_LRET(c,...) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { qError(__VA_ARGS__); return _code; } } while (0) +#define ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { goto _return; } } while (0) + +#define CHK_RETV(c) do { if (c) { return; } } while (0) +#define CHK_RET(c, r) do { if (c) { return r; } } while (0) +#define CHK_JMP(c) do { if (c) { goto _return; } } while (0) +#define CHK_LRETV(c,...) do { if (c) { qError(__VA_ARGS__); return; } } while (0) +#define CHK_LRET(c, r,...) do { if (c) { qError(__VA_ARGS__); return r; } } while (0) + +#define FILTER_GET_FIELD(i, id) (&((i)->fields[(id).type].fields[(id).idx])) +#define FILTER_GET_COL_FIELD(i, idx) (&((i)->fields[FLD_TYPE_COLUMN].fields[idx])) +#define FILTER_GET_COL_FIELD_TYPE(fi) (((SSchema *)((fi)->desc))->type) +#define FILTER_GET_COL_FIELD_SIZE(fi) (((SSchema *)((fi)->desc))->bytes) +#define FILTER_GET_COL_FIELD_DESC(fi) ((SSchema *)((fi)->desc)) +#define FILTER_GET_COL_FIELD_DATA(fi, ri) ((char *)(fi)->data + ((SSchema *)((fi)->desc))->bytes * (ri)) +#define FILTER_GET_VAL_FIELD_TYPE(fi) (((tVariant *)((fi)->desc))->nType) +#define FILTER_GET_VAL_FIELD_DATA(fi) ((char *)(fi)->data) +#define FILTER_GET_TYPE(fl) ((fl) & FLD_TYPE_MAX) + +#define FILTER_GROUP_UNIT(i, g, uid) ((i)->units + (g)->unitIdxs[uid]) +#define FILTER_UNIT_LEFT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->left) +#define FILTER_UNIT_RIGHT_FIELD(i, u) FILTER_GET_FIELD(i, (u)->right) +#define FILTER_UNIT_DATA_TYPE(u) ((u)->compare.type) +#define FILTER_UNIT_COL_DESC(i, u) FILTER_GET_COL_FIELD_DESC(FILTER_UNIT_LEFT_FIELD(i, u)) +#define FILTER_UNIT_COL_DATA(i, u, ri) FILTER_GET_COL_FIELD_DATA(FILTER_UNIT_LEFT_FIELD(i, u), ri) +#define FILTER_UNIT_COL_SIZE(i, u) FILTER_GET_COL_FIELD_SIZE(FILTER_UNIT_LEFT_FIELD(i, u)) +#define FILTER_UNIT_VAL_DATA(i, u) FILTER_GET_VAL_FIELD_DATA(FILTER_UNIT_RIGHT_FIELD(i, u)) +#define FILTER_UNIT_COL_IDX(u) ((u)->left.idx) +#define FILTER_UNIT_OPTR(u) ((u)->compare.optr) +#define FILTER_UNIT_COMP_FUNC(u) ((u)->compare.func) + +#define FILTER_UNIT_CLR_F(i) memset((i)->unitFlags, 0, (i)->unitNum * sizeof(*info->unitFlags)) +#define FILTER_UNIT_SET_F(i, idx) (i)->unitFlags[idx] = 1 +#define FILTER_UNIT_GET_F(i, idx) ((i)->unitFlags[idx]) +#define FILTER_UNIT_GET_R(i, idx) ((i)->unitRes[idx]) +#define FILTER_UNIT_SET_R(i, idx, v) (i)->unitRes[idx] = (v) + +#define FILTER_PUSH_UNIT(colInfo, u) do { (colInfo).type = RANGE_TYPE_UNIT; (colInfo).dataType = FILTER_UNIT_DATA_TYPE(u);taosArrayPush((SArray *)((colInfo).info), &u);} while (0) +#define FILTER_PUSH_VAR_HASH(colInfo, ha) do { (colInfo).type = RANGE_TYPE_VAR_HASH; (colInfo).info = ha;} while (0) +#define FILTER_PUSH_CTX(colInfo, ctx) do { (colInfo).type = RANGE_TYPE_MR_CTX; (colInfo).info = ctx;} while (0) + +#define FILTER_COPY_IDX(dst, src, n) do { *(dst) = malloc(sizeof(uint16_t) * n); memcpy(*(dst), src, sizeof(uint16_t) * n);} while (0) + +#define FILTER_ADD_CTX_TO_GRES(gres, idx, ctx) do { if ((gres)->colCtxs == NULL) { (gres)->colCtxs = taosArrayInit(gres->colNum, sizeof(SFilterColCtx)); } SFilterColCtx cCtx = {idx, ctx}; taosArrayPush((gres)->colCtxs, &cCtx); } while (0) + + +#define FILTER_ALL_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_ALL) +#define FILTER_EMPTY_RES(i) FILTER_GET_FLAG((i)->status, FI_STATUS_EMPTY) + + +extern int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options); +extern bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p); +extern int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data); +extern int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win); +extern int32_t filterConverNcharColumns(SFilterInfo* pFilterInfo, int32_t rows, bool *gotNchar); +extern int32_t filterFreeNcharColumns(SFilterInfo* pFilterInfo); +extern void filterFreeInfo(SFilterInfo *info); +extern bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t numOfCols, int32_t numOfRows); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_QFILTER_H diff --git a/src/query/inc/qTableMeta.h b/src/query/inc/qTableMeta.h index 0dae74ac82..d6b04b0330 100644 --- a/src/query/inc/qTableMeta.h +++ b/src/query/inc/qTableMeta.h @@ -3,6 +3,7 @@ #include "tsdb.h" //todo tsdb should not be here #include "qSqlparser.h" +#include "qFilter.h" typedef struct SFieldInfo { int16_t numOfOutput; // number of column in result @@ -16,6 +17,14 @@ typedef struct SCond { char * cond; } SCond; +typedef struct STblCond { + uint64_t uid; + int16_t idx; //table index + int32_t len; // length of tag query condition data + char * cond; +} STblCond; + + typedef struct SJoinNode { uint64_t uid; int16_t tagColId; @@ -89,6 +98,11 @@ typedef struct STableMetaInfo { struct SQInfo; // global merge operator struct SQueryAttr; // query object +typedef struct STableFilter { + uint64_t uid; + SFilterInfo info; +} STableFilter; + typedef struct SQueryInfo { int16_t command; // the command may be different for each subclause, so keep it seperately. uint32_t type; // query/insert type @@ -106,8 +120,11 @@ typedef struct SQueryInfo { SLimitVal slimit; STagCond tagCond; + SArray * colCond; + SOrderVal order; int16_t numOfTables; + int16_t curTableIdx; STableMetaInfo **pTableMetaInfo; struct STSBuf *tsBuf; diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 5323b4306f..22e4f87ef9 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -2545,77 +2545,14 @@ static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, i #define IS_PREFILTER_TYPE(_t) ((_t) != TSDB_DATA_TYPE_BINARY && (_t) != TSDB_DATA_TYPE_NCHAR) -static bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) { +static FORCE_INLINE bool doFilterByBlockStatistics(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis, SQLFunctionCtx *pCtx, int32_t numOfRows) { SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; - if (pDataStatis == NULL || pQueryAttr->numOfFilterCols == 0) { + if (pDataStatis == NULL || pQueryAttr->pFilters == NULL) { return true; } - bool ret = true; - for (int32_t k = 0; k < pQueryAttr->numOfFilterCols; ++k) { - SSingleColumnFilterInfo *pFilterInfo = &pQueryAttr->pFilterInfo[k]; - int32_t index = -1; - for(int32_t i = 0; i < pQueryAttr->numOfCols; ++i) { - if (pDataStatis[i].colId == pFilterInfo->info.colId) { - index = i; - break; - } - } - - // no statistics data, load the true data block - if (index == -1) { - return true; - } - - // not support pre-filter operation on binary/nchar data type - if (!IS_PREFILTER_TYPE(pFilterInfo->info.type)) { - return true; - } - - // all data in current column are NULL, no need to check its boundary value - if (pDataStatis[index].numOfNull == numOfRows) { - - // if isNULL query exists, load the null data column - for (int32_t j = 0; j < pFilterInfo->numOfFilters; ++j) { - SColumnFilterElem *pFilterElem = &pFilterInfo->pFilters[j]; - if (pFilterElem->fp == isNullOperator) { - return true; - } - } - - continue; - } - - SDataStatis* pDataBlockst = &pDataStatis[index]; - - if (pFilterInfo->info.type == TSDB_DATA_TYPE_FLOAT) { - float minval = (float)(*(double *)(&pDataBlockst->min)); - float maxval = (float)(*(double *)(&pDataBlockst->max)); - - for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { - if (pFilterInfo->pFilters[i].filterInfo.lowerRelOptr == TSDB_RELATION_IN) { - continue; - } - ret &= pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval, TSDB_DATA_TYPE_FLOAT); - if (ret == false) { - return false; - } - } - } else { - for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { - if (pFilterInfo->pFilters[i].filterInfo.lowerRelOptr == TSDB_RELATION_IN) { - continue; - } - ret &= pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pDataBlockst->min, (char *)&pDataBlockst->max, pFilterInfo->info.type); - if (ret == false) { - return false; - } - } - } - } - - return ret; + return filterRangeExecute(pQueryAttr->pFilters, pDataStatis, pQueryAttr->numOfCols, numOfRows); } static bool overlapWithTimeWindow(SQueryAttr* pQueryAttr, SDataBlockInfo* pBlockInfo) { @@ -2834,6 +2771,49 @@ void filterRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSingleColumnFilterInf tfree(p); } +void filterColRowsInDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SSDataBlock* pBlock, bool ascQuery) { + int32_t numOfRows = pBlock->info.rows; + + int8_t *p = calloc(numOfRows, sizeof(int8_t)); + bool all = true; + + if (pRuntimeEnv->pTsBuf != NULL) { + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, 0); + + TSKEY* k = (TSKEY*) pColInfoData->pData; + for (int32_t i = 0; i < numOfRows; ++i) { + int32_t offset = ascQuery? i:(numOfRows - i - 1); + int32_t ret = doTSJoinFilter(pRuntimeEnv, k[offset], ascQuery); + if (ret == TS_JOIN_TAG_NOT_EQUALS) { + break; + } else if (ret == TS_JOIN_TS_NOT_EQUALS) { + all = false; + continue; + } else { + assert(ret == TS_JOIN_TS_EQUAL); + p[offset] = true; + } + + if (!tsBufNextPos(pRuntimeEnv->pTsBuf)) { + break; + } + } + + // save the cursor status + pRuntimeEnv->current->cur = tsBufGetCursor(pRuntimeEnv->pTsBuf); + } else { + all = filterExecute(pRuntimeEnv->pQueryAttr->pFilters, numOfRows, p); + } + + if (!all) { + doCompactSDataBlock(pBlock, numOfRows, p); + } + + tfree(p); +} + + + static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId); static void doSetTagValueInParam(void* pTable, int32_t tagColId, tVariant *tag, int16_t type, int16_t bytes); @@ -2875,6 +2855,15 @@ void doSetFilterColumnInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFi } } + +void doSetFilterColInfo(SFilterInfo * pFilters, SSDataBlock* pBlock) { + for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) { + SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, j); + + filterSetColFieldData(pFilters, pColInfo->info.colId, pColInfo->pData); + } +} + int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock, uint32_t* status) { *status = BLK_DATA_NO_NEEDED; @@ -2911,7 +2900,7 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa // Calculate all time windows that are overlapping or contain current data block. // If current data block is contained by all possible time window, do not load current data block. - if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 || + if (pQueryAttr->pFilters || pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 || (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pQueryAttr, &pBlock->info))) { (*status) = BLK_DATA_ALL_NEEDED; } @@ -3013,9 +3002,12 @@ int32_t loadDataBlockOnDemand(SQueryRuntimeEnv* pRuntimeEnv, STableScanInfo* pTa return terrno; } - doSetFilterColumnInfo(pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock); - if (pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL) { - filterRowsInDataBlock(pRuntimeEnv, pQueryAttr->pFilterInfo, pQueryAttr->numOfFilterCols, pBlock, ascQuery); + if (pQueryAttr->pFilters != NULL) { + doSetFilterColInfo(pQueryAttr->pFilters, pBlock); + } + + if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) { + filterColRowsInDataBlock(pRuntimeEnv, pBlock, ascQuery); } } @@ -6899,7 +6891,8 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols); pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput); pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols); - pQueryMsg->tagCondLen = htonl(pQueryMsg->tagCondLen); + pQueryMsg->tagCondLen = htons(pQueryMsg->tagCondLen); + pQueryMsg->colCondLen = htons(pQueryMsg->colCondLen); pQueryMsg->tsBuf.tsOffset = htonl(pQueryMsg->tsBuf.tsOffset); pQueryMsg->tsBuf.tsLen = htonl(pQueryMsg->tsBuf.tsLen); pQueryMsg->tsBuf.tsNumOfBlocks = htonl(pQueryMsg->tsBuf.tsNumOfBlocks); @@ -6930,7 +6923,7 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pColInfo->colId = htons(pColInfo->colId); pColInfo->type = htons(pColInfo->type); pColInfo->bytes = htons(pColInfo->bytes); - pColInfo->flist.numOfFilters = htons(pColInfo->flist.numOfFilters); + pColInfo->flist.numOfFilters = 0; if (!isValidDataType(pColInfo->type)) { qDebug("qmsg:%p, invalid data type in source column, index:%d, type:%d", pQueryMsg, col, pColInfo->type); @@ -6938,6 +6931,7 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { goto _cleanup; } +/* int32_t numOfFilters = pColInfo->flist.numOfFilters; if (numOfFilters > 0) { pColInfo->flist.filterInfo = calloc(numOfFilters, sizeof(SColumnFilterInfo)); @@ -6951,8 +6945,21 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { if (code != TSDB_CODE_SUCCESS) { goto _cleanup; } +*/ } + if (pQueryMsg->colCondLen > 0) { + param->colCond = calloc(1, pQueryMsg->colCondLen); + if (param->colCond == NULL) { + code = TSDB_CODE_QRY_OUT_OF_MEMORY; + goto _cleanup; + } + + memcpy(param->colCond, pMsg, pQueryMsg->colCondLen); + pMsg += pQueryMsg->colCondLen; + } + + param->tableScanOperator = pQueryMsg->tableScanOperator; param->pExpr = calloc(pQueryMsg->numOfOutput, POINTER_BYTES); if (param->pExpr == NULL) { @@ -7526,6 +7533,28 @@ int32_t createQueryFunc(SQueriedTableInfo* pTableInfo, int32_t numOfOutput, SExp return TSDB_CODE_SUCCESS; } +int32_t createQueryFilter(char *data, uint16_t len, SFilterInfo** pFilters) { + tExprNode* expr = NULL; + + TRY(TSDB_MAX_TAG_CONDITIONS) { + expr = exprTreeFromBinary(data, len); + } CATCH( code ) { + CLEANUP_EXECUTE(); + return code; + } END_TRY + + if (expr == NULL) { + qError("failed to create expr tree"); + return TSDB_CODE_QRY_APP_ERROR; + } + + int32_t ret = filterInitFromTree(expr, pFilters, 0); + tExprTreeDestroy(expr, NULL); + + return ret; +} + + // todo refactor int32_t createIndirectQueryFuncExprFromMsg(SQueryTableMsg* pQueryMsg, int32_t numOfOutput, SExprInfo** pExprInfo, SSqlExpr** pExpr, SExprInfo* prevExpr, SUdfInfo *pUdfInfo) { @@ -7675,7 +7704,7 @@ void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFil int32_t createFilterInfo(SQueryAttr* pQueryAttr, uint64_t qId) { for (int32_t i = 0; i < pQueryAttr->numOfCols; ++i) { - if (pQueryAttr->tableCols[i].flist.numOfFilters > 0) { + if (pQueryAttr->tableCols[i].flist.numOfFilters > 0 && pQueryAttr->tableCols[i].flist.filterInfo != NULL) { pQueryAttr->numOfFilterCols++; } } @@ -7758,7 +7787,7 @@ FORCE_INLINE bool checkQIdEqual(void *qHandle, uint64_t qId) { } SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, SExprInfo* pExprs, - SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, int32_t vgId, + SExprInfo* pSecExprs, STableGroupInfo* pTableGroupInfo, SColumnInfo* pTagCols, SFilterInfo* pFilters, int32_t vgId, char* sql, uint64_t qId, SUdfInfo* pUdfInfo) { int16_t numOfCols = pQueryMsg->numOfCols; int16_t numOfOutput = pQueryMsg->numOfOutput; @@ -7810,7 +7839,8 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S pQueryAttr->needReverseScan = pQueryMsg->needReverseScan; pQueryAttr->stateWindow = pQueryMsg->stateWindow; pQueryAttr->vgId = vgId; - + pQueryAttr->pFilters = pFilters; + pQueryAttr->tableCols = calloc(numOfCols, sizeof(SSingleColumnFilterInfo)); if (pQueryAttr->tableCols == NULL) { goto _cleanup; @@ -7843,10 +7873,6 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S } doUpdateExprColumnIndex(pQueryAttr); - int32_t ret = createFilterInfo(pQueryAttr, pQInfo->qId); - if (ret != TSDB_CODE_SUCCESS) { - goto _cleanup; - } if (pSecExprs != NULL) { int32_t resultRowSize = 0; @@ -7961,6 +7987,8 @@ _cleanup_qinfo: tfree(pExprs); + filterFreeInfo(pFilters); + _cleanup: freeQInfo(pQInfo); return NULL; @@ -8316,6 +8344,8 @@ void freeQueryAttr(SQueryAttr* pQueryAttr) { taosArrayDestroy(pQueryAttr->pGroupbyExpr->columnInfo); tfree(pQueryAttr->pGroupbyExpr); } + + filterFreeInfo(pQueryAttr->pFilters); } } diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c new file mode 100644 index 0000000000..1171bb0896 --- /dev/null +++ b/src/query/src/qFilter.c @@ -0,0 +1,3076 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include "os.h" +#include "queryLog.h" +#include "qFilter.h" +#include "tcompare.h" +#include "hash.h" +#include "tscUtil.h" + +OptrStr gOptrStr[] = { + {TSDB_RELATION_INVALID, "invalid"}, + {TSDB_RELATION_LESS, "<"}, + {TSDB_RELATION_GREATER, ">"}, + {TSDB_RELATION_EQUAL, "="}, + {TSDB_RELATION_LESS_EQUAL, "<="}, + {TSDB_RELATION_GREATER_EQUAL, ">="}, + {TSDB_RELATION_NOT_EQUAL, "!="}, + {TSDB_RELATION_LIKE, "like"}, + {TSDB_RELATION_ISNULL, "is null"}, + {TSDB_RELATION_NOTNULL, "not null"}, + {TSDB_RELATION_IN, "in"}, + {TSDB_RELATION_AND, "and"}, + {TSDB_RELATION_OR, "or"}, + {TSDB_RELATION_NOT, "not"} +}; + +static FORCE_INLINE int32_t filterFieldColDescCompare(const void *desc1, const void *desc2) { + const SSchema *sch1 = desc1; + const SSchema *sch2 = desc2; + + return sch1->colId != sch2->colId; +} + +static FORCE_INLINE int32_t filterFieldValDescCompare(const void *desc1, const void *desc2) { + const tVariant *val1 = desc1; + const tVariant *val2 = desc2; + + return tVariantCompare(val1, val2); +} + + +filter_desc_compare_func gDescCompare [FLD_TYPE_MAX] = { + NULL, + filterFieldColDescCompare, + filterFieldValDescCompare +}; + +bool filterRangeCompGi (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0; +} +bool filterRangeCompGe (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0; +} +bool filterRangeCompLi (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(minv, maxr) <= 0; +} +bool filterRangeCompLe (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(minv, maxr) < 0; +} +bool filterRangeCompii (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0 && cfunc(minv, maxr) <= 0; +} +bool filterRangeCompee (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0 && cfunc(minv, maxr) < 0; +} +bool filterRangeCompei (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) > 0 && cfunc(minv, maxr) <= 0; +} +bool filterRangeCompie (const void *minv, const void *maxv, const void *minr, const void *maxr, __compar_fn_t cfunc) { + return cfunc(maxv, minr) >= 0 && cfunc(minv, maxr) < 0; +} + +rangeCompFunc filterGetRangeCompFunc(char sflag, char eflag) { + if (FILTER_GET_FLAG(sflag, RANGE_FLG_NULL)) { + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompLe; + } + + return filterRangeCompLi; + } + + if (FILTER_GET_FLAG(eflag, RANGE_FLG_NULL)) { + if (FILTER_GET_FLAG(sflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompGe; + } + + return filterRangeCompGi; + } + + if (FILTER_GET_FLAG(sflag, RANGE_FLG_EXCLUDE)) { + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompee; + } + + return filterRangeCompei; + } + + if (FILTER_GET_FLAG(eflag, RANGE_FLG_EXCLUDE)) { + return filterRangeCompie; + } + + return filterRangeCompii; +} + +rangeCompFunc gRangeCompare[] = {filterRangeCompee, filterRangeCompei, filterRangeCompie, filterRangeCompii, filterRangeCompGe, + filterRangeCompGi, filterRangeCompLe, filterRangeCompLi}; + + +int8_t filterGetRangeCompFuncFromOptrs(uint8_t optr, uint8_t optr2) { + if (optr2) { + assert(optr2 == TSDB_RELATION_LESS || optr2 == TSDB_RELATION_LESS_EQUAL); + + if (optr == TSDB_RELATION_GREATER) { + if (optr2 == TSDB_RELATION_LESS) { + return 0; + } + + return 1; + } + + if (optr2 == TSDB_RELATION_LESS) { + return 2; + } + + return 3; + } else { + switch (optr) { + case TSDB_RELATION_GREATER: + return 4; + case TSDB_RELATION_GREATER_EQUAL: + return 5; + case TSDB_RELATION_LESS: + return 6; + case TSDB_RELATION_LESS_EQUAL: + return 7; + default: + break; + } + } + + return -1; +} + +__compar_fn_t gDataCompare[] = {compareInt32Val, compareInt8Val, compareInt16Val, compareInt64Val, compareFloatVal, + compareDoubleVal, compareLenPrefixedStr, compareStrPatternComp, compareFindItemInSet, compareWStrPatternComp, + compareLenPrefixedWStr, compareUint8Val, compareUint16Val, compareUint32Val, compareUint64Val, + setCompareBytes1, setCompareBytes2, setCompareBytes4, setCompareBytes8 +}; + +int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) { + int8_t comparFn = 0; + + if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) { + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + return 15; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + return 16; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_FLOAT: + return 17; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + return 18; + default: + assert(0); + } + } + + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: comparFn = 1; break; + case TSDB_DATA_TYPE_SMALLINT: comparFn = 2; break; + case TSDB_DATA_TYPE_INT: comparFn = 0; break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: comparFn = 3; break; + case TSDB_DATA_TYPE_FLOAT: comparFn = 4; break; + case TSDB_DATA_TYPE_DOUBLE: comparFn = 5; break; + case TSDB_DATA_TYPE_BINARY: { + if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */ + comparFn = 7; + } else if (optr == TSDB_RELATION_IN) { + comparFn = 8; + } else { /* normal relational comparFn */ + comparFn = 6; + } + + break; + } + + case TSDB_DATA_TYPE_NCHAR: { + if (optr == TSDB_RELATION_LIKE) { + comparFn = 9; + } else if (optr == TSDB_RELATION_IN) { + comparFn = 8; + } else { + comparFn = 10; + } + break; + } + + case TSDB_DATA_TYPE_UTINYINT: comparFn = 11; break; + case TSDB_DATA_TYPE_USMALLINT: comparFn = 12;break; + case TSDB_DATA_TYPE_UINT: comparFn = 13;break; + case TSDB_DATA_TYPE_UBIGINT: comparFn = 14;break; + + default: + comparFn = 0; + break; + } + + return comparFn; +} + + +static FORCE_INLINE int32_t filterCompareGroupCtx(const void *pLeft, const void *pRight) { + SFilterGroupCtx *left = *((SFilterGroupCtx**)pLeft), *right = *((SFilterGroupCtx**)pRight); + if (left->colNum > right->colNum) return 1; + if (left->colNum < right->colNum) return -1; + return 0; +} + +int32_t filterInitUnitsFields(SFilterInfo *info) { + info->unitSize = FILTER_DEFAULT_UNIT_SIZE; + info->units = calloc(info->unitSize, sizeof(SFilterUnit)); + + info->fields[FLD_TYPE_COLUMN].num = 0; + info->fields[FLD_TYPE_COLUMN].size = FILTER_DEFAULT_FIELD_SIZE; + info->fields[FLD_TYPE_COLUMN].fields = calloc(info->fields[FLD_TYPE_COLUMN].size, COL_FIELD_SIZE); + info->fields[FLD_TYPE_VALUE].num = 0; + info->fields[FLD_TYPE_VALUE].size = FILTER_DEFAULT_FIELD_SIZE; + info->fields[FLD_TYPE_VALUE].fields = calloc(info->fields[FLD_TYPE_VALUE].size, sizeof(SFilterField)); + + return TSDB_CODE_SUCCESS; +} + +static FORCE_INLINE SFilterRangeNode* filterNewRange(SFilterRangeCtx *ctx, SFilterRange* ra) { + SFilterRangeNode *r = NULL; + + if (ctx->rf) { + r = ctx->rf; + ctx->rf = ctx->rf->next; + r->prev = NULL; + r->next = NULL; + } else { + r = calloc(1, sizeof(SFilterRangeNode)); + } + + FILTER_COPY_RA(&r->ra, ra); + + return r; +} + +void* filterInitRangeCtx(int32_t type, int32_t options) { + if (type > TSDB_DATA_TYPE_UBIGINT || type < TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + qError("not supported range type:%d", type); + return NULL; + } + + SFilterRangeCtx *ctx = calloc(1, sizeof(SFilterRangeCtx)); + + ctx->type = type; + ctx->options = options; + ctx->pCompareFunc = getComparFunc(type, 0); + + return ctx; +} + + +int32_t filterResetRangeCtx(SFilterRangeCtx *ctx) { + ctx->status = 0; + + if (ctx->rf == NULL) { + ctx->rf = ctx->rs; + ctx->rs = NULL; + return TSDB_CODE_SUCCESS; + } + + ctx->isnull = false; + ctx->notnull = false; + ctx->isrange = false; + + SFilterRangeNode *r = ctx->rf; + + while (r && r->next) { + r = r->next; + } + + r->next = ctx->rs; + ctx->rs = NULL; + return TSDB_CODE_SUCCESS; +} + +int32_t filterReuseRangeCtx(SFilterRangeCtx *ctx, int32_t type, int32_t options) { + filterResetRangeCtx(ctx); + + ctx->type = type; + ctx->options = options; + ctx->pCompareFunc = getComparFunc(type, 0); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterConvertRange(SFilterRangeCtx *cur, SFilterRange *ra, bool *notNull) { + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + int32_t sr = cur->pCompareFunc(&ra->s, getDataMin(cur->type)); + if (sr == 0) { + FILTER_SET_FLAG(ra->sflag, RANGE_FLG_NULL); + } + } + + if (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + int32_t er = cur->pCompareFunc(&ra->e, getDataMax(cur->type)); + if (er == 0) { + FILTER_SET_FLAG(ra->eflag, RANGE_FLG_NULL); + } + } + + + if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL) && FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + *notNull = true; + } else { + *notNull = false; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddRangeOptr(void* h, uint8_t raOptr, int32_t optr, bool *empty, bool *all) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (optr == TSDB_RELATION_AND) { + SET_AND_OPTR(ctx, raOptr); + if (CHK_AND_OPTR(ctx) || (raOptr == FILTER_DUMMY_EMPTY_OPTR)) { + FILTER_SET_FLAG(ctx->status, MR_ST_EMPTY); + *empty = true; + } + } else { + SET_OR_OPTR(ctx, raOptr); + if (CHK_OR_OPTR(ctx)) { + FILTER_SET_FLAG(ctx->status, MR_ST_ALL); + *all = true; + } + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterAddRangeImpl(void* h, SFilterRange* ra, int32_t optr) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (ctx->rs == NULL) { + if ((FILTER_GET_FLAG(ctx->status, MR_ST_START) == 0) + || (FILTER_GET_FLAG(ctx->status, MR_ST_ALL) && (optr == TSDB_RELATION_AND)) + || ((!FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) && (optr == TSDB_RELATION_OR))) { + APPEND_RANGE(ctx, ctx->rs, ra); + FILTER_SET_FLAG(ctx->status, MR_ST_START); + } + + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + int32_t cr = 0; + + if (optr == TSDB_RELATION_AND) { + while (r != NULL) { + cr = ctx->pCompareFunc(&r->ra.s, &ra->e); + if (FILTER_GREATER(cr, r->ra.sflag, ra->eflag)) { + FREE_FROM_RANGE(ctx, r); + break; + } + + cr = ctx->pCompareFunc(&ra->s, &r->ra.e); + if (FILTER_GREATER(cr, ra->sflag, r->ra.eflag)) { + rn = r->next; + FREE_RANGE(ctx, r); + r = rn; + continue; + } + + cr = ctx->pCompareFunc(&ra->s, &r->ra.s); + if (FILTER_GREATER(cr, ra->sflag, r->ra.sflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.s, &ra->s); + cr == 0 ? (r->ra.sflag |= ra->sflag) : (r->ra.sflag = ra->sflag); + } + + cr = ctx->pCompareFunc(&r->ra.e, &ra->e); + if (FILTER_GREATER(cr, r->ra.eflag, ra->eflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.e, &ra->e); + cr == 0 ? (r->ra.eflag |= ra->eflag) : (r->ra.eflag = ra->eflag); + break; + } + + r = r->next; + } + + return TSDB_CODE_SUCCESS; + } + + + //TSDB_RELATION_OR + + bool smerged = false; + bool emerged = false; + + while (r != NULL) { + cr = ctx->pCompareFunc(&r->ra.s, &ra->e); + if (FILTER_GREATER(cr, r->ra.sflag, ra->eflag)) { + if (emerged == false) { + INSERT_RANGE(ctx, r, ra); + } + + break; + } + + if (smerged == false) { + cr = ctx->pCompareFunc(&ra->s, &r->ra.e); + if (FILTER_GREATER(cr, ra->sflag, r->ra.eflag)) { + if (r->next) { + r= r->next; + continue; + } + + APPEND_RANGE(ctx, r, ra); + break; + } + + cr = ctx->pCompareFunc(&r->ra.s, &ra->s); + if (FILTER_GREATER(cr, r->ra.sflag, ra->sflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.s, &ra->s); + cr == 0 ? (r->ra.sflag &= ra->sflag) : (r->ra.sflag = ra->sflag); + } + + smerged = true; + } + + if (emerged == false) { + cr = ctx->pCompareFunc(&ra->e, &r->ra.e); + if (FILTER_GREATER(cr, ra->eflag, r->ra.eflag)) { + SIMPLE_COPY_VALUES((char *)&r->ra.e, &ra->e); + if (cr == 0) { + r->ra.eflag &= ra->eflag; + break; + } + + r->ra.eflag = ra->eflag; + emerged = true; + r = r->next; + continue; + } + + break; + } + + cr = ctx->pCompareFunc(&ra->e, &r->ra.e); + if (FILTER_GREATER(cr, ra->eflag, r->ra.eflag)) { + rn = r->next; + FREE_RANGE(ctx, r); + r = rn; + + continue; + } else { + SIMPLE_COPY_VALUES(&r->prev->ra.e, (char *)&r->ra.e); + cr == 0 ? (r->prev->ra.eflag &= r->ra.eflag) : (r->prev->ra.eflag = r->ra.eflag); + FREE_RANGE(ctx, r); + + break; + } + } + + if (ctx->rs && ctx->rs->next == NULL) { + bool notnull; + filterConvertRange(ctx, &ctx->rs->ra, ¬null); + if (notnull) { + bool all = false; + FREE_FROM_RANGE(ctx, ctx->rs); + filterAddRangeOptr(h, TSDB_RELATION_NOTNULL, optr, NULL, &all); + if (all) { + FILTER_SET_FLAG(ctx->status, MR_ST_ALL); + } + } + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddRange(void* h, SFilterRange* ra, int32_t optr) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + SIMPLE_COPY_VALUES(&ra->s, getDataMin(ctx->type)); + //FILTER_CLR_FLAG(ra->sflag, RA_NULL); + } + + if (FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + SIMPLE_COPY_VALUES(&ra->e, getDataMax(ctx->type)); + //FILTER_CLR_FLAG(ra->eflag, RA_NULL); + } + + return filterAddRangeImpl(h, ra, optr); +} + + +int32_t filterAddRangeCtx(void *dst, void *src, int32_t optr) { + SFilterRangeCtx *dctx = (SFilterRangeCtx *)dst; + SFilterRangeCtx *sctx = (SFilterRangeCtx *)src; + + assert(optr == TSDB_RELATION_OR); + + if (sctx->rs == NULL) { + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = sctx->rs; + + while (r) { + filterAddRange(dctx, &r->ra, optr); + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterCopyRangeCtx(void *dst, void *src) { + SFilterRangeCtx *dctx = (SFilterRangeCtx *)dst; + SFilterRangeCtx *sctx = (SFilterRangeCtx *)src; + + dctx->status = sctx->status; + + dctx->isnull = sctx->isnull; + dctx->notnull = sctx->notnull; + dctx->isrange = sctx->isrange; + + SFilterRangeNode *r = sctx->rs; + SFilterRangeNode *dr = dctx->rs; + + while (r) { + APPEND_RANGE(dctx, dr, &r->ra); + if (dr == NULL) { + dr = dctx->rs; + } else { + dr = dr->next; + } + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterFinishRange(void* h) { + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + if (FILTER_GET_FLAG(ctx->status, MR_ST_FIN)) { + return TSDB_CODE_SUCCESS; + } + + if (FILTER_GET_FLAG(ctx->options, FI_OPTION_TIMESTAMP)) { + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + + while (r && r->next) { + int64_t tmp = 1; + operateVal(&tmp, &r->ra.e, &tmp, TSDB_BINARY_OP_ADD, ctx->type); + if (ctx->pCompareFunc(&tmp, &r->next->ra.s) == 0) { + rn = r->next; + SIMPLE_COPY_VALUES((char *)&r->next->ra.s, (char *)&r->ra.s); + FREE_RANGE(ctx, r); + r = rn; + + continue; + } + + r = r->next; + } + } + + FILTER_SET_FLAG(ctx->status, MR_ST_FIN); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGetRangeNum(void* h, int32_t* num) { + filterFinishRange(h); + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + + *num = 0; + + SFilterRangeNode *r = ctx->rs; + + while (r) { + ++(*num); + r = r->next; + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterGetRangeRes(void* h, SFilterRange *ra) { + filterFinishRange(h); + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + uint32_t num = 0; + SFilterRangeNode* r = ctx->rs; + + while (r) { + FILTER_COPY_RA(ra, &r->ra); + + ++num; + r = r->next; + ++ra; + } + + if (num == 0) { + qError("no range result"); + return TSDB_CODE_QRY_APP_ERROR; + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterSourceRangeFromCtx(SFilterRangeCtx *ctx, void *sctx, int32_t optr, bool *empty, bool *all) { + SFilterRangeCtx *src = (SFilterRangeCtx *)sctx; + + if (src->isnull){ + filterAddRangeOptr(ctx, TSDB_RELATION_ISNULL, optr, empty, all); + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + if (src->notnull) { + filterAddRangeOptr(ctx, TSDB_RELATION_NOTNULL, optr, empty, all); + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + if (src->isrange) { + filterAddRangeOptr(ctx, 0, optr, empty, all); + + if (!(optr == TSDB_RELATION_OR && ctx->notnull)) { + filterAddRangeCtx(ctx, src, optr); + } + + if (FILTER_GET_FLAG(ctx->status, MR_ST_ALL)) { + *all = true; + } + } + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterFreeRangeCtx(void* h) { + if (h == NULL) { + return TSDB_CODE_SUCCESS; + } + + SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; + SFilterRangeNode *r = ctx->rs; + SFilterRangeNode *rn = NULL; + + while (r) { + rn = r->next; + free(r); + r = rn; + } + + r = ctx->rf; + while (r) { + rn = r->next; + free(r); + r = rn; + } + + free(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterDetachCnfGroup(SFilterGroup *gp1, SFilterGroup *gp2, SArray* group) { + SFilterGroup gp = {0}; + + gp.unitNum = gp1->unitNum + gp2->unitNum; + gp.unitIdxs = calloc(gp.unitNum, sizeof(*gp.unitIdxs)); + memcpy(gp.unitIdxs, gp1->unitIdxs, gp1->unitNum * sizeof(*gp.unitIdxs)); + memcpy(gp.unitIdxs + gp1->unitNum, gp2->unitIdxs, gp2->unitNum * sizeof(*gp.unitIdxs)); + + gp.unitFlags = NULL; + + taosArrayPush(group, &gp); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterDetachCnfGroups(SArray* group, SArray* left, SArray* right) { + int32_t leftSize = (int32_t)taosArrayGetSize(left); + int32_t rightSize = (int32_t)taosArrayGetSize(right); + + CHK_LRET(taosArrayGetSize(left) <= 0, TSDB_CODE_QRY_APP_ERROR, "empty group"); + CHK_LRET(taosArrayGetSize(right) <= 0, TSDB_CODE_QRY_APP_ERROR, "empty group"); + + for (int32_t l = 0; l < leftSize; ++l) { + SFilterGroup *gp1 = taosArrayGet(left, l); + + for (int32_t r = 0; r < rightSize; ++r) { + SFilterGroup *gp2 = taosArrayGet(right, r); + + filterDetachCnfGroup(gp1, gp2, group); + } + } + + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGetFiledByDesc(SFilterFields* fields, int32_t type, void *v) { + for (uint16_t i = 0; i < fields->num; ++i) { + if (0 == gDescCompare[type](fields->fields[i].desc, v)) { + return i; + } + } + + return -1; +} + + +int32_t filterGetFiledByData(SFilterInfo *info, int32_t type, void *v, int32_t dataLen) { + if (type == FLD_TYPE_VALUE) { + if (info->pctx.valHash == false) { + qError("value hash is empty"); + return -1; + } + + void *hv = taosHashGet(info->pctx.valHash, v, dataLen); + if (hv) { + return *(int32_t *)hv; + } + } + + return -1; +} + + +int32_t filterAddField(SFilterInfo *info, void *desc, void **data, int32_t type, SFilterFieldId *fid, int32_t dataLen, bool freeIfExists) { + int32_t idx = -1; + uint16_t *num; + + num = &info->fields[type].num; + + if (*num > 0) { + if (type == FLD_TYPE_COLUMN) { + idx = filterGetFiledByDesc(&info->fields[type], type, desc); + } else if (data && (*data) && dataLen > 0 && FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + idx = filterGetFiledByData(info, type, *data, dataLen); + } + } + + if (idx < 0) { + idx = *num; + if (idx >= info->fields[type].size) { + info->fields[type].size += FILTER_DEFAULT_FIELD_SIZE; + info->fields[type].fields = realloc(info->fields[type].fields, info->fields[type].size * sizeof(SFilterField)); + } + + info->fields[type].fields[idx].flag = type; + info->fields[type].fields[idx].desc = desc; + info->fields[type].fields[idx].data = data ? *data : NULL; + + if (type == FLD_TYPE_COLUMN) { + FILTER_SET_FLAG(info->fields[type].fields[idx].flag, FLD_DATA_NO_FREE); + } + + ++(*num); + + if (data && (*data) && dataLen > 0 && FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + if (info->pctx.valHash == NULL) { + info->pctx.valHash = taosHashInit(FILTER_DEFAULT_GROUP_SIZE * FILTER_DEFAULT_VALUE_SIZE, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, false); + } + + taosHashPut(info->pctx.valHash, *data, dataLen, &idx, sizeof(idx)); + } + } else { + if (freeIfExists) { + tfree(desc); + } + + if (data && freeIfExists) { + tfree(*data); + } + } + + fid->type = type; + fid->idx = idx; + + return TSDB_CODE_SUCCESS; +} + +static FORCE_INLINE int32_t filterAddColFieldFromField(SFilterInfo *info, SFilterField *field, SFilterFieldId *fid) { + filterAddField(info, field->desc, &field->data, FILTER_GET_TYPE(field->flag), fid, 0, false); + + FILTER_SET_FLAG(field->flag, FLD_DESC_NO_FREE); + FILTER_SET_FLAG(field->flag, FLD_DATA_NO_FREE); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddFieldFromNode(SFilterInfo *info, tExprNode *node, SFilterFieldId *fid) { + CHK_LRET(node == NULL, TSDB_CODE_QRY_APP_ERROR, "empty node"); + CHK_RET(node->nodeType != TSQL_NODE_COL && node->nodeType != TSQL_NODE_VALUE, TSDB_CODE_QRY_APP_ERROR); + + int32_t type; + void *v; + + if (node->nodeType == TSQL_NODE_COL) { + type = FLD_TYPE_COLUMN; + v = node->pSchema; + node->pSchema = NULL; + } else { + type = FLD_TYPE_VALUE; + v = node->pVal; + node->pVal = NULL; + } + + filterAddField(info, v, NULL, type, fid, 0, true); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterAddUnit(SFilterInfo *info, uint8_t optr, SFilterFieldId *left, SFilterFieldId *right, uint16_t *uidx) { + if (FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + if (info->pctx.unitHash == NULL) { + info->pctx.unitHash = taosHashInit(FILTER_DEFAULT_GROUP_SIZE * FILTER_DEFAULT_UNIT_SIZE, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, false); + } else { + int64_t v = 0; + FILTER_PACKAGE_UNIT_HASH_KEY(&v, optr, left->idx, right ? right->idx : -1); + void *hu = taosHashGet(info->pctx.unitHash, &v, sizeof(v)); + if (hu) { + *uidx = *(uint16_t *)hu; + return TSDB_CODE_SUCCESS; + } + } + } + + if (info->unitNum >= info->unitSize) { + uint16_t psize = info->unitSize; + info->unitSize += FILTER_DEFAULT_UNIT_SIZE; + info->units = realloc(info->units, info->unitSize * sizeof(SFilterUnit)); + memset(info->units + psize, 0, sizeof(*info->units) * FILTER_DEFAULT_UNIT_SIZE); + } + + SFilterUnit *u = &info->units[info->unitNum]; + + u->compare.optr = optr; + u->left = *left; + if (right) { + u->right = *right; + } + + if (u->right.type == FLD_TYPE_VALUE) { + SFilterField *val = FILTER_UNIT_RIGHT_FIELD(info, u); + assert(FILTER_GET_FLAG(val->flag, FLD_TYPE_VALUE)); + } else { + assert(optr == TSDB_RELATION_ISNULL || optr == TSDB_RELATION_NOTNULL || optr == FILTER_DUMMY_EMPTY_OPTR); + } + + SFilterField *col = FILTER_UNIT_LEFT_FIELD(info, u); + assert(FILTER_GET_FLAG(col->flag, FLD_TYPE_COLUMN)); + + info->units[info->unitNum].compare.type = FILTER_GET_COL_FIELD_TYPE(col); + + *uidx = info->unitNum; + + if (FILTER_GET_FLAG(info->options, FI_OPTION_NEED_UNIQE)) { + int64_t v = 0; + FILTER_PACKAGE_UNIT_HASH_KEY(&v, optr, left->idx, right ? right->idx : -1); + taosHashPut(info->pctx.unitHash, &v, sizeof(v), uidx, sizeof(*uidx)); + } + + ++info->unitNum; + + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterAddUnitToGroup(SFilterGroup *group, uint16_t unitIdx) { + if (group->unitNum >= group->unitSize) { + group->unitSize += FILTER_DEFAULT_UNIT_SIZE; + group->unitIdxs = realloc(group->unitIdxs, group->unitSize * sizeof(*group->unitIdxs)); + } + + group->unitIdxs[group->unitNum++] = unitIdx; + + return TSDB_CODE_SUCCESS; +} + +int32_t filterConvertSetFromBinary(void **q, const char *buf, int32_t len, uint32_t tType) { + SBufferReader br = tbufInitReader(buf, len, false); + uint32_t sType = tbufReadUint32(&br); + SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(tType), true, false); + int32_t code = 0; + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(tType)); + + int dummy = -1; + tVariant tmpVar = {0}; + size_t t = 0; + int32_t sz = tbufReadInt32(&br); + void *pvar = NULL; + int64_t val = 0; + int32_t bufLen = 0; + if (IS_NUMERIC_TYPE(sType)) { + bufLen = 60; // The maximum length of string that a number is converted to. + } else { + bufLen = 128; + } + + char *tmp = calloc(1, bufLen * TSDB_NCHAR_SIZE); + + for (int32_t i = 0; i < sz; i++) { + switch (sType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + *(uint8_t *)&val = (uint8_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + *(uint16_t *)&val = (uint16_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + *(uint32_t *)&val = (uint32_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + *(uint64_t *)&val = (uint64_t)tbufReadInt64(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + *(double *)&val = tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_FLOAT: { + *(float *)&val = (float)tbufReadDouble(&br); + t = sizeof(val); + pvar = &val; + break; + } + case TSDB_DATA_TYPE_BINARY: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + pvar = (char *)tbufReadBinary(&br, &t); + break; + } + default: + taosHashCleanup(pObj); + *q = NULL; + assert(0); + } + + tVariantCreateFromBinary(&tmpVar, (char *)pvar, t, sType); + + if (bufLen < t) { + tmp = realloc(tmp, t * TSDB_NCHAR_SIZE); + bufLen = (int32_t)t; + } + + bool converted = false; + char extInfo = 0; + + switch (tType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_TINYINT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_SMALLINT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_INT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_BIGINT: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + if (tVariantDump(&tmpVar, (char *)&val, tType, false)) { + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_FLOAT: { + if (tVariantDumpEx(&tmpVar, (char *)&val, tType, false, &converted, &extInfo)) { + if (converted) { + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + continue; + } + + goto _return; + } + pvar = &val; + t = sizeof(val); + break; + } + case TSDB_DATA_TYPE_BINARY: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto _return; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + case TSDB_DATA_TYPE_NCHAR: { + if (tVariantDump(&tmpVar, tmp, tType, true)) { + goto _return; + } + t = varDataLen(tmp); + pvar = varDataVal(tmp); + break; + } + default: + goto _return; + } + + taosHashPut(pObj, (char *)pvar, t, &dummy, sizeof(dummy)); + tVariantDestroy(&tmpVar); + memset(&tmpVar, 0, sizeof(tmpVar)); + } + + *q = (void *)pObj; + pObj = NULL; + +_return: + tVariantDestroy(&tmpVar); + taosHashCleanup(pObj); + tfree(tmp); + + return code; +} + + + +int32_t filterAddGroupUnitFromNode(SFilterInfo *info, tExprNode* tree, SArray *group) { + SFilterFieldId left = {0}, right = {0}; + + filterAddFieldFromNode(info, tree->_node.pLeft, &left); + + tVariant* var = tree->_node.pRight->pVal; + int32_t type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(info, left)); + int32_t len = 0; + uint16_t uidx = 0; + + if (tree->_node.optr == TSDB_RELATION_IN && (!IS_VAR_DATA_TYPE(type))) { + void *data = NULL; + filterConvertSetFromBinary((void **)&data, var->pz, var->nLen, type); + CHK_LRET(data == NULL, TSDB_CODE_QRY_APP_ERROR, "failed to convert in param"); + + if (taosHashGetSize((SHashObj *)data) <= 0) { + filterAddUnit(info, FILTER_DUMMY_EMPTY_OPTR, &left, NULL, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + taosHashCleanup(data); + + return TSDB_CODE_SUCCESS; + } + + void *p = taosHashIterate((SHashObj *)data, NULL); + while(p) { + void *key = taosHashGetDataKey((SHashObj *)data, p); + void *fdata = NULL; + + if (IS_VAR_DATA_TYPE(type)) { + len = (int32_t)taosHashGetDataKeyLen((SHashObj *)data, p); + fdata = malloc(len + VARSTR_HEADER_SIZE); + varDataLen(fdata) = len; + memcpy(varDataVal(fdata), key, len); + len += VARSTR_HEADER_SIZE; + } else { + fdata = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(fdata, key); + len = tDataTypes[type].bytes; + } + + filterAddField(info, NULL, &fdata, FLD_TYPE_VALUE, &right, len, true); + + filterAddUnit(info, TSDB_RELATION_EQUAL, &left, &right, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + + p = taosHashIterate((SHashObj *)data, p); + } + + taosHashCleanup(data); + } else { + filterAddFieldFromNode(info, tree->_node.pRight, &right); + + filterAddUnit(info, tree->_node.optr, &left, &right, &uidx); + + SFilterGroup fgroup = {0}; + filterAddUnitToGroup(&fgroup, uidx); + + taosArrayPush(group, &fgroup); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddUnitFromUnit(SFilterInfo *dst, SFilterInfo *src, SFilterUnit* u, uint16_t *uidx) { + SFilterFieldId left, right, *pright = &right; + int32_t type = FILTER_UNIT_DATA_TYPE(u); + uint16_t flag = FLD_DESC_NO_FREE; + + filterAddField(dst, FILTER_UNIT_COL_DESC(src, u), NULL, FLD_TYPE_COLUMN, &left, 0, false); + SFilterField *t = FILTER_UNIT_LEFT_FIELD(src, u); + FILTER_SET_FLAG(t->flag, flag); + + if (u->right.type == FLD_TYPE_VALUE) { + void *data = FILTER_UNIT_VAL_DATA(src, u); + if (IS_VAR_DATA_TYPE(type)) { + if (FILTER_UNIT_OPTR(u) == TSDB_RELATION_IN) { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, 0, false); + + t = FILTER_GET_FIELD(dst, right); + + FILTER_SET_FLAG(t->flag, FLD_DATA_IS_HASH); + } else { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, varDataTLen(data), false); + } + } else { + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, false); + } + + flag = FLD_DATA_NO_FREE; + t = FILTER_UNIT_RIGHT_FIELD(src, u); + FILTER_SET_FLAG(t->flag, flag); + } else { + pright = NULL; + } + + return filterAddUnit(dst, FILTER_UNIT_OPTR(u), &left, pright, uidx); +} + +int32_t filterAddUnitRight(SFilterInfo *info, uint8_t optr, SFilterFieldId *right, uint16_t uidx) { + SFilterUnit *u = &info->units[uidx]; + + u->compare.optr2 = optr; + u->right2 = *right; + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterAddGroupUnitFromCtx(SFilterInfo *dst, SFilterInfo *src, SFilterRangeCtx *ctx, uint16_t cidx, SFilterGroup *g, int32_t optr, SArray *res) { + SFilterFieldId left, right, right2; + uint16_t uidx = 0; + + SFilterField *col = FILTER_GET_COL_FIELD(src, cidx); + + filterAddColFieldFromField(dst, col, &left); + + int32_t type = FILTER_GET_COL_FIELD_TYPE(FILTER_GET_FIELD(dst, left)); + + if (optr == TSDB_RELATION_AND) { + if (ctx->isnull) { + assert(ctx->notnull == false && ctx->isrange == false); + filterAddUnit(dst, TSDB_RELATION_ISNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + + if (ctx->notnull) { + assert(ctx->isnull == false && ctx->isrange == false); + filterAddUnit(dst, TSDB_RELATION_NOTNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + + if (!ctx->isrange) { + assert(ctx->isnull || ctx->notnull); + return TSDB_CODE_SUCCESS; + } + + assert(ctx->rs && ctx->rs->next == NULL); + + SFilterRange *ra = &ctx->rs->ra; + + assert(!((FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) && (FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)))); + + if ((!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) && (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL))) { + __compar_fn_t func = getComparFunc(type, 0); + if (func(&ra->s, &ra->e) == 0) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, TSDB_RELATION_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } else { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + void *data2 = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data2, &ra->e); + filterAddField(dst, NULL, &data2, FLD_TYPE_VALUE, &right2, tDataTypes[type].bytes, true); + + filterAddUnit(dst, FILTER_GET_FLAG(ra->sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitRight(dst, FILTER_GET_FLAG(ra->eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &right2, uidx); + filterAddUnitToGroup(g, uidx); + return TSDB_CODE_SUCCESS; + } + } + + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(ra->sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + if (!FILTER_GET_FLAG(ra->eflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &ra->e); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(ra->eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + return TSDB_CODE_SUCCESS; + } + + // OR PROCESS + + SFilterGroup ng = {0}; + g = &ng; + + assert(ctx->isnull || ctx->notnull || ctx->isrange); + + if (ctx->isnull) { + filterAddUnit(dst, TSDB_RELATION_ISNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + taosArrayPush(res, g); + } + + if (ctx->notnull) { + assert(!ctx->isrange); + memset(g, 0, sizeof(*g)); + + filterAddUnit(dst, TSDB_RELATION_NOTNULL, &left, NULL, &uidx); + filterAddUnitToGroup(g, uidx); + taosArrayPush(res, g); + } + + if (!ctx->isrange) { + assert(ctx->isnull || ctx->notnull); + g->unitNum = 0; + return TSDB_CODE_SUCCESS; + } + + SFilterRangeNode *r = ctx->rs; + + while (r) { + memset(g, 0, sizeof(*g)); + + if ((!FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) &&(!FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL))) { + __compar_fn_t func = getComparFunc(type, 0); + if (func(&r->ra.s, &r->ra.e) == 0) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, TSDB_RELATION_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } else { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + void *data2 = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data2, &r->ra.e); + filterAddField(dst, NULL, &data2, FLD_TYPE_VALUE, &right2, tDataTypes[type].bytes, true); + + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitRight(dst, FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &right2, uidx); + filterAddUnitToGroup(g, uidx); + } + + taosArrayPush(res, g); + + r = r->next; + + continue; + } + + if (!FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.s); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_GREATER : TSDB_RELATION_GREATER_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + if (!FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL)) { + void *data = malloc(sizeof(int64_t)); + SIMPLE_COPY_VALUES(data, &r->ra.e); + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, tDataTypes[type].bytes, true); + filterAddUnit(dst, FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? TSDB_RELATION_LESS : TSDB_RELATION_LESS_EQUAL, &left, &right, &uidx); + filterAddUnitToGroup(g, uidx); + } + + assert (g->unitNum > 0); + + taosArrayPush(res, g); + + r = r->next; + } + + g->unitNum = 0; + + return TSDB_CODE_SUCCESS; +} + + +static void filterFreeGroup(void *pItem) { + if (pItem == NULL) { + return; + } + + SFilterGroup* p = (SFilterGroup*) pItem; + tfree(p->unitIdxs); + tfree(p->unitFlags); +} + + +int32_t filterTreeToGroup(tExprNode* tree, SFilterInfo *info, SArray* group) { + int32_t code = TSDB_CODE_SUCCESS; + SArray* leftGroup = NULL; + SArray* rightGroup = NULL; + + if (tree->nodeType != TSQL_NODE_EXPR) { + qError("invalid nodeType:%d", tree->nodeType); + return TSDB_CODE_QRY_APP_ERROR; + } + + if (tree->_node.optr == TSDB_RELATION_AND) { + leftGroup = taosArrayInit(4, sizeof(SFilterGroup)); + rightGroup = taosArrayInit(4, sizeof(SFilterGroup)); + ERR_JRET(filterTreeToGroup(tree->_node.pLeft, info, leftGroup)); + ERR_JRET(filterTreeToGroup(tree->_node.pRight, info, rightGroup)); + + ERR_JRET(filterDetachCnfGroups(group, leftGroup, rightGroup)); + + taosArrayDestroyEx(leftGroup, filterFreeGroup); + taosArrayDestroyEx(rightGroup, filterFreeGroup); + + return TSDB_CODE_SUCCESS; + } + + if (tree->_node.optr == TSDB_RELATION_OR) { + ERR_RET(filterTreeToGroup(tree->_node.pLeft, info, group)); + ERR_RET(filterTreeToGroup(tree->_node.pRight, info, group)); + + return TSDB_CODE_SUCCESS; + } + + code = filterAddGroupUnitFromNode(info, tree, group); + + +_return: + + taosArrayDestroyEx(leftGroup, filterFreeGroup); + taosArrayDestroyEx(rightGroup, filterFreeGroup); + + return code; +} + +#if 0 +int32_t filterInitUnitFunc(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit* unit = &info->units[i]; + + info->cunits[i].func = getComparFunc(FILTER_UNIT_DATA_TYPE(unit), unit->compare.optr); + } + + return TSDB_CODE_SUCCESS; +} +#endif + + +void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) { + if (qDebugFlag & DEBUG_DEBUG) { + CHK_LRETV(info == NULL, "%s - FilterInfo: EMPTY", msg); + + if (options == 0) { + qDebug("%s - FilterInfo:", msg); + qDebug("COLUMN Field Num:%u", info->fields[FLD_TYPE_COLUMN].num); + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField *field = &info->fields[FLD_TYPE_COLUMN].fields[i]; + SSchema *sch = field->desc; + qDebug("COL%d => [%d][%s]", i, sch->colId, sch->name); + } + + qDebug("VALUE Field Num:%u", info->fields[FLD_TYPE_VALUE].num); + for (uint16_t i = 0; i < info->fields[FLD_TYPE_VALUE].num; ++i) { + SFilterField *field = &info->fields[FLD_TYPE_VALUE].fields[i]; + if (field->desc) { + tVariant *var = field->desc; + if (var->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { + qDebug("VAL%d => [type:TS][val:[%" PRIi64"] - [%" PRId64 "]]", i, *(int64_t *)field->data, *(((int64_t *)field->data) + 1)); + } else { + qDebug("VAL%d => [type:%d][val:%" PRIx64"]", i, var->nType, var->i64); //TODO + } + } else if (field->data) { + qDebug("VAL%d => [type:NIL][val:NIL]", i); //TODO + } + } + + qDebug("UNIT Num:%u", info->unitNum); + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + int32_t type = FILTER_UNIT_DATA_TYPE(unit); + int32_t len = 0; + int32_t tlen = 0; + char str[256] = {0}; + + SFilterField *left = FILTER_UNIT_LEFT_FIELD(info, unit); + SSchema *sch = left->desc; + len = sprintf(str, "UNIT[%d] => [%d][%s] %s [", i, sch->colId, sch->name, gOptrStr[unit->compare.optr].str); + + if (unit->right.type == FLD_TYPE_VALUE && FILTER_UNIT_OPTR(unit) != TSDB_RELATION_IN) { + SFilterField *right = FILTER_UNIT_RIGHT_FIELD(info, unit); + char *data = right->data; + if (IS_VAR_DATA_TYPE(type)) { + tlen = varDataLen(data); + data += VARSTR_HEADER_SIZE; + } + converToStr(str + len, type, data, tlen > 32 ? 32 : tlen, &tlen); + } else { + strcat(str, "NULL"); + } + strcat(str, "]"); + + qDebug("%s", str); //TODO + } + + qDebug("GROUP Num:%u", info->groupNum); + for (uint16_t i = 0; i < info->groupNum; ++i) { + SFilterGroup *group = &info->groups[i]; + qDebug("Group%d : unit num[%u]", i, group->unitNum); + + for (uint16_t u = 0; u < group->unitNum; ++u) { + qDebug("unit id:%u", group->unitIdxs[u]); + } + } + + return; + } + + qDebug("%s - RANGE info:", msg); + + qDebug("RANGE Num:%u", info->colRangeNum); + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + SFilterRangeCtx *ctx = info->colRange[i]; + qDebug("Column ID[%d] RANGE: isnull[%d],notnull[%d],range[%d]", ctx->colId, ctx->isnull, ctx->notnull, ctx->isrange); + if (ctx->isrange) { + SFilterRangeNode *r = ctx->rs; + while (r) { + char str[256] = {0}; + int32_t tlen = 0; + if (FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_NULL)) { + strcat(str,"(NULL)"); + } else { + FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? strcat(str,"(") : strcat(str,"["); + converToStr(str + strlen(str), ctx->type, &r->ra.s, tlen > 32 ? 32 : tlen, &tlen); + FILTER_GET_FLAG(r->ra.sflag, RANGE_FLG_EXCLUDE) ? strcat(str,")") : strcat(str,"]"); + } + strcat(str, " - "); + if (FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_NULL)) { + strcat(str, "(NULL)"); + } else { + FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? strcat(str,"(") : strcat(str,"["); + converToStr(str + strlen(str), ctx->type, &r->ra.e, tlen > 32 ? 32 : tlen, &tlen); + FILTER_GET_FLAG(r->ra.eflag, RANGE_FLG_EXCLUDE) ? strcat(str,")") : strcat(str,"]"); + } + qDebug("range: %s", str); + + r = r->next; + } + } + } + } +} + +void filterFreeColInfo(void *data) { + SFilterColInfo* info = (SFilterColInfo *)data; + + if (info->info == NULL) { + return; + } + + if (info->type == RANGE_TYPE_VAR_HASH) { + //TODO + } else if (info->type == RANGE_TYPE_MR_CTX) { + filterFreeRangeCtx(info->info); + } else if (info->type == RANGE_TYPE_UNIT) { + taosArrayDestroy((SArray *)info->info); + } + + //NO NEED TO FREE UNIT + + info->type = 0; + info->info = NULL; +} + +void filterFreeColCtx(void *data) { + SFilterColCtx* ctx = (SFilterColCtx *)data; + + if (ctx->ctx) { + filterFreeRangeCtx(ctx->ctx); + } +} + + +void filterFreeGroupCtx(SFilterGroupCtx* gRes) { + if (gRes == NULL) { + return; + } + + tfree(gRes->colIdx); + + int16_t i = 0, j = 0; + + while (i < gRes->colNum) { + if (gRes->colInfo[j].info) { + filterFreeColInfo(&gRes->colInfo[j]); + ++i; + } + + ++j; + } + + tfree(gRes->colInfo); + tfree(gRes); +} + +void filterFreeField(SFilterField* field, int32_t type) { + if (field == NULL) { + return; + } + + if (!FILTER_GET_FLAG(field->flag, FLD_DESC_NO_FREE)) { + if (type == FLD_TYPE_VALUE) { + tVariantDestroy(field->desc); + } + + tfree(field->desc); + } + + if (!FILTER_GET_FLAG(field->flag, FLD_DATA_NO_FREE)) { + if (FILTER_GET_FLAG(field->flag, FLD_DATA_IS_HASH)) { + taosHashCleanup(field->data); + } else { + tfree(field->data); + } + } +} + +void filterFreePCtx(SFilterPCtx *pctx) { + taosHashCleanup(pctx->valHash); + taosHashCleanup(pctx->unitHash); +} + +void filterFreeInfo(SFilterInfo *info) { + CHK_RETV(info == NULL); + + tfree(info->cunits); + + for (int32_t i = 0; i < FLD_TYPE_MAX; ++i) { + for (uint16_t f = 0; f < info->fields[i].num; ++f) { + filterFreeField(&info->fields[i].fields[f], i); + } + + tfree(info->fields[i].fields); + } + + for (int32_t i = 0; i < info->groupNum; ++i) { + filterFreeGroup(&info->groups[i]); + } + + tfree(info->groups); + + tfree(info->units); + + tfree(info->unitRes); + + tfree(info->unitFlags); + + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + filterFreeRangeCtx(info->colRange[i]); + } + + tfree(info->colRange); + + filterFreePCtx(&info->pctx); + + if (!FILTER_GET_FLAG(info->status, FI_STATUS_CLONED)) { + tfree(info); + } +} + +int32_t filterHandleValueExtInfo(SFilterUnit* unit, char extInfo) { + assert(extInfo > 0 || extInfo < 0); + + uint8_t optr = FILTER_UNIT_OPTR(unit); + switch (optr) { + case TSDB_RELATION_GREATER: + case TSDB_RELATION_GREATER_EQUAL: + unit->compare.optr = (extInfo > 0) ? FILTER_DUMMY_EMPTY_OPTR : TSDB_RELATION_NOTNULL; + break; + case TSDB_RELATION_LESS: + case TSDB_RELATION_LESS_EQUAL: + unit->compare.optr = (extInfo > 0) ? TSDB_RELATION_NOTNULL : FILTER_DUMMY_EMPTY_OPTR; + break; + case TSDB_RELATION_EQUAL: + unit->compare.optr = FILTER_DUMMY_EMPTY_OPTR; + break; + default: + assert(0); + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterInitValFieldData(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit* unit = &info->units[i]; + if (unit->right.type != FLD_TYPE_VALUE) { + assert(unit->compare.optr == TSDB_RELATION_ISNULL || unit->compare.optr == TSDB_RELATION_NOTNULL || unit->compare.optr == FILTER_DUMMY_EMPTY_OPTR); + continue; + } + + SFilterField* right = FILTER_UNIT_RIGHT_FIELD(info, unit); + + assert(FILTER_GET_FLAG(right->flag, FLD_TYPE_VALUE)); + + uint32_t type = FILTER_UNIT_DATA_TYPE(unit); + SFilterField* fi = right; + + tVariant* var = fi->desc; + + if (var == NULL) { + assert(fi->data != NULL); + continue; + } + + if (unit->compare.optr == TSDB_RELATION_IN) { + filterConvertSetFromBinary((void **)&fi->data, var->pz, var->nLen, type); + CHK_LRET(fi->data == NULL, TSDB_CODE_QRY_APP_ERROR, "failed to convert in param"); + + FILTER_SET_FLAG(fi->flag, FLD_DATA_IS_HASH); + + continue; + } + + if (type == TSDB_DATA_TYPE_BINARY) { + size_t len = (var->nType == TSDB_DATA_TYPE_BINARY || var->nType == TSDB_DATA_TYPE_NCHAR) ? var->nLen : MAX_NUM_STR_SIZE; + fi->data = calloc(1, len + 1 + VARSTR_HEADER_SIZE); + } else if (type == TSDB_DATA_TYPE_NCHAR) { + size_t len = (var->nType == TSDB_DATA_TYPE_BINARY || var->nType == TSDB_DATA_TYPE_NCHAR) ? var->nLen : MAX_NUM_STR_SIZE; + fi->data = calloc(1, (len + 1) * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); + } else { + if (var->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { //TIME RANGE + fi->data = calloc(var->nLen, tDataTypes[type].bytes); + for (int32_t a = 0; a < var->nLen; ++a) { + int64_t *v = taosArrayGet(var->arr, a); + assignVal((char *)fi->data + a * tDataTypes[type].bytes, (char *)v, 0, type); + } + + continue; + } else { + fi->data = calloc(1, sizeof(int64_t)); + } + } + + bool converted = false; + char extInfo = 0; + if (tVariantDumpEx(var, (char*)fi->data, type, true, &converted, &extInfo)) { + if (converted) { + filterHandleValueExtInfo(unit, extInfo); + + continue; + } + qError("dump value to type[%d] failed", type); + return TSDB_CODE_TSC_INVALID_OPERATION; + } + } + + return TSDB_CODE_SUCCESS; +} + + +bool filterDoCompare(__compar_fn_t func, uint8_t optr, void *left, void *right) { + int32_t ret = func(left, right); + + switch (optr) { + case TSDB_RELATION_EQUAL: { + return ret == 0; + } + case TSDB_RELATION_NOT_EQUAL: { + return ret != 0; + } + case TSDB_RELATION_GREATER_EQUAL: { + return ret >= 0; + } + case TSDB_RELATION_GREATER: { + return ret > 0; + } + case TSDB_RELATION_LESS_EQUAL: { + return ret <= 0; + } + case TSDB_RELATION_LESS: { + return ret < 0; + } + case TSDB_RELATION_LIKE: { + return ret == 0; + } + case TSDB_RELATION_IN: { + return ret == 1; + } + + default: + assert(false); + } + + return true; +} + + +int32_t filterAddUnitRange(SFilterInfo *info, SFilterUnit* u, SFilterRangeCtx *ctx, int32_t optr) { + int32_t type = FILTER_UNIT_DATA_TYPE(u); + uint8_t uoptr = FILTER_UNIT_OPTR(u); + void *val = FILTER_UNIT_VAL_DATA(info, u); + SFilterRange ra = {0}; + int64_t tmp = 0; + + switch (uoptr) { + case TSDB_RELATION_GREATER: + SIMPLE_COPY_VALUES(&ra.s, val); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_EXCLUDE); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_GREATER_EQUAL: + SIMPLE_COPY_VALUES(&ra.s, val); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_LESS: + SIMPLE_COPY_VALUES(&ra.e, val); + FILTER_SET_FLAG(ra.eflag, RANGE_FLG_EXCLUDE); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_LESS_EQUAL: + SIMPLE_COPY_VALUES(&ra.e, val); + FILTER_SET_FLAG(ra.sflag, RANGE_FLG_NULL); + break; + case TSDB_RELATION_NOT_EQUAL: + assert(type == TSDB_DATA_TYPE_BOOL); + if (GET_INT8_VAL(val)) { + SIMPLE_COPY_VALUES(&ra.s, &tmp); + SIMPLE_COPY_VALUES(&ra.e, &tmp); + } else { + *(bool *)&tmp = true; + SIMPLE_COPY_VALUES(&ra.s, &tmp); + SIMPLE_COPY_VALUES(&ra.e, &tmp); + } + break; + case TSDB_RELATION_EQUAL: + SIMPLE_COPY_VALUES(&ra.s, val); + SIMPLE_COPY_VALUES(&ra.e, val); + break; + default: + assert(0); + } + + filterAddRange(ctx, &ra, optr); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterCompareRangeCtx(SFilterRangeCtx *ctx1, SFilterRangeCtx *ctx2, bool *equal) { + CHK_JMP(ctx1->status != ctx2->status); + CHK_JMP(ctx1->isnull != ctx2->isnull); + CHK_JMP(ctx1->notnull != ctx2->notnull); + CHK_JMP(ctx1->isrange != ctx2->isrange); + + SFilterRangeNode *r1 = ctx1->rs; + SFilterRangeNode *r2 = ctx2->rs; + + while (r1 && r2) { + CHK_JMP(r1->ra.sflag != r2->ra.sflag); + CHK_JMP(r1->ra.eflag != r2->ra.eflag); + CHK_JMP(r1->ra.s != r2->ra.s); + CHK_JMP(r1->ra.e != r2->ra.e); + + r1 = r1->next; + r2 = r2->next; + } + + CHK_JMP(r1 != r2); + + *equal = true; + + return TSDB_CODE_SUCCESS; + +_return: + *equal = false; + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeUnits(SFilterInfo *info, SFilterGroupCtx* gRes, uint16_t colIdx, bool *empty) { + SArray* colArray = (SArray *)gRes->colInfo[colIdx].info; + int32_t size = (int32_t)taosArrayGetSize(colArray); + int32_t type = gRes->colInfo[colIdx].dataType; + SFilterRangeCtx* ctx = filterInitRangeCtx(type, 0); + + for (uint32_t i = 0; i < size; ++i) { + SFilterUnit* u = taosArrayGetP(colArray, i); + uint8_t optr = FILTER_UNIT_OPTR(u); + + filterAddRangeOptr(ctx, optr, TSDB_RELATION_AND, empty, NULL); + CHK_JMP(*empty); + + if (!FILTER_NO_MERGE_OPTR(optr)) { + filterAddUnitRange(info, u, ctx, TSDB_RELATION_AND); + CHK_JMP(MR_EMPTY_RES(ctx)); + } + } + + taosArrayDestroy(colArray); + + FILTER_PUSH_CTX(gRes->colInfo[colIdx], ctx); + + return TSDB_CODE_SUCCESS; + +_return: + + *empty = true; + + filterFreeRangeCtx(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeGroupUnits(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t* gResNum) { + bool empty = false; + uint16_t *colIdx = malloc(info->fields[FLD_TYPE_COLUMN].num * sizeof(uint16_t)); + uint16_t colIdxi = 0; + uint16_t gResIdx = 0; + + for (uint16_t i = 0; i < info->groupNum; ++i) { + SFilterGroup* g = info->groups + i; + + gRes[gResIdx] = calloc(1, sizeof(SFilterGroupCtx)); + gRes[gResIdx]->colInfo = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(SFilterColInfo)); + colIdxi = 0; + empty = false; + + for (uint16_t j = 0; j < g->unitNum; ++j) { + SFilterUnit* u = FILTER_GROUP_UNIT(info, g, j); + uint16_t cidx = FILTER_UNIT_COL_IDX(u); + + if (gRes[gResIdx]->colInfo[cidx].info == NULL) { + gRes[gResIdx]->colInfo[cidx].info = (SArray *)taosArrayInit(4, POINTER_BYTES); + colIdx[colIdxi++] = cidx; + ++gRes[gResIdx]->colNum; + } else { + if (!FILTER_NO_MERGE_DATA_TYPE(FILTER_UNIT_DATA_TYPE(u))) { + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + } + } + + FILTER_PUSH_UNIT(gRes[gResIdx]->colInfo[cidx], u); + } + + if (colIdxi > 1) { + qsort(colIdx, colIdxi, sizeof(uint16_t), getComparFunc(TSDB_DATA_TYPE_USMALLINT, 0)); + } + + for (uint16_t l = 0; l < colIdxi; ++l) { + int32_t type = gRes[gResIdx]->colInfo[colIdx[l]].dataType; + + if (FILTER_NO_MERGE_DATA_TYPE(type)) { + continue; + } + + filterMergeUnits(info, gRes[gResIdx], colIdx[l], &empty); + + if (empty) { + break; + } + } + + if (empty) { + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + filterFreeGroupCtx(gRes[gResIdx]); + gRes[gResIdx] = NULL; + + continue; + } + + gRes[gResIdx]->colNum = colIdxi; + FILTER_COPY_IDX(&gRes[gResIdx]->colIdx, colIdx, colIdxi); + ++gResIdx; + } + + tfree(colIdx); + + *gResNum = gResIdx; + + if (gResIdx == 0) { + FILTER_SET_FLAG(info->status, FI_STATUS_EMPTY); + } + + return TSDB_CODE_SUCCESS; +} + +void filterCheckColConflict(SFilterGroupCtx* gRes1, SFilterGroupCtx* gRes2, bool *conflict) { + uint16_t idx1 = 0, idx2 = 0, m = 0, n = 0; + bool equal = false; + + for (; m < gRes1->colNum; ++m) { + idx1 = gRes1->colIdx[m]; + + equal = false; + + for (; n < gRes2->colNum; ++n) { + idx2 = gRes2->colIdx[n]; + if (idx1 < idx2) { + *conflict = true; + return; + } + + if (idx1 > idx2) { + continue; + } + + if (FILTER_NO_MERGE_DATA_TYPE(gRes1->colInfo[idx1].dataType)) { + *conflict = true; + return; + } + + ++n; + equal = true; + break; + } + + if (!equal) { + *conflict = true; + return; + } + } + + *conflict = false; + return; +} + + +int32_t filterMergeTwoGroupsImpl(SFilterInfo *info, SFilterRangeCtx **ctx, int32_t optr, uint16_t cidx, SFilterGroupCtx* gRes1, SFilterGroupCtx* gRes2, bool *empty, bool *all) { + SFilterField *fi = FILTER_GET_COL_FIELD(info, cidx); + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + + if ((*ctx) == NULL) { + *ctx = filterInitRangeCtx(type, 0); + } else { + filterReuseRangeCtx(*ctx, type, 0); + } + + assert(gRes2->colInfo[cidx].type == RANGE_TYPE_MR_CTX); + assert(gRes1->colInfo[cidx].type == RANGE_TYPE_MR_CTX); + + filterCopyRangeCtx(*ctx, gRes2->colInfo[cidx].info); + filterSourceRangeFromCtx(*ctx, gRes1->colInfo[cidx].info, optr, empty, all); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeTwoGroups(SFilterInfo *info, SFilterGroupCtx** gRes1, SFilterGroupCtx** gRes2, bool *all) { + bool conflict = false; + + filterCheckColConflict(*gRes1, *gRes2, &conflict); + if (conflict) { + return TSDB_CODE_SUCCESS; + } + + FILTER_SET_FLAG(info->status, FI_STATUS_REWRITE); + + uint16_t idx1 = 0, idx2 = 0, m = 0, n = 0; + bool numEqual = (*gRes1)->colNum == (*gRes2)->colNum; + bool equal = false; + uint16_t equal1 = 0, equal2 = 0, merNum = 0; + SFilterRangeCtx *ctx = NULL; + SFilterColCtx colCtx = {0}; + SArray* colCtxs = taosArrayInit((*gRes2)->colNum, sizeof(SFilterColCtx)); + + for (; m < (*gRes1)->colNum; ++m) { + idx1 = (*gRes1)->colIdx[m]; + + for (; n < (*gRes2)->colNum; ++n) { + idx2 = (*gRes2)->colIdx[n]; + + if (idx1 > idx2) { + continue; + } + + assert(idx1 == idx2); + + ++merNum; + + filterMergeTwoGroupsImpl(info, &ctx, TSDB_RELATION_OR, idx1, *gRes1, *gRes2, NULL, all); + + CHK_JMP(*all); + + if (numEqual) { + if ((*gRes1)->colNum == 1) { + ++equal1; + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + taosArrayPush(colCtxs, &colCtx); + break; + } else { + filterCompareRangeCtx(ctx, (*gRes1)->colInfo[idx1].info, &equal); + if (equal) { + ++equal1; + } + + filterCompareRangeCtx(ctx, (*gRes2)->colInfo[idx2].info, &equal); + if (equal) { + ++equal2; + } + + CHK_JMP(equal1 != merNum && equal2 != merNum); + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + ctx = NULL; + taosArrayPush(colCtxs, &colCtx); + } + } else { + filterCompareRangeCtx(ctx, (*gRes1)->colInfo[idx1].info, &equal); + if (equal) { + ++equal1; + } + + CHK_JMP(equal1 != merNum); + colCtx.colIdx = idx1; + colCtx.ctx = ctx; + ctx = NULL; + taosArrayPush(colCtxs, &colCtx); + } + + ++n; + break; + } + } + + assert(merNum > 0); + + SFilterColInfo *colInfo = NULL; + assert (merNum == equal1 || merNum == equal2); + + filterFreeGroupCtx(*gRes2); + *gRes2 = NULL; + + assert(colCtxs && taosArrayGetSize(colCtxs) > 0); + + int32_t ctxSize = (int32_t)taosArrayGetSize(colCtxs); + SFilterColCtx *pctx = NULL; + + for (int32_t i = 0; i < ctxSize; ++i) { + pctx = taosArrayGet(colCtxs, i); + colInfo = &(*gRes1)->colInfo[pctx->colIdx]; + + filterFreeColInfo(colInfo); + FILTER_PUSH_CTX((*gRes1)->colInfo[pctx->colIdx], pctx->ctx); + } + + taosArrayDestroy(colCtxs); + + return TSDB_CODE_SUCCESS; + +_return: + + if (colCtxs) { + if (taosArrayGetSize(colCtxs) > 0) { + taosArrayDestroyEx(colCtxs, filterFreeColCtx); + } else { + taosArrayDestroy(colCtxs); + } + } + + filterFreeRangeCtx(ctx); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterMergeGroups(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t *gResNum) { + if (*gResNum <= 1) { + return TSDB_CODE_SUCCESS; + } + + qsort(gRes, *gResNum, POINTER_BYTES, filterCompareGroupCtx); + + int32_t pEnd = 0, cStart = 0, cEnd = 0; + uint16_t pColNum = 0, cColNum = 0; + int32_t movedNum = 0; + bool all = false; + + cColNum = gRes[0]->colNum; + + for (int32_t i = 1; i <= *gResNum; ++i) { + if (i < (*gResNum) && gRes[i]->colNum == cColNum) { + continue; + } + + cEnd = i - 1; + + movedNum = 0; + if (pColNum > 0) { + for (int32_t m = 0; m <= pEnd; ++m) { + for (int32_t n = cStart; n <= cEnd; ++n) { + assert(m < n); + filterMergeTwoGroups(info, &gRes[m], &gRes[n], &all); + + CHK_JMP(all); + + if (gRes[n] == NULL) { + if (n < ((*gResNum) - 1)) { + memmove(&gRes[n], &gRes[n+1], (*gResNum-n-1) * POINTER_BYTES); + } + + --cEnd; + --(*gResNum); + ++movedNum; + --n; + } + } + } + } + + for (int32_t m = cStart; m < cEnd; ++m) { + for (int32_t n = m + 1; n <= cEnd; ++n) { + assert(m < n); + filterMergeTwoGroups(info, &gRes[m], &gRes[n], &all); + + CHK_JMP(all); + + if (gRes[n] == NULL) { + if (n < ((*gResNum) - 1)) { + memmove(&gRes[n], &gRes[n+1], (*gResNum-n-1) * POINTER_BYTES); + } + + --cEnd; + --(*gResNum); + ++movedNum; + --n; + } + } + } + + pColNum = cColNum; + pEnd = cEnd; + + i -= movedNum; + + if (i >= (*gResNum)) { + break; + } + + cStart = i; + cEnd = i; + cColNum = gRes[i]->colNum; + } + + return TSDB_CODE_SUCCESS; + +_return: + + FILTER_SET_FLAG(info->status, FI_STATUS_ALL); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterConvertGroupFromArray(SFilterInfo *info, SArray* group) { + size_t groupSize = taosArrayGetSize(group); + + info->groupNum = (uint16_t)groupSize; + + if (info->groupNum > 0) { + info->groups = calloc(info->groupNum, sizeof(*info->groups)); + } + + for (size_t i = 0; i < groupSize; ++i) { + SFilterGroup *pg = taosArrayGet(group, i); + pg->unitFlags = calloc(pg->unitNum, sizeof(*pg->unitFlags)); + info->groups[i] = *pg; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterRewrite(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t gResNum) { + if (!FILTER_GET_FLAG(info->status, FI_STATUS_REWRITE)) { + qDebug("no need rewrite"); + return TSDB_CODE_SUCCESS; + } + + SFilterInfo oinfo = *info; + + FILTER_SET_FLAG(oinfo.status, FI_STATUS_CLONED); + + SArray* group = taosArrayInit(FILTER_DEFAULT_GROUP_SIZE, sizeof(SFilterGroup)); + SFilterGroupCtx *res = NULL; + SFilterColInfo *colInfo = NULL; + int32_t optr = 0; + uint16_t uidx = 0; + + memset(info, 0, sizeof(*info)); + + info->colRangeNum = oinfo.colRangeNum; + info->colRange = oinfo.colRange; + oinfo.colRangeNum = 0; + oinfo.colRange = NULL; + + FILTER_SET_FLAG(info->options, FI_OPTION_NEED_UNIQE); + + filterInitUnitsFields(info); + + for (int32_t i = 0; i < gResNum; ++i) { + res = gRes[i]; + + optr = (res->colNum > 1) ? TSDB_RELATION_AND : TSDB_RELATION_OR; + + SFilterGroup ng = {0}; + + for (uint16_t m = 0; m < res->colNum; ++m) { + colInfo = &res->colInfo[res->colIdx[m]]; + if (FILTER_NO_MERGE_DATA_TYPE(colInfo->dataType)) { + assert(colInfo->type == RANGE_TYPE_UNIT); + int32_t usize = (int32_t)taosArrayGetSize((SArray *)colInfo->info); + + for (int32_t n = 0; n < usize; ++n) { + SFilterUnit* u = taosArrayGetP((SArray *)colInfo->info, n); + + filterAddUnitFromUnit(info, &oinfo, u, &uidx); + filterAddUnitToGroup(&ng, uidx); + } + + continue; + } + + assert(colInfo->type == RANGE_TYPE_MR_CTX); + + filterAddGroupUnitFromCtx(info, &oinfo, colInfo->info, res->colIdx[m], &ng, optr, group); + } + + if (ng.unitNum > 0) { + taosArrayPush(group, &ng); + } + } + + filterConvertGroupFromArray(info, group); + + taosArrayDestroy(group); + + filterFreeInfo(&oinfo); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterGenerateColRange(SFilterInfo *info, SFilterGroupCtx** gRes, int32_t gResNum) { + uint16_t *idxs = NULL; + uint16_t colNum = 0; + SFilterGroupCtx *res = NULL; + uint16_t *idxNum = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(*idxNum)); + + for (int32_t i = 0; i < gResNum; ++i) { + for (uint16_t m = 0; m < gRes[i]->colNum; ++m) { + SFilterColInfo *colInfo = &gRes[i]->colInfo[gRes[i]->colIdx[m]]; + if (FILTER_NO_MERGE_DATA_TYPE(colInfo->dataType)) { + continue; + } + + ++idxNum[gRes[i]->colIdx[m]]; + } + } + + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + if (idxNum[i] < gResNum) { + continue; + } + + assert(idxNum[i] == gResNum); + + if (idxs == NULL) { + idxs = calloc(info->fields[FLD_TYPE_COLUMN].num, sizeof(*idxs)); + } + + idxs[colNum++] = i; + } + + CHK_JMP(colNum <= 0); + + info->colRangeNum = colNum; + info->colRange = calloc(colNum, POINTER_BYTES); + + for (int32_t i = 0; i < gResNum; ++i) { + res = gRes[i]; + uint16_t n = 0; + + for (uint16_t m = 0; m < info->colRangeNum; ++m) { + for (; n < res->colNum; ++n) { + if (res->colIdx[n] < idxs[m]) { + continue; + } + + assert(res->colIdx[n] == idxs[m]); + + SFilterColInfo * colInfo = &res->colInfo[res->colIdx[n]]; + if (info->colRange[m] == NULL) { + info->colRange[m] = filterInitRangeCtx(colInfo->dataType, 0); + SFilterField* fi = FILTER_GET_COL_FIELD(info, res->colIdx[n]); + info->colRange[m]->colId = ((SSchema*)fi->desc)->colId; + } + + assert(colInfo->type == RANGE_TYPE_MR_CTX); + + bool all = false; + filterSourceRangeFromCtx(info->colRange[m], colInfo->info, TSDB_RELATION_OR, NULL, &all); + if (all) { + filterFreeRangeCtx(info->colRange[m]); + info->colRange[m] = NULL; + + if (m < (info->colRangeNum - 1)) { + memmove(&info->colRange[m], &info->colRange[m + 1], (info->colRangeNum - m - 1) * POINTER_BYTES); + memmove(&idxs[m], &idxs[m + 1], (info->colRangeNum - m - 1) * sizeof(*idxs)); + } + + --info->colRangeNum; + --m; + + CHK_JMP(info->colRangeNum <= 0); + } + + ++n; + break; + } + } + } + +_return: + tfree(idxNum); + tfree(idxs); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterPostProcessRange(SFilterInfo *info) { + for (uint16_t i = 0; i < info->colRangeNum; ++i) { + SFilterRangeCtx* ctx = info->colRange[i]; + SFilterRangeNode *r = ctx->rs; + while (r) { + r->rc.func = filterGetRangeCompFunc(r->ra.sflag, r->ra.eflag); + r = r->next; + } + } + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterGenerateComInfo(SFilterInfo *info) { + uint16_t n = 0; + + info->cunits = malloc(info->unitNum * sizeof(*info->cunits)); + + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + + info->cunits[i].func = filterGetCompFuncIdx(FILTER_UNIT_DATA_TYPE(unit), unit->compare.optr); + info->cunits[i].rfunc = filterGetRangeCompFuncFromOptrs(unit->compare.optr, unit->compare.optr2); + info->cunits[i].optr = FILTER_UNIT_OPTR(unit); + info->cunits[i].colData = NULL; + + if (unit->right.type == FLD_TYPE_VALUE) { + info->cunits[i].valData = FILTER_UNIT_VAL_DATA(info, unit); + } else { + info->cunits[i].valData = NULL; + } + if (unit->right2.type == FLD_TYPE_VALUE) { + info->cunits[i].valData2 = FILTER_GET_VAL_FIELD_DATA(FILTER_GET_FIELD(info, unit->right2)); + } else { + info->cunits[i].valData2 = info->cunits[i].valData; + } + + info->cunits[i].dataSize = FILTER_UNIT_COL_SIZE(info, unit); + info->cunits[i].dataType = FILTER_UNIT_DATA_TYPE(unit); + } + + uint16_t cgroupNum = info->groupNum + 1; + + for (uint16_t i = 0; i < info->groupNum; ++i) { + cgroupNum += info->groups[i].unitNum; + } + + info->cgroups = malloc(cgroupNum * sizeof(*info->cgroups)); + + for (uint16_t i = 0; i < info->groupNum; ++i) { + info->cgroups[n++] = info->groups[i].unitNum; + + for (uint16_t m = 0; m < info->groups[i].unitNum; ++m) { + info->cgroups[n++] = info->groups[i].unitIdxs[m]; + } + } + + info->cgroups[n] = 0; + + return TSDB_CODE_SUCCESS; +} + +int32_t filterUpdateComUnits(SFilterInfo *info) { + for (uint16_t i = 0; i < info->unitNum; ++i) { + SFilterUnit *unit = &info->units[i]; + + info->cunits[i].colData = FILTER_UNIT_COL_DATA(info, unit, 0); + } + + return TSDB_CODE_SUCCESS; +} + + +static FORCE_INLINE bool filterExecuteImplAll(void *info, int32_t numOfRows, int8_t* p) { + return true; +} +static FORCE_INLINE bool filterExecuteImplEmpty(void *info, int32_t numOfRows, int8_t* p) { + return false; +} +static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + p[i] = isNull(colData, info->cunits[uidx].dataType); + if (p[i] == 0) { + all = false; + } + } + + return all; +} +static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + p[i] = !isNull(colData, info->cunits[uidx].dataType); + if (p[i] == 0) { + all = false; + } + } + + return all; +} + +bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + uint16_t dataSize = info->cunits[0].dataSize; + char *colData = (char *)info->cunits[0].colData; + rangeCompFunc rfunc = gRangeCompare[info->cunits[0].rfunc]; + void *valData = info->cunits[0].valData; + void *valData2 = info->cunits[0].valData2; + __compar_fn_t func = gDataCompare[info->cunits[0].func]; + + for (int32_t i = 0; i < numOfRows; ++i) { + if (isNull(colData, info->cunits[0].dataType)) { + all = false; + colData += dataSize; + continue; + } + + p[i] = (*rfunc)(colData, colData, valData, valData2, func); + + if (p[i] == 0) { + all = false; + } + + colData += dataSize; + } + + return all; +} + +bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + uint16_t uidx = info->groups[0].unitIdxs[0]; + void *colData = (char *)info->cunits[uidx].colData + info->cunits[uidx].dataSize * i; + if (isNull(colData, info->cunits[uidx].dataType)) { + all = false; + continue; + } + + p[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, colData, info->cunits[uidx].valData); + + if (p[i] == 0) { + all = false; + } + } + + return all; +} + + +bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t* p) { + SFilterInfo *info = (SFilterInfo *)pinfo; + bool all = true; + + for (int32_t i = 0; i < numOfRows; ++i) { + //FILTER_UNIT_CLR_F(info); + + for (uint32_t g = 0; g < info->groupNum; ++g) { + SFilterGroup *group = &info->groups[g]; + for (uint32_t u = 0; u < group->unitNum; ++u) { + uint16_t uidx = group->unitIdxs[u]; + SFilterComUnit *cunit = &info->cunits[uidx]; + void *colData = (char *)cunit->colData + cunit->dataSize * i; + + //if (FILTER_UNIT_GET_F(info, uidx)) { + // p[i] = FILTER_UNIT_GET_R(info, uidx); + //} else { + uint8_t optr = cunit->optr; + + if (isNull(colData, cunit->dataType)) { + p[i] = optr == TSDB_RELATION_ISNULL ? true : false; + } else { + if (optr == TSDB_RELATION_NOTNULL) { + p[i] = 1; + } else if (optr == TSDB_RELATION_ISNULL) { + p[i] = 0; + } else if (cunit->rfunc >= 0) { + p[i] = (*gRangeCompare[cunit->rfunc])(colData, colData, cunit->valData, cunit->valData2, gDataCompare[cunit->func]); + } else { + p[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, colData, cunit->valData); + } + + //FILTER_UNIT_SET_R(info, uidx, p[i]); + //FILTER_UNIT_SET_F(info, uidx); + } + + if (p[i] == 0) { + break; + } + } + + if (p[i]) { + break; + } + } + + if (p[i] == 0) { + all = false; + } + } + + return all; +} + +FORCE_INLINE bool filterExecute(SFilterInfo *info, int32_t numOfRows, int8_t* p) { + return (*info->func)(info, numOfRows, p); +} + +int32_t filterSetExecFunc(SFilterInfo *info) { + if (FILTER_ALL_RES(info)) { + info->func = filterExecuteImplAll; + return TSDB_CODE_SUCCESS; + } + + if (FILTER_EMPTY_RES(info)) { + info->func = filterExecuteImplEmpty; + return TSDB_CODE_SUCCESS; + } + + if (info->unitNum > 1) { + info->func = filterExecuteImpl; + return TSDB_CODE_SUCCESS; + } + + if (info->units[0].compare.optr == TSDB_RELATION_ISNULL) { + info->func = filterExecuteImplIsNull; + return TSDB_CODE_SUCCESS; + } + + if (info->units[0].compare.optr == TSDB_RELATION_NOTNULL) { + info->func = filterExecuteImplNotNull; + return TSDB_CODE_SUCCESS; + } + + if (info->cunits[0].rfunc >= 0) { + info->func = filterExecuteImplRange; + return TSDB_CODE_SUCCESS; + } + + info->func = filterExecuteImplMisc; + return TSDB_CODE_SUCCESS; +} + + + +int32_t filterPreprocess(SFilterInfo *info) { + SFilterGroupCtx** gRes = calloc(info->groupNum, sizeof(SFilterGroupCtx *)); + int32_t gResNum = 0; + + filterMergeGroupUnits(info, gRes, &gResNum); + + filterMergeGroups(info, gRes, &gResNum); + + if (FILTER_GET_FLAG(info->status, FI_STATUS_ALL)) { + qInfo("Final - FilterInfo: [ALL]"); + goto _return; + } + + + if (FILTER_GET_FLAG(info->status, FI_STATUS_EMPTY)) { + qInfo("Final - FilterInfo: [EMPTY]"); + goto _return; + } + + filterGenerateColRange(info, gRes, gResNum); + + filterDumpInfoToString(info, "Final", 1); + + filterPostProcessRange(info); + + filterRewrite(info, gRes, gResNum); + + filterGenerateComInfo(info); + +_return: + + filterSetExecFunc(info); + + for (int32_t i = 0; i < gResNum; ++i) { + filterFreeGroupCtx(gRes[i]); + } + + tfree(gRes); + + return TSDB_CODE_SUCCESS; +} + +int32_t filterSetColFieldData(SFilterInfo *info, int16_t colId, void *data) { + CHK_LRET(info == NULL, TSDB_CODE_QRY_APP_ERROR, "info NULL"); + CHK_LRET(info->fields[FLD_TYPE_COLUMN].num <= 0, TSDB_CODE_QRY_APP_ERROR, "no column fileds"); + + if (FILTER_ALL_RES(info) || FILTER_EMPTY_RES(info)) { + return TSDB_CODE_SUCCESS; + } + + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + SSchema* sch = fi->desc; + if (sch->colId == colId) { + fi->data = data; + + break; + } + } + + filterUpdateComUnits(info); + + return TSDB_CODE_SUCCESS; +} + + +int32_t filterInitFromTree(tExprNode* tree, SFilterInfo **pinfo, uint32_t options) { + int32_t code = TSDB_CODE_SUCCESS; + SFilterInfo *info = NULL; + + CHK_LRET(tree == NULL || pinfo == NULL, TSDB_CODE_QRY_APP_ERROR, "invalid param"); + + if (*pinfo == NULL) { + *pinfo = calloc(1, sizeof(SFilterInfo)); + } + + info = *pinfo; + + info->options = options; + + SArray* group = taosArrayInit(FILTER_DEFAULT_GROUP_SIZE, sizeof(SFilterGroup)); + + filterInitUnitsFields(info); + + code = filterTreeToGroup(tree, info, group); + + ERR_JRET(code); + + filterConvertGroupFromArray(info, group); + + ERR_JRET(filterInitValFieldData(info)); + + if (!FILTER_GET_FLAG(info->options, FI_OPTION_NO_REWRITE)) { + filterDumpInfoToString(info, "Before preprocess", 0); + + ERR_JRET(filterPreprocess(info)); + + CHK_JMP(FILTER_GET_FLAG(info->status, FI_STATUS_ALL)); + + if (FILTER_GET_FLAG(info->status, FI_STATUS_EMPTY)) { + taosArrayDestroy(group); + return code; + } + + //ERR_JRET(filterInitUnitFunc(info)); + } + + info->unitRes = malloc(info->unitNum * sizeof(*info->unitRes)); + info->unitFlags = malloc(info->unitNum * sizeof(*info->unitFlags)); + + filterDumpInfoToString(info, "Final", 0); + + taosArrayDestroy(group); + + return code; + +_return: + qInfo("No filter, code:%d", code); + + taosArrayDestroy(group); + + filterFreeInfo(*pinfo); + + *pinfo = NULL; + + return code; +} + + + + +bool filterRangeExecute(SFilterInfo *info, SDataStatis *pDataStatis, int32_t numOfCols, int32_t numOfRows) { + if (FILTER_EMPTY_RES(info)) { + return false; + } + + if (FILTER_ALL_RES(info)) { + return true; + } + + bool ret = true; + void *minVal, *maxVal; + + for (int32_t k = 0; k < info->colRangeNum; ++k) { + int32_t index = -1; + SFilterRangeCtx *ctx = info->colRange[k]; + for(int32_t i = 0; i < numOfCols; ++i) { + if (pDataStatis[i].colId == ctx->colId) { + index = i; + break; + } + } + + // no statistics data, load the true data block + if (index == -1) { + return true; + } + + // not support pre-filter operation on binary/nchar data type + if (FILTER_NO_MERGE_DATA_TYPE(ctx->type)) { + return true; + } + + if ((pDataStatis[index].numOfNull <= 0) && (ctx->isnull && !ctx->notnull && !ctx->isrange)) { + return false; + } + + // all data in current column are NULL, no need to check its boundary value + if (pDataStatis[index].numOfNull == numOfRows) { + + // if isNULL query exists, load the null data column + if ((ctx->notnull || ctx->isrange) && (!ctx->isnull)) { + return false; + } + + continue; + } + + SDataStatis* pDataBlockst = &pDataStatis[index]; + + SFilterRangeNode *r = ctx->rs; + + if (ctx->type == TSDB_DATA_TYPE_FLOAT) { + float minv = (float)(*(double *)(&pDataBlockst->min)); + float maxv = (float)(*(double *)(&pDataBlockst->max)); + + minVal = &minv; + maxVal = &maxv; + } else { + minVal = &pDataBlockst->min; + maxVal = &pDataBlockst->max; + } + + while (r) { + ret = r->rc.func(minVal, maxVal, &r->rc.s, &r->rc.e, ctx->pCompareFunc); + if (ret) { + break; + } + r = r->next; + } + + CHK_RET(!ret, ret); + } + + return ret; +} + + + +int32_t filterGetTimeRange(SFilterInfo *info, STimeWindow *win) { + SFilterRange ra = {0}; + SFilterRangeCtx *prev = filterInitRangeCtx(TSDB_DATA_TYPE_TIMESTAMP, FI_OPTION_TIMESTAMP); + SFilterRangeCtx *tmpc = filterInitRangeCtx(TSDB_DATA_TYPE_TIMESTAMP, FI_OPTION_TIMESTAMP); + SFilterRangeCtx *cur = NULL; + int32_t num = 0; + int32_t optr = 0; + int32_t code = 0; + bool empty = false, all = false; + + for (int32_t i = 0; i < info->groupNum; ++i) { + SFilterGroup *group = &info->groups[i]; + if (group->unitNum > 1) { + cur = tmpc; + optr = TSDB_RELATION_AND; + } else { + cur = prev; + optr = TSDB_RELATION_OR; + } + + for (int32_t u = 0; u < group->unitNum; ++u) { + uint16_t uidx = group->unitIdxs[u]; + SFilterUnit *unit = &info->units[uidx]; + + uint8_t raOptr = FILTER_UNIT_OPTR(unit); + + filterAddRangeOptr(cur, raOptr, TSDB_RELATION_AND, &empty, NULL); + CHK_JMP(empty); + + if (FILTER_NO_MERGE_OPTR(raOptr)) { + continue; + } + + SFilterField *right = FILTER_UNIT_RIGHT_FIELD(info, unit); + void *s = FILTER_GET_VAL_FIELD_DATA(right); + void *e = FILTER_GET_VAL_FIELD_DATA(right) + tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; + + SIMPLE_COPY_VALUES(&ra.s, s); + SIMPLE_COPY_VALUES(&ra.e, e); + + filterAddRange(cur, &ra, optr); + } + + if (cur->notnull) { + prev->notnull = true; + break; + } + + if (group->unitNum > 1) { + filterSourceRangeFromCtx(prev, cur, TSDB_RELATION_OR, &empty, &all); + filterResetRangeCtx(cur); + if (all) { + break; + } + } + } + + if (prev->notnull) { + *win = TSWINDOW_INITIALIZER; + } else { + filterGetRangeNum(prev, &num); + if (num > 1) { + qError("only one time range accepted, num:%d", num); + ERR_JRET(TSDB_CODE_QRY_INVALID_TIME_CONDITION); + } + + CHK_JMP(num < 1); + + SFilterRange tra; + filterGetRangeRes(prev, &tra); + win->skey = tra.s; + win->ekey = tra.e; + } + + filterFreeRangeCtx(prev); + filterFreeRangeCtx(tmpc); + + qDebug("qFilter time range:[%"PRId64 "]-[%"PRId64 "]", win->skey, win->ekey); + return TSDB_CODE_SUCCESS; + +_return: + + *win = TSWINDOW_DESC_INITIALIZER; + + filterFreeRangeCtx(prev); + filterFreeRangeCtx(tmpc); + + qDebug("qFilter time range:[%"PRId64 "]-[%"PRId64 "]", win->skey, win->ekey); + + return code; +} + + +int32_t filterConverNcharColumns(SFilterInfo* info, int32_t rows, bool *gotNchar) { + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + if (type == TSDB_DATA_TYPE_NCHAR) { + SFilterField nfi = {0}; + nfi.desc = fi->desc; + int32_t bytes = FILTER_GET_COL_FIELD_SIZE(fi); + nfi.data = malloc(rows * bytes); + int32_t bufSize = bytes - VARSTR_HEADER_SIZE; + for (int32_t j = 0; j < rows; ++j) { + char *src = FILTER_GET_COL_FIELD_DATA(fi, j); + char *dst = FILTER_GET_COL_FIELD_DATA(&nfi, j); + int32_t len = 0; + taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); + varDataLen(dst) = len; + } + + fi->data = nfi.data; + + *gotNchar = true; + } + } + + if (*gotNchar) { + filterUpdateComUnits(info); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t filterFreeNcharColumns(SFilterInfo* info) { + for (uint16_t i = 0; i < info->fields[FLD_TYPE_COLUMN].num; ++i) { + SFilterField* fi = &info->fields[FLD_TYPE_COLUMN].fields[i]; + int32_t type = FILTER_GET_COL_FIELD_TYPE(fi); + if (type == TSDB_DATA_TYPE_NCHAR) { + tfree(fi->data); + } + } + + return TSDB_CODE_SUCCESS; +} + + + + + diff --git a/src/query/src/qSqlParser.c b/src/query/src/qSqlParser.c index e93553c4df..011892fe93 100644 --- a/src/query/src/qSqlParser.c +++ b/src/query/src/qSqlParser.c @@ -423,6 +423,9 @@ tSqlExpr *tSqlExprClone(tSqlExpr *pSrc) { pExpr->pRight = tSqlExprClone(pSrc->pRight); } + memset(&pExpr->value, 0, sizeof(pExpr->value)); + tVariantAssign(&pExpr->value, &pSrc->value); + //we don't clone paramList now because clone is only used for between/and assert(pSrc->Expr.paramList == NULL); return pExpr; @@ -478,9 +481,7 @@ static void doDestroySqlExprNode(tSqlExpr *pExpr) { return; } - if (pExpr->tokenId == TK_STRING) { - tVariantDestroy(&pExpr->value); - } + tVariantDestroy(&pExpr->value); tSqlExprListDestroy(pExpr->Expr.paramList); free(pExpr); diff --git a/src/query/src/queryMain.c b/src/query/src/queryMain.c index 7d30f7c668..403b51426f 100644 --- a/src/query/src/queryMain.c +++ b/src/query/src/queryMain.c @@ -103,6 +103,12 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi } } + if (param.colCond != NULL) { + if ((code = createQueryFilter(param.colCond, pQueryMsg->colCondLen, ¶m.pFilters)) != TSDB_CODE_SUCCESS) { + goto _over; + } + } + param.pGroupbyExpr = createGroupbyExprFromMsg(pQueryMsg, param.pGroupColIndex, &code); if ((param.pGroupbyExpr == NULL && pQueryMsg->numOfGroupCols != 0) || code != TSDB_CODE_SUCCESS) { goto _over; @@ -162,13 +168,19 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi assert(pQueryMsg->stableQuery == isSTableQuery); (*pQInfo) = createQInfoImpl(pQueryMsg, param.pGroupbyExpr, param.pExprs, param.pSecExprs, &tableGroupInfo, - param.pTagColumnInfo, vgId, param.sql, qId, param.pUdfInfo); + param.pTagColumnInfo, param.pFilters, vgId, param.sql, qId, param.pUdfInfo); param.sql = NULL; param.pExprs = NULL; param.pSecExprs = NULL; param.pGroupbyExpr = NULL; param.pTagColumnInfo = NULL; + param.pFilters = NULL; + + if ((*pQInfo) == NULL) { + code = TSDB_CODE_QRY_OUT_OF_MEMORY; + goto _over; + } param.pUdfInfo = NULL; code = initQInfo(&pQueryMsg->tsBuf, tsdb, NULL, *pQInfo, ¶m, (char*)pQueryMsg, pQueryMsg->prevResultLen, NULL); @@ -178,6 +190,8 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi taosArrayDestroy(param.pGroupbyExpr->columnInfo); } + tfree(param.colCond); + destroyUdfInfo(param.pUdfInfo); taosArrayDestroy(param.pTableIdList); @@ -190,6 +204,8 @@ int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryMsg, qi freeColumnFilterInfo(column->flist.filterInfo, column->flist.numOfFilters); } + filterFreeInfo(param.pFilters); + //pQInfo already freed in initQInfo, but *pQInfo may not pointer to null; if (code != TSDB_CODE_SUCCESS) { *pQInfo = NULL; diff --git a/src/query/tests/CMakeLists.txt b/src/query/tests/CMakeLists.txt index cc4b607bb4..349d511f15 100644 --- a/src/query/tests/CMakeLists.txt +++ b/src/query/tests/CMakeLists.txt @@ -27,3 +27,4 @@ SET_SOURCE_FILES_PROPERTIES(./percentileTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./resultBufferTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./tsBufTest.cpp PROPERTIES COMPILE_FLAGS -w) SET_SOURCE_FILES_PROPERTIES(./unitTest.cpp PROPERTIES COMPILE_FLAGS -w) +SET_SOURCE_FILES_PROPERTIES(./rangeMergeTest.cpp PROPERTIES COMPILE_FLAGS -w) diff --git a/src/query/tests/rangeMergeTest.cpp b/src/query/tests/rangeMergeTest.cpp new file mode 100644 index 0000000000..e65508a300 --- /dev/null +++ b/src/query/tests/rangeMergeTest.cpp @@ -0,0 +1,367 @@ +#include +#include + +#include "qResultbuf.h" +#include "taos.h" +#include "taosdef.h" + +#include "qFilter.h" + +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" + +extern "C" { + extern void* filterInitRangeCtx(int32_t type, int32_t options); + extern int32_t filterGetRangeNum(void* h, int32_t* num); + extern int32_t filterGetRangeRes(void* h, SFilterRange *ra); + extern int32_t filterFreeRangeCtx(void* h); + extern int32_t filterAddRange(void* h, SFilterRange* ra, int32_t optr); +} + +namespace { + + +void intDataTest() { + printf("running %s\n", __FUNCTION__); + int32_t asize = 0; + SFilterRange ra[10] = {0}; + int64_t *s =NULL; + int64_t *e =NULL; + int64_t s0[3] = {-100, 1, 3}; + int64_t e0[3] = {0 , 2, 4}; + int64_t s1[3] = {INT64_MIN, 0 , 3}; + int64_t e1[3] = {100 , 50, 4}; + int64_t s2[5] = {1 , 3 , 10,30,70}; + int64_t e2[5] = {10, 100, 20,50,120}; + int64_t s3[3] = {1 , 20 , 5}; + int64_t e3[3] = {10, 100, 25}; + int64_t s4[2] = {10, 0}; + int64_t e4[2] = {20, 5}; + int64_t s5[3] = {0, 6 ,7}; + int64_t e5[3] = {4, 10,20}; + + int64_t rs[10]; + int64_t re[10]; + + int32_t num = 0; + void *h = NULL; + + s = s0; + e = e0; + asize = sizeof(s0)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 3); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, -100); + ASSERT_EQ(ra[0].e, 0); + ASSERT_EQ(ra[1].s, 1); + ASSERT_EQ(ra[1].e, 2); + ASSERT_EQ(ra[2].s, 3); + ASSERT_EQ(ra[2].e, 4); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, FI_OPTION_TIMESTAMP); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, -100); + ASSERT_EQ(ra[0].e, 4); + filterFreeRangeCtx(h); + + + s = s1; + e = e1; + asize = sizeof(s1)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 3); + ASSERT_EQ(ra[0].e, 4); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, INT64_MIN); + ASSERT_EQ(ra[0].e, 100); + filterFreeRangeCtx(h); + + + + s = s2; + e = e2; + asize = sizeof(s2)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 1); + ASSERT_EQ(ra[0].e, 120); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, i % 2 ? TSDB_RELATION_OR : TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, i % 2 ? TSDB_RELATION_AND : TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 70); + ASSERT_EQ(ra[0].e, 120); + filterFreeRangeCtx(h); + + + s = s3; + e = e3; + asize = sizeof(s3)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 1); + ASSERT_EQ(ra[0].e, 100); + filterFreeRangeCtx(h); + + + + + s = s4; + e = e4; + asize = sizeof(s4)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 5); + ASSERT_EQ(ra[1].s, 10); + ASSERT_EQ(ra[1].e, 20); + filterFreeRangeCtx(h); + + + s = s5; + e = e5; + asize = sizeof(s5)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 4); + ASSERT_EQ(ra[1].s, 6); + ASSERT_EQ(ra[1].e, 20); + filterFreeRangeCtx(h); + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].s = s[i]; + ra[0].e = e[i]; + + filterAddRange(h, ra, (i == (asize -1)) ? TSDB_RELATION_AND : TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 1); + filterGetRangeRes(h, ra); + ASSERT_EQ(ra[0].s, 7); + ASSERT_EQ(ra[0].e, 10); + filterFreeRangeCtx(h); + + + + int64_t s6[2] = {0, 4}; + int64_t e6[2] = {4, 6}; + s = s6; + e = e6; + asize = sizeof(s6)/sizeof(s[0]); + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].eflag = 1; + ra[1].sflag = 4; + + ra[i].s = s[i]; + ra[i].e = e[i]; + + filterAddRange(h, ra + i, TSDB_RELATION_AND); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 0); + filterFreeRangeCtx(h); + + + + memset(ra, 0, sizeof(ra)); + h = filterInitRangeCtx(TSDB_DATA_TYPE_BIGINT, 0); + for (int32_t i = 0; i < asize; ++i) { + ra[0].eflag = 1; + ra[1].sflag = 1; + + ra[i].s = s[i]; + ra[i].e = e[i]; + + filterAddRange(h, ra + i, TSDB_RELATION_OR); + } + filterGetRangeNum(h, &num); + ASSERT_EQ(num, 2); + ASSERT_EQ(ra[0].s, 0); + ASSERT_EQ(ra[0].e, 4); + ASSERT_EQ(ra[0].eflag, 1); + ASSERT_EQ(ra[1].s, 4); + ASSERT_EQ(ra[1].e, 6); + ASSERT_EQ(ra[1].sflag, 1); + filterFreeRangeCtx(h); + +} + + +} // namespace + +TEST(testCase, rangeMergeTest) { + intDataTest(); + +} diff --git a/src/util/inc/hash.h b/src/util/inc/hash.h index 6c4145810b..7a93745dc8 100644 --- a/src/util/inc/hash.h +++ b/src/util/inc/hash.h @@ -42,7 +42,7 @@ typedef struct SHashNode { #define GET_HASH_NODE_KEY(_n) ((char*)(_n) + sizeof(SHashNode) + (_n)->dataLen) #define GET_HASH_NODE_DATA(_n) ((char*)(_n) + sizeof(SHashNode)) -#define GET_HASH_PNODE(_n) ((char*)(_n) - sizeof(SHashNode)); +#define GET_HASH_PNODE(_n) ((SHashNode *)((char*)(_n) - sizeof(SHashNode))) typedef enum SHashLockTypeE { HASH_NO_LOCK = 0, @@ -170,6 +170,10 @@ void *taosHashIterate(SHashObj *pHashObj, void *p); void taosHashCancelIterate(SHashObj *pHashObj, void *p); +void *taosHashGetDataKey(SHashObj *pHashObj, void *data); + +uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data); + #ifdef __cplusplus } #endif diff --git a/src/util/inc/tcompare.h b/src/util/inc/tcompare.h index fe46f00086..cf61b7165a 100644 --- a/src/util/inc/tcompare.h +++ b/src/util/inc/tcompare.h @@ -53,6 +53,38 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr); int32_t taosArrayCompareString(const void* a, const void* b); +int32_t setCompareBytes1(const void *pLeft, const void *pRight); + +int32_t setCompareBytes2(const void *pLeft, const void *pRight); + +int32_t setCompareBytes4(const void *pLeft, const void *pRight); +int32_t setCompareBytes8(const void *pLeft, const void *pRight); + +int32_t compareInt32Val(const void *pLeft, const void *pRight); +int32_t compareInt64Val(const void *pLeft, const void *pRight); + +int32_t compareInt16Val(const void *pLeft, const void *pRight); + +int32_t compareInt8Val(const void *pLeft, const void *pRight); + +int32_t compareUint32Val(const void *pLeft, const void *pRight); +int32_t compareUint64Val(const void *pLeft, const void *pRight); + +int32_t compareUint16Val(const void *pLeft, const void *pRight); + +int32_t compareUint8Val(const void* pLeft, const void* pRight); + +int32_t compareFloatVal(const void *pLeft, const void *pRight); + +int32_t compareDoubleVal(const void *pLeft, const void *pRight); + +int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight); + +int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight); +int32_t compareStrPatternComp(const void* pLeft, const void* pRight); +int32_t compareFindItemInSet(const void *pLeft, const void* pRight); +int32_t compareWStrPatternComp(const void* pLeft, const void* pRight); + #ifdef __cplusplus } #endif diff --git a/src/util/src/hash.c b/src/util/src/hash.c index 6118aa7bef..a22ce34a0e 100644 --- a/src/util/src/hash.c +++ b/src/util/src/hash.c @@ -776,6 +776,17 @@ size_t taosHashGetMemSize(const SHashObj *pHashObj) { return (pHashObj->capacity * (sizeof(SHashEntry) + POINTER_BYTES)) + sizeof(SHashNode) * taosHashGetSize(pHashObj) + sizeof(SHashObj); } +FORCE_INLINE void *taosHashGetDataKey(SHashObj *pHashObj, void *data) { + SHashNode * node = GET_HASH_PNODE(data); + return GET_HASH_NODE_KEY(node); +} + +FORCE_INLINE uint32_t taosHashGetDataKeyLen(SHashObj *pHashObj, void *data) { + SHashNode * node = GET_HASH_PNODE(data); + return node->keyLen; +} + + // release the pNode, return next pNode, and lock the current entry static void *taosHashReleaseNode(SHashObj *pHashObj, void *p, int *slot) { diff --git a/src/util/src/tcompare.c b/src/util/src/tcompare.c index e953f4c464..7577451f88 100644 --- a/src/util/src/tcompare.c +++ b/src/util/src/tcompare.c @@ -19,6 +19,22 @@ #include "tarray.h" #include "hash.h" +int32_t setCompareBytes1(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0; +} + +int32_t setCompareBytes2(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 2) ? 1 : 0; +} + +int32_t setCompareBytes4(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 4) ? 1 : 0; +} + +int32_t setCompareBytes8(const void *pLeft, const void *pRight) { + return NULL != taosHashGet((SHashObj *)pRight, pLeft, 8) ? 1 : 0; +} + int32_t compareInt32Val(const void *pLeft, const void *pRight) { int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight); if (left > right) return 1; @@ -48,21 +64,21 @@ int32_t compareInt8Val(const void *pLeft, const void *pRight) { } int32_t compareUint32Val(const void *pLeft, const void *pRight) { - int32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight); + uint32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; } int32_t compareUint64Val(const void *pLeft, const void *pRight) { - int64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight); + uint64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; } int32_t compareUint16Val(const void *pLeft, const void *pRight) { - int16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight); + uint16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight); if (left > right) return 1; if (left < right) return -1; return 0; @@ -262,7 +278,7 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH; } -static int32_t compareStrPatternComp(const void* pLeft, const void* pRight) { +int32_t compareStrPatternComp(const void* pLeft, const void* pRight) { SPatternCompareInfo pInfo = {'%', '_'}; char pattern[128] = {0}; @@ -290,11 +306,11 @@ int32_t taosArrayCompareString(const void* a, const void* b) { // const SArray* arr = (const SArray*) pRight; // return taosArraySearchString(arr, pLeft, taosArrayCompareString, TD_EQ) == NULL ? 0 : 1; //} -static int32_t compareFindItemInSet(const void *pLeft, const void* pRight) { +int32_t compareFindItemInSet(const void *pLeft, const void* pRight) { return NULL != taosHashGet((SHashObj *)pRight, varDataVal(pLeft), varDataLen(pLeft)) ? 1 : 0; } -static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { +int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { SPatternCompareInfo pInfo = {'%', '_'}; wchar_t pattern[128] = {0}; @@ -309,6 +325,29 @@ static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { __compar_fn_t getComparFunc(int32_t type, int32_t optr) { __compar_fn_t comparFn = NULL; + + if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) { + switch (type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + return setCompareBytes1; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + return setCompareBytes2; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_FLOAT: + return setCompareBytes4; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + return setCompareBytes8; + default: + assert(0); + } + } switch (type) { case TSDB_DATA_TYPE_BOOL: @@ -334,6 +373,8 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) { case TSDB_DATA_TYPE_NCHAR: { if (optr == TSDB_RELATION_LIKE) { comparFn = compareWStrPatternComp; + } else if (optr == TSDB_RELATION_IN) { + comparFn = compareFindItemInSet; } else { comparFn = compareLenPrefixedWStr; } diff --git a/src/util/src/terror.c b/src/util/src/terror.c index 42fc76e6c9..49e46cdde8 100644 --- a/src/util/src/terror.c +++ b/src/util/src/terror.c @@ -280,6 +280,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_IN_EXEC, "Multiple retrieval of TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW, "Too many time window in query") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_ENOUGH_BUFFER, "Query buffer limit has reached") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INCONSISTAN, "File inconsistance in replica") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INVALID_TIME_CONDITION, "One valid time range condition expected") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_SYS_ERROR, "System error") diff --git a/tests/pytest/query/queryBetweenAnd.py b/tests/pytest/query/queryBetweenAnd.py index cd4320f523..3d038b3d2f 100644 --- a/tests/pytest/query/queryBetweenAnd.py +++ b/tests/pytest/query/queryBetweenAnd.py @@ -101,7 +101,7 @@ class TDTestCase: # tdSql.query(f"select * from t1 where c2 between {pow(10,38)*3.4} and {pow(10,38)*3.4+1}") # tdSql.checkRows(1) tdSql.query(f"select * from t2 where c2 between {-3.4*10**38-1} and {-3.4*10**38}") - tdSql.checkRows(0) + tdSql.checkRows(2) tdSql.error(f"select * from t2 where c2 between null and {-3.4*10**38}") # tdSql.checkRows(3) @@ -203,4 +203,4 @@ class TDTestCase: tdLog.success(f"{__file__} successfully executed") tdCases.addLinux(__file__, TDTestCase()) -tdCases.addWindows(__file__, TDTestCase()) \ No newline at end of file +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/script/general/parser/condition.sim b/tests/script/general/parser/condition.sim new file mode 100644 index 0000000000..56706467f1 --- /dev/null +++ b/tests/script/general/parser/condition.sim @@ -0,0 +1,111 @@ +system sh/stop_dnodes.sh + +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 1 +system sh/cfg.sh -n dnode1 -c maxtablespervnode -v 4 +system sh/exec.sh -n dnode1 -s start + +sleep 100 +sql connect + +sql drop database if exists cdb +sql create database if not exists cdb +sql use cdb +sql create table stb1 (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(10), t3 double) + +sql create table tb1 using stb1 tags(1,'1',1.0) +sql create table tb2 using stb1 tags(2,'2',2.0) +sql create table tb3 using stb1 tags(3,'3',3.0) +sql create table tb4 using stb1 tags(4,'4',4.0) +sql create table tb5 using stb1 tags(5,'5',5.0) +sql create table tb6 using stb1 tags(6,'6',6.0) + +sql insert into tb1 values ('2021-05-05 18:19:00',1,1.0,1,1,1,1.0,true ,'1','1') +sql insert into tb1 values ('2021-05-05 18:19:01',2,2.0,2,2,2,2.0,true ,'2','2') +sql insert into tb1 values ('2021-05-05 18:19:02',3,3.0,3,3,3,3.0,false,'3','3') +sql insert into tb1 values ('2021-05-05 18:19:03',4,4.0,4,4,4,4.0,false,'4','4') +sql insert into tb1 values ('2021-05-05 18:19:04',11,11.0,11,11,11,11.0,true ,'11','11') +sql insert into tb1 values ('2021-05-05 18:19:05',12,12.0,12,12,12,12.0,true ,'12','12') +sql insert into tb1 values ('2021-05-05 18:19:06',13,13.0,13,13,13,13.0,false,'13','13') +sql insert into tb1 values ('2021-05-05 18:19:07',14,14.0,14,14,14,14.0,false,'14','14') +sql insert into tb2 values ('2021-05-05 18:19:08',21,21.0,21,21,21,21.0,true ,'21','21') +sql insert into tb2 values ('2021-05-05 18:19:09',22,22.0,22,22,22,22.0,true ,'22','22') +sql insert into tb2 values ('2021-05-05 18:19:10',23,23.0,23,23,23,23.0,false,'23','23') +sql insert into tb2 values ('2021-05-05 18:19:11',24,24.0,24,24,24,24.0,false,'24','24') +sql insert into tb3 values ('2021-05-05 18:19:12',31,31.0,31,31,31,31.0,true ,'31','31') +sql insert into tb3 values ('2021-05-05 18:19:13',32,32.0,32,32,32,32.0,true ,'32','32') +sql insert into tb3 values ('2021-05-05 18:19:14',33,33.0,33,33,33,33.0,false,'33','33') +sql insert into tb3 values ('2021-05-05 18:19:15',34,34.0,34,34,34,34.0,false,'34','34') +sql insert into tb4 values ('2021-05-05 18:19:16',41,41.0,41,41,41,41.0,true ,'41','41') +sql insert into tb4 values ('2021-05-05 18:19:17',42,42.0,42,42,42,42.0,true ,'42','42') +sql insert into tb4 values ('2021-05-05 18:19:18',43,43.0,43,43,43,43.0,false,'43','43') +sql insert into tb4 values ('2021-05-05 18:19:19',44,44.0,44,44,44,44.0,false,'44','44') +sql insert into tb5 values ('2021-05-05 18:19:20',51,51.0,51,51,51,51.0,true ,'51','51') +sql insert into tb5 values ('2021-05-05 18:19:21',52,52.0,52,52,52,52.0,true ,'52','52') +sql insert into tb5 values ('2021-05-05 18:19:22',53,53.0,53,53,53,53.0,false,'53','53') +sql insert into tb5 values ('2021-05-05 18:19:23',54,54.0,54,54,54,54.0,false,'54','54') +sql insert into tb6 values ('2021-05-05 18:19:24',61,61.0,61,61,61,61.0,true ,'61','61') +sql insert into tb6 values ('2021-05-05 18:19:25',62,62.0,62,62,62,62.0,true ,'62','62') +sql insert into tb6 values ('2021-05-05 18:19:26',63,63.0,63,63,63,63.0,false,'63','63') +sql insert into tb6 values ('2021-05-05 18:19:27',64,64.0,64,64,64,64.0,false,'64','64') +sql insert into tb6 values ('2021-05-05 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sql create table stb2 (ts timestamp, u1 int unsigned, u2 bigint unsigned, u3 smallint unsigned, u4 tinyint unsigned, ts2 timestamp) TAGS(t1 int unsigned, t2 bigint unsigned, t3 timestamp, t4 int) + +sql create table tb2_1 using stb2 tags(1,1,'2021-05-05 18:38:38',1) +sql create table tb2_2 using stb2 tags(2,2,'2021-05-05 18:58:58',2) + +sql insert into tb2_1 values ('2021-05-05 18:19:00',1,2,3,4,'2021-05-05 18:28:01') +sql insert into tb2_1 values ('2021-05-05 18:19:01',5,6,7,8,'2021-05-05 18:28:02') +sql insert into tb2_1 values ('2021-05-05 18:19:02',2,2,3,4,'2021-05-05 18:28:03') +sql insert into tb2_1 values ('2021-05-05 18:19:03',5,6,7,8,'2021-05-05 18:28:04') +sql insert into tb2_1 values ('2021-05-05 18:19:04',3,2,3,4,'2021-05-05 18:28:05') +sql insert into tb2_1 values ('2021-05-05 18:19:05',5,6,7,8,'2021-05-05 18:28:06') +sql insert into tb2_1 values ('2021-05-05 18:19:06',4,2,3,4,'2021-05-05 18:28:07') +sql insert into tb2_1 values ('2021-05-05 18:19:07',5,6,7,8,'2021-05-05 18:28:08') +sql insert into tb2_1 values ('2021-05-05 18:19:08',5,2,3,4,'2021-05-05 18:28:09') +sql insert into tb2_1 values ('2021-05-05 18:19:09',5,6,7,8,'2021-05-05 18:28:10') +sql insert into tb2_1 values ('2021-05-05 18:19:10',6,2,3,4,'2021-05-05 18:28:11') +sql insert into tb2_2 values ('2021-05-05 18:19:11',5,6,7,8,'2021-05-05 18:28:12') +sql insert into tb2_2 values ('2021-05-05 18:19:12',7,2,3,4,'2021-05-05 18:28:13') +sql insert into tb2_2 values ('2021-05-05 18:19:13',5,6,7,8,'2021-05-05 18:28:14') +sql insert into tb2_2 values ('2021-05-05 18:19:14',8,2,3,4,'2021-05-05 18:28:15') +sql insert into tb2_2 values ('2021-05-05 18:19:15',5,6,7,8,'2021-05-05 18:28:16') + +sql create table stb3 (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int, t2 binary(10), t3 double) + +sql create table tb3_1 using stb3 tags(1,'1',1.0) +sql create table tb3_2 using stb3 tags(2,'2',2.0) + +sql insert into tb3_1 values ('2021-01-05 18:19:00',1,1.0,1,1,1,1.0,true ,'1','1') +sql insert into tb3_1 values ('2021-02-05 18:19:01',2,2.0,2,2,2,2.0,true ,'2','2') +sql insert into tb3_1 values ('2021-03-05 18:19:02',3,3.0,3,3,3,3.0,false,'3','3') +sql insert into tb3_1 values ('2021-04-05 18:19:03',4,4.0,4,4,4,4.0,false,'4','4') +sql insert into tb3_1 values ('2021-05-05 18:19:28',5,NULL,5,NULL,5,NULL,true,NULL,'5') +sql insert into tb3_1 values ('2021-06-05 18:19:28',NULL,6.0,NULL,6,NULL,6.0,NULL,'6',NULL) +sql insert into tb3_1 values ('2021-07-05 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sql insert into tb3_2 values ('2021-01-06 18:19:00',11,11.0,11,11,11,11.0,true ,'11','11') +sql insert into tb3_2 values ('2021-02-06 18:19:01',12,12.0,12,12,12,12.0,true ,'12','12') +sql insert into tb3_2 values ('2021-03-06 18:19:02',13,13.0,13,13,13,13.0,false,'13','13') +sql insert into tb3_2 values ('2021-04-06 18:19:03',14,14.0,14,14,14,14.0,false,'14','14') +sql insert into tb3_2 values ('2021-05-06 18:19:28',15,NULL,15,NULL,15,NULL,true,NULL,'15') +sql insert into tb3_2 values ('2021-06-06 18:19:28',NULL,16.0,NULL,16,NULL,16.0,NULL,'16',NULL) +sql insert into tb3_2 values ('2021-07-06 18:19:28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL) + +sleep 100 + +sql connect + +run general/parser/condition_query.sim + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 100 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sql connect +sleep 100 + +run general/parser/condition_query.sim + diff --git a/tests/script/general/parser/condition_query.sim b/tests/script/general/parser/condition_query.sim new file mode 100644 index 0000000000..7600e510d3 --- /dev/null +++ b/tests/script/general/parser/condition_query.sim @@ -0,0 +1,2628 @@ + +sql use cdb; + +print "column test" +sql select * from stb1 +if $rows != 29 then + return -1 +endi +sql select * from stb1 where c1 > 0 +if $rows != 28 then + return -1 +endi + +sql_error select * from stb1 where c8 > 0 +sql_error select * from stb1 where c7 in (0,2,3,1); +sql_error select * from stb1 where c8 in (true); +sql_error select * from stb1 where c8 in (1,2); +sql_error select * from stb1 where t2 in (3.0); +sql_error select ts,c1,c7 from stb1 where c7 > false +sql_error select * from stb1 where c1 > NULL; +sql_error select * from stb1 where c1 = NULL; +sql_error select * from stb1 where c1 LIKE '%1'; +sql_error select * from stb1 where c2 LIKE '%1'; +sql_error select * from stb1 where c3 LIKE '%1'; +sql_error select * from stb1 where c4 LIKE '%1'; +sql_error select * from stb1 where c5 LIKE '%1'; +sql_error select * from stb1 where c6 LIKE '%1'; +sql_error select * from stb1 where c7 LIKE '%1'; +sql_error select * from stb1 where c1 = 'NULL'; +sql_error select * from stb1 where c2 > 'NULL'; +sql_error select * from stb1 where c3 <> 'NULL'; +sql_error select * from stb1 where c4 != 'null'; +sql_error select * from stb1 where c5 >= 'null'; +sql_error select * from stb1 where c6 <= 'null'; +sql_error select * from stb1 where c7 < 'nuLl'; +sql_error select * from stb1 where c8 < 'nuLl'; +sql_error select * from stb1 where c9 > 'nuLl'; +sql_error select * from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b; +sql_error select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 or b.c1 < 60; +sql_error select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and ((a.c1 > 50 and a.c1 < 60) or (b.c2 > 60)); +sql_error select * from stb1 where 'c2' is null; +sql_error select * from stb1 where 'c2' is not null; + +sql select * from stb1 where c2 > 3.0 or c2 < 60; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c2 > 3.0 or c2 < 60 and c2 > 50; +if $rows != 25 then + return -1 +endi +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50; +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50 and (c2 != 53 and c2 != 63); +if $rows != 6 then + return -1 +endi + +sql select * from stb1 where (c2 > 3.0 or c2 < 60) and c2 > 50 and (c2 != 53 or c2 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c3 > 3.0 or c3 < 60) and c3 > 50 and (c3 != 53 or c3 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c4 > 3.0 or c4 < 60) and c4 > 50 and (c4 != 53 or c4 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c5 > 3.0 or c5 < 60) and c5 > 50 and (c5 != 53 or c5 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where (c6 > 3.0 or c6 < 60) and c6 > 50 and (c6 != 53 or c6 != 63); +if $rows != 8 then + return -1 +endi + +sql select * from stb1 where c8 = '51'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi + +sql select * from stb1 where c8 != '51'; +if $rows != 27 then + return -1 +endi + +#xxx +sql select * from stb1 where c8 = '51' and c8 != '51'; +if $rows != 0 then + return -1 +endi + +#xxx +sql select * from stb1 where c8 = '51' or c8 != '51'; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c9 = '51'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi + +sql select * from stb1 where c9 != '51'; +if $rows != 27 then + return -1 +endi + +sql select * from stb1 where c9 = '51' and c9 != '51'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = '51' or c9 != '51'; +if $rows != 28 then + return -1 +endi + +sql select ts,c1,c7 from stb1 where c7 = false +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data01 != 3 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data11 != 4 then + return -1 +endi +if $data12 != 0 then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data21 != 13 then + return -1 +endi +if $data22 != 0 then + return -1 +endi +if $data30 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data31 != 14 then + return -1 +endi +if $data32 != 0 then + return -1 +endi + + +sql select ts,c1,c7 from stb1 where c7 = true +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data11 != 2 then + return -1 +endi +if $data12 != 1 then + return -1 +endi +if $data20 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data21 != 11 then + return -1 +endi +if $data22 != 1 then + return -1 +endi +if $data30 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data31 != 12 then + return -1 +endi +if $data32 != 1 then + return -1 +endi + + +sql select * from stb1 where c8 = '51' or c8 = '4' +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data01 != 4 then + return -1 +endi +if $data10 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data11 != 51 then + return -1 +endi + + +sql select * from stb1 where c1 > 50 and c1 > 53 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 < 52 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 > 51 and c1 > 54 +if $rows != 4 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 > 51 or c1 > 54 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 and c1 < 51 or c1 > 54 +if $rows != 4 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 and c1 > 54 +if $rows != 5 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 > 51 and c1 < 54 +if $rows != 7 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 and c1 > 53 or c1 < 51 or c1 > 54 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 and c1 < 51 or c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 > 51 and c1 > 54 +if $rows != 8 then + return -1 +endi +sql select * from stb1 where c1 > 50 or c1 > 53 or c1 < 51 or c1 > 54 +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where (c1 > 50 and c1 > 53) and c1 < 52 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 52) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or c1 < 51 +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) +if $rows != 28 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or c1 < 51 +if $rows != 25 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) +if $rows != 5 then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and c1 < 51 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) +if $rows != 8 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) and (c1 < 51 and c1 > 54) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 and c1 < 51 or c1 > 54) +if $rows != 4 then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or (c1 < 51 and c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51 and c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and (c1 < 51 and c1 > 54) +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) and c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53) or (c1 < 51 or c1 > 54) +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51 or c1 > 54) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 and c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 and (c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) and (c1 < 51 or c1 > 54) +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51 or c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 and c1 < 51) or c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 and c1 < 51) or c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or (c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51 and c1 > 54) +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 8 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c1 > 62 or (c1 > 53 or c1 < 51) and c1 > 54 +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53) or (c1 < 51 or c1 > 54) +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51 or c1 > 54) +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 50 or c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select * from stb1 where c1 > 50 or (c1 > 53 or c1 < 51) or c1 > 54 +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +sql select ts,c1 from stb1 where (c1 > 60 or c1 < 10 or (c1 > 20 and c1 < 30)) and ts > '2021-05-05 18:19:00.000' and ts < '2021-05-05 18:19:25.000' and c1 != 21 and c1 != 22 +if $rows != 6 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data31 != 23 then + return -1 +endi +if $data40 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data41 != 24 then + return -1 +endi +if $data50 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data51 != 61 then + return -1 +endi + + +sql select * from stb1 where (c1 > 40 or c1 < 20) and (c2 < 53 or c2 >= 63) and c3 > 1 and c3 < 5 +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi + +sql select * from stb1 where (c1 > 52 or c1 < 10) and (c2 > 1 and c2 < 61) +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data31 != 53 then + return -1 +endi +if $data40 != @21-05-05 18:19:23.000@ then + return -1 +endi +if $data41 != 54 then + return -1 +endi + +sql select * from stb1 where (c3 > 52 or c3 < 10) and (c4 > 1 and c4 < 61) and (c5 = 2 or c6 = 3.0 or c6 = 4.0 or c6 = 53); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data21 != 4 then + return -1 +endi +if $data30 != @21-05-05 18:19:22.000@ then + return -1 +endi +if $data31 != 53 then + return -1 +endi + +sql select * from stb1 where c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c2 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c3 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c4 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c5 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c6 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c7 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c8 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1%' and c8 like '%1'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi + +#xxx +sql select * from stb1 where c8 like '1' and c8 like '2'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi + +sql select * from stb1 where c1 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c2 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c3 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c4 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c5 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c6 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c7 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c8 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c9 is not null; +if $rows != 28 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 1 then + return -1 +endi +sql select * from stb1 where c1 > 63 or c1 is null; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data01 != 64 then + return -1 +endi +if $data10 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null and c3 is not null; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 is null and c2 is null and ts > '2021-05-05 18:19:00.000' and ts < '2021-05-05 18:19:28.000'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 > 0; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is not null or c1 > 1; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 is null or c1 > 40) and c1 < 44; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:17.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:18.000@ then + return -1 +endi + +sql select * from stb1 where c1 in (11,21,31,41) and c1 in (11,42); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where c8 in ('11','21','31','41') and c8 in ('11','42'); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 60 and c2 > 40) or (c1 > 62 and c2 > 50); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 = 3 or c1 = 5 or c1 >= 44 and c1 <= 52; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:19.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select * from stb1 where c8 LIKE '%1'; +if $rows != 7 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where c9 LIKE '%1'; +if $rows != 7 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:24.000@ then + return -1 +endi +sql select * from stb1 where (c8 LIKE '%1' or c9 like '_2') and (c5 > 50 or c6 > 30) and ( c8 like '3_' or c9 like '4_') and (c4 <= 31 or c4 >= 42); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:17.000@ then + return -1 +endi + +sql select * from stb1 where c1 in (1,3); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where c3 in (11,22); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi + +sql select * from stb1 where c4 in (3,33); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) and c8 in ('22','55'); +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) and c8 in ('33','54'); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select * from stb1 where c5 in (3,33) or c8 in ('22','54'); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:14.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:23.000@ then + return -1 +endi + +sql select * from stb1 where (c9 in ('3','1','2','4','5') or c9 in ('33','11','22','44','55')) and c9 in ('1','3','11','13'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb2 where (u1 in (1) or u2 in (5,6)) and (u3 in (3,6) or u4 in (7,8)) and ts2 in ('2021-05-05 18:28:02.000','2021-05-05 18:28:15.000','2021-05-05 18:28:01.000'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi + +sql select * from stb2 where u2 in (2) and u3 in (1,2,3) and u4 in (1,2,4,5) and u1 > 3 and u1 < 6 and u1 != 4; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi + +sql select avg(c1) from tb1 where (c1 > 12 or c2 > 10) and (c3 < 12 or c3 > 13); +if $rows != 1 then + return -1 +endi +if $data00 != 12.500000000 then + return -1 +endi + +sql select count(c1),sum(c3) from tb1 where ((c7 = true and c6 > 2) or (c1 > 10 or c3 < 3)) and ((c8 like '1%') or (c9 like '%2' or c9 like '%3')) interval(5s); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data01 != 3 then + return -1 +endi +if $data02 != 14 then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data12 != 39 then + return -1 +endi + +sql select * from stb1 where c8 = 'null'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c8 = 'NULL'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = 'null'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c9 = 'NULL'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 in (0,1); +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +sql select * from stb1 where c6 in (0,2,3,1); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +sql select ts,c1 from (select * from stb1 where (c1 > 60 or c1 < 10) and (c7 = true or c5 > 2 and c5 < 63)) where (c3 > 61 or c3 < 3); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:25.000@ then + return -1 +endi + +#sql select a.* from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50; +sql select a.ts from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:25.000@ then + return -1 +endi + +#sql select a.ts,a.c1,a.c8,a.c9 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 and b.c1 < 60; +sql select a.ts,a.c1,a.c8 from (select * from stb1 where c7=true) a, (select * from stb1 where c1 > 30) b where a.ts=b.ts and a.c1 > 50 and b.c1 < 60; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:20.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and (a.c1 < 10 or a.c1 > 30) and (b.u1 < 5 or b.u1 > 5); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and a.c1 < 30 and b.u1 > 1 and a.c1 > 10 and b.u1 < 8 and b.u1<>5; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 is not null; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is not null; +if $rows != 29 then + return -1 +endi +sql select * from stb1 where c1 is null or c1 > 20 or c1 < 25; +if $rows != 29 then + return -1 +endi +sql select * from stb1 where (c1 > 20 or c1 < 25) and c1 is null; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where (c1 > 20 or c1 < 25) and (c1 > 62 or c1 < 3); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 11 and c1 != 11 and c1 != 14 and c1 < 14; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi +sql select * from stb1 where (c1 > 60 or c1 < 4 or c1 > 10 and c1 < 20 and c1 != 13 or c1 < 2 or c1 > 50) +if $rows != 14 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:04.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 or c1 >= 62; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 >= 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 >= 62 and c1 != 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 >= 62 or c1 != 62; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 >= 62 and c1 = 62; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 != 62; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 62 and c1 = 62; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c1 is not null and c1 is not null; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 is not null or c1 is not null; +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where c1 is null and c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c1 is null or c1 is null; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c2 > 3 and c2 < 3; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 = 3; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where c2 > 3 and c2 <= 3; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where c2 >= 3 and c2 <= 3; +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where (c2 in (1,2,3,4) or c2 in (11,12,13,14)) and c2 != 11 and c2 >2 and c2 != 14; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 60 or c1 < 4 or c1 > 10 and c1 < 20 and c1 != 13 or c1 < 2 or c1 > 50) and (c1 != 51 and c1 <= 54 and c1 != 54 and c1 >=1 and c1 != 1) and (c1 >= 11 and c1 <=52 and c1 != 52 and c1 != 11); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 1 and c1 is not null and c1 < 5; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select * from (select * from stb1 where c2 > 10 and c6 < 40) where c9 in ('11','21','31'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi + +sql select * from stb1 where c1 > 40 and c2 > 50 and c3 > 62 or c1 < 2 and c2 < 3; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c2 < 30); +if $rows != 28 then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c2 < 30) or (c1 is null and c2 is null); +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 > 3 and c2 > 4) or (c1 < 60 and c3 < 30) or (c1 is null and c2 is null); +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where (c1 > 60 and c2 < 63) or (c1 >62 and c3 < 30) or (c1 is null and c2 is null); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where c1 between 60 and 9999999999; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +sql select * from stb1 where c1 > 9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 < 9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c1 = 9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c1 <> 9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c4 < -9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c4 > -9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c4 = -9999999999; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c4 <> -9999999999; +if $rows != 28 then + return -1 +endi +sql select * from stb1 where c5 in (-9999999999); +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c5 in (9999999999); +if $rows != 0 then + return -1 +endi +sql select * from stb1 where c5 in (-9999999999,3,4,9999999999); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select * from stb3 where c1 > 3 and c1 < 2; +if $rows != 0 then + return -1 +endi + +sql select * from stb3 where c1 is null order by ts; +if $rows != 4 then + return -1 +endi +if $data00 != @21-06-05 18:19:28.000@ then + return -1 +endi +if $data10 != @21-06-06 18:19:28.000@ then + return -1 +endi +if $data20 != @21-07-05 18:19:28.000@ then + return -1 +endi +if $data30 != @21-07-06 18:19:28.000@ then + return -1 +endi + +sql select * from stb3 where c1 is not null order by ts; +if $rows != 10 then + return -1 +endi +if $data00 != @21-01-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-01-06 18:19:00.000@ then + return -1 +endi +if $data20 != @21-02-05 18:19:01.000@ then + return -1 +endi +if $data30 != @21-02-06 18:19:01.000@ then + return -1 +endi +if $data40 != @21-03-05 18:19:02.000@ then + return -1 +endi +if $data50 != @21-03-06 18:19:02.000@ then + return -1 +endi +if $data60 != @21-04-05 18:19:03.000@ then + return -1 +endi +if $data70 != @21-04-06 18:19:03.000@ then + return -1 +endi + + +sql select * from stb3 where c1 > 11; +if $rows != 4 then + return -1 +endi +if $data00 != @21-02-06 18:19:01.000@ then + return -1 +endi +if $data10 != @21-03-06 18:19:02.000@ then + return -1 +endi +if $data20 != @21-04-06 18:19:03.000@ then + return -1 +endi +if $data30 != @21-05-06 18:19:28.000@ then + return -1 +endi + +sql select * from stb3 where c1 is not null or c1 is null; +if $rows != 14 then + return -1 +endi + + + +print "ts test" +sql_error select ts,c1,c7 from stb1 where ts != '2021-05-05 18:19:27' +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts < '2021-05-05 18:19:02.000'; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:20.000' and ts != '2021-05-05 18:19:22.000'; +sql_error select * from stb1 where ts2 like '2021-05-05%'; +sql_error select ts,c1,c2 from stb1 where (ts > '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:05.000') and ts > '2021-05-05 18:19:01.000' and ts < '2021-05-05 18:19:27.000'; +sql_error select ts,c1,c2 from stb1 where (ts > '2021-05-05 18:19:20.000' or ts < '2021-05-05 18:19:05.000') and ts != '2021-05-05 18:19:25.000'; +sql_error select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:15.000' and ts <= '2021-05-05 18:19:20.000') or (ts >= '2021-05-05 18:19:11.000' and ts <= '2021-05-05 18:19:14.000')); +sql_error select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:24.000'; +sql select * from stb1 where ts is null; +if $rows != 0 then + return -1 +endi +sql select * from stb1 where ts is not null and ts is null; +if $rows != 0 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' and ts < '2021-05-05 18:19:10.000'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:02'; +if $rows != 0 then + return -1 +endi + +sql select * from stb1 where ts is not null; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where ts is not null or ts is null; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' and ts < '2021-05-05 18:19:26.000'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts < '2021-05-05 18:19:28.000'; +if $rows != 29 then + return -1 +endi +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts > '2021-05-05 18:19:27.000'; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts > '2021-05-05 18:19:20.000' or ts < '2021-05-05 18:19:05.000' or ts != '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ts >= '2021-05-05 18:19:25.000' or ts <> '2021-05-05 18:19:25.000'; +if $rows != 29 then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.999') or (ts >= '2021-05-05 18:19:15.000' and ts <= '2021-05-05 18:19:20.000') or (ts >= '2021-05-05 18:19:11.000' and ts <= '2021-05-05 18:19:14.999')); +if $rows != 16 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:12.000' and ts <= '2021-05-05 18:19:14.000') or (ts >= '2021-05-05 18:19:08.000' and ts <= '2021-05-05 18:19:17.000'); +if $rows != 13 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:03.000') or (ts >= '2021-05-05 18:19:01.000' and ts <= '2021-05-05 18:19:08.000'); +if $rows != 10 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi + +sql select ts,c1,c2 from stb1 where ((ts >= '2021-05-05 18:19:08.000' and ts <= '2021-05-05 18:19:10.000') or (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:03.000') or (ts >= '2021-05-05 18:19:05.000' and ts <= '2021-05-05 18:19:06.000') or (ts >= '2021-05-05 18:19:03.000' and ts <= '2021-05-05 18:19:12.000')) and (ts >= '2021-05-05 18:19:10.000'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:12.000@ then + return -1 +endi + +sql select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:25.000' and ts != '2021-05-05 18:19:18'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts > '2021-05-05 18:19:25'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:28.000@ then + return -1 +endi + +sql select * from stb1 where ts < '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:25'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:23.000' and ts < '2021-05-05 18:19:25'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:25'; +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select * from stb1 where ts < '2021-05-05 18:19:03.000' or ts < '2021-05-05 18:19:25'; +if $rows != 25 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25'; +if $rows != 29 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi + +sql select * from stb1 where (ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25') and (ts > '2021-05-05 18:19:23.000' and ts < '2021-05-05 18:19:26'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi + +sql select * from stb1 where (ts > '2021-05-05 18:19:23.000' or ts < '2021-05-05 18:19:25') and (ts > '2021-05-05 18:19:23.000' or ts > '2021-05-05 18:19:26'); +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:26.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:28.000@ then + return -1 +endi + + +sql select * from stb2 where ts2 in ('2021-05-05 18:28:03','2021-05-05 18:28:05','2021-05-05 18:28:08'); +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select * from stb2 where t3 in ('2021-05-05 18:38:38','2021-05-05 18:38:28','2021-05-05 18:38:08') and ts2 in ('2021-05-05 18:28:04','2021-05-05 18:28:04','2021-05-05 18:28:03'); +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi + +sql select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and (a.ts < '2021-05-05 18:19:03.000' or a.ts >= '2021-05-05 18:19:13.000') and (b.ts >= '2021-05-05 18:19:01.000' and b.ts <= '2021-05-05 18:19:14.000'); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select a.ts,c.ts,b.c1,c.u1,c.u2 from (select * from stb1) a, (select * from stb1) b, (select * from stb2) c where a.ts=b.ts and b.ts=c.ts and a.ts <= '2021-05-05 18:19:12.000' and b.ts >= '2021-05-05 18:19:06.000' and c.ts >= '2021-05-05 18:19:08.000' and c.ts <= '2021-05-05 18:19:11.000' and a.ts != '2021-05-05 18:19:10.000'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select ts,c1,c2,c8 from (select * from stb1) where (ts <= '2021-05-05 18:19:06.000' or ts >= '2021-05-05 18:19:13.000') and (ts >= '2021-05-05 18:19:02.000' and ts <= '2021-05-05 18:19:14.000') and ts != '2021-05-05 18:19:04.000'; +if $rows != 6 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:14.000@ then + return -1 +endi + +sql select ts,c1,c2,c8 from (select * from stb1) where (ts <= '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:26.000' or ts = '2021-05-05 18:19:26.000') and ts != '2021-05-05 18:19:03.000' and ts != '2021-05-05 18:19:26.000'; +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:27.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:28.000@ then + return -1 +endi + +print "tbname test" +sql_error select * from stb1 where tbname like '%3' and tbname like '%4'; + +sql select * from stb1 where tbname like 'tb%'; +if $rows != 29 then + return -1 +endi + +sql select * from stb1 where tbname like '%2'; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:11.000@ then + return -1 +endi + +print "tag test" +sql select * from stb1 where t1 in (1,2) and t1 in (2,3); +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:08.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:09.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:10.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select * from stb2 where t1 in (1,2) and t2 in (2) and t3 in ('2021-05-05 18:58:57.000'); +if $rows != 0 then + return -1 +endi + +print "join test" +sql_error select * from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.ts =tb2_1.ts; +sql select tb1.ts from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts > '2021-05-05 18:19:03.000' and tb2_1.ts < '2021-05-05 18:19:06.000'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:05.000@ then + return -1 +endi +sql select tb1.ts,tb1.*,tb2_1.* from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts > '2021-05-05 18:19:03.000' and tb2_1.u1 < 5; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:06.000@ then + return -1 +endi + +sql select tb1.ts,tb1.*,tb2_1.* from tb1, tb2_1 where tb1.ts=tb2_1.ts and tb1.ts >= '2021-05-05 18:19:03.000' and tb1.c7=false and tb2_1.u3>4; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:07.000@ then + return -1 +endi + +sql select stb1.ts,stb1.c1,stb1.t1,stb2.ts,stb2.u1,stb2.t4 from stb1, stb2 where stb1.ts=stb2.ts and stb1.t1 = stb2.t4; +if $rows != 9 then + return -1 +endi +if $data00 != @21-05-05 18:19:00.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:01.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:03.000@ then + return -1 +endi +if $data40 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data50 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data60 != @21-05-05 18:19:06.000@ then + return -1 +endi +if $data70 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data80 != @21-05-05 18:19:11.000@ then + return -1 +endi + +sql select stb1.ts,stb1.c1,stb1.t1,stb2.ts,stb2.u1,stb2.t4 from stb1, stb2 where stb1.ts=stb2.ts and stb1.t1 = stb2.t4 and stb1.c1 > 2 and stb2.u1 <=4; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:02.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:04.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:06.000@ then + return -1 +endi + +print "column&ts test" +sql_error select count(*) from stb1 where ts > 0 or c1 > 0; +sql select * from stb1 where ts > '2021-05-05 18:19:03.000' and ts < '2021-05-05 18:19:20.000' and (c1 > 23 or c1 < 14) and c7 in (true) and c8 like '%2'; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:05.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:17.000@ then + return -1 +endi + +print "column&tbname test" +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0; +sql select * from stb1 where tbname like '%3' and c6 < 34 and c5 != 33 and c4 > 31; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:13.000@ then + return -1 +endi + +print "column&tag test" +sql_error select * from stb1 where t1 > 0 or c1 > 0 +sql_error select * from stb1 where c1 > 0 or t1 > 0 +sql_error select * from stb1 where t1 > 0 or c1 > 0 or t1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 or c1 > 1 +sql_error select * from stb1 where t1 > 0 and c1 > 0 or t1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where c1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where t1 > 0 or t1 > 0 and c1 > 1 +sql_error select * from stb1 where (c1 > 0 and t1 > 0 ) or (t1 > 1 and c1 > 3) +sql_error select * from stb1 where (c1 > 0 and t1 > 0 ) or t1 > 1 +sql_error select a.ts,b.ts,a.c1,b.u1,b.u2 from (select * from stb1) a, (select * from stb2) b where a.ts=b.ts and a.t1=b.t1; + +sql select * from stb1 where c1 < 63 and t1 > 5 +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:24.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:25.000@ then + return -1 +endi +sql select * from stb1 where t1 > 3 and t1 < 5 and c1 != 42 and c1 != 44; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:16.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:18.000@ then + return -1 +endi +sql select * from stb1 where t1 > 1 and c1 > 21 and t1 < 3 and c1 < 24 and t1 != 3 and c1 != 23; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:09.000@ then + return -1 +endi +sql select * from stb1 where c1 > 1 and (t1 > 3 or t1 < 2) and (c2 > 2 and c2 < 62 and t1 != 4) and (t1 > 2 and t1 < 6) and c7 = true and c8 like '%2'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:21.000@ then + return -1 +endi + +sql select * from stb1 where c1!=31 and c1 !=32 and c1 <> 63 and c1 <>1 and c1 <> 21 and c1 <> 2 and c7 <> true and c8 <> '3' and c9 <> '4' and c2<>13 and c3 <> 23 and c4 <> 33 and c5 <> 34 and c6 <> 43 and c2 <> 53 and t1 <> 5 and t2 <>4; +if $rows != 3 then + return -1 +endi +if $data00 != @21-05-05 18:19:07.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:27.000@ then + return -1 +endi + + +print "column&join test" +sql_error select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.c1 > 0; + + +print "ts&tbname test" +sql_error select count(*) from stb1 where ts > 0 or tbname like 'tb%'; + +print "ts&tag test" +sql_error select count(*) from stb1 where ts > 0 or t1 > 0; + +sql select * from stb2 where t1!=1 and t2=2 and t3 in ('2021-05-05 18:58:58.000') and ts < '2021-05-05 18:19:13.000'; +if $rows != 2 then + return -1 +endi +if $data00 != @21-05-05 18:19:11.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:12.000@ then + return -1 +endi + +print "ts&join test" +sql_error select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts or tb1.ts > 0; +sql select tb1.ts,tb1.c1,tb2_1.u1 from tb1, tb2_1 where tb1.ts=tb2_1.ts and (tb1.ts > '2021-05-05 18:19:05.000' or tb1.ts < '2021-05-05 18:19:03.000' or tb1.ts > 0); + + +print "tbname&tag test" +sql select * from stb1 where tbname like 'tb%' and (t1=1 or t2=2 or t3=3) and t1 > 2; +if $rows != 4 then + return -1 +endi +if $data00 != @21-05-05 18:19:12.000@ then + return -1 +endi +if $data10 != @21-05-05 18:19:13.000@ then + return -1 +endi +if $data20 != @21-05-05 18:19:14.000@ then + return -1 +endi +if $data30 != @21-05-05 18:19:15.000@ then + return -1 +endi + +print "tbname&join test" + +print "tag&join test" + + + + + +print "column&ts&tbname test" +sql_error select count(*) from stb1 where tbname like 'tb%' or c1 > 0 or ts > 0; + +print "column&ts&tag test" +sql_error select count(*) from stb1 where t1 > 0 or c1 > 0 or ts > 0; +sql_error select count(*) from stb1 where c1 > 0 or t1 > 0 or ts > 0; + +sql select * from stb1 where (t1 > 0 or t1 > 2 ) and ts > '2021-05-05 18:19:10.000' and (c1 > 1 or c1 > 3) and (c6 > 40 or c6 < 30) and (c8 like '%3' or c8 like '_4') and (c9 like '1%' or c9 like '6%' or (c9 like '%3' and c9 != '23')) and ts > '2021-05-05 18:19:22.000' and ts <= '2021-05-05 18:19:26.000'; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:26.000@ then + return -1 +endi +sql select * from stb1 where ts > '2021-05-05 18:19:00.000' and c1 > 2 and t1 != 1 and c2 >= 23 and t2 >= 3 and c3 < 63 and c7 = false and t3 > 3 and t3 < 6 and c8 like '4%' and ts < '2021-05-05 18:19:19.000' and c2 > 40 and c3 != 42; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-05 18:19:18.000@ then + return -1 +endi +print "column&ts&join test" + +print "column&tbname&tag test" +sql_error select count(*) from stb1 where c1 > 0 or tbname in ('tb1') or t1 > 0; + +print "column&tbname&join test" +print "column&tag&join test" +print "ts&tbname&tag test" +sql_error select count(*) from stb1 where ts > 0 or tbname in ('tb1') or t1 > 0; + +print "ts&tbname&join test" +print "ts&tag&join test" +print "tbname&tag&join test" + + + + +print "column&ts&tbname&tag test" +sql_error select * from stb1 where (tbname like 'tb%' or ts > '2021-05-05 18:19:01.000') and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select * from stb1 where (ts > '2021-05-05 18:19:01.000') and (ts > '2021-05-05 18:19:02.000' or t1 > 3) and (t1 > 5 or t1 < 4) and c1 > 0; +sql_error select ts,c1,c7 from stb1 where ts > '2021-05-05 18:19:03.000' or ts > '2021-05-05 18:19:20.000' and col > 0 and t1 > 0; + + +print "column&ts&tbname&join test" +print "column&ts&tag&join test" +print "column&tbname&tag&join test" +print "ts&tbname&tag&join test" + + +print "column&ts&tbname&tag&join test" + +#system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/set_tag_vals.sim b/tests/script/general/parser/set_tag_vals.sim index 74184f94d4..4a63f9c6f1 100644 --- a/tests/script/general/parser/set_tag_vals.sim +++ b/tests/script/general/parser/set_tag_vals.sim @@ -83,10 +83,7 @@ while $i < $tbNum endw print ================== all tags have been changed! -sql select tbname from $stb where t3 = 'NULL' -if $rows != 0 then - return -1 -endi +sql_error select tbname from $stb where t3 = 'NULL' print ================== set tag to NULL sql create table stb1_tg (ts timestamp, c1 int) tags(t1 int,t2 bigint,t3 double,t4 float,t5 smallint,t6 tinyint) @@ -227,4 +224,4 @@ if $data04 != NULL then return -1 endi -system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/where.sim b/tests/script/general/parser/where.sim index 781b2725b5..6b789de490 100644 --- a/tests/script/general/parser/where.sim +++ b/tests/script/general/parser/where.sim @@ -65,7 +65,14 @@ $tb = $tbPrefix . $i sql_error select * from $tb where c7 # TBASE-654 : invalid filter expression cause server crashed -sql_error select count(*) from $tb where c1<10 and c1<>2 +sql select count(*) from $tb where c1<10 and c1<>2 +if $rows != 1 then + return -1 +endi +if $data00 != 900 then + return -1 +endi + sql select * from $tb where c7 = false $val = $rowNum / 100 @@ -253,30 +260,11 @@ sql insert into tb_where_NULL values ('2019-01-01 09:00:02.000', 2, 'val2') sql_error select * from tb_where_NULL where c1 = NULL sql_error select * from tb_where_NULL where c1 <> NULL sql_error select * from tb_where_NULL where c1 < NULL -sql select * from tb_where_NULL where c1 = "NULL" -if $rows != 0 then - return -1 -endi - -sql select * from tb_where_NULL where c1 <> "NULL" -if $rows != 2 then - return -1 -endi -sql select * from tb_where_NULL where c1 <> "nulL" -if $rows != 2 then - return -1 -endi - -sql select * from tb_where_NULL where c1 > "NULL" -if $rows != 0 then - return -1 -endi - -sql select * from tb_where_NULL where c1 >= "NULL" -if $rows != 0 then - return -1 -endi - +sql_error select * from tb_where_NULL where c1 = "NULL" +sql_error select * from tb_where_NULL where c1 <> "NULL" +sql_error select * from tb_where_NULL where c1 <> "nulL" +sql_error select * from tb_where_NULL where c1 > "NULL" +sql_error select * from tb_where_NULL where c1 >= "NULL" sql select * from tb_where_NULL where c2 = "NULL" if $rows != 0 then return -1 diff --git a/tests/script/test.sh b/tests/script/test.sh index 29a15db4dc..f2dc578987 100755 --- a/tests/script/test.sh +++ b/tests/script/test.sh @@ -121,6 +121,7 @@ echo "rpcDebugFlag 143" >> $TAOS_CFG echo "tmrDebugFlag 131" >> $TAOS_CFG echo "cDebugFlag 143" >> $TAOS_CFG echo "udebugFlag 143" >> $TAOS_CFG +echo "debugFlag 143" >> $TAOS_CFG echo "wal 0" >> $TAOS_CFG echo "asyncLog 0" >> $TAOS_CFG echo "locale en_US.UTF-8" >> $TAOS_CFG