[TD-32] fix bugs in super table query.
This commit is contained in:
parent
e45701a667
commit
8ff864021b
|
@ -636,10 +636,11 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
||||||
|
|
||||||
pModel = createColumnModel(pSchema, pQueryInfo->exprsInfo.numOfExprs, capacity);
|
pModel = createColumnModel(pSchema, pQueryInfo->exprsInfo.numOfExprs, capacity);
|
||||||
|
|
||||||
// for (int32_t i = 0; i < pTableMetaInfo->pMetricMeta->numOfVnodes; ++i) {
|
size_t numOfSubs = taosArrayGetSize(pTableMetaInfo->vgroupIdList);
|
||||||
// (*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pModel);
|
for (int32_t i = 0; i < numOfSubs; ++i) {
|
||||||
// (*pMemBuffer)[i]->flushModel = MULTIPLE_APPEND_MODEL;
|
(*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pModel);
|
||||||
// }
|
(*pMemBuffer)[i]->flushModel = MULTIPLE_APPEND_MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
if (createOrderDescriptor(pOrderDesc, pCmd, pModel) != TSDB_CODE_SUCCESS) {
|
if (createOrderDescriptor(pOrderDesc, pCmd, pModel) != TSDB_CODE_SUCCESS) {
|
||||||
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
|
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
|
||||||
|
|
|
@ -509,31 +509,31 @@ int tscBuildRetrieveMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int tscBuildSubmitMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
int tscBuildSubmitMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||||
SSubmitMsg *pShellMsg;
|
|
||||||
char * pMsg, *pStart;
|
|
||||||
|
|
||||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||||
STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
STableMeta* pTableMeta = tscGetMetaInfo(pQueryInfo, 0)->pTableMeta;
|
||||||
|
|
||||||
pStart = pSql->cmd.payload + tsRpcHeadSize;
|
char* pMsg = pSql->cmd.payload + tsRpcHeadSize;
|
||||||
pMsg = pStart;
|
|
||||||
|
// NOTE: shell message size should not include SMsgDesc
|
||||||
|
int32_t size = pSql->cmd.payloadLen - sizeof(SMsgDesc);
|
||||||
|
|
||||||
SMsgDesc* pMsgDesc = (SMsgDesc*) pMsg;
|
SMsgDesc* pMsgDesc = (SMsgDesc*) pMsg;
|
||||||
pMsgDesc->numOfVnodes = htonl(1); //set the number of vnodes
|
|
||||||
|
pMsgDesc->numOfVnodes = htonl(1); //todo set the right number of vnodes
|
||||||
pMsg += sizeof(SMsgDesc);
|
pMsg += sizeof(SMsgDesc);
|
||||||
|
|
||||||
pShellMsg = (SSubmitMsg *)pMsg;
|
SSubmitMsg *pShellMsg = (SSubmitMsg *)pMsg;
|
||||||
|
|
||||||
pShellMsg->header.vgId = htonl(pTableMeta->vgId);
|
pShellMsg->header.vgId = htonl(pTableMeta->vgId);
|
||||||
pShellMsg->header.contLen = htonl(pSql->cmd.payloadLen);
|
pShellMsg->header.contLen = htonl(size);
|
||||||
pShellMsg->length = pShellMsg->header.contLen;
|
pShellMsg->length = pShellMsg->header.contLen;
|
||||||
|
|
||||||
pShellMsg->numOfBlocks = htonl(pSql->cmd.numOfTablesInSubmit); // number of meters to be inserted
|
pShellMsg->numOfBlocks = htonl(pSql->cmd.numOfTablesInSubmit); // number of meters to be inserted
|
||||||
|
|
||||||
// pSql->cmd.payloadLen is set during parse sql routine, so we do not use it here
|
// pSql->cmd.payloadLen is set during copying data into paylaod
|
||||||
pSql->cmd.msgType = TSDB_MSG_TYPE_SUBMIT;
|
pSql->cmd.msgType = TSDB_MSG_TYPE_SUBMIT;
|
||||||
|
tscTrace("%p build submit msg, vgId:%d numOfVnodes:%d", pSql, pTableMeta->vgId, htons(pMsgDesc->numOfVnodes));
|
||||||
|
|
||||||
// tscTrace("%p update submit msg vnode:%s:%d", pSql, taosIpStr(pTableMeta->vpeerDesc[pTableMeta->index].ip),
|
|
||||||
// htons(pShellMsg->vnode));
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1006,14 +1006,12 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
|
||||||
|
|
||||||
pRes->qhandle = 1; // hack the qhandle check
|
pRes->qhandle = 1; // hack the qhandle check
|
||||||
|
|
||||||
const uint32_t nBufferSize = (1 << 16); // 64KB
|
const uint32_t nBufferSize = (1u << 16); // 64KB
|
||||||
|
|
||||||
SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||||
|
|
||||||
int32_t numOfSubQueries = 1;
|
int32_t numOfSubQueries = taosArrayGetSize(pTableMetaInfo->vgroupIdList);
|
||||||
// int32_t numOfSubQueries = pTableMetaInfo->pMetricMeta->numOfVnodes;
|
|
||||||
|
|
||||||
assert(numOfSubQueries > 0);
|
assert(numOfSubQueries > 0);
|
||||||
|
|
||||||
int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, nBufferSize);
|
int32_t ret = tscLocalReducerEnvCreate(pSql, &pMemoryBuf, &pDesc, &pModel, nBufferSize);
|
||||||
|
@ -1119,7 +1117,7 @@ static void tscFreeSubSqlObj(SRetrieveSupport *trsupport, SSqlObj *pSql) {
|
||||||
tfree(trsupport);
|
tfree(trsupport);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tscRetrieveFromVnodeCallBack(void *param, TAOS_RES *tres, int numOfRows);
|
static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfRows);
|
||||||
|
|
||||||
static void tscAbortFurtherRetryRetrieval(SRetrieveSupport *trsupport, TAOS_RES *tres, int32_t errCode) {
|
static void tscAbortFurtherRetryRetrieval(SRetrieveSupport *trsupport, TAOS_RES *tres, int32_t errCode) {
|
||||||
// set no disk space error info
|
// set no disk space error info
|
||||||
|
@ -1141,7 +1139,7 @@ static void tscAbortFurtherRetryRetrieval(SRetrieveSupport *trsupport, TAOS_RES
|
||||||
|
|
||||||
pthread_mutex_unlock(&trsupport->queryMutex);
|
pthread_mutex_unlock(&trsupport->queryMutex);
|
||||||
|
|
||||||
tscRetrieveFromVnodeCallBack(trsupport, tres, trsupport->pState->code);
|
tscRetrieveFromDnodeCallBack(trsupport, tres, trsupport->pState->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tscHandleSubRetrievalError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numOfRows) {
|
static void tscHandleSubRetrievalError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numOfRows) {
|
||||||
|
@ -1236,7 +1234,86 @@ static void tscHandleSubRetrievalError(SRetrieveSupport *trsupport, SSqlObj *pSq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tscRetrieveFromVnodeCallBack(void *param, TAOS_RES *tres, int numOfRows) {
|
static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* pSql) {
|
||||||
|
int32_t idx = trsupport->subqueryIndex;
|
||||||
|
SSqlObj * pPObj = trsupport->pParentSqlObj;
|
||||||
|
tOrderDescriptor *pDesc = trsupport->pOrderDescriptor;
|
||||||
|
|
||||||
|
SSubqueryState* pState = trsupport->pState;
|
||||||
|
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||||
|
|
||||||
|
// data in from current vnode is stored in cache and disk
|
||||||
|
uint32_t numOfRowsFromSubquery = trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->numOfElems;
|
||||||
|
// tscTrace("%p sub:%p all data retrieved from ip:%u,vid:%d, numOfRows:%d, orderOfSub:%d", pPObj, pSql, pSvd->ip,
|
||||||
|
// pSvd->vnode, numOfRowsFromSubquery, idx);
|
||||||
|
|
||||||
|
tColModelCompact(pDesc->pColumnModel, trsupport->localBuffer, pDesc->pColumnModel->capacity);
|
||||||
|
|
||||||
|
#ifdef _DEBUG_VIEW
|
||||||
|
printf("%" PRIu64 " rows data flushed to disk:\n", trsupport->localBuffer->numOfElems);
|
||||||
|
SSrcColumnInfo colInfo[256] = {0};
|
||||||
|
tscGetSrcColumnInfo(colInfo, pQueryInfo);
|
||||||
|
tColModelDisplayEx(pDesc->pColumnModel, trsupport->localBuffer->data, trsupport->localBuffer->numOfElems,
|
||||||
|
trsupport->localBuffer->numOfElems, colInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (tsTotalTmpDirGB != 0 && tsAvailTmpDirGB < tsMinimalTmpDirGB) {
|
||||||
|
tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pPObj, pSql,
|
||||||
|
tsAvailTmpDirGB, tsMinimalTmpDirGB);
|
||||||
|
tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_CLI_NO_DISKSPACE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// each result for a vnode is ordered as an independant list,
|
||||||
|
// then used as an input of loser tree for disk-based merge routine
|
||||||
|
int32_t ret = tscFlushTmpBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer,
|
||||||
|
pQueryInfo->groupbyExpr.orderType);
|
||||||
|
if (ret != 0) { // set no disk space error info, and abort retry
|
||||||
|
return tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_CLI_NO_DISKSPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep this value local variable, since the pState variable may be released by other threads, if atomic_add opertion
|
||||||
|
// increases the finished value up to pState->numOfTotal value, which means all subqueries are completed.
|
||||||
|
// In this case, the comparsion between finished value and released pState->numOfTotal is not safe.
|
||||||
|
int32_t numOfTotal = pState->numOfTotal;
|
||||||
|
|
||||||
|
int32_t finished = atomic_add_fetch_32(&pState->numOfCompleted, 1);
|
||||||
|
if (finished < numOfTotal) {
|
||||||
|
tscTrace("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pPObj, pSql, trsupport->subqueryIndex, finished);
|
||||||
|
return tscFreeSubSqlObj(trsupport, pSql);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all sub-queries are returned, start to local merge process
|
||||||
|
pDesc->pColumnModel->capacity = trsupport->pExtMemBuffer[idx]->numOfElemsPerPage;
|
||||||
|
|
||||||
|
tscTrace("%p retrieve from %d vnodes completed.final NumOfRows:%d,start to build loser tree", pPObj,
|
||||||
|
pState->numOfTotal, pState->numOfRetrievedRows);
|
||||||
|
|
||||||
|
SQueryInfo *pPQueryInfo = tscGetQueryInfoDetail(&pPObj->cmd, 0);
|
||||||
|
tscClearInterpInfo(pPQueryInfo);
|
||||||
|
|
||||||
|
tscCreateLocalReducer(trsupport->pExtMemBuffer, pState->numOfTotal, pDesc, trsupport->pFinalColModel,
|
||||||
|
&pPObj->cmd, &pPObj->res);
|
||||||
|
tscTrace("%p build loser tree completed", pPObj);
|
||||||
|
|
||||||
|
pPObj->res.precision = pSql->res.precision;
|
||||||
|
pPObj->res.numOfRows = 0;
|
||||||
|
pPObj->res.row = 0;
|
||||||
|
|
||||||
|
// only free once
|
||||||
|
tfree(trsupport->pState);
|
||||||
|
tscFreeSubSqlObj(trsupport, pSql);
|
||||||
|
|
||||||
|
// set the command flag must be after the semaphore been correctly set.
|
||||||
|
pPObj->cmd.command = TSDB_SQL_RETRIEVE_METRIC;
|
||||||
|
if (pPObj->res.code == TSDB_CODE_SUCCESS) {
|
||||||
|
(*pPObj->fp)(pPObj->param, pPObj, 0);
|
||||||
|
} else {
|
||||||
|
tscQueueAsyncRes(pPObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfRows) {
|
||||||
SRetrieveSupport *trsupport = (SRetrieveSupport *)param;
|
SRetrieveSupport *trsupport = (SRetrieveSupport *)param;
|
||||||
int32_t idx = trsupport->subqueryIndex;
|
int32_t idx = trsupport->subqueryIndex;
|
||||||
SSqlObj * pPObj = trsupport->pParentSqlObj;
|
SSqlObj * pPObj = trsupport->pParentSqlObj;
|
||||||
|
@ -1265,15 +1342,15 @@ static void tscRetrieveFromVnodeCallBack(void *param, TAOS_RES *tres, int numOfR
|
||||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||||
|
|
||||||
// SVnodeSidList *vnodeInfo = tscGetVnodeSidList(pTableMetaInfo->pMetricMeta, idx);
|
// SVnodeSidList *vnodeInfo = tscGetVnodeSidList(pTableMetaInfo->pMetricMeta, idx);
|
||||||
SVnodeSidList *vnodeInfo = 0;
|
// SVnodeSidList *vnodeInfo = 0;
|
||||||
SVnodeDesc * pSvd = &vnodeInfo->vpeerDesc[vnodeInfo->index];
|
// SVnodeDesc * pSvd = &vnodeInfo->vpeerDesc[vnodeInfo->index];
|
||||||
|
|
||||||
if (numOfRows > 0) {
|
if (numOfRows > 0) {
|
||||||
assert(pRes->numOfRows == numOfRows);
|
assert(pRes->numOfRows == numOfRows);
|
||||||
int64_t num = atomic_add_fetch_64(&pState->numOfRetrievedRows, numOfRows);
|
int64_t num = atomic_add_fetch_64(&pState->numOfRetrievedRows, numOfRows);
|
||||||
|
|
||||||
tscTrace("%p sub:%p retrieve numOfRows:%d totalNumOfRows:%d from ip:%u,vid:%d,orderOfSub:%d", pPObj, pSql,
|
// tscTrace("%p sub:%p retrieve numOfRows:%d totalNumOfRows:%d from ip:%u,vid:%d,orderOfSub:%d", pPObj, pSql,
|
||||||
pRes->numOfRows, pState->numOfRetrievedRows, pSvd->ip, pSvd->vnode, idx);
|
// pRes->numOfRows, pState->numOfRetrievedRows, pSvd->ip, pSvd->vnode, idx);
|
||||||
|
|
||||||
if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) {
|
if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||||
tscError("%p sub:%p num of OrderedRes is too many, max allowed:%" PRId64 " , current:%" PRId64,
|
tscError("%p sub:%p num of OrderedRes is too many, max allowed:%" PRId64 " , current:%" PRId64,
|
||||||
|
@ -1299,85 +1376,16 @@ static void tscRetrieveFromVnodeCallBack(void *param, TAOS_RES *tres, int numOfR
|
||||||
|
|
||||||
int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data,
|
int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data,
|
||||||
pRes->numOfRows, pQueryInfo->groupbyExpr.orderType);
|
pRes->numOfRows, pQueryInfo->groupbyExpr.orderType);
|
||||||
if (ret < 0) {
|
if (ret < 0) { // set no disk space error info, and abort retry
|
||||||
// set no disk space error info, and abort retry
|
|
||||||
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_CLI_NO_DISKSPACE);
|
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_CLI_NO_DISKSPACE);
|
||||||
} else {
|
} else if (pRes->completed) {
|
||||||
|
tscAllDataRetrievedFromDnode(trsupport, pSql);
|
||||||
|
} else { // continue fetch data from dnode
|
||||||
pthread_mutex_unlock(&trsupport->queryMutex);
|
pthread_mutex_unlock(&trsupport->queryMutex);
|
||||||
taos_fetch_rows_a(tres, tscRetrieveFromVnodeCallBack, param);
|
taos_fetch_rows_a(tres, tscRetrieveFromDnodeCallBack, param);
|
||||||
}
|
|
||||||
|
|
||||||
} else { // all data has been retrieved to client
|
|
||||||
/* data in from current vnode is stored in cache and disk */
|
|
||||||
uint32_t numOfRowsFromVnode = trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->numOfElems;
|
|
||||||
tscTrace("%p sub:%p all data retrieved from ip:%u,vid:%d, numOfRows:%d, orderOfSub:%d", pPObj, pSql, pSvd->ip,
|
|
||||||
pSvd->vnode, numOfRowsFromVnode, idx);
|
|
||||||
|
|
||||||
tColModelCompact(pDesc->pColumnModel, trsupport->localBuffer, pDesc->pColumnModel->capacity);
|
|
||||||
|
|
||||||
#ifdef _DEBUG_VIEW
|
|
||||||
printf("%" PRIu64 " rows data flushed to disk:\n", trsupport->localBuffer->numOfElems);
|
|
||||||
SSrcColumnInfo colInfo[256] = {0};
|
|
||||||
tscGetSrcColumnInfo(colInfo, pQueryInfo);
|
|
||||||
tColModelDisplayEx(pDesc->pColumnModel, trsupport->localBuffer->data, trsupport->localBuffer->numOfElems,
|
|
||||||
trsupport->localBuffer->numOfElems, colInfo);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tsTotalTmpDirGB != 0 && tsAvailTmpDirGB < tsMinimalTmpDirGB) {
|
|
||||||
tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pPObj, pSql,
|
|
||||||
tsAvailTmpDirGB, tsMinimalTmpDirGB);
|
|
||||||
tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_CLI_NO_DISKSPACE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// each result for a vnode is ordered as an independant list,
|
|
||||||
// then used as an input of loser tree for disk-based merge routine
|
|
||||||
int32_t ret = tscFlushTmpBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer,
|
|
||||||
pQueryInfo->groupbyExpr.orderType);
|
|
||||||
if (ret != 0) {
|
|
||||||
/* set no disk space error info, and abort retry */
|
|
||||||
return tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_CLI_NO_DISKSPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep this value local variable, since the pState variable may be released by other threads, if atomic_add opertion
|
|
||||||
// increases the finished value up to pState->numOfTotal value, which means all subqueries are completed.
|
|
||||||
// In this case, the comparsion between finished value and released pState->numOfTotal is not safe.
|
|
||||||
int32_t numOfTotal = pState->numOfTotal;
|
|
||||||
|
|
||||||
int32_t finished = atomic_add_fetch_32(&pState->numOfCompleted, 1);
|
|
||||||
if (finished < numOfTotal) {
|
|
||||||
tscTrace("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pPObj, pSql, trsupport->subqueryIndex, finished);
|
|
||||||
return tscFreeSubSqlObj(trsupport, pSql);
|
|
||||||
}
|
|
||||||
|
|
||||||
// all sub-queries are returned, start to local merge process
|
|
||||||
pDesc->pColumnModel->capacity = trsupport->pExtMemBuffer[idx]->numOfElemsPerPage;
|
|
||||||
|
|
||||||
tscTrace("%p retrieve from %d vnodes completed.final NumOfRows:%d,start to build loser tree", pPObj,
|
|
||||||
pState->numOfTotal, pState->numOfRetrievedRows);
|
|
||||||
|
|
||||||
SQueryInfo *pPQueryInfo = tscGetQueryInfoDetail(&pPObj->cmd, 0);
|
|
||||||
tscClearInterpInfo(pPQueryInfo);
|
|
||||||
|
|
||||||
tscCreateLocalReducer(trsupport->pExtMemBuffer, pState->numOfTotal, pDesc, trsupport->pFinalColModel,
|
|
||||||
&pPObj->cmd, &pPObj->res);
|
|
||||||
tscTrace("%p build loser tree completed", pPObj);
|
|
||||||
|
|
||||||
pPObj->res.precision = pSql->res.precision;
|
|
||||||
pPObj->res.numOfRows = 0;
|
|
||||||
pPObj->res.row = 0;
|
|
||||||
|
|
||||||
// only free once
|
|
||||||
tfree(trsupport->pState);
|
|
||||||
tscFreeSubSqlObj(trsupport, pSql);
|
|
||||||
|
|
||||||
// set the command flag must be after the semaphore been correctly set.
|
|
||||||
pPObj->cmd.command = TSDB_SQL_RETRIEVE_METRIC;
|
|
||||||
if (pPObj->res.code == TSDB_CODE_SUCCESS) {
|
|
||||||
(*pPObj->fp)(pPObj->param, pPObj, 0);
|
|
||||||
} else {
|
|
||||||
tscQueueAsyncRes(pPObj);
|
|
||||||
}
|
}
|
||||||
|
} else { // all data has been retrieved to client
|
||||||
|
tscAllDataRetrievedFromDnode(trsupport, pSql);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1437,7 +1445,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if a query on a vnode is failed, all retrieve operations from vnode that occurs later
|
* if a query on a vnode is failed, all retrieve operations from vnode that occurs later
|
||||||
* than this one are actually not necessary, we simply call the tscRetrieveFromVnodeCallBack
|
* than this one are actually not necessary, we simply call the tscRetrieveFromDnodeCallBack
|
||||||
* function to abort current and remain retrieve process.
|
* function to abort current and remain retrieve process.
|
||||||
*
|
*
|
||||||
* NOTE: threadsafe is required.
|
* NOTE: threadsafe is required.
|
||||||
|
@ -1475,7 +1483,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
||||||
trsupport->subqueryIndex, pState->code);
|
trsupport->subqueryIndex, pState->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
tscRetrieveFromVnodeCallBack(param, tres, pState->code);
|
tscRetrieveFromDnodeCallBack(param, tres, pState->code);
|
||||||
} else { // success, proceed to retrieve data from dnode
|
} else { // success, proceed to retrieve data from dnode
|
||||||
if (vnodeInfo != NULL) {
|
if (vnodeInfo != NULL) {
|
||||||
tscTrace("%p sub:%p query complete,ip:%u,vid:%d,orderOfSub:%d,retrieve data", trsupport->pParentSqlObj, pSql,
|
tscTrace("%p sub:%p query complete,ip:%u,vid:%d,orderOfSub:%d,retrieve data", trsupport->pParentSqlObj, pSql,
|
||||||
|
@ -1486,7 +1494,7 @@ void tscRetrieveDataRes(void *param, TAOS_RES *tres, int code) {
|
||||||
trsupport->subqueryIndex);
|
trsupport->subqueryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
taos_fetch_rows_a(tres, tscRetrieveFromVnodeCallBack, param);
|
taos_fetch_rows_a(tres, tscRetrieveFromDnodeCallBack, param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -608,7 +608,7 @@ int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) {
|
||||||
* the payloadLen should be actual message body size
|
* the payloadLen should be actual message body size
|
||||||
* the old value of payloadLen is the allocated payload size
|
* the old value of payloadLen is the allocated payload size
|
||||||
*/
|
*/
|
||||||
pCmd->payloadLen = pDataBlock->nAllocSize - tsRpcHeadSize - sizeof(SMsgDesc);
|
pCmd->payloadLen = pDataBlock->nAllocSize - tsRpcHeadSize;
|
||||||
|
|
||||||
assert(pCmd->allocSize >= pCmd->payloadLen + tsRpcHeadSize + 100 && pCmd->payloadLen > 0);
|
assert(pCmd->allocSize >= pCmd->payloadLen + tsRpcHeadSize + 100 && pCmd->payloadLen > 0);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
|
|
|
@ -2204,7 +2204,7 @@ static int32_t getInitialPageNum(SQInfo *pQInfo) {
|
||||||
size_t s = taosArrayGetSize(pQInfo->pTableIdList);
|
size_t s = taosArrayGetSize(pQInfo->pTableIdList);
|
||||||
num = MAX(s, INITIAL_RESULT_ROWS_VALUE);
|
num = MAX(s, INITIAL_RESULT_ROWS_VALUE);
|
||||||
} else { // for super table query, one page for each subset
|
} else { // for super table query, one page for each subset
|
||||||
// num = pQInfo->pSidSet->numOfSubSet;
|
num = 1;//pQInfo->pSidSet->numOfSubSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(num > 0);
|
assert(num > 0);
|
||||||
|
@ -3873,7 +3873,7 @@ static int32_t getNumOfSubset(SQInfo *pQInfo) {
|
||||||
if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (isIntervalQuery(pQuery))) {
|
if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (isIntervalQuery(pQuery))) {
|
||||||
totalSubset = numOfClosedTimeWindow(&pQInfo->runtimeEnv.windowResInfo);
|
totalSubset = numOfClosedTimeWindow(&pQInfo->runtimeEnv.windowResInfo);
|
||||||
} else {
|
} else {
|
||||||
// totalSubset = pQInfo->pSidSet->numOfSubSet;
|
totalSubset = 1;//pQInfo->pSidSet->numOfSubSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalSubset;
|
return totalSubset;
|
||||||
|
@ -3909,19 +3909,18 @@ static int32_t doCopyToSData(SQInfo *pQInfo, SWindowResult *result, int32_t orde
|
||||||
|
|
||||||
int32_t numOfRowsToCopy = result[i].numOfRows - pQInfo->offset;
|
int32_t numOfRowsToCopy = result[i].numOfRows - pQInfo->offset;
|
||||||
int32_t oldOffset = pQInfo->offset;
|
int32_t oldOffset = pQInfo->offset;
|
||||||
assert(0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* current output space is not enough to keep all the result data of this group, only copy partial results
|
* current output space is not enough to keep all the result data of this group, only copy partial results
|
||||||
* to SQuery object's result buffer
|
* to SQuery object's result buffer
|
||||||
*/
|
*/
|
||||||
// if (numOfRowsToCopy > pQuery->pointsToRead - numOfResult) {
|
if (numOfRowsToCopy > pQuery->rec.capacity - numOfResult) {
|
||||||
// numOfRowsToCopy = pQuery->pointsToRead - numOfResult;
|
numOfRowsToCopy = pQuery->rec.capacity - numOfResult;
|
||||||
// pQInfo->offset += numOfRowsToCopy;
|
pQInfo->offset += numOfRowsToCopy;
|
||||||
// } else {
|
} else {
|
||||||
// pQInfo->offset = 0;
|
pQInfo->offset = 0;
|
||||||
// pQInfo->subgroupIdx += 1;
|
pQInfo->subgroupIdx += 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
|
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
|
||||||
int32_t size = pRuntimeEnv->pCtx[j].outputBytes;
|
int32_t size = pRuntimeEnv->pCtx[j].outputBytes;
|
||||||
|
@ -3932,13 +3931,12 @@ static int32_t doCopyToSData(SQInfo *pQInfo, SWindowResult *result, int32_t orde
|
||||||
}
|
}
|
||||||
|
|
||||||
numOfResult += numOfRowsToCopy;
|
numOfResult += numOfRowsToCopy;
|
||||||
assert(0);
|
if (numOfResult == pQuery->rec.capacity) {
|
||||||
// if (numOfResult == pQuery->rec.pointsToRead) {
|
break;
|
||||||
// break;
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dTrace("QInfo:%p copy data to SQuery buf completed", GET_QINFO_ADDR(pQuery));
|
dTrace("QInfo:%p copy data to SQuery buf completed", pQInfo);
|
||||||
|
|
||||||
#ifdef _DEBUG_VIEW
|
#ifdef _DEBUG_VIEW
|
||||||
displayInterResult(pQuery->sdata, pQuery, numOfResult);
|
displayInterResult(pQuery->sdata, pQuery, numOfResult);
|
||||||
|
@ -4135,10 +4133,11 @@ int32_t vnodeQueryResultInterpolate(SQInfo *pQInfo, tFilePage **pDst, tFilePage
|
||||||
}
|
}
|
||||||
|
|
||||||
void vnodePrintQueryStatistics(SQInfo *pQInfo) {
|
void vnodePrintQueryStatistics(SQInfo *pQInfo) {
|
||||||
|
#if 0
|
||||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||||
|
|
||||||
SQuery *pQuery = pRuntimeEnv->pQuery;
|
SQuery *pQuery = pRuntimeEnv->pQuery;
|
||||||
#if 0
|
|
||||||
SQueryCostSummary *pSummary = &pRuntimeEnv->summary;
|
SQueryCostSummary *pSummary = &pRuntimeEnv->summary;
|
||||||
if (pRuntimeEnv->pResultBuf == NULL) {
|
if (pRuntimeEnv->pResultBuf == NULL) {
|
||||||
pSummary->tmpBufferInDisk = 0;
|
pSummary->tmpBufferInDisk = 0;
|
||||||
|
@ -4179,41 +4178,30 @@ void vnodePrintQueryStatistics(SQInfo *pQInfo) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t initQInfo(SQInfo *pQInfo, void *param, void* tsdb) {
|
int32_t doInitializeQInfo(SQInfo *pQInfo, void *param, void* tsdb, bool isSTableQuery) {
|
||||||
|
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||||
|
|
||||||
SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
|
SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
// only the successful complete requries the sem_post/over = 1 operations.
|
|
||||||
if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
|
|
||||||
(!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
|
|
||||||
dTrace("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey,
|
|
||||||
pQuery->window.ekey, pQuery->order.order);
|
|
||||||
|
|
||||||
sem_post(&pQInfo->dataReady);
|
|
||||||
setQueryStatus(pQuery, QUERY_COMPLETED);
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
setScanLimitationByResultBuffer(pQuery);
|
setScanLimitationByResultBuffer(pQuery);
|
||||||
changeExecuteScanOrder(pQuery, false);
|
changeExecuteScanOrder(pQuery, false);
|
||||||
|
|
||||||
// dataInCache requires lastKey value
|
// dataInCache requires lastKey value
|
||||||
pQuery->lastKey = pQuery->window.skey;
|
pQuery->lastKey = pQuery->window.skey;
|
||||||
|
|
||||||
STsdbQueryCond cond = {0};
|
STsdbQueryCond cond = {
|
||||||
|
.twindow = pQuery->window,
|
||||||
cond.twindow = (STimeWindow){.skey = pQuery->window.skey, .ekey = pQuery->window.ekey};
|
.order = pQuery->order.order,
|
||||||
cond.order = pQuery->order.order;
|
.colList = *pQuery->colList,
|
||||||
cond.colList = *pQuery->colList;
|
};
|
||||||
|
|
||||||
SArray *cols = taosArrayInit(pQuery->numOfCols, sizeof(pQuery->colList[0]));
|
SArray *cols = taosArrayInit(pQuery->numOfCols, sizeof(pQuery->colList[0]));
|
||||||
for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
|
for (int32_t i = 0; i < pQuery->numOfCols; ++i) {
|
||||||
taosArrayPush(cols, &pQuery->colList[i]);
|
taosArrayPush(cols, &pQuery->colList[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pQInfo->runtimeEnv.pQueryHandle = tsdbQueryByTableId(tsdb, &cond, pQInfo->pTableIdList, cols);
|
pRuntimeEnv->pQueryHandle = tsdbQueryByTableId(tsdb, &cond, pQInfo->pTableIdList, cols);
|
||||||
|
|
||||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
|
||||||
pRuntimeEnv->pQuery = pQuery;
|
pRuntimeEnv->pQuery = pQuery;
|
||||||
|
|
||||||
pRuntimeEnv->pTSBuf = param;
|
pRuntimeEnv->pTSBuf = param;
|
||||||
|
@ -4224,15 +4212,34 @@ int32_t initQInfo(SQInfo *pQInfo, void *param, void* tsdb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create runtime environment
|
// create runtime environment
|
||||||
code = setupQueryRuntimeEnv(&pQInfo->runtimeEnv, NULL, pQuery->order.order, false);
|
code = setupQueryRuntimeEnv(pRuntimeEnv, NULL, pQuery->order.order, isSTableQuery);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
pRuntimeEnv->numOfRowsPerPage = getNumOfRowsInResultPage(pQuery, false);
|
pRuntimeEnv->numOfRowsPerPage = getNumOfRowsInResultPage(pQuery, isSTableQuery);
|
||||||
if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
|
|
||||||
|
if (isSTableQuery) {
|
||||||
|
int32_t rows = getInitialPageNum(pQInfo);
|
||||||
|
code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rows, pQuery->rowSize);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pQuery->intervalTime == 0) {
|
||||||
|
int16_t type = TSDB_DATA_TYPE_NULL;
|
||||||
|
|
||||||
|
if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // group by columns not tags;
|
||||||
|
type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr);
|
||||||
|
} else {
|
||||||
|
type = TSDB_DATA_TYPE_INT; // group id
|
||||||
|
}
|
||||||
|
|
||||||
|
initWindowResInfo(&pRuntimeEnv->windowResInfo, pRuntimeEnv, 512, 4096, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
|
||||||
int32_t rows = getInitialPageNum(pQInfo);
|
int32_t rows = getInitialPageNum(pQInfo);
|
||||||
|
|
||||||
code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rows, pQuery->rowSize);
|
code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rows, pQuery->rowSize);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
|
@ -4349,6 +4356,7 @@ static int64_t queryOnDataBlocks(SQInfo *pQInfo) {
|
||||||
for(int32_t i = 0; i < numOfTables; ++i) {
|
for(int32_t i = 0; i < numOfTables; ++i) {
|
||||||
if (pQInfo->pTableDataInfo[i].pTableQInfo->tid == blockInfo.sid) {
|
if (pQInfo->pTableDataInfo[i].pTableQInfo->tid == blockInfo.sid) {
|
||||||
pTableDataInfo = &pQInfo->pTableDataInfo[i];
|
pTableDataInfo = &pQInfo->pTableDataInfo[i];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4361,7 +4369,7 @@ static int64_t queryOnDataBlocks(SQInfo *pQInfo) {
|
||||||
SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, &blockInfo, &pStatis);
|
SArray * pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, &blockInfo, &pStatis);
|
||||||
|
|
||||||
TSKEY nextKey = blockInfo.window.ekey;
|
TSKEY nextKey = blockInfo.window.ekey;
|
||||||
if (pQuery->intervalTime == 0) {
|
if (!isIntervalQuery(pQuery)) {
|
||||||
setExecutionContext(pQInfo, pTableQueryInfo, pTableDataInfo->tableIndex, pTableDataInfo->groupIdx, nextKey);
|
setExecutionContext(pQInfo, pTableQueryInfo, pTableDataInfo->tableIndex, pTableDataInfo->groupIdx, nextKey);
|
||||||
} else { // interval query
|
} else { // interval query
|
||||||
setIntervalQueryRange(pTableQueryInfo, pQInfo, nextKey);
|
setIntervalQueryRange(pTableQueryInfo, pQInfo, nextKey);
|
||||||
|
@ -4487,9 +4495,10 @@ static int64_t doCheckMetersInGroup(SQInfo *pQInfo, int32_t index, int32_t start
|
||||||
*/
|
*/
|
||||||
static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
|
static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
|
||||||
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->runtimeEnv;
|
||||||
|
|
||||||
#if 0
|
|
||||||
SQuery* pQuery = pRuntimeEnv->pQuery;
|
SQuery* pQuery = pRuntimeEnv->pQuery;
|
||||||
|
setQueryStatus(pQuery, QUERY_COMPLETED);
|
||||||
|
|
||||||
|
#if 0
|
||||||
// tSidSet *pTableIdList = pSupporter->pSidSet;
|
// tSidSet *pTableIdList = pSupporter->pSidSet;
|
||||||
|
|
||||||
int32_t vid = getMeterObj(pSupporter->pMetersHashTable, pMeterSidExtInfo[0]->sid)->vnode;
|
int32_t vid = getMeterObj(pSupporter->pMetersHashTable, pMeterSidExtInfo[0]->sid)->vnode;
|
||||||
|
@ -4876,9 +4885,10 @@ static void multiTableQueryProcess(SQInfo *pQInfo) {
|
||||||
doRestoreContext(pQInfo);
|
doRestoreContext(pQInfo);
|
||||||
} else {
|
} else {
|
||||||
dTrace("QInfo:%p no need to do reversed scan, query completed", pQInfo);
|
dTrace("QInfo:%p no need to do reversed scan, query completed", pQInfo);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setQueryStatus(pQuery, QUERY_COMPLETED);
|
||||||
|
|
||||||
if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) {
|
if (pQInfo->code != TSDB_CODE_SUCCESS || isQueryKilled(pQInfo)) {
|
||||||
dTrace("QInfo:%p query killed or error occurred, code:%d, abort", pQInfo, pQInfo->code);
|
dTrace("QInfo:%p query killed or error occurred, code:%d, abort", pQInfo, pQInfo->code);
|
||||||
return;
|
return;
|
||||||
|
@ -5245,14 +5255,16 @@ static int32_t validateQueryMsg(SQueryTableMsg *pQueryMsg) {
|
||||||
static char* createTableIdList(SQueryTableMsg* pQueryMsg, char* pMsg, SArray** pTableIdList) {
|
static char* createTableIdList(SQueryTableMsg* pQueryMsg, char* pMsg, SArray** pTableIdList) {
|
||||||
assert(pQueryMsg->numOfTables > 0);
|
assert(pQueryMsg->numOfTables > 0);
|
||||||
|
|
||||||
*pTableIdList = taosArrayInit(pQueryMsg->numOfTables, sizeof(STableIdInfo));
|
*pTableIdList = taosArrayInit(pQueryMsg->numOfTables, sizeof(STableId));
|
||||||
|
|
||||||
STableIdInfo *pTableIdInfo = (STableIdInfo *)pMsg;
|
STableIdInfo *pTableIdInfo = (STableIdInfo *)pMsg;
|
||||||
pTableIdInfo->sid = htonl(pTableIdInfo->sid);
|
pTableIdInfo->sid = htonl(pTableIdInfo->sid);
|
||||||
pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
|
pTableIdInfo->uid = htobe64(pTableIdInfo->uid);
|
||||||
pTableIdInfo->key = htobe64(pTableIdInfo->key);
|
pTableIdInfo->key = htobe64(pTableIdInfo->key);
|
||||||
|
|
||||||
taosArrayPush(*pTableIdList, pTableIdInfo);
|
STableId id = {.uid = pTableIdInfo->uid, .tid = pTableIdInfo->sid};
|
||||||
|
taosArrayPush(*pTableIdList, &id);
|
||||||
|
|
||||||
pMsg += sizeof(STableIdInfo);
|
pMsg += sizeof(STableIdInfo);
|
||||||
|
|
||||||
for (int32_t j = 1; j < pQueryMsg->numOfTables; ++j) {
|
for (int32_t j = 1; j < pQueryMsg->numOfTables; ++j) {
|
||||||
|
@ -5820,7 +5832,18 @@ static SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGrou
|
||||||
|
|
||||||
pQuery->pos = -1;
|
pQuery->pos = -1;
|
||||||
|
|
||||||
dTrace("QInfo %p is allocated", pQInfo);
|
pQuery->window.skey = pQueryMsg->window.skey;
|
||||||
|
pQuery->window.ekey = pQueryMsg->window.ekey;
|
||||||
|
pQuery->lastKey = pQuery->window.skey;
|
||||||
|
|
||||||
|
if (sem_init(&pQInfo->dataReady, 0, 0) != 0) {
|
||||||
|
dError("QInfo:%p init dataReady sem failed, reason:%s", pQInfo, strerror(errno));
|
||||||
|
goto _clean_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
vnodeParametersSafetyCheck(pQuery);
|
||||||
|
|
||||||
|
dTrace("qmsg:%p create QInfo:%p, QInfo created", pQueryMsg, pQInfo);
|
||||||
return pQInfo;
|
return pQInfo;
|
||||||
|
|
||||||
_clean_memory:
|
_clean_memory:
|
||||||
|
@ -5859,49 +5882,34 @@ static bool isValidQInfo(void *param) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeQInfo(SQInfo *pQInfo);
|
static void freeQInfo(SQInfo *pQInfo);
|
||||||
static int32_t createQInfo(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyExpr, SSqlFunctionExpr *pSqlExprs,
|
static int32_t initializeQInfo(SQueryTableMsg *pQueryMsg, void* tsdb, SQInfo *pQInfo, bool isSTable) {
|
||||||
SArray *pTableIdList, void* tsdb, SQInfo **pQInfo) {
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
SQuery *pQuery = pQInfo->runtimeEnv.pQuery;
|
||||||
|
|
||||||
(*pQInfo) = createQInfoImpl(pQueryMsg, pGroupbyExpr, pSqlExprs, pTableIdList);
|
|
||||||
if ((*pQInfo) == NULL) {
|
|
||||||
code = TSDB_CODE_SERV_OUT_OF_MEMORY;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
SQuery *pQuery = (*pQInfo)->runtimeEnv.pQuery;
|
|
||||||
dTrace("qmsg:%p create QInfo:%p, QInfo created", pQueryMsg, pQInfo);
|
|
||||||
|
|
||||||
pQuery->window.skey = pQueryMsg->window.skey;
|
|
||||||
pQuery->window.ekey = pQueryMsg->window.ekey;
|
|
||||||
pQuery->lastKey = pQuery->window.skey;
|
|
||||||
|
|
||||||
if (sem_init(&(*pQInfo)->dataReady, 0, 0) != 0) {
|
|
||||||
dError("QInfo:%p init dataReady sem failed, reason:%s", pQInfo, strerror(errno));
|
|
||||||
code = TSDB_CODE_APP_ERROR;
|
|
||||||
goto _error;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnodeParametersSafetyCheck(pQuery);
|
|
||||||
|
|
||||||
STSBuf *pTSBuf = NULL;
|
STSBuf *pTSBuf = NULL;
|
||||||
if (pQueryMsg->tsLen > 0) { // open new file to save the result
|
if (pQueryMsg->tsLen > 0) { // open new file to save the result
|
||||||
char *tsBlock = (char *)pQueryMsg + pQueryMsg->tsOffset;
|
char *tsBlock = (char *)pQueryMsg + pQueryMsg->tsOffset;
|
||||||
pTSBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder);
|
pTSBuf = tsBufCreateFromCompBlocks(tsBlock, pQueryMsg->tsNumOfBlocks, pQueryMsg->tsLen, pQueryMsg->tsOrder);
|
||||||
|
|
||||||
tsBufResetPos(pTSBuf);
|
tsBufResetPos(pTSBuf);
|
||||||
tsBufNextPos(pTSBuf);
|
tsBufNextPos(pTSBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter the qualified
|
// only the successful complete requries the sem_post/over = 1 operations.
|
||||||
if ((code = initQInfo(*pQInfo, pTSBuf, tsdb)) != TSDB_CODE_SUCCESS) {
|
if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.skey > pQuery->window.ekey)) ||
|
||||||
goto _error;
|
(!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->window.ekey > pQuery->window.skey))) {
|
||||||
|
dTrace("QInfo:%p no result in time range %" PRId64 "-%" PRId64 ", order %d", pQInfo, pQuery->window.skey,
|
||||||
|
pQuery->window.ekey, pQuery->order.order);
|
||||||
|
|
||||||
|
sem_post(&pQInfo->dataReady);
|
||||||
|
setQueryStatus(pQuery, QUERY_COMPLETED);
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (pQInfo->over == 1) {
|
// filter the qualified
|
||||||
// vnodeAddRefCount(pQInfo); // for retrieve procedure
|
if ((code = doInitializeQInfo(pQInfo, pTSBuf, tsdb, isSTable)) != TSDB_CODE_SUCCESS) {
|
||||||
// return pQInfo;
|
goto _error;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// dTrace("QInfo:%p set query flag and prepare runtime environment completed, ref:%d, wait for schedule", pQInfo,
|
// dTrace("QInfo:%p set query flag and prepare runtime environment completed, ref:%d, wait for schedule", pQInfo,
|
||||||
// pQInfo->refCount);
|
// pQInfo->refCount);
|
||||||
|
@ -5909,7 +5917,7 @@ static int32_t createQInfo(SQueryTableMsg *pQueryMsg, SSqlGroupbyExpr *pGroupbyE
|
||||||
|
|
||||||
_error:
|
_error:
|
||||||
// table query ref will be decrease during error handling
|
// table query ref will be decrease during error handling
|
||||||
freeQInfo(*pQInfo);
|
freeQInfo(pQInfo);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6068,7 +6076,10 @@ int32_t qCreateQueryInfo(void* tsdb, SQueryTableMsg *pQueryMsg, SQInfo **pQInfo)
|
||||||
|
|
||||||
// super table query
|
// super table query
|
||||||
SArray* res = NULL;
|
SArray* res = NULL;
|
||||||
|
bool isSTableQuery = false;
|
||||||
if ((pQueryMsg->queryType & TSDB_QUERY_TYPE_STABLE_QUERY) != 0) {
|
if ((pQueryMsg->queryType & TSDB_QUERY_TYPE_STABLE_QUERY) != 0) {
|
||||||
|
isSTableQuery = true;
|
||||||
|
|
||||||
STableId* id = taosArrayGet(pTableIdList, 0);
|
STableId* id = taosArrayGet(pTableIdList, 0);
|
||||||
id->uid = -1;
|
id->uid = -1;
|
||||||
|
|
||||||
|
@ -6081,8 +6092,13 @@ int32_t qCreateQueryInfo(void* tsdb, SQueryTableMsg *pQueryMsg, SQInfo **pQInfo)
|
||||||
res = pTableIdList;
|
res = pTableIdList;
|
||||||
}
|
}
|
||||||
|
|
||||||
code = createQInfo(pQueryMsg, pGroupbyExpr, pExprs, res, tsdb, pQInfo);
|
(*pQInfo) = createQInfoImpl(pQueryMsg, pGroupbyExpr, pExprs, res);
|
||||||
|
if ((*pQInfo) == NULL) {
|
||||||
|
code = TSDB_CODE_SERV_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = initializeQInfo(pQueryMsg, tsdb, *pQInfo, isSTableQuery);
|
||||||
|
|
||||||
_query_over:
|
_query_over:
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
taosArrayDestroy(pTableIdList);
|
taosArrayDestroy(pTableIdList);
|
||||||
|
|
|
@ -73,7 +73,7 @@ typedef struct SQueryFilesInfo {
|
||||||
char dbFilePathPrefix[PATH_MAX];
|
char dbFilePathPrefix[PATH_MAX];
|
||||||
} SQueryFilesInfo;
|
} SQueryFilesInfo;
|
||||||
|
|
||||||
typedef struct STableQueryInfo {
|
typedef struct STableCheckInfo {
|
||||||
STableId tableId;
|
STableId tableId;
|
||||||
TSKEY lastKey;
|
TSKEY lastKey;
|
||||||
STable * pTableObj;
|
STable * pTableObj;
|
||||||
|
@ -81,7 +81,8 @@ typedef struct STableQueryInfo {
|
||||||
int32_t numOfBlocks;
|
int32_t numOfBlocks;
|
||||||
int32_t start;
|
int32_t start;
|
||||||
SCompBlock *pBlock;
|
SCompBlock *pBlock;
|
||||||
} STableQueryInfo;
|
SSkipListIterator* iter;
|
||||||
|
} STableCheckInfo;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SCompBlock *compBlock;
|
SCompBlock *compBlock;
|
||||||
|
@ -90,14 +91,19 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct STableDataBlockInfoEx {
|
typedef struct STableDataBlockInfoEx {
|
||||||
SCompBlockFields pBlock;
|
SCompBlockFields pBlock;
|
||||||
STableQueryInfo* pMeterDataInfo;
|
STableCheckInfo* pMeterDataInfo;
|
||||||
int32_t blockIndex;
|
int32_t blockIndex;
|
||||||
int32_t groupIdx; /* number of group is less than the total number of meters */
|
int32_t groupIdx; /* number of group is less than the total number of meters */
|
||||||
} STableDataBlockInfoEx;
|
} STableDataBlockInfoEx;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SINGLE_TABLE_MODEL = 1,
|
||||||
|
MULTI_TABLE_MODEL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct STsdbQueryHandle {
|
typedef struct STsdbQueryHandle {
|
||||||
struct STsdbRepo* pTsdb;
|
struct STsdbRepo* pTsdb;
|
||||||
|
int8_t model; // access model, single table model or multi-table model
|
||||||
SQueryHandlePos cur; // current position
|
SQueryHandlePos cur; // current position
|
||||||
SQueryHandlePos start; // the start position, used for secondary/third iteration
|
SQueryHandlePos start; // the start position, used for secondary/third iteration
|
||||||
int32_t unzipBufSize;
|
int32_t unzipBufSize;
|
||||||
|
@ -120,14 +126,13 @@ typedef struct STsdbQueryHandle {
|
||||||
bool locateStart;
|
bool locateStart;
|
||||||
int32_t realNumOfRows;
|
int32_t realNumOfRows;
|
||||||
bool loadDataAfterSeek; // load data after seek.
|
bool loadDataAfterSeek; // load data after seek.
|
||||||
SArray* pTableQueryInfo;
|
SArray* pTableCheckInfo;
|
||||||
int32_t activeIndex;
|
int32_t activeIndex;
|
||||||
|
|
||||||
int32_t tableIndex;
|
int32_t tableIndex;
|
||||||
bool isFirstSlot;
|
bool isFirstSlot;
|
||||||
void * qinfo; // query info handle, for debug purpose
|
void * qinfo; // query info handle, for debug purpose
|
||||||
|
|
||||||
SSkipListIterator* memIter;
|
|
||||||
STableDataBlockInfoEx *pDataBlockInfoEx;
|
STableDataBlockInfoEx *pDataBlockInfoEx;
|
||||||
} STsdbQueryHandle;
|
} STsdbQueryHandle;
|
||||||
|
|
||||||
|
@ -271,19 +276,21 @@ tsdb_query_handle_t *tsdbQueryByTableId(tsdb_repo_t* tsdb, STsdbQueryCond *pCond
|
||||||
size_t size = taosArrayGetSize(idList);
|
size_t size = taosArrayGetSize(idList);
|
||||||
assert(size >= 1);
|
assert(size >= 1);
|
||||||
|
|
||||||
pQueryHandle->pTableQueryInfo = taosArrayInit(size, sizeof(STableQueryInfo));
|
pQueryHandle->pTableCheckInfo = taosArrayInit(size, sizeof(STableCheckInfo));
|
||||||
for(int32_t i = 0; i < size; ++i) {
|
for(int32_t i = 0; i < size; ++i) {
|
||||||
STableId id = *(STableId*) taosArrayGet(idList, i);
|
STableId id = *(STableId*) taosArrayGet(idList, i);
|
||||||
|
|
||||||
STableQueryInfo info = {
|
STableCheckInfo info = {
|
||||||
.lastKey = pQueryHandle->window.skey,
|
.lastKey = pQueryHandle->window.skey,
|
||||||
.tableId = id,
|
.tableId = id,
|
||||||
.pTableObj = tsdbGetTableByUid(tsdbGetMeta(tsdb), id.uid), //todo this may be failed
|
.pTableObj = tsdbGetTableByUid(tsdbGetMeta(tsdb), id.uid), //todo this may be failed
|
||||||
};
|
};
|
||||||
|
|
||||||
taosArrayPush(pQueryHandle->pTableQueryInfo, &info);
|
taosArrayPush(pQueryHandle->pTableCheckInfo, &info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pQueryHandle->model = (size > 1)? MULTI_TABLE_MODEL:SINGLE_TABLE_MODEL;
|
||||||
|
|
||||||
pQueryHandle->activeIndex = 0;
|
pQueryHandle->activeIndex = 0;
|
||||||
|
|
||||||
// malloc buffer in order to load data from file
|
// malloc buffer in order to load data from file
|
||||||
|
@ -314,11 +321,13 @@ tsdb_query_handle_t *tsdbQueryByTableId(tsdb_repo_t* tsdb, STsdbQueryCond *pCond
|
||||||
return (tsdb_query_handle_t)pQueryHandle;
|
return (tsdb_query_handle_t)pQueryHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tsdbNextDataBlock(tsdb_query_handle_t *pQueryHandle) {
|
static bool hasMoreDataInCacheForSingleModel(STsdbQueryHandle* pHandle) {
|
||||||
STsdbQueryHandle* pHandle = (STsdbQueryHandle*) pQueryHandle;
|
assert(pHandle->activeIndex == 0 && taosArrayGetSize(pHandle->pTableCheckInfo) == 1);
|
||||||
STableQueryInfo* pTableQInfo = taosArrayGet(pHandle->pTableQueryInfo, pHandle->activeIndex);
|
|
||||||
|
|
||||||
STable *pTable = pTableQInfo->pTableObj;
|
STableCheckInfo* pTableCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
|
||||||
|
|
||||||
|
STable *pTable = pTableCheckInfo->pTableObj;
|
||||||
|
assert(pTable != NULL);
|
||||||
|
|
||||||
// no data in cache, abort
|
// no data in cache, abort
|
||||||
if (pTable->mem == NULL && pTable->imem == NULL) {
|
if (pTable->mem == NULL && pTable->imem == NULL) {
|
||||||
|
@ -326,13 +335,49 @@ bool tsdbNextDataBlock(tsdb_query_handle_t *pQueryHandle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// all data in mem are checked already.
|
// all data in mem are checked already.
|
||||||
if (pTableQInfo->lastKey > pTable->mem->keyLast) {
|
if (pTableCheckInfo->lastKey > pTable->mem->keyLast) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasMoreDataInCacheForMultiModel(STsdbQueryHandle* pHandle) {
|
||||||
|
size_t numOfTables = taosArrayGetSize(pHandle->pTableCheckInfo);
|
||||||
|
assert(numOfTables > 0);
|
||||||
|
|
||||||
|
while(pHandle->activeIndex < numOfTables) {
|
||||||
|
STableCheckInfo* pTableCheckInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
|
||||||
|
|
||||||
|
STable *pTable = pTableCheckInfo->pTableObj;
|
||||||
|
if (pTable->mem == NULL && pTable->imem == NULL) {
|
||||||
|
pHandle->activeIndex += 1; // try next table if exits
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all data in mem are checked already.
|
||||||
|
if (pTableCheckInfo->lastKey > pTable->mem->keyLast) {
|
||||||
|
pHandle->activeIndex += 1; // try next table if exits
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all tables has checked already
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle data in cache situation
|
||||||
|
bool tsdbNextDataBlock(tsdb_query_handle_t *pQueryHandle) {
|
||||||
|
STsdbQueryHandle* pHandle = (STsdbQueryHandle*) pQueryHandle;
|
||||||
|
if (pHandle->model == SINGLE_TABLE_MODEL) {
|
||||||
|
return hasMoreDataInCacheForSingleModel(pHandle);
|
||||||
|
} else {
|
||||||
|
return hasMoreDataInCacheForMultiModel(pHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int tsdbReadRowsFromCache(SSkipListIterator *pIter, TSKEY maxKey, int maxRowsToRead,
|
static int tsdbReadRowsFromCache(SSkipListIterator *pIter, TSKEY maxKey, int maxRowsToRead,
|
||||||
TSKEY* skey, TSKEY* ekey, STsdbQueryHandle* pHandle) {
|
TSKEY* skey, TSKEY* ekey, STsdbQueryHandle* pHandle) {
|
||||||
int numOfRows = 0;
|
int numOfRows = 0;
|
||||||
|
@ -370,7 +415,7 @@ static int tsdbReadRowsFromCache(SSkipListIterator *pIter, TSKEY maxKey, int max
|
||||||
SDataBlockInfo tsdbRetrieveDataBlockInfo(tsdb_query_handle_t *pQueryHandle) {
|
SDataBlockInfo tsdbRetrieveDataBlockInfo(tsdb_query_handle_t *pQueryHandle) {
|
||||||
STsdbQueryHandle* pHandle = (STsdbQueryHandle*) pQueryHandle;
|
STsdbQueryHandle* pHandle = (STsdbQueryHandle*) pQueryHandle;
|
||||||
|
|
||||||
STableQueryInfo* pTableQInfo = taosArrayGet(pHandle->pTableQueryInfo, pHandle->activeIndex);
|
STableCheckInfo* pTableQInfo = taosArrayGet(pHandle->pTableCheckInfo, pHandle->activeIndex);
|
||||||
STable *pTable = pTableQInfo->pTableObj;
|
STable *pTable = pTableQInfo->pTableObj;
|
||||||
|
|
||||||
TSKEY skey = 0, ekey = 0;
|
TSKEY skey = 0, ekey = 0;
|
||||||
|
@ -379,11 +424,11 @@ SDataBlockInfo tsdbRetrieveDataBlockInfo(tsdb_query_handle_t *pQueryHandle) {
|
||||||
if (pTable->mem != NULL) {
|
if (pTable->mem != NULL) {
|
||||||
|
|
||||||
// create mem table iterator if it is not created yet
|
// create mem table iterator if it is not created yet
|
||||||
if (pHandle->memIter == NULL) {
|
if (pTableQInfo->iter == NULL) {
|
||||||
pHandle->memIter = tSkipListCreateIter(pTable->mem->pData);
|
pTableQInfo->iter = tSkipListCreateIter(pTable->mem->pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
rows = tsdbReadRowsFromCache(pHandle->memIter, INT64_MAX, 2, &skey, &ekey, pHandle);
|
rows = tsdbReadRowsFromCache(pTableQInfo->iter, INT64_MAX, 2, &skey, &ekey, pHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDataBlockInfo blockInfo = {
|
SDataBlockInfo blockInfo = {
|
||||||
|
|
Loading…
Reference in New Issue