Merge remote-tracking branch 'origin/3.0' into fix/mnode
This commit is contained in:
commit
2f32e122af
|
@ -30,7 +30,7 @@ typedef uint64_t TDRowVerT;
|
|||
typedef int16_t col_id_t;
|
||||
typedef int8_t col_type_t;
|
||||
typedef int32_t col_bytes_t;
|
||||
typedef uint16_t schema_ver_t;
|
||||
typedef int32_t schema_ver_t;
|
||||
typedef int32_t func_id_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
|
|
@ -146,7 +146,8 @@ bool fmIsBuiltinFunc(const char* pFunc);
|
|||
|
||||
bool fmIsAggFunc(int32_t funcId);
|
||||
bool fmIsScalarFunc(int32_t funcId);
|
||||
bool fmIsNonstandardSQLFunc(int32_t funcId);
|
||||
bool fmIsVectorFunc(int32_t funcId);
|
||||
bool fmIsIndefiniteRowsFunc(int32_t funcId);
|
||||
bool fmIsStringFunc(int32_t funcId);
|
||||
bool fmIsDatetimeFunc(int32_t funcId);
|
||||
bool fmIsSelectFunc(int32_t funcId);
|
||||
|
|
|
@ -59,10 +59,10 @@ extern "C" {
|
|||
for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); \
|
||||
(NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext)
|
||||
|
||||
#define DESTORY_LIST(list) \
|
||||
do { \
|
||||
nodesDestroyList(list); \
|
||||
list = NULL; \
|
||||
#define DESTORY_LIST(list) \
|
||||
do { \
|
||||
nodesDestroyList((list)); \
|
||||
(list) = NULL; \
|
||||
} while (0)
|
||||
|
||||
typedef enum ENodeType {
|
||||
|
@ -96,6 +96,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_EXPLAIN_OPTIONS,
|
||||
QUERY_NODE_STREAM_OPTIONS,
|
||||
QUERY_NODE_TOPIC_OPTIONS,
|
||||
QUERY_NODE_LEFT_VALUE,
|
||||
|
||||
// Statement nodes are used in parser and planner module.
|
||||
QUERY_NODE_SET_OPERATOR,
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef struct SScanLogicNode {
|
|||
int64_t sliding;
|
||||
int8_t intervalUnit;
|
||||
int8_t slidingUnit;
|
||||
SNode* pTagCond;
|
||||
} SScanLogicNode;
|
||||
|
||||
typedef struct SJoinLogicNode {
|
||||
|
@ -343,6 +344,7 @@ typedef struct SSubplan {
|
|||
SNodeList* pParents; // the data destination subplan, get data from current subplan
|
||||
SPhysiNode* pNode; // physical plan of current subplan
|
||||
SDataSinkNode* pDataSink; // data of the subplan flow into the datasink
|
||||
SNode* pTagCond;
|
||||
} SSubplan;
|
||||
|
||||
typedef enum EExplainMode { EXPLAIN_MODE_DISABLE = 1, EXPLAIN_MODE_STATIC, EXPLAIN_MODE_ANALYZE } EExplainMode;
|
||||
|
|
|
@ -81,6 +81,7 @@ typedef struct SValueNode {
|
|||
char* literal;
|
||||
bool isDuration;
|
||||
bool translate;
|
||||
bool notReserved;
|
||||
int16_t placeholderNo;
|
||||
union {
|
||||
bool b;
|
||||
|
@ -93,6 +94,10 @@ typedef struct SValueNode {
|
|||
char unit;
|
||||
} SValueNode;
|
||||
|
||||
typedef struct SLeftValueNode {
|
||||
ENodeType type;
|
||||
} SLeftValueNode;
|
||||
|
||||
typedef struct SOperatorNode {
|
||||
SExprNode node; // QUERY_NODE_OPERATOR
|
||||
EOperatorType opType;
|
||||
|
@ -236,7 +241,7 @@ typedef struct SSelectStmt {
|
|||
bool isTimeOrderQuery;
|
||||
bool hasAggFuncs;
|
||||
bool hasRepeatScanFuncs;
|
||||
bool hasNonstdSQLFunc;
|
||||
bool hasIndefiniteRowsFunc;
|
||||
} SSelectStmt;
|
||||
|
||||
typedef enum ESetOperatorType { SET_OP_TYPE_UNION_ALL = 1, SET_OP_TYPE_UNION } ESetOperatorType;
|
||||
|
|
|
@ -253,6 +253,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_MND_TRANS_INVALID_STAGE TAOS_DEF_ERROR_CODE(0, 0x03D2)
|
||||
#define TSDB_CODE_MND_TRANS_CONFLICT TAOS_DEF_ERROR_CODE(0, 0x03D3)
|
||||
#define TSDB_CODE_MND_TRANS_UNKNOW_ERROR TAOS_DEF_ERROR_CODE(0, 0x03D4)
|
||||
#define TSDB_CODE_MND_TRANS_CLOG_IS_NULL TAOS_DEF_ERROR_CODE(0, 0x03D5)
|
||||
|
||||
// mnode-mq
|
||||
#define TSDB_CODE_MND_TOPIC_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x03E0)
|
||||
|
@ -638,6 +639,7 @@ int32_t* taosGetErrno();
|
|||
#define TSDB_CODE_PAR_NOT_ALLOWED_FUNC TAOS_DEF_ERROR_CODE(0, 0x264F)
|
||||
#define TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY TAOS_DEF_ERROR_CODE(0, 0x2650)
|
||||
#define TSDB_CODE_PAR_INVALID_DROP_COL TAOS_DEF_ERROR_CODE(0, 0x2651)
|
||||
#define TSDB_CODE_PAR_INVALID_COL_JSON TAOS_DEF_ERROR_CODE(0, 0x2652)
|
||||
|
||||
//planner
|
||||
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
||||
|
|
|
@ -132,6 +132,7 @@ typedef enum EOperatorType {
|
|||
OP_TYPE_MOD,
|
||||
// unary arithmetic operator
|
||||
OP_TYPE_MINUS,
|
||||
OP_TYPE_ASSIGN,
|
||||
|
||||
// bit operator
|
||||
OP_TYPE_BIT_AND,
|
||||
|
@ -233,6 +234,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_MAX_TAG_CONDITIONS 1024
|
||||
|
||||
#define TSDB_MAX_JSON_TAG_LEN 16384
|
||||
#define TSDB_MAX_JSON_KEY_LEN 256
|
||||
|
||||
#define TSDB_AUTH_LEN 16
|
||||
#define TSDB_PASSWORD_LEN 32
|
||||
|
|
|
@ -82,7 +82,7 @@ typedef struct {
|
|||
do { \
|
||||
SEncoder coder = {0}; \
|
||||
tEncoderInit(&coder, NULL, 0); \
|
||||
if ((E)(&coder, S) == 0) { \
|
||||
if ((E)(&coder, S) >= 0) { \
|
||||
SIZE = coder.pos; \
|
||||
RET = 0; \
|
||||
} else { \
|
||||
|
|
|
@ -866,8 +866,7 @@ static char* parseTagDatatoJson(void* p) {
|
|||
if (j == 0) {
|
||||
if (*val == TSDB_DATA_TYPE_NULL) {
|
||||
string = taosMemoryCalloc(1, 8);
|
||||
sprintf(varDataVal(string), "%s", TSDB_DATA_NULL_STR_L);
|
||||
varDataSetLen(string, strlen(varDataVal(string)));
|
||||
sprintf(string, "%s", TSDB_DATA_NULL_STR_L);
|
||||
goto end;
|
||||
}
|
||||
continue;
|
||||
|
@ -1003,7 +1002,7 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t numOfRows, int
|
|||
length = 0;
|
||||
}
|
||||
varDataSetLen(dst, length + CHAR_BYTES * 2);
|
||||
*(char*)(varDataVal(dst), length + CHAR_BYTES) = '\"';
|
||||
*(char*)POINTER_SHIFT(varDataVal(dst), length + CHAR_BYTES) = '\"';
|
||||
} else if (jsonInnerType == TSDB_DATA_TYPE_DOUBLE) {
|
||||
double jsonVd = *(double*)(jsonInnerData);
|
||||
sprintf(varDataVal(dst), "%.9lf", jsonVd);
|
||||
|
|
|
@ -1538,7 +1538,7 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SArray* pDataBlocks
|
|||
int32_t msgLen = sizeof(SSubmitReq);
|
||||
int32_t numOfBlks = 0;
|
||||
SRowBuilder rb = {0};
|
||||
tdSRowInit(&rb, 0); // TODO: use the latest version
|
||||
tdSRowInit(&rb, pTSchema->version); // TODO: use the latest version
|
||||
|
||||
for (int32_t i = 0; i < sz; ++i) {
|
||||
SSDataBlock* pDataBlock = taosArrayGet(pDataBlocks, i);
|
||||
|
|
|
@ -3817,7 +3817,7 @@ int tDecodeSVCreateStbReq(SDecoder *pCoder, SVCreateStbReq *pReq) {
|
|||
|
||||
STSchema *tdGetSTSChemaFromSSChema(SSchema **pSchema, int32_t nCols) {
|
||||
STSchemaBuilder schemaBuilder = {0};
|
||||
if (tdInitTSchemaBuilder(&schemaBuilder, 0) < 0) {
|
||||
if (tdInitTSchemaBuilder(&schemaBuilder, 1) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -924,7 +924,7 @@ void tdSRowPrint(STSRow *row, STSchema *pSchema, const char *tag) {
|
|||
STSRowIter iter = {0};
|
||||
tdSTSRowIterInit(&iter, pSchema);
|
||||
tdSTSRowIterReset(&iter, row);
|
||||
printf("%s >>>", tag);
|
||||
printf("%s >>>type:%d,sver:%d ", tag, (int32_t)TD_ROW_TYPE(row), (int32_t)TD_ROW_SVER(row));
|
||||
for (int i = 0; i < pSchema->numOfCols; ++i) {
|
||||
STColumn *stCol = pSchema->columns + i;
|
||||
SCellVal sVal = {255, NULL};
|
||||
|
|
|
@ -25,7 +25,6 @@ extern "C" {
|
|||
int32_t mndInitSync(SMnode *pMnode);
|
||||
void mndCleanupSync(SMnode *pMnode);
|
||||
bool mndIsMaster(SMnode *pMnode);
|
||||
bool mndIsRestored(SMnode *pMnode);
|
||||
int32_t mndSyncPropose(SMnode *pMnode, SSdbRaw *pRaw);
|
||||
void mndSyncStart(SMnode *pMnode);
|
||||
void mndSyncStop(SMnode *pMnode);
|
||||
|
|
|
@ -35,7 +35,7 @@ int32_t mndDropTopicByDB(SMnode *pMnode, STrans *pTrans, SDbObj *pDb);
|
|||
|
||||
const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]);
|
||||
|
||||
int32_t mndSetTopicRedoLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic);
|
||||
int32_t mndSetTopicCommitLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -419,7 +419,7 @@ static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) {
|
|||
SMqTopicObj topicObj = {0};
|
||||
memcpy(&topicObj, pTopic, sizeof(SMqTopicObj));
|
||||
topicObj.refConsumerCnt = pTopic->refConsumerCnt + 1;
|
||||
if (mndSetTopicRedoLogs(pMnode, pTrans, &topicObj) != 0) goto SUBSCRIBE_OVER;
|
||||
if (mndSetTopicCommitLogs(pMnode, pTrans, &topicObj) != 0) goto SUBSCRIBE_OVER;
|
||||
|
||||
mndReleaseTopic(pMnode, pTopic);
|
||||
}
|
||||
|
|
|
@ -448,13 +448,13 @@ static int32_t mndCreateDnode(SMnode *pMnode, SRpcMsg *pReq, SCreateDnodeReq *pC
|
|||
}
|
||||
mDebug("trans:%d, used to create dnode:%s", pTrans->id, dnodeObj.ep);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndDnodeActionEncode(&dnodeObj);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndDnodeActionEncode(&dnodeObj);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -524,13 +524,13 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode) {
|
|||
}
|
||||
mDebug("trans:%d, used to drop dnode:%d", pTrans->id, pDnode->id);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndDnodeActionEncode(pDnode);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndDnodeActionEncode(pDnode);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPED);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
|
|
@ -153,6 +153,7 @@ int32_t mndCreateOffsets(STrans *pTrans, const char *cgroup, const char *topicNa
|
|||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY);
|
||||
// commit log or redo log?
|
||||
if (mndTransAppendRedolog(pTrans, pOffsetRaw) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -188,7 +189,7 @@ static int32_t mndProcessCommitOffsetReq(SRpcMsg *pMsg) {
|
|||
pOffsetObj->offset = pOffset->offset;
|
||||
SSdbRaw *pOffsetRaw = mndOffsetActionEncode(pOffsetObj);
|
||||
sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY);
|
||||
mndTransAppendRedolog(pTrans, pOffsetRaw);
|
||||
mndTransAppendCommitlog(pTrans, pOffsetRaw);
|
||||
if (create) {
|
||||
taosMemoryFree(pOffsetObj);
|
||||
} else {
|
||||
|
|
|
@ -743,9 +743,7 @@ static int32_t mndCreateStb(SMnode *pMnode, SRpcMsg *pReq, SMCreateStbReq *pCrea
|
|||
|
||||
mDebug("trans:%d, used to create stb:%s", pTrans->id, pCreate->name);
|
||||
|
||||
if (mndBuildStbFromReq(pMnode, &stbObj, pCreate, pDb) != 0) {
|
||||
goto _OVER;
|
||||
}
|
||||
if (mndBuildStbFromReq(pMnode, &stbObj, pCreate, pDb) != 0) goto _OVER;
|
||||
|
||||
if (mndAddStbToTrans(pMnode, pTrans, pDb, &stbObj) < 0) goto _OVER;
|
||||
|
||||
|
|
|
@ -279,13 +279,13 @@ int32_t mndAddStreamToTrans(SMnode *pMnode, SStreamObj *pStream, const char *ast
|
|||
}
|
||||
mDebug("trans:%d, used to create stream:%s", pTrans->id, pStream->name);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndStreamActionEncode(pStream);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndStreamActionEncode(pStream);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -479,7 +479,7 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu
|
|||
SMqTopicObj topicObj = {0};
|
||||
memcpy(&topicObj, pTopic, sizeof(SMqTopicObj));
|
||||
topicObj.refConsumerCnt = pTopic->refConsumerCnt - consumerNum;
|
||||
if (mndSetTopicRedoLogs(pMnode, pTrans, &topicObj) != 0) goto REB_FAIL;
|
||||
if (mndSetTopicCommitLogs(pMnode, pTrans, &topicObj) != 0) goto REB_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,7 +156,6 @@ void mndSyncStop(SMnode *pMnode) {}
|
|||
bool mndIsMaster(SMnode *pMnode) {
|
||||
SSyncMgmt *pMgmt = &pMnode->syncMgmt;
|
||||
pMgmt->state = syncGetMyRole(pMgmt->sync);
|
||||
return pMgmt->state == TAOS_SYNC_STATE_LEADER;
|
||||
}
|
||||
|
||||
bool mndIsRestored(SMnode *pMnode) { return pMnode->syncMgmt.restored; }
|
||||
return (pMgmt->state == TAOS_SYNC_STATE_LEADER) && (pMnode->syncMgmt.restored);
|
||||
}
|
||||
|
|
|
@ -386,14 +386,14 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
|
|||
}
|
||||
mDebug("trans:%d, used to create topic:%s", pTrans->id, pCreate->name);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndTopicActionEncode(&topicObj);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndTopicActionEncode(&topicObj);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
taosMemoryFreeClear(topicObj.physicalPlan);
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -473,13 +473,13 @@ CREATE_TOPIC_OVER:
|
|||
}
|
||||
|
||||
static int32_t mndDropTopic(SMnode *pMnode, STrans *pTrans, SRpcMsg *pReq, SMqTopicObj *pTopic) {
|
||||
SSdbRaw *pRedoRaw = mndTopicActionEncode(pTopic);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndTopicActionEncode(pTopic);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPED);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -627,11 +627,11 @@ static int32_t mndRetrieveTopic(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl
|
|||
return numOfRows;
|
||||
}
|
||||
|
||||
int32_t mndSetTopicRedoLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic) {
|
||||
SSdbRaw *pRedoRaw = mndTopicActionEncode(pTopic);
|
||||
if (pRedoRaw == NULL) return -1;
|
||||
if (mndTransAppendCommitlog(pTrans, pRedoRaw) != 0) return -1;
|
||||
if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY) != 0) return -1;
|
||||
int32_t mndSetTopicCommitLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic) {
|
||||
SSdbRaw *pCommitRaw = mndTopicActionEncode(pTopic);
|
||||
if (pCommitRaw == NULL) return -1;
|
||||
if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1;
|
||||
if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -761,6 +761,12 @@ int32_t mndTransPrepare(SMnode *pMnode, STrans *pTrans) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (taosArrayGetSize(pTrans->commitLogs) <= 0) {
|
||||
terrno = TSDB_CODE_MND_TRANS_CLOG_IS_NULL;
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
mDebug("trans:%d, prepare transaction", pTrans->id);
|
||||
if (mndTransSync(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -1073,6 +1079,8 @@ static bool mndTransPerformRedoLogStage(SMnode *pMnode, STrans *pTrans) {
|
|||
}
|
||||
|
||||
static bool mndTransPerformRedoActionStage(SMnode *pMnode, STrans *pTrans) {
|
||||
if (!mndIsMaster(pMnode)) return false;
|
||||
|
||||
bool continueExec = true;
|
||||
int32_t code = mndTransExecuteRedoActions(pMnode, pTrans);
|
||||
|
||||
|
@ -1162,6 +1170,8 @@ static bool mndTransPerformUndoLogStage(SMnode *pMnode, STrans *pTrans) {
|
|||
}
|
||||
|
||||
static bool mndTransPerformUndoActionStage(SMnode *pMnode, STrans *pTrans) {
|
||||
if (!mndIsMaster(pMnode)) return false;
|
||||
|
||||
bool continueExec = true;
|
||||
int32_t code = mndTransExecuteUndoActions(pMnode, pTrans);
|
||||
|
||||
|
|
|
@ -272,13 +272,13 @@ static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate
|
|||
}
|
||||
mDebug("trans:%d, used to create user:%s", pTrans->id, pCreate->user);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndUserActionEncode(&userObj);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndUserActionEncode(&userObj);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to commit redo log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -352,13 +352,13 @@ static int32_t mndAlterUser(SMnode *pMnode, SUserObj *pOld, SUserObj *pNew, SRpc
|
|||
}
|
||||
mDebug("trans:%d, used to alter user:%s", pTrans->id, pOld->user);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndUserActionEncode(pNew);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndUserActionEncode(pNew);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
@ -559,13 +559,13 @@ static int32_t mndDropUser(SMnode *pMnode, SRpcMsg *pReq, SUserObj *pUser) {
|
|||
}
|
||||
mDebug("trans:%d, used to drop user:%s", pTrans->id, pUser->user);
|
||||
|
||||
SSdbRaw *pRedoRaw = mndUserActionEncode(pUser);
|
||||
if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) {
|
||||
mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr());
|
||||
SSdbRaw *pCommitRaw = mndUserActionEncode(pUser);
|
||||
if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) {
|
||||
mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr());
|
||||
mndTransDrop(pTrans);
|
||||
return -1;
|
||||
}
|
||||
sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPED);
|
||||
sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED);
|
||||
|
||||
if (mndTransPrepare(pMnode, pTrans) != 0) {
|
||||
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
|
||||
|
|
|
@ -86,7 +86,6 @@ static void *mndThreadFp(void *param) {
|
|||
lastTime++;
|
||||
taosMsleep(100);
|
||||
if (pMnode->stopped) break;
|
||||
if (!mndIsMaster(pMnode) || !mndIsRestored(pMnode)) continue;
|
||||
|
||||
if (lastTime % (tsTransPullupInterval * 10) == 0) {
|
||||
mndPullupTrans(pMnode);
|
||||
|
@ -446,7 +445,8 @@ int32_t mndProcessMsg(SRpcMsg *pMsg) {
|
|||
mTrace("msg:%p, will be processed, type:%s app:%p", pMsg, TMSG_INFO(pMsg->msgType), ahandle);
|
||||
|
||||
if (IsReq(pMsg)) {
|
||||
if (!mndIsMaster(pMnode) || !mndIsRestored(pMnode)) {
|
||||
if (!mndIsMaster(pMnode) && pMsg->msgType != TDMT_MND_TRANS_TIMER && pMsg->msgType != TDMT_MND_MQ_TIMER &&
|
||||
pMsg->msgType != TDMT_MND_TELEM_TIMER) {
|
||||
terrno = TSDB_CODE_APP_NOT_READY;
|
||||
mDebug("msg:%p, failed to process since %s, app:%p", pMsg, terrstr(), ahandle);
|
||||
return -1;
|
||||
|
@ -506,7 +506,7 @@ int64_t mndGenerateUid(char *name, int32_t len) {
|
|||
|
||||
int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgroupInfo *pVgroupInfo,
|
||||
SMonGrantInfo *pGrantInfo) {
|
||||
if (!mndIsMaster(pMnode) || !mndIsRestored(pMnode)) return -1;
|
||||
if (!mndIsMaster(pMnode)) return -1;
|
||||
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
int64_t ms = taosGetTimestampMs();
|
||||
|
|
|
@ -48,7 +48,6 @@ target_sources(
|
|||
# tq
|
||||
"src/tq/tq.c"
|
||||
"src/tq/tqCommit.c"
|
||||
"src/tq/tqMetaStore.c"
|
||||
"src/tq/tqOffset.c"
|
||||
"src/tq/tqPush.c"
|
||||
"src/tq/tqRead.c"
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
#include "executor.h"
|
||||
#include "os.h"
|
||||
#include "tcache.h"
|
||||
#include "thash.h"
|
||||
#include "tmsg.h"
|
||||
#include "tqueue.h"
|
||||
#include "trpc.h"
|
||||
#include "ttimer.h"
|
||||
#include "wal.h"
|
||||
|
@ -41,45 +41,6 @@ extern "C" {
|
|||
#define tqTrace(...) do { if (tqDebugFlag & DEBUG_TRACE) { taosPrintLog("TQ ", DEBUG_TRACE, tqDebugFlag, __VA_ARGS__); }} while(0)
|
||||
// clang-format on
|
||||
|
||||
#define TQ_BUFFER_SIZE 4
|
||||
|
||||
#define TQ_BUCKET_MASK 0xFF
|
||||
#define TQ_BUCKET_SIZE 256
|
||||
|
||||
#define TQ_PAGE_SIZE 4096
|
||||
// key + offset + size
|
||||
#define TQ_IDX_SIZE 24
|
||||
// 4096 / 24
|
||||
#define TQ_MAX_IDX_ONE_PAGE 170
|
||||
// 24 * 170
|
||||
#define TQ_IDX_PAGE_BODY_SIZE 4080
|
||||
// 4096 - 4080
|
||||
#define TQ_IDX_PAGE_HEAD_SIZE 16
|
||||
|
||||
#define TQ_ACTION_CONST 0
|
||||
#define TQ_ACTION_INUSE 1
|
||||
#define TQ_ACTION_INUSE_CONT 2
|
||||
#define TQ_ACTION_INTXN 3
|
||||
|
||||
#define TQ_SVER 0
|
||||
|
||||
// TODO: inplace mode is not implemented
|
||||
#define TQ_UPDATE_INPLACE 0
|
||||
#define TQ_UPDATE_APPEND 1
|
||||
|
||||
#define TQ_DUP_INTXN_REWRITE 0
|
||||
#define TQ_DUP_INTXN_REJECT 2
|
||||
|
||||
static inline bool tqUpdateAppend(int32_t tqConfigFlag) { return tqConfigFlag & TQ_UPDATE_APPEND; }
|
||||
|
||||
static inline bool tqDupIntxnReject(int32_t tqConfigFlag) { return tqConfigFlag & TQ_DUP_INTXN_REJECT; }
|
||||
|
||||
static const int8_t TQ_CONST_DELETE = TQ_ACTION_CONST;
|
||||
|
||||
#define TQ_DELETE_TOKEN (void*)&TQ_CONST_DELETE
|
||||
|
||||
typedef enum { TQ_ITEM_READY, TQ_ITEM_PROCESS, TQ_ITEM_EMPTY } STqItemStatus;
|
||||
|
||||
typedef struct STqOffsetCfg STqOffsetCfg;
|
||||
typedef struct STqOffsetStore STqOffsetStore;
|
||||
|
||||
|
@ -98,53 +59,6 @@ struct STqReadHandle {
|
|||
STSchema* pSchema;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int16_t ver;
|
||||
int16_t action;
|
||||
int32_t checksum;
|
||||
int64_t ssize;
|
||||
char content[];
|
||||
} STqSerializedHead;
|
||||
|
||||
typedef int32_t (*FTqSerialize)(const void* pObj, STqSerializedHead** ppHead);
|
||||
typedef int32_t (*FTqDeserialize)(void* self, const STqSerializedHead* pHead, void** ppObj);
|
||||
typedef void (*FTqDelete)(void*);
|
||||
|
||||
typedef struct {
|
||||
int64_t key;
|
||||
int64_t offset;
|
||||
int64_t serializedSize;
|
||||
void* valueInUse;
|
||||
void* valueInTxn;
|
||||
} STqMetaHandle;
|
||||
|
||||
typedef struct STqMetaList {
|
||||
STqMetaHandle handle;
|
||||
struct STqMetaList* next;
|
||||
// struct STqMetaList* inTxnPrev;
|
||||
// struct STqMetaList* inTxnNext;
|
||||
struct STqMetaList* unpersistPrev;
|
||||
struct STqMetaList* unpersistNext;
|
||||
} STqMetaList;
|
||||
|
||||
typedef struct {
|
||||
STQ* pTq;
|
||||
STqMetaList* bucket[TQ_BUCKET_SIZE];
|
||||
// a table head
|
||||
STqMetaList* unpersistHead;
|
||||
// topics that are not connectted
|
||||
STqMetaList* unconnectTopic;
|
||||
|
||||
TdFilePtr pFile;
|
||||
TdFilePtr pIdxFile;
|
||||
|
||||
char* dirPath;
|
||||
int32_t tqConfigFlag;
|
||||
FTqSerialize pSerializer;
|
||||
FTqDeserialize pDeserializer;
|
||||
FTqDelete pDeleter;
|
||||
} STqMetaStore;
|
||||
|
||||
typedef struct {
|
||||
int64_t consumerId;
|
||||
int32_t epoch;
|
||||
|
@ -172,6 +86,9 @@ typedef struct {
|
|||
qTaskInfo_t task[5];
|
||||
} STqExec;
|
||||
|
||||
int32_t tEncodeSTqExec(SEncoder* pEncoder, const STqExec* pExec);
|
||||
int32_t tDecodeSTqExec(SDecoder* pDecoder, STqExec* pExec);
|
||||
|
||||
struct STQ {
|
||||
char* path;
|
||||
SHashObj* pushMgr; // consumerId -> STqExec*
|
||||
|
@ -179,7 +96,7 @@ struct STQ {
|
|||
SHashObj* pStreamTasks;
|
||||
SVnode* pVnode;
|
||||
SWal* pWal;
|
||||
// TDB* pTdb;
|
||||
TDB* pTdb;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -187,89 +104,12 @@ typedef struct {
|
|||
tmr_h timer;
|
||||
} STqMgmt;
|
||||
|
||||
static STqMgmt tqMgmt;
|
||||
|
||||
typedef struct {
|
||||
int8_t status;
|
||||
int64_t offset;
|
||||
qTaskInfo_t task;
|
||||
STqReadHandle* pReadHandle;
|
||||
} STqTaskItem;
|
||||
|
||||
// new version
|
||||
typedef struct {
|
||||
int64_t firstOffset;
|
||||
int64_t lastOffset;
|
||||
STqTaskItem output[TQ_BUFFER_SIZE];
|
||||
} STqBuffer;
|
||||
|
||||
typedef struct {
|
||||
char topicName[TSDB_TOPIC_FNAME_LEN];
|
||||
char* sql;
|
||||
char* logicalPlan;
|
||||
char* physicalPlan;
|
||||
char* qmsg;
|
||||
STqBuffer buffer;
|
||||
SWalReadHandle* pReadhandle;
|
||||
} STqTopic;
|
||||
|
||||
typedef struct {
|
||||
int64_t consumerId;
|
||||
int32_t epoch;
|
||||
char cgroup[TSDB_TOPIC_FNAME_LEN];
|
||||
SArray* topics; // SArray<STqTopic>
|
||||
} STqConsumer;
|
||||
|
||||
typedef struct {
|
||||
int8_t type;
|
||||
int8_t nodeType;
|
||||
int8_t reserved[6];
|
||||
int64_t streamId;
|
||||
qTaskInfo_t task;
|
||||
// TODO sync function
|
||||
} STqStreamPusher;
|
||||
|
||||
typedef struct {
|
||||
int8_t inited;
|
||||
tmr_h timer;
|
||||
} STqPushMgmt;
|
||||
|
||||
static STqPushMgmt tqPushMgmt;
|
||||
static STqMgmt tqMgmt = {0};
|
||||
|
||||
// init once
|
||||
int tqInit();
|
||||
void tqCleanUp();
|
||||
|
||||
// open in each vnode
|
||||
// required by vnode
|
||||
|
||||
int32_t tqSerializeConsumer(const STqConsumer*, STqSerializedHead**);
|
||||
int32_t tqDeserializeConsumer(STQ*, const STqSerializedHead*, STqConsumer**);
|
||||
|
||||
static int FORCE_INLINE tqQueryExecuting(int32_t status) { return status; }
|
||||
|
||||
// tqMetaStore.h
|
||||
STqMetaStore* tqStoreOpen(STQ* pTq, const char* path, FTqSerialize pSerializer, FTqDeserialize pDeserializer,
|
||||
FTqDelete pDeleter, int32_t tqConfigFlag);
|
||||
int32_t tqStoreClose(STqMetaStore*);
|
||||
// int32_t tqStoreDelete(TqMetaStore*);
|
||||
// int32_t tqStoreCommitAll(TqMetaStore*);
|
||||
int32_t tqStorePersist(STqMetaStore*);
|
||||
// clean deleted idx and data from persistent file
|
||||
int32_t tqStoreCompact(STqMetaStore*);
|
||||
|
||||
void* tqHandleGet(STqMetaStore*, int64_t key);
|
||||
// make it unpersist
|
||||
void* tqHandleTouchGet(STqMetaStore*, int64_t key);
|
||||
int32_t tqHandleMovePut(STqMetaStore*, int64_t key, void* value);
|
||||
int32_t tqHandleCopyPut(STqMetaStore*, int64_t key, void* value, size_t vsize);
|
||||
// delete committed kv pair
|
||||
// notice that a delete action still needs to be committed
|
||||
int32_t tqHandleDel(STqMetaStore*, int64_t key);
|
||||
int32_t tqHandlePurge(STqMetaStore*, int64_t key);
|
||||
int32_t tqHandleCommit(STqMetaStore*, int64_t key);
|
||||
int32_t tqHandleAbort(STqMetaStore*, int64_t key);
|
||||
|
||||
// tqOffset
|
||||
STqOffsetStore* STqOffsetOpen(STqOffsetCfg*);
|
||||
void STqOffsetClose(STqOffsetStore*);
|
||||
|
|
|
@ -278,12 +278,13 @@ STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver) {
|
|||
pSW = metaGetTableSchema(pMeta, quid, sver, 0);
|
||||
if (!pSW) return NULL;
|
||||
|
||||
tdInitTSchemaBuilder(&sb, 0);
|
||||
tdInitTSchemaBuilder(&sb, sver);
|
||||
for (int i = 0; i < pSW->nCols; i++) {
|
||||
pSchema = pSW->pSchema + i;
|
||||
tdAddColToSchema(&sb, pSchema->type, pSchema->flags, pSchema->colId, pSchema->bytes);
|
||||
}
|
||||
pTSchema = tdGetSchemaFromBuilder(&sb);
|
||||
|
||||
tdDestroyTSchemaBuilder(&sb);
|
||||
|
||||
taosMemoryFree(pSW->pSchema);
|
||||
|
|
|
@ -607,31 +607,39 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
|
|||
if (iCol == 0) {
|
||||
// TODO : need to update tag index
|
||||
}
|
||||
|
||||
ctbEntry.version = version;
|
||||
SKVRowBuilder kvrb = {0};
|
||||
const SKVRow pOldTag = (const SKVRow)ctbEntry.ctbEntry.pTags;
|
||||
SKVRow pNewTag = NULL;
|
||||
if(pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON){
|
||||
ctbEntry.ctbEntry.pTags = taosMemoryMalloc(pAlterTbReq->nTagVal);
|
||||
if(ctbEntry.ctbEntry.pTags == NULL){
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _err;
|
||||
}
|
||||
memcpy((void*)ctbEntry.ctbEntry.pTags, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
|
||||
}else{
|
||||
SKVRowBuilder kvrb = {0};
|
||||
const SKVRow pOldTag = (const SKVRow)ctbEntry.ctbEntry.pTags;
|
||||
SKVRow pNewTag = NULL;
|
||||
|
||||
tdInitKVRowBuilder(&kvrb);
|
||||
for (int32_t i = 0; i < pTagSchema->nCols; i++) {
|
||||
SSchema *pCol = &pTagSchema->pSchema[i];
|
||||
if (iCol == i) {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
|
||||
} else {
|
||||
void *p = tdGetKVRowValOfCol(pOldTag, pCol->colId);
|
||||
if (p) {
|
||||
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, p, varDataTLen(p));
|
||||
} else {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, p, pCol->bytes);
|
||||
tdInitKVRowBuilder(&kvrb);
|
||||
for (int32_t i = 0; i < pTagSchema->nCols; i++) {
|
||||
SSchema *pCol = &pTagSchema->pSchema[i];
|
||||
if (iCol == i) {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
|
||||
} else {
|
||||
void *p = tdGetKVRowValOfCol(pOldTag, pCol->colId);
|
||||
if (p) {
|
||||
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, p, varDataTLen(p));
|
||||
} else {
|
||||
tdAddColToKVRow(&kvrb, pCol->colId, p, pCol->bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctbEntry.ctbEntry.pTags = tdGetKVRowFromBuilder(&kvrb);
|
||||
tdDestroyKVRowBuilder(&kvrb);
|
||||
ctbEntry.ctbEntry.pTags = tdGetKVRowFromBuilder(&kvrb);
|
||||
tdDestroyKVRowBuilder(&kvrb);
|
||||
}
|
||||
|
||||
// save to table.db
|
||||
metaSaveToTbDb(pMeta, &ctbEntry);
|
||||
|
@ -641,6 +649,7 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA
|
|||
|
||||
tDecoderClear(&dc1);
|
||||
tDecoderClear(&dc2);
|
||||
if (ctbEntry.ctbEntry.pTags) taosMemoryFree((void*)ctbEntry.ctbEntry.pTags);
|
||||
if (ctbEntry.pBuf) taosMemoryFree(ctbEntry.pBuf);
|
||||
if (stbEntry.pBuf) tdbFree(stbEntry.pBuf);
|
||||
tdbTbcClose(pTbDbc);
|
||||
|
|
|
@ -14,14 +14,37 @@
|
|||
*/
|
||||
|
||||
#include "tq.h"
|
||||
#include "tqueue.h"
|
||||
|
||||
int32_t tqInit() {
|
||||
//
|
||||
int8_t old;
|
||||
while (1) {
|
||||
old = atomic_val_compare_exchange_8(&tqMgmt.inited, 0, 2);
|
||||
if (old != 2) break;
|
||||
}
|
||||
|
||||
if (old == 0) {
|
||||
tqMgmt.timer = taosTmrInit(10000, 100, 10000, "TQ");
|
||||
if (tqMgmt.timer == NULL) {
|
||||
atomic_store_8(&tqMgmt.inited, 0);
|
||||
return -1;
|
||||
}
|
||||
atomic_store_8(&tqMgmt.inited, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tqCleanUp() {}
|
||||
void tqCleanUp() {
|
||||
int8_t old;
|
||||
while (1) {
|
||||
old = atomic_val_compare_exchange_8(&tqMgmt.inited, 1, 2);
|
||||
if (old != 2) break;
|
||||
}
|
||||
|
||||
if (old == 1) {
|
||||
taosTmrCleanUp(tqMgmt.timer);
|
||||
atomic_store_8(&tqMgmt.inited, 0);
|
||||
}
|
||||
}
|
||||
|
||||
STQ* tqOpen(const char* path, SVnode* pVnode, SWal* pWal) {
|
||||
STQ* pTq = taosMemoryMalloc(sizeof(STQ));
|
||||
|
@ -32,9 +55,9 @@ STQ* tqOpen(const char* path, SVnode* pVnode, SWal* pWal) {
|
|||
pTq->path = strdup(path);
|
||||
pTq->pVnode = pVnode;
|
||||
pTq->pWal = pWal;
|
||||
/*if (tdbOpen(path, 4096, 1, &pTq->pTdb) < 0) {*/
|
||||
/*ASSERT(0);*/
|
||||
/*}*/
|
||||
if (tdbOpen(path, 4096, 1, &pTq->pTdb) < 0) {
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
pTq->execs = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK);
|
||||
|
||||
|
@ -51,11 +74,45 @@ void tqClose(STQ* pTq) {
|
|||
taosHashCleanup(pTq->execs);
|
||||
taosHashCleanup(pTq->pStreamTasks);
|
||||
taosHashCleanup(pTq->pushMgr);
|
||||
tdbClose(pTq->pTdb);
|
||||
taosMemoryFree(pTq);
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
int32_t tEncodeSTqExec(SEncoder* pEncoder, const STqExec* pExec) {
|
||||
if (tStartEncode(pEncoder) < 0) return -1;
|
||||
if (tEncodeCStr(pEncoder, pExec->subKey) < 0) return -1;
|
||||
if (tEncodeI64(pEncoder, pExec->consumerId) < 0) return -1;
|
||||
if (tEncodeI32(pEncoder, pExec->epoch) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pExec->subType) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pExec->withTbName) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pExec->withSchema) < 0) return -1;
|
||||
if (tEncodeI8(pEncoder, pExec->withTag) < 0) return -1;
|
||||
if (pExec->subType == TOPIC_SUB_TYPE__TABLE) {
|
||||
if (tEncodeCStr(pEncoder, pExec->qmsg) < 0) return -1;
|
||||
// TODO encode modified exec
|
||||
}
|
||||
tEndEncode(pEncoder);
|
||||
return pEncoder->pos;
|
||||
}
|
||||
|
||||
int32_t tDecodeSTqExec(SDecoder* pDecoder, STqExec* pExec) {
|
||||
if (tStartDecode(pDecoder) < 0) return -1;
|
||||
if (tDecodeCStrTo(pDecoder, pExec->subKey) < 0) return -1;
|
||||
if (tDecodeI64(pDecoder, &pExec->consumerId) < 0) return -1;
|
||||
if (tDecodeI32(pDecoder, &pExec->epoch) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pExec->subType) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pExec->withTbName) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pExec->withSchema) < 0) return -1;
|
||||
if (tDecodeI8(pDecoder, &pExec->withTag) < 0) return -1;
|
||||
if (pExec->subType == TOPIC_SUB_TYPE__TABLE) {
|
||||
if (tDecodeCStrAlloc(pDecoder, &pExec->qmsg) < 0) return -1;
|
||||
// TODO decode modified exec
|
||||
}
|
||||
tEndDecode(pDecoder);
|
||||
return 0;
|
||||
}
|
||||
int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) {
|
||||
void* pIter = NULL;
|
||||
while (1) {
|
||||
|
@ -214,7 +271,7 @@ int tqPushMsg(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver)
|
|||
if (taosHashGetSize(pTq->pStreamTasks) == 0) return 0;
|
||||
|
||||
if (tdUpdateExpireWindow(pTq->pVnode->pSma, msg, ver) != 0) {
|
||||
// TODO error handle
|
||||
// TODO handle sma error
|
||||
}
|
||||
void* data = taosMemoryMalloc(msgLen);
|
||||
if (data == NULL) {
|
||||
|
@ -230,134 +287,6 @@ int tqPushMsg(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver)
|
|||
|
||||
int tqCommit(STQ* pTq) {
|
||||
// do nothing
|
||||
/*return tqStorePersist(pTq->tqMeta);*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqGetTopicHandleSize(const STqTopic* pTopic) {
|
||||
return strlen(pTopic->topicName) + strlen(pTopic->sql) + strlen(pTopic->physicalPlan) + strlen(pTopic->qmsg) +
|
||||
sizeof(int64_t) * 3;
|
||||
}
|
||||
|
||||
int32_t tqGetConsumerHandleSize(const STqConsumer* pConsumer) {
|
||||
int num = taosArrayGetSize(pConsumer->topics);
|
||||
int32_t sz = 0;
|
||||
for (int i = 0; i < num; i++) {
|
||||
STqTopic* pTopic = taosArrayGet(pConsumer->topics, i);
|
||||
sz += tqGetTopicHandleSize(pTopic);
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tEncodeSTqTopic(void** buf, const STqTopic* pTopic) {
|
||||
int32_t tlen = 0;
|
||||
tlen += taosEncodeString(buf, pTopic->topicName);
|
||||
/*tlen += taosEncodeString(buf, pTopic->sql);*/
|
||||
/*tlen += taosEncodeString(buf, pTopic->physicalPlan);*/
|
||||
tlen += taosEncodeString(buf, pTopic->qmsg);
|
||||
/*tlen += taosEncodeFixedI64(buf, pTopic->persistedOffset);*/
|
||||
/*tlen += taosEncodeFixedI64(buf, pTopic->committedOffset);*/
|
||||
/*tlen += taosEncodeFixedI64(buf, pTopic->currentOffset);*/
|
||||
return tlen;
|
||||
}
|
||||
|
||||
static FORCE_INLINE const void* tDecodeSTqTopic(const void* buf, STqTopic* pTopic) {
|
||||
buf = taosDecodeStringTo(buf, pTopic->topicName);
|
||||
/*buf = taosDecodeString(buf, &pTopic->sql);*/
|
||||
/*buf = taosDecodeString(buf, &pTopic->physicalPlan);*/
|
||||
buf = taosDecodeString(buf, &pTopic->qmsg);
|
||||
/*buf = taosDecodeFixedI64(buf, &pTopic->persistedOffset);*/
|
||||
/*buf = taosDecodeFixedI64(buf, &pTopic->committedOffset);*/
|
||||
/*buf = taosDecodeFixedI64(buf, &pTopic->currentOffset);*/
|
||||
return buf;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t tEncodeSTqConsumer(void** buf, const STqConsumer* pConsumer) {
|
||||
int32_t sz;
|
||||
|
||||
int32_t tlen = 0;
|
||||
tlen += taosEncodeFixedI64(buf, pConsumer->consumerId);
|
||||
tlen += taosEncodeFixedI32(buf, pConsumer->epoch);
|
||||
tlen += taosEncodeString(buf, pConsumer->cgroup);
|
||||
sz = taosArrayGetSize(pConsumer->topics);
|
||||
tlen += taosEncodeFixedI32(buf, sz);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
STqTopic* pTopic = taosArrayGet(pConsumer->topics, i);
|
||||
tlen += tEncodeSTqTopic(buf, pTopic);
|
||||
}
|
||||
return tlen;
|
||||
}
|
||||
|
||||
static FORCE_INLINE const void* tDecodeSTqConsumer(const void* buf, STqConsumer* pConsumer) {
|
||||
int32_t sz;
|
||||
|
||||
buf = taosDecodeFixedI64(buf, &pConsumer->consumerId);
|
||||
buf = taosDecodeFixedI32(buf, &pConsumer->epoch);
|
||||
buf = taosDecodeStringTo(buf, pConsumer->cgroup);
|
||||
buf = taosDecodeFixedI32(buf, &sz);
|
||||
pConsumer->topics = taosArrayInit(sz, sizeof(STqTopic));
|
||||
if (pConsumer->topics == NULL) return NULL;
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
STqTopic pTopic;
|
||||
buf = tDecodeSTqTopic(buf, &pTopic);
|
||||
taosArrayPush(pConsumer->topics, &pTopic);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int tqSerializeConsumer(const STqConsumer* pConsumer, STqSerializedHead** ppHead) {
|
||||
int32_t sz = tEncodeSTqConsumer(NULL, pConsumer);
|
||||
|
||||
if (sz > (*ppHead)->ssize) {
|
||||
void* tmpPtr = taosMemoryRealloc(*ppHead, sizeof(STqSerializedHead) + sz);
|
||||
if (tmpPtr == NULL) {
|
||||
taosMemoryFree(*ppHead);
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
*ppHead = tmpPtr;
|
||||
(*ppHead)->ssize = sz;
|
||||
}
|
||||
|
||||
void* ptr = (*ppHead)->content;
|
||||
void* abuf = ptr;
|
||||
tEncodeSTqConsumer(&abuf, pConsumer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqDeserializeConsumer(STQ* pTq, const STqSerializedHead* pHead, STqConsumer** ppConsumer) {
|
||||
const void* str = pHead->content;
|
||||
*ppConsumer = taosMemoryCalloc(1, sizeof(STqConsumer));
|
||||
if (*ppConsumer == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
if (tDecodeSTqConsumer(str, *ppConsumer) == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
STqConsumer* pConsumer = *ppConsumer;
|
||||
int32_t sz = taosArrayGetSize(pConsumer->topics);
|
||||
for (int32_t i = 0; i < sz; i++) {
|
||||
STqTopic* pTopic = taosArrayGet(pConsumer->topics, i);
|
||||
pTopic->pReadhandle = walOpenReadHandle(pTq->pWal);
|
||||
if (pTopic->pReadhandle == NULL) {
|
||||
ASSERT(false);
|
||||
}
|
||||
for (int j = 0; j < TQ_BUFFER_SIZE; j++) {
|
||||
pTopic->buffer.output[j].status = 0;
|
||||
STqReadHandle* pReadHandle = tqInitSubmitMsgScanner(pTq->pVnode->pMeta);
|
||||
SReadHandle handle = {
|
||||
.reader = pReadHandle,
|
||||
.meta = pTq->pVnode->pMeta,
|
||||
.pMsgCb = &pTq->pVnode->msgCb,
|
||||
};
|
||||
pTopic->buffer.output[j].pReadHandle = pReadHandle;
|
||||
pTopic->buffer.output[j].task = qCreateStreamExecTaskInfo(pTopic->qmsg, &handle);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,622 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "tq.h"
|
||||
// #include <fcntl.h>
|
||||
// #include <string.h>
|
||||
// #include <unistd.h>
|
||||
// #include "osDir.h"
|
||||
|
||||
#define TQ_META_NAME "tq.meta"
|
||||
#define TQ_IDX_NAME "tq.idx"
|
||||
|
||||
static int32_t tqHandlePutCommitted(STqMetaStore*, int64_t key, void* value);
|
||||
static void* tqHandleGetUncommitted(STqMetaStore*, int64_t key);
|
||||
|
||||
static inline void tqLinkUnpersist(STqMetaStore* pMeta, STqMetaList* pNode) {
|
||||
if (pNode->unpersistNext == NULL) {
|
||||
pNode->unpersistNext = pMeta->unpersistHead->unpersistNext;
|
||||
pNode->unpersistPrev = pMeta->unpersistHead;
|
||||
pMeta->unpersistHead->unpersistNext->unpersistPrev = pNode;
|
||||
pMeta->unpersistHead->unpersistNext = pNode;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int64_t tqSeekLastPage(TdFilePtr pFile) {
|
||||
int offset = taosLSeekFile(pFile, 0, SEEK_END);
|
||||
int pageNo = offset / TQ_PAGE_SIZE;
|
||||
int curPageOffset = pageNo * TQ_PAGE_SIZE;
|
||||
return taosLSeekFile(pFile, curPageOffset, SEEK_SET);
|
||||
}
|
||||
|
||||
// TODO: the struct is tightly coupled with index entry
|
||||
typedef struct STqIdxPageHead {
|
||||
int16_t writeOffset;
|
||||
int8_t unused[14];
|
||||
} STqIdxPageHead;
|
||||
|
||||
typedef struct STqIdxPageBuf {
|
||||
STqIdxPageHead head;
|
||||
char buffer[TQ_IDX_PAGE_BODY_SIZE];
|
||||
} STqIdxPageBuf;
|
||||
|
||||
static inline int tqReadLastPage(TdFilePtr pFile, STqIdxPageBuf* pBuf) {
|
||||
int offset = tqSeekLastPage(pFile);
|
||||
int nBytes;
|
||||
if ((nBytes = taosReadFile(pFile, pBuf, TQ_PAGE_SIZE)) == -1) {
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
return -1;
|
||||
}
|
||||
if (nBytes == 0) {
|
||||
memset(pBuf, 0, TQ_PAGE_SIZE);
|
||||
pBuf->head.writeOffset = TQ_IDX_PAGE_HEAD_SIZE;
|
||||
}
|
||||
ASSERT(nBytes == 0 || nBytes == pBuf->head.writeOffset);
|
||||
|
||||
return taosLSeekFile(pFile, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
STqMetaStore* tqStoreOpen(STQ* pTq, const char* path, FTqSerialize serializer, FTqDeserialize deserializer,
|
||||
FTqDelete deleter, int32_t tqConfigFlag) {
|
||||
STqMetaStore* pMeta = taosMemoryCalloc(1, sizeof(STqMetaStore));
|
||||
if (pMeta == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
pMeta->pTq = pTq;
|
||||
|
||||
// concat data file name and index file name
|
||||
size_t pathLen = strlen(path);
|
||||
pMeta->dirPath = taosMemoryMalloc(pathLen + 1);
|
||||
if (pMeta->dirPath == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
taosMemoryFree(pMeta);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(pMeta->dirPath, path);
|
||||
|
||||
char* name = taosMemoryMalloc(pathLen + 10);
|
||||
|
||||
strcpy(name, path);
|
||||
if (!taosDirExist(name) && taosMkDir(name) != 0) {
|
||||
terrno = TSDB_CODE_TQ_FAILED_TO_CREATE_DIR;
|
||||
tqError("failed to create dir:%s since %s ", name, terrstr());
|
||||
}
|
||||
strcat(name, "/" TQ_IDX_NAME);
|
||||
TdFilePtr pIdxFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ);
|
||||
if (pIdxFile == NULL) {
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
tqError("failed to open file:%s since %s ", name, terrstr());
|
||||
// free memory
|
||||
taosMemoryFree(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pMeta->pIdxFile = pIdxFile;
|
||||
pMeta->unpersistHead = taosMemoryCalloc(1, sizeof(STqMetaList));
|
||||
if (pMeta->unpersistHead == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
taosMemoryFree(name);
|
||||
return NULL;
|
||||
}
|
||||
pMeta->unpersistHead->unpersistNext = pMeta->unpersistHead->unpersistPrev = pMeta->unpersistHead;
|
||||
|
||||
strcpy(name, path);
|
||||
strcat(name, "/" TQ_META_NAME);
|
||||
TdFilePtr pFile = taosOpenFile(name, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ);
|
||||
if (pFile == NULL) {
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
tqError("failed to open file:%s since %s", name, terrstr());
|
||||
taosMemoryFree(name);
|
||||
return NULL;
|
||||
}
|
||||
taosMemoryFree(name);
|
||||
|
||||
pMeta->pFile = pFile;
|
||||
|
||||
pMeta->pSerializer = serializer;
|
||||
pMeta->pDeserializer = deserializer;
|
||||
pMeta->pDeleter = deleter;
|
||||
pMeta->tqConfigFlag = tqConfigFlag;
|
||||
|
||||
// read idx file and load into memory
|
||||
STqIdxPageBuf idxBuf;
|
||||
STqSerializedHead* serializedObj = taosMemoryMalloc(TQ_PAGE_SIZE);
|
||||
if (serializedObj == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
}
|
||||
int idxRead;
|
||||
int allocated = TQ_PAGE_SIZE;
|
||||
bool readEnd = false;
|
||||
while ((idxRead = taosReadFile(pIdxFile, &idxBuf, TQ_PAGE_SIZE))) {
|
||||
if (idxRead == -1) {
|
||||
// TODO: handle error
|
||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||
tqError("failed to read tq index file since %s", terrstr());
|
||||
}
|
||||
ASSERT(idxBuf.head.writeOffset == idxRead);
|
||||
// loop read every entry
|
||||
for (int i = 0; i < idxBuf.head.writeOffset - TQ_IDX_PAGE_HEAD_SIZE; i += TQ_IDX_SIZE) {
|
||||
STqMetaList* pNode = taosMemoryCalloc(1, sizeof(STqMetaList));
|
||||
if (pNode == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
// TODO: free memory
|
||||
}
|
||||
memcpy(&pNode->handle, &idxBuf.buffer[i], TQ_IDX_SIZE);
|
||||
|
||||
taosLSeekFile(pFile, pNode->handle.offset, SEEK_SET);
|
||||
if (allocated < pNode->handle.serializedSize) {
|
||||
void* ptr = taosMemoryRealloc(serializedObj, pNode->handle.serializedSize);
|
||||
if (ptr == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
// TODO: free memory
|
||||
}
|
||||
serializedObj = ptr;
|
||||
allocated = pNode->handle.serializedSize;
|
||||
}
|
||||
serializedObj->ssize = pNode->handle.serializedSize;
|
||||
if (taosReadFile(pFile, serializedObj, pNode->handle.serializedSize) != pNode->handle.serializedSize) {
|
||||
// TODO: read error
|
||||
}
|
||||
if (serializedObj->action == TQ_ACTION_INUSE) {
|
||||
if (serializedObj->ssize != sizeof(STqSerializedHead)) {
|
||||
pMeta->pDeserializer(pTq, serializedObj, &pNode->handle.valueInUse);
|
||||
} else {
|
||||
pNode->handle.valueInUse = TQ_DELETE_TOKEN;
|
||||
}
|
||||
} else if (serializedObj->action == TQ_ACTION_INTXN) {
|
||||
if (serializedObj->ssize != sizeof(STqSerializedHead)) {
|
||||
pMeta->pDeserializer(pTq, serializedObj, &pNode->handle.valueInTxn);
|
||||
} else {
|
||||
pNode->handle.valueInTxn = TQ_DELETE_TOKEN;
|
||||
}
|
||||
} else if (serializedObj->action == TQ_ACTION_INUSE_CONT) {
|
||||
if (serializedObj->ssize != sizeof(STqSerializedHead)) {
|
||||
pMeta->pDeserializer(pTq, serializedObj, &pNode->handle.valueInUse);
|
||||
} else {
|
||||
pNode->handle.valueInUse = TQ_DELETE_TOKEN;
|
||||
}
|
||||
STqSerializedHead* ptr = POINTER_SHIFT(serializedObj, serializedObj->ssize);
|
||||
if (ptr->ssize != sizeof(STqSerializedHead)) {
|
||||
pMeta->pDeserializer(pTq, ptr, &pNode->handle.valueInTxn);
|
||||
} else {
|
||||
pNode->handle.valueInTxn = TQ_DELETE_TOKEN;
|
||||
}
|
||||
} else {
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
// put into list
|
||||
int bucketKey = pNode->handle.key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pBucketNode = pMeta->bucket[bucketKey];
|
||||
if (pBucketNode == NULL) {
|
||||
pMeta->bucket[bucketKey] = pNode;
|
||||
} else if (pBucketNode->handle.key == pNode->handle.key) {
|
||||
pNode->next = pBucketNode->next;
|
||||
pMeta->bucket[bucketKey] = pNode;
|
||||
} else {
|
||||
while (pBucketNode->next && pBucketNode->next->handle.key != pNode->handle.key) {
|
||||
pBucketNode = pBucketNode->next;
|
||||
}
|
||||
if (pBucketNode->next) {
|
||||
ASSERT(pBucketNode->next->handle.key == pNode->handle.key);
|
||||
STqMetaList* pNodeFound = pBucketNode->next;
|
||||
pNode->next = pNodeFound->next;
|
||||
pBucketNode->next = pNode;
|
||||
pBucketNode = pNodeFound;
|
||||
} else {
|
||||
pNode->next = pMeta->bucket[bucketKey];
|
||||
pMeta->bucket[bucketKey] = pNode;
|
||||
pBucketNode = NULL;
|
||||
}
|
||||
}
|
||||
if (pBucketNode) {
|
||||
if (pBucketNode->handle.valueInUse && pBucketNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pBucketNode->handle.valueInUse);
|
||||
}
|
||||
if (pBucketNode->handle.valueInTxn && pBucketNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pBucketNode->handle.valueInTxn);
|
||||
}
|
||||
taosMemoryFree(pBucketNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
taosMemoryFree(serializedObj);
|
||||
return pMeta;
|
||||
}
|
||||
|
||||
int32_t tqStoreClose(STqMetaStore* pMeta) {
|
||||
// commit data and idx
|
||||
tqStorePersist(pMeta);
|
||||
ASSERT(pMeta->unpersistHead && pMeta->unpersistHead->next == NULL);
|
||||
taosCloseFile(&pMeta->pFile);
|
||||
taosCloseFile(&pMeta->pIdxFile);
|
||||
// free memory
|
||||
for (int i = 0; i < TQ_BUCKET_SIZE; i++) {
|
||||
STqMetaList* pNode = pMeta->bucket[i];
|
||||
while (pNode) {
|
||||
ASSERT(pNode->unpersistNext == NULL);
|
||||
ASSERT(pNode->unpersistPrev == NULL);
|
||||
if (pNode->handle.valueInTxn && pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInTxn);
|
||||
}
|
||||
if (pNode->handle.valueInUse && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInUse);
|
||||
}
|
||||
STqMetaList* next = pNode->next;
|
||||
taosMemoryFree(pNode);
|
||||
pNode = next;
|
||||
}
|
||||
}
|
||||
taosMemoryFree(pMeta->dirPath);
|
||||
taosMemoryFree(pMeta->unpersistHead);
|
||||
taosMemoryFree(pMeta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqStoreDelete(STqMetaStore* pMeta) {
|
||||
taosCloseFile(&pMeta->pFile);
|
||||
taosCloseFile(&pMeta->pIdxFile);
|
||||
// free memory
|
||||
for (int i = 0; i < TQ_BUCKET_SIZE; i++) {
|
||||
STqMetaList* pNode = pMeta->bucket[i];
|
||||
pMeta->bucket[i] = NULL;
|
||||
while (pNode) {
|
||||
if (pNode->handle.valueInTxn && pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInTxn);
|
||||
}
|
||||
if (pNode->handle.valueInUse && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInUse);
|
||||
}
|
||||
STqMetaList* next = pNode->next;
|
||||
taosMemoryFree(pNode);
|
||||
pNode = next;
|
||||
}
|
||||
}
|
||||
taosMemoryFree(pMeta->unpersistHead);
|
||||
taosRemoveDir(pMeta->dirPath);
|
||||
taosMemoryFree(pMeta->dirPath);
|
||||
taosMemoryFree(pMeta);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqStorePersist(STqMetaStore* pMeta) {
|
||||
STqIdxPageBuf idxBuf;
|
||||
int64_t* bufPtr = (int64_t*)idxBuf.buffer;
|
||||
STqMetaList* pHead = pMeta->unpersistHead;
|
||||
STqMetaList* pNode = pHead->unpersistNext;
|
||||
STqSerializedHead* pSHead = taosMemoryMalloc(sizeof(STqSerializedHead));
|
||||
if (pSHead == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pSHead->ver = TQ_SVER;
|
||||
pSHead->checksum = 0;
|
||||
pSHead->ssize = sizeof(STqSerializedHead);
|
||||
/*int allocatedSize = sizeof(STqSerializedHead);*/
|
||||
int offset = taosLSeekFile(pMeta->pFile, 0, SEEK_CUR);
|
||||
|
||||
tqReadLastPage(pMeta->pIdxFile, &idxBuf);
|
||||
|
||||
if (idxBuf.head.writeOffset == TQ_PAGE_SIZE) {
|
||||
taosLSeekFile(pMeta->pIdxFile, 0, SEEK_END);
|
||||
memset(&idxBuf, 0, TQ_PAGE_SIZE);
|
||||
idxBuf.head.writeOffset = TQ_IDX_PAGE_HEAD_SIZE;
|
||||
} else {
|
||||
bufPtr = POINTER_SHIFT(&idxBuf, idxBuf.head.writeOffset);
|
||||
}
|
||||
|
||||
while (pHead != pNode) {
|
||||
int nBytes = 0;
|
||||
|
||||
if (pNode->handle.valueInUse) {
|
||||
if (pNode->handle.valueInTxn) {
|
||||
pSHead->action = TQ_ACTION_INUSE_CONT;
|
||||
} else {
|
||||
pSHead->action = TQ_ACTION_INUSE;
|
||||
}
|
||||
|
||||
if (pNode->handle.valueInUse == TQ_DELETE_TOKEN) {
|
||||
pSHead->ssize = sizeof(STqSerializedHead);
|
||||
} else {
|
||||
pMeta->pSerializer(pNode->handle.valueInUse, &pSHead);
|
||||
}
|
||||
nBytes = taosWriteFile(pMeta->pFile, pSHead, pSHead->ssize);
|
||||
ASSERT(nBytes == pSHead->ssize);
|
||||
}
|
||||
|
||||
if (pNode->handle.valueInTxn) {
|
||||
pSHead->action = TQ_ACTION_INTXN;
|
||||
if (pNode->handle.valueInTxn == TQ_DELETE_TOKEN) {
|
||||
pSHead->ssize = sizeof(STqSerializedHead);
|
||||
} else {
|
||||
pMeta->pSerializer(pNode->handle.valueInTxn, &pSHead);
|
||||
}
|
||||
int nBytesTxn = taosWriteFile(pMeta->pFile, pSHead, pSHead->ssize);
|
||||
ASSERT(nBytesTxn == pSHead->ssize);
|
||||
nBytes += nBytesTxn;
|
||||
}
|
||||
pNode->handle.offset = offset;
|
||||
offset += nBytes;
|
||||
|
||||
// write idx file
|
||||
// TODO: endian check and convert
|
||||
*(bufPtr++) = pNode->handle.key;
|
||||
*(bufPtr++) = pNode->handle.offset;
|
||||
*(bufPtr++) = (int64_t)nBytes;
|
||||
idxBuf.head.writeOffset += TQ_IDX_SIZE;
|
||||
|
||||
if (idxBuf.head.writeOffset >= TQ_PAGE_SIZE) {
|
||||
nBytes = taosWriteFile(pMeta->pIdxFile, &idxBuf, TQ_PAGE_SIZE);
|
||||
// TODO: handle error with tfile
|
||||
ASSERT(nBytes == TQ_PAGE_SIZE);
|
||||
memset(&idxBuf, 0, TQ_PAGE_SIZE);
|
||||
idxBuf.head.writeOffset = TQ_IDX_PAGE_HEAD_SIZE;
|
||||
bufPtr = (int64_t*)&idxBuf.buffer;
|
||||
}
|
||||
// remove from unpersist list
|
||||
pHead->unpersistNext = pNode->unpersistNext;
|
||||
pHead->unpersistNext->unpersistPrev = pHead;
|
||||
pNode->unpersistPrev = pNode->unpersistNext = NULL;
|
||||
pNode = pHead->unpersistNext;
|
||||
|
||||
// remove from bucket
|
||||
if (pNode->handle.valueInUse == TQ_DELETE_TOKEN && pNode->handle.valueInTxn == NULL) {
|
||||
int bucketKey = pNode->handle.key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pBucketHead = pMeta->bucket[bucketKey];
|
||||
if (pBucketHead == pNode) {
|
||||
pMeta->bucket[bucketKey] = pNode->next;
|
||||
} else {
|
||||
STqMetaList* pBucketNode = pBucketHead;
|
||||
while (pBucketNode->next != NULL && pBucketNode->next != pNode) {
|
||||
pBucketNode = pBucketNode->next;
|
||||
}
|
||||
// impossible for pBucket->next == NULL
|
||||
ASSERT(pBucketNode->next == pNode);
|
||||
pBucketNode->next = pNode->next;
|
||||
}
|
||||
taosMemoryFree(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
// write left bytes
|
||||
taosMemoryFree(pSHead);
|
||||
// TODO: write new version in tfile
|
||||
if ((char*)bufPtr != idxBuf.buffer) {
|
||||
int nBytes = taosWriteFile(pMeta->pIdxFile, &idxBuf, idxBuf.head.writeOffset);
|
||||
// TODO: handle error in tfile
|
||||
ASSERT(nBytes == idxBuf.head.writeOffset);
|
||||
}
|
||||
// TODO: using fsync in tfile
|
||||
taosFsyncFile(pMeta->pIdxFile);
|
||||
taosFsyncFile(pMeta->pFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tqHandlePutCommitted(STqMetaStore* pMeta, int64_t key, void* value) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInUse && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInUse);
|
||||
}
|
||||
// change pointer ownership
|
||||
pNode->handle.valueInUse = value;
|
||||
return 0;
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
STqMetaList* pNewNode = taosMemoryCalloc(1, sizeof(STqMetaList));
|
||||
if (pNewNode == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pNewNode->handle.key = key;
|
||||
pNewNode->handle.valueInUse = value;
|
||||
pNewNode->next = pMeta->bucket[bucketKey];
|
||||
// put into unpersist list
|
||||
pNewNode->unpersistPrev = pMeta->unpersistHead;
|
||||
pNewNode->unpersistNext = pMeta->unpersistHead->unpersistNext;
|
||||
pMeta->unpersistHead->unpersistNext->unpersistPrev = pNewNode;
|
||||
pMeta->unpersistHead->unpersistNext = pNewNode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* tqHandleGet(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInUse != NULL && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
return pNode->handle.valueInUse;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* tqHandleTouchGet(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInUse != NULL && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return pNode->handle.valueInUse;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int32_t tqHandlePutImpl(STqMetaStore* pMeta, int64_t key, void* value) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInTxn) {
|
||||
if (tqDupIntxnReject(pMeta->tqConfigFlag)) {
|
||||
terrno = TSDB_CODE_TQ_META_KEY_DUP_IN_TXN;
|
||||
return -1;
|
||||
}
|
||||
if (pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInTxn);
|
||||
}
|
||||
}
|
||||
pNode->handle.valueInTxn = value;
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return 0;
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
STqMetaList* pNewNode = taosMemoryCalloc(1, sizeof(STqMetaList));
|
||||
if (pNewNode == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pNewNode->handle.key = key;
|
||||
pNewNode->handle.valueInTxn = value;
|
||||
pNewNode->next = pMeta->bucket[bucketKey];
|
||||
pMeta->bucket[bucketKey] = pNewNode;
|
||||
tqLinkUnpersist(pMeta, pNewNode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tqHandleMovePut(STqMetaStore* pMeta, int64_t key, void* value) { return tqHandlePutImpl(pMeta, key, value); }
|
||||
|
||||
int32_t tqHandleCopyPut(STqMetaStore* pMeta, int64_t key, void* value, size_t vsize) {
|
||||
void* vmem = taosMemoryMalloc(vsize);
|
||||
if (vmem == NULL) {
|
||||
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
memcpy(vmem, value, vsize);
|
||||
return tqHandlePutImpl(pMeta, key, vmem);
|
||||
}
|
||||
|
||||
static void* tqHandleGetUncommitted(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInTxn != NULL && pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
return pNode->handle.valueInTxn;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t tqHandleCommit(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInTxn == NULL) {
|
||||
terrno = TSDB_CODE_TQ_META_KEY_NOT_IN_TXN;
|
||||
return -1;
|
||||
}
|
||||
if (pNode->handle.valueInUse && pNode->handle.valueInUse != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInUse);
|
||||
}
|
||||
pNode->handle.valueInUse = pNode->handle.valueInTxn;
|
||||
pNode->handle.valueInTxn = NULL;
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return 0;
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
terrno = TSDB_CODE_TQ_META_NO_SUCH_KEY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tqHandleAbort(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInTxn) {
|
||||
if (pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
pMeta->pDeleter(pNode->handle.valueInTxn);
|
||||
}
|
||||
pNode->handle.valueInTxn = NULL;
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return 0;
|
||||
}
|
||||
terrno = TSDB_CODE_TQ_META_KEY_NOT_IN_TXN;
|
||||
return -1;
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
terrno = TSDB_CODE_TQ_META_NO_SUCH_KEY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tqHandleDel(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
if (pNode->handle.valueInTxn != TQ_DELETE_TOKEN) {
|
||||
if (pNode->handle.valueInTxn) {
|
||||
pMeta->pDeleter(pNode->handle.valueInTxn);
|
||||
}
|
||||
|
||||
pNode->handle.valueInTxn = TQ_DELETE_TOKEN;
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
terrno = TSDB_CODE_TQ_META_NO_SUCH_KEY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tqHandlePurge(STqMetaStore* pMeta, int64_t key) {
|
||||
int64_t bucketKey = key & TQ_BUCKET_MASK;
|
||||
STqMetaList* pNode = pMeta->bucket[bucketKey];
|
||||
while (pNode) {
|
||||
if (pNode->handle.key == key) {
|
||||
pNode->handle.valueInUse = TQ_DELETE_TOKEN;
|
||||
tqLinkUnpersist(pMeta, pNode);
|
||||
return 0;
|
||||
} else {
|
||||
pNode = pNode->next;
|
||||
}
|
||||
}
|
||||
terrno = TSDB_CODE_TQ_META_NO_SUCH_KEY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: clean deleted idx and data from persistent file
|
||||
int32_t tqStoreCompact(STqMetaStore* pMeta) { return 0; }
|
|
@ -1638,9 +1638,7 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa
|
|||
int32_t numOfColsOfRow1 = 0;
|
||||
|
||||
if (pSchema1 == NULL) {
|
||||
// pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row1));
|
||||
// TODO: use the real schemaVersion
|
||||
pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, 1);
|
||||
pSchema1 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row1));
|
||||
}
|
||||
|
||||
#ifdef TD_DEBUG_PRINT_ROW
|
||||
|
@ -1657,9 +1655,7 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa
|
|||
if (row2) {
|
||||
isRow2DataRow = TD_IS_TP_ROW(row2);
|
||||
if (pSchema2 == NULL) {
|
||||
// pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row2));
|
||||
// TODO: use the real schemaVersion
|
||||
pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, 1);
|
||||
pSchema2 = metaGetTbTSchema(REPO_META(pTsdbReadHandle->pTsdb), uid, TD_ROW_SVER(row2));
|
||||
}
|
||||
if (isRow2DataRow) {
|
||||
numOfColsOfRow2 = schemaNCols(pSchema2);
|
||||
|
|
|
@ -1,279 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
|
||||
#include "tqMetaStore.h"
|
||||
|
||||
struct Foo {
|
||||
int32_t a;
|
||||
};
|
||||
|
||||
int FooSerializer(const void* pObj, STqSerializedHead** ppHead) {
|
||||
Foo* foo = (Foo*)pObj;
|
||||
if ((*ppHead) == NULL || (*ppHead)->ssize < sizeof(STqSerializedHead) + sizeof(int32_t)) {
|
||||
*ppHead = (STqSerializedHead*)taosMemoryRealloc(*ppHead, sizeof(STqSerializedHead) + sizeof(int32_t));
|
||||
(*ppHead)->ssize = sizeof(STqSerializedHead) + sizeof(int32_t);
|
||||
}
|
||||
*(int32_t*)(*ppHead)->content = foo->a;
|
||||
return (*ppHead)->ssize;
|
||||
}
|
||||
|
||||
const void* FooDeserializer(const STqSerializedHead* pHead, void** ppObj) {
|
||||
if (*ppObj == NULL) {
|
||||
*ppObj = taosMemoryRealloc(*ppObj, sizeof(int32_t));
|
||||
}
|
||||
Foo* pFoo = *(Foo**)ppObj;
|
||||
pFoo->a = *(int32_t*)pHead->content;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FooDeleter(void* pObj) { taosMemoryFree(pObj); }
|
||||
|
||||
class TqMetaUpdateAppendTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
taosRemoveDir(pathName);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
}
|
||||
|
||||
void TearDown() override { tqStoreClose(pMeta); }
|
||||
|
||||
STqMetaStore* pMeta;
|
||||
const char* pathName = TD_TMP_DIR_PATH "tq_test";
|
||||
};
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, copyPutTest) {
|
||||
Foo foo;
|
||||
foo.a = 3;
|
||||
tqHandleCopyPut(pMeta, 1, &foo, sizeof(Foo));
|
||||
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
|
||||
tqHandleCommit(pMeta, 1);
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo->a, 3);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, persistTest) {
|
||||
Foo* pFoo = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pFoo->a = 2;
|
||||
tqHandleMovePut(pMeta, 1, pFoo);
|
||||
Foo* pBar = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pBar == NULL, true);
|
||||
tqHandleCommit(pMeta, 1);
|
||||
pBar = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pBar->a, pFoo->a);
|
||||
pBar = (Foo*)tqHandleGet(pMeta, 2);
|
||||
EXPECT_EQ(pBar == NULL, true);
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
pBar = (Foo*)tqHandleGet(pMeta, 1);
|
||||
ASSERT_EQ(pBar != NULL, true);
|
||||
EXPECT_EQ(pBar->a, 2);
|
||||
|
||||
pBar = (Foo*)tqHandleGet(pMeta, 2);
|
||||
EXPECT_EQ(pBar == NULL, true);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, uncommittedTest) {
|
||||
Foo* pFoo = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pFoo->a = 3;
|
||||
tqHandleMovePut(pMeta, 1, pFoo);
|
||||
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, abortTest) {
|
||||
Foo* pFoo = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pFoo->a = 3;
|
||||
tqHandleMovePut(pMeta, 1, pFoo);
|
||||
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
|
||||
tqHandleAbort(pMeta, 1);
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, deleteTest) {
|
||||
Foo* pFoo = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pFoo->a = 3;
|
||||
tqHandleMovePut(pMeta, 1, pFoo);
|
||||
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
|
||||
tqHandleCommit(pMeta, 1);
|
||||
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
ASSERT_EQ(pFoo != NULL, true);
|
||||
EXPECT_EQ(pFoo->a, 3);
|
||||
|
||||
tqHandleDel(pMeta, 1);
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
ASSERT_EQ(pFoo != NULL, true);
|
||||
EXPECT_EQ(pFoo->a, 3);
|
||||
|
||||
tqHandleCommit(pMeta, 1);
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
pFoo = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo == NULL, true);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, intxnPersist) {
|
||||
Foo* pFoo = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pFoo->a = 3;
|
||||
tqHandleMovePut(pMeta, 1, pFoo);
|
||||
tqHandleCommit(pMeta, 1);
|
||||
|
||||
Foo* pBar = (Foo*)taosMemoryMalloc(sizeof(Foo));
|
||||
pBar->a = 4;
|
||||
tqHandleMovePut(pMeta, 1, pBar);
|
||||
|
||||
Foo* pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo1->a, 3);
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo1->a, 3);
|
||||
|
||||
tqHandleCommit(pMeta, 1);
|
||||
|
||||
pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo1->a, 4);
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
pFoo1 = (Foo*)tqHandleGet(pMeta, 1);
|
||||
EXPECT_EQ(pFoo1->a, 4);
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, multiplePage) {
|
||||
taosSeedRand(0);
|
||||
std::vector<int> v;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
v.push_back(taosRand());
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
}
|
||||
for (int i = 0; i < 500; i++) {
|
||||
tqHandleCommit(pMeta, i);
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||
EXPECT_EQ(pFoo->a, v[i]);
|
||||
}
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
for (int i = 500; i < 1000; i++) {
|
||||
tqHandleCommit(pMeta, i);
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||
EXPECT_EQ(pFoo->a, v[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||
EXPECT_EQ(pFoo->a, v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, multipleRewrite) {
|
||||
taosSeedRand(0);
|
||||
std::vector<int> v;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
v.push_back(taosRand());
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 500; i++) {
|
||||
tqHandleCommit(pMeta, i);
|
||||
v[i] = taosRand();
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
}
|
||||
|
||||
for (int i = 500; i < 1000; i++) {
|
||||
v[i] = taosRand();
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
tqHandleCommit(pMeta, i);
|
||||
}
|
||||
|
||||
tqStoreClose(pMeta);
|
||||
pMeta = tqStoreOpen(pathName, FooSerializer, FooDeserializer, FooDeleter, TQ_UPDATE_APPEND);
|
||||
ASSERT(pMeta);
|
||||
|
||||
for (int i = 500; i < 1000; i++) {
|
||||
v[i] = taosRand();
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
tqHandleCommit(pMeta, i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||
EXPECT_EQ(pFoo->a, v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TqMetaUpdateAppendTest, dupCommit) {
|
||||
taosSeedRand(0);
|
||||
std::vector<int> v;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
v.push_back(taosRand());
|
||||
Foo foo;
|
||||
foo.a = v[i];
|
||||
tqHandleCopyPut(pMeta, i, &foo, sizeof(Foo));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int ret = tqHandleCommit(pMeta, i);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = tqHandleCommit(pMeta, i);
|
||||
EXPECT_EQ(ret, -1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int ret = tqHandleCommit(pMeta, i);
|
||||
EXPECT_EQ(ret, -1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
Foo* pFoo = (Foo*)tqHandleGet(pMeta, i);
|
||||
ASSERT_EQ(pFoo != NULL, true) << " at idx " << i << "\n";
|
||||
EXPECT_EQ(pFoo->a, v[i]);
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ static int32_t getSchemaBytes(const SSchema* pSchema) {
|
|||
case TSDB_DATA_TYPE_BINARY:
|
||||
return (pSchema->bytes - VARSTR_HEADER_SIZE);
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
return (pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
default:
|
||||
return pSchema->bytes;
|
||||
|
|
|
@ -106,7 +106,7 @@ static void destroyTableQueryInfoImpl(STableQueryInfo* pTableQueryInfo);
|
|||
|
||||
static SColumnInfo* extractColumnFilterInfo(SExprInfo* pExpr, int32_t numOfOutput, int32_t* numOfFilterCols);
|
||||
|
||||
static void releaseQueryBuf(size_t numOfTables);
|
||||
static void releaseQueryBuf(size_t numOfTables);
|
||||
|
||||
static int32_t getNumOfScanTimes(STaskAttr* pQueryAttr);
|
||||
|
||||
|
@ -154,8 +154,9 @@ SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn,
|
|||
|
||||
void operatorDummyCloseFn(void* param, int32_t numOfCols) {}
|
||||
|
||||
static int32_t doCopyToSDataBlock(SExecTaskInfo* taskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo,
|
||||
const int32_t* rowCellOffset, SqlFunctionCtx* pCtx, int32_t numOfExprs);
|
||||
static int32_t doCopyToSDataBlock(SExecTaskInfo* taskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo,
|
||||
SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo, const int32_t* rowCellOffset,
|
||||
SqlFunctionCtx* pCtx, int32_t numOfExprs);
|
||||
|
||||
static void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size);
|
||||
static void setResultBufSize(STaskAttr* pQueryAttr, SResultInfo* pResultInfo);
|
||||
|
@ -182,10 +183,10 @@ static int compareRowData(const void* a, const void* b, const void* userData) {
|
|||
|
||||
int16_t offset = supporter->dataOffset;
|
||||
return 0;
|
||||
// char* in1 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page1, pRow1->offset, offset);
|
||||
// char* in2 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page2, pRow2->offset, offset);
|
||||
// char* in1 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page1, pRow1->offset, offset);
|
||||
// char* in2 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page2, pRow2->offset, offset);
|
||||
|
||||
// return (in1 != NULL && in2 != NULL) ? supporter->comFunc(in1, in2) : 0;
|
||||
// return (in1 != NULL && in2 != NULL) ? supporter->comFunc(in1, in2) : 0;
|
||||
}
|
||||
|
||||
// setup the output buffer for each operator
|
||||
|
@ -582,8 +583,9 @@ void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow
|
|||
colDataAppendInt64(pColData, 4, &pQueryWindow->ekey);
|
||||
}
|
||||
|
||||
void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow* pWin, SColumnInfoData* pTimeWindowData, int32_t offset,
|
||||
int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput, int32_t order) {
|
||||
void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow* pWin,
|
||||
SColumnInfoData* pTimeWindowData, int32_t offset, int32_t forwardStep, TSKEY* tsCol,
|
||||
int32_t numOfTotal, int32_t numOfOutput, int32_t order) {
|
||||
for (int32_t k = 0; k < numOfOutput; ++k) {
|
||||
// keep it temporarily
|
||||
bool hasAgg = pCtx[k].input.colDataAggIsSet;
|
||||
|
@ -665,8 +667,8 @@ static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SqlFunctionCtx* pC
|
|||
}
|
||||
}
|
||||
|
||||
void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order, int32_t scanFlag,
|
||||
bool createDummyCol) {
|
||||
void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
|
||||
int32_t scanFlag, bool createDummyCol) {
|
||||
if (pBlock->pBlockAgg != NULL) {
|
||||
doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
|
||||
} else {
|
||||
|
@ -717,7 +719,7 @@ static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunc
|
|||
}
|
||||
|
||||
static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
|
||||
int32_t scanFlag, bool createDummyCol) {
|
||||
int32_t scanFlag, bool createDummyCol) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
for (int32_t i = 0; i < pOperator->numOfExprs; ++i) {
|
||||
|
@ -725,7 +727,7 @@ static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCt
|
|||
pCtx[i].input.numOfRows = pBlock->info.rows;
|
||||
|
||||
pCtx[i].pSrcBlock = pBlock;
|
||||
pCtx[i].scanFlag = scanFlag;
|
||||
pCtx[i].scanFlag = scanFlag;
|
||||
|
||||
SInputColumnInfoData* pInput = &pCtx[i].input;
|
||||
pInput->uid = pBlock->info.uid;
|
||||
|
@ -834,7 +836,7 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
|
|||
SColumnInfoData idata = {.info = pResColData->info, .hasNull = true};
|
||||
|
||||
SScalarParam dest = {.columnData = &idata};
|
||||
int32_t code = scalarCalculate(pExpr[k].pExpr->_optrRoot.pRootNode, pBlockList, &dest);
|
||||
int32_t code = scalarCalculate(pExpr[k].pExpr->_optrRoot.pRootNode, pBlockList, &dest);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
taosArrayDestroy(pBlockList);
|
||||
return code;
|
||||
|
@ -852,7 +854,7 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc
|
|||
// _rowts/_c0, not tbname column
|
||||
if (fmIsPseudoColumnFunc(pfCtx->functionId) && (!fmIsScanPseudoColumnFunc(pfCtx->functionId))) {
|
||||
// do nothing
|
||||
} else if (fmIsNonstandardSQLFunc(pfCtx->functionId)) {
|
||||
} else if (fmIsIndefiniteRowsFunc(pfCtx->functionId)) {
|
||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[k]);
|
||||
pfCtx->fpSet.init(&pCtx[k], pResInfo);
|
||||
|
||||
|
@ -950,14 +952,14 @@ static bool functionNeedToExecute(SqlFunctionCtx* pCtx) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_FIRST) {
|
||||
// // return QUERY_IS_ASC_QUERY(pQueryAttr);
|
||||
// }
|
||||
//
|
||||
// // denote the order type
|
||||
// if ((functionId == FUNCTION_LAST_DST || functionId == FUNCTION_LAST)) {
|
||||
// // return pCtx->param[0].i == pQueryAttr->order.order;
|
||||
// }
|
||||
// if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_FIRST) {
|
||||
// // return QUERY_IS_ASC_QUERY(pQueryAttr);
|
||||
// }
|
||||
//
|
||||
// // denote the order type
|
||||
// if ((functionId == FUNCTION_LAST_DST || functionId == FUNCTION_LAST)) {
|
||||
// // return pCtx->param[0].i == pQueryAttr->order.order;
|
||||
// }
|
||||
|
||||
// in the reverse table scan, only the following functions need to be executed
|
||||
// if (IS_REVERSE_SCAN(pRuntimeEnv) ||
|
||||
|
@ -1072,19 +1074,19 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu
|
|||
for (int32_t i = 0; i < numOfOutput; ++i) {
|
||||
if (strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
|
||||
pValCtx[num++] = &pCtx[i];
|
||||
} else if (fmIsAggFunc(pCtx[i].functionId)) {
|
||||
} else if (fmIsSelectFunc(pCtx[i].functionId)) {
|
||||
p = &pCtx[i];
|
||||
}
|
||||
// if (functionId == FUNCTION_TAG_DUMMY || functionId == FUNCTION_TS_DUMMY) {
|
||||
// tagLen += pCtx[i].resDataInfo.bytes;
|
||||
// pTagCtx[num++] = &pCtx[i];
|
||||
// } else if (functionId == FUNCTION_TS || functionId == FUNCTION_TAG) {
|
||||
// // tag function may be the group by tag column
|
||||
// // ts may be the required primary timestamp column
|
||||
// continue;
|
||||
// } else {
|
||||
// // the column may be the normal column, group by normal_column, the functionId is FUNCTION_PRJ
|
||||
// }
|
||||
// if (functionId == FUNCTION_TAG_DUMMY || functionId == FUNCTION_TS_DUMMY) {
|
||||
// tagLen += pCtx[i].resDataInfo.bytes;
|
||||
// pTagCtx[num++] = &pCtx[i];
|
||||
// } else if (functionId == FUNCTION_TS || functionId == FUNCTION_TAG) {
|
||||
// // tag function may be the group by tag column
|
||||
// // ts may be the required primary timestamp column
|
||||
// continue;
|
||||
// } else {
|
||||
// // the column may be the normal column, group by normal_column, the functionId is FUNCTION_PRJ
|
||||
// }
|
||||
}
|
||||
|
||||
if (p != NULL) {
|
||||
|
@ -1123,7 +1125,7 @@ SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput,
|
|||
SFuncExecEnv env = {0};
|
||||
pCtx->functionId = pExpr->pExpr->_function.pFunctNode->funcId;
|
||||
|
||||
if (fmIsAggFunc(pCtx->functionId) || fmIsNonstandardSQLFunc(pCtx->functionId)) {
|
||||
if (fmIsAggFunc(pCtx->functionId) || fmIsIndefiniteRowsFunc(pCtx->functionId)) {
|
||||
bool isUdaf = fmIsUserDefinedFunc(pCtx->functionId);
|
||||
if (!isUdaf) {
|
||||
fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet);
|
||||
|
@ -1882,7 +1884,7 @@ void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numO
|
|||
}
|
||||
|
||||
static void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowRes, bool keep);
|
||||
void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock, SArray* pColMatchInfo) {
|
||||
void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock, SArray* pColMatchInfo) {
|
||||
if (pFilterNode == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -2005,8 +2007,9 @@ static void doUpdateNumOfRows(SResultRow* pRow, int32_t numOfExprs, const int32_
|
|||
}
|
||||
}
|
||||
|
||||
int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo,
|
||||
const int32_t* rowCellOffset, SqlFunctionCtx* pCtx, int32_t numOfExprs) {
|
||||
int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf,
|
||||
SGroupResInfo* pGroupResInfo, const int32_t* rowCellOffset, SqlFunctionCtx* pCtx,
|
||||
int32_t numOfExprs) {
|
||||
int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
|
||||
int32_t start = pGroupResInfo->index;
|
||||
|
||||
|
@ -2055,11 +2058,11 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
|
|||
} else {
|
||||
// expand the result into multiple rows. E.g., _wstartts, top(k, 20)
|
||||
// the _wstartts needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||
char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
|
||||
for(int32_t k = 0; k < pRow->numOfRows; ++k) {
|
||||
colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
|
||||
}
|
||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
|
||||
char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
|
||||
for (int32_t k = 0; k < pRow->numOfRows; ++k) {
|
||||
colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2070,14 +2073,16 @@ int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprI
|
|||
}
|
||||
}
|
||||
|
||||
qDebug("%s result generated, rows:%d, groupId:%"PRIu64, GET_TASKID(pTaskInfo), pBlock->info.rows, pBlock->info.groupId);
|
||||
qDebug("%s result generated, rows:%d, groupId:%" PRIu64, GET_TASKID(pTaskInfo), pBlock->info.rows,
|
||||
pBlock->info.groupId);
|
||||
blockDataUpdateTsWindow(pBlock, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, SDiskbasedBuf* pBuf) {
|
||||
SExprInfo* pExprInfo = pOperator->pExpr;
|
||||
int32_t numOfExprs = pOperator->numOfExprs;
|
||||
void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo,
|
||||
SDiskbasedBuf* pBuf) {
|
||||
SExprInfo* pExprInfo = pOperator->pExpr;
|
||||
int32_t numOfExprs = pOperator->numOfExprs;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
||||
int32_t* rowCellOffset = pbInfo->rowCellInfoOffset;
|
||||
|
@ -2746,10 +2751,10 @@ int32_t setSDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadI
|
|||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumnInfoData idata = {0};
|
||||
|
||||
idata.info.type = pSchema[i].type;
|
||||
idata.info.type = pSchema[i].type;
|
||||
idata.info.bytes = pSchema[i].bytes;
|
||||
idata.info.colId = pSchema[i].colId;
|
||||
idata.hasNull = true;
|
||||
idata.hasNull = true;
|
||||
|
||||
taosArrayPush(pBlock->pDataBlock, &idata);
|
||||
if (IS_VAR_DATA_TYPE(idata.info.type)) {
|
||||
|
@ -3099,7 +3104,7 @@ static int32_t initDataSource(int32_t numOfSources, SExchangeInfo* pInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SOperatorInfo* createExchangeOperatorInfo(void *pTransporter, const SNodeList* pSources, SSDataBlock* pBlock,
|
||||
SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, const SNodeList* pSources, SSDataBlock* pBlock,
|
||||
SExecTaskInfo* pTaskInfo) {
|
||||
SExchangeInfo* pInfo = taosMemoryCalloc(1, sizeof(SExchangeInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
|
@ -3212,7 +3217,7 @@ static bool needToMerge(SSDataBlock* pBlock, SArray* groupInfo, char** buf, int3
|
|||
static void doMergeResultImpl(SSortedMergeOperatorInfo* pInfo, SqlFunctionCtx* pCtx, int32_t numOfExpr,
|
||||
int32_t rowIndex) {
|
||||
for (int32_t j = 0; j < numOfExpr; ++j) { // TODO set row index
|
||||
// pCtx[j].startRow = rowIndex;
|
||||
// pCtx[j].startRow = rowIndex;
|
||||
}
|
||||
|
||||
for (int32_t j = 0; j < numOfExpr; ++j) {
|
||||
|
@ -3263,7 +3268,7 @@ static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock
|
|||
|
||||
SqlFunctionCtx* pCtx = pInfo->binfo.pCtx;
|
||||
for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
|
||||
// pCtx[i].size = 1;
|
||||
// pCtx[i].size = 1;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pBlock->info.rows; ++i) {
|
||||
|
@ -3489,10 +3494,11 @@ _error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t *order, int32_t* scanFlag) {
|
||||
int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scanFlag) {
|
||||
// todo add more information about exchange operation
|
||||
int32_t type = pOperator->operatorType;
|
||||
if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
|
||||
if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN ||
|
||||
type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
|
||||
*order = TSDB_ORDER_ASC;
|
||||
*scanFlag = MAIN_SCAN;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -3520,7 +3526,7 @@ static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
|
|||
SAggOperatorInfo* pAggInfo = pOperator->info;
|
||||
|
||||
SOptrBasicInfo* pInfo = &pAggInfo->binfo;
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
SOperatorInfo* downstream = pOperator->pDownstream[0];
|
||||
|
||||
int32_t order = TSDB_ORDER_ASC;
|
||||
int32_t scanFlag = MAIN_SCAN;
|
||||
|
@ -3859,7 +3865,8 @@ static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
|
|||
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order, scanFlag, false);
|
||||
blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);
|
||||
|
||||
code = projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfExprs, pProjectInfo->pPseudoColInfo);
|
||||
code = projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfExprs,
|
||||
pProjectInfo->pPseudoColInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
longjmp(pTaskInfo->env, code);
|
||||
}
|
||||
|
@ -4109,7 +4116,7 @@ static STableQueryInfo* initTableQueryInfo(const STableGroupInfo* pTableGroupInf
|
|||
for (int32_t i = 0; i < taosArrayGetSize(pTableGroupInfo->pGroupList); ++i) {
|
||||
SArray* pa = taosArrayGetP(pTableGroupInfo->pGroupList, i);
|
||||
for (int32_t j = 0; j < taosArrayGetSize(pa); ++j) {
|
||||
STableKeyInfo* pk = taosArrayGet(pa, j);
|
||||
STableKeyInfo* pk = taosArrayGet(pa, j);
|
||||
STableQueryInfo* pTQueryInfo = &pTableQueryInfo[index++];
|
||||
pTQueryInfo->lastKey = pk->lastKey;
|
||||
}
|
||||
|
@ -4245,9 +4252,9 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SExprInfo* p
|
|||
goto _error;
|
||||
}
|
||||
|
||||
pInfo->limit = *pLimit;
|
||||
pInfo->slimit = *pSlimit;
|
||||
pInfo->curOffset = pLimit->offset;
|
||||
pInfo->limit = *pLimit;
|
||||
pInfo->slimit = *pSlimit;
|
||||
pInfo->curOffset = pLimit->offset;
|
||||
pInfo->curSOffset = pSlimit->offset;
|
||||
|
||||
pInfo->binfo.pRes = pResBlock;
|
||||
|
@ -4266,15 +4273,15 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SExprInfo* p
|
|||
initAggInfo(&pInfo->binfo, &pInfo->aggSup, pExprInfo, numOfCols, pResBlock, keyBufSize, pTaskInfo->id.str);
|
||||
setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfCols, pTaskInfo);
|
||||
|
||||
pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pInfo->binfo.pCtx, numOfCols);
|
||||
pOperator->name = "ProjectOperator";
|
||||
pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pInfo->binfo.pCtx, numOfCols);
|
||||
pOperator->name = "ProjectOperator";
|
||||
pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pExpr = pExprInfo;
|
||||
pOperator->numOfExprs = num;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
pOperator->blocking = false;
|
||||
pOperator->status = OP_NOT_OPENED;
|
||||
pOperator->info = pInfo;
|
||||
pOperator->pExpr = pExprInfo;
|
||||
pOperator->numOfExprs = num;
|
||||
pOperator->pTaskInfo = pTaskInfo;
|
||||
|
||||
pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doProjectOperation, NULL, NULL,
|
||||
destroyProjectOperatorInfo, NULL, NULL, NULL);
|
||||
|
@ -4393,10 +4400,10 @@ static SColumn* createColumn(int32_t blockId, int32_t slotId, int32_t colId, SDa
|
|||
}
|
||||
|
||||
pCol->slotId = slotId;
|
||||
pCol->colId = colId;
|
||||
pCol->bytes = pType->bytes;
|
||||
pCol->type = pType->type;
|
||||
pCol->scale = pType->scale;
|
||||
pCol->colId = colId;
|
||||
pCol->bytes = pType->bytes;
|
||||
pCol->type = pType->type;
|
||||
pCol->scale = pType->scale;
|
||||
pCol->precision = pType->precision;
|
||||
pCol->dataBlockId = blockId;
|
||||
|
||||
|
@ -4471,10 +4478,10 @@ SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t*
|
|||
if (strcmp(pExp->pExpr->_function.functionName, "tbname") == 0) {
|
||||
pFuncNode->pParameterList = nodesMakeList();
|
||||
ASSERT(LIST_LENGTH(pFuncNode->pParameterList) == 0);
|
||||
SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
|
||||
if (NULL == res) { // todo handle error
|
||||
SValueNode* res = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
|
||||
if (NULL == res) { // todo handle error
|
||||
} else {
|
||||
res->node.resType = (SDataType) {.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
|
||||
res->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
|
||||
nodesListAppend(pFuncNode->pParameterList, res);
|
||||
}
|
||||
}
|
||||
|
@ -4544,7 +4551,7 @@ static SArray* extractColumnInfo(SNodeList* pNodeList);
|
|||
static SArray* createSortInfo(SNodeList* pNodeList);
|
||||
static SArray* extractPartitionColInfo(SNodeList* pNodeList);
|
||||
|
||||
void extractTableSchemaVersion(SReadHandle *pHandle, uint64_t uid, SExecTaskInfo* pTaskInfo) {
|
||||
void extractTableSchemaVersion(SReadHandle* pHandle, uint64_t uid, SExecTaskInfo* pTaskInfo) {
|
||||
SMetaReader mr = {0};
|
||||
metaReaderInit(&mr, pHandle->meta, 0);
|
||||
metaGetTableEntryByUid(&mr, uid);
|
||||
|
@ -4591,7 +4598,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
SSDataBlock* pResBlock = createResDataBlock(pExchange->node.pOutputDataBlockDesc);
|
||||
return createExchangeOperatorInfo(pHandle->pMsgCb->clientRpc, pExchange->pSrcEndPoints, pResBlock, pTaskInfo);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) {
|
||||
SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; // simple child table.
|
||||
SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode; // simple child table.
|
||||
STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
|
||||
|
||||
int32_t numOfCols = 0;
|
||||
|
@ -4600,8 +4607,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
if (pHandle->vnode) {
|
||||
pDataReader = doCreateDataReader(pTableScanNode, pHandle, pTableGroupInfo, (uint64_t)queryId, taskId);
|
||||
} else {
|
||||
doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo,
|
||||
queryId, taskId);
|
||||
doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId);
|
||||
}
|
||||
|
||||
if (pDataReader == NULL && terrno != 0) {
|
||||
|
@ -4612,15 +4618,17 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
}
|
||||
|
||||
SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;
|
||||
SOperatorInfo* pOperatorDumy = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
|
||||
SOperatorInfo* pOperatorDumy = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
|
||||
|
||||
SArray* tableIdList = extractTableIdList(pTableGroupInfo);
|
||||
|
||||
SSDataBlock* pResBlock = createResDataBlock(pDescNode);
|
||||
SArray* pCols = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, pTaskInfo, COL_MATCH_FROM_COL_ID);
|
||||
SArray* pCols =
|
||||
extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, pTaskInfo, COL_MATCH_FROM_COL_ID);
|
||||
|
||||
SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pDataReader, pHandle, pScanPhyNode->uid, pResBlock, pCols, tableIdList, pTaskInfo,
|
||||
pScanPhyNode->node.pConditions, pOperatorDumy);
|
||||
SOperatorInfo* pOperator =
|
||||
createStreamScanOperatorInfo(pHandle->reader, pDataReader, pHandle, pScanPhyNode->uid, pResBlock, pCols,
|
||||
tableIdList, pTaskInfo, pScanPhyNode->node.pConditions, pOperatorDumy);
|
||||
taosArrayDestroy(tableIdList);
|
||||
return pOperator;
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
|
||||
|
@ -4632,7 +4640,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
SSDataBlock* pResBlock = createResDataBlock(pDescNode);
|
||||
|
||||
int32_t numOfOutputCols = 0;
|
||||
SArray* colList = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfOutputCols, pTaskInfo, COL_MATCH_FROM_COL_ID);
|
||||
SArray* colList =
|
||||
extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfOutputCols, pTaskInfo, COL_MATCH_FROM_COL_ID);
|
||||
SOperatorInfo* pOperator = createSysTableScanOperatorInfo(
|
||||
pHandle, pResBlock, &pScanNode->tableName, pScanNode->node.pConditions, pSysScanPhyNode->mgmtEpSet, colList,
|
||||
pTaskInfo, pSysScanPhyNode->showRewrite, pSysScanPhyNode->accountId);
|
||||
|
@ -4654,8 +4663,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
SExprInfo* pExprInfo = createExprInfo(pScanPhyNode->pScanPseudoCols, NULL, &num);
|
||||
|
||||
int32_t numOfOutputCols = 0;
|
||||
SArray* colList =
|
||||
extractColMatchInfo(pScanPhyNode->pScanPseudoCols, pDescNode, &numOfOutputCols, pTaskInfo, COL_MATCH_FROM_COL_ID);
|
||||
SArray* colList = extractColMatchInfo(pScanPhyNode->pScanPseudoCols, pDescNode, &numOfOutputCols, pTaskInfo,
|
||||
COL_MATCH_FROM_COL_ID);
|
||||
|
||||
SOperatorInfo* pOperator =
|
||||
createTagScanOperatorInfo(pHandle, pExprInfo, num, pResBlock, colList, pTableGroupInfo, pTaskInfo);
|
||||
|
@ -4737,7 +4746,8 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols);
|
||||
|
||||
int32_t numOfOutputCols = 0;
|
||||
SArray* pColList = extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, pTaskInfo, COL_MATCH_FROM_SLOT_ID);
|
||||
SArray* pColList =
|
||||
extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, pTaskInfo, COL_MATCH_FROM_SLOT_ID);
|
||||
|
||||
pOptr = createSortOperatorInfo(ops[0], pResBlock, info, pExprInfo, numOfCols, pColList, pTaskInfo);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW == type) {
|
||||
|
@ -4769,7 +4779,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo
|
|||
int32_t tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
|
||||
|
||||
SColumnNode* pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
|
||||
SColumn col = extractColumnFromColumnNode(pColNode);
|
||||
SColumn col = extractColumnFromColumnNode(pColNode);
|
||||
pOptr = createStatewindowOperatorInfo(ops[0], pExprInfo, num, pResBlock, &as, tsSlotId, &col, pTaskInfo);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_JOIN == type) {
|
||||
SJoinPhysiNode* pJoinNode = (SJoinPhysiNode*)pPhyNode;
|
||||
|
@ -4837,11 +4847,11 @@ int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysi
|
|||
|
||||
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
|
||||
SColumn c = {0};
|
||||
c.slotId = pColNode->slotId;
|
||||
c.colId = pColNode->colId;
|
||||
c.type = pColNode->node.resType.type;
|
||||
c.bytes = pColNode->node.resType.bytes;
|
||||
c.scale = pColNode->node.resType.scale;
|
||||
c.slotId = pColNode->slotId;
|
||||
c.colId = pColNode->colId;
|
||||
c.type = pColNode->node.resType.type;
|
||||
c.bytes = pColNode->node.resType.bytes;
|
||||
c.scale = pColNode->node.resType.scale;
|
||||
c.precision = pColNode->node.resType.precision;
|
||||
return c;
|
||||
}
|
||||
|
@ -5238,15 +5248,15 @@ int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SExplainExecInfo
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t initCatchSupporter(SCatchSupporter* pCatchSup, size_t rowSize, size_t keyBufSize,
|
||||
const char* pKey, const char* pDir) {
|
||||
int32_t initCatchSupporter(SCatchSupporter* pCatchSup, size_t rowSize, size_t keyBufSize, const char* pKey,
|
||||
const char* pDir) {
|
||||
pCatchSup->keySize = sizeof(int64_t) + sizeof(int64_t) + sizeof(TSKEY);
|
||||
pCatchSup->pKeyBuf = taosMemoryCalloc(1, pCatchSup->keySize);
|
||||
int32_t pageSize = rowSize * 32;
|
||||
int32_t bufSize = pageSize * 4096;
|
||||
createDiskbasedBuf(&pCatchSup->pDataBuf, pageSize, bufSize, pKey, pDir);
|
||||
_hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
|
||||
pCatchSup->pWindowHashTable = taosHashInit(10000, hashFn, true, HASH_NO_LOCK);;
|
||||
pCatchSup->pWindowHashTable = taosHashInit(10000, hashFn, true, HASH_NO_LOCK);
|
||||
;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ extern "C" {
|
|||
|
||||
#define FUNC_MGT_AGG_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(0)
|
||||
#define FUNC_MGT_SCALAR_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(1)
|
||||
#define FUNC_MGT_NONSTANDARD_SQL_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(2)
|
||||
#define FUNC_MGT_INDEFINITE_ROWS_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(2)
|
||||
#define FUNC_MGT_STRING_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(3)
|
||||
#define FUNC_MGT_DATETIME_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(4)
|
||||
#define FUNC_MGT_TIMELINE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(5)
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
*/
|
||||
|
||||
#include "builtins.h"
|
||||
#include "querynodes.h"
|
||||
#include "builtinsimpl.h"
|
||||
#include "querynodes.h"
|
||||
#include "scalar.h"
|
||||
#include "taoserror.h"
|
||||
#include "tdatablock.h"
|
||||
|
@ -185,6 +185,19 @@ static int32_t translateApercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
if (!IS_NUMERIC_TYPE(para1Type) || !IS_INTEGER_TYPE(para2Type)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
SNode* pParamNode = nodesListGetNode(pFunc->pParameterList, 1);
|
||||
if (nodeType(pParamNode) != QUERY_NODE_VALUE) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
SValueNode* pValue = (SValueNode*)pParamNode;
|
||||
if (pValue->datum.i < 0 || pValue->datum.i > 100) {
|
||||
return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pValue->notReserved = true;
|
||||
|
||||
if (3 == paraNum) {
|
||||
SNode* pPara3 = nodesListGetNode(pFunc->pParameterList, 2);
|
||||
if (QUERY_NODE_VALUE != nodeType(pPara3) || !validAperventileAlgo((SValueNode*)pPara3)) {
|
||||
|
@ -215,7 +228,7 @@ static int32_t translateTop(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
SValueNode* pValue = (SValueNode*) pParamNode;
|
||||
SValueNode* pValue = (SValueNode*)pParamNode;
|
||||
if (pValue->node.resType.type != TSDB_DATA_TYPE_BIGINT) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
@ -224,6 +237,8 @@ static int32_t translateTop(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pValue->notReserved = true;
|
||||
|
||||
SDataType* pType = &((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
|
||||
pFunc->node.resType = (SDataType){.bytes = pType->bytes, .type = pType->type};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -336,7 +351,7 @@ static int32_t translateStateCount(SFunctionNode* pFunc, char* pErrBuf, int32_t
|
|||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT };
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -361,7 +376,7 @@ static int32_t translateStateDuration(SFunctionNode* pFunc, char* pErrBuf, int32
|
|||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT };
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -392,7 +407,7 @@ static int32_t translateCsum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[resType].bytes, .type = resType};
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -434,7 +449,7 @@ static int32_t translateSample(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
}
|
||||
|
||||
SExprNode* pCol = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||
uint8_t colType = pCol->resType.type;
|
||||
uint8_t colType = pCol->resType.type;
|
||||
if (IS_VAR_DATA_TYPE(colType)) {
|
||||
pFunc->node.resType = (SDataType){.bytes = pCol->resType.bytes, .type = colType};
|
||||
} else {
|
||||
|
@ -463,7 +478,7 @@ static int32_t translateTail(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
}
|
||||
|
||||
SExprNode* pCol = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||
uint8_t colType = pCol->resType.type;
|
||||
uint8_t colType = pCol->resType.type;
|
||||
if (IS_VAR_DATA_TYPE(colType)) {
|
||||
pFunc->node.resType = (SDataType){.bytes = pCol->resType.bytes, .type = colType};
|
||||
} else {
|
||||
|
@ -500,8 +515,7 @@ static int32_t translateUnique(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
|
||||
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
if (QUERY_NODE_COLUMN != nodeType(pPara)) {
|
||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
||||
"The parameters of UNIQUE can only be columns");
|
||||
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of UNIQUE can only be columns");
|
||||
}
|
||||
|
||||
pFunc->node.resType = ((SExprNode*)pPara)->resType;
|
||||
|
@ -823,7 +837,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "top",
|
||||
.type = FUNCTION_TYPE_TOP,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC,
|
||||
.classification = FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC,
|
||||
.translateFunc = translateTop,
|
||||
.getEnvFunc = getTopBotFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
|
@ -833,7 +847,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "bottom",
|
||||
.type = FUNCTION_TYPE_BOTTOM,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC,
|
||||
.classification = FUNC_MGT_SELECT_FUNC | FUNC_MGT_INDEFINITE_ROWS_FUNC,
|
||||
.translateFunc = translateBottom,
|
||||
.getEnvFunc = getTopBotFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
|
@ -915,7 +929,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "diff",
|
||||
.type = FUNCTION_TYPE_DIFF,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateDiff,
|
||||
.getEnvFunc = getDiffFuncEnv,
|
||||
.initFunc = diffFunctionSetup,
|
||||
|
@ -925,7 +939,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "state_count",
|
||||
.type = FUNCTION_TYPE_STATE_COUNT,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC,
|
||||
.translateFunc = translateStateCount,
|
||||
.getEnvFunc = getStateFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
|
@ -935,7 +949,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "state_duration",
|
||||
.type = FUNCTION_TYPE_STATE_DURATION,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateStateDuration,
|
||||
.getEnvFunc = getStateFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
|
@ -945,7 +959,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "csum",
|
||||
.type = FUNCTION_TYPE_CSUM,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateCsum,
|
||||
.getEnvFunc = getCsumFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
|
@ -955,7 +969,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "mavg",
|
||||
.type = FUNCTION_TYPE_MAVG,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateMavg,
|
||||
.getEnvFunc = getMavgFuncEnv,
|
||||
.initFunc = mavgFunctionSetup,
|
||||
|
@ -965,7 +979,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "sample",
|
||||
.type = FUNCTION_TYPE_SAMPLE,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateSample,
|
||||
.getEnvFunc = getSampleFuncEnv,
|
||||
.initFunc = sampleFunctionSetup,
|
||||
|
@ -975,7 +989,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "tail",
|
||||
.type = FUNCTION_TYPE_TAIL,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateTail,
|
||||
.getEnvFunc = getTailFuncEnv,
|
||||
.initFunc = tailFunctionSetup,
|
||||
|
@ -985,7 +999,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "unique",
|
||||
.type = FUNCTION_TYPE_UNIQUE,
|
||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.classification = FUNC_MGT_INDEFINITE_ROWS_FUNC | FUNC_MGT_TIMELINE_FUNC,
|
||||
.translateFunc = translateUnique,
|
||||
.getEnvFunc = getUniqueFuncEnv,
|
||||
.initFunc = uniqueFunctionSetup,
|
||||
|
|
|
@ -145,6 +145,8 @@ bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MG
|
|||
|
||||
bool fmIsScalarFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCALAR_FUNC); }
|
||||
|
||||
bool fmIsVectorFunc(int32_t funcId) { return !fmIsScalarFunc(funcId); }
|
||||
|
||||
bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SELECT_FUNC); }
|
||||
|
||||
bool fmIsTimelineFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_TIMELINE_FUNC); }
|
||||
|
@ -157,7 +159,7 @@ bool fmIsWindowPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(
|
|||
|
||||
bool fmIsWindowClauseFunc(int32_t funcId) { return fmIsAggFunc(funcId) || fmIsWindowPseudoColumnFunc(funcId); }
|
||||
|
||||
bool fmIsNonstandardSQLFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_NONSTANDARD_SQL_FUNC); }
|
||||
bool fmIsIndefiniteRowsFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_INDEFINITE_ROWS_FUNC); }
|
||||
|
||||
bool fmIsSpecialDataRequiredFunc(int32_t funcId) {
|
||||
return isSpecificClassifyFunc(funcId, FUNC_MGT_SPECIAL_DATA_REQUIRED);
|
||||
|
|
|
@ -138,6 +138,7 @@ static void udfdCtrlReadCb(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf);
|
|||
static int32_t udfdUvInit();
|
||||
static void udfdCloseWalkCb(uv_handle_t *handle, void *arg);
|
||||
static int32_t udfdRun();
|
||||
static void udfdConnectMnodeThreadFunc(void* args);
|
||||
|
||||
void udfdProcessRequest(uv_work_t *req) {
|
||||
SUvUdfWork *uvUdf = (SUvUdfWork *)(req->data);
|
||||
|
@ -870,6 +871,23 @@ static int32_t udfdRun() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void udfdConnectMnodeThreadFunc(void* args) {
|
||||
int32_t retryMnodeTimes = 0;
|
||||
int32_t code = 0;
|
||||
while (retryMnodeTimes++ <= TSDB_MAX_REPLICA) {
|
||||
uv_sleep(100 * (1 << retryMnodeTimes));
|
||||
code = udfdConnectToMnode();
|
||||
if (code == 0) {
|
||||
break;
|
||||
}
|
||||
fnError("udfd can not connect to mnode, code: %s. retry", tstrerror(code));
|
||||
}
|
||||
|
||||
if (code != 0) {
|
||||
fnError("udfd can not connect to mnode");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!taosCheckSystemIsSmallEnd()) {
|
||||
printf("failed to start since on non-small-end machines\n");
|
||||
|
@ -902,30 +920,18 @@ int main(int argc, char *argv[]) {
|
|||
return -3;
|
||||
}
|
||||
|
||||
int32_t retryMnodeTimes = 0;
|
||||
int32_t code = 0;
|
||||
while (retryMnodeTimes++ <= TSDB_MAX_REPLICA) {
|
||||
uv_sleep(100 * (1 << retryMnodeTimes));
|
||||
code = udfdConnectToMnode();
|
||||
if (code == 0) {
|
||||
break;
|
||||
}
|
||||
fnError("can not connect to mnode, code: %s. retry", tstrerror(code));
|
||||
}
|
||||
|
||||
if (code != 0) {
|
||||
fnError("failed to start since can not connect to mnode");
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (udfdUvInit() != 0) {
|
||||
fnError("uv init failure");
|
||||
return -5;
|
||||
}
|
||||
|
||||
uv_thread_t mnodeConnectThread;
|
||||
uv_thread_create(&mnodeConnectThread, udfdConnectMnodeThreadFunc, NULL);
|
||||
|
||||
udfdRun();
|
||||
|
||||
removeListeningPipe();
|
||||
uv_thread_join(&mnodeConnectThread);
|
||||
udfdCloseClientRpc();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -34,7 +34,7 @@ if (${BUILD_WITH_INVERTEDINDEX})
|
|||
endif(${BUILD_WITH_INVERTEDINDEX})
|
||||
|
||||
|
||||
#if (${BUILD_TEST})
|
||||
# add_subdirectory(test)
|
||||
#endif(${BUILD_TEST})
|
||||
if (${BUILD_TEST})
|
||||
add_subdirectory(test)
|
||||
endif(${BUILD_TEST})
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct TFileHeader {
|
|||
} TFileHeader;
|
||||
#pragma pack(pop)
|
||||
|
||||
#define TFILE_HEADER_SIZE (sizeof(TFileHeader))
|
||||
#define TFILE_HEADER_SIZE (sizeof(TFileHeader))
|
||||
#define TFILE_HEADER_NO_FST (TFILE_HEADER_SIZE - sizeof(int32_t))
|
||||
|
||||
typedef struct TFileValue {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "lucene++/Lucene_c.h"
|
||||
#endif
|
||||
|
||||
#define INDEX_NUM_OF_THREADS 4
|
||||
#define INDEX_NUM_OF_THREADS 1
|
||||
#define INDEX_QUEUE_SIZE 200
|
||||
|
||||
#define INDEX_DATA_BOOL_NULL 0x02
|
||||
|
@ -117,7 +117,6 @@ int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) {
|
|||
sIdx->path = tstrdup(path);
|
||||
taosThreadMutexInit(&sIdx->mtx, NULL);
|
||||
tsem_init(&sIdx->sem, 0, 0);
|
||||
// taosThreadCondInit(&sIdx->finished, NULL);
|
||||
|
||||
sIdx->refId = indexAddRef(sIdx);
|
||||
indexAcquireRef(sIdx->refId);
|
||||
|
@ -143,13 +142,13 @@ void indexDestroy(void* handle) {
|
|||
return;
|
||||
}
|
||||
void indexClose(SIndex* sIdx) {
|
||||
indexReleaseRef(sIdx->refId);
|
||||
bool ref = 0;
|
||||
if (sIdx->colObj != NULL) {
|
||||
void* iter = taosHashIterate(sIdx->colObj, NULL);
|
||||
while (iter) {
|
||||
IndexCache** pCache = iter;
|
||||
indexCacheForceToMerge((void*)(*pCache));
|
||||
indexInfo("%s wait to merge", (*pCache)->colName);
|
||||
indexWait((void*)(sIdx));
|
||||
iter = taosHashIterate(sIdx->colObj, iter);
|
||||
indexCacheUnRef(*pCache);
|
||||
|
@ -157,7 +156,7 @@ void indexClose(SIndex* sIdx) {
|
|||
taosHashCleanup(sIdx->colObj);
|
||||
sIdx->colObj = NULL;
|
||||
}
|
||||
// taosMsleep(1000 * 5);
|
||||
indexReleaseRef(sIdx->refId);
|
||||
indexRemoveRef(sIdx->refId);
|
||||
}
|
||||
int64_t indexAddRef(void* p) {
|
||||
|
@ -554,8 +553,29 @@ void iterateValueDestroy(IterateValue* value, bool destroy) {
|
|||
taosMemoryFree(value->colVal);
|
||||
value->colVal = NULL;
|
||||
}
|
||||
|
||||
static int64_t indexGetAvaialbleVer(SIndex* sIdx, IndexCache* cache) {
|
||||
ICacheKey key = {.suid = cache->suid, .colName = cache->colName, .nColName = strlen(cache->colName)};
|
||||
int64_t ver = CACHE_VERSION(cache);
|
||||
taosThreadMutexLock(&sIdx->mtx);
|
||||
TFileReader* trd = tfileCacheGet(((IndexTFile*)sIdx->tindex)->cache, &key);
|
||||
if (trd != NULL) {
|
||||
if (ver < trd->header.version) {
|
||||
ver = trd->header.version + 1;
|
||||
} else {
|
||||
ver += 1;
|
||||
}
|
||||
indexInfo("header: %d, ver: %" PRId64 "", trd->header.version, ver);
|
||||
tfileReaderUnRef(trd);
|
||||
} else {
|
||||
indexInfo("not found reader base %p", trd);
|
||||
}
|
||||
taosThreadMutexUnlock(&sIdx->mtx);
|
||||
return ver;
|
||||
}
|
||||
static int indexGenTFile(SIndex* sIdx, IndexCache* cache, SArray* batch) {
|
||||
int32_t version = CACHE_VERSION(cache);
|
||||
int64_t version = indexGetAvaialbleVer(sIdx, cache);
|
||||
indexInfo("file name version: %" PRId64 "", version);
|
||||
uint8_t colType = cache->type;
|
||||
|
||||
TFileWriter* tw = tfileWriterOpen(sIdx->path, cache->suid, version, cache->colName, colType);
|
||||
|
@ -575,6 +595,7 @@ static int indexGenTFile(SIndex* sIdx, IndexCache* cache, SArray* batch) {
|
|||
if (reader == NULL) {
|
||||
return -1;
|
||||
}
|
||||
indexInfo("success to create tfile, reopen it, %s", reader->ctx->file.buf);
|
||||
|
||||
TFileHeader* header = &reader->header;
|
||||
ICacheKey key = {.suid = cache->suid, .colName = header->colName, .nColName = strlen(header->colName)};
|
||||
|
|
|
@ -335,6 +335,9 @@ IndexCache* indexCacheCreate(SIndex* idx, uint64_t suid, const char* colName, in
|
|||
taosThreadCondInit(&cache->finished, NULL);
|
||||
|
||||
indexCacheRef(cache);
|
||||
if (idx != NULL) {
|
||||
indexAcquireRef(idx->refId);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
void indexCacheDebug(IndexCache* cache) {
|
||||
|
@ -426,13 +429,16 @@ void indexCacheDestroy(void* cache) {
|
|||
if (pCache == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
indexMemUnRef(pCache->mem);
|
||||
indexMemUnRef(pCache->imm);
|
||||
taosMemoryFree(pCache->colName);
|
||||
|
||||
taosThreadMutexDestroy(&pCache->mtx);
|
||||
taosThreadCondDestroy(&pCache->finished);
|
||||
|
||||
if (pCache->index != NULL) {
|
||||
indexReleaseRef(((SIndex*)pCache->index)->refId);
|
||||
}
|
||||
taosMemoryFree(pCache);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ WriterCtx* writerCtxCreate(WriterType type, const char* path, bool readOnly, int
|
|||
int64_t file_size;
|
||||
taosStatFile(path, &file_size, NULL);
|
||||
ctx->file.size = (int)file_size;
|
||||
|
||||
} else {
|
||||
// ctx->file.pFile = open(path, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
ctx->file.pFile = taosOpenFile(path, TD_FILE_READ);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
p *
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
|
@ -152,10 +151,13 @@ TFileReader* tfileCacheGet(TFileCache* tcache, ICacheKey* key) {
|
|||
char buf[128] = {0};
|
||||
int32_t sz = indexSerialCacheKey(key, buf);
|
||||
assert(sz < sizeof(buf));
|
||||
indexInfo("Try to get key: %s", buf);
|
||||
TFileReader** reader = taosHashGet(tcache->tableCache, buf, sz);
|
||||
if (reader == NULL) {
|
||||
if (reader == NULL || *reader == NULL) {
|
||||
indexInfo("failed to get key: %s", buf);
|
||||
return NULL;
|
||||
}
|
||||
indexInfo("Get key: %s file: %s", buf, (*reader)->ctx->file.buf);
|
||||
tfileReaderRef(*reader);
|
||||
|
||||
return *reader;
|
||||
|
@ -165,9 +167,10 @@ void tfileCachePut(TFileCache* tcache, ICacheKey* key, TFileReader* reader) {
|
|||
int32_t sz = indexSerialCacheKey(key, buf);
|
||||
// remove last version index reader
|
||||
TFileReader** p = taosHashGet(tcache->tableCache, buf, sz);
|
||||
if (p != NULL) {
|
||||
if (p != NULL && *p != NULL) {
|
||||
TFileReader* oldReader = *p;
|
||||
taosHashRemove(tcache->tableCache, buf, sz);
|
||||
indexInfo("found %s, remove file %s", buf, oldReader->ctx->file.buf);
|
||||
oldReader->remove = true;
|
||||
tfileReaderUnRef(oldReader);
|
||||
}
|
||||
|
@ -180,7 +183,6 @@ TFileReader* tfileReaderCreate(WriterCtx* ctx) {
|
|||
if (reader == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reader->ctx = ctx;
|
||||
|
||||
if (0 != tfileReaderVerify(reader)) {
|
||||
|
@ -202,6 +204,7 @@ TFileReader* tfileReaderCreate(WriterCtx* ctx) {
|
|||
tfileReaderDestroy(reader);
|
||||
return NULL;
|
||||
}
|
||||
reader->remove = false;
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
@ -536,7 +539,7 @@ TFileReader* tfileReaderOpen(char* path, uint64_t suid, int32_t version, const c
|
|||
indexError("failed to open readonly file: %s, reason: %s", fullname, terrstr());
|
||||
return NULL;
|
||||
}
|
||||
indexInfo("open read file name:%s, file size: %d", wc->file.buf, wc->file.size);
|
||||
indexTrace("open read file name:%s, file size: %d", wc->file.buf, wc->file.size);
|
||||
|
||||
TFileReader* reader = tfileReaderCreate(wc);
|
||||
return reader;
|
||||
|
|
|
@ -674,10 +674,13 @@ class IndexObj {
|
|||
// opt
|
||||
numOfWrite = 0;
|
||||
numOfRead = 0;
|
||||
indexInit();
|
||||
// indexInit();
|
||||
}
|
||||
int Init(const std::string& dir) {
|
||||
taosRemoveDir(dir.c_str());
|
||||
int Init(const std::string& dir, bool remove = true) {
|
||||
if (remove) {
|
||||
taosRemoveDir(dir.c_str());
|
||||
taosMkDir(dir.c_str());
|
||||
}
|
||||
taosMkDir(dir.c_str());
|
||||
int ret = indexOpen(&opts, dir.c_str(), &idx);
|
||||
if (ret != 0) {
|
||||
|
@ -838,8 +841,11 @@ class IndexEnv2 : public ::testing::Test {
|
|||
initLog();
|
||||
index = new IndexObj();
|
||||
}
|
||||
virtual void TearDown() { delete index; }
|
||||
IndexObj* index;
|
||||
virtual void TearDown() {
|
||||
// taosMsleep(500);
|
||||
delete index;
|
||||
}
|
||||
IndexObj* index;
|
||||
};
|
||||
TEST_F(IndexEnv2, testIndexOpen) {
|
||||
std::string path = TD_TMP_DIR_PATH "test";
|
||||
|
@ -951,6 +957,8 @@ static void single_write_and_search(IndexObj* idx) {
|
|||
target = idx->SearchOne("tag2", "Test");
|
||||
}
|
||||
static void multi_write_and_search(IndexObj* idx) {
|
||||
idx->PutOne("tag1", "Hello");
|
||||
idx->PutOne("tag2", "Test");
|
||||
int target = idx->SearchOne("tag1", "Hello");
|
||||
target = idx->SearchOne("tag2", "Test");
|
||||
idx->WriteMultiMillonData("tag1", "hello world test", 100 * 100);
|
||||
|
@ -992,16 +1000,16 @@ TEST_F(IndexEnv2, testIndex_MultiWrite_and_MultiRead) {
|
|||
}
|
||||
}
|
||||
|
||||
// TEST_F(IndexEnv2, testIndex_restart) {
|
||||
// std::string path = TD_TMP_DIR_PATH "cache_and_tfile";
|
||||
// if (index->Init(path) != 0) {
|
||||
// }
|
||||
// index->SearchOneTarget("tag1", "Hello", 10);
|
||||
// index->SearchOneTarget("tag2", "Test", 10);
|
||||
//}
|
||||
TEST_F(IndexEnv2, testIndex_restart) {
|
||||
std::string path = TD_TMP_DIR_PATH "cache_and_tfile";
|
||||
if (index->Init(path, false) != 0) {
|
||||
}
|
||||
index->SearchOneTarget("tag1", "Hello", 10);
|
||||
index->SearchOneTarget("tag2", "Test", 10);
|
||||
}
|
||||
// TEST_F(IndexEnv2, testIndex_restart1) {
|
||||
// std::string path = TD_TMP_DIR_PATH "cache_and_tfile";
|
||||
// if (index->Init(path) != 0) {
|
||||
// if (index->Init(path, false) != 0) {
|
||||
// }
|
||||
// index->ReadMultiMillonData("tag1", "coding");
|
||||
// index->SearchOneTarget("tag1", "Hello", 10);
|
||||
|
@ -1018,16 +1026,16 @@ TEST_F(IndexEnv2, testIndex_MultiWrite_and_MultiRead) {
|
|||
// std::cout << "reader sz: " << index->SearchOne("tag1", "Hello") << std::endl;
|
||||
// assert(3 == index->SearchOne("tag1", "Hello"));
|
||||
//}
|
||||
// TEST_F(IndexEnv2, testIndexMultiTag) {
|
||||
// std::string path = TD_TMP_DIR_PATH "multi_tag";
|
||||
// if (index->Init(path) != 0) {
|
||||
// }
|
||||
// int64_t st = taosGetTimestampUs();
|
||||
// int32_t num = 1000 * 10000;
|
||||
// index->WriteMultiMillonData("tag1", "xxxxxxxxxxxxxxx", num);
|
||||
// std::cout << "numOfRow: " << num << "\ttime cost:" << taosGetTimestampUs() - st << std::endl;
|
||||
// // index->WriteMultiMillonData("tag2", "xxxxxxxxxxxxxxxxxxxxxxxxx", 100 * 10000);
|
||||
//}
|
||||
TEST_F(IndexEnv2, testIndexMultiTag) {
|
||||
std::string path = TD_TMP_DIR_PATH "multi_tag";
|
||||
if (index->Init(path) != 0) {
|
||||
}
|
||||
int64_t st = taosGetTimestampUs();
|
||||
int32_t num = 100 * 100;
|
||||
index->WriteMultiMillonData("tag1", "xxxxxxxxxxxxxxx", num);
|
||||
std::cout << "numOfRow: " << num << "\ttime cost:" << taosGetTimestampUs() - st << std::endl;
|
||||
// index->WriteMultiMillonData("tag2", "xxxxxxxxxxxxxxxxxxxxxxxxx", 100 * 10000);
|
||||
}
|
||||
TEST_F(IndexEnv2, testLongComVal1) {
|
||||
std::string path = TD_TMP_DIR_PATH "long_colVal";
|
||||
if (index->Init(path) != 0) {
|
||||
|
|
|
@ -19,6 +19,21 @@
|
|||
#include "taos.h"
|
||||
#include "taoserror.h"
|
||||
|
||||
#define COPY_SCALAR_FIELD(fldname) \
|
||||
do { \
|
||||
(pDst)->fldname = (pSrc)->fldname; \
|
||||
} while (0)
|
||||
|
||||
#define COPY_CHAR_ARRAY_FIELD(fldname) \
|
||||
do { \
|
||||
strcpy((pDst)->fldname, (pSrc)->fldname); \
|
||||
} while (0)
|
||||
|
||||
#define COPY_OBJECT_FIELD(fldname, size) \
|
||||
do { \
|
||||
memcpy(&((pDst)->fldname), &((pSrc)->fldname), size); \
|
||||
} while (0)
|
||||
|
||||
#define COPY_CHAR_POINT_FIELD(fldname) \
|
||||
do { \
|
||||
if (NULL == (pSrc)->fldname) { \
|
||||
|
@ -70,27 +85,61 @@
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {}
|
||||
|
||||
static SNode* exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
|
||||
dataTypeCopy(&pSrc->resType, &pDst->resType);
|
||||
pDst->pAssociation = NULL;
|
||||
COPY_OBJECT_FIELD(resType, sizeof(SDataType));
|
||||
COPY_CHAR_ARRAY_FIELD(aliasName);
|
||||
COPY_CHAR_ARRAY_FIELD(userAlias);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
pDst->pProjectRef = NULL;
|
||||
COPY_SCALAR_FIELD(tableId);
|
||||
COPY_SCALAR_FIELD(tableType);
|
||||
COPY_SCALAR_FIELD(colId);
|
||||
COPY_SCALAR_FIELD(colType);
|
||||
COPY_CHAR_ARRAY_FIELD(dbName);
|
||||
COPY_CHAR_ARRAY_FIELD(tableName);
|
||||
COPY_CHAR_ARRAY_FIELD(tableAlias);
|
||||
COPY_CHAR_ARRAY_FIELD(colName);
|
||||
COPY_SCALAR_FIELD(dataBlockId);
|
||||
COPY_SCALAR_FIELD(slotId);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
COPY_CHAR_POINT_FIELD(literal);
|
||||
COPY_SCALAR_FIELD(isDuration);
|
||||
COPY_SCALAR_FIELD(translate);
|
||||
COPY_SCALAR_FIELD(notReserved);
|
||||
COPY_SCALAR_FIELD(placeholderNo);
|
||||
COPY_SCALAR_FIELD(typeData);
|
||||
COPY_SCALAR_FIELD(unit);
|
||||
if (!pSrc->translate) {
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
switch (pSrc->node.resType.type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
COPY_SCALAR_FIELD(datum.b);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
COPY_SCALAR_FIELD(datum.i);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
COPY_SCALAR_FIELD(datum.d);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
COPY_SCALAR_FIELD(datum.u);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
|
@ -104,7 +153,7 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
// todo
|
||||
case TSDB_DATA_TYPE_MEDIUMBLOB:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -113,6 +162,7 @@ static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
|||
|
||||
static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
COPY_SCALAR_FIELD(opType);
|
||||
CLONE_NODE_FIELD(pLeft);
|
||||
CLONE_NODE_FIELD(pRight);
|
||||
return (SNode*)pDst;
|
||||
|
@ -120,18 +170,27 @@ static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
|
|||
|
||||
static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
COPY_SCALAR_FIELD(condType);
|
||||
CLONE_NODE_LIST_FIELD(pParameterList);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
COPY_CHAR_ARRAY_FIELD(functionName);
|
||||
COPY_SCALAR_FIELD(funcId);
|
||||
COPY_SCALAR_FIELD(funcType);
|
||||
CLONE_NODE_LIST_FIELD(pParameterList);
|
||||
COPY_SCALAR_FIELD(udfBufSize);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* tableNodeCopy(const STableNode* pSrc, STableNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, exprNodeCopy);
|
||||
COPY_CHAR_ARRAY_FIELD(dbName);
|
||||
COPY_CHAR_ARRAY_FIELD(tableName);
|
||||
COPY_CHAR_ARRAY_FIELD(tableAlias);
|
||||
COPY_SCALAR_FIELD(precision);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -159,6 +218,8 @@ static SNode* realTableNodeCopy(const SRealTableNode* pSrc, SRealTableNode* pDst
|
|||
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
|
||||
CLONE_OBJECT_FIELD(pMeta, tableMetaClone);
|
||||
CLONE_OBJECT_FIELD(pVgroupList, vgroupsInfoClone);
|
||||
COPY_CHAR_ARRAY_FIELD(qualDbName);
|
||||
COPY_SCALAR_FIELD(ratio);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -170,6 +231,7 @@ static SNode* tempTableNodeCopy(const STempTableNode* pSrc, STempTableNode* pDst
|
|||
|
||||
static SNode* joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(table, tableNodeCopy);
|
||||
COPY_SCALAR_FIELD(joinType);
|
||||
CLONE_NODE_FIELD(pLeft);
|
||||
CLONE_NODE_FIELD(pRight);
|
||||
CLONE_NODE_FIELD(pOnCond);
|
||||
|
@ -177,21 +239,30 @@ static SNode* joinTableNodeCopy(const SJoinTableNode* pSrc, SJoinTableNode* pDst
|
|||
}
|
||||
|
||||
static SNode* targetNodeCopy(const STargetNode* pSrc, STargetNode* pDst) {
|
||||
COPY_SCALAR_FIELD(dataBlockId);
|
||||
COPY_SCALAR_FIELD(slotId);
|
||||
CLONE_NODE_FIELD(pExpr);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* groupingSetNodeCopy(const SGroupingSetNode* pSrc, SGroupingSetNode* pDst) {
|
||||
COPY_SCALAR_FIELD(groupingSetType);
|
||||
CLONE_NODE_LIST_FIELD(pParameterList);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* orderByExprNodeCopy(const SOrderByExprNode* pSrc, SOrderByExprNode* pDst) {
|
||||
CLONE_NODE_FIELD(pExpr);
|
||||
COPY_SCALAR_FIELD(order);
|
||||
COPY_SCALAR_FIELD(nullOrder);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) { return (SNode*)pDst; }
|
||||
static SNode* limitNodeCopy(const SLimitNode* pSrc, SLimitNode* pDst) {
|
||||
COPY_SCALAR_FIELD(limit);
|
||||
COPY_SCALAR_FIELD(offset);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* stateWindowNodeCopy(const SStateWindowNode* pSrc, SStateWindowNode* pDst) {
|
||||
CLONE_NODE_FIELD(pCol);
|
||||
|
@ -215,13 +286,16 @@ static SNode* intervalWindowNodeCopy(const SIntervalWindowNode* pSrc, SIntervalW
|
|||
}
|
||||
|
||||
static SNode* nodeListNodeCopy(const SNodeListNode* pSrc, SNodeListNode* pDst) {
|
||||
COPY_OBJECT_FIELD(dataType, sizeof(SDataType));
|
||||
CLONE_NODE_LIST_FIELD(pNodeList);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) {
|
||||
COPY_SCALAR_FIELD(mode);
|
||||
CLONE_NODE_FIELD(pValues);
|
||||
CLONE_NODE_FIELD(pWStartTs);
|
||||
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -229,7 +303,7 @@ static SNode* logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
|
|||
CLONE_NODE_LIST_FIELD(pTargets);
|
||||
CLONE_NODE_FIELD(pConditions);
|
||||
CLONE_NODE_LIST_FIELD(pChildren);
|
||||
pDst->pParent = NULL;
|
||||
COPY_SCALAR_FIELD(optimizedFlag);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -239,12 +313,25 @@ static SNode* logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) {
|
|||
CLONE_NODE_LIST_FIELD(pScanPseudoCols);
|
||||
CLONE_OBJECT_FIELD(pMeta, tableMetaClone);
|
||||
CLONE_OBJECT_FIELD(pVgroupList, vgroupsInfoClone);
|
||||
COPY_SCALAR_FIELD(scanType);
|
||||
COPY_OBJECT_FIELD(scanSeq[0], sizeof(uint8_t) * 2);
|
||||
COPY_OBJECT_FIELD(scanRange, sizeof(STimeWindow));
|
||||
COPY_OBJECT_FIELD(tableName, sizeof(SName));
|
||||
COPY_SCALAR_FIELD(showRewrite);
|
||||
COPY_SCALAR_FIELD(ratio);
|
||||
CLONE_NODE_LIST_FIELD(pDynamicScanFuncs);
|
||||
COPY_SCALAR_FIELD(dataRequired);
|
||||
COPY_SCALAR_FIELD(interval);
|
||||
COPY_SCALAR_FIELD(offset);
|
||||
COPY_SCALAR_FIELD(sliding);
|
||||
COPY_SCALAR_FIELD(intervalUnit);
|
||||
COPY_SCALAR_FIELD(slidingUnit);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
COPY_SCALAR_FIELD(joinType);
|
||||
CLONE_NODE_FIELD(pOnConditions);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
@ -259,32 +346,50 @@ static SNode* logicAggCopy(const SAggLogicNode* pSrc, SAggLogicNode* pDst) {
|
|||
static SNode* logicProjectCopy(const SProjectLogicNode* pSrc, SProjectLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
CLONE_NODE_LIST_FIELD(pProjections);
|
||||
COPY_CHAR_ARRAY_FIELD(stmtName);
|
||||
COPY_SCALAR_FIELD(limit);
|
||||
COPY_SCALAR_FIELD(offset);
|
||||
COPY_SCALAR_FIELD(slimit);
|
||||
COPY_SCALAR_FIELD(soffset);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* logicVnodeModifCopy(const SVnodeModifLogicNode* pSrc, SVnodeModifLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
pDst->pDataBlocks = NULL;
|
||||
pDst->pVgDataBlocks = NULL;
|
||||
COPY_SCALAR_FIELD(msgType);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* logicExchangeCopy(const SExchangeLogicNode* pSrc, SExchangeLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
COPY_SCALAR_FIELD(srcGroupId);
|
||||
COPY_SCALAR_FIELD(precision);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
COPY_SCALAR_FIELD(winType);
|
||||
CLONE_NODE_LIST_FIELD(pFuncs);
|
||||
COPY_SCALAR_FIELD(interval);
|
||||
COPY_SCALAR_FIELD(offset);
|
||||
COPY_SCALAR_FIELD(sliding);
|
||||
COPY_SCALAR_FIELD(intervalUnit);
|
||||
COPY_SCALAR_FIELD(slidingUnit);
|
||||
COPY_SCALAR_FIELD(sessionGap);
|
||||
CLONE_NODE_FIELD(pTspk);
|
||||
CLONE_NODE_FIELD(pStateExpr);
|
||||
COPY_SCALAR_FIELD(triggerType);
|
||||
COPY_SCALAR_FIELD(watermark);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* logicFillCopy(const SFillLogicNode* pSrc, SFillLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
COPY_SCALAR_FIELD(mode);
|
||||
CLONE_NODE_FIELD(pWStartTs);
|
||||
CLONE_NODE_FIELD(pValues);
|
||||
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -301,28 +406,41 @@ static SNode* logicPartitionCopy(const SPartitionLogicNode* pSrc, SPartitionLogi
|
|||
}
|
||||
|
||||
static SNode* logicSubplanCopy(const SLogicSubplan* pSrc, SLogicSubplan* pDst) {
|
||||
COPY_OBJECT_FIELD(id, sizeof(SSubplanId));
|
||||
CLONE_NODE_FIELD(pNode);
|
||||
pDst->pChildren = NULL;
|
||||
pDst->pParents = NULL;
|
||||
pDst->pVgroupList = NULL;
|
||||
COPY_SCALAR_FIELD(subplanType);
|
||||
COPY_SCALAR_FIELD(level);
|
||||
COPY_SCALAR_FIELD(splitFlag);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) {
|
||||
COPY_SCALAR_FIELD(dataBlockId);
|
||||
CLONE_NODE_LIST_FIELD(pSlots);
|
||||
COPY_SCALAR_FIELD(totalRowSize);
|
||||
COPY_SCALAR_FIELD(outputRowSize);
|
||||
COPY_SCALAR_FIELD(precision);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* slotDescCopy(const SSlotDescNode* pSrc, SSlotDescNode* pDst) {
|
||||
dataTypeCopy(&pSrc->dataType, &pDst->dataType);
|
||||
COPY_SCALAR_FIELD(slotId);
|
||||
COPY_OBJECT_FIELD(dataType, sizeof(SDataType));
|
||||
COPY_SCALAR_FIELD(reserve);
|
||||
COPY_SCALAR_FIELD(output);
|
||||
COPY_SCALAR_FIELD(tag);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* downstreamSourceCopy(const SDownstreamSourceNode* pSrc, SDownstreamSourceNode* pDst) {
|
||||
COPY_OBJECT_FIELD(addr, sizeof(SQueryNodeAddr));
|
||||
COPY_SCALAR_FIELD(taskId);
|
||||
COPY_SCALAR_FIELD(schedId);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
static SNode* selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
|
||||
COPY_SCALAR_FIELD(isDistinct);
|
||||
CLONE_NODE_LIST_FIELD(pProjectionList);
|
||||
CLONE_NODE_FIELD(pFromTable);
|
||||
CLONE_NODE_FIELD(pWhere);
|
||||
|
@ -333,6 +451,12 @@ static SNode* selectStmtCopy(const SSelectStmt* pSrc, SSelectStmt* pDst) {
|
|||
CLONE_NODE_LIST_FIELD(pOrderByList);
|
||||
CLONE_NODE_FIELD(pLimit);
|
||||
CLONE_NODE_FIELD(pLimit);
|
||||
COPY_CHAR_ARRAY_FIELD(stmtName);
|
||||
COPY_SCALAR_FIELD(precision);
|
||||
COPY_SCALAR_FIELD(isEmptyResult);
|
||||
COPY_SCALAR_FIELD(isTimeOrderQuery);
|
||||
COPY_SCALAR_FIELD(hasAggFuncs);
|
||||
COPY_SCALAR_FIELD(hasRepeatScanFuncs);
|
||||
return (SNode*)pDst;
|
||||
}
|
||||
|
||||
|
@ -345,7 +469,6 @@ SNodeptr nodesCloneNode(const SNodeptr pNode) {
|
|||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
memcpy(pDst, pNode, nodesNodeSize(nodeType(pNode)));
|
||||
switch (nodeType(pNode)) {
|
||||
case QUERY_NODE_COLUMN:
|
||||
return columnNodeCopy((const SColumnNode*)pNode, (SColumnNode*)pDst);
|
||||
|
@ -387,6 +510,8 @@ SNodeptr nodesCloneNode(const SNodeptr pNode) {
|
|||
return slotDescCopy((const SSlotDescNode*)pNode, (SSlotDescNode*)pDst);
|
||||
case QUERY_NODE_DOWNSTREAM_SOURCE:
|
||||
return downstreamSourceCopy((const SDownstreamSourceNode*)pNode, (SDownstreamSourceNode*)pDst);
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return pDst;
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
return selectStmtCopy((const SSelectStmt*)pNode, (SSelectStmt*)pDst);
|
||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||
|
|
|
@ -78,6 +78,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "TableOptions";
|
||||
case QUERY_NODE_INDEX_OPTIONS:
|
||||
return "IndexOptions";
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return "LeftValue";
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return "SetOperator";
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -490,6 +492,7 @@ static const char* jkScanLogicPlanScanCols = "ScanCols";
|
|||
static const char* jkScanLogicPlanScanPseudoCols = "ScanPseudoCols";
|
||||
static const char* jkScanLogicPlanTableMetaSize = "TableMetaSize";
|
||||
static const char* jkScanLogicPlanTableMeta = "TableMeta";
|
||||
static const char* jkScanLogicPlanTagCond = "TagCond";
|
||||
|
||||
static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
||||
|
@ -507,6 +510,9 @@ static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkScanLogicPlanTableMeta, tableMetaToJson, pNode->pMeta);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkScanLogicPlanTagCond, nodeToJson, pNode->pTagCond);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -528,6 +534,9 @@ static int32_t jsonToLogicScanNode(const SJson* pJson, void* pObj) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonMakeObject(pJson, jkScanLogicPlanTableMeta, jsonToTableMeta, (void**)&pNode->pMeta, objSize);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkScanLogicPlanTagCond, &pNode->pTagCond);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -1775,6 +1784,7 @@ static const char* jkSubplanDbFName = "DbFName";
|
|||
static const char* jkSubplanNodeAddr = "NodeAddr";
|
||||
static const char* jkSubplanRootNode = "RootNode";
|
||||
static const char* jkSubplanDataSink = "DataSink";
|
||||
static const char* jkSubplanTagCond = "TagCond";
|
||||
|
||||
static int32_t subplanToJson(const void* pObj, SJson* pJson) {
|
||||
const SSubplan* pNode = (const SSubplan*)pObj;
|
||||
|
@ -1801,6 +1811,9 @@ static int32_t subplanToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkSubplanDataSink, nodeToJson, pNode->pDataSink);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkSubplanTagCond, nodeToJson, pNode->pTagCond);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -1831,6 +1844,9 @@ static int32_t jsonToSubplan(const SJson* pJson, void* pObj) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkSubplanDataSink, (SNode**)&pNode->pDataSink);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkSubplanTagCond, (SNode**)&pNode->pTagCond);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -2175,7 +2191,7 @@ static int32_t jsonToDatum(const SJson* pJson, void* pObj) {
|
|||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
varDataSetLen(pNode->datum.p, pNode->node.resType.bytes);
|
||||
varDataSetLen(pNode->datum.p, pNode->node.resType.bytes - VARSTR_HEADER_SIZE);
|
||||
if (TSDB_DATA_TYPE_NCHAR == pNode->node.resType.type) {
|
||||
char* buf = taosMemoryCalloc(1, pNode->node.resType.bytes * 2 + VARSTR_HEADER_SIZE + 1);
|
||||
if (NULL == buf) {
|
||||
|
@ -3019,6 +3035,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
break;
|
||||
case QUERY_NODE_DOWNSTREAM_SOURCE:
|
||||
return downstreamSourceNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to serialize.
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return setOperatorToJson(pObj, pJson);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -3130,6 +3148,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToSlotDescNode(pJson, pObj);
|
||||
case QUERY_NODE_DOWNSTREAM_SOURCE:
|
||||
return jsonToDownstreamSourceNode(pJson, pObj);
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to deserialize.
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return jsonToSetOperator(pJson, pObj);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
|
|
@ -79,6 +79,8 @@ int32_t nodesNodeSize(ENodeType type) {
|
|||
return sizeof(SStreamOptions);
|
||||
case QUERY_NODE_TOPIC_OPTIONS:
|
||||
return sizeof(STopicOptions);
|
||||
case QUERY_NODE_LEFT_VALUE:
|
||||
return sizeof(SLeftValueNode);
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return sizeof(SSetOperator);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -1117,6 +1119,7 @@ bool nodesIsComparisonOp(const SOperatorNode* pOp) {
|
|||
bool nodesIsJsonOp(const SOperatorNode* pOp) {
|
||||
switch (pOp->opType) {
|
||||
case OP_TYPE_JSON_GET_VALUE:
|
||||
case OP_TYPE_JSON_CONTAINS:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -342,25 +342,19 @@ SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType typ
|
|||
CHECK_OUT_OF_MEM(cond);
|
||||
cond->condType = type;
|
||||
cond->pParameterList = nodesMakeList();
|
||||
if ((QUERY_NODE_LOGIC_CONDITION == nodeType(pParam1) && type != ((SLogicConditionNode*)pParam1)->condType) ||
|
||||
(QUERY_NODE_LOGIC_CONDITION == nodeType(pParam2) && type != ((SLogicConditionNode*)pParam2)->condType)) {
|
||||
nodesListAppend(cond->pParameterList, pParam1);
|
||||
nodesListAppend(cond->pParameterList, pParam2);
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam1) && type == ((SLogicConditionNode*)pParam1)->condType) {
|
||||
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam1)->pParameterList);
|
||||
((SLogicConditionNode*)pParam1)->pParameterList = NULL;
|
||||
nodesDestroyNode(pParam1);
|
||||
} else {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam1)) {
|
||||
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam1)->pParameterList);
|
||||
((SLogicConditionNode*)pParam1)->pParameterList = NULL;
|
||||
nodesDestroyNode(pParam1);
|
||||
} else {
|
||||
nodesListAppend(cond->pParameterList, pParam1);
|
||||
}
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam2)) {
|
||||
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam2)->pParameterList);
|
||||
((SLogicConditionNode*)pParam2)->pParameterList = NULL;
|
||||
nodesDestroyNode(pParam2);
|
||||
} else {
|
||||
nodesListAppend(cond->pParameterList, pParam2);
|
||||
}
|
||||
nodesListAppend(cond->pParameterList, pParam1);
|
||||
}
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam2) && type == ((SLogicConditionNode*)pParam2)->condType) {
|
||||
nodesListAppendList(cond->pParameterList, ((SLogicConditionNode*)pParam2)->pParameterList);
|
||||
((SLogicConditionNode*)pParam2)->pParameterList = NULL;
|
||||
nodesDestroyNode(pParam2);
|
||||
} else {
|
||||
nodesListAppend(cond->pParameterList, pParam2);
|
||||
}
|
||||
return (SNode*)cond;
|
||||
}
|
||||
|
|
|
@ -647,7 +647,7 @@ static FORCE_INLINE int32_t MemRowAppend(SMsgBuf* pMsgBuf, const void* value, in
|
|||
if (TSDB_DATA_TYPE_BINARY == pa->schema->type) {
|
||||
const char* rowEnd = tdRowEnd(rb->pBuf);
|
||||
STR_WITH_SIZE_TO_VARSTR(rowEnd, value, len);
|
||||
tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NORM, rowEnd, true, pa->toffset, pa->colIdx);
|
||||
tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NORM, rowEnd, false, pa->toffset, pa->colIdx);
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == pa->schema->type) {
|
||||
// if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
|
||||
int32_t output = 0;
|
||||
|
|
|
@ -292,8 +292,8 @@ static bool isScanPseudoColumnFunc(const SNode* pNode) {
|
|||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsScanPseudoColumnFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isNonstandardSQLFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsNonstandardSQLFunc(((SFunctionNode*)pNode)->funcId));
|
||||
static bool isIndefiniteRowsFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsIndefiniteRowsFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isDistinctOrderBy(STranslateContext* pCxt) {
|
||||
|
@ -646,12 +646,13 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD
|
|||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + VARSTR_HEADER_SIZE + 1);
|
||||
pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
|
||||
if (NULL == pVal->datum.p) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
||||
}
|
||||
varDataSetLen(pVal->datum.p, targetDt.bytes);
|
||||
strncpy(varDataVal(pVal->datum.p), pVal->literal, targetDt.bytes);
|
||||
int32_t len = TMIN(targetDt.bytes - VARSTR_HEADER_SIZE, pVal->node.resType.bytes);
|
||||
varDataSetLen(pVal->datum.p, len);
|
||||
strncpy(varDataVal(pVal->datum.p), pVal->literal, len);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
|
@ -662,22 +663,20 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int32_t bytes = targetDt.bytes * TSDB_NCHAR_SIZE;
|
||||
pVal->datum.p = taosMemoryCalloc(1, bytes + VARSTR_HEADER_SIZE + 1);
|
||||
pVal->datum.p = taosMemoryCalloc(1, targetDt.bytes + 1);
|
||||
if (NULL == pVal->datum.p) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
|
||||
;
|
||||
}
|
||||
|
||||
int32_t output = 0;
|
||||
if (!taosMbsToUcs4(pVal->literal, pVal->node.resType.bytes, (TdUcs4*)varDataVal(pVal->datum.p), bytes,
|
||||
&output)) {
|
||||
int32_t len = 0;
|
||||
if (!taosMbsToUcs4(pVal->literal, pVal->node.resType.bytes, (TdUcs4*)varDataVal(pVal->datum.p),
|
||||
targetDt.bytes - VARSTR_HEADER_SIZE, &len)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||
}
|
||||
varDataSetLen(pVal->datum.p, output);
|
||||
varDataSetLen(pVal->datum.p, len);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_DECIMAL:
|
||||
case TSDB_DATA_TYPE_BLOB:
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||
|
@ -690,8 +689,20 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD
|
|||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t calcTypeBytes(SDataType dt) {
|
||||
if (TSDB_DATA_TYPE_BINARY == dt.type) {
|
||||
return dt.bytes + VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
return dt.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
} else {
|
||||
return dt.bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
||||
return translateValueImpl(pCxt, pVal, pVal->node.resType);
|
||||
SDataType dt = pVal->node.resType;
|
||||
dt.bytes = calcTypeBytes(dt);
|
||||
return translateValueImpl(pCxt, pVal, dt);
|
||||
}
|
||||
|
||||
static bool isMultiResFunc(SNode* pNode) {
|
||||
|
@ -726,8 +737,7 @@ static EDealRes translateUnaryOperator(STranslateContext* pCxt, SOperatorNode* p
|
|||
static EDealRes translateArithmeticOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type ||
|
||||
TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if ((TSDB_DATA_TYPE_TIMESTAMP == ldt.type && TSDB_DATA_TYPE_TIMESTAMP == rdt.type) ||
|
||||
|
@ -752,14 +762,14 @@ static EDealRes translateArithmeticOperator(STranslateContext* pCxt, SOperatorNo
|
|||
static EDealRes translateComparisonOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||
SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType;
|
||||
SDataType rdt = ((SExprNode*)(pOp->pRight))->resType;
|
||||
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
if (TSDB_DATA_TYPE_BLOB == ldt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||
}
|
||||
if (OP_TYPE_IN == pOp->opType || OP_TYPE_NOT_IN == pOp->opType) {
|
||||
((SExprNode*)pOp->pRight)->resType = ((SExprNode*)pOp->pLeft)->resType;
|
||||
}
|
||||
if (nodesIsRegularOp(pOp)) {
|
||||
if (!IS_STR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
if (!IS_VAR_DATA_TYPE(((SExprNode*)(pOp->pLeft))->resType.type)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pLeft))->aliasName);
|
||||
}
|
||||
if (QUERY_NODE_VALUE != nodeType(pOp->pRight) || !IS_STR_DATA_TYPE(((SExprNode*)(pOp->pRight))->resType.type)) {
|
||||
|
@ -806,7 +816,7 @@ static EDealRes haveAggOrNonstdFunction(SNode* pNode, void* pContext) {
|
|||
if (isAggFunc(pNode)) {
|
||||
*((bool*)pContext) = true;
|
||||
return DEAL_RES_END;
|
||||
} else if (isNonstandardSQLFunc(pNode)) {
|
||||
} else if (isIndefiniteRowsFunc(pNode)) {
|
||||
*((bool*)pContext) = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
|
@ -851,6 +861,15 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
|
|||
return hasInvalidFunc;
|
||||
}
|
||||
|
||||
static int32_t getFuncInfo(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog,
|
||||
.pRpc = pCxt->pParseCxt->pTransporter,
|
||||
.pMgmtEps = &pCxt->pParseCxt->mgmtEpSet,
|
||||
.pErrBuf = pCxt->msgBuf.buf,
|
||||
.errBufLen = pCxt->msgBuf.len};
|
||||
return fmGetFuncInfo(¶m, pFunc);
|
||||
}
|
||||
|
||||
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
SNode* pParam = NULL;
|
||||
FOREACH(pParam, pFunc->pParameterList) {
|
||||
|
@ -859,12 +878,7 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
}
|
||||
}
|
||||
|
||||
SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog,
|
||||
.pRpc = pCxt->pParseCxt->pTransporter,
|
||||
.pMgmtEps = &pCxt->pParseCxt->mgmtEpSet,
|
||||
.pErrBuf = pCxt->msgBuf.buf,
|
||||
.errBufLen = pCxt->msgBuf.len};
|
||||
pCxt->errCode = fmGetFuncInfo(¶m, pFunc);
|
||||
pCxt->errCode = getFuncInfo(pCxt, pFunc);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsAggFunc(pFunc->funcId)) {
|
||||
if (beforeHaving(pCxt->currClause)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
|
||||
|
@ -872,7 +886,7 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
if (hasInvalidFuncNesting(pFunc->pParameterList)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_AGG_FUNC_NESTING);
|
||||
}
|
||||
if (pCxt->pCurrStmt->hasNonstdSQLFunc) {
|
||||
if (pCxt->pCurrStmt->hasIndefiniteRowsFunc) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
|
||||
|
@ -899,14 +913,15 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsNonstandardSQLFunc(pFunc->funcId)) {
|
||||
if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrStmt->hasNonstdSQLFunc || pCxt->pCurrStmt->hasAggFuncs) {
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsIndefiniteRowsFunc(pFunc->funcId)) {
|
||||
if (SQL_CLAUSE_SELECT != pCxt->currClause || pCxt->pCurrStmt->hasIndefiniteRowsFunc ||
|
||||
pCxt->pCurrStmt->hasAggFuncs) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
if (hasInvalidFuncNesting(pFunc->pParameterList)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_AGG_FUNC_NESTING);
|
||||
}
|
||||
pCxt->pCurrStmt->hasNonstdSQLFunc = true;
|
||||
pCxt->pCurrStmt->hasIndefiniteRowsFunc = true;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR;
|
||||
}
|
||||
|
@ -990,7 +1005,7 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode
|
|||
strcpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName);
|
||||
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
translateFunction(pCxt, pFunc);
|
||||
pCxt->errCode == getFuncInfo(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
*pNode = (SNode*)pFunc;
|
||||
|
@ -1060,7 +1075,7 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
|
|||
}
|
||||
|
||||
static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
|
||||
if (isAggFunc(*pNode)) {
|
||||
if (isAggFunc(*pNode) || isIndefiniteRowsFunc(*pNode)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
|
@ -1097,7 +1112,7 @@ static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
|
|||
pCxt->existAggFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (isNonstandardSQLFunc(pNode)) {
|
||||
if (isIndefiniteRowsFunc(pNode)) {
|
||||
pCxt->existNonstdFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
|
@ -1939,7 +1954,7 @@ static int32_t createCastFunc(STranslateContext* pCxt, SNode* pExpr, SDataType d
|
|||
nodesDestroyNode(pFunc);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
if (DEAL_RES_ERROR == translateFunction(pCxt, pFunc)) {
|
||||
if (TSDB_CODE_SUCCESS != getFuncInfo(pCxt, pFunc)) {
|
||||
nodesClearList(pFunc->pParameterList);
|
||||
pFunc->pParameterList = NULL;
|
||||
nodesDestroyNode(pFunc);
|
||||
|
@ -2343,16 +2358,6 @@ static int32_t translateAlterDatabase(STranslateContext* pCxt, SAlterDatabaseStm
|
|||
return buildCmdMsg(pCxt, TDMT_MND_ALTER_DB, (FSerializeFunc)tSerializeSAlterDbReq, &alterReq);
|
||||
}
|
||||
|
||||
static int32_t calcTypeBytes(SDataType dt) {
|
||||
if (TSDB_DATA_TYPE_BINARY == dt.type) {
|
||||
return dt.bytes + VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
return dt.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
} else {
|
||||
return dt.bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t columnDefNodeToField(SNodeList* pList, SArray** pArray) {
|
||||
*pArray = taosArrayInit(LIST_LENGTH(pList), sizeof(SField));
|
||||
SNode* pNode;
|
||||
|
@ -2478,6 +2483,9 @@ static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
|
|||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FIRST_COLUMN);
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code && pCol->dataType.type == TSDB_DATA_TYPE_JSON) {
|
||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COL_JSON);
|
||||
}
|
||||
int32_t len = strlen(pCol->colName);
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != taosHashGet(pHash, pCol->colName, len)) {
|
||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DUPLICATED_COLUMN);
|
||||
|
@ -2485,7 +2493,7 @@ static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if ((TSDB_DATA_TYPE_VARCHAR == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_BINARY_LEN) ||
|
||||
(TSDB_DATA_TYPE_NCHAR == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_NCHAR_LEN)) {
|
||||
code = code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
|
||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -4082,24 +4090,15 @@ static int32_t addValToKVRow(STranslateContext* pCxt, SValueNode* pVal, const SS
|
|||
}
|
||||
|
||||
static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* pFunc, SValueNode** pVal) {
|
||||
if (DEAL_RES_ERROR == translateFunction(pCxt, pFunc)) {
|
||||
return pCxt->errCode;
|
||||
int32_t code = getFuncInfo(pCxt, pFunc);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal);
|
||||
}
|
||||
return scalarCalculateConstants((SNode*)pFunc, (SNode**)pVal);
|
||||
}
|
||||
|
||||
static int32_t colDataBytesToValueDataBytes(uint8_t type, int32_t bytes) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == type || TSDB_DATA_TYPE_BINARY == type || TSDB_DATA_TYPE_VARBINARY == type) {
|
||||
return bytes - VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == type) {
|
||||
return (bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
}
|
||||
return bytes;
|
||||
return code;
|
||||
}
|
||||
|
||||
static SDataType schemaToDataType(SSchema* pSchema) {
|
||||
SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes, .precision = 0, .scale = 0};
|
||||
dt.bytes = colDataBytesToValueDataBytes(pSchema->type, pSchema->bytes);
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
@ -4453,11 +4452,38 @@ static int32_t buildUpdateTagValReq(STranslateContext* pCxt, SAlterTableStmt* pS
|
|||
}
|
||||
|
||||
pReq->isNull = (TSDB_DATA_TYPE_NULL == pStmt->pVal->node.resType.type);
|
||||
pReq->nTagVal = pStmt->pVal->node.resType.bytes;
|
||||
if (TSDB_DATA_TYPE_NCHAR == pStmt->pVal->node.resType.type) {
|
||||
pReq->nTagVal = pReq->nTagVal * TSDB_NCHAR_SIZE;
|
||||
if(pStmt->pVal->node.resType.type == TSDB_DATA_TYPE_JSON){
|
||||
SKVRowBuilder kvRowBuilder = {0};
|
||||
int32_t code = tdInitKVRowBuilder(&kvRowBuilder);
|
||||
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
if (pStmt->pVal->literal && strlen(pStmt->pVal->literal) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
|
||||
return buildSyntaxErrMsg(&pCxt->msgBuf, "json string too long than 4095", pStmt->pVal->literal);
|
||||
}
|
||||
|
||||
code = parseJsontoTagData(pStmt->pVal->literal, &kvRowBuilder, &pCxt->msgBuf, pSchema->colId);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
|
||||
SKVRow row = tdGetKVRowFromBuilder(&kvRowBuilder);
|
||||
if (NULL == row) {
|
||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
pReq->nTagVal = kvRowLen(row);
|
||||
pReq->pTagVal = row;
|
||||
pStmt->pVal->datum.p = row; // for free
|
||||
tdDestroyKVRowBuilder(&kvRowBuilder);
|
||||
}else{
|
||||
pReq->nTagVal = pStmt->pVal->node.resType.bytes;
|
||||
if (TSDB_DATA_TYPE_NCHAR == pStmt->pVal->node.resType.type) {
|
||||
pReq->nTagVal = pReq->nTagVal * TSDB_NCHAR_SIZE;
|
||||
}
|
||||
pReq->pTagVal = nodesGetValueFromNode(pStmt->pVal);
|
||||
}
|
||||
pReq->pTagVal = nodesGetValueFromNode(pStmt->pVal);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -4654,7 +4680,26 @@ static int32_t rewriteAlterTable(STranslateContext* pCxt, SQuery* pQuery) {
|
|||
return code;
|
||||
}
|
||||
|
||||
if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
|
||||
}
|
||||
|
||||
if (pStmt->dataType.type == TSDB_DATA_TYPE_JSON && pStmt->alterType == TSDB_ALTER_TABLE_ADD_COLUMN) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COL_JSON);
|
||||
}
|
||||
|
||||
if (getNumOfTags(pTableMeta) == 1 && pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "can not drop tag if there is only one tag");
|
||||
}
|
||||
|
||||
if (TSDB_SUPER_TABLE == pTableMeta->tableType) {
|
||||
SSchema* pTagsSchema = getTableTagSchema(pTableMeta);
|
||||
if (getNumOfTags(pTableMeta) == 1 && pTagsSchema->type == TSDB_DATA_TYPE_JSON &&
|
||||
(pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG ||
|
||||
pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG ||
|
||||
pStmt->alterType == TSDB_ALTER_TABLE_UPDATE_TAG_BYTES)) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else if (TSDB_CHILD_TABLE != pTableMeta->tableType && TSDB_NORMAL_TABLE != pTableMeta->tableType) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
|
||||
|
|
|
@ -171,6 +171,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
|||
return "Window query not supported, since the result of subquery not include valid timestamp column";
|
||||
case TSDB_CODE_PAR_INVALID_DROP_COL:
|
||||
return "No columns can be dropped";
|
||||
case TSDB_CODE_PAR_INVALID_COL_JSON:
|
||||
return "Only tag can be json type";
|
||||
case TSDB_CODE_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
default:
|
||||
|
@ -328,7 +330,7 @@ int parseJsontoTagData(const char* json, SKVRowBuilder* kvRowBuilder, SMsgBuf* p
|
|||
// set json NULL data
|
||||
uint8_t jsonNULL = TSDB_DATA_TYPE_NULL;
|
||||
int jsonIndex = startColId + 1;
|
||||
if (!json || strcasecmp(json, TSDB_DATA_NULL_STR_L) == 0) {
|
||||
if (!json || strtrim((char*)json) == 0 ||strcasecmp(json, TSDB_DATA_NULL_STR_L) == 0) {
|
||||
tdAddColToKVRow(kvRowBuilder, jsonIndex, &jsonNULL, CHAR_BYTES);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -360,12 +362,12 @@ int parseJsontoTagData(const char* json, SKVRowBuilder* kvRowBuilder, SMsgBuf* p
|
|||
retCode = buildSyntaxErrMsg(pMsgBuf, "json key not validate", jsonKey);
|
||||
goto end;
|
||||
}
|
||||
// if(strlen(jsonKey) > TSDB_MAX_JSON_KEY_LEN){
|
||||
// tscError("json key too long error");
|
||||
// retCode = tscSQLSyntaxErrMsg(errMsg, "json key too long, more than 256", NULL);
|
||||
// goto end;
|
||||
// }
|
||||
size_t keyLen = strlen(jsonKey);
|
||||
if(keyLen > TSDB_MAX_JSON_KEY_LEN){
|
||||
qError("json key too long error");
|
||||
retCode = buildSyntaxErrMsg(pMsgBuf, "json key too long, more than 256", jsonKey);
|
||||
goto end;
|
||||
}
|
||||
if (keyLen == 0 || taosHashGet(keyHash, jsonKey, keyLen) != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
|||
|
||||
target_link_libraries(
|
||||
planner
|
||||
PRIVATE os util nodes catalog cjson parser function qcom scalar
|
||||
PRIVATE os util nodes catalog cjson parser function qcom scalar index
|
||||
PUBLIC transport
|
||||
)
|
||||
|
||||
|
|
|
@ -418,7 +418,7 @@ static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr)
|
|||
}
|
||||
|
||||
static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) {
|
||||
if (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc && NULL == pSelect->pGroupByList) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -442,8 +442,8 @@ static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect,
|
|||
code = rewriteExprForSelect(pAgg->pGroupKeys, pSelect, SQL_CLAUSE_GROUP_BY);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code && pSelect->hasAggFuncs) {
|
||||
code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, fmIsAggFunc, &pAgg->pAggFuncs);
|
||||
if (TSDB_CODE_SUCCESS == code && (pSelect->hasAggFuncs || pSelect->hasIndefiniteRowsFunc)) {
|
||||
code = nodesCollectFuncs(pSelect, SQL_CLAUSE_GROUP_BY, fmIsVectorFunc, &pAgg->pAggFuncs);
|
||||
}
|
||||
|
||||
// rewrite the expression in subsequent clauses
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "filter.h"
|
||||
#include "functionMgt.h"
|
||||
#include "index.h"
|
||||
#include "planInt.h"
|
||||
|
||||
#define OPTIMIZE_FLAG_MASK(n) (1 << n)
|
||||
|
@ -313,22 +314,53 @@ static EDealRes cpdIsPrimaryKeyCondImpl(SNode* pNode, void* pContext) {
|
|||
}
|
||||
|
||||
static bool cpdIsPrimaryKeyCond(SNode* pNode) {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode)) {
|
||||
return false;
|
||||
}
|
||||
bool isPrimaryKeyCond = false;
|
||||
nodesWalkExpr(pNode, cpdIsPrimaryKeyCondImpl, &isPrimaryKeyCond);
|
||||
return isPrimaryKeyCond;
|
||||
}
|
||||
|
||||
static int32_t cpdPartitionScanLogicCond(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pOtherCond) {
|
||||
static EDealRes cpdIsTagCondImpl(SNode* pNode, void* pContext) {
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||
*((bool*)pContext) = ((COLUMN_TYPE_TAG == ((SColumnNode*)pNode)->colType) ? true : false);
|
||||
return *((bool*)pContext) ? DEAL_RES_CONTINUE : DEAL_RES_END;
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static bool cpdIsTagCond(SNode* pNode) {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode)) {
|
||||
return false;
|
||||
}
|
||||
bool isTagCond = false;
|
||||
nodesWalkExpr(pNode, cpdIsTagCondImpl, &isTagCond);
|
||||
return isTagCond;
|
||||
}
|
||||
|
||||
static int32_t cpdPartitionScanLogicCond(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pTagCond,
|
||||
SNode** pOtherCond) {
|
||||
SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pScan->node.pConditions;
|
||||
|
||||
if (LOGIC_COND_TYPE_AND != pLogicCond->condType) {
|
||||
*pPrimaryKeyCond = NULL;
|
||||
*pOtherCond = pScan->node.pConditions;
|
||||
pScan->node.pConditions = NULL;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SNodeList* pPrimaryKeyConds = NULL;
|
||||
SNodeList* pTagConds = NULL;
|
||||
SNodeList* pOtherConds = NULL;
|
||||
SNode* pCond = NULL;
|
||||
FOREACH(pCond, pLogicCond->pParameterList) {
|
||||
if (cpdIsPrimaryKeyCond(pCond)) {
|
||||
code = nodesListMakeAppend(&pPrimaryKeyConds, nodesCloneNode(pCond));
|
||||
} else if (cpdIsTagCond(pScan->node.pConditions)) {
|
||||
code = nodesListMakeAppend(&pTagConds, nodesCloneNode(pCond));
|
||||
} else {
|
||||
code = nodesListMakeAppend(&pOtherConds, nodesCloneNode(pCond));
|
||||
}
|
||||
|
@ -338,37 +370,46 @@ static int32_t cpdPartitionScanLogicCond(SScanLogicNode* pScan, SNode** pPrimary
|
|||
}
|
||||
|
||||
SNode* pTempPrimaryKeyCond = NULL;
|
||||
SNode* pTempTagCond = NULL;
|
||||
SNode* pTempOtherCond = NULL;
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = cpdMergeConds(&pTempPrimaryKeyCond, &pPrimaryKeyConds);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = cpdMergeConds(&pTempTagCond, &pTagConds);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = cpdMergeConds(&pTempOtherCond, &pOtherConds);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pPrimaryKeyCond = pTempPrimaryKeyCond;
|
||||
*pTagCond = pTempTagCond;
|
||||
*pOtherCond = pTempOtherCond;
|
||||
nodesDestroyNode(pScan->node.pConditions);
|
||||
pScan->node.pConditions = NULL;
|
||||
} else {
|
||||
nodesDestroyList(pPrimaryKeyConds);
|
||||
nodesDestroyList(pTagConds);
|
||||
nodesDestroyList(pOtherConds);
|
||||
nodesDestroyNode(pTempPrimaryKeyCond);
|
||||
nodesDestroyNode(pTempTagCond);
|
||||
nodesDestroyNode(pTempOtherCond);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t cpdPartitionScanCond(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pOtherCond) {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pScan->node.pConditions) &&
|
||||
LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)pScan->node.pConditions)->condType) {
|
||||
return cpdPartitionScanLogicCond(pScan, pPrimaryKeyCond, pOtherCond);
|
||||
static int32_t cpdPartitionScanCond(SScanLogicNode* pScan, SNode** pPrimaryKeyCond, SNode** pTagCond,
|
||||
SNode** pOtherCond) {
|
||||
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pScan->node.pConditions)) {
|
||||
return cpdPartitionScanLogicCond(pScan, pPrimaryKeyCond, pTagCond, pOtherCond);
|
||||
}
|
||||
|
||||
if (cpdIsPrimaryKeyCond(pScan->node.pConditions)) {
|
||||
*pPrimaryKeyCond = pScan->node.pConditions;
|
||||
} else if (cpdIsTagCond(pScan->node.pConditions)) {
|
||||
*pTagCond = pScan->node.pConditions;
|
||||
} else {
|
||||
*pOtherCond = pScan->node.pConditions;
|
||||
}
|
||||
|
@ -391,6 +432,32 @@ static int32_t cpdCalcTimeRange(SScanLogicNode* pScan, SNode** pPrimaryKeyCond,
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t cpdApplyTagIndex(SScanLogicNode* pScan, SNode** pTagCond, SNode** pOtherCond) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SIdxFltStatus idxStatus = idxGetFltStatus(*pTagCond);
|
||||
switch (idxStatus) {
|
||||
case SFLT_NOT_INDEX:
|
||||
code = cpdCondAppend(pOtherCond, pTagCond);
|
||||
break;
|
||||
case SFLT_COARSE_INDEX:
|
||||
pScan->pTagCond = nodesCloneNode(*pTagCond);
|
||||
if (NULL == pScan->pTagCond) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
code = cpdCondAppend(pOtherCond, pTagCond);
|
||||
break;
|
||||
case SFLT_ACCURATE_INDEX:
|
||||
pScan->pTagCond = *pTagCond;
|
||||
*pTagCond = NULL;
|
||||
break;
|
||||
default:
|
||||
code = TSDB_CODE_FAILED;
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode* pScan) {
|
||||
if (NULL == pScan->node.pConditions || OPTIMIZE_FLAG_TEST_MASK(pScan->node.optimizedFlag, OPTIMIZE_FLAG_CPD) ||
|
||||
TSDB_SYSTEM_TABLE == pScan->pMeta->tableType) {
|
||||
|
@ -398,11 +465,15 @@ static int32_t cpdOptimizeScanCondition(SOptimizeContext* pCxt, SScanLogicNode*
|
|||
}
|
||||
|
||||
SNode* pPrimaryKeyCond = NULL;
|
||||
SNode* pTagCond = NULL;
|
||||
SNode* pOtherCond = NULL;
|
||||
int32_t code = cpdPartitionScanCond(pScan, &pPrimaryKeyCond, &pOtherCond);
|
||||
int32_t code = cpdPartitionScanCond(pScan, &pPrimaryKeyCond, &pTagCond, &pOtherCond);
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pPrimaryKeyCond) {
|
||||
code = cpdCalcTimeRange(pScan, &pPrimaryKeyCond, &pOtherCond);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) {
|
||||
code = cpdApplyTagIndex(pScan, &pTagCond, &pOtherCond);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pScan->node.pConditions = pOtherCond;
|
||||
}
|
||||
|
@ -618,30 +689,6 @@ static bool cpdContainPrimaryKeyEqualCond(SJoinLogicNode* pJoin, SNode* pCond) {
|
|||
}
|
||||
}
|
||||
|
||||
// static int32_t cpdCheckOpCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SNode* pOnCond) {
|
||||
// if (!cpdIsPrimaryKeyEqualCond(pJoin, pOnCond)) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// return TSDB_CODE_SUCCESS;
|
||||
// }
|
||||
|
||||
// static int32_t cpdCheckLogicCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin, SLogicConditionNode* pOnCond) {
|
||||
// if (LOGIC_COND_TYPE_AND != pOnCond->condType) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// bool hasPrimaryKeyEqualCond = false;
|
||||
// SNode* pCond = NULL;
|
||||
// FOREACH(pCond, pOnCond->pParameterList) {
|
||||
// if (cpdIsPrimaryKeyEqualCond(pJoin, pCond)) {
|
||||
// hasPrimaryKeyEqualCond = true;
|
||||
// }
|
||||
// }
|
||||
// if (!hasPrimaryKeyEqualCond) {
|
||||
// return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
// }
|
||||
// return TSDB_CODE_SUCCESS;
|
||||
// }
|
||||
|
||||
static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||
if (NULL == pJoin->pOnConditions) {
|
||||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_NOT_SUPPORT_CROSS_JOIN);
|
||||
|
@ -650,11 +697,6 @@ static int32_t cpdCheckJoinOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin)
|
|||
return generateUsageErrMsg(pCxt->pPlanCxt->pMsg, pCxt->pPlanCxt->msgLen, TSDB_CODE_PLAN_EXPECTED_TS_EQUAL);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
// if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions)) {
|
||||
// return cpdCheckLogicCond(pCxt, pJoin, (SLogicConditionNode*)pJoin->pOnConditions);
|
||||
// } else {
|
||||
// return cpdCheckOpCond(pCxt, pJoin, pJoin->pOnConditions);
|
||||
// }
|
||||
}
|
||||
|
||||
static int32_t cpdPushJoinCondition(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) {
|
||||
|
|
|
@ -411,7 +411,7 @@ static int32_t createScanCols(SPhysiPlanContext* pCxt, SScanPhysiNode* pScanPhys
|
|||
return sortScanCols(pScanPhysiNode->pScanCols);
|
||||
}
|
||||
|
||||
static int32_t createScanPhysiNodeFinalize(SPhysiPlanContext* pCxt, SScanLogicNode* pScanLogicNode,
|
||||
static int32_t createScanPhysiNodeFinalize(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode,
|
||||
SScanPhysiNode* pScanPhysiNode, SPhysiNode** pPhyNode) {
|
||||
int32_t code = createScanCols(pCxt, pScanPhysiNode, pScanLogicNode->pScanCols);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -438,6 +438,12 @@ static int32_t createScanPhysiNodeFinalize(SPhysiPlanContext* pCxt, SScanLogicNo
|
|||
pScanPhysiNode->uid = pScanLogicNode->pMeta->uid;
|
||||
pScanPhysiNode->tableType = pScanLogicNode->pMeta->tableType;
|
||||
memcpy(&pScanPhysiNode->tableName, &pScanLogicNode->tableName, sizeof(SName));
|
||||
if (NULL != pScanLogicNode->pTagCond) {
|
||||
pSubplan->pTagCond = nodesCloneNode(pScanLogicNode->pTagCond);
|
||||
if (NULL == pSubplan->pTagCond) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -463,7 +469,7 @@ static int32_t createTagScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubpla
|
|||
}
|
||||
vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode);
|
||||
taosArrayPush(pCxt->pExecNodeList, &pSubplan->execNode);
|
||||
return createScanPhysiNodeFinalize(pCxt, pScanLogicNode, (SScanPhysiNode*)pTagScan, pPhyNode);
|
||||
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pTagScan, pPhyNode);
|
||||
}
|
||||
|
||||
static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode,
|
||||
|
@ -498,7 +504,7 @@ static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubp
|
|||
pTableScan->intervalUnit = pScanLogicNode->intervalUnit;
|
||||
pTableScan->slidingUnit = pScanLogicNode->slidingUnit;
|
||||
|
||||
return createScanPhysiNodeFinalize(pCxt, pScanLogicNode, (SScanPhysiNode*)pTableScan, pPhyNode);
|
||||
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pTableScan, pPhyNode);
|
||||
}
|
||||
|
||||
static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan,
|
||||
|
@ -522,7 +528,7 @@ static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan*
|
|||
pScan->mgmtEpSet = pCxt->pPlanCxt->mgmtEpSet;
|
||||
tNameGetFullDbName(&pScanLogicNode->tableName, pSubplan->dbFName);
|
||||
|
||||
return createScanPhysiNodeFinalize(pCxt, pScanLogicNode, (SScanPhysiNode*)pScan, pPhyNode);
|
||||
return createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pScan, pPhyNode);
|
||||
}
|
||||
|
||||
static int32_t createStreamScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubplan, SScanLogicNode* pScanLogicNode,
|
||||
|
@ -599,14 +605,17 @@ typedef struct SRewritePrecalcExprsCxt {
|
|||
static EDealRes collectAndRewrite(SRewritePrecalcExprsCxt* pCxt, SNode** pNode) {
|
||||
SNode* pExpr = nodesCloneNode(*pNode);
|
||||
if (NULL == pExpr) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
if (nodesListAppend(pCxt->pPrecalcExprs, pExpr)) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
nodesDestroyNode(pExpr);
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||
if (NULL == pCol) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
nodesDestroyNode(pExpr);
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
|
@ -624,16 +633,45 @@ static EDealRes collectAndRewrite(SRewritePrecalcExprsCxt* pCxt, SNode** pNode)
|
|||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
|
||||
static int32_t rewriteValueToOperator(SRewritePrecalcExprsCxt* pCxt, SNode** pNode) {
|
||||
SOperatorNode* pOper = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR);
|
||||
if (NULL == pOper) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
pOper->pLeft = nodesMakeNode(QUERY_NODE_LEFT_VALUE);
|
||||
if (NULL == pOper->pLeft) {
|
||||
nodesDestroyNode(pOper);
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
SValueNode* pVal = (SValueNode*)*pNode;
|
||||
pOper->node.resType = pVal->node.resType;
|
||||
strcpy(pOper->node.aliasName, pVal->node.aliasName);
|
||||
pOper->opType = OP_TYPE_ASSIGN;
|
||||
pOper->pRight = *pNode;
|
||||
*pNode = (SNode*)pOper;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EDealRes doRewritePrecalcExprs(SNode** pNode, void* pContext) {
|
||||
SRewritePrecalcExprsCxt* pCxt = (SRewritePrecalcExprsCxt*)pContext;
|
||||
switch (nodeType(*pNode)) {
|
||||
case QUERY_NODE_VALUE: {
|
||||
if (((SValueNode*)*pNode)->notReserved) {
|
||||
break;
|
||||
}
|
||||
pCxt->errCode = rewriteValueToOperator(pCxt, pNode);
|
||||
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
return collectAndRewrite(pCxt, pNode);
|
||||
}
|
||||
case QUERY_NODE_OPERATOR:
|
||||
case QUERY_NODE_LOGIC_CONDITION: {
|
||||
return collectAndRewrite(pContext, pNode);
|
||||
return collectAndRewrite(pCxt, pNode);
|
||||
}
|
||||
case QUERY_NODE_FUNCTION: {
|
||||
if (fmIsScalarFunc(((SFunctionNode*)(*pNode))->funcId)) {
|
||||
return collectAndRewrite(pContext, pNode);
|
||||
return collectAndRewrite(pCxt, pNode);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -677,9 +715,8 @@ static int32_t rewritePrecalcExprs(SPhysiPlanContext* pCxt, SNodeList* pList, SN
|
|||
}
|
||||
SRewritePrecalcExprsCxt cxt = {.errCode = TSDB_CODE_SUCCESS, .pPrecalcExprs = *pPrecalcExprs};
|
||||
nodesRewriteExprs(*pRewrittenList, doRewritePrecalcExprs, &cxt);
|
||||
if (0 == LIST_LENGTH(cxt.pPrecalcExprs)) {
|
||||
nodesDestroyList(cxt.pPrecalcExprs);
|
||||
*pPrecalcExprs = NULL;
|
||||
if (0 == LIST_LENGTH(cxt.pPrecalcExprs) || TSDB_CODE_SUCCESS != cxt.errCode) {
|
||||
DESTORY_LIST(*pPrecalcExprs);
|
||||
}
|
||||
return cxt.errCode;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,13 @@
|
|||
#include "planInt.h"
|
||||
#include "scalar.h"
|
||||
|
||||
static void dumpQueryPlan(SQueryPlan* pPlan) {
|
||||
char* pStr = NULL;
|
||||
nodesNodeToString(pPlan, false, &pStr, NULL);
|
||||
planDebugL("Query Plan: %s", pStr);
|
||||
taosMemoryFree(pStr);
|
||||
}
|
||||
|
||||
int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNodeList) {
|
||||
SLogicNode* pLogicNode = NULL;
|
||||
SLogicSubplan* pLogicSubplan = NULL;
|
||||
|
@ -36,6 +43,9 @@ int32_t qCreateQueryPlan(SPlanContext* pCxt, SQueryPlan** pPlan, SArray* pExecNo
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createPhysiPlan(pCxt, pLogicPlan, pPlan, pExecNodeList);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
dumpQueryPlan(*pPlan);
|
||||
}
|
||||
|
||||
nodesDestroyNode(pLogicNode);
|
||||
nodesDestroyNode(pLogicSubplan);
|
||||
|
|
|
@ -50,4 +50,6 @@ TEST_F(PlanBasicTest, func) {
|
|||
run("SELECT DIFF(c1) FROM t1");
|
||||
|
||||
run("SELECT PERCENTILE(c1, 60) FROM t1");
|
||||
|
||||
run("SELECT TOP(c1, 60) FROM t1");
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ TEST_F(PlanGroupByTest, aggFunc) {
|
|||
run("SELECT LAST(*), FIRST(*) FROM t1");
|
||||
|
||||
run("SELECT LAST(*), FIRST(*) FROM t1 GROUP BY c1");
|
||||
|
||||
run("SELECT SUM(10), COUNT(c1) FROM t1 GROUP BY c2");
|
||||
}
|
||||
|
||||
TEST_F(PlanGroupByTest, selectFunc) {
|
||||
|
|
|
@ -32,6 +32,12 @@ TEST_F(PlanOptimizeTest, optimizeScanData) {
|
|||
run("SELECT PERCENTILE(c1, 40), COUNT(*) FROM t1");
|
||||
}
|
||||
|
||||
TEST_F(PlanOptimizeTest, ConditionPushDown) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT ts, c1 FROM st1 WHERE tag1 > 4");
|
||||
}
|
||||
|
||||
TEST_F(PlanOptimizeTest, orderByPrimaryKey) {
|
||||
useDb("root", "test");
|
||||
|
||||
|
|
|
@ -233,45 +233,45 @@ class PlannerTestBaseImpl {
|
|||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_PARSER == module) {
|
||||
if (res_.prepareAst_.empty()) {
|
||||
cout << "syntax tree : " << endl;
|
||||
cout << "+++++++++++++++++++++syntax tree : " << endl;
|
||||
cout << res_.ast_ << endl;
|
||||
} else {
|
||||
cout << "prepare syntax tree : " << endl;
|
||||
cout << "+++++++++++++++++++++prepare syntax tree : " << endl;
|
||||
cout << res_.prepareAst_ << endl;
|
||||
cout << "bound syntax tree : " << endl;
|
||||
cout << "+++++++++++++++++++++bound syntax tree : " << endl;
|
||||
cout << res_.boundAst_ << endl;
|
||||
cout << "syntax tree : " << endl;
|
||||
cout << "+++++++++++++++++++++syntax tree : " << endl;
|
||||
cout << res_.ast_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_LOGIC == module) {
|
||||
cout << "raw logic plan : " << endl;
|
||||
cout << "+++++++++++++++++++++raw logic plan : " << endl;
|
||||
cout << res_.rawLogicPlan_ << endl;
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_OPTIMIZED == module) {
|
||||
cout << "optimized logic plan : " << endl;
|
||||
cout << "+++++++++++++++++++++optimized logic plan : " << endl;
|
||||
cout << res_.optimizedLogicPlan_ << endl;
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_SPLIT == module) {
|
||||
cout << "split logic plan : " << endl;
|
||||
cout << "+++++++++++++++++++++split logic plan : " << endl;
|
||||
cout << res_.splitLogicPlan_ << endl;
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_SCALED == module) {
|
||||
cout << "scaled logic plan : " << endl;
|
||||
cout << "+++++++++++++++++++++scaled logic plan : " << endl;
|
||||
cout << res_.scaledLogicPlan_ << endl;
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_PHYSICAL == module) {
|
||||
cout << "physical plan : " << endl;
|
||||
cout << "+++++++++++++++++++++physical plan : " << endl;
|
||||
cout << res_.physiPlan_ << endl;
|
||||
}
|
||||
|
||||
if (DUMP_MODULE_ALL == module || DUMP_MODULE_SUBPLAN == module) {
|
||||
cout << "physical subplan : " << endl;
|
||||
cout << "+++++++++++++++++++++physical subplan : " << endl;
|
||||
for (const auto& subplan : res_.physiSubplans_) {
|
||||
cout << subplan << endl;
|
||||
}
|
||||
|
|
|
@ -182,6 +182,11 @@ int32_t sclCopyValueNodeValue(SValueNode *pNode, void **res) {
|
|||
|
||||
int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t *rowNum) {
|
||||
switch (nodeType(node)) {
|
||||
case QUERY_NODE_LEFT_VALUE: {
|
||||
SSDataBlock* pb = taosArrayGetP(ctx->pBlockList, 0);
|
||||
param->numOfRows = pb->info.rows;
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_VALUE: {
|
||||
SValueNode *valueNode = (SValueNode *)node;
|
||||
|
||||
|
@ -845,7 +850,7 @@ EDealRes sclWalkTarget(SNode* pNode, SScalarCtx *ctx) {
|
|||
}
|
||||
|
||||
EDealRes sclCalcWalker(SNode* pNode, void* pContext) {
|
||||
if (QUERY_NODE_VALUE == nodeType(pNode) || QUERY_NODE_NODE_LIST == nodeType(pNode) || QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||
if (QUERY_NODE_VALUE == nodeType(pNode) || QUERY_NODE_NODE_LIST == nodeType(pNode) || QUERY_NODE_COLUMN == nodeType(pNode)|| QUERY_NODE_LEFT_VALUE == nodeType(pNode)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -824,7 +824,7 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
|
|||
}
|
||||
//for constant conversion, need to set proper length of pOutput description
|
||||
if (len < outputLen) {
|
||||
pOutput->columnData->info.bytes = len;
|
||||
pOutput->columnData->info.bytes = len + VARSTR_HEADER_SIZE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1333,6 +1333,22 @@ void vectorMathMinus(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pO
|
|||
doReleaseVec(pLeftCol, leftConvert);
|
||||
}
|
||||
|
||||
void vectorAssign(SScalarParam* pLeft, SScalarParam* pRight, SScalarParam *pOut, int32_t _ord) {
|
||||
SColumnInfoData *pOutputCol = pOut->columnData;
|
||||
|
||||
pOut->numOfRows = pLeft->numOfRows;
|
||||
|
||||
if (colDataIsNull_s(pRight->columnData, 0)) {
|
||||
for (int32_t i = 0; i < pOut->numOfRows; ++i) {
|
||||
colDataAppend(pOutputCol, i, NULL, true);
|
||||
}
|
||||
} else {
|
||||
for (int32_t i = 0; i < pOut->numOfRows; ++i) {
|
||||
colDataAppend(pOutputCol, i, colDataGetData(pRight->columnData, 0), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vectorConcat(SScalarParam* pLeft, SScalarParam* pRight, void *out, int32_t _ord) {
|
||||
#if 0
|
||||
int32_t len = pLeft->bytes + pRight->bytes;
|
||||
|
@ -1691,6 +1707,8 @@ _bin_scalar_fn_t getBinScalarOperatorFn(int32_t binFunctionId) {
|
|||
return vectorMathRemainder;
|
||||
case OP_TYPE_MINUS:
|
||||
return vectorMathMinus;
|
||||
case OP_TYPE_ASSIGN:
|
||||
return vectorAssign;
|
||||
case OP_TYPE_GREATER_THAN:
|
||||
return vectorGreater;
|
||||
case OP_TYPE_GREATER_EQUAL:
|
||||
|
|
|
@ -1089,7 +1089,7 @@ void makeCalculate(void *json, void *key, int32_t rightType, void *rightData, do
|
|||
}else if(opType == OP_TYPE_ADD || opType == OP_TYPE_SUB || opType == OP_TYPE_MULTI || opType == OP_TYPE_DIV ||
|
||||
opType == OP_TYPE_MOD || opType == OP_TYPE_MINUS){
|
||||
printf("1result:%f,except:%f\n", *((double *)colDataGetData(column, 0)), exceptValue);
|
||||
ASSERT_TRUE(abs(*((double *)colDataGetData(column, 0)) - exceptValue) < 1e-15);
|
||||
ASSERT_TRUE(fabs(*((double *)colDataGetData(column, 0)) - exceptValue) < 0.0001);
|
||||
}else if(opType == OP_TYPE_BIT_AND || opType == OP_TYPE_BIT_OR){
|
||||
printf("2result:%ld,except:%f\n", *((int64_t *)colDataGetData(column, 0)), exceptValue);
|
||||
ASSERT_EQ(*((int64_t *)colDataGetData(column, 0)), exceptValue);
|
||||
|
@ -1107,8 +1107,10 @@ void makeCalculate(void *json, void *key, int32_t rightType, void *rightData, do
|
|||
|
||||
TEST(columnTest, json_column_arith_op) {
|
||||
scltInitLogFile();
|
||||
char *rightv= "{\"k1\":4,\"k2\":\"hello\",\"k3\":null,\"k4\":true,\"k5\":5.44}";
|
||||
char *rightvTmp= "{\"k1\":4,\"k2\":\"hello\",\"k3\":null,\"k4\":true,\"k5\":5.44}";
|
||||
|
||||
char rightv[256] = {0};
|
||||
memcpy(rightv, rightvTmp, strlen(rightvTmp));
|
||||
SKVRowBuilder kvRowBuilder;
|
||||
tdInitKVRowBuilder(&kvRowBuilder);
|
||||
parseJsontoTagData(rightv, &kvRowBuilder, NULL, 0);
|
||||
|
@ -1189,8 +1191,10 @@ void *prepareNchar(char* rightData){
|
|||
|
||||
TEST(columnTest, json_column_logic_op) {
|
||||
scltInitLogFile();
|
||||
char *rightv= "{\"k1\":4,\"k2\":\"hello\",\"k3\":null,\"k4\":true,\"k5\":5.44,\"k6\":\"6.6hello\"}";
|
||||
char *rightvTmp= "{\"k1\":4,\"k2\":\"hello\",\"k3\":null,\"k4\":true,\"k5\":5.44,\"k6\":\"6.6hello\"}";
|
||||
|
||||
char rightv[256] = {0};
|
||||
memcpy(rightv, rightvTmp, strlen(rightvTmp));
|
||||
SKVRowBuilder kvRowBuilder;
|
||||
tdInitKVRowBuilder(&kvRowBuilder);
|
||||
parseJsontoTagData(rightv, &kvRowBuilder, NULL, 0);
|
||||
|
|
|
@ -264,7 +264,7 @@ int32_t schBuildAndSendMsg(SSchJob *job, SSchTask *task, SQueryNodeAddr *addr, i
|
|||
SSchJob *schAcquireJob(int64_t refId);
|
||||
int32_t schReleaseJob(int64_t refId);
|
||||
void schFreeFlowCtrl(SSchJob *pJob);
|
||||
int32_t schCheckJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel);
|
||||
int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel);
|
||||
int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask);
|
||||
int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough);
|
||||
int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask);
|
||||
|
@ -275,6 +275,32 @@ int32_t schBuildAndSendHbMsg(SQueryNodeEpId *nodeEpId);
|
|||
int32_t schCloneSMsgSendInfo(void *src, void **dst);
|
||||
int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob);
|
||||
void schFreeJobImpl(void *job);
|
||||
int32_t schMakeHbCallbackParam(SSchJob *pJob, SSchTask *pTask, void **pParam);
|
||||
int32_t schMakeHbRpcCtx(SSchJob *pJob, SSchTask *pTask, SRpcCtx *pCtx);
|
||||
int32_t schEnsureHbConnection(SSchJob *pJob, SSchTask *pTask);
|
||||
int32_t schUpdateHbConnection(SQueryNodeEpId *epId, SSchTrans *trans);
|
||||
int32_t schHandleHbCallback(void *param, const SDataBuf *pMsg, int32_t code);
|
||||
void schFreeRpcCtx(SRpcCtx *pCtx);
|
||||
int32_t schGetCallbackFp(int32_t msgType, __async_send_cb_fn_t *fp);
|
||||
bool schJobNeedToStop(SSchJob *pJob, int8_t *pStatus);
|
||||
int32_t schProcessOnTaskSuccess(SSchJob *pJob, SSchTask *pTask);
|
||||
int32_t schSaveJobQueryRes(SSchJob *pJob, SResReadyRsp *rsp);
|
||||
int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRsp *pRsp);
|
||||
void schProcessOnDataFetched(SSchJob *job);
|
||||
int32_t schGetTaskFromTaskList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask);
|
||||
int32_t schUpdateTaskExecNodeHandle(SSchTask *pTask, void *handle, int32_t rspCode);
|
||||
void schFreeRpcCtxVal(const void *arg);
|
||||
int32_t schMakeBrokenLinkVal(SSchJob *pJob, SSchTask *pTask, SRpcBrokenlinkVal *brokenVal, bool isHb);
|
||||
int32_t schRecordTaskExecNode(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr, void *handle);
|
||||
int32_t schExecStaticExplain(void *transport, SArray *pNodeList, SQueryPlan *pDag, int64_t *job, const char *sql,
|
||||
bool syncSchedule);
|
||||
int32_t schExecJobImpl(void *transport, SArray *pNodeList, SQueryPlan *pDag, int64_t *job, const char *sql,
|
||||
int64_t startTs, bool sync);
|
||||
int32_t schChkUpdateJobStatus(SSchJob *pJob, int8_t newStatus);
|
||||
int32_t schCancelJob(SSchJob *pJob);
|
||||
int32_t schProcessOnJobDropped(SSchJob *pJob, int32_t errCode);
|
||||
uint64_t schGenTaskId(void);
|
||||
void schCloseJobRef(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -40,7 +40,7 @@ void schFreeFlowCtrl(SSchJob *pJob) {
|
|||
pJob->flowCtrl = NULL;
|
||||
}
|
||||
|
||||
int32_t schCheckJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) {
|
||||
int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) {
|
||||
if (!SCH_IS_QUERY_JOB(pJob)) {
|
||||
SCH_JOB_DLOG("job no need flow ctrl, queryJob:%d", SCH_IS_QUERY_JOB(pJob));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "catalog.h"
|
||||
#include "command.h"
|
||||
#include "query.h"
|
||||
#include "schedulerInt.h"
|
||||
#include "tmsg.h"
|
||||
#include "tref.h"
|
||||
#include "trpc.h"
|
||||
|
||||
void schCloseJobRef(void) {
|
||||
if (!atomic_load_8((int8_t *)&schMgmt.exit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SCH_LOCK(SCH_WRITE, &schMgmt.lock);
|
||||
if (atomic_load_32(&schMgmt.jobNum) <= 0 && schMgmt.jobRef >= 0) {
|
||||
taosCloseRef(schMgmt.jobRef);
|
||||
schMgmt.jobRef = -1;
|
||||
}
|
||||
SCH_UNLOCK(SCH_WRITE, &schMgmt.lock);
|
||||
}
|
||||
|
||||
uint64_t schGenTaskId(void) { return atomic_add_fetch_64(&schMgmt.taskId, 1); }
|
||||
|
||||
uint64_t schGenUUID(void) {
|
||||
static uint64_t hashId = 0;
|
||||
static int32_t requestSerialId = 0;
|
||||
|
||||
if (hashId == 0) {
|
||||
char uid[64];
|
||||
int32_t code = taosGetSystemUUID(uid, tListLen(uid));
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("Failed to get the system uid, reason:%s", tstrerror(TAOS_SYSTEM_ERROR(errno)));
|
||||
} else {
|
||||
hashId = MurmurHash3_32(uid, strlen(uid));
|
||||
}
|
||||
}
|
||||
|
||||
int64_t ts = taosGetTimestampMs();
|
||||
uint64_t pid = taosGetPId();
|
||||
int32_t val = atomic_add_fetch_32(&requestSerialId, 1);
|
||||
|
||||
uint64_t id = ((hashId & 0x0FFF) << 52) | ((pid & 0x0FFF) << 40) | ((ts & 0xFFFFFF) << 16) | (val & 0xFFFF);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
void schFreeRpcCtxVal(const void *arg) {
|
||||
if (NULL == arg) {
|
||||
return;
|
||||
}
|
||||
|
||||
SMsgSendInfo *pMsgSendInfo = (SMsgSendInfo *)arg;
|
||||
taosMemoryFreeClear(pMsgSendInfo->param);
|
||||
taosMemoryFreeClear(pMsgSendInfo);
|
||||
}
|
||||
|
||||
void schFreeRpcCtx(SRpcCtx *pCtx) {
|
||||
if (NULL == pCtx) {
|
||||
return;
|
||||
}
|
||||
void *pIter = taosHashIterate(pCtx->args, NULL);
|
||||
while (pIter) {
|
||||
SRpcCtxVal *ctxVal = (SRpcCtxVal *)pIter;
|
||||
|
||||
(*ctxVal->freeFunc)(ctxVal->val);
|
||||
|
||||
pIter = taosHashIterate(pCtx->args, pIter);
|
||||
}
|
||||
|
||||
taosHashCleanup(pCtx->args);
|
||||
|
||||
if (pCtx->brokenVal.freeFunc) {
|
||||
(*pCtx->brokenVal.freeFunc)(pCtx->brokenVal.val);
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -14,17 +14,17 @@
|
|||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "tcompare.h"
|
||||
#include "os.h"
|
||||
#include "taoserror.h"
|
||||
#include "tcompare.h"
|
||||
#include "tref.h"
|
||||
#include "walInt.h"
|
||||
|
||||
typedef struct {
|
||||
int8_t stop;
|
||||
int8_t inited;
|
||||
uint32_t seq;
|
||||
int32_t refSetId;
|
||||
int8_t stop;
|
||||
int8_t inited;
|
||||
uint32_t seq;
|
||||
int32_t refSetId;
|
||||
TdThread thread;
|
||||
} SWalMgmt;
|
||||
|
||||
|
@ -36,30 +36,42 @@ static void walFreeObj(void *pWal);
|
|||
int64_t walGetSeq() { return (int64_t)atomic_load_32(&tsWal.seq); }
|
||||
|
||||
int32_t walInit() {
|
||||
int8_t old = atomic_val_compare_exchange_8(&tsWal.inited, 0, 1);
|
||||
if (old == 1) return 0;
|
||||
|
||||
tsWal.refSetId = taosOpenRef(TSDB_MIN_VNODES, walFreeObj);
|
||||
|
||||
int32_t code = walCreateThread();
|
||||
if (code != 0) {
|
||||
wError("failed to init wal module since %s", tstrerror(code));
|
||||
atomic_store_8(&tsWal.inited, 0);
|
||||
return code;
|
||||
int8_t old;
|
||||
while (1) {
|
||||
old = atomic_val_compare_exchange_8(&tsWal.inited, 0, 2);
|
||||
if (old != 2) break;
|
||||
}
|
||||
|
||||
if (old == 0) {
|
||||
tsWal.refSetId = taosOpenRef(TSDB_MIN_VNODES, walFreeObj);
|
||||
|
||||
int32_t code = walCreateThread();
|
||||
if (code != 0) {
|
||||
wError("failed to init wal module since %s", tstrerror(code));
|
||||
atomic_store_8(&tsWal.inited, 0);
|
||||
return code;
|
||||
}
|
||||
|
||||
wInfo("wal module is initialized, rsetId:%d", tsWal.refSetId);
|
||||
atomic_store_8(&tsWal.inited, 1);
|
||||
}
|
||||
|
||||
wInfo("wal module is initialized, rsetId:%d", tsWal.refSetId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void walCleanUp() {
|
||||
int8_t old = atomic_val_compare_exchange_8(&tsWal.inited, 1, 0);
|
||||
if (old == 0) {
|
||||
return;
|
||||
int8_t old;
|
||||
while (1) {
|
||||
old = atomic_val_compare_exchange_8(&tsWal.inited, 1, 2);
|
||||
if (old != 2) break;
|
||||
}
|
||||
|
||||
if (old == 1) {
|
||||
walStopThread();
|
||||
taosCloseRef(tsWal.refSetId);
|
||||
wInfo("wal module is cleaned up");
|
||||
atomic_store_8(&tsWal.inited, 0);
|
||||
}
|
||||
walStopThread();
|
||||
taosCloseRef(tsWal.refSetId);
|
||||
wInfo("wal module is cleaned up");
|
||||
}
|
||||
|
||||
SWal *walOpen(const char *path, SWalCfg *pCfg) {
|
||||
|
@ -126,7 +138,6 @@ SWal *walOpen(const char *path, SWalCfg *pCfg) {
|
|||
}
|
||||
|
||||
if (walCheckAndRepairIdx(pWal) < 0) {
|
||||
|
||||
}
|
||||
|
||||
wDebug("vgId:%d, wal:%p is opened, level:%d fsyncPeriod:%d", pWal->cfg.vgId, pWal, pWal->cfg.level,
|
||||
|
|
|
@ -259,6 +259,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_TRANS_NOT_EXIST, "Transaction not exist
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TRANS_INVALID_STAGE, "Invalid stage to kill")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TRANS_CONFLICT, "Conflict transaction not completed")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TRANS_UNKNOW_ERROR, "Unknown transaction error")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TRANS_CLOG_IS_NULL, "Transaction commitlog is null")
|
||||
|
||||
// mnode-mq
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOPIC_ALREADY_EXIST, "Topic already exists")
|
||||
|
|
|
@ -52,7 +52,7 @@ size_t strtrim(char *z) {
|
|||
int32_t j = 0;
|
||||
|
||||
int32_t delta = 0;
|
||||
while (z[j] == ' ') {
|
||||
while (isspace(z[j])) {
|
||||
++j;
|
||||
}
|
||||
|
||||
|
@ -65,9 +65,9 @@ size_t strtrim(char *z) {
|
|||
|
||||
int32_t stop = 0;
|
||||
while (z[j] != 0) {
|
||||
if (z[j] == ' ' && stop == 0) {
|
||||
if (isspace(z[j]) && stop == 0) {
|
||||
stop = j;
|
||||
} else if (z[j] != ' ' && stop != 0) {
|
||||
} else if (!isspace(z[j]) && stop != 0) {
|
||||
stop = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,565 @@
|
|||
###################################################################
|
||||
# Copyright (c) 2016 by TAOS Technologies, Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is proprietary and confidential to TAOS Technologies.
|
||||
# No part of this file may be reproduced, db_test.stored, transmitted,
|
||||
# disclosed or used in any form or by any means other than as
|
||||
# expressly provided by the written permission from Jianhui Tao
|
||||
#
|
||||
###################################################################
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import taos
|
||||
from util.log import tdLog
|
||||
from util.cases import tdCases
|
||||
from util.sql import tdSql
|
||||
import json
|
||||
|
||||
|
||||
class TDTestCase:
|
||||
def caseDescription(self):
|
||||
'''
|
||||
Json tag test case, include create table with json tag, select json tag and query with json tag in where condition, besides, include json tag in group by/order by/join/subquery.
|
||||
case1: [TD-12452] fix error if json tag is NULL
|
||||
case2: [TD-12389] describe child table, tag length error if the tag is json tag
|
||||
'''
|
||||
return
|
||||
|
||||
def init(self, conn, logSql):
|
||||
tdLog.debug("start to execute %s" % __file__)
|
||||
tdSql.init(conn.cursor(), logSql)
|
||||
|
||||
def run(self):
|
||||
tdSql.prepare()
|
||||
print("============== STEP 1 ===== prepare data & validate json string")
|
||||
tdSql.error("create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json, tagint int)")
|
||||
tdSql.error("create table if not exists jsons1(ts timestamp, data json) tags(tagint int)")
|
||||
tdSql.execute("create table if not exists jsons1(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)")
|
||||
tdSql.execute("insert into jsons1_1 using jsons1 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 1, false, 'json1', '你是') (1591060608000, 23, true, '等等', 'json')")
|
||||
tdSql.execute("insert into jsons1_2 using jsons1 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060628000, 2, true, 'json2', 'sss')")
|
||||
tdSql.execute("insert into jsons1_3 using jsons1 tags('{\"tag1\":false,\"tag2\":\"beijing\"}') values (1591060668000, 3, false, 'json3', 'efwe')")
|
||||
tdSql.execute("insert into jsons1_4 using jsons1 tags('{\"tag1\":null,\"tag2\":\"shanghai\",\"tag3\":\"hello\"}') values (1591060728000, 4, true, 'json4', '323sd')")
|
||||
tdSql.execute("insert into jsons1_5 using jsons1 tags('{\"tag1\":1.232, \"tag2\":null}') values(1591060928000, 1, false, '你就会', 'ewe')")
|
||||
tdSql.execute("insert into jsons1_6 using jsons1 tags('{\"tag1\":11,\"tag2\":\"\",\"tag2\":null}') values(1591061628000, 11, false, '你就会','')")
|
||||
tdSql.execute("insert into jsons1_7 using jsons1 tags('{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '你就会', 'dws')")
|
||||
|
||||
# test duplicate key using the first one. elimate empty key
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_8 using jsons1 tags('{\"tag1\":null, \"tag1\":true, \"tag1\":45, \"1tag$\":2, \" \":90, \"\":32}')")
|
||||
#tdSql.query("select jtag from jsons1_8")
|
||||
#tdSql.checkData(0, 0, '{"tag1":null,"1tag$":2," ":90}')
|
||||
|
||||
# test empty json string, save as jtag is NULL
|
||||
tdSql.execute("insert into jsons1_9 using jsons1 tags('\t') values (1591062328000, 24, NULL, '你就会', '2sdw')")
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_10 using jsons1 tags('')")
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_11 using jsons1 tags(' ')")
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_12 using jsons1 tags('{}')")
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_13 using jsons1 tags('null')")
|
||||
|
||||
# test invalidate json
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('\"efwewf\"')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('3333')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('33.33')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('false')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('[1,true]')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{222}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"fe\"}')")
|
||||
#
|
||||
# test invalidate json key, key must can be printed assic char
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":[1,true]}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"tag1\":{}}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"。loc\":\"fff\"}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"\t\":\"fff\"}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"试试\":\"fff\"}')")
|
||||
|
||||
# test invalidate json value, value number can not be inf,nan TD-12166
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"k\":1.8e308}')")
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_14 using jsons1 tags('{\"k\":-1.8e308}')")
|
||||
#
|
||||
#test length limit
|
||||
char1= ''.join(['abcd']*64)
|
||||
char3= ''.join(['abcd']*1021)
|
||||
print(len(char3)) # 4084
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_15 using jsons1 tags('{\"%s1\":5}')" % char1) # len(key)=257
|
||||
tdSql.execute("CREATE TABLE if not exists jsons1_15 using jsons1 tags('{\"%s\":5}')" % char1) # len(key)=256
|
||||
tdSql.error("CREATE TABLE if not exists jsons1_16 using jsons1 tags('{\"TSSSS\":\"%s\"}')" % char3) # len(object)=4096
|
||||
#tdSql.execute("CREATE TABLE if not exists jsons1_16 using jsons1 tags('{\"TSSS\":\"%s\"}')" % char3) # len(object)=4095
|
||||
tdSql.execute("drop table if exists jsons1_15")
|
||||
tdSql.execute("drop table if exists jsons1_16")
|
||||
#
|
||||
print("============== STEP 2 ===== alter table json tag")
|
||||
tdSql.error("ALTER STABLE jsons1 add tag tag2 nchar(20)")
|
||||
tdSql.error("ALTER STABLE jsons1 drop tag jtag")
|
||||
tdSql.error("ALTER TABLE jsons1 MODIFY TAG jtag nchar(128)")
|
||||
#
|
||||
tdSql.execute("ALTER TABLE jsons1_1 SET TAG jtag='{\"tag1\":\"femail\",\"tag2\":35,\"tag3\":true}'")
|
||||
# tdSql.query("select jtag from jsons1_1")
|
||||
# tdSql.checkData(0, 0, '{"tag1":"femail","tag2":35,"tag3":true}')
|
||||
tdSql.execute("ALTER TABLE jsons1 rename TAG jtag jtag_new")
|
||||
tdSql.execute("ALTER TABLE jsons1 rename TAG jtag_new jtag")
|
||||
|
||||
tdSql.execute("create table st(ts timestamp, i int) tags(t int)")
|
||||
tdSql.error("ALTER STABLE st add tag jtag json")
|
||||
tdSql.error("ALTER STABLE st add column jtag json")
|
||||
#
|
||||
# print("============== STEP 3 ===== query table")
|
||||
# # test error syntax
|
||||
# tdSql.error("select * from jsons1 where jtag->tag1='beijing'")
|
||||
# tdSql.error("select * from jsons1 where jtag->'location'")
|
||||
# tdSql.error("select * from jsons1 where jtag->''")
|
||||
# tdSql.error("select * from jsons1 where jtag->''=9")
|
||||
# tdSql.error("select -> from jsons1")
|
||||
# tdSql.error("select * from jsons1 where contains")
|
||||
# tdSql.error("select * from jsons1 where jtag->")
|
||||
# tdSql.error("select jtag->location from jsons1")
|
||||
# tdSql.error("select jtag contains location from jsons1")
|
||||
# tdSql.error("select * from jsons1 where jtag contains location")
|
||||
# tdSql.error("select * from jsons1 where jtag contains''")
|
||||
# tdSql.error("select * from jsons1 where jtag contains 'location'='beijing'")
|
||||
#
|
||||
# # test function error
|
||||
# tdSql.error("select avg(jtag->'tag1') from jsons1")
|
||||
# tdSql.error("select avg(jtag) from jsons1")
|
||||
# tdSql.error("select min(jtag->'tag1') from jsons1")
|
||||
# tdSql.error("select min(jtag) from jsons1")
|
||||
# tdSql.error("select ceil(jtag->'tag1') from jsons1")
|
||||
# tdSql.error("select ceil(jtag) from jsons1")
|
||||
#
|
||||
# # test select normal column
|
||||
# tdSql.query("select dataint from jsons1")
|
||||
# tdSql.checkRows(9)
|
||||
# tdSql.checkData(1, 0, 1)
|
||||
|
||||
# test select json tag
|
||||
# tdSql.query("select * from jsons1")
|
||||
# tdSql.checkRows(8)
|
||||
# tdSql.query("select jtag from jsons1")
|
||||
# tdSql.checkRows(7)
|
||||
# tdSql.query("select jtag from jsons1 where jtag is null")
|
||||
# tdSql.checkRows(5)
|
||||
# tdSql.query("select jtag from jsons1 where jtag is not null")
|
||||
# tdSql.checkRows(8)
|
||||
|
||||
# test jtag is NULL
|
||||
#tdSql.query("select jtag from jsons1_9")
|
||||
#tdSql.checkData(0, 0, None)
|
||||
|
||||
# # test select json tag->'key', value is string
|
||||
# tdSql.query("select jtag->'tag1' from jsons1_1")
|
||||
# tdSql.checkData(0, 0, '"femail"')
|
||||
# tdSql.query("select jtag->'tag2' from jsons1_6")
|
||||
# tdSql.checkData(0, 0, '""')
|
||||
# # test select json tag->'key', value is int
|
||||
# tdSql.query("select jtag->'tag2' from jsons1_1")
|
||||
# tdSql.checkData(0, 0, 35)
|
||||
# # test select json tag->'key', value is bool
|
||||
# tdSql.query("select jtag->'tag3' from jsons1_1")
|
||||
# tdSql.checkData(0, 0, "true")
|
||||
# # test select json tag->'key', value is null
|
||||
# tdSql.query("select jtag->'tag1' from jsons1_4")
|
||||
# tdSql.checkData(0, 0, "null")
|
||||
# # test select json tag->'key', value is double
|
||||
# tdSql.query("select jtag->'tag1' from jsons1_5")
|
||||
# tdSql.checkData(0, 0, "1.232000000")
|
||||
# # test select json tag->'key', key is not exist
|
||||
# tdSql.query("select jtag->'tag10' from jsons1_4")
|
||||
# tdSql.checkData(0, 0, None)
|
||||
#
|
||||
# tdSql.query("select jtag->'tag1' from jsons1")
|
||||
# tdSql.checkRows(13)
|
||||
# test header name
|
||||
res = tdSql.getColNameList("select jtag->'tag1' from jsons1")
|
||||
cname_list = []
|
||||
cname_list.append("jtag->'tag1'")
|
||||
tdSql.checkColNameList(res, cname_list)
|
||||
|
||||
|
||||
|
||||
# # test where with json tag
|
||||
# tdSql.error("select * from jsons1_1 where jtag is not null")
|
||||
# tdSql.error("select * from jsons1 where jtag='{\"tag1\":11,\"tag2\":\"\"}'")
|
||||
# tdSql.error("select * from jsons1 where jtag->'tag1'={}")
|
||||
#
|
||||
# # where json value is string
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'='beijing'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select dataint,tbname,jtag->'tag1',jtag from jsons1 where jtag->'tag2'='beijing'")
|
||||
# tdSql.checkData(0, 0, 2)
|
||||
# tdSql.checkData(0, 1, 'jsons1_2')
|
||||
# tdSql.checkData(0, 2, 5)
|
||||
# tdSql.checkData(0, 3, '{"tag1":5,"tag2":"beijing"}')
|
||||
# tdSql.checkData(1, 0, 3)
|
||||
# tdSql.checkData(1, 1, 'jsons1_3')
|
||||
# tdSql.checkData(1, 2, 'false')
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'='beijing'")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'='收到货'")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'>'beijing'")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'>='beijing'")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'<'beijing'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'<='beijing'")
|
||||
# tdSql.checkRows(4)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'!='beijing'")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2'=''")
|
||||
# tdSql.checkRows(2)
|
||||
#
|
||||
# # where json value is int
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=5")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.checkData(0, 1, 2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=10")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'<54")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'<=11")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'>4")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'>=5")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'!=5")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'!=55")
|
||||
# tdSql.checkRows(3)
|
||||
#
|
||||
# # where json value is double
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=1.232")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'<1.232")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'<=1.232")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'>1.23")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'>=1.232")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'!=1.232")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'!=3.232")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.error("select * from jsons1 where jtag->'tag1'/0=3")
|
||||
# tdSql.error("select * from jsons1 where jtag->'tag1'/5=1")
|
||||
#
|
||||
# # where json value is bool
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=true")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=false")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'!=false")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.error("select * from jsons1 where jtag->'tag1'>false")
|
||||
#
|
||||
# # where json value is null
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=null") # only json suport =null. This synatx will change later.
|
||||
# tdSql.checkRows(1)
|
||||
#
|
||||
# # where json is null
|
||||
# tdSql.query("select * from jsons1 where jtag is null")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag is not null")
|
||||
# tdSql.checkRows(8)
|
||||
#
|
||||
# # where json key is null
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag_no_exist'=3")
|
||||
# tdSql.checkRows(0)
|
||||
#
|
||||
# # where json value is not exist
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' is null")
|
||||
# tdSql.checkData(0, 0, 'jsons1_9')
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag4' is null")
|
||||
# tdSql.checkRows(9)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag3' is not null")
|
||||
# tdSql.checkRows(4)
|
||||
#
|
||||
# # test contains
|
||||
# tdSql.query("select * from jsons1 where jtag contains 'tag1'")
|
||||
# tdSql.checkRows(8)
|
||||
# tdSql.query("select * from jsons1 where jtag contains 'tag3'")
|
||||
# tdSql.checkRows(4)
|
||||
# tdSql.query("select * from jsons1 where jtag contains 'tag_no_exist'")
|
||||
# tdSql.checkRows(0)
|
||||
#
|
||||
# # test json tag in where condition with and/or
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='beijing'")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=false or jtag->'tag2'='beijing'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=false and jtag->'tag2'='shanghai'")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'=13 or jtag->'tag2'>35")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' is not null and jtag contains 'tag3'")
|
||||
# tdSql.checkRows(4)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1'='femail' and jtag contains 'tag3'")
|
||||
# tdSql.checkRows(2)
|
||||
#
|
||||
#
|
||||
# # test with between and
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' between 1 and 30")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' between 'femail' and 'beijing'")
|
||||
# tdSql.checkRows(2)
|
||||
#
|
||||
# # test with tbname/normal column
|
||||
# tdSql.query("select * from jsons1 where tbname = 'jsons1_1'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=3")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where tbname = 'jsons1_1' and jtag contains 'tag3' and dataint=23")
|
||||
# tdSql.checkRows(1)
|
||||
#
|
||||
#
|
||||
# # test where condition like
|
||||
# tdSql.query("select *,tbname from jsons1 where jtag->'tag2' like 'bei%'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select *,tbname from jsons1 where jtag->'tag1' like 'fe%' and jtag->'tag2' is not null")
|
||||
# tdSql.checkRows(2)
|
||||
#
|
||||
# # test where condition in no support in
|
||||
# tdSql.error("select * from jsons1 where jtag->'tag1' in ('beijing')")
|
||||
#
|
||||
# # test where condition match/nmath
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' match 'ma'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' match 'ma$'")
|
||||
# tdSql.checkRows(0)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag2' match 'jing$'")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' match '收到'")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select * from jsons1 where jtag->'tag1' nmatch 'ma'")
|
||||
# tdSql.checkRows(1)
|
||||
#
|
||||
# # test distinct
|
||||
# tdSql.execute("insert into jsons1_14 using jsons1 tags('{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":null}') values(1591062628000, 2, NULL, '你就会', 'dws')")
|
||||
# tdSql.query("select distinct jtag->'tag1' from jsons1")
|
||||
# tdSql.checkRows(8)
|
||||
# tdSql.query("select distinct jtag from jsons1")
|
||||
# tdSql.checkRows(9)
|
||||
#
|
||||
# #test dumplicate key with normal colomn
|
||||
# tdSql.execute("INSERT INTO jsons1_15 using jsons1 tags('{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"是是是\"}') values(1591060828000, 4, false, 'jjsf', \"你就会\")")
|
||||
# tdSql.query("select *,tbname,jtag from jsons1 where jtag->'datastr' match '是' and datastr match 'js'")
|
||||
# tdSql.checkRows(1)
|
||||
# tdSql.query("select tbname,jtag->'tbname' from jsons1 where jtag->'tbname'='tt' and tbname='jsons1_14'")
|
||||
# tdSql.checkRows(0)
|
||||
#
|
||||
# # test join
|
||||
# tdSql.execute("create table if not exists jsons2(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)")
|
||||
# tdSql.execute("insert into jsons2_1 using jsons2 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 2, false, 'json2', '你是2')")
|
||||
# tdSql.execute("insert into jsons2_2 using jsons2 tags('{\"tag1\":5,\"tag2\":null}') values (1591060628000, 2, true, 'json2', 'sss')")
|
||||
#
|
||||
# tdSql.execute("create table if not exists jsons3(ts timestamp, dataInt int, dataBool bool, dataStr nchar(50), dataStrBin binary(150)) tags(jtag json)")
|
||||
# tdSql.execute("insert into jsons3_1 using jsons3 tags('{\"tag1\":\"fff\",\"tag2\":5, \"tag3\":true}') values(1591060618000, 3, false, 'json3', '你是3')")
|
||||
# tdSql.execute("insert into jsons3_2 using jsons3 tags('{\"tag1\":5,\"tag2\":\"beijing\"}') values (1591060638000, 2, true, 'json3', 'sss')")
|
||||
# tdSql.query("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'")
|
||||
# tdSql.checkData(0, 0, "sss")
|
||||
# tdSql.checkData(0, 2, "true")
|
||||
#
|
||||
# res = tdSql.getColNameList("select 'sss',33,a.jtag->'tag3' from jsons2 a,jsons3 b where a.ts=b.ts and a.jtag->'tag1'=b.jtag->'tag1'")
|
||||
# cname_list = []
|
||||
# cname_list.append("sss")
|
||||
# cname_list.append("33")
|
||||
# cname_list.append("a.jtag->'tag3'")
|
||||
# tdSql.checkColNameList(res, cname_list)
|
||||
#
|
||||
# # test group by & order by json tag
|
||||
# tdSql.error("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag2'")
|
||||
# tdSql.error("select count(*) from jsons1 group by jtag->'tag1' order by jtag")
|
||||
# tdSql.query("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' desc")
|
||||
# tdSql.checkRows(8)
|
||||
# tdSql.checkData(1, 0, 2)
|
||||
# tdSql.checkData(1, 1, '"femail"')
|
||||
# tdSql.checkData(2, 0, 1)
|
||||
# tdSql.checkData(2, 1, 11)
|
||||
# tdSql.checkData(5, 0, 1)
|
||||
# tdSql.checkData(5, 1, "false")
|
||||
# tdSql.checkData(6, 0, 1)
|
||||
# tdSql.checkData(6, 1, "null")
|
||||
# tdSql.checkData(7, 0, 2)
|
||||
# tdSql.checkData(7, 1, None)
|
||||
#
|
||||
# tdSql.query("select count(*) from jsons1 group by jtag->'tag1' order by jtag->'tag1' asc")
|
||||
# tdSql.checkRows(8)
|
||||
# tdSql.checkData(0, 0, 2)
|
||||
# tdSql.checkData(0, 1, None)
|
||||
# tdSql.checkData(2, 0, 1)
|
||||
# tdSql.checkData(2, 1, "false")
|
||||
# tdSql.checkData(5, 0, 1)
|
||||
# tdSql.checkData(5, 1, 11)
|
||||
# tdSql.checkData(6, 0, 2)
|
||||
# tdSql.checkData(6, 1, '"femail"')
|
||||
#
|
||||
# # test stddev with group by json tag
|
||||
# tdSql.query("select stddev(dataint) from jsons1 group by jtag->'tag1'")
|
||||
# tdSql.checkData(0, 0, 10)
|
||||
# tdSql.checkData(0, 1, None)
|
||||
# tdSql.checkData(1, 0, 0)
|
||||
# tdSql.checkData(1, 1, "null")
|
||||
# tdSql.checkData(6, 0, 11)
|
||||
# tdSql.checkData(6, 1, '"femail"')
|
||||
#
|
||||
# res = tdSql.getColNameList("select stddev(dataint) from jsons1 group by jsons1.jtag->'tag1'")
|
||||
# cname_list = []
|
||||
# cname_list.append("stddev(dataint)")
|
||||
# cname_list.append("jsons1.jtag->'tag1'")
|
||||
# tdSql.checkColNameList(res, cname_list)
|
||||
#
|
||||
# # test top/bottom with group by json tag
|
||||
# tdSql.query("select top(dataint,100) from jsons1 group by jtag->'tag1'")
|
||||
# tdSql.checkRows(11)
|
||||
# tdSql.checkData(0, 1, 4)
|
||||
# tdSql.checkData(1, 1, 24)
|
||||
# tdSql.checkData(1, 2, None)
|
||||
# tdSql.checkData(8, 1, 1)
|
||||
# tdSql.checkData(8, 2, '"femail"')
|
||||
#
|
||||
# # test having
|
||||
# tdSql.query("select stddev(dataint) from jsons1 group by jtag->'tag1' having stddev(dataint) > 0")
|
||||
# tdSql.checkRows(2)
|
||||
#
|
||||
# # subquery with json tag
|
||||
# tdSql.query("select * from (select jtag, dataint from jsons1)")
|
||||
# tdSql.checkRows(11)
|
||||
# tdSql.checkData(1, 1, 1)
|
||||
# tdSql.checkData(2, 0, '{"tag1":5,"tag2":"beijing"}')
|
||||
#
|
||||
# tdSql.query("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)")
|
||||
# tdSql.checkRows(11)
|
||||
# tdSql.checkData(1, 0, '"femail"')
|
||||
# tdSql.checkData(2, 0, 5)
|
||||
#
|
||||
# res = tdSql.getColNameList("select jtag->'tag1' from (select jtag->'tag1', dataint from jsons1)")
|
||||
# cname_list = []
|
||||
# cname_list.append("jtag->'tag1'")
|
||||
# tdSql.checkColNameList(res, cname_list)
|
||||
#
|
||||
# tdSql.query("select ts,tbname,jtag->'tag1' from (select jtag->'tag1',tbname,ts from jsons1 order by ts)")
|
||||
# tdSql.checkRows(11)
|
||||
# tdSql.checkData(1, 1, "jsons1_1")
|
||||
# tdSql.checkData(1, 2, '"femail"')
|
||||
#
|
||||
# # union all
|
||||
# tdSql.error("select jtag->'tag1' from jsons1 union all select jtag->'tag2' from jsons2")
|
||||
# tdSql.error("select jtag->'tag1' from jsons1_1 union all select jtag->'tag2' from jsons2_1")
|
||||
#
|
||||
# tdSql.query("select jtag->'tag1' from jsons1_1 union all select jtag->'tag1' from jsons2_1")
|
||||
# tdSql.checkRows(2)
|
||||
# tdSql.query("select dataint,jtag->'tag1',tbname from jsons1 union all select dataint,jtag->'tag1',tbname from jsons2")
|
||||
# tdSql.checkRows(13)
|
||||
# tdSql.query("select dataint,jtag,tbname from jsons1 union all select dataint,jtag,tbname from jsons2")
|
||||
# tdSql.checkRows(13)
|
||||
#
|
||||
# #show create table
|
||||
# tdSql.query("show create table jsons1")
|
||||
# tdSql.checkData(0, 1, 'CREATE TABLE `jsons1` (`ts` TIMESTAMP,`dataint` INT,`databool` BOOL,`datastr` NCHAR(50),`datastrbin` BINARY(150)) TAGS (`jtag` JSON)')
|
||||
#
|
||||
# #test aggregate function:count/avg/twa/irate/sum/stddev/leastsquares
|
||||
# tdSql.query("select count(*) from jsons1 where jtag is not null")
|
||||
# tdSql.checkData(0, 0, 10)
|
||||
# tdSql.query("select avg(dataint) from jsons1 where jtag is not null")
|
||||
# tdSql.checkData(0, 0, 5.3)
|
||||
# tdSql.error("select twa(dataint) from jsons1 where jtag is not null")
|
||||
# tdSql.error("select irate(dataint) from jsons1 where jtag is not null")
|
||||
# tdSql.query("select sum(dataint) from jsons1 where jtag->'tag1' is not null")
|
||||
# tdSql.checkData(0, 0, 49)
|
||||
# tdSql.query("select stddev(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 4.496912521)
|
||||
# tdSql.error("SELECT LEASTSQUARES(dataint, 1, 1) from jsons1 where jtag is not null")
|
||||
#
|
||||
# #test selection function:min/max/first/last/top/bottom/percentile/apercentile/last_row/interp
|
||||
# tdSql.query("select min(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 1)
|
||||
# tdSql.query("select max(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 11)
|
||||
# tdSql.query("select first(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 2)
|
||||
# tdSql.query("select last(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 11)
|
||||
# tdSql.query("select top(dataint,100) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select bottom(dataint,100) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.error("select percentile(dataint,20) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.query("select apercentile(dataint, 50) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 1.5)
|
||||
# tdSql.query("select last_row(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 11)
|
||||
# tdSql.error("select interp(dataint) from jsons1 where ts = '2020-06-02 09:17:08.000' and jtag->'tag1'>1")
|
||||
#
|
||||
# #test calculation function:diff/derivative/spread/ceil/floor/round/
|
||||
# tdSql.error("select diff(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.error("select derivative(dataint, 10m, 0) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.query("select spread(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkData(0, 0, 10)
|
||||
# tdSql.query("select ceil(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select floor(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkRows(3)
|
||||
# tdSql.query("select round(dataint) from jsons1 where jtag->'tag1'>1")
|
||||
# tdSql.checkRows(3)
|
||||
#
|
||||
# #test TD-12077
|
||||
# tdSql.execute("insert into jsons1_16 using jsons1 tags('{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":-2.111}') values(1591062628000, 2, NULL, '你就会', 'dws')")
|
||||
# tdSql.query("select jtag->'tag3' from jsons1_16")
|
||||
# tdSql.checkData(0, 0, '-2.111000000')
|
||||
#
|
||||
# # test TD-12452
|
||||
# tdSql.execute("ALTER TABLE jsons1_1 SET TAG jtag=NULL")
|
||||
# tdSql.query("select jtag from jsons1_1")
|
||||
# tdSql.checkData(0, 0, None)
|
||||
# tdSql.execute("CREATE TABLE if not exists jsons1_20 using jsons1 tags(NULL)")
|
||||
# tdSql.query("select jtag from jsons1_20")
|
||||
# tdSql.checkData(0, 0, None)
|
||||
# tdSql.execute("insert into jsons1_21 using jsons1 tags(NULL) values(1591061628000, 11, false, '你就会','')")
|
||||
# tdSql.query("select jtag from jsons1_21")
|
||||
# tdSql.checkData(0, 0, None)
|
||||
#
|
||||
# #test TD-12389
|
||||
tdSql.query("describe jsons1")
|
||||
tdSql.checkData(5, 2, 4095)
|
||||
tdSql.query("describe jsons1_1")
|
||||
tdSql.checkData(5, 2, 4095)
|
||||
#
|
||||
# #test TD-13918
|
||||
# tdSql.execute("drop table if exists jsons_13918_1")
|
||||
# tdSql.execute("drop table if exists jsons_13918_2")
|
||||
# tdSql.execute("drop table if exists jsons_13918_3")
|
||||
# tdSql.execute("drop table if exists jsons_13918_4")
|
||||
# tdSql.execute("drop table if exists jsons_stb")
|
||||
# tdSql.execute("create table jsons_stb (ts timestamp, dataInt int) tags (jtag json)")
|
||||
# tdSql.error("create table jsons_13918_1 using jsons_stb tags ('nullx')")
|
||||
# tdSql.error("create table jsons_13918_2 using jsons_stb tags (nullx)")
|
||||
# tdSql.error("insert into jsons_13918_3 using jsons_stb tags('NULLx') values(1591061628001, 11)")
|
||||
# tdSql.error("insert into jsons_13918_4 using jsons_stb tags(NULLx) values(1591061628002, 11)")
|
||||
# tdSql.execute("create table jsons_13918_1 using jsons_stb tags ('null')")
|
||||
# tdSql.execute("create table jsons_13918_2 using jsons_stb tags (null)")
|
||||
# tdSql.execute("insert into jsons_13918_1 values(1591061628003, 11)")
|
||||
# tdSql.execute("insert into jsons_13918_2 values(1591061628004, 11)")
|
||||
# tdSql.execute("insert into jsons_13918_3 using jsons_stb tags('NULL') values(1591061628005, 11)")
|
||||
# tdSql.execute("insert into jsons_13918_4 using jsons_stb tags(\"NULL\") values(1591061628006, 11)")
|
||||
# tdSql.query("select * from jsons_stb")
|
||||
# tdSql.checkRows(4)
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success("%s successfully executed" % __file__)
|
||||
|
||||
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
|
Loading…
Reference in New Issue