enh: support hash join
This commit is contained in:
parent
86db8efcda
commit
319ab5f2c2
|
@ -151,9 +151,10 @@ typedef struct SJoinLogicNode {
|
||||||
bool hashJoinHint;
|
bool hashJoinHint;
|
||||||
|
|
||||||
// FOR HASH JOIN
|
// FOR HASH JOIN
|
||||||
STimeWindow timeRange; //table onCond filter
|
int32_t timeRangeTarget; //table onCond filter
|
||||||
SNode* pLeftOnCond; //table onCond filter
|
STimeWindow timeRange; //table onCond filter
|
||||||
SNode* pRightOnCond; //table onCond filter
|
SNode* pLeftOnCond; //table onCond filter
|
||||||
|
SNode* pRightOnCond; //table onCond filter
|
||||||
} SJoinLogicNode;
|
} SJoinLogicNode;
|
||||||
|
|
||||||
typedef struct SAggLogicNode {
|
typedef struct SAggLogicNode {
|
||||||
|
@ -527,10 +528,15 @@ typedef struct SHashJoinPhysiNode {
|
||||||
SNode* pJLimit;
|
SNode* pJLimit;
|
||||||
SNodeList* pOnLeft;
|
SNodeList* pOnLeft;
|
||||||
SNodeList* pOnRight;
|
SNodeList* pOnRight;
|
||||||
STimeWindow timeRange; //table onCond filter
|
SNode* leftPrimExpr;
|
||||||
SNode* pLeftOnCond; //table onCond filter
|
SNode* rightPrimExpr;
|
||||||
SNode* pRightOnCond; //table onCond filter
|
int32_t leftPrimSlotId;
|
||||||
SNode* pFullOnCond; //preFilter
|
int32_t rightPrimSlotId;
|
||||||
|
int32_t timeRangeTarget; //table onCond filter
|
||||||
|
STimeWindow timeRange; //table onCond filter
|
||||||
|
SNode* pLeftOnCond; //table onCond filter
|
||||||
|
SNode* pRightOnCond; //table onCond filter
|
||||||
|
SNode* pFullOnCond; //preFilter
|
||||||
SNodeList* pTargets;
|
SNodeList* pTargets;
|
||||||
SQueryStat inputStat[2];
|
SQueryStat inputStat[2];
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,15 @@ enum {
|
||||||
FLT_OPTION_NEED_UNIQE = 4,
|
FLT_OPTION_NEED_UNIQE = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum EConditionType {
|
||||||
|
COND_TYPE_PRIMARY_KEY = 1,
|
||||||
|
COND_TYPE_TAG_INDEX,
|
||||||
|
COND_TYPE_TAG,
|
||||||
|
COND_TYPE_NORMAL
|
||||||
|
} EConditionType;
|
||||||
|
|
||||||
|
|
||||||
#define FILTER_RESULT_ALL_QUALIFIED 0x1
|
#define FILTER_RESULT_ALL_QUALIFIED 0x1
|
||||||
#define FILTER_RESULT_NONE_QUALIFIED 0x2
|
#define FILTER_RESULT_NONE_QUALIFIED 0x2
|
||||||
#define FILTER_RESULT_PARTIAL_QUALIFIED 0x3
|
#define FILTER_RESULT_PARTIAL_QUALIFIED 0x3
|
||||||
|
@ -54,6 +63,8 @@ extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg **pColsAgg,
|
||||||
/* condition split interface */
|
/* condition split interface */
|
||||||
int32_t filterPartitionCond(SNode **pCondition, SNode **pPrimaryKeyCond, SNode **pTagIndexCond, SNode **pTagCond,
|
int32_t filterPartitionCond(SNode **pCondition, SNode **pPrimaryKeyCond, SNode **pTagIndexCond, SNode **pTagCond,
|
||||||
SNode **pOtherCond);
|
SNode **pOtherCond);
|
||||||
|
bool filterIsMultiTableColsCond(SNode *pCond);
|
||||||
|
EConditionType filterClassifyCondition(SNode *pNode);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,7 @@ extern "C" {
|
||||||
#define EXPLAIN_JOIN_EQ_RIGHT_FORMAT "Right Equal Cond: "
|
#define EXPLAIN_JOIN_EQ_RIGHT_FORMAT "Right Equal Cond: "
|
||||||
#define EXPLAIN_COUNT_NUM_FORMAT "Window Count=%" PRId64
|
#define EXPLAIN_COUNT_NUM_FORMAT "Window Count=%" PRId64
|
||||||
#define EXPLAIN_COUNT_SLIDING_FORMAT "Window Sliding=%" PRId64
|
#define EXPLAIN_COUNT_SLIDING_FORMAT "Window Sliding=%" PRId64
|
||||||
|
#define EXPLAIN_TABLE_TIMERANGE_FORMAT "%s Table Time Range: [%" PRId64 ", %" PRId64 "]"
|
||||||
|
|
||||||
#define EXPLAIN_PLANNING_TIME_FORMAT "Planning Time: %.3f ms"
|
#define EXPLAIN_PLANNING_TIME_FORMAT "Planning Time: %.3f ms"
|
||||||
#define EXPLAIN_EXEC_TIME_FORMAT "Execution Time: %.3f ms"
|
#define EXPLAIN_EXEC_TIME_FORMAT "Execution Time: %.3f ms"
|
||||||
|
|
|
@ -61,6 +61,15 @@ char* qExplainGetAsofOpStr(int32_t opType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* qExplainGetTimerangeTargetStr(int32_t target) {
|
||||||
|
static char* targetName[] = {"", "Left", "Right", "Left/Right"};
|
||||||
|
if (target <= 0 || target > 3) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetName[target];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void qExplainFreeResNode(SExplainResNode *resNode) {
|
void qExplainFreeResNode(SExplainResNode *resNode) {
|
||||||
if (NULL == resNode) {
|
if (NULL == resNode) {
|
||||||
|
@ -1700,19 +1709,11 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
|
||||||
EXPLAIN_ROW_END();
|
EXPLAIN_ROW_END();
|
||||||
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
|
|
||||||
if (pJoinNode->node.pConditions || pJoinNode->pFullOnCond) {
|
if (pJoinNode->node.pConditions) {
|
||||||
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
|
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_FILTER_FORMAT);
|
||||||
if (pJoinNode->node.pConditions) {
|
QRY_ERR_RET(nodesNodeToSQL(pJoinNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
|
||||||
QRY_ERR_RET(nodesNodeToSQL(pJoinNode->node.pConditions, tbuf + VARSTR_HEADER_SIZE,
|
TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
||||||
TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
|
||||||
}
|
|
||||||
if (pJoinNode->pFullOnCond) {
|
|
||||||
if (pJoinNode->node.pConditions) {
|
|
||||||
EXPLAIN_ROW_APPEND(" AND ");
|
|
||||||
}
|
|
||||||
QRY_ERR_RET(nodesNodeToSQL(pJoinNode->pFullOnCond, tbuf + VARSTR_HEADER_SIZE,
|
|
||||||
TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
|
||||||
}
|
|
||||||
EXPLAIN_ROW_END();
|
EXPLAIN_ROW_END();
|
||||||
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
}
|
}
|
||||||
|
@ -1740,8 +1741,21 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
|
||||||
nodesNodeToSQL(pJoinNode->pTagEqCond, tbuf + VARSTR_HEADER_SIZE, TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
nodesNodeToSQL(pJoinNode->pTagEqCond, tbuf + VARSTR_HEADER_SIZE, TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
||||||
conditionsGot = true;
|
conditionsGot = true;
|
||||||
}
|
}
|
||||||
|
if (pJoinNode->pFullOnCond) {
|
||||||
|
if (conditionsGot) {
|
||||||
|
EXPLAIN_ROW_APPEND(" AND ");
|
||||||
|
}
|
||||||
|
QRY_ERR_RET(nodesNodeToSQL(pJoinNode->pFullOnCond, tbuf + VARSTR_HEADER_SIZE,
|
||||||
|
TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen));
|
||||||
|
}
|
||||||
EXPLAIN_ROW_END();
|
EXPLAIN_ROW_END();
|
||||||
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
|
|
||||||
|
if (pJoinNode->timeRangeTarget) {
|
||||||
|
EXPLAIN_ROW_NEW(level + 1, EXPLAIN_TABLE_TIMERANGE_FORMAT, qExplainGetTimerangeTargetStr(pJoinNode->timeRangeTarget), pJoinNode->timeRange.skey, pJoinNode->timeRange.ekey);
|
||||||
|
EXPLAIN_ROW_END();
|
||||||
|
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ extern "C" {
|
||||||
#define HJOIN_ROW_BITMAP_SIZE (2 * 1048576)
|
#define HJOIN_ROW_BITMAP_SIZE (2 * 1048576)
|
||||||
#define HJOIN_BLK_THRESHOLD_RATIO 0.9
|
#define HJOIN_BLK_THRESHOLD_RATIO 0.9
|
||||||
|
|
||||||
|
typedef int32_t (*hJoinImplFp)(SOperatorInfo*);
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct SBufRowInfo {
|
typedef struct SBufRowInfo {
|
||||||
void* next;
|
void* next;
|
||||||
|
@ -33,12 +36,24 @@ typedef struct SBufRowInfo {
|
||||||
} SBufRowInfo;
|
} SBufRowInfo;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
typedef enum EHJoinPhase {
|
||||||
|
E_JOIN_PHASE_PRE = 1,
|
||||||
|
E_JOIN_PHASE_CUR,
|
||||||
|
E_JOIN_PHASE_POST
|
||||||
|
} EHJoinPhase;
|
||||||
|
|
||||||
typedef struct SHJoinCtx {
|
typedef struct SHJoinCtx {
|
||||||
bool rowRemains;
|
bool rowRemains;
|
||||||
|
bool midRemains;
|
||||||
int64_t limit;
|
int64_t limit;
|
||||||
SBufRowInfo* pBuildRow;
|
SBufRowInfo* pBuildRow;
|
||||||
SSDataBlock* pProbeData;
|
SSDataBlock* pProbeData;
|
||||||
int32_t probeIdx;
|
EHJoinPhase probePhase;
|
||||||
|
int32_t probePreIdx;
|
||||||
|
int32_t probeStartIdx;
|
||||||
|
int32_t probeEndIdx;
|
||||||
|
int32_t probePostIdx;
|
||||||
|
bool readMatch;
|
||||||
} SHJoinCtx;
|
} SHJoinCtx;
|
||||||
|
|
||||||
typedef struct SHJoinColInfo {
|
typedef struct SHJoinColInfo {
|
||||||
|
@ -64,11 +79,31 @@ typedef struct SGroupData {
|
||||||
SBufRowInfo* rows;
|
SBufRowInfo* rows;
|
||||||
} SGroupData;
|
} SGroupData;
|
||||||
|
|
||||||
typedef struct SHJoinTableInfo {
|
|
||||||
|
typedef struct SHJoinColMap {
|
||||||
|
int32_t srcSlot;
|
||||||
|
int32_t dstSlot;
|
||||||
|
bool vardata;
|
||||||
|
int32_t bytes;
|
||||||
|
} SHJoinColMap;
|
||||||
|
|
||||||
|
// for now timetruncate only
|
||||||
|
typedef struct SHJoinPrimExprCtx {
|
||||||
|
int64_t truncateUnit;
|
||||||
|
int64_t timezoneUnit;
|
||||||
|
int32_t targetSlotId;
|
||||||
|
} SHJoinPrimExprCtx;
|
||||||
|
|
||||||
|
typedef struct SHJoinTableCtx {
|
||||||
int32_t downStreamIdx;
|
int32_t downStreamIdx;
|
||||||
SOperatorInfo* downStream;
|
SOperatorInfo* downStream;
|
||||||
int32_t blkId;
|
int32_t blkId;
|
||||||
SQueryStat inputStat;
|
SQueryStat inputStat;
|
||||||
|
bool hasTimeRange;
|
||||||
|
|
||||||
|
SHJoinColMap* primCol;
|
||||||
|
SNode* primExpr;
|
||||||
|
SHJoinPrimExprCtx primCtx;
|
||||||
|
|
||||||
int32_t keyNum;
|
int32_t keyNum;
|
||||||
SHJoinColInfo* keyCols;
|
SHJoinColInfo* keyCols;
|
||||||
|
@ -82,7 +117,7 @@ typedef struct SHJoinTableInfo {
|
||||||
int32_t valBufSize;
|
int32_t valBufSize;
|
||||||
SArray* valVarCols;
|
SArray* valVarCols;
|
||||||
bool valColExist;
|
bool valColExist;
|
||||||
} SHJoinTableInfo;
|
} SHJoinTableCtx;
|
||||||
|
|
||||||
typedef struct SHJoinExecInfo {
|
typedef struct SHJoinExecInfo {
|
||||||
int64_t buildBlkNum;
|
int64_t buildBlkNum;
|
||||||
|
@ -95,14 +130,16 @@ typedef struct SHJoinExecInfo {
|
||||||
|
|
||||||
|
|
||||||
typedef struct SHJoinOperatorInfo {
|
typedef struct SHJoinOperatorInfo {
|
||||||
int32_t joinType;
|
EJoinType joinType;
|
||||||
SHJoinTableInfo tbs[2];
|
EJoinSubType subType;
|
||||||
SHJoinTableInfo* pBuild;
|
SHJoinTableCtx tbs[2];
|
||||||
SHJoinTableInfo* pProbe;
|
SHJoinTableCtx* pBuild;
|
||||||
|
SHJoinTableCtx* pProbe;
|
||||||
SFilterInfo* pPreFilter;
|
SFilterInfo* pPreFilter;
|
||||||
SFilterInfo* pFinFilter;
|
SFilterInfo* pFinFilter;
|
||||||
SSDataBlock* finBlk;
|
SSDataBlock* finBlk;
|
||||||
SSDataBlock* midBlk;
|
SSDataBlock* midBlk;
|
||||||
|
STimeWindow tblTimeRange;
|
||||||
int32_t pResColNum;
|
int32_t pResColNum;
|
||||||
int8_t* pResColMap;
|
int8_t* pResColMap;
|
||||||
SArray* pRowBufs;
|
SArray* pRowBufs;
|
||||||
|
@ -111,6 +148,7 @@ typedef struct SHJoinOperatorInfo {
|
||||||
SHJoinCtx ctx;
|
SHJoinCtx ctx;
|
||||||
SHJoinExecInfo execInfo;
|
SHJoinExecInfo execInfo;
|
||||||
int32_t blkThreshold;
|
int32_t blkThreshold;
|
||||||
|
hJoinImplFp joinFp;
|
||||||
} SHJoinOperatorInfo;
|
} SHJoinOperatorInfo;
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,6 +170,16 @@ typedef struct SHJoinOperatorInfo {
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
int32_t hInnerJoinDo(struct SOperatorInfo* pOperator);
|
||||||
|
int32_t hLeftJoinDo(struct SOperatorInfo* pOperator);
|
||||||
|
void hJoinSetDone(struct SOperatorInfo* pOperator);
|
||||||
|
void hJoinAppendResToBlock(struct SOperatorInfo* pOperator, SSDataBlock* pRes, bool* allFetched);
|
||||||
|
bool hJoinCopyKeyColsDataToBuf(SHJoinTableCtx* pTable, int32_t rowIdx, size_t *pBufLen);
|
||||||
|
int32_t hJoinCopyMergeMidBlk(SHJoinCtx* pCtx, SSDataBlock** ppMid, SSDataBlock** ppFin);
|
||||||
|
int32_t hJoinHandleMidRemains(SHJoinOperatorInfo* pJoin, SHJoinCtx* pCtx);
|
||||||
|
bool hJoinBlkReachThreshold(SHJoinOperatorInfo* pInfo, int64_t blkRows);
|
||||||
|
int32_t hJoinCopyNMatchRowsToBlock(SHJoinOperatorInfo* pJoin, SSDataBlock* pRes, int32_t startIdx, int32_t rows);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
||||||
#define MJOIN_BLK_SIZE_LIMIT 10485760
|
#define MJOIN_BLK_SIZE_LIMIT 10485760
|
||||||
#define MJOIN_ROW_BITMAP_SIZE (2 * 1048576)
|
#define MJOIN_ROW_BITMAP_SIZE (2 * 1048576)
|
||||||
#endif
|
#endif
|
||||||
|
#define MJOIN_SEMI_ANTI_BLK_ROWS_NUM 64
|
||||||
#define MJOIN_BLK_THRESHOLD_RATIO 0.9
|
#define MJOIN_BLK_THRESHOLD_RATIO 0.9
|
||||||
|
|
||||||
struct SMJoinOperatorInfo;
|
struct SMJoinOperatorInfo;
|
||||||
|
|
|
@ -29,3 +29,321 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t hInnerJoinDo(struct SOperatorInfo* pOperator) {
|
||||||
|
SHJoinOperatorInfo* pJoin = pOperator->info;
|
||||||
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
SSDataBlock* pRes = pJoin->finBlk;
|
||||||
|
size_t bufLen = 0;
|
||||||
|
int32_t code = 0;
|
||||||
|
bool allFetched = false;
|
||||||
|
|
||||||
|
if (pJoin->ctx.pBuildRow) {
|
||||||
|
hJoinAppendResToBlock(pOperator, pRes, &allFetched);
|
||||||
|
if (pRes->info.rows >= pRes->info.capacity) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
} else {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; pCtx->probeStartIdx <= pCtx->probeEndIdx; ++pCtx->probeStartIdx) {
|
||||||
|
if (hJoinCopyKeyColsDataToBuf(pProbe, pCtx->probeStartIdx, &bufLen)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGroupData* pGroup = tSimpleHashGet(pJoin->pKeyHash, pProbe->keyData, bufLen);
|
||||||
|
/*
|
||||||
|
size_t keySize = 0;
|
||||||
|
int32_t* pKey = tSimpleHashGetKey(pGroup, &keySize);
|
||||||
|
ASSERT(keySize == bufLen && 0 == memcmp(pKey, pProbe->keyData, bufLen));
|
||||||
|
int64_t rows = getSingleKeyRowsNum(pGroup->rows);
|
||||||
|
pJoin->execInfo.expectRows += rows;
|
||||||
|
qTrace("hash_key:%d, rows:%" PRId64, *pKey, rows);
|
||||||
|
*/
|
||||||
|
if (pGroup) {
|
||||||
|
pCtx->pBuildRow = pGroup->rows;
|
||||||
|
hJoinAppendResToBlock(pOperator, pRes, &allFetched);
|
||||||
|
if (pRes->info.rows >= pRes->info.capacity) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->rowRemains = false;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hLeftJoinHandleSeqRowRemains(struct SOperatorInfo* pOperator, SHJoinOperatorInfo* pJoin, bool* loopCont) {
|
||||||
|
bool allFetched = false;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
|
||||||
|
while (!allFetched) {
|
||||||
|
hJoinAppendResToBlock(pOperator, pJoin->midBlk, &allFetched);
|
||||||
|
if (pJoin->midBlk->info.rows > 0) {
|
||||||
|
doFilter(pJoin->midBlk, pJoin->pPreFilter, NULL);
|
||||||
|
if (pJoin->midBlk->info.rows > 0) {
|
||||||
|
pCtx->readMatch = true;
|
||||||
|
HJ_ERR_RET(hJoinCopyMergeMidBlk(pCtx, &pJoin->midBlk, &pJoin->finBlk));
|
||||||
|
|
||||||
|
if (pCtx->midRemains) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = false;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allFetched && !pCtx->readMatch) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pCtx->probeStartIdx, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = false;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
*loopCont = true;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hLeftJoinHandleSeqProbeRows(struct SOperatorInfo* pOperator, SHJoinOperatorInfo* pJoin, bool* loopCont) {
|
||||||
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
size_t bufLen = 0;
|
||||||
|
bool allFetched = false;
|
||||||
|
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; pCtx->probeStartIdx <= pCtx->probeEndIdx; ++pCtx->probeStartIdx) {
|
||||||
|
if (hJoinCopyKeyColsDataToBuf(pProbe, pCtx->probeStartIdx, &bufLen)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGroupData* pGroup = tSimpleHashGet(pJoin->pKeyHash, pProbe->keyData, bufLen);
|
||||||
|
/*
|
||||||
|
size_t keySize = 0;
|
||||||
|
int32_t* pKey = tSimpleHashGetKey(pGroup, &keySize);
|
||||||
|
ASSERT(keySize == bufLen && 0 == memcmp(pKey, pProbe->keyData, bufLen));
|
||||||
|
int64_t rows = getSingleKeyRowsNum(pGroup->rows);
|
||||||
|
pJoin->execInfo.expectRows += rows;
|
||||||
|
qTrace("hash_key:%d, rows:%" PRId64, *pKey, rows);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NULL == pGroup) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pCtx->probeStartIdx, 1));
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
*loopCont = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->readMatch = false;
|
||||||
|
pCtx->pBuildRow = pGroup->rows;
|
||||||
|
allFetched = false;
|
||||||
|
|
||||||
|
while (!allFetched) {
|
||||||
|
hJoinAppendResToBlock(pOperator, pJoin->midBlk, &allFetched);
|
||||||
|
if (pJoin->midBlk->info.rows > 0) {
|
||||||
|
doFilter(pJoin->midBlk, pJoin->pPreFilter, NULL);
|
||||||
|
if (pJoin->midBlk->info.rows > 0) {
|
||||||
|
pCtx->readMatch = true;
|
||||||
|
HJ_ERR_RET(hJoinCopyMergeMidBlk(pCtx, &pJoin->midBlk, &pJoin->finBlk));
|
||||||
|
|
||||||
|
if (pCtx->midRemains) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allFetched && !pCtx->readMatch) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pCtx->probeStartIdx, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->probePhase = E_JOIN_PHASE_POST;
|
||||||
|
*loopCont = true;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t hLeftJoinHandleRowRemains(struct SOperatorInfo* pOperator, SHJoinOperatorInfo* pJoin, bool* loopCont) {
|
||||||
|
bool allFetched = false;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
|
||||||
|
hJoinAppendResToBlock(pOperator, pJoin->finBlk, &allFetched);
|
||||||
|
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = false;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
} else {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*loopCont = true;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t hLeftJoinHandleProbeRows(struct SOperatorInfo* pOperator, SHJoinOperatorInfo* pJoin, bool* loopCont) {
|
||||||
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
size_t bufLen = 0;
|
||||||
|
bool allFetched = false;
|
||||||
|
|
||||||
|
for (; pCtx->probeStartIdx <= pCtx->probeEndIdx; ++pCtx->probeStartIdx) {
|
||||||
|
if (hJoinCopyKeyColsDataToBuf(pProbe, pCtx->probeStartIdx, &bufLen)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGroupData* pGroup = tSimpleHashGet(pJoin->pKeyHash, pProbe->keyData, bufLen);
|
||||||
|
/*
|
||||||
|
size_t keySize = 0;
|
||||||
|
int32_t* pKey = tSimpleHashGetKey(pGroup, &keySize);
|
||||||
|
ASSERT(keySize == bufLen && 0 == memcmp(pKey, pProbe->keyData, bufLen));
|
||||||
|
int64_t rows = getSingleKeyRowsNum(pGroup->rows);
|
||||||
|
pJoin->execInfo.expectRows += rows;
|
||||||
|
qTrace("hash_key:%d, rows:%" PRId64, *pKey, rows);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NULL == pGroup) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pCtx->probeStartIdx, 1));
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
*loopCont = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->pBuildRow = pGroup->rows;
|
||||||
|
|
||||||
|
hJoinAppendResToBlock(pOperator, pJoin->finBlk, &allFetched);
|
||||||
|
if (hJoinBlkReachThreshold(pJoin, pJoin->finBlk->info.rows)) {
|
||||||
|
if (allFetched) {
|
||||||
|
++pCtx->probeStartIdx;
|
||||||
|
}
|
||||||
|
*loopCont = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->probePhase = E_JOIN_PHASE_POST;
|
||||||
|
*loopCont = true;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int32_t hLeftJoinDo(struct SOperatorInfo* pOperator) {
|
||||||
|
SHJoinOperatorInfo* pJoin = pOperator->info;
|
||||||
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
|
|
||||||
|
while (pCtx->rowRemains) {
|
||||||
|
switch (pCtx->probePhase) {
|
||||||
|
case E_JOIN_PHASE_PRE: {
|
||||||
|
int32_t rows = pCtx->probeStartIdx - pCtx->probePreIdx;
|
||||||
|
int32_t rowsLeft = pJoin->finBlk->info.capacity - pJoin->finBlk->info.rows;
|
||||||
|
if (rows <= rowsLeft) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, 0, rows));
|
||||||
|
pCtx->probePhase = E_JOIN_PHASE_CUR;
|
||||||
|
} else {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, 0, rowsLeft));
|
||||||
|
pJoin->ctx.probePreIdx += rowsLeft;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_JOIN_PHASE_CUR: {
|
||||||
|
bool loopCont = false;
|
||||||
|
if (NULL == pJoin->ctx.pBuildRow) {
|
||||||
|
HJ_ERR_RET(pJoin->pPreFilter ? hLeftJoinHandleSeqProbeRows(pOperator, pJoin, &loopCont) : hLeftJoinHandleProbeRows(pOperator, pJoin, &loopCont));
|
||||||
|
} else {
|
||||||
|
HJ_ERR_RET(pJoin->pPreFilter ? hLeftJoinHandleSeqRowRemains(pOperator, pJoin, &loopCont) : hLeftJoinHandleRowRemains(pOperator, pJoin, &loopCont));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loopCont) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_JOIN_PHASE_POST: {
|
||||||
|
if (pCtx->probeEndIdx < (pCtx->pProbeData->info.rows - 1) && pCtx->probePostIdx <= (pCtx->pProbeData->info.rows - 1)) {
|
||||||
|
int32_t rowsLeft = pJoin->finBlk->info.capacity - pJoin->finBlk->info.rows;
|
||||||
|
int32_t rows = pCtx->pProbeData->info.rows - pCtx->probePostIdx;
|
||||||
|
if (rows <= rowsLeft) {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pJoin->ctx.probePostIdx, rows));
|
||||||
|
pCtx->rowRemains = false;
|
||||||
|
} else {
|
||||||
|
HJ_ERR_RET(hJoinCopyNMatchRowsToBlock(pJoin, pJoin->finBlk, pJoin->ctx.probePostIdx, rowsLeft));
|
||||||
|
pCtx->probePostIdx += rowsLeft;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pJoin->ctx.rowRemains = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,106 @@
|
||||||
#include "tmsg.h"
|
#include "tmsg.h"
|
||||||
#include "ttypes.h"
|
#include "ttypes.h"
|
||||||
#include "hashjoin.h"
|
#include "hashjoin.h"
|
||||||
|
#include "functionMgt.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool hJoinBlkReachThreshold(SHJoinOperatorInfo* pInfo, int64_t blkRows) {
|
||||||
|
if (INT64_MAX == pInfo->ctx.limit || pInfo->pFinFilter != NULL) {
|
||||||
|
return blkRows >= pInfo->blkThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (pInfo->execInfo.resRows + blkRows) >= pInfo->ctx.limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hJoinHandleMidRemains(SHJoinOperatorInfo* pJoin, SHJoinCtx* pCtx) {
|
||||||
|
ASSERT(0 < pJoin->midBlk->info.rows);
|
||||||
|
|
||||||
|
TSWAP(pJoin->midBlk, pJoin->finBlk);
|
||||||
|
|
||||||
|
pCtx->midRemains = false;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hJoinCopyMergeMidBlk(SHJoinCtx* pCtx, SSDataBlock** ppMid, SSDataBlock** ppFin) {
|
||||||
|
SSDataBlock* pLess = *ppMid;
|
||||||
|
SSDataBlock* pMore = *ppFin;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ((*ppMid)->info.rows < (*ppFin)->info.rows) {
|
||||||
|
pLess = (*ppMid);
|
||||||
|
pMore = (*ppFin);
|
||||||
|
} else {
|
||||||
|
pLess = (*ppFin);
|
||||||
|
pMore = (*ppMid);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32_t totalRows = pMore->info.rows + pLess->info.rows;
|
||||||
|
if (totalRows <= pMore->info.capacity) {
|
||||||
|
HJ_ERR_RET(blockDataMerge(pMore, pLess));
|
||||||
|
blockDataCleanup(pLess);
|
||||||
|
pCtx->midRemains = false;
|
||||||
|
} else {
|
||||||
|
int32_t copyRows = pMore->info.capacity - pMore->info.rows;
|
||||||
|
HJ_ERR_RET(blockDataMergeNRows(pMore, pLess, pLess->info.rows - copyRows, copyRows));
|
||||||
|
blockDataShrinkNRows(pLess, copyRows);
|
||||||
|
pCtx->midRemains = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (pMore != (*ppFin)) {
|
||||||
|
TSWAP(*ppMid, *ppFin);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t hJoinSetImplFp(SHJoinOperatorInfo* pJoin) {
|
||||||
|
switch (pJoin->joinType) {
|
||||||
|
case JOIN_TYPE_INNER:
|
||||||
|
pJoin->joinFp = hInnerJoinDo;
|
||||||
|
break;
|
||||||
|
case JOIN_TYPE_LEFT:
|
||||||
|
case JOIN_TYPE_RIGHT: {
|
||||||
|
switch (pJoin->subType) {
|
||||||
|
case JOIN_STYPE_OUTER:
|
||||||
|
pJoin->joinFp = hLeftJoinDo;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t hJoinLaunchPrimExpr(SSDataBlock* pBlock, SHJoinTableCtx* pTable, int32_t startIdx, int32_t endIdx) {
|
||||||
|
if (NULL == pTable->primExpr) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHJoinPrimExprCtx* pCtx = &pTable->primCtx;
|
||||||
|
SColumnInfoData* pPrimIn = taosArrayGet(pBlock->pDataBlock, pTable->primCol->srcSlot);
|
||||||
|
SColumnInfoData* pPrimOut = taosArrayGet(pBlock->pDataBlock, pTable->primCtx.targetSlotId);
|
||||||
|
if (0 != pCtx->timezoneUnit) {
|
||||||
|
for (int32_t i = startIdx; i <= endIdx; ++i) {
|
||||||
|
((int64_t*)pPrimOut->pData)[i] = ((int64_t*)pPrimIn->pData)[i] / pCtx->truncateUnit * pCtx->truncateUnit - pCtx->timezoneUnit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int32_t i = startIdx; i <= endIdx; ++i) {
|
||||||
|
((int64_t*)pPrimOut->pData)[i] = ((int64_t*)pPrimIn->pData)[i] / pCtx->truncateUnit * pCtx->truncateUnit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int64_t hJoinGetSingleKeyRowsNum(SBufRowInfo* pRow) {
|
static int64_t hJoinGetSingleKeyRowsNum(SBufRowInfo* pRow) {
|
||||||
|
@ -52,7 +152,7 @@ static int64_t hJoinGetRowsNumOfKeyHash(SSHashObj* pHash) {
|
||||||
return rowsNum;
|
return rowsNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinInitKeyColsInfo(SHJoinTableInfo* pTable, SNodeList* pList) {
|
static int32_t hJoinInitKeyColsInfo(SHJoinTableCtx* pTable, SNodeList* pList) {
|
||||||
pTable->keyNum = LIST_LENGTH(pList);
|
pTable->keyNum = LIST_LENGTH(pList);
|
||||||
|
|
||||||
pTable->keyCols = taosMemoryMalloc(pTable->keyNum * sizeof(SHJoinColInfo));
|
pTable->keyCols = taosMemoryMalloc(pTable->keyNum * sizeof(SHJoinColInfo));
|
||||||
|
@ -106,7 +206,7 @@ static bool hJoinIsValColInKeyCols(int16_t slotId, int32_t keyNum, SHJoinColInfo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinInitValColsInfo(SHJoinTableInfo* pTable, SNodeList* pList) {
|
static int32_t hJoinInitValColsInfo(SHJoinTableCtx* pTable, SNodeList* pList) {
|
||||||
hJoinGetValColsNum(pList, pTable->blkId, &pTable->valNum);
|
hJoinGetValColsNum(pList, pTable->blkId, &pTable->valNum);
|
||||||
if (pTable->valNum == 0) {
|
if (pTable->valNum == 0) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -157,18 +257,72 @@ static int32_t hJoinInitValColsInfo(SHJoinTableInfo* pTable, SNodeList* pList) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t hJoinInitPrimKeyInfo(SHJoinTableCtx* pTable, int32_t slotId) {
|
||||||
|
pTable->primCol = taosMemoryMalloc(sizeof(SHJoinColMap));
|
||||||
|
if (NULL == pTable->primCol) {
|
||||||
|
return TSDB_CODE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pTable->primCol->srcSlot = slotId;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t hJoinInitPrimExprCtx(SNode* pNode, SHJoinPrimExprCtx* pCtx, SHJoinTableCtx* pTable) {
|
||||||
|
if (NULL == pNode) {
|
||||||
|
pCtx->targetSlotId = pTable->primCol->srcSlot;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QUERY_NODE_TARGET != nodeType(pNode)) {
|
||||||
|
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
STargetNode* pTarget = (STargetNode*)pNode;
|
||||||
|
if (QUERY_NODE_FUNCTION != nodeType(pTarget->pExpr)) {
|
||||||
|
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pTarget->pExpr;
|
||||||
|
if (FUNCTION_TYPE_TIMETRUNCATE != pFunc->funcType) {
|
||||||
|
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (4 != pFunc->pParameterList->length && 5 != pFunc->pParameterList->length) {
|
||||||
|
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
SValueNode* pUnit = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
|
||||||
|
SValueNode* pCurrTz = (5 == pFunc->pParameterList->length) ? (SValueNode*)nodesListGetNode(pFunc->pParameterList, 2) : NULL;
|
||||||
|
SValueNode* pTimeZone = (5 == pFunc->pParameterList->length) ? (SValueNode*)nodesListGetNode(pFunc->pParameterList, 4) : (SValueNode*)nodesListGetNode(pFunc->pParameterList, 3);
|
||||||
|
|
||||||
|
pCtx->truncateUnit = pUnit->typeData;
|
||||||
|
if ((NULL == pCurrTz || 1 == pCurrTz->typeData) && pCtx->truncateUnit >= (86400 * TSDB_TICK_PER_SECOND(pFunc->node.resType.precision))) {
|
||||||
|
pCtx->timezoneUnit = offsetFromTz(varDataVal(pTimeZone->datum.p), TSDB_TICK_PER_SECOND(pFunc->node.resType.precision));
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx->targetSlotId = pTarget->slotId;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32_t hJoinInitTableInfo(SHJoinOperatorInfo* pJoin, SHashJoinPhysiNode* pJoinNode, SOperatorInfo** pDownstream, int32_t idx, SQueryStat* pStat) {
|
static int32_t hJoinInitTableInfo(SHJoinOperatorInfo* pJoin, SHashJoinPhysiNode* pJoinNode, SOperatorInfo** pDownstream, int32_t idx, SQueryStat* pStat) {
|
||||||
SNodeList* pKeyList = NULL;
|
SNodeList* pKeyList = NULL;
|
||||||
SHJoinTableInfo* pTable = &pJoin->tbs[idx];
|
SHJoinTableCtx* pTable = &pJoin->tbs[idx];
|
||||||
pTable->downStream = pDownstream[idx];
|
pTable->downStream = pDownstream[idx];
|
||||||
pTable->blkId = pDownstream[idx]->resultDataBlockId;
|
pTable->blkId = pDownstream[idx]->resultDataBlockId;
|
||||||
if (0 == idx) {
|
if (0 == idx) {
|
||||||
pKeyList = pJoinNode->pOnLeft;
|
pKeyList = pJoinNode->pOnLeft;
|
||||||
|
pTable->hasTimeRange = pJoinNode->timeRangeTarget & 0x1;
|
||||||
} else {
|
} else {
|
||||||
pKeyList = pJoinNode->pOnRight;
|
pKeyList = pJoinNode->pOnRight;
|
||||||
|
pTable->hasTimeRange = pJoinNode->timeRangeTarget & 0x2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HJ_ERR_RET(hJoinInitPrimKeyInfo(pTable, (0 == idx) ? pJoinNode->leftPrimSlotId : pJoinNode->rightPrimSlotId));
|
||||||
|
|
||||||
int32_t code = hJoinInitKeyColsInfo(pTable, pKeyList);
|
int32_t code = hJoinInitKeyColsInfo(pTable, pKeyList);
|
||||||
if (code) {
|
if (code) {
|
||||||
return code;
|
return code;
|
||||||
|
@ -180,6 +334,8 @@ static int32_t hJoinInitTableInfo(SHJoinOperatorInfo* pJoin, SHashJoinPhysiNode*
|
||||||
|
|
||||||
memcpy(&pTable->inputStat, pStat, sizeof(*pStat));
|
memcpy(&pTable->inputStat, pStat, sizeof(*pStat));
|
||||||
|
|
||||||
|
HJ_ERR_RET(hJoinInitPrimExprCtx(pTable->primExpr, &pTable->primCtx, pTable));
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,9 +344,11 @@ static void hJoinSetBuildAndProbeTable(SHJoinOperatorInfo* pInfo, SHashJoinPhysi
|
||||||
int32_t probeIdx = 1;
|
int32_t probeIdx = 1;
|
||||||
|
|
||||||
pInfo->joinType = pJoinNode->joinType;
|
pInfo->joinType = pJoinNode->joinType;
|
||||||
|
pInfo->subType = pJoinNode->subType;
|
||||||
|
|
||||||
switch (pInfo->joinType) {
|
switch (pInfo->joinType) {
|
||||||
case JOIN_TYPE_INNER:
|
case JOIN_TYPE_INNER:
|
||||||
|
case JOIN_TYPE_FULL:
|
||||||
if (pInfo->tbs[0].inputStat.inputRowNum <= pInfo->tbs[1].inputStat.inputRowNum) {
|
if (pInfo->tbs[0].inputStat.inputRowNum <= pInfo->tbs[1].inputStat.inputRowNum) {
|
||||||
buildIdx = 0;
|
buildIdx = 0;
|
||||||
probeIdx = 1;
|
probeIdx = 1;
|
||||||
|
@ -216,6 +374,14 @@ static void hJoinSetBuildAndProbeTable(SHJoinOperatorInfo* pInfo, SHashJoinPhysi
|
||||||
|
|
||||||
pInfo->pBuild->downStreamIdx = buildIdx;
|
pInfo->pBuild->downStreamIdx = buildIdx;
|
||||||
pInfo->pProbe->downStreamIdx = probeIdx;
|
pInfo->pProbe->downStreamIdx = probeIdx;
|
||||||
|
|
||||||
|
if (0 == buildIdx) {
|
||||||
|
pInfo->pBuild->primExpr = pJoinNode->leftPrimExpr;
|
||||||
|
pInfo->pProbe->primExpr = pJoinNode->rightPrimExpr;
|
||||||
|
} else {
|
||||||
|
pInfo->pBuild->primExpr = pJoinNode->rightPrimExpr;
|
||||||
|
pInfo->pProbe->primExpr = pJoinNode->leftPrimExpr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinBuildResColsMap(SHJoinOperatorInfo* pInfo, SHashJoinPhysiNode* pJoinNode) {
|
static int32_t hJoinBuildResColsMap(SHJoinOperatorInfo* pInfo, SHashJoinPhysiNode* pJoinNode) {
|
||||||
|
@ -263,11 +429,12 @@ static int32_t hJoinInitBufPages(SHJoinOperatorInfo* pInfo) {
|
||||||
return hJoinAddPageToBufs(pInfo->pRowBufs);
|
return hJoinAddPageToBufs(pInfo->pRowBufs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hJoinFreeTableInfo(SHJoinTableInfo* pTable) {
|
static void hJoinFreeTableInfo(SHJoinTableCtx* pTable) {
|
||||||
taosMemoryFreeClear(pTable->keyCols);
|
taosMemoryFreeClear(pTable->keyCols);
|
||||||
taosMemoryFreeClear(pTable->keyBuf);
|
taosMemoryFreeClear(pTable->keyBuf);
|
||||||
taosMemoryFreeClear(pTable->valCols);
|
taosMemoryFreeClear(pTable->valCols);
|
||||||
taosArrayDestroy(pTable->valVarCols);
|
taosArrayDestroy(pTable->valVarCols);
|
||||||
|
taosMemoryFree(pTable->primCol);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hJoinFreeBufPage(void* param) {
|
static void hJoinFreeBufPage(void* param) {
|
||||||
|
@ -305,9 +472,9 @@ static FORCE_INLINE char* hJoinRetrieveColDataFromRowBufs(SArray* pRowBufs, SBuf
|
||||||
return pPage->data + pRow->offset;
|
return pPage->data + pRow->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE int32_t hJoinCopyResRowsToBlock(SHJoinOperatorInfo* pJoin, int32_t rowNum, SBufRowInfo* pStart, SSDataBlock* pRes) {
|
static int32_t hJoinCopyResRowsToBlock(SHJoinOperatorInfo* pJoin, int32_t rowNum, SBufRowInfo* pStart, SSDataBlock* pRes) {
|
||||||
SHJoinTableInfo* pBuild = pJoin->pBuild;
|
SHJoinTableCtx* pBuild = pJoin->pBuild;
|
||||||
SHJoinTableInfo* pProbe = pJoin->pProbe;
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
int32_t buildIdx = 0, buildValIdx = 0;
|
int32_t buildIdx = 0, buildValIdx = 0;
|
||||||
int32_t probeIdx = 0;
|
int32_t probeIdx = 0;
|
||||||
SBufRowInfo* pRow = pStart;
|
SBufRowInfo* pRow = pStart;
|
||||||
|
@ -347,7 +514,7 @@ static FORCE_INLINE int32_t hJoinCopyResRowsToBlock(SHJoinOperatorInfo* pJoin, i
|
||||||
SColumnInfoData* pSrc = taosArrayGet(pJoin->ctx.pProbeData->pDataBlock, pProbe->valCols[probeIdx].srcSlot);
|
SColumnInfoData* pSrc = taosArrayGet(pJoin->ctx.pProbeData->pDataBlock, pProbe->valCols[probeIdx].srcSlot);
|
||||||
SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pProbe->valCols[probeIdx].dstSlot);
|
SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pProbe->valCols[probeIdx].dstSlot);
|
||||||
|
|
||||||
code = colDataCopyNItems(pDst, pRes->info.rows, colDataGetData(pSrc, pJoin->ctx.probeIdx), rowNum, colDataIsNull_s(pSrc, pJoin->ctx.probeIdx));
|
code = colDataCopyNItems(pDst, pRes->info.rows, colDataGetData(pSrc, pJoin->ctx.probeStartIdx), rowNum, colDataIsNull_s(pSrc, pJoin->ctx.probeStartIdx));
|
||||||
if (code) {
|
if (code) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -360,8 +527,37 @@ static FORCE_INLINE int32_t hJoinCopyResRowsToBlock(SHJoinOperatorInfo* pJoin, i
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t hJoinCopyNMatchRowsToBlock(SHJoinOperatorInfo* pJoin, SSDataBlock* pRes, int32_t startIdx, int32_t rows) {
|
||||||
|
SHJoinTableCtx* pBuild = pJoin->pBuild;
|
||||||
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
|
int32_t buildIdx = 0;
|
||||||
|
int32_t probeIdx = 0;
|
||||||
|
int32_t code = 0;
|
||||||
|
|
||||||
static FORCE_INLINE void hJoinAppendResToBlock(struct SOperatorInfo* pOperator, SSDataBlock* pRes, bool* allFetched) {
|
for (int32_t i = 0; i < pJoin->pResColNum; ++i) {
|
||||||
|
if (pJoin->pResColMap[i]) {
|
||||||
|
SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pBuild->valCols[buildIdx].dstSlot);
|
||||||
|
colDataSetNItemsNull(pDst, pRes->info.rows, rows);
|
||||||
|
|
||||||
|
buildIdx++;
|
||||||
|
} else {
|
||||||
|
SColumnInfoData* pSrc = taosArrayGet(pJoin->ctx.pProbeData->pDataBlock, pProbe->valCols[probeIdx].srcSlot);
|
||||||
|
SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pProbe->valCols[probeIdx].dstSlot);
|
||||||
|
|
||||||
|
colDataAssignNRows(pDst, pRes->info.rows, pSrc, startIdx, rows);
|
||||||
|
|
||||||
|
probeIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pRes->info.rows += rows;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void hJoinAppendResToBlock(struct SOperatorInfo* pOperator, SSDataBlock* pRes, bool* allFetched) {
|
||||||
SHJoinOperatorInfo* pJoin = pOperator->info;
|
SHJoinOperatorInfo* pJoin = pOperator->info;
|
||||||
SHJoinCtx* pCtx = &pJoin->ctx;
|
SHJoinCtx* pCtx = &pJoin->ctx;
|
||||||
SBufRowInfo* pStart = pCtx->pBuildRow;
|
SBufRowInfo* pStart = pCtx->pBuildRow;
|
||||||
|
@ -387,7 +583,7 @@ static FORCE_INLINE void hJoinAppendResToBlock(struct SOperatorInfo* pOperator,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static FORCE_INLINE bool hJoinCopyKeyColsDataToBuf(SHJoinTableInfo* pTable, int32_t rowIdx, size_t *pBufLen) {
|
bool hJoinCopyKeyColsDataToBuf(SHJoinTableCtx* pTable, int32_t rowIdx, size_t *pBufLen) {
|
||||||
char *pData = NULL;
|
char *pData = NULL;
|
||||||
size_t bufLen = 0;
|
size_t bufLen = 0;
|
||||||
|
|
||||||
|
@ -428,61 +624,7 @@ static FORCE_INLINE bool hJoinCopyKeyColsDataToBuf(SHJoinTableInfo* pTable, int3
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t hJoinSetKeyColsData(SSDataBlock* pBlock, SHJoinTableCtx* pTable) {
|
||||||
static void doHashJoinImpl(struct SOperatorInfo* pOperator) {
|
|
||||||
SHJoinOperatorInfo* pJoin = pOperator->info;
|
|
||||||
SHJoinTableInfo* pProbe = pJoin->pProbe;
|
|
||||||
SHJoinCtx* pCtx = &pJoin->ctx;
|
|
||||||
SSDataBlock* pRes = pJoin->finBlk;
|
|
||||||
size_t bufLen = 0;
|
|
||||||
bool allFetched = false;
|
|
||||||
|
|
||||||
if (pJoin->ctx.pBuildRow) {
|
|
||||||
hJoinAppendResToBlock(pOperator, pRes, &allFetched);
|
|
||||||
if (pRes->info.rows >= pRes->info.capacity) {
|
|
||||||
if (allFetched) {
|
|
||||||
++pCtx->probeIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
++pCtx->probeIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; pCtx->probeIdx < pCtx->pProbeData->info.rows; ++pCtx->probeIdx) {
|
|
||||||
if (hJoinCopyKeyColsDataToBuf(pProbe, pCtx->probeIdx, &bufLen)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGroupData* pGroup = tSimpleHashGet(pJoin->pKeyHash, pProbe->keyData, bufLen);
|
|
||||||
/*
|
|
||||||
size_t keySize = 0;
|
|
||||||
int32_t* pKey = tSimpleHashGetKey(pGroup, &keySize);
|
|
||||||
ASSERT(keySize == bufLen && 0 == memcmp(pKey, pProbe->keyData, bufLen));
|
|
||||||
int64_t rows = getSingleKeyRowsNum(pGroup->rows);
|
|
||||||
pJoin->execInfo.expectRows += rows;
|
|
||||||
qTrace("hash_key:%d, rows:%" PRId64, *pKey, rows);
|
|
||||||
*/
|
|
||||||
if (pGroup) {
|
|
||||||
pCtx->pBuildRow = pGroup->rows;
|
|
||||||
hJoinAppendResToBlock(pOperator, pRes, &allFetched);
|
|
||||||
if (pRes->info.rows >= pRes->info.capacity) {
|
|
||||||
if (allFetched) {
|
|
||||||
++pCtx->probeIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qTrace("no key matched");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pCtx->rowRemains = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t hJoinSetKeyColsData(SSDataBlock* pBlock, SHJoinTableInfo* pTable) {
|
|
||||||
for (int32_t i = 0; i < pTable->keyNum; ++i) {
|
for (int32_t i = 0; i < pTable->keyNum; ++i) {
|
||||||
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, pTable->keyCols[i].srcSlot);
|
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, pTable->keyCols[i].srcSlot);
|
||||||
if (pTable->keyCols[i].vardata != IS_VAR_DATA_TYPE(pCol->info.type)) {
|
if (pTable->keyCols[i].vardata != IS_VAR_DATA_TYPE(pCol->info.type)) {
|
||||||
|
@ -503,7 +645,7 @@ static int32_t hJoinSetKeyColsData(SSDataBlock* pBlock, SHJoinTableInfo* pTable)
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinSetValColsData(SSDataBlock* pBlock, SHJoinTableInfo* pTable) {
|
static int32_t hJoinSetValColsData(SSDataBlock* pBlock, SHJoinTableCtx* pTable) {
|
||||||
if (!pTable->valColExist) {
|
if (!pTable->valColExist) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -534,7 +676,7 @@ static int32_t hJoinSetValColsData(SSDataBlock* pBlock, SHJoinTableInfo* pTable)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static FORCE_INLINE void hJoinCopyValColsDataToBuf(SHJoinTableInfo* pTable, int32_t rowIdx) {
|
static FORCE_INLINE void hJoinCopyValColsDataToBuf(SHJoinTableCtx* pTable, int32_t rowIdx) {
|
||||||
if (!pTable->valColExist) {
|
if (!pTable->valColExist) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -596,7 +738,7 @@ static FORCE_INLINE int32_t hJoinGetValBufFromPages(SArray* pPages, int32_t bufS
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE int32_t hJoinGetValBufSize(SHJoinTableInfo* pTable, int32_t rowIdx) {
|
static FORCE_INLINE int32_t hJoinGetValBufSize(SHJoinTableCtx* pTable, int32_t rowIdx) {
|
||||||
if (NULL == pTable->valVarCols) {
|
if (NULL == pTable->valVarCols) {
|
||||||
return pTable->valBufSize;
|
return pTable->valBufSize;
|
||||||
}
|
}
|
||||||
|
@ -614,7 +756,7 @@ static FORCE_INLINE int32_t hJoinGetValBufSize(SHJoinTableInfo* pTable, int32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32_t hJoinAddRowToHashImpl(SHJoinOperatorInfo* pJoin, SGroupData* pGroup, SHJoinTableInfo* pTable, size_t keyLen, int32_t rowIdx) {
|
static int32_t hJoinAddRowToHashImpl(SHJoinOperatorInfo* pJoin, SGroupData* pGroup, SHJoinTableCtx* pTable, size_t keyLen, int32_t rowIdx) {
|
||||||
SGroupData group = {0};
|
SGroupData group = {0};
|
||||||
SBufRowInfo* pRow = NULL;
|
SBufRowInfo* pRow = NULL;
|
||||||
|
|
||||||
|
@ -652,7 +794,7 @@ static int32_t hJoinAddRowToHashImpl(SHJoinOperatorInfo* pJoin, SGroupData* pGro
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinAddRowToHash(SHJoinOperatorInfo* pJoin, SSDataBlock* pBlock, size_t keyLen, int32_t rowIdx) {
|
static int32_t hJoinAddRowToHash(SHJoinOperatorInfo* pJoin, SSDataBlock* pBlock, size_t keyLen, int32_t rowIdx) {
|
||||||
SHJoinTableInfo* pBuild = pJoin->pBuild;
|
SHJoinTableCtx* pBuild = pJoin->pBuild;
|
||||||
int32_t code = hJoinSetValColsData(pBlock, pBuild);
|
int32_t code = hJoinSetValColsData(pBlock, pBuild);
|
||||||
if (code) {
|
if (code) {
|
||||||
return code;
|
return code;
|
||||||
|
@ -669,15 +811,64 @@ static int32_t hJoinAddRowToHash(SHJoinOperatorInfo* pJoin, SSDataBlock* pBlock,
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hJoinFilterTimeRange(SSDataBlock* pBlock, STimeWindow* pRange, int32_t primSlot, int32_t* startIdx, int32_t* endIdx) {
|
||||||
|
SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, primSlot);
|
||||||
|
if (NULL == pCol) {
|
||||||
|
qError("hash join can't get prim col, slot:%d, slotNum:%d", primSlot, (int32_t)taosArrayGetSize(pBlock->pDataBlock));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSKEY skey = *(TSKEY*)colDataGetData(pCol, 0);
|
||||||
|
TSKEY ekey = *(TSKEY*)colDataGetData(pCol, (pBlock->info.rows - 1));
|
||||||
|
|
||||||
|
if (ekey < pRange->skey || skey > pRange->ekey) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skey >= pRange->skey && ekey <= pRange->ekey) {
|
||||||
|
*startIdx = 0;
|
||||||
|
*endIdx = pBlock->info.rows - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skey < pRange->skey && ekey > pRange->ekey) {
|
||||||
|
TSKEY *pStart = (TSKEY*)taosbsearch(&pRange->skey, pCol->pData, pBlock->info.rows, sizeof(TSKEY), compareInt64Val, TD_GE);
|
||||||
|
TSKEY *pEnd = (TSKEY*)taosbsearch(&pRange->ekey, pCol->pData, pBlock->info.rows, sizeof(TSKEY), compareInt64Val, TD_LE);
|
||||||
|
*startIdx = ((uint64_t)pStart - (uint64_t)pCol->pData) / sizeof(int64_t);
|
||||||
|
*endIdx = ((uint64_t)pEnd - (uint64_t)pCol->pData) / sizeof(int64_t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skey >= pRange->skey) {
|
||||||
|
TSKEY *pEnd = (TSKEY*)taosbsearch(&pRange->ekey, pCol->pData, pBlock->info.rows, sizeof(TSKEY), compareInt64Val, TD_LE);
|
||||||
|
*startIdx = 0;
|
||||||
|
*endIdx = ((uint64_t)pEnd - (uint64_t)pCol->pData) / sizeof(int64_t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSKEY *pStart = (TSKEY*)taosbsearch(&pRange->skey, pCol->pData, pBlock->info.rows, sizeof(TSKEY), compareInt64Val, TD_GE);
|
||||||
|
*startIdx = ((uint64_t)pStart - (uint64_t)pCol->pData) / sizeof(int64_t);
|
||||||
|
*endIdx = pBlock->info.rows - 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t hJoinAddBlockRowsToHash(SSDataBlock* pBlock, SHJoinOperatorInfo* pJoin) {
|
static int32_t hJoinAddBlockRowsToHash(SSDataBlock* pBlock, SHJoinOperatorInfo* pJoin) {
|
||||||
SHJoinTableInfo* pBuild = pJoin->pBuild;
|
SHJoinTableCtx* pBuild = pJoin->pBuild;
|
||||||
|
int32_t startIdx = 0, endIdx = pBlock->info.rows - 1;
|
||||||
|
if (pBuild->hasTimeRange && !hJoinFilterTimeRange(pBlock, &pJoin->tblTimeRange, pBuild->primCol->srcSlot, &startIdx, &endIdx)) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
HJ_ERR_RET(hJoinLaunchPrimExpr(pBlock, pBuild, startIdx, endIdx));
|
||||||
|
|
||||||
int32_t code = hJoinSetKeyColsData(pBlock, pBuild);
|
int32_t code = hJoinSetKeyColsData(pBlock, pBuild);
|
||||||
if (code) {
|
if (code) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bufLen = 0;
|
size_t bufLen = 0;
|
||||||
for (int32_t i = 0; i < pBlock->info.rows; ++i) {
|
for (int32_t i = startIdx; i <= endIdx; ++i) {
|
||||||
if (hJoinCopyKeyColsDataToBuf(pBuild, i, &bufLen)) {
|
if (hJoinCopyKeyColsDataToBuf(pBuild, i, &bufLen)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -690,7 +881,7 @@ static int32_t hJoinAddBlockRowsToHash(SSDataBlock* pBlock, SHJoinOperatorInfo*
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinBuildHash(struct SOperatorInfo* pOperator) {
|
static int32_t hJoinBuildHash(struct SOperatorInfo* pOperator, bool* queryDone) {
|
||||||
SHJoinOperatorInfo* pJoin = pOperator->info;
|
SHJoinOperatorInfo* pJoin = pOperator->info;
|
||||||
SSDataBlock* pBlock = NULL;
|
SSDataBlock* pBlock = NULL;
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
@ -710,12 +901,36 @@ static int32_t hJoinBuildHash(struct SOperatorInfo* pOperator) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_INNER_NONE_JOIN(pJoin->joinType, pJoin->subType) && tSimpleHashGetSize(pJoin->pKeyHash) <= 0) {
|
||||||
|
hJoinSetDone(pOperator);
|
||||||
|
*queryDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qTrace("build table rows:%" PRId64, hJoinGetRowsNumOfKeyHash(pJoin->pKeyHash));
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t hJoinPrepareStart(struct SOperatorInfo* pOperator, SSDataBlock* pBlock) {
|
static int32_t hJoinPrepareStart(struct SOperatorInfo* pOperator, SSDataBlock* pBlock) {
|
||||||
SHJoinOperatorInfo* pJoin = pOperator->info;
|
SHJoinOperatorInfo* pJoin = pOperator->info;
|
||||||
SHJoinTableInfo* pProbe = pJoin->pProbe;
|
SHJoinTableCtx* pProbe = pJoin->pProbe;
|
||||||
|
int32_t startIdx = 0, endIdx = pBlock->info.rows - 1;
|
||||||
|
if (pProbe->hasTimeRange && !hJoinFilterTimeRange(pBlock, &pJoin->tblTimeRange, pProbe->primCol->srcSlot, &startIdx, &endIdx)) {
|
||||||
|
if (!IS_INNER_NONE_JOIN(pJoin->joinType, pJoin->subType)) {
|
||||||
|
pJoin->ctx.probeEndIdx = -1;
|
||||||
|
pJoin->ctx.probePostIdx = 0;
|
||||||
|
pJoin->ctx.pProbeData = pBlock;
|
||||||
|
pJoin->ctx.rowRemains = true;
|
||||||
|
pJoin->ctx.probePhase = E_JOIN_PHASE_POST;
|
||||||
|
|
||||||
|
HJ_ERR_RET((*pJoin->joinFp)(pOperator));
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
HJ_ERR_RET(hJoinLaunchPrimExpr(pBlock, pProbe, startIdx, endIdx));
|
||||||
|
|
||||||
int32_t code = hJoinSetKeyColsData(pBlock, pProbe);
|
int32_t code = hJoinSetKeyColsData(pBlock, pProbe);
|
||||||
if (code) {
|
if (code) {
|
||||||
return code;
|
return code;
|
||||||
|
@ -725,17 +940,26 @@ static int32_t hJoinPrepareStart(struct SOperatorInfo* pOperator, SSDataBlock* p
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
pJoin->ctx.probeIdx = 0;
|
pJoin->ctx.probeStartIdx = startIdx;
|
||||||
|
pJoin->ctx.probeEndIdx = endIdx;
|
||||||
pJoin->ctx.pBuildRow = NULL;
|
pJoin->ctx.pBuildRow = NULL;
|
||||||
pJoin->ctx.pProbeData = pBlock;
|
pJoin->ctx.pProbeData = pBlock;
|
||||||
pJoin->ctx.rowRemains = true;
|
pJoin->ctx.rowRemains = true;
|
||||||
|
pJoin->ctx.probePreIdx = 0;
|
||||||
|
pJoin->ctx.probePostIdx = endIdx + 1;
|
||||||
|
|
||||||
doHashJoinImpl(pOperator);
|
if (!IS_INNER_NONE_JOIN(pJoin->joinType, pJoin->subType) && startIdx > 0) {
|
||||||
|
pJoin->ctx.probePhase = E_JOIN_PHASE_PRE;
|
||||||
|
} else {
|
||||||
|
pJoin->ctx.probePhase = E_JOIN_PHASE_CUR;
|
||||||
|
}
|
||||||
|
|
||||||
|
HJ_ERR_RET((*pJoin->joinFp)(pOperator));
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hJoinSetDone(struct SOperatorInfo* pOperator) {
|
void hJoinSetDone(struct SOperatorInfo* pOperator) {
|
||||||
setOperatorCompleted(pOperator);
|
setOperatorCompleted(pOperator);
|
||||||
|
|
||||||
SHJoinOperatorInfo* pInfo = pOperator->info;
|
SHJoinOperatorInfo* pInfo = pOperator->info;
|
||||||
|
@ -749,7 +973,6 @@ static SSDataBlock* hJoinMainProcess(struct SOperatorInfo* pOperator) {
|
||||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
SSDataBlock* pRes = pJoin->finBlk;
|
SSDataBlock* pRes = pJoin->finBlk;
|
||||||
pRes->info.rows = 0;
|
|
||||||
int64_t st = 0;
|
int64_t st = 0;
|
||||||
|
|
||||||
if (pOperator->cost.openCost == 0) {
|
if (pOperator->cost.openCost == 0) {
|
||||||
|
@ -757,30 +980,35 @@ static SSDataBlock* hJoinMainProcess(struct SOperatorInfo* pOperator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pOperator->status == OP_EXEC_DONE) {
|
if (pOperator->status == OP_EXEC_DONE) {
|
||||||
|
pRes->info.rows = 0;
|
||||||
goto _return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pJoin->keyHashBuilt) {
|
if (!pJoin->keyHashBuilt) {
|
||||||
pJoin->keyHashBuilt = true;
|
pJoin->keyHashBuilt = true;
|
||||||
|
|
||||||
code = hJoinBuildHash(pOperator);
|
bool queryDone = false;
|
||||||
|
code = hJoinBuildHash(pOperator, &queryDone);
|
||||||
if (code) {
|
if (code) {
|
||||||
pTaskInfo->code = code;
|
pTaskInfo->code = code;
|
||||||
T_LONG_JMP(pTaskInfo->env, code);
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tSimpleHashGetSize(pJoin->pKeyHash) <= 0) {
|
if (queryDone) {
|
||||||
hJoinSetDone(pOperator);
|
|
||||||
goto _return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//qTrace("build table rows:%" PRId64, getRowsNumOfKeyHash(pJoin->pKeyHash));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pJoin->ctx.rowRemains) {
|
blockDataCleanup(pRes);
|
||||||
doHashJoinImpl(pOperator);
|
|
||||||
|
|
||||||
if (pRes->info.rows >= pRes->info.capacity && pJoin->pFinFilter != NULL) {
|
if (pJoin->ctx.rowRemains) {
|
||||||
|
code = (*pJoin->joinFp)(pOperator);
|
||||||
|
if (code) {
|
||||||
|
pTaskInfo->code = code;
|
||||||
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pRes->info.rows > 0 && pJoin->pFinFilter != NULL) {
|
||||||
doFilter(pRes, pJoin->pFinFilter, NULL);
|
doFilter(pRes, pJoin->pFinFilter, NULL);
|
||||||
}
|
}
|
||||||
if (pRes->info.rows > 0) {
|
if (pRes->info.rows > 0) {
|
||||||
|
@ -804,13 +1032,14 @@ static SSDataBlock* hJoinMainProcess(struct SOperatorInfo* pOperator) {
|
||||||
T_LONG_JMP(pTaskInfo->env, code);
|
T_LONG_JMP(pTaskInfo->env, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pRes->info.rows < pJoin->blkThreshold) {
|
if (!hJoinBlkReachThreshold(pJoin, pRes->info.rows)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pJoin->pFinFilter != NULL) {
|
if (pRes->info.rows > 0 && pJoin->pFinFilter != NULL) {
|
||||||
doFilter(pRes, pJoin->pFinFilter, NULL);
|
doFilter(pRes, pJoin->pFinFilter, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pRes->info.rows > 0) {
|
if (pRes->info.rows > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -912,12 +1141,13 @@ SOperatorInfo* createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t n
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
if (pOperator == NULL || pInfo == NULL) {
|
if (pOperator == NULL || pInfo == NULL) {
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
goto _error;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pInfo->ctx.limit = pJoinNode->node.pLimit ? ((SLimitNode*)pJoinNode->node.pLimit)->limit : INT64_MAX;
|
pInfo->tblTimeRange.skey = pJoinNode->timeRange.skey;
|
||||||
|
pInfo->tblTimeRange.ekey = pJoinNode->timeRange.ekey;
|
||||||
|
|
||||||
hJoinInitResBlocks(pInfo, pJoinNode);
|
pInfo->ctx.limit = pJoinNode->node.pLimit ? ((SLimitNode*)pJoinNode->node.pLimit)->limit : INT64_MAX;
|
||||||
|
|
||||||
setOperatorInfo(pOperator, "HashJoinOperator", QUERY_NODE_PHYSICAL_PLAN_HASH_JOIN, false, OP_NOT_OPENED, pInfo, pTaskInfo);
|
setOperatorInfo(pOperator, "HashJoinOperator", QUERY_NODE_PHYSICAL_PLAN_HASH_JOIN, false, OP_NOT_OPENED, pInfo, pTaskInfo);
|
||||||
|
|
||||||
|
@ -925,29 +1155,25 @@ SOperatorInfo* createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t n
|
||||||
hJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 1, &pJoinNode->inputStat[1]);
|
hJoinInitTableInfo(pInfo, pJoinNode, pDownstream, 1, &pJoinNode->inputStat[1]);
|
||||||
|
|
||||||
hJoinSetBuildAndProbeTable(pInfo, pJoinNode);
|
hJoinSetBuildAndProbeTable(pInfo, pJoinNode);
|
||||||
code = hJoinBuildResColsMap(pInfo, pJoinNode);
|
|
||||||
if (code) {
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
code = hJoinInitBufPages(pInfo);
|
HJ_ERR_JRET(hJoinBuildResColsMap(pInfo, pJoinNode));
|
||||||
if (code) {
|
|
||||||
goto _error;
|
HJ_ERR_JRET(hJoinInitBufPages(pInfo));
|
||||||
}
|
|
||||||
|
|
||||||
size_t hashCap = pInfo->pBuild->inputStat.inputRowNum > 0 ? (pInfo->pBuild->inputStat.inputRowNum * 1.5) : 1024;
|
size_t hashCap = pInfo->pBuild->inputStat.inputRowNum > 0 ? (pInfo->pBuild->inputStat.inputRowNum * 1.5) : 1024;
|
||||||
pInfo->pKeyHash = tSimpleHashInit(hashCap, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY));
|
pInfo->pKeyHash = tSimpleHashInit(hashCap, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY));
|
||||||
if (pInfo->pKeyHash == NULL) {
|
if (pInfo->pKeyHash == NULL) {
|
||||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||||
goto _error;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HJ_ERR_JRET(hJoinHandleConds(pInfo, pJoinNode));
|
HJ_ERR_JRET(hJoinHandleConds(pInfo, pJoinNode));
|
||||||
|
|
||||||
code = appendDownstream(pOperator, pDownstream, numOfDownstream);
|
HJ_ERR_JRET(hJoinInitResBlocks(pInfo, pJoinNode));
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
|
||||||
goto _error;
|
HJ_ERR_JRET(hJoinSetImplFp(pInfo));
|
||||||
}
|
|
||||||
|
HJ_ERR_JRET(appendDownstream(pOperator, pDownstream, numOfDownstream));
|
||||||
|
|
||||||
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, hJoinMainProcess, NULL, destroyHashJoinOperator, optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
|
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, hJoinMainProcess, NULL, destroyHashJoinOperator, optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
|
||||||
|
|
||||||
|
@ -955,7 +1181,7 @@ SOperatorInfo* createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t n
|
||||||
|
|
||||||
return pOperator;
|
return pOperator;
|
||||||
|
|
||||||
_error:
|
_return:
|
||||||
if (pInfo != NULL) {
|
if (pInfo != NULL) {
|
||||||
destroyHashJoinOperator(pInfo);
|
destroyHashJoinOperator(pInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,11 @@ static uint32_t mJoinGetFinBlkCapacity(SMJoinOperatorInfo* pJoin, SSortMergeJoin
|
||||||
uint32_t maxRows = TMAX(MJOIN_DEFAULT_BLK_ROWS_NUM, MJOIN_BLK_SIZE_LIMIT/pJoinNode->node.pOutputDataBlockDesc->totalRowSize);
|
uint32_t maxRows = TMAX(MJOIN_DEFAULT_BLK_ROWS_NUM, MJOIN_BLK_SIZE_LIMIT/pJoinNode->node.pOutputDataBlockDesc->totalRowSize);
|
||||||
if (INT64_MAX != pJoin->ctx.mergeCtx.limit && NULL == pJoin->pFinFilter) {
|
if (INT64_MAX != pJoin->ctx.mergeCtx.limit && NULL == pJoin->pFinFilter) {
|
||||||
uint32_t limitMaxRows = pJoin->ctx.mergeCtx.limit / MJOIN_BLK_THRESHOLD_RATIO + 1;
|
uint32_t limitMaxRows = pJoin->ctx.mergeCtx.limit / MJOIN_BLK_THRESHOLD_RATIO + 1;
|
||||||
return (maxRows > limitMaxRows) ? limitMaxRows : maxRows;
|
maxRows = TMIN(maxRows, limitMaxRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JOIN_STYPE_SEMI == pJoinNode->subType || JOIN_STYPE_ANTI == pJoinNode->subType) {
|
||||||
|
maxRows = TMIN(MJOIN_SEMI_ANTI_BLK_ROWS_NUM, maxRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxRows;
|
return maxRows;
|
||||||
|
@ -257,7 +261,7 @@ static int32_t mOuterJoinMergeSeqCart(SMJoinMergeCtx* pCtx) {
|
||||||
int32_t startGrpIdx = 0;
|
int32_t startGrpIdx = 0;
|
||||||
int32_t startRowIdx = -1;
|
int32_t startRowIdx = -1;
|
||||||
|
|
||||||
blockDataCleanup(pCtx->midBlk);
|
//blockDataCleanup(pCtx->midBlk);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (; !GRP_DONE(probeGrp) && !BLK_IS_FULL(pCtx->finBlk);
|
for (; !GRP_DONE(probeGrp) && !BLK_IS_FULL(pCtx->finBlk);
|
||||||
|
@ -350,7 +354,7 @@ static int32_t mOuterJoinHashGrpCartFilter(SMJoinMergeCtx* pCtx, bool* contLoop)
|
||||||
SMJoinGrpRows* probeGrp = taosArrayGet(probe->eqGrps, probe->grpIdx);
|
SMJoinGrpRows* probeGrp = taosArrayGet(probe->eqGrps, probe->grpIdx);
|
||||||
int32_t startRowIdx = 0;
|
int32_t startRowIdx = 0;
|
||||||
|
|
||||||
blockDataCleanup(pCtx->midBlk);
|
//blockDataCleanup(pCtx->midBlk);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
startRowIdx = build->grpRowIdx;
|
startRowIdx = build->grpRowIdx;
|
||||||
|
|
|
@ -496,6 +496,7 @@ static int32_t logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) {
|
||||||
COPY_SCALAR_FIELD(hashJoinHint);
|
COPY_SCALAR_FIELD(hashJoinHint);
|
||||||
CLONE_NODE_FIELD(pLeftOnCond);
|
CLONE_NODE_FIELD(pLeftOnCond);
|
||||||
CLONE_NODE_FIELD(pRightOnCond);
|
CLONE_NODE_FIELD(pRightOnCond);
|
||||||
|
COPY_SCALAR_FIELD(timeRangeTarget);
|
||||||
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
|
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2189,6 +2189,7 @@ static const char* jkJoinPhysiPlanLeftOnCond = "LeftOnCond";
|
||||||
static const char* jkJoinPhysiPlanRightOnCond = "RightOnCond";
|
static const char* jkJoinPhysiPlanRightOnCond = "RightOnCond";
|
||||||
static const char* jkJoinPhysiPlanTimeRangeSKey = "TimeRangeSKey";
|
static const char* jkJoinPhysiPlanTimeRangeSKey = "TimeRangeSKey";
|
||||||
static const char* jkJoinPhysiPlanTimeRangeEKey = "TimeRangeEKey";
|
static const char* jkJoinPhysiPlanTimeRangeEKey = "TimeRangeEKey";
|
||||||
|
static const char* jkJoinPhysiPlanTimeRangeTarget = "TimeRangeTarget";
|
||||||
|
|
||||||
static int32_t physiMergeJoinNodeToJson(const void* pObj, SJson* pJson) {
|
static int32_t physiMergeJoinNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SSortMergeJoinPhysiNode* pNode = (const SSortMergeJoinPhysiNode*)pObj;
|
const SSortMergeJoinPhysiNode* pNode = (const SSortMergeJoinPhysiNode*)pObj;
|
||||||
|
@ -2333,12 +2334,27 @@ static int32_t physiHashJoinNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanJoinType, pNode->joinType);
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanJoinType, pNode->joinType);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanSubType, pNode->subType);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = nodeListToJson(pJson, jkJoinPhysiPlanOnLeftCols, pNode->pOnLeft);
|
code = nodeListToJson(pJson, jkJoinPhysiPlanOnLeftCols, pNode->pOnLeft);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = nodeListToJson(pJson, jkJoinPhysiPlanOnRightCols, pNode->pOnRight);
|
code = nodeListToJson(pJson, jkJoinPhysiPlanOnRightCols, pNode->pOnRight);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkJoinPhysiPlanLeftPrimExpr, nodeToJson, pNode->leftPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddObject(pJson, jkJoinPhysiPlanRightPrimExpr, nodeToJson, pNode->rightPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanLeftPrimSlotId, pNode->leftPrimSlotId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanRightPrimSlotId, pNode->rightPrimSlotId);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonAddObject(pJson, jkJoinPhysiPlanOnConditions, nodeToJson, pNode->pFullOnCond);
|
code = tjsonAddObject(pJson, jkJoinPhysiPlanOnConditions, nodeToJson, pNode->pFullOnCond);
|
||||||
}
|
}
|
||||||
|
@ -2363,6 +2379,9 @@ static int32_t physiHashJoinNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonAddObject(pJson, jkJoinPhysiPlanRightOnCond, nodeToJson, pNode->pRightOnCond);
|
code = tjsonAddObject(pJson, jkJoinPhysiPlanRightOnCond, nodeToJson, pNode->pRightOnCond);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanTimeRangeTarget, pNode->timeRangeTarget);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanTimeRangeSKey, pNode->timeRange.skey);
|
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanTimeRangeSKey, pNode->timeRange.skey);
|
||||||
}
|
}
|
||||||
|
@ -2381,12 +2400,27 @@ static int32_t jsonToPhysiHashJoinNode(const SJson* pJson, void* pObj) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
tjsonGetNumberValue(pJson, jkJoinPhysiPlanJoinType, pNode->joinType, code);
|
tjsonGetNumberValue(pJson, jkJoinPhysiPlanJoinType, pNode->joinType, code);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
tjsonGetNumberValue(pJson, jkJoinPhysiPlanSubType, pNode->subType, code);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = jsonToNodeList(pJson, jkJoinPhysiPlanOnLeftCols, &pNode->pOnLeft);
|
code = jsonToNodeList(pJson, jkJoinPhysiPlanOnLeftCols, &pNode->pOnLeft);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = jsonToNodeList(pJson, jkJoinPhysiPlanOnRightCols, &pNode->pOnRight);
|
code = jsonToNodeList(pJson, jkJoinPhysiPlanOnRightCols, &pNode->pOnRight);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = jsonToNodeObject(pJson, jkJoinPhysiPlanLeftPrimExpr, &pNode->leftPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = jsonToNodeObject(pJson, jkJoinPhysiPlanRightPrimExpr, &pNode->rightPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
tjsonGetNumberValue(pJson, jkJoinPhysiPlanLeftPrimSlotId, pNode->leftPrimSlotId, code);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
tjsonGetNumberValue(pJson, jkJoinPhysiPlanRightPrimSlotId, pNode->rightPrimSlotId, code);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = jsonToNodeObject(pJson, jkJoinPhysiPlanOnConditions, &pNode->pFullOnCond);
|
code = jsonToNodeObject(pJson, jkJoinPhysiPlanOnConditions, &pNode->pFullOnCond);
|
||||||
}
|
}
|
||||||
|
@ -2411,6 +2445,9 @@ static int32_t jsonToPhysiHashJoinNode(const SJson* pJson, void* pObj) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = jsonToNodeObject(pJson, jkJoinPhysiPlanRightOnCond, &pNode->pRightOnCond);
|
code = jsonToNodeObject(pJson, jkJoinPhysiPlanRightOnCond, &pNode->pRightOnCond);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
tjsonGetNumberValue(pJson, jkJoinPhysiPlanTimeRangeTarget, pNode->timeRangeTarget, code);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonGetBigIntValue(pJson, jkJoinPhysiPlanTimeRangeSKey, &pNode->timeRange.skey);
|
code = tjsonGetBigIntValue(pJson, jkJoinPhysiPlanTimeRangeSKey, &pNode->timeRange.skey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2641,8 +2641,14 @@ static int32_t msgToPhysiMergeJoinNode(STlvDecoder* pDecoder, void* pObj) {
|
||||||
enum {
|
enum {
|
||||||
PHY_HASH_JOIN_CODE_BASE_NODE = 1,
|
PHY_HASH_JOIN_CODE_BASE_NODE = 1,
|
||||||
PHY_HASH_JOIN_CODE_JOIN_TYPE,
|
PHY_HASH_JOIN_CODE_JOIN_TYPE,
|
||||||
|
PHY_HASH_JOIN_CODE_JOIN_STYPE,
|
||||||
PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN,
|
PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN,
|
||||||
PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN,
|
PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN,
|
||||||
|
PHY_HASH_JOIN_CODE_LEFT_PRIM_EXPR,
|
||||||
|
PHY_HASH_JOIN_CODE_RIGHT_PRIM_EXPR,
|
||||||
|
PHY_HASH_JOIN_CODE_LEFT_PRIM_SLOTID,
|
||||||
|
PHY_HASH_JOIN_CODE_RIGHT_PRIM_SLOTID,
|
||||||
|
PHY_HASH_JOIN_CODE_TIME_RANGE_TARGET,
|
||||||
PHY_HASH_JOIN_CODE_ON_CONDITIONS,
|
PHY_HASH_JOIN_CODE_ON_CONDITIONS,
|
||||||
PHY_HASH_JOIN_CODE_TARGETS,
|
PHY_HASH_JOIN_CODE_TARGETS,
|
||||||
PHY_HASH_JOIN_CODE_INPUT_ROW_NUM0,
|
PHY_HASH_JOIN_CODE_INPUT_ROW_NUM0,
|
||||||
|
@ -2663,12 +2669,30 @@ static int32_t physiHashJoinNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tlvEncodeEnum(pEncoder, PHY_HASH_JOIN_CODE_JOIN_TYPE, pNode->joinType);
|
code = tlvEncodeEnum(pEncoder, PHY_HASH_JOIN_CODE_JOIN_TYPE, pNode->joinType);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeEnum(pEncoder, PHY_HASH_JOIN_CODE_JOIN_STYPE, pNode->subType);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN, nodeListToMsg, pNode->pOnLeft);
|
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN, nodeListToMsg, pNode->pOnLeft);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN, nodeListToMsg, pNode->pOnRight);
|
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN, nodeListToMsg, pNode->pOnRight);
|
||||||
}
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_LEFT_PRIM_EXPR, nodeToMsg, pNode->leftPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_RIGHT_PRIM_EXPR, nodeToMsg, pNode->rightPrimExpr);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeI32(pEncoder, PHY_HASH_JOIN_CODE_LEFT_PRIM_SLOTID, pNode->leftPrimSlotId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeI32(pEncoder, PHY_HASH_JOIN_CODE_RIGHT_PRIM_SLOTID, pNode->rightPrimSlotId);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = tlvEncodeI32(pEncoder, PHY_HASH_JOIN_CODE_TIME_RANGE_TARGET, pNode->timeRangeTarget);
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_CONDITIONS, nodeToMsg, pNode->pFullOnCond);
|
code = tlvEncodeObj(pEncoder, PHY_HASH_JOIN_CODE_ON_CONDITIONS, nodeToMsg, pNode->pFullOnCond);
|
||||||
}
|
}
|
||||||
|
@ -2717,12 +2741,30 @@ static int32_t msgToPhysiHashJoinNode(STlvDecoder* pDecoder, void* pObj) {
|
||||||
case PHY_HASH_JOIN_CODE_JOIN_TYPE:
|
case PHY_HASH_JOIN_CODE_JOIN_TYPE:
|
||||||
code = tlvDecodeEnum(pTlv, &pNode->joinType, sizeof(pNode->joinType));
|
code = tlvDecodeEnum(pTlv, &pNode->joinType, sizeof(pNode->joinType));
|
||||||
break;
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_JOIN_STYPE:
|
||||||
|
code = tlvDecodeEnum(pTlv, &pNode->subType, sizeof(pNode->subType));
|
||||||
|
break;
|
||||||
case PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN:
|
case PHY_HASH_JOIN_CODE_ON_LEFT_COLUMN:
|
||||||
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pOnLeft);
|
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pOnLeft);
|
||||||
break;
|
break;
|
||||||
case PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN:
|
case PHY_HASH_JOIN_CODE_ON_RIGHT_COLUMN:
|
||||||
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pOnRight);
|
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pOnRight);
|
||||||
break;
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_LEFT_PRIM_EXPR:
|
||||||
|
code = msgToNodeFromTlv(pTlv, (void**)&pNode->leftPrimExpr);
|
||||||
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_RIGHT_PRIM_EXPR:
|
||||||
|
code = msgToNodeFromTlv(pTlv, (void**)&pNode->rightPrimExpr);
|
||||||
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_LEFT_PRIM_SLOTID:
|
||||||
|
code = tlvDecodeI32(pTlv, &pNode->leftPrimSlotId);
|
||||||
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_RIGHT_PRIM_SLOTID:
|
||||||
|
code = tlvDecodeI32(pTlv, &pNode->rightPrimSlotId);
|
||||||
|
break;
|
||||||
|
case PHY_HASH_JOIN_CODE_TIME_RANGE_TARGET:
|
||||||
|
code = tlvDecodeI32(pTlv, &pNode->timeRangeTarget);
|
||||||
|
break;
|
||||||
case PHY_HASH_JOIN_CODE_ON_CONDITIONS:
|
case PHY_HASH_JOIN_CODE_ON_CONDITIONS:
|
||||||
code = msgToNodeFromTlv(pTlv, (void**)&pNode->pFullOnCond);
|
code = msgToNodeFromTlv(pTlv, (void**)&pNode->pFullOnCond);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1459,6 +1459,8 @@ void nodesDestroyNode(SNode* pNode) {
|
||||||
destroyPhysiNode((SPhysiNode*)pPhyNode);
|
destroyPhysiNode((SPhysiNode*)pPhyNode);
|
||||||
nodesDestroyList(pPhyNode->pOnLeft);
|
nodesDestroyList(pPhyNode->pOnLeft);
|
||||||
nodesDestroyList(pPhyNode->pOnRight);
|
nodesDestroyList(pPhyNode->pOnRight);
|
||||||
|
nodesDestroyNode(pPhyNode->leftPrimExpr);
|
||||||
|
nodesDestroyNode(pPhyNode->rightPrimExpr);
|
||||||
nodesDestroyNode(pPhyNode->pFullOnCond);
|
nodesDestroyNode(pPhyNode->pFullOnCond);
|
||||||
nodesDestroyList(pPhyNode->pTargets);
|
nodesDestroyList(pPhyNode->pTargets);
|
||||||
|
|
||||||
|
|
|
@ -54,18 +54,18 @@ static void setColumnInfo(SFunctionNode* pFunc, SColumnNode* pCol, bool isPartit
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FUNCTION_TYPE_WSTART:
|
case FUNCTION_TYPE_WSTART:
|
||||||
if (!isPartitionBy) {
|
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
||||||
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
|
||||||
}
|
|
||||||
pCol->colType = COLUMN_TYPE_WINDOW_START;
|
pCol->colType = COLUMN_TYPE_WINDOW_START;
|
||||||
pCol->isPrimTs = true;
|
if (!isPartitionBy) {
|
||||||
|
pCol->isPrimTs = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case FUNCTION_TYPE_WEND:
|
case FUNCTION_TYPE_WEND:
|
||||||
if (!isPartitionBy) {
|
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
||||||
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
|
||||||
}
|
|
||||||
pCol->colType = COLUMN_TYPE_WINDOW_END;
|
pCol->colType = COLUMN_TYPE_WINDOW_END;
|
||||||
pCol->isPrimTs = true;
|
if (!isPartitionBy) {
|
||||||
|
pCol->isPrimTs = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case FUNCTION_TYPE_WDURATION:
|
case FUNCTION_TYPE_WDURATION:
|
||||||
pCol->colType = COLUMN_TYPE_WINDOW_DURATION;
|
pCol->colType = COLUMN_TYPE_WINDOW_DURATION;
|
||||||
|
|
|
@ -2160,6 +2160,11 @@ int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, S
|
||||||
}
|
}
|
||||||
return nodesListMakeAppend(pSequencingNodes, (SNode*)pNode);
|
return nodesListMakeAppend(pSequencingNodes, (SNode*)pNode);
|
||||||
}
|
}
|
||||||
|
case QUERY_NODE_LOGIC_PLAN_SORT: {
|
||||||
|
*keepSort = true;
|
||||||
|
NODES_CLEAR_LIST(*pSequencingNodes);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
case QUERY_NODE_LOGIC_PLAN_JOIN: {
|
case QUERY_NODE_LOGIC_PLAN_JOIN: {
|
||||||
return sortPriKeyOptHandleJoinSort(pNode, groupSort, pSort, pNotOptimize, pSequencingNodes, keepSort);
|
return sortPriKeyOptHandleJoinSort(pNode, groupSort, pSort, pNotOptimize, pSequencingNodes, keepSort);
|
||||||
}
|
}
|
||||||
|
@ -2423,7 +2428,7 @@ static bool joinCondMayBeOptimized(SLogicNode* pNode) {
|
||||||
SScanLogicNode* pLScan = (SScanLogicNode*)pLeft;
|
SScanLogicNode* pLScan = (SScanLogicNode*)pLeft;
|
||||||
SScanLogicNode* pRScan = (SScanLogicNode*)pRight;
|
SScanLogicNode* pRScan = (SScanLogicNode*)pRight;
|
||||||
|
|
||||||
if (!IS_TSWINDOW_SPECIFIED(pLScan->scanRange) && !IS_TSWINDOW_SPECIFIED(pLScan->scanRange)) {
|
if (!IS_TSWINDOW_SPECIFIED(pLScan->scanRange) && !IS_TSWINDOW_SPECIFIED(pRScan->scanRange)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4744,7 +4749,7 @@ static bool hashJoinOptShouldBeOptimized(SLogicNode* pNode) {
|
||||||
goto _return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((JOIN_STYPE_NONE != pJoin->subType && JOIN_STYPE_OUTER != pJoin->subType) || NULL != pJoin->pTagOnCond || NULL != pJoin->pColOnCond || pNode->pChildren->length != 2 ) {
|
if ((JOIN_STYPE_NONE != pJoin->subType && JOIN_STYPE_OUTER != pJoin->subType) || JOIN_TYPE_FULL == pJoin->joinType || pNode->pChildren->length != 2 ) {
|
||||||
goto _return;
|
goto _return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4766,8 +4771,9 @@ static int32_t hashJoinOptSplitPrimFromLogicCond(SNode **pCondition, SNode **pPr
|
||||||
SNodeList *pPrimaryKeyConds = NULL;
|
SNodeList *pPrimaryKeyConds = NULL;
|
||||||
SNode *pCond = NULL;
|
SNode *pCond = NULL;
|
||||||
WHERE_EACH(pCond, pLogicCond->pParameterList) {
|
WHERE_EACH(pCond, pLogicCond->pParameterList) {
|
||||||
if (isCondColumnsFromMultiTable(pCond) || COND_TYPE_PRIMARY_KEY != classifyCondition(pCond)) {
|
if (filterIsMultiTableColsCond(pCond) || COND_TYPE_PRIMARY_KEY != filterClassifyCondition(pCond)) {
|
||||||
WHERE_NEXT;
|
WHERE_NEXT;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
||||||
|
@ -4809,11 +4815,11 @@ int32_t hashJoinOptSplitPrimCond(SNode **pCondition, SNode **pPrimaryKeyCond) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needOutput = false;
|
bool needOutput = false;
|
||||||
if (isCondColumnsFromMultiTable(*pCondition)) {
|
if (filterIsMultiTableColsCond(*pCondition)) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
EConditionType type = classifyCondition(*pCondition);
|
EConditionType type = filterClassifyCondition(*pCondition);
|
||||||
if (COND_TYPE_PRIMARY_KEY == type) {
|
if (COND_TYPE_PRIMARY_KEY == type) {
|
||||||
*pPrimaryKeyCond = *pCondition;
|
*pPrimaryKeyCond = *pCondition;
|
||||||
*pCondition = NULL;
|
*pCondition = NULL;
|
||||||
|
@ -4830,6 +4836,7 @@ static int32_t hashJoinOptRewriteJoin(SOptimizeContext* pCxt, SLogicNode* pNode,
|
||||||
pJoin->joinAlgo = JOIN_ALGO_HASH;
|
pJoin->joinAlgo = JOIN_ALGO_HASH;
|
||||||
|
|
||||||
if (NULL != pJoin->pColOnCond) {
|
if (NULL != pJoin->pColOnCond) {
|
||||||
|
#if 0
|
||||||
EJoinType t = pJoin->joinType;
|
EJoinType t = pJoin->joinType;
|
||||||
EJoinSubType s = pJoin->subType;
|
EJoinSubType s = pJoin->subType;
|
||||||
|
|
||||||
|
@ -4887,8 +4894,20 @@ static int32_t hashJoinOptRewriteJoin(SOptimizeContext* pCxt, SLogicNode* pNode,
|
||||||
pJoin->timeRange.skey = TMAX(ltimeRange.skey, rtimeRange.skey);
|
pJoin->timeRange.skey = TMAX(ltimeRange.skey, rtimeRange.skey);
|
||||||
pJoin->timeRange.ekey = TMIN(ltimeRange.ekey, rtimeRange.ekey);
|
pJoin->timeRange.ekey = TMIN(ltimeRange.ekey, rtimeRange.ekey);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
SNode* pPrimaryKeyCond = NULL;
|
||||||
|
hashJoinOptSplitPrimCond(&pJoin->pColOnCond, &pPrimaryKeyCond);
|
||||||
|
if (NULL != pPrimaryKeyCond) {
|
||||||
|
bool isStrict = false;
|
||||||
|
code = getTimeRangeFromNode(&pPrimaryKeyCond, &pJoin->timeRange, &isStrict);
|
||||||
|
nodesDestroyNode(pPrimaryKeyCond);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
pJoin->timeRange = TSWINDOW_INITIALIZER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (NULL != pJoin->pTagOnCond && !TSWINDOW_IS_EQUAL(pJoin->timeRange, TSWINDOW_DESC_INITIALIZER)) {
|
if (NULL != pJoin->pTagOnCond && !TSWINDOW_IS_EQUAL(pJoin->timeRange, TSWINDOW_DESC_INITIALIZER)) {
|
||||||
EJoinType t = pJoin->joinType;
|
EJoinType t = pJoin->joinType;
|
||||||
EJoinSubType s = pJoin->subType;
|
EJoinSubType s = pJoin->subType;
|
||||||
|
@ -4917,14 +4936,16 @@ static int32_t hashJoinOptRewriteJoin(SOptimizeContext* pCxt, SLogicNode* pNode,
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!TSWINDOW_IS_EQUAL(pJoin->timeRange, TSWINDOW_DESC_INITIALIZER)) {
|
if (!TSWINDOW_IS_EQUAL(pJoin->timeRange, TSWINDOW_DESC_INITIALIZER)) {
|
||||||
FOREACH(pNode, pJoin->node.pChildren) {
|
SNode* pChild = NULL;
|
||||||
if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pNode)) {
|
FOREACH(pChild, pJoin->node.pChildren) {
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pChild)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SScanLogicNode* pScan = (SScanLogicNode*)pNode;
|
SScanLogicNode* pScan = (SScanLogicNode*)pChild;
|
||||||
if (TSWINDOW_IS_EQUAL(pScan->scanRange, TSWINDOW_INITIALIZER)) {
|
if (TSWINDOW_IS_EQUAL(pScan->scanRange, TSWINDOW_INITIALIZER)) {
|
||||||
continue;
|
continue;
|
||||||
} else if (pJoin->timeRange.ekey < pScan->scanRange.skey || pJoin->timeRange.skey > pScan->scanRange.ekey) {
|
} else if (pJoin->timeRange.ekey < pScan->scanRange.skey || pJoin->timeRange.skey > pScan->scanRange.ekey) {
|
||||||
|
@ -4937,6 +4958,58 @@ static int32_t hashJoinOptRewriteJoin(SOptimizeContext* pCxt, SLogicNode* pNode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pJoin->timeRangeTarget = 0;
|
||||||
|
|
||||||
|
if (!TSWINDOW_IS_EQUAL(pJoin->timeRange, TSWINDOW_INITIALIZER)) {
|
||||||
|
SNode* pChild = NULL;
|
||||||
|
int32_t timeRangeTarget = 1;
|
||||||
|
FOREACH(pChild, pJoin->node.pChildren) {
|
||||||
|
if (QUERY_NODE_LOGIC_PLAN_SCAN != nodeType(pChild)) {
|
||||||
|
timeRangeTarget++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SScanLogicNode* pScan = (SScanLogicNode*)pChild;
|
||||||
|
if (TSWINDOW_IS_EQUAL(pScan->scanRange, pJoin->timeRange)) {
|
||||||
|
timeRangeTarget++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool replaced = false;
|
||||||
|
switch (pJoin->joinType) {
|
||||||
|
case JOIN_TYPE_INNER:
|
||||||
|
pScan->scanRange.skey = pJoin->timeRange.skey;
|
||||||
|
pScan->scanRange.ekey = pJoin->timeRange.ekey;
|
||||||
|
replaced = true;
|
||||||
|
break;
|
||||||
|
case JOIN_TYPE_LEFT:
|
||||||
|
if (2 == timeRangeTarget) {
|
||||||
|
pScan->scanRange.skey = pJoin->timeRange.skey;
|
||||||
|
pScan->scanRange.ekey = pJoin->timeRange.ekey;
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JOIN_TYPE_RIGHT:
|
||||||
|
if (1 == timeRangeTarget) {
|
||||||
|
pScan->scanRange.skey = pJoin->timeRange.skey;
|
||||||
|
pScan->scanRange.ekey = pJoin->timeRange.ekey;
|
||||||
|
replaced = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replaced) {
|
||||||
|
timeRangeTarget++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pJoin->timeRangeTarget += timeRangeTarget;
|
||||||
|
timeRangeTarget++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pCxt->optimized = true;
|
pCxt->optimized = true;
|
||||||
OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_STB_JOIN);
|
OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_STB_JOIN);
|
||||||
|
|
||||||
|
|
|
@ -792,7 +792,7 @@ static int32_t setColEqList(SNode* pEqCond, int16_t leftBlkId, int16_t rightBlkI
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t setColEqCond(SNode* pEqCond, int32_t subType, int16_t leftBlkId, int16_t rightBlkId, SSortMergeJoinPhysiNode* pJoin) {
|
static int32_t setMergeJoinPrimColEqCond(SNode* pEqCond, int32_t subType, int16_t leftBlkId, int16_t rightBlkId, SSortMergeJoinPhysiNode* pJoin) {
|
||||||
if (QUERY_NODE_OPERATOR == nodeType(pEqCond)) {
|
if (QUERY_NODE_OPERATOR == nodeType(pEqCond)) {
|
||||||
SOperatorNode* pOp = (SOperatorNode*)pEqCond;
|
SOperatorNode* pOp = (SOperatorNode*)pEqCond;
|
||||||
if (pOp->opType != OP_TYPE_EQUAL && JOIN_STYPE_ASOF != subType) {
|
if (pOp->opType != OP_TYPE_EQUAL && JOIN_STYPE_ASOF != subType) {
|
||||||
|
@ -922,7 +922,7 @@ static int32_t createMergeJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChi
|
||||||
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pPrimKeyEqCond,
|
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pPrimKeyEqCond,
|
||||||
&pJoin->pPrimKeyCond);
|
&pJoin->pPrimKeyCond);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = setColEqCond(pJoin->pPrimKeyCond, pJoin->subType, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoin);
|
code = setMergeJoinPrimColEqCond(pJoin->pPrimKeyCond, pJoin->subType, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoin);
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->leftPrimExpr) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->leftPrimExpr) {
|
||||||
code = addDataBlockSlot(pCxt, &pJoin->leftPrimExpr, pLeftDesc);
|
code = addDataBlockSlot(pCxt, &pJoin->leftPrimExpr, pLeftDesc);
|
||||||
|
@ -937,7 +937,13 @@ static int32_t createMergeJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChi
|
||||||
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->addPrimEqCond,
|
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->addPrimEqCond,
|
||||||
&pPrimKeyCond);
|
&pPrimKeyCond);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = setColEqCond(pPrimKeyCond, pJoin->subType, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoin);
|
code = setMergeJoinPrimColEqCond(pPrimKeyCond, pJoin->subType, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoin);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->leftPrimExpr) {
|
||||||
|
code = addDataBlockSlot(pCxt, &pJoin->leftPrimExpr, pLeftDesc);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->rightPrimExpr) {
|
||||||
|
code = addDataBlockSlot(pCxt, &pJoin->rightPrimExpr, pRightDesc);
|
||||||
}
|
}
|
||||||
nodesDestroyNode(pPrimKeyCond);
|
nodesDestroyNode(pPrimKeyCond);
|
||||||
}
|
}
|
||||||
|
@ -1127,6 +1133,107 @@ static int32_t sortHashJoinTargets(int16_t lBlkId, int16_t rBlkId, SHashJoinPhys
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t setHashJoinPrimColEqCond(SNode* pEqCond, int16_t leftBlkId, int16_t rightBlkId, SHashJoinPhysiNode* pJoin) {
|
||||||
|
if (QUERY_NODE_OPERATOR == nodeType(pEqCond)) {
|
||||||
|
SOperatorNode* pOp = (SOperatorNode*)pEqCond;
|
||||||
|
if (pOp->opType != OP_TYPE_EQUAL) {
|
||||||
|
planError("invalid primary cond opType, opType:%d", pOp->opType);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (nodeType(pOp->pLeft)) {
|
||||||
|
case QUERY_NODE_COLUMN: {
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pOp->pLeft;
|
||||||
|
if (leftBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->leftPrimSlotId = pCol->slotId;
|
||||||
|
} else if (rightBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->rightPrimSlotId = pCol->slotId;
|
||||||
|
} else {
|
||||||
|
planError("invalid primary key col equal cond, leftBlockId:%d", pCol->dataBlockId);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pOp->pLeft;
|
||||||
|
if (FUNCTION_TYPE_TIMETRUNCATE != pFunc->funcType) {
|
||||||
|
planError("invalid primary cond left function type, leftFuncType:%d", pFunc->funcType);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (QUERY_NODE_COLUMN != nodeType(pParam)) {
|
||||||
|
planError("invalid primary cond left timetruncate param type, leftParamType:%d", nodeType(pParam));
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pParam;
|
||||||
|
if (leftBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->leftPrimSlotId = pCol->slotId;
|
||||||
|
pJoin->leftPrimExpr = nodesCloneNode((SNode*)pFunc);
|
||||||
|
} else if (rightBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->rightPrimSlotId = pCol->slotId;
|
||||||
|
pJoin->rightPrimExpr = nodesCloneNode((SNode*)pFunc);
|
||||||
|
} else {
|
||||||
|
planError("invalid primary key col equal cond, leftBlockId:%d", pCol->dataBlockId);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
planError("invalid primary cond left node type, leftNodeType:%d", nodeType(pOp->pLeft));
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (nodeType(pOp->pRight)) {
|
||||||
|
case QUERY_NODE_COLUMN: {
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pOp->pRight;
|
||||||
|
if (leftBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->leftPrimSlotId = pCol->slotId;
|
||||||
|
} else if (rightBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->rightPrimSlotId = pCol->slotId;
|
||||||
|
} else {
|
||||||
|
planError("invalid primary key col equal cond, rightBlockId:%d", pCol->dataBlockId);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUERY_NODE_FUNCTION: {
|
||||||
|
SFunctionNode* pFunc = (SFunctionNode*)pOp->pRight;
|
||||||
|
if (FUNCTION_TYPE_TIMETRUNCATE != pFunc->funcType) {
|
||||||
|
planError("invalid primary cond right function type, rightFuncType:%d", pFunc->funcType);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (QUERY_NODE_COLUMN != nodeType(pParam)) {
|
||||||
|
planError("invalid primary cond right timetruncate param type, rightParamType:%d", nodeType(pParam));
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
SColumnNode* pCol = (SColumnNode*)pParam;
|
||||||
|
if (leftBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->leftPrimSlotId = pCol->slotId;
|
||||||
|
pJoin->leftPrimExpr = nodesCloneNode((SNode*)pFunc);
|
||||||
|
} else if (rightBlkId == pCol->dataBlockId) {
|
||||||
|
pJoin->rightPrimSlotId = pCol->slotId;
|
||||||
|
pJoin->rightPrimExpr = nodesCloneNode((SNode*)pFunc);
|
||||||
|
} else {
|
||||||
|
planError("invalid primary key col equal cond, rightBlockId:%d", pCol->dataBlockId);
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
planError("invalid primary cond right node type, rightNodeType:%d", nodeType(pOp->pRight));
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
planError("invalid primary key col equal cond, type:%d", nodeType(pEqCond));
|
||||||
|
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32_t createHashJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SJoinLogicNode* pJoinLogicNode,
|
static int32_t createHashJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SJoinLogicNode* pJoinLogicNode,
|
||||||
SPhysiNode** pPhyNode) {
|
SPhysiNode** pPhyNode) {
|
||||||
SHashJoinPhysiNode* pJoin =
|
SHashJoinPhysiNode* pJoin =
|
||||||
|
@ -1144,10 +1251,23 @@ static int32_t createHashJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChil
|
||||||
pJoin->pWindowOffset = nodesCloneNode(pJoinLogicNode->pWindowOffset);
|
pJoin->pWindowOffset = nodesCloneNode(pJoinLogicNode->pWindowOffset);
|
||||||
pJoin->pJLimit = nodesCloneNode(pJoinLogicNode->pJLimit);
|
pJoin->pJLimit = nodesCloneNode(pJoinLogicNode->pJLimit);
|
||||||
pJoin->node.inputTsOrder = pJoinLogicNode->node.inputTsOrder;
|
pJoin->node.inputTsOrder = pJoinLogicNode->node.inputTsOrder;
|
||||||
|
pJoin->timeRangeTarget = pJoinLogicNode->timeRangeTarget;
|
||||||
pJoin->timeRange.skey = pJoinLogicNode->timeRange.skey;
|
pJoin->timeRange.skey = pJoinLogicNode->timeRange.skey;
|
||||||
pJoin->timeRange.ekey = pJoinLogicNode->timeRange.ekey;
|
pJoin->timeRange.ekey = pJoinLogicNode->timeRange.ekey;
|
||||||
|
|
||||||
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pPrimKeyEqCond, &pJoin->pPrimKeyCond);
|
if (NULL != pJoinLogicNode->pPrimKeyEqCond) {
|
||||||
|
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pPrimKeyEqCond,
|
||||||
|
&pJoin->pPrimKeyCond);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
code = setHashJoinPrimColEqCond(pJoin->pPrimKeyCond, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoin);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->leftPrimExpr) {
|
||||||
|
code = addDataBlockSlot(pCxt, &pJoin->leftPrimExpr, pLeftDesc);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoin->rightPrimExpr) {
|
||||||
|
code = addDataBlockSlot(pCxt, &pJoin->rightPrimExpr, pRightDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pColEqCond, &pJoin->pColEqCond);
|
code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pColEqCond, &pJoin->pColEqCond);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include "functionMgt.h"
|
#include "functionMgt.h"
|
||||||
#include "planInt.h"
|
#include "planInt.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
#include "filter.h"
|
||||||
|
|
||||||
static char* getUsageErrFormat(int32_t errCode) {
|
static char* getUsageErrFormat(int32_t errCode) {
|
||||||
switch (errCode) {
|
switch (errCode) {
|
||||||
|
|
|
@ -4802,14 +4802,8 @@ static EDealRes classifyConditionImpl(SNode *pNode, void *pContext) {
|
||||||
return DEAL_RES_CONTINUE;
|
return DEAL_RES_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum EConditionType {
|
|
||||||
COND_TYPE_PRIMARY_KEY = 1,
|
|
||||||
COND_TYPE_TAG_INDEX,
|
|
||||||
COND_TYPE_TAG,
|
|
||||||
COND_TYPE_NORMAL
|
|
||||||
} EConditionType;
|
|
||||||
|
|
||||||
static EConditionType classifyCondition(SNode *pNode) {
|
EConditionType filterClassifyCondition(SNode *pNode) {
|
||||||
SClassifyConditionCxt cxt = {.hasPrimaryKey = false, .hasTagIndexCol = false, .hasOtherCol = false};
|
SClassifyConditionCxt cxt = {.hasPrimaryKey = false, .hasTagIndexCol = false, .hasOtherCol = false};
|
||||||
nodesWalkExpr(pNode, classifyConditionImpl, &cxt);
|
nodesWalkExpr(pNode, classifyConditionImpl, &cxt);
|
||||||
return cxt.hasOtherCol ? COND_TYPE_NORMAL
|
return cxt.hasOtherCol ? COND_TYPE_NORMAL
|
||||||
|
@ -4819,7 +4813,7 @@ static EConditionType classifyCondition(SNode *pNode) {
|
||||||
: (cxt.hasTagIndexCol ? COND_TYPE_TAG_INDEX : COND_TYPE_TAG)));
|
: (cxt.hasTagIndexCol ? COND_TYPE_TAG_INDEX : COND_TYPE_TAG)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isCondColumnsFromMultiTable(SNode *pCond) {
|
bool filterIsMultiTableColsCond(SNode *pCond) {
|
||||||
SNodeList *pCondCols = nodesMakeList();
|
SNodeList *pCondCols = nodesMakeList();
|
||||||
int32_t code = nodesCollectColumnsFromNode(pCond, NULL, COLLECT_COL_TYPE_ALL, &pCondCols);
|
int32_t code = nodesCollectColumnsFromNode(pCond, NULL, COLLECT_COL_TYPE_ALL, &pCondCols);
|
||||||
if (code == TSDB_CODE_SUCCESS) {
|
if (code == TSDB_CODE_SUCCESS) {
|
||||||
|
@ -4851,12 +4845,12 @@ static int32_t partitionLogicCond(SNode **pCondition, SNode **pPrimaryKeyCond, S
|
||||||
SNodeList *pOtherConds = NULL;
|
SNodeList *pOtherConds = NULL;
|
||||||
SNode *pCond = NULL;
|
SNode *pCond = NULL;
|
||||||
FOREACH(pCond, pLogicCond->pParameterList) {
|
FOREACH(pCond, pLogicCond->pParameterList) {
|
||||||
if (isCondColumnsFromMultiTable(pCond)) {
|
if (filterIsMultiTableColsCond(pCond)) {
|
||||||
if (NULL != pOtherCond) {
|
if (NULL != pOtherCond) {
|
||||||
code = nodesListMakeAppend(&pOtherConds, nodesCloneNode(pCond));
|
code = nodesListMakeAppend(&pOtherConds, nodesCloneNode(pCond));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (classifyCondition(pCond)) {
|
switch (filterClassifyCondition(pCond)) {
|
||||||
case COND_TYPE_PRIMARY_KEY:
|
case COND_TYPE_PRIMARY_KEY:
|
||||||
if (NULL != pPrimaryKeyCond) {
|
if (NULL != pPrimaryKeyCond) {
|
||||||
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
||||||
|
@ -4942,13 +4936,13 @@ int32_t filterPartitionCond(SNode **pCondition, SNode **pPrimaryKeyCond, SNode *
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needOutput = false;
|
bool needOutput = false;
|
||||||
if (isCondColumnsFromMultiTable(*pCondition)) {
|
if (filterIsMultiTableColsCond(*pCondition)) {
|
||||||
if (NULL != pOtherCond) {
|
if (NULL != pOtherCond) {
|
||||||
*pOtherCond = *pCondition;
|
*pOtherCond = *pCondition;
|
||||||
needOutput = true;
|
needOutput = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (classifyCondition(*pCondition)) {
|
switch (filterClassifyCondition(*pCondition)) {
|
||||||
case COND_TYPE_PRIMARY_KEY:
|
case COND_TYPE_PRIMARY_KEY:
|
||||||
if (NULL != pPrimaryKeyCond) {
|
if (NULL != pPrimaryKeyCond) {
|
||||||
*pPrimaryKeyCond = *pCondition;
|
*pPrimaryKeyCond = *pCondition;
|
||||||
|
|
Loading…
Reference in New Issue