add the union support in sql parser: fix bugs and refactor some codes. #1032. [TBASE-1140]
This commit is contained in:
parent
d99b94a582
commit
82706e1b41
|
@ -238,6 +238,11 @@ void sortRemoveDuplicates(STableDataBlocks* dataBuf);
|
|||
|
||||
void tscPrintSelectClause(SSqlCmd* pCmd, int32_t subClauseIndex);
|
||||
|
||||
bool hasMoreVnodesToTry(SSqlObj *pSql);
|
||||
void tscTryQueryNextVnode(SSqlObj *pSql, __async_cb_func_t fp);
|
||||
void tscAsyncQuerySingleRowForNextVnode(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -457,6 +457,8 @@ extern int tsInsertHeadSize;
|
|||
extern int tscNumOfThreads;
|
||||
extern SIpStrList tscMgmtIpList;
|
||||
|
||||
typedef void (*__async_cb_func_t)(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "taosmsg.h"
|
||||
#include "tast.h"
|
||||
#include "tlog.h"
|
||||
#include "tscSQLParser.h"
|
||||
#include "tscSyntaxtreefunction.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsdb.h"
|
||||
|
@ -26,7 +27,6 @@
|
|||
#include "tstoken.h"
|
||||
#include "ttypes.h"
|
||||
#include "tutil.h"
|
||||
#include "tscSQLParser.h"
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
|
@ -26,19 +26,18 @@
|
|||
#include "tutil.h"
|
||||
#include "tnote.h"
|
||||
|
||||
void tscProcessFetchRow(SSchedMsg *pMsg);
|
||||
void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows);
|
||||
static void tscProcessAsyncRetrieveNextVnode(void *param, TAOS_RES *tres, int numOfRows);
|
||||
static void tscProcessAsyncContinueRetrieve(void *param, TAOS_RES *tres, int numOfRows);
|
||||
static void tscProcessFetchRow(SSchedMsg *pMsg);
|
||||
static void tscAsyncQueryRowsForNextVnode(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRows, void (*fp)());
|
||||
|
||||
/*
|
||||
* proxy function to perform sequentially query&retrieve operation.
|
||||
* If sql queries upon metric and two-stage merge procedure is not needed,
|
||||
* it will sequentially query&retrieve data for all vnodes in pCmd->pMetricMeta
|
||||
* Proxy function to perform sequentially query&retrieve operation.
|
||||
* If sql queries upon a super table and two-stage merge procedure is not involved (when employ the projection
|
||||
* query), it will sequentially query&retrieve data for all vnodes
|
||||
*/
|
||||
static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOfRows);
|
||||
static void tscProcessAsyncFetchSingleRowProxy(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
// TODO return the correct error code to client in tscQueueAsyncError
|
||||
void taos_query_a(TAOS *taos, const char *sqlstr, void (*fp)(void *, TAOS_RES *, int), void *param) {
|
||||
|
@ -118,39 +117,24 @@ static void tscProcessAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOf
|
|||
SSqlRes *pRes = &pSql->res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
if (numOfRows == 0) {
|
||||
if (hasMoreVnodesToTry(pSql)) { // sequentially retrieve data from remain vnodes.
|
||||
tscTryQueryNextVnode(pSql, tscAsyncQueryRowsForNextVnode);
|
||||
} else {
|
||||
/*
|
||||
* 1. has reach the limitation
|
||||
* 2. no remain virtual nodes to be retrieved anymore
|
||||
*/
|
||||
(*pSql->fetchFp)(param, pSql, 0);
|
||||
}
|
||||
|
||||
// sequentially retrieve data from remain vnodes first, query vnode specified by vnodeIdx
|
||||
if (numOfRows == 0 && tscProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||
// vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
assert(pMeterMetaInfo->vnodeIndex >= 0);
|
||||
|
||||
/* reach the maximum number of output rows, abort */
|
||||
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) {
|
||||
(*pSql->fetchFp)(param, tres, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the limit value according to current retrieval results */
|
||||
pQueryInfo->limit.limit = pCmd->globalLimit - pRes->numOfTotal;
|
||||
pQueryInfo->limit.offset = pRes->offset;
|
||||
|
||||
if ((++(pMeterMetaInfo->vnodeIndex)) < pMeterMetaInfo->pMetricMeta->numOfVnodes) {
|
||||
tscTrace("%p retrieve data from next vnode:%d", pSql, pMeterMetaInfo->vnodeIndex);
|
||||
|
||||
pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first.
|
||||
|
||||
tscResetForNextRetrieve(pRes);
|
||||
pSql->fp = tscProcessAsyncRetrieveNextVnode;
|
||||
tscProcessSql(pSql);
|
||||
return;
|
||||
}
|
||||
} else { // localreducer has handle this situation
|
||||
// local reducer has handle this situation during super table non-projection query.
|
||||
if (pCmd->command != TSDB_SQL_RETRIEVE_METRIC) {
|
||||
pRes->numOfTotal += pRes->numOfRows;
|
||||
}
|
||||
}
|
||||
|
||||
(*pSql->fetchFp)(param, tres, numOfRows);
|
||||
}
|
||||
|
@ -185,14 +169,18 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
|
|||
}
|
||||
|
||||
/*
|
||||
* retrieve callback for fetch rows proxy. It serves as the callback function of querying vnode
|
||||
* retrieve callback for fetch rows proxy.
|
||||
* The below two functions both serve as the callback function of query virtual node.
|
||||
* query callback first, and then followed by retrieve callback
|
||||
*/
|
||||
static void tscProcessAsyncRetrieveNextVnode(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
static void tscAsyncQueryRowsForNextVnode(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
// query completed, continue to retrieve
|
||||
tscProcessAsyncRetrieveImpl(param, tres, numOfRows, tscProcessAsyncFetchRowsProxy);
|
||||
}
|
||||
|
||||
static void tscProcessAsyncContinueRetrieve(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
tscProcessAsyncRetrieveImpl(param, tres, numOfRows, tscProcessAsyncRetrieve);
|
||||
void tscAsyncQuerySingleRowForNextVnode(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
// query completed, continue to retrieve
|
||||
tscProcessAsyncRetrieveImpl(param, tres, numOfRows, tscProcessAsyncFetchSingleRowProxy);
|
||||
}
|
||||
|
||||
void taos_fetch_rows_a(TAOS_RES *taosa, void (*fp)(void *, TAOS_RES *, int), void *param) {
|
||||
|
@ -250,8 +238,12 @@ void taos_fetch_row_a(TAOS_RES *taosa, void (*fp)(void *, TAOS_RES *, TAOS_ROW),
|
|||
|
||||
if (pRes->row >= pRes->numOfRows) {
|
||||
tscResetForNextRetrieve(pRes);
|
||||
pSql->fp = tscProcessAsyncRetrieve;
|
||||
pSql->fp = tscProcessAsyncFetchSingleRowProxy;
|
||||
|
||||
if (pCmd->command != TSDB_SQL_RETRIEVE_METRIC && pCmd->command < TSDB_SQL_LOCAL) {
|
||||
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
|
||||
}
|
||||
|
||||
tscProcessSql(pSql);
|
||||
} else {
|
||||
SSchedMsg schedMsg;
|
||||
|
@ -263,50 +255,32 @@ void taos_fetch_row_a(TAOS_RES *taosa, void (*fp)(void *, TAOS_RES *, TAOS_ROW),
|
|||
}
|
||||
}
|
||||
|
||||
void tscProcessAsyncRetrieve(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
void tscProcessAsyncFetchSingleRowProxy(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
SSqlObj *pSql = (SSqlObj *)tres;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
if (numOfRows == 0) {
|
||||
// sequentially retrieve data from remain vnodes.
|
||||
if (tscProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||
if (hasMoreVnodesToTry(pSql)) { // sequentially retrieve data from remain vnodes.
|
||||
tscTryQueryNextVnode(pSql, tscAsyncQuerySingleRowForNextVnode);
|
||||
} else {
|
||||
/*
|
||||
* vnode is denoted by vnodeIdx, continue to query vnode specified by vnodeIdx till all vnode have been retrieved
|
||||
* 1. has reach the limitation
|
||||
* 2. no remain virtual nodes to be retrieved anymore
|
||||
*/
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
assert(pMeterMetaInfo->vnodeIndex >= 0);
|
||||
|
||||
/* reach the maximum number of output rows, abort */
|
||||
if (pCmd->globalLimit > 0 && pRes->numOfTotal >= pCmd->globalLimit) {
|
||||
(*pSql->fetchFp)(pSql->param, pSql, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* update the limit value according to current retrieval results */
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
pQueryInfo->limit.limit = pCmd->globalLimit - pRes->numOfTotal;
|
||||
|
||||
if ((++pMeterMetaInfo->vnodeIndex) <= pMeterMetaInfo->pMetricMeta->numOfVnodes) {
|
||||
pSql->cmd.command = TSDB_SQL_SELECT; // reset flag to launch query first.
|
||||
|
||||
tscResetForNextRetrieve(pRes);
|
||||
pSql->fp = tscProcessAsyncContinueRetrieve;
|
||||
tscProcessSql(pSql);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
(*pSql->fetchFp)(pSql->param, pSql, NULL);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < pCmd->numOfCols; ++i)
|
||||
pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i, pQueryInfo->order) + pRes->bytes[i] * pRes->row;
|
||||
pRes->row++;
|
||||
|
||||
(*pSql->fetchFp)(pSql->param, pSql, pSql->res.tsrow);
|
||||
}
|
||||
}
|
||||
|
||||
void tscProcessFetchRow(SSchedMsg *pMsg) {
|
||||
SSqlObj *pSql = (SSqlObj *)pMsg->ahandle;
|
||||
|
@ -314,12 +288,12 @@ void tscProcessFetchRow(SSchedMsg *pMsg) {
|
|||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
assert(pCmd->numOfCols == pQueryInfo->fieldsInfo.numOfOutputCols);
|
||||
|
||||
for (int i = 0; i < pCmd->numOfCols; ++i)
|
||||
for (int i = 0; i < pCmd->numOfCols; ++i) {
|
||||
pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i, pQueryInfo->order) + pRes->bytes[i] * pRes->row;
|
||||
pRes->row++;
|
||||
}
|
||||
|
||||
pRes->row++;
|
||||
(*pSql->fetchFp)(pSql->param, pSql, pRes->tsrow);
|
||||
}
|
||||
|
||||
|
|
|
@ -164,8 +164,7 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSuppor
|
|||
}
|
||||
|
||||
// todo handle failed to create sub query
|
||||
SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState,
|
||||
/*int32_t* numOfComplete, int32_t* gc,*/ int32_t index) {
|
||||
SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState, int32_t index) {
|
||||
SJoinSubquerySupporter* pSupporter = calloc(1, sizeof(SJoinSubquerySupporter));
|
||||
if (pSupporter == NULL) {
|
||||
return NULL;
|
||||
|
@ -175,14 +174,16 @@ SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pS
|
|||
pSupporter->pState = pState;
|
||||
|
||||
pSupporter->subqueryIndex = index;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
|
||||
pSupporter->interval = pQueryInfo->nAggTimeInterval;
|
||||
pSupporter->limit = pQueryInfo->limit;
|
||||
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, 0, index);
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, pSql->cmd.clauseIndex, index);
|
||||
pSupporter->uid = pMeterMetaInfo->pMeterMeta->uid;
|
||||
|
||||
assert (pSupporter->uid != 0);
|
||||
|
||||
getTmpfilePath("join-", pSupporter->path);
|
||||
pSupporter->f = fopen(pSupporter->path, "w");
|
||||
|
||||
|
@ -236,37 +237,47 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
|
|||
int32_t numOfSub = 0;
|
||||
SJoinSubquerySupporter* pSupporter = NULL;
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
pSupporter = pSql->pSubs[i]->param;
|
||||
pSupporter->pState->numOfCompleted = 0;
|
||||
|
||||
/*
|
||||
* If the columns are not involved in the final select clause, the secondary query will not be launched
|
||||
* for the subquery.
|
||||
*/
|
||||
SSubqueryState* pState = NULL;
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
pSupporter = pSql->pSubs[i]->param;
|
||||
if (pSupporter->exprsInfo.numOfExprs > 0) {
|
||||
++numOfSub;
|
||||
}
|
||||
}
|
||||
|
||||
// scan all subquery, if one sub query has only ts, ignore it
|
||||
tscTrace(
|
||||
"%p start to launch secondary subqueries, total:%d, only:%d needs to query, others are not retrieve in "
|
||||
"select clause",
|
||||
pSql, pSql->numOfSubs, numOfSub);
|
||||
assert(numOfSub > 0);
|
||||
|
||||
// scan all subquery, if one sub query has only ts, ignore it
|
||||
tscTrace("%p start to launch secondary subqueries, total:%d, only:%d needs to query, others are not retrieve in "
|
||||
"select clause", pSql, pSql->numOfSubs, numOfSub);
|
||||
|
||||
/*
|
||||
* the subqueries that do not actually launch the secondary query to virtual node is set as completed.
|
||||
*/
|
||||
pState = pSupporter->pState;
|
||||
pState->numOfTotal = pSql->numOfSubs;
|
||||
pState->numOfCompleted = (pSql->numOfSubs - numOfSub);
|
||||
|
||||
int32_t j = 0;
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
SSqlObj* pSub = pSql->pSubs[i];
|
||||
pSupporter = pSub->param;
|
||||
pSupporter->pState->numOfTotal = numOfSub;
|
||||
|
||||
if (pSupporter->exprsInfo.numOfExprs == 0) {
|
||||
tscTrace("%p subquery %d, not need to launch query, ignore it", pSql, i);
|
||||
|
||||
tscDestroyJoinSupporter(pSupporter);
|
||||
taos_free_result(pSub);
|
||||
tscFreeSqlObj(pSub);
|
||||
|
||||
pSql->pSubs[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo refactor to avoid the memory problem handling
|
||||
SSqlObj* pNew = createSubqueryObj(pSql, (int16_t)i, tscJoinQueryCallback, pSupporter, NULL);
|
||||
if (pNew == NULL) {
|
||||
pSql->numOfSubs = i; // revise the number of subquery
|
||||
|
@ -279,7 +290,8 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
|
|||
|
||||
tscClearSubqueryInfo(&pNew->cmd);
|
||||
|
||||
pSql->pSubs[j++] = pNew;
|
||||
pSql->pSubs[i] = pNew;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
|
||||
SQueryInfo* pSubQueryInfo = tscGetQueryInfoDetail(&pSub->cmd, 0);
|
||||
|
||||
|
@ -307,6 +319,7 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
|
|||
|
||||
// todo refactor function name
|
||||
SQueryInfo* pNewQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
|
||||
assert(pNew->numOfSubs == 0 && pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1);
|
||||
|
||||
tscAddTimestampColumn(pQueryInfo, TSDB_FUNC_TS, 0);
|
||||
tscFieldInfoCalOffset(pNewQueryInfo);
|
||||
|
@ -334,12 +347,15 @@ int32_t tscLaunchSecondSubquery(SSqlObj* pSql) {
|
|||
tscPrintSelectClause(&pNew->cmd, 0);
|
||||
#endif
|
||||
|
||||
tscTrace("%p subquery:%p tableIndex:%d, vnodeIdx:%d, type:%d, transfer to ts_comp query to retrieve timestamps, "
|
||||
"exprInfo:%d, colList:%d, fieldsInfo:%d, name:%s",
|
||||
pSql, pNew, 0, pMeterMetaInfo->vnodeIndex, pNewQueryInfo->type,
|
||||
pNewQueryInfo->exprsInfo.numOfExprs, pNewQueryInfo->colList.numOfCols,
|
||||
pNewQueryInfo->fieldsInfo.numOfOutputCols, pNewQueryInfo->pMeterInfo[0]->name);
|
||||
|
||||
tscProcessSql(pNew);
|
||||
}
|
||||
|
||||
// revise the number of subs
|
||||
pSql->numOfSubs = j;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -537,13 +553,35 @@ static void joinRetrieveCallback(void* param, TAOS_RES* tres, int numOfRows) {
|
|||
}
|
||||
}
|
||||
|
||||
void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
||||
int32_t numOfFetch = 0;
|
||||
|
||||
assert(pSql->numOfSubs >= 1);
|
||||
|
||||
static SJoinSubquerySupporter* tscUpdateSubqueryStatus(SSqlObj* pSql, int32_t numOfFetch) {
|
||||
int32_t notInvolved = 0;
|
||||
SJoinSubquerySupporter* pSupporter = NULL;
|
||||
SSubqueryState* pState = NULL;
|
||||
|
||||
for(int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
if (pSql->pSubs[i] == NULL) {
|
||||
notInvolved++;
|
||||
} else {
|
||||
pSupporter = (SJoinSubquerySupporter*)pSql->pSubs[i]->param;
|
||||
pState = pSupporter->pState;
|
||||
}
|
||||
}
|
||||
|
||||
pState->numOfTotal = pSql->numOfSubs;
|
||||
pState->numOfCompleted = pSql->numOfSubs - numOfFetch;
|
||||
|
||||
return pSupporter;
|
||||
}
|
||||
|
||||
void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
||||
int32_t numOfFetch = 0;
|
||||
assert(pSql->numOfSubs >= 1);
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
if (pSql->pSubs[i] == NULL) { // this subquery does not need to involve in secondary query
|
||||
continue;
|
||||
}
|
||||
|
||||
SSqlRes *pRes = &pSql->pSubs[i]->res;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->pSubs[i]->cmd, 0);
|
||||
|
||||
|
@ -568,12 +606,13 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
|||
// TODO multi-vnode retrieve for projection query with limitation has bugs, since the global limiation is not handled
|
||||
tscTrace("%p retrieve data from %d subqueries", pSql, numOfFetch);
|
||||
|
||||
SJoinSubquerySupporter* pSupporter = (SJoinSubquerySupporter*)pSql->pSubs[0]->param;
|
||||
pSupporter->pState->numOfTotal = numOfFetch; // wait for all subqueries completed
|
||||
pSupporter->pState->numOfCompleted = 0;
|
||||
SJoinSubquerySupporter* pSupporter = tscUpdateSubqueryStatus(pSql, numOfFetch);
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
SSqlObj* pSql1 = pSql->pSubs[i];
|
||||
if (pSql1 == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SSqlRes* pRes1 = &pSql1->res;
|
||||
SSqlCmd* pCmd1 = &pSql1->cmd;
|
||||
|
@ -581,9 +620,7 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
|||
pSupporter = (SJoinSubquerySupporter*)pSql1->param;
|
||||
|
||||
// wait for all subqueries completed
|
||||
pSupporter->pState->numOfTotal = numOfFetch;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd1, 0);
|
||||
|
||||
assert(pRes1->numOfRows >= 0 && pQueryInfo->numOfTables == 1);
|
||||
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
|
@ -605,6 +642,16 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql) {
|
|||
|
||||
// wait for all subquery completed
|
||||
tsem_wait(&pSql->rspSem);
|
||||
|
||||
// update the records for each subquery
|
||||
for(int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
if (pSql->pSubs[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SSqlRes* pRes1 = &pSql->pSubs[i]->res;
|
||||
pRes1->numOfTotalInCurrentClause += pRes1->numOfRows;
|
||||
}
|
||||
}
|
||||
|
||||
// all subqueries return, set the result output index
|
||||
|
@ -618,7 +665,7 @@ void tscSetupOutputColumnIndex(SSqlObj* pSql) {
|
|||
return; // the column transfer support struct has been built
|
||||
}
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
pRes->pColumnIndex = calloc(1, sizeof(SColumnIndex) * pQueryInfo->fieldsInfo.numOfOutputCols);
|
||||
|
||||
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
|
||||
|
@ -626,15 +673,15 @@ void tscSetupOutputColumnIndex(SSqlObj* pSql) {
|
|||
|
||||
int32_t tableIndexOfSub = -1;
|
||||
for (int32_t j = 0; j < pQueryInfo->numOfTables; ++j) {
|
||||
SSqlObj* pSub = pSql->pSubs[j];
|
||||
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSub->cmd, 0, 0);
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, j);
|
||||
if (pMeterMetaInfo->pMeterMeta->uid == pExpr->uid) {
|
||||
tableIndexOfSub = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(tableIndexOfSub >= 0 && tableIndexOfSub < pQueryInfo->numOfTables);
|
||||
|
||||
SSqlCmd* pSubCmd = &pSql->pSubs[tableIndexOfSub]->cmd;
|
||||
SQueryInfo* pSubQueryInfo = tscGetQueryInfoDetail(pSubCmd, 0);
|
||||
|
||||
|
@ -710,7 +757,6 @@ void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code) {
|
|||
if (atomic_add_fetch_32(&pSupporter->pState->numOfCompleted, 1) >= pSupporter->pState->numOfTotal) {
|
||||
tscSetupOutputColumnIndex(pParentSql);
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
|
||||
/**
|
||||
|
|
|
@ -989,7 +989,6 @@ int doParseInsertSql(SSqlObj *pSql, char *str) {
|
|||
pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pQueryInfo);
|
||||
} else {
|
||||
pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
// assert(pQueryInfo->numOfTables == 1);
|
||||
}
|
||||
|
||||
if ((code = tscAllocPayload(pCmd, TSDB_PAYLOAD_SIZE)) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1053,6 +1052,8 @@ int doParseInsertSql(SSqlObj *pSql, char *str) {
|
|||
}
|
||||
|
||||
void *fp = pSql->fp;
|
||||
ptrdiff_t pos = pSql->asyncTblPos - pSql->sqlstr;
|
||||
|
||||
if ((code = tscCheckIfCreateTable(&str, pSql)) != TSDB_CODE_SUCCESS) {
|
||||
/*
|
||||
* For async insert, after get the metermeta from server, the sql string will not be
|
||||
|
@ -1062,7 +1063,7 @@ int doParseInsertSql(SSqlObj *pSql, char *str) {
|
|||
*/
|
||||
if (fp != NULL) {
|
||||
if (TSDB_CODE_ACTION_IN_PROGRESS == code) {
|
||||
tscTrace("async insert and waiting to get meter meta, then continue parse sql: %s", pSql->asyncTblPos);
|
||||
tscTrace("async insert and waiting to get meter meta, then continue parse sql from offset: %" PRId64, pos);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -1277,11 +1278,8 @@ int tsParseInsertSql(SSqlObj *pSql) {
|
|||
SQueryInfo *pQueryInfo = NULL;
|
||||
tscGetQueryInfoDetailSafely(pCmd, pCmd->clauseIndex, &pQueryInfo);
|
||||
|
||||
if (sToken.type == TK_INSERT) {
|
||||
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_INSERT);
|
||||
} else {
|
||||
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_IMPORT);
|
||||
}
|
||||
uint16_t type = (sToken.type == TK_INSERT)? TSDB_QUERY_TYPE_INSERT:TSDB_QUERY_TYPE_IMPORT;
|
||||
TSDB_QUERY_SET_TYPE(pQueryInfo->type, type);
|
||||
|
||||
sToken = tStrGetToken(pSql->sqlstr, &index, false, 0, NULL);
|
||||
if (sToken.type != TK_INTO) {
|
||||
|
|
|
@ -42,12 +42,6 @@ typedef struct SColumnList {
|
|||
SColumnIndex ids[TSDB_MAX_COLUMNS];
|
||||
} SColumnList;
|
||||
|
||||
typedef struct SColumnIdListRes {
|
||||
SSchema* pSchema;
|
||||
int32_t numOfCols;
|
||||
SColumnList list;
|
||||
} SColumnIdListRes;
|
||||
|
||||
static SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t outputIndex, int32_t colIdx, int32_t tableIndex);
|
||||
|
||||
static int32_t setShowInfo(SSqlObj* pSql, SSqlInfo* pInfo);
|
||||
|
@ -518,6 +512,8 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
if ((code = doCheckForQuery(pSql, pQuerySql, i)) != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
tscPrintSelectClause(pCmd, i);
|
||||
}
|
||||
|
||||
// set the command/global limit parameters from the first subclause to the sqlcmd object
|
||||
|
@ -1078,9 +1074,10 @@ static void extractColumnNameFromString(tSQLExprItem* pItem) {
|
|||
int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable) {
|
||||
assert(pSelection != NULL && pCmd != NULL);
|
||||
|
||||
const char* msg1 = "invalid column name/illegal column type in arithmetic expression";
|
||||
const char* msg1 = "invalid column name, or illegal column type";
|
||||
const char* msg2 = "functions can not be mixed up";
|
||||
const char* msg3 = "not support query expression";
|
||||
const char* msg4 = "columns from different table mixed up in arithmetic expression";
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex);
|
||||
|
||||
|
@ -1112,18 +1109,18 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
|
||||
} else if (pItem->pNode->nSQLOptr >= TK_PLUS && pItem->pNode->nSQLOptr <= TK_REM) {
|
||||
// arithmetic function in select
|
||||
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
SSchema* pSchema = tsGetSchema(pMeterMetaInfo->pMeterMeta);
|
||||
|
||||
SColumnIdListRes columnList = {.pSchema = pSchema, .numOfCols = pMeterMetaInfo->pMeterMeta->numOfColumns,
|
||||
.list = {0}};
|
||||
|
||||
int32_t ret =
|
||||
validateArithmeticSQLExpr(pItem->pNode, pQueryInfo, &columnList.list);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
SColumnList columnList = {0};
|
||||
if (validateArithmeticSQLExpr(pItem->pNode, pQueryInfo, &columnList) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
|
||||
}
|
||||
|
||||
int32_t tableIndex = columnList.ids[0].tableIndex;
|
||||
for(int32_t f = 1; f < columnList.num; ++f) {
|
||||
if (columnList.ids[f].tableIndex != tableIndex) {
|
||||
return invalidSqlErrMsg(pQueryInfo->msg, msg4);
|
||||
}
|
||||
}
|
||||
|
||||
char arithmeticExprStr[1024] = {0};
|
||||
char* p = arithmeticExprStr;
|
||||
|
||||
|
@ -1132,10 +1129,10 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
}
|
||||
|
||||
// expr string is set as the parameter of function
|
||||
SColumnIndex index = {0};
|
||||
SColumnIndex index = {.tableIndex = tableIndex};
|
||||
SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, outputIndex, TSDB_FUNC_ARITHM, &index, TSDB_DATA_TYPE_DOUBLE,
|
||||
sizeof(double), sizeof(double));
|
||||
addExprParams(pExpr, arithmeticExprStr, TSDB_DATA_TYPE_BINARY, strlen(arithmeticExprStr), 0);
|
||||
addExprParams(pExpr, arithmeticExprStr, TSDB_DATA_TYPE_BINARY, strlen(arithmeticExprStr), index.tableIndex);
|
||||
|
||||
/* todo alias name should use the original sql string */
|
||||
if (pItem->aliasName != NULL) {
|
||||
|
@ -1144,7 +1141,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
strncpy(pExpr->aliasName, arithmeticExprStr, TSDB_COL_NAME_LEN);
|
||||
}
|
||||
|
||||
insertResultField(pQueryInfo, i, &columnList.list, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName);
|
||||
insertResultField(pQueryInfo, i, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName);
|
||||
} else {
|
||||
/*
|
||||
* not support such expression
|
||||
|
@ -2883,7 +2880,7 @@ static int32_t validateSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnL
|
|||
return TSDB_CODE_INVALID_SQL;
|
||||
}
|
||||
|
||||
pList->ids[pList->num++].columnIndex = index.columnIndex;
|
||||
pList->ids[pList->num++] = index;
|
||||
} else if (pExpr->nSQLOptr == TK_FLOAT && (isnan(pExpr->val.dKey) || isinf(pExpr->val.dKey))) {
|
||||
return TSDB_CODE_INVALID_SQL;
|
||||
} else if (pExpr->nSQLOptr >= TK_MIN && pExpr->nSQLOptr <= TK_LAST_ROW) {
|
||||
|
@ -5142,7 +5139,8 @@ void tscPrintSelectClause(SSqlCmd* pCmd, int32_t subClauseIndex) {
|
|||
for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
|
||||
int32_t size = sprintf(str + offset, "%s(%d)", aAggs[pExpr->functionId].aName, pExpr->colInfo.colId);
|
||||
int32_t size = sprintf(str + offset, "%s(uid:%" PRId64 ", %d)", aAggs[pExpr->functionId].aName,
|
||||
pExpr->uid, pExpr->colInfo.colId);
|
||||
offset += size;
|
||||
|
||||
if (i < pQueryInfo->exprsInfo.numOfExprs - 1) {
|
||||
|
|
|
@ -725,6 +725,13 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSubquerySu
|
|||
pNewQueryInfo->colList.numOfCols++;
|
||||
}
|
||||
}
|
||||
|
||||
tscTrace("%p subquery:%p tableIndex:%d, vnodeIdx:%d, type:%d, transfer to ts_comp query to retrieve timestamps, "
|
||||
"exprInfo:%d, colList:%d, fieldsInfo:%d, name:%s",
|
||||
pSql, pNew, tableIndex, pMeterMetaInfo->vnodeIndex, pNewQueryInfo->type,
|
||||
pNewQueryInfo->exprsInfo.numOfExprs, pNewQueryInfo->colList.numOfCols,
|
||||
pNewQueryInfo->fieldsInfo.numOfOutputCols, pNewQueryInfo->pMeterInfo[0]->name);
|
||||
|
||||
} else {
|
||||
SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
|
||||
pNewQueryInfo->type |= TSDB_QUERY_TYPE_SUBQUERY;
|
||||
|
@ -734,6 +741,7 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSubquerySu
|
|||
tscPrintSelectClause(&pNew->cmd, 0);
|
||||
#endif
|
||||
|
||||
|
||||
return tscProcessSql(pNew);
|
||||
}
|
||||
|
||||
|
|
|
@ -446,6 +446,10 @@ static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
|||
bool allSubqueryExhausted = true;
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
if (pSql->pSubs[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SSqlRes *pRes1 = &pSql->pSubs[i]->res;
|
||||
SSqlCmd *pCmd1 = &pSql->pSubs[i]->cmd;
|
||||
|
||||
|
@ -456,7 +460,7 @@ static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
|||
|
||||
/*
|
||||
* if the global limitation is not reached, and current result has not exhausted, or next more vnodes are
|
||||
* available, go on
|
||||
* available, goes on
|
||||
*/
|
||||
if (pMetaInfo->vnodeIndex < pMetaInfo->pMetricMeta->numOfVnodes && pRes1->row < pRes1->numOfRows &&
|
||||
(!tscHasReachLimitation(pQueryInfo1, pRes1))) {
|
||||
|
@ -483,37 +487,25 @@ static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
|
|||
return hasData;
|
||||
}
|
||||
|
||||
static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
|
||||
static void **tscBuildResFromSubqueries(SSqlObj *pSql) {
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
while (1) {
|
||||
if (!tscHashRemainDataInSubqueryResultSet(pSql)) { // free all sub sqlobj
|
||||
tscTrace("%p at least one subquery exhausted, free all other %d subqueries", pSql, pSql->numOfSubs - 1);
|
||||
|
||||
SSubqueryState *pState = NULL;
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
SSqlObj *pChildObj = pSql->pSubs[i];
|
||||
|
||||
SJoinSubquerySupporter *pSupporter = (SJoinSubquerySupporter *)pChildObj->param;
|
||||
pState = pSupporter->pState;
|
||||
|
||||
tscDestroyJoinSupporter(pChildObj->param);
|
||||
taos_free_result(pChildObj);
|
||||
}
|
||||
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
if (pRes->tsrow == NULL) {
|
||||
pRes->tsrow = malloc(POINTER_BYTES * pQueryInfo->exprsInfo.numOfExprs);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (pSql->numOfSubs >= 2) { // do merge result
|
||||
|
||||
int32_t numOfTableHasRes = 0;
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
if (pSql->pSubs[i] != 0) {
|
||||
numOfTableHasRes++;
|
||||
}
|
||||
}
|
||||
|
||||
if (numOfTableHasRes >= 2) { // do merge result
|
||||
SSqlRes *pRes1 = &pSql->pSubs[0]->res;
|
||||
SSqlRes *pRes2 = &pSql->pSubs[1]->res;
|
||||
|
||||
|
@ -528,8 +520,13 @@ static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
|
|||
pRes2->row++;
|
||||
}
|
||||
} else { // only one subquery
|
||||
SSqlRes *pRes1 = &pSql->pSubs[0]->res;
|
||||
doSetResultRowData(pSql->pSubs[0]);
|
||||
SSqlObj *pSub = pSql->pSubs[0];
|
||||
if (pSub == NULL) {
|
||||
pSub = pSql->pSubs[1];
|
||||
}
|
||||
|
||||
SSqlRes *pRes1 = &pSub->res;
|
||||
doSetResultRowData(pSub);
|
||||
|
||||
success = (pRes1->row++ < pRes1->numOfRows);
|
||||
}
|
||||
|
@ -543,8 +540,32 @@ static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
|
|||
pRes->tsrow[i] = pRes1->tsrow[columnIndex];
|
||||
}
|
||||
|
||||
pRes->numOfTotalInCurrentClause++;
|
||||
|
||||
break;
|
||||
} else { // continue retrieve data from vnode
|
||||
if (!tscHashRemainDataInSubqueryResultSet(pSql)) { // free all sub sqlobj
|
||||
tscTrace("%p at least one subquery exhausted, free all other %d subqueries", pSql, pSql->numOfSubs - 1);
|
||||
|
||||
SSubqueryState *pState = NULL;
|
||||
|
||||
for (int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
SSqlObj *pChildObj = pSql->pSubs[i];
|
||||
if (pChildObj == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SJoinSubquerySupporter *pSupporter = (SJoinSubquerySupporter *)pChildObj->param;
|
||||
pState = pSupporter->pState;
|
||||
|
||||
tscDestroyJoinSupporter(pChildObj->param);
|
||||
taos_free_result(pChildObj);
|
||||
}
|
||||
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tscFetchDatablockFromSubquery(pSql);
|
||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||
return NULL;
|
||||
|
@ -555,94 +576,6 @@ static void **tscJoinResultsetFromBuf(SSqlObj *pSql) {
|
|||
return pRes->tsrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* If current vnode query does not return results anymore (pRes->numOfRows == 0), try the next vnode if exists,
|
||||
* in case of multi-vnode super table projection query and the result does not reach the limitation.
|
||||
*/
|
||||
static bool hasMoreVnodesToTry(SSqlObj *pSql) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
return pRes->numOfRows == 0 && tscProjectionQueryOnSTable(pQueryInfo, 0) && !tscHasReachLimitation(pQueryInfo, pRes);
|
||||
}
|
||||
|
||||
static void tscTryQueryNextVnode(SSqlObj *pSql) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
/*
|
||||
* no result returned from the current virtual node anymore, try the next vnode if exists
|
||||
* if case of: multi-vnode super table projection query
|
||||
*/
|
||||
assert(pRes->numOfRows == 0 && tscProjectionQueryOnSTable(pQueryInfo, 0) && !tscHasReachLimitation(pQueryInfo, pRes));
|
||||
|
||||
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
int32_t totalVnode = pMeterMetaInfo->pMetricMeta->numOfVnodes;
|
||||
|
||||
while (++pMeterMetaInfo->vnodeIndex < totalVnode) {
|
||||
tscTrace("%p current vnode:%d exhausted, try next:%d. total vnode:%d. current numOfRes:%d", pSql,
|
||||
pMeterMetaInfo->vnodeIndex - 1, pMeterMetaInfo->vnodeIndex, totalVnode, pRes->numOfTotalInCurrentClause);
|
||||
|
||||
/*
|
||||
* update the limit and offset value for the query on the next vnode,
|
||||
* according to current retrieval results
|
||||
*
|
||||
* NOTE:
|
||||
* if the pRes->offset is larger than 0, the start returned position has not reached yet.
|
||||
* Therefore, the pRes->numOfRows, as well as pRes->numOfTotalInCurrentClause, must be 0.
|
||||
* The pRes->offset value will be updated by virtual node, during query execution.
|
||||
*/
|
||||
if (pQueryInfo->clauseLimit >= 0) {
|
||||
pQueryInfo->limit.limit = pQueryInfo->clauseLimit - pRes->numOfTotalInCurrentClause;
|
||||
}
|
||||
|
||||
pQueryInfo->limit.offset = pRes->offset;
|
||||
|
||||
assert((pRes->offset >= 0 && pRes->numOfRows == 0) || (pRes->offset == 0 && pRes->numOfRows >= 0));
|
||||
tscTrace("%p new query to next vnode, vnode index:%d, limit:%" PRId64 ", offset:%" PRId64 ", glimit:%" PRId64, pSql,
|
||||
pMeterMetaInfo->vnodeIndex, pQueryInfo->limit.limit, pQueryInfo->limit.offset, pQueryInfo->clauseLimit);
|
||||
|
||||
/*
|
||||
* For project query with super table join, the numOfSub is equalled to the number of all subqueries.
|
||||
* Therefore, we need to reset the value of numOfSubs to be 0.
|
||||
*
|
||||
* For super table join with projection query, if anyone of the subquery is exhausted, the query completed.
|
||||
*/
|
||||
pSql->numOfSubs = 0;
|
||||
|
||||
pCmd->command = TSDB_SQL_SELECT;
|
||||
assert(pSql->fp == NULL);
|
||||
|
||||
int32_t ret = tscProcessSql(pSql); // todo check for failure
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
pSql->res.code = ret;
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve data
|
||||
assert(pCmd->command == TSDB_SQL_SELECT);
|
||||
pCmd->command = TSDB_SQL_FETCH;
|
||||
|
||||
if ((ret = tscProcessSql(pSql)) != TSDB_CODE_SUCCESS) {
|
||||
pSql->res.code = ret;
|
||||
return;
|
||||
}
|
||||
|
||||
// if the result from current virtual node are empty, try next if exists. otherwise, return the results.
|
||||
if (pRes->numOfRows > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pRes->numOfRows == 0) {
|
||||
tscTrace("%p all vnodes exhausted, prj query completed. total res:%d", pSql, totalVnode, pRes->numOfTotal);
|
||||
}
|
||||
}
|
||||
|
||||
TAOS_ROW taos_fetch_row_impl(TAOS_RES *res) {
|
||||
SSqlObj *pSql = (SSqlObj *)res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
@ -657,7 +590,7 @@ TAOS_ROW taos_fetch_row_impl(TAOS_RES *res) {
|
|||
|
||||
if (pRes->code == TSDB_CODE_SUCCESS) {
|
||||
tscTrace("%p data from all subqueries have been retrieved to client", pSql);
|
||||
return tscJoinResultsetFromBuf(pSql);
|
||||
return tscBuildResFromSubqueries(pSql);
|
||||
} else {
|
||||
tscTrace("%p retrieve data from subquery failed, code:%d", pSql, pRes->code);
|
||||
return NULL;
|
||||
|
@ -679,7 +612,7 @@ TAOS_ROW taos_fetch_row_impl(TAOS_RES *res) {
|
|||
tscProcessSql(pSql); // retrieve data from virtual node
|
||||
|
||||
if (hasMoreVnodesToTry(pSql)) {
|
||||
tscTryQueryNextVnode(pSql);
|
||||
tscTryQueryNextVnode(pSql, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -822,6 +755,11 @@ void taos_free_result(TAOS_RES *res) {
|
|||
|
||||
// set freeFlag to 1 in retrieve message if there are un-retrieved results
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
if (pQueryInfo == NULL) {
|
||||
tscFreeSqlObjPartial(pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
|
||||
|
||||
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
|
|
|
@ -1888,7 +1888,6 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
#endif
|
||||
|
||||
char* name = pMeterMetaInfo->name;
|
||||
|
||||
SMeterMetaInfo* pFinalInfo = NULL;
|
||||
|
||||
if (pPrevSql == NULL) {
|
||||
|
@ -1907,13 +1906,16 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
pMeterMetaInfo->tagColumnIndex);
|
||||
}
|
||||
|
||||
assert(pFinalInfo->pMeterMeta != NULL);
|
||||
assert(pFinalInfo->pMeterMeta != NULL && pNewQueryInfo->numOfTables == 1);
|
||||
if (UTIL_METER_IS_SUPERTABLE(pMeterMetaInfo)) {
|
||||
assert(pFinalInfo->pMetricMeta != NULL);
|
||||
}
|
||||
|
||||
tscTrace("%p new subquery %p, tableIndex:%d, vnodeIdx:%d, type:%d", pSql, pNew, tableIndex,
|
||||
pMeterMetaInfo->vnodeIndex, pNewQueryInfo->type);
|
||||
tscTrace("%p new subquery %p, tableIndex:%d, vnodeIdx:%d, type:%d, exprInfo:%d, colList:%d,"
|
||||
"fieldInfo:%d, name:%s", pSql, pNew, tableIndex,
|
||||
pMeterMetaInfo->vnodeIndex, pNewQueryInfo->type, pNewQueryInfo->exprsInfo.numOfExprs, pNewQueryInfo->colList.numOfCols,
|
||||
pNewQueryInfo->fieldsInfo.numOfOutputCols, pFinalInfo->name);
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
@ -1990,3 +1992,102 @@ bool tscHasReachLimitation(SQueryInfo* pQueryInfo, SSqlRes* pRes) {
|
|||
}
|
||||
|
||||
char* tscGetErrorMsgPayload(SSqlCmd* pCmd) { return pCmd->payload; }
|
||||
|
||||
/**
|
||||
* If current vnode query does not return results anymore (pRes->numOfRows == 0), try the next vnode if exists,
|
||||
* in case of multi-vnode super table projection query and the result does not reach the limitation.
|
||||
*/
|
||||
bool hasMoreVnodesToTry(SSqlObj *pSql) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
return pRes->numOfRows == 0 && tscProjectionQueryOnSTable(pQueryInfo, 0) && !tscHasReachLimitation(pQueryInfo, pRes);
|
||||
}
|
||||
|
||||
void tscTryQueryNextVnode(SSqlObj *pSql, __async_cb_func_t fp) {
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
/*
|
||||
* no result returned from the current virtual node anymore, try the next vnode if exists
|
||||
* if case of: multi-vnode super table projection query
|
||||
*/
|
||||
assert(pRes->numOfRows == 0 && tscProjectionQueryOnSTable(pQueryInfo, 0) && !tscHasReachLimitation(pQueryInfo, pRes));
|
||||
|
||||
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
|
||||
int32_t totalVnode = pMeterMetaInfo->pMetricMeta->numOfVnodes;
|
||||
|
||||
while (++pMeterMetaInfo->vnodeIndex < totalVnode) {
|
||||
tscTrace("%p current vnode:%d exhausted, try next:%d. total vnode:%d. current numOfRes:%d", pSql,
|
||||
pMeterMetaInfo->vnodeIndex - 1, pMeterMetaInfo->vnodeIndex, totalVnode, pRes->numOfTotalInCurrentClause);
|
||||
|
||||
/*
|
||||
* update the limit and offset value for the query on the next vnode,
|
||||
* according to current retrieval results
|
||||
*
|
||||
* NOTE:
|
||||
* if the pRes->offset is larger than 0, the start returned position has not reached yet.
|
||||
* Therefore, the pRes->numOfRows, as well as pRes->numOfTotalInCurrentClause, must be 0.
|
||||
* The pRes->offset value will be updated by virtual node, during query execution.
|
||||
*/
|
||||
if (pQueryInfo->clauseLimit >= 0) {
|
||||
pQueryInfo->limit.limit = pQueryInfo->clauseLimit - pRes->numOfTotalInCurrentClause;
|
||||
}
|
||||
|
||||
pQueryInfo->limit.offset = pRes->offset;
|
||||
|
||||
assert((pRes->offset >= 0 && pRes->numOfRows == 0) || (pRes->offset == 0 && pRes->numOfRows >= 0));
|
||||
tscTrace("%p new query to next vnode, vnode index:%d, limit:%" PRId64 ", offset:%" PRId64 ", glimit:%" PRId64, pSql,
|
||||
pMeterMetaInfo->vnodeIndex, pQueryInfo->limit.limit, pQueryInfo->limit.offset, pQueryInfo->clauseLimit);
|
||||
|
||||
/*
|
||||
* For project query with super table join, the numOfSub is equalled to the number of all subqueries.
|
||||
* Therefore, we need to reset the value of numOfSubs to be 0.
|
||||
*
|
||||
* For super table join with projection query, if anyone of the subquery is exhausted, the query completed.
|
||||
*/
|
||||
pSql->numOfSubs = 0;
|
||||
pCmd->command = TSDB_SQL_SELECT;
|
||||
|
||||
tscResetForNextRetrieve(pRes);
|
||||
|
||||
// in case of async query, set the callback function
|
||||
void* fp1 = pSql->fp;
|
||||
if (fp1 != NULL) {
|
||||
assert(fp != NULL);
|
||||
pSql->fp = fp;
|
||||
}
|
||||
|
||||
int32_t ret = tscProcessSql(pSql); // todo check for failure
|
||||
if (fp != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
pSql->res.code = ret;
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve data
|
||||
assert(pCmd->command == TSDB_SQL_SELECT);
|
||||
pCmd->command = TSDB_SQL_FETCH;
|
||||
|
||||
if ((ret = tscProcessSql(pSql)) != TSDB_CODE_SUCCESS) {
|
||||
pSql->res.code = ret;
|
||||
return;
|
||||
}
|
||||
|
||||
// if the result from current virtual node are empty, try next if exists. otherwise, return the results.
|
||||
if (pRes->numOfRows > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pRes->numOfRows == 0) {
|
||||
tscTrace("%p all vnodes exhausted, prj query completed. total res:%d", pSql, totalVnode, pRes->numOfTotal);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue