diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 451c2f291e..d2cdb123bc 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -80,6 +80,7 @@ typedef struct SColumnNode { uint16_t projIdx; // the idx in project list, start from 1 EColumnType colType; // column or tag bool hasIndex; + bool isPrimTs; char dbName[TSDB_DB_NAME_LEN]; char tableName[TSDB_TABLE_NAME_LEN]; char tableAlias[TSDB_TABLE_NAME_LEN]; @@ -210,6 +211,7 @@ typedef struct SViewNode { #define JOIN_JLIMIT_MAX_VALUE 1024 #define IS_INNER_NONE_JOIN(_type, _stype) ((_type) == JOIN_TYPE_INNER && (_stype) == JOIN_STYPE_NONE) +#define IS_SEMI_JOIN(_stype) ((_stype) == JOIN_STYPE_SEMI) #define IS_WINDOW_JOIN(_stype) ((_stype) == JOIN_STYPE_WIN) #define IS_ASOF_JOIN(_stype) ((_stype) == JOIN_STYPE_ASOF) @@ -329,6 +331,7 @@ typedef enum EFillMode { typedef enum ETimeLineMode { TIME_LINE_NONE = 1, + TIME_LINE_BLOCK, TIME_LINE_MULTI, TIME_LINE_GLOBAL, } ETimeLineMode; @@ -416,6 +419,7 @@ typedef struct SSelectStmt { bool onlyHasKeepOrderFunc; bool groupSort; bool tagScan; + bool joinContains; } SSelectStmt; typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType; @@ -431,6 +435,7 @@ typedef struct SSetOperator { char stmtName[TSDB_TABLE_NAME_LEN]; uint8_t precision; ETimeLineMode timeLineResMode; + bool joinContains; } SSetOperator; typedef enum ESqlClause { diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 2ac2c3ccbd..7ae393f5a6 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -158,6 +158,7 @@ int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray); SArray* serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap); SArray* serializeVgroupsDropTableBatch(SHashObj* pVgroupHashmap); void destoryCatalogReq(SCatalogReq *pCatalogReq); +bool isPrimaryKeyImpl(SNode* pExpr); #ifdef __cplusplus } diff --git a/include/util/taoserror.h b/include/util/taoserror.h index fe4b474e98..0adf0f062d 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -762,6 +762,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_GRP_WINDOW_NOT_ALLOWED TAOS_DEF_ERROR_CODE(0, 0x2671) #define TSDB_CODE_PAR_INVALID_WJOIN_HAVING_EXPR TAOS_DEF_ERROR_CODE(0, 0x2672) #define TSDB_CODE_PAR_INVALID_WIN_OFFSET_UNIT TAOS_DEF_ERROR_CODE(0, 0x2673) +#define TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED TAOS_DEF_ERROR_CODE(0, 0x2674) #define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF) //planner diff --git a/source/libs/executor/inc/mergejoin.h b/source/libs/executor/inc/mergejoin.h index b8d99047d7..6a8df55dc9 100755 --- a/source/libs/executor/inc/mergejoin.h +++ b/source/libs/executor/inc/mergejoin.h @@ -19,7 +19,7 @@ extern "C" { #endif -#if 1 +#if 0 #define MJOIN_DEFAULT_BLK_ROWS_NUM 2 //4096 #define MJOIN_HJOIN_CART_THRESHOLD 10 #define MJOIN_BLK_SIZE_LIMIT 0 //10485760 diff --git a/source/libs/executor/src/mergejoinoperator.c b/source/libs/executor/src/mergejoinoperator.c index acf0b6e622..b8df782cd9 100644 --- a/source/libs/executor/src/mergejoinoperator.c +++ b/source/libs/executor/src/mergejoinoperator.c @@ -799,7 +799,7 @@ static int32_t mJoinInitPrimExprCtx(SNode* pNode, SMJoinPrimExprCtx* pCtx, SMJoi pCtx->truncateUnit = pUnit->typeData; if ((NULL == pCurrTz || 1 == pCurrTz->typeData) && pCtx->truncateUnit >= (86400 * TSDB_TICK_PER_SECOND(pFunc->node.resType.precision))) { - pCtx->timezoneUnit = offsetFromTz(pTimeZone->datum.p, TSDB_TICK_PER_SECOND(pFunc->node.resType.precision)); + pCtx->timezoneUnit = offsetFromTz(varDataVal(pTimeZone->datum.p), TSDB_TICK_PER_SECOND(pFunc->node.resType.precision)); } pCtx->targetSlotId = pTarget->slotId; diff --git a/source/libs/executor/test/joinTests.cpp b/source/libs/executor/test/joinTests.cpp index 6186367e1b..d1fd8c2d30 100755 --- a/source/libs/executor/test/joinTests.cpp +++ b/source/libs/executor/test/joinTests.cpp @@ -66,7 +66,7 @@ enum { }; #define COL_DISPLAY_WIDTH 18 -#define JT_MAX_LOOP 5000 +#define JT_MAX_LOOP 10000 #define LEFT_BLK_ID 0 #define RIGHT_BLK_ID 1 @@ -101,6 +101,7 @@ typedef struct { bool printInputRow; bool printResRow; bool logHistory; + bool noKeepResRows; } SJoinTestCtrl; @@ -181,6 +182,8 @@ typedef struct { SArray* leftRowsList; SArray* rightRowsList; SArray* rightFilterOut; + + int64_t startTsUs; } SJoinTestCtx; typedef struct { @@ -203,7 +206,7 @@ typedef struct { SJoinTestCtx jtCtx = {0}; -SJoinTestCtrl jtCtrl = {1, 1, 1, 0}; +SJoinTestCtrl jtCtrl = {1, 1, 1, 0, 0}; SJoinTestStat jtStat = {0}; SJoinTestResInfo jtRes = {0}; @@ -245,13 +248,15 @@ void printResRow(char* value, int32_t type) { void pushResRow(char* buf, int32_t size) { jtCtx.resRows++; - - int32_t* rows = (int32_t*)tSimpleHashGet(jtCtx.jtResRows, buf, size); - if (rows) { - (*rows)++; - } else { - int32_t n = 1; - tSimpleHashPut(jtCtx.jtResRows, buf, size, &n, sizeof(n)); + + if (!jtCtrl.noKeepResRows) { + int32_t* rows = (int32_t*)tSimpleHashGet(jtCtx.jtResRows, buf, size); + if (rows) { + (*rows)++; + } else { + int32_t n = 1; + tSimpleHashPut(jtCtx.jtResRows, buf, size, &n, sizeof(n)); + } } } @@ -915,22 +920,24 @@ void appendAsofLeftEachResGrps(char* leftInRow, int32_t rightOffset, int32_t rig } void appendLeftNonMatchGrp(char* leftInRow) { - memset(jtCtx.resColBuf, 0, jtCtx.resColSize); - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (!jtCtx.resColList[c]) { - continue; + if (!jtCtrl.noKeepResRows) { + memset(jtCtx.resColBuf, 0, jtCtx.resColSize); + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (!jtCtx.resColList[c]) { + continue; + } + + if (*((bool*)leftInRow + c)) { + *(char*)(jtCtx.resColBuf + c) = true; + } else { + memcpy(jtCtx.resColBuf + jtCtx.resColOffset[c], leftInRow + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes); + } } - - if (*((bool*)leftInRow + c)) { - *(char*)(jtCtx.resColBuf + c) = true; - } else { - memcpy(jtCtx.resColBuf + jtCtx.resColOffset[c], leftInRow + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes); - } - } - - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (jtCtx.resColList[MAX_SLOT_NUM + c]) { - *(char*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true; + + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (jtCtx.resColList[MAX_SLOT_NUM + c]) { + *(char*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true; + } } } @@ -1390,21 +1397,23 @@ void makeAppendBlkData(SSDataBlock** ppLeft, SSDataBlock** ppRight, int32_t left } void putNMatchRowToRes(char* lrow, int32_t tableOffset, int32_t peerOffset) { - memset(jtCtx.resColBuf, 0, jtCtx.resColSize); + if (!jtCtrl.noKeepResRows) { + memset(jtCtx.resColBuf, 0, jtCtx.resColSize); - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (jtCtx.resColList[tableOffset + c]) { - if (*(bool*)(lrow + c)) { - *(bool*)(jtCtx.resColBuf + tableOffset + c) = true; - } else { - memcpy(jtCtx.resColBuf + jtCtx.resColOffset[tableOffset + c], lrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (jtCtx.resColList[tableOffset + c]) { + if (*(bool*)(lrow + c)) { + *(bool*)(jtCtx.resColBuf + tableOffset + c) = true; + } else { + memcpy(jtCtx.resColBuf + jtCtx.resColOffset[tableOffset + c], lrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + } } } - } - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (jtCtx.resColList[peerOffset + c]) { - *(bool*)(jtCtx.resColBuf + peerOffset + c) = true; + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (jtCtx.resColList[peerOffset + c]) { + *(bool*)(jtCtx.resColBuf + peerOffset + c) = true; + } } } @@ -1412,27 +1421,29 @@ void putNMatchRowToRes(char* lrow, int32_t tableOffset, int32_t peerOffset) { } void putMatchRowToRes(char* lrow, char* rrow, int32_t cols) { - memset(jtCtx.resColBuf, 0, jtCtx.resColSize); + if (!jtCtrl.noKeepResRows) { + memset(jtCtx.resColBuf, 0, jtCtx.resColSize); - if (cols & LEFT_TABLE_COLS) { - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (jtCtx.resColList[c]) { - if (*(bool*)(lrow + c)) { - *(bool*)(jtCtx.resColBuf + c) = true; - } else { - memcpy(jtCtx.resColBuf + jtCtx.resColOffset[c], lrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + if (cols & LEFT_TABLE_COLS) { + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (jtCtx.resColList[c]) { + if (*(bool*)(lrow + c)) { + *(bool*)(jtCtx.resColBuf + c) = true; + } else { + memcpy(jtCtx.resColBuf + jtCtx.resColOffset[c], lrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + } } } } - } - if (cols & RIGHT_TABLE_COLS) { - for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { - if (jtCtx.resColList[MAX_SLOT_NUM + c]) { - if (*(bool*)(rrow + c)) { - *(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true; - } else { - memcpy(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], rrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + if (cols & RIGHT_TABLE_COLS) { + for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) { + if (jtCtx.resColList[MAX_SLOT_NUM + c]) { + if (*(bool*)(rrow + c)) { + *(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true; + } else { + memcpy(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], rrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes); + } } } } @@ -2636,13 +2647,14 @@ void printActualResInfo() { } printf("Actual Result Summary:\n\t blkNum:%d\n\t rowNum:%d%s\n\t leftBlkRead:%d\n\t rightBlkRead:%d\n\t +rows:%d%s\n\t " - "-rows:%d%s\n\t matchRows:%d%s\n", + "-rows:%d%s\n\t matchRows:%d%s\n\t executionTime:%" PRId64 "us\n", jtRes.blkNum, jtRes.rowNum, jtRes.rowNum == jtCtx.resRows ? "" : "*", jtCtx.leftBlkReadIdx, jtCtx.rightBlkReadIdx, jtRes.addRowNum, jtRes.addRowNum ? "*" : "", jtRes.subRowNum, jtRes.subRowNum ? "*" : "", - jtRes.matchNum, jtRes.matchNum == jtCtx.resRows ? "" : "*"); + jtRes.matchNum, jtRes.matchNum == jtCtx.resRows ? "" : "*", + taosGetTimestampUs() - jtCtx.startTsUs); } void printStatInfo(char* caseName) { @@ -2655,12 +2667,14 @@ void checkJoinDone(char* caseName) { int32_t iter = 0; void* p = NULL; void* key = NULL; - while (NULL != (p = tSimpleHashIterate(jtCtx.jtResRows, p, &iter))) { - key = tSimpleHashGetKey(p, NULL); - jtRes.succeed = false; - jtRes.subRowNum += *(int32_t*)p; - for (int32_t i = 0; i < *(int32_t*)p; ++i) { - printResRow((char*)key, 0); + if (!jtCtrl.noKeepResRows) { + while (NULL != (p = tSimpleHashIterate(jtCtx.jtResRows, p, &iter))) { + key = tSimpleHashGetKey(p, NULL); + jtRes.succeed = false; + jtRes.subRowNum += *(int32_t*)p; + for (int32_t i = 0; i < *(int32_t*)p; ++i) { + printResRow((char*)key, 0); + } } } @@ -2712,25 +2726,29 @@ void checkJoinRes(SSDataBlock* pBlock) { } jtStat.totalResRows += pBlock->info.rows; - for (int32_t r = 0; r < pBlock->info.rows; ++r) { - memset(jtCtx.resColBuf, 0, jtCtx.resColSize); + if (jtCtrl.noKeepResRows) { + jtRes.matchNum += pBlock->info.rows; + } else { + for (int32_t r = 0; r < pBlock->info.rows; ++r) { + memset(jtCtx.resColBuf, 0, jtCtx.resColSize); - putRowToResColBuf(pBlock, r, true); - - char* value = (char*)tSimpleHashGet(jtCtx.jtResRows, jtCtx.resColBuf, jtCtx.resColSize); - if (NULL == value) { + putRowToResColBuf(pBlock, r, true); + + char* value = (char*)tSimpleHashGet(jtCtx.jtResRows, jtCtx.resColBuf, jtCtx.resColSize); + if (NULL == value) { + putRowToResColBuf(pBlock, r, false); + printResRow(jtCtx.resColBuf, 1); + jtRes.succeed = false; + jtRes.addRowNum++; + continue; + } + + rmResRow(); + putRowToResColBuf(pBlock, r, false); - printResRow(jtCtx.resColBuf, 1); - jtRes.succeed = false; - jtRes.addRowNum++; - continue; + printResRow(jtCtx.resColBuf, 2); + jtRes.matchNum++; } - - rmResRow(); - - putRowToResColBuf(pBlock, r, false); - printResRow(jtCtx.resColBuf, 2); - jtRes.matchNum++; } } @@ -2840,14 +2858,15 @@ void runSingleTest(char* caseName, SJoinTestParam* param) { bool contLoop = true; SSortMergeJoinPhysiNode* pNode = createDummySortMergeJoinPhysiNode(param); - createDummyBlkList(100, 10, 100, 10, 10); + createDummyBlkList(10, 10, 10, 10, 3); while (contLoop) { rerunBlockedHere(); resetForJoinRerun(2, pNode, param->pTask); printBasicInfo(caseName); printOutputInfo(); - + + jtCtx.startTsUs = taosGetTimestampUs(); while (true) { SSDataBlock* pBlock = jtCtx.pJoinOp->fpSet.getNextFn(jtCtx.pJoinOp); if (NULL == pBlock) { @@ -2872,7 +2891,7 @@ void handleCaseEnd() { } // namespace -#if 1 +#if 0 #if 1 TEST(innerJoin, noCondTest) { SJoinTestParam param; @@ -2983,7 +3002,7 @@ TEST(innerJoin, fullCondTest) { #endif -#if 1 +#if 0 #if 1 TEST(leftOuterJoin, noCondTest) { SJoinTestParam param; @@ -3094,7 +3113,7 @@ TEST(leftOuterJoin, fullCondTest) { #endif #endif -#if 1 +#if 0 #if 1 TEST(fullOuterJoin, noCondTest) { SJoinTestParam param; @@ -3205,7 +3224,7 @@ TEST(fullOuterJoin, fullCondTest) { #endif #endif -#if 1 +#if 0 #if 1 TEST(leftSemiJoin, noCondTest) { SJoinTestParam param; @@ -3316,7 +3335,7 @@ TEST(leftSemiJoin, fullCondTest) { #endif #endif -#if 1 +#if 0 #if 1 TEST(leftAntiJoin, noCondTest) { SJoinTestParam param; @@ -3427,7 +3446,7 @@ TEST(leftAntiJoin, fullCondTest) { #endif #endif -#if 1 +#if 0 #if 1 TEST(leftAsofJoin, noCondGreaterThanTest) { SJoinTestParam param; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 1705b9da48..99927ed889 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -113,6 +113,7 @@ static int32_t columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) { COPY_SCALAR_FIELD(projIdx); COPY_SCALAR_FIELD(colType); COPY_SCALAR_FIELD(hasIndex); + COPY_SCALAR_FIELD(isPrimTs); COPY_CHAR_ARRAY_FIELD(dbName); COPY_CHAR_ARRAY_FIELD(tableName); COPY_CHAR_ARRAY_FIELD(tableAlias); diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index 828396c9aa..e8b0b53dd6 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -761,6 +761,7 @@ static SNode* createPrimaryKeyCol(SAstCreateContext* pCxt, const SToken* pFuncNa } else { strncpy(pCol->colName, pFuncName->z, pFuncName->n); } + pCol->isPrimTs = true; return (SNode*)pCol; } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 0392d486e0..912fc373c5 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -897,14 +897,14 @@ static bool isTimeLineAlignedQuery(SNode* pStmt) { return false; } -static bool isPrimaryKeyImpl(SNode* pExpr) { +bool isPrimaryKeyImpl(SNode* pExpr) { if (QUERY_NODE_COLUMN == nodeType(pExpr)) { - return (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId); + return ((PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId) && ((SColumnNode*)pExpr)->isPrimTs); } else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) { SFunctionNode* pFunc = (SFunctionNode*)pExpr; if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType || FUNCTION_TYPE_GROUP_KEY == pFunc->funcType || FUNCTION_TYPE_FIRST == pFunc->funcType || FUNCTION_TYPE_LAST == pFunc->funcType || - FUNCTION_TYPE_LAST_ROW == pFunc->funcType) { + FUNCTION_TYPE_LAST_ROW == pFunc->funcType || FUNCTION_TYPE_TIMETRUNCATE == pFunc->funcType) { return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0)); } else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType || FUNCTION_TYPE_IROWTS == pFunc->funcType) { @@ -969,7 +969,8 @@ static void setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColum taosArrayPush(pExpr->pAssociation, &assNode); strcpy(pCol->tableAlias, pTable->table.tableAlias); - pCol->colId = isPrimaryKey(pTable, (SNode*)pExpr) ? PRIMARYKEY_TIMESTAMP_COL_ID : 0; + pCol->isPrimTs = isPrimaryKey(pTable, (SNode*)pExpr); + pCol->colId = pCol->isPrimTs ? PRIMARYKEY_TIMESTAMP_COL_ID : 0; strcpy(pCol->colName, pExpr->aliasName); if ('\0' == pCol->node.aliasName[0]) { strcpy(pCol->node.aliasName, pCol->colName); @@ -1019,10 +1020,73 @@ static bool isInternalPrimaryKey(const SColumnNode* pCol) { (0 == strcmp(pCol->colName, ROWTS_PSEUDO_COLUMN_NAME) || 0 == strcmp(pCol->colName, C0_PSEUDO_COLUMN_NAME)); } -static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, const STableNode* pTable, - bool* pFound) { + +static void setColumnPrimTs(STranslateContext* pCxt, SColumnNode* pCol, STableNode* pTable) { + if (PRIMARYKEY_TIMESTAMP_COL_ID != pCol->colId) { + return; + } + + bool joinQuery = false; + SJoinTableNode* pJoinTable = NULL; + if (QUERY_NODE_SELECT_STMT == nodeType(pCxt->pCurrStmt) && + NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable && + QUERY_NODE_JOIN_TABLE == nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) { + joinQuery = true; + pJoinTable = (SJoinTableNode*)((SSelectStmt*)pCxt->pCurrStmt)->pFromTable; + } + + pCol->isPrimTs = true; + + if (!joinQuery) { + return; + } + + switch (pJoinTable->joinType) { + case JOIN_TYPE_INNER: + pCol->isPrimTs = true; + break; + case JOIN_TYPE_LEFT: + if (!IS_SEMI_JOIN(pJoinTable->subType) && 0 != strcmp(pTable->tableAlias, ((STableNode*)pJoinTable->pLeft)->tableAlias)) { + pCol->isPrimTs = false; + } + break; + case JOIN_TYPE_RIGHT: + if (!IS_SEMI_JOIN(pJoinTable->subType) && 0 != strcmp(pTable->tableAlias, ((STableNode*)pJoinTable->pRight)->tableAlias)) { + pCol->isPrimTs = false; + } + break; + default: + pCol->isPrimTs = false; + break; + } +} + +static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, STableNode* pTable, + bool* pFound, bool keepOriginTable) { SColumnNode* pCol = *pColRef; *pFound = false; + bool joinQuery = false; + SJoinTableNode* pJoinTable = NULL; + + if (QUERY_NODE_SELECT_STMT == nodeType(pCxt->pCurrStmt) && + NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable && + QUERY_NODE_JOIN_TABLE == nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) { + joinQuery = true; + pJoinTable = (SJoinTableNode*)((SSelectStmt*)pCxt->pCurrStmt)->pFromTable; + if (isInternalPrimaryKey(pCol) && (!IS_WINDOW_JOIN(pJoinTable->subType) || !keepOriginTable)) { + switch (pJoinTable->joinType) { + case JOIN_TYPE_LEFT: + pTable = (STableNode*)pJoinTable->pLeft; + break; + case JOIN_TYPE_RIGHT: + pTable = (STableNode*)pJoinTable->pRight; + break; + default: + break; + } + } + } + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; if (isInternalPrimaryKey(pCol)) { @@ -1031,6 +1095,7 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, } setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema, -1, pCol); + pCol->isPrimTs = true; *pFound = true; return TSDB_CODE_SUCCESS; } @@ -1039,6 +1104,7 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, if (0 == strcmp(pCol->colName, pMeta->schema[i].name) && !invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) { setColumnInfoBySchema((SRealTableNode*)pTable, pMeta->schema + i, (i - pMeta->tableInfo.numOfColumns), pCol); + setColumnPrimTs(pCxt, pCol, pTable); *pFound = true; break; } @@ -1057,6 +1123,7 @@ static int32_t findAndSetColumn(STranslateContext* pCxt, SColumnNode** pColRef, *pFound = true; } else if (isPrimaryKey(pTempTable, pNode) && isInternalPrimaryKey(pCol)) { setColumnInfoByExpr(pTempTable, pExpr, pColRef); + pCol->isPrimTs = true; *pFound = true; } } @@ -1073,7 +1140,7 @@ static EDealRes translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode** if (belongTable((*pCol), pTable)) { foundTable = true; bool foundCol = false; - pCxt->errCode = findAndSetColumn(pCxt, pCol, pTable, &foundCol); + pCxt->errCode = findAndSetColumn(pCxt, pCol, pTable, &foundCol, false); if (TSDB_CODE_SUCCESS != pCxt->errCode) { return DEAL_RES_ERROR; } @@ -1097,7 +1164,7 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod for (size_t i = 0; i < nums; ++i) { STableNode* pTable = taosArrayGetP(pTables, i); bool foundCol = false; - pCxt->errCode = findAndSetColumn(pCxt, pCol, pTable, &foundCol); + pCxt->errCode = findAndSetColumn(pCxt, pCol, pTable, &foundCol, false); if (TSDB_CODE_SUCCESS != pCxt->errCode) { return DEAL_RES_ERROR; } @@ -1988,6 +2055,8 @@ static int32_t translateInterpPseudoColumnFunc(STranslateContext* pCxt, SNode** return TSDB_CODE_SUCCESS; } + + static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { if (!fmIsTimelineFunc(pFunc->funcId)) { return TSDB_CODE_SUCCESS; @@ -1997,12 +2066,15 @@ static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFu "%s function must be used in select statements", pFunc->functionName); } SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt; - if (NULL != pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && + if ((NULL != pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && !isGlobalTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery) && - !isTimeLineAlignedQuery(pCxt->pCurrStmt)) { + !isTimeLineAlignedQuery(pCxt->pCurrStmt)) || + (NULL != pSelect->pFromTable && QUERY_NODE_JOIN_TABLE == nodeType(pSelect->pFromTable) && + (TIME_LINE_GLOBAL != pSelect->timeLineResMode && TIME_LINE_MULTI != pSelect->timeLineResMode))) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, "%s function requires valid time series input", pFunc->functionName); } + return TSDB_CODE_SUCCESS; } @@ -2826,7 +2898,7 @@ static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) { } static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect, SNodeList* pList) { - if (NULL == getGroupByList(pCxt) && NULL == pSelect->pWindow && (!isWindowJoinStmt(pSelect) || !pSelect->hasAggFuncs)) { + if (NULL == getGroupByList(pCxt) && NULL == pSelect->pWindow && (!isWindowJoinStmt(pSelect) || (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc))) { return TSDB_CODE_SUCCESS; } nodesRewriteExprs(pList, doCheckExprForGroupBy, pCxt); @@ -3331,19 +3403,68 @@ static int32_t addPrimJoinEqCond(SNode** pCond, SRealTableNode* leftTable, SReal return TSDB_CODE_SUCCESS; } -static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) { - if ((QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pLeft) && - !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pLeft)->pSubquery)) || - (QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pRight) && - !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pRight)->pSubquery))) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, - "Join requires valid time series input"); + +static bool getJoinContais(SNode* pNode) { + if (QUERY_NODE_REAL_TABLE == nodeType(pNode)) { + return false; } + if (QUERY_NODE_JOIN_TABLE == nodeType(pNode)) { + return true; + } + if (QUERY_NODE_TEMP_TABLE == nodeType(pNode)) { + pNode = ((STempTableNode*)pNode)->pSubquery; + } + + switch (nodeType(pNode)) { + case QUERY_NODE_REAL_TABLE: + return false; + case QUERY_NODE_JOIN_TABLE: + return true; + case QUERY_NODE_TEMP_TABLE: + pNode = ((STempTableNode*)pNode)->pSubquery; + break; + default: + break; + } + + switch (nodeType(pNode)) { + case QUERY_NODE_SELECT_STMT: { + SSelectStmt* pSelect = (SSelectStmt*)pNode; + return pSelect->joinContains; + } + case QUERY_NODE_SET_OPERATOR: { + SSetOperator* pSet = (SSetOperator*)pNode; + return pSet->joinContains; + } + default: + break; + } + + return false; +} + +static bool getBothJoinContais(SNode* pLeft, SNode* pRight) { + bool joinContains = false; + if (NULL != pLeft) { + joinContains= getJoinContais(pLeft); + } + + if (NULL != pRight && !joinContains) { + joinContains= getJoinContais(pRight); + } + + return joinContains; +} + +static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) { + if (JOIN_STYPE_NONE != pJoinTable->subType && getBothJoinContais(pJoinTable->pLeft, pJoinTable->pRight)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, "Nested join not supported now"); + } + if (IS_ASOF_JOIN(pJoinTable->subType) || IS_WINDOW_JOIN(pJoinTable->subType)) { if (QUERY_NODE_REAL_TABLE != nodeType(pJoinTable->pLeft) || QUERY_NODE_REAL_TABLE != nodeType(pJoinTable->pRight)) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, - "Only support ASOF/WINDOW join between tables"); + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, "Only support ASOF/WINDOW join between tables"); } SRealTableNode* pLeft = (SRealTableNode*)pJoinTable->pLeft; @@ -3358,7 +3479,26 @@ static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTabl "Unsupported ASOF/WINDOW join table type"); } - return addPrimJoinEqCond(&pJoinTable->addPrimCond, pLeft, pRight, pJoinTable->joinType, pJoinTable->subType); + int32_t code = addPrimJoinEqCond(&pJoinTable->addPrimCond, pLeft, pRight, pJoinTable->joinType, pJoinTable->subType); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + + if (IS_WINDOW_JOIN(pJoinTable->subType)) { + SSelectStmt* pCurrSmt = (SSelectStmt*)(pCxt->pCurrStmt); + if (NULL != pCurrSmt->pWindow || NULL != pCurrSmt->pPartitionByList || NULL != pCurrSmt->pGroupByList) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, + "No WINDOW/GROUP BY/PARTITION BY allowed in WINDOW join"); + } + } + + if ((QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pLeft) && + !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pLeft)->pSubquery)) || + (QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pRight) && + !isGlobalTimeLineQuery(((STempTableNode*)pJoinTable->pRight)->pSubquery))) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SUPPORT_JOIN, + "Join requires valid time series input"); } return TSDB_CODE_SUCCESS; @@ -3368,6 +3508,7 @@ static int32_t translateJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoin int32_t code = TSDB_CODE_SUCCESS; EJoinType type = pJoinTable->joinType; EJoinSubType* pSType = &pJoinTable->subType; + SSelectStmt* pCurrSmt = (SSelectStmt*)(pCxt->pCurrStmt); switch (type) { case JOIN_TYPE_INNER: @@ -3495,6 +3636,7 @@ int32_t validateJoinConds(STranslateContext* pCxt, SJoinTableNode* pJoinTable) { return code; } + static int32_t translateAudit(STranslateContext* pCxt, SRealTableNode* pRealTable, SName* pName) { if (pRealTable->pMeta->tableType == TSDB_SUPER_TABLE) { if (IS_AUDIT_DBNAME(pName->dbname) && IS_AUDIT_STB_NAME(pName->tname)) { @@ -3508,7 +3650,170 @@ static int32_t translateAudit(STranslateContext* pCxt, SRealTableNode* pRealTabl return 0; } +static bool isJoinTagEqualOnCond(SNode* pCond, char* leftTableAlias, char* rightTableAlias) { + if (QUERY_NODE_OPERATOR != nodeType(pCond)) { + return false; + } + SOperatorNode* pOper = (SOperatorNode*)pCond; + if (QUERY_NODE_COLUMN != nodeType(pOper->pLeft) || NULL == pOper->pRight || QUERY_NODE_COLUMN != nodeType(pOper->pRight)) { + return false; + } + SColumnNode* pLeft = (SColumnNode*)(pOper->pLeft); + SColumnNode* pRight = (SColumnNode*)(pOper->pRight); + + if ((COLUMN_TYPE_TAG != pLeft->colType) || (COLUMN_TYPE_TAG != pRight->colType)) { + return false; + } + + if (OP_TYPE_EQUAL != pOper->opType) { + return false; + } + + if (pLeft->node.resType.type != pRight->node.resType.type || + pLeft->node.resType.bytes != pRight->node.resType.bytes) { + return false; + } + bool isEqual = false; + if (0 == strcmp(pLeft->tableAlias, leftTableAlias)) { + isEqual = (0 == strcmp(pRight->tableAlias, rightTableAlias)); + } else if (0 == strcmp(pLeft->tableAlias, rightTableAlias)) { + isEqual = (0 == strcmp(pRight->tableAlias, leftTableAlias)); + } + + return isEqual; +} + +static bool joinTagEqCondContains(SNode* pCond, char* leftTableAlias, char* rightTableAlias) { + if (QUERY_NODE_LOGIC_CONDITION == nodeType(pCond)) { + SLogicConditionNode* pLogic = (SLogicConditionNode*)pCond; + if (LOGIC_COND_TYPE_AND != pLogic->condType) { + return false; + } + + FOREACH(pCond, pLogic->pParameterList) { + if (isJoinTagEqualOnCond(pCond, leftTableAlias, rightTableAlias)) { + return true; + } + } + + return false; + } + + if (QUERY_NODE_OPERATOR == nodeType(pCond)) { + return isJoinTagEqualOnCond(pCond, leftTableAlias, rightTableAlias); + } + + return false; +} + +static bool innerJoinTagEqCondContains(SJoinTableNode* pJoinTable, SNode* pWhere) { + bool condContains = false; + SRealTableNode *pLeftTable = (SRealTableNode*)pJoinTable->pLeft; + SRealTableNode *pRightTable = (SRealTableNode*)pJoinTable->pRight; + + if (NULL != pJoinTable->pOnCond) { + condContains = joinTagEqCondContains(pJoinTable->pOnCond, pLeftTable->table.tableAlias, pRightTable->table.tableAlias); + } + if (NULL != pWhere && !condContains) { + condContains = joinTagEqCondContains(pWhere, pLeftTable->table.tableAlias, pRightTable->table.tableAlias); + } + + return condContains; +} + +static bool joinNonPrimColCondContains(SJoinTableNode* pJoinTable) { + if (NULL == pJoinTable->pOnCond) { + return false; + } + + if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoinTable->pOnCond)) { + SLogicConditionNode* pLogic = (SLogicConditionNode*)pJoinTable->pOnCond; + if (LOGIC_COND_TYPE_AND != pLogic->condType) { + return false; + } + + SNode* pNode = NULL; + FOREACH(pNode, pLogic->pParameterList) { + if (QUERY_NODE_OPERATOR != nodeType(pNode)) { + continue; + } + SOperatorNode* pOp = (SOperatorNode*)pNode; + if (OP_TYPE_EQUAL != pOp->opType) { + continue; + } + if (QUERY_NODE_COLUMN != nodeType(pOp->pLeft) || NULL == pOp->pRight || QUERY_NODE_COLUMN != nodeType(pOp->pRight)) { + continue; + } + if (isPrimaryKeyImpl(pOp->pLeft) || isPrimaryKeyImpl(pOp->pRight)) { + continue; + } + return true; + } + + return false; + } + + if (QUERY_NODE_OPERATOR == nodeType(pJoinTable->pOnCond)) { + SOperatorNode* pOp = (SOperatorNode*)pJoinTable->pOnCond; + if (OP_TYPE_EQUAL != pOp->opType) { + return false; + } + if (QUERY_NODE_COLUMN != nodeType(pOp->pLeft) || NULL == pOp->pRight || QUERY_NODE_COLUMN != nodeType(pOp->pRight)) { + return false; + } + if (isPrimaryKeyImpl(pOp->pLeft) || isPrimaryKeyImpl(pOp->pRight)) { + return false; + } + + return true; + } + + return false; +} + +static int32_t setJoinTimeLineResMode(STranslateContext* pCxt) { + SSelectStmt* pCurrSmt = (SSelectStmt*)(pCxt->pCurrStmt); + if (QUERY_NODE_JOIN_TABLE != nodeType(pCurrSmt->pFromTable)) { + return TSDB_CODE_SUCCESS; + } + + SJoinTableNode* pJoinTable = (SJoinTableNode*)pCurrSmt->pFromTable; + if (JOIN_TYPE_FULL == pJoinTable->joinType) { + pCurrSmt->timeLineResMode = TIME_LINE_NONE; + return TSDB_CODE_SUCCESS; + } + + if (TIME_LINE_NONE == pCurrSmt->timeLineResMode) { + return TSDB_CODE_SUCCESS; + } + + if (pJoinTable->table.singleTable || pJoinTable->hasSubQuery || pJoinTable->isLowLevelJoin) { + return TSDB_CODE_SUCCESS; + } + + switch (pJoinTable->subType) { + case JOIN_STYPE_NONE: { + if (innerJoinTagEqCondContains(pJoinTable, pCurrSmt->pWhere)) { + pCurrSmt->timeLineResMode = TIME_LINE_BLOCK; + } + break; + } + case JOIN_STYPE_ASOF: + case JOIN_STYPE_WIN: { + if (joinNonPrimColCondContains(pJoinTable)) { + pCurrSmt->timeLineResMode = TIME_LINE_BLOCK; + } + break; + } + default: + break; + } + + return TSDB_CODE_SUCCESS; +} + int32_t translateTable(STranslateContext* pCxt, SNode** pTable, SNode* pJoinParent) { + SSelectStmt* pCurrSmt = (SSelectStmt*)(pCxt->pCurrStmt); int32_t code = TSDB_CODE_SUCCESS; switch (nodeType(*pTable)) { case QUERY_NODE_REAL_TABLE: { @@ -3561,10 +3866,12 @@ int32_t translateTable(STranslateContext* pCxt, SNode** pTable, SNode* pJoinPare ((SSelectStmt*)pCxt->pCurrStmt)->isEmptyResult = true; } if (QUERY_NODE_SELECT_STMT == nodeType(pTempTable->pSubquery) && isSelectStmt(pCxt->pCurrStmt)) { + pCurrSmt->joinContains = ((SSelectStmt*)pTempTable->pSubquery)->joinContains; SSelectStmt* pSubStmt = (SSelectStmt*)pTempTable->pSubquery; - SSelectStmt* pCurrSmt = (SSelectStmt*)(pCxt->pCurrStmt); pCurrSmt->timeLineResMode = pSubStmt->timeLineResMode; } + + pCurrSmt->joinContains = (getJoinContais(pTempTable->pSubquery) ? true : false); pTempTable->table.precision = getStmtPrecision(pTempTable->pSubquery); pTempTable->table.singleTable = stmtIsSingleTable(pTempTable->pSubquery); code = addNamespace(pCxt, pTempTable); @@ -3599,7 +3906,8 @@ int32_t translateTable(STranslateContext* pCxt, SNode** pTable, SNode* pJoinPare ((SJoinTableNode*)pJoinTable->pRight)->isLowLevelJoin = true; } code = validateJoinConds(pCxt, pJoinTable); - } + } + pCurrSmt->joinContains = true; break; } default: @@ -4333,7 +4641,7 @@ static int32_t translateSessionWindow(STranslateContext* pCxt, SSelectStmt* pSel if ('y' == pSession->pGap->unit || 'n' == pSession->pGap->unit || 0 == pSession->pGap->datum.i) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTER_SESSION_GAP); } - if (PRIMARYKEY_TIMESTAMP_COL_ID != pSession->pCol->colId) { + if (!isPrimaryKeyImpl((SNode*)pSession->pCol)) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTER_SESSION_COL); } return TSDB_CODE_SUCCESS; @@ -4439,6 +4747,14 @@ static int32_t translateWindow(STranslateContext* pCxt, SSelectStmt* pSelect) { ((SRealTableNode*)pSelect->pFromTable)->pMeta->tableType == TSDB_SYSTEM_TABLE) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED, "WINDOW"); } + if ((NULL != pSelect->pFromTable && QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && + !isGlobalTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery) && + !isTimeLineAlignedQuery(pCxt->pCurrStmt)) || + (NULL != pSelect->pFromTable && QUERY_NODE_JOIN_TABLE == nodeType(pSelect->pFromTable) && + ((QUERY_NODE_INTERVAL_WINDOW != nodeType(pSelect->pWindow) && TIME_LINE_GLOBAL != pSelect->timeLineResMode && TIME_LINE_MULTI != pSelect->timeLineResMode) || (QUERY_NODE_INTERVAL_WINDOW == nodeType(pSelect->pWindow) && TIME_LINE_NONE == pSelect->timeLineResMode)))) { + return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY); + } + pCxt->currClause = SQL_CLAUSE_WINDOW; int32_t code = translateExpr(pCxt, &pSelect->pWindow); if (TSDB_CODE_SUCCESS == code) { @@ -4919,9 +5235,9 @@ static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* p pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; strcpy(pCol->colName, ROWTS_PSEUDO_COLUMN_NAME); bool found = false; - int32_t code = findAndSetColumn(pCxt, &pCol, pTable, &found); + int32_t code = findAndSetColumn(pCxt, &pCol, pTable, &found, true); if (TSDB_CODE_SUCCESS != code || !found) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TIMELINE_FUNC); + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED); } *pPrimaryKey = (SNode*)pCol; return TSDB_CODE_SUCCESS; @@ -5077,69 +5393,6 @@ static int32_t translateSelectWithoutFrom(STranslateContext* pCxt, SSelectStmt* return translateExprList(pCxt, pSelect->pProjectionList); } -static int32_t translateWinJoin(STranslateContext* pCxt, SSelectStmt* pSelect) { - if (QUERY_NODE_JOIN_TABLE != nodeType(pSelect->pFromTable) || !pSelect->hasAggFuncs) { - return TSDB_CODE_SUCCESS; - } - - SJoinTableNode* pJoinTable = (SJoinTableNode*)pSelect->pFromTable; - if (JOIN_STYPE_WIN != pJoinTable->subType) { - return TSDB_CODE_SUCCESS; - } - - if (pSelect->pGroupByList || pSelect->pPartitionByList || pSelect->pWindow) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GRP_WINDOW_NOT_ALLOWED); - } - -/* - SRealTableNode* pProbeTable = NULL; - switch (pJoinTable->joinType) { - case JOIN_TYPE_LEFT: - pProbeTable = (SRealTableNode*)pJoinTable->pLeft; - break; - case JOIN_TYPE_RIGHT: - pProbeTable = (SRealTableNode*)pJoinTable->pRight; - break; - default: - return TSDB_CODE_PAR_INTERNAL_ERROR; - } - - SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - SSchema* pColSchema = &pProbeTable->pMeta->schema[0]; - strcpy(pCol->dbName, pProbeTable->table.dbName); - strcpy(pCol->tableAlias, pProbeTable->table.tableAlias); - strcpy(pCol->tableName, pProbeTable->table.tableName); - strcpy(pCol->colName, pColSchema->name); - strcpy(pCol->node.aliasName, pColSchema->name); - strcpy(pCol->node.userAlias, pColSchema->name); - pCol->tableId = pProbeTable->pMeta->uid; - pCol->tableType = pProbeTable->pMeta->tableType; - pCol->colId = pColSchema->colId; - pCol->colType = COLUMN_TYPE_COLUMN; - pCol->hasIndex = (pColSchema != NULL && IS_IDX_ON(pColSchema)); - pCol->node.resType.type = pColSchema->type; - pCol->node.resType.bytes = pColSchema->bytes; - pCol->node.resType.precision = pProbeTable->pMeta->tableInfo.precision; - - SGroupingSetNode* groupingSet = (SGroupingSetNode*)nodesMakeNode(QUERY_NODE_GROUPING_SET); - if (NULL == groupingSet) { - nodesDestroyNode((SNode*)pCol); - return TSDB_CODE_OUT_OF_MEMORY; - } - groupingSet->groupingSetType = GP_TYPE_NORMAL; - groupingSet->pParameterList = nodesMakeList(); - nodesListAppend(groupingSet->pParameterList, (SNode*)pCol); - - pSelect->pGroupByList = nodesMakeList(); - nodesListAppend(pSelect->pGroupByList, (SNode*)groupingSet); -*/ - return TSDB_CODE_SUCCESS; -} - static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect) { pCxt->pCurrStmt = (SNode*)pSelect; int32_t code = translateFrom(pCxt, &pSelect->pFromTable); @@ -5147,6 +5400,9 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect pSelect->precision = ((STableNode*)pSelect->pFromTable)->precision; code = translateWhere(pCxt, pSelect); } + if (TSDB_CODE_SUCCESS == code) { + code = setJoinTimeLineResMode(pCxt); + } if (TSDB_CODE_SUCCESS == code) { code = translatePartitionBy(pCxt, pSelect); } @@ -5174,9 +5430,6 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect if (TSDB_CODE_SUCCESS == code) { code = checkIsEmptyResult(pCxt, pSelect); } - if (TSDB_CODE_SUCCESS == code) { - code = translateWinJoin(pCxt, pSelect); - } if (TSDB_CODE_SUCCESS == code) { resetSelectFuncNumWithoutDup(pSelect); code = checkAggColCoexist(pCxt, pSelect); @@ -5327,6 +5580,9 @@ static int32_t translateSetOperator(STranslateContext* pCxt, SSetOperator* pSetO if (TSDB_CODE_SUCCESS == code) { code = translateQuery(pCxt, pSetOperator->pRight); } + if (TSDB_CODE_SUCCESS == code) { + pSetOperator->joinContains = getBothJoinContais(pSetOperator->pLeft, pSetOperator->pRight); + } if (TSDB_CODE_SUCCESS == code) { pSetOperator->precision = calcSetOperatorPrecision(pSetOperator); code = translateSetOperProject(pCxt, pSetOperator); diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 03dfe5bf3c..052296f19a 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -153,7 +153,7 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Some functions are allowed only in the SELECT list of a query. " "And, cannot be mixed with other non scalar functions or columns."; case TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY: - return "Window query not supported, since the result of subquery not include valid timestamp column"; + return "Window query not supported, since not valid primary timestamp column as input"; case TSDB_CODE_PAR_INVALID_DROP_COL: return "No columns can be dropped"; case TSDB_CODE_PAR_INVALID_COL_JSON: @@ -198,6 +198,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Not supported window join having expr"; case TSDB_CODE_PAR_INVALID_WIN_OFFSET_UNIT: return "Invalid WINDOW_OFFSET unit \"%s\""; + case TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED: + return "Valid primary timestamp required"; default: return "Unknown error"; } diff --git a/source/libs/planner/inc/planInt.h b/source/libs/planner/inc/planInt.h index aa281a683e..a072ebd49e 100644 --- a/source/libs/planner/inc/planInt.h +++ b/source/libs/planner/inc/planInt.h @@ -62,6 +62,8 @@ SFunctionNode* createGroupKeyAggFunc(SColumnNode* pGroupCol); #define CLONE_SLIMIT 1 << 1 #define CLONE_LIMIT_SLIMIT (CLONE_LIMIT | CLONE_SLIMIT) bool cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat); +int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, SSortLogicNode* pSort, + bool* pNotOptimize, SNodeList** pSequencingNodes, bool* keepSort); #ifdef __cplusplus } diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index 45da4ccf9f..b8a5c61877 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -17,6 +17,7 @@ #include "filter.h" #include "functionMgt.h" #include "tglobal.h" +#include "parser.h" typedef struct SLogicPlanContext { SPlanContext* pPlanCxt; @@ -57,12 +58,14 @@ static void setColumnInfo(SFunctionNode* pFunc, SColumnNode* pCol, bool isPartit pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; } pCol->colType = COLUMN_TYPE_WINDOW_START; + pCol->isPrimTs = true; break; case FUNCTION_TYPE_WEND: if (!isPartitionBy) { pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; } pCol->colType = COLUMN_TYPE_WINDOW_END; + pCol->isPrimTs = true; break; case FUNCTION_TYPE_WDURATION: pCol->colType = COLUMN_TYPE_WINDOW_DURATION; @@ -551,7 +554,7 @@ static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect pJoin->pJLimit = nodesCloneNode(pJoinTable->pJLimit); pJoin->addPrimEqCond = nodesCloneNode(pJoinTable->addPrimCond); pJoin->node.pChildren = nodesMakeList(); - pJoin->seqWinGroup = (JOIN_STYPE_WIN == pJoinTable->subType) && pSelect->hasAggFuncs; + pJoin->seqWinGroup = (JOIN_STYPE_WIN == pJoinTable->subType) && (pSelect->hasAggFuncs || pSelect->hasIndefiniteRowsFunc); if (NULL == pJoin->node.pChildren) { code = TSDB_CODE_OUT_OF_MEMORY; } @@ -1250,7 +1253,7 @@ static bool isPrimaryKeySort(SNodeList* pOrderByList) { if (QUERY_NODE_COLUMN != nodeType(pExpr)) { return false; } - return PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId; + return isPrimaryKeyImpl(pExpr); } static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index bddf9cfd47..ccba6a4a37 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -19,6 +19,7 @@ #include "systable.h" #include "tglobal.h" #include "ttime.h" +#include "parser.h" #define OPTIMIZE_FLAG_MASK(n) (1 << n) @@ -1634,7 +1635,7 @@ static bool sortPriKeyOptIsPriKeyOrderBy(SNodeList* pSortKeys) { return false; } SNode* pNode = ((SOrderByExprNode*)nodesListGetNode(pSortKeys, 0))->pExpr; - return (QUERY_NODE_COLUMN == nodeType(pNode) ? (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pNode)->colId) : false); + return (QUERY_NODE_COLUMN == nodeType(pNode) ? isPrimaryKeyImpl(pNode) : false); } static bool sortPriKeyOptMayBeOptimized(SLogicNode* pNode) { @@ -1646,7 +1647,14 @@ static bool sortPriKeyOptMayBeOptimized(SLogicNode* pNode) { 1 != LIST_LENGTH(pSort->node.pChildren)) { return false; } - SNode* pChild; + SNode* pChild = nodesListGetNode(pSort->node.pChildren, 0); + if (QUERY_NODE_LOGIC_PLAN_JOIN == nodeType(pChild)) { + SJoinLogicNode* pJoin = (SJoinLogicNode*)pChild; + if (JOIN_TYPE_FULL == pJoin->joinType) { + return false; + } + } + FOREACH(pChild, pSort->node.pChildren) { SLogicNode* pSortDescendent = optFindPossibleNode((SLogicNode*)pChild, sortPriKeyOptMayBeOptimized); if (pSortDescendent != NULL) { @@ -1656,13 +1664,124 @@ static bool sortPriKeyOptMayBeOptimized(SLogicNode* pNode) { return true; } -static int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, EOrder sortOrder, - bool* pNotOptimize, SNodeList** pSequencingNodes) { +static int32_t sortPriKeyOptHandleLeftRightJoinSort(SJoinLogicNode* pJoin, SSortLogicNode* pSort, bool* pNotOptimize, bool* keepSort) { + if (JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_NONE == pJoin->subType) { + return TSDB_CODE_SUCCESS; + } + + SSHashObj* pLeftTables = NULL; + SSHashObj* pRightTables = NULL; + bool sortByLeft = true, sortByRight = true, sortByProbe = false; + collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pLeftTables); + collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pRightTables); + + SOrderByExprNode* pExprNode = (SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0); + SColumnNode* pSortCol = (SColumnNode*)pExprNode->pExpr; + if (NULL == tSimpleHashGet(pLeftTables, pSortCol->tableAlias, strlen(pSortCol->tableAlias))) { + sortByLeft = false; + } + if (NULL == tSimpleHashGet(pRightTables, pSortCol->tableAlias, strlen(pSortCol->tableAlias))) { + sortByRight = false; + } + + tSimpleHashCleanup(pLeftTables); + tSimpleHashCleanup(pRightTables); + + if (!sortByLeft && !sortByRight) { + planError("sort by primary key not in any join subtable, tableAlias: %s", pSortCol->tableAlias); + return TSDB_CODE_PLAN_INTERNAL_ERROR; + } + + if (sortByLeft && sortByRight) { + planError("sort by primary key in both join subtables, tableAlias: %s", pSortCol->tableAlias); + return TSDB_CODE_PLAN_INTERNAL_ERROR; + } + + if ((JOIN_TYPE_LEFT == pJoin->joinType && sortByLeft) || (JOIN_TYPE_RIGHT == pJoin->joinType && sortByRight)) { + sortByProbe = true; + } + + switch (pJoin->subType) { + case JOIN_STYPE_OUTER: { + if (sortByProbe) { + return TSDB_CODE_SUCCESS; + } + + *pNotOptimize = true; + return TSDB_CODE_SUCCESS; + } + case JOIN_STYPE_ANTI: { + if (sortByProbe) { + return TSDB_CODE_SUCCESS; + } + + *keepSort = false; + return TSDB_CODE_SUCCESS; + } + case JOIN_STYPE_ASOF: + case JOIN_STYPE_WIN: { + if (sortByProbe) { + if (NULL != pJoin->pLeftEqNodes && pJoin->pLeftEqNodes->length > 0) { + *pNotOptimize = true; + } + return TSDB_CODE_SUCCESS; + } + + *pNotOptimize = true; + return TSDB_CODE_SUCCESS; + } + default: + return TSDB_CODE_PLAN_INTERNAL_ERROR; + } + + return TSDB_CODE_SUCCESS; +} + + +static int32_t sortPriKeyOptHandleJoinSort(SLogicNode* pNode, bool groupSort, SSortLogicNode* pSort, + bool* pNotOptimize, SNodeList** pSequencingNodes, bool* keepSort) { + SJoinLogicNode* pJoin = (SJoinLogicNode*)pNode; + int32_t code = TSDB_CODE_SUCCESS; + + switch (pJoin->joinType) { + case JOIN_TYPE_LEFT: + case JOIN_TYPE_RIGHT: { + code = sortPriKeyOptHandleLeftRightJoinSort(pJoin, pSort, pNotOptimize, keepSort); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + if (*pNotOptimize || !(*keepSort)) { + return TSDB_CODE_SUCCESS; + } + break; + } + default: + break; + } + + code = sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), groupSort, + pSort, pNotOptimize, pSequencingNodes, keepSort); + if (TSDB_CODE_SUCCESS == code) { + code = sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 1), groupSort, + pSort, pNotOptimize, pSequencingNodes, keepSort); + } + + return code; +} + + +static EOrder sortPriKeyOptGetPriKeyOrder(SSortLogicNode* pSort) { + return ((SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0))->order; +} + +int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, SSortLogicNode* pSort, + bool* pNotOptimize, SNodeList** pSequencingNodes, bool* keepSort) { if (NULL != pNode->pLimit || NULL != pNode->pSlimit) { *pNotOptimize = false; return TSDB_CODE_SUCCESS; } + EOrder sortOrder = sortPriKeyOptGetPriKeyOrder(pSort); switch (nodeType(pNode)) { case QUERY_NODE_LOGIC_PLAN_SCAN: { SScanLogicNode* pScan = (SScanLogicNode*)pNode; @@ -1673,13 +1792,7 @@ static int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool group return nodesListMakeAppend(pSequencingNodes, (SNode*)pNode); } case QUERY_NODE_LOGIC_PLAN_JOIN: { - int32_t code = sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), groupSort, - sortOrder, pNotOptimize, pSequencingNodes); - if (TSDB_CODE_SUCCESS == code) { - code = sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 1), groupSort, - sortOrder, pNotOptimize, pSequencingNodes); - } - return code; + return sortPriKeyOptHandleJoinSort(pNode, groupSort, pSort, pNotOptimize, pSequencingNodes, keepSort); } case QUERY_NODE_LOGIC_PLAN_WINDOW: { SWindowLogicNode* pWindowLogicNode = (SWindowLogicNode*)pNode; @@ -1703,19 +1816,16 @@ static int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool group return TSDB_CODE_SUCCESS; } - return sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), groupSort, sortOrder, - pNotOptimize, pSequencingNodes); + return sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pNode->pChildren, 0), groupSort, pSort, + pNotOptimize, pSequencingNodes, keepSort); } -static EOrder sortPriKeyOptGetPriKeyOrder(SSortLogicNode* pSort) { - return ((SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0))->order; -} -static int32_t sortPriKeyOptGetSequencingNodes(SSortLogicNode* pSort, bool groupSort, SNodeList** pSequencingNodes) { +static int32_t sortPriKeyOptGetSequencingNodes(SSortLogicNode* pSort, bool groupSort, SNodeList** pSequencingNodes, bool* keepSort) { bool notOptimize = false; int32_t code = sortPriKeyOptGetSequencingNodesImpl((SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0), groupSort, - sortPriKeyOptGetPriKeyOrder(pSort), ¬Optimize, pSequencingNodes); + pSort, ¬Optimize, pSequencingNodes, keepSort); if (TSDB_CODE_SUCCESS != code || notOptimize) { NODES_CLEAR_LIST(*pSequencingNodes); } @@ -1761,10 +1871,22 @@ static int32_t sortPriKeyOptApply(SOptimizeContext* pCxt, SLogicSubplan* pLogicS static int32_t sortPrimaryKeyOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SSortLogicNode* pSort) { SNodeList* pSequencingNodes = NULL; - int32_t code = sortPriKeyOptGetSequencingNodes(pSort, pSort->groupSort, &pSequencingNodes); + bool keepSort = true; + int32_t code = sortPriKeyOptGetSequencingNodes(pSort, pSort->groupSort, &pSequencingNodes, &keepSort); if (TSDB_CODE_SUCCESS == code) { if (pSequencingNodes != NULL) { code = sortPriKeyOptApply(pCxt, pLogicSubplan, pSort, pSequencingNodes); + } else if (!keepSort) { + SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0); + if (NULL == pSort->node.pParent) { + TSWAP(pSort->node.pTargets, pChild->pTargets); + } + int32_t code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pSort, pChild); + if (TSDB_CODE_SUCCESS == code) { + NODES_CLEAR_LIST(pSort->node.pChildren); + nodesDestroyNode((SNode*)pSort); + } + pCxt->optimized = true; } else { // if we decided not to push down sort info to children, we should propagate output ts order to parents of pSort optSetParentOrder(pSort->node.pParent, sortPriKeyOptGetPriKeyOrder(pSort), 0); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 27294b7ee0..25b887b86d 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -595,7 +595,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_FUNCTION_NAME, "Invalid function na TAOS_DEFINE_ERROR(TSDB_CODE_PAR_COMMENT_TOO_LONG, "Comment too long") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_ALLOWED_FUNC, "Some functions are allowed only in the SELECT list of a query. " "And, cannot be mixed with other non scalar functions or columns.") -TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY, "Window query not supported, since the result of subquery not include valid timestamp column") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY, "Window query not supported, since not valid primary timestamp column as input") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_DROP_COL, "No columns can be dropped") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_COL_JSON, "Only tag can be json type") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_VALUE_TOO_LONG, "Value too long for column/tag") @@ -626,6 +626,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_SUPPORT_MULTI_RESULT, "Operator not suppor TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_WJOIN_HAVING_EXPR, "Invalid window join having expr") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_GRP_WINDOW_NOT_ALLOWED, "GROUP BY/PARTITION BY/WINDOW-clause can't be used in WINDOW join") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_WIN_OFFSET_UNIT, "Invalid window offset unit") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED, "Valid primary timestamp required") //planner TAOS_DEFINE_ERROR(TSDB_CODE_PLAN_INTERNAL_ERROR, "Planner internal error") diff --git a/tests/script/tsim/join/full_join.sim b/tests/script/tsim/join/full_join.sim index 535f9c1066..3037f4859a 100644 --- a/tests/script/tsim/join/full_join.sim +++ b/tests/script/tsim/join/full_join.sim @@ -144,3 +144,97 @@ sql select a.ts, b.ts from tba1 a full join tba2 b on a.ts = b.ts and a.ts < '20 if $rows != 7 then return -1 endi +if $data00 != NULL then + return -1 +endi +if $data10 != NULL then + return -1 +endi +if $data20 != NULL then + return -1 +endi +if $data30 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data40 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data50 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data60 != @23-11-17 16:29:04.000@ then + return -1 +endi + +sql select a.ts, b.ts from tba1 a full join tba2 b on a.ts = b.ts and a.ts < '2023-11-17 16:29:03' and b.ts < '2023-11-17 16:29:03' order by b.ts desc; +if $rows != 7 then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data41 != NULL then + return -1 +endi +if $data51 != NULL then + return -1 +endi +if $data61 != NULL then + return -1 +endi + +sql select b.ts, a.ts from tba1 a full join tba2 b on a.ts = b.ts and a.ts < '2023-11-17 16:29:03' and b.ts < '2023-11-17 16:29:03' order by b.ts desc, a.ts; +if $rows != 7 then + return -1 +endi +if $data00 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data40 != NULL then + return -1 +endi +if $data50 != NULL then + return -1 +endi +if $data60 != NULL then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data31 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data51 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data61 != @23-11-17 16:29:04.000@ then + return -1 +endi diff --git a/tests/script/tsim/join/inner_join.sim b/tests/script/tsim/join/inner_join.sim index 189580a80a..8f18c1386a 100644 --- a/tests/script/tsim/join/inner_join.sim +++ b/tests/script/tsim/join/inner_join.sim @@ -168,5 +168,20 @@ if $data11 != @23-11-17 16:29:04.000@ then return -1 endi - +sql select a.ts, b.ts from sta a join sta b on a.ts=b.ts order by a.ts desc, b.ts; +if $rows != 12 then + return -1 +endi +if $data00 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:04.000@ then + return -1 +endi diff --git a/tests/script/tsim/join/join.sim b/tests/script/tsim/join/join.sim index 6bde57072f..f2b0039bb0 100644 --- a/tests/script/tsim/join/join.sim +++ b/tests/script/tsim/join/join.sim @@ -70,6 +70,8 @@ run tsim/join/right_asof_join.sim run tsim/join/left_win_join.sim run tsim/join/right_win_join.sim run tsim/join/join_scalar.sim +run tsim/join/join_timeline.sim +run tsim/join/join_nested.sim print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT @@ -89,5 +91,7 @@ run tsim/join/right_asof_join.sim run tsim/join/left_win_join.sim run tsim/join/right_win_join.sim run tsim/join/join_scalar.sim +run tsim/join/join_timeline.sim +run tsim/join/join_nested.sim system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/join/join_nested.sim b/tests/script/tsim/join/join_nested.sim new file mode 100644 index 0000000000..d1f8b9144e --- /dev/null +++ b/tests/script/tsim/join/join_nested.sim @@ -0,0 +1,110 @@ +sql connect +sql use test0; + +sql select a.ts from sta a ,(select TIMETRUNCATE(ts,1d) ts from sta) b where timetruncate(a.ts, 1d) = b.ts; +if $rows != 64 then + return -1 +endi + +sql select a.*,b.* from (select * from sta partition by tbname) a join (select * from sta partition by tbname order by ts) b on a.ts = b.ts; +sql select a.*,b.* from (select * from sta partition by tbname order by ts) a join (select * from sta partition by tbname order by ts) b on a.ts = b.ts; + + + + +sql select sum(c1) from (select a.col1 c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1); +if $rows != 1 then + return -1 +endi +if $data00 != 30 then + return -1 +endi + +sql select sum(c1) from (select a.col1 c1 from sta a join sta b on a.ts = b.ts); +if $rows != 1 then + return -1 +endi +if $data00 != 42 then + return -1 +endi + +sql select diff(c1) from (select a.ts, a.col1 c1 from tba1 a join sta b on a.ts = b.ts where b.t1 > 1); +if $rows != 1 then + return -1 +endi +if $data00 != 3 then + return -1 +endi + +sql select diff(c1) from (select b.col1 c1, a.ts from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 where a.t1 > 1 order by a.ts); +if $rows != 3 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 2 then + return -1 +endi +if $data20 != 2 then + return -1 +endi + +sql select count(c1) from (select a.ts, a.col1 c1 from tba1 a join sta b on a.ts = b.ts) interval(1s); +if $rows != 4 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 2 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select count(c1) from (select a.ts ts1, a.col1 c1 from tba1 a join sta b on a.ts = b.ts) c session(c.ts1, 1s); +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 4 then + return -1 +endi + +sql select count(c1) from (select b.ts, a.col1 c1 from tba1 a join sta b on a.ts = b.ts) c session(c.ts, 1s); +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 4 then + return -1 +endi + +sql select count(c1) from (select b.ts, a.col1 c1 from tba1 a join sta b on a.ts = b.ts partition by a.col1 order by a.ts) c session(c.ts, 1s); +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 4 then + return -1 +endi + +sql_error select diff(c1) from (select a.ts, a.col1 c1 from sta a join sta b on a.ts = b.ts); +sql_error select diff(c1) from (select a.col1 c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1); +sql_error select diff(c1) from (select a.col1 c1 from sta a join sta b on a.ts = b.ts); +sql_error select diff(c1) from (select a.col1 c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 order by a.ts); +sql_error select diff(c1) from (select a.col1 c1, a.ts from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 order by a.ts); +sql_error select count(c1) from (select a.col1 c1 from tba1 a join sta b on a.ts = b.ts) interval(1s); +sql_error select count(c1) from (select b.ts, a.col1 c1 from tba1 a join sta b on a.ts = b.ts partition by a.col1) c session(c.ts, 1s); + diff --git a/tests/script/tsim/join/join_timeline.sim b/tests/script/tsim/join/join_timeline.sim new file mode 100644 index 0000000000..4ceb99405e --- /dev/null +++ b/tests/script/tsim/join/join_timeline.sim @@ -0,0 +1,658 @@ +sql connect +sql use test0; + +#inner join + join group +sql select sum(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1; +if $rows != 1 then + return -1 +endi +if $data00 != 30 then + return -1 +endi + +sql_error select diff(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1; +sql_error select csum(b.col1) from sta a join sta b on a.ts = b.ts and a.t1 = b.t1; + +sql select count(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 interval(1s); +if $rows != 6 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 2 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi + +sql_error select count(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 session(a.ts, 1s); +sql_error select count(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 session(b.ts, 1s); +sql_error select count(a.col1) c1 from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 state_window(b.col1); +sql_error select csum(b.col1) from sta a join sta b on a.ts = b.ts and a.t1 = b.t1 interval(1s); + +#inner join + no join group +sql select sum(a.col1) c1 from sta a join sta b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 42 then + return -1 +endi + +sql select diff(a.col1) c1 from tba1 a join tba2 b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 3 then + return -1 +endi + +sql_error select csum(b.col1) from sta a join sta b on a.ts = b.ts; +sql select csum(b.col1) from tba1 a join tba2 b on a.ts = b.ts; +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 7 then + return -1 +endi + +sql select count(a.col1) c1 from sta a join sta b on a.ts = b.ts interval(1s); +if $rows != 6 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 4 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi + +sql select count(a.col1) c1 from sta a join sta b on a.ts = b.ts session(a.ts, 1s); +if $rows != 1 then + return -1 +endi +if $data00 != 12 then + return -1 +endi +sql select count(a.col1) c1 from sta a join sta b on a.ts = b.ts session(b.ts, 1s); +if $rows != 1 then + return -1 +endi +if $data00 != 12 then + return -1 +endi + + +sql select count(a.col1) c1 from sta a join sta b on a.ts = b.ts state_window(b.col1); + +#left join +sql select sum(a.col1) c1 from sta a left join sta b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 42 then + return -1 +endi + +sql select diff(a.col1) c1 from tba1 a left join tba2 b on a.ts = b.ts; +if $rows != 3 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi + +sql select diff(b.col1) c1 from tba1 a left join tba2 b on a.ts = b.ts; +if $rows != 3 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != 3 then + return -1 +endi +if $data20 != NULL then + return -1 +endi + +sql_error select csum(b.col1) from sta a left join sta b on a.ts = b.ts; +sql select csum(b.col1) from tba1 a left join tba2 b on a.ts = b.ts; +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 7 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left join sta b on a.ts = b.ts interval(1s); +if $rows != 6 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 4 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left join sta b on a.ts = b.ts session(a.ts, 1s); +if $rows != 1 then + return -1 +endi +if $data00 != 12 then + return -1 +endi +sql_error select count(a.col1) c1 from sta a left join sta b on a.ts = b.ts session(b.ts, 1s); + +sql select count(a.col1) c1 from sta a left join sta b on a.ts = b.ts state_window(b.col1); + + + +#left semi join +sql select sum(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 30 then + return -1 +endi + +sql select diff(a.col1) c1 from tba1 a left semi join tba2 b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 3 then + return -1 +endi + +sql select diff(b.col1) c1 from tba1 a left semi join tba2 b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 3 then + return -1 +endi + +sql_error select csum(b.col1) from sta a left semi join sta b on a.ts = b.ts; +sql select csum(b.col1) from tba1 a left semi join tba2 b on a.ts = b.ts; +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 7 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts interval(1s); +if $rows != 6 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 2 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts session(a.ts, 1s); +if $rows != 1 then + return -1 +endi +if $data00 != 8 then + return -1 +endi +sql select count(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts session(b.ts, 1s); +if $rows != 1 then + return -1 +endi +if $data00 != 8 then + return -1 +endi + + +sql select count(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts state_window(b.col1); + + +#left anti join +sql select sum(a.col1) c1 from sta a left anti join sta b on a.ts = b.ts; +if $rows != 0 then + return -1 +endi + +sql select diff(a.col1) c1 from tba1 a left anti join tba2 b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 2 then + return -1 +endi + +#??????? +sql select diff(b.col1) c1 from tba1 a left anti join tba2 b on a.ts = b.ts; + +sql select csum(b.col1) from sta a left anti join sta b on a.ts = b.ts; +if $rows != 0 then + return -1 +endi + +sql select csum(b.col1) from tba1 a left anti join tba2 b on a.ts = b.ts; +if $rows != 0 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left anti join sta b on a.ts = b.ts interval(1s); +if $rows != 0 then + return -1 +endi +sql select count(a.col1) c1 from tba1 a left anti join tba2 b on a.ts = b.ts interval(1s); +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +sql select count(a.col1) c1 from sta a left anti join sta b on a.ts = b.ts session(a.ts, 1s); +if $rows != 0 then + return -1 +endi +sql select count(a.col1) c1 from tba1 a left anti join tba2 b on a.ts = b.ts session(a.ts, 1s); +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +sql_error select count(a.col1) c1 from sta a left anti join sta b on a.ts = b.ts session(b.ts, 1s); + +sql select count(a.col1) c1 from sta a left semi join sta b on a.ts = b.ts state_window(b.col1); + + +#left asof join + join group +sql select sum(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1; +if $rows != 1 then + return -1 +endi +if $data00 != 30 then + return -1 +endi + +sql_error select diff(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1; +sql_error select diff(b.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1; + +sql_error select csum(a.col1) from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1; +sql_error select csum(b.col1) from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1; + +sql select count(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1 interval(1s); +if $rows != 6 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 2 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi + +sql_error select count(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1 session(a.ts, 1s); +sql_error select count(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1 session(b.ts, 1s); + +sql_error select count(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts and a.t1 = b.t1 state_window(b.col1); + + + +#left asof join + no join group +sql select sum(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 30 then + return -1 +endi + +sql_error select diff(a.col1) c1 from sta a left asof join sta b on a.ts > b.ts; +sql select diff(a.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts; +if $rows != 3 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi + +sql select diff(b.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts; +if $rows != 3 then + return -1 +endi +if $data00 != NULL then + return -1 +endi +if $data10 != 0 then + return -1 +endi +if $data20 != 2 then + return -1 +endi + +sql select csum(a.col1) from tba1 a left asof join tba2 b on a.ts > b.ts; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 4 then + return -1 +endi +if $data20 != 8 then + return -1 +endi +if $data30 != 13 then + return -1 +endi + +sql select csum(b.col1) from tba1 a left asof join tba2 b on a.ts > b.ts; +if $rows != 3 then + return -1 +endi +if $data00 != 3 then + return -1 +endi +if $data10 != 6 then + return -1 +endi +if $data20 != 11 then + return -1 +endi + +sql select count(a.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts interval(1s); +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +sql select count(a.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts session(a.ts, 1s); +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 3 then + return -1 +endi + +sql_error select count(a.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts session(b.ts, 1s); + +sql select count(a.col1) c1 from tba1 a left asof join tba2 b on a.ts > b.ts state_window(b.col1); + + + +#left win join + join group +sql select sum(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s); +if $rows != 8 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 6 then + return -1 +endi +if $data20 != 5 then + return -1 +endi +if $data30 != 7 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 6 then + return -1 +endi +if $data60 != 12 then + return -1 +endi +if $data70 != 10 then + return -1 +endi + +sql_error select diff(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s); +sql_error select csum(a.col1) from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s); + +sql_error select count(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s) interval(1s); +sql_error select count(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s) session(a.ts, 1s); +sql_error select count(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s) session(b.ts, 1s); +sql_error select count(a.col1) c1 from sta a left window join sta b on a.t1 = b.t1 window_offset(-1s, 1s) state_window(b.col1); + + +#left win join + no join group +sql select sum(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s) order by c1; +if $rows != 8 then + return -1 +endi +if $data00 != 3 then + return -1 +endi +if $data10 != 6 then + return -1 +endi +if $data20 != 12 then + return -1 +endi +if $data30 != 12 then + return -1 +endi +if $data40 != 14 then + return -1 +endi +if $data50 != 16 then + return -1 +endi +if $data60 != 20 then + return -1 +endi +if $data70 != 20 then + return -1 +endi + +sql_error select diff(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s); +sql select diff(a.col1) c1 from tba1 a left window join tba2 b window_offset(-1s, 0s); +if $rows != 0 then + return -1 +endi +sql select diff(b.col1) c1 from tba1 a left window join tba2 b window_offset(-1s, 0s); +if $rows != 0 then + return -1 +endi +sql select diff(b.col1) c1 from sta a left window join tba1 b window_offset(-1s, 1s); +if $rows != 7 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 1 then + return -1 +endi +if $data30 != 1 then + return -1 +endi +if $data40 != 1 then + return -1 +endi +if $data50 != 1 then + return -1 +endi +if $data60 != 1 then + return -1 +endi + +sql_error select csum(a.col1) from sta a left window join sta b window_offset(-1s, 1s); +sql_error select csum(a.col1) from tba1 a left window join tba2 b window_offset(-1s, 1s); +sql select csum(a.col1) from tba1 a left window join tba2 b window_offset(-1s, 0s); +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 3 then + return -1 +endi +if $data20 != 4 then + return -1 +endi +if $data30 != 5 then + return -1 +endi +sql select csum(b.col1) from tba1 a left window join tba2 b window_offset(-1s, 1s); +if $rows != 7 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +if $data20 != 3 then + return -1 +endi +if $data30 != 8 then + return -1 +endi +if $data40 != 5 then + return -1 +endi +if $data50 != 5 then + return -1 +endi +if $data60 != 12 then + return -1 +endi + +sql_error select count(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s) interval(1s); +sql_error select count(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s) session(a.ts, 1s); +sql_error select count(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s) session(b.ts, 1s); +sql_error select count(a.col1) c1 from sta a left window join sta b window_offset(-1s, 1s) state_window(b.col1); + + +#full join +sql select sum(a.col1) c1 from sta a full join sta b on a.ts = b.ts; +if $rows != 1 then + return -1 +endi +if $data00 != 42 then + return -1 +endi + +sql_error select diff(a.col1) c1 from tba1 a full join tba2 b on a.ts = b.ts; +sql_error select diff(b.col1) c1 from tba1 a full join tba2 b on a.ts = b.ts; +sql_error select csum(b.col1) from sta a full join sta b on a.ts = b.ts; +sql_error select csum(b.col1) from tba1 a full join tba2 b on a.ts = b.ts; +sql_error select count(a.col1) c1 from sta a full join sta b on a.ts = b.ts interval(1s); +sql_error select count(a.col1) c1 from sta a full join sta b on a.ts = b.ts session(a.ts, 1s); +sql_error select count(a.col1) c1 from sta a full join sta b on a.ts = b.ts session(b.ts, 1s); +sql_error select count(a.col1) c1 from sta a full join sta b on a.ts = b.ts state_window(b.col1); + diff --git a/tests/script/tsim/join/left_anti_join.sim b/tests/script/tsim/join/left_anti_join.sim index a04dcba9f9..fe8e64aae5 100644 --- a/tests/script/tsim/join/left_anti_join.sim +++ b/tests/script/tsim/join/left_anti_join.sim @@ -119,3 +119,73 @@ endi if $data11 != NULL then return -1 endi +if $data20 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi + +sql select a.ts, b.ts from sta a left anti join sta b on a.ts = b.ts and b.ts < '2023-11-17 16:29:03.000' order by b.ts desc; +if $rows != 4 then + return -1 +endi +if $data00 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi + +sql select a.ts, b.ts from sta a left anti join sta b on a.ts = b.ts and b.ts < '2023-11-17 16:29:03.000' order by a.ts desc, b.ts; +if $rows != 4 then + return -1 +endi +if $data00 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi diff --git a/tests/script/tsim/join/left_asof_join.sim b/tests/script/tsim/join/left_asof_join.sim index d9471c0468..b304fa1cfe 100644 --- a/tests/script/tsim/join/left_asof_join.sim +++ b/tests/script/tsim/join/left_asof_join.sim @@ -506,6 +506,69 @@ if $data31 != @23-11-17 16:29:03.000@ then return -1 endi +sql select a.ts, b.ts from tba1 a left asof join tba2 b on a.ts > b.ts and a.col1=b.col1 jlimit 2 order by a.ts desc; +if $rows != 4 then + return -1 +endi +if $data00 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi + +sql select a.ts, b.ts from tba1 a left asof join tba2 b on a.ts > b.ts and a.col1=b.col1 jlimit 2 order by b.ts desc; +if $rows != 4 then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data31 != NULL then + return -1 +endi + +sql select a.ts, b.ts from tba1 a left asof join tba2 b on a.ts > b.ts and a.col1=b.col1 jlimit 2 order by b.ts desc, a.ts; +if $rows != 4 then + return -1 +endi +if $data00 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:03.000@ then + return -1 +endi + sql select a.ts, b.ts from sta a left asof join sta b on a.ts > b.ts and a.col1=b.col1 jlimit 2 order by a.ts if $rows != 8 then return -1 @@ -1125,6 +1188,55 @@ if $data11 != @23-11-17 16:29:05.000@ then return -1 endi +sql select a.ts, b.ts from sta a left asof join sta b on a.ts < b.ts jlimit 2 order by b.ts desc; +if $rows != 14 then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:04.000@ then + return -1 +endi + +sql select a.ts, b.ts from sta a left asof join sta b on a.ts < b.ts jlimit 2 order by b.ts desc, a.ts; +if $rows != 14 then + return -1 +endi +if $data00 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data40 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data50 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data60 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data70 != @23-11-17 16:29:02.000@ then + return -1 +endi + sql select a.ts, b.ts from sta a left asof join sta b on a.ts = b.ts order by a.ts desc; if $rows != 8 then return -1 diff --git a/tests/script/tsim/join/left_join.sim b/tests/script/tsim/join/left_join.sim index 13e2774163..653f3bb0c1 100644 --- a/tests/script/tsim/join/left_join.sim +++ b/tests/script/tsim/join/left_join.sim @@ -204,3 +204,48 @@ if $data11 != @23-11-17 16:29:04.000@ then return -1 endi +sql select a.ts, b.ts from tba1 a left join tba2 b on a.ts=b.ts order by b.ts desc; +if $rows != 4 then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data31 != NULL then + return -1 +endi + +sql select a.ts, b.ts from tba1 a left join tba2 b on a.ts=b.ts order by b.ts desc, a.ts desc; +if $rows != 4 then + return -1 +endi +if $data00 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi diff --git a/tests/script/tsim/join/left_semi_join.sim b/tests/script/tsim/join/left_semi_join.sim index 27872ce0a3..5dfa38b032 100644 --- a/tests/script/tsim/join/left_semi_join.sim +++ b/tests/script/tsim/join/left_semi_join.sim @@ -108,6 +108,40 @@ if $data11 != @23-11-17 16:29:04.000@ then return -1 endi +sql select a.ts, b.ts from tba1 a left semi join tba2 b on a.ts = b.ts order by b.ts desc; +if $rows != 2 then + return -1 +endi +if $data00 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:00.000@ then + return -1 +endi + +sql select a.ts, b.ts from tba1 a left semi join tba2 b on a.ts = b.ts order by b.ts desc, a.ts; +if $rows != 2 then + return -1 +endi +if $data00 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:00.000@ then + return -1 +endi + sql_error select a.ts, b.ts from sta a left semi join sta b jlimit 3 where a.ts > b.ts; sql_error select a.ts, b.ts from sta a left semi join sta b where a.ts > b.ts; diff --git a/tests/script/tsim/join/left_win_join.sim b/tests/script/tsim/join/left_win_join.sim index 972c9e954c..0addf075d3 100644 --- a/tests/script/tsim/join/left_win_join.sim +++ b/tests/script/tsim/join/left_win_join.sim @@ -783,6 +783,51 @@ if $data21 != @23-11-17 16:29:04.000@ then return -1 endi +sql select a.ts, b.ts from sta a left window join sta b window_offset(1s, 2s) order by b.ts desc; +if $rows != 16 then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data51 != @23-11-17 16:29:04.000@ then + return -1 +endi +sql select a.ts, b.ts from sta a left window join sta b window_offset(1s, 2s) order by b.ts; +if $rows != 16 then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data11 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data51 != @23-11-17 16:29:02.000@ then + return -1 +endi + sql select a.ts, b.ts from sta a left window join sta b on a.t1=b.t1 window_offset(-2s, -1s) order by a.ts desc, b.ts; if $rows != 9 then return -1 diff --git a/tests/script/tsim/join/right_win_join.sim b/tests/script/tsim/join/right_win_join.sim index 07bed65655..1756783835 100644 --- a/tests/script/tsim/join/right_win_join.sim +++ b/tests/script/tsim/join/right_win_join.sim @@ -104,6 +104,105 @@ if $data61 != @23-11-17 16:29:05.000@ then return -1 endi +sql select a.ts, b.ts from tba1 a right window join tba2 b window_offset(-1s, 1s) order by b.ts desc; +if $rows != 7 then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data51 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data61 != @23-11-17 16:29:00.000@ then + return -1 +endi + +sql select a.ts, b.ts from tba1 a right window join tba2 b window_offset(-1s, 1s) order by a.ts desc; +if $rows != 7 then + return -1 +endi +if $data00 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data40 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data50 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data60 != @23-11-17 16:29:00.000@ then + return -1 +endi + +sql select a.ts, b.ts from tba1 a right window join tba2 b window_offset(-1s, 1s) order by b.ts desc, a.ts; +if $rows != 7 then + return -1 +endi +if $data00 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data01 != @23-11-17 16:29:05.000@ then + return -1 +endi +if $data10 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data11 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data20 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data21 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data30 != @23-11-17 16:29:04.000@ then + return -1 +endi +if $data31 != @23-11-17 16:29:03.000@ then + return -1 +endi +if $data40 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data41 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data50 != @23-11-17 16:29:02.000@ then + return -1 +endi +if $data51 != @23-11-17 16:29:01.000@ then + return -1 +endi +if $data60 != @23-11-17 16:29:00.000@ then + return -1 +endi +if $data61 != @23-11-17 16:29:00.000@ then + return -1 +endi + sql select a.ts, b.ts from tba1 a right window join tba2 b window_offset(-1s, 1s) jlimit 1; if $rows != 4 then return -1