enh: support ? in limit clause
This commit is contained in:
parent
2871a04107
commit
84c37d501a
|
@ -313,9 +313,9 @@ typedef struct SOrderByExprNode {
|
|||
} SOrderByExprNode;
|
||||
|
||||
typedef struct SLimitNode {
|
||||
ENodeType type; // QUERY_NODE_LIMIT
|
||||
int64_t limit;
|
||||
int64_t offset;
|
||||
ENodeType type; // QUERY_NODE_LIMIT
|
||||
SValueNode* limit;
|
||||
SValueNode* offset;
|
||||
} SLimitNode;
|
||||
|
||||
typedef struct SStateWindowNode {
|
||||
|
@ -681,6 +681,7 @@ int32_t nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal);
|
|||
int32_t nodesMakeValueNodeFromString(char* literal, SValueNode** ppValNode);
|
||||
int32_t nodesMakeValueNodeFromBool(bool b, SValueNode** ppValNode);
|
||||
int32_t nodesMakeValueNodeFromInt32(int32_t value, SNode** ppNode);
|
||||
int32_t nodesMakeValueNodeFromInt64(int64_t value, SNode** ppNode);
|
||||
|
||||
char* nodesGetFillModeString(EFillMode mode);
|
||||
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
|
||||
|
|
|
@ -237,6 +237,63 @@ int main(int argc, char** argv) {
|
|||
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) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
|
|
|
@ -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_BLANK_FORMAT);
|
||||
}
|
||||
if (NULL != pJoinNode->pJLimit) {
|
||||
if (NULL != pJoinNode->pJLimit && NULL != ((SLimitNode*)pJoinNode->pJLimit)->limit) {
|
||||
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);
|
||||
}
|
||||
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,
|
||||
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 getOffset(const SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->offset; }
|
||||
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 || NULL == ((SLimitNode*)pLimit)->offset) ? -1 : ((SLimitNode*)pLimit)->offset->datum.i; }
|
||||
static void releaseColInfoData(void* pCol);
|
||||
|
||||
void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
|
||||
|
|
|
@ -1185,7 +1185,7 @@ int32_t createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDow
|
|||
pInfo->tblTimeRange.skey = pJoinNode->timeRange.skey;
|
||||
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);
|
||||
|
||||
|
|
|
@ -3592,7 +3592,7 @@ int32_t mJoinInitWindowCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* p
|
|||
switch (pJoinNode->subType) {
|
||||
case JOIN_STYPE_ASOF:
|
||||
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->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);
|
||||
|
@ -3609,7 +3609,7 @@ int32_t mJoinInitWindowCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* p
|
|||
SWindowOffsetNode* pOffsetNode = (SWindowOffsetNode*)pJoinNode->pWindowOffset;
|
||||
SValueNode* pWinBegin = (SValueNode*)pOffsetNode->pStartOffset;
|
||||
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->winEndOffset = pWinEnd->datum.i;
|
||||
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;
|
||||
|
||||
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->build->eqRowLimit = pCtx->jLimit;
|
||||
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->multiRowsGrp = !((JOIN_STYPE_SEMI == pJoin->subType || JOIN_STYPE_ANTI == pJoin->subType) && NULL == pJoin->pPreFilter);
|
||||
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 {
|
||||
pTable->multiEqGrpRows = true;
|
||||
|
@ -1169,7 +1169,7 @@ static FORCE_INLINE SSDataBlock* mJoinRetrieveImpl(SMJoinOperatorInfo* pJoin, SM
|
|||
|
||||
static int32_t mJoinInitCtx(SMJoinOperatorInfo* pJoin, SSortMergeJoinPhysiNode* pJoinNode) {
|
||||
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->outBlkId = pJoinNode->node.pOutputDataBlockDesc->dataBlockId;
|
||||
|
||||
|
|
|
@ -84,9 +84,11 @@ int32_t createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortN
|
|||
|
||||
calcSortOperMaxTupleLength(pInfo, pSortNode->pSortKeys);
|
||||
pInfo->maxRows = -1;
|
||||
if (pSortNode->node.pLimit) {
|
||||
if (pSortNode->node.pLimit && ((SLimitNode*)pSortNode->node.pLimit)->limit) {
|
||||
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 =
|
||||
|
|
|
@ -1417,15 +1417,15 @@ int32_t createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode
|
|||
pInfo->interval = interval;
|
||||
pInfo->twAggSup = as;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -864,7 +864,11 @@ SSortMergeJoinPhysiNode* createDummySortMergeJoinPhysiNode(SJoinTestParam* param
|
|||
SLimitNode* limitNode = NULL;
|
||||
code = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1418,6 +1418,7 @@ SNode* qptMakeExprNode(SNode** ppNode) {
|
|||
|
||||
SNode* qptMakeLimitNode(SNode** ppNode) {
|
||||
SNode* pNode = NULL;
|
||||
int32_t code = 0;
|
||||
if (QPT_NCORRECT_LOW_PROB()) {
|
||||
return qptMakeRandNode(&pNode);
|
||||
}
|
||||
|
@ -1429,15 +1430,27 @@ SNode* qptMakeLimitNode(SNode** ppNode) {
|
|||
|
||||
if (!qptCtx.param.correctExpected) {
|
||||
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) {
|
||||
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 {
|
||||
pLimit->limit = taosRand();
|
||||
pLimit->limit->datum.i = taosRand();
|
||||
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) { \
|
||||
break; \
|
||||
} \
|
||||
int32_t code = nodesCloneNode((pSrc)->fldname, &((pDst)->fldname)); \
|
||||
int32_t code = nodesCloneNode((SNode*)(pSrc)->fldname, (SNode**)&((pDst)->fldname)); \
|
||||
if (NULL == (pDst)->fldname) { \
|
||||
return code; \
|
||||
} \
|
||||
|
@ -346,8 +346,8 @@ static int32_t orderByExprNodeCopy(const SOrderByExprNode* pSrc, SOrderByExprNod
|
|||
}
|
||||
|
||||
static int32_t limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
|
||||
COPY_SCALAR_FIELD(limit);
|
||||
COPY_SCALAR_FIELD(offset);
|
||||
CLONE_NODE_FIELD(limit);
|
||||
CLONE_NODE_FIELD(offset);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -4933,9 +4933,9 @@ static const char* jkLimitOffset = "Offset";
|
|||
static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
||||
|
||||
int32_t code = tjsonAddIntegerToObject(pJson, jkLimitLimit, pNode->limit);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddIntegerToObject(pJson, jkLimitOffset, pNode->offset);
|
||||
int32_t code = tjsonAddObject(pJson, jkLimitLimit, nodeToJson, pNode->limit);
|
||||
if (TSDB_CODE_SUCCESS == code && pNode->offset) {
|
||||
code = tjsonAddObject(pJson, jkLimitOffset, nodeToJson, pNode->offset);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -4944,9 +4944,9 @@ static int32_t limitNodeToJson(const void* pObj, SJson* pJson) {
|
|||
static int32_t jsonToLimitNode(const SJson* pJson, void* 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) {
|
||||
code = tjsonGetBigIntValue(pJson, jkLimitOffset, &pNode->offset);
|
||||
code = jsonToNodeObject(pJson, jkLimitOffset, (SNode**)&pNode->offset);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
|
|
@ -1246,9 +1246,9 @@ enum { LIMIT_CODE_LIMIT = 1, LIMIT_CODE_OFFSET };
|
|||
static int32_t limitNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||
const SLimitNode* pNode = (const SLimitNode*)pObj;
|
||||
|
||||
int32_t code = tlvEncodeI64(pEncoder, LIMIT_CODE_LIMIT, pNode->limit);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeI64(pEncoder, LIMIT_CODE_OFFSET, pNode->offset);
|
||||
int32_t code = tlvEncodeObj(pEncoder, LIMIT_CODE_LIMIT, nodeToMsg, pNode->limit);
|
||||
if (TSDB_CODE_SUCCESS == code && pNode->offset) {
|
||||
code = tlvEncodeObj(pEncoder, LIMIT_CODE_OFFSET, nodeToMsg, pNode->offset);
|
||||
}
|
||||
|
||||
return code;
|
||||
|
@ -1262,10 +1262,10 @@ static int32_t msgToLimitNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
tlvForEach(pDecoder, pTlv, code) {
|
||||
switch (pTlv->type) {
|
||||
case LIMIT_CODE_LIMIT:
|
||||
code = tlvDecodeI64(pTlv, &pNode->limit);
|
||||
code = msgToNodeFromTlv(pTlv, (void**)&pNode->limit);
|
||||
break;
|
||||
case LIMIT_CODE_OFFSET:
|
||||
code = tlvDecodeI64(pTlv, &pNode->offset);
|
||||
code = msgToNodeFromTlv(pTlv, (void**)&pNode->offset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1106,8 +1106,12 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
case QUERY_NODE_ORDER_BY_EXPR:
|
||||
nodesDestroyNode(((SOrderByExprNode*)pNode)->pExpr);
|
||||
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;
|
||||
}
|
||||
case QUERY_NODE_STATE_WINDOW: {
|
||||
SStateWindowNode* pState = (SStateWindowNode*)pNode;
|
||||
nodesDestroyNode(pState->pCol);
|
||||
|
@ -3097,6 +3101,25 @@ int32_t nodesMakeValueNodeFromInt32(int32_t value, SNode** ppNode) {
|
|||
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) {
|
||||
return (QUERY_NODE_COLUMN == nodeType(pNode)) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]) &&
|
||||
(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* pJoinCond);
|
||||
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* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode* pGap);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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_PLUS NK_FLOAT(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &B); }
|
||||
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) ::= NK_QUESTION(B). { A = createPlaceholderValueNode(pCxt, &B); }
|
||||
|
||||
|
||||
%type literal_list { SNodeList* }
|
||||
%destructor literal_list { nodesDestroyList($$); }
|
||||
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) ::= 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(A) ::=
|
||||
|
@ -1660,14 +1665,14 @@ order_by_clause_opt(A) ::= .
|
|||
order_by_clause_opt(A) ::= ORDER BY sort_specification_list(B). { A = B; }
|
||||
|
||||
slimit_clause_opt(A) ::= . { A = NULL; }
|
||||
slimit_clause_opt(A) ::= SLIMIT NK_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 NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
||||
slimit_clause_opt(A) ::= SLIMIT unsigned_integer(B). { A = createLimitNode(pCxt, B, NULL); }
|
||||
slimit_clause_opt(A) ::= SLIMIT unsigned_integer(B) SOFFSET unsigned_integer(C). { 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) ::= LIMIT NK_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 NK_INTEGER(C) NK_COMMA NK_INTEGER(B). { A = createLimitNode(pCxt, &B, &C); }
|
||||
limit_clause_opt(A) ::= LIMIT unsigned_integer(B). { A = createLimitNode(pCxt, B, NULL); }
|
||||
limit_clause_opt(A) ::= LIMIT unsigned_integer(B) OFFSET unsigned_integer(C). { 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(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); }
|
||||
|
|
|
@ -1287,14 +1287,14 @@ _err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) {
|
||||
SNode* createLimitNode(SAstCreateContext* pCxt, SNode* pLimit, SNode* pOffset) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SLimitNode* limitNode = NULL;
|
||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
||||
CHECK_MAKE_NODE(limitNode);
|
||||
limitNode->limit = taosStr2Int64(pLimit->z, NULL, 10);
|
||||
limitNode->limit = (SValueNode*)pLimit;
|
||||
if (NULL != pOffset) {
|
||||
limitNode->offset = taosStr2Int64(pOffset->z, NULL, 10);
|
||||
limitNode->offset = (SValueNode*)pOffset;
|
||||
}
|
||||
return (SNode*)limitNode;
|
||||
_err:
|
||||
|
|
|
@ -4729,16 +4729,20 @@ static int32_t translateJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoin
|
|||
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) {
|
||||
return buildInvalidOperationMsgExt(&pCxt->msgBuf, "JLIMIT not supported for %s join",
|
||||
getFullJoinTypeString(type, *pSType));
|
||||
}
|
||||
SLimitNode* pJLimit = (SLimitNode*)pJoinTable->pJLimit;
|
||||
if (pJLimit->limit > JOIN_JLIMIT_MAX_VALUE || pJLimit->limit < 0) {
|
||||
code = translateExpr(pCxt, &pJoinTable->pJLimit);
|
||||
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]");
|
||||
}
|
||||
if (0 == pJLimit->limit) {
|
||||
if (0 == pJLimit->limit->datum.i) {
|
||||
pCurrSmt->isEmptyResult = true;
|
||||
}
|
||||
}
|
||||
|
@ -6994,16 +6998,22 @@ static int32_t translateFrom(STranslateContext* pCxt, SNode** pTable) {
|
|||
}
|
||||
|
||||
static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if ((NULL != pSelect->pLimit && pSelect->pLimit->offset < 0) ||
|
||||
(NULL != pSelect->pSlimit && pSelect->pSlimit->offset < 0)) {
|
||||
int32_t code = translateExpr(pCxt, (SNode**)&pSelect->pLimit);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateExpr(pCxt, (SNode**)&pSelect->pSlimit);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 TSDB_CODE_SUCCESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* pTable, SNode** pPrimaryKey) {
|
||||
|
@ -7482,7 +7492,7 @@ static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pS
|
|||
}
|
||||
|
||||
static int32_t checkSetOperLimit(STranslateContext* pCxt, SLimitNode* pLimit) {
|
||||
if ((NULL != pLimit && pLimit->offset < 0)) {
|
||||
if ((NULL != pLimit && NULL != pLimit->offset && pLimit->offset->datum.i < 0)) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
|
|
@ -3705,8 +3705,14 @@ static int32_t rewriteTailOptCreateLimit(SNode* pLimit, SNode* pOffset, SNode**
|
|||
if (NULL == pLimitNode) {
|
||||
return code;
|
||||
}
|
||||
pLimitNode->limit = NULL == pLimit ? -1 : ((SValueNode*)pLimit)->datum.i;
|
||||
pLimitNode->offset = NULL == pOffset ? 0 : ((SValueNode*)pOffset)->datum.i;
|
||||
code = nodesMakeValueNodeFromInt64(NULL == pLimit ? -1 : ((SValueNode*)pLimit)->datum.i, (SNode**)&pLimitNode->limit);
|
||||
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;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1823,9 +1823,9 @@ static int32_t createAggPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren,
|
|||
if (NULL == pAgg) {
|
||||
return terrno;
|
||||
}
|
||||
if (pAgg->node.pSlimit) {
|
||||
if (pAgg->node.pSlimit && ((SLimitNode*)pAgg->node.pSlimit)->limit) {
|
||||
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);
|
||||
|
|
|
@ -133,8 +133,12 @@ static int32_t splCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pChild, SE
|
|||
nodesDestroyNode((SNode*)pExchange);
|
||||
return code;
|
||||
}
|
||||
((SLimitNode*)pChild->pLimit)->limit += ((SLimitNode*)pChild->pLimit)->offset;
|
||||
((SLimitNode*)pChild->pLimit)->offset = 0;
|
||||
if (((SLimitNode*)pChild->pLimit)->limit && ((SLimitNode*)pChild->pLimit)->offset) {
|
||||
((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;
|
||||
|
@ -679,8 +683,12 @@ static int32_t stbSplCreateMergeNode(SSplitContext* pCxt, SLogicSubplan* pSubpla
|
|||
if (TSDB_CODE_SUCCESS == code && NULL != pSplitNode->pLimit) {
|
||||
pMerge->node.pLimit = NULL;
|
||||
code = nodesCloneNode(pSplitNode->pLimit, &pMerge->node.pLimit);
|
||||
((SLimitNode*)pSplitNode->pLimit)->limit += ((SLimitNode*)pSplitNode->pLimit)->offset;
|
||||
((SLimitNode*)pSplitNode->pLimit)->offset = 0;
|
||||
if (((SLimitNode*)pSplitNode->pLimit)->limit && ((SLimitNode*)pSplitNode->pLimit)->offset) {
|
||||
((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) {
|
||||
code = stbSplRewriteFromMergeNode(pMerge, pSplitNode);
|
||||
|
@ -1427,8 +1435,12 @@ static int32_t stbSplGetSplitNodeForScan(SStableSplitInfo* pInfo, SLogicNode** p
|
|||
if (NULL == (*pSplitNode)->pLimit) {
|
||||
return code;
|
||||
}
|
||||
((SLimitNode*)pInfo->pSplitNode->pLimit)->limit += ((SLimitNode*)pInfo->pSplitNode->pLimit)->offset;
|
||||
((SLimitNode*)pInfo->pSplitNode->pLimit)->offset = 0;
|
||||
if (((SLimitNode*)pInfo->pSplitNode->pLimit)->limit && ((SLimitNode*)pInfo->pSplitNode->pLimit)->offset) {
|
||||
((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;
|
||||
|
@ -1579,8 +1591,12 @@ static int32_t stbSplSplitMergeScanNode(SSplitContext* pCxt, SLogicSubplan* pSub
|
|||
int32_t code = stbSplCreateMergeScanNode(pScan, &pMergeScan, &pMergeKeys);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (NULL != pMergeScan->pLimit) {
|
||||
((SLimitNode*)pMergeScan->pLimit)->limit += ((SLimitNode*)pMergeScan->pLimit)->offset;
|
||||
((SLimitNode*)pMergeScan->pLimit)->offset = 0;
|
||||
if (((SLimitNode*)pMergeScan->pLimit)->limit && ((SLimitNode*)pMergeScan->pLimit)->offset) {
|
||||
((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);
|
||||
}
|
||||
|
|
|
@ -592,8 +592,12 @@ int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, b
|
|||
if (pParent->pLimit && (cloneWhat & CLONE_LIMIT)) {
|
||||
code = nodesCloneNode(pParent->pLimit, (SNode**)&pLimit);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pLimit->limit += pLimit->offset;
|
||||
pLimit->offset = 0;
|
||||
if (pLimit->limit && pLimit->offset) {
|
||||
pLimit->limit->datum.i += pLimit->offset->datum.i;
|
||||
}
|
||||
if (pLimit->offset) {
|
||||
pLimit->offset->datum.i = 0;
|
||||
}
|
||||
cloned = true;
|
||||
}
|
||||
}
|
||||
|
@ -601,8 +605,12 @@ int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, b
|
|||
if (pParent->pSlimit && (cloneWhat & CLONE_SLIMIT)) {
|
||||
code = nodesCloneNode(pParent->pSlimit, (SNode**)&pSlimit);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pSlimit->limit += pSlimit->offset;
|
||||
pSlimit->offset = 0;
|
||||
if (pSlimit->limit && pSlimit->offset) {
|
||||
pSlimit->limit->datum.i += pSlimit->offset->datum.i;
|
||||
}
|
||||
if (pSlimit->offset) {
|
||||
pSlimit->offset->datum.i = 0;
|
||||
}
|
||||
cloned = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue