homework-jianmu/source/libs/executor/test/joinTests.cpp

3781 lines
108 KiB
C++
Executable File

/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include <iostream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wformat"
#include <addr_any.h>
#ifdef WINDOWS
#define TD_USE_WINSOCK
#endif
#include "os.h"
#include "executor.h"
#include "executorInt.h"
#include "function.h"
#include "operator.h"
#include "taos.h"
#include "tdatablock.h"
#include "tdef.h"
#include "tvariant.h"
#include "stub.h"
#include "querytask.h"
namespace {
typedef struct {
bool succeed;
int32_t blkNum;
int32_t rowNum;
int32_t addRowNum;
int32_t subRowNum;
int32_t matchNum;
} SJoinTestResInfo;
typedef struct {
int32_t maxResRows;
int32_t maxResBlkRows;
int64_t totalResRows;
int64_t useMSecs;
SArray* pHistory;
} SJoinTestStat;
enum {
TEST_NO_COND = 1,
TEST_EQ_COND,
TEST_ON_COND,
TEST_FULL_COND
};
#define JT_PRINTF (void)printf
#define COL_DISPLAY_WIDTH 18
#define JT_MAX_LOOP 1000
#define LEFT_BLK_ID 0
#define RIGHT_BLK_ID 1
#define RES_BLK_ID 2
#define MAX_SLOT_NUM 4
#define LEFT_TABLE_COLS 0x1
#define RIGHT_TABLE_COLS 0x2
#define ALL_TABLE_COLS (LEFT_TABLE_COLS | RIGHT_TABLE_COLS)
#define JT_MAX_JLIMIT 20
#define JT_MAX_WINDOW_OFFSET 5
#define JT_KEY_SOLT_ID (MAX_SLOT_NUM - 1)
#define JT_PRIM_TS_SLOT_ID 0
int32_t jtInputColType[MAX_SLOT_NUM] = {TSDB_DATA_TYPE_TIMESTAMP, TSDB_DATA_TYPE_INT, TSDB_DATA_TYPE_INT, TSDB_DATA_TYPE_BIGINT};
char* jtColCondStr[] = {"", "NO COND", "EQ COND", "ON COND", "FULL COND"};
char* jtJoinTypeStr[] = {"INNER", "LEFT", "RIGHT", "FULL"};
char* jtSubTypeStr[] = {"", "OUTER", "SEMI", "ANTI", "ASOF", "WINDOW"};
int64_t TIMESTAMP_FILTER_VALUE = 10000000000;
int32_t INT_FILTER_VALUE = 200000000;
int64_t BIGINT_FILTER_VALUE = 3000000000000000;
int64_t jtFilterValue[] = {TIMESTAMP_FILTER_VALUE, INT_FILTER_VALUE, INT_FILTER_VALUE, BIGINT_FILTER_VALUE};
bool jtErrorRerun = false;
bool jtInRerun = false;
typedef struct {
bool printTestInfo;
bool printInputRow;
bool printResRow;
bool logHistory;
bool noKeepResRows;
} SJoinTestCtrl;
typedef struct {
bool filter;
bool asc;
bool grpJoin;
int32_t leftMaxRows;
int32_t leftMaxGrpRows;
int32_t rightMaxRows;
int32_t rightMaxGrpRows;
int32_t blkRows;
int32_t colCond;
int32_t joinType;
int32_t subType;
int32_t asofOpType;
int64_t jLimit;
int64_t winStartOffset;
int64_t winEndOffset;
int64_t inGrpId;
int32_t leftTotalRows;
int32_t rightTotalRows;
int32_t blkRowSize;
int32_t inputStat;
int32_t colEqNum;
int32_t colEqList[MAX_SLOT_NUM];
int32_t colOnNum;
int32_t colOnList[MAX_SLOT_NUM];
int32_t leftFilterNum;
int32_t leftFilterColList[MAX_SLOT_NUM];
int32_t rightFilterNum;
int32_t rightFilterColList[MAX_SLOT_NUM];
int32_t keyInSlotIdx;
int32_t keyOutSlotIdx;
int32_t keyColOffset;
int32_t resColNum;
int32_t resColInSlot[MAX_SLOT_NUM * 2];
int32_t resColList[MAX_SLOT_NUM * 2];
int32_t resColOffset[MAX_SLOT_NUM * 2];
int32_t resColSize;
char* resColBuf;
int32_t colRowDataBufSize;
char* colRowDataBuf;
int32_t colRowOffset[MAX_SLOT_NUM];
int64_t curTs;
int64_t curKeyOffset;
int32_t grpOffset[MAX_SLOT_NUM];
int32_t leftBlkReadIdx;
SArray* leftBlkList;
int32_t rightBlkReadIdx;
SArray* rightBlkList;
int64_t resRows;
bool leftColOnly;
bool rightColOnly;
SSHashObj* jtResRows;
SOperatorInfo* pJoinOp;
int32_t loopIdx;
int32_t rightFinMatchNum;
bool* rightFinMatch;
int32_t inColOffset[MAX_SLOT_NUM];
int32_t inColSize;
char* inColBuf;
SArray* leftRowsList;
SArray* rightRowsList;
SArray* rightFilterOut;
int64_t startTsUs;
} SJoinTestCtx;
typedef struct {
SJoinTestResInfo res;
SJoinTestCtx ctx;
} SJoinTestHistory;
typedef struct {
EJoinType joinType;
EJoinSubType subType;
int32_t asofOp;
int64_t jLimit;
int32_t cond;
bool filter;
bool asc;
bool grpJoin;
bool timetruncate;
SExecTaskInfo* pTask;
} SJoinTestParam;
SJoinTestCtx jtCtx = {0};
SJoinTestCtrl jtCtrl = {0, 0, 0, 0, 0};
SJoinTestStat jtStat = {0};
SJoinTestResInfo jtRes = {0};
void printResRow(char* value, int32_t type) {
if (!jtCtrl.printResRow) {
return;
}
JT_PRINTF(" ");
for (int32_t i = 0; i < jtCtx.resColNum; ++i) {
int32_t slot = jtCtx.resColInSlot[i];
if (0 == type && ((jtCtx.leftColOnly && slot >= MAX_SLOT_NUM) ||
(jtCtx.rightColOnly && slot < MAX_SLOT_NUM))) {
("%18s", " ");
continue;
}
if (*(bool*)(value + slot)) {
JT_PRINTF("%18s", " NULL");
continue;
}
switch (jtInputColType[slot % MAX_SLOT_NUM]) {
case TSDB_DATA_TYPE_TIMESTAMP:
JT_PRINTF("%18" PRId64 , *(int64_t*)(value + jtCtx.resColOffset[slot]));
break;
case TSDB_DATA_TYPE_INT:
JT_PRINTF("%18d", *(int32_t*)(value + jtCtx.resColOffset[slot]));
break;
case TSDB_DATA_TYPE_BIGINT:
JT_PRINTF("%18" PRId64, *(int64_t*)(value + jtCtx.resColOffset[slot]));
break;
}
}
JT_PRINTF("\t %s\n", 0 == type ? "-" : (1 == type ? "+" : ""));
}
void pushResRow(char* buf, int32_t size) {
jtCtx.resRows++;
if (!jtCtrl.noKeepResRows) {
int32_t* rows = (int32_t*)tSimpleHashGet(jtCtx.jtResRows, buf, size);
if (rows) {
(*rows)++;
} else {
int32_t n = 1;
assert(0 == tSimpleHashPut(jtCtx.jtResRows, buf, size, &n, sizeof(n)));
}
}
}
void rmResRow() {
int32_t* rows = (int32_t*)tSimpleHashGet(jtCtx.jtResRows, jtCtx.resColBuf, jtCtx.resColSize);
if (rows) {
(*rows)--;
if ((*rows) == 0) {
(void)tSimpleHashRemove(jtCtx.jtResRows, jtCtx.resColBuf, jtCtx.resColSize);
}
} else {
assert(0);
}
}
static int32_t jtMergeEqCond(SNode** ppDst, SNode** ppSrc) {
if (NULL == *ppSrc) {
return TSDB_CODE_SUCCESS;
}
if (NULL == *ppDst) {
*ppDst = *ppSrc;
*ppSrc = NULL;
return TSDB_CODE_SUCCESS;
}
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*ppSrc)) {
TSWAP(*ppDst, *ppSrc);
}
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*ppDst)) {
SLogicConditionNode* pLogic = (SLogicConditionNode*)*ppDst;
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*ppSrc)) {
assert(0 == nodesListStrictAppendList(pLogic->pParameterList, ((SLogicConditionNode*)(*ppSrc))->pParameterList));
((SLogicConditionNode*)(*ppSrc))->pParameterList = NULL;
} else {
assert(0 == nodesListStrictAppend(pLogic->pParameterList, *ppSrc));
*ppSrc = NULL;
}
nodesDestroyNode(*ppSrc);
*ppSrc = NULL;
return TSDB_CODE_SUCCESS;
}
SLogicConditionNode* pLogicCond = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogicCond);
if (NULL == pLogicCond) {
return code;
}
pLogicCond->node.resType.type = TSDB_DATA_TYPE_BOOL;
pLogicCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pLogicCond->condType = LOGIC_COND_TYPE_AND;
pLogicCond->pParameterList = NULL;
code = nodesMakeList(&pLogicCond->pParameterList);
assert(0 == nodesListStrictAppend(pLogicCond->pParameterList, *ppSrc));
assert(0 == nodesListStrictAppend(pLogicCond->pParameterList, *ppDst));
*ppDst = (SNode*)pLogicCond;
*ppSrc = NULL;
return TSDB_CODE_SUCCESS;
}
void createDummyDownstreamOperators(int32_t num, SOperatorInfo** ppRes) {
for (int32_t i = 0; i < num; ++i) {
SOperatorInfo* p = (SOperatorInfo*)taosMemoryCalloc(1, sizeof(SOperatorInfo));
assert(NULL != p);
p->resultDataBlockId = i;
ppRes[i] = p;
}
}
void createTargetSlotList(SSortMergeJoinPhysiNode* p) {
jtCtx.resColNum = 0;
TAOS_MEMSET(jtCtx.resColList, 0, sizeof(jtCtx.resColList));
jtCtx.resColSize = MAX_SLOT_NUM * 2 * sizeof(bool);
jtCtx.keyInSlotIdx = -1;
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.colOnList[i] || jtCtx.colEqList[i] || jtCtx.leftFilterColList[i]) {
jtCtx.resColList[i] = 1;
}
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.colOnList[i] || jtCtx.colEqList[i] || jtCtx.rightFilterColList[i]) {
jtCtx.resColList[MAX_SLOT_NUM + i] = 1;
}
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (0 == jtCtx.resColList[i]) {
jtCtx.resColList[i]= taosRand() % 2;
}
if ((jtCtx.joinType == JOIN_TYPE_LEFT || jtCtx.joinType == JOIN_TYPE_FULL) && (i == JT_KEY_SOLT_ID)) {
jtCtx.resColList[i] = 1;
}
if (jtCtx.resColList[i] && i == JT_KEY_SOLT_ID && (jtCtx.joinType == JOIN_TYPE_LEFT || jtCtx.joinType == JOIN_TYPE_FULL)) {
jtCtx.keyInSlotIdx = JT_KEY_SOLT_ID;
}
}
if (jtCtx.keyInSlotIdx < 0 || ((jtCtx.joinType == JOIN_TYPE_RIGHT || jtCtx.joinType == JOIN_TYPE_FULL))) {
jtCtx.resColList[MAX_SLOT_NUM + JT_KEY_SOLT_ID]= 1;
jtCtx.keyInSlotIdx = JT_KEY_SOLT_ID + MAX_SLOT_NUM;
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (0 == jtCtx.resColList[MAX_SLOT_NUM + i]) {
jtCtx.resColList[MAX_SLOT_NUM + i]= taosRand() % 2;
}
}
int32_t idx = 0;
int32_t dstIdx = 0;
int32_t dstOffset = jtCtx.resColSize;
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.resColList[i]) {
jtCtx.resColOffset[i] = dstOffset;
jtCtx.resColInSlot[dstIdx] = i;
if (jtCtx.keyInSlotIdx == i) {
jtCtx.keyColOffset = dstOffset;
}
STargetNode* pTarget = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_TARGET, (SNode**)&pTarget);
SColumnNode* pCol = NULL;
code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
assert(NULL != pTarget && NULL != pCol);
pCol->dataBlockId = LEFT_BLK_ID;
pCol->slotId = i;
pTarget->dataBlockId = RES_BLK_ID;
pTarget->slotId = dstIdx++;
pTarget->pExpr = (SNode*)pCol;
dstOffset += tDataTypes[jtInputColType[i]].bytes;
jtCtx.resColSize += tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesListMakeStrictAppend(&p->pTargets, (SNode*)pTarget));
jtCtx.resColNum++;
}
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.resColList[MAX_SLOT_NUM + i]) {
jtCtx.resColOffset[MAX_SLOT_NUM + i] = dstOffset;
jtCtx.resColInSlot[dstIdx] = i + MAX_SLOT_NUM;
if (jtCtx.keyInSlotIdx == (i + MAX_SLOT_NUM)) {
jtCtx.keyColOffset = dstOffset;
}
STargetNode* pTarget = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_TARGET, (SNode**)&pTarget);
SColumnNode* pCol = NULL;
code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
assert(NULL != pTarget && NULL != pCol);
pCol->dataBlockId = RIGHT_BLK_ID;
pCol->slotId = i;
pTarget->dataBlockId = RES_BLK_ID;
pTarget->slotId = dstIdx++;
pTarget->pExpr = (SNode*)pCol;
dstOffset += tDataTypes[jtInputColType[i]].bytes;
jtCtx.resColSize += tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesListMakeStrictAppend(&p->pTargets, (SNode*)pTarget));
jtCtx.resColNum++;
}
}
jtCtx.resColBuf = (char*)taosMemoryRealloc(jtCtx.resColBuf, jtCtx.resColSize);
assert(NULL != jtCtx.resColBuf);
}
void createColEqCondStart(SSortMergeJoinPhysiNode* p) {
jtCtx.colEqNum = 0;
do {
jtCtx.colEqNum = taosRand() % MAX_SLOT_NUM; // except TIMESTAMP
} while (0 == jtCtx.colEqNum);
int32_t idx = 0;
TAOS_MEMSET(jtCtx.colEqList, 0, sizeof(jtCtx.colEqList));
for (int32_t i = 0; i < jtCtx.colEqNum; ) {
idx = taosRand() % MAX_SLOT_NUM;
if (jtCtx.colEqList[idx]) {
continue;
}
if (TSDB_DATA_TYPE_TIMESTAMP == jtInputColType[idx]) {
continue;
}
jtCtx.colEqList[idx] = 1;
++i;
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.colEqList[i]) {
SColumnNode* pCol1 = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol1);
assert(pCol1);
pCol1->dataBlockId = LEFT_BLK_ID;
pCol1->slotId = i;
pCol1->node.resType.type = jtInputColType[i];
pCol1->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesListMakeStrictAppend(&p->pEqLeft, (SNode*)pCol1));
SColumnNode* pCol2 = NULL;
code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol2);
pCol2->dataBlockId = RIGHT_BLK_ID;
pCol2->slotId = i;
pCol2->node.resType.type = jtInputColType[i];
pCol2->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesListMakeStrictAppend(&p->pEqRight, (SNode*)pCol2));
}
}
}
void createColOnCondStart(SSortMergeJoinPhysiNode* p) {
jtCtx.colOnNum = 0;
do {
jtCtx.colOnNum = taosRand() % (MAX_SLOT_NUM + 1);
} while (0 == jtCtx.colOnNum || (jtCtx.colOnNum + jtCtx.colEqNum) > MAX_SLOT_NUM);
int32_t idx = 0;
TAOS_MEMSET(jtCtx.colOnList, 0, sizeof(jtCtx.colOnList));
for (int32_t i = 0; i < jtCtx.colOnNum; ) {
idx = taosRand() % MAX_SLOT_NUM;
if (jtCtx.colOnList[idx] || jtCtx.colEqList[idx]) {
continue;
}
jtCtx.colOnList[idx] = 1;
++i;
}
}
int32_t getDstSlotId(int32_t srcIdx) {
for (int32_t i = 0; i < jtCtx.resColNum; ++i) {
if (jtCtx.resColInSlot[i] == srcIdx) {
return i;
}
}
return -1;
}
void createColEqCondEnd(SSortMergeJoinPhysiNode* p) {
if (jtCtx.colEqNum <= 0) {
return;
}
SLogicConditionNode* pLogic = NULL;
if (jtCtx.colEqNum > 1) {
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogic);
assert(pLogic);
pLogic->node.resType.type = TSDB_DATA_TYPE_BOOL;
pLogic->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pLogic->condType = LOGIC_COND_TYPE_AND;
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.colEqList[i]) {
SColumnNode* pCol1 = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol1);
assert(pCol1);
pCol1->dataBlockId = RES_BLK_ID;
pCol1->slotId = getDstSlotId(i);
pCol1->node.resType.type = jtInputColType[i];
pCol1->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
SColumnNode* pCol2 = NULL;
code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol2);
assert(pCol2);
pCol2->dataBlockId = RES_BLK_ID;
pCol2->slotId = getDstSlotId(MAX_SLOT_NUM + i);
pCol2->node.resType.type = jtInputColType[i];
pCol2->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
SOperatorNode* pOp = NULL;
code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOp);
assert(pOp);
pOp->opType = OP_TYPE_EQUAL;
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pOp->pLeft = (SNode*)pCol1;
pOp->pRight = (SNode*)pCol2;
if (jtCtx.colEqNum > 1) {
assert(0 == nodesListMakeStrictAppend(&pLogic->pParameterList, (SNode*)pOp));
} else {
p->pFullOnCond = (SNode*)pOp;
break;
}
}
}
if (jtCtx.colEqNum > 1) {
p->pFullOnCond = (SNode*)pLogic;
}
}
void createColOnCondEnd(SSortMergeJoinPhysiNode* p) {
if (jtCtx.colOnNum <= 0) {
return;
}
SLogicConditionNode* pLogic = NULL;
if (jtCtx.colOnNum > 1) {
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogic);
assert(pLogic);
pLogic->node.resType.type = TSDB_DATA_TYPE_BOOL;
pLogic->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pLogic->condType = LOGIC_COND_TYPE_AND;
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.colOnList[i]) {
SColumnNode* pCol1 = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol1);
assert(pCol1);
pCol1->dataBlockId = RES_BLK_ID;
pCol1->slotId = getDstSlotId(i);
pCol1->node.resType.type = jtInputColType[i];
pCol1->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
SColumnNode* pCol2 = NULL;
code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol2);
assert(pCol2);
pCol2->dataBlockId = RES_BLK_ID;
pCol2->slotId = getDstSlotId(MAX_SLOT_NUM + i);
pCol2->node.resType.type = jtInputColType[i];
pCol2->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
SOperatorNode* pOp = NULL;
code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOp);
assert(pOp);
pOp->opType = OP_TYPE_GREATER_THAN;
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pOp->pLeft = (SNode*)pCol1;
pOp->pRight = (SNode*)pCol2;
if (jtCtx.colOnNum > 1) {
assert(0 == nodesListMakeStrictAppend(&pLogic->pParameterList, (SNode*)pOp));
} else {
p->pColOnCond = (SNode*)pOp;
break;
}
}
}
if (jtCtx.colOnNum > 1) {
p->pColOnCond = (SNode*)pLogic;
}
SNode* pTmp = NULL;
int32_t code = nodesCloneNode(p->pColOnCond, &pTmp);
assert(pTmp);
assert(0 == jtMergeEqCond(&p->pFullOnCond, &pTmp));
}
void createColCond(SSortMergeJoinPhysiNode* p, int32_t cond) {
jtCtx.colCond = cond;
switch (cond) {
case TEST_NO_COND:
jtCtx.colEqNum = 0;
jtCtx.colOnNum = 0;
TAOS_MEMSET(jtCtx.colEqList, 0, sizeof(jtCtx.colEqList));
TAOS_MEMSET(jtCtx.colOnList, 0, sizeof(jtCtx.colOnList));
break;
case TEST_EQ_COND:
createColEqCondStart(p);
jtCtx.colOnNum = 0;
TAOS_MEMSET(jtCtx.colOnList, 0, sizeof(jtCtx.colOnList));
break;
case TEST_ON_COND:
createColOnCondStart(p);
jtCtx.colEqNum = 0;
TAOS_MEMSET(jtCtx.colEqList, 0, sizeof(jtCtx.colEqList));
break;
case TEST_FULL_COND:
createColEqCondStart(p);
createColOnCondStart(p);
break;
default:
break;
}
}
void* getFilterValue(int32_t type) {
switch (type) {
case TSDB_DATA_TYPE_TIMESTAMP:
return &TIMESTAMP_FILTER_VALUE;
case TSDB_DATA_TYPE_INT:
return &INT_FILTER_VALUE;
case TSDB_DATA_TYPE_BIGINT:
return &BIGINT_FILTER_VALUE;
default:
return NULL;
}
}
void createFilterStart(SSortMergeJoinPhysiNode* p, bool filter) {
jtCtx.filter = filter;
if (!filter) {
jtCtx.leftFilterNum = 0;
jtCtx.rightFilterNum = 0;
TAOS_MEMSET(jtCtx.leftFilterColList, 0, sizeof(jtCtx.leftFilterColList));
TAOS_MEMSET(jtCtx.rightFilterColList, 0, sizeof(jtCtx.rightFilterColList));
return;
}
if ((JOIN_STYPE_SEMI == jtCtx.subType || JOIN_STYPE_ANTI == jtCtx.subType) && JOIN_TYPE_LEFT == jtCtx.joinType) {
jtCtx.rightFilterNum = 0;
jtCtx.leftFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
if (0 == jtCtx.leftFilterNum) {
do {
jtCtx.leftFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
} while (0 == jtCtx.leftFilterNum);
}
} else if ((JOIN_STYPE_SEMI == jtCtx.subType || JOIN_STYPE_ANTI == jtCtx.subType) && JOIN_TYPE_RIGHT == jtCtx.joinType) {
jtCtx.leftFilterNum = 0;
jtCtx.rightFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
if (0 == jtCtx.rightFilterNum) {
do {
jtCtx.rightFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
} while (0 == jtCtx.rightFilterNum);
}
} else {
jtCtx.leftFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
if (0 == jtCtx.leftFilterNum) {
do {
jtCtx.rightFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
} while (0 == jtCtx.rightFilterNum);
} else {
jtCtx.rightFilterNum = taosRand() % (MAX_SLOT_NUM + 1);
}
}
int32_t idx = 0;
TAOS_MEMSET(jtCtx.leftFilterColList, 0, sizeof(jtCtx.leftFilterColList));
TAOS_MEMSET(jtCtx.rightFilterColList, 0, sizeof(jtCtx.rightFilterColList));
for (int32_t i = 0; i < jtCtx.leftFilterNum; ) {
idx = taosRand() % MAX_SLOT_NUM;
if (jtCtx.leftFilterColList[idx]) {
continue;
}
jtCtx.leftFilterColList[idx] = 1;
++i;
}
for (int32_t i = 0; i < jtCtx.rightFilterNum; ) {
idx = taosRand() % MAX_SLOT_NUM;
if (jtCtx.rightFilterColList[idx]) {
continue;
}
jtCtx.rightFilterColList[idx] = 1;
++i;
}
}
void createFilterEnd(SSortMergeJoinPhysiNode* p, bool filter) {
if (!filter || (jtCtx.leftFilterNum <= 0 && jtCtx.rightFilterNum <= 0)) {
return;
}
SLogicConditionNode* pLogic = NULL;
if ((jtCtx.leftFilterNum + jtCtx.rightFilterNum) > 1) {
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogic);
assert(pLogic);
pLogic->node.resType.type = TSDB_DATA_TYPE_BOOL;
pLogic->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pLogic->condType = LOGIC_COND_TYPE_AND;
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.leftFilterColList[i]) {
SColumnNode* pCol = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_COLUMN,(SNode**)&pCol);
assert(pCol);
pCol->dataBlockId = RES_BLK_ID;
pCol->slotId = getDstSlotId(i);
pCol->node.resType.type = jtInputColType[i];
pCol->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
(void)sprintf(pCol->colName, "l%d", i);
SValueNode* pVal = NULL;
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pVal);
assert(pVal);
pVal->node.resType.type = jtInputColType[i];
pVal->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesSetValueNodeValue(pVal, getFilterValue(jtInputColType[i])));
SOperatorNode* pOp = NULL;
code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOp);
assert(pOp);
pOp->opType = OP_TYPE_GREATER_THAN;
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pOp->pLeft = (SNode*)pCol;
pOp->pRight = (SNode*)pVal;
if ((jtCtx.leftFilterNum + jtCtx.rightFilterNum) > 1) {
assert(0 == nodesListMakeStrictAppend(&pLogic->pParameterList, (SNode*)pOp));
} else {
p->node.pConditions = (SNode*)pOp;
break;
}
}
}
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (jtCtx.rightFilterColList[i]) {
SColumnNode* pCol = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
assert(pCol);
pCol->dataBlockId = RES_BLK_ID;
pCol->slotId = getDstSlotId(MAX_SLOT_NUM + i);
pCol->node.resType.type = jtInputColType[i];
pCol->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
(void)sprintf(pCol->colName, "r%d", i);
SValueNode* pVal = NULL;
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pVal);
assert(pVal);
pVal->node.resType.type = jtInputColType[i];
pVal->node.resType.bytes = tDataTypes[jtInputColType[i]].bytes;
assert(0 == nodesSetValueNodeValue(pVal, getFilterValue(jtInputColType[i])));
SOperatorNode* pOp = NULL;
code = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&pOp);
assert(pOp);
pOp->opType = OP_TYPE_GREATER_THAN;
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
pOp->pLeft = (SNode*)pCol;
pOp->pRight = (SNode*)pVal;
if ((jtCtx.leftFilterNum + jtCtx.rightFilterNum) > 1) {
assert(0 == nodesListMakeStrictAppend(&pLogic->pParameterList, (SNode*)pOp));
} else {
p->node.pConditions = (SNode*)pOp;
break;
}
}
}
if ((jtCtx.leftFilterNum + jtCtx.rightFilterNum) > 1) {
p->node.pConditions = (SNode*)pLogic;
}
}
void updateColRowInfo() {
jtCtx.blkRowSize = MAX_SLOT_NUM * sizeof(bool);
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
jtCtx.colRowOffset[i] = jtCtx.blkRowSize;
jtCtx.blkRowSize += tDataTypes[jtInputColType[i]].bytes;
}
}
void createBlockDescNode(SDataBlockDescNode** ppNode) {
SDataBlockDescNode* pDesc = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_DATABLOCK_DESC, (SNode**)&pDesc);
assert(pDesc);
pDesc->dataBlockId = RES_BLK_ID;
pDesc->totalRowSize = jtCtx.resColSize - MAX_SLOT_NUM * 2 * sizeof(bool);
pDesc->outputRowSize = pDesc->totalRowSize;
for (int32_t i = 0; i < jtCtx.resColNum; ++i) {
SSlotDescNode* pSlot = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_SLOT_DESC, (SNode**)&pSlot);
assert(pSlot);
pSlot->slotId = i;
int32_t slotIdx = jtCtx.resColInSlot[i] >= MAX_SLOT_NUM ? jtCtx.resColInSlot[i] - MAX_SLOT_NUM : jtCtx.resColInSlot[i];
pSlot->dataType.type = jtInputColType[slotIdx];
pSlot->dataType.bytes = tDataTypes[pSlot->dataType.type].bytes;
assert(0 == nodesListMakeStrictAppend(&pDesc->pSlots, (SNode *)pSlot));
}
*ppNode = pDesc;
}
SSortMergeJoinPhysiNode* createDummySortMergeJoinPhysiNode(SJoinTestParam* param) {
SSortMergeJoinPhysiNode* p = NULL;
int32_t code = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN, (SNode**)&p);
assert(p);
p->joinType = param->joinType;
p->subType = param->subType;
p->asofOpType = param->asofOp;
p->grpJoin = param->grpJoin;
if (p->subType == JOIN_STYPE_WIN || param->jLimit > 1 || taosRand() % 2) {
SLimitNode* limitNode = NULL;
code = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
assert(limitNode);
limitNode->limit = param->jLimit;
p->pJLimit = (SNode*)limitNode;
}
p->leftPrimSlotId = JT_PRIM_TS_SLOT_ID;
p->rightPrimSlotId = JT_PRIM_TS_SLOT_ID;
p->node.inputTsOrder = param->asc ? ORDER_ASC : ORDER_DESC;
if (JOIN_STYPE_WIN == p->subType) {
SWindowOffsetNode* pOffset = NULL;
code = nodesMakeNode(QUERY_NODE_WINDOW_OFFSET, (SNode**)&pOffset);
assert(pOffset);
SValueNode* pStart = NULL;
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pStart);
assert(pStart);
SValueNode* pEnd = NULL;
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pEnd);
assert(pEnd);
pStart->node.resType.type = TSDB_DATA_TYPE_BIGINT;
pStart->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
pStart->datum.i = (taosRand() % 2) ? (((int32_t)-1) * (int64_t)(taosRand() % JT_MAX_WINDOW_OFFSET)) : (taosRand() % JT_MAX_WINDOW_OFFSET);
pEnd->node.resType.type = TSDB_DATA_TYPE_BIGINT;
pEnd->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
pEnd->datum.i = (taosRand() % 2) ? (((int32_t)-1) * (int64_t)(taosRand() % JT_MAX_WINDOW_OFFSET)) : (taosRand() % JT_MAX_WINDOW_OFFSET);
if (pStart->datum.i > pEnd->datum.i) {
TSWAP(pStart->datum.i, pEnd->datum.i);
}
pOffset->pStartOffset = (SNode*)pStart;
pOffset->pEndOffset = (SNode*)pEnd;
p->pWindowOffset = (SNode*)pOffset;
jtCtx.winStartOffset = pStart->datum.i;
jtCtx.winEndOffset = pEnd->datum.i;
}
jtCtx.grpJoin = param->grpJoin;
jtCtx.joinType = param->joinType;
jtCtx.subType = param->subType;
jtCtx.asc = param->asc;
jtCtx.jLimit = param->jLimit;
jtCtx.asofOpType = param->asofOp;
jtCtx.leftColOnly = (JOIN_TYPE_LEFT == param->joinType && JOIN_STYPE_SEMI == param->subType);
jtCtx.rightColOnly = (JOIN_TYPE_RIGHT == param->joinType && JOIN_STYPE_SEMI == param->subType);
jtCtx.inGrpId = 1;
createColCond(p, param->cond);
createFilterStart(p, param->filter);
createTargetSlotList(p);
createColEqCondEnd(p);
createColOnCondEnd(p);
createFilterEnd(p, param->filter);
updateColRowInfo();
createBlockDescNode(&p->node.pOutputDataBlockDesc);
return p;
}
SExecTaskInfo* createDummyTaskInfo(char* taskId) {
SExecTaskInfo* p = (SExecTaskInfo*)taosMemoryCalloc(1, sizeof(SExecTaskInfo));
assert(p);
p->id.str = taskId;
return p;
}
SSDataBlock* createDummyBlock(int32_t blkId) {
SSDataBlock* p = NULL;
int32_t code = createDataBlock(&p);
assert(code == 0);
p->info.id.blockId = blkId;
p->info.type = STREAM_INVALID;
p->info.calWin.skey = INT64_MIN;
p->info.calWin.ekey = INT64_MAX;
p->info.watermark = INT64_MIN;
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
SColumnInfoData idata =
createColumnInfoData(jtInputColType[i], tDataTypes[jtInputColType[i]].bytes, i);
assert(0 == blockDataAppendColInfo(p, &idata));
}
return p;
}
void appendAsofLeftEachResGrps(char* leftInRow, int32_t rightOffset, int32_t rightRows) {
TAOS_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 {
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[c], leftInRow + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes);
}
}
int32_t endIdx = TMIN(rightRows, taosArrayGetSize(jtCtx.rightRowsList) - rightOffset) + rightOffset;
for (int32_t r = rightOffset; r < endIdx; ++r) {
bool* rightFilterOut = (bool*)taosArrayGet(jtCtx.rightFilterOut, r);
if (*rightFilterOut) {
continue;
}
char* rightResRows = (char*)taosArrayGet(jtCtx.rightRowsList, r);
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
if (jtCtx.resColList[MAX_SLOT_NUM + c]) {
if (*(bool*)(rightResRows + c)) {
*(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true;
TAOS_MEMSET(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], 0, tDataTypes[jtInputColType[c]].bytes);
} else {
*(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = false;
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], rightResRows + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes);
}
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
}
void appendLeftNonMatchGrp(char* leftInRow) {
if (!jtCtrl.noKeepResRows) {
TAOS_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 {
TAOS_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;
}
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
void appendAllAsofResRows() {
int32_t leftRows = taosArrayGetSize(jtCtx.leftRowsList);
int32_t rightRows = taosArrayGetSize(jtCtx.rightRowsList);
if (rightRows <= 0) {
if (0 == jtCtx.rightFilterNum) {
for (int32_t i = 0; i < leftRows; ++i) {
char* leftInRow = (char*)taosArrayGet(jtCtx.leftRowsList, i);
assert(leftInRow);
appendLeftNonMatchGrp(leftInRow);
}
}
} else {
assert(rightRows <= jtCtx.jLimit);
for (int32_t i = 0; i < leftRows; ++i) {
char* leftInRow = (char*)taosArrayGet(jtCtx.leftRowsList, i);
assert(leftInRow);
appendAsofLeftEachResGrps(leftInRow, 0, rightRows);
}
}
taosArrayClear(jtCtx.leftRowsList);
}
void chkAppendAsofForwardGrpResRows(bool forceOut) {
int32_t rightRows = taosArrayGetSize(jtCtx.rightRowsList);
if (rightRows < jtCtx.jLimit && !forceOut) {
return;
}
int32_t rightRemains = rightRows;
int32_t rightOffset = 0;
int32_t leftRows = taosArrayGetSize(jtCtx.leftRowsList);
int32_t i = 0;
for (; i < leftRows; ++i) {
char* leftRow = (char*)taosArrayGet(jtCtx.leftRowsList, i);
assert(leftRow);
int64_t* leftTs = (int64_t*)(leftRow + jtCtx.inColOffset[JT_PRIM_TS_SLOT_ID]);
bool append = false;
for (int32_t r = rightOffset; r < rightRows; ++r) {
char* rightRow = (char*)taosArrayGet(jtCtx.rightRowsList, r);
assert(rightRow);
int64_t* rightTs = (int64_t*)(rightRow + jtCtx.inColOffset[JT_PRIM_TS_SLOT_ID]);
if (((jtCtx.asc && *leftTs > *rightTs) || (!jtCtx.asc && *leftTs < *rightTs)) || (*leftTs == *rightTs && (OP_TYPE_LOWER_THAN == jtCtx.asofOpType || OP_TYPE_GREATER_THAN == jtCtx.asofOpType))) {
rightOffset++;
rightRemains--;
if (rightRemains < jtCtx.jLimit && !forceOut) {
taosArrayPopFrontBatch(jtCtx.rightRowsList, rightOffset);
taosArrayPopFrontBatch(jtCtx.rightFilterOut, rightOffset);
taosArrayPopFrontBatch(jtCtx.leftRowsList, i);
return;
}
continue;
}
appendAsofLeftEachResGrps(leftRow, rightOffset, jtCtx.jLimit);
append = true;
break;
}
if (!append) {
if (!forceOut) {
break;
}
if (0 == jtCtx.rightFilterNum) {
appendLeftNonMatchGrp(leftRow);
}
}
}
taosArrayPopFrontBatch(jtCtx.rightRowsList, rightOffset);
taosArrayPopFrontBatch(jtCtx.rightFilterOut, rightOffset);
taosArrayPopFrontBatch(jtCtx.leftRowsList, i);
}
void appendWinEachResGrps(char* leftInRow, int32_t rightOffset, int32_t rightRows) {
if (rightOffset < 0) {
if (0 == jtCtx.rightFilterNum) {
appendLeftNonMatchGrp(leftInRow);
}
return;
}
TAOS_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 {
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[c], leftInRow + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes);
}
}
int32_t endIdx = rightRows + rightOffset;
int32_t beginIdx = (!jtCtx.asc && rightRows > jtCtx.jLimit) ? (endIdx - jtCtx.jLimit) : rightOffset;
for (int32_t r = beginIdx; r < endIdx; ++r) {
bool* rightFilterOut = (bool*)taosArrayGet(jtCtx.rightFilterOut, r);
if (*rightFilterOut) {
continue;
}
char* rightResRows = (char*)taosArrayGet(jtCtx.rightRowsList, r);
assert(rightResRows);
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
if (jtCtx.resColList[MAX_SLOT_NUM + c]) {
if (*(bool*)(rightResRows + c)) {
*(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = true;
TAOS_MEMSET(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], 0, tDataTypes[jtInputColType[c]].bytes);
} else {
*(bool*)(jtCtx.resColBuf + MAX_SLOT_NUM + c) = false;
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], rightResRows + jtCtx.inColOffset[c], tDataTypes[jtInputColType[c]].bytes);
}
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
}
void chkAppendWinResRows(bool forceOut) {
int32_t rightRows = taosArrayGetSize(jtCtx.rightRowsList);
if (rightRows < jtCtx.jLimit && !forceOut) {
return;
}
int32_t rightRemains = rightRows;
int32_t rightOffset = 0;
int32_t leftRows = taosArrayGetSize(jtCtx.leftRowsList);
int32_t i = 0;
for (; i < leftRows; ++i) {
char* leftRow = (char*)taosArrayGet(jtCtx.leftRowsList, i);
assert(leftRow);
int64_t* leftTs = (int64_t*)(leftRow + jtCtx.inColOffset[JT_PRIM_TS_SLOT_ID]);
int64_t winStart = *leftTs + jtCtx.winStartOffset;
int64_t winEnd = *leftTs + jtCtx.winEndOffset;
int32_t winBeginIdx = -1;
bool append = false;
bool winClosed = false;
for (int32_t r = rightOffset; r < rightRows; ++r) {
char* rightRow = (char*)taosArrayGet(jtCtx.rightRowsList, r);
assert(rightRow);
int64_t* rightTs = (int64_t*)(rightRow + jtCtx.inColOffset[JT_PRIM_TS_SLOT_ID]);
if ((jtCtx.asc && *rightTs < winStart) || (!jtCtx.asc && *rightTs > winEnd)) {
rightOffset++;
rightRemains--;
if (rightRemains < jtCtx.jLimit && !forceOut) {
taosArrayPopFrontBatch(jtCtx.rightRowsList, rightOffset);
taosArrayPopFrontBatch(jtCtx.rightFilterOut, rightOffset);
taosArrayPopFrontBatch(jtCtx.leftRowsList, i);
return;
}
continue;
} else if ((jtCtx.asc && *rightTs > winEnd) || (!jtCtx.asc && *rightTs < winStart)) {
winClosed = true;
appendWinEachResGrps(leftRow, winBeginIdx, r - winBeginIdx);
append = true;
break;
}
if (-1 == winBeginIdx) {
winBeginIdx = r;
}
if (jtCtx.asc && (r - winBeginIdx + 1) >= jtCtx.jLimit) {
appendWinEachResGrps(leftRow, winBeginIdx, jtCtx.jLimit);
append = true;
break;
}
}
if (!append) {
if (!forceOut) {
break;
}
if (winBeginIdx >= 0) {
appendWinEachResGrps(leftRow, winBeginIdx, rightRows - winBeginIdx);
} else if (0 == jtCtx.rightFilterNum) {
appendLeftNonMatchGrp(leftRow);
}
}
}
taosArrayPopFrontBatch(jtCtx.rightRowsList, rightOffset);
taosArrayPopFrontBatch(jtCtx.rightFilterOut, rightOffset);
taosArrayPopFrontBatch(jtCtx.leftRowsList, i);
}
void trimForAsofJlimit() {
int32_t rowNum = taosArrayGetSize(jtCtx.rightRowsList);
if (rowNum <= jtCtx.jLimit) {
return;
}
taosArrayPopFrontBatch(jtCtx.rightRowsList, rowNum - jtCtx.jLimit);
taosArrayPopFrontBatch(jtCtx.rightFilterOut, rowNum - jtCtx.jLimit);
}
void createGrpRows(SSDataBlock** ppBlk, int32_t blkId, int32_t grpRows) {
if (grpRows <= 0) {
return;
}
if (NULL == *ppBlk) {
*ppBlk = createDummyBlock((blkId == LEFT_BLK_ID) ? LEFT_BLK_ID : RIGHT_BLK_ID);
assert(*ppBlk);
assert(0 == blockDataEnsureCapacity(*ppBlk, jtCtx.blkRows));
assert(NULL != taosArrayPush((blkId == LEFT_BLK_ID) ? jtCtx.leftBlkList : jtCtx.rightBlkList, ppBlk));
}
if (jtCtx.grpJoin) {
(*ppBlk)->info.id.groupId = jtCtx.inGrpId;
}
jtCtx.inputStat |= (1 << blkId);
SArray* pTableRows = NULL;
int32_t tableOffset = 0;
int32_t peerOffset = 0;
bool keepRes = false;
bool keepInput = false;
if (blkId == LEFT_BLK_ID) {
if ((jtCtx.joinType == JOIN_TYPE_LEFT || jtCtx.joinType == JOIN_TYPE_FULL) && (jtCtx.subType != JOIN_STYPE_SEMI && jtCtx.subType != JOIN_STYPE_ASOF && jtCtx.subType != JOIN_STYPE_WIN)) {
keepRes = true;
}
peerOffset = MAX_SLOT_NUM;
} else {
if ((jtCtx.joinType == JOIN_TYPE_RIGHT || jtCtx.joinType == JOIN_TYPE_FULL) && (jtCtx.subType != JOIN_STYPE_SEMI && jtCtx.subType != JOIN_STYPE_ASOF && jtCtx.subType != JOIN_STYPE_WIN)) {
keepRes = true;
}
tableOffset = MAX_SLOT_NUM;
}
if (JOIN_STYPE_ASOF == jtCtx.subType) {
keepInput = jtCtx.asofOpType != OP_TYPE_EQUAL ? true : (blkId == LEFT_BLK_ID);
pTableRows = (blkId == LEFT_BLK_ID) ? jtCtx.leftRowsList : jtCtx.rightRowsList;
} else if (JOIN_STYPE_WIN == jtCtx.subType) {
keepInput = true;
pTableRows = (blkId == LEFT_BLK_ID) ? jtCtx.leftRowsList : jtCtx.rightRowsList;
}
int32_t filterNum = (blkId == LEFT_BLK_ID) ? jtCtx.leftFilterNum : jtCtx.rightFilterNum;
int32_t peerFilterNum = (blkId == LEFT_BLK_ID) ? jtCtx.rightFilterNum : jtCtx.leftFilterNum;
int32_t* filterCol = (blkId == LEFT_BLK_ID) ? jtCtx.leftFilterColList : jtCtx.rightFilterColList;
char* pData = NULL;
int32_t tmpInt = 0;
int64_t tmpBigint = 0;
bool isNull = false;
bool filterOut = false;
bool addToRowList = false;
int32_t vRange = TMAX(grpRows / 3, 3);
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
jtCtx.grpOffset[c] = c * TMAX(100, grpRows);
}
for (int32_t i = 0; i < grpRows; ++i) {
if ((*ppBlk)->info.rows >= (*ppBlk)->info.capacity) {
*ppBlk = createDummyBlock((blkId == LEFT_BLK_ID) ? LEFT_BLK_ID : RIGHT_BLK_ID);
assert(*ppBlk);
assert(0 == blockDataEnsureCapacity(*ppBlk, jtCtx.blkRows));
assert(NULL != taosArrayPush((blkId == LEFT_BLK_ID) ? jtCtx.leftBlkList : jtCtx.rightBlkList, ppBlk));
if (jtCtx.grpJoin) {
(*ppBlk)->info.id.groupId = jtCtx.inGrpId;
}
}
filterOut = (peerFilterNum > 0 && (jtCtx.subType != JOIN_STYPE_ASOF && jtCtx.subType != JOIN_STYPE_WIN)) ? true : false;
if (!filterOut) {
TAOS_MEMSET(jtCtx.resColBuf, 0, jtCtx.resColSize);
if (keepInput) {
TAOS_MEMSET(jtCtx.inColBuf, 0, jtCtx.inColSize);
}
}
addToRowList = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
jtCtx.asc ? ++jtCtx.curTs : --jtCtx.curTs;
pData = (char*)&jtCtx.curTs;
isNull = false;
if (!filterOut && filterNum && filterCol[c] && jtCtx.curTs <= TIMESTAMP_FILTER_VALUE) {
filterOut = true;
}
break;
case TSDB_DATA_TYPE_INT:
if (taosRand() % 10) {
tmpInt = (taosRand() % 2) ? INT_FILTER_VALUE + jtCtx.grpOffset[c] + taosRand() % vRange : INT_FILTER_VALUE - jtCtx.grpOffset[c] - taosRand() % vRange;
pData = (char*)&tmpInt;
isNull = false;
if (!filterOut && filterNum && filterCol[c] && tmpInt <= INT_FILTER_VALUE) {
filterOut = true;
}
} else {
isNull = true;
if (filterNum && filterCol[c]) {
filterOut = true;
}
}
break;
case TSDB_DATA_TYPE_BIGINT:
tmpBigint = (taosRand() % 2) ? BIGINT_FILTER_VALUE + jtCtx.curKeyOffset++ : BIGINT_FILTER_VALUE - jtCtx.curKeyOffset++;
pData = (char*)&tmpBigint;
isNull = false;
if (!filterOut && filterNum && filterCol[c] && tmpBigint <= BIGINT_FILTER_VALUE) {
filterOut = true;
}
break;
default:
break;
}
SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet((*ppBlk)->pDataBlock, c);
assert(pCol);
assert(0 == colDataSetVal(pCol, (*ppBlk)->info.rows, pData, isNull));
if (keepInput) {
if (!filterOut || (blkId != LEFT_BLK_ID)) {
if (isNull) {
*(char*)(jtCtx.inColBuf + c) = true;
} else {
TAOS_MEMCPY(jtCtx.inColBuf + jtCtx.inColOffset[c], pData, tDataTypes[jtInputColType[c]].bytes);
}
} else {
addToRowList = false;
}
} else if (keepRes && !filterOut && jtCtx.resColList[tableOffset + c]) {
if (isNull) {
*(char*)(jtCtx.resColBuf + tableOffset + c) = true;
} else {
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[tableOffset + c], pData, tDataTypes[jtInputColType[c]].bytes);
}
}
}
if (keepInput && addToRowList) {
assert(NULL != taosArrayPush(pTableRows, jtCtx.inColBuf));
if (blkId == RIGHT_BLK_ID) {
bool fout = filterOut ? true : false;
assert(NULL != taosArrayPush(jtCtx.rightFilterOut, &fout));
}
}
if (keepRes && !filterOut) {
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
if (jtCtx.resColList[peerOffset + c]) {
*(char*)(jtCtx.resColBuf + peerOffset + c) = true;
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
(*ppBlk)->info.rows++;
}
if (keepInput) {
if (JOIN_STYPE_ASOF == jtCtx.subType) {
if (((jtCtx.asc && (jtCtx.asofOpType == OP_TYPE_GREATER_EQUAL || jtCtx.asofOpType == OP_TYPE_GREATER_THAN)) || (!jtCtx.asc && (jtCtx.asofOpType == OP_TYPE_LOWER_EQUAL || jtCtx.asofOpType == OP_TYPE_LOWER_THAN)) ) || jtCtx.asofOpType == OP_TYPE_EQUAL) {
if (blkId == LEFT_BLK_ID) {
appendAllAsofResRows();
} else {
trimForAsofJlimit();
}
} else {
chkAppendAsofForwardGrpResRows(false);
}
} else {
chkAppendWinResRows(false);
}
}
}
void createRowData(SSDataBlock* pBlk, int64_t tbOffset, int32_t rowIdx, int32_t vRange) {
int32_t tmpInt = 0;
int64_t tmpBig = 0;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlk->pDataBlock, c);
assert(pCol);
int32_t rv = taosRand() % 10;
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
*(int64_t*)(jtCtx.colRowDataBuf + tbOffset + rowIdx * jtCtx.blkRowSize + jtCtx.colRowOffset[c]) = jtCtx.curTs;
assert(0 == colDataSetVal(pCol, pBlk->info.rows, (char*)&jtCtx.curTs, false));
break;
case TSDB_DATA_TYPE_INT:
if (rv) {
tmpInt = (taosRand() % 2) ? INT_FILTER_VALUE + jtCtx.grpOffset[c] + taosRand() % vRange : INT_FILTER_VALUE - taosRand() % vRange;
*(int32_t*)(jtCtx.colRowDataBuf + tbOffset + rowIdx * jtCtx.blkRowSize + jtCtx.colRowOffset[c]) = tmpInt;
assert(0 == colDataSetVal(pCol, pBlk->info.rows, (char*)&tmpInt, false));
} else {
*(bool*)(jtCtx.colRowDataBuf + tbOffset + rowIdx * jtCtx.blkRowSize + c) = true;
assert(0 == colDataSetVal(pCol, pBlk->info.rows, NULL, true));
}
break;
case TSDB_DATA_TYPE_BIGINT:
tmpBig = (taosRand() % 2) ? BIGINT_FILTER_VALUE + jtCtx.curKeyOffset++ : BIGINT_FILTER_VALUE - jtCtx.curKeyOffset++;
*(int64_t*)(jtCtx.colRowDataBuf + tbOffset + rowIdx * jtCtx.blkRowSize + jtCtx.colRowOffset[c]) = tmpBig;
assert(0 == colDataSetVal(pCol, pBlk->info.rows, (char*)&tmpBig, false));
break;
default:
break;
}
}
pBlk->info.rows++;
}
void makeAppendBlkData(SSDataBlock** ppLeft, SSDataBlock** ppRight, int32_t leftGrpRows, int32_t rightGrpRows) {
int64_t totalSize = (leftGrpRows + rightGrpRows) * jtCtx.blkRowSize;
int64_t rightOffset = leftGrpRows * jtCtx.blkRowSize;
if (jtCtx.colRowDataBufSize < totalSize) {
jtCtx.colRowDataBuf = (char*)taosMemoryRealloc(jtCtx.colRowDataBuf, totalSize);
assert(jtCtx.colRowDataBuf);
}
TAOS_MEMSET(jtCtx.colRowDataBuf, 0, totalSize);
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
jtCtx.grpOffset[c] = c * TMAX(leftGrpRows, rightGrpRows);
}
int32_t vRange = TMAX(leftGrpRows / 100, 3);
for (int32_t i = 0; i < leftGrpRows; ++i) {
if ((*ppLeft)->info.rows >= (*ppLeft)->info.capacity) {
*ppLeft = createDummyBlock(LEFT_BLK_ID);
assert(*ppLeft);
assert(0 == blockDataEnsureCapacity(*ppLeft, jtCtx.blkRows));
assert(NULL != taosArrayPush(jtCtx.leftBlkList, ppLeft));
if (jtCtx.grpJoin) {
(*ppLeft)->info.id.groupId = jtCtx.inGrpId;
}
}
createRowData(*ppLeft, 0, i, vRange);
}
vRange = TMAX(rightGrpRows / 100, 3);
for (int32_t i = 0; i < rightGrpRows; ++i) {
if ((*ppRight)->info.rows >= (*ppRight)->info.capacity) {
*ppRight = createDummyBlock(RIGHT_BLK_ID);
assert(*ppRight);
assert(0 == blockDataEnsureCapacity(*ppRight, jtCtx.blkRows));
assert(NULL != taosArrayPush(jtCtx.rightBlkList, ppRight));
if (jtCtx.grpJoin) {
(*ppRight)->info.id.groupId = jtCtx.inGrpId;
}
}
createRowData(*ppRight, rightOffset, i, vRange);
}
}
void putNMatchRowToRes(char* lrow, int32_t tableOffset, int32_t peerOffset) {
if (!jtCtrl.noKeepResRows) {
TAOS_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 {
TAOS_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;
}
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
void putMatchRowToRes(char* lrow, char* rrow, int32_t cols) {
if (!jtCtrl.noKeepResRows) {
TAOS_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 {
TAOS_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 {
TAOS_MEMCPY(jtCtx.resColBuf + jtCtx.resColOffset[MAX_SLOT_NUM + c], rrow + jtCtx.colRowOffset[c], tDataTypes[jtInputColType[c]].bytes);
}
}
}
}
}
pushResRow(jtCtx.resColBuf, jtCtx.resColSize);
}
void innerJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
bool leftMatch = false, rightMatch = false, filterOut = false;
void* lValue = NULL, *rValue = NULL, *filterValue = NULL;
int64_t lBig = 0, rBig = 0, fbig = 0;
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
for (int32_t l = 0; l < leftGrpRows; ++l) {
char* lrow = jtCtx.colRowDataBuf + jtCtx.blkRowSize * l;
filterOut = false;
leftMatch = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
default:
break;
}
if (jtCtx.leftFilterNum && jtCtx.leftFilterColList[c] && ((*(bool*)(lrow + c)) || lBig <= fbig)) {
filterOut = true;
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
break;
}
}
if (filterOut || !leftMatch) {
continue;
}
for (int32_t r = 0; r < rightGrpRows; ++r) {
char* rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
rightMatch = true;
filterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
if (!*(bool*)(rrow + c)) {
rValue = rrow + jtCtx.colRowOffset[c];
}
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
rBig = *(int32_t*)rValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
default:
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && ((*(bool*)(rrow + c)) || lBig != rBig)) {
rightMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && ((*(bool*)(rrow + c)) || lBig <= rBig)) {
rightMatch = false;
break;
}
if (jtCtx.rightFilterNum && jtCtx.rightFilterColList[c] && ((*(bool*)(rrow + c)) || rBig <= fbig)) {
filterOut = true;
break;
}
}
if (filterOut || !rightMatch) {
continue;
}
putMatchRowToRes(lrow, rrow, ALL_TABLE_COLS);
}
}
}
void leftJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
bool leftMatch = false, rightMatch = false, filterOut = false;
void* lValue = NULL, *rValue = NULL, *filterValue = NULL;
int64_t lBig = 0, rBig = 0, fbig = 0;
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
for (int32_t l = 0; l < leftGrpRows; ++l) {
char* lrow = jtCtx.colRowDataBuf + jtCtx.blkRowSize * l;
filterOut = false;
leftMatch = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
default:
break;
}
if (jtCtx.leftFilterNum && jtCtx.leftFilterColList[c] && ((*(bool*)(lrow + c)) || lBig <= fbig)) {
filterOut = true;
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
}
}
if (filterOut) {
continue;
}
if (false == leftMatch) {
if (0 == jtCtx.rightFilterNum) {
putNMatchRowToRes(lrow, 0, MAX_SLOT_NUM);
}
continue;
}
leftMatch = false;
for (int32_t r = 0; r < rightGrpRows; ++r) {
char* rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
rightMatch = true;
filterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
if (!*(bool*)(rrow + c)) {
rValue = rrow + jtCtx.colRowOffset[c];
}
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
rBig = *(int32_t*)rValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
default:
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && ((*(bool*)(rrow + c)) || lBig != rBig)) {
rightMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && ((*(bool*)(rrow + c)) || lBig <= rBig)) {
rightMatch = false;
break;
}
if (jtCtx.rightFilterNum && jtCtx.rightFilterColList[c] && ((*(bool*)(rrow + c)) || rBig <= fbig)) {
filterOut = true;
}
}
if (rightMatch) {
leftMatch = true;
}
if (filterOut) {
continue;
}
if (rightMatch) {
putMatchRowToRes(lrow, rrow, ALL_TABLE_COLS);
}
}
if (!leftMatch && 0 == jtCtx.rightFilterNum) {
putNMatchRowToRes(lrow, 0, MAX_SLOT_NUM);
}
}
}
void semiJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
bool leftMatch = false, rightMatch = false, filterOut = false;
void* lValue = NULL, *rValue = NULL, *filterValue = NULL;
int64_t lBig = 0, rBig = 0, fbig = 0;
int64_t leftTbOffset = 0;
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
char* rrow = NULL;
for (int32_t l = 0; l < leftGrpRows; ++l) {
char* lrow = jtCtx.colRowDataBuf + leftTbOffset + jtCtx.blkRowSize * l;
filterOut = false;
leftMatch = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
default:
break;
}
if (jtCtx.leftFilterNum && jtCtx.leftFilterColList[c] && ((*(bool*)(lrow + c)) || lBig <= fbig)) {
filterOut = true;
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
break;
}
}
if (filterOut || !leftMatch) {
continue;
}
for (int32_t r = 0; r < rightGrpRows; ++r) {
rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
rightMatch = true;
filterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
if (!*(bool*)(rrow + c)) {
rValue = rrow + jtCtx.colRowOffset[c];
}
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
rBig = *(int32_t*)rValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
default:
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && ((*(bool*)(rrow + c)) || lBig != rBig)) {
rightMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && ((*(bool*)(rrow + c)) || lBig <= rBig)) {
rightMatch = false;
break;
}
if (jtCtx.rightFilterNum && jtCtx.rightFilterColList[c] && ((*(bool*)(rrow + c)) || rBig <= fbig)) {
filterOut = true;
break;
}
}
if (filterOut || !rightMatch) {
continue;
}
break;
}
if (!filterOut && rightMatch) {
putMatchRowToRes(lrow, rrow, LEFT_TABLE_COLS);
}
}
}
void antiJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
bool leftMatch = false, rightMatch = false, filterOut = false;
void* lValue = NULL, *rValue = NULL, *filterValue = NULL;
int64_t lBig = 0, rBig = 0, fbig = 0;
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
assert(0 == jtCtx.rightFilterNum);
for (int32_t l = 0; l < leftGrpRows; ++l) {
char* lrow = jtCtx.colRowDataBuf + jtCtx.blkRowSize * l;
filterOut = false;
leftMatch = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
default:
break;
}
if (jtCtx.leftFilterNum && jtCtx.leftFilterColList[c] && ((*(bool*)(lrow + c)) || lBig <= fbig)) {
filterOut = true;
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && (*(bool*)(lrow + c))) {
leftMatch = false;
}
}
if (filterOut) {
continue;
}
if (false == leftMatch) {
putNMatchRowToRes(lrow, 0, MAX_SLOT_NUM);
continue;
}
leftMatch = false;
for (int32_t r = 0; r < rightGrpRows; ++r) {
char* rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
rightMatch = true;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
if (!*(bool*)(rrow + c)) {
rValue = rrow + jtCtx.colRowOffset[c];
}
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
rBig = *(int32_t*)rValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
default:
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && ((*(bool*)(rrow + c)) || lBig != rBig)) {
rightMatch = false;
break;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && ((*(bool*)(rrow + c)) || lBig <= rBig)) {
rightMatch = false;
break;
}
}
if (rightMatch) {
leftMatch = true;
break;
}
}
if (!leftMatch) {
putNMatchRowToRes(lrow, 0, MAX_SLOT_NUM);
}
}
}
void addAsofEqInRows(int32_t rowsNum, int64_t tbOffset, bool leftTable) {
bool filterOut = false;
void* cvalue = NULL;
int64_t cbig = 0, fbig = 0;
int32_t filterNum = leftTable ? jtCtx.leftFilterNum : jtCtx.rightFilterNum;
int32_t* filterCol = leftTable ? jtCtx.leftFilterColList : jtCtx.rightFilterColList;
SArray* rowList = leftTable ? jtCtx.leftRowsList : jtCtx.rightRowsList;
if (!leftTable) {
rowsNum = TMIN(rowsNum, jtCtx.jLimit);
}
for (int32_t l = 0; l < rowsNum; ++l) {
char* row = jtCtx.colRowDataBuf + tbOffset + jtCtx.blkRowSize * l;
filterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
cvalue = row + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
cbig = *(int64_t*)cvalue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
cbig = *(int32_t*)cvalue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
cbig = *(int64_t*)cvalue;
break;
default:
break;
}
if (filterNum && filterCol[c] && ((*(bool*)(row + c)) || cbig <= fbig)) {
filterOut = true;
break;
}
}
if (filterOut && leftTable) {
continue;
}
assert(NULL != taosArrayPush(rowList, row));
if (!leftTable) {
assert(NULL != taosArrayPush(jtCtx.rightFilterOut, &filterOut));
}
}
if (!leftTable && ((jtCtx.asc && (jtCtx.asofOpType == OP_TYPE_GREATER_EQUAL || jtCtx.asofOpType == OP_TYPE_GREATER_THAN)) || (!jtCtx.asc && (jtCtx.asofOpType == OP_TYPE_LOWER_EQUAL || jtCtx.asofOpType == OP_TYPE_LOWER_THAN))) || jtCtx.asofOpType == OP_TYPE_EQUAL) {
trimForAsofJlimit();
}
}
void asofJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
if (jtCtx.asc) {
switch (jtCtx.asofOpType) {
case OP_TYPE_GREATER_THAN:
addAsofEqInRows(leftGrpRows, 0, true);
appendAllAsofResRows();
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
break;
case OP_TYPE_GREATER_EQUAL:
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
appendAllAsofResRows();
break;
case OP_TYPE_LOWER_THAN:
case OP_TYPE_LOWER_EQUAL:
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
chkAppendAsofForwardGrpResRows(false);
break;
case OP_TYPE_EQUAL:
taosArrayClear(jtCtx.leftRowsList);
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
chkAppendAsofForwardGrpResRows(true);
taosArrayClear(jtCtx.leftRowsList);
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
break;
default:
return;
}
return;
}
switch (jtCtx.asofOpType) {
case OP_TYPE_LOWER_THAN:
addAsofEqInRows(leftGrpRows, 0, true);
appendAllAsofResRows();
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
break;
case OP_TYPE_LOWER_EQUAL:
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
appendAllAsofResRows();
break;
case OP_TYPE_GREATER_THAN:
case OP_TYPE_GREATER_EQUAL:
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
chkAppendAsofForwardGrpResRows(false);
break;
case OP_TYPE_EQUAL:
taosArrayClear(jtCtx.leftRowsList);
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
addAsofEqInRows(leftGrpRows, 0, true);
addAsofEqInRows(rightGrpRows, rightTbOffset, false);
chkAppendAsofForwardGrpResRows(true);
taosArrayClear(jtCtx.leftRowsList);
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
break;
default:
return;
}
}
void addWinEqInRows(int32_t rowsNum, int64_t tbOffset, bool leftTable) {
bool filterOut = false;
void* cvalue = NULL;
int64_t cbig = 0, fbig = 0;
int32_t filterNum = leftTable ? jtCtx.leftFilterNum : jtCtx.rightFilterNum;
int32_t* filterCol = leftTable ? jtCtx.leftFilterColList : jtCtx.rightFilterColList;
SArray* rowList = leftTable ? jtCtx.leftRowsList : jtCtx.rightRowsList;
for (int32_t l = 0; l < rowsNum; ++l) {
char* row = jtCtx.colRowDataBuf + tbOffset + jtCtx.blkRowSize * l;
filterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
cvalue = row + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
cbig = *(int64_t*)cvalue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
cbig = *(int32_t*)cvalue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
cbig = *(int64_t*)cvalue;
break;
default:
break;
}
if (filterNum && filterCol[c] && ((*(bool*)(row + c)) || cbig <= fbig)) {
filterOut = true;
break;
}
}
if (filterOut && leftTable) {
continue;
}
assert(NULL != taosArrayPush(rowList, row));
if (!leftTable) {
assert(NULL != taosArrayPush(jtCtx.rightFilterOut, &filterOut));
}
}
}
void winJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
addWinEqInRows(leftGrpRows, 0, true);
addWinEqInRows(rightGrpRows, rightTbOffset, false);
chkAppendWinResRows(false);
}
void fullJoinAppendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
bool leftMatch = false, rightMatch = false, lfilterOut = false, rfilterOut = false;
void* lValue = NULL, *rValue = NULL, *filterValue = NULL;
int64_t lBig = 0, rBig = 0, fbig = 0;
int64_t rightTbOffset = jtCtx.blkRowSize * leftGrpRows;
TAOS_MEMSET(jtCtx.rightFinMatch, 0, rightGrpRows * sizeof(bool));
for (int32_t l = 0; l < leftGrpRows; ++l) {
char* lrow = jtCtx.colRowDataBuf + jtCtx.blkRowSize * l;
lfilterOut = false;
leftMatch = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
break;
default:
break;
}
if (jtCtx.leftFilterNum && jtCtx.leftFilterColList[c] && ((*(bool*)(lrow + c)) || lBig <= fbig)) {
lfilterOut = true;
}
}
for (int32_t r = 0; r < rightGrpRows; ++r) {
char* rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
rightMatch = true;
rfilterOut = false;
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
lValue = lrow + jtCtx.colRowOffset[c];
if (!*(bool*)(rrow + c)) {
rValue = rrow + jtCtx.colRowOffset[c];
}
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
fbig = TIMESTAMP_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
case TSDB_DATA_TYPE_INT:
fbig = INT_FILTER_VALUE;
lBig = *(int32_t*)lValue;
rBig = *(int32_t*)rValue;
break;
case TSDB_DATA_TYPE_BIGINT:
fbig = BIGINT_FILTER_VALUE;
lBig = *(int64_t*)lValue;
rBig = *(int64_t*)rValue;
break;
default:
break;
}
if (jtCtx.colEqNum && jtCtx.colEqList[c] && ((*(bool*)(lrow + c)) || (*(bool*)(rrow + c)) || lBig != rBig)) {
rightMatch = false;
}
if (jtCtx.colOnNum && jtCtx.colOnList[c] && ((*(bool*)(lrow + c)) || (*(bool*)(rrow + c)) || lBig <= rBig)) {
rightMatch = false;
}
if (jtCtx.rightFilterNum && jtCtx.rightFilterColList[c] && ((*(bool*)(rrow + c)) || rBig <= fbig)) {
rfilterOut = true;
}
}
if (rightMatch) {
jtCtx.rightFinMatch[r] = true;
}
if (rfilterOut) {
if (!rightMatch) {
jtCtx.rightFinMatch[r] = true;
}
continue;
}
if (!lfilterOut && rightMatch) {
putMatchRowToRes(lrow, rrow, ALL_TABLE_COLS);
leftMatch= true;
}
}
if (!lfilterOut && !leftMatch && 0 == jtCtx.rightFilterNum) {
putNMatchRowToRes(lrow, 0, MAX_SLOT_NUM);
}
}
if (0 == jtCtx.leftFilterNum) {
for (int32_t r = 0; r < rightGrpRows; ++r) {
if (!jtCtx.rightFinMatch[r]) {
char* rrow = jtCtx.colRowDataBuf + rightTbOffset + jtCtx.blkRowSize * r;
putNMatchRowToRes(rrow, MAX_SLOT_NUM, 0);
}
}
}
}
void appendEqGrpRes(int32_t leftGrpRows, int32_t rightGrpRows) {
switch (jtCtx.joinType) {
case JOIN_TYPE_INNER:
innerJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
case JOIN_TYPE_LEFT: {
switch (jtCtx.subType) {
case JOIN_STYPE_OUTER:
leftJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
case JOIN_STYPE_SEMI:
semiJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
case JOIN_STYPE_ANTI:
antiJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
case JOIN_STYPE_ASOF:
asofJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
case JOIN_STYPE_WIN:
winJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
default:
break;
}
break;
}
case JOIN_TYPE_FULL:
fullJoinAppendEqGrpRes(leftGrpRows, rightGrpRows);
break;
default:
break;
}
}
void createTsEqGrpRows(SSDataBlock** ppLeft, SSDataBlock** ppRight, int32_t leftGrpRows, int32_t rightGrpRows) {
if (leftGrpRows <= 0 && rightGrpRows <= 0) {
return;
}
if (leftGrpRows > 0 && rightGrpRows > 0) {
jtCtx.inputStat |= (1 << 2);
}
jtCtx.asc ? ++jtCtx.curTs : --jtCtx.curTs;
if (NULL == *ppLeft && leftGrpRows > 0) {
*ppLeft = createDummyBlock(LEFT_BLK_ID);
assert(*ppLeft);
assert(0 == blockDataEnsureCapacity(*ppLeft, jtCtx.blkRows));
assert(NULL != taosArrayPush(jtCtx.leftBlkList, ppLeft));
}
if (jtCtx.grpJoin) {
(*ppLeft)->info.id.groupId = jtCtx.inGrpId;
}
if (NULL == *ppRight && rightGrpRows > 0) {
*ppRight = createDummyBlock(RIGHT_BLK_ID);
assert(*ppRight);
assert(0 == blockDataEnsureCapacity(*ppRight, jtCtx.blkRows));
assert(NULL != taosArrayPush(jtCtx.rightBlkList, ppRight));
}
if (jtCtx.grpJoin) {
(*ppRight)->info.id.groupId = jtCtx.inGrpId;
}
makeAppendBlkData(ppLeft, ppRight, leftGrpRows, rightGrpRows);
appendEqGrpRes(leftGrpRows, rightGrpRows);
}
void forceFlushResRows() {
if (JOIN_STYPE_ASOF == jtCtx.subType && taosArrayGetSize(jtCtx.leftRowsList) > 0) {
assert((jtCtx.asc && (OP_TYPE_LOWER_EQUAL == jtCtx.asofOpType || OP_TYPE_LOWER_THAN == jtCtx.asofOpType))
|| (!jtCtx.asc && (OP_TYPE_GREATER_EQUAL == jtCtx.asofOpType || OP_TYPE_GREATER_THAN == jtCtx.asofOpType)));
chkAppendAsofForwardGrpResRows(true);
} else if (JOIN_STYPE_WIN == jtCtx.subType && taosArrayGetSize(jtCtx.leftRowsList) > 0) {
chkAppendWinResRows(true);
}
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
taosArrayClear(jtCtx.leftRowsList);
}
void createBothBlkRowsData(void) {
SSDataBlock* pLeft = NULL;
SSDataBlock* pRight = NULL;
jtCtx.leftTotalRows = taosRand() % jtCtx.leftMaxRows;
jtCtx.rightTotalRows = taosRand() % jtCtx.rightMaxRows;
int32_t minTotalRows = TMIN(jtCtx.leftTotalRows, jtCtx.rightTotalRows);
int32_t maxTotalRows = TMAX(jtCtx.leftTotalRows, jtCtx.rightTotalRows);
jtCtx.curTs = jtCtx.asc ? (TIMESTAMP_FILTER_VALUE - minTotalRows / 5) : (TIMESTAMP_FILTER_VALUE + 4 * maxTotalRows / 5);
int32_t leftTotalRows = 0, rightTotalRows = 0;
int32_t leftGrpRows = 0, rightGrpRows = 0;
int32_t grpType = 0;
while (leftTotalRows < jtCtx.leftTotalRows || rightTotalRows < jtCtx.rightTotalRows) {
if (leftTotalRows >= jtCtx.leftTotalRows) {
grpType = 1;
} else if (rightTotalRows >= jtCtx.rightTotalRows) {
grpType = 0;
} else {
grpType = taosRand() % 10;
}
leftGrpRows = taosRand() % jtCtx.leftMaxGrpRows;
rightGrpRows = taosRand() % jtCtx.rightMaxGrpRows;
if ((leftTotalRows + leftGrpRows) > jtCtx.leftTotalRows) {
leftGrpRows = jtCtx.leftTotalRows - leftTotalRows;
}
if ((rightTotalRows + rightGrpRows) > jtCtx.rightTotalRows) {
rightGrpRows = jtCtx.rightTotalRows - rightTotalRows;
}
if (0 != grpType && 1 != grpType && (leftGrpRows <= 0 || rightGrpRows <= 0)) {
if (leftGrpRows <= 0) {
grpType = 1;
} else {
grpType = 0;
}
}
if (jtCtx.grpJoin && (0 == taosRand() % 3)) {
forceFlushResRows();
jtCtx.inGrpId++;
pLeft = NULL;
pRight = NULL;
}
switch (grpType) {
case 0:
createGrpRows(&pLeft, LEFT_BLK_ID, leftGrpRows);
leftTotalRows += leftGrpRows;
break;
case 1:
createGrpRows(&pRight, RIGHT_BLK_ID, rightGrpRows);
rightTotalRows += rightGrpRows;
break;
default:
createTsEqGrpRows(&pLeft, &pRight, leftGrpRows, rightGrpRows);
leftTotalRows += leftGrpRows;
rightTotalRows += rightGrpRows;
break;
}
}
forceFlushResRows();
}
void createDummyBlkList(int32_t leftMaxRows, int32_t leftMaxGrpRows, int32_t rightMaxRows, int32_t rightMaxGrpRows, int32_t blkRows) {
jtCtx.leftMaxRows = leftMaxRows;
jtCtx.leftMaxGrpRows = leftMaxGrpRows;
jtCtx.rightMaxRows = rightMaxRows;
jtCtx.rightMaxGrpRows = rightMaxGrpRows;
jtCtx.blkRows = blkRows;
int32_t maxGrpRows = TMAX(leftMaxGrpRows, rightMaxGrpRows);
if (maxGrpRows > jtCtx.rightFinMatchNum) {
jtCtx.rightFinMatchNum = maxGrpRows;
jtCtx.rightFinMatch = (bool*)taosMemoryRealloc(jtCtx.rightFinMatch, maxGrpRows * sizeof(bool));
assert(jtCtx.rightFinMatch);
}
taosArrayClear(jtCtx.leftRowsList);
taosArrayClear(jtCtx.rightRowsList);
taosArrayClear(jtCtx.rightFilterOut);
createBothBlkRowsData();
}
void rerunBlockedHere() {
while (jtInRerun) {
taosSsleep(1);
}
}
SSDataBlock* getDummyInputBlock(struct SOperatorInfo* pOperator, int32_t idx) {
switch (idx) {
case LEFT_BLK_ID:
if (jtCtx.leftBlkReadIdx >= taosArrayGetSize(jtCtx.leftBlkList)) {
return NULL;
}
return (SSDataBlock*)taosArrayGetP(jtCtx.leftBlkList, jtCtx.leftBlkReadIdx++);
break;
case RIGHT_BLK_ID:
if (jtCtx.rightBlkReadIdx >= taosArrayGetSize(jtCtx.rightBlkList)) {
return NULL;
}
return (SSDataBlock*)taosArrayGetP(jtCtx.rightBlkList, jtCtx.rightBlkReadIdx++);
break;
default:
return NULL;
}
}
void joinTestReplaceRetrieveFp() {
static Stub stub;
stub.set(getNextBlockFromDownstreamRemain, getDummyInputBlock);
{
#ifdef WINDOWS
AddrAny any;
std::map<std::string, void *> result;
any.get_func_addr("getNextBlockFromDownstreamRemain", result);
for (const auto &f : result) {
stub.set(f.second, getDummyInputBlock);
}
#endif
#ifdef LINUX
AddrAny any("libexecutor.so");
std::map<std::string, void *> result;
any.get_global_func_addr_dynsym("^getNextBlockFromDownstreamRemain$", result);
for (const auto &f : result) {
stub.set(f.second, getDummyInputBlock);
}
#endif
}
}
void printColList(char* title, bool left, int32_t* colList, bool filter, char* opStr) {
bool first = true;
JT_PRINTF("\t %s:", title);
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
if (colList[i]) {
if (!first) {
JT_PRINTF(" AND ");
}
first = false;
if (filter) {
JT_PRINTF("%sc%d%s%" PRId64 , left ? "l" : "r", i, opStr, jtFilterValue[i]);
} else {
JT_PRINTF("lc%d%src%d", i, opStr, i);
}
}
}
JT_PRINTF("\n");
}
void printInputRowData(SSDataBlock* pBlk, int32_t* rowIdx) {
if (jtCtx.grpJoin) {
JT_PRINTF("%5" PRIu64, pBlk->info.id.groupId);
}
for (int32_t c = 0; c < MAX_SLOT_NUM; ++c) {
SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlk->pDataBlock, c);
assert(pCol);
assert(pCol->info.type == jtInputColType[c]);
if (colDataIsNull_s(pCol, *rowIdx)) {
JT_PRINTF("%18s", " NULL");
} else {
switch (jtInputColType[c]) {
case TSDB_DATA_TYPE_TIMESTAMP:
case TSDB_DATA_TYPE_BIGINT:
JT_PRINTF("%18" PRId64, *(int64_t*)colDataGetData(pCol, *rowIdx));
break;
case TSDB_DATA_TYPE_INT:
JT_PRINTF("%18d", *(int32_t*)colDataGetData(pCol, *rowIdx));
break;
default:
assert(0);
}
}
}
(*rowIdx)++;
}
void printInputData() {
int32_t leftRowIdx = 0, rightRowIdx = 0;
JT_PRINTF("\nInput Data:\n");
while (jtCtx.leftBlkReadIdx < taosArrayGetSize(jtCtx.leftBlkList) || jtCtx.rightBlkReadIdx < taosArrayGetSize(jtCtx.rightBlkList)) {
if (jtCtx.leftBlkReadIdx < taosArrayGetSize(jtCtx.leftBlkList)) {
while (true) {
SSDataBlock* pBlk = (SSDataBlock*)taosArrayGetP(jtCtx.leftBlkList, jtCtx.leftBlkReadIdx);
assert(pBlk);
if (leftRowIdx < pBlk->info.rows) {
printInputRowData(pBlk, &leftRowIdx);
break;
}
JT_PRINTF("\t%*s-------------------------blk end-------------------------------", jtCtx.grpJoin ? 6 : 0, " ");
jtCtx.leftBlkReadIdx++;
leftRowIdx = 0;
break;
}
} else {
JT_PRINTF("%*s", jtCtx.grpJoin ? 77 : 72, " ");
}
if (jtCtx.rightBlkReadIdx < taosArrayGetSize(jtCtx.rightBlkList)) {
while (true) {
SSDataBlock* pBlk = (SSDataBlock*)taosArrayGetP(jtCtx.rightBlkList, jtCtx.rightBlkReadIdx);
assert(pBlk);
if (rightRowIdx < pBlk->info.rows) {
printInputRowData(pBlk, &rightRowIdx);
break;
}
JT_PRINTF("\t%*s--------------------------blk end----------------------------\t", jtCtx.grpJoin ? 6 : 0, " ");
jtCtx.rightBlkReadIdx++;
rightRowIdx = 0;
break;
}
}
JT_PRINTF("\n");
}
jtCtx.leftBlkReadIdx = jtCtx.rightBlkReadIdx = 0;
}
char* getInputStatStr(char* inputStat) {
if (jtCtx.inputStat & (1 << LEFT_BLK_ID)) {
TAOS_STRCAT(inputStat, "L");
}
if (jtCtx.inputStat & (1 << RIGHT_BLK_ID)) {
TAOS_STRCAT(inputStat, "R");
}
if (jtCtx.inputStat & (1 << 2)) {
TAOS_STRCAT(inputStat, "E");
}
return inputStat;
}
char* getAsofOpStr() {
switch (jtCtx.asofOpType) {
case OP_TYPE_GREATER_THAN:
return ">";
case OP_TYPE_GREATER_EQUAL:
return ">=";
case OP_TYPE_LOWER_THAN:
return "<";
case OP_TYPE_LOWER_EQUAL:
return "<=";
case OP_TYPE_EQUAL:
return "=";
default:
return "UNKNOWN";
}
}
void printBasicInfo(char* caseName) {
if (!jtCtrl.printTestInfo) {
return;
}
char inputStat[4] = {0};
JT_PRINTF("\n%dth TEST [%s] START\nBasic Info:\n\t asc:%d\n\t filter:%d\n\t maxRows:left-%d right-%d\n\t "
"maxGrpRows:left-%d right-%d\n\t blkRows:%d\n\t colCond:%s\n\t joinType:%s\n\t "
"subType:%s\n\t inputStat:%s\n\t groupJoin:%s\n", jtCtx.loopIdx, caseName, jtCtx.asc, jtCtx.filter, jtCtx.leftMaxRows, jtCtx.rightMaxRows,
jtCtx.leftMaxGrpRows, jtCtx.rightMaxGrpRows, jtCtx.blkRows, jtColCondStr[jtCtx.colCond], jtJoinTypeStr[jtCtx.joinType],
jtSubTypeStr[jtCtx.subType], getInputStatStr(inputStat), jtCtx.grpJoin ? "true" : "false");
if (JOIN_STYPE_ASOF == jtCtx.subType) {
JT_PRINTF("\t asofOp:%s\n\t JLimit:%" PRId64 "\n", getAsofOpStr(), jtCtx.jLimit);
} else if (JOIN_STYPE_WIN == jtCtx.subType) {
JT_PRINTF("\t windowOffset:[%" PRId64 ", %" PRId64 "]\n\t JLimit:%" PRId64 "\n", jtCtx.winStartOffset, jtCtx.winEndOffset, jtCtx.jLimit);
}
JT_PRINTF("Input Info:\n\t totalBlk:left-%d right-%d\n\t totalRows:left-%d right-%d\n\t "
"blkRowSize:%d\n\t inputCols:left-%s %s %s %s right-%s %s %s %s\n",
(int32_t)taosArrayGetSize(jtCtx.leftBlkList), (int32_t)taosArrayGetSize(jtCtx.rightBlkList),
jtCtx.leftTotalRows, jtCtx.rightTotalRows,
jtCtx.blkRowSize, tDataTypes[jtInputColType[0]].name, tDataTypes[jtInputColType[1]].name,
tDataTypes[jtInputColType[2]].name, tDataTypes[jtInputColType[3]].name, tDataTypes[jtInputColType[0]].name,
tDataTypes[jtInputColType[1]].name, tDataTypes[jtInputColType[2]].name, tDataTypes[jtInputColType[3]].name);
if (jtCtx.colEqNum) {
JT_PRINTF("\t colEqNum:%d\n", jtCtx.colEqNum);
printColList("colEqList", false, jtCtx.colEqList, false, "=");
}
if (jtCtx.colOnNum) {
JT_PRINTF("\t colOnNum:%d\n", jtCtx.colOnNum);
printColList("colOnList", false, jtCtx.colOnList, false, ">");
}
if (jtCtx.leftFilterNum) {
JT_PRINTF("\t leftFilterNum:%d\n", jtCtx.leftFilterNum);
printColList("leftFilterList", true, jtCtx.leftFilterColList, true, ">");
}
if (jtCtx.rightFilterNum) {
JT_PRINTF("\t rightFilterNum:%d\n", jtCtx.rightFilterNum);
printColList("rightFilterList", false, jtCtx.rightFilterColList, true, ">");
}
JT_PRINTF("\t resColSize:%d\n\t resColNum:%d\n\t resColList:", jtCtx.resColSize, jtCtx.resColNum);
for (int32_t i = 0; i < jtCtx.resColNum; ++i) {
int32_t s = jtCtx.resColInSlot[i];
int32_t idx = s >= MAX_SLOT_NUM ? s - MAX_SLOT_NUM : s;
JT_PRINTF("%sc%d[%s]\t", s >= MAX_SLOT_NUM ? "r" : "l", s, tDataTypes[jtInputColType[idx]].name);
}
if (jtCtrl.printInputRow) {
printInputData();
}
}
void printOutputInfo() {
if (!jtCtrl.printTestInfo) {
return;
}
JT_PRINTF("\nOutput Info:\n\t expectedRows:%d\n\t ", jtCtx.resRows);
JT_PRINTF("Actual Result:\n");
}
void printActualResInfo() {
if (!jtCtrl.printTestInfo) {
return;
}
JT_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\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 ? "" : "*",
taosGetTimestampUs() - jtCtx.startTsUs);
}
void printStatInfo(char* caseName) {
JT_PRINTF("\n TEST [%s] Stat:\n\t maxResRows:%d\n\t maxResBlkRows:%d\n\t totalResRows:%" PRId64 "\n\t useMSecs:%" PRId64 "\n",
caseName, jtStat.maxResRows, jtStat.maxResBlkRows, jtStat.totalResRows, jtStat.useMSecs);
}
void checkJoinDone(char* caseName) {
int32_t iter = 0;
void* p = NULL;
void* key = NULL;
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);
}
}
}
printActualResInfo();
JT_PRINTF("\n%dth TEST [%s] Final Result: %s\n", jtCtx.loopIdx, caseName, jtRes.succeed ? "SUCCEED" : "FAILED");
}
void putRowToResColBuf(SSDataBlock* pBlock, int32_t r, bool ignoreTbCols) {
for (int32_t c = 0; c < jtCtx.resColNum; ++c) {
int32_t slot = jtCtx.resColInSlot[c];
if (ignoreTbCols && ((jtCtx.leftColOnly && slot >= MAX_SLOT_NUM) ||
(jtCtx.rightColOnly && slot < MAX_SLOT_NUM))) {
continue;
}
SColumnInfoData* pCol = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, c);
assert(pCol);
switch (jtInputColType[slot % MAX_SLOT_NUM]) {
case TSDB_DATA_TYPE_TIMESTAMP:
case TSDB_DATA_TYPE_BIGINT:
if (colDataIsNull_s(pCol, r)) {
*(bool*)(jtCtx.resColBuf + slot) = true;
} else {
*(int64_t*)(jtCtx.resColBuf + jtCtx.resColOffset[slot]) = *(int64_t*)colDataGetData(pCol, r);
}
break;
case TSDB_DATA_TYPE_INT:
if (colDataIsNull_s(pCol, r)) {
*(bool*)(jtCtx.resColBuf + slot) = true;
} else {
*(int32_t*)(jtCtx.resColBuf + jtCtx.resColOffset[slot]) = *(int32_t*)colDataGetData(pCol, r);
}
break;
default:
break;
}
}
}
void checkJoinRes(SSDataBlock* pBlock) {
jtRes.rowNum += pBlock->info.rows;
if (jtRes.rowNum > jtStat.maxResRows) {
jtStat.maxResRows = jtRes.rowNum;
}
jtRes.blkNum++;
if (pBlock->info.rows > jtStat.maxResBlkRows) {
jtStat.maxResBlkRows = pBlock->info.rows;
}
jtStat.totalResRows += pBlock->info.rows;
if (jtCtrl.noKeepResRows) {
jtRes.matchNum += pBlock->info.rows;
} else {
for (int32_t r = 0; r < pBlock->info.rows; ++r) {
TAOS_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, false);
printResRow(jtCtx.resColBuf, 1);
jtRes.succeed = false;
jtRes.addRowNum++;
continue;
}
rmResRow();
putRowToResColBuf(pBlock, r, false);
printResRow(jtCtx.resColBuf, 2);
jtRes.matchNum++;
}
}
}
void resetForJoinRerun(int32_t dsNum, SSortMergeJoinPhysiNode* pNode, SExecTaskInfo* pTask) {
jtCtx.leftBlkReadIdx = 0;
jtCtx.rightBlkReadIdx = 0;
jtCtx.curKeyOffset = 0;
TAOS_MEMSET(&jtRes, 0, sizeof(jtRes));
jtRes.succeed = true;
SOperatorInfo* pDownstreams[2];
createDummyDownstreamOperators(2, pDownstreams);
SOperatorInfo* ppDownstreams[] = {pDownstreams[0], pDownstreams[1]};
int32_t code = createMergeJoinOperatorInfo(ppDownstreams, 2, pNode, pTask, &jtCtx.pJoinOp);
ASSERT_TRUE(NULL != jtCtx.pJoinOp);
}
void handleJoinDone(bool* contLoop) {
destroyOperator(jtCtx.pJoinOp);
jtCtx.pJoinOp = NULL;
if (jtRes.succeed) {
*contLoop = false;
return;
}
if (jtErrorRerun) {
*contLoop = false;
return;
}
jtInRerun = true;
}
void jtInitLogFile() {
const char *defaultLogFileNamePrefix = "jtlog";
const int32_t maxLogFileNum = 10;
tsAsyncLog = 0;
qDebugFlag = 159;
TAOS_STRCPY(tsLogDir, TD_LOG_DIR_PATH);
if (taosInitLog(defaultLogFileNamePrefix, maxLogFileNum, false) < 0) {
JT_PRINTF("failed to open log file in directory:%s\n", tsLogDir);
}
}
void initJoinTest() {
jtCtx.leftBlkList = taosArrayInit(10, POINTER_BYTES);
jtCtx.rightBlkList = taosArrayInit(10, POINTER_BYTES);
assert(jtCtx.leftBlkList && jtCtx.rightBlkList);
jtCtx.jtResRows = tSimpleHashInit(10000000, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY));
assert(jtCtx.jtResRows);
joinTestReplaceRetrieveFp();
if (jtCtrl.logHistory) {
jtStat.pHistory = taosArrayInit(100000, sizeof(SJoinTestHistory));
assert(jtStat.pHistory);
}
int32_t offset = MAX_SLOT_NUM * sizeof(bool);
for (int32_t i = 0; i < MAX_SLOT_NUM; ++i) {
jtCtx.inColOffset[i] = offset;
offset += tDataTypes[jtInputColType[i]].bytes;
}
jtCtx.inColSize = offset;
jtCtx.inColBuf = (char*)taosMemoryMalloc(jtCtx.inColSize);
assert(jtCtx.inColBuf);
jtCtx.leftRowsList = taosArrayInit(1024, jtCtx.inColSize);
jtCtx.rightRowsList = taosArrayInit(1024, jtCtx.inColSize);
jtCtx.rightFilterOut = taosArrayInit(1024, sizeof(bool));
assert(jtCtx.leftRowsList && jtCtx.rightRowsList && jtCtx.rightFilterOut);
jtInitLogFile();
}
void handleTestDone() {
if (jtCtrl.logHistory) {
SJoinTestHistory h;
TAOS_MEMCPY(&h.ctx, &jtCtx, sizeof(h.ctx));
TAOS_MEMCPY(&h.res, &jtRes, sizeof(h.res));
assert(NULL != taosArrayPush(jtStat.pHistory, &h));
}
int32_t blkNum = taosArrayGetSize(jtCtx.leftBlkList);
for (int32_t i = 0; i < blkNum; ++i) {
SSDataBlock* pBlk = (SSDataBlock*)taosArrayGetP(jtCtx.leftBlkList, i);
assert(pBlk);
(void)blockDataDestroy(pBlk);
}
taosArrayClear(jtCtx.leftBlkList);
blkNum = taosArrayGetSize(jtCtx.rightBlkList);
for (int32_t i = 0; i < blkNum; ++i) {
SSDataBlock* pBlk = (SSDataBlock*)taosArrayGetP(jtCtx.rightBlkList, i);
assert(pBlk);
(void)blockDataDestroy(pBlk);
}
taosArrayClear(jtCtx.rightBlkList);
tSimpleHashClear(jtCtx.jtResRows);
jtCtx.resRows = 0;
jtCtx.inputStat = 0;
}
void runSingleTest(char* caseName, SJoinTestParam* param) {
bool contLoop = true;
SSortMergeJoinPhysiNode* pNode = createDummySortMergeJoinPhysiNode(param);
assert(pNode);
createDummyBlkList(1000, 1000, 1000, 1000, 100);
while (contLoop) {
rerunBlockedHere();
resetForJoinRerun(2, pNode, param->pTask);
printBasicInfo(caseName);
printOutputInfo();
jtCtx.startTsUs = taosGetTimestampUs();
while (true) {
SSDataBlock* pBlock = NULL;
int32_t code = jtCtx.pJoinOp->fpSet.getNextFn(jtCtx.pJoinOp, &pBlock);
if (NULL == pBlock) {
checkJoinDone(caseName);
break;
} else {
checkJoinRes(pBlock);
}
}
handleJoinDone(&contLoop);
}
nodesDestroyNode((SNode*)pNode);
handleTestDone();
}
void handleCaseEnd() {
taosMemoryFreeClear(jtCtx.rightFinMatch);
jtCtx.rightFinMatchNum = 0;
}
} // namespace
#if 1
#if 1
TEST(innerJoin, noCondTest) {
SJoinTestParam param;
char* caseName = "innerJoin:noCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_INNER;
param.subType = JOIN_STYPE_NONE;
param.cond = TEST_NO_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(innerJoin, eqCondTest) {
SJoinTestParam param;
char* caseName = "innerJoin:eqCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_INNER;
param.subType = JOIN_STYPE_NONE;
param.cond = TEST_EQ_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(innerJoin, onCondTest) {
SJoinTestParam param;
char* caseName = "innerJoin:onCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_INNER;
param.subType = JOIN_STYPE_NONE;
param.cond = TEST_ON_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(innerJoin, fullCondTest) {
SJoinTestParam param;
char* caseName = "innerJoin:fullCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_INNER;
param.subType = JOIN_STYPE_NONE;
param.cond = TEST_FULL_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(leftOuterJoin, noCondTest) {
SJoinTestParam param;
char* caseName = "leftOuterJoin:noCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_NO_COND;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftOuterJoin, eqCondTest) {
SJoinTestParam param;
char* caseName = "leftOuterJoin:eqCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_EQ_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftOuterJoin, onCondTest) {
SJoinTestParam param;
char* caseName = "leftOuterJoin:onCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_ON_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftOuterJoin, fullCondTest) {
SJoinTestParam param;
char* caseName = "leftOuterJoin:fullCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_FULL_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(fullOuterJoin, noCondTest) {
SJoinTestParam param;
char* caseName = "fullOuterJoin:noCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_FULL;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_NO_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(fullOuterJoin, eqCondTest) {
SJoinTestParam param;
char* caseName = "fullOuterJoin:eqCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_FULL;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_EQ_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
handleCaseEnd();
}
#endif
#if 1
TEST(fullOuterJoin, onCondTest) {
SJoinTestParam param;
char* caseName = "fullOuterJoin:onCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_FULL;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_ON_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(fullOuterJoin, fullCondTest) {
SJoinTestParam param;
char* caseName = "fullOuterJoin:fullCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_FULL;
param.subType = JOIN_STYPE_OUTER;
param.cond = TEST_FULL_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(leftSemiJoin, noCondTest) {
SJoinTestParam param;
char* caseName = "leftSemiJoin:noCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_SEMI;
param.cond = TEST_NO_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftSemiJoin, eqCondTest) {
SJoinTestParam param;
char* caseName = "leftSemiJoin:eqCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_SEMI;
param.cond = TEST_EQ_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
handleCaseEnd();
}
#endif
#if 1
TEST(leftSemiJoin, onCondTest) {
SJoinTestParam param;
char* caseName = "leftSemiJoin:onCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_SEMI;
param.cond = TEST_ON_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftSemiJoin, fullCondTest) {
SJoinTestParam param;
char* caseName = "leftSemiJoin:fullCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_SEMI;
param.cond = TEST_FULL_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(leftAntiJoin, noCondTest) {
SJoinTestParam param;
char* caseName = "leftAntiJoin:noCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ANTI;
param.cond = TEST_NO_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAntiJoin, eqCondTest) {
SJoinTestParam param;
char* caseName = "leftAntiJoin:eqCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ANTI;
param.cond = TEST_EQ_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
handleCaseEnd();
}
#endif
#if 1
TEST(leftAntiJoin, onCondTest) {
SJoinTestParam param;
char* caseName = "leftAntiJoin:onCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ANTI;
param.cond = TEST_ON_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAntiJoin, fullCondTest) {
SJoinTestParam param;
char* caseName = "leftAntiJoin:fullCondTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ANTI;
param.cond = TEST_FULL_COND;
param.asc = true;
param.grpJoin = false;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.filter = false;
runSingleTest(caseName, &param);
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(leftAsofJoin, noCondGreaterThanTest) {
SJoinTestParam param;
char* caseName = "leftAsofJoin:noCondGreaterThanTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ASOF;
param.cond = TEST_NO_COND;
param.asofOp = OP_TYPE_GREATER_THAN;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAsofJoin, noCondGreaterEqTest) {
SJoinTestParam param;
char* caseName = "leftAsofJoin:noCondGreaterEqTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ASOF;
param.cond = TEST_NO_COND;
param.asofOp = OP_TYPE_GREATER_EQUAL;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAsofJoin, noCondEqTest) {
SJoinTestParam param;
char* caseName = "leftAsofJoin:noCondEqTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ASOF;
param.cond = TEST_NO_COND;
param.asofOp = OP_TYPE_EQUAL;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAsofJoin, noCondLowerThanTest) {
SJoinTestParam param;
char* caseName = "leftAsofJoin:noCondLowerThanTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ASOF;
param.cond = TEST_NO_COND;
param.asofOp = OP_TYPE_LOWER_THAN;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#if 1
TEST(leftAsofJoin, noCondLowerEqTest) {
SJoinTestParam param;
char* caseName = "leftAsofJoin:noCondLowerEqTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_ASOF;
param.cond = TEST_NO_COND;
param.asofOp = OP_TYPE_LOWER_EQUAL;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
#if 1
#if 1
TEST(leftWinJoin, noCondProjectionTest) {
SJoinTestParam param;
char* caseName = "leftWinJoin:noCondProjectionTest";
SExecTaskInfo* pTask = createDummyTaskInfo(caseName);
assert(pTask);
param.pTask = pTask;
param.joinType = JOIN_TYPE_LEFT;
param.subType = JOIN_STYPE_WIN;
param.cond = TEST_NO_COND;
param.asc = true;
for (jtCtx.loopIdx = 0; jtCtx.loopIdx < JT_MAX_LOOP; ++jtCtx.loopIdx) {
param.asc = !param.asc;
param.jLimit = taosRand() % 2 ? (1 + (taosRand() % JT_MAX_JLIMIT)) : 1;
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = false;
runSingleTest(caseName, &param);
param.grpJoin = taosRand() % 2 ? true : false;
param.filter = true;
runSingleTest(caseName, &param);
}
printStatInfo(caseName);
taosMemoryFree(pTask);
}
#endif
#endif
int main(int argc, char** argv) {
taosSeedRand(taosGetTimestampSec());
initJoinTest();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#pragma GCC diagnosti