Merge pull request #29633 from taosdata/fix/TD-33551
enh: support ? in limit clause
This commit is contained in:
commit
08e56fd27f
|
@ -313,9 +313,9 @@ typedef struct SOrderByExprNode {
|
||||||
} SOrderByExprNode;
|
} SOrderByExprNode;
|
||||||
|
|
||||||
typedef struct SLimitNode {
|
typedef struct SLimitNode {
|
||||||
ENodeType type; // QUERY_NODE_LIMIT
|
ENodeType type; // QUERY_NODE_LIMIT
|
||||||
int64_t limit;
|
SValueNode* limit;
|
||||||
int64_t offset;
|
SValueNode* offset;
|
||||||
} SLimitNode;
|
} SLimitNode;
|
||||||
|
|
||||||
typedef struct SStateWindowNode {
|
typedef struct SStateWindowNode {
|
||||||
|
@ -681,6 +681,7 @@ int32_t nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal);
|
||||||
int32_t nodesMakeValueNodeFromString(char* literal, SValueNode** ppValNode);
|
int32_t nodesMakeValueNodeFromString(char* literal, SValueNode** ppValNode);
|
||||||
int32_t nodesMakeValueNodeFromBool(bool b, SValueNode** ppValNode);
|
int32_t nodesMakeValueNodeFromBool(bool b, SValueNode** ppValNode);
|
||||||
int32_t nodesMakeValueNodeFromInt32(int32_t value, SNode** ppNode);
|
int32_t nodesMakeValueNodeFromInt32(int32_t value, SNode** ppNode);
|
||||||
|
int32_t nodesMakeValueNodeFromInt64(int64_t value, SNode** ppNode);
|
||||||
|
|
||||||
char* nodesGetFillModeString(EFillMode mode);
|
char* nodesGetFillModeString(EFillMode mode);
|
||||||
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
|
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
|
||||||
|
|
|
@ -237,6 +237,63 @@ int main(int argc, char** argv) {
|
||||||
return RUN_ALL_TESTS();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(stmt2Case, stmt2_test_limit) {
|
||||||
|
TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0);
|
||||||
|
ASSERT_NE(taos, nullptr);
|
||||||
|
do_query(taos, "drop database if exists stmt2_testdb_7");
|
||||||
|
do_query(taos, "create database IF NOT EXISTS stmt2_testdb_7");
|
||||||
|
do_query(taos, "create stable stmt2_testdb_7.stb (ts timestamp, b binary(10)) tags(t1 int, t2 binary(10))");
|
||||||
|
do_query(taos,
|
||||||
|
"insert into stmt2_testdb_7.tb2 using stmt2_testdb_7.stb tags(2,'xyz') values(1591060628000, "
|
||||||
|
"'abc'),(1591060628001,'def'),(1591060628004, 'hij')");
|
||||||
|
do_query(taos, "use stmt2_testdb_7");
|
||||||
|
|
||||||
|
|
||||||
|
TAOS_STMT2_OPTION option = {0, true, true, NULL, NULL};
|
||||||
|
|
||||||
|
|
||||||
|
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||||
|
ASSERT_NE(stmt, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
const char* sql = "select * from stmt2_testdb_7.tb2 where ts > ? and ts < ? limit ?";
|
||||||
|
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||||
|
checkError(stmt, code);
|
||||||
|
|
||||||
|
|
||||||
|
int t64_len[1] = {sizeof(int64_t)};
|
||||||
|
int b_len[1] = {3};
|
||||||
|
int x = 2;
|
||||||
|
int x_len = sizeof(int);
|
||||||
|
int64_t ts[2] = {1591060627000, 1591060628005};
|
||||||
|
TAOS_STMT2_BIND params[3] = {{TSDB_DATA_TYPE_TIMESTAMP, &ts[0], t64_len, NULL, 1},
|
||||||
|
{TSDB_DATA_TYPE_TIMESTAMP, &ts[1], t64_len, NULL, 1},
|
||||||
|
{TSDB_DATA_TYPE_INT, &x, &x_len, NULL, 1}};
|
||||||
|
TAOS_STMT2_BIND* paramv = ¶ms[0];
|
||||||
|
TAOS_STMT2_BINDV bindv = {1, NULL, NULL, ¶mv};
|
||||||
|
code = taos_stmt2_bind_param(stmt, &bindv, -1);
|
||||||
|
checkError(stmt, code);
|
||||||
|
|
||||||
|
|
||||||
|
taos_stmt2_exec(stmt, NULL);
|
||||||
|
checkError(stmt, code);
|
||||||
|
|
||||||
|
|
||||||
|
TAOS_RES* pRes = taos_stmt2_result(stmt);
|
||||||
|
ASSERT_NE(pRes, nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
int getRecordCounts = 0;
|
||||||
|
while ((taos_fetch_row(pRes))) {
|
||||||
|
getRecordCounts++;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(getRecordCounts, 2);
|
||||||
|
taos_stmt2_close(stmt);
|
||||||
|
do_query(taos, "drop database if exists stmt2_testdb_7");
|
||||||
|
taos_close(taos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(stmt2Case, insert_stb_get_fields_Test) {
|
TEST(stmt2Case, insert_stb_get_fields_Test) {
|
||||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||||
ASSERT_NE(taos, nullptr);
|
ASSERT_NE(taos, nullptr);
|
||||||
|
|
|
@ -202,13 +202,13 @@ do { \
|
||||||
#define EXPLAIN_SUM_ROW_END() do { varDataSetLen(tbuf, tlen); tlen += VARSTR_HEADER_SIZE; } while (0)
|
#define EXPLAIN_SUM_ROW_END() do { varDataSetLen(tbuf, tlen); tlen += VARSTR_HEADER_SIZE; } while (0)
|
||||||
|
|
||||||
#define EXPLAIN_ROW_APPEND_LIMIT_IMPL(_pLimit, sl) do { \
|
#define EXPLAIN_ROW_APPEND_LIMIT_IMPL(_pLimit, sl) do { \
|
||||||
if (_pLimit) { \
|
if (_pLimit && ((SLimitNode*)_pLimit)->limit) { \
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); \
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); \
|
||||||
SLimitNode* pLimit = (SLimitNode*)_pLimit; \
|
SLimitNode* pLimit = (SLimitNode*)_pLimit; \
|
||||||
EXPLAIN_ROW_APPEND(((sl) ? EXPLAIN_SLIMIT_FORMAT : EXPLAIN_LIMIT_FORMAT), pLimit->limit); \
|
EXPLAIN_ROW_APPEND(((sl) ? EXPLAIN_SLIMIT_FORMAT : EXPLAIN_LIMIT_FORMAT), pLimit->limit->datum.i); \
|
||||||
if (pLimit->offset) { \
|
if (pLimit->offset) { \
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); \
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); \
|
||||||
EXPLAIN_ROW_APPEND(((sl) ? EXPLAIN_SOFFSET_FORMAT : EXPLAIN_OFFSET_FORMAT), pLimit->offset);\
|
EXPLAIN_ROW_APPEND(((sl) ? EXPLAIN_SOFFSET_FORMAT : EXPLAIN_OFFSET_FORMAT), pLimit->offset->datum.i);\
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -676,9 +676,9 @@ static int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_WIN_OFFSET_FORMAT, pStart->literal, pEnd->literal);
|
EXPLAIN_ROW_APPEND(EXPLAIN_WIN_OFFSET_FORMAT, pStart->literal, pEnd->literal);
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
}
|
}
|
||||||
if (NULL != pJoinNode->pJLimit) {
|
if (NULL != pJoinNode->pJLimit && NULL != ((SLimitNode*)pJoinNode->pJLimit)->limit) {
|
||||||
SLimitNode* pJLimit = (SLimitNode*)pJoinNode->pJLimit;
|
SLimitNode* pJLimit = (SLimitNode*)pJoinNode->pJLimit;
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_JLIMIT_FORMAT, pJLimit->limit);
|
EXPLAIN_ROW_APPEND(EXPLAIN_JLIMIT_FORMAT, pJLimit->limit->datum.i);
|
||||||
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
|
||||||
}
|
}
|
||||||
if (IS_WINDOW_JOIN(pJoinNode->subType)) {
|
if (IS_WINDOW_JOIN(pJoinNode->subType)) {
|
||||||
|
|
|
@ -54,8 +54,8 @@ static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* list, SNode* p
|
||||||
static int32_t getTableList(void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond,
|
static int32_t getTableList(void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond,
|
||||||
STableListInfo* pListInfo, uint8_t* digest, const char* idstr, SStorageAPI* pStorageAPI);
|
STableListInfo* pListInfo, uint8_t* digest, const char* idstr, SStorageAPI* pStorageAPI);
|
||||||
|
|
||||||
static int64_t getLimit(const SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->limit; }
|
static int64_t getLimit(const SNode* pLimit) { return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->limit) ? -1 : ((SLimitNode*)pLimit)->limit->datum.i; }
|
||||||
static int64_t getOffset(const SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->offset; }
|
static int64_t getOffset(const SNode* pLimit) { return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->offset) ? -1 : ((SLimitNode*)pLimit)->offset->datum.i; }
|
||||||
static void releaseColInfoData(void* pCol);
|
static void releaseColInfoData(void* pCol);
|
||||||
|
|
||||||
void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
|
void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
|
||||||
|
|
|
@ -1185,7 +1185,7 @@ int32_t createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDow
|
||||||
pInfo->tblTimeRange.skey = pJoinNode->timeRange.skey;
|
pInfo->tblTimeRange.skey = pJoinNode->timeRange.skey;
|
||||||
pInfo->tblTimeRange.ekey = pJoinNode->timeRange.ekey;
|
pInfo->tblTimeRange.ekey = pJoinNode->timeRange.ekey;
|
||||||
|
|
||||||
pInfo->ctx.limit = pJoinNode->node.pLimit ? ((SLimitNode*)pJoinNode->node.pLimit)->limit : INT64_MAX;
|
pInfo->ctx.limit = (pJoinNode->node.pLimit && ((SLimitNode*)pJoinNode->node.pLimit)->limit) ? ((SLimitNode*)pJoinNode->node.pLimit)->limit->datum.i : 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);
|
||||||
|
|
||||||
|
|
|
@ -3592,7 +3592,7 @@ int32_t mJoinInitWindowCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* p
|
||||||
switch (pJoinNode->subType) {
|
switch (pJoinNode->subType) {
|
||||||
case JOIN_STYPE_ASOF:
|
case JOIN_STYPE_ASOF:
|
||||||
pCtx->asofOpType = pJoinNode->asofOpType;
|
pCtx->asofOpType = pJoinNode->asofOpType;
|
||||||
pCtx->jLimit = pJoinNode->pJLimit ? ((SLimitNode*)pJoinNode->pJLimit)->limit : 1;
|
pCtx->jLimit = (pJoinNode->pJLimit && ((SLimitNode*)pJoinNode->pJLimit)->limit) ? ((SLimitNode*)pJoinNode->pJLimit)->limit->datum.i : 1;
|
||||||
pCtx->eqRowsAcq = ASOF_EQ_ROW_INCLUDED(pCtx->asofOpType);
|
pCtx->eqRowsAcq = ASOF_EQ_ROW_INCLUDED(pCtx->asofOpType);
|
||||||
pCtx->lowerRowsAcq = (JOIN_TYPE_RIGHT != pJoin->joinType) ? ASOF_LOWER_ROW_INCLUDED(pCtx->asofOpType) : ASOF_GREATER_ROW_INCLUDED(pCtx->asofOpType);
|
pCtx->lowerRowsAcq = (JOIN_TYPE_RIGHT != pJoin->joinType) ? ASOF_LOWER_ROW_INCLUDED(pCtx->asofOpType) : ASOF_GREATER_ROW_INCLUDED(pCtx->asofOpType);
|
||||||
pCtx->greaterRowsAcq = (JOIN_TYPE_RIGHT != pJoin->joinType) ? ASOF_GREATER_ROW_INCLUDED(pCtx->asofOpType) : ASOF_LOWER_ROW_INCLUDED(pCtx->asofOpType);
|
pCtx->greaterRowsAcq = (JOIN_TYPE_RIGHT != pJoin->joinType) ? ASOF_GREATER_ROW_INCLUDED(pCtx->asofOpType) : ASOF_LOWER_ROW_INCLUDED(pCtx->asofOpType);
|
||||||
|
@ -3609,7 +3609,7 @@ int32_t mJoinInitWindowCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* p
|
||||||
SWindowOffsetNode* pOffsetNode = (SWindowOffsetNode*)pJoinNode->pWindowOffset;
|
SWindowOffsetNode* pOffsetNode = (SWindowOffsetNode*)pJoinNode->pWindowOffset;
|
||||||
SValueNode* pWinBegin = (SValueNode*)pOffsetNode->pStartOffset;
|
SValueNode* pWinBegin = (SValueNode*)pOffsetNode->pStartOffset;
|
||||||
SValueNode* pWinEnd = (SValueNode*)pOffsetNode->pEndOffset;
|
SValueNode* pWinEnd = (SValueNode*)pOffsetNode->pEndOffset;
|
||||||
pCtx->jLimit = pJoinNode->pJLimit ? ((SLimitNode*)pJoinNode->pJLimit)->limit : INT64_MAX;
|
pCtx->jLimit = (pJoinNode->pJLimit && ((SLimitNode*)pJoinNode->pJLimit)->limit) ? ((SLimitNode*)pJoinNode->pJLimit)->limit->datum.i : INT64_MAX;
|
||||||
pCtx->winBeginOffset = pWinBegin->datum.i;
|
pCtx->winBeginOffset = pWinBegin->datum.i;
|
||||||
pCtx->winEndOffset = pWinEnd->datum.i;
|
pCtx->winEndOffset = pWinEnd->datum.i;
|
||||||
pCtx->eqRowsAcq = (pCtx->winBeginOffset <= 0 && pCtx->winEndOffset >= 0);
|
pCtx->eqRowsAcq = (pCtx->winBeginOffset <= 0 && pCtx->winEndOffset >= 0);
|
||||||
|
@ -3662,7 +3662,7 @@ int32_t mJoinInitMergeCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJ
|
||||||
pCtx->hashCan = pJoin->probe->keyNum > 0;
|
pCtx->hashCan = pJoin->probe->keyNum > 0;
|
||||||
|
|
||||||
if (JOIN_STYPE_ASOF == pJoinNode->subType || JOIN_STYPE_WIN == pJoinNode->subType) {
|
if (JOIN_STYPE_ASOF == pJoinNode->subType || JOIN_STYPE_WIN == pJoinNode->subType) {
|
||||||
pCtx->jLimit = pJoinNode->pJLimit ? ((SLimitNode*)pJoinNode->pJLimit)->limit : 1;
|
pCtx->jLimit = (pJoinNode->pJLimit && ((SLimitNode*)pJoinNode->pJLimit)->limit) ? ((SLimitNode*)pJoinNode->pJLimit)->limit->datum.i : 1;
|
||||||
pJoin->subType = JOIN_STYPE_OUTER;
|
pJoin->subType = JOIN_STYPE_OUTER;
|
||||||
pJoin->build->eqRowLimit = pCtx->jLimit;
|
pJoin->build->eqRowLimit = pCtx->jLimit;
|
||||||
pJoin->grpResetFp = mLeftJoinGroupReset;
|
pJoin->grpResetFp = mLeftJoinGroupReset;
|
||||||
|
|
|
@ -986,7 +986,7 @@ static int32_t mJoinInitTableInfo(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysi
|
||||||
pTable->multiEqGrpRows = !((JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_ANTI == pJoin->subType) && NULL == pJoin->pFPreFilter);
|
pTable->multiEqGrpRows = !((JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_ANTI == pJoin->subType) && NULL == pJoin->pFPreFilter);
|
||||||
pTable->multiRowsGrp = !((JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_ANTI == pJoin->subType) && NULL == pJoin->pPreFilter);
|
pTable->multiRowsGrp = !((JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_ANTI == pJoin->subType) && NULL == pJoin->pPreFilter);
|
||||||
if (JOIN_STYPE_ASOF == pJoinNode->subType) {
|
if (JOIN_STYPE_ASOF == pJoinNode->subType) {
|
||||||
pTable->eqRowLimit = pJoinNode->pJLimit ? ((SLimitNode*)pJoinNode->pJLimit)->limit : 1;
|
pTable->eqRowLimit = (pJoinNode->pJLimit && ((SLimitNode*)pJoinNode->pJLimit)->limit) ? ((SLimitNode*)pJoinNode->pJLimit)->limit->datum.i : 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pTable->multiEqGrpRows = true;
|
pTable->multiEqGrpRows = true;
|
||||||
|
@ -1169,7 +1169,7 @@ static FORCE_INLINE SSDataBlock* mJoinRetrieveImpl(SMJoinOperatorInfo* pJoin, SM
|
||||||
|
|
||||||
static int32_t mJoinInitCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode) {
|
static int32_t mJoinInitCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode) {
|
||||||
pJoin->ctx.mergeCtx.groupJoin = pJoinNode->grpJoin;
|
pJoin->ctx.mergeCtx.groupJoin = pJoinNode->grpJoin;
|
||||||
pJoin->ctx.mergeCtx.limit = pJoinNode->node.pLimit ? ((SLimitNode*)pJoinNode->node.pLimit)->limit : INT64_MAX;
|
pJoin->ctx.mergeCtx.limit = (pJoinNode->node.pLimit && ((SLimitNode*)pJoinNode->node.pLimit)->limit) ? ((SLimitNode*)pJoinNode->node.pLimit)->limit->datum.i : INT64_MAX;
|
||||||
pJoin->retrieveFp = pJoinNode->grpJoin ? mJoinGrpRetrieveImpl : mJoinRetrieveImpl;
|
pJoin->retrieveFp = pJoinNode->grpJoin ? mJoinGrpRetrieveImpl : mJoinRetrieveImpl;
|
||||||
pJoin->outBlkId = pJoinNode->node.pOutputDataBlockDesc->dataBlockId;
|
pJoin->outBlkId = pJoinNode->node.pOutputDataBlockDesc->dataBlockId;
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,11 @@ int32_t createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortN
|
||||||
|
|
||||||
calcSortOperMaxTupleLength(pInfo, pSortNode->pSortKeys);
|
calcSortOperMaxTupleLength(pInfo, pSortNode->pSortKeys);
|
||||||
pInfo->maxRows = -1;
|
pInfo->maxRows = -1;
|
||||||
if (pSortNode->node.pLimit) {
|
if (pSortNode->node.pLimit && ((SLimitNode*)pSortNode->node.pLimit)->limit) {
|
||||||
SLimitNode* pLimit = (SLimitNode*)pSortNode->node.pLimit;
|
SLimitNode* pLimit = (SLimitNode*)pSortNode->node.pLimit;
|
||||||
if (pLimit->limit > 0) pInfo->maxRows = pLimit->limit + pLimit->offset;
|
if (pLimit->limit->datum.i > 0) {
|
||||||
|
pInfo->maxRows = pLimit->limit->datum.i + (pLimit->offset ? pLimit->offset->datum.i : 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pOperator->exprSupp.pCtx =
|
pOperator->exprSupp.pCtx =
|
||||||
|
|
|
@ -1417,15 +1417,15 @@ int32_t createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode
|
||||||
pInfo->interval = interval;
|
pInfo->interval = interval;
|
||||||
pInfo->twAggSup = as;
|
pInfo->twAggSup = as;
|
||||||
pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock;
|
pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock;
|
||||||
if (pPhyNode->window.node.pLimit) {
|
if (pPhyNode->window.node.pLimit && ((SLimitNode*)pPhyNode->window.node.pLimit)->limit) {
|
||||||
SLimitNode* pLimit = (SLimitNode*)pPhyNode->window.node.pLimit;
|
SLimitNode* pLimit = (SLimitNode*)pPhyNode->window.node.pLimit;
|
||||||
pInfo->limited = true;
|
pInfo->limited = true;
|
||||||
pInfo->limit = pLimit->limit + pLimit->offset;
|
pInfo->limit = pLimit->limit->datum.i + (pLimit->offset ? pLimit->offset->datum.i : 0);
|
||||||
}
|
}
|
||||||
if (pPhyNode->window.node.pSlimit) {
|
if (pPhyNode->window.node.pSlimit && ((SLimitNode*)pPhyNode->window.node.pSlimit)->limit) {
|
||||||
SLimitNode* pLimit = (SLimitNode*)pPhyNode->window.node.pSlimit;
|
SLimitNode* pLimit = (SLimitNode*)pPhyNode->window.node.pSlimit;
|
||||||
pInfo->slimited = true;
|
pInfo->slimited = true;
|
||||||
pInfo->slimit = pLimit->limit + pLimit->offset;
|
pInfo->slimit = pLimit->limit->datum.i + (pLimit->offset ? pLimit->offset->datum.i : 0);
|
||||||
pInfo->curGroupId = UINT64_MAX;
|
pInfo->curGroupId = UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -864,7 +864,11 @@ SSortMergeJoinPhysiNode* createDummySortMergeJoinPhysiNode(SJoinTestParam* param
|
||||||
SLimitNode* limitNode = NULL;
|
SLimitNode* limitNode = NULL;
|
||||||
code = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
code = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
||||||
assert(limitNode);
|
assert(limitNode);
|
||||||
limitNode->limit = param->jLimit;
|
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&limitNode->limit);
|
||||||
|
assert(limitNode->limit);
|
||||||
|
limitNode->limit->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
limitNode->limit->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
||||||
|
limitNode->limit->datum.i = param->jLimit;
|
||||||
p->pJLimit = (SNode*)limitNode;
|
p->pJLimit = (SNode*)limitNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1418,6 +1418,7 @@ SNode* qptMakeExprNode(SNode** ppNode) {
|
||||||
|
|
||||||
SNode* qptMakeLimitNode(SNode** ppNode) {
|
SNode* qptMakeLimitNode(SNode** ppNode) {
|
||||||
SNode* pNode = NULL;
|
SNode* pNode = NULL;
|
||||||
|
int32_t code = 0;
|
||||||
if (QPT_NCORRECT_LOW_PROB()) {
|
if (QPT_NCORRECT_LOW_PROB()) {
|
||||||
return qptMakeRandNode(&pNode);
|
return qptMakeRandNode(&pNode);
|
||||||
}
|
}
|
||||||
|
@ -1429,15 +1430,27 @@ SNode* qptMakeLimitNode(SNode** ppNode) {
|
||||||
|
|
||||||
if (!qptCtx.param.correctExpected) {
|
if (!qptCtx.param.correctExpected) {
|
||||||
if (taosRand() % 2) {
|
if (taosRand() % 2) {
|
||||||
pLimit->limit = taosRand() * ((taosRand() % 2) ? 1 : -1);
|
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pLimit->limit);
|
||||||
|
assert(pLimit->limit);
|
||||||
|
pLimit->limit->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
pLimit->limit->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
||||||
|
pLimit->limit->datum.i = taosRand() * ((taosRand() % 2) ? 1 : -1);
|
||||||
}
|
}
|
||||||
if (taosRand() % 2) {
|
if (taosRand() % 2) {
|
||||||
pLimit->offset = taosRand() * ((taosRand() % 2) ? 1 : -1);
|
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pLimit->offset);
|
||||||
|
assert(pLimit->offset);
|
||||||
|
pLimit->offset->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
pLimit->offset->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
||||||
|
pLimit->offset->datum.i = taosRand() * ((taosRand() % 2) ? 1 : -1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pLimit->limit = taosRand();
|
pLimit->limit->datum.i = taosRand();
|
||||||
if (taosRand() % 2) {
|
if (taosRand() % 2) {
|
||||||
pLimit->offset = taosRand();
|
code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pLimit->offset);
|
||||||
|
assert(pLimit->offset);
|
||||||
|
pLimit->offset->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
pLimit->offset->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
||||||
|
pLimit->offset->datum.i = taosRand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
if (NULL == (pSrc)->fldname) { \
|
if (NULL == (pSrc)->fldname) { \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
int32_t code = nodesCloneNode((pSrc)->fldname, &((pDst)->fldname)); \
|
int32_t code = nodesCloneNode((SNode*)(pSrc)->fldname, (SNode**)&((pDst)->fldname)); \
|
||||||
if (NULL == (pDst)->fldname) { \
|
if (NULL == (pDst)->fldname) { \
|
||||||
return code; \
|
return code; \
|
||||||
} \
|
} \
|
||||||
|
@ -346,8 +346,8 @@ static int32_t orderByExprNodeCopy(const SOrderByExprNode* pSrc, SOrderByExprNod
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
|
static int32_t limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
|
||||||
COPY_SCALAR_FIELD(limit);
|
CLONE_NODE_FIELD(limit);
|
||||||
COPY_SCALAR_FIELD(offset);
|
CLONE_NODE_FIELD(offset);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4933,9 +4933,9 @@ static const char* jkLimitOffset = "Offset";
|
||||||
static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
|
static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
||||||
|
|
||||||
int32_t code = tjsonAddIntegerToObject(pJson, jkLimitLimit, pNode->limit);
|
int32_t code = tjsonAddObject(pJson, jkLimitLimit, nodeToJson, pNode->limit);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code && pNode->offset) {
|
||||||
code = tjsonAddIntegerToObject(pJson, jkLimitOffset, pNode->offset);
|
code = tjsonAddObject(pJson, jkLimitOffset, nodeToJson, pNode->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
|
@ -4944,9 +4944,9 @@ static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
|
||||||
static int32_t jsonToLimitNode(const SJson* pJson, void* pObj) {
|
static int32_t jsonToLimitNode(const SJson* pJson, void* pObj) {
|
||||||
SLimitNode* pNode = (SLimitNode*)pObj;
|
SLimitNode* pNode = (SLimitNode*)pObj;
|
||||||
|
|
||||||
int32_t code = tjsonGetBigIntValue(pJson, jkLimitLimit, &pNode->limit);
|
int32_t code = jsonToNodeObject(pJson, jkLimitLimit, (SNode**)&pNode->limit);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = tjsonGetBigIntValue(pJson, jkLimitOffset, &pNode->offset);
|
code = jsonToNodeObject(pJson, jkLimitOffset, (SNode**)&pNode->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
|
|
|
@ -1246,9 +1246,9 @@ enum { LIMIT_CODE_LIMIT = 1, LIMIT_CODE_OFFSET };
|
||||||
static int32_t limitNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
static int32_t limitNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||||
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
||||||
|
|
||||||
int32_t code = tlvEncodeI64(pEncoder, LIMIT_CODE_LIMIT, pNode->limit);
|
int32_t code = tlvEncodeObj(pEncoder, LIMIT_CODE_LIMIT, nodeToMsg, pNode->limit);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code && pNode->offset) {
|
||||||
code = tlvEncodeI64(pEncoder, LIMIT_CODE_OFFSET, pNode->offset);
|
code = tlvEncodeObj(pEncoder, LIMIT_CODE_OFFSET, nodeToMsg, pNode->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
|
@ -1262,10 +1262,10 @@ static int32_t msgToLimitNode(STlvDecoder* pDecoder, void* pObj) {
|
||||||
tlvForEach(pDecoder, pTlv, code) {
|
tlvForEach(pDecoder, pTlv, code) {
|
||||||
switch (pTlv->type) {
|
switch (pTlv->type) {
|
||||||
case LIMIT_CODE_LIMIT:
|
case LIMIT_CODE_LIMIT:
|
||||||
code = tlvDecodeI64(pTlv, &pNode->limit);
|
code = msgToNodeFromTlv(pTlv, (void**)&pNode->limit);
|
||||||
break;
|
break;
|
||||||
case LIMIT_CODE_OFFSET:
|
case LIMIT_CODE_OFFSET:
|
||||||
code = tlvDecodeI64(pTlv, &pNode->offset);
|
code = msgToNodeFromTlv(pTlv, (void**)&pNode->offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1106,8 +1106,12 @@ void nodesDestroyNode(SNode* pNode) {
|
||||||
case QUERY_NODE_ORDER_BY_EXPR:
|
case QUERY_NODE_ORDER_BY_EXPR:
|
||||||
nodesDestroyNode(((SOrderByExprNode*)pNode)->pExpr);
|
nodesDestroyNode(((SOrderByExprNode*)pNode)->pExpr);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_LIMIT: // no pointer field
|
case QUERY_NODE_LIMIT: {
|
||||||
|
SLimitNode* pLimit = (SLimitNode*)pNode;
|
||||||
|
nodesDestroyNode((SNode*)pLimit->limit);
|
||||||
|
nodesDestroyNode((SNode*)pLimit->offset);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case QUERY_NODE_STATE_WINDOW: {
|
case QUERY_NODE_STATE_WINDOW: {
|
||||||
SStateWindowNode* pState = (SStateWindowNode*)pNode;
|
SStateWindowNode* pState = (SStateWindowNode*)pNode;
|
||||||
nodesDestroyNode(pState->pCol);
|
nodesDestroyNode(pState->pCol);
|
||||||
|
@ -3097,6 +3101,25 @@ int32_t nodesMakeValueNodeFromInt32(int32_t value, SNode** ppNode) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t nodesMakeValueNodeFromInt64(int64_t value, SNode** ppNode) {
|
||||||
|
SValueNode* pValNode = NULL;
|
||||||
|
int32_t code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pValNode);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pValNode->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
pValNode->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
||||||
|
code = nodesSetValueNodeValue(pValNode, &value);
|
||||||
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
|
pValNode->translate = true;
|
||||||
|
pValNode->isNull = false;
|
||||||
|
*ppNode = (SNode*)pValNode;
|
||||||
|
} else {
|
||||||
|
nodesDestroyNode((SNode*)pValNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool nodesIsStar(SNode* pNode) {
|
bool nodesIsStar(SNode* pNode) {
|
||||||
return (QUERY_NODE_COLUMN == nodeType(pNode)) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]) &&
|
return (QUERY_NODE_COLUMN == nodeType(pNode)) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]) &&
|
||||||
(0 == strcmp(((SColumnNode*)pNode)->colName, "*"));
|
(0 == strcmp(((SColumnNode*)pNode)->colName, "*"));
|
||||||
|
|
|
@ -152,7 +152,7 @@ SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, SToken
|
||||||
SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight,
|
SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight,
|
||||||
SNode* pJoinCond);
|
SNode* pJoinCond);
|
||||||
SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName);
|
SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName);
|
||||||
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset);
|
SNode* createLimitNode(SAstCreateContext* pCxt, SNode* pLimit, SNode* pOffset);
|
||||||
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder);
|
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder);
|
||||||
SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode* pGap);
|
SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode* pGap);
|
||||||
SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr);
|
SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr);
|
||||||
|
|
|
@ -1078,6 +1078,10 @@ signed_integer(A) ::= NK_MINUS(B) NK_INTEGER(C).
|
||||||
A = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t);
|
A = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned_integer(A) ::= NK_INTEGER(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B); }
|
||||||
|
unsigned_integer(A) ::= NK_QUESTION(B). { A = releaseRawExprNode(pCxt, createRawExprNode(pCxt, &B, createPlaceholderValueNode(pCxt, &B))); }
|
||||||
|
|
||||||
signed_float(A) ::= NK_FLOAT(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B); }
|
signed_float(A) ::= NK_FLOAT(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B); }
|
||||||
signed_float(A) ::= NK_PLUS NK_FLOAT(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B); }
|
signed_float(A) ::= NK_PLUS NK_FLOAT(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B); }
|
||||||
signed_float(A) ::= NK_MINUS(B) NK_FLOAT(C). {
|
signed_float(A) ::= NK_MINUS(B) NK_FLOAT(C). {
|
||||||
|
@ -1098,6 +1102,7 @@ signed_literal(A) ::= NULL(B).
|
||||||
signed_literal(A) ::= literal_func(B). { A = releaseRawExprNode(pCxt, B); }
|
signed_literal(A) ::= literal_func(B). { A = releaseRawExprNode(pCxt, B); }
|
||||||
signed_literal(A) ::= NK_QUESTION(B). { A = createPlaceholderValueNode(pCxt, &B); }
|
signed_literal(A) ::= NK_QUESTION(B). { A = createPlaceholderValueNode(pCxt, &B); }
|
||||||
|
|
||||||
|
|
||||||
%type literal_list { SNodeList* }
|
%type literal_list { SNodeList* }
|
||||||
%destructor literal_list { nodesDestroyList($$); }
|
%destructor literal_list { nodesDestroyList($$); }
|
||||||
literal_list(A) ::= signed_literal(B). { A = createNodeList(pCxt, B); }
|
literal_list(A) ::= signed_literal(B). { A = createNodeList(pCxt, B); }
|
||||||
|
@ -1480,7 +1485,7 @@ window_offset_literal(A) ::= NK_MINUS(B) NK_VARIABLE(C).
|
||||||
}
|
}
|
||||||
|
|
||||||
jlimit_clause_opt(A) ::= . { A = NULL; }
|
jlimit_clause_opt(A) ::= . { A = NULL; }
|
||||||
jlimit_clause_opt(A) ::= JLIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); }
|
jlimit_clause_opt(A) ::= JLIMIT unsigned_integer(B). { A = createLimitNode(pCxt, B, NULL); }
|
||||||
|
|
||||||
/************************************************ query_specification *************************************************/
|
/************************************************ query_specification *************************************************/
|
||||||
query_specification(A) ::=
|
query_specification(A) ::=
|
||||||
|
@ -1660,14 +1665,14 @@ order_by_clause_opt(A) ::= .
|
||||||
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { A = B; }
|
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { A = B; }
|
||||||
|
|
||||||
slimit_clause_opt(A) ::= . { A = NULL; }
|
slimit_clause_opt(A) ::= . { A = NULL; }
|
||||||
slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); }
|
slimit_clause_opt(A) ::= SLIMIT unsigned_integer(B). { A = createLimitNode(pCxt, B, NULL); }
|
||||||
slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(B) SOFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); }
|
slimit_clause_opt(A) ::= SLIMIT unsigned_integer(B) SOFFSET unsigned_integer(C). { A = createLimitNode(pCxt, B, C); }
|
||||||
slimit_clause_opt(A) ::= SLIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
slimit_clause_opt(A) ::= SLIMIT unsigned_integer(C) NK_COMMA unsigned_integer(B). { A = createLimitNode(pCxt, B, C); }
|
||||||
|
|
||||||
limit_clause_opt(A) ::= . { A = NULL; }
|
limit_clause_opt(A) ::= . { A = NULL; }
|
||||||
limit_clause_opt(A) ::= LIMIT NK_INTEGER(B). { A = createLimitNode(pCxt, &B, NULL); }
|
limit_clause_opt(A) ::= LIMIT unsigned_integer(B). { A = createLimitNode(pCxt, B, NULL); }
|
||||||
limit_clause_opt(A) ::= LIMIT NK_INTEGER(B) OFFSET NK_INTEGER(C). { A = createLimitNode(pCxt, &B, &C); }
|
limit_clause_opt(A) ::= LIMIT unsigned_integer(B) OFFSET unsigned_integer(C). { A = createLimitNode(pCxt, B, C); }
|
||||||
limit_clause_opt(A) ::= LIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
limit_clause_opt(A) ::= LIMIT unsigned_integer(C) NK_COMMA unsigned_integer(B). { A = createLimitNode(pCxt, B, C); }
|
||||||
|
|
||||||
/************************************************ subquery ************************************************************/
|
/************************************************ subquery ************************************************************/
|
||||||
subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); }
|
subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); }
|
||||||
|
|
|
@ -1287,14 +1287,14 @@ _err:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) {
|
SNode* createLimitNode(SAstCreateContext* pCxt, SNode* pLimit, SNode* pOffset) {
|
||||||
CHECK_PARSER_STATUS(pCxt);
|
CHECK_PARSER_STATUS(pCxt);
|
||||||
SLimitNode* limitNode = NULL;
|
SLimitNode* limitNode = NULL;
|
||||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
||||||
CHECK_MAKE_NODE(limitNode);
|
CHECK_MAKE_NODE(limitNode);
|
||||||
limitNode->limit = taosStr2Int64(pLimit->z, NULL, 10);
|
limitNode->limit = (SValueNode*)pLimit;
|
||||||
if (NULL != pOffset) {
|
if (NULL != pOffset) {
|
||||||
limitNode->offset = taosStr2Int64(pOffset->z, NULL, 10);
|
limitNode->offset = (SValueNode*)pOffset;
|
||||||
}
|
}
|
||||||
return (SNode*)limitNode;
|
return (SNode*)limitNode;
|
||||||
_err:
|
_err:
|
||||||
|
|
|
@ -4729,16 +4729,20 @@ static int32_t translateJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoin
|
||||||
return buildInvalidOperationMsg(&pCxt->msgBuf, "WINDOW_OFFSET required for WINDOW join");
|
return buildInvalidOperationMsg(&pCxt->msgBuf, "WINDOW_OFFSET required for WINDOW join");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pJoinTable->pJLimit) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pJoinTable->pJLimit && NULL != ((SLimitNode*)pJoinTable->pJLimit)->limit) {
|
||||||
if (*pSType != JOIN_STYPE_ASOF && *pSType != JOIN_STYPE_WIN) {
|
if (*pSType != JOIN_STYPE_ASOF && *pSType != JOIN_STYPE_WIN) {
|
||||||
return buildInvalidOperationMsgExt(&pCxt->msgBuf, "JLIMIT not supported for %s join",
|
return buildInvalidOperationMsgExt(&pCxt->msgBuf, "JLIMIT not supported for %s join",
|
||||||
getFullJoinTypeString(type, *pSType));
|
getFullJoinTypeString(type, *pSType));
|
||||||
}
|
}
|
||||||
SLimitNode* pJLimit = (SLimitNode*)pJoinTable->pJLimit;
|
SLimitNode* pJLimit = (SLimitNode*)pJoinTable->pJLimit;
|
||||||
if (pJLimit->limit > JOIN_JLIMIT_MAX_VALUE || pJLimit->limit < 0) {
|
code = translateExpr(pCxt, (SNode**)&pJLimit->limit);
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
if (pJLimit->limit->datum.i > JOIN_JLIMIT_MAX_VALUE || pJLimit->limit->datum.i < 0) {
|
||||||
return buildInvalidOperationMsg(&pCxt->msgBuf, "JLIMIT value is out of valid range [0, 1024]");
|
return buildInvalidOperationMsg(&pCxt->msgBuf, "JLIMIT value is out of valid range [0, 1024]");
|
||||||
}
|
}
|
||||||
if (0 == pJLimit->limit) {
|
if (0 == pJLimit->limit->datum.i) {
|
||||||
pCurrSmt->isEmptyResult = true;
|
pCurrSmt->isEmptyResult = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6994,16 +6998,32 @@ static int32_t translateFrom(STranslateContext* pCxt, SNode** pTable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
if ((NULL != pSelect->pLimit && pSelect->pLimit->offset < 0) ||
|
int32_t code = 0;
|
||||||
(NULL != pSelect->pSlimit && pSelect->pSlimit->offset < 0)) {
|
|
||||||
|
if (pSelect->pLimit && pSelect->pLimit->limit) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pSelect->pLimit->limit);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && pSelect->pLimit && pSelect->pLimit->offset) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pSelect->pLimit->offset);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && pSelect->pSlimit && pSelect->pSlimit->limit) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pSelect->pSlimit->limit);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && pSelect->pSlimit && pSelect->pSlimit->offset) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pSelect->pSlimit->offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((TSDB_CODE_SUCCESS == code) &&
|
||||||
|
((NULL != pSelect->pLimit && pSelect->pLimit->offset && pSelect->pLimit->offset->datum.i < 0) ||
|
||||||
|
(NULL != pSelect->pSlimit && pSelect->pSlimit->offset && pSelect->pSlimit->offset->datum.i < 0))) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != pSelect->pSlimit && (NULL == pSelect->pPartitionByList && NULL == pSelect->pGroupByList)) {
|
if ((TSDB_CODE_SUCCESS == code) && NULL != pSelect->pSlimit && (NULL == pSelect->pPartitionByList && NULL == pSelect->pGroupByList)) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* pTable, SNode** pPrimaryKey) {
|
static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* pTable, SNode** pPrimaryKey) {
|
||||||
|
@ -7482,7 +7502,14 @@ static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pS
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t checkSetOperLimit(STranslateContext* pCxt, SLimitNode* pLimit) {
|
static int32_t checkSetOperLimit(STranslateContext* pCxt, SLimitNode* pLimit) {
|
||||||
if ((NULL != pLimit && pLimit->offset < 0)) {
|
int32_t code = 0;
|
||||||
|
if (pLimit && pLimit->limit) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pLimit->limit);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && pLimit && pLimit->offset) {
|
||||||
|
code = translateExpr(pCxt, (SNode**)&pLimit->offset);
|
||||||
|
}
|
||||||
|
if (TSDB_CODE_SUCCESS == code && (NULL != pLimit && NULL != pLimit->offset && pLimit->offset->datum.i < 0)) {
|
||||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
|
@ -3705,8 +3705,14 @@ static int32_t rewriteTailOptCreateLimit(SNode* pLimit, SNode* pOffset, SNode**
|
||||||
if (NULL == pLimitNode) {
|
if (NULL == pLimitNode) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
pLimitNode->limit = NULL == pLimit ? -1 : ((SValueNode*)pLimit)->datum.i;
|
code = nodesMakeValueNodeFromInt64(NULL == pLimit ? -1 : ((SValueNode*)pLimit)->datum.i, (SNode**)&pLimitNode->limit);
|
||||||
pLimitNode->offset = NULL == pOffset ? 0 : ((SValueNode*)pOffset)->datum.i;
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
code = nodesMakeValueNodeFromInt64(NULL == pOffset ? 0 : ((SValueNode*)pOffset)->datum.i, (SNode**)&pLimitNode->offset);
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
*pOutput = (SNode*)pLimitNode;
|
*pOutput = (SNode*)pLimitNode;
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1823,9 +1823,9 @@ static int32_t createAggPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren,
|
||||||
if (NULL == pAgg) {
|
if (NULL == pAgg) {
|
||||||
return terrno;
|
return terrno;
|
||||||
}
|
}
|
||||||
if (pAgg->node.pSlimit) {
|
if (pAgg->node.pSlimit && ((SLimitNode*)pAgg->node.pSlimit)->limit) {
|
||||||
pSubPlan->dynamicRowThreshold = true;
|
pSubPlan->dynamicRowThreshold = true;
|
||||||
pSubPlan->rowsThreshold = ((SLimitNode*)pAgg->node.pSlimit)->limit;
|
pSubPlan->rowsThreshold = ((SLimitNode*)pAgg->node.pSlimit)->limit->datum.i;
|
||||||
}
|
}
|
||||||
|
|
||||||
pAgg->mergeDataBlock = (GROUP_ACTION_KEEP == pAggLogicNode->node.groupAction ? false : true);
|
pAgg->mergeDataBlock = (GROUP_ACTION_KEEP == pAggLogicNode->node.groupAction ? false : true);
|
||||||
|
|
|
@ -133,8 +133,12 @@ static int32_t splCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pChild, SE
|
||||||
nodesDestroyNode((SNode*)pExchange);
|
nodesDestroyNode((SNode*)pExchange);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
((SLimitNode*)pChild->pLimit)->limit += ((SLimitNode*)pChild->pLimit)->offset;
|
if (((SLimitNode*)pChild->pLimit)->limit && ((SLimitNode*)pChild->pLimit)->offset) {
|
||||||
((SLimitNode*)pChild->pLimit)->offset = 0;
|
((SLimitNode*)pChild->pLimit)->limit->datum.i += ((SLimitNode*)pChild->pLimit)->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (((SLimitNode*)pChild->pLimit)->offset) {
|
||||||
|
((SLimitNode*)pChild->pLimit)->offset->datum.i = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*pOutput = pExchange;
|
*pOutput = pExchange;
|
||||||
|
@ -679,8 +683,12 @@ static int32_t stbSplCreateMergeNode(SSplitContext* pCxt, SLogicSubplan* pSubpla
|
||||||
if (TSDB_CODE_SUCCESS == code && NULL != pSplitNode->pLimit) {
|
if (TSDB_CODE_SUCCESS == code && NULL != pSplitNode->pLimit) {
|
||||||
pMerge->node.pLimit = NULL;
|
pMerge->node.pLimit = NULL;
|
||||||
code = nodesCloneNode(pSplitNode->pLimit, &pMerge->node.pLimit);
|
code = nodesCloneNode(pSplitNode->pLimit, &pMerge->node.pLimit);
|
||||||
((SLimitNode*)pSplitNode->pLimit)->limit += ((SLimitNode*)pSplitNode->pLimit)->offset;
|
if (((SLimitNode*)pSplitNode->pLimit)->limit && ((SLimitNode*)pSplitNode->pLimit)->offset) {
|
||||||
((SLimitNode*)pSplitNode->pLimit)->offset = 0;
|
((SLimitNode*)pSplitNode->pLimit)->limit->datum.i += ((SLimitNode*)pSplitNode->pLimit)->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (((SLimitNode*)pSplitNode->pLimit)->offset) {
|
||||||
|
((SLimitNode*)pSplitNode->pLimit)->offset->datum.i = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = stbSplRewriteFromMergeNode(pMerge, pSplitNode);
|
code = stbSplRewriteFromMergeNode(pMerge, pSplitNode);
|
||||||
|
@ -1427,8 +1435,12 @@ static int32_t stbSplGetSplitNodeForScan(SStableSplitInfo* pInfo, SLogicNode** p
|
||||||
if (NULL == (*pSplitNode)->pLimit) {
|
if (NULL == (*pSplitNode)->pLimit) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
((SLimitNode*)pInfo->pSplitNode->pLimit)->limit += ((SLimitNode*)pInfo->pSplitNode->pLimit)->offset;
|
if (((SLimitNode*)pInfo->pSplitNode->pLimit)->limit && ((SLimitNode*)pInfo->pSplitNode->pLimit)->offset) {
|
||||||
((SLimitNode*)pInfo->pSplitNode->pLimit)->offset = 0;
|
((SLimitNode*)pInfo->pSplitNode->pLimit)->limit->datum.i += ((SLimitNode*)pInfo->pSplitNode->pLimit)->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (((SLimitNode*)pInfo->pSplitNode->pLimit)->offset) {
|
||||||
|
((SLimitNode*)pInfo->pSplitNode->pLimit)->offset->datum.i = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
@ -1579,8 +1591,12 @@ static int32_t stbSplSplitMergeScanNode(SSplitContext* pCxt, SLogicSubplan* pSub
|
||||||
int32_t code = stbSplCreateMergeScanNode(pScan, &pMergeScan, &pMergeKeys);
|
int32_t code = stbSplCreateMergeScanNode(pScan, &pMergeScan, &pMergeKeys);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
if (NULL != pMergeScan->pLimit) {
|
if (NULL != pMergeScan->pLimit) {
|
||||||
((SLimitNode*)pMergeScan->pLimit)->limit += ((SLimitNode*)pMergeScan->pLimit)->offset;
|
if (((SLimitNode*)pMergeScan->pLimit)->limit && ((SLimitNode*)pMergeScan->pLimit)->offset) {
|
||||||
((SLimitNode*)pMergeScan->pLimit)->offset = 0;
|
((SLimitNode*)pMergeScan->pLimit)->limit->datum.i += ((SLimitNode*)pMergeScan->pLimit)->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (((SLimitNode*)pMergeScan->pLimit)->offset) {
|
||||||
|
((SLimitNode*)pMergeScan->pLimit)->offset->datum.i = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
code = stbSplCreateMergeNode(pCxt, pSubplan, (SLogicNode*)pScan, pMergeKeys, pMergeScan, groupSort, true);
|
code = stbSplCreateMergeNode(pCxt, pSubplan, (SLogicNode*)pScan, pMergeKeys, pMergeScan, groupSort, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,8 +592,12 @@ int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, b
|
||||||
if (pParent->pLimit && (cloneWhat & CLONE_LIMIT)) {
|
if (pParent->pLimit && (cloneWhat & CLONE_LIMIT)) {
|
||||||
code = nodesCloneNode(pParent->pLimit, (SNode**)&pLimit);
|
code = nodesCloneNode(pParent->pLimit, (SNode**)&pLimit);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
pLimit->limit += pLimit->offset;
|
if (pLimit->limit && pLimit->offset) {
|
||||||
pLimit->offset = 0;
|
pLimit->limit->datum.i += pLimit->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (pLimit->offset) {
|
||||||
|
pLimit->offset->datum.i = 0;
|
||||||
|
}
|
||||||
cloned = true;
|
cloned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,8 +605,12 @@ int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, b
|
||||||
if (pParent->pSlimit && (cloneWhat & CLONE_SLIMIT)) {
|
if (pParent->pSlimit && (cloneWhat & CLONE_SLIMIT)) {
|
||||||
code = nodesCloneNode(pParent->pSlimit, (SNode**)&pSlimit);
|
code = nodesCloneNode(pParent->pSlimit, (SNode**)&pSlimit);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
pSlimit->limit += pSlimit->offset;
|
if (pSlimit->limit && pSlimit->offset) {
|
||||||
pSlimit->offset = 0;
|
pSlimit->limit->datum.i += pSlimit->offset->datum.i;
|
||||||
|
}
|
||||||
|
if (pSlimit->offset) {
|
||||||
|
pSlimit->offset->datum.i = 0;
|
||||||
|
}
|
||||||
cloned = true;
|
cloned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ class TDTestCase:
|
||||||
tdSql.checkData(9, 1, '8')
|
tdSql.checkData(9, 1, '8')
|
||||||
tdSql.checkData(9, 2, 8)
|
tdSql.checkData(9, 2, 8)
|
||||||
|
|
||||||
tdSql.query('select * from d1.st order by ts limit 2;')
|
tdSql.query('select * from d1.st order by ts,pk limit 2;')
|
||||||
tdSql.checkRows(2)
|
tdSql.checkRows(2)
|
||||||
tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0))
|
tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0))
|
||||||
tdSql.checkData(0, 1, '1')
|
tdSql.checkData(0, 1, '1')
|
||||||
|
@ -286,7 +286,7 @@ class TDTestCase:
|
||||||
tdSql.checkData(9, 1, '8')
|
tdSql.checkData(9, 1, '8')
|
||||||
tdSql.checkData(9, 2, 8)
|
tdSql.checkData(9, 2, 8)
|
||||||
|
|
||||||
tdSql.query('select * from d2.st order by ts limit 2;')
|
tdSql.query('select * from d2.st order by ts,pk limit 2;')
|
||||||
tdSql.checkRows(2)
|
tdSql.checkRows(2)
|
||||||
tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0))
|
tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0))
|
||||||
tdSql.checkData(0, 1, '1')
|
tdSql.checkData(0, 1, '1')
|
||||||
|
|
Loading…
Reference in New Issue