fix: add left join case
This commit is contained in:
parent
6d24c08651
commit
e55b7c52d8
|
@ -191,26 +191,29 @@ static int32_t doCopyNItems(struct SColumnInfoData* pColumnInfoData, int32_t cur
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t start = 1;
|
size_t start = 1;
|
||||||
|
|
||||||
// the first item
|
|
||||||
memcpy(pColumnInfoData->pData, pData, itemLen);
|
|
||||||
|
|
||||||
int32_t t = 0;
|
int32_t t = 0;
|
||||||
int32_t count = log(numOfRows) / log(2);
|
int32_t count = log(numOfRows) / log(2);
|
||||||
|
uint32_t startOffset = (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) ? pColumnInfoData->varmeta.length : (currentRow * itemLen);
|
||||||
|
|
||||||
|
// the first item
|
||||||
|
memcpy(pColumnInfoData->pData + startOffset, pData, itemLen);
|
||||||
|
|
||||||
while (t < count) {
|
while (t < count) {
|
||||||
int32_t xlen = 1 << t;
|
int32_t xlen = 1 << t;
|
||||||
memcpy(pColumnInfoData->pData + start * itemLen + pColumnInfoData->varmeta.length, pColumnInfoData->pData,
|
memcpy(pColumnInfoData->pData + start * itemLen + startOffset,
|
||||||
|
pColumnInfoData->pData + startOffset,
|
||||||
xlen * itemLen);
|
xlen * itemLen);
|
||||||
t += 1;
|
t += 1;
|
||||||
start += xlen;
|
start += xlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the tail part
|
// the tail part
|
||||||
if (numOfRows > start) {
|
if (numOfRows > start) {
|
||||||
memcpy(pColumnInfoData->pData + start * itemLen + currentRow * itemLen, pColumnInfoData->pData,
|
memcpy(pColumnInfoData->pData + start * itemLen + startOffset,
|
||||||
|
pColumnInfoData->pData + startOffset,
|
||||||
(numOfRows - start) * itemLen);
|
(numOfRows - start) * itemLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
|
if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
|
||||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||||
pColumnInfoData->varmeta.offset[i + currentRow] = pColumnInfoData->varmeta.length + i * itemLen;
|
pColumnInfoData->varmeta.offset[i + currentRow] = pColumnInfoData->varmeta.length + i * itemLen;
|
||||||
|
|
|
@ -191,15 +191,18 @@ typedef struct SMJoinOperatorInfo {
|
||||||
#define GRP_REMAIN_ROWS(_grp) ((_grp)->endIdx - (_grp)->readIdx + 1)
|
#define GRP_REMAIN_ROWS(_grp) ((_grp)->endIdx - (_grp)->readIdx + 1)
|
||||||
#define GRP_DONE(_grp) ((_grp)->readIdx > (_grp)->endIdx)
|
#define GRP_DONE(_grp) ((_grp)->readIdx > (_grp)->endIdx)
|
||||||
|
|
||||||
#define MJOIN_TB_ROWS_DONE(_tb) ((_tb)->blkRowIdx >= (_tb)->blk->info.rows)
|
#define MJOIN_PROBE_TB_ROWS_DONE(_tb) ((_tb)->blkRowIdx >= (_tb)->blk->info.rows)
|
||||||
|
#define MJOIN_BUILD_TB_ROWS_DONE(_tb) ((NULL == (_tb)->blk) || ((_tb)->blkRowIdx >= (_tb)->blk->info.rows))
|
||||||
|
|
||||||
#define BLK_IS_FULL(_blk) ((_blk)->info.rows == (_blk)->info.capacity)
|
#define BLK_IS_FULL(_blk) ((_blk)->info.rows == (_blk)->info.capacity)
|
||||||
|
|
||||||
|
|
||||||
#define MJOIN_GET_TB_COL_TS(_col, _ts, _tb) \
|
#define MJOIN_GET_TB_COL_TS(_col, _ts, _tb) \
|
||||||
do { \
|
do { \
|
||||||
(_col) = taosArrayGet((_tb)->blk->pDataBlock, (_tb)->primCol->srcSlot); \
|
if (NULL != (_tb)->blk) { \
|
||||||
(_ts) = *((int64_t*)(_col)->pData + (_tb)->blkRowIdx); \
|
(_col) = taosArrayGet((_tb)->blk->pDataBlock, (_tb)->primCol->srcSlot); \
|
||||||
|
(_ts) = *((int64_t*)(_col)->pData + (_tb)->blkRowIdx); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define MJOIN_GET_TB_CUR_TS(_col, _ts, _tb) \
|
#define MJOIN_GET_TB_CUR_TS(_col, _ts, _tb) \
|
||||||
|
|
|
@ -61,28 +61,37 @@ static int32_t mJoinInitPrimKeyInfo(SMJoinTableCtx* pTable, int32_t slotId) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t mJoinInitKeyColsInfo(SMJoinTableCtx* pTable, SNodeList* pList) {
|
static int32_t mJoinInitColsInfo(int32_t* colNum, int64_t* rowSize, SMJoinColInfo** pCols, SNodeList* pList) {
|
||||||
pTable->keyNum = LIST_LENGTH(pList);
|
*colNum = LIST_LENGTH(pList);
|
||||||
|
|
||||||
pTable->keyCols = taosMemoryMalloc(pTable->keyNum * sizeof(SMJoinColInfo));
|
*pCols = taosMemoryMalloc((*colNum) * sizeof(SMJoinColInfo));
|
||||||
if (NULL == pTable->keyCols) {
|
if (NULL == *pCols) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t bufSize = 0;
|
*rowSize = 0;
|
||||||
|
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
SNode* pNode = NULL;
|
SNode* pNode = NULL;
|
||||||
FOREACH(pNode, pList) {
|
FOREACH(pNode, pList) {
|
||||||
SColumnNode* pColNode = (SColumnNode*)pNode;
|
SColumnNode* pColNode = (SColumnNode*)pNode;
|
||||||
pTable->keyCols[i].srcSlot = pColNode->slotId;
|
(*pCols)[i].srcSlot = pColNode->slotId;
|
||||||
pTable->keyCols[i].vardata = IS_VAR_DATA_TYPE(pColNode->node.resType.type);
|
(*pCols)[i].vardata = IS_VAR_DATA_TYPE(pColNode->node.resType.type);
|
||||||
pTable->keyCols[i].bytes = pColNode->node.resType.bytes;
|
(*pCols)[i].bytes = pColNode->node.resType.bytes;
|
||||||
bufSize += pColNode->node.resType.bytes;
|
*rowSize += pColNode->node.resType.bytes;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t mJoinInitKeyColsInfo(SMJoinTableCtx* pTable, SNodeList* pList) {
|
||||||
|
int64_t rowSize = 0;
|
||||||
|
MJ_ERR_RET(mJoinInitColsInfo(&pTable->keyNum, &rowSize, &pTable->keyCols, pList));
|
||||||
|
|
||||||
if (pTable->keyNum > 1) {
|
if (pTable->keyNum > 1) {
|
||||||
pTable->keyBuf = taosMemoryMalloc(bufSize);
|
pTable->keyBuf = taosMemoryMalloc(rowSize);
|
||||||
if (NULL == pTable->keyBuf) {
|
if (NULL == pTable->keyBuf) {
|
||||||
return TSDB_CODE_OUT_OF_MEMORY;
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -91,27 +100,44 @@ static int32_t mJoinInitKeyColsInfo(SMJoinTableCtx* pTable, SNodeList* pList) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t mJoinInitColsMap(int32_t* colNum, SMJoinColMap** pCols, int32_t blkId, SNodeList* pList) {
|
||||||
|
*pCols = taosMemoryMalloc(LIST_LENGTH(pList) * sizeof(SMJoinColMap));
|
||||||
|
if (NULL == *pCols) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t i = 0;
|
||||||
|
SNode* pNode = NULL;
|
||||||
|
FOREACH(pNode, pList) {
|
||||||
|
STargetNode* pTarget = (STargetNode*)pNode;
|
||||||
|
SColumnNode* pColumn = (SColumnNode*)pTarget->pExpr;
|
||||||
|
if (pColumn->dataBlockId == blkId) {
|
||||||
|
(*pCols)[i].srcSlot = pColumn->slotId;
|
||||||
|
(*pCols)[i].dstSlot = pTarget->slotId;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*colNum = i;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t mJoinInitTableInfo(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode, SOperatorInfo** pDownstream, int32_t idx, SQueryStat* pStat) {
|
static int32_t mJoinInitTableInfo(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode, SOperatorInfo** pDownstream, int32_t idx, SQueryStat* pStat) {
|
||||||
SMJoinTableCtx* pTable = &pJoin->tbs[idx];
|
SMJoinTableCtx* pTable = &pJoin->tbs[idx];
|
||||||
pTable->downStream = pDownstream[idx];
|
pTable->downStream = pDownstream[idx];
|
||||||
pTable->blkId = pDownstream[idx]->resultDataBlockId;
|
pTable->blkId = pDownstream[idx]->resultDataBlockId;
|
||||||
int32_t code = mJoinInitPrimKeyInfo(pTable, (0 == idx) ? pJoinNode->leftPrimSlotId : pJoinNode->rightPrimSlotId);
|
MJ_ERR_RET(mJoinInitPrimKeyInfo(pTable, (0 == idx) ? pJoinNode->leftPrimSlotId : pJoinNode->rightPrimSlotId));
|
||||||
if (code) {
|
|
||||||
return code;
|
MJ_ERR_RET(mJoinInitKeyColsInfo(pTable, (0 == idx) ? pJoinNode->pEqLeft : pJoinNode->pEqRight));
|
||||||
}
|
MJ_ERR_RET(mJoinInitColsMap(&pTable->finNum, &pTable->finCols, pTable->blkId, pJoinNode->pTargets));
|
||||||
code = mJoinInitKeyColsInfo(pTable, (0 == idx) ? pJoinNode->pEqLeft : pJoinNode->pEqRight);
|
|
||||||
if (code) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
code = mJoinInitValColsInfo(pTable, pJoinNode->pTargets);
|
|
||||||
if (code) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
memcpy(&pTable->inputStat, pStat, sizeof(*pStat));
|
memcpy(&pTable->inputStat, pStat, sizeof(*pStat));
|
||||||
|
|
||||||
pTable->eqGrps = taosArrayInit(8, sizeof(SMJoinGrpRows));
|
pTable->eqGrps = taosArrayInit(8, sizeof(SMJoinGrpRows));
|
||||||
|
taosArrayReserve(pTable->eqGrps, 1);
|
||||||
|
|
||||||
if (E_JOIN_TB_BUILD == pTable->type) {
|
if (E_JOIN_TB_BUILD == pTable->type) {
|
||||||
pTable->createdBlks = taosArrayInit(8, POINTER_BYTES);
|
pTable->createdBlks = taosArrayInit(8, POINTER_BYTES);
|
||||||
pTable->pGrpArrays = taosArrayInit(32, POINTER_BYTES);
|
pTable->pGrpArrays = taosArrayInit(32, POINTER_BYTES);
|
||||||
|
@ -167,6 +193,7 @@ static void mJoinSetBuildAndProbeTable(SMJoinOperatorInfo* pInfo, SSortMergeJoin
|
||||||
static int32_t mJoinInitMergeCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode) {
|
static int32_t mJoinInitMergeCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode) {
|
||||||
SMJoinMergeCtx* pCtx = &pJoin->ctx.mergeCtx;
|
SMJoinMergeCtx* pCtx = &pJoin->ctx.mergeCtx;
|
||||||
|
|
||||||
|
pCtx->pJoin = pJoin;
|
||||||
pCtx->lastEqTs = INT64_MIN;
|
pCtx->lastEqTs = INT64_MIN;
|
||||||
pCtx->hashCan = pJoin->probe->keyNum > 0;
|
pCtx->hashCan = pJoin->probe->keyNum > 0;
|
||||||
|
|
||||||
|
@ -984,14 +1011,14 @@ static SSDataBlock* mLeftJoinDo(struct SOperatorInfo* pOperator) {
|
||||||
return pCtx->finBlk;
|
return pCtx->finBlk;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MJOIN_TB_ROWS_DONE(pJoin->probe)) {
|
if (MJOIN_PROBE_TB_ROWS_DONE(pJoin->probe)) {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
MJOIN_GET_TB_CUR_TS(pProbeCol, probeTs, pJoin->probe);
|
MJOIN_GET_TB_CUR_TS(pProbeCol, probeTs, pJoin->probe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!MJOIN_TB_ROWS_DONE(pJoin->probe) && !MJOIN_TB_ROWS_DONE(pJoin->build)) {
|
while (!MJOIN_PROBE_TB_ROWS_DONE(pJoin->probe) && !MJOIN_BUILD_TB_ROWS_DONE(pJoin->build)) {
|
||||||
if (probeTs == buildTs) {
|
if (probeTs == buildTs) {
|
||||||
pCtx->lastEqTs = probeTs;
|
pCtx->lastEqTs = probeTs;
|
||||||
MJ_ERR_JRET(mLeftJoinProcessEqualGrp(pCtx, probeTs, false));
|
MJ_ERR_JRET(mLeftJoinProcessEqualGrp(pCtx, probeTs, false));
|
||||||
|
@ -999,9 +1026,10 @@ static SSDataBlock* mLeftJoinDo(struct SOperatorInfo* pOperator) {
|
||||||
return pCtx->finBlk;
|
return pCtx->finBlk;
|
||||||
}
|
}
|
||||||
|
|
||||||
MJOIN_GET_TB_CUR_TS(pBuildCol, buildTs, pJoin->build);
|
MJOIN_GET_TB_COL_TS(pBuildCol, buildTs, pJoin->build);
|
||||||
MJOIN_GET_TB_CUR_TS(pProbeCol, probeTs, pJoin->probe);
|
MJOIN_GET_TB_COL_TS(pProbeCol, probeTs, pJoin->probe);
|
||||||
} else if (LEFT_JOIN_NO_EQUAL(asc, probeTs, buildTs)) {
|
} else if (LEFT_JOIN_NO_EQUAL(asc, probeTs, buildTs)) {
|
||||||
|
pCtx->probeNEqGrp.blk = pJoin->probe->blk;
|
||||||
pCtx->probeNEqGrp.beginIdx = pJoin->probe->blkRowIdx;
|
pCtx->probeNEqGrp.beginIdx = pJoin->probe->blkRowIdx;
|
||||||
pCtx->probeNEqGrp.readIdx = pCtx->probeNEqGrp.beginIdx;
|
pCtx->probeNEqGrp.readIdx = pCtx->probeNEqGrp.beginIdx;
|
||||||
pCtx->probeNEqGrp.endIdx = pCtx->probeNEqGrp.beginIdx;
|
pCtx->probeNEqGrp.endIdx = pCtx->probeNEqGrp.beginIdx;
|
||||||
|
@ -1031,6 +1059,20 @@ static SSDataBlock* mLeftJoinDo(struct SOperatorInfo* pOperator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!MJOIN_PROBE_TB_ROWS_DONE(pJoin->probe)) {
|
||||||
|
pCtx->probeNEqGrp.blk = pJoin->probe->blk;
|
||||||
|
pCtx->probeNEqGrp.beginIdx = pJoin->probe->blkRowIdx;
|
||||||
|
pCtx->probeNEqGrp.readIdx = pCtx->probeNEqGrp.beginIdx;
|
||||||
|
pCtx->probeNEqGrp.endIdx = pJoin->probe->blk->info.rows - 1;
|
||||||
|
|
||||||
|
pJoin->probe->blkRowIdx = pJoin->probe->blk->info.rows;
|
||||||
|
|
||||||
|
MJ_ERR_JRET(mLeftJoinNonEqCart(pCtx));
|
||||||
|
if (pCtx->finBlk->info.rows >= pCtx->blkThreshold) {
|
||||||
|
return pCtx->finBlk;
|
||||||
|
}
|
||||||
|
}
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
|
@ -1147,9 +1189,7 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t
|
||||||
|
|
||||||
mJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 0, &pJoinNode->inputStat[0]);
|
mJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 0, &pJoinNode->inputStat[0]);
|
||||||
mJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 1, &pJoinNode->inputStat[1]);
|
mJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 1, &pJoinNode->inputStat[1]);
|
||||||
|
|
||||||
MJ_ERR_JRET(mJoinInitCtx(pInfo, pJoinNode));
|
|
||||||
|
|
||||||
if (pJoinNode->pFullOnCond != NULL) {
|
if (pJoinNode->pFullOnCond != NULL) {
|
||||||
MJ_ERR_JRET(filterInitFromNode(pJoinNode->pFullOnCond, &pInfo->pFPreFilter, 0));
|
MJ_ERR_JRET(filterInitFromNode(pJoinNode->pFullOnCond, &pInfo->pFPreFilter, 0));
|
||||||
}
|
}
|
||||||
|
@ -1162,6 +1202,8 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t
|
||||||
MJ_ERR_JRET(filterInitFromNode(pJoinNode->node.pConditions, &pInfo->pFinFilter, 0));
|
MJ_ERR_JRET(filterInitFromNode(pJoinNode->node.pConditions, &pInfo->pFinFilter, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MJ_ERR_JRET(mJoinInitCtx(pInfo, pJoinNode));
|
||||||
|
|
||||||
if (pJoinNode->node.inputTsOrder == ORDER_ASC) {
|
if (pJoinNode->node.inputTsOrder == ORDER_ASC) {
|
||||||
pInfo->inputTsOrder = TSDB_ORDER_ASC;
|
pInfo->inputTsOrder = TSDB_ORDER_ASC;
|
||||||
} else if (pJoinNode->node.inputTsOrder == ORDER_DESC) {
|
} else if (pJoinNode->node.inputTsOrder == ORDER_DESC) {
|
||||||
|
|
|
@ -555,7 +555,7 @@ static EDealRes pdcJoinIsCrossTableCond(SNode* pNode, void* pContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ECondAction pdcJoinGetCondAction(SJoinLogicNode* pJoin, SSHashObj* pLeftTbls, SSHashObj* pRightTbls,
|
static ECondAction pdcJoinGetCondAction(SJoinLogicNode* pJoin, SSHashObj* pLeftTbls, SSHashObj* pRightTbls,
|
||||||
SNode* pNode) {
|
SNode* pNode, bool whereCond) {
|
||||||
EJoinType t = pJoin->joinType;
|
EJoinType t = pJoin->joinType;
|
||||||
EJoinSubType s = pJoin->subType;
|
EJoinSubType s = pJoin->subType;
|
||||||
SCpdIsMultiTableCondCxt cxt = {
|
SCpdIsMultiTableCondCxt cxt = {
|
||||||
|
@ -564,19 +564,19 @@ static ECondAction pdcJoinGetCondAction(SJoinLogicNode* pJoin, SSHashObj* pLeftT
|
||||||
|
|
||||||
if (cxt.havaLeftCol) {
|
if (cxt.havaLeftCol) {
|
||||||
if (cxt.haveRightCol) {
|
if (cxt.haveRightCol) {
|
||||||
if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_ON_COND) {
|
if ((!whereCond) || (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_ON_COND)) {
|
||||||
return COND_ACTION_PUSH_JOIN;
|
return COND_ACTION_PUSH_JOIN;
|
||||||
}
|
}
|
||||||
return COND_ACTION_STAY;
|
return COND_ACTION_STAY;
|
||||||
}
|
}
|
||||||
if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_LEFT_FLT) {
|
if ((!whereCond) || (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_LEFT_FLT)) {
|
||||||
return COND_ACTION_PUSH_LEFT_CHILD;
|
return COND_ACTION_PUSH_LEFT_CHILD;
|
||||||
}
|
}
|
||||||
return COND_ACTION_STAY;
|
return COND_ACTION_STAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cxt.haveRightCol) {
|
if (cxt.haveRightCol) {
|
||||||
if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_RIGHT_FLT) {
|
if ((!whereCond) || (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_RIGHT_FLT)) {
|
||||||
return COND_ACTION_PUSH_RIGHT_CHILD;
|
return COND_ACTION_PUSH_RIGHT_CHILD;
|
||||||
}
|
}
|
||||||
return COND_ACTION_STAY;
|
return COND_ACTION_STAY;
|
||||||
|
@ -586,7 +586,7 @@ static ECondAction pdcJoinGetCondAction(SJoinLogicNode* pJoin, SSHashObj* pLeftT
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
||||||
SNode** pRightChildCond) {
|
SNode** pRightChildCond, bool whereCond) {
|
||||||
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)*pSrcCond;
|
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)*pSrcCond;
|
||||||
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
|
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
|
||||||
return TSDB_CODE_PLAN_NOT_SUPPORT_JOIN_COND;
|
return TSDB_CODE_PLAN_NOT_SUPPORT_JOIN_COND;
|
||||||
|
@ -604,7 +604,7 @@ static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SN
|
||||||
SNodeList* pRemainConds = NULL;
|
SNodeList* pRemainConds = NULL;
|
||||||
SNode* pCond = NULL;
|
SNode* pCond = NULL;
|
||||||
FOREACH(pCond, pLogicCond->pParameterList) {
|
FOREACH(pCond, pLogicCond->pParameterList) {
|
||||||
ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, pCond);
|
ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, pCond, whereCond);
|
||||||
if (COND_ACTION_PUSH_JOIN == condAction && NULL != pOnCond) {
|
if (COND_ACTION_PUSH_JOIN == condAction && NULL != pOnCond) {
|
||||||
code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond));
|
code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond));
|
||||||
} else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) {
|
} else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) {
|
||||||
|
@ -662,13 +662,13 @@ static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SN
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t pdcJoinSplitOpCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
static int32_t pdcJoinSplitOpCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
||||||
SNode** pRightChildCond) {
|
SNode** pRightChildCond, bool whereCond) {
|
||||||
SSHashObj* pLeftTables = NULL;
|
SSHashObj* pLeftTables = NULL;
|
||||||
SSHashObj* pRightTables = NULL;
|
SSHashObj* pRightTables = NULL;
|
||||||
collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pLeftTables);
|
collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pLeftTables);
|
||||||
collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pRightTables);
|
collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pRightTables);
|
||||||
|
|
||||||
ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, *pSrcCond);
|
ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, *pSrcCond, whereCond);
|
||||||
|
|
||||||
tSimpleHashCleanup(pLeftTables);
|
tSimpleHashCleanup(pLeftTables);
|
||||||
tSimpleHashCleanup(pRightTables);
|
tSimpleHashCleanup(pRightTables);
|
||||||
|
@ -689,11 +689,11 @@ static int32_t pdcJoinSplitOpCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t pdcJoinSplitCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
static int32_t pdcJoinSplitCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond,
|
||||||
SNode** pRightChildCond) {
|
SNode** pRightChildCond, bool whereCond) {
|
||||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pSrcCond)) {
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pSrcCond)) {
|
||||||
return pdcJoinSplitLogicCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond);
|
return pdcJoinSplitLogicCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond, whereCond);
|
||||||
} else {
|
} else {
|
||||||
return pdcJoinSplitOpCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond);
|
return pdcJoinSplitOpCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond, whereCond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1132,7 +1132,7 @@ static int32_t pdcDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||||
SNode* pRightChildCond = NULL;
|
SNode* pRightChildCond = NULL;
|
||||||
int32_t code = pdcJoinCheckAllCond(pCxt, pJoin);
|
int32_t code = pdcJoinCheckAllCond(pCxt, pJoin);
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->node.pConditions && 0 != gJoinOpt[t][s].pushDownFlag) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->node.pConditions && 0 != gJoinOpt[t][s].pushDownFlag) {
|
||||||
code = pdcJoinSplitCond(pJoin, &pJoin->node.pConditions, &pOnCond, &pLeftChildCond, &pRightChildCond);
|
code = pdcJoinSplitCond(pJoin, &pJoin->node.pConditions, &pOnCond, &pLeftChildCond, &pRightChildCond, true);
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pOnCond) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pOnCond) {
|
||||||
code = pdcJoinPushDownOnCond(pCxt, pJoin, &pOnCond);
|
code = pdcJoinPushDownOnCond(pCxt, pJoin, &pOnCond);
|
||||||
}
|
}
|
||||||
|
@ -1145,7 +1145,7 @@ static int32_t pdcDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = pdcJoinSplitCond(pJoin, &pJoin->pFullOnCond, NULL, &pLeftChildCond, &pRightChildCond);
|
code = pdcJoinSplitCond(pJoin, &pJoin->pFullOnCond, NULL, &pLeftChildCond, &pRightChildCond, false);
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) {
|
||||||
code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond);
|
code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
system sh/stop_dnodes.sh
|
||||||
|
system sh/deploy.sh -n dnode1 -i 1
|
||||||
|
system sh/exec.sh -n dnode1 -s start
|
||||||
|
sql connect
|
||||||
|
sql drop database if exists test0
|
||||||
|
sql create database test0 vgroups 3;
|
||||||
|
sql use test0;
|
||||||
|
create stable sta (ts timestamp, col1 int) tags(t1 int);
|
||||||
|
create table tba1 using sta tags(1);
|
||||||
|
create table tba2 using sta tags(2);
|
||||||
|
|
||||||
|
insert into tba1 values ('2023-11-17 16:29:00', 1);
|
||||||
|
insert into tba1 values ('2023-11-17 16:29:02', 3);
|
||||||
|
insert into tba1 values ('2023-11-17 16:29:03', 4);
|
||||||
|
insert into tba1 values ('2023-11-17 16:29:04', 5);
|
||||||
|
|
||||||
|
insert into tba2 values ('2023-11-17 16:29:00', 2);
|
||||||
|
insert into tba2 values ('2023-11-17 16:29:01', 3);
|
||||||
|
insert into tba2 values ('2023-11-17 16:29:03', 5);
|
||||||
|
insert into tba2 values ('2023-11-17 16:29:05', 7);
|
||||||
|
|
||||||
|
sql drop database if exists testa
|
||||||
|
sql create database testa vgroups 3;
|
||||||
|
sql use testa;
|
||||||
|
|
||||||
|
sql create table sta1(ts timestamp, f int, g int) tags (t int);
|
||||||
|
sql insert into cta11 using sta1 tags(1) values('2023-10-16 09:10:11', 100111, 1001110);
|
||||||
|
sql insert into cta12 using sta1 tags(2) values('2023-10-16 09:10:12', 100112, 1001120);
|
||||||
|
sql insert into cta13 using sta1 tags(3) values('2023-10-16 09:10:13', 100113, 1001130);
|
||||||
|
sql insert into cta14 using sta1 tags(4) values('2023-10-16 09:10:14', 100114, 1001140);
|
||||||
|
|
||||||
|
sql create table st2(ts timestamp, f int, g int) tags (t int);
|
||||||
|
sql insert into cta21 using st2 tags(1) values('2023-10-16 09:10:11', 100221, 1002210);
|
||||||
|
sql insert into cta22 using st2 tags(2) values('2023-10-16 09:10:12', 100222, 1002220);
|
||||||
|
sql insert into cta23 using st2 tags(3) values('2023-10-16 09:10:13', 100223, 1002230);
|
||||||
|
sql insert into cta24 using st2 tags(4) values('2023-10-16 09:10:14', 100224, 1002240);
|
||||||
|
|
||||||
|
sql create table stt(ts timestamp, f int, g int) tags (t int);
|
||||||
|
sql create table tt using stt tags(99);
|
||||||
|
|
||||||
|
sql create table stv(ts timestamp, h int) tags (t1 int);
|
||||||
|
sql insert into ctv1 using stv tags(1) values('2023-10-16 10:10:10', 1);
|
||||||
|
|
||||||
|
sql drop database if exists testb
|
||||||
|
sql create database testb vgroups 1;
|
||||||
|
sql use testb;
|
||||||
|
|
||||||
|
sql create table stb1(ts timestamp, f int,g int) tags (t int);
|
||||||
|
sql insert into ctb11 using stb1 tags(1) values('2023-10-16 09:10:11', 110111, 1101110);
|
||||||
|
sql insert into ctb12 using stb1 tags(2) values('2023-10-16 09:10:12', 110112, 1101120);
|
||||||
|
sql insert into ctb13 using stb1 tags(3) values('2023-10-16 09:10:13', 110113, 1101130);
|
||||||
|
sql insert into ctb14 using stb1 tags(4) values('2023-10-16 09:10:14', 110114, 1101140);
|
||||||
|
|
||||||
|
sql create table st2(ts timestamp, f int, g int) tags (t int);
|
||||||
|
sql insert into ctb21 using st2 tags(1) values('2023-10-16 09:10:11', 110221, 1102210);
|
||||||
|
sql insert into ctb22 using st2 tags(2) values('2023-10-16 09:10:12', 110222, 1102220);
|
||||||
|
sql insert into ctb23 using st2 tags(3) values('2023-10-16 09:10:13', 110223, 1102230);
|
||||||
|
sql insert into ctb24 using st2 tags(4) values('2023-10-16 09:10:14', 110224, 1102240);
|
||||||
|
|
||||||
|
run tsim/join/left_join.sim
|
||||||
|
|
||||||
|
print ================== restart server to commit data into disk
|
||||||
|
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
||||||
|
system sh/exec.sh -n dnode1 -s start
|
||||||
|
print ================== server restart completed
|
||||||
|
|
||||||
|
run tsim/join/left_join.sim
|
||||||
|
|
||||||
|
system sh/exec.sh -n dnode1 -s stop -x SIGINT
|
|
@ -0,0 +1,96 @@
|
||||||
|
sql connect
|
||||||
|
sql use test0;
|
||||||
|
|
||||||
|
sql select a.col1, b.col1 from sta a left join sta b on a.ts = b.ts and a.ts < '2023-11-17 16:29:02' and b.ts < '2023-11-17 16:29:01' order by a.col1, b.col1;
|
||||||
|
if $rows != 5 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data00 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data01 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data10 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data11 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data20 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data21 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data30 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data31 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data40 != 3 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data41 != NULL then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
||||||
|
sql select a.col1, b.col1 from tba1 a left join tba2 b on a.ts = b.ts order by a.col1, b.col1;
|
||||||
|
if $rows != 4 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data00 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data01 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data10 != 3 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data11 != NULL then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data20 != 4 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data21 != 5 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data30 != 5 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data31 != NULL then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
||||||
|
sql select a.col1, b.col1 from tba2 a left join tba1 b on a.ts = b.ts order by a.col1, b.col1;
|
||||||
|
if $rows != 4 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data00 != 2 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data01 != 1 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data10 != 3 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data11 != NULL then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data20 != 5 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data21 != 4 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data30 != 7 then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
if $data31 != NULL then
|
||||||
|
return -1
|
||||||
|
endi
|
||||||
|
|
Loading…
Reference in New Issue