diff --git a/src/client/inc/tscSQLParser.h b/src/client/inc/tscSQLParser.h
index dd579d08c3c6b1465ce6b34e29f453c7b00827ec..0e4ad279dc0beaf0c56109583d3d02f5ae60b4f3 100644
--- a/src/client/inc/tscSQLParser.h
+++ b/src/client/inc/tscSQLParser.h
@@ -86,15 +86,16 @@ enum _sql_cmd {
TSDB_SQL_MAX //48
};
-#define MAX_TOKEN_LEN 30
-
-// token type
enum {
TSQL_NODE_TYPE_EXPR = 0x1,
TSQL_NODE_TYPE_ID = 0x2,
TSQL_NODE_TYPE_VALUE = 0x4,
};
+#define NON_ARITHMEIC_EXPR 0
+#define NORMAL_ARITHMETIC 1
+#define AGG_ARIGHTMEIC 2
+
extern char tTokenTypeSwitcher[13];
#define toTSDBType(x) \
@@ -112,7 +113,7 @@ typedef struct SLimitVal {
} SLimitVal;
typedef struct SOrderVal {
- int32_t order;
+ uint32_t order;
int32_t orderColId;
} SOrderVal;
diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h
index c67e7cb679592886040bd9cf6cf6d7adec5a656c..a869e45198fe2da615b2178c55a32bcd64a9285a 100644
--- a/src/client/inc/tscUtil.h
+++ b/src/client/inc/tscUtil.h
@@ -128,6 +128,8 @@ void tscFieldInfoSetValFromSchema(SFieldInfo* pFieldInfo, int32_t index, SSchema
void tscFieldInfoSetValFromField(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* pField);
void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, const char* name, int16_t bytes);
void tscFieldInfoUpdateVisible(SFieldInfo* pFieldInfo, int32_t index, bool visible);
+void tscFieldInfoSetExpr(SFieldInfo* pFieldInfo, int32_t index, SSqlExpr* pExpr);
+void tscFieldInfoSetBinExpr(SFieldInfo* pFieldInfo, int32_t index, SSqlFunctionExpr* pExpr);
void tscFieldInfoCalOffset(SQueryInfo* pQueryInfo);
void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo);
@@ -149,9 +151,10 @@ SSqlExpr* tscSqlExprInsertEmpty(SQueryInfo* pQueryInfo, int32_t index, int16_t f
SSqlExpr* tscSqlExprUpdate(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, int16_t srcColumnIndex, int16_t type,
int16_t size);
+int32_t tscSqlExprNumOfExprs(SQueryInfo* pQueryInfo);
SSqlExpr* tscSqlExprGet(SQueryInfo* pQueryInfo, int32_t index);
-void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t uid);
+void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t uid, bool deepcopy);
void* tscSqlExprDestroy(SSqlExpr* pExpr);
void tscSqlExprInfoDestroy(SSqlExprInfo* pExprInfo);
diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h
index 700d6a43cf25a4be54f87bdccb35d46dc51d3867..7e3b54545a5c6fb942d2a70da6c09b5f47123727 100644
--- a/src/client/inc/tsclient.h
+++ b/src/client/inc/tsclient.h
@@ -32,9 +32,8 @@ extern "C" {
#include "tutil.h"
#include "trpc.h"
-#define TSC_GET_RESPTR_BASE(res, _queryinfo, col, ord) \
- (res->data + tscFieldInfoGetOffset(_queryinfo, col) * res->numOfRows)
-
+#define TSC_GET_RESPTR_BASE(res, _queryinfo, col) (res->data + ((_queryinfo)->fieldsInfo.pSqlExpr[col]->offset) * res->numOfRows)
+
// forward declaration
struct SSqlInfo;
@@ -71,13 +70,19 @@ typedef struct SSqlExpr {
int16_t interResBytes; // inter result buffer size
int16_t numOfParams; // argument value of each function
tVariant param[3]; // parameters are not more than 3
+ int32_t offset; // sub result column value of arithmetic expression.
} SSqlExpr;
+typedef struct SColumnIndex {
+ int16_t tableIndex;
+ int16_t columnIndex;
+} SColumnIndex;
+
typedef struct SFieldInfo {
int16_t numOfOutputCols; // number of column in result
int16_t numOfAlloc; // allocated size
TAOS_FIELD *pFields;
- short * pOffset;
+// short * pOffset;
/*
* define if this column is belong to the queried result, it may be add by parser to faciliate
@@ -86,20 +91,17 @@ typedef struct SFieldInfo {
* NOTE: these hidden columns always locate at the end of the output columns
*/
bool * pVisibleCols;
- int32_t numOfHiddenCols; // the number of column not belongs to the queried result columns
+ int32_t numOfHiddenCols; // the number of column not belongs to the queried result columns
+ SSqlFunctionExpr** pExpr; // used for aggregation arithmetic express,such as count(*)+count(*)
+ SSqlExpr** pSqlExpr;
} SFieldInfo;
typedef struct SSqlExprInfo {
- int16_t numOfAlloc;
- int16_t numOfExprs;
- SSqlExpr *pExprs;
+ int16_t numOfAlloc;
+ int16_t numOfExprs;
+ SSqlExpr** pExprs;
} SSqlExprInfo;
-typedef struct SColumnIndex {
- int16_t tableIndex;
- int16_t columnIndex;
-} SColumnIndex;
-
typedef struct SColumnBase {
SColumnIndex colIndex;
int32_t numOfFilters;
@@ -164,7 +166,7 @@ typedef struct STableDataBlocks {
int32_t rowSize; // row size for current table
uint32_t nAllocSize;
- uint32_t headerSize; // header for metadata (submit metadata)
+ uint32_t headerSize; // header for metadata (submit metadata)
uint32_t size;
/*
@@ -199,9 +201,9 @@ typedef struct SQueryInfo {
char intervalTimeUnit;
int64_t etime, stime;
- int64_t nAggTimeInterval; // aggregation time interval
- int64_t nSlidingTime; // sliding window in mseconds
- SSqlGroupbyExpr groupbyExpr; // group by tags info
+ int64_t intervalTime; // aggregation time interval
+ int64_t slidingTime; // sliding window in mseconds
+ SSqlGroupbyExpr groupbyExpr; // group by tags info
SColumnBaseInfo colList;
SFieldInfo fieldsInfo;
@@ -217,9 +219,9 @@ typedef struct SQueryInfo {
int64_t * defaultVal; // default value for interpolation
char * msg; // pointer to the pCmd->payload to keep error message temporarily
int64_t clauseLimit; // limit for current sub clause
-
+
// offset value in the original sql expression, NOT sent to virtual node, only applied at client side
- int64_t prjOffset;
+ int64_t prjOffset;
} SQueryInfo;
// data source from sql string or from file
@@ -270,29 +272,27 @@ typedef struct SResRec {
struct STSBuf;
typedef struct {
- int32_t code;
- int64_t numOfRows; // num of results in current retrieved
- int64_t numOfTotal; // num of total results
- int64_t numOfTotalInCurrentClause; // num of total result in current subclause
-
- char * pRsp;
- int rspType;
- int rspLen;
- uint64_t qhandle;
- int64_t uid;
- int64_t useconds;
- int64_t offset; // offset value from vnode during projection query of stable
- int row;
- int16_t numOfnchar;
- int16_t precision;
- int32_t numOfGroups;
- SResRec * pGroupRec;
- char * data;
- short * bytes;
- void ** tsrow;
- char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
+ int32_t code;
+ int64_t numOfRows; // num of results in current retrieved
+ int64_t numOfTotal; // num of total results
+ int64_t numOfTotalInCurrentClause; // num of total result in current subclause
+ char * pRsp;
+ int rspType;
+ int rspLen;
+ uint64_t qhandle;
+ int64_t uid;
+ int64_t useconds;
+ int64_t offset; // offset value from vnode during projection query of stable
+ int row;
+ int16_t numOfCols;
+ int16_t precision;
+ int32_t numOfGroups;
+ SResRec * pGroupRec;
+ char * data;
+ void ** tsrow;
+ char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
+ SColumnIndex *pColumnIndex;
struct SLocalReducer *pLocalReducer;
- SColumnIndex * pColumnIndex;
} SSqlRes;
typedef struct _tsc_obj {
@@ -400,19 +400,17 @@ int taos_retrieve(TAOS_RES *res);
int32_t tscTansformSQLFunctionForSTableQuery(SQueryInfo *pQueryInfo);
void tscRestoreSQLFunctionForMetricQuery(SQueryInfo *pQueryInfo);
-void tscClearSqlMetaInfoForce(SSqlCmd *pCmd);
-
int32_t tscCreateResPointerInfo(SSqlRes *pRes, SQueryInfo *pQueryInfo);
void tscDestroyResPointerInfo(SSqlRes *pRes);
void tscFreeSqlCmdData(SSqlCmd *pCmd);
-void tscFreeResData(SSqlObj* pSql);
+void tscFreeResData(SSqlObj *pSql);
/**
* free query result of the sql object
* @param pObj
*/
-void tscFreeSqlResult(SSqlObj* pSql);
+void tscFreeSqlResult(SSqlObj *pSql);
/**
* only free part of resources allocated during query.
diff --git a/src/client/src/tscAst.c b/src/client/src/tscAst.c
index f34067006ac50bb0261c10f2cf0f74f68126ce29..22100bc1d17c71af57b1230e2421e135b0c9eec6 100644
--- a/src/client/src/tscAst.c
+++ b/src/client/src/tscAst.c
@@ -158,7 +158,7 @@ static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols,
return pNode;
}
-static uint8_t getBinaryExprOptr(SSQLToken *pToken) {
+uint8_t getBinaryExprOptr(SSQLToken *pToken) {
switch (pToken->type) {
case TK_LT:
return TSDB_RELATION_LESS;
@@ -183,6 +183,7 @@ static uint8_t getBinaryExprOptr(SSQLToken *pToken) {
case TK_STAR:
return TSDB_BINARY_OP_MULTIPLY;
case TK_SLASH:
+ case TK_DIVIDE:
return TSDB_BINARY_OP_DIVIDE;
case TK_REM:
return TSDB_BINARY_OP_REMAINDER;
diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c
index fddca2bc89952b08b1a86caa3c0874a75f4aa503..9528097d207f7d2546c3702f2c2712591fb81cc6 100644
--- a/src/client/src/tscAsync.c
+++ b/src/client/src/tscAsync.c
@@ -284,8 +284,15 @@ void tscAsyncFetchSingleRowProxy(void *param, TAOS_RES *tres, int numOfRows) {
return;
}
- 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;
+ for (int i = 0; i < pCmd->numOfCols; ++i){
+ SSqlExpr* pExpr = pQueryInfo->fieldsInfo.pSqlExpr[i];
+ if (pExpr != NULL) {
+ pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i) + pExpr->resBytes * pRes->row;
+ } else {
+ //todo add
+ }
+ }
+
pRes->row++;
(*pSql->fetchFp)(pSql->param, pSql, pSql->res.tsrow);
@@ -299,7 +306,12 @@ void tscProcessFetchRow(SSchedMsg *pMsg) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
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;
+ SSqlExpr* pExpr = pQueryInfo->fieldsInfo.pSqlExpr[i];
+ if (pExpr != NULL) {
+ pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i) + pExpr->resBytes * pRes->row;
+ } else {
+ //todo add
+ }
}
pRes->row++;
diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c
index 837a0ce0054b8fd7cc92a7b164f667cb6841a276..88b1fc0c28157f9023a3fbef62dabc05802cf05c 100644
--- a/src/client/src/tscFunctionImpl.c
+++ b/src/client/src/tscFunctionImpl.c
@@ -322,6 +322,10 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
return TSDB_CODE_SUCCESS;
}
+bool stableQueryFunctChanged(int32_t funcId) {
+ return (aAggs[funcId].stableFuncId != funcId);
+}
+
/**
* the numOfRes should be kept, since it may be used later
* and allow the ResultInfo to be re initialized
@@ -719,12 +723,15 @@ static int32_t first_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY
return BLK_DATA_NO_NEEDED;
}
- SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
- if (pInfo->hasResult != DATA_SET_FLAG) {
- return BLK_DATA_ALL_NEEDED;
- } else { // data in current block is not earlier than current result
- return (pInfo->ts <= start) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
- }
+ // result buffer has not been set yet.
+ return BLK_DATA_ALL_NEEDED;
+ //todo optimize the filter info
+// SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
+// if (pInfo->hasResult != DATA_SET_FLAG) {
+// return BLK_DATA_ALL_NEEDED;
+// } else { // data in current block is not earlier than current result
+// return (pInfo->ts <= start) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
+// }
}
static int32_t last_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId,
@@ -733,12 +740,13 @@ static int32_t last_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY
return BLK_DATA_NO_NEEDED;
}
- SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
- if (pInfo->hasResult != DATA_SET_FLAG) {
- return BLK_DATA_ALL_NEEDED;
- } else {
- return (pInfo->ts > end) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
- }
+ return BLK_DATA_ALL_NEEDED;
+// SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
+// if (pInfo->hasResult != DATA_SET_FLAG) {
+// return BLK_DATA_ALL_NEEDED;
+// } else {
+// return (pInfo->ts > end) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
+// }
}
//////////////////////////////////////////////////////////////////////////////////////////////
@@ -1437,7 +1445,9 @@ static void stddev_next_step(SQLFunctionCtx *pCtx) {
*/
pStd->stage++;
avg_finalizer(pCtx);
-
+
+ pResInfo->initialized = true; // set it initialized to avoid re-initialization
+
// save average value into tmpBuf, for second stage scan
SAvgInfo *pAvg = pResInfo->interResultBuf;
@@ -2184,7 +2194,7 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) {
// only the first_stage_merge is directly written data into final output buffer
if (pResInfo->superTableQ && pCtx->currentStage != SECONDARY_STAGE_MERGE) {
return (STopBotInfo*) pCtx->aOutputBuf;
- } else { // for normal table query and super table at the secondary_stage, result is written to intermediate buffer
+ } else { // during normal table query and super table at the secondary_stage, result is written to intermediate buffer
return pResInfo->interResultBuf;
}
}
@@ -3312,7 +3322,7 @@ static void arithmetic_function(SQLFunctionCtx *pCtx) {
tSQLBinaryExprCalcTraverse(sas->pExpr->pBinExprInfo.pBinExpr, pCtx->size, pCtx->aOutputBuf, sas, pCtx->order,
arithmetic_callback_function);
- pCtx->aOutputBuf += pCtx->outputBytes * pCtx->size/* * GET_FORWARD_DIRECTION_FACTOR(pCtx->order)*/;
+ pCtx->aOutputBuf += pCtx->outputBytes * pCtx->size;
pCtx->param[1].pz = NULL;
}
@@ -3573,6 +3583,7 @@ void spread_function_finalizer(SQLFunctionCtx *pCtx) {
}
GET_RES_INFO(pCtx)->numOfRes = 1; // todo add test case
+ doFinalizer(pCtx);
}
/*
diff --git a/src/client/src/tscJoinProcess.c b/src/client/src/tscJoinProcess.c
index 1bafb60f1a0e487aeaa7b70e1c1817111f8a631d..afd8e98edac4522089e0aaafa02237da67bdd1cc 100644
--- a/src/client/src/tscJoinProcess.c
+++ b/src/client/src/tscJoinProcess.c
@@ -100,7 +100,7 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSubquerySupporter* pSuppor
* in case of stable query, limit/offset is not applied here. the limit/offset is applied to the
* final results which is acquired after the secondry merge of in the client.
*/
- if (pLimit->offset == 0 || pQueryInfo->nAggTimeInterval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
+ if (pLimit->offset == 0 || pQueryInfo->intervalTime > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
if (*st > elem1.ts) {
*st = elem1.ts;
}
@@ -165,7 +165,7 @@ SJoinSubquerySupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pS
pSupporter->subqueryIndex = index;
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
- pSupporter->interval = pQueryInfo->nAggTimeInterval;
+ pSupporter->interval = pQueryInfo->intervalTime;
pSupporter->limit = pQueryInfo->limit;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(&pSql->cmd, pSql->cmd.clauseIndex, index);
@@ -275,6 +275,7 @@ int32_t tscLaunchSecondPhaseSubqueries(SSqlObj* pSql) {
pSubQueryInfo->tsBuf = NULL;
// free result for async object will also free sqlObj
+ assert(pSubQueryInfo->exprsInfo.numOfExprs == 1); // ts_comp query only requires one resutl columns
taos_free_result(pPrevSub);
SSqlObj *pNew = createSubqueryObj(pSql, (int16_t) i, tscJoinQueryCallback, pSupporter, NULL);
@@ -293,24 +294,26 @@ int32_t tscLaunchSecondPhaseSubqueries(SSqlObj* pSql) {
// set the second stage sub query for join process
pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_SEC_STAGE;
- pQueryInfo->nAggTimeInterval = pSupporter->interval;
+ pQueryInfo->intervalTime = pSupporter->interval;
pQueryInfo->groupbyExpr = pSupporter->groupbyExpr;
tscColumnBaseInfoCopy(&pQueryInfo->colList, &pSupporter->colList, 0);
tscTagCondCopy(&pQueryInfo->tagCond, &pSupporter->tagCond);
- tscSqlExprCopy(&pQueryInfo->exprsInfo, &pSupporter->exprsInfo, pSupporter->uid);
+ tscSqlExprCopy(&pQueryInfo->exprsInfo, &pSupporter->exprsInfo, pSupporter->uid, false);
tscFieldInfoCopyAll(&pQueryInfo->fieldsInfo, &pSupporter->fieldsInfo);
-
+
+ pSupporter->exprsInfo.numOfExprs = 0;
+ pSupporter->fieldsInfo.numOfOutputCols = 0;
+
/*
* if the first column of the secondary query is not ts function, add this function.
* Because this column is required to filter with timestamp after intersecting.
*/
- if (pSupporter->exprsInfo.pExprs[0].functionId != TSDB_FUNC_TS) {
+ if (pSupporter->exprsInfo.pExprs[0]->functionId != TSDB_FUNC_TS) {
tscAddTimestampColumn(pQueryInfo, TSDB_FUNC_TS, 0);
}
- // todo refactor function name
SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetail(&pNew->cmd, 0);
assert(pNew->numOfSubs == 0 && pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1);
diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c
index 8c90554e936286432da712c77f4d70141d225882..ab57719d0979d4994e2c5ee913f21d320ca21561 100644
--- a/src/client/src/tscLocal.c
+++ b/src/client/src/tscLocal.c
@@ -251,6 +251,13 @@ static int32_t tscBuildMeterSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
tscFieldInfoSetValue(&pQueryInfo->fieldsInfo, 3, TSDB_DATA_TYPE_BINARY, "Note", noteColLength);
rowLen += noteColLength;
+
+ //set the sqlexpr part
+ SColumnIndex index = {0};
+ pQueryInfo->fieldsInfo.pSqlExpr[0] = tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, TSDB_COL_NAME_LEN, TSDB_COL_NAME_LEN);
+ pQueryInfo->fieldsInfo.pSqlExpr[1] = tscSqlExprInsert(pQueryInfo, 1, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, typeColLength, typeColLength);
+ pQueryInfo->fieldsInfo.pSqlExpr[2] = tscSqlExprInsert(pQueryInfo, 2, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_INT, sizeof(int32_t), sizeof(int32_t));
+ pQueryInfo->fieldsInfo.pSqlExpr[3] = tscSqlExprInsert(pQueryInfo, 3, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, noteColLength, noteColLength);
return rowLen;
}
@@ -455,6 +462,8 @@ void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnNa
tscInitResObjForLocalQuery(pSql, 1, valueLength);
TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, 0);
+ pQueryInfo->fieldsInfo.pSqlExpr[0] = pQueryInfo->exprsInfo.pExprs[0];
+
strncpy(pRes->data, val, pField->bytes);
}
diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c
index bf0418d69068b18fa95fc2fa2db8d5b24f4e70fc..92323dcdfe05e40fd0281ca9dd0495f0230fd1e9 100644
--- a/src/client/src/tscSQLParser.c
+++ b/src/client/src/tscSQLParser.c
@@ -22,6 +22,7 @@
#include "tstoken.h"
#include "tstrbuild.h"
#include "ttime.h"
+#include "tast.h"
#include "tscSQLParser.h"
#include "tscUtil.h"
@@ -58,9 +59,9 @@ static int32_t setObjFullName(char* fullName, const char* account, SSQLToken* pD
static void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t nameLength);
static void getRevisedName(char* resultFieldName, int32_t functionId, int32_t maxLen, char* columnName);
-static int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprItem* pItem);
+static int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprItem* pItem, bool isResultColumn);
static int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
- int8_t type, char* fieldName);
+ int8_t type, char* fieldName, SSqlExpr* pSqlExpr);
static int32_t changeFunctionID(int32_t optr, int16_t* functionId);
static int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable);
@@ -85,7 +86,7 @@ static int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo);
static int32_t validateSqlFunctionInStreamSql(SQueryInfo* pQueryInfo);
static int32_t buildArithmeticExprString(tSQLExpr* pExpr, char** exprString);
static int32_t validateFunctionsInIntervalOrGroupbyQuery(SQueryInfo* pQueryInfo);
-static int32_t validateArithmeticSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList);
+static int32_t validateArithmeticSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type);
static int32_t validateDNodeConfig(tDCLSQL* pOptions);
static int32_t validateLocalConfig(tDCLSQL* pOptions);
static int32_t validateColumnName(char* name);
@@ -93,7 +94,6 @@ static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo);
static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField);
static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo);
-static bool hasDefaultQueryTimeRange(SQueryInfo *pQueryInfo);
static void updateTagColumnIndex(SQueryInfo* pQueryInfo, int32_t tableIndex);
@@ -115,6 +115,9 @@ static int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo);
static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo);
static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
+static int32_t tSQLBinaryExprCreateFromSqlExpr(tSQLSyntaxNode **pExpr, tSQLExpr* pAst, int32_t* num,
+ SColIndexEx** pColIndex, SSqlExprInfo* pExprInfo);
+
/*
* Used during parsing query sql. Since the query sql usually small in length, error position
* is not needed in the final error message.
@@ -127,7 +130,7 @@ static int32_t tscQueryOnlyMetricTags(SQueryInfo* pQueryInfo, bool* queryOnMetri
assert(QUERY_IS_STABLE_QUERY(pQueryInfo->type));
*queryOnMetricTags = true;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId != TSDB_FUNC_TAGPRJ &&
@@ -203,7 +206,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
int32_t code = tscGetQueryInfoDetailSafely(pCmd, pCmd->clauseIndex, &pQueryInfo);
assert(pQueryInfo->numOfTables == 0);
-
+
SMeterMetaInfo* pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pQueryInfo);
pCmd->command = pInfo->type;
@@ -413,7 +416,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
const char* msg3 = "name too long";
pCmd->command = pInfo->type;
- //tDCLSQL* pDCL = pInfo->pDCLInfo;
+ // tDCLSQL* pDCL = pInfo->pDCLInfo;
SUserInfo* pUser = &pInfo->pDCLInfo->user;
SSQLToken* pName = &pUser->user;
@@ -501,7 +504,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
case TSDB_SQL_SELECT: {
assert(pCmd->numOfClause == 1);
const char* msg1 = "columns in select clause not identical";
-
+
for (int32_t i = pCmd->numOfClause; i < pInfo->subclauseInfo.numOfClause; ++i) {
SQueryInfo* pqi = NULL;
if ((code = tscGetQueryInfoDetailSafely(pCmd, i, &pqi)) != TSDB_CODE_SUCCESS) {
@@ -516,18 +519,18 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
if ((code = doCheckForQuery(pSql, pQuerySql, i)) != TSDB_CODE_SUCCESS) {
return code;
}
-
+
tscPrintSelectClause(pSql, i);
}
-
+
// set the command/global limit parameters from the first subclause to the sqlcmd object
SQueryInfo* pQueryInfo1 = tscGetQueryInfoDetail(pCmd, 0);
pCmd->command = pQueryInfo1->command;
-
+
// if there is only one element, the limit of clause is the limit of global result.
- for(int32_t i = 1; i < pCmd->numOfClause; ++i) {
+ for (int32_t i = 1; i < pCmd->numOfClause; ++i) {
SQueryInfo* pQueryInfo2 = tscGetQueryInfoDetail(pCmd, i);
-
+
int32_t ret = tscFieldInfoCompare(&pQueryInfo1->fieldsInfo, &pQueryInfo2->fieldsInfo);
if (ret != 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
@@ -567,7 +570,7 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
* are available.
*/
static bool isTopBottomQuery(SQueryInfo* pQueryInfo) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
int32_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
@@ -590,25 +593,29 @@ int32_t parseIntervalClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
// interval is not null
SSQLToken* t = &pQuerySql->interval;
- if (getTimestampInUsFromStr(t->z, t->n, &pQueryInfo->nAggTimeInterval) != TSDB_CODE_SUCCESS) {
+ if (getTimestampInUsFromStr(t->z, t->n, &pQueryInfo->intervalTime) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
}
// if the unit of time window value is millisecond, change the value from microsecond
if (pMeterMetaInfo->pMeterMeta->precision == TSDB_TIME_PRECISION_MILLI) {
- pQueryInfo->nAggTimeInterval = pQueryInfo->nAggTimeInterval / 1000;
+ pQueryInfo->intervalTime = pQueryInfo->intervalTime / 1000;
}
/* parser has filter the illegal type, no need to check here */
pQueryInfo->intervalTimeUnit = pQuerySql->interval.z[pQuerySql->interval.n - 1];
// interval cannot be less than 10 milliseconds
- if (pQueryInfo->nAggTimeInterval < tsMinIntervalTime) {
+ if (pQueryInfo->intervalTime < tsMinIntervalTime) {
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
}
// for top/bottom + interval query, we do not add additional timestamp column in the front
if (isTopBottomQuery(pQueryInfo)) {
+ if (parseSlidingClause(pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+
return TSDB_CODE_SUCCESS;
}
@@ -616,18 +623,18 @@ int32_t parseIntervalClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
* check invalid SQL:
* select count(tbname)/count(tag1)/count(tag2) from super_table_name interval(1d);
*/
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_COUNT && TSDB_COL_IS_TAG(pExpr->colInfo.flag)) {
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
}
}
-
+
/*
* check invalid SQL:
* select tbname, tags_fields from super_table_name interval(1s)
*/
- if (tscQueryMetricTags(pQueryInfo) && pQueryInfo->nAggTimeInterval > 0) {
+ if (tscQueryMetricTags(pQueryInfo) && pQueryInfo->intervalTime > 0) {
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
}
@@ -648,19 +655,20 @@ int32_t parseIntervalClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
}
SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
- tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE);
+ SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE);
SColumnList ids = getColumnList(1, 0, PRIMARYKEY_TIMESTAMP_COL_INDEX);
- int32_t ret = insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS].aName);
+ int32_t ret =
+ insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS].aName, pExpr);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
-
+
if (parseSlidingClause(pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
}
-
+
return TSDB_CODE_SUCCESS;
}
@@ -672,20 +680,20 @@ int32_t parseSlidingClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
SSQLToken* pSliding = &pQuerySql->sliding;
if (pSliding->n != 0) {
- getTimestampInUsFromStr(pSliding->z, pSliding->n, &pQueryInfo->nSlidingTime);
+ getTimestampInUsFromStr(pSliding->z, pSliding->n, &pQueryInfo->slidingTime);
if (pMeterMetaInfo->pMeterMeta->precision == TSDB_TIME_PRECISION_MILLI) {
- pQueryInfo->nSlidingTime /= 1000;
+ pQueryInfo->slidingTime /= 1000;
}
- if (pQueryInfo->nSlidingTime < tsMinSlidingTime) {
+ if (pQueryInfo->slidingTime < tsMinSlidingTime) {
return invalidSqlErrMsg(pQueryInfo->msg, msg0);
}
- if (pQueryInfo->nSlidingTime > pQueryInfo->nAggTimeInterval) {
+ if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) {
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
}
} else {
- pQueryInfo->nSlidingTime = -1;
+ pQueryInfo->slidingTime = pQueryInfo->intervalTime;
}
return TSDB_CODE_SUCCESS;
@@ -699,11 +707,11 @@ int32_t setMeterID(SMeterMetaInfo* pMeterMetaInfo, SSQLToken* pzTableName, SSqlO
// backup the old name in pMeterMetaInfo
size_t size = strlen(pMeterMetaInfo->name);
- char* oldName = NULL;
+ char* oldName = NULL;
if (size > 0) {
oldName = strdup(pMeterMetaInfo->name);
}
-
+
if (hasSpecifyDB(pzTableName)) {
// db has been specified in sql string so we ignore current db path
code = setObjFullName(pMeterMetaInfo->name, getAccountId(pSql), NULL, pzTableName, NULL);
@@ -722,7 +730,7 @@ int32_t setMeterID(SMeterMetaInfo* pMeterMetaInfo, SSQLToken* pzTableName, SSqlO
free(oldName);
return code;
}
-
+
/*
* the old name exists and is not equalled to the new name. Release the metermeta/metricmeta
* that are corresponding to the old name for the new table name.
@@ -734,7 +742,7 @@ int32_t setMeterID(SMeterMetaInfo* pMeterMetaInfo, SSQLToken* pzTableName, SSqlO
} else {
assert(pMeterMetaInfo->pMeterMeta == NULL && pMeterMetaInfo->pMetricMeta == NULL);
}
-
+
tfree(oldName);
return TSDB_CODE_SUCCESS;
}
@@ -881,7 +889,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) {
const char* msg6 = "invalid data type in tags";
assert(pCmd->numOfClause == 1);
-
+
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
STableMeta* pMeterMeta = pMeterMetaInfo->pMeterMeta;
@@ -1099,11 +1107,11 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
const char* msg3 = "not support query expression";
const char* msg4 = "columns from different table mixed up in arithmetic expression";
const char* msg5 = "invalid function name";
-
+
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex);
for (int32_t i = 0; i < pSelection->nExpr; ++i) {
- int32_t outputIndex = pQueryInfo->fieldsInfo.numOfOutputCols;
+ int32_t outputIndex = pQueryInfo->exprsInfo.numOfExprs;
tSQLExprItem* pItem = &pSelection->a[i];
// project on all fields
@@ -1115,7 +1123,6 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
// if the name of column is quoted, remove it and set the right information for later process
extractColumnNameFromString(pItem);
-
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
// select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2
@@ -1124,45 +1131,94 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
}
} else if (pItem->pNode->nSQLOptr >= TK_COUNT && pItem->pNode->nSQLOptr <= TK_AVG_IRATE) {
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
- if (addExprAndResultField(pQueryInfo, outputIndex, pItem) != TSDB_CODE_SUCCESS) {
+ if (addExprAndResultField(pQueryInfo, outputIndex, pItem, true) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
}
} else if (pItem->pNode->nSQLOptr >= TK_PLUS && pItem->pNode->nSQLOptr <= TK_REM) {
- // arithmetic function in select
+ // arithmetic function in select clause
SColumnList columnList = {0};
- if (validateArithmeticSQLExpr(pItem->pNode, pQueryInfo, &columnList) != TSDB_CODE_SUCCESS) {
+ int32_t arithmeticType = NON_ARITHMEIC_EXPR;
+
+ if (validateArithmeticSQLExpr(pItem->pNode, pQueryInfo, &columnList, &arithmeticType) != 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;
-
- if (buildArithmeticExprString(pItem->pNode, &p) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_INVALID_SQL;
- }
-
- // expr string is set as the parameter of function
- 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), index.tableIndex);
-
- /* todo alias name should use the original sql string */
- if (pItem->aliasName != NULL) {
- strncpy(pExpr->aliasName, pItem->aliasName, TSDB_COL_NAME_LEN);
+
+ if (arithmeticType == NORMAL_ARITHMETIC) {
+ pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
+
+ // all columns in arithmetic expression must belong to the same table
+ for (int32_t f = 1; f < columnList.num; ++f) {
+ if (columnList.ids[f].tableIndex != tableIndex) {
+ return invalidSqlErrMsg(pQueryInfo->msg, msg4);
+ }
+ }
+
+ if (buildArithmeticExprString(pItem->pNode, &p) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+
+ // expr string is set as the parameter of function
+ 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), index.tableIndex);
+
+ /* todo alias name should use the original sql string */
+ char* name = (pItem->aliasName != NULL)? pItem->aliasName:arithmeticExprStr;
+ strncpy(pExpr->aliasName, name, TSDB_COL_NAME_LEN);
+
+ insertResultField(pQueryInfo, i, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName, pExpr);
} else {
- strncpy(pExpr->aliasName, arithmeticExprStr, TSDB_COL_NAME_LEN);
+ columnList.num = 0;
+ columnList.ids[0] = (SColumnIndex) {0, 0};
+
+ insertResultField(pQueryInfo, i, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, "abc", NULL);
+
+ int32_t slot = tscNumOfFields(pQueryInfo) - 1;
+
+ if (pQueryInfo->fieldsInfo.pExpr[slot] == NULL) {
+ SSqlFunctionExpr* pFuncExpr = calloc(1, sizeof(SSqlFunctionExpr));
+ tscFieldInfoSetBinExpr(&pQueryInfo->fieldsInfo, slot, pFuncExpr);
+
+ // arithmetic expression always return result in the format of double float
+ pFuncExpr->resBytes = sizeof(double);
+ pFuncExpr->interResBytes = sizeof(double);
+ pFuncExpr->resType = TSDB_DATA_TYPE_DOUBLE;
+
+ SSqlBinaryExprInfo* pBinExprInfo = &pFuncExpr->pBinExprInfo;
+
+ tSQLSyntaxNode* pNode = NULL;
+ SColIndexEx* pColIndex = NULL;
+
+ int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pNode, pItem->pNode, &pBinExprInfo->numOfCols, &pColIndex, &pQueryInfo->exprsInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ tSQLBinaryExprDestroy(&pNode->pExpr, NULL);
+ return invalidSqlErrMsg(pQueryInfo->msg, "invalid expression in select clause");
+ }
+
+ pBinExprInfo->pBinExpr = pNode->pExpr;
+ pBinExprInfo->pReqColumns = pColIndex;
+
+ for(int32_t k = 0; k < pBinExprInfo->numOfCols; ++k) {
+ SColIndexEx* pCol = &pBinExprInfo->pReqColumns[k];
+ for(int32_t f = 0; f < pQueryInfo->exprsInfo.numOfExprs; ++f) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, f);
+ if (strcmp(pExpr->aliasName, pCol->name) == 0) {
+ pCol->colIdxInBuf = f;
+ break;
+ }
+ }
+
+ assert(pCol->colIdxInBuf >= 0 && pCol->colIdxInBuf < pQueryInfo->exprsInfo.numOfExprs);
+ tfree(pNode);
+ }
+ }
}
-
- insertResultField(pQueryInfo, i, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName);
} else {
/*
* not support such expression
@@ -1184,7 +1240,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
pQueryInfo->type |= TSDB_QUERY_TYPE_STABLE_QUERY;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
- if (tscQueryMetricTags(pQueryInfo)) { // local handle the metric tag query
+ if (tscQueryMetricTags(pQueryInfo)) { // local handle the metric tag query
pCmd->count = pMeterMetaInfo->pMeterMeta->numOfColumns; // the number of meter schema, tricky.
pQueryInfo->command = TSDB_SQL_RETRIEVE_TAGS;
}
@@ -1203,13 +1259,15 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
return TSDB_CODE_SUCCESS;
}
-int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes, int8_t type,
- char* fieldName) {
+int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnList* pIdList, int16_t bytes,
+ int8_t type, char* fieldName, SSqlExpr* pSqlExpr) {
for (int32_t i = 0; i < pIdList->num; ++i) {
tscColumnBaseInfoInsert(pQueryInfo, &(pIdList->ids[i]));
}
tscFieldInfoSetValue(&pQueryInfo->fieldsInfo, outputIndex, type, fieldName, bytes);
+ tscFieldInfoSetExpr(&pQueryInfo->fieldsInfo, outputIndex, pSqlExpr);
+
return TSDB_CODE_SUCCESS;
}
@@ -1272,7 +1330,8 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn
SSchema* pSchema = tsGetColumnSchema(pMeterMeta, pIndex->columnIndex);
char* colName = (pItem->aliasName == NULL) ? pSchema->name : pItem->aliasName;
-
+ strncpy(pExpr->aliasName, colName, tListLen(pExpr->aliasName));
+
SColumnList ids = {0};
ids.num = 1;
ids.ids[0] = *pIndex;
@@ -1281,7 +1340,7 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn
ids.num = 0;
}
- insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, pExpr->resType, colName);
+ insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr);
}
void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId,
@@ -1294,7 +1353,7 @@ void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex
ids.num = 0;
}
- insertResultField(pQueryInfo, outputColIndex, &ids, pColSchema->bytes, pColSchema->type, pColSchema->name);
+ insertResultField(pQueryInfo, outputColIndex, &ids, pColSchema->bytes, pColSchema->type, pColSchema->name, pExpr);
pExpr->colInfo.flag = flag;
if (TSDB_COL_IS_TAG(flag)) {
@@ -1316,7 +1375,8 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum
}
for (int32_t j = 0; j < numOfTotalColumns; ++j) {
- doAddProjectCol(pQueryInfo, startPos + j, j, pIndex->tableIndex);
+ SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos + j, j, pIndex->tableIndex);
+ strncpy(pExpr->aliasName, pSchema[j].name, tListLen(pExpr->aliasName));
pIndex->columnIndex = j;
SColumnList ids = {0};
@@ -1325,7 +1385,7 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum
// tag columns do not add to source list
ids.num = (j >= pMeterMeta->numOfColumns) ? 0 : 1;
- insertResultField(pQueryInfo, startPos + j, &ids, pSchema[j].bytes, pSchema[j].type, pSchema[j].name);
+ insertResultField(pQueryInfo, startPos + j, &ids, pSchema[j].bytes, pSchema[j].type, pSchema[j].name, pExpr);
}
return numOfTotalColumns;
@@ -1335,7 +1395,7 @@ int32_t addProjectionExprAndResultField(SQueryInfo* pQueryInfo, tSQLExprItem* pI
const char* msg0 = "invalid column name";
const char* msg1 = "tag for table query is not allowed";
- int32_t startPos = pQueryInfo->fieldsInfo.numOfOutputCols;
+ int32_t startPos = pQueryInfo->exprsInfo.numOfExprs;
if (pItem->pNode->nSQLOptr == TK_ALL) { // project on all fields
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
@@ -1411,9 +1471,10 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema,
} else {
getRevisedName(columnName, functionID, TSDB_COL_NAME_LEN, pSchema[pColIndex->columnIndex].name);
}
-
- tscSqlExprInsert(pQueryInfo, resColIdx, functionID, pColIndex, type, bytes, bytes);
-
+
+ SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, resColIdx, functionID, pColIndex, type, bytes, bytes);
+ strncpy(pExpr->aliasName, columnName, tListLen(pExpr->aliasName));
+
// for point interpolation/last_row query, we need the timestamp column to be loaded
SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
if (functionID == TSDB_FUNC_INTERP || functionID == TSDB_FUNC_LAST_ROW) {
@@ -1421,12 +1482,12 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema,
}
SColumnList ids = getColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex);
- insertResultField(pQueryInfo, resColIdx, &ids, bytes, type, columnName);
+ insertResultField(pQueryInfo, resColIdx, &ids, bytes, type, columnName, pExpr);
return TSDB_CODE_SUCCESS;
}
-int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprItem* pItem) {
+int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprItem* pItem, bool finalResult) {
SMeterMetaInfo* pMeterMetaInfo = NULL;
int32_t optr = pItem->pNode->nSQLOptr;
@@ -1449,6 +1510,7 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
return TSDB_CODE_INVALID_SQL;
}
+ SSqlExpr* pExpr = NULL;
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (pItem->pNode->pParam != NULL) {
@@ -1469,7 +1531,7 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
+ pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
} else {
// count the number of meters created according to the metric
if (getColumnIndexByName(pToken, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
@@ -1484,22 +1546,28 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
}
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
+ pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
}
} else { // count(*) is equalled to count(primary_timestamp_key)
index = (SColumnIndex){0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
int32_t size = tDataTypeDesc[TSDB_DATA_TYPE_BIGINT].nSize;
- tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
+ pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionID, &index, TSDB_DATA_TYPE_BIGINT, size, size);
}
-
- char columnName[TSDB_COL_NAME_LEN] = {0};
- getColumnName(pItem, columnName, TSDB_COL_NAME_LEN);
-
- // count always use the primary timestamp key column, which is 0.
+
+ memset(pExpr->aliasName, 0, tListLen(pExpr->aliasName));
+ getColumnName(pItem, pExpr->aliasName, TSDB_COL_NAME_LEN);
+
SColumnList ids = getColumnList(1, index.tableIndex, index.columnIndex);
-
- insertResultField(pQueryInfo, colIdx, &ids, sizeof(int64_t), TSDB_DATA_TYPE_BIGINT, columnName);
+ if (finalResult) {
+ int32_t numOfOutput = tscNumOfFields(pQueryInfo);
+ insertResultField(pQueryInfo, numOfOutput, &ids, sizeof(int64_t), TSDB_DATA_TYPE_BIGINT, pExpr->aliasName, pExpr);
+ } else {
+ for (int32_t i = 0; i < ids.num; ++i) {
+ tscColumnBaseInfoInsert(pQueryInfo, &(ids.ids[i]));
+ }
+ }
+
return TSDB_CODE_SUCCESS;
}
case TK_SUM:
@@ -1543,9 +1611,6 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
}
- char columnName[TSDB_COL_NAME_LEN] = {0};
- getColumnName(pItem, columnName, TSDB_COL_NAME_LEN);
-
int16_t resultType = 0;
int16_t resultSize = 0;
int16_t intermediateResSize = 0;
@@ -1564,11 +1629,11 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
if (optr == TK_DIFF) {
colIdx += 1;
SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0};
- tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
+ SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE,
TSDB_KEYSIZE);
SColumnList ids = getColumnList(1, 0, 0);
- insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS_DUMMY].aName);
+ insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS_DUMMY].aName, pExpr);
}
// functions can not be applied to tags
@@ -1598,8 +1663,18 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
SColumnList ids = {0};
ids.num = 1;
ids.ids[0] = index;
-
- insertResultField(pQueryInfo, colIdx, &ids, pExpr->resBytes, pExpr->resType, columnName);
+
+ memset(pExpr->aliasName, 0, tListLen(pExpr->aliasName));
+ getColumnName(pItem, pExpr->aliasName, TSDB_COL_NAME_LEN);
+
+ if (finalResult) {
+ int32_t numOfOutput = tscNumOfFields(pQueryInfo);
+ insertResultField(pQueryInfo, numOfOutput, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr);
+ } else {
+ for (int32_t i = 0; i < ids.num; ++i) {
+ tscColumnBaseInfoInsert(pQueryInfo, &(ids.ids[i]));
+ }
+ }
return TSDB_CODE_SUCCESS;
}
@@ -1701,10 +1776,7 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
if (pParamElem->pNode->nSQLOptr != TK_ID) {
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
}
-
- char columnName[TSDB_COL_NAME_LEN] = {0};
- getColumnName(pItem, columnName, TSDB_COL_NAME_LEN);
-
+
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
if (getColumnIndexByName(&pParamElem->pNode->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
@@ -1735,7 +1807,8 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
int16_t resultSize = pSchema[index.columnIndex].bytes;
char val[8] = {0};
- int32_t numOfAddedColumn = 1;
+ SSqlExpr* pExpr = NULL;
+
if (optr == TK_PERCENTILE || optr == TK_APERCENTILE) {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_DOUBLE);
@@ -1757,7 +1830,7 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
return TSDB_CODE_INVALID_SQL;
}
- SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionId, &index, resultType, resultSize, resultSize);
+ pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionId, &index, resultType, resultSize, resultSize);
addExprParams(pExpr, val, TSDB_DATA_TYPE_DOUBLE, sizeof(double), 0);
} else {
tVariantDump(pVariant, val, TSDB_DATA_TYPE_BIGINT);
@@ -1774,22 +1847,30 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIdx, tSQLExprIt
// set the first column ts for top/bottom query
SColumnIndex index1 = {0, PRIMARYKEY_TIMESTAMP_COL_INDEX};
- tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE);
+ pExpr = tscSqlExprInsert(pQueryInfo, 0, TSDB_FUNC_TS, &index1, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE);
const int32_t TS_COLUMN_INDEX = 0;
SColumnList ids = getColumnList(1, 0, TS_COLUMN_INDEX);
insertResultField(pQueryInfo, TS_COLUMN_INDEX, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP,
- aAggs[TSDB_FUNC_TS].aName);
+ aAggs[TSDB_FUNC_TS].aName, pExpr);
colIdx += 1; // the first column is ts
- numOfAddedColumn += 1;
- SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionId, &index, resultType, resultSize, resultSize);
+ pExpr = tscSqlExprInsert(pQueryInfo, colIdx, functionId, &index, resultType, resultSize, resultSize);
addExprParams(pExpr, val, TSDB_DATA_TYPE_BIGINT, sizeof(int64_t), 0);
}
-
+
+ memset(pExpr->aliasName, 0, tListLen(pExpr->aliasName));
+ getColumnName(pItem, pExpr->aliasName, TSDB_COL_NAME_LEN);
+
SColumnList ids = getColumnList(1, 0, index.columnIndex);
- insertResultField(pQueryInfo, colIdx, &ids, resultSize, resultType, columnName);
+ if (finalResult) {
+ insertResultField(pQueryInfo, colIdx, &ids, resultSize, resultType, pExpr->aliasName, pExpr);
+ } else {
+ for (int32_t i = 0; i < ids.num; ++i) {
+ tscColumnBaseInfoInsert(pQueryInfo, &(ids.ids[i]));
+ }
+ }
return TSDB_CODE_SUCCESS;
}
@@ -2036,7 +2117,7 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
SSqlCmd* pCmd = &pSql->cmd;
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
assert(pCmd->numOfClause == 1);
-
+
pCmd->command = TSDB_SQL_SHOW;
const char* msg1 = "invalid name";
@@ -2166,16 +2247,17 @@ int32_t tscTansformSQLFunctionForSTableQuery(SQueryInfo* pQueryInfo) {
int16_t type = 0;
int16_t intermediateBytes = 0;
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, k);
- TAOS_FIELD* pField = tscFieldInfoGetField(pQueryInfo, k);
-
int16_t functionId = aAggs[pExpr->functionId].stableFuncId;
+ int32_t colIndex = pExpr->colInfo.colIdx;
+ SSchema* pSrcSchema = tsGetColumnSchema(pMeterMetaInfo->pMeterMeta, colIndex);
+
if ((functionId >= TSDB_FUNC_SUM && functionId <= TSDB_FUNC_TWA) ||
(functionId >= TSDB_FUNC_FIRST_DST && functionId <= TSDB_FUNC_LAST_DST) ||
(functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) {
- if (getResultDataInfo(pField->type, pField->bytes, functionId, pExpr->param[0].i64Key, &type, &bytes,
+ if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, pExpr->param[0].i64Key, &type, &bytes,
&intermediateBytes, 0, true) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
}
@@ -2197,15 +2279,31 @@ void tscRestoreSQLFunctionForMetricQuery(SQueryInfo* pQueryInfo) {
return;
}
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
- TAOS_FIELD* pField = tscFieldInfoGetField(pQueryInfo, i);
-
- if ((pExpr->functionId >= TSDB_FUNC_FIRST_DST && pExpr->functionId <= TSDB_FUNC_LAST_DST) ||
- (pExpr->functionId >= TSDB_FUNC_SUM && pExpr->functionId <= TSDB_FUNC_MAX)) {
- pExpr->resBytes = pField->bytes;
- pExpr->resType = pField->type;
- }
+ SSchema* pSchema = tsGetColumnSchema(pMeterMetaInfo->pMeterMeta, pExpr->colInfo.colIdx);
+
+// if (/*(pExpr->functionId >= TSDB_FUNC_FIRST_DST && pExpr->functionId <= TSDB_FUNC_LAST_DST) ||
+// (pExpr->functionId >= TSDB_FUNC_SUM && pExpr->functionId <= TSDB_FUNC_MAX) ||
+// pExpr->functionId == TSDB_FUNC_LAST_ROW*/) {
+ // the final result size and type in the same as query on single table.
+ // so here, set the flag to be false;
+ int16_t inter = 0;
+
+ int32_t functionId = pExpr->functionId;
+ if (functionId >= TSDB_FUNC_TS && functionId <= TSDB_FUNC_DIFF) {
+ continue;
+ }
+
+ if (functionId == TSDB_FUNC_FIRST_DST) {
+ functionId = TSDB_FUNC_FIRST;
+ } else if (functionId == TSDB_FUNC_LAST_DST) {
+ functionId = TSDB_FUNC_LAST;
+ }
+
+ getResultDataInfo(pSchema->type, pSchema->bytes, functionId, 0, &pExpr->resType, &pExpr->resBytes,
+ &inter, 0, false);
+// }
}
}
@@ -2213,9 +2311,9 @@ bool hasUnsupportFunctionsForSTableQuery(SQueryInfo* pQueryInfo) {
const char* msg1 = "TWA not allowed to apply to super table directly";
const char* msg2 = "TWA only support group by tbname for super table query";
const char* msg3 = "function not support for super table query";
-
+
// filter sql function not supported by metric query yet.
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
int32_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
if ((aAggs[functionId].nStatus & TSDB_FUNCSTATE_METRIC) == 0) {
invalidSqlErrMsg(pQueryInfo->msg, msg3);
@@ -2252,7 +2350,7 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo) {
// diff function cannot be executed with other function
// arithmetic function can be executed with other arithmetic functions
- for (int32_t i = startIdx + 1; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = startIdx + 1; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
int16_t functionId = pExpr->functionId;
@@ -2554,7 +2652,13 @@ static int32_t tSQLExprNodeToString(tSQLExpr* pExpr, char** str) {
} else if (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_STRING) { // value
*str += tVariantToString(&pExpr->val, *str);
- } else {
+ } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) {
+ /*
+ * arithmetic expression of aggregation, such as count(ts) + count(ts) *2
+ */
+ strncpy(*str, pExpr->operand.z, pExpr->operand.n);
+ *str += pExpr->operand.n;
+ } else { // not supported operation
assert(false);
}
@@ -2890,8 +2994,7 @@ int32_t buildArithmeticExprString(tSQLExpr* pExpr, char** exprString) {
tSQLExpr* pLeft = pExpr->pLeft;
tSQLExpr* pRight = pExpr->pRight;
- *(*exprString) = '(';
- *exprString += 1;
+ *(*exprString)++ = '(';
if (pLeft->nSQLOptr >= TK_PLUS && pLeft->nSQLOptr <= TK_REM) {
buildArithmeticExprString(pLeft, exprString);
@@ -2913,50 +3016,67 @@ int32_t buildArithmeticExprString(tSQLExpr* pExpr, char** exprString) {
}
}
- *(*exprString) = ')';
- *exprString += 1;
+ *(*exprString)++ = ')';
return TSDB_CODE_SUCCESS;
}
-static int32_t validateSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList) {
+static int32_t validateSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
if (pExpr->nSQLOptr == TK_ID) {
- SColumnIndex index = COLUMN_INDEX_INITIALIZER;
- if (getColumnIndexByName(&pExpr->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
- return TSDB_CODE_INVALID_SQL;
- }
+ if (*type == NON_ARITHMEIC_EXPR) {
+ *type = NORMAL_ARITHMETIC;
+ } else if (*type == AGG_ARIGHTMEIC) {
+ return TSDB_CODE_INVALID_SQL;
+ }
- // if column is timestamp, bool, binary, nchar, not support arithmetic, so return invalid sql
- STableMeta* pMeterMeta = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, index.tableIndex)->pMeterMeta;
- SSchema* pSchema = tsGetSchema(pMeterMeta) + index.columnIndex;
- if ((pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) || (pSchema->type == TSDB_DATA_TYPE_BOOL)
- || (pSchema->type == TSDB_DATA_TYPE_BINARY) || (pSchema->type == TSDB_DATA_TYPE_NCHAR)){
- return TSDB_CODE_INVALID_SQL;
- }
-
- pList->ids[pList->num++] = index;
+ SColumnIndex index = COLUMN_INDEX_INITIALIZER;
+ if (getColumnIndexByName(&pExpr->colInfo, pQueryInfo, &index) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+
+ // if column is timestamp, bool, binary, nchar, not support arithmetic, so return invalid sql
+ STableMeta* pMeterMeta = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, index.tableIndex)->pMeterMeta;
+ SSchema* pSchema = tsGetSchema(pMeterMeta) + index.columnIndex;
+ if ((pSchema->type == TSDB_DATA_TYPE_TIMESTAMP) || (pSchema->type == TSDB_DATA_TYPE_BOOL) ||
+ (pSchema->type == TSDB_DATA_TYPE_BINARY) || (pSchema->type == TSDB_DATA_TYPE_NCHAR)) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+
+ 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_AVG_IRATE) {
- return TSDB_CODE_INVALID_SQL;
+ } else if (pExpr->nSQLOptr >= TK_COUNT && pExpr->nSQLOptr <= TK_AVG_IRATE) {
+ if (*type == NON_ARITHMEIC_EXPR) {
+ *type = AGG_ARIGHTMEIC;
+ } else if (*type == NORMAL_ARITHMETIC) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+
+ int32_t outputIndex = pQueryInfo->exprsInfo.numOfExprs;
+ tSQLExprItem item = {.pNode = pExpr, .aliasName = NULL};
+
+ // sql function in selection clause, append sql function info in pSqlCmd structure sequentially
+ if (addExprAndResultField(pQueryInfo, outputIndex, &item, false) != TSDB_CODE_SUCCESS) {
+ return TSDB_CODE_INVALID_SQL;
+ }
}
return TSDB_CODE_SUCCESS;
}
-static int32_t validateArithmeticSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList) {
+static int32_t validateArithmeticSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
if (pExpr == NULL) {
return TSDB_CODE_SUCCESS;
}
tSQLExpr* pLeft = pExpr->pLeft;
if (pLeft->nSQLOptr >= TK_PLUS && pLeft->nSQLOptr <= TK_REM) {
- int32_t ret = validateArithmeticSQLExpr(pLeft, pQueryInfo, pList);
+ int32_t ret = validateArithmeticSQLExpr(pLeft, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
} else {
- int32_t ret = validateSQLExpr(pLeft, pQueryInfo, pList);
+ int32_t ret = validateSQLExpr(pLeft, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
@@ -2964,12 +3084,12 @@ static int32_t validateArithmeticSQLExpr(tSQLExpr* pExpr, SQueryInfo* pQueryInfo
tSQLExpr* pRight = pExpr->pRight;
if (pRight->nSQLOptr >= TK_PLUS && pRight->nSQLOptr <= TK_REM) {
- int32_t ret = validateArithmeticSQLExpr(pRight, pQueryInfo, pList);
+ int32_t ret = validateArithmeticSQLExpr(pRight, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
} else {
- int32_t ret = validateSQLExpr(pRight, pQueryInfo, pList);
+ int32_t ret = validateSQLExpr(pRight, pQueryInfo, pList, type);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
@@ -3771,6 +3891,7 @@ int32_t getTimeRange(int64_t* stime, int64_t* etime, tSQLExpr* pRight, int32_t o
return TSDB_CODE_SUCCESS;
}
+// todo error !!!!
int32_t tsRewriteFieldNameIfNecessary(SQueryInfo* pQueryInfo) {
const char rep[] = {'(', ')', '*', ',', '.', '/', '\\', '+', '-', '%', ' '};
@@ -3817,7 +3938,7 @@ int32_t parseFillClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
}
if (pQueryInfo->defaultVal == NULL) {
- pQueryInfo->defaultVal = calloc(pQueryInfo->fieldsInfo.numOfOutputCols, sizeof(int64_t));
+ pQueryInfo->defaultVal = calloc(pQueryInfo->exprsInfo.numOfExprs, sizeof(int64_t));
if (pQueryInfo->defaultVal == NULL) {
return TSDB_CODE_CLI_OUT_OF_MEMORY;
}
@@ -3827,7 +3948,7 @@ int32_t parseFillClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
pQueryInfo->interpoType = TSDB_INTERPO_NONE;
} else if (strncasecmp(pItem->pVar.pz, "null", 4) == 0 && pItem->pVar.nLen == 4) {
pQueryInfo->interpoType = TSDB_INTERPO_NULL;
- for (int32_t i = START_INTERPO_COL_IDX; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = START_INTERPO_COL_IDX; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
TAOS_FIELD* pFields = tscFieldInfoGetField(pQueryInfo, i);
setNull((char*)&pQueryInfo->defaultVal[i], pFields->type, pFields->bytes);
}
@@ -3849,12 +3970,12 @@ int32_t parseFillClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
if (tscIsPointInterpQuery(pQueryInfo)) {
startPos = 0;
- if (numOfFillVal > pQueryInfo->fieldsInfo.numOfOutputCols) {
- numOfFillVal = pQueryInfo->fieldsInfo.numOfOutputCols;
+ if (numOfFillVal > pQueryInfo->exprsInfo.numOfExprs) {
+ numOfFillVal = pQueryInfo->exprsInfo.numOfExprs;
}
} else {
- numOfFillVal = (pFillToken->nExpr > pQueryInfo->fieldsInfo.numOfOutputCols)
- ? pQueryInfo->fieldsInfo.numOfOutputCols
+ numOfFillVal = (pFillToken->nExpr > pQueryInfo->exprsInfo.numOfExprs)
+ ? pQueryInfo->exprsInfo.numOfExprs
: pFillToken->nExpr;
}
@@ -3862,28 +3983,29 @@ int32_t parseFillClause(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySQL) {
for (int32_t i = startPos; i < numOfFillVal; ++i, ++j) {
TAOS_FIELD* pFields = tscFieldInfoGetField(pQueryInfo, i);
-
+
if (pFields->type == TSDB_DATA_TYPE_BINARY || pFields->type == TSDB_DATA_TYPE_NCHAR) {
setNull((char*)(&pQueryInfo->defaultVal[i]), pFields->type, pFields->bytes);
continue;
}
-
+
int32_t ret = tVariantDump(&pFillToken->a[j].pVar, (char*)&pQueryInfo->defaultVal[i], pFields->type);
if (ret != TSDB_CODE_SUCCESS) {
return invalidSqlErrMsg(pQueryInfo->msg, msg);
}
}
- if ((pFillToken->nExpr < pQueryInfo->fieldsInfo.numOfOutputCols) ||
- ((pFillToken->nExpr - 1 < pQueryInfo->fieldsInfo.numOfOutputCols) && (tscIsPointInterpQuery(pQueryInfo)))) {
+ if ((pFillToken->nExpr < pQueryInfo->exprsInfo.numOfExprs) ||
+ ((pFillToken->nExpr - 1 < pQueryInfo->exprsInfo.numOfExprs) && (tscIsPointInterpQuery(pQueryInfo)))) {
tVariantListItem* lastItem = &pFillToken->a[pFillToken->nExpr - 1];
- for (int32_t i = numOfFillVal; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = numOfFillVal; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
TAOS_FIELD* pFields = tscFieldInfoGetField(pQueryInfo, i);
- tVariantDump(&lastItem->pVar, (char*)&pQueryInfo->defaultVal[i], pFields->type);
if (pFields->type == TSDB_DATA_TYPE_BINARY || pFields->type == TSDB_DATA_TYPE_NCHAR) {
setNull((char*)(&pQueryInfo->defaultVal[i]), pFields->type, pFields->bytes);
+ } else {
+ tVariantDump(&lastItem->pVar, (char*)&pQueryInfo->defaultVal[i], pFields->type);
}
}
}
@@ -4277,11 +4399,11 @@ int32_t validateSqlFunctionInStreamSql(SQueryInfo* pQueryInfo) {
const char* msg0 = "sample interval can not be less than 10ms.";
const char* msg1 = "functions not allowed in select clause";
- if (pQueryInfo->nAggTimeInterval != 0 && pQueryInfo->nAggTimeInterval < 10) {
+ if (pQueryInfo->intervalTime != 0 && pQueryInfo->intervalTime < 10) {
return invalidSqlErrMsg(pQueryInfo->msg, msg0);
}
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
int32_t functId = tscSqlExprGet(pQueryInfo, i)->functionId;
if (!IS_STREAM_QUERY_VALID(aAggs[functId].nStatus)) {
return invalidSqlErrMsg(pQueryInfo->msg, msg1);
@@ -4296,13 +4418,13 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SQueryInfo* pQueryInfo) {
const char* msg1 = "column projection is not compatible with interval";
// multi-output set/ todo refactor
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, k);
// projection query on primary timestamp, the selectivity function needs to be present.
if (pExpr->functionId == TSDB_FUNC_PRJ && pExpr->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
bool hasSelectivity = false;
- for (int32_t j = 0; j < pQueryInfo->fieldsInfo.numOfOutputCols; ++j) {
+ for (int32_t j = 0; j < pQueryInfo->exprsInfo.numOfExprs; ++j) {
SSqlExpr* pEx = tscSqlExprGet(pQueryInfo, j);
if ((aAggs[pEx->functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) == TSDB_FUNCSTATE_SELECTIVITY) {
hasSelectivity = true;
@@ -4470,13 +4592,15 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
const char* msg1 = "slimit/soffset only available for STable query";
const char* msg2 = "function not supported on table";
const char* msg3 = "slimit/soffset can not apply to projection query";
-
+
// handle the limit offset value, validate the limit
pQueryInfo->limit = pQuerySql->limit;
pQueryInfo->clauseLimit = pQueryInfo->limit.limit;
-
pQueryInfo->slimit = pQuerySql->slimit;
-
+
+ tscTrace("%p limit:%d, offset:%" PRId64 " slimit:%d, soffset:%" PRId64, pSql, pQueryInfo->limit.limit,
+ pQueryInfo->limit.offset, pQueryInfo->slimit.limit, pQueryInfo->slimit.offset);
+
if (pQueryInfo->slimit.offset < 0 || pQueryInfo->limit.offset < 0) {
return invalidSqlErrMsg(pQueryInfo->msg, msg0);
}
@@ -4500,24 +4624,16 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
if (pQueryInfo->slimit.limit > 0 || pQueryInfo->slimit.offset > 0) {
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
}
-
+
+ // for projection query on super table, all queries are subqueries
if (tscNonOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
-// if (pQueryInfo->order.orderColId >= 0) {
-// if (pQueryInfo->limit.limit == -1) {
-// return invalidSqlErrMsg(pQueryInfo->msg, msg4);
-// } else if (pQueryInfo->limit.limit > 10000) { // the result set can not be larger than 10000
-// //todo use global config parameter
-// return invalidSqlErrMsg(pQueryInfo->msg, msg5);
-// }
-// }
-
- pQueryInfo->type |= TSDB_QUERY_TYPE_SUBQUERY; // for projection query on super table, all queries are subqueries
+ pQueryInfo->type |= TSDB_QUERY_TYPE_SUBQUERY;
}
}
}
if (pQueryInfo->slimit.limit == 0) {
- tscTrace("%p limit 0, no output result", pSql);
+ tscTrace("%p slimit 0, no output result", pSql);
pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
return TSDB_CODE_SUCCESS;
}
@@ -4543,7 +4659,7 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
// keep original limitation value in globalLimit
pQueryInfo->clauseLimit = pQueryInfo->limit.limit;
pQueryInfo->prjOffset = pQueryInfo->limit.offset;
-
+
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
/*
* the limitation/offset value should be removed during retrieve data from virtual node,
@@ -4553,7 +4669,7 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
if (pQueryInfo->limit.limit > 0) {
pQueryInfo->limit.limit = -1;
}
-
+
pQueryInfo->limit.offset = 0;
}
} else {
@@ -4562,7 +4678,7 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL*
}
// filter the query functions operating on "tbname" column that are not supported by normal columns.
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->colInfo.colIdx == TSDB_TBNAME_COLUMN_INDEX) {
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
@@ -4677,7 +4793,7 @@ void tscAddTimestampColumn(SQueryInfo* pQueryInfo, int16_t functionId, int16_t t
// NOTE: tag column does not add to source column list
SColumnList ids = getColumnList(1, tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX);
- insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, "ts");
+ insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, "ts", pExpr);
}
}
@@ -4700,13 +4816,13 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau
int16_t bytes = pSchema[index.columnIndex].bytes;
char* name = pSchema[index.columnIndex].name;
- pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, TSDB_FUNC_TAG, &index, type, bytes,
+ pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs, TSDB_FUNC_TAG, &index, type, bytes,
bytes);
pExpr->colInfo.flag = TSDB_COL_TAG;
// NOTE: tag column does not add to source column list
SColumnList ids = {0};
- insertResultField(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, &ids, bytes, type, name);
+ insertResultField(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs, &ids, bytes, type, name, pExpr);
int32_t relIndex = index.columnIndex;
@@ -4721,7 +4837,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau
// limit the output to be 1 for each state value
static void doLimitOutputNormalColOfGroupby(SSqlExpr* pExpr) {
int32_t outputRow = 1;
- tVariantCreateFromBinary(&pExpr->param[0], (char*) &outputRow, sizeof(int32_t), TSDB_DATA_TYPE_INT);
+ tVariantCreateFromBinary(&pExpr->param[0], (char*)&outputRow, sizeof(int32_t), TSDB_DATA_TYPE_INT);
pExpr->numOfParams = 1;
}
@@ -4733,25 +4849,25 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) {
SSchema* pSchema = tsGetColumnSchema(pMeterMetaInfo->pMeterMeta, index);
SColumnIndex colIndex = {.tableIndex = 0, .columnIndex = index};
- SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, TSDB_FUNC_PRJ, &colIndex,
+ SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs, TSDB_FUNC_PRJ, &colIndex,
pSchema->type, pSchema->bytes, pSchema->bytes);
pExpr->colInfo.flag = TSDB_COL_NORMAL;
doLimitOutputNormalColOfGroupby(pExpr);
-
+
// NOTE: tag column does not add to source column list
SColumnList list = {0};
list.num = 1;
list.ids[0] = colIndex;
- insertResultField(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, &list, pSchema->bytes, pSchema->type,
- pSchema->name);
- tscFieldInfoUpdateVisible(&pQueryInfo->fieldsInfo, pQueryInfo->fieldsInfo.numOfOutputCols - 1, false);
+ insertResultField(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs - 1, &list, pSchema->bytes, pSchema->type,
+ pSchema->name, pExpr);
+ tscFieldInfoUpdateVisible(&pQueryInfo->fieldsInfo, pQueryInfo->exprsInfo.numOfExprs - 1, false);
}
static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
int32_t tagLength = 0;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_TAGPRJ || pExpr->functionId == TSDB_FUNC_TAG) {
pExpr->functionId = TSDB_FUNC_TAG_DUMMY;
@@ -4765,7 +4881,7 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
SSchema* pSchema = tsGetSchema(pMeterMetaInfo->pMeterMeta);
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId != TSDB_FUNC_TAG_DUMMY && pExpr->functionId != TSDB_FUNC_TS_DUMMY) {
SSchema* pColSchema = &pSchema[pExpr->colInfo.colIdx];
@@ -4776,7 +4892,7 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
}
static void doUpdateSqlFunctionForColPrj(SQueryInfo* pQueryInfo) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_PRJ) {
bool qualifiedCol = false;
@@ -4808,7 +4924,7 @@ static bool onlyTagPrjFunction(SQueryInfo* pQueryInfo) {
bool hasTagPrj = false;
bool hasColumnPrj = false;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_PRJ) {
hasColumnPrj = true;
@@ -4824,7 +4940,7 @@ static bool onlyTagPrjFunction(SQueryInfo* pQueryInfo) {
static bool allTagPrjInGroupby(SQueryInfo* pQueryInfo) {
bool allInGroupby = true;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId != TSDB_FUNC_TAGPRJ) {
continue;
@@ -4841,7 +4957,7 @@ static bool allTagPrjInGroupby(SQueryInfo* pQueryInfo) {
}
static void updateTagPrjFunction(SQueryInfo* pQueryInfo) {
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_TAGPRJ) {
pExpr->functionId = TSDB_FUNC_TAG;
@@ -4863,7 +4979,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo) {
int16_t numOfSelectivity = 0;
int16_t numOfAggregation = 0;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_TAGPRJ ||
(pExpr->functionId == TSDB_FUNC_PRJ && pExpr->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
@@ -4872,7 +4988,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo) {
}
}
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
int16_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TS ||
functionId == TSDB_FUNC_ARITHM) {
@@ -4904,7 +5020,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo) {
* If more than one selectivity functions exist, all the selectivity functions must be last_row.
* Otherwise, return with error code.
*/
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
int16_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
if (functionId == TSDB_FUNC_TAGPRJ) {
continue;
@@ -4965,22 +5081,22 @@ static int32_t doAddGroupbyColumnsOnDemand(SQueryInfo* pQueryInfo) {
if (TSDB_COL_IS_TAG(pColIndex->flag)) {
SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex};
- SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, TSDB_FUNC_TAG, &index,
+ SSqlExpr* pExpr = tscSqlExprInsert(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs, TSDB_FUNC_TAG, &index,
type, bytes, bytes);
pExpr->colInfo.flag = TSDB_COL_TAG;
// NOTE: tag column does not add to source column list
SColumnList ids = {0};
- insertResultField(pQueryInfo, pQueryInfo->fieldsInfo.numOfOutputCols, &ids, bytes, type, name);
+ insertResultField(pQueryInfo, pQueryInfo->exprsInfo.numOfExprs-1, &ids, bytes, type, name, pExpr);
} else {
// if this query is "group by" normal column, interval is not allowed
- if (pQueryInfo->nAggTimeInterval > 0) {
+ if (pQueryInfo->intervalTime > 0) {
return invalidSqlErrMsg(pQueryInfo->msg, msg2);
}
bool hasGroupColumn = false;
- for (int32_t j = 0; j < pQueryInfo->fieldsInfo.numOfOutputCols; ++j) {
+ for (int32_t j = 0; j < pQueryInfo->exprsInfo.numOfExprs; ++j) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, j);
if (pExpr->colInfo.colId == pColIndex->colId) {
break;
@@ -5008,7 +5124,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
// only retrieve tags, group by is not supportted
if (pCmd->command == TSDB_SQL_RETRIEVE_TAGS) {
- if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->nAggTimeInterval > 0) {
+ if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->intervalTime > 0) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
} else {
return TSDB_CODE_SUCCESS;
@@ -5023,7 +5139,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
}
// check all query functions in selection clause, multi-output functions are not allowed
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
int32_t functId = pExpr->functionId;
@@ -5111,11 +5227,8 @@ int32_t doLocalQueryProcess(SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
}
SSqlExpr* pExpr1 = tscSqlExprInsertEmpty(pQueryInfo, 0, TSDB_FUNC_TAG_DUMMY);
- if (pExprList->a[0].aliasName != NULL) {
- strncpy(pExpr1->aliasName, pExprList->a[0].aliasName, tListLen(pExpr1->aliasName));
- } else {
- strncpy(pExpr1->aliasName, functionsInfo[index].name, tListLen(pExpr1->aliasName));
- }
+ const char* name = (pExprList->a[0].aliasName != NULL)? pExprList->a[0].aliasName:functionsInfo[index].name;
+ strncpy(pExpr1->aliasName, name, tListLen(pExpr1->aliasName));
switch (index) {
case 0:
@@ -5220,8 +5333,8 @@ void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex) {
}
int32_t totalBufSize = 1024;
-
- char str[1024] = {0};
+
+ char str[1024] = {0};
int32_t offset = 0;
offset += sprintf(str, "num:%d [", pQueryInfo->exprsInfo.numOfExprs);
@@ -5229,12 +5342,13 @@ void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex) {
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
char tmpBuf[1024] = {0};
- int32_t tmpLen = 0;
- tmpLen = sprintf(tmpBuf, "%s(uid:%" PRId64 ", %d)", aAggs[pExpr->functionId].aName, pExpr->uid, pExpr->colInfo.colId);
+ int32_t tmpLen = 0;
+ tmpLen =
+ sprintf(tmpBuf, "%s(uid:%" PRId64 ", %d)", aAggs[pExpr->functionId].aName, pExpr->uid, pExpr->colInfo.colId);
if (tmpLen + offset > totalBufSize) break;
offset += sprintf(str + offset, "%s", tmpBuf);
-
+
if (i < pQueryInfo->exprsInfo.numOfExprs - 1) {
str[offset++] = ',';
}
@@ -5424,7 +5538,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
if (parseIntervalClause(pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
} else {
- if ((pQueryInfo->nAggTimeInterval > 0) &&
+ if ((pQueryInfo->intervalTime > 0) &&
(validateFunctionsInIntervalOrGroupbyQuery(pQueryInfo) != TSDB_CODE_SUCCESS)) {
return TSDB_CODE_INVALID_SQL;
}
@@ -5454,7 +5568,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
* not here.
*/
if (pQuerySql->fillType != NULL) {
- if (pQueryInfo->nAggTimeInterval == 0) {
+ if (pQueryInfo->intervalTime == 0) {
return invalidSqlErrMsg(pQueryInfo->msg, msg3);
}
@@ -5493,7 +5607,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
if (pMeterMetaInfo == NULL) {
pMeterMetaInfo = tscAddEmptyMeterMetaInfo(pQueryInfo);
}
-
+
// too many result columns not support order by in query
if (pQuerySql->pSelection->nExpr > TSDB_MAX_COLUMNS) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg8);
@@ -5517,7 +5631,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
}
pQueryInfo->command = TSDB_SQL_SELECT;
-
+
// set all query tables, which are maybe more than one.
for (int32_t i = 0; i < pQuerySql->from->nExpr; ++i) {
tVariant* pTableItem = &pQuerySql->from->a[i].pVar;
@@ -5566,7 +5680,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
if (parseIntervalClause(pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
return TSDB_CODE_INVALID_SQL;
} else {
- if ((pQueryInfo->nAggTimeInterval > 0) &&
+ if ((pQueryInfo->intervalTime > 0) &&
(validateFunctionsInIntervalOrGroupbyQuery(pQueryInfo) != TSDB_CODE_SUCCESS)) {
return TSDB_CODE_INVALID_SQL;
}
@@ -5603,7 +5717,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
// no result due to invalid query time range
if (pQueryInfo->stime > pQueryInfo->etime) {
- pCmd->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
+ pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT;
return TSDB_CODE_SUCCESS;
}
@@ -5633,24 +5747,24 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
updateTagColumnIndex(pQueryInfo, i);
}
-
+
/*
* fill options are set at the end position, when all columns are set properly
* the columns may be increased due to group by operation
*/
if (pQuerySql->fillType != NULL) {
- if (pQueryInfo->nAggTimeInterval == 0 && (!tscIsPointInterpQuery(pQueryInfo))) {
+ if (pQueryInfo->intervalTime == 0 && (!tscIsPointInterpQuery(pQueryInfo))) {
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
}
-
- if (pQueryInfo->nAggTimeInterval > 0) {
+
+ if (pQueryInfo->intervalTime > 0) {
int64_t timeRange = labs(pQueryInfo->stime - pQueryInfo->etime);
// number of result is not greater than 10,000,000
- if ((timeRange == 0) || (timeRange / pQueryInfo->nAggTimeInterval) > MAX_RETRIEVE_ROWS_IN_INTERVAL_QUERY) {
+ if ((timeRange == 0) || (timeRange / pQueryInfo->intervalTime) > MAX_RETRIEVE_ROWS_IN_INTERVAL_QUERY) {
return invalidSqlErrMsg(pQueryInfo->msg, msg6);
}
}
-
+
int32_t ret = parseFillClause(pQueryInfo, pQuerySql);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
@@ -5660,7 +5774,80 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return TSDB_CODE_SUCCESS; // Does not build query message here
}
-bool hasDefaultQueryTimeRange(SQueryInfo *pQueryInfo) {
- return (pQueryInfo->stime == 0 && pQueryInfo->etime == INT64_MAX) ||
- (pQueryInfo->stime == INT64_MAX && pQueryInfo->etime == 0);
+static int32_t tSQLBinaryExprCreateFromSqlExpr(tSQLSyntaxNode **pExpr, tSQLExpr* pAst, int32_t* num,
+ SColIndexEx** pColIndex, SSqlExprInfo* pExprInfo) {
+ tSQLSyntaxNode* pLeft = NULL;
+ tSQLSyntaxNode* pRight= NULL;
+
+ if (pAst->pLeft != NULL) {
+ int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pLeft, pAst->pLeft, num, pColIndex, pExprInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (pAst->pRight != NULL) {
+ int32_t ret = tSQLBinaryExprCreateFromSqlExpr(&pRight, pAst->pRight, num, pColIndex, pExprInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (pAst->pLeft == NULL) {
+ if (pAst->nSQLOptr >= TK_TINYINT && pAst->nSQLOptr <= TK_DOUBLE) {
+ *pExpr = calloc(1, sizeof(tSQLSyntaxNode) + sizeof(tVariant));
+ (*pExpr)->nodeType = TSQL_NODE_VALUE;
+ (*pExpr)->pVal = (tVariant*) ((char*)(*pExpr) + sizeof(tSQLSyntaxNode));
+ tVariantAssign((*pExpr)->pVal, &pAst->val);
+ } else if (pAst->nSQLOptr >= TK_COUNT && pAst->nSQLOptr <= TK_AVG_IRATE) {
+ *pExpr = calloc(1, sizeof(tSQLSyntaxNode) + sizeof(SSchemaEx));
+ (*pExpr)->nodeType = TSQL_NODE_COL;
+ (*pExpr)->pSchema = (SSchema*)((char*)(*pExpr) + sizeof(tSQLSyntaxNode));
+ strncpy((*pExpr)->pSchema->name, pAst->operand.z, pAst->operand.n);
+
+ // set the input column data byte and type.
+ for (int32_t i = 0; i < pExprInfo->numOfExprs; ++i) {
+ if (strcmp((*pExpr)->pSchema->name, pExprInfo->pExprs[i]->aliasName) == 0) {
+ (*pExpr)->pSchema->type = pExprInfo->pExprs[i]->resType;
+ (*pExpr)->pSchema->bytes = pExprInfo->pExprs[i]->resBytes;
+ break;
+ }
+ }
+ } else { //todo return error
+ return TSDB_CODE_SUCCESS;
+ }
+
+ (*pExpr)->colId = -1;
+
+ *pColIndex = realloc(*pColIndex, (++(*num)) * sizeof(SColIndexEx));
+ memset(&(*pColIndex)[(*num) - 1], 0, sizeof(SColIndexEx));
+
+ strncpy((*pColIndex)[(*num) - 1].name, pAst->operand.z, pAst->operand.n);
+ } else {
+ tSQLBinaryExpr *pBinExpr = (tSQLBinaryExpr *)calloc(1, sizeof(tSQLBinaryExpr));
+ pBinExpr->filterOnPrimaryKey = false;
+ pBinExpr->pLeft = pLeft;
+ pBinExpr->pRight = pRight;
+ SSQLToken t = {.type = pAst->nSQLOptr};
+ pBinExpr->nSQLBinaryOptr = getBinaryExprOptr(&t);
+
+ assert(pBinExpr->nSQLBinaryOptr != 0);
+
+ (*pExpr) = malloc(sizeof(tSQLSyntaxNode));
+ (*pExpr)->nodeType = TSQL_NODE_EXPR;
+ (*pExpr)->pExpr = pBinExpr;
+ (*pExpr)->colId = -1;
+
+ if (pBinExpr->nSQLBinaryOptr == TSDB_BINARY_OP_DIVIDE) {
+ if (pRight->nodeType == TSQL_NODE_VALUE) {
+ if (pRight->pVal->nType == TSDB_DATA_TYPE_INT && pRight->pVal->i64Key == 0) {
+ return TSDB_CODE_INVALID_SQL;
+ } else if (pRight->pVal->nType == TSDB_DATA_TYPE_FLOAT && pRight->pVal->dKey == 0) {
+ return TSDB_CODE_INVALID_SQL;
+ }
+ }
+ }
+ }
+
+ return TSDB_CODE_SUCCESS;
}
diff --git a/src/client/src/tscSecondaryMerge.c b/src/client/src/tscSecondaryMerge.c
index ca57030539a451d4967ace21fc688a1e44ffea76..51a59005f001f7555a3ffc2e5c7e15ed111af988 100644
--- a/src/client/src/tscSecondaryMerge.c
+++ b/src/client/src/tscSecondaryMerge.c
@@ -13,10 +13,11 @@
* along with this program. If not, see .
*/
+#include "tscSecondaryMerge.h"
#include "os.h"
#include "tlosertree.h"
-#include "tscSecondaryMerge.h"
#include "tscUtil.h"
+#include "tschemautil.h"
#include "tsclient.h"
#include "tutil.h"
@@ -58,40 +59,37 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SSqlRes *pRes, SLocalReducer *pRedu
* the fields and offset attributes in pCmd and pModel may be different due to
* merge requirement. So, the final result in pRes structure is formatted in accordance with the pCmd object.
*/
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SQLFunctionCtx *pCtx = &pReducer->pCtx[i];
+ SSqlExpr * pExpr = tscSqlExprGet(pQueryInfo, i);
- pCtx->aOutputBuf = pReducer->pResultBuf->data + tscFieldInfoGetOffset(pQueryInfo, i) * pReducer->resColModel->capacity;
+ pCtx->aOutputBuf =
+ pReducer->pResultBuf->data + tscFieldInfoGetOffset(pQueryInfo, i) * pReducer->resColModel->capacity;
pCtx->order = pQueryInfo->order.order;
- pCtx->functionId = pQueryInfo->exprsInfo.pExprs[i].functionId;
+ pCtx->functionId = pExpr->functionId;
// input buffer hold only one point data
- int16_t offset = getColumnModelOffset(pDesc->pColumnModel, i);
- SSchema* pSchema = getColumnModelSchema(pDesc->pColumnModel, i);
-
+ int16_t offset = getColumnModelOffset(pDesc->pColumnModel, i);
+ SSchema *pSchema = getColumnModelSchema(pDesc->pColumnModel, i);
+
pCtx->aInputElemBuf = pReducer->pTempBuffer->data + offset;
// input data format comes from pModel
pCtx->inputType = pSchema->type;
pCtx->inputBytes = pSchema->bytes;
- TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
// output data format yet comes from pCmd.
- pCtx->outputBytes = pField->bytes;
- pCtx->outputType = pField->type;
+ pCtx->outputBytes = pExpr->resBytes;
+ pCtx->outputType = pExpr->resType;
pCtx->startOffset = 0;
pCtx->size = 1;
pCtx->hasNull = true;
pCtx->currentStage = SECONDARY_STAGE_MERGE;
- pRes->bytes[i] = pField->bytes;
-
- SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
-
// for top/bottom function, the output of timestamp is the first column
- int32_t functionId = pExpr->functionId;
+ int32_t functionId = pExpr->functionId;
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
pCtx->ptsOutputBuf = pReducer->pCtx[0].aOutputBuf;
pCtx->param[2].i64Key = pQueryInfo->order.order;
@@ -107,12 +105,12 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SSqlRes *pRes, SLocalReducer *pRedu
pCtx->resultInfo->superTableQ = true;
}
- int16_t n = 0;
- int16_t tagLen = 0;
- SQLFunctionCtx** pTagCtx = calloc(pQueryInfo->fieldsInfo.numOfOutputCols, POINTER_BYTES);
+ int16_t n = 0;
+ int16_t tagLen = 0;
+ SQLFunctionCtx **pTagCtx = calloc(pQueryInfo->fieldsInfo.numOfOutputCols, POINTER_BYTES);
- SQLFunctionCtx* pCtx = NULL;
- for(int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ SQLFunctionCtx *pCtx = NULL;
+ for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_TAG_DUMMY || pExpr->functionId == TSDB_FUNC_TS_DUMMY) {
tagLen += pExpr->resBytes;
@@ -218,12 +216,12 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
#ifdef _DEBUG_VIEW
printf("load data page into mem for build loser tree: %" PRIu64 " rows\n", pDS->filePage.numOfElems);
SSrcColumnInfo colInfo[256] = {0};
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
tscGetSrcColumnInfo(colInfo, pQueryInfo);
- tColModelDisplayEx(pDesc->pColumnModel, pDS->filePage.data, pDS->filePage.numOfElems, pMemBuffer[0]->numOfElemsPerPage,
- colInfo);
+ tColModelDisplayEx(pDesc->pColumnModel, pDS->filePage.data, pDS->filePage.numOfElems,
+ pMemBuffer[0]->numOfElemsPerPage, colInfo);
#endif
if (pDS->filePage.numOfElems == 0) { // no data in this flush
tscTrace("%p flush data is empty, ignore %d flush record", pSqlObjAddr, idx);
@@ -244,8 +242,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
param->pLocalData = pReducer->pLocalDataSrc;
param->pDesc = pReducer->pDesc;
param->numOfElems = pReducer->pLocalDataSrc[0]->pMemBuffer->numOfElemsPerPage;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
param->groupOrderType = pQueryInfo->groupbyExpr.orderType;
pRes->code = tLoserTreeCreate(&pReducer->pLoserTree, pReducer->numOfBuffer, param, treeComparator);
@@ -255,7 +253,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
// the input data format follows the old format, but output in a new format.
// so, all the input must be parsed as old format
- pReducer->pCtx = (SQLFunctionCtx *)calloc(pQueryInfo->fieldsInfo.numOfOutputCols, sizeof(SQLFunctionCtx));
+ pReducer->pCtx = (SQLFunctionCtx *)calloc(pQueryInfo->exprsInfo.numOfExprs, sizeof(SQLFunctionCtx));
pReducer->rowSize = pMemBuffer[0]->nElemSize;
@@ -279,7 +277,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
pReducer->nResultBufSize = pMemBuffer[0]->pageSize * 16;
pReducer->pResultBuf = (tFilePage *)calloc(1, pReducer->nResultBufSize + sizeof(tFilePage));
-
+
int32_t finalRowLength = tscGetResRowLength(pQueryInfo);
pReducer->resColModel = finalmodel;
pReducer->resColModel->capacity = pReducer->nResultBufSize / finalRowLength;
@@ -288,12 +286,12 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
pReducer->pFinalRes = calloc(1, pReducer->rowSize * pReducer->resColModel->capacity);
pReducer->pBufForInterpo = calloc(1, pReducer->nResultBufSize);
- if (pReducer->pTempBuffer == NULL|| pReducer->discardData == NULL || pReducer->pResultBuf == NULL ||
+ if (pReducer->pTempBuffer == NULL || pReducer->discardData == NULL || pReducer->pResultBuf == NULL ||
pReducer->pBufForInterpo == NULL || pReducer->pFinalRes == NULL || pReducer->prevRowOfInput == NULL) {
tfree(pReducer->pTempBuffer);
tfree(pReducer->discardData);
tfree(pReducer->pResultBuf);
- tfree(pReducer->pFinalRes);
+ tfree(pReducer->pFinalRes);
tfree(pReducer->pBufForInterpo);
tfree(pReducer->prevRowOfInput);
@@ -302,30 +300,31 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
}
pReducer->pTempBuffer->numOfElems = 0;
- pReducer->pResInfo = calloc((size_t)pQueryInfo->fieldsInfo.numOfOutputCols, sizeof(SResultInfo));
+ pReducer->pResInfo = calloc((size_t)pQueryInfo->exprsInfo.numOfExprs, sizeof(SResultInfo));
tscCreateResPointerInfo(pRes, pQueryInfo);
tscInitSqlContext(pCmd, pRes, pReducer, pDesc);
// we change the capacity of schema to denote that there is only one row in temp buffer
pReducer->pDesc->pColumnModel->capacity = 1;
-
- //restore the limitation value at the last stage
+
+ // restore the limitation value at the last stage
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
pQueryInfo->limit.limit = pQueryInfo->clauseLimit;
pQueryInfo->limit.offset = pQueryInfo->prjOffset;
}
-
+
pReducer->offset = pQueryInfo->limit.offset;
-
+
pRes->pLocalReducer = pReducer;
pRes->numOfGroups = 0;
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
- int16_t prec = pMeterMetaInfo->pMeterMeta->precision;
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
+ int16_t prec = pMeterMetaInfo->pMeterMeta->precision;
int64_t stime = (pQueryInfo->stime < pQueryInfo->etime) ? pQueryInfo->stime : pQueryInfo->etime;
- int64_t revisedSTime = taosGetIntervalStartTimestamp(stime, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit, prec);
+ int64_t revisedSTime =
+ taosGetIntervalStartTimestamp(stime, pQueryInfo->intervalTime, pQueryInfo->intervalTimeUnit, prec);
SInterpolationInfo *pInterpoInfo = &pReducer->interpolationInfo;
taosInitInterpoInfo(pInterpoInfo, pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols,
@@ -336,7 +335,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) {
pInterpoInfo->pTags[0] = (char *)pInterpoInfo->pTags + POINTER_BYTES * pQueryInfo->groupbyExpr.numOfGroupCols;
for (int32_t i = 1; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
- SSchema* pSchema = getColumnModelSchema(pReducer->resColModel, startIndex + i - 1);
+ SSchema *pSchema = getColumnModelSchema(pReducer->resColModel, startIndex + i - 1);
pInterpoInfo->pTags[i] = pSchema->bytes + pInterpoInfo->pTags[i - 1];
}
} else {
@@ -388,7 +387,7 @@ int32_t tscFlushTmpBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tF
int32_t saveToBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tFilePage *pPage, void *data,
int32_t numOfRows, int32_t orderType) {
SColumnModel *pModel = pDesc->pColumnModel;
-
+
if (pPage->numOfElems + numOfRows <= pModel->capacity) {
tColModelAppend(pModel, pPage, data, 0, numOfRows, numOfRows);
return 0;
@@ -445,11 +444,11 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
return;
}
- SSqlCmd *pCmd = &pSql->cmd;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ SSqlCmd * pCmd = &pSql->cmd;
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
// there is no more result, so we release all allocated resource
- SLocalReducer *pLocalReducer = (SLocalReducer*)atomic_exchange_ptr(&pRes->pLocalReducer, NULL);
+ SLocalReducer *pLocalReducer = (SLocalReducer *)atomic_exchange_ptr(&pRes->pLocalReducer, NULL);
if (pLocalReducer != NULL) {
int32_t status = 0;
while ((status = atomic_val_compare_exchange_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY,
@@ -461,19 +460,18 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
taosDestoryInterpoInfo(&pLocalReducer->interpolationInfo);
if (pLocalReducer->pCtx != NULL) {
- for(int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
SQLFunctionCtx *pCtx = &pLocalReducer->pCtx[i];
-
+
tVariantDestroy(&pCtx->tag);
if (pCtx->tagInfo.pTagCtxList != NULL) {
tfree(pCtx->tagInfo.pTagCtxList);
}
}
-
+
tfree(pLocalReducer->pCtx);
}
-
tfree(pLocalReducer->prevRowOfInput);
tfree(pLocalReducer->pTempBuffer);
@@ -514,15 +512,15 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
}
static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCmd, SColumnModel *pModel) {
- int32_t numOfGroupByCols = 0;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ int32_t numOfGroupByCols = 0;
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) {
numOfGroupByCols = pQueryInfo->groupbyExpr.numOfGroupCols;
}
// primary timestamp column is involved in final result
- if (pQueryInfo->nAggTimeInterval != 0 || tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
+ if (pQueryInfo->intervalTime != 0 || tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
numOfGroupByCols++;
}
@@ -539,7 +537,7 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
orderIdx[i] = startCols++;
}
- if (pQueryInfo->nAggTimeInterval != 0) {
+ if (pQueryInfo->intervalTime != 0) {
// the first column is the timestamp, handles queries like "interval(10m) group by tags"
orderIdx[numOfGroupByCols - 1] = PRIMARYKEY_TIMESTAMP_COL_INDEX;
}
@@ -556,17 +554,17 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
}
bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage *tmpBuffer) {
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
int16_t functionId = tscSqlExprGet(pQueryInfo, 0)->functionId;
// disable merge procedure for column projection query
assert(functionId != TSDB_FUNC_ARITHM);
-
+
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
return true;
}
-
+
if (functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_ARITHM) {
return false;
}
@@ -581,10 +579,10 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
if (pOrderDesc->orderIdx.pData[numOfCols - 1] == PRIMARYKEY_TIMESTAMP_COL_INDEX) { //<= 0
// super table interval query
- assert(pQueryInfo->nAggTimeInterval > 0);
+ assert(pQueryInfo->intervalTime > 0);
pOrderDesc->orderIdx.numOfCols -= 1;
} else { // simple group by query
- assert(pQueryInfo->nAggTimeInterval == 0);
+ assert(pQueryInfo->intervalTime == 0);
}
// only one row exists
@@ -599,11 +597,11 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- SSchema * pSchema = NULL;
+ SSchema * pSchema = NULL;
SColumnModel *pModel = NULL;
*pFinalModel = NULL;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
(*pMemBuffer) = (tExtMemBuffer **)malloc(POINTER_BYTES * pMeterMetaInfo->pMetricMeta->numOfVnodes);
@@ -613,7 +611,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
return pRes->code;
}
- pSchema = (SSchema *)calloc(1, sizeof(SSchema) * pQueryInfo->fieldsInfo.numOfOutputCols);
+ pSchema = (SSchema *)calloc(1, sizeof(SSchema) * pQueryInfo->exprsInfo.numOfExprs);
if (pSchema == NULL) {
tscError("%p failed to allocate memory", pSql);
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
@@ -621,7 +619,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
}
int32_t rlen = 0;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
pSchema[i].bytes = pExpr->resBytes;
@@ -634,8 +632,8 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
if (rlen != 0) {
capacity = nBufferSizes / rlen;
}
-
- pModel = createColumnModel(pSchema, pQueryInfo->fieldsInfo.numOfOutputCols, capacity);
+
+ pModel = createColumnModel(pSchema, pQueryInfo->exprsInfo.numOfExprs, capacity);
for (int32_t i = 0; i < pMeterMetaInfo->pMetricMeta->numOfVnodes; ++i) {
(*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pModel);
@@ -647,16 +645,43 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
return pRes->code;
}
- memset(pSchema, 0, sizeof(SSchema) * pQueryInfo->fieldsInfo.numOfOutputCols);
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
- TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
+ // final result depends on the fields number
+ memset(pSchema, 0, sizeof(SSchema) * pQueryInfo->exprsInfo.numOfExprs);
+ for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
+ SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
+
+ SSchema *p1 = tsGetColumnSchema(pMeterMetaInfo->pMeterMeta, pExpr->colInfo.colIdx);
+
+ int16_t inter = 0;
+ int16_t type = -1;
+ int16_t bytes = 0;
+
+ // if ((pExpr->functionId >= TSDB_FUNC_FIRST_DST && pExpr->functionId <= TSDB_FUNC_LAST_DST) ||
+ // (pExpr->functionId >= TSDB_FUNC_SUM && pExpr->functionId <= TSDB_FUNC_MAX) ||
+ // pExpr->functionId == TSDB_FUNC_LAST_ROW) {
+ // the final result size and type in the same as query on single table.
+ // so here, set the flag to be false;
+
+ int32_t functionId = pExpr->functionId;
+ if (functionId >= TSDB_FUNC_TS && functionId <= TSDB_FUNC_DIFF) {
+ type = pModel->pFields[i].field.type;
+ bytes = pModel->pFields[i].field.bytes;
+ } else {
+ if (functionId == TSDB_FUNC_FIRST_DST) {
+ functionId = TSDB_FUNC_FIRST;
+ } else if (functionId == TSDB_FUNC_LAST_DST) {
+ functionId = TSDB_FUNC_LAST;
+ }
- pSchema[i].type = pField->type;
- pSchema[i].bytes = pField->bytes;
- strcpy(pSchema[i].name, pField->name);
+ getResultDataInfo(p1->type, p1->bytes, functionId, 0, &type, &bytes, &inter, 0, false);
+ }
+
+ pSchema[i].type = type;
+ pSchema[i].bytes = bytes;
+ strcpy(pSchema[i].name, pModel->pFields[i].field.name);
}
- *pFinalModel = createColumnModel(pSchema, pQueryInfo->fieldsInfo.numOfOutputCols, capacity);
+ *pFinalModel = createColumnModel(pSchema, pQueryInfo->exprsInfo.numOfExprs, capacity);
tfree(pSchema);
return TSDB_CODE_SUCCESS;
@@ -746,13 +771,15 @@ void adjustLoserTreeFromNewData(SLocalReducer *pLocalReducer, SLocalDataSource *
}
}
-void savePrevRecordAndSetupInterpoInfo(SLocalReducer *pLocalReducer, SQueryInfo* pQueryInfo, SInterpolationInfo *pInterpoInfo) {
+void savePrevRecordAndSetupInterpoInfo(SLocalReducer *pLocalReducer, SQueryInfo *pQueryInfo,
+ SInterpolationInfo *pInterpoInfo) {
// discard following dataset in the same group and reset the interpolation information
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
- int16_t prec = pMeterMetaInfo->pMeterMeta->precision;
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
+ int16_t prec = pMeterMetaInfo->pMeterMeta->precision;
int64_t stime = (pQueryInfo->stime < pQueryInfo->etime) ? pQueryInfo->stime : pQueryInfo->etime;
- int64_t revisedSTime = taosGetIntervalStartTimestamp(stime, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit, prec);
+ int64_t revisedSTime =
+ taosGetIntervalStartTimestamp(stime, pQueryInfo->intervalTime, pQueryInfo->intervalTimeUnit, prec);
taosInitInterpoInfo(pInterpoInfo, pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols,
pLocalReducer->rowSize);
@@ -765,24 +792,25 @@ void savePrevRecordAndSetupInterpoInfo(SLocalReducer *pLocalReducer, SQueryInfo*
}
// todo merge with following function
-static void reversedCopyResultToDstBuf(SQueryInfo* pQueryInfo, SSqlRes *pRes, tFilePage *pFinalDataPage) {
-
- for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
- TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
-
- int32_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
- char * src = pFinalDataPage->data + (pRes->numOfRows - 1) * pField->bytes + pRes->numOfRows * offset;
- char * dst = pRes->data + pRes->numOfRows * offset;
-
- for (int32_t j = 0; j < pRes->numOfRows; ++j) {
- memcpy(dst, src, (size_t)pField->bytes);
- dst += pField->bytes;
- src -= pField->bytes;
- }
- }
-}
+// static void reversedCopyResultToDstBuf(SQueryInfo* pQueryInfo, SSqlRes *pRes, tFilePage *pFinalDataPage) {
+//
+// for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
+// TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
+//
+// int32_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
+// char * src = pFinalDataPage->data + (pRes->numOfRows - 1) * pField->bytes + pRes->numOfRows * offset;
+// char * dst = pRes->data + pRes->numOfRows * offset;
+//
+// for (int32_t j = 0; j < pRes->numOfRows; ++j) {
+// memcpy(dst, src, (size_t)pField->bytes);
+// dst += pField->bytes;
+// src -= pField->bytes;
+// }
+// }
+//}
-static void reversedCopyFromInterpolationToDstBuf(SQueryInfo* pQueryInfo, SSqlRes *pRes, tFilePage **pResPages, SLocalReducer *pLocalReducer) {
+static void reversedCopyFromInterpolationToDstBuf(SQueryInfo *pQueryInfo, SSqlRes *pRes, tFilePage **pResPages,
+ SLocalReducer *pLocalReducer) {
assert(0);
for (int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
@@ -806,11 +834,11 @@ static void reversedCopyFromInterpolationToDstBuf(SQueryInfo* pQueryInfo, SSqlRe
* by "interuptHandler" function in shell
*/
static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneOutput) {
- SSqlCmd * pCmd = &pSql->cmd;
- SSqlRes * pRes = &pSql->res;
- tFilePage *pFinalDataPage = pLocalReducer->pResultBuf;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ SSqlCmd * pCmd = &pSql->cmd;
+ SSqlRes * pRes = &pSql->res;
+ tFilePage * pFinalDataPage = pLocalReducer->pResultBuf;
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
if (pRes->pLocalReducer != pLocalReducer) {
/*
* Release the SSqlObj is called, and it is int destroying function invoked by other thread.
@@ -820,7 +848,7 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
assert(pRes->pLocalReducer == NULL);
}
- if (pQueryInfo->nAggTimeInterval == 0 || pQueryInfo->interpoType == TSDB_INTERPO_NONE) {
+ if (pQueryInfo->intervalTime == 0 || pQueryInfo->interpoType == TSDB_INTERPO_NONE) {
// no interval query, no interpolation
pRes->data = pLocalReducer->pFinalRes;
pRes->numOfRows = pFinalDataPage->numOfElems;
@@ -862,19 +890,14 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
}
int32_t rowSize = tscGetResRowLength(pQueryInfo);
- // handle the descend order output
-// if (pQueryInfo->order.order == TSQL_SO_ASC) {
- memcpy(pRes->data, pFinalDataPage->data, pRes->numOfRows * rowSize);
-// } else {
-// reversedCopyResultToDstBuf(pQueryInfo, pRes, pFinalDataPage);
-// }
+ memcpy(pRes->data, pFinalDataPage->data, pRes->numOfRows * rowSize);
pFinalDataPage->numOfElems = 0;
return;
}
int64_t *pPrimaryKeys = (int64_t *)pLocalReducer->pBufForInterpo;
-
+
SInterpolationInfo *pInterpoInfo = &pLocalReducer->interpolationInfo;
int64_t actualETime = (pQueryInfo->stime < pQueryInfo->etime) ? pQueryInfo->etime : pQueryInfo->stime;
@@ -889,22 +912,23 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
int32_t *functions = (int32_t *)((char *)srcData + pQueryInfo->fieldsInfo.numOfOutputCols * sizeof(void *));
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
- srcData[i] = pLocalReducer->pBufForInterpo + tscFieldInfoGetOffset(pQueryInfo, i) * pInterpoInfo->numOfRawDataInRows;
+ srcData[i] =
+ pLocalReducer->pBufForInterpo + tscFieldInfoGetOffset(pQueryInfo, i) * pInterpoInfo->numOfRawDataInRows;
functions[i] = tscSqlExprGet(pQueryInfo, i)->functionId;
}
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
- int8_t precision = pMeterMetaInfo->pMeterMeta->precision;
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
+ int8_t precision = pMeterMetaInfo->pMeterMeta->precision;
while (1) {
int32_t remains = taosNumOfRemainPoints(pInterpoInfo);
- TSKEY etime = taosGetRevisedEndKey(actualETime, pQueryInfo->order.order, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit,
- precision);
- int32_t nrows = taosGetNumOfResultWithInterpo(pInterpoInfo, pPrimaryKeys, remains, pQueryInfo->nAggTimeInterval, etime,
+ TSKEY etime = taosGetRevisedEndKey(actualETime, pQueryInfo->order.order, pQueryInfo->intervalTime,
+ pQueryInfo->intervalTimeUnit, precision);
+ int32_t nrows = taosGetNumOfResultWithInterpo(pInterpoInfo, pPrimaryKeys, remains, pQueryInfo->intervalTime, etime,
pLocalReducer->resColModel->capacity);
int32_t newRows = taosDoInterpoResult(pInterpoInfo, pQueryInfo->interpoType, pResPages, remains, nrows,
- pQueryInfo->nAggTimeInterval, pPrimaryKeys, pLocalReducer->resColModel, srcData,
+ pQueryInfo->intervalTime, pPrimaryKeys, pLocalReducer->resColModel, srcData,
pQueryInfo->defaultVal, functions, pLocalReducer->resColModel->capacity);
assert(newRows <= nrows);
@@ -914,7 +938,8 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
if (pQueryInfo->limit.offset > 0) {
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
- memmove(pResPages[i]->data, pResPages[i]->data + pField->bytes * pQueryInfo->limit.offset, newRows * pField->bytes);
+ memmove(pResPages[i]->data, pResPages[i]->data + pField->bytes * pQueryInfo->limit.offset,
+ newRows * pField->bytes);
}
}
@@ -937,7 +962,7 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
/* all output for current group are completed */
int32_t totalRemainRows =
- taosGetNumOfResWithoutLimit(pInterpoInfo, pPrimaryKeys, rpoints, pQueryInfo->nAggTimeInterval, actualETime);
+ taosGetNumOfResWithoutLimit(pInterpoInfo, pPrimaryKeys, rpoints, pQueryInfo->intervalTime, actualETime);
if (totalRemainRows <= 0) {
break;
}
@@ -962,10 +987,10 @@ static void doInterpolateResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, boo
if (pQueryInfo->order.order == TSQL_SO_ASC) {
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
- int16_t offset = getColumnModelOffset(pLocalReducer->resColModel, i);
+ int16_t offset = getColumnModelOffset(pLocalReducer->resColModel, i);
memcpy(pRes->data + offset * pRes->numOfRows, pResPages[i]->data, pField->bytes * pRes->numOfRows);
}
- } else {//todo bug??
+ } else { // todo bug??
reversedCopyFromInterpolationToDstBuf(pQueryInfo, pRes, pResPages, pLocalReducer);
}
}
@@ -985,9 +1010,9 @@ static void savePreviousRow(SLocalReducer *pLocalReducer, tFilePage *tmpBuffer)
// copy to previous temp buffer
for (int32_t i = 0; i < pColumnModel->numOfCols; ++i) {
- SSchema* pSchema = getColumnModelSchema(pColumnModel, i);
- int16_t offset = getColumnModelOffset(pColumnModel, i);
-
+ SSchema *pSchema = getColumnModelSchema(pColumnModel, i);
+ int16_t offset = getColumnModelOffset(pColumnModel, i);
+
memcpy(pLocalReducer->prevRowOfInput + offset, tmpBuffer->data + offset, pSchema->bytes);
}
@@ -995,19 +1020,19 @@ static void savePreviousRow(SLocalReducer *pLocalReducer, tFilePage *tmpBuffer)
pLocalReducer->hasPrevRow = true;
}
-static void doExecuteSecondaryMerge(SSqlCmd* pCmd, SLocalReducer *pLocalReducer, bool needInit) {
+static void doExecuteSecondaryMerge(SSqlCmd *pCmd, SLocalReducer *pLocalReducer, bool needInit) {
// the tag columns need to be set before all functions execution
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
- for(int32_t j = 0; j < pQueryInfo->fieldsInfo.numOfOutputCols; ++j) {
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
+ for (int32_t j = 0; j < pQueryInfo->exprsInfo.numOfExprs; ++j) {
SSqlExpr * pExpr = tscSqlExprGet(pQueryInfo, j);
SQLFunctionCtx *pCtx = &pLocalReducer->pCtx[j];
tVariantAssign(&pCtx->param[0], &pExpr->param[0]);
// tags/tags_dummy function, the tag field of SQLFunctionCtx is from the input buffer
- if (pExpr->functionId == TSDB_FUNC_TAG_DUMMY || pExpr->functionId == TSDB_FUNC_TAG ||
- pExpr->functionId == TSDB_FUNC_TS_DUMMY) {
+ int32_t functionId = pExpr->functionId;
+ if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TS_DUMMY) {
tVariantDestroy(&pCtx->tag);
tVariantCreateFromBinary(&pCtx->tag, pCtx->aInputElemBuf, pCtx->inputBytes, pCtx->inputType);
}
@@ -1019,7 +1044,7 @@ static void doExecuteSecondaryMerge(SSqlCmd* pCmd, SLocalReducer *pLocalReducer,
}
}
- for (int32_t j = 0; j < pQueryInfo->fieldsInfo.numOfOutputCols; ++j) {
+ for (int32_t j = 0; j < pQueryInfo->exprsInfo.numOfExprs; ++j) {
int32_t functionId = tscSqlExprGet(pQueryInfo, j)->functionId;
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) {
continue;
@@ -1029,7 +1054,7 @@ static void doExecuteSecondaryMerge(SSqlCmd* pCmd, SLocalReducer *pLocalReducer,
}
}
-static void handleUnprocessedRow(SSqlCmd* pCmd, SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
+static void handleUnprocessedRow(SSqlCmd *pCmd, SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
if (pLocalReducer->hasUnprocessedRow) {
pLocalReducer->hasUnprocessedRow = false;
doExecuteSecondaryMerge(pCmd, pLocalReducer, true);
@@ -1039,14 +1064,22 @@ static void handleUnprocessedRow(SSqlCmd* pCmd, SLocalReducer *pLocalReducer, tF
static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx) {
int64_t maxOutput = 0;
-
+
for (int32_t j = 0; j < pQueryInfo->exprsInfo.numOfExprs; ++j) {
- int32_t functionId = tscSqlExprGet(pQueryInfo, j)->functionId;
+ // SSqlExpr* pExpr = pQueryInfo->fieldsInfo.pSqlExpr[j];
+ // if (pExpr == NULL) {
+ // assert(pQueryInfo->fieldsInfo.pExpr[j] != NULL);
+ //
+ // maxOutput = 1;
+ // continue;
+ // }
/*
* ts, tag, tagprj function can not decide the output number of current query
* the number of output result is decided by main output
*/
+ SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, j);
+ int32_t functionId = pExpr->functionId;
if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
continue;
}
@@ -1055,6 +1088,7 @@ static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx)
maxOutput = GET_RES_INFO(&pCtx[j])->numOfRes;
}
}
+
return maxOutput;
}
@@ -1064,9 +1098,9 @@ static int64_t getNumOfResultLocal(SQueryInfo *pQueryInfo, SQLFunctionCtx *pCtx)
* filled with the same result, which is the tags, specified in group by clause
*
*/
-static void fillMultiRowsOfTagsVal(SQueryInfo* pQueryInfo, int32_t numOfRes, SLocalReducer *pLocalReducer) {
+static void fillMultiRowsOfTagsVal(SQueryInfo *pQueryInfo, int32_t numOfRes, SLocalReducer *pLocalReducer) {
int32_t maxBufSize = 0; // find the max tags column length to prepare the buffer
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, k);
if (maxBufSize < pExpr->resBytes && pExpr->functionId == TSDB_FUNC_TAG) {
maxBufSize = pExpr->resBytes;
@@ -1075,8 +1109,8 @@ static void fillMultiRowsOfTagsVal(SQueryInfo* pQueryInfo, int32_t numOfRes, SLo
assert(maxBufSize >= 0);
- char *buf = malloc((size_t) maxBufSize);
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
+ char *buf = malloc((size_t)maxBufSize);
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, k);
if (pExpr->functionId != TSDB_FUNC_TAG) {
continue;
@@ -1097,13 +1131,10 @@ static void fillMultiRowsOfTagsVal(SQueryInfo* pQueryInfo, int32_t numOfRes, SLo
free(buf);
}
-int32_t finalizeRes(SQueryInfo* pQueryInfo, SLocalReducer *pLocalReducer) {
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
+int32_t finalizeRes(SQueryInfo *pQueryInfo, SLocalReducer *pLocalReducer) {
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, k);
aAggs[pExpr->functionId].xFinalize(&pLocalReducer->pCtx[k]);
-
- // allow to re-initialize for the next round
- pLocalReducer->pCtx[k].resultInfo->initialized = false;
}
pLocalReducer->hasPrevRow = false;
@@ -1122,7 +1153,7 @@ int32_t finalizeRes(SQueryInfo* pQueryInfo, SLocalReducer *pLocalReducer) {
* results generated by simple aggregation function, we merge them all into one points
* *Exception*: column projection query, required no merge procedure
*/
-bool needToMerge(SQueryInfo* pQueryInfo, SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
+bool needToMerge(SQueryInfo *pQueryInfo, SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
int32_t ret = 0; // merge all result by default
int16_t functionId = tscSqlExprGet(pQueryInfo, 0)->functionId;
@@ -1144,7 +1175,7 @@ bool needToMerge(SQueryInfo* pQueryInfo, SLocalReducer *pLocalReducer, tFilePage
return (ret == 0);
}
-static bool reachGroupResultLimit(SQueryInfo* pQueryInfo, SSqlRes *pRes) {
+static bool reachGroupResultLimit(SQueryInfo *pQueryInfo, SSqlRes *pRes) {
return (pRes->numOfGroups >= pQueryInfo->slimit.limit && pQueryInfo->slimit.limit >= 0);
}
@@ -1152,7 +1183,7 @@ static bool saveGroupResultInfo(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
pRes->numOfGroups += 1;
// the output group is limited by the slimit clause
@@ -1175,11 +1206,11 @@ static bool saveGroupResultInfo(SSqlObj *pSql) {
* @return if current group is skipped, return false, and do NOT record it into pRes->numOfGroups
*/
bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool noMoreCurrentGroupRes) {
- SSqlCmd * pCmd = &pSql->cmd;
- SSqlRes * pRes = &pSql->res;
-
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
- tFilePage *pResBuf = pLocalReducer->pResultBuf;
+ SSqlCmd *pCmd = &pSql->cmd;
+ SSqlRes *pRes = &pSql->res;
+
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ tFilePage * pResBuf = pLocalReducer->pResultBuf;
SColumnModel *pModel = pLocalReducer->resColModel;
pRes->code = TSDB_CODE_SUCCESS;
@@ -1207,11 +1238,10 @@ bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool no
int32_t startIndex = pQueryInfo->fieldsInfo.numOfOutputCols - pQueryInfo->groupbyExpr.numOfGroupCols;
for (int32_t i = 0; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
- int16_t offset = getColumnModelOffset(pModel, startIndex + i);
- SSchema* pSchema = getColumnModelSchema(pModel, startIndex + i);
-
- memcpy(pInterpoInfo->pTags[i],
- pLocalReducer->pBufForInterpo + offset * pResBuf->numOfElems, pSchema->bytes);
+ int16_t offset = getColumnModelOffset(pModel, startIndex + i);
+ SSchema *pSchema = getColumnModelSchema(pModel, startIndex + i);
+
+ memcpy(pInterpoInfo->pTags[i], pLocalReducer->pBufForInterpo + offset * pResBuf->numOfElems, pSchema->bytes);
}
taosInterpoSetStartInfo(&pLocalReducer->interpolationInfo, pResBuf->numOfElems, pQueryInfo->interpoType);
@@ -1220,7 +1250,7 @@ bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool no
return true;
}
-void resetOutputBuf(SQueryInfo* pQueryInfo, SLocalReducer *pLocalReducer) { // reset output buffer to the beginning
+void resetOutputBuf(SQueryInfo *pQueryInfo, SLocalReducer *pLocalReducer) { // reset output buffer to the beginning
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
pLocalReducer->pCtx[i].aOutputBuf =
pLocalReducer->pResultBuf->data + tscFieldInfoGetOffset(pQueryInfo, i) * pLocalReducer->resColModel->capacity;
@@ -1233,21 +1263,22 @@ static void resetEnvForNewResultset(SSqlRes *pRes, SSqlCmd *pCmd, SLocalReducer
// In handling data in other groups, we need to reset the interpolation information for a new group data
pRes->numOfRows = 0;
pRes->numOfTotalInCurrentClause = 0;
-
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
pQueryInfo->limit.offset = pLocalReducer->offset;
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
- int16_t precision = pMeterMetaInfo->pMeterMeta->precision;
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfo(pCmd, pCmd->clauseIndex, 0);
+ int16_t precision = pMeterMetaInfo->pMeterMeta->precision;
// for group result interpolation, do not return if not data is generated
if (pQueryInfo->interpoType != TSDB_INTERPO_NONE) {
int64_t stime = (pQueryInfo->stime < pQueryInfo->etime) ? pQueryInfo->stime : pQueryInfo->etime;
- int64_t newTime = taosGetIntervalStartTimestamp(stime, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit, precision);
+ int64_t newTime =
+ taosGetIntervalStartTimestamp(stime, pQueryInfo->intervalTime, pQueryInfo->intervalTimeUnit, precision);
- taosInitInterpoInfo(&pLocalReducer->interpolationInfo, pQueryInfo->order.order, newTime, pQueryInfo->groupbyExpr.numOfGroupCols,
- pLocalReducer->rowSize);
+ taosInitInterpoInfo(&pLocalReducer->interpolationInfo, pQueryInfo->order.order, newTime,
+ pQueryInfo->groupbyExpr.numOfGroupCols, pLocalReducer->rowSize);
}
}
@@ -1259,12 +1290,12 @@ static bool doInterpolationForCurrentGroup(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
SLocalReducer * pLocalReducer = pRes->pLocalReducer;
SInterpolationInfo *pInterpoInfo = &pLocalReducer->interpolationInfo;
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
- int8_t p = pMeterMetaInfo->pMeterMeta->precision;
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
+ int8_t p = pMeterMetaInfo->pMeterMeta->precision;
if (taosHasRemainsDataForInterpolation(pInterpoInfo)) {
assert(pQueryInfo->interpoType != TSDB_INTERPO_NONE);
@@ -1273,9 +1304,10 @@ static bool doInterpolationForCurrentGroup(SSqlObj *pSql) {
int64_t etime = *(int64_t *)(pFinalDataBuf->data + TSDB_KEYSIZE * (pInterpoInfo->numOfRawDataInRows - 1));
int32_t remain = taosNumOfRemainPoints(pInterpoInfo);
- TSKEY ekey = taosGetRevisedEndKey(etime, pQueryInfo->order.order, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit, p);
+ TSKEY ekey =
+ taosGetRevisedEndKey(etime, pQueryInfo->order.order, pQueryInfo->intervalTime, pQueryInfo->intervalTimeUnit, p);
int32_t rows = taosGetNumOfResultWithInterpo(pInterpoInfo, (TSKEY *)pLocalReducer->pBufForInterpo, remain,
- pQueryInfo->nAggTimeInterval, ekey, pLocalReducer->resColModel->capacity);
+ pQueryInfo->intervalTime, ekey, pLocalReducer->resColModel->capacity);
if (rows > 0) { // do interpo
doInterpolateResult(pSql, pLocalReducer, false);
}
@@ -1295,9 +1327,9 @@ static bool doHandleLastRemainData(SSqlObj *pSql) {
bool prevGroupCompleted = (!pLocalReducer->discard) && pLocalReducer->hasUnprocessedRow;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
- SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
- int8_t precision = pMeterMetaInfo->pMeterMeta->precision;
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
+ int8_t precision = pMeterMetaInfo->pMeterMeta->precision;
if ((isAllSourcesCompleted(pLocalReducer) && !pLocalReducer->hasPrevRow) || pLocalReducer->pLocalDataSrc[0] == NULL ||
prevGroupCompleted) {
@@ -1305,8 +1337,9 @@ static bool doHandleLastRemainData(SSqlObj *pSql) {
if (pQueryInfo->interpoType != TSDB_INTERPO_NONE) {
int64_t etime = (pQueryInfo->stime < pQueryInfo->etime) ? pQueryInfo->etime : pQueryInfo->stime;
- etime = taosGetRevisedEndKey(etime, pQueryInfo->order.order, pQueryInfo->nAggTimeInterval, pQueryInfo->intervalTimeUnit, precision);
- int32_t rows = taosGetNumOfResultWithInterpo(pInterpoInfo, NULL, 0, pQueryInfo->nAggTimeInterval, etime,
+ etime = taosGetRevisedEndKey(etime, pQueryInfo->order.order, pQueryInfo->intervalTime,
+ pQueryInfo->intervalTimeUnit, precision);
+ int32_t rows = taosGetNumOfResultWithInterpo(pInterpoInfo, NULL, 0, pQueryInfo->intervalTime, etime,
pLocalReducer->resColModel->capacity);
if (rows > 0) { // do interpo
doInterpolateResult(pSql, pLocalReducer, true);
@@ -1334,15 +1367,15 @@ static bool doHandleLastRemainData(SSqlObj *pSql) {
return false;
}
-static void doMergeWithPrevRows(SSqlObj *pSql, int32_t numOfRes) {
- SSqlCmd * pCmd = &pSql->cmd;
- SSqlRes * pRes = &pSql->res;
-
+static void doProcessResultInNextWindow(SSqlObj *pSql, int32_t numOfRes) {
+ SSqlCmd *pCmd = &pSql->cmd;
+ SSqlRes *pRes = &pSql->res;
+
SLocalReducer *pLocalReducer = pRes->pLocalReducer;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
- for (int32_t k = 0; k < pQueryInfo->fieldsInfo.numOfOutputCols; ++k) {
- SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, k);
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
+ for (int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
+ SSqlExpr * pExpr = tscSqlExprGet(pQueryInfo, k);
SQLFunctionCtx *pCtx = &pLocalReducer->pCtx[k];
pCtx->aOutputBuf += pCtx->outputBytes * numOfRes;
@@ -1359,24 +1392,24 @@ static void doMergeWithPrevRows(SSqlObj *pSql, int32_t numOfRes) {
int32_t tscDoLocalreduce(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
-
+
tscResetForNextRetrieve(pRes);
-
+
if (pSql->signature != pSql || pRes == NULL || pRes->pLocalReducer == NULL) { // all data has been processed
tscTrace("%s call the drop local reducer", __FUNCTION__);
tscDestroyLocalReducer(pSql);
return 0;
}
-
+
SLocalReducer *pLocalReducer = pRes->pLocalReducer;
- SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
-
+ SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
// set the data merge in progress
int32_t prevStatus =
atomic_val_compare_exchange_32(&pLocalReducer->status, TSC_LOCALREDUCE_READY, TSC_LOCALREDUCE_IN_PROGRESS);
if (prevStatus != TSC_LOCALREDUCE_READY || pLocalReducer == NULL) {
- assert(prevStatus == TSC_LOCALREDUCE_TOBE_FREED); // it is in tscDestroyLocalReducer function already
+ assert(prevStatus == TSC_LOCALREDUCE_TOBE_FREED); // it is in tscDestroyLocalReducer function already
return TSDB_CODE_SUCCESS;
}
@@ -1474,8 +1507,7 @@ int32_t tscDoLocalreduce(SSqlObj *pSql) {
* if the previous group does NOT generate any result (pResBuf->numOfElems == 0),
* continue to process results instead of return results.
*/
- if ((!sameGroup && pResBuf->numOfElems > 0) ||
- (pResBuf->numOfElems == pLocalReducer->resColModel->capacity)) {
+ if ((!sameGroup && pResBuf->numOfElems > 0) || (pResBuf->numOfElems == pLocalReducer->resColModel->capacity)) {
// does not belong to the same group
bool notSkipped = doGenerateFinalResults(pSql, pLocalReducer, !sameGroup);
@@ -1528,7 +1560,7 @@ int32_t tscDoLocalreduce(SSqlObj *pSql) {
return TSDB_CODE_SUCCESS;
}
} else { // result buffer is not full
- doMergeWithPrevRows(pSql, numOfRes);
+ doProcessResultInNextWindow(pSql, numOfRes);
savePreviousRow(pLocalReducer, tmpBuffer);
}
}
diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c
index 10db2c47876d308a6a8e92ae2d1f54467154e107..c6efafe3329ff57e6d5c3f1dfadd1b49952c4beb 100644
--- a/src/client/src/tscServer.c
+++ b/src/client/src/tscServer.c
@@ -392,19 +392,23 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSubquerySu
tscColumnBaseInfoUpdateTableIndex(&pNewQueryInfo->colList, 0);
tscColumnBaseInfoCopy(&pSupporter->colList, &pNewQueryInfo->colList, 0);
- tscSqlExprCopy(&pSupporter->exprsInfo, &pNewQueryInfo->exprsInfo, pSupporter->uid);
-
+ tscSqlExprCopy(&pSupporter->exprsInfo, &pNewQueryInfo->exprsInfo, pSupporter->uid, false);
tscFieldInfoCopyAll(&pSupporter->fieldsInfo, &pNewQueryInfo->fieldsInfo);
+
tscTagCondCopy(&pSupporter->tagCond, &pNewQueryInfo->tagCond);
pNew->cmd.numOfCols = 0;
- pNewQueryInfo->nAggTimeInterval = 0;
+ pNewQueryInfo->intervalTime = 0;
memset(&pNewQueryInfo->limit, 0, sizeof(SLimitVal));
// backup the data and clear it in the sqlcmd object
pSupporter->groupbyExpr = pNewQueryInfo->groupbyExpr;
memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr));
+ // this data needs to be transfer to support struct
+ pNewQueryInfo->fieldsInfo.numOfOutputCols = 0;
+ pNewQueryInfo->exprsInfo.numOfExprs = 0;
+
// set the ts,tags that involved in join, as the output column of intermediate result
tscClearSubqueryInfo(&pNew->cmd);
@@ -649,7 +653,7 @@ int tscLaunchSTableSubqueries(SSqlObj *pSql) {
tExtMemBuffer ** pMemoryBuf = NULL;
tOrderDescriptor *pDesc = NULL;
- SColumnModel * pModel = NULL;
+ SColumnModel * pModel = NULL;
pRes->qhandle = 1; // hack the qhandle check
@@ -1066,8 +1070,6 @@ void tscKillMetricQuery(SSqlObj *pSql) {
//taosStopRpcConn(pSql->pSubs[i]->thandle);
}
- pSql->numOfSubs = 0;
-
/*
* 1. if the subqueries are not launched or partially launched, we need to waiting the launched
* query return to successfully free allocated resources.
@@ -1290,7 +1292,7 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) {
int32_t srcColListSize = pQueryInfo->colList.numOfCols * sizeof(SColumnInfo);
- int32_t exprSize = sizeof(SSqlFuncExprMsg) * pQueryInfo->fieldsInfo.numOfOutputCols;
+ int32_t exprSize = sizeof(SSqlFuncExprMsg) * pQueryInfo->exprsInfo.numOfExprs;
SMeterMetaInfo *pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, 0);
// meter query without tags values
@@ -1299,11 +1301,10 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) {
}
SSuperTableMeta *pMetricMeta = pMeterMetaInfo->pMetricMeta;
-
SVnodeSidList *pVnodeSidList = tscGetVnodeSidList(pMetricMeta, pMeterMetaInfo->vnodeIndex);
int32_t meterInfoSize = (pMetricMeta->tagLen + sizeof(STableSidExtInfo)) * pVnodeSidList->numOfSids;
- int32_t outputColumnSize = pQueryInfo->fieldsInfo.numOfOutputCols * sizeof(SSqlFuncExprMsg);
+ int32_t outputColumnSize = pQueryInfo->exprsInfo.numOfExprs * sizeof(SSqlFuncExprMsg);
int32_t size = meterInfoSize + outputColumnSize + srcColListSize + exprSize + MIN_QUERY_MSG_PKT_SIZE;
if (pQueryInfo->tsBuf != NULL) {
@@ -1319,7 +1320,7 @@ static char *doSerializeTableInfo(SSqlObj *pSql, int32_t numOfTables, int32_t vn
STableMeta * pMeterMeta = pMeterMetaInfo->pMeterMeta;
SSuperTableMeta *pMetricMeta = pMeterMetaInfo->pMetricMeta;
- tscTrace("%p vid:%d, query on %d meters", pSql, htons(vnodeId), numOfTables);
+ tscTrace("%p vid:%d, query on %d meters", pSql, vnodeId, numOfTables);
if (UTIL_METER_IS_NOMRAL_METER(pMeterMetaInfo)) {
#ifdef _DEBUG_VIEW
tscTrace("%p sid:%d, uid:%" PRIu64, pSql, pMeterMetaInfo->pMeterMeta->sid, pMeterMetaInfo->pMeterMeta->uid);
@@ -1436,12 +1437,12 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
return -1;
}
- pQueryMsg->nAggTimeInterval = htobe64(pQueryInfo->nAggTimeInterval);
+ pQueryMsg->intervalTime = htobe64(pQueryInfo->intervalTime);
pQueryMsg->intervalTimeUnit = pQueryInfo->intervalTimeUnit;
- pQueryMsg->slidingTime = htobe64(pQueryInfo->nSlidingTime);
+ pQueryMsg->slidingTime = htobe64(pQueryInfo->slidingTime);
- if (pQueryInfo->nAggTimeInterval < 0) {
- tscError("%p illegal value of aggregation time interval in query msg: %ld", pSql, pQueryInfo->nAggTimeInterval);
+ if (pQueryInfo->intervalTime < 0) {
+ tscError("%p illegal value of aggregation time interval in query msg: %ld", pSql, pQueryInfo->intervalTime);
return -1;
}
@@ -1521,7 +1522,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
SSqlFuncExprMsg *pSqlFuncExpr = (SSqlFuncExprMsg *)pMsg;
- for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
+ for (int32_t i = 0; i < tscSqlExprNumOfExprs(pQueryInfo); ++i) {
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
if (pExpr->functionId == TSDB_FUNC_ARITHM) {
@@ -1615,6 +1616,9 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
*((int16_t *)pMsg) += pCol->flag;
pMsg += sizeof(pCol->flag);
+
+ memcpy(pMsg, pCol->name, tListLen(pCol->name));
+ pMsg += tListLen(pCol->name);
}
}
@@ -2124,16 +2128,8 @@ static int tscSetResultPointer(SQueryInfo *pQueryInfo, SSqlRes *pRes) {
}
for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
- TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
- int16_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
-
- pRes->bytes[i] = pField->bytes;
-// if (pQueryInfo->order.order == TSQL_SO_DESC) {
-// pRes->bytes[i] = -pRes->bytes[i];
-// pRes->tsrow[i] = ((pRes->data + offset * pRes->numOfRows) + (pRes->numOfRows - 1) * pField->bytes);
-// } else {
- pRes->tsrow[i] = (pRes->data + offset * pRes->numOfRows);
-// }
+ int16_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
+ pRes->tsrow[i] = (pRes->data + offset * pRes->numOfRows);
}
return 0;
@@ -2348,8 +2344,10 @@ static int32_t tscEstimateMetricMetaMsgSize(SSqlCmd *pCmd) {
int32_t joinCondLen = (TSDB_TABLE_ID_LEN + sizeof(int16_t)) * 2;
int32_t elemSize = sizeof(SSuperTableMetaElemMsg) * pQueryInfo->numOfTables;
+
+ int32_t colSize = pQueryInfo->groupbyExpr.numOfGroupCols*sizeof(SColIndexEx);
- int32_t len = tagLen + joinCondLen + elemSize + defaultSize;
+ int32_t len = tagLen + joinCondLen + elemSize + colSize + defaultSize;
return MAX(len, TSDB_DEFAULT_PAYLOAD_SIZE);
}
@@ -2418,7 +2416,7 @@ int tscBuildMetricMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
int32_t condLen = 0;
if (pTagCond->numOfTagCond > 0) {
SCond *pCond = tsGetMetricQueryCondPos(pTagCond, uid);
- if (pCond != NULL) {
+ if (pCond != NULL && pCond->cond != NULL) {
condLen = strlen(pCond->cond) + 1;
bool ret = taosMbsToUcs4(pCond->cond, condLen, pMsg, condLen * TSDB_NCHAR_SIZE);
@@ -2440,11 +2438,14 @@ int tscBuildMetricMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
offset = pMsg - (char *)pMetaMsg;
pElem->tableCond = htonl(offset);
-
- uint32_t len = strlen(pTagCond->tbnameCond.cond);
+
+ uint32_t len = 0;
+ if (pTagCond->tbnameCond.cond != NULL) {
+ len = strlen(pTagCond->tbnameCond.cond);
+ memcpy(pMsg, pTagCond->tbnameCond.cond, len);
+ }
+
pElem->tableCondLen = htonl(len);
-
- memcpy(pMsg, pTagCond->tbnameCond.cond, len);
pMsg += len;
}
@@ -2474,6 +2475,7 @@ int tscBuildMetricMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pDestCol->colIdx = htons(pCol->colIdx);
pDestCol->colId = htons(pDestCol->colId);
pDestCol->flag = htons(pDestCol->flag);
+ strncpy(pDestCol->name, pCol->name, tListLen(pCol->name));
pMsg += sizeof(SColIndexEx);
}
@@ -2913,6 +2915,9 @@ int tscProcessShowRsp(SSqlObj *pSql) {
index.columnIndex = i;
tscColumnBaseInfoInsert(pQueryInfo, &index);
tscFieldInfoSetValFromSchema(&pQueryInfo->fieldsInfo, i, &pMeterSchema[i]);
+
+ pQueryInfo->fieldsInfo.pSqlExpr[i] = tscSqlExprInsert(pQueryInfo, i, TSDB_FUNC_TS_DUMMY, &index,
+ pMeterSchema[i].type, pMeterSchema[i].bytes, pMeterSchema[i].bytes);
}
tscFieldInfoCalOffset(pQueryInfo);
diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c
index 26569313f300b916a7b17aa13ab7ab719ca4f2cf..2f3312b0b6dca5d8ec5db584b4ca732b91fcdcdf 100644
--- a/src/client/src/tscSql.c
+++ b/src/client/src/tscSql.c
@@ -13,8 +13,9 @@
* along with this program. If not, see .
*/
-#include "os.h"
+#include
#include "hash.h"
+#include "os.h"
#include "tcache.h"
#include "tlog.h"
#include "tnote.h"
@@ -208,7 +209,7 @@ int taos_query_imp(STscObj *pObj, SSqlObj *pSql) {
taosCleanUpHashTable(pSql->pTableHashList);
pSql->pTableHashList = NULL;
}
-
+
tscDump("%p pObj:%p, SQL: %s", pSql, pObj, pSql->sqlstr);
pRes->code = (uint8_t)tsParseSql(pSql, false);
@@ -374,9 +375,7 @@ int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) {
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
-// pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i, pQueryInfo->order) +
-// pRes->bytes[i] * (1 - pQueryInfo->order.order) * (pRes->numOfRows - 1);
- pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i, pQueryInfo->order);
+ pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i);
}
*rows = pRes->tsrow;
@@ -384,54 +383,115 @@ int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) {
return (pQueryInfo->order.order == TSQL_SO_DESC) ? pRes->numOfRows : -pRes->numOfRows;
}
+static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pField) {
+ SSqlRes *pRes = &pSql->res;
+
+ if (isNull(pRes->tsrow[columnIndex], pField->type)) {
+ pRes->tsrow[columnIndex] = NULL;
+ } else if (pField->type == TSDB_DATA_TYPE_NCHAR) {
+ // convert unicode to native code in a temporary buffer extra one byte for terminated symbol
+ if (pRes->buffer[columnIndex] == NULL) {
+ pRes->buffer[columnIndex] = malloc(pField->bytes + TSDB_NCHAR_SIZE);
+ }
+
+ /* string terminated char for binary data*/
+ memset(pRes->buffer[columnIndex], 0, pField->bytes + TSDB_NCHAR_SIZE);
+
+ if (taosUcs4ToMbs(pRes->tsrow[columnIndex], pField->bytes, pRes->buffer[columnIndex])) {
+ pRes->tsrow[columnIndex] = pRes->buffer[columnIndex];
+ } else {
+ tscError("%p charset:%s to %s. val:%ls convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, pRes->tsrow);
+ pRes->tsrow[columnIndex] = NULL;
+ }
+ }
+}
+
+static char *getArithemicInputSrc(void *param, char *name, int32_t colId) {
+ SArithmeticSupport *pSupport = (SArithmeticSupport *)param;
+ SSqlFunctionExpr * pExpr = pSupport->pExpr;
+
+ int32_t index = -1;
+ for (int32_t i = 0; i < pExpr->pBinExprInfo.numOfCols; ++i) {
+ if (strcmp(name, pExpr->pBinExprInfo.pReqColumns[i].name) == 0) {
+ index = i;
+ break;
+ }
+ }
+
+ assert(index >= 0 && index < pExpr->pBinExprInfo.numOfCols);
+ return pSupport->data[index] + pSupport->offset * pSupport->elemSize[index];
+}
+
static void **doSetResultRowData(SSqlObj *pSql) {
SSqlCmd *pCmd = &pSql->cmd;
SSqlRes *pRes = &pSql->res;
-
+
assert(pRes->row >= 0 && pRes->row <= pRes->numOfRows);
-
+
if (pRes->row >= pRes->numOfRows) { // all the results has returned to invoker
tfree(pRes->tsrow);
return pRes->tsrow;
}
-
- SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+ SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
+
+ //todo refactor move away
+ for(int32_t k = 0; k < pQueryInfo->exprsInfo.numOfExprs; ++k) {
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, k);
+
+ if (k > 0) {
+ SSqlExpr* pPrev = tscSqlExprGet(pQueryInfo, k - 1);
+ pExpr->offset = pPrev->offset + pPrev->resBytes;
+ }
+ }
+
int32_t num = 0;
- for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutputCols; ++i) {
- pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i, pQueryInfo->order) + pRes->bytes[i] * pRes->row;
+ for (int i = 0; i < tscNumOfFields(pQueryInfo); ++i) {
+ if (pQueryInfo->fieldsInfo.pSqlExpr[i] != NULL) {
+ SSqlExpr* pExpr = pQueryInfo->fieldsInfo.pSqlExpr[i];
+ pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i) + pExpr->resBytes * pRes->row;
+ } else {
+ assert(0);
+ }
// primary key column cannot be null in interval query, no need to check
- if (i == 0 && pQueryInfo->nAggTimeInterval > 0) {
+ if (i == 0 && pQueryInfo->intervalTime > 0) {
continue;
}
TAOS_FIELD *pField = tscFieldInfoGetField(pQueryInfo, i);
- if (isNull(pRes->tsrow[i], pField->type)) {
- pRes->tsrow[i] = NULL;
- } else if (pField->type == TSDB_DATA_TYPE_NCHAR) {
- // convert unicode to native code in a temporary buffer extra one byte for terminated symbol
- if (pRes->buffer[num] == NULL) {
- pRes->buffer[num] = malloc(pField->bytes + TSDB_NCHAR_SIZE);
- }
-
- /* string terminated char for binary data*/
- memset(pRes->buffer[num], 0, pField->bytes + TSDB_NCHAR_SIZE);
+ transferNcharData(pSql, i, pField);
- if (taosUcs4ToMbs(pRes->tsrow[i], pField->bytes, pRes->buffer[num])) {
- pRes->tsrow[i] = pRes->buffer[num];
- } else {
- tscError("%p charset:%s to %s. val:%ls convert failed.", pSql, DEFAULT_UNICODE_ENCODEC, tsCharset, pRes->tsrow);
- pRes->tsrow[i] = NULL;
+ // calculate the result from serveral other columns
+ if (pQueryInfo->fieldsInfo.pExpr != NULL && pQueryInfo->fieldsInfo.pExpr[i] != NULL) {
+ SArithmeticSupport *sas = (SArithmeticSupport *)calloc(1, sizeof(SArithmeticSupport));
+ sas->offset = 0;
+ sas->pExpr = pQueryInfo->fieldsInfo.pExpr[i];
+
+ sas->numOfCols = sas->pExpr->pBinExprInfo.numOfCols;
+
+ if (pRes->buffer[i] == NULL) {
+ pRes->buffer[i] = malloc(tscFieldInfoGetField(pQueryInfo, i)->bytes);
+ }
+
+ for(int32_t k = 0; k < sas->numOfCols; ++k) {
+ int32_t columnIndex = sas->pExpr->pBinExprInfo.pReqColumns[k].colIdxInBuf;
+ SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, columnIndex);
+
+ sas->elemSize[k] = pExpr->resBytes;
+ sas->data[k] = (pRes->data + pRes->numOfRows* pExpr->offset) + pRes->row*pExpr->resBytes;
}
+
+ tSQLBinaryExprCalcTraverse(sas->pExpr->pBinExprInfo.pBinExpr, 1, pRes->buffer[i], sas, TSQL_SO_ASC, getArithemicInputSrc);
+ pRes->tsrow[i] = pRes->buffer[i];
- num++;
+ free(sas); //todo optimization
}
}
assert(num <= pQueryInfo->fieldsInfo.numOfOutputCols);
-
- pRes->row++; // index increase one-step
+
+ pRes->row++; // index increase one-step
return pRes->tsrow;
}
@@ -473,7 +533,7 @@ static bool tscHashRemainDataInSubqueryResultSet(SSqlObj *pSql) {
if (pSql->pSubs[i] == 0) {
continue;
}
-
+
SSqlRes * pRes1 = &pSql->pSubs[i]->res;
SQueryInfo *pQueryInfo1 = tscGetQueryInfoDetail(&pSql->pSubs[i]->cmd, 0);
@@ -509,11 +569,10 @@ static void **tscBuildResFromSubqueries(SSqlObj *pSql) {
if (numOfTableHasRes >= 2) { // do merge result
- success = (doSetResultRowData(pSql->pSubs[0]) != NULL) &&
- (doSetResultRowData(pSql->pSubs[1]) != NULL);
- // TSKEY key1 = *(TSKEY *)pRes1->tsrow[0];
- // TSKEY key2 = *(TSKEY *)pRes2->tsrow[0];
- // printf("first:%" PRId64 ", second:%" PRId64 "\n", key1, key2);
+ success = (doSetResultRowData(pSql->pSubs[0]) != NULL) && (doSetResultRowData(pSql->pSubs[1]) != NULL);
+ // TSKEY key1 = *(TSKEY *)pRes1->tsrow[0];
+ // TSKEY key2 = *(TSKEY *)pRes2->tsrow[0];
+ // printf("first:%" PRId64 ", second:%" PRId64 "\n", key1, key2);
} else { // only one subquery
SSqlObj *pSub = pSql->pSubs[0];
if (pSub == NULL) {
@@ -603,7 +662,7 @@ TAOS_ROW taos_fetch_row_impl(TAOS_RES *res) {
tscProcessSql(pSql); // retrieve data from virtual node
- //if failed to retrieve data from current virtual node, try next one if exists
+ // if failed to retrieve data from current virtual node, try next one if exists
if (hasMoreVnodesToTry(pSql)) {
tscTryQueryNextVnode(pSql, NULL);
}
@@ -645,7 +704,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
// current subclause is completed, try the next subclause
while (rows == NULL && pCmd->clauseIndex < pCmd->numOfClause - 1) {
tscTryQueryNextClause(pSql, NULL);
-
+
// if the rows is not NULL, return immediately
rows = taos_fetch_row_impl(res);
}
@@ -708,7 +767,7 @@ int taos_select_db(TAOS *taos, const char *db) {
return taos_query(taos, sql);
}
-void taos_free_result_imp(TAOS_RES* res, int keepCmd) {
+void taos_free_result_imp(TAOS_RES *res, int keepCmd) {
if (res == NULL) return;
SSqlObj *pSql = (SSqlObj *)res;
@@ -761,7 +820,7 @@ void taos_free_result_imp(TAOS_RES* res, int keepCmd) {
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
tscTrace("%p code:%d, numOfRows:%d, command:%d", pSql, pRes->code, pRes->numOfRows, pCmd->command);
-
+
void *fp = pSql->fp;
if (fp != NULL) {
pSql->freed = 1;
@@ -808,9 +867,7 @@ void taos_free_result_imp(TAOS_RES* res, int keepCmd) {
}
}
-void taos_free_result(TAOS_RES *res) {
- taos_free_result_imp(res, 0);
-}
+void taos_free_result(TAOS_RES *res) { taos_free_result_imp(res, 0); }
int taos_errno(TAOS *taos) {
STscObj *pObj = (STscObj *)taos;
@@ -826,26 +883,24 @@ int taos_errno(TAOS *taos) {
return code;
}
-static bool validErrorCode(int32_t code) {
- return code >= TSDB_CODE_SUCCESS && code < TSDB_CODE_MAX_ERROR_CODE;
-}
+static bool validErrorCode(int32_t code) { return code >= TSDB_CODE_SUCCESS && code < TSDB_CODE_MAX_ERROR_CODE; }
/*
* In case of invalid sql error, additional information is attached to explain
* why the sql is invalid
*/
-static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd* pCmd) {
+static bool hasAdditionalErrorInfo(int32_t code, SSqlCmd *pCmd) {
if (code != TSDB_CODE_INVALID_SQL) {
return false;
}
size_t len = strlen(pCmd->payload);
-
- char* z = NULL;
+
+ char *z = NULL;
if (len > 0) {
- z = strstr (pCmd->payload, "invalid SQL");
+ z = strstr(pCmd->payload, "invalid SQL");
}
-
+
return z != NULL;
}
@@ -856,12 +911,12 @@ char *taos_errstr(TAOS *taos) {
if (pObj == NULL || pObj->signature != pObj)
return (char*)tstrerror(globalCode);
- SSqlObj* pSql = pObj->pSql;
-
+ SSqlObj *pSql = pObj->pSql;
+
if (validErrorCode(pSql->res.code)) {
code = pSql->res.code;
} else {
- code = TSDB_CODE_OTHERS; //unknown error
+ code = TSDB_CODE_OTHERS; // unknown error
}
if (hasAdditionalErrorInfo(code, &pSql->cmd)) {
@@ -954,14 +1009,14 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR: {
- size_t xlen = 0;
- for (xlen = 0; xlen <= fields[i].bytes; xlen++) {
- char c = ((char*)row[i])[xlen];
- if (c == 0) break;
- str[len++] = c;
- }
- str[len] = 0;
- } break;
+ size_t xlen = 0;
+ for (xlen = 0; xlen <= fields[i].bytes; xlen++) {
+ char c = ((char *)row[i])[xlen];
+ if (c == 0) break;
+ str[len++] = c;
+ }
+ str[len] = 0;
+ } break;
case TSDB_DATA_TYPE_TIMESTAMP:
len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
diff --git a/src/client/src/tscStream.c b/src/client/src/tscStream.c
index 79b524be0f8fd9b18847e03e9420941c6ec0c05c..5fd0adf5b15b31abe741dd51025e8e0a5a211230 100644
--- a/src/client/src/tscStream.c
+++ b/src/client/src/tscStream.c
@@ -246,8 +246,6 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
int32_t retry = tsProjectExecInterval;
tscError("%p stream:%p, retrieve no data, code:%d, retry in %" PRId64 "ms", pSql, pStream, numOfRows, retry);
- tscClearSqlMetaInfoForce(&(pStream->pSql->cmd));
-
tscSetRetryTimer(pStream, pStream->pSql, retry);
return;
}
@@ -381,41 +379,41 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
- if (pQueryInfo->nAggTimeInterval < minIntervalTime) {
+ if (pQueryInfo->intervalTime < minIntervalTime) {
tscWarn("%p stream:%p, original sample interval:%ld too small, reset to:%" PRId64 "", pSql, pStream,
- pQueryInfo->nAggTimeInterval, minIntervalTime);
- pQueryInfo->nAggTimeInterval = minIntervalTime;
+ pQueryInfo->intervalTime, minIntervalTime);
+ pQueryInfo->intervalTime = minIntervalTime;
}
- pStream->interval = pQueryInfo->nAggTimeInterval; // it shall be derived from sql string
+ pStream->interval = pQueryInfo->intervalTime; // it shall be derived from sql string
- if (pQueryInfo->nSlidingTime == 0) {
- pQueryInfo->nSlidingTime = pQueryInfo->nAggTimeInterval;
+ if (pQueryInfo->slidingTime == 0) {
+ pQueryInfo->slidingTime = pQueryInfo->intervalTime;
}
int64_t minSlidingTime =
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinSlidingTime * 1000L : tsMinSlidingTime;
- if (pQueryInfo->nSlidingTime == -1) {
- pQueryInfo->nSlidingTime = pQueryInfo->nAggTimeInterval;
- } else if (pQueryInfo->nSlidingTime < minSlidingTime) {
+ if (pQueryInfo->slidingTime == -1) {
+ pQueryInfo->slidingTime = pQueryInfo->intervalTime;
+ } else if (pQueryInfo->slidingTime < minSlidingTime) {
tscWarn("%p stream:%p, original sliding value:%" PRId64 " too small, reset to:%" PRId64 "", pSql, pStream,
- pQueryInfo->nSlidingTime, minSlidingTime);
+ pQueryInfo->slidingTime, minSlidingTime);
- pQueryInfo->nSlidingTime = minSlidingTime;
+ pQueryInfo->slidingTime = minSlidingTime;
}
- if (pQueryInfo->nSlidingTime > pQueryInfo->nAggTimeInterval) {
+ if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) {
tscWarn("%p stream:%p, sliding value:%" PRId64 " can not be larger than interval range, reset to:%" PRId64 "", pSql, pStream,
- pQueryInfo->nSlidingTime, pQueryInfo->nAggTimeInterval);
+ pQueryInfo->slidingTime, pQueryInfo->intervalTime);
- pQueryInfo->nSlidingTime = pQueryInfo->nAggTimeInterval;
+ pQueryInfo->slidingTime = pQueryInfo->intervalTime;
}
- pStream->slidingTime = pQueryInfo->nSlidingTime;
+ pStream->slidingTime = pQueryInfo->slidingTime;
- pQueryInfo->nAggTimeInterval = 0; // clear the interval value to avoid the force time window split by query processor
- pQueryInfo->nSlidingTime = 0;
+ pQueryInfo->intervalTime = 0; // clear the interval value to avoid the force time window split by query processor
+ pQueryInfo->slidingTime = 0;
}
static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, int64_t stime) {
diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c
index 624220c3734cdf642ea4c977adda77cf4baea931..2a5af0473c8bc5c8e40807c43ee1968a9ead24f0 100644
--- a/src/client/src/tscUtil.c
+++ b/src/client/src/tscUtil.c
@@ -27,6 +27,7 @@
#include "tsclient.h"
#include "tsqldef.h"
#include "ttimer.h"
+#include "tast.h"
/*
* the detailed information regarding metric meta key is:
@@ -64,7 +65,7 @@ void tscGetMetricMetaCacheKey(SQueryInfo* pQueryInfo, char* str, uint64_t uid) {
size_t redundantLen = 20;
size_t bufSize = strlen(pMeterMetaInfo->name) + tbnameCondLen + strlen(join) + strlen(tagIdBuf);
- if (cond != NULL) {
+ if (cond != NULL && cond->cond != NULL) {
bufSize += strlen(cond->cond);
}
@@ -72,7 +73,7 @@ void tscGetMetricMetaCacheKey(SQueryInfo* pQueryInfo, char* str, uint64_t uid) {
char* tmp = calloc(1, bufSize);
int32_t keyLen = snprintf(tmp, bufSize, "%s,%s,%s,%d,%s,[%s],%d", pMeterMetaInfo->name,
- (cond != NULL ? cond->cond : NULL), (tbnameCondLen > 0 ? pTagCond->tbnameCond.cond : NULL),
+ ((cond != NULL && cond->cond != NULL) ? cond->cond : NULL), (tbnameCondLen > 0 ? pTagCond->tbnameCond.cond : NULL),
pTagCond->relType, join, tagIdBuf, pQueryInfo->groupbyExpr.orderType);
assert(keyLen <= bufSize);
@@ -202,6 +203,9 @@ STableSidExtInfo* tscGetMeterSidInfo(SVnodeSidList* pSidList, int32_t idx) {
tscError("illegal sidIdx:%d, reset to 0, sidIdx range:%d-%d", idx, 0, sidRange);
idx = 0;
}
+
+ assert(pSidList->pSidExtInfoList[idx] >= 0);
+
return (STableSidExtInfo*)(pSidList->pSidExtInfoList[idx] + (char*)pSidList);
}
@@ -211,7 +215,16 @@ bool tscIsTwoStageMergeMetricQuery(SQueryInfo* pQueryInfo, int32_t tableIndex) {
}
SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, tableIndex);
- if (pMeterMetaInfo == NULL || pMeterMetaInfo->pMetricMeta == NULL) {
+ if (pMeterMetaInfo == NULL) {
+ return false;
+ }
+
+ // for select query super table, the metricmeta can not be null in any cases.
+ if (pQueryInfo->command == TSDB_SQL_SELECT && UTIL_METER_IS_SUPERTABLE(pMeterMetaInfo)) {
+ assert(pMeterMetaInfo->pMetricMeta != NULL);
+ }
+
+ if (pMeterMetaInfo->pMetricMeta == NULL) {
return false;
}
@@ -335,35 +348,17 @@ void tscClearInterpInfo(SQueryInfo* pQueryInfo) {
tfree(pQueryInfo->defaultVal);
}
-void tscClearSqlMetaInfoForce(SSqlCmd* pCmd) {
- /* remove the metermeta/metricmeta in cache */
- // taosRemoveDataFromCache(tscCacheHandle, (void**)&(pCmd->pMeterMeta), true);
- // taosRemoveDataFromCache(tscCacheHandle, (void**)&(pCmd->pMetricMeta), true);
-}
-
int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
if (pRes->tsrow == NULL) {
- pRes->numOfnchar = 0;
-
int32_t numOfOutputCols = pQueryInfo->fieldsInfo.numOfOutputCols;
- for (int32_t i = 0; i < numOfOutputCols; ++i) {
- TAOS_FIELD* pField = tscFieldInfoGetField(pQueryInfo, i);
- if (pField->type == TSDB_DATA_TYPE_NCHAR) {
- pRes->numOfnchar++;
- }
- }
+ pRes->numOfCols = numOfOutputCols;
- pRes->tsrow = calloc(1, (POINTER_BYTES + sizeof(short)) * numOfOutputCols + POINTER_BYTES * pRes->numOfnchar);
- pRes->bytes = calloc(numOfOutputCols, sizeof(short));
-
- if (pRes->numOfnchar > 0) {
- pRes->buffer = calloc(POINTER_BYTES, pRes->numOfnchar);
- }
+ pRes->tsrow = calloc(POINTER_BYTES, numOfOutputCols);
+ pRes->buffer = calloc(POINTER_BYTES, numOfOutputCols);
// not enough memory
- if (pRes->tsrow == NULL || pRes->bytes == NULL || (pRes->buffer == NULL && pRes->numOfnchar > 0)) {
+ if (pRes->tsrow == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) {
tfree(pRes->tsrow);
- tfree(pRes->bytes);
tfree(pRes->buffer);
pRes->code = TSDB_CODE_CLI_OUT_OF_MEMORY;
@@ -376,13 +371,12 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
void tscDestroyResPointerInfo(SSqlRes* pRes) {
if (pRes->buffer != NULL) {
- assert(pRes->numOfnchar > 0);
// free all buffers containing the multibyte string
- for (int i = 0; i < pRes->numOfnchar; i++) {
+ for (int i = 0; i < pRes->numOfCols; i++) {
tfree(pRes->buffer[i]);
}
- pRes->numOfnchar = 0;
+ pRes->numOfCols = 0;
}
tfree(pRes->pRsp);
@@ -391,7 +385,6 @@ void tscDestroyResPointerInfo(SSqlRes* pRes) {
tfree(pRes->pGroupRec);
tfree(pRes->pColumnIndex);
tfree(pRes->buffer);
- tfree(pRes->bytes);
pRes->data = NULL; // pRes->data points to the buffer of pRsp, no need to free
}
@@ -835,11 +828,18 @@ static void ensureSpace(SFieldInfo* pFieldInfo, int32_t size) {
pFieldInfo->pFields = realloc(pFieldInfo->pFields, newSize * sizeof(TAOS_FIELD));
memset(&pFieldInfo->pFields[oldSize], 0, inc * sizeof(TAOS_FIELD));
- pFieldInfo->pOffset = realloc(pFieldInfo->pOffset, newSize * sizeof(int16_t));
- memset(&pFieldInfo->pOffset[oldSize], 0, inc * sizeof(int16_t));
+// pFieldInfo->pOffset = realloc(pFieldInfo->pOffset, newSize * sizeof(int16_t));
+// memset(&pFieldInfo->pOffset[oldSize], 0, inc * sizeof(int16_t));
pFieldInfo->pVisibleCols = realloc(pFieldInfo->pVisibleCols, newSize * sizeof(bool));
+ memset(&pFieldInfo->pVisibleCols[oldSize], 0, inc * sizeof(bool));
+ pFieldInfo->pSqlExpr = realloc(pFieldInfo->pSqlExpr, POINTER_BYTES*newSize);
+ pFieldInfo->pExpr = realloc(pFieldInfo->pExpr, POINTER_BYTES*newSize);
+
+ memset(&pFieldInfo->pSqlExpr[oldSize], 0, inc * POINTER_BYTES);
+ memset(&pFieldInfo->pExpr[oldSize], 0, inc * POINTER_BYTES);
+
pFieldInfo->numOfAlloc = newSize;
}
}
@@ -848,6 +848,15 @@ static void evic(SFieldInfo* pFieldInfo, int32_t index) {
if (index < pFieldInfo->numOfOutputCols) {
memmove(&pFieldInfo->pFields[index + 1], &pFieldInfo->pFields[index],
sizeof(pFieldInfo->pFields[0]) * (pFieldInfo->numOfOutputCols - index));
+
+ memmove(&pFieldInfo->pVisibleCols[index + 1], &pFieldInfo->pVisibleCols[index],
+ sizeof(pFieldInfo->pVisibleCols[0]) * (pFieldInfo->numOfOutputCols - index));
+
+ memmove(&pFieldInfo->pSqlExpr[index + 1], &pFieldInfo->pSqlExpr[index],
+ sizeof(pFieldInfo->pSqlExpr[0]) * (pFieldInfo->numOfOutputCols - index));
+
+ memmove(&pFieldInfo->pExpr[index + 1], &pFieldInfo->pExpr[index],
+ sizeof(pFieldInfo->pExpr[0]) * (pFieldInfo->numOfOutputCols - index));
}
}
@@ -872,7 +881,6 @@ void tscFieldInfoSetValFromField(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIE
memcpy(&pFieldInfo->pFields[index], pField, sizeof(TAOS_FIELD));
pFieldInfo->pVisibleCols[index] = true;
-
pFieldInfo->numOfOutputCols++;
}
@@ -906,29 +914,49 @@ void tscFieldInfoSetValue(SFieldInfo* pFieldInfo, int32_t index, int8_t type, co
pFieldInfo->numOfOutputCols++;
}
-void tscFieldInfoCalOffset(SQueryInfo* pQueryInfo) {
- SFieldInfo* pFieldInfo = &pQueryInfo->fieldsInfo;
- pFieldInfo->pOffset[0] = 0;
+void tscFieldInfoSetExpr(SFieldInfo* pFieldInfo, int32_t index, SSqlExpr* pExpr) {
+ assert(index >= 0 && index < pFieldInfo->numOfOutputCols);
+ pFieldInfo->pSqlExpr[index] = pExpr;
+}
+
+void tscFieldInfoSetBinExpr(SFieldInfo* pFieldInfo, int32_t index, SSqlFunctionExpr* pExpr) {
+ assert(index >= 0 && index < pFieldInfo->numOfOutputCols);
+ pFieldInfo->pExpr[index] = pExpr;
+}
- for (int32_t i = 1; i < pFieldInfo->numOfOutputCols; ++i) {
- pFieldInfo->pOffset[i] = pFieldInfo->pOffset[i - 1] + pFieldInfo->pFields[i - 1].bytes;
+void tscFieldInfoCalOffset(SQueryInfo* pQueryInfo) {
+ SSqlExprInfo* pExprInfo = &pQueryInfo->exprsInfo;
+ pExprInfo->pExprs[0]->offset = 0;
+
+ for (int32_t i = 1; i < pExprInfo->numOfExprs; ++i) {
+ pExprInfo->pExprs[i]->offset = pExprInfo->pExprs[i - 1]->offset + pExprInfo->pExprs[i - 1]->resBytes;
}
}
void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo) {
- SFieldInfo* pFieldInfo = &pQueryInfo->fieldsInfo;
- if (pFieldInfo->numOfOutputCols == 0) {
+// SFieldInfo* pFieldInfo = &pQueryInfo->fieldsInfo;
+// if (pFieldInfo->numOfOutputCols == 0) {
+// return;
+// }
+//
+// pFieldInfo->pOffset[0] = 0;
+//
+// /*
+// * the retTypeLen is used to store the intermediate result length
+// * for potential secondary merge exists
+// */
+// for (int32_t i = 1; i < pFieldInfo->numOfOutputCols; ++i) {
+// pFieldInfo->pOffset[i] = pFieldInfo->pOffset[i - 1] + tscSqlExprGet(pQueryInfo, i - 1)->resBytes;
+// }
+ SSqlExprInfo* pExprInfo = &pQueryInfo->exprsInfo;
+ if (pExprInfo->numOfExprs == 0) {
return;
}
-
- pFieldInfo->pOffset[0] = 0;
-
- /*
- * the retTypeLen is used to store the intermediate result length
- * for potential secondary merge exists
- */
- for (int32_t i = 1; i < pFieldInfo->numOfOutputCols; ++i) {
- pFieldInfo->pOffset[i] = pFieldInfo->pOffset[i - 1] + tscSqlExprGet(pQueryInfo, i - 1)->resBytes;
+
+ pExprInfo->pExprs[0]->offset = 0;
+
+ for (int32_t i = 1; i < pExprInfo->numOfExprs; ++i) {
+ pExprInfo->pExprs[i]->offset = pExprInfo->pExprs[i - 1]->offset + pExprInfo->pExprs[i - 1]->resBytes;
}
}
@@ -944,6 +972,8 @@ void tscFieldInfoCopy(SFieldInfo* src, SFieldInfo* dst, const int32_t* indexList
for (int32_t i = 0; i < size; ++i) {
assert(indexList[i] >= 0 && indexList[i] <= src->numOfOutputCols);
tscFieldInfoSetValFromField(dst, i, &src->pFields[indexList[i]]);
+ dst->pVisibleCols[i] = src->pVisibleCols[indexList[i]];
+ dst->pSqlExpr[i] = src->pSqlExpr[indexList[i]];
}
}
}
@@ -952,12 +982,14 @@ void tscFieldInfoCopyAll(SFieldInfo* dst, SFieldInfo* src) {
*dst = *src;
dst->pFields = malloc(sizeof(TAOS_FIELD) * dst->numOfAlloc);
- dst->pOffset = malloc(sizeof(short) * dst->numOfAlloc);
dst->pVisibleCols = malloc(sizeof(bool) * dst->numOfAlloc);
+ dst->pSqlExpr = malloc(POINTER_BYTES * dst->numOfAlloc);
+ dst->pExpr = malloc(POINTER_BYTES * dst->numOfAlloc);
memcpy(dst->pFields, src->pFields, sizeof(TAOS_FIELD) * dst->numOfOutputCols);
- memcpy(dst->pOffset, src->pOffset, sizeof(short) * dst->numOfOutputCols);
memcpy(dst->pVisibleCols, src->pVisibleCols, sizeof(bool) * dst->numOfOutputCols);
+ memcpy(dst->pSqlExpr, src->pSqlExpr, POINTER_BYTES * dst->numOfOutputCols);
+ memcpy(dst->pExpr, src->pExpr, POINTER_BYTES * dst->numOfOutputCols);
}
TAOS_FIELD* tscFieldInfoGetField(SQueryInfo* pQueryInfo, int32_t index) {
@@ -971,11 +1003,11 @@ TAOS_FIELD* tscFieldInfoGetField(SQueryInfo* pQueryInfo, int32_t index) {
int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQueryInfo->fieldsInfo.numOfOutputCols; }
int16_t tscFieldInfoGetOffset(SQueryInfo* pQueryInfo, int32_t index) {
- if (index >= pQueryInfo->fieldsInfo.numOfOutputCols) {
+ if (index >= pQueryInfo->exprsInfo.numOfExprs) {
return 0;
}
- return pQueryInfo->fieldsInfo.pOffset[index];
+ return pQueryInfo->exprsInfo.pExprs[index]->offset;
}
int32_t tscFieldInfoCompare(SFieldInfo* pFieldInfo1, SFieldInfo* pFieldInfo2) {
@@ -999,13 +1031,16 @@ int32_t tscFieldInfoCompare(SFieldInfo* pFieldInfo1, SFieldInfo* pFieldInfo2) {
}
int32_t tscGetResRowLength(SQueryInfo* pQueryInfo) {
- SFieldInfo* pFieldInfo = &pQueryInfo->fieldsInfo;
- if (pFieldInfo->numOfOutputCols <= 0) {
+ if (pQueryInfo->exprsInfo.numOfExprs <= 0) {
return 0;
}
-
- return pFieldInfo->pOffset[pFieldInfo->numOfOutputCols - 1] +
- pFieldInfo->pFields[pFieldInfo->numOfOutputCols - 1].bytes;
+
+ int32_t size = 0;
+ for(int32_t i = 0; i < pQueryInfo->exprsInfo.numOfExprs; ++i) {
+ size += pQueryInfo->exprsInfo.pExprs[i]->resBytes;
+ }
+
+ return size;
}
void tscClearFieldInfo(SFieldInfo* pFieldInfo) {
@@ -1013,10 +1048,19 @@ void tscClearFieldInfo(SFieldInfo* pFieldInfo) {
return;
}
- tfree(pFieldInfo->pOffset);
tfree(pFieldInfo->pFields);
tfree(pFieldInfo->pVisibleCols);
-
+ tfree(pFieldInfo->pSqlExpr);
+
+ for(int32_t i = 0; i < pFieldInfo->numOfOutputCols; ++i) {
+ if (pFieldInfo->pExpr[i] != NULL) {
+ tSQLBinaryExprDestroy(&pFieldInfo->pExpr[i]->pBinExprInfo.pBinExpr, NULL);
+ tfree(pFieldInfo->pExpr[i]->pBinExprInfo.pReqColumns);
+ tfree(pFieldInfo->pExpr[i]);
+ }
+ }
+
+ tfree(pFieldInfo->pExpr);
memset(pFieldInfo, 0, sizeof(SFieldInfo));
}
@@ -1054,11 +1098,12 @@ SSqlExpr* tscSqlExprInsertEmpty(SQueryInfo* pQueryInfo, int32_t index, int16_t f
_exprCheckSpace(pExprInfo, pExprInfo->numOfExprs + 1);
_exprEvic(pExprInfo, index);
-
- SSqlExpr* pExpr = &pExprInfo->pExprs[index];
+
+ SSqlExpr* pExpr = calloc(1, sizeof(SSqlExpr));
pExpr->functionId = functionId;
-
+
pExprInfo->numOfExprs++;
+ pExprInfo->pExprs[index] = pExpr;
return pExpr;
}
@@ -1071,8 +1116,9 @@ SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functi
_exprCheckSpace(pExprInfo, pExprInfo->numOfExprs + 1);
_exprEvic(pExprInfo, index);
- SSqlExpr* pExpr = &pExprInfo->pExprs[index];
-
+ SSqlExpr* pExpr = calloc(1, sizeof(SSqlExpr));
+ pExprInfo->pExprs[index] = pExpr;
+
pExpr->functionId = functionId;
int16_t numOfCols = pMeterMetaInfo->pMeterMeta->numOfColumns;
@@ -1114,7 +1160,7 @@ SSqlExpr* tscSqlExprUpdate(SQueryInfo* pQueryInfo, int32_t index, int16_t functi
return NULL;
}
- SSqlExpr* pExpr = &pExprInfo->pExprs[index];
+ SSqlExpr* pExpr = pExprInfo->pExprs[index];
pExpr->functionId = functionId;
@@ -1127,6 +1173,10 @@ SSqlExpr* tscSqlExprUpdate(SQueryInfo* pQueryInfo, int32_t index, int16_t functi
return pExpr;
}
+int32_t tscSqlExprNumOfExprs(SQueryInfo* pQueryInfo) {
+ return pQueryInfo->exprsInfo.numOfExprs;
+}
+
void addExprParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes, int16_t tableIndex) {
if (pExpr == NULL || argument == NULL || bytes == 0) {
return;
@@ -1145,7 +1195,7 @@ SSqlExpr* tscSqlExprGet(SQueryInfo* pQueryInfo, int32_t index) {
return NULL;
}
- return &pQueryInfo->exprsInfo.pExprs[index];
+ return pQueryInfo->exprsInfo.pExprs[index];
}
void* tscSqlExprDestroy(SSqlExpr* pExpr) {
@@ -1157,6 +1207,8 @@ void* tscSqlExprDestroy(SSqlExpr* pExpr) {
tVariantDestroy(&pExpr->param[i]);
}
+ tfree(pExpr);
+
return NULL;
}
@@ -1168,8 +1220,8 @@ void tscSqlExprInfoDestroy(SSqlExprInfo* pExprInfo) {
return;
}
- for(int32_t i = 0; i < pExprInfo->numOfAlloc; ++i) {
- tscSqlExprDestroy(&pExprInfo->pExprs[i]);
+ for(int32_t i = 0; i < pExprInfo->numOfExprs; ++i) {
+ tscSqlExprDestroy(pExprInfo->pExprs[i]);
}
tfree(pExprInfo->pExprs);
@@ -1179,27 +1231,40 @@ void tscSqlExprInfoDestroy(SSqlExprInfo* pExprInfo) {
}
-void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t tableuid) {
+void tscSqlExprCopy(SSqlExprInfo* dst, const SSqlExprInfo* src, uint64_t tableuid, bool deepcopy) {
if (src == NULL) {
return;
}
*dst = *src;
- dst->pExprs = calloc(dst->numOfAlloc, sizeof(SSqlExpr));
+ dst->pExprs = calloc(dst->numOfAlloc, POINTER_BYTES);
+
int16_t num = 0;
for (int32_t i = 0; i < src->numOfExprs; ++i) {
- if (src->pExprs[i].uid == tableuid) {
- dst->pExprs[num++] = src->pExprs[i];
+ if (src->pExprs[i]->uid == tableuid) {
+
+ if (deepcopy) {
+ dst->pExprs[num] = calloc(1, sizeof(SSqlExpr));
+ *dst->pExprs[num] = *src->pExprs[i];
+ } else {
+ dst->pExprs[num] = src->pExprs[i];
+ }
+
+ num++;
}
}
dst->numOfExprs = num;
- for (int32_t i = 0; i < dst->numOfExprs; ++i) {
- for (int32_t j = 0; j < src->pExprs[i].numOfParams; ++j) {
- tVariantAssign(&dst->pExprs[i].param[j], &src->pExprs[i].param[j]);
+
+ if (deepcopy) {
+ for (int32_t i = 0; i < dst->numOfExprs; ++i) {
+ for (int32_t j = 0; j < src->pExprs[i]->numOfParams; ++j) {
+ tVariantAssign(&dst->pExprs[i]->param[j], &src->pExprs[i]->param[j]);
+ }
}
}
+
}
static void clearVal(SColumnBase* pBase) {
@@ -1954,7 +2019,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
}
uint64_t uid = pMeterMetaInfo->pMeterMeta->uid;
- tscSqlExprCopy(&pNewQueryInfo->exprsInfo, &pQueryInfo->exprsInfo, uid);
+ tscSqlExprCopy(&pNewQueryInfo->exprsInfo, &pQueryInfo->exprsInfo, uid, true);
int32_t numOfOutputCols = pNewQueryInfo->exprsInfo.numOfExprs;
@@ -1969,7 +2034,19 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
tscFieldInfoCopy(&pQueryInfo->fieldsInfo, &pNewQueryInfo->fieldsInfo, indexList, numOfOutputCols);
free(indexList);
-
+
+ // make sure the the sqlExpr for each fields is correct
+// todo handle the agg arithmetic expression
+ for(int32_t f = 0; f < pNewQueryInfo->fieldsInfo.numOfOutputCols; ++f) {
+ char* name = pNewQueryInfo->fieldsInfo.pFields[f].name;
+ for(int32_t k1 = 0; k1 < pNewQueryInfo->exprsInfo.numOfExprs; ++k1) {
+ SSqlExpr* pExpr1 = tscSqlExprGet(pNewQueryInfo, k1);
+ if (strcmp(name, pExpr1->aliasName) == 0) {
+ pNewQueryInfo->fieldsInfo.pSqlExpr[f] = pExpr1;
+ }
+ }
+ }
+
tscFieldInfoUpdateOffsetForInterResult(pNewQueryInfo);
}
diff --git a/src/connector/jdbc/CMakeLists.txt b/src/connector/jdbc/CMakeLists.txt
index 56a65a8ab526ad901941768938416f8bb10704c9..05c8bebafe79469466fa956c479aab80ccbc5943 100644
--- a/src/connector/jdbc/CMakeLists.txt
+++ b/src/connector/jdbc/CMakeLists.txt
@@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
POST_BUILD
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
- COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-1.0.2-dist.jar ${LIBRARY_OUTPUT_PATH}
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-1.0.3-dist.jar ${LIBRARY_OUTPUT_PATH}
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
COMMENT "build jdbc driver")
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml
index 75abea9edcd4b2f14d69feeb885669801b54700d..36f1a1010c372b319fab7fceaf13c9c44689dc6b 100755
--- a/src/connector/jdbc/pom.xml
+++ b/src/connector/jdbc/pom.xml
@@ -4,7 +4,7 @@
com.taosdata.jdbc
taos-jdbcdriver
- 1.0.2
+ 1.0.3
jar
JDBCDriver
diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h
index cb2a286e64ece3b7c58bd7197d2fe10124cd27fe..f74bff7e57fa5a0e9773263d23ea536068ef866e 100644
--- a/src/inc/taosmsg.h
+++ b/src/inc/taosmsg.h
@@ -359,6 +359,7 @@ typedef struct SColIndexEx {
int16_t colIdx;
int16_t colIdxInBuf;
uint16_t flag; // denote if it is a tag or not
+ char name[TSDB_COL_NAME_LEN];
} SColIndexEx;
/* sql function msg, to describe the message to vnode about sql function
@@ -456,7 +457,7 @@ typedef struct {
int16_t numOfCols; // the number of columns will be load from vnode
char intervalTimeUnit; // time interval type, for revisement of interval(1d)
- int64_t nAggTimeInterval; // time interval for aggregation, in million second
+ int64_t intervalTime; // time interval for aggregation, in million second
int64_t slidingTime; // value for sliding window
// tag schema, used to parse tag information in pSidExtInfo
diff --git a/src/inc/tresultBuf.h b/src/inc/tresultBuf.h
index a464479af27a7e8515f4260c0ea6a73aed780933..b99c44e73fcbd834152640b80f8a59728c7cfd8f 100644
--- a/src/inc/tresultBuf.h
+++ b/src/inc/tresultBuf.h
@@ -14,7 +14,7 @@ typedef struct SIDList {
int32_t* pData;
} SIDList;
-typedef struct SQueryResultBuf {
+typedef struct SQueryDiskbasedResultBuf {
int32_t numOfRowsPerPage;
int32_t numOfPages;
int64_t totalBufSize;
@@ -27,7 +27,7 @@ typedef struct SQueryResultBuf {
uint32_t numOfAllocGroupIds; // number of allocated id list
void* idsTable; // id hash table
SIDList* list; // for each id, there is a page id list
-} SQueryResultBuf;
+} SQueryDiskbasedResultBuf;
/**
* create disk-based result buffer
@@ -36,7 +36,7 @@ typedef struct SQueryResultBuf {
* @param rowSize
* @return
*/
-int32_t createResultBuf(SQueryResultBuf** pResultBuf, int32_t size, int32_t rowSize);
+int32_t createDiskbasedResultBuffer(SQueryDiskbasedResultBuf** pResultBuf, int32_t size, int32_t rowSize);
/**
*
@@ -45,14 +45,14 @@ int32_t createResultBuf(SQueryResultBuf** pResultBuf, int32_t size, int32_t rowS
* @param pageId
* @return
*/
-tFilePage* getNewDataBuf(SQueryResultBuf* pResultBuf, int32_t groupId, int32_t* pageId);
+tFilePage* getNewDataBuf(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId);
/**
*
* @param pResultBuf
* @return
*/
-int32_t getNumOfRowsPerPage(SQueryResultBuf* pResultBuf);
+int32_t getNumOfRowsPerPage(SQueryDiskbasedResultBuf* pResultBuf);
/**
*
@@ -60,7 +60,7 @@ int32_t getNumOfRowsPerPage(SQueryResultBuf* pResultBuf);
* @param groupId
* @return
*/
-SIDList getDataBufPagesIdList(SQueryResultBuf* pResultBuf, int32_t groupId);
+SIDList getDataBufPagesIdList(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId);
/**
* get the specified buffer page by id
@@ -68,27 +68,27 @@ SIDList getDataBufPagesIdList(SQueryResultBuf* pResultBuf, int32_t groupId);
* @param id
* @return
*/
-tFilePage* getResultBufferPageById(SQueryResultBuf* pResultBuf, int32_t id);
+tFilePage* getResultBufferPageById(SQueryDiskbasedResultBuf* pResultBuf, int32_t id);
/**
* get the total buffer size in the format of disk file
* @param pResultBuf
* @return
*/
-int32_t getResBufSize(SQueryResultBuf* pResultBuf);
+int32_t getResBufSize(SQueryDiskbasedResultBuf* pResultBuf);
/**
* get the number of groups in the result buffer
* @param pResultBuf
* @return
*/
-int32_t getNumOfResultBufGroupId(SQueryResultBuf* pResultBuf);
+int32_t getNumOfResultBufGroupId(SQueryDiskbasedResultBuf* pResultBuf);
/**
* destroy result buffer
* @param pResultBuf
*/
-void destroyResultBuf(SQueryResultBuf* pResultBuf);
+void destroyResultBuf(SQueryDiskbasedResultBuf* pResultBuf);
/**
*
diff --git a/src/plugins/http/inc/httpHandle.h b/src/plugins/http/inc/httpHandle.h
index c564337187088b9ced276984c1a5cdec210c6af8..9c6a263c5bd328ca0fc59eb5365f7722324ef729 100644
--- a/src/plugins/http/inc/httpHandle.h
+++ b/src/plugins/http/inc/httpHandle.h
@@ -37,7 +37,7 @@
#define HTTP_STEP_SIZE 1024 //http message get process step by step
#define HTTP_MAX_URL 5 //http url stack size
#define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size
-#define HTTP_GC_TARGET_SIZE 128
+#define HTTP_GC_TARGET_SIZE 512
#define HTTP_VERSION_10 0
#define HTTP_VERSION_11 1
diff --git a/src/plugins/http/src/gcJson.c b/src/plugins/http/src/gcJson.c
index 1a86c5d24f23ec62bb1c51aabdd0639940edc54a..8f596337146a3937df72287f332917b3bffa21ac 100644
--- a/src/plugins/http/src/gcJson.c
+++ b/src/plugins/http/src/gcJson.c
@@ -127,42 +127,43 @@ bool gcBuildQueryJson(HttpContext *pContext, HttpSqlCmd *cmd, TAOS_RES *result,
// for group by
if (groupFields != -1) {
char target[HTTP_GC_TARGET_SIZE];
+ int len;
+ len = snprintf(target,HTTP_GC_TARGET_SIZE,"%s{",aliasBuffer);
+ for (int i = dataFields + 1; inum++;
pObj->size++;
-
-// char key[512] = {0};
-// memcpy(key, pNode->key, MIN(512, pNode->keyLen));
-// pTrace("key:%s %p add to hash table", key, pNode);
}
int32_t taosNumElemsInHashTable(HashObj *pObj) {
@@ -525,29 +521,3 @@ int32_t taosGetHashMaxOverflowLength(HashObj* pObj) {
return num;
}
-
-int32_t taosCheckHashTable(HashObj *pObj) {
- for(int32_t i = 0; i < pObj->capacity; ++i) {
- SHashEntry *pEntry = pObj->hashList[i];
-
- SHashNode* pNode = pEntry->next;
- if (pNode != NULL) {
- assert(pEntry == pNode->prev1);
- int32_t num = 1;
-
- SHashNode* pNext = pNode->next;
-
- while(pNext) {
- assert(pNext->prev == pNode);
-
- pNode = pNext;
- pNext = pNext->next;
- num ++;
- }
-
- assert(num == pEntry->num);
- }
- }
-
- return 0;
-}
diff --git a/src/util/src/textbuffer.c b/src/util/src/textbuffer.c
index 860de6782be97ce83032cf60d3d2f303af18c795..8ce090d335ea8105d22d2342de9d9a3e61b4592f 100644
--- a/src/util/src/textbuffer.c
+++ b/src/util/src/textbuffer.c
@@ -468,8 +468,8 @@ int32_t compare_a(tOrderDescriptor *pDescriptor, int32_t numOfRows1, int32_t s1,
return ret;
}
} else {
- SSchema *pSchema = &pDescriptor->pColumnModel->pFields[colIdx];
- int32_t ret = columnValueAscendingComparator(f1, f2, pSchema->type, pSchema->bytes);
+ SSchemaEx *pSchema = &pDescriptor->pColumnModel->pFields[colIdx];
+ int32_t ret = columnValueAscendingComparator(f1, f2, pSchema->field.type, pSchema->field.bytes);
if (ret == 0) {
continue;
} else {
@@ -500,8 +500,8 @@ int32_t compare_d(tOrderDescriptor *pDescriptor, int32_t numOfRows1, int32_t s1,
return ret;
}
} else {
- SSchema *pSchema = &pDescriptor->pColumnModel->pFields[colIdx];
- int32_t ret = columnValueAscendingComparator(f1, f2, pSchema->type, pSchema->bytes);
+ SSchemaEx *pSchema = &pDescriptor->pColumnModel->pFields[colIdx];
+ int32_t ret = columnValueAscendingComparator(f1, f2, pSchema->field.type, pSchema->field.bytes);
if (ret == 0) {
continue;
} else {
diff --git a/src/util/src/tinterpolation.c b/src/util/src/tinterpolation.c
index 82cc52cd42ef2a4c8c40d61d40aa6e956b96a1be..cb7c8854ce914d22680db5429871857ac445f1fe 100644
--- a/src/util/src/tinterpolation.c
+++ b/src/util/src/tinterpolation.c
@@ -13,9 +13,6 @@
* along with this program. If not, see .
*/
-#include
-#include
-
#include "os.h"
#include "taosmsg.h"
#include "textbuffer.h"
@@ -47,7 +44,7 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t timeRange, char
char** tzname = _tzname;
#endif
- int64_t t = (precision == TSDB_TIME_PRECISION_MILLI)?MILLISECOND_PER_SECOND:MILLISECOND_PER_SECOND*1000L;
+ int64_t t = (precision == TSDB_TIME_PRECISION_MILLI) ? MILLISECOND_PER_SECOND : MILLISECOND_PER_SECOND * 1000L;
int64_t revStartime = (startTime / timeRange) * timeRange + timezone * t;
int64_t revEndtime = revStartime + timeRange - 1;
@@ -78,14 +75,14 @@ void taosInitInterpoInfo(SInterpolationInfo* pInterpoInfo, int32_t order, int64_
}
// the SInterpolationInfo itself will not be released
-void taosDestoryInterpoInfo(SInterpolationInfo *pInterpoInfo) {
+void taosDestoryInterpoInfo(SInterpolationInfo* pInterpoInfo) {
if (pInterpoInfo == NULL) {
return;
}
-
+
tfree(pInterpoInfo->prevValues);
tfree(pInterpoInfo->nextValues);
-
+
tfree(pInterpoInfo->pTags);
}
@@ -94,7 +91,7 @@ void taosInterpoSetStartInfo(SInterpolationInfo* pInterpoInfo, int32_t numOfRawD
return;
}
- pInterpoInfo->rowIdx = 0;//INTERPOL_IS_ASC_INTERPOL(pInterpoInfo) ? 0 : numOfRawDataInRows - 1;
+ pInterpoInfo->rowIdx = 0;
pInterpoInfo->numOfRawDataInRows = numOfRawDataInRows;
}
@@ -118,14 +115,9 @@ int32_t taosGetNumOfResWithoutLimit(SInterpolationInfo* pInterpoInfo, int64_t* p
if (numOfAvailRawData > 0) {
int32_t finalNumOfResult = 0;
-// if (pInterpoInfo->order == TSQL_SO_ASC) {
- // get last timestamp, calculate the result size
- int64_t lastKey = pPrimaryKeyArray[pInterpoInfo->numOfRawDataInRows - 1];
- finalNumOfResult = (int32_t)(labs(lastKey - pInterpoInfo->startTimestamp) / nInterval) + 1;
-// } else { // todo error less than one!!!
-// TSKEY lastKey = pPrimaryKeyArray[0];
-// finalNumOfResult = (int32_t)((pInterpoInfo->startTimestamp - lastKey) / nInterval) + 1;
-// }
+ // get last timestamp, calculate the result size
+ int64_t lastKey = pPrimaryKeyArray[pInterpoInfo->numOfRawDataInRows - 1];
+ finalNumOfResult = (int32_t)(labs(lastKey - pInterpoInfo->startTimestamp) / nInterval) + 1;
assert(finalNumOfResult >= numOfAvailRawData);
return finalNumOfResult;
@@ -140,7 +132,9 @@ int32_t taosGetNumOfResWithoutLimit(SInterpolationInfo* pInterpoInfo, int64_t* p
}
}
-bool taosHasRemainsDataForInterpolation(SInterpolationInfo* pInterpoInfo) { return taosNumOfRemainPoints(pInterpoInfo) > 0; }
+bool taosHasRemainsDataForInterpolation(SInterpolationInfo* pInterpoInfo) {
+ return taosNumOfRemainPoints(pInterpoInfo) > 0;
+}
int32_t taosNumOfRemainPoints(SInterpolationInfo* pInterpoInfo) {
if (pInterpoInfo->rowIdx == -1 || pInterpoInfo->numOfRawDataInRows == 0) {
@@ -197,28 +191,22 @@ int taosDoLinearInterpolation(int32_t type, SPoint* point1, SPoint* point2, SPoi
return 0;
}
-static char* getPos(char* data, int32_t bytes, int32_t order, int32_t capacity, int32_t index) {
-// if (order == TSQL_SO_ASC) {
- return data + index * bytes;
-// } else {
-// return data + (capacity - index - 1) * bytes;
-// }
-}
+static char* getPos(char* data, int32_t bytes, int32_t index) { return data + index * bytes; }
-static void setTagsValueInInterpolation(tFilePage** data, char** pTags, SColumnModel* pModel, int32_t order, int32_t start,
- int32_t capacity, int32_t num) {
+static void setTagsValueInInterpolation(tFilePage** data, char** pTags, SColumnModel* pModel, int32_t order,
+ int32_t start, int32_t capacity, int32_t num) {
for (int32_t j = 0, i = start; i < pModel->numOfCols; ++i, ++j) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, order, capacity, num);
+
+ char* val1 = getPos(data[i]->data, pSchema->bytes, num);
assignVal(val1, pTags[j], pSchema->bytes, pSchema->type);
}
}
static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interpoType, tFilePage** data,
- SColumnModel* pModel, int32_t* num, char** srcData, int64_t nInterval, int64_t* defaultVal,
- int64_t currentTimestamp, int32_t capacity, int32_t numOfTags, char** pTags,
- bool outOfBound) {
+ SColumnModel* pModel, int32_t* num, char** srcData, int64_t nInterval,
+ int64_t* defaultVal, int64_t currentTimestamp, int32_t capacity, int32_t numOfTags,
+ char** pTags, bool outOfBound) {
char** prevValues = &pInterpoInfo->prevValues;
char** nextValues = &pInterpoInfo->nextValues;
@@ -226,7 +214,7 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pInterpoInfo->order);
- char* val = getPos(data[0]->data, TSDB_KEYSIZE, pInterpoInfo->order, capacity, *num);
+ char* val = getPos(data[0]->data, TSDB_KEYSIZE, *num);
*(TSKEY*)val = pInterpoInfo->startTimestamp;
int32_t numOfValCols = pModel->numOfCols - numOfTags;
@@ -237,9 +225,9 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
if (pInterpolationData != NULL) {
for (int32_t i = 1; i < numOfValCols; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
- int16_t offset = getColumnModelOffset(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, capacity, *num);
+ int16_t offset = getColumnModelOffset(pModel, i);
+
+ char* val1 = getPos(data[i]->data, pSchema->bytes, *num);
if (isNull(pInterpolationData + offset, pSchema->type)) {
setNull(val1, pSchema->type, pSchema->bytes);
@@ -250,8 +238,8 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
} else { /* no prev value yet, set the value for null */
for (int32_t i = 1; i < numOfValCols; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, capacity, *num);
+
+ char* val1 = getPos(data[i]->data, pSchema->bytes, *num);
setNull(val1, pSchema->type, pSchema->bytes);
}
}
@@ -262,10 +250,10 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
if (*prevValues != NULL && !outOfBound) {
for (int32_t i = 1; i < numOfValCols; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
- int16_t offset = getColumnModelOffset(pModel, i);
-
+ int16_t offset = getColumnModelOffset(pModel, i);
+
int16_t type = pSchema->type;
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, capacity, *num);
+ char* val1 = getPos(data[i]->data, pSchema->bytes, *num);
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BOOL) {
setNull(val1, type, pSchema->bytes);
@@ -283,8 +271,8 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
} else {
for (int32_t i = 1; i < numOfValCols; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, capacity, *num);
+
+ char* val1 = getPos(data[i]->data, pSchema->bytes, *num);
setNull(val1, pSchema->type, pSchema->bytes);
}
@@ -293,8 +281,8 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
} else { /* default value interpolation */
for (int32_t i = 1; i < numOfValCols; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, capacity, *num);
+
+ char* val1 = getPos(data[i]->data, pSchema->bytes, *num);
assignVal(val1, (char*)&defaultVal[i], pSchema->bytes, pSchema->type);
}
@@ -307,6 +295,20 @@ static void doInterpoResultImpl(SInterpolationInfo* pInterpoInfo, int16_t interp
(*num) += 1;
}
+static void initBeforeAfterDataBuf(SColumnModel* pModel, char** nextValues) {
+ if (*nextValues != NULL) {
+ return;
+ }
+
+ *nextValues = calloc(1, pModel->rowSize);
+ for (int i = 1; i < pModel->numOfCols; i++) {
+ int16_t offset = getColumnModelOffset(pModel, i);
+ SSchema* pSchema = getColumnModelSchema(pModel, i);
+
+ setNull(*nextValues + offset, pSchema->type, pSchema->bytes);
+ }
+}
+
int32_t taosDoInterpoResult(SInterpolationInfo* pInterpoInfo, int16_t interpoType, tFilePage** data,
int32_t numOfRawDataInRows, int32_t outputRows, int64_t nInterval,
const int64_t* pPrimaryKeyArray, SColumnModel* pModel, char** srcData, int64_t* defaultVal,
@@ -341,71 +343,58 @@ int32_t taosDoInterpoResult(SInterpolationInfo* pInterpoInfo, int16_t interpoTyp
if ((pInterpoInfo->startTimestamp < currentTimestamp && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
(pInterpoInfo->startTimestamp > currentTimestamp && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) {
/* set the next value for interpolation */
- if (*nextValues == NULL) {
- *nextValues = calloc(1, pModel->rowSize);
- for (int i = 1; i < pModel->numOfCols; i++) {
- int16_t offset = getColumnModelOffset(pModel, i);
- SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- setNull(*nextValues + offset, pSchema->type, pSchema->bytes);
- }
- }
-
+ initBeforeAfterDataBuf(pModel, nextValues);
+
int32_t offset = pInterpoInfo->rowIdx;
for (int32_t tlen = 0, i = 0; i < pModel->numOfCols - numOfTags; ++i) {
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
+
memcpy(*nextValues + tlen, srcData[i] + offset * pSchema->bytes, pSchema->bytes);
tlen += pSchema->bytes;
}
}
- while (((pInterpoInfo->startTimestamp < currentTimestamp && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
- (pInterpoInfo->startTimestamp > currentTimestamp && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) &&
- num < outputRows) {
- doInterpoResultImpl(pInterpoInfo, interpoType, data, pModel, &num, srcData, nInterval, defaultVal,
- currentTimestamp, bufSize, numOfTags, pTags, false);
- }
-
- /* output buffer is full, abort */
- if ((num == outputRows && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
- (num < 0 && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) {
- pInterpoInfo->numOfTotalInterpo += pInterpoInfo->numOfCurrentInterpo;
- return outputRows;
- }
-
- if (pInterpoInfo->startTimestamp == currentTimestamp) {
- if (*prevValues == NULL) {
- *prevValues = calloc(1, pModel->rowSize);
- for (int i = 1; i < pModel->numOfCols; i++) {
- int16_t offset = getColumnModelOffset(pModel, i);
- SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- setNull(*prevValues + offset, pSchema->type, pSchema->bytes);
- }
+ if (((pInterpoInfo->startTimestamp < currentTimestamp && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
+ (pInterpoInfo->startTimestamp > currentTimestamp && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) &&
+ num < outputRows) {
+ while (((pInterpoInfo->startTimestamp < currentTimestamp && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
+ (pInterpoInfo->startTimestamp > currentTimestamp && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) &&
+ num < outputRows) {
+ doInterpoResultImpl(pInterpoInfo, interpoType, data, pModel, &num, srcData, nInterval, defaultVal,
+ currentTimestamp, bufSize, numOfTags, pTags, false);
}
+ /* output buffer is full, abort */
+ if ((num == outputRows && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
+ (num < 0 && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo))) {
+ pInterpoInfo->numOfTotalInterpo += pInterpoInfo->numOfCurrentInterpo;
+ return outputRows;
+ }
+ } else {
+ assert(pInterpoInfo->startTimestamp == currentTimestamp);
+
+ initBeforeAfterDataBuf(pModel, prevValues);
+
// assign rows to dst buffer
int32_t i = 0;
for (int32_t tlen = 0; i < pModel->numOfCols - numOfTags; ++i) {
- int16_t offset = getColumnModelOffset(pModel, i);
+ int16_t offset = getColumnModelOffset(pModel, i);
SSchema* pSchema = getColumnModelSchema(pModel, i);
-
- char* val1 = getPos(data[i]->data, pSchema->bytes, pInterpoInfo->order, bufSize, num);
+ char* val1 = getPos(data[i]->data, pSchema->bytes, num);
+ char* src = srcData[i] + pInterpoInfo->rowIdx * pSchema->bytes;
+
if (i == 0 ||
- (functionIDs[i] != TSDB_FUNC_COUNT &&
- !isNull(srcData[i] + pInterpoInfo->rowIdx * pSchema->bytes, pSchema->type)) ||
- (functionIDs[i] == TSDB_FUNC_COUNT &&
- *(int64_t*)(srcData[i] + pInterpoInfo->rowIdx * pSchema->bytes) != 0)) {
-
- assignVal(val1, srcData[i] + pInterpoInfo->rowIdx * pSchema->bytes, pSchema->bytes, pSchema->type);
- memcpy(*prevValues + tlen, srcData[i] + pInterpoInfo->rowIdx * pSchema->bytes, pSchema->bytes);
- } else { // i > 0 and isNULL, do interpolation
+ (functionIDs[i] != TSDB_FUNC_COUNT && !isNull(src, pSchema->type)) ||
+ (functionIDs[i] == TSDB_FUNC_COUNT && *(int64_t*)(src) != 0)) {
+ assignVal(val1, src, pSchema->bytes, pSchema->type);
+ memcpy(*prevValues + tlen, src, pSchema->bytes);
+ } else { // i > 0 and data is null , do interpolation
if (interpoType == TSDB_INTERPO_PREV) {
assignVal(val1, *prevValues + offset, pSchema->bytes, pSchema->type);
} else if (interpoType == TSDB_INTERPO_LINEAR) {
- // TODO:
+ assignVal(val1, src, pSchema->bytes, pSchema->type);
+ memcpy(*prevValues + tlen, src, pSchema->bytes);
} else {
assignVal(val1, (char*)&defaultVal[i], pSchema->bytes, pSchema->type);
}
@@ -416,11 +405,11 @@ int32_t taosDoInterpoResult(SInterpolationInfo* pInterpoInfo, int16_t interpoTyp
/* set the tag value for final result */
setTagsValueInInterpolation(data, pTags, pModel, pInterpoInfo->order, pModel->numOfCols - numOfTags, bufSize,
num);
- }
- pInterpoInfo->startTimestamp += (nInterval * step);
- pInterpoInfo->rowIdx += 1;
- num += 1;
+ pInterpoInfo->startTimestamp += (nInterval * step);
+ pInterpoInfo->rowIdx += 1;
+ num += 1;
+ }
if ((pInterpoInfo->rowIdx >= pInterpoInfo->numOfRawDataInRows && INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) ||
(pInterpoInfo->rowIdx < 0 && !INTERPOL_IS_ASC_INTERPOL(pInterpoInfo)) || num >= outputRows) {
diff --git a/src/util/src/tresultBuf.c b/src/util/src/tresultBuf.c
index 31218670acc0a95c865de27ea945d1ed5ee19e29..a7377f16575147934f68148adb2d16126288ffc9 100644
--- a/src/util/src/tresultBuf.c
+++ b/src/util/src/tresultBuf.c
@@ -7,8 +7,8 @@
#define DEFAULT_INTERN_BUF_SIZE 16384L
-int32_t createResultBuf(SQueryResultBuf** pResultBuf, int32_t size, int32_t rowSize) {
- SQueryResultBuf* pResBuf = calloc(1, sizeof(SQueryResultBuf));
+int32_t createDiskbasedResultBuffer(SQueryDiskbasedResultBuf** pResultBuf, int32_t size, int32_t rowSize) {
+ SQueryDiskbasedResultBuf* pResBuf = calloc(1, sizeof(SQueryDiskbasedResultBuf));
pResBuf->numOfRowsPerPage = (DEFAULT_INTERN_BUF_SIZE - sizeof(tFilePage)) / rowSize;
pResBuf->numOfPages = size;
@@ -50,17 +50,17 @@ int32_t createResultBuf(SQueryResultBuf** pResultBuf, int32_t size, int32_t rowS
return TSDB_CODE_SUCCESS;
}
-tFilePage* getResultBufferPageById(SQueryResultBuf* pResultBuf, int32_t id) {
+tFilePage* getResultBufferPageById(SQueryDiskbasedResultBuf* pResultBuf, int32_t id) {
assert(id < pResultBuf->numOfPages && id >= 0);
return (tFilePage*)(pResultBuf->pBuf + DEFAULT_INTERN_BUF_SIZE * id);
}
-int32_t getNumOfResultBufGroupId(SQueryResultBuf* pResultBuf) { return taosNumElemsInHashTable(pResultBuf->idsTable); }
+int32_t getNumOfResultBufGroupId(SQueryDiskbasedResultBuf* pResultBuf) { return taosNumElemsInHashTable(pResultBuf->idsTable); }
-int32_t getResBufSize(SQueryResultBuf* pResultBuf) { return pResultBuf->totalBufSize; }
+int32_t getResBufSize(SQueryDiskbasedResultBuf* pResultBuf) { return pResultBuf->totalBufSize; }
-static int32_t extendDiskFileSize(SQueryResultBuf* pResultBuf, int32_t numOfPages) {
+static int32_t extendDiskFileSize(SQueryDiskbasedResultBuf* pResultBuf, int32_t numOfPages) {
assert(pResultBuf->numOfPages * DEFAULT_INTERN_BUF_SIZE == pResultBuf->totalBufSize);
int32_t ret = munmap(pResultBuf->pBuf, pResultBuf->totalBufSize);
@@ -88,11 +88,11 @@ static int32_t extendDiskFileSize(SQueryResultBuf* pResultBuf, int32_t numOfPage
return TSDB_CODE_SUCCESS;
}
-static bool noMoreAvailablePages(SQueryResultBuf* pResultBuf) {
+static bool noMoreAvailablePages(SQueryDiskbasedResultBuf* pResultBuf) {
return (pResultBuf->allocateId == pResultBuf->numOfPages - 1);
}
-static int32_t getGroupIndex(SQueryResultBuf* pResultBuf, int32_t groupId) {
+static int32_t getGroupIndex(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId) {
assert(pResultBuf != NULL);
char* p = taosGetDataFromHashTable(pResultBuf->idsTable, (const char*)&groupId, sizeof(int32_t));
@@ -106,7 +106,7 @@ static int32_t getGroupIndex(SQueryResultBuf* pResultBuf, int32_t groupId) {
return slot;
}
-static int32_t addNewGroupId(SQueryResultBuf* pResultBuf, int32_t groupId) {
+static int32_t addNewGroupId(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId) {
int32_t num = getNumOfResultBufGroupId(pResultBuf); // the num is the newest allocated group id slot
if (pResultBuf->numOfAllocGroupIds <= num) {
@@ -148,7 +148,7 @@ static int32_t doRegisterId(SIDList* pList, int32_t id) {
return 0;
}
-static void registerPageId(SQueryResultBuf* pResultBuf, int32_t groupId, int32_t pageId) {
+static void registerPageId(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t pageId) {
int32_t slot = getGroupIndex(pResultBuf, groupId);
if (slot < 0) {
slot = addNewGroupId(pResultBuf, groupId);
@@ -158,7 +158,7 @@ static void registerPageId(SQueryResultBuf* pResultBuf, int32_t groupId, int32_t
doRegisterId(pList, pageId);
}
-tFilePage* getNewDataBuf(SQueryResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) {
+tFilePage* getNewDataBuf(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId, int32_t* pageId) {
if (noMoreAvailablePages(pResultBuf)) {
if (extendDiskFileSize(pResultBuf, pResultBuf->incStep) != TSDB_CODE_SUCCESS) {
return NULL;
@@ -177,9 +177,9 @@ tFilePage* getNewDataBuf(SQueryResultBuf* pResultBuf, int32_t groupId, int32_t*
return page;
}
-int32_t getNumOfRowsPerPage(SQueryResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; }
+int32_t getNumOfRowsPerPage(SQueryDiskbasedResultBuf* pResultBuf) { return pResultBuf->numOfRowsPerPage; }
-SIDList getDataBufPagesIdList(SQueryResultBuf* pResultBuf, int32_t groupId) {
+SIDList getDataBufPagesIdList(SQueryDiskbasedResultBuf* pResultBuf, int32_t groupId) {
SIDList list = {0};
int32_t slot = getGroupIndex(pResultBuf, groupId);
if (slot < 0) {
@@ -189,7 +189,7 @@ SIDList getDataBufPagesIdList(SQueryResultBuf* pResultBuf, int32_t groupId) {
}
}
-void destroyResultBuf(SQueryResultBuf* pResultBuf) {
+void destroyResultBuf(SQueryDiskbasedResultBuf* pResultBuf) {
if (pResultBuf == NULL) {
return;
}
diff --git a/src/vnode/detail/inc/vnode.h b/src/vnode/detail/inc/vnode.h
index 481dbb19ddc0823b8be84b378fcaf8b6ae88f85e..ecd9e3f39275bb495a884442f221256e62ba5ee0 100644
--- a/src/vnode/detail/inc/vnode.h
+++ b/src/vnode/detail/inc/vnode.h
@@ -259,7 +259,7 @@ typedef struct SQuery {
int64_t blockId;
TSKEY skey;
TSKEY ekey;
- int64_t nAggTimeInterval;
+ int64_t intervalTime;
int64_t slidingTime; // sliding time for sliding window query
char intervalTimeUnit; // interval data type, used for daytime revise
int8_t precision;
diff --git a/src/vnode/detail/inc/vnodeQueryImpl.h b/src/vnode/detail/inc/vnodeQueryImpl.h
index cce66786fd993b1b300a5a2abbe27e5f4eff37de..e3507d5f82e8c156ffdc5a3babae8ea5af079398 100644
--- a/src/vnode/detail/inc/vnodeQueryImpl.h
+++ b/src/vnode/detail/inc/vnodeQueryImpl.h
@@ -25,7 +25,7 @@ extern "C" {
#include "hash.h"
#include "hashutil.h"
-#define GET_QINFO_ADDR(x) ((char*)(x)-offsetof(SQInfo, query))
+#define GET_QINFO_ADDR(x) ((char*)(x)-offsetof(SQInfo, query))
#define Q_STATUS_EQUAL(p, s) (((p) & (s)) != 0)
/*
@@ -33,10 +33,10 @@ extern "C" {
* The page size should be sufficient for at least one output result or intermediate result.
* Some intermediate results may be extremely large, such as top/bottom(100) query.
*/
-#define DEFAULT_INTERN_BUF_SIZE 16384L
+#define DEFAULT_INTERN_BUF_SIZE 16384L
-#define INIT_ALLOCATE_DISK_PAGES 60L
-#define DEFAULT_DATA_FILE_MAPPING_PAGES 2L
+#define INIT_ALLOCATE_DISK_PAGES 60L
+#define DEFAULT_DATA_FILE_MAPPING_PAGES 2L
#define DEFAULT_DATA_FILE_MMAP_WINDOW_SIZE (DEFAULT_DATA_FILE_MAPPING_PAGES * DEFAULT_INTERN_BUF_SIZE)
#define IO_ENGINE_MMAP 0
@@ -56,7 +56,7 @@ typedef enum {
* the program will call this function again, if this status is set.
* used to transfer from QUERY_RESBUF_FULL
*/
- QUERY_NOT_COMPLETED = 0x1,
+ QUERY_NOT_COMPLETED = 0x1u,
/*
* output buffer is full, so, the next query will be employed,
@@ -66,7 +66,7 @@ typedef enum {
* this status is only exist in group-by clause and
* diff/add/division/multiply/ query.
*/
- QUERY_RESBUF_FULL = 0x2,
+ QUERY_RESBUF_FULL = 0x2u,
/*
* query is over
@@ -76,14 +76,13 @@ typedef enum {
* 2. when the query range on timestamp is satisfied, it is also denoted as
* query_compeleted
*/
- QUERY_COMPLETED = 0x4,
+ QUERY_COMPLETED = 0x4u,
/*
* all data has been scanned, so current search is stopped,
* At last, the function will transfer this status to QUERY_COMPLETED
*/
- QUERY_NO_DATA_TO_CHECK = 0x8,
-
+ QUERY_NO_DATA_TO_CHECK = 0x8u,
} vnodeQueryStatus;
typedef struct SPointInterpoSupporter {
@@ -112,15 +111,15 @@ typedef enum {
DISK_DATA_DISCARDED = 0x01,
} vnodeDiskLoadStatus;
-#define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN)
-#define IS_SUPPLEMENT_SCAN(runtime) (!IS_MASTER_SCAN(runtime))
+#define IS_MASTER_SCAN(runtime) (((runtime)->scanFlag & 1u) == MASTER_SCAN)
+#define IS_SUPPLEMENT_SCAN(runtime) ((runtime)->scanFlag == SUPPLEMENTARY_SCAN)
#define SET_SUPPLEMENT_SCAN_FLAG(runtime) ((runtime)->scanFlag = SUPPLEMENTARY_SCAN)
#define SET_MASTER_SCAN_FLAG(runtime) ((runtime)->scanFlag = MASTER_SCAN)
typedef int (*__block_search_fn_t)(char* data, int num, int64_t key, int order);
static FORCE_INLINE SMeterObj* getMeterObj(void* hashHandle, int32_t sid) {
- return *(SMeterObj**)taosGetDataFromHashTable(hashHandle, (const char*) &sid, sizeof(sid));
+ return *(SMeterObj**)taosGetDataFromHashTable(hashHandle, (const char*)&sid, sizeof(sid));
}
bool isQueryKilled(SQuery* pQuery);
@@ -130,7 +129,7 @@ bool isSumAvgRateQuery(SQuery *pQuery);
bool isTopBottomQuery(SQuery* pQuery);
bool isFirstLastRowQuery(SQuery* pQuery);
bool isTSCompQuery(SQuery* pQuery);
-bool notHasQueryTimeRange(SQuery *pQuery);
+bool notHasQueryTimeRange(SQuery* pQuery);
bool needSupplementaryScan(SQuery* pQuery);
bool onDemandLoadDatablock(SQuery* pQuery, int16_t queryRangeSet);
@@ -149,16 +148,15 @@ void vnodeScanAllData(SQueryRuntimeEnv* pRuntimeEnv);
int32_t vnodeQueryResultInterpolate(SQInfo* pQInfo, tFilePage** pDst, tFilePage** pDataSrc, int32_t numOfRows,
int32_t* numOfInterpo);
-void copyResToQueryResultBuf(SMeterQuerySupportObj* pSupporter, SQuery* pQuery);
+void copyResToQueryResultBuf(STableQuerySupportObj* pSupporter, SQuery* pQuery);
-void doSkipResults(SQueryRuntimeEnv* pRuntimeEnv);
-void doFinalizeResult(SQueryRuntimeEnv* pRuntimeEnv);
+void doSkipResults(SQueryRuntimeEnv* pRuntimeEnv);
+void doFinalizeResult(SQueryRuntimeEnv* pRuntimeEnv);
int64_t getNumOfResult(SQueryRuntimeEnv* pRuntimeEnv);
-void forwardIntervalQueryRange(SMeterQuerySupportObj* pSupporter, SQueryRuntimeEnv* pRuntimeEnv);
void forwardQueryStartPosition(SQueryRuntimeEnv* pRuntimeEnv);
-bool normalizedFirstQueryRange(bool dataInDisk, bool dataInCache, SMeterQuerySupportObj* pSupporter,
+bool normalizedFirstQueryRange(bool dataInDisk, bool dataInCache, STableQuerySupportObj* pSupporter,
SPointInterpoSupporter* pPointInterpSupporter, int64_t* key);
void pointInterpSupporterInit(SQuery* pQuery, SPointInterpoSupporter* pInterpoSupport);
@@ -166,41 +164,42 @@ void pointInterpSupporterDestroy(SPointInterpoSupporter* pPointInterpSupport);
void pointInterpSupporterSetData(SQInfo* pQInfo, SPointInterpoSupporter* pPointInterpSupport);
int64_t loadRequiredBlockIntoMem(SQueryRuntimeEnv* pRuntimeEnv, SPositionInfo* position);
-int32_t doCloseAllOpenedResults(SMeterQuerySupportObj* pSupporter);
-void disableFunctForSuppleScan(SQueryRuntimeEnv* pRuntimeEnv, int32_t order);
-void enableFunctForMasterScan(SQueryRuntimeEnv* pRuntimeEnv, int32_t order);
+void disableFunctForSuppleScan(STableQuerySupportObj* pSupporter, int32_t order);
+void enableFunctForMasterScan(SQueryRuntimeEnv* pRuntimeEnv, int32_t order);
+
+int32_t mergeMetersResultToOneGroups(STableQuerySupportObj* pSupporter);
+void copyFromWindowResToSData(SQInfo* pQInfo, SWindowResult* result);
-int32_t mergeMetersResultToOneGroups(SMeterQuerySupportObj* pSupporter);
-void copyFromGroupBuf(SQInfo* pQInfo, SOutputRes* result);
+SBlockInfo getBlockInfo(SQueryRuntimeEnv *pRuntimeEnv);
+SBlockInfo getBlockBasicInfo(SQueryRuntimeEnv *pRuntimeEnv, void* pBlock, int32_t type);
-SBlockInfo getBlockBasicInfo(SQueryRuntimeEnv* pRuntimeEnv, void* pBlock, int32_t blockType);
SCacheBlock* getCacheDataBlock(SMeterObj* pMeterObj, SQueryRuntimeEnv* pRuntimeEnv, int32_t slot);
-void queryOnBlock(SMeterQuerySupportObj* pSupporter, int64_t* primaryKeys, int32_t blockStatus,
- SBlockInfo* pBlockBasicInfo, SMeterDataInfo* pDataHeadInfoEx, SField* pFields,
- __block_search_fn_t searchFn);
+void stableApplyFunctionsOnBlock(STableQuerySupportObj* pSupporter, SMeterDataInfo* pMeterDataInfo,
+ SBlockInfo* pBlockInfo, SField* pFields, __block_search_fn_t searchFn);
-int32_t vnodeFilterQualifiedMeters(SQInfo *pQInfo, int32_t vid, tSidSet *pSidSet, SMeterDataInfo *pMeterDataInfo,
- int32_t *numOfMeters, SMeterDataInfo ***pReqMeterDataInfo);
-int32_t vnodeGetVnodeHeaderFileIdx(int32_t* fid, SQueryRuntimeEnv* pRuntimeEnv, int32_t order);
+int32_t vnodeFilterQualifiedMeters(SQInfo* pQInfo, int32_t vid, tSidSet* pSidSet, SMeterDataInfo* pMeterDataInfo,
+ int32_t* numOfMeters, SMeterDataInfo*** pReqMeterDataInfo);
+int32_t vnodeGetVnodeHeaderFileIndex(int32_t* fid, SQueryRuntimeEnv* pRuntimeEnv, int32_t order);
int32_t createDataBlocksInfoEx(SMeterDataInfo** pMeterDataInfo, int32_t numOfMeters,
SMeterDataBlockInfoEx** pDataBlockInfoEx, int32_t numOfCompBlocks,
int32_t* nAllocBlocksInfoSize, int64_t addr);
-void freeMeterBlockInfoEx(SMeterDataBlockInfoEx* pDataBlockInfoEx, int32_t len);
+void freeMeterBlockInfoEx(SMeterDataBlockInfoEx* pDataBlockInfoEx, int32_t len);
-void setExecutionContext(SMeterQuerySupportObj* pSupporter, SOutputRes* outputRes, int32_t meterIdx, int32_t groupIdx,
- SMeterQueryInfo* sqinfo);
-int32_t setIntervalQueryExecutionContext(SMeterQuerySupportObj* pSupporter, int32_t meterIdx, SMeterQueryInfo* sqinfo);
+void setExecutionContext(STableQuerySupportObj* pSupporter, SMeterQueryInfo* pMeterQueryInfo, int32_t meterIdx,
+ int32_t groupIdx, TSKEY nextKey);
+int32_t setAdditionalInfo(STableQuerySupportObj *pSupporter, int32_t meterIdx, SMeterQueryInfo *pMeterQueryInfo);
+void doGetAlignedIntervalQueryRangeImpl(SQuery* pQuery, int64_t pKey, int64_t keyFirst, int64_t keyLast,
+ int64_t* actualSkey, int64_t* actualEkey, int64_t* skey, int64_t* ekey);
int64_t getQueryStartPositionInCache(SQueryRuntimeEnv* pRuntimeEnv, int32_t* slot, int32_t* pos, bool ignoreQueryRange);
-int64_t getNextAccessedKeyInData(SQuery* pQuery, int64_t* pPrimaryCol, SBlockInfo* pBlockInfo, int32_t blockStatus);
-int32_t getDataBlocksForMeters(SMeterQuerySupportObj* pSupporter, SQuery* pQuery, int32_t numOfMeters,
- const char* filePath, SMeterDataInfo** pMeterDataInfo, uint32_t* numOfBlocks);
+int32_t getDataBlocksForMeters(STableQuerySupportObj* pSupporter, SQuery* pQuery, int32_t numOfMeters,
+ const char* filePath, SMeterDataInfo** pMeterDataInfo, uint32_t* numOfBlocks);
int32_t LoadDatablockOnDemand(SCompBlock* pBlock, SField** pFields, uint8_t* blkStatus, SQueryRuntimeEnv* pRuntimeEnv,
int32_t fileIdx, int32_t slotIdx, __block_search_fn_t searchFn, bool onDemand);
-int32_t vnodeGetHeaderFile(SQueryRuntimeEnv *pRuntimeEnv, int32_t fileIndex);
+int32_t vnodeGetHeaderFile(SQueryRuntimeEnv* pRuntimeEnv, int32_t fileIndex);
/**
* Create SMeterQueryInfo.
@@ -210,14 +209,14 @@ int32_t vnodeGetHeaderFile(SQueryRuntimeEnv *pRuntimeEnv, int32_t fileIndex);
* @param ekey
* @return
*/
-SMeterQueryInfo* createMeterQueryInfo(SQuery* pQuery, int32_t sid, TSKEY skey, TSKEY ekey);
+SMeterQueryInfo* createMeterQueryInfo(STableQuerySupportObj* pSupporter, int32_t sid, TSKEY skey, TSKEY ekey);
/**
* Destroy meter query info
* @param pMeterQInfo
* @param numOfCols
*/
-void destroyMeterQueryInfo(SMeterQueryInfo *pMeterQueryInfo, int32_t numOfCols);
+void destroyMeterQueryInfo(SMeterQueryInfo* pMeterQueryInfo, int32_t numOfCols);
/**
* change the meter query info for supplement scan
@@ -225,7 +224,8 @@ void destroyMeterQueryInfo(SMeterQueryInfo *pMeterQueryInfo, int32_t numOfCols);
* @param skey
* @param ekey
*/
-void changeMeterQueryInfoForSuppleQuery(SQueryResultBuf* pResultBuf, SMeterQueryInfo *pMeterQueryInfo, TSKEY skey, TSKEY ekey);
+void changeMeterQueryInfoForSuppleQuery(SQuery* pQuery, SMeterQueryInfo* pMeterQueryInfo,
+ TSKEY skey, TSKEY ekey);
/**
* add the new allocated disk page to meter query info
@@ -234,14 +234,8 @@ void changeMeterQueryInfoForSuppleQuery(SQueryResultBuf* pResultBuf, SMeterQuery
* @param pMeterQueryInfo
* @param pSupporter
*/
-tFilePage* addDataPageForMeterQueryInfo(SQuery* pQuery, SMeterQueryInfo *pMeterQueryInfo, SMeterQuerySupportObj *pSupporter);
-
-/**
- * save the query range data into SMeterQueryInfo
- * @param pRuntimeEnv
- * @param pMeterQueryInfo
- */
-void saveIntervalQueryRange(SQueryRuntimeEnv* pRuntimeEnv, SMeterQueryInfo* pMeterQueryInfo);
+tFilePage* addDataPageForMeterQueryInfo(SQuery* pQuery, SMeterQueryInfo* pMeterQueryInfo,
+ STableQuerySupportObj* pSupporter);
/**
* restore the query range data from SMeterQueryInfo to runtime environment
@@ -258,7 +252,7 @@ void restoreIntervalQueryRange(SQueryRuntimeEnv* pRuntimeEnv, SMeterQueryInfo* p
* @param pSupporter
* @param key
*/
-void setIntervalQueryRange(SMeterQueryInfo *pMeterQueryInfo, SMeterQuerySupportObj* pSupporter, int64_t key);
+void setIntervalQueryRange(SMeterQueryInfo* pMeterQueryInfo, STableQuerySupportObj* pSupporter, int64_t key);
/**
* set the meter data information
@@ -275,16 +269,22 @@ void vnodeCheckIfDataExists(SQueryRuntimeEnv* pRuntimeEnv, SMeterObj* pMeterObj,
void displayInterResult(SData** pdata, SQuery* pQuery, int32_t numOfRows);
-void vnodePrintQueryStatistics(SMeterQuerySupportObj* pSupporter);
+void vnodePrintQueryStatistics(STableQuerySupportObj* pSupporter);
+
+void clearTimeWindowResBuf(SQueryRuntimeEnv* pRuntimeEnv, SWindowResult* pOneOutputRes);
+void copyTimeWindowResBuf(SQueryRuntimeEnv* pRuntimeEnv, SWindowResult* dst, const SWindowResult* src);
+
+int32_t initWindowResInfo(SWindowResInfo* pWindowResInfo, SQueryRuntimeEnv* pRuntimeEnv, int32_t size,
+ int32_t threshold, int16_t type);
-void clearGroupResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pOneOutputRes);
-void copyGroupResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes* dst, const SOutputRes* src);
+void cleanupTimeWindowInfo(SWindowResInfo* pWindowResInfo, SQueryRuntimeEnv* pRuntimeEnv);
+void resetTimeWindowInfo(SQueryRuntimeEnv* pRuntimeEnv, SWindowResInfo* pWindowResInfo);
+void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num);
-void resetSlidingWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SSlidingWindowInfo* pSlidingWindowInfo);
-void clearCompletedSlidingWindows(SQueryRuntimeEnv* pRuntimeEnv);
-int32_t numOfClosedSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo);
-void closeSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo, int32_t slot);
-void closeAllSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo);
+void clearClosedTimeWindow(SQueryRuntimeEnv* pRuntimeEnv);
+int32_t numOfClosedTimeWindow(SWindowResInfo* pWindowResInfo);
+void closeTimeWindow(SWindowResInfo* pWindowResInfo, int32_t slot);
+void closeAllTimeWindow(SWindowResInfo* pWindowResInfo);
#ifdef __cplusplus
}
diff --git a/src/vnode/detail/inc/vnodeRead.h b/src/vnode/detail/inc/vnodeRead.h
index 2765ff76fc5f120ca7f8ccc2214196b54dfd8507..2758cfe1d9610257c7ddf0658874a7ee57511fc0 100644
--- a/src/vnode/detail/inc/vnodeRead.h
+++ b/src/vnode/detail/inc/vnodeRead.h
@@ -86,16 +86,26 @@ typedef struct SQueryCostSummary {
} SQueryCostSummary;
typedef struct SPosInfo {
- int64_t pageId;
- int32_t rowId;
+ int16_t pageId;
+ int16_t rowId;
} SPosInfo;
-typedef struct SOutputRes {
+typedef struct STimeWindow {
+ TSKEY skey;
+ TSKEY ekey;
+} STimeWindow;
+
+typedef struct SWindowStatus {
+ bool closed;
+} SWindowStatus;
+
+typedef struct SWindowResult {
uint16_t numOfRows;
- int32_t nAlloc;
- SPosInfo pos;
- SResultInfo* resultInfo;
-} SOutputRes;
+ SPosInfo pos; // Position of current result in disk-based output buffer
+ SResultInfo* resultInfo; // For each result column, there is a resultInfo
+ STimeWindow window; // The time window that current result covers.
+ SWindowStatus status;
+} SWindowResult;
/*
* header files info, avoid to iterate the directory, the data is acquired
@@ -118,19 +128,8 @@ typedef struct SQueryFilesInfo {
char dbFilePathPrefix[PATH_MAX];
} SQueryFilesInfo;
-typedef struct STimeWindow {
- TSKEY skey;
- TSKEY ekey;
-} STimeWindow;
-
-typedef struct SWindowStatus {
- STimeWindow window;
- bool closed;
-} SWindowStatus;
-
-typedef struct SSlidingWindowInfo {
- SOutputRes* pResult; // reference to SQuerySupporter->pResult
- SWindowStatus* pStatus; // current query window closed or not?
+typedef struct SWindowResInfo {
+ SWindowResult* pResult; // reference to SQuerySupporter->pResult
void* hashList; // hash list for quick access
int16_t type; // data type for hash key
int32_t capacity; // max capacity
@@ -140,14 +139,14 @@ typedef struct SSlidingWindowInfo {
int64_t startTime; // start time of the first time window for sliding query
int64_t prevSKey; // previous (not completed) sliding window start key
int64_t threshold; // threshold for return completed results.
-} SSlidingWindowInfo;
+} SWindowResInfo;
typedef struct SQueryRuntimeEnv {
SPositionInfo startPos; /* the start position, used for secondary/third iteration */
SPositionInfo endPos; /* the last access position in query, served as the start pos of reversed order query */
SPositionInfo nextPos; /* start position of the next scan */
SData* colDataBuffer[TSDB_MAX_COLUMNS];
- SResultInfo* resultInfo;
+ SResultInfo* resultInfo; // todo refactor to merge with SWindowResInfo
uint8_t blockStatus; // Indicate if data block is loaded, the block is first/last/internal block
int32_t unzipBufSize;
SData* primaryColBuffer;
@@ -161,28 +160,25 @@ typedef struct SQueryRuntimeEnv {
SQueryFilesInfo vnodeFileInfo;
int16_t numOfRowsPerPage;
int16_t offset[TSDB_MAX_COLUMNS];
- int16_t scanFlag; // denotes reversed scan of data or not
+ uint16_t scanFlag; // denotes reversed scan of data or not
SInterpolationInfo interpoInfo;
SData** pInterpoBuf;
- SSlidingWindowInfo swindowResInfo;
+ SWindowResInfo windowResInfo;
STSBuf* pTSBuf;
STSCursor cur;
SQueryCostSummary summary;
-
- STimeWindow intervalWindow; // the complete time window, not affected by the actual data distribution
+ bool stableQuery; // is super table query or not
+ SQueryDiskbasedResultBuf* pResultBuf; // query result buffer based on blocked-wised disk file
/*
* Temporarily hold the in-memory cache block info during scan cache blocks
- * Here we do not use the cacheblock info from pMeterObj, simple because it may change anytime
- * during the query by the subumit/insert handling threads.
+ * Here we do not use the cache block info from pMeterObj, simple because it may change anytime
+ * during the query by the submit/insert handling threads.
* So we keep a copy of the support structure as well as the cache block data itself.
*/
SCacheBlock cacheBlock;
-
- SQueryResultBuf* pResultBuf;
- bool stableQuery; // is super table query or not
} SQueryRuntimeEnv;
/* intermediate pos during multimeter query involves interval */
@@ -191,14 +187,12 @@ typedef struct SMeterQueryInfo {
int64_t skey;
int64_t ekey;
int32_t numOfRes;
- int32_t reverseIndex; // reversed output indicator, start from (numOfRes-1)
- int16_t reverseFillRes; // denote if reverse fill the results in supplementary scan required or not
int16_t queryRangeSet; // denote if the query range is set, only available for interval query
- int16_t lastResRows;
int64_t tag;
STSCursor cur;
- SResultInfo* resultInfo;
int32_t sid; // for retrieve the page id list
+
+ SWindowResInfo windowResInfo;
} SMeterQueryInfo;
typedef struct SMeterDataInfo {
@@ -212,7 +206,7 @@ typedef struct SMeterDataInfo {
SMeterQueryInfo* pMeterQInfo;
} SMeterDataInfo;
-typedef struct SMeterQuerySupportObj {
+typedef struct STableQuerySupportObj {
void* pMetersHashTable; // meter table hash list
SMeterSidExtInfo** pMeterSidExtInfo;
@@ -225,13 +219,11 @@ typedef struct SMeterQuerySupportObj {
* rows may be generated by a specific subgroup. When query on all subgroups is executed,
* the result is copy to output buffer. This attribution is not used during single meter query processing.
*/
- SOutputRes* pResult;
SQueryRuntimeEnv runtimeEnv;
int64_t rawSKey;
int64_t rawEKey;
int32_t subgroupIdx;
int32_t offset; /* offset in group result set of subgroup */
-
tSidSet* pSidSet;
/*
@@ -247,7 +239,7 @@ typedef struct SMeterQuerySupportObj {
SMeterDataInfo* pMeterDataInfo;
TSKEY* tsList;
-} SMeterQuerySupportObj;
+} STableQuerySupportObj;
typedef struct _qinfo {
uint64_t signature;
@@ -273,18 +265,18 @@ typedef struct _qinfo {
SMeterObj* pObj;
sem_t dataReady;
- SMeterQuerySupportObj* pMeterQuerySupporter;
+ STableQuerySupportObj* pTableQuerySupporter;
int (*fp)(SMeterObj*, SQuery*);
} SQInfo;
-int32_t vnodeQuerySingleMeterPrepare(SQInfo* pQInfo, SMeterObj* pMeterObj, SMeterQuerySupportObj* pSMultiMeterObj,
+int32_t vnodeQueryTablePrepare(SQInfo* pQInfo, SMeterObj* pMeterObj, STableQuerySupportObj* pSMultiMeterObj,
void* param);
void vnodeQueryFreeQInfoEx(SQInfo* pQInfo);
bool vnodeParametersSafetyCheck(SQuery* pQuery);
-int32_t vnodeMultiMeterQueryPrepare(SQInfo* pQInfo, SQuery* pQuery, void* param);
+int32_t vnodeSTableQueryPrepare(SQInfo* pQInfo, SQuery* pQuery, void* param);
/**
* decrease the numofQuery of each table that is queried, enable the
diff --git a/src/vnode/detail/src/vnodeQueryImpl.c b/src/vnode/detail/src/vnodeQueryImpl.c
index 104e4b859e3009fd3741957b32583162a3f32ceb..f761205719c8020b871448942461b2df2dc265d9 100644
--- a/src/vnode/detail/src/vnodeQueryImpl.c
+++ b/src/vnode/detail/src/vnodeQueryImpl.c
@@ -13,9 +13,9 @@
* along with this program. If not, see .
*/
-#include "os.h"
#include "hash.h"
#include "hashutil.h"
+#include "os.h"
#include "taosmsg.h"
#include "textbuffer.h"
#include "ttime.h"
@@ -55,7 +55,7 @@ static int32_t readDataFromDiskFile(int fd, SQInfo *pQInfo, SQueryFilesInfo *pQu
static void vnodeInitLoadCompBlockInfo(SLoadCompBlockInfo *pCompBlockLoadInfo);
static int32_t moveToNextBlock(SQueryRuntimeEnv *pRuntimeEnv, int32_t step, __block_search_fn_t searchFn,
bool loadData);
-static int32_t doMergeMetersResultsToGroupRes(SMeterQuerySupportObj *pSupporter, SQuery *pQuery,
+static int32_t doMergeMetersResultsToGroupRes(STableQuerySupportObj *pSupporter, SQuery *pQuery,
SQueryRuntimeEnv *pRuntimeEnv, SMeterDataInfo *pMeterDataInfo,
int32_t start, int32_t end);
@@ -65,25 +65,22 @@ static TSKEY getTimestampInDiskBlock(SQueryRuntimeEnv *pRuntimeEnv, int32_t inde
static void savePointPosition(SPositionInfo *position, int32_t fileId, int32_t slot, int32_t pos);
static int32_t getNextDataFileCompInfo(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *pMeterObj, int32_t step);
-static void setGroupOutputBuffer(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pResult);
-
-static void getAlignedIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY keyInData, TSKEY skey, TSKEY ekey);
-
-static int32_t saveResult(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo, int32_t numOfResult);
-static void applyIntervalQueryOnBlock(SMeterQuerySupportObj *pSupporter, SMeterDataInfo *pMeterDataInfo,
- SBlockInfo *pBlockInfo, int32_t blockStatus, SField *pFields,
- __block_search_fn_t searchFn);
+static void setWindowResOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pResult);
-static void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx);
-static int32_t flushFromResultBuf(SMeterQuerySupportObj *pSupporter, const SQuery *pQuery,
+static void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx, SResultInfo *pResultInfo);
+static int32_t flushFromResultBuf(STableQuerySupportObj *pSupporter, const SQuery *pQuery,
const SQueryRuntimeEnv *pRuntimeEnv);
-static void validateTimestampForSupplementResult(SQueryRuntimeEnv *pRuntimeEnv, int64_t numOfIncrementRes);
static void getBasicCacheInfoSnapshot(SQuery *pQuery, SCacheInfo *pCacheInfo, int32_t vid);
static TSKEY getQueryPositionForCacheInvalid(SQueryRuntimeEnv *pRuntimeEnv, __block_search_fn_t searchFn);
static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx, int32_t functionId);
-static void doGetAlignedIntervalQueryRangeImpl(SQuery *pQuery, int64_t pKey, int64_t keyFirst, int64_t keyLast,
- int64_t *actualSkey, int64_t *actualEkey, int64_t *skey, int64_t *ekey);
-static void getNextLogicalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow* pTimeWindow);
+static void getNextTimeWindow(SQuery *pQuery, STimeWindow *pTimeWindow);
+
+static int32_t getGroupResultId(int32_t groupIndex) {
+ int32_t base = 200000;
+ return base + (groupIndex * 10000);
+}
+
+static FORCE_INLINE bool isIntervalQuery(SQuery *pQuery) { return pQuery->intervalTime > 0; }
// check the offset value integrity
static FORCE_INLINE int32_t validateHeaderOffsetSegment(SQInfo *pQInfo, char *filePath, int32_t vid, char *data,
@@ -248,7 +245,7 @@ static void vnodeInitLoadCompBlockInfo(SLoadCompBlockInfo *pCompBlockLoadInfo) {
}
static int32_t vnodeIsDatablockLoaded(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *pMeterObj, int32_t fileIndex,
- bool loadPrimaryTS) {
+ bool loadTS) {
SQuery * pQuery = pRuntimeEnv->pQuery;
SLoadDataBlockInfo *pLoadInfo = &pRuntimeEnv->loadBlockInfo;
@@ -256,7 +253,7 @@ static int32_t vnodeIsDatablockLoaded(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *
if (pLoadInfo->fileId == pQuery->fileId && pLoadInfo->slotIdx == pQuery->slot && pQuery->slot != -1 &&
pLoadInfo->sid == pMeterObj->sid && pLoadInfo->fileListIndex == fileIndex) {
// previous load operation does not load the primary timestamp column, we only need to load the timestamp column
- if (pLoadInfo->tsLoaded == false && pLoadInfo->tsLoaded != loadPrimaryTS) {
+ if (pLoadInfo->tsLoaded == false && pLoadInfo->tsLoaded != loadTS) {
return DISK_BLOCK_LOAD_TS;
} else {
return DISK_BLOCK_NO_NEED_TO_LOAD;
@@ -402,7 +399,6 @@ static void doCloseQueryFiles(SQueryFilesInfo *pVnodeFileInfo) {
assert(pVnodeFileInfo->current < pVnodeFileInfo->numOfFiles && pVnodeFileInfo->current >= 0);
pVnodeFileInfo->headerFileSize = -1;
-
doCloseQueryFileInfoFD(pVnodeFileInfo);
}
@@ -461,11 +457,12 @@ static int vnodeGetCompBlockInfo(SMeterObj *pMeterObj, SQueryRuntimeEnv *pRuntim
SHeaderFileInfo *pHeadeFileInfo = &pRuntimeEnv->vnodeFileInfo.pFileInfo[fileIndex];
int64_t st = taosGetTimestampUs();
-
- if (vnodeIsCompBlockInfoLoaded(pRuntimeEnv, pMeterObj, fileIndex)) {
+
+ // if the corresponding data/header files are already closed, re-open them here
+ if (vnodeIsCompBlockInfoLoaded(pRuntimeEnv, pMeterObj, fileIndex) &&
+ pRuntimeEnv->vnodeFileInfo.current == fileIndex) {
dTrace("QInfo:%p vid:%d sid:%d id:%s, fileId:%d compBlock info is loaded, not reload", GET_QINFO_ADDR(pQuery),
pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pHeadeFileInfo->fileID);
-
return pQuery->numOfBlocks;
}
@@ -586,9 +583,9 @@ static void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, int64_t StartQue
char *primaryColumnData, int32_t size, int32_t functionId, SField *pField, bool hasNull,
int32_t blockStatus, void *param, int32_t scanFlag);
-void createQueryResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pResultRow, bool isSTableQuery, SPosInfo *posInfo);
+void createQueryResultInfo(SQuery *pQuery, SWindowResult *pResultRow, bool isSTableQuery, SPosInfo *posInfo);
-static void destroyGroupResultBuf(SOutputRes *pOneOutputRes, int32_t nOutputCols);
+static void destroyTimeWindowRes(SWindowResult *pOneOutputRes, int32_t nOutputCols);
static int32_t binarySearchForBlockImpl(SCompBlock *pBlock, int32_t numOfBlocks, TSKEY skey, int32_t order) {
int32_t firstSlot = 0;
@@ -921,7 +918,7 @@ static int32_t loadDataBlockIntoMem(SCompBlock *pBlock, SField **pField, SQueryR
int32_t ret = 0;
/* the first round always be 1, the secondary round is determined by queried function */
- int32_t round = pRuntimeEnv->scanFlag;
+ int32_t round = (IS_MASTER_SCAN(pRuntimeEnv)) ? 0 : 1;
while (j < pBlock->numOfCols && i < pQuery->numOfCols) {
if ((*pField)[j].colId < pQuery->colList[i].data.colId) {
@@ -988,7 +985,6 @@ static int32_t loadDataBlockIntoMem(SCompBlock *pBlock, SField **pField, SQueryR
return ret;
}
-// todo ignore the blockType, pass the pQuery into this function
SBlockInfo getBlockBasicInfo(SQueryRuntimeEnv *pRuntimeEnv, void *pBlock, int32_t blockType) {
SBlockInfo blockInfo = {0};
if (IS_FILE_BLOCK(blockType)) {
@@ -1010,22 +1006,6 @@ SBlockInfo getBlockBasicInfo(SQueryRuntimeEnv *pRuntimeEnv, void *pBlock, int32_
return blockInfo;
}
-static bool checkQueryRangeAgainstNextBlock(SBlockInfo *pBlockInfo, SQueryRuntimeEnv *pRuntimeEnv) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
-
- if ((QUERY_IS_ASC_QUERY(pQuery) && pBlockInfo->keyFirst > pQuery->ekey) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && pBlockInfo->keyLast < pQuery->ekey)) {
- int32_t pos = QUERY_IS_ASC_QUERY(pQuery) ? 0 : pBlockInfo->size - 1;
-
- savePointPosition(&pRuntimeEnv->nextPos, pQuery->fileId, pQuery->slot, pos);
- setQueryStatus(pQuery, QUERY_COMPLETED);
-
- return false;
- }
-
- return true;
-}
-
/**
*
* @param pQuery
@@ -1033,29 +1013,34 @@ static bool checkQueryRangeAgainstNextBlock(SBlockInfo *pBlockInfo, SQueryRuntim
* @param forwardStep
* @return TRUE means query not completed, FALSE means query is completed
*/
-static bool queryCompleteInBlock(SQuery *pQuery, SBlockInfo *pBlockInfo, int32_t forwardStep) {
- if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) {
- // assert(pQuery->checkBufferInLoop == 1 && pQuery->over == QUERY_RESBUF_FULL && pQuery->pointsOffset == 0);
+static bool queryPausedInCurrentBlock(SQuery *pQuery, SBlockInfo *pBlockInfo, int32_t forwardStep) {
+ // current query completed
+ if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+ return true;
+ }
+ // output buffer is full, pause current query
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) {
assert((QUERY_IS_ASC_QUERY(pQuery) && forwardStep + pQuery->pos <= pBlockInfo->size) ||
(!QUERY_IS_ASC_QUERY(pQuery) && pQuery->pos - forwardStep + 1 >= 0));
- // current query completed
- if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
- }
+ return true;
+ }
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED)) {
return true;
- } else { // query completed
- if ((pQuery->ekey <= pBlockInfo->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->ekey >= pBlockInfo->keyFirst && !QUERY_IS_ASC_QUERY(pQuery))) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
- return true;
- }
+ }
- return false;
+ // query completed
+ if ((pQuery->ekey <= pBlockInfo->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pQuery->ekey >= pBlockInfo->keyFirst && !QUERY_IS_ASC_QUERY(pQuery))) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+ return true;
}
+
+ return false;
}
/**
@@ -1072,7 +1057,7 @@ void savePointPosition(SPositionInfo *position, int32_t fileId, int32_t slot, in
position->pos = pos;
}
-bool isCacheBlockValid(SQuery *pQuery, SCacheBlock *pBlock, SMeterObj *pMeterObj) {
+bool isCacheBlockValid(SQuery *pQuery, SCacheBlock *pBlock, SMeterObj *pMeterObj, int32_t slot) {
if (pMeterObj != pBlock->pMeterObj || pBlock->blockId > pQuery->blockId) {
SMeterObj *pNewMeterObj = pBlock->pMeterObj;
char * id = (pNewMeterObj != NULL) ? pNewMeterObj->meterId : NULL;
@@ -1096,11 +1081,19 @@ bool isCacheBlockValid(SQuery *pQuery, SCacheBlock *pBlock, SMeterObj *pMeterObj
dWarn(
"QInfo:%p vid:%d sid:%d id:%s, cache block is empty. slot:%d first:%d, last:%d, numOfBlocks:%d,"
"allocated but not write data yet.",
- GET_QINFO_ADDR(pQuery), pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->slot, pQuery->firstSlot,
+ GET_QINFO_ADDR(pQuery), pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, slot, pQuery->firstSlot,
pQuery->currentSlot, pQuery->numOfBlocks);
return false;
}
+
+ SCacheInfo* pCacheInfo = (SCacheInfo*) pMeterObj->pCache;
+ if (pCacheInfo->commitPoint == pMeterObj->pointsPerBlock && pQuery->slot == pCacheInfo->currentSlot) {
+ dWarn("QInfo:%p vid:%d sid:%d id:%s, cache block is committed, ignore. slot:%d first:%d, last:%d, numOfBlocks:%d",
+ GET_QINFO_ADDR(pQuery), pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, slot, pQuery->firstSlot,
+ pQuery->currentSlot, pQuery->numOfBlocks);
+ return false;
+ }
return true;
}
@@ -1114,6 +1107,7 @@ SCacheBlock *getCacheDataBlock(SMeterObj *pMeterObj, SQueryRuntimeEnv *pRuntimeE
return NULL;
}
+ vnodeFreeFields(pQuery);
getBasicCacheInfoSnapshot(pQuery, pCacheInfo, pMeterObj->vnode);
SCacheBlock *pBlock = pCacheInfo->cacheBlocks[slot];
@@ -1131,7 +1125,7 @@ SCacheBlock *getCacheDataBlock(SMeterObj *pMeterObj, SQueryRuntimeEnv *pRuntimeE
}
// block is empty or block does not belongs to current table, return NULL value
- if (!isCacheBlockValid(pQuery, pBlock, pMeterObj)) {
+ if (!isCacheBlockValid(pQuery, pBlock, pMeterObj, slot)) {
return NULL;
}
@@ -1217,7 +1211,7 @@ SCacheBlock *getCacheDataBlock(SMeterObj *pMeterObj, SQueryRuntimeEnv *pRuntimeE
pQuery->fileId = -1;
pQuery->slot = slot;
- if (!isCacheBlockValid(pQuery, pNewBlock, pMeterObj)) {
+ if (!isCacheBlockValid(pQuery, pNewBlock, pMeterObj, slot)) {
return NULL;
}
@@ -1252,6 +1246,16 @@ static void *getGenericDataBlock(SMeterObj *pMeterObj, SQueryRuntimeEnv *pRuntim
}
}
+SBlockInfo getBlockInfo(SQueryRuntimeEnv *pRuntimeEnv) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+
+ void *pBlock = getGenericDataBlock(pRuntimeEnv->pMeterObj, pRuntimeEnv, pQuery->slot);
+ assert(pBlock != NULL);
+
+ int32_t blockType = IS_DISK_DATA_BLOCK(pQuery) ? BLK_FILE_BLOCK : BLK_CACHE_BLOCK;
+ return getBlockBasicInfo(pRuntimeEnv, pBlock, blockType);
+}
+
static int32_t getFileIdFromKey(int32_t vid, TSKEY key) {
SVnodeObj *pVnode = &vnodeList[vid];
int64_t delta = (int64_t)pVnode->cfg.daysPerFile * tsMsPerDay[(uint8_t)pVnode->cfg.precision];
@@ -1438,403 +1442,737 @@ static char *getDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sa
return dataBlock;
}
-/**
- *
- * @param pRuntimeEnv
- * @param forwardStep
- * @param primaryKeyCol
- * @param pFields
- * @param isDiskFileBlock
- * @return the incremental number of output value, so it maybe 0 for fixed number of query,
- * such as count/min/max etc.
- */
-static int32_t blockwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t forwardStep, TSKEY *primaryKeyCol,
- SField *pFields, SBlockInfo *pBlockInfo) {
- SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
- SQuery * pQuery = pRuntimeEnv->pQuery;
-
- bool isDiskFileBlock = IS_FILE_BLOCK(pRuntimeEnv->blockStatus);
- int64_t prevNumOfRes = getNumOfResult(pRuntimeEnv);
-
- SArithmeticSupport *sasArray = calloc((size_t)pQuery->numOfOutputCols, sizeof(SArithmeticSupport));
+static SWindowResult *getWindowResult(SWindowResInfo *pWindowResInfo, int32_t slot) {
+ assert(pWindowResInfo != NULL && slot >= 0 && slot < pWindowResInfo->size);
+ return &pWindowResInfo->pResult[slot];
+}
- for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
- int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
+static bool isWindowResClosed(SWindowResInfo *pWindowResInfo, int32_t slot) {
+ return (getWindowResult(pWindowResInfo, slot)->status.closed == true);
+}
- SField dummyField = {0};
+static int32_t curTimeWindow(SWindowResInfo *pWindowResInfo) {
+ assert(pWindowResInfo->curIndex >= 0 && pWindowResInfo->curIndex < pWindowResInfo->size);
+ return pWindowResInfo->curIndex;
+}
- bool hasNull = hasNullVal(pQuery, k, pBlockInfo, pFields, isDiskFileBlock);
- char *dataBlock = getDataBlocks(pRuntimeEnv, &sasArray[k], k, forwardStep);
+static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowResInfo, char *pData,
+ int16_t bytes) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
- SField *tpField = NULL;
+ int32_t *p1 = (int32_t *)taosGetDataFromHashTable(pWindowResInfo->hashList, pData, bytes);
+ if (p1 != NULL) {
+ pWindowResInfo->curIndex = *p1;
+ } else { // more than the capacity, reallocate the resources
+ if (pWindowResInfo->size >= pWindowResInfo->capacity) {
+ int64_t newCap = pWindowResInfo->capacity * 2;
- if (pFields != NULL) {
- tpField = getFieldInfo(pQuery, pBlockInfo, pFields, k);
- /*
- * Field info not exist, the required column is not present in current block,
- * so all data must be null value in current block.
- */
- if (tpField == NULL) {
- tpField = &dummyField;
- tpField->numOfNullPoints = (int32_t)forwardStep;
+ char *t = realloc(pWindowResInfo->pResult, newCap * sizeof(SWindowResult));
+ if (t != NULL) {
+ pWindowResInfo->pResult = (SWindowResult *)t;
+ memset(&pWindowResInfo->pResult[pWindowResInfo->capacity], 0, sizeof(SWindowResult) * pWindowResInfo->capacity);
+ } else {
+ // todo
}
- }
- TSKEY ts = QUERY_IS_ASC_QUERY(pQuery) ? pRuntimeEnv->intervalWindow.skey : pRuntimeEnv->intervalWindow.ekey;
- setExecParams(pQuery, &pCtx[k], ts, dataBlock, (char *)primaryKeyCol, forwardStep, functionId, tpField, hasNull,
- pRuntimeEnv->blockStatus, &sasArray[k], pRuntimeEnv->scanFlag);
- }
+ for (int32_t i = pWindowResInfo->capacity; i < newCap; ++i) {
+ SPosInfo pos = {-1, -1};
+ createQueryResultInfo(pQuery, &pWindowResInfo->pResult[i], pRuntimeEnv->stableQuery, &pos);
+ }
- /*
- * the sqlfunctionCtx parameters should be set done before all functions are invoked,
- * since the selectivity + tag_prj query needs all parameters been set done.
- * tag_prj function are changed to be TSDB_FUNC_TAG_DUMMY
- */
- for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
- int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
- if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
- aAggs[functionId].xFunction(&pCtx[k]);
+ pWindowResInfo->capacity = newCap;
}
- }
- int64_t numOfIncrementRes = getNumOfResult(pRuntimeEnv) - prevNumOfRes;
- validateTimestampForSupplementResult(pRuntimeEnv, numOfIncrementRes);
-
- tfree(sasArray);
+ // add a new result set for a new group
+ pWindowResInfo->curIndex = pWindowResInfo->size++;
+ taosAddToHashTable(pWindowResInfo->hashList, pData, bytes, (char *)&pWindowResInfo->curIndex, sizeof(int32_t));
+ }
- return (int32_t)numOfIncrementRes;
+ return getWindowResult(pWindowResInfo, pWindowResInfo->curIndex);
}
-/**
- * if sfields is null
- * 1. count(*)/spread(ts) is invoked
- * 2. this column does not exists
- *
- * first filter the data block according to the value filter condition, then, if the top/bottom query applied,
- * invoke the filter function to decide if the data block need to be accessed or not.
- * TODO handle the whole data block is NULL situation
- * @param pQuery
- * @param pField
- * @return
- */
-static bool needToLoadDataBlock(SQuery *pQuery, SField *pField, SQLFunctionCtx *pCtx, int32_t numOfTotalPoints) {
- if (pField == NULL) {
- return false; // no need to load data
- }
+// get the correct time window according to the handled timestamp
+static STimeWindow getActiveTimeWindow(SWindowResInfo *pWindowResInfo, int64_t ts, SQuery *pQuery) {
+ STimeWindow w = {0};
- for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
- SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
- int32_t colIndex = pFilterInfo->info.colIdx;
+ if (pWindowResInfo->curIndex == -1) { // the first window, from the previous stored value
+ w.skey = pWindowResInfo->prevSKey;
+ w.ekey = w.skey + pQuery->intervalTime - 1;
+ } else {
+ int32_t slot = curTimeWindow(pWindowResInfo);
+ w = getWindowResult(pWindowResInfo, slot)->window;
+ }
- // this column not valid in current data block
- if (colIndex < 0 || pField[colIndex].colId != pFilterInfo->info.data.colId) {
- continue;
- }
+ if (w.skey > ts || w.ekey < ts) {
+ int64_t st = w.skey;
- // not support pre-filter operation on binary/nchar data type
- if (!vnodeSupportPrefilter(pFilterInfo->info.data.type)) {
- continue;
+ if (st > ts) {
+ st -= ((st - ts + pQuery->slidingTime - 1) / pQuery->slidingTime) * pQuery->slidingTime;
}
- // all points in current column are NULL, no need to check its boundary value
- if (pField[colIndex].numOfNullPoints == numOfTotalPoints) {
- continue;
+ int64_t et = st + pQuery->intervalTime - 1;
+ if (et < ts) {
+ st += ((ts - et + pQuery->slidingTime - 1) / pQuery->slidingTime) * pQuery->slidingTime;
}
- if (pFilterInfo->info.data.type == TSDB_DATA_TYPE_FLOAT) {
- float minval = *(double *)(&pField[colIndex].min);
- float maxval = *(double *)(&pField[colIndex].max);
-
- for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
- if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval)) {
- return true;
- }
- }
- } else {
- for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
- if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pField[colIndex].min,
- (char *)&pField[colIndex].max)) {
- return true;
- }
- }
- }
+ w.skey = st;
+ w.ekey = w.skey + pQuery->intervalTime - 1;
}
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- int32_t functId = pQuery->pSelectExpr[i].pBase.functionId;
- if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
- return top_bot_datablock_filter(&pCtx[i], functId, (char *)&pField[i].min, (char *)&pField[i].max);
- }
+ /*
+ * query border check, skey should not be bounded by the query time range, since the value skey will
+ * be used as the time window index value. So we only change ekey of time window accordingly.
+ */
+ if (w.ekey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) {
+ w.ekey = pQuery->ekey;
}
- return true;
-}
+ assert(ts >= w.skey && ts <= w.ekey && w.skey != 0);
-static SOutputRes *doSetSlidingWindowFromKey(SSlidingWindowInfo *pSlidingWindowInfo, char *pData, int16_t bytes,
- SWindowStatus **pStatus) {
- int32_t p = -1;
+ return w;
+}
- int32_t *p1 = (int32_t *)taosGetDataFromHashTable(pSlidingWindowInfo->hashList, pData, bytes);
- if (p1 != NULL) {
- p = *p1;
+static int32_t addNewWindowResultBuf(SWindowResult *pWindowRes, SQueryDiskbasedResultBuf *pResultBuf, int32_t sid,
+ int32_t numOfRowsPerPage) {
+ if (pWindowRes->pos.pageId != -1) {
+ return 0;
+ }
- pSlidingWindowInfo->curIndex = p;
- if (pStatus != NULL) {
- *pStatus = &pSlidingWindowInfo->pStatus[p];
- }
- } else { // more than the capacity, reallocate the resources
- if (pSlidingWindowInfo->size >= pSlidingWindowInfo->capacity) {
- int64_t newCap = pSlidingWindowInfo->capacity * 2;
+ tFilePage *pData = NULL;
- char *t = realloc(pSlidingWindowInfo->pStatus, newCap * sizeof(SWindowStatus));
- if (t != NULL) {
- pSlidingWindowInfo->pStatus = (SWindowStatus *)t;
- memset(&pSlidingWindowInfo->pStatus[pSlidingWindowInfo->capacity], 0, sizeof(SWindowStatus) * pSlidingWindowInfo->capacity);
- } else {
- // todo
- }
+ // in the first scan, new space needed for results
+ int32_t pageId = -1;
+ SIDList list = getDataBufPagesIdList(pResultBuf, sid);
- pSlidingWindowInfo->capacity = newCap;
- }
+ if (list.size == 0) {
+ pData = getNewDataBuf(pResultBuf, sid, &pageId);
+ } else {
+ pageId = getLastPageId(&list);
+ pData = getResultBufferPageById(pResultBuf, pageId);
- // add a new result set for a new group
- if (pStatus != NULL) {
- *pStatus = &pSlidingWindowInfo->pStatus[pSlidingWindowInfo->size];
+ if (pData->numOfElems >= numOfRowsPerPage) {
+ pData = getNewDataBuf(pResultBuf, sid, &pageId);
+ if (pData != NULL) {
+ assert(pData->numOfElems == 0); // number of elements must be 0 for new allocated buffer
+ }
}
+ }
- p = pSlidingWindowInfo->size;
- pSlidingWindowInfo->curIndex = pSlidingWindowInfo->size;
+ if (pData == NULL) {
+ return -1;
+ }
- pSlidingWindowInfo->size += 1;
- taosAddToHashTable(pSlidingWindowInfo->hashList, pData, bytes, (char *)&pSlidingWindowInfo->curIndex, sizeof(int32_t));
+ // set the number of rows in current disk page
+ if (pWindowRes->pos.pageId == -1) { // not allocated yet, allocate new buffer
+ pWindowRes->pos.pageId = pageId;
+ pWindowRes->pos.rowId = pData->numOfElems++;
}
- return &pSlidingWindowInfo->pResult[p];
+ return 0;
}
-static int32_t initSlidingWindowInfo(SSlidingWindowInfo *pSlidingWindowInfo, int32_t threshold, int16_t type, int32_t rowSizes,
- SOutputRes *pRes) {
- pSlidingWindowInfo->capacity = threshold;
- pSlidingWindowInfo->threshold = threshold;
+static int32_t setWindowOutputBufByKey(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowResInfo, int32_t sid,
+ STimeWindow *win) {
+ assert(win->skey <= win->ekey);
+ SQueryDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
- pSlidingWindowInfo->type = type;
+ SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, pWindowResInfo, (char *)&win->skey, TSDB_KEYSIZE);
+ if (pWindowRes == NULL) {
+ return -1;
+ }
- _hash_fn_t fn = taosGetDefaultHashFunction(type);
- pSlidingWindowInfo->hashList = taosInitHashTable(threshold, fn, false);
+ // not assign result buffer yet, add new result buffer
+ if (pWindowRes->pos.pageId == -1) {
+ int32_t ret = addNewWindowResultBuf(pWindowRes, pResultBuf, sid, pRuntimeEnv->numOfRowsPerPage);
+ if (ret != 0) {
+ return -1;
+ }
+ }
- pSlidingWindowInfo->curIndex = -1;
- pSlidingWindowInfo->size = 0;
- pSlidingWindowInfo->pResult = pRes;
+ // set time window for current result
+ pWindowRes->window = *win;
-// createResultBuf(&pSlidingWindowInfo->pResultBuf, 10, rowSizes);
-
- pSlidingWindowInfo->pStatus = calloc(threshold, sizeof(SWindowStatus));
-// pSlidingWindowInfo->pResultInfo = calloc(threshold, POINTER_BYTES);
-
-// for(int32_t i = 0; i < threshold; ++i) {
-// pSlidingWindowInfo->pResultInfo[i] = calloc((size_t)numOfOutput, sizeof(SResultInfo));
-
-
-// }
-
- if (pSlidingWindowInfo->pStatus == NULL || pSlidingWindowInfo->hashList == NULL) {
- return -1;
- }
+ setWindowResOutputBuf(pRuntimeEnv, pWindowRes);
+ initCtxOutputBuf(pRuntimeEnv);
return TSDB_CODE_SUCCESS;
}
-static void destroySlidingWindowInfo(SSlidingWindowInfo *pSlidingWindowInfo) {
- if (pSlidingWindowInfo == NULL || pSlidingWindowInfo->capacity == 0) {
- assert(pSlidingWindowInfo->hashList == NULL && pSlidingWindowInfo->pResult == NULL);
- return;
+static SWindowStatus *getTimeWindowResStatus(SWindowResInfo *pWindowResInfo, int32_t slot) {
+ assert(slot >= 0 && slot < pWindowResInfo->size);
+ return &pWindowResInfo->pResult[slot].status;
+}
+
+static int32_t getForwardStepsInBlock(int32_t numOfPoints, __block_search_fn_t searchFn, TSKEY ekey, int16_t pos,
+ int16_t order, int64_t *pData) {
+ int32_t endPos = searchFn((char *)pData, numOfPoints, ekey, order);
+ int32_t forwardStep = 0;
+
+ if (endPos >= 0) {
+ forwardStep = (order == TSQL_SO_ASC) ? (endPos - pos) : (pos - endPos);
+ assert(forwardStep >= 0);
+
+ // endPos data is equalled to the key so, we do need to read the element in endPos
+ if (pData[endPos] == ekey) {
+ forwardStep += 1;
+ }
}
- taosCleanUpHashTable(pSlidingWindowInfo->hashList);
-// destroyResultBuf(pSlidingWindowInfo->pResultBuf);
-
- tfree(pSlidingWindowInfo->pStatus);
+ return forwardStep;
}
-void resetSlidingWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SSlidingWindowInfo *pSlidingWindowInfo) {
- if (pSlidingWindowInfo == NULL || pSlidingWindowInfo->capacity == 0) {
+/**
+ * NOTE: the query status only set for the first scan of master scan.
+ */
+static void doCheckQueryCompleted(SQueryRuntimeEnv *pRuntimeEnv, TSKEY lastKey, SWindowResInfo *pWindowResInfo) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+ if (pRuntimeEnv->scanFlag != MASTER_SCAN || (!isIntervalQuery(pQuery))) {
return;
}
-
- for (int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SOutputRes *pOneRes = &pSlidingWindowInfo->pResult[i];
- clearGroupResultBuf(pRuntimeEnv, pOneRes);
+
+ // no qualified results exist, abort check
+ if (pWindowResInfo->size == 0) {
+ return;
}
- memset(pSlidingWindowInfo->pStatus, 0, sizeof(SWindowStatus) * pSlidingWindowInfo->capacity);
+ // query completed
+ if ((lastKey >= pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (lastKey <= pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ closeAllTimeWindow(pWindowResInfo);
- pSlidingWindowInfo->curIndex = -1;
- taosCleanUpHashTable(pSlidingWindowInfo->hashList);
- pSlidingWindowInfo->size = 0;
-
- _hash_fn_t fn = taosGetDefaultHashFunction(pSlidingWindowInfo->type);
- pSlidingWindowInfo->hashList = taosInitHashTable(pSlidingWindowInfo->capacity, fn, false);
+ pWindowResInfo->curIndex = pWindowResInfo->size - 1;
+ setQueryStatus(pQuery, QUERY_COMPLETED | QUERY_RESBUF_FULL);
+ } else { // set the current index to be the last unclosed window
+ int32_t i = 0;
+ int64_t skey = 0;
- pSlidingWindowInfo->startTime = 0;
- pSlidingWindowInfo->prevSKey = 0;
-}
+ for (i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowResult *pResult = &pWindowResInfo->pResult[i];
+ if (pResult->status.closed) {
+ continue;
+ }
-void clearCompletedSlidingWindows(SQueryRuntimeEnv* pRuntimeEnv) {
- SSlidingWindowInfo* pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
- if (pSlidingWindowInfo == NULL || pSlidingWindowInfo->capacity == 0 || pSlidingWindowInfo->size == 0) {
- return;
- }
+ if ((pResult->window.ekey <= lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pResult->window.skey >= lastKey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ closeTimeWindow(pWindowResInfo, i);
+ } else {
+ skey = pResult->window.skey;
+ break;
+ }
+ }
- int32_t i = 0;
- for (i = 0; i < pSlidingWindowInfo->size; ++i) {
- SWindowStatus *pStatus = &pSlidingWindowInfo->pStatus[i];
- if (pStatus->closed) { // remove the window slot from hash table
- taosDeleteFromHashTable(pSlidingWindowInfo->hashList, (const char *)&pStatus->window.skey, TSDB_KEYSIZE);
+ // all windows are closed, set the last one to be the skey
+ if (skey == 0) {
+ assert(i == pWindowResInfo->size);
+ pWindowResInfo->curIndex = pWindowResInfo->size - 1;
} else {
- break;
+ pWindowResInfo->curIndex = i;
}
- }
- if (i == 0) {
- return;
- }
-
- int32_t remain = pSlidingWindowInfo->size - i;
-
- //clear remain list
- memmove(pSlidingWindowInfo->pStatus, &pSlidingWindowInfo->pStatus[i], remain * sizeof(SWindowStatus));
- memset(&pSlidingWindowInfo->pStatus[remain], 0, (pSlidingWindowInfo->capacity - remain) * sizeof(SWindowStatus));
-
- for(int32_t k = 0; k < remain; ++k) {
- copyGroupResultBuf(pRuntimeEnv, &pSlidingWindowInfo->pResult[k], &pSlidingWindowInfo->pResult[i + k]);
- }
-
- for(int32_t k = remain; k < pSlidingWindowInfo->size; ++k) {
- SOutputRes *pOneRes = &pSlidingWindowInfo->pResult[k];
- clearGroupResultBuf(pRuntimeEnv, pOneRes);
- }
+ pWindowResInfo->prevSKey = pWindowResInfo->pResult[pWindowResInfo->curIndex].window.skey;
- pSlidingWindowInfo->size = remain;
+ // the number of completed slots are larger than the threshold, dump to client immediately.
+ int32_t n = numOfClosedTimeWindow(pWindowResInfo);
+ if (n > pWindowResInfo->threshold) {
+ setQueryStatus(pQuery, QUERY_RESBUF_FULL);
+ }
- for(int32_t k = 0; k < pSlidingWindowInfo->size; ++k) {
- SWindowStatus* pStatus = &pSlidingWindowInfo->pStatus[k];
- int32_t *p = (int32_t*) taosGetDataFromHashTable(pSlidingWindowInfo->hashList, (const char*)&pStatus->window.skey, TSDB_KEYSIZE);
- int32_t v = *p;
- v = (v - i);
-
- taosDeleteFromHashTable(pSlidingWindowInfo->hashList, (const char *)&pStatus->window.skey, TSDB_KEYSIZE);
-
- taosAddToHashTable(pSlidingWindowInfo->hashList, (const char*)&pStatus->window.skey, TSDB_KEYSIZE,
- (char *)&v, sizeof(int32_t));
+ dTrace("QInfo:%p total window:%d, closed:%d", GET_QINFO_ADDR(pQuery), pWindowResInfo->size, n);
}
-
- pSlidingWindowInfo->curIndex = -1;
-}
-int32_t numOfClosedSlidingWindow(SSlidingWindowInfo *pSlidingWindowInfo) {
- int32_t i = 0;
- while(i < pSlidingWindowInfo->size && pSlidingWindowInfo->pStatus[i].closed) {
- ++i;
- }
-
- return i;
+ assert(pWindowResInfo->prevSKey != 0);
}
-void closeSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo, int32_t slot) {
- assert(slot >= 0 && slot < pSlidingWindowInfo->size);
- SWindowStatus* pStatus = &pSlidingWindowInfo->pStatus[slot];
- pStatus->closed = true;
-}
+static int32_t getNumOfRowsInTimeWindow(SQuery *pQuery, SBlockInfo *pBlockInfo, TSKEY *pPrimaryColumn, int32_t startPos,
+ TSKEY ekey, __block_search_fn_t searchFn, bool updateLastKey) {
+ assert(startPos >= 0 && startPos < pBlockInfo->size);
-void closeAllSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo) {
- assert(pSlidingWindowInfo->size >=0 && pSlidingWindowInfo->capacity >= pSlidingWindowInfo->size);
-
- for(int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SWindowStatus* pStatus = &pSlidingWindowInfo->pStatus[i];
- pStatus->closed = true;
+ int32_t num = -1;
+ int32_t order = pQuery->order.order;
+
+ int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);
+
+ if (QUERY_IS_ASC_QUERY(pQuery)) {
+ if (ekey < pBlockInfo->keyLast) {
+ num = getForwardStepsInBlock(pBlockInfo->size, searchFn, ekey, startPos, order, pPrimaryColumn);
+ if (num == 0) { // no qualified data in current block, do not update the lastKey value
+ assert(ekey < pPrimaryColumn[startPos]);
+ } else {
+ if (updateLastKey) {
+ pQuery->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
+ }
+ }
+ } else {
+ num = pBlockInfo->size - startPos;
+ if (updateLastKey) {
+ pQuery->lastKey = pBlockInfo->keyLast + step;
+ }
+ }
+ } else { // desc
+ if (ekey > pBlockInfo->keyFirst) {
+ num = getForwardStepsInBlock(pBlockInfo->size, searchFn, ekey, startPos, order, pPrimaryColumn);
+ if (num == 0) { // no qualified data in current block, do not update the lastKey value
+ assert(ekey > pPrimaryColumn[startPos]);
+ } else {
+ if (updateLastKey) {
+ pQuery->lastKey = pPrimaryColumn[startPos - (num - 1)] + step;
+ }
+ }
+ } else {
+ num = startPos + 1;
+ if (updateLastKey) {
+ pQuery->lastKey = pBlockInfo->keyFirst + step;
+ }
+ }
}
+
+ assert(num >= 0);
+ return num;
}
-static SWindowStatus* getSlidingWindowStatus(SSlidingWindowInfo *pSlidingWindowInfo, int32_t slot) {
- return &pSlidingWindowInfo->pStatus[slot];
+static void doBlockwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SWindowStatus *pStatus, STimeWindow *pWin,
+ int32_t startPos, int32_t forwardStep) {
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
+
+ if (IS_MASTER_SCAN(pRuntimeEnv) || pStatus->closed) {
+ for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
+ pCtx[k].nStartQueryTimestamp = pWin->skey;
+ pCtx[k].size = forwardStep;
+ pCtx[k].startOffset = (QUERY_IS_ASC_QUERY(pQuery)) ? startPos : startPos - (forwardStep - 1);
+
+ int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
+ if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
+ aAggs[functionId].xFunction(&pCtx[k]);
+ }
+ }
+ }
}
-static bool slidingWindowClosed(SSlidingWindowInfo* pSlidingWindowInfo, int32_t slot) {
- return (pSlidingWindowInfo->pStatus[slot].closed == true);
+static void doRowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SWindowStatus *pStatus, STimeWindow *pWin,
+ int32_t offset) {
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
+
+ if (IS_MASTER_SCAN(pRuntimeEnv) || pStatus->closed) {
+ for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
+ pCtx[k].nStartQueryTimestamp = pWin->skey;
+
+ int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
+ if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
+ aAggs[functionId].xFunctionF(&pCtx[k], offset);
+ }
+ }
+ }
}
-static int32_t curSlidingWindow(SSlidingWindowInfo *pSlidingWindowInfo) {
- assert(pSlidingWindowInfo->curIndex >= 0 && pSlidingWindowInfo->curIndex < pSlidingWindowInfo->size);
-
- return pSlidingWindowInfo->curIndex;
+static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pNextWin,
+ SWindowResInfo *pWindowResInfo, SBlockInfo *pBlockInfo, TSKEY *primaryKeys,
+ __block_search_fn_t searchFn) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+
+ while (1) {
+ getNextTimeWindow(pQuery, pNextWin);
+
+ if (pWindowResInfo->startTime > pNextWin->skey || (pNextWin->skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pNextWin->ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ return -1;
+ }
+
+ // next time window is not in current block
+ if ((pNextWin->skey > pBlockInfo->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pNextWin->ekey < pBlockInfo->keyFirst && !QUERY_IS_ASC_QUERY(pQuery))) {
+ return -1;
+ }
+
+ TSKEY startKey = QUERY_IS_ASC_QUERY(pQuery) ? pNextWin->skey : pNextWin->ekey;
+ int32_t startPos = searchFn((char *)primaryKeys, pBlockInfo->size, startKey, pQuery->order.order);
+
+ /*
+ * This time window does not cover any data, try next time window,
+ * this case may happen when the time window is too small
+ */
+ if ((primaryKeys[startPos] > pNextWin->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (primaryKeys[startPos] < pNextWin->skey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ continue;
+ }
+
+// if (pNextWin->ekey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) {
+// pNextWin->ekey = pQuery->ekey;
+// }
+// if (pNextWin->skey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery)) {
+// pNextWin->skey = pQuery->ekey;
+// }
+
+ return startPos;
+ }
}
-// get the correct sliding window according to the handled timestamp
-static STimeWindow getActiveSlidingWindow(SSlidingWindowInfo* pSlidingWindowInfo, int64_t ts, SQuery* pQuery) {
- STimeWindow w = {0};
-
- if (pSlidingWindowInfo->curIndex == -1) { // the first window, from the prevous stored value
- w.skey = pSlidingWindowInfo->prevSKey;
- w.ekey = w.skey + pQuery->nAggTimeInterval - 1;
-
+static TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) {
+ TSKEY ekey = -1;
+ if (QUERY_IS_ASC_QUERY(pQuery)) {
+ ekey = pWindow->ekey;
+ if (ekey > pQuery->ekey) {
+ ekey = pQuery->ekey;
+ }
} else {
- SWindowStatus* pStatus = getSlidingWindowStatus(pSlidingWindowInfo, curSlidingWindow(pSlidingWindowInfo));
-
- if (pStatus->window.skey <= ts && pStatus->window.ekey >= ts) {
- w = pStatus->window;
- } else {
- int64_t st = pStatus->window.skey;
-
- while (st > ts) {
- st -= pQuery->slidingTime;
+ ekey = pWindow->skey;
+ if (ekey < pQuery->ekey) {
+ ekey = pQuery->ekey;
+ }
+ }
+
+ return ekey;
+}
+
+/**
+ *
+ * @param pRuntimeEnv
+ * @param forwardStep
+ * @param primaryKeyCol
+ * @param pFields
+ * @param isDiskFileBlock
+ * @return the incremental number of output value, so it maybe 0 for fixed number of query,
+ * such as count/min/max etc.
+ */
+static int32_t blockwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t forwardStep, SField *pFields,
+ SBlockInfo *pBlockInfo, SWindowResInfo *pWindowResInfo,
+ __block_search_fn_t searchFn) {
+ SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ TSKEY * primaryKeyCol = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
+
+ bool isDiskFileBlock = IS_FILE_BLOCK(pRuntimeEnv->blockStatus);
+ int64_t prevNumOfRes = getNumOfResult(pRuntimeEnv);
+
+ SArithmeticSupport *sasArray = calloc((size_t)pQuery->numOfOutputCols, sizeof(SArithmeticSupport));
+
+ for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
+ int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
+
+ SField dummyField = {0};
+
+ bool hasNull = hasNullVal(pQuery, k, pBlockInfo, pFields, isDiskFileBlock);
+ char *dataBlock = getDataBlocks(pRuntimeEnv, &sasArray[k], k, forwardStep);
+
+ SField *tpField = NULL;
+
+ if (pFields != NULL) {
+ tpField = getFieldInfo(pQuery, pBlockInfo, pFields, k);
+ /*
+ * Field info not exist, the required column is not present in current block,
+ * so all data must be null value in current block.
+ */
+ if (tpField == NULL) {
+ tpField = &dummyField;
+ tpField->numOfNullPoints = (int32_t)forwardStep;
}
-
- while ((st + pQuery->nAggTimeInterval - 1) < ts) {
- st += pQuery->slidingTime;
+ }
+
+ setExecParams(pQuery, &pCtx[k], pQuery->skey, dataBlock, (char *)primaryKeyCol, forwardStep, functionId, tpField,
+ hasNull, pRuntimeEnv->blockStatus, &sasArray[k], pRuntimeEnv->scanFlag);
+ }
+
+ int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+ if (isIntervalQuery(pQuery)) {
+ int32_t offset = GET_COL_DATA_POS(pQuery, 0, step);
+ TSKEY ts = primaryKeyCol[offset];
+
+ STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery);
+ if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, pRuntimeEnv->pMeterObj->sid, &win) != TSDB_CODE_SUCCESS) {
+ return 0;
+ }
+
+ TSKEY ekey = reviseWindowEkey(pQuery, &win);
+ forwardStep = getNumOfRowsInTimeWindow(pQuery, pBlockInfo, primaryKeyCol, pQuery->pos, ekey, searchFn, true);
+
+ SWindowStatus *pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo));
+ doBlockwiseApplyFunctions(pRuntimeEnv, pStatus, &win, pQuery->pos, forwardStep);
+
+ int32_t index = pWindowResInfo->curIndex;
+ STimeWindow nextWin = win;
+
+ while (1) {
+ int32_t startPos =
+ getNextQualifiedWindow(pRuntimeEnv, &nextWin, pWindowResInfo, pBlockInfo, primaryKeyCol, searchFn);
+ if (startPos < 0) {
+ break;
+ }
+
+ // null data, failed to allocate more memory buffer
+ int32_t sid = pRuntimeEnv->pMeterObj->sid;
+ if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, sid, &nextWin) != TSDB_CODE_SUCCESS) {
+ break;
+ }
+
+ ekey = reviseWindowEkey(pQuery, &nextWin);
+ forwardStep = getNumOfRowsInTimeWindow(pQuery, pBlockInfo, primaryKeyCol, startPos, ekey, searchFn, true);
+
+ pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo));
+ doBlockwiseApplyFunctions(pRuntimeEnv, pStatus, &nextWin, startPos, forwardStep);
+ }
+
+ pWindowResInfo->curIndex = index;
+ } else {
+ /*
+ * the sqlfunctionCtx parameters should be set done before all functions are invoked,
+ * since the selectivity + tag_prj query needs all parameters been set done.
+ * tag_prj function are changed to be TSDB_FUNC_TAG_DUMMY
+ */
+ for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
+ int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
+ if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
+ aAggs[functionId].xFunction(&pCtx[k]);
}
-
- w.skey = st;
- w.ekey = w.skey + pQuery->nAggTimeInterval - 1;
}
}
-
- assert(ts >= w.skey && ts <= w.ekey);
- return w;
+
+ /*
+ * No need to calculate the number of output results for group-by normal columns, interval query
+ * because the results of group by normal column is put into intermediate buffer.
+ */
+ int32_t num = 0;
+ if (!isIntervalQuery(pQuery)) {
+ num = getNumOfResult(pRuntimeEnv) - prevNumOfRes;
+ }
+
+ tfree(sasArray);
+ return (int32_t)num;
}
-static int32_t setGroupResultFromKey(SQueryRuntimeEnv *pRuntimeEnv, char *pData, int16_t type, int16_t bytes) {
- if (isNull(pData, type)) { // ignore the null value
- return -1;
+/**
+ * if sfields is null
+ * 1. count(*)/spread(ts) is invoked
+ * 2. this column does not exists
+ *
+ * first filter the data block according to the value filter condition, then, if the top/bottom query applied,
+ * invoke the filter function to decide if the data block need to be accessed or not.
+ * TODO handle the whole data block is NULL situation
+ * @param pQuery
+ * @param pField
+ * @return
+ */
+static bool needToLoadDataBlock(SQuery *pQuery, SField *pField, SQLFunctionCtx *pCtx, int32_t numOfTotalPoints) {
+ if (pField == NULL) {
+ return false; // no need to load data
}
- SOutputRes *pOutputRes = doSetSlidingWindowFromKey(&pRuntimeEnv->swindowResInfo, pData, bytes, NULL);
- if (pOutputRes == NULL) {
- return -1;
+ for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) {
+ SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k];
+ int32_t colIndex = pFilterInfo->info.colIdx;
+
+ // this column not valid in current data block
+ if (colIndex < 0 || pField[colIndex].colId != pFilterInfo->info.data.colId) {
+ continue;
+ }
+
+ // not support pre-filter operation on binary/nchar data type
+ if (!vnodeSupportPrefilter(pFilterInfo->info.data.type)) {
+ continue;
+ }
+
+ // all points in current column are NULL, no need to check its boundary value
+ if (pField[colIndex].numOfNullPoints == numOfTotalPoints) {
+ continue;
+ }
+
+ if (pFilterInfo->info.data.type == TSDB_DATA_TYPE_FLOAT) {
+ float minval = *(double *)(&pField[colIndex].min);
+ float maxval = *(double *)(&pField[colIndex].max);
+
+ for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
+ if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval)) {
+ return true;
+ }
+ }
+ } else {
+ for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) {
+ if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&pField[colIndex].min,
+ (char *)&pField[colIndex].max)) {
+ return true;
+ }
+ }
+ }
}
- setGroupOutputBuffer(pRuntimeEnv, pOutputRes);
- initCtxOutputBuf(pRuntimeEnv);
+ // todo disable this opt code block temporarily
+ // for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ // int32_t functId = pQuery->pSelectExpr[i].pBase.functionId;
+ // if (functId == TSDB_FUNC_TOP || functId == TSDB_FUNC_BOTTOM) {
+ // return top_bot_datablock_filter(&pCtx[i], functId, (char *)&pField[i].min, (char *)&pField[i].max);
+ // }
+ // }
+
+ return true;
+}
+
+int32_t initWindowResInfo(SWindowResInfo *pWindowResInfo, SQueryRuntimeEnv *pRuntimeEnv, int32_t size,
+ int32_t threshold, int16_t type) {
+ if (size < threshold) {
+ size = threshold;
+ }
+
+ pWindowResInfo->capacity = size;
+ pWindowResInfo->threshold = threshold;
+
+ pWindowResInfo->type = type;
+
+ _hash_fn_t fn = taosGetDefaultHashFunction(type);
+ pWindowResInfo->hashList = taosInitHashTable(threshold, fn, false);
+
+ pWindowResInfo->curIndex = -1;
+ pWindowResInfo->size = 0;
+
+ // use the pointer arraylist
+ pWindowResInfo->pResult = calloc(threshold, sizeof(SWindowResult));
+ for (int32_t i = 0; i < threshold; ++i) {
+ SPosInfo posInfo = {-1, -1};
+ createQueryResultInfo(pRuntimeEnv->pQuery, &pWindowResInfo->pResult[i], pRuntimeEnv->stableQuery, &posInfo);
+ }
return TSDB_CODE_SUCCESS;
}
-static int32_t setSlidingWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow *pTimeWindow) {
- assert(pTimeWindow->skey < pTimeWindow->ekey);
-
- int64_t st = pTimeWindow->skey;
-
- SWindowStatus *pStatus = NULL;
- SOutputRes* pOutputRes = doSetSlidingWindowFromKey(&pRuntimeEnv->swindowResInfo, (char *)&st, TSDB_KEYSIZE,
- &pStatus);
-
- if (pOutputRes == NULL) {
+void cleanupTimeWindowInfo(SWindowResInfo *pWindowResInfo, SQueryRuntimeEnv *pRuntimeEnv) {
+ if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0) {
+ assert(pWindowResInfo->hashList == NULL && pWindowResInfo->pResult == NULL);
+ return;
+ }
+
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowResult *pResult = &pWindowResInfo->pResult[i];
+ destroyTimeWindowRes(pResult, pRuntimeEnv->pQuery->numOfOutputCols);
+ }
+
+ taosCleanUpHashTable(pWindowResInfo->hashList);
+ tfree(pWindowResInfo->pResult);
+}
+
+void resetTimeWindowInfo(SQueryRuntimeEnv *pRuntimeEnv, SWindowResInfo *pWindowResInfo) {
+ if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0) {
+ return;
+ }
+
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowResult *pWindowRes = &pWindowResInfo->pResult[i];
+ clearTimeWindowResBuf(pRuntimeEnv, pWindowRes);
+ }
+
+ pWindowResInfo->curIndex = -1;
+ taosCleanUpHashTable(pWindowResInfo->hashList);
+ pWindowResInfo->size = 0;
+
+ _hash_fn_t fn = taosGetDefaultHashFunction(pWindowResInfo->type);
+ pWindowResInfo->hashList = taosInitHashTable(pWindowResInfo->capacity, fn, false);
+
+ pWindowResInfo->startTime = 0;
+ pWindowResInfo->prevSKey = 0;
+}
+
+void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) {
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
+ if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0 || pWindowResInfo->size == 0 || num == 0) {
+ return;
+ }
+
+ int32_t numOfClosed = numOfClosedTimeWindow(pWindowResInfo);
+ assert(num >= 0 && num <= numOfClosed);
+
+ for (int32_t i = 0; i < num; ++i) {
+ SWindowResult *pResult = &pWindowResInfo->pResult[i];
+ if (pResult->status.closed) { // remove the window slot from hash table
+ taosDeleteFromHashTable(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE);
+ } else {
+ break;
+ }
+ }
+
+ int32_t remain = pWindowResInfo->size - num;
+
+ // clear all the closed windows from the window list
+ for (int32_t k = 0; k < remain; ++k) {
+ copyTimeWindowResBuf(pRuntimeEnv, &pWindowResInfo->pResult[k], &pWindowResInfo->pResult[num + k]);
+ }
+
+ // move the unclosed window in the front of the window list
+ for (int32_t k = remain; k < pWindowResInfo->size; ++k) {
+ SWindowResult *pWindowRes = &pWindowResInfo->pResult[k];
+ clearTimeWindowResBuf(pRuntimeEnv, pWindowRes);
+ }
+
+ pWindowResInfo->size = remain;
+
+ for (int32_t k = 0; k < pWindowResInfo->size; ++k) {
+ SWindowResult *pResult = &pWindowResInfo->pResult[k];
+ int32_t *p = (int32_t *)taosGetDataFromHashTable(pWindowResInfo->hashList, (const char *)&pResult->window.skey,
+ TSDB_KEYSIZE);
+ int32_t v = (*p - num);
+ assert(v >= 0 && v <= pWindowResInfo->size);
+
+ // todo add the update function for hash table
+ taosDeleteFromHashTable(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE);
+ taosAddToHashTable(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE, (char *)&v,
+ sizeof(int32_t));
+ }
+
+ pWindowResInfo->curIndex = -1;
+}
+
+void clearClosedTimeWindow(SQueryRuntimeEnv *pRuntimeEnv) {
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
+ if (pWindowResInfo == NULL || pWindowResInfo->capacity == 0 || pWindowResInfo->size == 0) {
+ return;
+ }
+
+ int32_t numOfClosed = numOfClosedTimeWindow(pWindowResInfo);
+ clearFirstNTimeWindow(pRuntimeEnv, numOfClosed);
+}
+
+int32_t numOfClosedTimeWindow(SWindowResInfo *pWindowResInfo) {
+ int32_t i = 0;
+ while (i < pWindowResInfo->size && pWindowResInfo->pResult[i].status.closed) {
+ ++i;
+ }
+
+ return i;
+}
+
+void closeTimeWindow(SWindowResInfo *pWindowResInfo, int32_t slot) {
+ getWindowResult(pWindowResInfo, slot)->status.closed = true;
+}
+
+void closeAllTimeWindow(SWindowResInfo *pWindowResInfo) {
+ assert(pWindowResInfo->size >= 0 && pWindowResInfo->capacity >= pWindowResInfo->size);
+
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ pWindowResInfo->pResult[i].status.closed = true;
+ }
+}
+
+static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, char *pData, int16_t type, int16_t bytes) {
+ if (isNull(pData, type)) { // ignore the null value
return -1;
}
- pStatus->window = *pTimeWindow;
- setGroupOutputBuffer(pRuntimeEnv, pOutputRes);
- initCtxOutputBuf(pRuntimeEnv);
+ int32_t GROUPRESULTID = 1;
+
+ SQueryDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
+
+ SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, pData, bytes);
+ if (pWindowRes == NULL) {
+ return -1;
+ }
+ // not assign result buffer yet, add new result buffer
+ if (pWindowRes->pos.pageId == -1) {
+ int32_t ret = addNewWindowResultBuf(pWindowRes, pResultBuf, GROUPRESULTID, pRuntimeEnv->numOfRowsPerPage);
+ if (ret != 0) {
+ return -1;
+ }
+ }
+
+ setWindowResOutputBuf(pRuntimeEnv, pWindowRes);
+ initCtxOutputBuf(pRuntimeEnv);
return TSDB_CODE_SUCCESS;
}
@@ -1915,7 +2253,7 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx
}
// in the supplementary scan, only the following functions need to be executed
- if (!IS_MASTER_SCAN(pRuntimeEnv) &&
+ if (IS_SUPPLEMENT_SCAN(pRuntimeEnv) &&
!(functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST ||
functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TS)) {
return false;
@@ -1924,10 +2262,11 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx
return true;
}
-static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *forwardStep, TSKEY *primaryKeyCol,
- SField *pFields, SBlockInfo *pBlockInfo) {
+static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *forwardStep, SField *pFields,
+ SBlockInfo *pBlockInfo, SWindowResInfo *pWindowResInfo) {
SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
SQuery * pQuery = pRuntimeEnv->pQuery;
+ TSKEY * primaryKeyCol = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
bool isDiskFileBlock = IS_FILE_BLOCK(pRuntimeEnv->blockStatus);
SData **data = pRuntimeEnv->colDataBuffer;
@@ -1955,7 +2294,8 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
bool hasNull = hasNullVal(pQuery, k, pBlockInfo, pFields, isDiskFileBlock);
char *dataBlock = getDataBlocks(pRuntimeEnv, &sasArray[k], k, *forwardStep);
- TSKEY ts = QUERY_IS_ASC_QUERY(pQuery) ? pRuntimeEnv->intervalWindow.skey : pRuntimeEnv->intervalWindow.ekey;
+ TSKEY ts = pQuery->skey; // QUERY_IS_ASC_QUERY(pQuery) ? pRuntimeEnv->intervalWindow.skey :
+ // pRuntimeEnv->intervalWindow.ekey;
setExecParams(pQuery, &pCtx[k], ts, dataBlock, (char *)primaryKeyCol, (*forwardStep), functionId, pFields, hasNull,
pRuntimeEnv->blockStatus, &sasArray[k], pRuntimeEnv->scanFlag);
}
@@ -1982,14 +2322,13 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
}
int32_t j = 0;
- int64_t lastKey = 0;
-
+ TSKEY lastKey = -1;
+
for (j = 0; j < (*forwardStep); ++j) {
int32_t offset = GET_COL_DATA_POS(pQuery, j, step);
if (pRuntimeEnv->pTSBuf != NULL) {
int32_t r = doTSJoinFilter(pRuntimeEnv, offset);
-
if (r == TS_JOIN_TAG_NOT_EQUALS) {
break;
} else if (r == TS_JOIN_TS_NOT_EQUALS) {
@@ -2003,15 +2342,13 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
continue;
}
- // sliding window query
- if (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0) {
+ // interval window query
+ if (isIntervalQuery(pQuery)) {
// decide the time window according to the primary timestamp
- int64_t ts = primaryKeyCol[offset];
-
- SSlidingWindowInfo* pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
- STimeWindow win = getActiveSlidingWindow(pSlidingWindowInfo, ts, pQuery);
+ int64_t ts = primaryKeyCol[offset];
+ STimeWindow win = getActiveTimeWindow(pWindowResInfo, ts, pQuery);
- int32_t ret = setSlidingWindowFromKey(pRuntimeEnv, &win);
+ int32_t ret = setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, pRuntimeEnv->pMeterObj->sid, &win);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
continue;
}
@@ -2019,73 +2356,49 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
// all startOffset are identical
offset -= pCtx[0].startOffset;
- for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
- int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
- pCtx[k].nStartQueryTimestamp = win.skey;
-
- SWindowStatus* pStatus = getSlidingWindowStatus(pSlidingWindowInfo, curSlidingWindow(pSlidingWindowInfo));
-
- if (!IS_MASTER_SCAN(pRuntimeEnv) && !pStatus->closed) {
-// qTrace("QInfo:%p not completed in supplementary scan, ignore funcId:%d, window:%lld-%lld",
-// GET_QINFO_ADDR(pQuery), functionId, pStatus->window.skey, pStatus->window.ekey);
- continue;
- }
-
- if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
- aAggs[functionId].xFunctionF(&pCtx[k], offset);
- }
- }
+ SWindowStatus *pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo));
+ doRowwiseApplyFunctions(pRuntimeEnv, pStatus, &win, offset);
lastKey = ts;
- int32_t index = pRuntimeEnv->swindowResInfo.curIndex;
-
STimeWindow nextWin = win;
+ int32_t index = pWindowResInfo->curIndex;
+ int32_t sid = pRuntimeEnv->pMeterObj->sid;
+
while (1) {
- getNextLogicalQueryRange(pRuntimeEnv, &nextWin);
- if (pSlidingWindowInfo->startTime > nextWin.skey || (nextWin.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ getNextTimeWindow(pQuery, &nextWin);
+ if (pWindowResInfo->startTime > nextWin.skey || (nextWin.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(nextWin.skey > pQuery->skey && !QUERY_IS_ASC_QUERY(pQuery))) {
- pRuntimeEnv->swindowResInfo.curIndex = index;
break;
}
- if (ts >= nextWin.skey && ts <= nextWin.ekey) {
- // null data, failed to allocate more memory buffer
- if (setSlidingWindowFromKey(pRuntimeEnv, &nextWin) != TSDB_CODE_SUCCESS) {
- pRuntimeEnv->swindowResInfo.curIndex = index;
- break;
- }
+ if (ts < nextWin.skey || ts > nextWin.ekey) {
+ break;
+ }
- for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
- int32_t functionId = pQuery->pSelectExpr[k].pBase.functionId;
- pCtx[k].nStartQueryTimestamp = nextWin.skey;
-
- SWindowStatus* pStatus = getSlidingWindowStatus(pSlidingWindowInfo, curSlidingWindow(pSlidingWindowInfo));
- if (!IS_MASTER_SCAN(pRuntimeEnv) && !pStatus->closed) {
-// qTrace("QInfo:%p not completed in supplementary scan, ignore funcId:%d, window:%lld-%lld",
-// GET_QINFO_ADDR(pQuery), functionId, pStatus->window.skey, pStatus->window.ekey);
- continue;
- }
-
- if (functionNeedToExecute(pRuntimeEnv, &pCtx[k], functionId)) {
- aAggs[functionId].xFunctionF(&pCtx[k], offset);
- }
- }
- } else {
- pRuntimeEnv->swindowResInfo.curIndex = index;
+ // null data, failed to allocate more memory buffer
+ if (setWindowOutputBufByKey(pRuntimeEnv, pWindowResInfo, sid, &nextWin) != TSDB_CODE_SUCCESS) {
break;
}
+
+ pStatus = getTimeWindowResStatus(pWindowResInfo, curTimeWindow(pWindowResInfo));
+ doRowwiseApplyFunctions(pRuntimeEnv, pStatus, &nextWin, offset);
}
+
+ pWindowResInfo->curIndex = index;
} else { // other queries
// decide which group this rows belongs to according to current state value
if (groupbyStateValue) {
char *stateVal = groupbyColumnData + bytes * offset;
- int32_t ret = setGroupResultFromKey(pRuntimeEnv, stateVal, type, bytes);
+ int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, stateVal, type, bytes);
if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code
continue;
}
}
+ // update the lastKey
+ lastKey = primaryKeyCol[offset];
+
// all startOffset are identical
offset -= pCtx[0].startOffset;
@@ -2110,7 +2423,7 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
* requires checking buffer during loop
*/
if ((pQuery->checkBufferInLoop == 1) && (++numOfRes) >= pQuery->pointsOffset) {
- pQuery->lastKey = primaryKeyCol[pQuery->pos + j * step] + step;
+ pQuery->lastKey = lastKey + step;
*forwardStep = j + 1;
break;
}
@@ -2118,72 +2431,18 @@ static int32_t rowwiseApplyAllFunctions(SQueryRuntimeEnv *pRuntimeEnv, int32_t *
free(sasArray);
- if (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0 && IS_MASTER_SCAN(pRuntimeEnv)) {
- SSlidingWindowInfo *pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
-
- // query completed
- if ((lastKey >= pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (lastKey <= pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- closeAllSlidingWindow(pSlidingWindowInfo);
-
- pSlidingWindowInfo->curIndex = pSlidingWindowInfo->size - 1;
- setQueryStatus(pQuery, QUERY_COMPLETED | QUERY_RESBUF_FULL);
- } else {
- int32_t i = 0;
- int64_t skey = 0;
-
- for (i = 0; i < pSlidingWindowInfo->size; ++i) {
- SWindowStatus *pStatus = &pSlidingWindowInfo->pStatus[i];
- if ((pStatus->window.ekey <= lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pStatus->window.skey >= lastKey && !QUERY_IS_ASC_QUERY(pQuery))) {
- closeSlidingWindow(pSlidingWindowInfo, i);
- } else {
- skey = pStatus->window.skey;
- break;
- }
- }
-
- pSlidingWindowInfo->prevSKey = skey;
-
- // the number of completed slots are larger than the threshold, dump to client immediately.
- int32_t v = numOfClosedSlidingWindow(pSlidingWindowInfo);
- if (v > pSlidingWindowInfo->threshold) {
- setQueryStatus(pQuery, QUERY_RESBUF_FULL);
- }
-
- dTrace("QInfo:%p total window:%d, closed:%d", GET_QINFO_ADDR(pQuery), pSlidingWindowInfo->size, v);
- }
- }
-
/*
- * No need to calculate the number of output results for groupby normal columns
+ * No need to calculate the number of output results for group-by normal columns, interval query
* because the results of group by normal column is put into intermediate buffer.
*/
int32_t num = 0;
- if (!groupbyStateValue && !(pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
+ if (!groupbyStateValue && !isIntervalQuery(pQuery)) {
num = getNumOfResult(pRuntimeEnv) - prevNumOfRes;
}
return num;
}
-static int32_t getForwardStepsInBlock(int32_t numOfPoints, __block_search_fn_t searchFn, SQuery *pQuery,
- int64_t *pData) {
- int32_t endPos = searchFn((char *)pData, numOfPoints, pQuery->ekey, pQuery->order.order);
- int32_t forwardStep = 0;
-
- if (endPos >= 0) {
- forwardStep = QUERY_IS_ASC_QUERY(pQuery) ? (endPos - pQuery->pos) : (pQuery->pos - endPos);
- assert(forwardStep >= 0);
-
- // endPos data is equalled to the key so, we do need to read the element in endPos
- if (pData[endPos] == pQuery->ekey) {
- forwardStep += 1;
- }
- }
- return forwardStep;
-}
-
static int32_t reviseForwardSteps(SQueryRuntimeEnv *pRuntimeEnv, int32_t forwardStep) {
/*
* 1. If value filter exists, we try all data in current block, and do not set the QUERY_RESBUF_FULL flag.
@@ -2229,51 +2488,18 @@ static void validateQueryRangeAndData(SQueryRuntimeEnv *pRuntimeEnv, const TSKEY
!QUERY_IS_ASC_QUERY(pQuery)));
}
-static int32_t applyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *pBlockInfo, int64_t *pPrimaryColumn,
- SField *pFields, __block_search_fn_t searchFn, int32_t *numOfRes) {
- int32_t forwardStep = 0;
+static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *pBlockInfo, SField *pFields,
+ __block_search_fn_t searchFn, int32_t *numOfRes,
+ SWindowResInfo *pWindowResInfo) {
SQuery *pQuery = pRuntimeEnv->pQuery;
-
- int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+ TSKEY * pPrimaryColumn = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
validateQueryRangeAndData(pRuntimeEnv, pPrimaryColumn, pBlockInfo);
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- if (pQuery->ekey < pBlockInfo->keyLast) {
- forwardStep = getForwardStepsInBlock(pBlockInfo->size, searchFn, pQuery, pPrimaryColumn);
- assert(forwardStep >= 0);
-
- if (forwardStep == 0) {
- // no qualified data in current block, do not update the lastKey value
- assert(pQuery->ekey < pPrimaryColumn[pQuery->pos]);
- } else {
- pQuery->lastKey = pQuery->ekey + step;//pPrimaryColumn[pQuery->pos + (forwardStep - 1)] + step;
- }
-
- } else {
- forwardStep = pBlockInfo->size - pQuery->pos;
- assert(forwardStep > 0);
-
- pQuery->lastKey = pBlockInfo->keyLast + step;
- }
- } else { // desc
- if (pQuery->ekey > pBlockInfo->keyFirst) {
- forwardStep = getForwardStepsInBlock(pBlockInfo->size, searchFn, pQuery, pPrimaryColumn);
- assert(forwardStep >= 0);
-
- if (forwardStep == 0) {
- // no qualified data in current block, do not update the lastKey value
- assert(pQuery->ekey > pPrimaryColumn[pQuery->pos]);
- } else {
- pQuery->lastKey = pQuery->ekey + step;//pPrimaryColumn[pQuery->pos - (forwardStep - 1)] + step;
- }
- } else {
- forwardStep = pQuery->pos + 1;
- assert(forwardStep > 0);
-
- pQuery->lastKey = pBlockInfo->keyFirst + step;
- }
- }
+ int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+ int32_t forwardStep =
+ getNumOfRowsInTimeWindow(pQuery, pBlockInfo, pPrimaryColumn, pQuery->pos, pQuery->ekey, searchFn, true);
+ assert(forwardStep >= 0);
int32_t newForwardStep = reviseForwardSteps(pRuntimeEnv, forwardStep);
assert(newForwardStep <= forwardStep && newForwardStep >= 0);
@@ -2283,11 +2509,20 @@ static int32_t applyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *
pQuery->lastKey = pPrimaryColumn[pQuery->pos + (newForwardStep - 1) * step] + step;
}
- if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || isGroupbyNormalCol(pQuery->pGroupbyExpr) ||
- (pQuery->slidingTime != -1 && pQuery->nAggTimeInterval > 0)) {
- *numOfRes = rowwiseApplyAllFunctions(pRuntimeEnv, &newForwardStep, pPrimaryColumn, pFields, pBlockInfo);
+ if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
+ *numOfRes = rowwiseApplyAllFunctions(pRuntimeEnv, &newForwardStep, pFields, pBlockInfo, pWindowResInfo);
} else {
- *numOfRes = blockwiseApplyAllFunctions(pRuntimeEnv, newForwardStep, pPrimaryColumn, pFields, pBlockInfo);
+ *numOfRes = blockwiseApplyAllFunctions(pRuntimeEnv, newForwardStep, pFields, pBlockInfo, pWindowResInfo, searchFn);
+ }
+
+ TSKEY lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? pBlockInfo->keyLast : pBlockInfo->keyFirst;
+ doCheckQueryCompleted(pRuntimeEnv, lastKey, pWindowResInfo); // todo refactor merge
+
+ // interval query with limit applied
+ if (isIntervalQuery(pQuery) && pQuery->limit.limit > 0 &&
+ (pQuery->limit.limit + pQuery->limit.offset) <= numOfClosedTimeWindow(pWindowResInfo) &&
+ pRuntimeEnv->scanFlag == MASTER_SCAN) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
}
assert(*numOfRes >= 0);
@@ -2304,7 +2539,7 @@ static int32_t applyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *
return newForwardStep;
}
-int32_t vnodeGetVnodeHeaderFileIdx(int32_t *fid, SQueryRuntimeEnv *pRuntimeEnv, int32_t order) {
+int32_t vnodeGetVnodeHeaderFileIndex(int32_t *fid, SQueryRuntimeEnv *pRuntimeEnv, int32_t order) {
if (pRuntimeEnv->vnodeFileInfo.numOfFiles == 0) {
return -1;
}
@@ -2365,7 +2600,7 @@ int32_t getNextDataFileCompInfo(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *pMeter
int32_t fileIndex = 0;
int32_t order = (step == QUERY_ASC_FORWARD_STEP) ? TSQL_SO_ASC : TSQL_SO_DESC;
while (1) {
- fileIndex = vnodeGetVnodeHeaderFileIdx(&pQuery->fileId, pRuntimeEnv, order);
+ fileIndex = vnodeGetVnodeHeaderFileIndex(&pQuery->fileId, pRuntimeEnv, order);
// no files left, abort
if (fileIndex < 0) {
@@ -2438,9 +2673,8 @@ void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, int64_t startQueryTimes
// store the first&last timestamp into the intermediate buffer [1], the true
// value may be null but timestamp will never be null
pCtx->ptsList = (int64_t *)(primaryColumnData + startOffset * TSDB_KEYSIZE);
- } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM ||
- functionId == TSDB_FUNC_TWA || functionId == TSDB_FUNC_DIFF ||
- (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) {
+ } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_TWA ||
+ functionId == TSDB_FUNC_DIFF || (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) {
/*
* leastsquares function needs two columns of input, currently, the x value of linear equation is set to
* timestamp column, and the y-value is the column specified in pQuery->pSelectExpr[i].colIdxInBuffer
@@ -2484,8 +2718,8 @@ static void setCtxTagColumnInfo(SQuery *pQuery, SQLFunctionCtx *pCtx) {
if (isSelectivityWithTagsQuery(pQuery)) {
int32_t num = 0;
SQLFunctionCtx *p = NULL;
-
- int16_t tagLen = 0;
+
+ int16_t tagLen = 0;
SQLFunctionCtx **pTagCtx = calloc(pQuery->numOfOutputCols, POINTER_BYTES);
for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
@@ -2510,6 +2744,12 @@ static void setCtxTagColumnInfo(SQuery *pQuery, SQLFunctionCtx *pCtx) {
}
}
+static void setWindowResultInfo(SResultInfo *pResultInfo, SQuery *pQuery, bool isStableQuery) {
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ setResultInfoBuf(&pResultInfo[i], pQuery->pSelectExpr[i].interResBytes, isStableQuery);
+ }
+}
+
static int32_t setupQueryRuntimeEnv(SMeterObj *pMeterObj, SQuery *pQuery, SQueryRuntimeEnv *pRuntimeEnv,
SColumnModel *pTagsSchema, int16_t order, bool isSTableQuery) {
dTrace("QInfo:%p setup runtime env", GET_QINFO_ADDR(pQuery));
@@ -2532,8 +2772,8 @@ static int32_t setupQueryRuntimeEnv(SMeterObj *pMeterObj, SQuery *pQuery, SQuery
SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
if (TSDB_COL_IS_TAG(pSqlFuncMsg->colInfo.flag)) { // process tag column info
- SSchema* pSchema = getColumnModelSchema(pTagsSchema, pColIndexEx->colIdx);
-
+ SSchema *pSchema = getColumnModelSchema(pTagsSchema, pColIndexEx->colIdx);
+
pCtx->inputType = pSchema->type;
pCtx->inputBytes = pSchema->bytes;
} else {
@@ -2578,12 +2818,11 @@ static int32_t setupQueryRuntimeEnv(SMeterObj *pMeterObj, SQuery *pQuery, SQuery
if (i > 0) {
pRuntimeEnv->offset[i] = pRuntimeEnv->offset[i - 1] + pRuntimeEnv->pCtx[i - 1].outputBytes;
}
-
- // set the intermediate result output buffer
- SResultInfo *pResInfo = &pRuntimeEnv->resultInfo[i];
- setResultInfoBuf(pResInfo, pQuery->pSelectExpr[i].interResBytes, isSTableQuery);
}
+ // set the intermediate result output buffer
+ setWindowResultInfo(pRuntimeEnv->resultInfo, pQuery, isSTableQuery);
+
// if it is group by normal column, do not set output buffer, the output buffer is pResult
if (!isGroupbyNormalCol(pQuery->pGroupbyExpr) && !isSTableQuery) {
resetCtxOutputBuf(pRuntimeEnv);
@@ -2613,7 +2852,7 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) {
}
tfree(pRuntimeEnv->secondaryUnzipBuffer);
- destroySlidingWindowInfo(&pRuntimeEnv->swindowResInfo);
+ cleanupTimeWindowInfo(&pRuntimeEnv->windowResInfo, pRuntimeEnv);
if (pRuntimeEnv->pCtx != NULL) {
for (int32_t i = 0; i < pRuntimeEnv->pQuery->numOfOutputCols; ++i) {
@@ -2665,7 +2904,6 @@ static int64_t getOldestKey(int32_t numOfFiles, int64_t fileId, SVnodeCfg *pCfg)
}
bool isQueryKilled(SQuery *pQuery) {
- return false;
SQInfo *pQInfo = (SQInfo *)GET_QINFO_ADDR(pQuery);
/*
@@ -2682,7 +2920,7 @@ bool isQueryKilled(SQuery *pQuery) {
}
bool isFixedOutputQuery(SQuery *pQuery) {
- if (pQuery->nAggTimeInterval != 0) {
+ if (pQuery->intervalTime != 0) {
return false;
}
@@ -2731,8 +2969,8 @@ bool isSumAvgRateQuery(SQuery *pQuery) {
continue;
}
- if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE ||
- functionId == TSDB_FUNC_AVG_RATE || functionId == TSDB_FUNC_AVG_IRATE) {
+ if (functionId == TSDB_FUNC_SUM_RATE || functionId == TSDB_FUNC_SUM_IRATE || functionId == TSDB_FUNC_AVG_RATE ||
+ functionId == TSDB_FUNC_AVG_IRATE) {
return true;
}
}
@@ -3060,17 +3298,17 @@ void vnodeCheckIfDataExists(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *pMeterObj,
setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
}
-static void doGetAlignedIntervalQueryRangeImpl(SQuery *pQuery, int64_t pKey, int64_t keyFirst, int64_t keyLast,
- int64_t *actualSkey, int64_t *actualEkey, int64_t *skey, int64_t *ekey) {
+void doGetAlignedIntervalQueryRangeImpl(SQuery *pQuery, int64_t pKey, int64_t keyFirst, int64_t keyLast,
+ int64_t *actualSkey, int64_t *actualEkey, int64_t *skey, int64_t *ekey) {
assert(pKey >= keyFirst && pKey <= keyLast);
- *skey = taosGetIntervalStartTimestamp(pKey, pQuery->nAggTimeInterval, pQuery->intervalTimeUnit, pQuery->precision);
+ *skey = taosGetIntervalStartTimestamp(pKey, pQuery->intervalTime, pQuery->intervalTimeUnit, pQuery->precision);
- if (keyFirst > (INT64_MAX - pQuery->nAggTimeInterval)) {
+ if (keyFirst > (INT64_MAX - pQuery->intervalTime)) {
/*
- * if the actualSkey > INT64_MAX - pQuery->nAggTimeInterval, the query duration between
+ * if the actualSkey > INT64_MAX - pQuery->intervalTime, the query duration between
* actualSkey and actualEkey must be less than one interval.Therefore, no need to adjust the query ranges.
*/
- assert(keyLast - keyFirst < pQuery->nAggTimeInterval);
+ assert(keyLast - keyFirst < pQuery->intervalTime);
*actualSkey = keyFirst;
*actualEkey = keyLast;
@@ -3079,7 +3317,7 @@ static void doGetAlignedIntervalQueryRangeImpl(SQuery *pQuery, int64_t pKey, int
return;
}
- *ekey = *skey + pQuery->nAggTimeInterval - 1;
+ *ekey = *skey + pQuery->intervalTime - 1;
if (*skey < keyFirst) {
*actualSkey = keyFirst;
@@ -3094,42 +3332,6 @@ static void doGetAlignedIntervalQueryRangeImpl(SQuery *pQuery, int64_t pKey, int
}
}
-static void getAlignedIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, TSKEY key, TSKEY skey, TSKEY ekey) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
- if (pQuery->nAggTimeInterval == 0 || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
- return;
- }
-
- TSKEY skey2 = MIN(skey, ekey);
- TSKEY ekey2 = MAX(skey, ekey);
-
- // the actual first query range in skey1 and ekey1
- TSKEY skey1, ekey1;
-
- TSKEY windowSKey = 0, windowEKey = 0;
- doGetAlignedIntervalQueryRangeImpl(pQuery, key, skey2, ekey2, &skey1, &ekey1, &windowSKey, &windowEKey);
-
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- pQuery->skey = skey1;
- pQuery->ekey = ekey1;
-
- pRuntimeEnv->intervalWindow = (STimeWindow) {.skey = windowSKey, .ekey = windowEKey};
-
- assert(pQuery->skey <= pQuery->ekey &&
- pRuntimeEnv->intervalWindow.skey + (pQuery->nAggTimeInterval - 1) == pRuntimeEnv->intervalWindow.ekey);
- } else {
- pQuery->skey = ekey1;
- pQuery->ekey = skey1;
-
- pRuntimeEnv->intervalWindow = (STimeWindow) {.skey = windowEKey, .ekey = windowSKey};
-
- assert(pQuery->skey >= pQuery->ekey &&
- pRuntimeEnv->intervalWindow.skey - (pQuery->nAggTimeInterval - 1) == pRuntimeEnv->intervalWindow.ekey);
- }
-
- pQuery->lastKey = pQuery->skey;
-}
-
static void getOneRowFromDataBlock(SQueryRuntimeEnv *pRuntimeEnv, char **dst, int32_t pos) {
SQuery *pQuery = pRuntimeEnv->pQuery;
@@ -3139,7 +3341,7 @@ static void getOneRowFromDataBlock(SQueryRuntimeEnv *pRuntimeEnv, char **dst, in
}
}
-static bool getNeighborPoints(SMeterQuerySupportObj *pSupporter, SMeterObj *pMeterObj,
+static bool getNeighborPoints(STableQuerySupportObj *pSupporter, SMeterObj *pMeterObj,
SPointInterpoSupporter *pPointInterpSupporter) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
@@ -3244,7 +3446,7 @@ static bool getNeighborPoints(SMeterQuerySupportObj *pSupporter, SMeterObj *pMet
return true;
}
-static bool doGetQueryPos(TSKEY key, SMeterQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter) {
+static bool doGetQueryPos(TSKEY key, STableQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
SMeterObj * pMeterObj = pRuntimeEnv->pMeterObj;
@@ -3254,7 +3456,6 @@ static bool doGetQueryPos(TSKEY key, SMeterQuerySupportObj *pSupporter, SPointIn
if (isPointInterpoQuery(pQuery)) { /* no qualified data in this query range */
return getNeighborPoints(pSupporter, pMeterObj, pPointInterpSupporter);
} else {
- getAlignedIntervalQueryRange(pRuntimeEnv, key, pQuery->skey, pQuery->ekey);
return true;
}
} else { // key > pQuery->ekey, abort for normal query, continue for interp query
@@ -3266,7 +3467,7 @@ static bool doGetQueryPos(TSKEY key, SMeterQuerySupportObj *pSupporter, SPointIn
}
}
-static bool doSetDataInfo(SMeterQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter,
+static bool doSetDataInfo(STableQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter,
SMeterObj *pMeterObj, TSKEY nextKey) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
@@ -3286,13 +3487,12 @@ static bool doSetDataInfo(SMeterQuerySupportObj *pSupporter, SPointInterpoSuppor
return getNeighborPoints(pSupporter, pMeterObj, pPointInterpSupporter);
} else {
- getAlignedIntervalQueryRange(pRuntimeEnv, nextKey, pQuery->skey, pQuery->ekey);
return true;
}
}
// TODO refactor code, the best way to implement the last_row is utilizing the iterator
-bool normalizeUnBoundLastRowQuery(SMeterQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter) {
+bool normalizeUnBoundLastRowQuery(STableQuerySupportObj *pSupporter, SPointInterpoSupporter *pPointInterpSupporter) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
@@ -3354,12 +3554,49 @@ bool normalizeUnBoundLastRowQuery(SMeterQuerySupportObj *pSupporter, SPointInter
return getNeighborPoints(pSupporter, pMeterObj, pPointInterpSupporter);
}
+static int64_t getGreaterEqualTimestamp(SQueryRuntimeEnv *pRuntimeEnv) {
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ SMeterObj * pMeterObj = pRuntimeEnv->pMeterObj;
+ __block_search_fn_t searchFn = vnodeSearchKeyFunc[pMeterObj->searchAlgorithm];
+
+ if (QUERY_IS_ASC_QUERY(pQuery)) {
+ return -1;
+ }
+
+ TSKEY key = -1;
+
+ SPositionInfo p = {0};
+ { // todo refactor save the context
+ savePointPosition(&p, pQuery->fileId, pQuery->slot, pQuery->pos);
+ }
+
+ SWAP(pQuery->skey, pQuery->ekey, TSKEY);
+ pQuery->lastKey = pQuery->skey;
+ pQuery->order.order ^= 1u;
+
+ if (getQualifiedDataBlock(pMeterObj, pRuntimeEnv, QUERY_RANGE_GREATER_EQUAL, searchFn)) {
+ key = getTimestampInDiskBlock(pRuntimeEnv, pQuery->pos);
+ } else { // set no data in file
+ key = getQueryStartPositionInCache(pRuntimeEnv, &pQuery->slot, &pQuery->pos, false);
+ }
+
+ SWAP(pQuery->skey, pQuery->ekey, TSKEY);
+ pQuery->order.order ^= 1u;
+ pQuery->lastKey = pQuery->skey;
+
+ pQuery->fileId = p.fileId;
+ pQuery->pos = p.pos;
+ pQuery->slot = p.slot;
+
+ return key;
+}
+
/**
* determine the first query range, according to raw query range [skey, ekey] and group-by interval.
* the time interval for aggregating is not enforced to check its validation, the minimum interval is not less than
* 10ms, which is guaranteed by parser at client-side
*/
-bool normalizedFirstQueryRange(bool dataInDisk, bool dataInCache, SMeterQuerySupportObj *pSupporter,
+bool normalizedFirstQueryRange(bool dataInDisk, bool dataInCache, STableQuerySupportObj *pSupporter,
SPointInterpoSupporter *pPointInterpSupporter, int64_t *key) {
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
@@ -3473,7 +3710,7 @@ int64_t loadRequiredBlockIntoMem(SQueryRuntimeEnv *pRuntimeEnv, SPositionInfo *p
* load the file metadata into buffer first, then the specific data block.
* currently opened file is not the start file, reset to the start file
*/
- int32_t fileIdx = vnodeGetVnodeHeaderFileIdx(&pQuery->fileId, pRuntimeEnv, pQuery->order.order);
+ int32_t fileIdx = vnodeGetVnodeHeaderFileIndex(&pQuery->fileId, pRuntimeEnv, pQuery->order.order);
if (fileIdx < 0) { // ignore the files on disk
dError("QInfo:%p failed to get data file:%d", GET_QINFO_ADDR(pQuery), pQuery->fileId);
position->fileId = -1;
@@ -3565,7 +3802,7 @@ static void vnodeRecordAllFiles(SQInfo *pQInfo, int32_t vnodeId) {
struct dirent *pEntry = NULL;
size_t alloc = 4; // default allocated size
- SQueryFilesInfo *pVnodeFilesInfo = &(pQInfo->pMeterQuerySupporter->runtimeEnv.vnodeFileInfo);
+ SQueryFilesInfo *pVnodeFilesInfo = &(pQInfo->pTableQuerySupporter->runtimeEnv.vnodeFileInfo);
pVnodeFilesInfo->vnodeId = vnodeId;
sprintf(pVnodeFilesInfo->dbFilePathPrefix, "%s/vnode%d/db/", tsDirectory, vnodeId);
@@ -3721,9 +3958,9 @@ static void changeExecuteScanOrder(SQuery *pQuery, bool metricQuery) {
// in case of point-interpolation query, use asc order scan
char msg[] =
"QInfo:%p scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%" PRId64 "-%" PRId64
- ", "
- "new qrange:%" PRId64 "-%" PRId64;
+ ", new qrange:%" PRId64 "-%" PRId64;
+ // todo handle the case the the order irrelevant query type mixed up with order critical query type
// descending order query for last_row query
if (isFirstLastRowQuery(pQuery)) {
dTrace("QInfo:%p scan order changed for last_row query, old:%d, new:%d", GET_QINFO_ADDR(pQuery),
@@ -3740,7 +3977,7 @@ static void changeExecuteScanOrder(SQuery *pQuery, bool metricQuery) {
return;
}
- if (isPointInterpoQuery(pQuery) && pQuery->nAggTimeInterval == 0) {
+ if (isPointInterpoQuery(pQuery) && pQuery->intervalTime == 0) {
if (!QUERY_IS_ASC_QUERY(pQuery)) {
dTrace(msg, GET_QINFO_ADDR(pQuery), "interp", pQuery->order.order, TSQL_SO_ASC, pQuery->skey, pQuery->ekey,
pQuery->ekey, pQuery->skey);
@@ -3751,7 +3988,7 @@ static void changeExecuteScanOrder(SQuery *pQuery, bool metricQuery) {
return;
}
- if (pQuery->nAggTimeInterval == 0) {
+ if (pQuery->intervalTime == 0) {
if (onlyFirstQuery(pQuery)) {
if (!QUERY_IS_ASC_QUERY(pQuery)) {
dTrace(msg, GET_QINFO_ADDR(pQuery), "only-first", pQuery->order.order, TSQL_SO_ASC, pQuery->skey, pQuery->ekey,
@@ -3812,8 +4049,7 @@ static int32_t doSkipDataBlock(SQueryRuntimeEnv *pRuntimeEnv) {
void *pBlock = getGenericDataBlock(pMeterObj, pRuntimeEnv, pQuery->slot);
assert(pBlock != NULL);
- int32_t blockType = IS_DISK_DATA_BLOCK(pQuery) ? BLK_FILE_BLOCK : BLK_CACHE_BLOCK;
- SBlockInfo blockInfo = getBlockBasicInfo(pRuntimeEnv, pBlock, blockType);
+ SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv);
int32_t maxReads = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.size - pQuery->pos : pQuery->pos + 1;
assert(maxReads >= 0);
@@ -3843,9 +4079,9 @@ void forwardQueryStartPosition(SQueryRuntimeEnv *pRuntimeEnv) {
}
void *pBlock = getGenericDataBlock(pMeterObj, pRuntimeEnv, pQuery->slot);
+ assert(pBlock != NULL);
- int32_t blockType = (IS_DISK_DATA_BLOCK(pQuery)) ? BLK_FILE_BLOCK : BLK_CACHE_BLOCK;
- SBlockInfo blockInfo = getBlockBasicInfo(pRuntimeEnv, pBlock, blockType);
+ SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv);
// get the qualified data that can be skipped
int32_t maxReads = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.size - pQuery->pos : pQuery->pos + 1;
@@ -3855,71 +4091,186 @@ void forwardQueryStartPosition(SQueryRuntimeEnv *pRuntimeEnv) {
updateOffsetVal(pRuntimeEnv, &blockInfo, pBlock);
} else {
pQuery->limit.offset -= maxReads;
+
// update the lastkey, since the following skip operation may traverse to another media. update the lastkey first.
pQuery->lastKey = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.keyLast + 1 : blockInfo.keyFirst - 1;
doSkipDataBlock(pRuntimeEnv);
}
}
-static bool forwardQueryStartPosIfNeeded(SQInfo *pQInfo, SMeterQuerySupportObj *pSupporter, bool dataInDisk,
+static bool forwardQueryStartPosIfNeeded(SQInfo *pQInfo, STableQuerySupportObj *pSupporter, bool dataInDisk,
bool dataInCache) {
- SQuery *pQuery = &pQInfo->query;
+ SQuery * pQuery = &pQInfo->query;
+ SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
/* if queried with value filter, do NOT forward query start position */
- if (pQuery->numOfFilterCols > 0 || pSupporter->runtimeEnv.pTSBuf != NULL) {
+ if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL) {
return true;
}
if (pQuery->limit.offset > 0 && (!isTopBottomQuery(pQuery)) && pQuery->interpoType == TSDB_INTERPO_NONE) {
/*
* 1. for top/bottom query, the offset applies to the final result, not here
- * 2. for interval without interpolation query we forward pQuery->nAggTimeInterval at a time for
- * pQuery->limit.offset times. Since hole exists, pQuery->nAggTimeInterval*pQuery->limit.offset value is
+ * 2. for interval without interpolation query we forward pQuery->intervalTime at a time for
+ * pQuery->limit.offset times. Since hole exists, pQuery->intervalTime*pQuery->limit.offset value is
* not valid. otherwise, we only forward pQuery->limit.offset number of points
*/
- if (pQuery->nAggTimeInterval > 0) {
- while (1) {
- /*
- * the skey may not be the aligned start time
- * 1. it is the value of first existed data point, therefore, the range
- * between skey and ekey may be less than the interval value.
- * 2. the ekey may not be the actual end value of time interval, in case of the
- */
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- pQuery->skey = pQuery->ekey + 1;
- } else {
- pQuery->skey = pQuery->ekey - 1;
- }
+ if (isIntervalQuery(pQuery)) {
+ int16_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+ __block_search_fn_t searchFn = vnodeSearchKeyFunc[pRuntimeEnv->pMeterObj->searchAlgorithm];
+ SWindowResInfo * pWindowResInfo = &pRuntimeEnv->windowResInfo;
- // boundary check
- if ((pQuery->skey > pSupporter->rawEKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->skey < pSupporter->rawEKey && !QUERY_IS_ASC_QUERY(pQuery))) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
+ TSKEY * primaryKey = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
+ STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQuery);
- sem_post(&pQInfo->dataReady);
- pQInfo->over = 1;
- return false;
- }
+ while (pQuery->limit.offset > 0) {
+ SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv);
+
+ STimeWindow tw = win;
+ getNextTimeWindow(pQuery, &tw);
+
+ // next time window starts from current data block
+ if ((tw.skey <= blockInfo.keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (tw.ekey >= blockInfo.keyFirst && !QUERY_IS_ASC_QUERY(pQuery))) {
+
+ // query completed
+ if ((tw.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (tw.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+ break;
+ }
- /*
- * NOTE: the end key must be set the last value, to cover all possible
- * data. Otherwise, it may contain no data with only one interval time range
- */
- pQuery->ekey = pSupporter->rawEKey;
- pQuery->lastKey = pQuery->skey;
-
- // todo opt performance
- if (normalizedFirstQueryRange(dataInDisk, dataInCache, pSupporter, NULL, NULL) == false) {
- sem_post(&pQInfo->dataReady); // hack for next read for empty return
- pQInfo->over = 1;
- return false;
+ // check its position in this block to make sure this time window covers data.
+ if (IS_DISK_DATA_BLOCK(pQuery)) {
+ getTimestampInDiskBlock(pRuntimeEnv, 0);
+ }
+
+ tw = win;
+ int32_t startPos = getNextQualifiedWindow(pRuntimeEnv, &tw, pWindowResInfo, &blockInfo, primaryKey, searchFn);
+ assert(startPos >= 0);
+
+ pQuery->limit.offset -= 1;
+
+ // set the abort info
+ pQuery->pos = startPos;
+ pQuery->lastKey = primaryKey[startPos];
+ pWindowResInfo->prevSKey = tw.skey;
+ win = tw;
+ continue;
+ } else {
+ moveToNextBlock(pRuntimeEnv, step, searchFn, false);
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
+ break;
+ }
+
+ blockInfo = getBlockInfo(pRuntimeEnv);
+ if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+ break;
+ }
+
+ // set the window that start from the next data block
+ TSKEY key = (QUERY_IS_ASC_QUERY(pQuery))? blockInfo.keyFirst:blockInfo.keyLast;
+ STimeWindow n = getActiveTimeWindow(pWindowResInfo, key, pQuery);
+
+ // next data block are still covered by current time window
+ if (n.skey == win.skey && n.ekey == win.ekey) {
+ // do nothing
+ } else {
+ pQuery->limit.offset -= 1;
+
+ // query completed
+ if ((n.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (n.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+ break;
+ }
+
+ // set the abort info
+ pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0:blockInfo.size-1;
+ pQuery->lastKey = QUERY_IS_ASC_QUERY(pQuery)? blockInfo.keyFirst:blockInfo.keyLast;
+ pWindowResInfo->prevSKey = n.skey;
+
+ win = n;
+
+ if (pQuery->limit.offset == 0 && IS_DISK_DATA_BLOCK(pQuery)) {
+ getTimestampInDiskBlock(pRuntimeEnv, 0);
+ }
+ }
}
+
+// if (win.ekey <= blockInfo.keyLast) {
+// pQuery->limit.offset -= 1;
+//
+// if (win.ekey == blockInfo.keyLast) {
+// moveToNextBlock(pRuntimeEnv, step, searchFn, false);
+// if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
+// break;
+// }
+//
+// // next block does not included in time range, abort query
+// blockInfo = getBlockInfo(pRuntimeEnv);
+// if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+// (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+// setQueryStatus(pQuery, QUERY_COMPLETED);
+// break;
+// }
+//
+// // set the window that start from the next data block
+// win = getActiveTimeWindow(pWindowResInfo, blockInfo.keyFirst, pQuery);
+// } else {
+// // the time window is closed in current data block, load disk file block into memory to
+// // check the next time window
+// if (IS_DISK_DATA_BLOCK(pQuery)) {
+// getTimestampInDiskBlock(pRuntimeEnv, 0);
+// }
+//
+// STimeWindow nextWin = win;
+// int32_t startPos =
+// getNextQualifiedWindow(pRuntimeEnv, &nextWin, pWindowResInfo, &blockInfo, primaryKey, searchFn);
+//
+// if (startPos < 0) { // failed to find the qualified time window
+// assert((nextWin.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+// (nextWin.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery)));
+//
+// setQueryStatus(pQuery, QUERY_COMPLETED);
+// break;
+// } else { // set the abort info
+// pQuery->pos = startPos;
+// pQuery->lastKey = primaryKey[startPos];
+// win = nextWin;
+// }
+// }
+//
+// continue;
+// }
+//
+// moveToNextBlock(pRuntimeEnv, step, searchFn, false);
+// if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
+// break;
+// }
+//
+// blockInfo = getBlockInfo(pRuntimeEnv);
+// if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+// (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+// setQueryStatus(pQuery, QUERY_COMPLETED);
+// break;
+// }
+ }
- if (--pQuery->limit.offset == 0) {
- break;
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED) || pQuery->limit.offset > 0) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
+
+ sem_post(&pQInfo->dataReady); // hack for next read for empty return;
+ pQInfo->over = 1;
+ return false;
+ } else {
+ if (IS_DISK_DATA_BLOCK(pQuery)) {
+ getTimestampInDiskBlock(pRuntimeEnv, 0);
}
}
- } else {
+ } else { // forward the start position for projection query
forwardQueryStartPosition(&pSupporter->runtimeEnv);
if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
setQueryStatus(pQuery, QUERY_COMPLETED);
@@ -4005,7 +4356,7 @@ void pointInterpSupporterSetData(SQInfo *pQInfo, SPointInterpoSupporter *pPointI
}
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
int32_t count = 1;
@@ -4136,71 +4487,37 @@ void pointInterpSupporterDestroy(SPointInterpoSupporter *pPointInterpSupport) {
pPointInterpSupport->numOfCols = 0;
}
-static void allocMemForInterpo(SMeterQuerySupportObj *pSupporter, SQuery *pQuery, SMeterObj *pMeterObj) {
- if (pQuery->interpoType != TSDB_INTERPO_NONE) {
- assert(pQuery->nAggTimeInterval > 0 || (pQuery->nAggTimeInterval == 0 && isPointInterpoQuery(pQuery)));
-
- if (pQuery->nAggTimeInterval > 0) {
- pSupporter->runtimeEnv.pInterpoBuf = malloc(POINTER_BYTES * pQuery->numOfOutputCols);
-
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- pSupporter->runtimeEnv.pInterpoBuf[i] =
- calloc(1, sizeof(tFilePage) + pQuery->pSelectExpr[i].resBytes * pMeterObj->pointsPerFileBlock);
- }
- }
- }
-}
-
-static int32_t createQueryOutputBuffer(SMeterQuerySupportObj *pSupporter, SQuery *pQuery, bool isSTableQuery) {
- SQueryRuntimeEnv* pRuntimeEnv = &pSupporter->runtimeEnv;
-
- int32_t numOfRows = 0;
-
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
- numOfRows = 10000;
- } else {
- numOfRows = pSupporter->pSidSet->numOfSubSet;
- }
-
- createResultBuf(&pRuntimeEnv->pResultBuf, 100, pQuery->rowSize);
-
- // total number of initial results
- pSupporter->pResult = calloc(numOfRows, sizeof(SOutputRes));
- if (pSupporter->pResult == NULL) {
- return TSDB_CODE_SERV_OUT_OF_MEMORY;
- }
-
- int32_t pageId = -1;
- tFilePage* page = NULL;
-
- for (int32_t k = 0; k < numOfRows; ++k) {
- SOutputRes *pOneRes = &pSupporter->pResult[k];
- pOneRes->nAlloc = 1;
+static void allocMemForInterpo(STableQuerySupportObj *pSupporter, SQuery *pQuery, SMeterObj *pMeterObj) {
+ if (pQuery->interpoType != TSDB_INTERPO_NONE) {
+ assert(isIntervalQuery(pQuery) || (pQuery->intervalTime == 0 && isPointInterpoQuery(pQuery)));
- /*
- * for single table top/bottom query, the output for group by normal column, the output rows is
- * equals to the maximum rows, instead of 1.
- */
- if (!isSTableQuery && isTopBottomQuery(pQuery)) {
- assert(pQuery->numOfOutputCols > 1);
+ if (isIntervalQuery(pQuery)) {
+ pSupporter->runtimeEnv.pInterpoBuf = malloc(POINTER_BYTES * pQuery->numOfOutputCols);
- SSqlFunctionExpr *pExpr = &pQuery->pSelectExpr[1];
- pOneRes->nAlloc = pExpr->pBase.arg[0].argValue.i64;
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ pSupporter->runtimeEnv.pInterpoBuf[i] =
+ calloc(1, sizeof(tFilePage) + pQuery->pSelectExpr[i].resBytes * pMeterObj->pointsPerFileBlock);
+ }
}
+ }
+}
- if (page == NULL || page->numOfElems >= pRuntimeEnv->numOfRowsPerPage) {
- page = getNewDataBuf(pRuntimeEnv->pResultBuf, 0, &pageId);
- }
-
- assert(pageId >= 0);
-
- SPosInfo posInfo = {.pageId = pageId, .rowId = page->numOfElems};
-
- createQueryResultBuf(pRuntimeEnv, pOneRes, isSTableQuery, &posInfo);
- page->numOfElems += 1; // next row is available
+static int32_t getInitialPageNum(STableQuerySupportObj *pSupporter) {
+ SQuery *pQuery = pSupporter->runtimeEnv.pQuery;
+
+ int32_t num = 0;
+
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
+ num = 128;
+ } else if (isIntervalQuery(pQuery)) { // time window query, allocate one page for each table
+ num = pSupporter->numOfMeters;
+ } else { // for super table query, one page for each subset
+ num = pSupporter->pSidSet->numOfSubSet;
}
- return TSDB_CODE_SUCCESS;
+ assert(num > 0);
+
+ return num;
}
static int32_t allocateRuntimeEnvBuf(SQueryRuntimeEnv *pRuntimeEnv, SMeterObj *pMeterObj) {
@@ -4259,34 +4576,35 @@ _error_clean:
return TSDB_CODE_SERV_OUT_OF_MEMORY;
}
-static int32_t getRowParamForMultiRowsOutput(SQuery* pQuery, bool isSTableQuery) {
+static int32_t getRowParamForMultiRowsOutput(SQuery *pQuery, bool isSTableQuery) {
int32_t rowparam = 1;
-
+
if (isTopBottomQuery(pQuery) && (!isSTableQuery)) {
rowparam = pQuery->pSelectExpr[1].pBase.arg->argValue.i64;
}
-
+
return rowparam;
}
-static int32_t getNumOfRowsInResultPage(SQuery* pQuery, bool isSTableQuery) {
+static int32_t getNumOfRowsInResultPage(SQuery *pQuery, bool isSTableQuery) {
int32_t rowSize = pQuery->rowSize * getRowParamForMultiRowsOutput(pQuery, isSTableQuery);
return (DEFAULT_INTERN_BUF_SIZE - sizeof(tFilePage)) / rowSize;
}
-static char* getPosInResultPage(SQueryRuntimeEnv* pRuntimeEnv, int32_t columnIndex, SOutputRes* pResult) {
- SQuery* pQuery = pRuntimeEnv->pQuery;
- tFilePage* page = getResultBufferPageById(pRuntimeEnv->pResultBuf, pResult->pos.pageId);
-
+static char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int32_t columnIndex, SWindowResult *pResult) {
+ assert(pResult != NULL && pRuntimeEnv != NULL);
+
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ tFilePage *page = getResultBufferPageById(pRuntimeEnv->pResultBuf, pResult->pos.pageId);
+
int32_t numOfRows = getNumOfRowsInResultPage(pQuery, pRuntimeEnv->stableQuery);
int32_t realRowId = pResult->pos.rowId * getRowParamForMultiRowsOutput(pQuery, pRuntimeEnv->stableQuery);
-
- return ((char*)page->data) + pRuntimeEnv->offset[columnIndex] * numOfRows +
- pQuery->pSelectExpr[columnIndex].resBytes * realRowId;
+
+ return ((char *)page->data) + pRuntimeEnv->offset[columnIndex] * numOfRows +
+ pQuery->pSelectExpr[columnIndex].resBytes * realRowId;
}
-int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMeterQuerySupportObj *pSupporter,
- void *param) {
+int32_t vnodeQueryTablePrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, STableQuerySupportObj *pSupporter, void *param) {
SQuery *pQuery = &pQInfo->query;
int32_t code = TSDB_CODE_SUCCESS;
@@ -4354,10 +4672,13 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
}
vnodeRecordAllFiles(pQInfo, pMeterObj->vnode);
-
+
pRuntimeEnv->numOfRowsPerPage = getNumOfRowsInResultPage(pQuery, false);
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
- if ((code = createQueryOutputBuffer(pSupporter, pQuery, false)) != TSDB_CODE_SUCCESS) {
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
+ int32_t rows = getInitialPageNum(pSupporter);
+
+ code = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, rows, pQuery->rowSize);
+ if (code != TSDB_CODE_SUCCESS) {
return code;
}
@@ -4368,7 +4689,7 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
type = TSDB_DATA_TYPE_TIMESTAMP;
}
- initSlidingWindowInfo(&pRuntimeEnv->swindowResInfo, 3, type, pQuery->rowSize, pSupporter->pResult);
+ initWindowResInfo(&pRuntimeEnv->windowResInfo, pRuntimeEnv, rows, 4096, type);
}
pSupporter->rawSKey = pQuery->skey;
@@ -4394,17 +4715,20 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
pointInterpSupporterDestroy(&interpInfo);
return TSDB_CODE_SUCCESS;
}
- } else {
- // find the skey and ekey in case of sliding query
- // todo refactor
- if (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0) {
- int64_t skey = 0;
+ } else { // find the skey and ekey in case of sliding query
+ if (isIntervalQuery(pQuery)) {
+ STimeWindow win = {0};
- SWAP(pQuery->skey, pQuery->ekey, int64_t);
- pQuery->order.order ^= 1;
- pQuery->lastKey = pQuery->skey;
+ // find the minimum value for descending order query
+ TSKEY minKey = -1;
+ if (!QUERY_IS_ASC_QUERY(pQuery)) {
+ minKey = getGreaterEqualTimestamp(pRuntimeEnv);
+ }
- if (normalizedFirstQueryRange(dataInDisk, dataInCache, pSupporter, &interpInfo, &skey) == false) {
+ int64_t skey = 0;
+ if ((normalizedFirstQueryRange(dataInDisk, dataInCache, pSupporter, &interpInfo, &skey) == false) ||
+ (isFixedOutputQuery(pQuery) && !isTopBottomQuery(pQuery) && (pQuery->limit.offset > 0)) ||
+ (isTopBottomQuery(pQuery) && pQuery->limit.offset >= pQuery->pSelectExpr[1].pBase.arg[0].argValue.i64)) {
sem_post(&pQInfo->dataReady);
pQInfo->over = 1;
@@ -4412,36 +4736,29 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
return TSDB_CODE_SUCCESS;
}
- pQuery->skey = skey;
-
- pQuery->order.order ^= 1;
- SWAP(pQuery->skey, pQuery->ekey, int64_t);
-
- int64_t ekey = 0;
- pQuery->lastKey = pQuery->skey;
- if (normalizedFirstQueryRange(dataInDisk, dataInCache, pSupporter, &interpInfo, &ekey) == false) {
- //
+ if (!QUERY_IS_ASC_QUERY(pQuery)) {
+ win.skey = minKey;
+ win.ekey = skey;
+ } else {
+ win.skey = skey;
+ win.ekey = pQuery->ekey;
}
- pQuery->skey = ekey;
-
TSKEY skey1, ekey1;
TSKEY windowSKey = 0, windowEKey = 0;
- TSKEY minKey = MIN(pQuery->skey, pQuery->ekey);
- TSKEY maxKey = MAX(pQuery->skey, pQuery->ekey);
-
- doGetAlignedIntervalQueryRangeImpl(pQuery, minKey, minKey, maxKey, &skey1, &ekey1, &windowSKey, &windowEKey);
- pRuntimeEnv->swindowResInfo.startTime = windowSKey;
-
- pSupporter->rawSKey = pQuery->skey;
- pSupporter->rawEKey = pQuery->ekey;
+ doGetAlignedIntervalQueryRangeImpl(pQuery, win.skey, win.skey, win.ekey, &skey1, &ekey1, &windowSKey,
+ &windowEKey);
+ pRuntimeEnv->windowResInfo.startTime = windowSKey;
if (QUERY_IS_ASC_QUERY(pQuery)) {
- pRuntimeEnv->swindowResInfo.prevSKey = windowSKey;
+ pRuntimeEnv->windowResInfo.prevSKey = windowSKey;
} else {
- pRuntimeEnv->swindowResInfo.prevSKey = windowSKey + ((pQuery->skey - windowSKey) / pQuery->slidingTime) * pQuery->slidingTime;
+ pRuntimeEnv->windowResInfo.prevSKey =
+ windowSKey + ((win.ekey - windowSKey) / pQuery->slidingTime) * pQuery->slidingTime;
}
+
+ pQuery->over = QUERY_NOT_COMPLETED;
} else {
int64_t ekey = 0;
if ((normalizedFirstQueryRange(dataInDisk, dataInCache, pSupporter, &interpInfo, &ekey) == false) ||
@@ -4467,7 +4784,7 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
return TSDB_CODE_SUCCESS;
}
- int64_t rs = taosGetIntervalStartTimestamp(pSupporter->rawSKey, pQuery->nAggTimeInterval, pQuery->intervalTimeUnit,
+ int64_t rs = taosGetIntervalStartTimestamp(pSupporter->rawSKey, pQuery->intervalTime, pQuery->intervalTimeUnit,
pQuery->precision);
taosInitInterpoInfo(&pRuntimeEnv->interpoInfo, pQuery->order.order, rs, 0, 0);
allocMemForInterpo(pSupporter, pQuery, pMeterObj);
@@ -4479,17 +4796,17 @@ int32_t vnodeQuerySingleMeterPrepare(SQInfo *pQInfo, SMeterObj *pMeterObj, SMete
// the pQuery->skey is changed during normalizedFirstQueryRange, so set the newest lastkey value
pQuery->lastKey = pQuery->skey;
pRuntimeEnv->stableQuery = false;
-
+
return TSDB_CODE_SUCCESS;
}
void vnodeQueryFreeQInfoEx(SQInfo *pQInfo) {
- if (pQInfo == NULL || pQInfo->pMeterQuerySupporter == NULL) {
+ if (pQInfo == NULL || pQInfo->pTableQuerySupporter == NULL) {
return;
}
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
teardownQueryRuntimeEnv(&pSupporter->runtimeEnv);
tfree(pSupporter->pMeterSidExtInfo);
@@ -4500,16 +4817,16 @@ void vnodeQueryFreeQInfoEx(SQInfo *pQInfo) {
}
if (pSupporter->pSidSet != NULL || isGroupbyNormalCol(pQInfo->query.pGroupbyExpr) ||
- (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
+ isIntervalQuery(pQuery)) {
int32_t size = 0;
- if (isGroupbyNormalCol(pQInfo->query.pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
+ if (isGroupbyNormalCol(pQInfo->query.pGroupbyExpr) || isIntervalQuery(pQuery)) {
size = 10000;
} else if (pSupporter->pSidSet != NULL) {
size = pSupporter->pSidSet->numOfSubSet;
}
for (int32_t i = 0; i < size; ++i) {
- destroyGroupResultBuf(&pSupporter->pResult[i], pQInfo->query.numOfOutputCols);
+ // destroyTimeWindowRes(&pSupporter->pResult[i], pQInfo->query.numOfOutputCols);
}
}
@@ -4524,12 +4841,11 @@ void vnodeQueryFreeQInfoEx(SQInfo *pQInfo) {
tfree(pSupporter->pMeterDataInfo);
- tfree(pSupporter->pResult);
- tfree(pQInfo->pMeterQuerySupporter);
+ tfree(pQInfo->pTableQuerySupporter);
}
-int32_t vnodeMultiMeterQueryPrepare(SQInfo *pQInfo, SQuery *pQuery, void *param) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+int32_t vnodeSTableQueryPrepare(SQInfo *pQInfo, SQuery *pQuery, void *param) {
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->skey > pQuery->ekey)) ||
(!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->ekey > pQuery->skey))) {
@@ -4592,35 +4908,36 @@ int32_t vnodeMultiMeterQueryPrepare(SQInfo *pQInfo, SQuery *pQuery, void *param)
tSidSetSort(pSupporter->pSidSet);
vnodeRecordAllFiles(pQInfo, pTable->vnode);
- if ((ret = createQueryOutputBuffer(pSupporter, pQuery, true)) != TSDB_CODE_SUCCESS) {
+ int32_t size = getInitialPageNum(pSupporter);
+ ret = createDiskbasedResultBuffer(&pRuntimeEnv->pResultBuf, size, pQuery->rowSize);
+ if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // group by columns not tags;
- int16_t type = getGroupbyColumnType(pQuery, pQuery->pGroupbyExpr);
- initSlidingWindowInfo(&pRuntimeEnv->swindowResInfo, 4096, type, pQuery->rowSize, pSupporter->pResult);
- }
+ if (pQuery->intervalTime == 0) {
+ int16_t type = TSDB_DATA_TYPE_NULL;
- if (pQuery->nAggTimeInterval != 0 || isSumAvgRateQuery(pQuery)) {
- // one page for each table at least
- ret = createResultBuf(&pRuntimeEnv->pResultBuf, pSupporter->numOfMeters, pQuery->rowSize);
- if (ret != TSDB_CODE_SUCCESS) {
- return ret;
+ 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);
}
-
+
pRuntimeEnv->numOfRowsPerPage = getNumOfRowsInResultPage(pQuery, true);
-
+
// metric query do not invoke interpolation, it will be done at the second-stage merge
if (!isPointInterpoQuery(pQuery)) {
pQuery->interpoType = TSDB_INTERPO_NONE;
}
- TSKEY revisedStime = taosGetIntervalStartTimestamp(pSupporter->rawSKey, pQuery->nAggTimeInterval,
+ TSKEY revisedStime = taosGetIntervalStartTimestamp(pSupporter->rawSKey, pQuery->intervalTime,
pQuery->intervalTimeUnit, pQuery->precision);
taosInitInterpoInfo(&pRuntimeEnv->interpoInfo, pQuery->order.order, revisedStime, 0, 0);
pRuntimeEnv->stableQuery = true;
-
+
return TSDB_CODE_SUCCESS;
}
@@ -4629,7 +4946,7 @@ int32_t vnodeMultiMeterQueryPrepare(SQInfo *pQInfo, SQuery *pQuery, void *param)
* @param pQInfo
*/
void vnodeDecMeterRefcnt(SQInfo *pQInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
if (pSupporter == NULL || pSupporter->numOfMeters == 1) {
atomic_fetch_sub_32(&pQInfo->pObj->numOfQueries, 1);
@@ -4685,7 +5002,7 @@ TSKEY getTimestampInDiskBlock(SQueryRuntimeEnv *pRuntimeEnv, int32_t index) {
SMeterObj *pMeterObj = pRuntimeEnv->pMeterObj;
- int32_t fileIndex = vnodeGetVnodeHeaderFileIdx(&pQuery->fileId, pRuntimeEnv, pQuery->order.order);
+ int32_t fileIndex = vnodeGetVnodeHeaderFileIndex(&pQuery->fileId, pRuntimeEnv, pQuery->order.order);
dTrace("QInfo:%p vid:%d sid:%d id:%s, fileId:%d, slot:%d load data block due to primary key required",
GET_QINFO_ADDR(pQuery), pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->fileId, pQuery->slot);
@@ -4902,7 +5219,7 @@ static int32_t moveToNextBlock(SQueryRuntimeEnv *pRuntimeEnv, int32_t step, __bl
}
} else { // next block in the same file
int32_t fid = pQuery->fileId;
- fileIndex = vnodeGetVnodeHeaderFileIdx(&fid, pRuntimeEnv, pQuery->order.order);
+ fileIndex = vnodeGetVnodeHeaderFileIndex(&fid, pRuntimeEnv, pQuery->order.order);
pQuery->slot += step;
pQuery->pos = (step == QUERY_ASC_FORWARD_STEP) ? 0 : pQuery->pBlock[pQuery->slot].numOfPoints - 1;
@@ -4929,59 +5246,58 @@ static int32_t moveToNextBlock(SQueryRuntimeEnv *pRuntimeEnv, int32_t step, __bl
return DISK_DATA_LOADED;
}
-static void doHandleDataBlockImpl(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *pblockInfo, __block_search_fn_t searchFn,
- int32_t *numOfRes, int32_t blockLoadStatus, int32_t *forwardStep) {
+static int32_t doHandleDataBlockImpl(SQueryRuntimeEnv *pRuntimeEnv, SBlockInfo *pBlockInfo,
+ __block_search_fn_t searchFn, int32_t blockLoadStatus, int32_t *forwardStep) {
SQuery * pQuery = pRuntimeEnv->pQuery;
SQueryCostSummary *pSummary = &pRuntimeEnv->summary;
+ int32_t numOfRes = 0;
- TSKEY * primaryKeys = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
- int64_t start = taosGetTimestampUs();
+ if (IS_DISK_DATA_BLOCK(pQuery) && blockLoadStatus != DISK_DATA_LOADED) {
+ *forwardStep = pBlockInfo->size;
+ return numOfRes;
+ }
+ SField *pFields = NULL;
if (IS_DISK_DATA_BLOCK(pQuery)) {
- SCompBlock *pBlock = getDiskDataBlock(pQuery, pQuery->slot);
- *pblockInfo = getBlockBasicInfo(pRuntimeEnv, pBlock, BLK_FILE_BLOCK);
-
- if (blockLoadStatus == DISK_DATA_LOADED) {
- *forwardStep = applyFunctionsOnBlock(pRuntimeEnv, pblockInfo, primaryKeys, pQuery->pFields[pQuery->slot],
- searchFn, numOfRes);
- } else {
- *forwardStep = pblockInfo->size;
- }
-
- pSummary->fileTimeUs += (taosGetTimestampUs() - start);
- } else {
+ pFields = pQuery->pFields[pQuery->slot];
+ } else { // in case of cache data block, no need to load operation
assert(vnodeIsDatablockLoaded(pRuntimeEnv, pRuntimeEnv->pMeterObj, -1, true) == DISK_BLOCK_NO_NEED_TO_LOAD);
+ pFields = NULL;
+ }
+
+ int64_t start = taosGetTimestampUs();
- SCacheBlock *pBlock = getCacheDataBlock(pRuntimeEnv->pMeterObj, pRuntimeEnv, pQuery->slot);
- *pblockInfo = getBlockBasicInfo(pRuntimeEnv, pBlock, BLK_CACHE_BLOCK);
+ *forwardStep =
+ tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, pFields, searchFn, &numOfRes, &pRuntimeEnv->windowResInfo);
- *forwardStep = applyFunctionsOnBlock(pRuntimeEnv, pblockInfo, primaryKeys, NULL, searchFn, numOfRes);
+ int64_t elapsedTime = taosGetTimestampUs() - start;
- pSummary->cacheTimeUs += (taosGetTimestampUs() - start);
+ if (IS_DISK_DATA_BLOCK(pQuery)) {
+ pSummary->fileTimeUs += elapsedTime;
+ } else {
+ pSummary->cacheTimeUs += elapsedTime;
}
-}
-static void getNextLogicalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow* pTimeWindow) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
+ return numOfRes;
+}
+// previous time window may not be of the same size of pQuery->intervalTime
+static void getNextTimeWindow(SQuery *pQuery, STimeWindow *pTimeWindow) {
int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
-
+
pTimeWindow->skey += (pQuery->slidingTime * factor);
- pTimeWindow->ekey += (pQuery->slidingTime * factor);
+ pTimeWindow->ekey = pTimeWindow->skey + (pQuery->intervalTime - 1);
}
static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
- bool LOAD_DATA = true;
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ SMeterObj *pMeterObj = pRuntimeEnv->pMeterObj;
- int32_t forwardStep = 0;
+ bool LOAD_DATA = true;
int64_t cnt = 0;
- SMeterObj *pMeterObj = pRuntimeEnv->pMeterObj;
-
__block_search_fn_t searchFn = vnodeSearchKeyFunc[pMeterObj->searchAlgorithm];
int32_t blockLoadStatus = DISK_DATA_LOADED;
- SQueryCostSummary * pSummary = &pRuntimeEnv->summary;
int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
@@ -5001,9 +5317,9 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
return cnt;
}
- int32_t numOfRes = 0;
- SBlockInfo blockInfo = {0};
- doHandleDataBlockImpl(pRuntimeEnv, &blockInfo, searchFn, &numOfRes, blockLoadStatus, &forwardStep);
+ int32_t forwardStep = 0;
+ SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv);
+ /*int32_t numOfRes = */ doHandleDataBlockImpl(pRuntimeEnv, &blockInfo, searchFn, blockLoadStatus, &forwardStep);
dTrace("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64
", fileId:%d, slot:%d, pos:%d, bstatus:%d, rows:%d, checked:%d",
@@ -5016,90 +5332,66 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) {
cnt += forwardStep;
- if (queryCompleteInBlock(pQuery, &blockInfo, forwardStep)) {
+ if (queryPausedInCurrentBlock(pQuery, &blockInfo, forwardStep)) {
int32_t nextPos = accessPos + step;
/*
- * set the next access position, nextPos only required by
- * 1. interval query.
- * 2. multi-output query that may cause buffer overflow.
+ * set the next access position, nextPos only required when the interval query and projection query
+ * that cause output buffer overflow. When the query is completed, no need to load the next block any more.
*/
- if (pQuery->nAggTimeInterval > 0 ||
- (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL) && pQuery->checkBufferInLoop == 1)) {
+ if (!Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED) && Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) {
if (nextPos >= blockInfo.size || nextPos < 0) {
moveToNextBlock(pRuntimeEnv, step, searchFn, !LOAD_DATA);
// slot/pos/fileId is updated in moveToNextBlock function
savePointPosition(&pRuntimeEnv->nextPos, pQuery->fileId, pQuery->slot, pQuery->pos);
} else {
- savePointPosition(&pRuntimeEnv->nextPos, pQuery->fileId, pQuery->slot, accessPos + step);
+ savePointPosition(&pRuntimeEnv->nextPos, pQuery->fileId, pQuery->slot, nextPos);
}
}
+
break;
} else { // query not completed, move to next block
- int64_t start = taosGetTimestampUs();
-
blockLoadStatus = moveToNextBlock(pRuntimeEnv, step, searchFn, LOAD_DATA);
if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED)) {
- savePointPosition(&pRuntimeEnv->nextPos, pQuery->fileId, pQuery->slot, pQuery->pos);
setQueryStatus(pQuery, QUERY_COMPLETED);
break;
}
-
- int64_t delta = (taosGetTimestampUs() - start);
- if (IS_DISK_DATA_BLOCK(pQuery)) {
- pSummary->fileTimeUs += delta;
- } else {
- pSummary->cacheTimeUs += delta;
- }
}
// check next block
- void *pNextBlock = getGenericDataBlock(pMeterObj, pRuntimeEnv, pQuery->slot);
+ blockInfo = getBlockInfo(pRuntimeEnv);
- int32_t blockType = (IS_DISK_DATA_BLOCK(pQuery)) ? BLK_FILE_BLOCK : BLK_CACHE_BLOCK;
- blockInfo = getBlockBasicInfo(pRuntimeEnv, pNextBlock, blockType);
- if (!checkQueryRangeAgainstNextBlock(&blockInfo, pRuntimeEnv)) {
+ if ((QUERY_IS_ASC_QUERY(pQuery) && blockInfo.keyFirst > pQuery->ekey) ||
+ (!QUERY_IS_ASC_QUERY(pQuery) && blockInfo.keyLast < pQuery->ekey)) {
+ setQueryStatus(pQuery, QUERY_COMPLETED);
break;
}
- } // while(1)
-
- return cnt;
-}
-
-static void updatelastkey(SQuery *pQuery, SMeterQueryInfo *pMeterQInfo) { pMeterQInfo->lastKey = pQuery->lastKey; }
-void queryOnBlock(SMeterQuerySupportObj *pSupporter, int64_t *primaryKeys, int32_t blockStatus,
- SBlockInfo *pBlockBasicInfo, SMeterDataInfo *pMeterDataInfo, SField *pFields,
- __block_search_fn_t searchFn) {
- /* cache blocks may be assign to other meter, abort */
- if (pBlockBasicInfo->size <= 0) {
- return;
- }
-
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) {
+ break;
+ }
- if (pQuery->nAggTimeInterval == 0) { // not interval query
- int32_t numOfRes = 0;
- applyFunctionsOnBlock(pRuntimeEnv, pBlockBasicInfo, primaryKeys, pFields, searchFn, &numOfRes);
+ } // while(1)
- // note: only fixed number of output for each group by operation
- if (numOfRes > 0) {
- pSupporter->pResult[pMeterDataInfo->groupIdx].numOfRows = numOfRes;
- }
+ if (isIntervalQuery(pQuery) && IS_MASTER_SCAN(pRuntimeEnv)) {
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED | QUERY_NO_DATA_TO_CHECK)) {
+ closeAllTimeWindow(&pRuntimeEnv->windowResInfo);
+ pRuntimeEnv->windowResInfo.curIndex = pRuntimeEnv->windowResInfo.size - 1;
+ } else if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) { // check if window needs to be closed
+ SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv);
- // used to decide the correct start position in cache after check all data in files
- updatelastkey(pQuery, pMeterDataInfo->pMeterQInfo);
- if (pRuntimeEnv->pTSBuf != NULL) {
- pMeterDataInfo->pMeterQInfo->cur = tsBufGetCursor(pRuntimeEnv->pTSBuf);
+ // check if need to close window result or not
+ TSKEY t = (QUERY_IS_ASC_QUERY(pQuery)) ? blockInfo.keyFirst : blockInfo.keyLast;
+ doCheckQueryCompleted(pRuntimeEnv, t, &pRuntimeEnv->windowResInfo);
}
-
- } else {
- applyIntervalQueryOnBlock(pSupporter, pMeterDataInfo, pBlockBasicInfo, blockStatus, pFields, searchFn);
}
+
+ return cnt;
}
+static void updatelastkey(SQuery *pQuery, SMeterQueryInfo *pMeterQInfo) { pMeterQInfo->lastKey = pQuery->lastKey; }
+
/*
* set tag value in SQLFunctionCtx
* e.g.,tag information into input buffer
@@ -5109,7 +5401,7 @@ static void doSetTagValueInParam(SColumnModel *pTagSchema, int32_t tagColIdx, SM
assert(tagColIdx >= 0);
int16_t offset = getColumnModelOffset(pTagSchema, tagColIdx);
-
+
void * pStr = (char *)pMeterSidInfo->tags + offset;
SSchema *pCol = getColumnModelSchema(pTagSchema, tagColIdx);
@@ -5123,7 +5415,7 @@ static void doSetTagValueInParam(SColumnModel *pTagSchema, int32_t tagColIdx, SM
}
void vnodeSetTagValueInParam(tSidSet *pSidSet, SQueryRuntimeEnv *pRuntimeEnv, SMeterSidExtInfo *pMeterSidInfo) {
- SQuery * pQuery = pRuntimeEnv->pQuery;
+ SQuery * pQuery = pRuntimeEnv->pQuery;
SColumnModel *pTagSchema = pSidSet->pColumnModel;
SSqlFuncExprMsg *pFuncMsg = &pQuery->pSelectExpr[0].pBase;
@@ -5153,8 +5445,7 @@ void vnodeSetTagValueInParam(tSidSet *pSidSet, SQueryRuntimeEnv *pRuntimeEnv, SM
}
}
-static void doMerge(SQueryRuntimeEnv *pRuntimeEnv, int64_t timestamp, tFilePage *inputSrc, int32_t inputIdx,
- bool mergeFlag) {
+static void doMerge(SQueryRuntimeEnv *pRuntimeEnv, int64_t timestamp, SWindowResult *pWindowRes, bool mergeFlag) {
SQuery * pQuery = pRuntimeEnv->pQuery;
SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
@@ -5170,9 +5461,10 @@ static void doMerge(SQueryRuntimeEnv *pRuntimeEnv, int64_t timestamp, tFilePage
pCtx[i].hasNull = true;
pCtx[i].nStartQueryTimestamp = timestamp;
- pCtx[i].aInputElemBuf = ((char *)inputSrc->data) +
- ((int32_t)pRuntimeEnv->offset[i] * pRuntimeEnv->numOfRowsPerPage) +
- pCtx[i].outputBytes * inputIdx;
+ pCtx[i].aInputElemBuf = getPosInResultPage(pRuntimeEnv, i, pWindowRes);
+ // pCtx[i].aInputElemBuf = ((char *)inputSrc->data) +
+ // ((int32_t)pRuntimeEnv->offset[i] * pRuntimeEnv->numOfRowsPerPage) +
+ // pCtx[i].outputBytes * inputIdx;
// in case of tag column, the tag information should be extracted from input buffer
if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TAG) {
@@ -5262,7 +5554,7 @@ static void printBinaryData(int32_t functionId, char *data, int32_t srcDataType)
void UNUSED_FUNC displayInterResult(SData **pdata, SQuery *pQuery, int32_t numOfRows) {
int32_t numOfCols = pQuery->numOfOutputCols;
- printf("metric query intern-result, total:%d\n", numOfRows);
+ printf("super table query intermediate result, total:%d\n", numOfRows);
SQInfo * pQInfo = (SQInfo *)(GET_QINFO_ADDR(pQuery));
SMeterObj *pMeterObj = pQInfo->pObj;
@@ -5302,55 +5594,54 @@ void UNUSED_FUNC displayInterResult(SData **pdata, SQuery *pQuery, int32_t numOf
}
}
-static tFilePage *getMeterDataPage(SQueryResultBuf* pResultBuf, SMeterQueryInfo *pMeterQueryInfo, int32_t index) {
- SIDList pList = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
- return getResultBufferPageById(pResultBuf, pList.pData[index]);
-}
+// static tFilePage *getMeterDataPage(SQueryDiskbasedResultBuf *pResultBuf, SMeterQueryInfo *pMeterQueryInfo,
+// int32_t index) {
+// SIDList pList = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
+// return getResultBufferPageById(pResultBuf, pList.pData[index]);
+//}
-typedef struct Position {
- int32_t pageIdx;
- int32_t rowIdx;
-} Position;
+// typedef struct Position {
+// int32_t pageIdx;
+// int32_t rowIdx;
+//} Position;
typedef struct SCompSupporter {
SMeterDataInfo ** pMeterDataInfo;
- Position * pPosition;
- SMeterQuerySupportObj *pSupporter;
+ int32_t * position;
+ STableQuerySupportObj *pSupporter;
} SCompSupporter;
-int64_t getCurrentTimestamp(SCompSupporter *pSupportor, int32_t meterIdx) {
- Position * pPos = &pSupportor->pPosition[meterIdx];
- tFilePage *pPage = getMeterDataPage(pSupportor->pSupporter->runtimeEnv.pResultBuf,
- pSupportor->pMeterDataInfo[meterIdx]->pMeterQInfo, pPos->pageIdx);
-
- return *(int64_t *)(pPage->data + TSDB_KEYSIZE * pPos->rowIdx);
-}
-
-int32_t meterResultComparator(const void *pLeft, const void *pRight, void *param) {
+int32_t tableResultComparFn(const void *pLeft, const void *pRight, void *param) {
int32_t left = *(int32_t *)pLeft;
int32_t right = *(int32_t *)pRight;
- SCompSupporter *supporter = (SCompSupporter *)param;
- SQueryResultBuf* pResultBuf = supporter->pSupporter->runtimeEnv.pResultBuf;
-
- Position leftPos = supporter->pPosition[left];
- Position rightPos = supporter->pPosition[right];
+ SCompSupporter * supporter = (SCompSupporter *)param;
+ SQueryRuntimeEnv *pRuntimeEnv = &supporter->pSupporter->runtimeEnv;
+
+ int32_t leftPos = supporter->position[left];
+ int32_t rightPos = supporter->position[right];
/* left source is exhausted */
- if (leftPos.pageIdx == -1 && leftPos.rowIdx == -1) {
+ if (leftPos == -1) {
return 1;
}
/* right source is exhausted*/
- if (rightPos.pageIdx == -1 && rightPos.rowIdx == -1) {
+ if (rightPos == -1) {
return -1;
}
- tFilePage *pPageLeft = getMeterDataPage(pResultBuf, supporter->pMeterDataInfo[left]->pMeterQInfo, leftPos.pageIdx);
- int64_t leftTimestamp = *(int64_t *)(pPageLeft->data + TSDB_KEYSIZE * leftPos.rowIdx);
+ SWindowResInfo *pWindowResInfo1 = &supporter->pMeterDataInfo[left]->pMeterQInfo->windowResInfo;
+ SWindowResult * pWindowRes1 = getWindowResult(pWindowResInfo1, leftPos);
+
+ char *b1 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes1);
+ TSKEY leftTimestamp = GET_INT64_VAL(b1);
- tFilePage *pPageRight = getMeterDataPage(pResultBuf, supporter->pMeterDataInfo[right]->pMeterQInfo, rightPos.pageIdx);
- int64_t rightTimestamp = *(int64_t *)(pPageRight->data + TSDB_KEYSIZE * rightPos.rowIdx);
+ SWindowResInfo *pWindowResInfo2 = &supporter->pMeterDataInfo[right]->pMeterQInfo->windowResInfo;
+ SWindowResult * pWindowRes2 = getWindowResult(pWindowResInfo2, rightPos);
+
+ char *b2 = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes2);
+ TSKEY rightTimestamp = GET_INT64_VAL(b2);
if (leftTimestamp == rightTimestamp) {
return 0;
@@ -5359,7 +5650,7 @@ int32_t meterResultComparator(const void *pLeft, const void *pRight, void *param
return leftTimestamp > rightTimestamp ? 1 : -1;
}
-int32_t mergeMetersResultToOneGroups(SMeterQuerySupportObj *pSupporter) {
+int32_t mergeMetersResultToOneGroups(STableQuerySupportObj *pSupporter) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
@@ -5392,7 +5683,7 @@ int32_t mergeMetersResultToOneGroups(SMeterQuerySupportObj *pSupporter) {
return TSDB_CODE_SUCCESS;
}
-void copyResToQueryResultBuf(SMeterQuerySupportObj *pSupporter, SQuery *pQuery) {
+void copyResToQueryResultBuf(STableQuerySupportObj *pSupporter, SQuery *pQuery) {
if (pSupporter->offset == pSupporter->numOfGroupResultPages) {
pSupporter->numOfGroupResultPages = 0;
@@ -5408,142 +5699,153 @@ void copyResToQueryResultBuf(SMeterQuerySupportObj *pSupporter, SQuery *pQuery)
}
}
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQueryResultBuf* pResultBuf = pRuntimeEnv->pResultBuf;
-
- SIDList list = getDataBufPagesIdList(pResultBuf, 200000 + pSupporter->offset + (pSupporter->subgroupIdx - 1)* 10000);
-
+ SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
+ SQueryDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
+
+ int32_t id = getGroupResultId(pSupporter->subgroupIdx - 1);
+ SIDList list = getDataBufPagesIdList(pResultBuf, pSupporter->offset + id);
+
int32_t total = 0;
- for(int32_t i = 0; i < list.size; ++i) {
- tFilePage* pData = getResultBufferPageById(pResultBuf, list.pData[i]);
+ for (int32_t i = 0; i < list.size; ++i) {
+ tFilePage *pData = getResultBufferPageById(pResultBuf, list.pData[i]);
total += pData->numOfElems;
}
-
+
pQuery->sdata[0]->len = total;
-
+
int32_t offset = 0;
- for(int32_t num = 0; num < list.size; ++num) {
- tFilePage* pData = getResultBufferPageById(pResultBuf, list.pData[num]);
-
+ for (int32_t num = 0; num < list.size; ++num) {
+ tFilePage *pData = getResultBufferPageById(pResultBuf, list.pData[num]);
+
for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes;
- char* pDest = pQuery->sdata[i]->data;
-
- memcpy(pDest + offset*bytes, pData->data + pRuntimeEnv->offset[i] * pData->numOfElems, bytes * pData->numOfElems);
+ char * pDest = pQuery->sdata[i]->data;
+
+ memcpy(pDest + offset * bytes, pData->data + pRuntimeEnv->offset[i] * pData->numOfElems,
+ bytes * pData->numOfElems);
}
-
+
offset += pData->numOfElems;
}
assert(pQuery->pointsRead == 0);
-
+
pQuery->pointsRead += pQuery->sdata[0]->len;
pSupporter->offset += 1;
}
-int32_t doMergeMetersResultsToGroupRes(SMeterQuerySupportObj *pSupporter, SQuery *pQuery, SQueryRuntimeEnv *pRuntimeEnv,
- SMeterDataInfo *pMeterDataInfo, int32_t start, int32_t end) {
- // calculate the maximum required space
- if (pSupporter->groupResultSize == 0) {
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- pSupporter->groupResultSize += sizeof(tFilePage) + pQuery->pointsToRead * pRuntimeEnv->pCtx[i].outputBytes;
+int64_t getNumOfResultWindowRes(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pWindowRes) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+
+ int64_t maxOutput = 0;
+ for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
+ int32_t functionId = pQuery->pSelectExpr[j].pBase.functionId;
+
+ /*
+ * ts, tag, tagprj function can not decide the output number of current query
+ * the number of output result is decided by main output
+ */
+ if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) {
+ continue;
+ }
+
+ SResultInfo *pResultInfo = &pWindowRes->resultInfo[j];
+ if (pResultInfo != NULL && maxOutput < pResultInfo->numOfRes) {
+ maxOutput = pResultInfo->numOfRes;
}
}
+ return maxOutput;
+}
+
+int32_t doMergeMetersResultsToGroupRes(STableQuerySupportObj *pSupporter, SQuery *pQuery, SQueryRuntimeEnv *pRuntimeEnv,
+ SMeterDataInfo *pMeterDataInfo, int32_t start, int32_t end) {
tFilePage ** buffer = (tFilePage **)pQuery->sdata;
- Position * posArray = calloc(1, sizeof(Position) * (end - start));
- SMeterDataInfo **pValidMeter = malloc(POINTER_BYTES * (end - start));
+ int32_t * posList = calloc((end - start), sizeof(int32_t));
+ SMeterDataInfo **pTableList = malloc(POINTER_BYTES * (end - start));
+ // todo opt for the case of one table per group
int32_t numOfMeters = 0;
for (int32_t i = start; i < end; ++i) {
int32_t sid = pMeterDataInfo[i].pMeterQInfo->sid;
+
SIDList list = getDataBufPagesIdList(pRuntimeEnv->pResultBuf, sid);
-
- if (list.size > 0 && pMeterDataInfo[i].pMeterQInfo->numOfRes > 0) {
- pValidMeter[numOfMeters] = &pMeterDataInfo[i];
- // set the merge start position: page:0, index:0
- posArray[numOfMeters].pageIdx = 0;
- posArray[numOfMeters++].rowIdx = 0;
+ if (list.size > 0 && pMeterDataInfo[i].pMeterQInfo->windowResInfo.size > 0) {
+ pTableList[numOfMeters] = &pMeterDataInfo[i];
+ numOfMeters += 1;
}
}
if (numOfMeters == 0) {
- tfree(posArray);
- tfree(pValidMeter);
+ tfree(posList);
+ tfree(pTableList);
+
assert(pSupporter->numOfGroupResultPages == 0);
return 0;
}
- SCompSupporter cs = {pValidMeter, posArray, pSupporter};
- SLoserTreeInfo *pTree = NULL;
+ SCompSupporter cs = {pTableList, posList, pSupporter};
- tLoserTreeCreate(&pTree, numOfMeters, &cs, meterResultComparator);
+ SLoserTreeInfo *pTree = NULL;
+ tLoserTreeCreate(&pTree, numOfMeters, &cs, tableResultComparFn);
- SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
- resetMergeResultBuf(pQuery, pCtx);
+ SResultInfo *pResultInfo = calloc(pQuery->numOfOutputCols, sizeof(SResultInfo));
+ setWindowResultInfo(pResultInfo, pQuery, pRuntimeEnv->stableQuery);
+ resetMergeResultBuf(pQuery, pRuntimeEnv->pCtx, pResultInfo);
int64_t lastTimestamp = -1;
int64_t startt = taosGetTimestampMs();
while (1) {
- int32_t pos = pTree->pNode[0].index;
- Position * position = &cs.pPosition[pos];
- SQueryResultBuf* pResultBuf = cs.pSupporter->runtimeEnv.pResultBuf;
- tFilePage *pPage = getMeterDataPage(pResultBuf, pValidMeter[pos]->pMeterQInfo, position->pageIdx);
-
- int64_t ts = getCurrentTimestamp(&cs, pos);
- if (ts == lastTimestamp) {// merge with the last one
- doMerge(pRuntimeEnv, ts, pPage, position->rowIdx, true);
- } else {
- // copy data to disk buffer
- if (buffer[0]->numOfElems == pQuery->pointsToRead) {
- if (flushFromResultBuf(pSupporter, pQuery, pRuntimeEnv) != TSDB_CODE_SUCCESS) {
- return -1;
- }
+ int32_t pos = pTree->pNode[0].index;
- resetMergeResultBuf(pQuery, pCtx);
- }
+ SWindowResInfo *pWindowResInfo = &pTableList[pos]->pMeterQInfo->windowResInfo;
+ SWindowResult * pWindowRes = getWindowResult(pWindowResInfo, cs.position[pos]);
- pPage = getMeterDataPage(pResultBuf, pValidMeter[pos]->pMeterQInfo, position->pageIdx);
- if (pPage->numOfElems <= 0) { // current source data page is empty
- // do nothing
- } else {
- doMerge(pRuntimeEnv, ts, pPage, position->rowIdx, false);
- buffer[0]->numOfElems += 1;
- }
- }
+ char *b = getPosInResultPage(pRuntimeEnv, PRIMARYKEY_TIMESTAMP_COL_INDEX, pWindowRes);
+ TSKEY ts = GET_INT64_VAL(b);
- lastTimestamp = ts;
+ assert(ts == pWindowRes->window.skey);
+ int64_t num = getNumOfResultWindowRes(pRuntimeEnv, pWindowRes);
+ if (num <= 0) {
+ cs.position[pos] += 1;
- if (cs.pPosition[pos].rowIdx >= pPage->numOfElems - 1) {
- cs.pPosition[pos].rowIdx = 0;
- cs.pPosition[pos].pageIdx += 1; // try next page
+ if (cs.position[pos] >= pWindowResInfo->size) {
+ cs.position[pos] = -1;
- // check if current page is empty or not. if it is empty, ignore it and try next
- SIDList list = getDataBufPagesIdList(pRuntimeEnv->pResultBuf, cs.pMeterDataInfo[pos]->pMeterQInfo->sid);
- if (cs.pPosition[pos].pageIdx <= list.size - 1) {
- tFilePage *newPage = getMeterDataPage(pResultBuf, pValidMeter[pos]->pMeterQInfo, position->pageIdx);
-
- // if current source data page is null, it must be the last page of source output page
- if (newPage->numOfElems <= 0) {
- cs.pPosition[pos].pageIdx += 1;
- assert(cs.pPosition[pos].pageIdx >= list.size - 1);
+ // all input sources are exhausted
+ if (--numOfMeters == 0) {
+ break;
+ }
+ }
+ } else {
+ if (ts == lastTimestamp) { // merge with the last one
+ doMerge(pRuntimeEnv, ts, pWindowRes, true);
+ } else { // copy data to disk buffer
+ if (buffer[0]->numOfElems == pQuery->pointsToRead) {
+ if (flushFromResultBuf(pSupporter, pQuery, pRuntimeEnv) != TSDB_CODE_SUCCESS) {
+ return -1;
+ }
+
+ resetMergeResultBuf(pQuery, pRuntimeEnv->pCtx, pResultInfo);
}
+
+ doMerge(pRuntimeEnv, ts, pWindowRes, false);
+ buffer[0]->numOfElems += 1;
}
- // the following code must be executed if current source pages are exhausted
- if (cs.pPosition[pos].pageIdx >= list.size) {
- cs.pPosition[pos].pageIdx = -1;
- cs.pPosition[pos].rowIdx = -1;
+ lastTimestamp = ts;
+
+ cs.position[pos] += 1;
+ if (cs.position[pos] >= pWindowResInfo->size) {
+ cs.position[pos] = -1;
// all input sources are exhausted
if (--numOfMeters == 0) {
break;
}
}
- } else {
- cs.pPosition[pos].rowIdx += 1;
}
tLoserTreeAdjust(pTree, pos + pTree->numOfEntries);
@@ -5551,11 +5853,12 @@ int32_t doMergeMetersResultsToGroupRes(SMeterQuerySupportObj *pSupporter, SQuery
if (buffer[0]->numOfElems != 0) { // there are data in buffer
if (flushFromResultBuf(pSupporter, pQuery, pRuntimeEnv) != TSDB_CODE_SUCCESS) {
-// dError("QInfo:%p failed to flush data into temp file, abort query", GET_QINFO_ADDR(pQuery),
-// pSupporter->extBufFile);
+ // dError("QInfo:%p failed to flush data into temp file, abort query", GET_QINFO_ADDR(pQuery),
+ // pSupporter->extBufFile);
tfree(pTree);
- tfree(pValidMeter);
- tfree(posArray);
+ tfree(pTableList);
+ tfree(posList);
+ tfree(pResultInfo);
return -1;
}
@@ -5569,56 +5872,59 @@ int32_t doMergeMetersResultsToGroupRes(SMeterQuerySupportObj *pSupporter, SQuery
dTrace("QInfo:%p result merge completed, elapsed time:%" PRId64 " ms", GET_QINFO_ADDR(pQuery), endt - startt);
tfree(pTree);
- tfree(pValidMeter);
- tfree(posArray);
+ tfree(pTableList);
+ tfree(posList);
+ tfree(pResultInfo);
pSupporter->offset = 0;
return pSupporter->numOfGroupResultPages;
}
-int32_t flushFromResultBuf(SMeterQuerySupportObj *pSupporter, const SQuery *pQuery,
+int32_t flushFromResultBuf(STableQuerySupportObj *pSupporter, const SQuery *pQuery,
const SQueryRuntimeEnv *pRuntimeEnv) {
- SQueryResultBuf* pResultBuf = pRuntimeEnv->pResultBuf;
- int32_t capacity = (DEFAULT_INTERN_BUF_SIZE - sizeof(tFilePage))/ pQuery->rowSize;
-
+ SQueryDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf;
+ int32_t capacity = (DEFAULT_INTERN_BUF_SIZE - sizeof(tFilePage)) / pQuery->rowSize;
+
// the base value for group result, since the maximum number of table for each vnode will not exceed 100,000.
- int32_t base = 200000;
int32_t pageId = -1;
-
+
int32_t remain = pQuery->sdata[0]->len;
int32_t offset = 0;
-
- while(remain > 0) {
+
+ while (remain > 0) {
int32_t r = remain;
if (r > capacity) {
r = capacity;
}
-
- tFilePage* buf = getNewDataBuf(pResultBuf, base + pSupporter->subgroupIdx*10000 + pSupporter->numOfGroupResultPages, &pageId);
-
- //pagewise copy to dest buffer
+
+ int32_t id = getGroupResultId(pSupporter->subgroupIdx) + pSupporter->numOfGroupResultPages;
+ tFilePage *buf = getNewDataBuf(pResultBuf, id, &pageId);
+
+ // pagewise copy to dest buffer
for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
int32_t bytes = pRuntimeEnv->pCtx[i].outputBytes;
buf->numOfElems = r;
-
- memcpy(buf->data + pRuntimeEnv->offset[i] * buf->numOfElems, ((char*)pQuery->sdata[i]->data) + offset * bytes,
- buf->numOfElems * bytes);
+
+ memcpy(buf->data + pRuntimeEnv->offset[i] * buf->numOfElems, ((char *)pQuery->sdata[i]->data) + offset * bytes,
+ buf->numOfElems * bytes);
}
-
+
offset += r;
remain -= r;
}
-
+
pSupporter->numOfGroupResultPages += 1;
return TSDB_CODE_SUCCESS;
}
-void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx) {
+void resetMergeResultBuf(SQuery *pQuery, SQLFunctionCtx *pCtx, SResultInfo *pResultInfo) {
for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
pCtx[k].aOutputBuf = pQuery->sdata[k]->data - pCtx[k].outputBytes;
pCtx[k].size = 1;
pCtx[k].startOffset = 0;
+ pCtx[k].resultInfo = &pResultInfo[k];
+
pQuery->sdata[k]->len = 0;
}
}
@@ -5629,167 +5935,165 @@ void setMeterDataInfo(SMeterDataInfo *pMeterDataInfo, SMeterObj *pMeterObj, int3
pMeterDataInfo->meterOrderIdx = meterIdx;
}
-int32_t doCloseAllOpenedResults(SMeterQuerySupportObj *pSupporter) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
-
- /* for interval query, close all unclosed results */
- if (pQuery->nAggTimeInterval > 0) {
- SMeterDataInfo *pMeterInfo = pSupporter->pMeterDataInfo;
- for (int32_t i = 0; i < pSupporter->numOfMeters; ++i) {
- if (pMeterInfo[i].pMeterQInfo != NULL && pMeterInfo[i].pMeterQInfo->lastResRows > 0) {
- int32_t index = pMeterInfo[i].meterOrderIdx;
+static void doDisableFunctsForSupplementaryScan(SQuery *pQuery, SWindowResInfo *pWindowResInfo, int32_t order) {
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowStatus *pStatus = getTimeWindowResStatus(pWindowResInfo, i);
+ if (!pStatus->closed) {
+ continue;
+ }
- pRuntimeEnv->pMeterObj = getMeterObj(pSupporter->pMetersHashTable, pSupporter->pSidSet->pSids[index]->sid);
- assert(pRuntimeEnv->pMeterObj == pMeterInfo[i].pMeterObj);
+ SWindowResult *buf = getWindowResult(pWindowResInfo, i);
- int32_t ret = setIntervalQueryExecutionContext(pSupporter, i, pMeterInfo[i].pMeterQInfo);
- if (ret != TSDB_CODE_SUCCESS) {
- return ret;
- }
+ // open/close the specified query for each group result
+ for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
+ int32_t functId = pQuery->pSelectExpr[j].pBase.functionId;
- ret = saveResult(pSupporter, pMeterInfo[i].pMeterQInfo, pMeterInfo[i].pMeterQInfo->lastResRows);
- if (ret != TSDB_CODE_SUCCESS) {
- return ret;
- }
+ if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSQL_SO_DESC) ||
+ ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSQL_SO_ASC)) {
+ buf->resultInfo[j].complete = false;
+ } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
+ buf->resultInfo[j].complete = true;
}
}
}
-
- return TSDB_CODE_SUCCESS;
}
-void disableFunctForSuppleScan(SQueryRuntimeEnv *pRuntimeEnv, int32_t order) {
+void disableFunctForTableSuppleScan(SQueryRuntimeEnv *pRuntimeEnv, int32_t order) {
SQuery *pQuery = pRuntimeEnv->pQuery;
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0)) {
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1;
- }
-
- SSlidingWindowInfo *pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
-
- for (int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SWindowStatus *pStatus = &pSlidingWindowInfo->pStatus[i];
- if (!pStatus->closed) {
- continue;
- }
-
- SOutputRes *buf = &pSlidingWindowInfo->pResult[i];
-
- // open/close the specified query for each group result
- for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
- int32_t functId = pQuery->pSelectExpr[j].pBase.functionId;
+ // group by normal columns and interval query on normal table
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1u;
+ }
- if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSQL_SO_DESC) ||
- ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSQL_SO_ASC)) {
- buf->resultInfo[j].complete = false;
- } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
- buf->resultInfo[j].complete = true;
- }
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
+ doDisableFunctsForSupplementaryScan(pQuery, pWindowResInfo, order);
+ } else { // for simple result of table query,
+ for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
+ int32_t functId = pQuery->pSelectExpr[j].pBase.functionId;
+ SQLFunctionCtx* pCtx = &pRuntimeEnv->pCtx[j];
+
+ if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSQL_SO_DESC) ||
+ ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSQL_SO_ASC)) {
+ pCtx->resultInfo->complete = false;
+ } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
+ pCtx->resultInfo->complete = true;
}
}
- } else { // TODO ERROR!!
- // need to handle for each query result, not just the single runtime ctx.
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1;
- int32_t functId = pQuery->pSelectExpr[i].pBase.functionId;
+ }
- SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[i]);
- if (((functId == TSDB_FUNC_FIRST || functId == TSDB_FUNC_FIRST_DST) && order == TSQL_SO_DESC) ||
- ((functId == TSDB_FUNC_LAST || functId == TSDB_FUNC_LAST_DST) && order == TSQL_SO_ASC)) {
- pResInfo->complete = false;
+ pQuery->order.order = pQuery->order.order ^ 1u;
+}
+
+void disableFunctForSuppleScan(STableQuerySupportObj *pSupporter, int32_t order) {
+ SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1u;
+ }
+
+ if (isIntervalQuery(pQuery)) {
+ for (int32_t i = 0; i < pSupporter->numOfMeters; ++i) {
+ SMeterQueryInfo *pMeterQueryInfo = pSupporter->pMeterDataInfo[i].pMeterQInfo;
+ SWindowResInfo * pWindowResInfo = &pMeterQueryInfo->windowResInfo;
- } else if (functId != TSDB_FUNC_TS && functId != TSDB_FUNC_TAG) {
- pResInfo->complete = true;
- }
+ doDisableFunctsForSupplementaryScan(pQuery, pWindowResInfo, order);
}
+ } else {
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
+ doDisableFunctsForSupplementaryScan(pQuery, pWindowResInfo, order);
}
- pQuery->order.order = pQuery->order.order ^ 1;
+ pQuery->order.order = (pQuery->order.order) ^ 1u;
}
void enableFunctForMasterScan(SQueryRuntimeEnv *pRuntimeEnv, int32_t order) {
SQuery *pQuery = pRuntimeEnv->pQuery;
for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1;
+ pRuntimeEnv->pCtx[i].order = (pRuntimeEnv->pCtx[i].order) ^ 1u;
}
- pQuery->order.order = (pQuery->order.order ^ 1);
+ pQuery->order.order = (pQuery->order.order) ^ 1u;
}
-void createQueryResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pResultRow, bool isSTableQuery, SPosInfo *posInfo) {
- SQuery* pQuery = pRuntimeEnv->pQuery;
-
+void createQueryResultInfo(SQuery *pQuery, SWindowResult *pResultRow, bool isSTableQuery, SPosInfo *posInfo) {
int32_t numOfCols = pQuery->numOfOutputCols;
pResultRow->resultInfo = calloc((size_t)numOfCols, sizeof(SResultInfo));
- pResultRow->pos = *posInfo;//page->data + (pRuntimeEnv->offset[i] * pRuntimeEnv->numOfRowsPerPage) + page->numOfElems*s1;
-
- for (int32_t i = 0; i < numOfCols; ++i) {
- SResultInfo *pResultInfo = &pResultRow->resultInfo[i];
- size_t size = pQuery->pSelectExpr[i].interResBytes;
- setResultInfoBuf(pResultInfo, (int32_t)size, isSTableQuery);
- }
+ pResultRow->pos = *posInfo;
+
+ // set the intermediate result output buffer
+ setWindowResultInfo(pResultRow->resultInfo, pQuery, isSTableQuery);
}
-void clearGroupResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pOneOutputRes) {
- if (pOneOutputRes == NULL) {
+void clearTimeWindowResBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pWindowRes) {
+ if (pWindowRes == NULL) {
return;
}
for (int32_t i = 0; i < pRuntimeEnv->pQuery->numOfOutputCols; ++i) {
- SResultInfo *pResultInfo = &pOneOutputRes->resultInfo[i];
-// int32_t size = sizeof(tFilePage) + pResultInfo->bufLen * pOneOutputRes->nAlloc;
+ SResultInfo *pResultInfo = &pWindowRes->resultInfo[i];
-// memset(pOneOutputRes->pos[i], 0, (size_t)size);
- char* s = getPosInResultPage(pRuntimeEnv, i, pOneOutputRes);
+ char * s = getPosInResultPage(pRuntimeEnv, i, pWindowRes);
size_t size = pRuntimeEnv->pQuery->pSelectExpr[i].resBytes;
memset(s, 0, size);
-
+
resetResultInfo(pResultInfo);
}
+
+ pWindowRes->numOfRows = 0;
+ // pWindowRes->nAlloc = 0;
+ pWindowRes->pos = (SPosInfo){-1, -1};
+ pWindowRes->status.closed = false;
+ pWindowRes->window = (STimeWindow){0, 0};
}
-void copyGroupResultBuf(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes* dst, const SOutputRes* src) {
+/**
+ * The source window result pos attribution of the source window result does not assign to the destination,
+ * since the attribute of "Pos" is bound to each window result when the window result is created in the
+ * disk-based result buffer.
+ */
+void copyTimeWindowResBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *dst, const SWindowResult *src) {
dst->numOfRows = src->numOfRows;
- dst->nAlloc = src->nAlloc;
-
+ // dst->nAlloc = src->nAlloc;
+ dst->window = src->window;
+ dst->status = src->status;
+
int32_t nOutputCols = pRuntimeEnv->pQuery->numOfOutputCols;
-
- for(int32_t i = 0; i < nOutputCols; ++i) {
+
+ for (int32_t i = 0; i < nOutputCols; ++i) {
SResultInfo *pDst = &dst->resultInfo[i];
SResultInfo *pSrc = &src->resultInfo[i];
-
- char* buf = pDst->interResultBuf;
+
+ char *buf = pDst->interResultBuf;
memcpy(pDst, pSrc, sizeof(SResultInfo));
pDst->interResultBuf = buf; // restore the allocated buffer
-
+
// copy the result info struct
memcpy(pDst->interResultBuf, pSrc->interResultBuf, pDst->bufLen);
// copy the output buffer data from src to dst, the position info keep unchanged
- char* dstBuf = getPosInResultPage(pRuntimeEnv, i, dst);
- char* srcBuf = getPosInResultPage(pRuntimeEnv, i, src);
+ char * dstBuf = getPosInResultPage(pRuntimeEnv, i, dst);
+ char * srcBuf = getPosInResultPage(pRuntimeEnv, i, (SWindowResult *)src);
size_t s = pRuntimeEnv->pQuery->pSelectExpr[i].resBytes;
-
+
memcpy(dstBuf, srcBuf, s);
}
}
-void destroyGroupResultBuf(SOutputRes *pOneOutputRes, int32_t nOutputCols) {
- if (pOneOutputRes == NULL) {
+void destroyTimeWindowRes(SWindowResult *pWindowRes, int32_t nOutputCols) {
+ if (pWindowRes == NULL) {
return;
}
for (int32_t i = 0; i < nOutputCols; ++i) {
-// free(pOneOutputRes->pos[i]);
- free(pOneOutputRes->resultInfo[i].interResultBuf);
+ free(pWindowRes->resultInfo[i].interResultBuf);
}
- free(pOneOutputRes->resultInfo);
-// free(pOneOutputRes->result);
+ free(pWindowRes->resultInfo);
}
void resetCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) {
@@ -5829,7 +6133,7 @@ void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) {
// set next output position
if (IS_OUTER_FORWARD(aAggs[functionId].nStatus)) {
- pRuntimeEnv->pCtx[j].aOutputBuf += pRuntimeEnv->pCtx[j].outputBytes * output /** factor*/;
+ pRuntimeEnv->pCtx[j].aOutputBuf += pRuntimeEnv->pCtx[j].outputBytes * output;
}
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) {
@@ -5840,7 +6144,7 @@ void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) {
*
* diff function is handled in multi-output function
*/
- pRuntimeEnv->pCtx[j].ptsOutputBuf += TSDB_KEYSIZE * output/* * factor*/;
+ pRuntimeEnv->pCtx[j].ptsOutputBuf += TSDB_KEYSIZE * output;
}
resetResultInfo(pRuntimeEnv->pCtx[j].resultInfo);
@@ -5853,7 +6157,7 @@ void initCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv) {
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
int32_t functionId = pQuery->pSelectExpr[j].pBase.functionId;
pRuntimeEnv->pCtx[j].currentStage = 0;
-
+
aAggs[functionId].init(&pRuntimeEnv->pCtx[j]);
}
}
@@ -5898,24 +6202,17 @@ typedef struct SQueryStatus {
SPositionInfo start;
SPositionInfo next;
SPositionInfo end;
-
- TSKEY skey;
- TSKEY ekey;
- int8_t overStatus;
- TSKEY lastKey;
-
- STSCursor cur;
+ int8_t overStatus;
+ TSKEY lastKey;
+ STSCursor cur;
} SQueryStatus;
-
+// todo refactor
static void queryStatusSave(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus *pStatus) {
SQuery *pQuery = pRuntimeEnv->pQuery;
pStatus->overStatus = pQuery->over;
pStatus->lastKey = pQuery->lastKey;
- pStatus->skey = pQuery->skey;
- pStatus->ekey = pQuery->ekey;
-
pStatus->start = pRuntimeEnv->startPos;
pStatus->next = pRuntimeEnv->nextPos;
pStatus->end = pRuntimeEnv->endPos;
@@ -5923,7 +6220,7 @@ static void queryStatusSave(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus *pStatus
pStatus->cur = tsBufGetCursor(pRuntimeEnv->pTSBuf); // save the cursor
if (pRuntimeEnv->pTSBuf) {
- pRuntimeEnv->pTSBuf->cur.order ^= 1;
+ pRuntimeEnv->pTSBuf->cur.order ^= 1u;
tsBufNextPos(pRuntimeEnv->pTSBuf);
}
@@ -5932,19 +6229,13 @@ static void queryStatusSave(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus *pStatus
SWAP(pQuery->skey, pQuery->ekey, TSKEY);
pQuery->lastKey = pQuery->skey;
pRuntimeEnv->startPos = pRuntimeEnv->endPos;
-
- SWAP(pRuntimeEnv->intervalWindow.skey, pRuntimeEnv->intervalWindow.ekey, TSKEY);
}
static void queryStatusRestore(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus *pStatus) {
SQuery *pQuery = pRuntimeEnv->pQuery;
SWAP(pQuery->skey, pQuery->ekey, TSKEY);
- SWAP(pRuntimeEnv->intervalWindow.skey, pRuntimeEnv->intervalWindow.ekey, TSKEY);
-
- pQuery->lastKey = pStatus->lastKey;
- pQuery->skey = pStatus->skey;
- pQuery->ekey = pStatus->ekey;
+ pQuery->lastKey = pStatus->lastKey;
pQuery->over = pStatus->overStatus;
pRuntimeEnv->startPos = pStatus->start;
@@ -5963,7 +6254,7 @@ static void doSingleMeterSupplementScan(SQueryRuntimeEnv *pRuntimeEnv) {
}
dTrace("QInfo:%p start to supp scan", GET_QINFO_ADDR(pQuery));
-
+
SET_SUPPLEMENT_SCAN_FLAG(pRuntimeEnv);
// usually this load operation will incur load disk block operation
@@ -5973,7 +6264,7 @@ static void doSingleMeterSupplementScan(SQueryRuntimeEnv *pRuntimeEnv) {
(!QUERY_IS_ASC_QUERY(pQuery) && endKey >= pQuery->ekey));
// close necessary function execution during supplementary scan
- disableFunctForSuppleScan(pRuntimeEnv, pQuery->order.order);
+ disableFunctForTableSuppleScan(pRuntimeEnv, pQuery->order.order);
queryStatusSave(pRuntimeEnv, &qStatus);
doScanAllDataBlocks(pRuntimeEnv);
@@ -5998,60 +6289,90 @@ void setQueryStatus(SQuery *pQuery, int8_t status) {
}
}
-void vnodeScanAllData(SQueryRuntimeEnv *pRuntimeEnv) {
+bool needScanDataBlocksAgain(SQueryRuntimeEnv *pRuntimeEnv) {
SQuery *pQuery = pRuntimeEnv->pQuery;
- setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
-
- /* store the start query position */
- savePointPosition(&pRuntimeEnv->startPos, pQuery->fileId, pQuery->slot, pQuery->pos);
- int64_t skey = pQuery->lastKey;
-
- while (1) {
- doScanAllDataBlocks(pRuntimeEnv);
+ bool toContinue = false;
- bool toContinue = true;
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
+ // for each group result, call the finalize function for each column
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
- // for each group result, call the finalize function for each column
- SSlidingWindowInfo *pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowResult *pResult = getWindowResult(pWindowResInfo, i);
+ if (!pResult->status.closed) {
+ continue;
+ }
- for (int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SOutputRes *buf = &pSlidingWindowInfo->pResult[i];
+ setWindowResOutputBuf(pRuntimeEnv, pResult);
- SWindowStatus *pStatus = &pSlidingWindowInfo->pStatus[i];
- if (!pStatus->closed) {
+ for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
+ int16_t functId = pQuery->pSelectExpr[j].pBase.functionId;
+ if (functId == TSDB_FUNC_TS) {
continue;
}
+
+ aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]);
+ SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
+
+ toContinue |= (!pResInfo->complete);
+ }
+ }
+ } else {
+ for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
+ int16_t functId = pQuery->pSelectExpr[j].pBase.functionId;
+ if (functId == TSDB_FUNC_TS) {
+ continue;
+ }
+
+ aAggs[functId].xNextStep(&pRuntimeEnv->pCtx[j]);
+ SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
- setGroupOutputBuffer(pRuntimeEnv, buf);
+ toContinue |= (!pResInfo->complete);
+ }
+ }
- for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
- aAggs[pQuery->pSelectExpr[j].pBase.functionId].xNextStep(&pRuntimeEnv->pCtx[j]);
- SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
+ return toContinue;
+}
- toContinue &= (pResInfo->complete);
- }
- }
- } else {
- for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
- aAggs[pQuery->pSelectExpr[j].pBase.functionId].xNextStep(&pRuntimeEnv->pCtx[j]);
- SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[j]);
+void vnodeScanAllData(SQueryRuntimeEnv *pRuntimeEnv) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+ setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
- toContinue &= (pResInfo->complete);
- }
- }
+ /* store the start query position */
+ savePointPosition(&pRuntimeEnv->startPos, pQuery->fileId, pQuery->slot, pQuery->pos);
+ int64_t oldSkey = pQuery->skey;
+ int64_t oldEkey = pQuery->ekey;
+
+ int64_t skey = pQuery->lastKey;
+ int32_t status = pQuery->over;
+
+ SET_MASTER_SCAN_FLAG(pRuntimeEnv);
+ int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+
+ while (1) {
+ doScanAllDataBlocks(pRuntimeEnv);
- if (toContinue) {
+ if (!needScanDataBlocksAgain(pRuntimeEnv)) {
+ // restore the status
+ if (pRuntimeEnv->scanFlag == REPEAT_SCAN) {
+ pQuery->over = status;
+ }
break;
}
- // set the correct start position, and load the corresponding block in buffer if required.
- TSKEY actKey = loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->startPos);
- assert((QUERY_IS_ASC_QUERY(pQuery) && actKey >= pQuery->skey) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && actKey <= pQuery->skey));
+ /*
+ * set the correct start position, and load the corresponding block in buffer for next
+ * round scan all data blocks.
+ */
+ TSKEY key = loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->startPos);
+ assert((QUERY_IS_ASC_QUERY(pQuery) && key >= pQuery->skey) || (!QUERY_IS_ASC_QUERY(pQuery) && key <= pQuery->skey));
- setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
+ status = pQuery->over;
+ pQuery->ekey = pQuery->lastKey - step;
pQuery->lastKey = pQuery->skey;
+
+ setQueryStatus(pQuery, QUERY_NOT_COMPLETED);
+ pRuntimeEnv->scanFlag = REPEAT_SCAN;
/* check if query is killed or not */
if (isQueryKilled(pQuery)) {
@@ -6060,33 +6381,36 @@ void vnodeScanAllData(SQueryRuntimeEnv *pRuntimeEnv) {
}
}
- int64_t newSkey = pQuery->skey;
+ // no need to set the end key
+ int64_t curLastKey = pQuery->lastKey;
pQuery->skey = skey;
+ pQuery->ekey = pQuery->lastKey - step;
doSingleMeterSupplementScan(pRuntimeEnv);
-
- // update the pQuery->skey/pQuery->ekey to limit the scan scope of sliding query during
- // supplementary scan
- pQuery->skey = newSkey;
+
+ // update the pQuery->skey/pQuery->ekey to limit the scan scope of sliding query during supplementary scan
+ pQuery->skey = oldSkey;
+ pQuery->ekey = oldEkey;
+ pQuery->lastKey = curLastKey;
}
void doFinalizeResult(SQueryRuntimeEnv *pRuntimeEnv) {
SQuery *pQuery = pRuntimeEnv->pQuery;
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || isIntervalQuery(pQuery)) {
// for each group result, call the finalize function for each column
- SSlidingWindowInfo *pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
- closeAllSlidingWindow(pSlidingWindowInfo);
+ closeAllTimeWindow(pWindowResInfo);
}
-
- for (int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SOutputRes *buf = &pSlidingWindowInfo->pResult[i];
- if (!slidingWindowClosed(pSlidingWindowInfo, i)) {
+
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowResult *buf = &pWindowResInfo->pResult[i];
+ if (!isWindowResClosed(pWindowResInfo, i)) {
continue;
}
-
- setGroupOutputBuffer(pRuntimeEnv, buf);
+
+ setWindowResOutputBuf(pRuntimeEnv, buf);
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
aAggs[pQuery->pSelectExpr[j].pBase.functionId].xFinalize(&pRuntimeEnv->pCtx[j]);
@@ -6144,89 +6468,6 @@ int64_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv) {
return maxOutput;
}
-static int32_t getNextIntervalQueryRange(SMeterQuerySupportObj *pSupporter, SQueryRuntimeEnv *pRuntimeEnv,
- int64_t *skey, int64_t *ekey) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
-
- int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
-
- *skey = pRuntimeEnv->intervalWindow.skey + (pQuery->slidingTime * factor);
- *ekey = pRuntimeEnv->intervalWindow.ekey + (pQuery->slidingTime * factor);
-
- if (pQuery->slidingTime > 0) {
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- // the next sliding window is not contained in the query time range
- if (*skey < pSupporter->rawSKey) {
- *skey = pSupporter->rawSKey;
- }
-
- if (*skey > pSupporter->rawEKey) {
- return QUERY_COMPLETED;
- }
-
- if (*ekey > pSupporter->rawEKey) {
- *ekey = pSupporter->rawEKey;
- }
- } else {
- if (*skey > pSupporter->rawSKey) {
- *skey = pSupporter->rawSKey;
- }
-
- if (*skey < pSupporter->rawEKey) {
- return QUERY_COMPLETED;
- }
-
- if (*ekey < pSupporter->rawEKey) {
- *ekey = pSupporter->rawEKey;
- }
- }
- }
-
- return QUERY_NOT_COMPLETED;
-}
-
-/*
- * forward the query range for next interval query
- */
-void forwardIntervalQueryRange(SMeterQuerySupportObj *pSupporter, SQueryRuntimeEnv *pRuntimeEnv) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
- if (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0) {
- if ((QUERY_IS_ASC_QUERY(pQuery) && pQuery->lastKey >= pQuery->ekey) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && pQuery->lastKey <= pQuery->ekey)) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
- } else {
- /*TSKEY nextTimestamp =*/ loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->nextPos);
- }
-
- return;
- }
-
- int32_t r = getNextIntervalQueryRange(pSupporter, pRuntimeEnv, &pQuery->skey, &pQuery->ekey);
- if (r == QUERY_COMPLETED) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
- return;
- }
-
- getNextLogicalQueryRange(pRuntimeEnv, &pRuntimeEnv->intervalWindow);
-
- /* ensure the search in cache will return right position */
- pQuery->lastKey = pQuery->skey;
-
- TSKEY nextTimestamp = loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->nextPos);
- if ((nextTimestamp > pSupporter->rawEKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (nextTimestamp < pSupporter->rawEKey && !QUERY_IS_ASC_QUERY(pQuery)) ||
- Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
- setQueryStatus(pQuery, QUERY_COMPLETED);
- return;
- }
-
- // bridge the gap in group by time function
- if ((nextTimestamp > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (nextTimestamp < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- getAlignedIntervalQueryRange(pRuntimeEnv, nextTimestamp, pSupporter->rawSKey, pSupporter->rawEKey);
- }
-}
-
static int32_t offsetComparator(const void *pLeft, const void *pRight) {
SMeterDataInfo **pLeft1 = (SMeterDataInfo **)pLeft;
SMeterDataInfo **pRight1 = (SMeterDataInfo **)pRight;
@@ -6252,7 +6493,7 @@ int32_t vnodeFilterQualifiedMeters(SQInfo *pQInfo, int32_t vid, tSidSet *pSidSet
int32_t *numOfMeters, SMeterDataInfo ***pReqMeterDataInfo) {
SQuery *pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SMeterSidExtInfo ** pMeterSidExtInfo = pSupporter->pMeterSidExtInfo;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
@@ -6348,7 +6589,8 @@ int32_t vnodeFilterQualifiedMeters(SQInfo *pQInfo, int32_t vid, tSidSet *pSidSet
pOneMeterDataInfo->offsetInHeaderFile = (uint64_t)compHeader->compInfoOffset;
if (pOneMeterDataInfo->pMeterQInfo == NULL) {
- pOneMeterDataInfo->pMeterQInfo = createMeterQueryInfo(pQuery, pMeterObj->sid, pSupporter->rawSKey, pSupporter->rawEKey);
+ pOneMeterDataInfo->pMeterQInfo =
+ createMeterQueryInfo(pSupporter, pMeterObj->sid, pSupporter->rawSKey, pSupporter->rawEKey);
}
(*pReqMeterDataInfo)[*numOfMeters] = pOneMeterDataInfo;
@@ -6367,26 +6609,19 @@ int32_t vnodeFilterQualifiedMeters(SQInfo *pQInfo, int32_t vid, tSidSet *pSidSet
return TSDB_CODE_SUCCESS;
}
-SMeterQueryInfo *createMeterQueryInfo(SQuery *pQuery, int32_t sid, TSKEY skey, TSKEY ekey) {
+SMeterQueryInfo *createMeterQueryInfo(STableQuerySupportObj *pSupporter, int32_t sid, TSKEY skey, TSKEY ekey) {
+ SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
+
SMeterQueryInfo *pMeterQueryInfo = calloc(1, sizeof(SMeterQueryInfo));
pMeterQueryInfo->skey = skey;
pMeterQueryInfo->ekey = ekey;
pMeterQueryInfo->lastKey = skey;
-// pMeterQueryInfo->numOfPages = 0;
-// pMeterQueryInfo->numOfAlloc = INIT_ALLOCATE_DISK_PAGES;
-// pMeterQueryInfo->pageList = calloc(pMeterQueryInfo->numOfAlloc, sizeof(uint32_t));
- pMeterQueryInfo->lastResRows = 0;
pMeterQueryInfo->sid = sid;
pMeterQueryInfo->cur.vnodeIndex = -1;
- pMeterQueryInfo->resultInfo = calloc((size_t)pQuery->numOfOutputCols, sizeof(SResultInfo));
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- SResultInfo *pResInfo = &pMeterQueryInfo->resultInfo[i];
- setResultInfoBuf(pResInfo, pQuery->pSelectExpr[i].interResBytes, true);
- }
-
+ initWindowResInfo(&pMeterQueryInfo->windowResInfo, pRuntimeEnv, 100, 100, TSDB_DATA_TYPE_INT);
return pMeterQueryInfo;
}
@@ -6395,53 +6630,35 @@ void destroyMeterQueryInfo(SMeterQueryInfo *pMeterQueryInfo, int32_t numOfCols)
return;
}
-// free(pMeterQueryInfo->pageList);
- for (int32_t i = 0; i < numOfCols; ++i) {
- tfree(pMeterQueryInfo->resultInfo[i].interResultBuf);
- }
+ // free(pMeterQueryInfo->pageList);
+ // for (int32_t i = 0; i < numOfCols; ++i) {
+ // tfree(pMeterQueryInfo->[i].interResultBuf);
+ // }
- free(pMeterQueryInfo->resultInfo);
+ // free(pMeterQueryInfo->resultInfo);
free(pMeterQueryInfo);
}
-void changeMeterQueryInfoForSuppleQuery(SQueryResultBuf* pResultBuf, SMeterQueryInfo *pMeterQueryInfo, TSKEY skey,
- TSKEY ekey) {
+void changeMeterQueryInfoForSuppleQuery(SQuery *pQuery, SMeterQueryInfo *pMeterQueryInfo, TSKEY skey, TSKEY ekey) {
if (pMeterQueryInfo == NULL) {
return;
}
- pMeterQueryInfo->skey = skey;
- pMeterQueryInfo->ekey = ekey;
- pMeterQueryInfo->lastKey = pMeterQueryInfo->skey;
-
- pMeterQueryInfo->queryRangeSet = 0;
- pMeterQueryInfo->cur.order = pMeterQueryInfo->cur.order ^ 1;
- pMeterQueryInfo->cur.vnodeIndex = -1;
-
- // previous does not generate any results
- SIDList list = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
-
- if (list.size == 0) {
- pMeterQueryInfo->reverseFillRes = 0;
+ // order has change already!
+ int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
+ if (!QUERY_IS_ASC_QUERY(pQuery)) {
+ assert(pMeterQueryInfo->ekey >= pMeterQueryInfo->lastKey + step);
} else {
- pMeterQueryInfo->reverseIndex = pMeterQueryInfo->numOfRes;
- pMeterQueryInfo->reverseFillRes = 1;
+ assert(pMeterQueryInfo->ekey <= pMeterQueryInfo->lastKey + step);
}
-}
-void saveIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, SMeterQueryInfo *pMeterQueryInfo) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
-
- pMeterQueryInfo->skey = pQuery->skey;
- pMeterQueryInfo->ekey = pQuery->ekey;
- pMeterQueryInfo->lastKey = pQuery->lastKey;
+ pMeterQueryInfo->ekey = pMeterQueryInfo->lastKey + step;
- assert(((pQuery->lastKey >= pQuery->skey) && QUERY_IS_ASC_QUERY(pQuery)) ||
- ((pQuery->lastKey <= pQuery->skey) && !QUERY_IS_ASC_QUERY(pQuery)));
+ SWAP(pMeterQueryInfo->skey, pMeterQueryInfo->ekey, TSKEY);
+ pMeterQueryInfo->lastKey = pMeterQueryInfo->skey;
- if (pRuntimeEnv->pTSBuf != NULL) {
- pMeterQueryInfo->cur = tsBufGetCursor(pRuntimeEnv->pTSBuf);
- }
+ pMeterQueryInfo->cur.order = pMeterQueryInfo->cur.order ^ 1u;
+ pMeterQueryInfo->cur.vnodeIndex = -1;
}
void restoreIntervalQueryRange(SQueryRuntimeEnv *pRuntimeEnv, SMeterQueryInfo *pMeterQueryInfo) {
@@ -6555,7 +6772,7 @@ static bool setCurrentQueryRange(SMeterDataInfo *pMeterDataInfo, SQuery *pQuery,
* @param pMeterDataInfo
* @return
*/
-int32_t getDataBlocksForMeters(SMeterQuerySupportObj *pSupporter, SQuery *pQuery, int32_t numOfMeters,
+int32_t getDataBlocksForMeters(STableQuerySupportObj *pSupporter, SQuery *pQuery, int32_t numOfMeters,
const char *filePath, SMeterDataInfo **pMeterDataInfo, uint32_t *numOfBlocks) {
SQInfo * pQInfo = (SQInfo *)GET_QINFO_ADDR(pQuery);
SQueryCostSummary *pSummary = &pSupporter->runtimeEnv.summary;
@@ -6590,13 +6807,13 @@ int32_t getDataBlocksForMeters(SMeterQuerySupportObj *pSupporter, SQuery *pQuery
size_t bufferSize = size + sizeof(TSCKSUM);
pMeterDataInfo[j]->numOfBlocks = compInfo.numOfBlocks;
- char* p = realloc(pMeterDataInfo[j]->pBlock, bufferSize);
+ char *p = realloc(pMeterDataInfo[j]->pBlock, bufferSize);
if (p == NULL) {
clearAllMeterDataBlockInfo(pMeterDataInfo, 0, numOfMeters);
return TSDB_CODE_SERV_OUT_OF_MEMORY;
} else {
memset(p, 0, bufferSize);
- pMeterDataInfo[j]->pBlock = (SCompBlock*) p;
+ pMeterDataInfo[j]->pBlock = (SCompBlock *)p;
}
read(pVnodeFileInfo->headerFd, pMeterDataInfo[j]->pBlock, bufferSize);
@@ -6633,7 +6850,7 @@ int32_t getDataBlocksForMeters(SMeterQuerySupportObj *pSupporter, SQuery *pQuery
if (!setValidDataBlocks(pMeterDataInfo[j], end)) {
clearAllMeterDataBlockInfo(pMeterDataInfo, 0, numOfMeters);
-
+
pQInfo->killed = 1; // set query kill, abort current query since no memory available
return TSDB_CODE_SERV_OUT_OF_MEMORY;
}
@@ -6756,10 +6973,10 @@ int32_t createDataBlocksInfoEx(SMeterDataInfo **pMeterDataInfo, int32_t numOfMet
for (int32_t k = 0; k < pMeterDataInfo[j]->numOfBlocks; ++k) {
SMeterDataBlockInfoEx *pBlockInfoEx = &supporter.pDataBlockInfoEx[numOfQualMeters][k];
-
+
pBlockInfoEx->pBlock.compBlock = &pBlock[k];
pBlockInfoEx->pBlock.fields = NULL;
-
+
pBlockInfoEx->pMeterDataInfo = pMeterDataInfo[j];
pBlockInfoEx->groupIdx = pMeterDataInfo[j]->groupIdx; // set the group index
pBlockInfoEx->blockIndex = pMeterDataInfo[j]->start + k; // set the block index in original meter
@@ -6803,516 +7020,97 @@ int32_t createDataBlocksInfoEx(SMeterDataInfo **pMeterDataInfo, int32_t numOfMet
* for(int32_t i = 0; i < cnt - 1; ++i) {
* assert((*pDataBlockInfoEx)[i].pBlock.compBlock->offset < (*pDataBlockInfoEx)[i+1].pBlock.compBlock->offset);
* }
- */
-
- dTrace("QInfo %p %d data blocks sort completed", addr, cnt);
- cleanBlockOrderSupporter(&supporter, numOfMeters);
- free(pTree);
-
- return TSDB_CODE_SUCCESS;
-}
-
-/**
- * set output buffer for different group
- * @param pRuntimeEnv
- * @param pDataBlockInfoEx
- */
-void setExecutionContext(SMeterQuerySupportObj *pSupporter, SOutputRes *outputRes, int32_t meterIdx, int32_t groupIdx,
- SMeterQueryInfo *pMeterQueryInfo) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
-
- setGroupOutputBuffer(pRuntimeEnv, &outputRes[groupIdx]);
- initCtxOutputBuf(pRuntimeEnv);
-
- vnodeSetTagValueInParam(pSupporter->pSidSet, pRuntimeEnv, pSupporter->pMeterSidExtInfo[meterIdx]);
-
- // set the right cursor position for ts buffer
- if (pSupporter->runtimeEnv.pTSBuf != NULL) {
- if (pMeterQueryInfo->cur.vnodeIndex == -1) {
- pMeterQueryInfo->tag = pRuntimeEnv->pCtx[0].tag.i64Key;
-
- tsBufGetElemStartPos(pSupporter->runtimeEnv.pTSBuf, 0, pMeterQueryInfo->tag);
- } else {
- tsBufSetCursor(pSupporter->runtimeEnv.pTSBuf, &pMeterQueryInfo->cur);
- }
- }
-}
-
-static void setGroupOutputBuffer(SQueryRuntimeEnv *pRuntimeEnv, SOutputRes *pResult) {
- SQuery *pQuery = pRuntimeEnv->pQuery;
-
- // Note: pResult->pos[i]->numOfElems == 0, there is only fixed number of results for each group
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
- pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult);
-
- int32_t functionId = pQuery->pSelectExpr[i].pBase.functionId;
- if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
- pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].aOutputBuf;
- }
-
- /*
- * set the output buffer information and intermediate buffer
- * not all queries require the interResultBuf, such as COUNT
- */
- pCtx->resultInfo = &pResult->resultInfo[i];
-
- // set super table query flag
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (!isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
- pResInfo->superTableQ = true;
- }
- }
-}
-
-static char *getOutputResPos(SQueryRuntimeEnv *pRuntimeEnv, tFilePage *pData, int32_t row, int32_t col) {
- // the output for each record should be less than the DEFAULT_INTERN_BUF_SIZE
- assert(pRuntimeEnv->pCtx[col].outputBytes <= DEFAULT_INTERN_BUF_SIZE);
-
- return (char *)pData->data + pRuntimeEnv->offset[col] * pRuntimeEnv->numOfRowsPerPage +
- pRuntimeEnv->pCtx[col].outputBytes * row;
-}
-
-void setCtxOutputPointerForSupplementScan(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
-
- int32_t index = pMeterQueryInfo->reverseIndex;
- tFilePage *pData = NULL;
- int32_t i = 0;
-
- SQueryResultBuf* pResultBuf = pRuntimeEnv->pResultBuf;
-
- // find the position for this output result
- SIDList list = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
- for (; i < list.size; ++i) {
- pData = getResultBufferPageById(pResultBuf, list.pData[i]);
- if (index <= pData->numOfElems) {
- break;
- }
-
- index -= pData->numOfElems;
- }
-
- assert(index >= 0);
-
- /*
- * if it is the first records in master scan, no next results exist, so no need to init the result buffer
- * all data are processed and save to buffer during supplementary scan.
- */
- if (index == 0) {
- return;
- }
-
- for (int32_t k = 0; k < pQuery->numOfOutputCols; ++k) {
- SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[k];
-
- pCtx->aOutputBuf = getOutputResPos(pRuntimeEnv, pData, index - 1, k);
- SResultInfo *pResInfo = GET_RES_INFO(pCtx);
- if (pResInfo->complete) {
- continue;
- }
-
- int32_t functId = pQuery->pSelectExpr[k].pBase.functionId;
-
- // setup runtime environment
- if ((QUERY_IS_ASC_QUERY(pQuery) && functId == TSDB_FUNC_FIRST_DST) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && functId == TSDB_FUNC_LAST_DST)) {
- if (pMeterQueryInfo->lastResRows == 0) {
- pCtx->currentStage = 0;
-
- resetResultInfo(pResInfo);
- aAggs[functId].init(pCtx);
- }
- }
- }
-
- // the first column is always the timestamp for interval query
- TSKEY ts = *(TSKEY *)pRuntimeEnv->pCtx[0].aOutputBuf;
- SMeterObj *pMeterObj = pRuntimeEnv->pMeterObj;
- qTrace("QInfo:%p vid:%d sid:%d id:%s, set output result pointer, ts:%" PRId64 ", index:%d", GET_QINFO_ADDR(pQuery),
- pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, ts, pMeterQueryInfo->reverseIndex);
-}
+ */
-void validateTimestampForSupplementResult(SQueryRuntimeEnv *pRuntimeEnv, int64_t numOfIncrementRes) {
- SQuery * pQuery = pRuntimeEnv->pQuery;
- SQLFunctionCtx *pCtx = pRuntimeEnv->pCtx;
+ dTrace("QInfo %p %d data blocks sort completed", addr, cnt);
+ cleanBlockOrderSupporter(&supporter, numOfMeters);
+ free(pTree);
- if (pRuntimeEnv->scanFlag == SUPPLEMENTARY_SCAN && numOfIncrementRes > 0) {
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- int32_t functionId = pQuery->pSelectExpr[i].pBase.functionId;
- if (functionId == TSDB_FUNC_TS) {
- assert(*(TSKEY *)pCtx[i].aOutputBuf == pCtx[i].nStartQueryTimestamp);
- }
- }
- }
+ return TSDB_CODE_SUCCESS;
}
-int32_t setOutputBufferForIntervalQuery(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo) {
+/**
+ * set output buffer for different group
+ * @param pRuntimeEnv
+ * @param pDataBlockInfoEx
+ */
+void setExecutionContext(STableQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo, int32_t meterIdx,
+ int32_t groupIdx, TSKEY nextKey) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- tFilePage * pData = NULL;
-
- SQueryResultBuf* pResultBuf = pRuntimeEnv->pResultBuf;
-
- // in the first scan, new space needed for results
- SIDList list = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
- int32_t pageId = -1;
- if (list.size == 0) {
- pData = getNewDataBuf(pResultBuf, pMeterQueryInfo->sid, &pageId);
- } else {
- pData = getResultBufferPageById(pResultBuf, getLastPageId(&list));
+ SWindowResInfo * pWindowResInfo = &pRuntimeEnv->windowResInfo;
+ int32_t GROUPRESULTID = 1;
- if (pData->numOfElems >= pRuntimeEnv->numOfRowsPerPage) {
- pData = getNewDataBuf(pResultBuf, pMeterQueryInfo->sid, &pageId);
- if (pData != NULL) {
- assert(pData->numOfElems == 0); // number of elements must be 0 for new allocated buffer
- }
- }
+ SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, pWindowResInfo, (char *)&groupIdx, sizeof(groupIdx));
+ if (pWindowRes == NULL) {
+ return;
}
- if (pData == NULL) {
- return -1;
+ /*
+ * not assign result buffer yet, add new result buffer
+ * all group belong to one result set, and each group result has different group id so set the id to be one
+ */
+ if (pWindowRes->pos.pageId == -1) {
+ if (addNewWindowResultBuf(pWindowRes, pRuntimeEnv->pResultBuf, GROUPRESULTID, pRuntimeEnv->numOfRowsPerPage) !=
+ TSDB_CODE_SUCCESS) {
+ return;
+ }
}
- for (int32_t i = 0; i < pRuntimeEnv->pQuery->numOfOutputCols; ++i) {
- pRuntimeEnv->pCtx[i].aOutputBuf = getOutputResPos(pRuntimeEnv, pData, pData->numOfElems, i);
- pRuntimeEnv->pCtx[i].resultInfo = &pMeterQueryInfo->resultInfo[i];
- }
+ setWindowResOutputBuf(pRuntimeEnv, pWindowRes);
+ initCtxOutputBuf(pRuntimeEnv);
- return TSDB_CODE_SUCCESS;
+ pMeterQueryInfo->lastKey = nextKey;
+ setAdditionalInfo(pSupporter, meterIdx, pMeterQueryInfo);
}
-int32_t setIntervalQueryExecutionContext(SMeterQuerySupportObj *pSupporter, int32_t meterIdx,
- SMeterQueryInfo *pMeterQueryInfo) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
+static void setWindowResOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SWindowResult *pResult) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
- if (IS_MASTER_SCAN(pRuntimeEnv)) {
- if (setOutputBufferForIntervalQuery(pSupporter, pMeterQueryInfo) != TSDB_CODE_SUCCESS) {
- // not enough disk space or memory buffer for intermediate results
- return -1;
- }
+ // Note: pResult->pos[i]->numOfElems == 0, there is only fixed number of results for each group
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ SQLFunctionCtx *pCtx = &pRuntimeEnv->pCtx[i];
+ pCtx->aOutputBuf = getPosInResultPage(pRuntimeEnv, i, pResult);
- if (pMeterQueryInfo->lastResRows == 0) {
- initCtxOutputBuf(pRuntimeEnv);
+ int32_t functionId = pQuery->pSelectExpr[i].pBase.functionId;
+ if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) {
+ pCtx->ptsOutputBuf = pRuntimeEnv->pCtx[0].aOutputBuf;
}
- } else {
- if (pMeterQueryInfo->reverseFillRes) {
- setCtxOutputPointerForSupplementScan(pSupporter, pMeterQueryInfo);
- } else {
- /*
- * set output buffer for reverse scan data blocks
- * find the correct output position of existed results during
- *
- * If the master scan does not produce any results, new spaces needed to be allocated during supplement scan
- */
- if (setOutputBufferForIntervalQuery(pSupporter, pMeterQueryInfo) != TSDB_CODE_SUCCESS) {
- return -1;
- }
- }
+ /*
+ * set the output buffer information and intermediate buffer
+ * not all queries require the interResultBuf, such as COUNT
+ */
+ pCtx->resultInfo = &pResult->resultInfo[i];
+
+ // set super table query flag
+ SResultInfo *pResInfo = GET_RES_INFO(pCtx);
+ pResInfo->superTableQ = pRuntimeEnv->stableQuery;
}
+}
+
+int32_t setAdditionalInfo(STableQuerySupportObj *pSupporter, int32_t meterIdx, SMeterQueryInfo *pMeterQueryInfo) {
+ SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
+ assert(pMeterQueryInfo->lastKey > 0);
vnodeSetTagValueInParam(pSupporter->pSidSet, pRuntimeEnv, pSupporter->pMeterSidExtInfo[meterIdx]);
// both the master and supplement scan needs to set the correct ts comp start position
- if (pSupporter->runtimeEnv.pTSBuf != NULL) {
+ if (pRuntimeEnv->pTSBuf != NULL) {
if (pMeterQueryInfo->cur.vnodeIndex == -1) {
pMeterQueryInfo->tag = pRuntimeEnv->pCtx[0].tag.i64Key;
- tsBufGetElemStartPos(pSupporter->runtimeEnv.pTSBuf, 0, pMeterQueryInfo->tag);
+ tsBufGetElemStartPos(pRuntimeEnv->pTSBuf, 0, pMeterQueryInfo->tag);
// keep the cursor info of current meter
- pMeterQueryInfo->cur = pSupporter->runtimeEnv.pTSBuf->cur;
+ pMeterQueryInfo->cur = pRuntimeEnv->pTSBuf->cur;
} else {
- tsBufSetCursor(pSupporter->runtimeEnv.pTSBuf, &pMeterQueryInfo->cur);
+ tsBufSetCursor(pRuntimeEnv->pTSBuf, &pMeterQueryInfo->cur);
}
}
return 0;
}
-//static void doApplyIntervalQueryOnBlock(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo,
-// SBlockInfo *pBlockInfo, int64_t *pPrimaryCol, SField *pFields,
-// __block_search_fn_t searchFn) {
-// SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
-// SQuery * pQuery = pRuntimeEnv->pQuery;
-// int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
-//
-// int64_t nextKey = -1;
-// bool queryCompleted = false;
-//
-// while (1) {
-// int32_t numOfRes = 0;
-// int32_t steps = applyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, pPrimaryCol, pFields, searchFn, &numOfRes);
-// assert(steps > 0);
-//
-// // NOTE: in case of stable query, only ONE(or ZERO) row of pos generated for each query range
-// if (pMeterQueryInfo->lastResRows == 0) {
-// pMeterQueryInfo->lastResRows = numOfRes;
-// } else {
-// assert(pMeterQueryInfo->lastResRows == 1);
-// }
-//
-// int32_t pos = pQuery->pos + steps * factor;
-//
-// // query does not reach the end of current block
-// if ((pos < pBlockInfo->size && QUERY_IS_ASC_QUERY(pQuery)) || (pos >= 0 && !QUERY_IS_ASC_QUERY(pQuery))) {
-// nextKey = pPrimaryCol[pos];
-// } else {
-// assert((pQuery->lastKey > pBlockInfo->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
-// (pQuery->lastKey < pBlockInfo->keyFirst && !QUERY_IS_ASC_QUERY(pQuery)));
-// }
-//
-// // all data satisfy current query are checked, query completed
-// if (QUERY_IS_ASC_QUERY(pQuery)) {
-// queryCompleted = (nextKey > pQuery->ekey || pQuery->ekey <= pBlockInfo->keyLast);
-// } else {
-// queryCompleted = (nextKey < pQuery->ekey || pQuery->ekey >= pBlockInfo->keyFirst);
-// }
-//
-// /*
-// * 1. there may be more date that satisfy current query interval, other than
-// * current block, we need to try next data blocks
-// * 2. query completed, since reaches the upper bound of the main query range
-// */
-// if (QUERY_IS_ASC_QUERY(pQuery)) {
-// if (pQuery->lastKey > pBlockInfo->keyLast || pQuery->lastKey > pSupporter->rawEKey ||
-// nextKey > pSupporter->rawEKey) {
-// /*
-// * current interval query is completed, set query pos flag closed and
-// * try next data block if pQuery->ekey == pSupporter->rawEKey, whole query is completed
-// */
-// if (pQuery->lastKey > pBlockInfo->keyLast) {
-// assert(pQuery->ekey >= pBlockInfo->keyLast);
-// }
-//
-// if (pQuery->lastKey > pSupporter->rawEKey || nextKey > pSupporter->rawEKey) {
-// /* whole query completed, save pos and abort */
-// assert(queryCompleted);
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-//
-// // save the pQuery->lastKey for retrieve data in cache, actually, there will be no qualified data in cache.
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-// } else if (pQuery->ekey == pBlockInfo->keyLast) {
-// /* current interval query is completed, set the next query range on other data blocks if exist */
-// int64_t prevEKey = pQuery->ekey;
-//
-// getAlignedIntervalQueryRange(pRuntimeEnv, pQuery->lastKey, pSupporter->rawSKey, pSupporter->rawEKey);
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-//
-// assert(queryCompleted && prevEKey < pQuery->skey);
-// if (pMeterQueryInfo->lastResRows > 0) {
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-// }
-// } else {
-// /*
-// * Data that satisfy current query range may locate in current block and blocks that are directly right
-// * next to current block. Therefore, we need to keep the query range(interval) unchanged until reaching
-// * the direct next data block, while only forwards the pQuery->lastKey.
-// *
-// * With the information of the directly next data block, whether locates in cache or disk,
-// * current interval query being completed or not can be decided.
-// */
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-// assert(pQuery->lastKey > pBlockInfo->keyLast && pQuery->lastKey <= pQuery->ekey);
-//
-// /*
-// * if current block is the last block of current file, we still close the pos flag, and
-// * merge with other meters in the same group
-// */
-// if (queryCompleted) {
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-// }
-// }
-//
-// break;
-// }
-// } else {
-// if (pQuery->lastKey < pBlockInfo->keyFirst || pQuery->lastKey < pSupporter->rawEKey ||
-// nextKey < pSupporter->rawEKey) {
-// if (pQuery->lastKey < pBlockInfo->keyFirst) {
-// assert(pQuery->ekey <= pBlockInfo->keyFirst);
-// }
-//
-// if (pQuery->lastKey < pSupporter->rawEKey || (nextKey < pSupporter->rawEKey && nextKey != -1)) {
-// /* whole query completed, save pos and abort */
-// assert(queryCompleted);
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-//
-// /*
-// * save the pQuery->lastKey for retrieve data in cache, actually,
-// * there will be no qualified data in cache.
-// */
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-// } else if (pQuery->ekey == pBlockInfo->keyFirst) {
-// // current interval query is completed, set the next query range on other data blocks if exist
-// int64_t prevEKey = pQuery->ekey;
-//
-// getAlignedIntervalQueryRange(pRuntimeEnv, pQuery->lastKey, pSupporter->rawSKey, pSupporter->rawEKey);
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-//
-// assert(queryCompleted && prevEKey > pQuery->skey);
-// if (pMeterQueryInfo->lastResRows > 0) {
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-// }
-// } else {
-// /*
-// * Data that satisfy current query range may locate in current block and blocks that are
-// * directly right next to current block. Therefore, we need to keep the query range(interval)
-// * unchanged until reaching the direct next data block, while only forwards the pQuery->lastKey.
-// *
-// * With the information of the directly next data block, whether locates in cache or disk,
-// * current interval query being completed or not can be decided.
-// */
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-// assert(pQuery->lastKey < pBlockInfo->keyFirst && pQuery->lastKey >= pQuery->ekey);
-//
-// /*
-// * if current block is the last block of current file, we still close the pos
-// * flag, and merge with other meters in the same group
-// */
-// if (queryCompleted) {
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-// }
-// }
-//
-// break;
-// }
-// }
-//
-// assert(queryCompleted);
-// saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-//
-// assert((nextKey >= pQuery->lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
-// (nextKey <= pQuery->lastKey && !QUERY_IS_ASC_QUERY(pQuery)));
-//
-// /* still in the same block to query */
-// getAlignedIntervalQueryRange(pRuntimeEnv, nextKey, pSupporter->rawSKey, pSupporter->rawEKey);
-// saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-//
-// int32_t newPos = searchFn((char *)pPrimaryCol, pBlockInfo->size, pQuery->skey, pQuery->order.order);
-// assert(newPos == pQuery->pos + steps * factor);
-//
-// pQuery->pos = newPos;
-// }
-//}
-
-static void doApplyIntervalQueryOnBlock_rv(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo,
- SBlockInfo *pBlockInfo, int64_t *pPrimaryCol, SField *pFields,
- __block_search_fn_t searchFn) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
- int32_t factor = GET_FORWARD_DIRECTION_FACTOR(pQuery->order.order);
-
- while (1) {
- int64_t nextKey = -1;
- int32_t numOfRes = 0;
-
- int32_t steps = applyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, pPrimaryCol, pFields, searchFn, &numOfRes);
- assert(steps > 0);
-
- // NOTE: in case of stable query, only ONE(or ZERO) row of result generated for each query range
- if (pMeterQueryInfo->lastResRows == 0) {
- pMeterQueryInfo->lastResRows = numOfRes;
- } else {
- assert(pMeterQueryInfo->lastResRows == 1);
- }
-
- int32_t pos = pQuery->pos + steps * factor;
-
- // query does not reach the end of current block
- if ((pos < pBlockInfo->size && QUERY_IS_ASC_QUERY(pQuery)) || (pos >= 0 && !QUERY_IS_ASC_QUERY(pQuery))) {
- nextKey = pPrimaryCol[pos];
- } else {
- assert((pQuery->lastKey > pBlockInfo->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->lastKey < pBlockInfo->keyFirst && !QUERY_IS_ASC_QUERY(pQuery)));
- }
-
- // all data satisfy current query are checked, query completed
- bool completed = false;
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- completed = (pQuery->lastKey > pQuery->ekey);
- } else {
- completed = (pQuery->lastKey < pQuery->ekey);
- }
-
- /*
- * 1. there may be more date that satisfy current query interval, other than
- * current block, we need to try next data blocks
- * 2. query completed, since reaches the upper bound of the main query range
- */
- if (!completed) {
- /*
- * Data that satisfy current query range may locate in current block and blocks that are directly right
- * next to current block. Therefore, we need to keep the query range(interval) unchanged until reaching
- * the direct next data block, while only forwards the pQuery->lastKey.
- *
- * With the information of the directly next data block, whether locates in cache or disk,
- * current interval query being completed or not can be decided.
- */
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-
- if (QUERY_IS_ASC_QUERY(pQuery)) {
- assert(pQuery->lastKey > pBlockInfo->keyLast && pQuery->lastKey <= pQuery->ekey);
- } else {
- assert(pQuery->lastKey < pBlockInfo->keyFirst && pQuery->lastKey >= pQuery->ekey);
- }
-
- break;
- }
-
- assert(completed);
-
- // while the interval time window is less than the time range gap between two points, nextKey may be greater than
- // pSupporter->rawEKey
- if (pQuery->ekey == pSupporter->rawEKey || (nextKey > pSupporter->rawEKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (nextKey < pSupporter->rawEKey && !QUERY_IS_ASC_QUERY(pQuery))) {
- /* whole query completed, save result and abort */
- saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-
- // save the pQuery->lastKey for retrieve data in cache, actually, there will be no qualified data in cache.
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-
- return;
- } else if ((QUERY_IS_ASC_QUERY(pQuery) && pQuery->ekey == pBlockInfo->keyLast) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && pQuery->ekey == pBlockInfo->keyFirst)) {
- /* current interval query is completed, set the next query range on other data blocks if exist */
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
- return;
- }
-
- saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
-
- assert(pos >= 0 && pos < pBlockInfo->size);
- assert((nextKey >= pQuery->lastKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (nextKey <= pQuery->lastKey && !QUERY_IS_ASC_QUERY(pQuery)));
-
- /* still in the same block to query */
- getAlignedIntervalQueryRange(pRuntimeEnv, nextKey, pSupporter->rawSKey, pSupporter->rawEKey);
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-
- int32_t newPos = searchFn((char *)pPrimaryCol, pBlockInfo->size, pQuery->skey, pQuery->order.order);
- assert(newPos == pQuery->pos + steps * factor);
-
- pQuery->pos = newPos;
- }
-
-}
-int64_t getNextAccessedKeyInData(SQuery *pQuery, int64_t *pPrimaryCol, SBlockInfo *pBlockInfo, int32_t blockStatus) {
- assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->size - 1);
-
- TSKEY key = -1;
- if (IS_DATA_BLOCK_LOADED(blockStatus)) {
- key = pPrimaryCol[pQuery->pos];
- } else {
- assert(pQuery->pos == pBlockInfo->size - 1 || pQuery->pos == 0);
- key = QUERY_IS_ASC_QUERY(pQuery) ? pBlockInfo->keyFirst : pBlockInfo->keyLast;
- }
-
- assert((key >= pQuery->skey && QUERY_IS_ASC_QUERY(pQuery)) || (key <= pQuery->skey && !QUERY_IS_ASC_QUERY(pQuery)));
- return key;
-}
-
/*
* There are two cases to handle:
*
@@ -7322,42 +7120,61 @@ int64_t getNextAccessedKeyInData(SQuery *pQuery, int64_t *pPrimaryCol, SBlockInf
* merged during merge stage. In this case, we need the pMeterQueryInfo->lastResRows to decide if there
* is a previous result generated or not.
*/
-void setIntervalQueryRange(SMeterQueryInfo *pMeterQueryInfo, SMeterQuerySupportObj *pSupporter, TSKEY key) {
+void setIntervalQueryRange(SMeterQueryInfo *pMeterQueryInfo, STableQuerySupportObj *pSupporter, TSKEY key) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
if (pMeterQueryInfo->queryRangeSet) {
- assert((QUERY_IS_ASC_QUERY(pQuery) && pQuery->lastKey >= pQuery->skey) ||
- (!QUERY_IS_ASC_QUERY(pQuery) && pQuery->lastKey <= pQuery->skey));
-
- if ((pQuery->ekey < key && QUERY_IS_ASC_QUERY(pQuery)) || (pQuery->ekey > key && !QUERY_IS_ASC_QUERY(pQuery))) {
- /*
- * last query on this block of the meter is done, start next interval on this block
- * otherwise, keep the previous query range and proceed
- */
- getAlignedIntervalQueryRange(pRuntimeEnv, key, pSupporter->rawSKey, pSupporter->rawEKey);
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
-
- // previous query does not be closed, save the results and close it
- if (pMeterQueryInfo->lastResRows > 0) {
- saveResult(pSupporter, pMeterQueryInfo, pMeterQueryInfo->lastResRows);
- }
- } else {
- /* current query not completed, continue. do nothing with respect to query range, */
- }
+ pQuery->lastKey = key;
+ pMeterQueryInfo->lastKey = key;
} else {
pQuery->skey = key;
- assert(pMeterQueryInfo->lastResRows == 0);
+ STimeWindow win = {.skey = key, pSupporter->rawEKey};
+ // for too small query range, no data in this interval.
if ((QUERY_IS_ASC_QUERY(pQuery) && (pQuery->ekey < pQuery->skey)) ||
(!QUERY_IS_ASC_QUERY(pQuery) && (pQuery->skey < pQuery->ekey))) {
- // for too small query range, no data in this interval.
return;
}
- getAlignedIntervalQueryRange(pRuntimeEnv, pQuery->skey, pSupporter->rawSKey, pSupporter->rawEKey);
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
+ /**
+ * In handling the both ascending and descending order super table query, we need to find the first qualified
+ * timestamp of this table, and then set the first qualified start timestamp.
+ * In ascending query, key is the first qualified timestamp. However, in the descending order query, additional
+ * operations involve.
+ */
+ if (!QUERY_IS_ASC_QUERY(pQuery)) {
+ TSKEY k = getGreaterEqualTimestamp(pRuntimeEnv);
+ win.skey = k;
+ win.ekey = key; // current key is the last timestamp value that are contained in query time window
+
+ SPositionInfo p = {.fileId = pQuery->fileId, .slot = pQuery->slot, .pos = pQuery->pos};
+ loadRequiredBlockIntoMem(pRuntimeEnv, &p);
+ }
+
+ TSKEY skey1, ekey1;
+ TSKEY windowSKey = 0, windowEKey = 0;
+
+ SWindowResInfo *pWindowResInfo = &pMeterQueryInfo->windowResInfo;
+
+ doGetAlignedIntervalQueryRangeImpl(pQuery, win.skey, win.skey, win.ekey, &skey1, &ekey1, &windowSKey, &windowEKey);
+ pWindowResInfo->startTime = windowSKey; // windowSKey may be 0 in case of 1970 timestamp
+ // assert(pWindowResInfo->startTime > 0);
+
+ if (pWindowResInfo->prevSKey == 0) {
+ if (QUERY_IS_ASC_QUERY(pQuery)) {
+ pWindowResInfo->prevSKey = windowSKey;
+ } else {
+ assert(win.ekey == pQuery->skey);
+ pWindowResInfo->prevSKey = windowSKey + ((win.ekey - windowSKey) / pQuery->slidingTime) * pQuery->slidingTime;
+ }
+ }
+
pMeterQueryInfo->queryRangeSet = 1;
+ pMeterQueryInfo->lastKey = pQuery->skey;
+ pMeterQueryInfo->skey = pQuery->skey;
+
+ pQuery->lastKey = pQuery->skey;
}
}
@@ -7415,7 +7232,7 @@ int32_t LoadDatablockOnDemand(SCompBlock *pBlock, SField **pFields, uint8_t *blk
if (((pQuery->lastKey <= pBlock->keyFirst && pQuery->ekey >= pBlock->keyLast && QUERY_IS_ASC_QUERY(pQuery)) ||
(pQuery->ekey <= pBlock->keyFirst && pQuery->lastKey >= pBlock->keyLast && !QUERY_IS_ASC_QUERY(pQuery))) &&
onDemand) {
- int32_t req = 0;
+ uint32_t req = 0;
if (pQuery->numOfFilterCols > 0) {
req = BLK_DATA_ALL_NEEDED;
} else {
@@ -7425,7 +7242,7 @@ int32_t LoadDatablockOnDemand(SCompBlock *pBlock, SField **pFields, uint8_t *blk
pQuery->pSelectExpr[i].pBase.colInfo.colId, *blkStatus);
}
- if (pRuntimeEnv->pTSBuf > 0 || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
+ if (pRuntimeEnv->pTSBuf > 0 || isIntervalQuery(pQuery)) {
req |= BLK_DATA_ALL_NEEDED;
}
}
@@ -7487,9 +7304,8 @@ int32_t LoadDatablockOnDemand(SCompBlock *pBlock, SField **pFields, uint8_t *blk
/* find first qualified record position in this block */
if (loadTS) {
- /* find first qualified record position in this block */
- pQuery->pos =
- searchFn(pRuntimeEnv->primaryColBuffer->data, pBlock->numOfPoints, pQuery->lastKey, pQuery->order.order);
+ pQuery->pos = searchFn((char *)primaryKeys, pBlock->numOfPoints, pQuery->lastKey, pQuery->order.order);
+
/* boundary timestamp check */
assert(pBlock->keyFirst == primaryKeys[0] && pBlock->keyLast == primaryKeys[pBlock->numOfPoints - 1]);
}
@@ -7509,121 +7325,15 @@ int32_t LoadDatablockOnDemand(SCompBlock *pBlock, SField **pFields, uint8_t *blk
}
bool onDemandLoadDatablock(SQuery *pQuery, int16_t queryRangeSet) {
- return (pQuery->nAggTimeInterval == 0) || ((queryRangeSet == 1) && (pQuery->nAggTimeInterval > 0));
-}
-
-static void validateResultBuf(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pSupporter->runtimeEnv.pQuery;
- SQueryResultBuf* pResultBuf = pRuntimeEnv->pResultBuf;
-
- SIDList list = getDataBufPagesIdList(pResultBuf, pMeterQueryInfo->sid);
- int32_t id = getLastPageId(&list);
-
- tFilePage* newOutput = getResultBufferPageById(pResultBuf, id);
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- assert(pRuntimeEnv->pCtx[i].aOutputBuf - newOutput->data < DEFAULT_INTERN_BUF_SIZE);
- }
-}
-
-int32_t saveResult(SMeterQuerySupportObj *pSupporter, SMeterQueryInfo *pMeterQueryInfo, int32_t numOfResult) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
-
- // no results generated, do nothing for master scan
- if (numOfResult <= 0) {
- if (IS_MASTER_SCAN(pRuntimeEnv)) {
- return TSDB_CODE_SUCCESS;
- } else {
- /*
- * There is a case that no result generated during the the supplement scan, and during the main
- * scan also no result generated. The index can be backwards moved.
- *
- * However, if during the main scan, there is a result generated, such as applies count to timestamp, which
- * always generates a result, but applies last query to a NULL column may fail to generate results during the
- * supplement scan.
- *
- * NOTE:
- * nStartQueryTimestamp is the actually timestamp of current interval, if the actually interval timestamp
- * equals to the recorded timestamp that is acquired during the master scan, backwards one step even
- * there is no results during the supplementary scan.
- */
- TSKEY ts = *(TSKEY *)pRuntimeEnv->pCtx[0].aOutputBuf;
- if (ts == pRuntimeEnv->pCtx[0].nStartQueryTimestamp && pMeterQueryInfo->reverseIndex > 0) {
- assert(pMeterQueryInfo->numOfRes >= 0 && pMeterQueryInfo->reverseIndex > 0 &&
- pMeterQueryInfo->reverseIndex <= pMeterQueryInfo->numOfRes);
-
- // backward one step from the previous position, the start position is (pMeterQueryInfo->numOfRows-1);
- pMeterQueryInfo->reverseIndex -= 1;
- setCtxOutputPointerForSupplementScan(pSupporter, pMeterQueryInfo);
- }
-
- return TSDB_CODE_SUCCESS;
- }
- }
-
- assert(pMeterQueryInfo->lastResRows == 1);
- numOfResult = 1;
- pMeterQueryInfo->lastResRows = 0;
-
- if (IS_SUPPLEMENT_SCAN(pRuntimeEnv) && pMeterQueryInfo->reverseFillRes == 1) {
- assert(pMeterQueryInfo->numOfRes > 0 && pMeterQueryInfo->reverseIndex > 0 &&
- pMeterQueryInfo->reverseIndex <= pMeterQueryInfo->numOfRes);
- // backward one step from the previous position, the start position is (pMeterQueryInfo->numOfRows-1);
- pMeterQueryInfo->reverseIndex -= 1;
- setCtxOutputPointerForSupplementScan(pSupporter, pMeterQueryInfo);
- } else {
- SIDList list = getDataBufPagesIdList(pRuntimeEnv->pResultBuf, pMeterQueryInfo->sid);
-
- int32_t pageId = getLastPageId(&list);
- tFilePage* pData = getResultBufferPageById(pRuntimeEnv->pResultBuf, pageId);
-
- // in handling records occuring around '1970-01-01', the aligned start timestamp may be 0.
- TSKEY ts = *(TSKEY *)getOutputResPos(pRuntimeEnv, pData, pData->numOfElems, 0);
-
- SMeterObj *pMeterObj = pRuntimeEnv->pMeterObj;
- qTrace("QInfo:%p vid:%d sid:%d id:%s, save results, ts:%" PRId64 ", total:%d", GET_QINFO_ADDR(pQuery),
- pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, ts, pMeterQueryInfo->numOfRes + 1);
-
- pData->numOfElems += numOfResult;
- pMeterQueryInfo->numOfRes += numOfResult;
- assert(pData->numOfElems <= pRuntimeEnv->numOfRowsPerPage);
-
- if (setOutputBufferForIntervalQuery(pSupporter, pMeterQueryInfo) != TSDB_CODE_SUCCESS) {
- return -1;
- }
-
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- resetResultInfo(&pMeterQueryInfo->resultInfo[i]);
- }
-
- validateResultBuf(pSupporter, pMeterQueryInfo);
- initCtxOutputBuf(pRuntimeEnv);
-#if 0
- SSchema sc[TSDB_MAX_COLUMNS] = {0};
- sc[0].type = TSDB_DATA_TYPE_BIGINT;
- sc[0].bytes = 8;
-
- sc[1].type = TSDB_DATA_TYPE_BIGINT;
- sc[1].bytes = 8;
-
- UNUSED(sc);
- SColumnModel *cm = createColumnModel(sc, pQuery->numOfOutputCols, pRuntimeEnv->numOfRowsPerPage);
-
-// if (outputPage->numOfElems + numOfResult >= pRuntimeEnv->numOfRowsPerPage)
- tColModelDisplay(cm, outputPage->data, outputPage->numOfElems, pRuntimeEnv->numOfRowsPerPage);
-#endif
- }
-
- return TSDB_CODE_SUCCESS;
+ return (pQuery->intervalTime == 0) || ((queryRangeSet == 1) && (isIntervalQuery(pQuery)));
}
-static int32_t getNumOfSubset(SMeterQuerySupportObj *pSupporter) {
+static int32_t getNumOfSubset(STableQuerySupportObj *pSupporter) {
SQuery *pQuery = pSupporter->runtimeEnv.pQuery;
int32_t totalSubset = 0;
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->nAggTimeInterval > 0 && pQuery->slidingTime > 0)) {
- totalSubset = numOfClosedSlidingWindow(&pSupporter->runtimeEnv.swindowResInfo);
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (isIntervalQuery(pQuery))) {
+ totalSubset = numOfClosedTimeWindow(&pSupporter->runtimeEnv.windowResInfo);
} else {
totalSubset = pSupporter->pSidSet->numOfSubSet;
}
@@ -7631,26 +7341,26 @@ static int32_t getNumOfSubset(SMeterQuerySupportObj *pSupporter) {
return totalSubset;
}
-static int32_t doCopyFromGroupBuf(SMeterQuerySupportObj *pSupporter, SOutputRes *result, int32_t orderType) {
+static int32_t doCopyToSData(STableQuerySupportObj *pSupporter, SWindowResult *result, int32_t orderType) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
int32_t numOfResult = 0;
int32_t startIdx = 0;
- int32_t forward = 1;
-
- dTrace("QInfo:%p start to copy data to dest buf", GET_QINFO_ADDR(pSupporter->runtimeEnv.pQuery));
+ int32_t step = -1;
+ dTrace("QInfo:%p start to copy data from windowResInfo to pQuery buf", GET_QINFO_ADDR(pQuery));
int32_t totalSubset = getNumOfSubset(pSupporter);
if (orderType == TSQL_SO_ASC) {
startIdx = pSupporter->subgroupIdx;
- } else { // desc
+ step = 1;
+ } else { // desc order copy all data
startIdx = totalSubset - pSupporter->subgroupIdx - 1;
- forward = -1;
+ step = -1;
}
- for (int32_t i = startIdx; (i < totalSubset) && (i >= 0); i += forward) {
+ for (int32_t i = startIdx; (i < totalSubset) && (i >= 0); i += step) {
if (result[i].numOfRows == 0) {
pSupporter->offset = 0;
pSupporter->subgroupIdx += 1;
@@ -7662,8 +7372,11 @@ static int32_t doCopyFromGroupBuf(SMeterQuerySupportObj *pSupporter, SOutputRes
int32_t numOfRowsToCopy = result[i].numOfRows - pSupporter->offset;
int32_t oldOffset = pSupporter->offset;
+ /*
+ * 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
+ */
if (numOfRowsToCopy > pQuery->pointsToRead - numOfResult) {
- // current output space is not enough for the keep the data of this group
numOfRowsToCopy = pQuery->pointsToRead - numOfResult;
pSupporter->offset += numOfRowsToCopy;
} else {
@@ -7672,10 +7385,11 @@ static int32_t doCopyFromGroupBuf(SMeterQuerySupportObj *pSupporter, SOutputRes
}
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
- int32_t elemSize = pRuntimeEnv->pCtx[j].outputBytes;
- char * outputBuf = pQuery->sdata[j]->data + numOfResult * elemSize;
- char* p = getPosInResultPage(pRuntimeEnv, j, &result[i]);
- memcpy(outputBuf, p + oldOffset * elemSize, elemSize * numOfRowsToCopy);
+ int32_t size = pRuntimeEnv->pCtx[j].outputBytes;
+
+ char *out = pQuery->sdata[j]->data + numOfResult * size;
+ char *in = getPosInResultPage(pRuntimeEnv, j, &result[i]);
+ memcpy(out, in + oldOffset * size, size * numOfRowsToCopy);
}
numOfResult += numOfRowsToCopy;
@@ -7684,7 +7398,7 @@ static int32_t doCopyFromGroupBuf(SMeterQuerySupportObj *pSupporter, SOutputRes
}
}
- dTrace("QInfo:%p done copy data to dst buf", GET_QINFO_ADDR(pSupporter->runtimeEnv.pQuery));
+ dTrace("QInfo:%p copy data to SQuery buf completed", GET_QINFO_ADDR(pQuery));
#ifdef _DEBUG_VIEW
displayInterResult(pQuery->sdata, pQuery, numOfResult);
@@ -7693,58 +7407,63 @@ static int32_t doCopyFromGroupBuf(SMeterQuerySupportObj *pSupporter, SOutputRes
}
/**
- * copyFromGroupBuf support copy data in ascending/descending order
+ * copyFromWindowResToSData support copy data in ascending/descending order
+ * For interval query of both super table and table, copy the data in ascending order, since the output results are
+ * ordered in SWindowResutl already. While handling the group by query for both table and super table,
+ * all group result are completed already.
+ *
* @param pQInfo
* @param result
*/
-void copyFromGroupBuf(SQInfo *pQInfo, SOutputRes *result) {
+void copyFromWindowResToSData(SQInfo *pQInfo, SWindowResult *result) {
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
int32_t orderType = (pQuery->pGroupbyExpr != NULL) ? pQuery->pGroupbyExpr->orderType : TSQL_SO_ASC;
- int32_t numOfResult = doCopyFromGroupBuf(pSupporter, result, orderType);
+ int32_t numOfResult = doCopyToSData(pSupporter, result, orderType);
pQuery->pointsRead += numOfResult;
assert(pQuery->pointsRead <= pQuery->pointsToRead);
}
-static void applyIntervalQueryOnBlock(SMeterQuerySupportObj *pSupporter, SMeterDataInfo *pMeterDataInfo,
- SBlockInfo *pBlockInfo, int32_t blockStatus, SField *pFields,
- __block_search_fn_t searchFn) {
- SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
- SQuery * pQuery = pRuntimeEnv->pQuery;
- SMeterQueryInfo * pMeterQueryInfo = pMeterDataInfo->pMeterQInfo;
+static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv, SMeterDataInfo *pMeterDataInfo) {
+ SQuery *pQuery = pRuntimeEnv->pQuery;
- int64_t* pPrimaryKey = (int64_t*) pRuntimeEnv->primaryColBuffer->data;
- /*
- * for each block, we need to handle the previous query, since the determination of previous query being completed
- * or not is based on the start key of current block.
- */
- TSKEY key = getNextAccessedKeyInData(pQuery, pPrimaryKey, pBlockInfo, blockStatus);
- setIntervalQueryRange(pMeterDataInfo->pMeterQInfo, pSupporter, key);
+ // update the number of result for each, only update the number of rows for the corresponding window result.
+ if (pQuery->intervalTime == 0) {
+ int32_t g = pMeterDataInfo->groupIdx;
+ assert(pRuntimeEnv->windowResInfo.size > 0);
- if (((pQuery->skey > pQuery->ekey) && QUERY_IS_ASC_QUERY(pQuery)) ||
- ((pQuery->skey < pQuery->ekey) && !QUERY_IS_ASC_QUERY(pQuery))) {
- return;
+ SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&g, sizeof(g));
+ if (pWindowRes->numOfRows == 0) {
+ pWindowRes->numOfRows = getNumOfResult(pRuntimeEnv);
+ }
}
+}
+
+void stableApplyFunctionsOnBlock(STableQuerySupportObj *pSupporter, SMeterDataInfo *pMeterDataInfo,
+ SBlockInfo *pBlockInfo, SField *pFields, __block_search_fn_t searchFn) {
+ SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
+ SQuery * pQuery = pRuntimeEnv->pQuery;
+ SMeterQueryInfo * pMeterQueryInfo = pMeterDataInfo->pMeterQInfo;
+ SWindowResInfo * pWindowResInfo = &pMeterQueryInfo->windowResInfo;
- if (((pBlockInfo->keyLast < pQuery->ekey) && QUERY_IS_ASC_QUERY(pQuery)) ||
- ((pBlockInfo->keyFirst > pQuery->ekey) && !QUERY_IS_ASC_QUERY(pQuery))) {
- int32_t numOfRes = 0;
- /* current block is included in this interval */
- int32_t steps = applyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, pPrimaryKey, pFields, searchFn, &numOfRes);
- assert(numOfRes <= 1 && numOfRes >= 0 && steps > 0);
+ int64_t *pPrimaryKey = (int64_t *)pRuntimeEnv->primaryColBuffer->data;
- if (pMeterQueryInfo->lastResRows == 0) {
- pMeterQueryInfo->lastResRows = numOfRes;
- } else {
- assert(pMeterQueryInfo->lastResRows == 1);
- }
+ int32_t forwardStep =
+ getNumOfRowsInTimeWindow(pQuery, pBlockInfo, pPrimaryKey, pQuery->pos, pQuery->ekey, searchFn, true);
- saveIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
+ int32_t numOfRes = 0;
+ if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL) {
+ numOfRes = rowwiseApplyAllFunctions(pRuntimeEnv, &forwardStep, pFields, pBlockInfo, pWindowResInfo);
} else {
- doApplyIntervalQueryOnBlock_rv(pSupporter, pMeterQueryInfo, pBlockInfo, pPrimaryKey, pFields, searchFn);
+ numOfRes = blockwiseApplyAllFunctions(pRuntimeEnv, forwardStep, pFields, pBlockInfo, pWindowResInfo, searchFn);
}
+
+ assert(numOfRes >= 0);
+
+ updateWindowResNumOfRes(pRuntimeEnv, pMeterDataInfo);
+ updatelastkey(pQuery, pMeterQueryInfo);
}
// we need to split the refstatsult into different packages.
@@ -7758,7 +7477,7 @@ int32_t vnodeGetResultSize(void *thandle, int32_t *numOfRows) {
*
* TODO handle the case that the file is too large to send back one time
*/
- if (pQInfo->pMeterQuerySupporter != NULL && isTSCompQuery(pQuery) && (*numOfRows) > 0) {
+ if (pQInfo->pTableQuerySupporter != NULL && isTSCompQuery(pQuery) && (*numOfRows) > 0) {
struct stat fstat;
if (stat(pQuery->sdata[0]->data, &fstat) == 0) {
*numOfRows = fstat.st_size;
@@ -7779,7 +7498,7 @@ int64_t vnodeGetOffsetVal(void *thandle) {
bool vnodeHasRemainResults(void *handle) {
SQInfo * pQInfo = (SQInfo *)handle;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
if (pSupporter == NULL || pQInfo->query.interpoType == TSDB_INTERPO_NONE) {
return false;
@@ -7803,10 +7522,10 @@ bool vnodeHasRemainResults(void *handle) {
// query has completed
if (Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED | QUERY_NO_DATA_TO_CHECK)) {
- TSKEY ekey = taosGetRevisedEndKey(pSupporter->rawEKey, pQuery->order.order, pQuery->nAggTimeInterval,
+ TSKEY ekey = taosGetRevisedEndKey(pSupporter->rawEKey, pQuery->order.order, pQuery->intervalTime,
pQuery->intervalTimeUnit, pQuery->precision);
int32_t numOfTotal = taosGetNumOfResultWithInterpo(pInterpoInfo, (TSKEY *)pRuntimeEnv->pInterpoBuf[0]->data,
- remain, pQuery->nAggTimeInterval, ekey, pQuery->pointsToRead);
+ remain, pQuery->intervalTime, ekey, pQuery->pointsToRead);
return numOfTotal > 0;
}
@@ -7817,7 +7536,7 @@ bool vnodeHasRemainResults(void *handle) {
static int32_t resultInterpolate(SQInfo *pQInfo, tFilePage **data, tFilePage **pDataSrc, int32_t numOfRows,
int32_t outputRows) {
SQuery * pQuery = &pQInfo->query;
- SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pMeterQuerySupporter->runtimeEnv;
+ SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pTableQuerySupporter->runtimeEnv;
assert(pRuntimeEnv->pCtx[0].outputBytes == TSDB_KEYSIZE);
@@ -7839,7 +7558,7 @@ static int32_t resultInterpolate(SQInfo *pQInfo, tFilePage **data, tFilePage **p
}
int32_t numOfRes = taosDoInterpoResult(&pRuntimeEnv->interpoInfo, pQuery->interpoType, data, numOfRows, outputRows,
- pQuery->nAggTimeInterval, (int64_t *)pDataSrc[0]->data, pModel, srcData,
+ pQuery->intervalTime, (int64_t *)pDataSrc[0]->data, pModel, srcData,
pQuery->defaultVal, functions, pRuntimeEnv->pMeterObj->pointsPerFileBlock);
destroyColumnModel(pModel);
@@ -7907,18 +7626,17 @@ int32_t vnodeCopyQueryResultToMsg(void *handle, char *data, int32_t numOfRows) {
int32_t vnodeQueryResultInterpolate(SQInfo *pQInfo, tFilePage **pDst, tFilePage **pDataSrc, int32_t numOfRows,
int32_t *numOfInterpo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = pRuntimeEnv->pQuery;
while (1) {
numOfRows = taosNumOfRemainPoints(&pRuntimeEnv->interpoInfo);
- TSKEY ekey = taosGetRevisedEndKey(pSupporter->rawEKey, pQuery->order.order, pQuery->nAggTimeInterval,
+ TSKEY ekey = taosGetRevisedEndKey(pSupporter->rawEKey, pQuery->order.order, pQuery->intervalTime,
pQuery->intervalTimeUnit, pQuery->precision);
- int32_t numOfFinalRows =
- taosGetNumOfResultWithInterpo(&pRuntimeEnv->interpoInfo, (TSKEY *)pDataSrc[0]->data, numOfRows,
- pQuery->nAggTimeInterval, ekey, pQuery->pointsToRead);
+ int32_t numOfFinalRows = taosGetNumOfResultWithInterpo(&pRuntimeEnv->interpoInfo, (TSKEY *)pDataSrc[0]->data,
+ numOfRows, pQuery->intervalTime, ekey, pQuery->pointsToRead);
int32_t ret = resultInterpolate(pQInfo, pDst, pDataSrc, numOfRows, numOfFinalRows);
assert(ret == numOfFinalRows);
@@ -7949,7 +7667,7 @@ int32_t vnodeQueryResultInterpolate(SQInfo *pQInfo, tFilePage **pDst, tFilePage
}
}
-void vnodePrintQueryStatistics(SMeterQuerySupportObj *pSupporter) {
+void vnodePrintQueryStatistics(STableQuerySupportObj *pSupporter) {
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery *pQuery = pRuntimeEnv->pQuery;
diff --git a/src/vnode/detail/src/vnodeQueryProcess.c b/src/vnode/detail/src/vnodeQueryProcess.c
index c243a78e837cbc0f1ad60d83a7786da3aae54d3a..ae51365918b142e392dcffa27a6b071543f3d02e 100644
--- a/src/vnode/detail/src/vnodeQueryProcess.c
+++ b/src/vnode/detail/src/vnodeQueryProcess.c
@@ -26,8 +26,9 @@
#include "vnodeQueryImpl.h"
-#define ALL_CACHE_BLOCKS_CHECKED(q) \
- (((q)->slot == (q)->currentSlot && QUERY_IS_ASC_QUERY(q)) || ((q)->slot == (q)->firstSlot && (!QUERY_IS_ASC_QUERY(q))))
+#define ALL_CACHE_BLOCKS_CHECKED(q) \
+ (((q)->slot == (q)->currentSlot && QUERY_IS_ASC_QUERY(q)) || \
+ ((q)->slot == (q)->firstSlot && (!QUERY_IS_ASC_QUERY(q))))
#define FORWARD_CACHE_BLOCK_CHECK_SLOT(slot, step, maxblocks) (slot) = ((slot) + (step) + (maxblocks)) % (maxblocks);
@@ -47,23 +48,10 @@ static bool isGroupbyEachTable(SSqlGroupbyExpr *pGroupbyExpr, tSidSet *pSidset)
return false;
}
-static bool doCheckWithPrevQueryRange(SQInfo *pQInfo, TSKEY nextKey, SMeterDataInfo *pMeterInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
- SQuery * pQuery = &pQInfo->query;
- SMeterObj * pMeterObj = pMeterInfo->pMeterObj;
-
- /* no data for current query */
+static bool doCheckWithPrevQueryRange(SQuery *pQuery, TSKEY nextKey) {
if ((nextKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(nextKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- if (((nextKey > pSupporter->rawEKey) && QUERY_IS_ASC_QUERY(pQuery)) ||
- ((nextKey < pSupporter->rawEKey) && (!QUERY_IS_ASC_QUERY(pQuery)))) {
- dTrace("QInfo:%p vid:%d sid:%d id:%s, no data qualified in block, ignore", pQInfo, pMeterObj->vnode,
- pMeterObj->sid, pMeterObj->meterId);
-
- return false;
- } else { // in case of interval query, forward the query range
- setIntervalQueryRange(pMeterInfo->pMeterQInfo, pSupporter, nextKey);
- }
+ return false;
}
return true;
@@ -86,8 +74,8 @@ static void setStartPositionForCacheBlock(SQuery *pQuery, SCacheBlock *pBlock, b
}
static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) {
- SQuery* pQuery = pRuntimeEnv->pQuery;
-
+ SQuery *pQuery = pRuntimeEnv->pQuery;
+
for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
SResultInfo *pResInfo = GET_RES_INFO(&pRuntimeEnv->pCtx[i]);
if (pResInfo != NULL) {
@@ -96,10 +84,10 @@ static void enableExecutionForNextTable(SQueryRuntimeEnv *pRuntimeEnv) {
}
}
-static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
+static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo) {
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
- SQueryRuntimeEnv * pRuntimeEnv = &pQInfo->pMeterQuerySupporter->runtimeEnv;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
+ SQueryRuntimeEnv * pRuntimeEnv = &pQInfo->pTableQuerySupporter->runtimeEnv;
SMeterSidExtInfo **pMeterSidExtInfo = pSupporter->pMeterSidExtInfo;
@@ -131,17 +119,18 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
pQInfo->pObj = pMeterObj;
pRuntimeEnv->pMeterObj = pMeterObj;
- if (pMeterInfo[k].pMeterQInfo == NULL) {
- pMeterInfo[k].pMeterQInfo = createMeterQueryInfo(pQuery, pMeterObj->sid, pSupporter->rawSKey, pSupporter->rawEKey);
+ if (pMeterDataInfo[k].pMeterQInfo == NULL) {
+ pMeterDataInfo[k].pMeterQInfo =
+ createMeterQueryInfo(pSupporter, pMeterObj->sid, pSupporter->rawSKey, pSupporter->rawEKey);
}
- if (pMeterInfo[k].pMeterObj == NULL) { // no data in disk for this meter, set its pointer
- setMeterDataInfo(&pMeterInfo[k], pMeterObj, k, groupIdx);
+ if (pMeterDataInfo[k].pMeterObj == NULL) { // no data in disk for this meter, set its pointer
+ setMeterDataInfo(&pMeterDataInfo[k], pMeterObj, k, groupIdx);
}
- assert(pMeterInfo[k].meterOrderIdx == k && pMeterObj == pMeterInfo[k].pMeterObj);
+ assert(pMeterDataInfo[k].meterOrderIdx == k && pMeterObj == pMeterDataInfo[k].pMeterObj);
- SMeterQueryInfo *pMeterQueryInfo = pMeterInfo[k].pMeterQInfo;
+ SMeterQueryInfo *pMeterQueryInfo = pMeterDataInfo[k].pMeterQInfo;
restoreIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
/*
@@ -154,29 +143,18 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
vnodeUpdateQueryColumnIndex(pQuery, pMeterObj);
vnodeUpdateFilterColumnIndex(pQuery);
- if (pQuery->nAggTimeInterval == 0) {
- if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- dTrace(
- "QInfo:%p vid:%d sid:%d id:%s, query completed, ignore data in cache. qrange:%" PRId64 "-%" PRId64 ", "
- "lastKey:%" PRId64,
- pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey,
- pQuery->lastKey);
-
- continue;
- }
+ if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ dTrace("QInfo:%p vid:%d sid:%d id:%s, query completed, ignore data in cache. qrange:%" PRId64 "-%" PRId64
+ ", lastKey:%" PRId64,
+ pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey,
+ pQuery->lastKey);
- setExecutionContext(pSupporter, pSupporter->pResult, k, pMeterInfo[k].groupIdx, pMeterQueryInfo);
- } else {
- int32_t ret = setIntervalQueryExecutionContext(pSupporter, k, pMeterQueryInfo);
- if (ret != TSDB_CODE_SUCCESS) {
- pQInfo->killed = 1;
- return;
- }
+ continue;
}
- qTrace("QInfo:%p vid:%d sid:%d id:%s, query in cache, qrange:%" PRId64 "-%" PRId64 ", lastKey:%" PRId64, pQInfo, pMeterObj->vnode,
- pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey, pQuery->lastKey);
+ qTrace("QInfo:%p vid:%d sid:%d id:%s, query in cache, qrange:%" PRId64 "-%" PRId64 ", lastKey:%" PRId64, pQInfo,
+ pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey, pQuery->lastKey);
/*
* find the appropriated start position in cache
@@ -186,7 +164,7 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
* should be ignored (the fourth parameter).
*/
TSKEY nextKey = getQueryStartPositionInCache(pRuntimeEnv, &pQuery->slot, &pQuery->pos, true);
- if (nextKey < 0) {
+ if (nextKey < 0 || !doCheckWithPrevQueryRange(pQuery, nextKey)) {
qTrace("QInfo:%p vid:%d sid:%d id:%s, no data qualified in cache, cache blocks:%d, lastKey:%" PRId64, pQInfo,
pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->numOfBlocks, pQuery->lastKey);
continue;
@@ -199,10 +177,6 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
continue;
}
- if (!doCheckWithPrevQueryRange(pQInfo, nextKey, &pMeterInfo[k])) {
- continue;
- }
-
bool firstCheckSlot = true;
SCacheInfo *pCacheInfo = (SCacheInfo *)pMeterObj->pCache;
@@ -224,24 +198,39 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
setStartPositionForCacheBlock(pQuery, pBlock, &firstCheckSlot);
- TSKEY* primaryKeys = (TSKEY*) pRuntimeEnv->primaryColBuffer->data;
-
+ TSKEY *primaryKeys = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
+ TSKEY key = primaryKeys[pQuery->pos];
+
// in handling file data block, the timestamp range validation is done during fetching candidate file blocks
- if ((primaryKeys[pQuery->pos] > pSupporter->rawEKey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (primaryKeys[pQuery->pos] < pSupporter->rawEKey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ if ((key > pSupporter->rawEKey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (key < pSupporter->rawEKey && !QUERY_IS_ASC_QUERY(pQuery))) {
break;
}
+ if (pQuery->intervalTime == 0) {
+ setExecutionContext(pSupporter, pMeterQueryInfo, k, pMeterDataInfo[k].groupIdx, key);
+ } else {
+ setIntervalQueryRange(pMeterQueryInfo, pSupporter, key);
+ int32_t ret = setAdditionalInfo(pSupporter, k, pMeterQueryInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ pQInfo->killed = 1;
+ return;
+ }
+ }
+
+ qTrace("QInfo:%p vid:%d sid:%d id:%s, query in cache, qrange:%" PRId64 "-%" PRId64 ", lastKey:%" PRId64, pQInfo,
+ pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey, pQuery->lastKey);
+
// only record the key on last block
SET_CACHE_BLOCK_FLAG(pRuntimeEnv->blockStatus);
- SBlockInfo binfo = getBlockBasicInfo(pRuntimeEnv, pBlock, BLK_CACHE_BLOCK);
+ SBlockInfo binfo = getBlockInfo(pRuntimeEnv);
dTrace("QInfo:%p check data block, brange:%" PRId64 "-%" PRId64 ", fileId:%d, slot:%d, pos:%d, bstatus:%d",
GET_QINFO_ADDR(pQuery), binfo.keyFirst, binfo.keyLast, pQuery->fileId, pQuery->slot, pQuery->pos,
pRuntimeEnv->blockStatus);
totalBlocks++;
- queryOnBlock(pSupporter, primaryKeys, pRuntimeEnv->blockStatus, &binfo, &pMeterInfo[k], NULL, searchFn);
+ stableApplyFunctionsOnBlock(pSupporter, &pMeterDataInfo[k], &binfo, NULL, searchFn);
if (ALL_CACHE_BLOCKS_CHECKED(pQuery)) {
break;
@@ -266,7 +255,7 @@ static void queryOnMultiDataCache(SQInfo *pQInfo, SMeterDataInfo *pMeterInfo) {
static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo) {
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
SMeterDataBlockInfoEx *pDataBlockInfoEx = NULL;
int32_t nAllocBlocksInfoSize = 0;
@@ -274,9 +263,9 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
SMeterObj * pTempMeter = getMeterObj(pSupporter->pMetersHashTable, pSupporter->pMeterSidExtInfo[0]->sid);
__block_search_fn_t searchFn = vnodeSearchKeyFunc[pTempMeter->searchAlgorithm];
- int32_t vnodeId = pTempMeter->vnode;
- SQueryFilesInfo* pVnodeFileInfo = &pRuntimeEnv->vnodeFileInfo;
-
+ int32_t vnodeId = pTempMeter->vnode;
+ SQueryFilesInfo *pVnodeFileInfo = &pRuntimeEnv->vnodeFileInfo;
+
dTrace("QInfo:%p start to check data blocks in %d files", pQInfo, pVnodeFileInfo->numOfFiles);
int32_t fid = QUERY_IS_ASC_QUERY(pQuery) ? -1 : INT32_MAX;
@@ -291,7 +280,7 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
break;
}
- int32_t fileIdx = vnodeGetVnodeHeaderFileIdx(&fid, pRuntimeEnv, pQuery->order.order);
+ int32_t fileIdx = vnodeGetVnodeHeaderFileIndex(&fid, pRuntimeEnv, pQuery->order.order);
if (fileIdx < 0) { // no valid file, abort current search
break;
}
@@ -304,25 +293,25 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
fid += step;
continue;
}
-
+
int32_t numOfQualifiedMeters = 0;
assert(fileIdx == pRuntimeEnv->vnodeFileInfo.current);
-
+
SMeterDataInfo **pReqMeterDataInfo = NULL;
- int32_t ret = vnodeFilterQualifiedMeters(pQInfo, vnodeId, pSupporter->pSidSet, pMeterDataInfo,
+ int32_t ret = vnodeFilterQualifiedMeters(pQInfo, vnodeId, pSupporter->pSidSet, pMeterDataInfo,
&numOfQualifiedMeters, &pReqMeterDataInfo);
if (ret != TSDB_CODE_SUCCESS) {
dError("QInfo:%p failed to create meterdata struct to perform query processing, abort", pQInfo);
-
+
tfree(pReqMeterDataInfo);
pQInfo->code = -ret;
pQInfo->killed = 1;
-
+
return;
}
dTrace("QInfo:%p file:%s, %d meters qualified", pQInfo, pVnodeFileInfo->dataFilePath, numOfQualifiedMeters);
-
+
// none of meters in query set have pHeaderFileData in this file, try next file
if (numOfQualifiedMeters == 0) {
fid += step;
@@ -335,17 +324,17 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
pReqMeterDataInfo, &numOfBlocks);
if (ret != TSDB_CODE_SUCCESS) {
dError("QInfo:%p failed to get data block before scan data blocks, abort", pQInfo);
-
+
tfree(pReqMeterDataInfo);
pQInfo->code = -ret;
pQInfo->killed = 1;
-
+
return;
}
dTrace("QInfo:%p file:%s, %d meters contains %d blocks to be checked", pQInfo, pVnodeFileInfo->dataFilePath,
numOfQualifiedMeters, numOfBlocks);
-
+
if (numOfBlocks == 0) {
fid += step;
tfree(pReqMeterDataInfo);
@@ -353,7 +342,7 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
}
ret = createDataBlocksInfoEx(pReqMeterDataInfo, numOfQualifiedMeters, &pDataBlockInfoEx, numOfBlocks,
- &nAllocBlocksInfoSize, (int64_t)pQInfo);
+ &nAllocBlocksInfoSize, (int64_t)pQInfo);
if (ret != TSDB_CODE_SUCCESS) { // failed to create data blocks
dError("QInfo:%p build blockInfoEx failed, abort", pQInfo);
tfree(pReqMeterDataInfo);
@@ -383,8 +372,8 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
stimeUnit = taosGetTimestampMs();
} else if ((j % TRACE_OUTPUT_BLOCK_CNT) == 0) {
etimeUnit = taosGetTimestampMs();
- dTrace("QInfo:%p load and check %" PRId64 " blocks, and continue. elapsed:%" PRId64 " ms", pQInfo, TRACE_OUTPUT_BLOCK_CNT,
- etimeUnit - stimeUnit);
+ dTrace("QInfo:%p load and check %" PRId64 " blocks, and continue. elapsed:%" PRId64 " ms", pQInfo,
+ TRACE_OUTPUT_BLOCK_CNT, etimeUnit - stimeUnit);
stimeUnit = taosGetTimestampMs();
}
@@ -398,56 +387,60 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
restoreIntervalQueryRange(pRuntimeEnv, pMeterQueryInfo);
- if (pQuery->nAggTimeInterval == 0 && !isSumAvgRateQuery(pQuery)) { // normal query
- if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
- qTrace(
- "QInfo:%p vid:%d sid:%d id:%s, query completed, no need to scan this data block. qrange:%" PRId64 "-%" PRId64 ", "
- "lastKey:%" PRId64,
- pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey,
- pQuery->lastKey);
+ if ((pQuery->lastKey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
+ (pQuery->lastKey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) {
+ qTrace("QInfo:%p vid:%d sid:%d id:%s, query completed, no need to scan this data block. qrange:%" PRId64
+ "-%" PRId64 ", lastKey:%" PRId64,
+ pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey,
+ pQuery->lastKey);
- continue;
- }
-
- setExecutionContext(pSupporter, pSupporter->pResult, pOneMeterDataInfo->meterOrderIdx,
- pOneMeterDataInfo->groupIdx, pMeterQueryInfo);
- } else { // interval query
- ret = setIntervalQueryExecutionContext(pSupporter, pOneMeterDataInfo->meterOrderIdx, pMeterQueryInfo);
- if (ret != TSDB_CODE_SUCCESS) {
- tfree(pReqMeterDataInfo); // error code has been set
- pQInfo->killed = 1;
- return;
- }
+ continue;
}
SCompBlock *pBlock = pInfoEx->pBlock.compBlock;
bool ondemandLoad = onDemandLoadDatablock(pQuery, pMeterQueryInfo->queryRangeSet);
- int32_t ret = LoadDatablockOnDemand(pBlock, &pInfoEx->pBlock.fields, &pRuntimeEnv->blockStatus, pRuntimeEnv,
- fileIdx, pInfoEx->blockIndex, searchFn, ondemandLoad);
+ ret = LoadDatablockOnDemand(pBlock, &pInfoEx->pBlock.fields, &pRuntimeEnv->blockStatus, pRuntimeEnv, fileIdx,
+ pInfoEx->blockIndex, searchFn, ondemandLoad);
if (ret != DISK_DATA_LOADED) {
pSummary->skippedFileBlocks++;
continue;
}
SBlockInfo binfo = getBlockBasicInfo(pRuntimeEnv, pBlock, BLK_FILE_BLOCK);
+ int64_t nextKey = -1;
assert(pQuery->pos >= 0 && pQuery->pos < pBlock->numOfPoints);
TSKEY *primaryKeys = (TSKEY *)pRuntimeEnv->primaryColBuffer->data;
if (IS_DATA_BLOCK_LOADED(pRuntimeEnv->blockStatus) && needPrimaryTimestampCol(pQuery, &binfo)) {
- TSKEY nextKey = primaryKeys[pQuery->pos];
- if (!doCheckWithPrevQueryRange(pQInfo, nextKey, pOneMeterDataInfo)) {
+ nextKey = primaryKeys[pQuery->pos];
+
+ if (!doCheckWithPrevQueryRange(pQuery, nextKey)) {
+ qTrace("QInfo:%p vid:%d sid:%d id:%s, no data qualified in data file, lastKey:%" PRId64, pQInfo,
+ pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->numOfBlocks, pQuery->lastKey);
continue;
}
} else {
// if data block is not loaded, it must be the intermediate blocks
assert((pBlock->keyFirst >= pQuery->lastKey && pBlock->keyLast <= pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
(pBlock->keyFirst >= pQuery->ekey && pBlock->keyLast <= pQuery->lastKey && !QUERY_IS_ASC_QUERY(pQuery)));
+ nextKey = QUERY_IS_ASC_QUERY(pQuery) ? pBlock->keyFirst : pBlock->keyLast;
}
- queryOnBlock(pSupporter, primaryKeys, pRuntimeEnv->blockStatus, &binfo, pOneMeterDataInfo, pInfoEx->pBlock.fields,
- searchFn);
+ if (pQuery->intervalTime == 0) {
+ setExecutionContext(pSupporter, pMeterQueryInfo, pOneMeterDataInfo->meterOrderIdx, pOneMeterDataInfo->groupIdx,
+ nextKey);
+ } else { // interval query
+ setIntervalQueryRange(pMeterQueryInfo, pSupporter, nextKey);
+ ret = setAdditionalInfo(pSupporter, pOneMeterDataInfo->meterOrderIdx, pMeterQueryInfo);
+ if (ret != TSDB_CODE_SUCCESS) {
+ tfree(pReqMeterDataInfo); // error code has been set
+ pQInfo->killed = 1;
+ return;
+ }
+ }
+
+ stableApplyFunctionsOnBlock(pSupporter, pOneMeterDataInfo, &binfo, pInfoEx->pBlock.fields, searchFn);
}
tfree(pReqMeterDataInfo);
@@ -470,7 +463,7 @@ static void queryOnMultiDataFiles(SQInfo *pQInfo, SMeterDataInfo *pMeterDataInfo
static bool multimeterMultioutputHelper(SQInfo *pQInfo, bool *dataInDisk, bool *dataInCache, int32_t index,
int32_t start) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SMeterSidExtInfo **pMeterSidExtInfo = pSupporter->pMeterSidExtInfo;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
@@ -486,13 +479,13 @@ static bool multimeterMultioutputHelper(SQInfo *pQInfo, bool *dataInDisk, bool *
vnodeSetTagValueInParam(pSupporter->pSidSet, pRuntimeEnv, pMeterSidExtInfo[index]);
- dTrace("QInfo:%p query on (%d): vid:%d sid:%d meterId:%s, qrange:%" PRId64 "-%" PRId64, pQInfo, index - start, pMeterObj->vnode,
- pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey);
+ dTrace("QInfo:%p query on (%d): vid:%d sid:%d meterId:%s, qrange:%" PRId64 "-%" PRId64, pQInfo, index - start,
+ pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey);
pQInfo->pObj = pMeterObj;
pQuery->lastKey = pQuery->skey;
pRuntimeEnv->pMeterObj = pMeterObj;
-
+
vnodeUpdateQueryColumnIndex(pQuery, pRuntimeEnv->pMeterObj);
vnodeUpdateFilterColumnIndex(pQuery);
@@ -500,8 +493,8 @@ static bool multimeterMultioutputHelper(SQInfo *pQInfo, bool *dataInDisk, bool *
// data in file or cache is not qualified for the query. abort
if (!(dataInCache || dataInDisk)) {
- dTrace("QInfo:%p vid:%d sid:%d meterId:%s, qrange:%" PRId64 "-%" PRId64 ", nores, %p", pQInfo, pMeterObj->vnode, pMeterObj->sid,
- pMeterObj->meterId, pQuery->skey, pQuery->ekey, pQuery);
+ dTrace("QInfo:%p vid:%d sid:%d meterId:%s, qrange:%" PRId64 "-%" PRId64 ", nores, %p", pQInfo, pMeterObj->vnode,
+ pMeterObj->sid, pMeterObj->meterId, pQuery->skey, pQuery->ekey, pQuery);
return false;
}
@@ -525,7 +518,7 @@ static bool multimeterMultioutputHelper(SQInfo *pQInfo, bool *dataInDisk, bool *
static int64_t doCheckMetersInGroup(SQInfo *pQInfo, int32_t index, int32_t start) {
SQuery * pQuery = &pQInfo->query;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
bool dataInDisk = true;
@@ -556,7 +549,7 @@ static int64_t doCheckMetersInGroup(SQInfo *pQInfo, int32_t index, int32_t start
pointInterpSupporterDestroy(&pointInterpSupporter);
vnodeScanAllData(pRuntimeEnv);
-
+
// first/last_row query, do not invoke the finalize for super table query
doFinalizeResult(pRuntimeEnv);
@@ -580,7 +573,7 @@ static int64_t doCheckMetersInGroup(SQInfo *pQInfo, int32_t index, int32_t start
* @param pQInfo
*/
static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SMeterSidExtInfo **pMeterSidExtInfo = pSupporter->pMeterSidExtInfo;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
@@ -589,10 +582,10 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
tSidSet *pSids = pSupporter->pSidSet;
int32_t vid = getMeterObj(pSupporter->pMetersHashTable, pMeterSidExtInfo[0]->sid)->vnode;
-
+
if (isPointInterpoQuery(pQuery)) {
resetCtxOutputBuf(pRuntimeEnv);
-
+
assert(pQuery->limit.offset == 0 && pQuery->limit.limit != 0);
while (pSupporter->subgroupIdx < pSids->numOfSubSet) {
@@ -600,8 +593,8 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
int32_t end = pSids->starterPos[pSupporter->subgroupIdx + 1] - 1;
if (isFirstLastRowQuery(pQuery)) {
- dTrace("QInfo:%p last_row query on vid:%d, numOfGroups:%d, current group:%d", pQInfo, vid,
- pSids->numOfSubSet, pSupporter->subgroupIdx);
+ dTrace("QInfo:%p last_row query on vid:%d, numOfGroups:%d, current group:%d", pQInfo, vid, pSids->numOfSubSet,
+ pSupporter->subgroupIdx);
TSKEY key = -1;
int32_t index = -1;
@@ -633,8 +626,8 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
int64_t num = doCheckMetersInGroup(pQInfo, index, start);
assert(num >= 0);
} else {
- dTrace("QInfo:%p interp query on vid:%d, numOfGroups:%d, current group:%d", pQInfo, vid,
- pSids->numOfSubSet, pSupporter->subgroupIdx);
+ dTrace("QInfo:%p interp query on vid:%d, numOfGroups:%d, current group:%d", pQInfo, vid, pSids->numOfSubSet,
+ pSupporter->subgroupIdx);
for (int32_t k = start; k <= end; ++k) {
if (isQueryKilled(pQuery)) {
@@ -670,7 +663,7 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
* we need to return it to client in the first place.
*/
if (pSupporter->subgroupIdx > 0) {
- copyFromGroupBuf(pQInfo, pSupporter->pResult);
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
pQInfo->pointsRead += pQuery->pointsRead;
if (pQuery->pointsRead > 0) {
@@ -681,10 +674,10 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
if (pSupporter->meterIdx >= pSids->numOfSids) {
return;
}
-
+
resetCtxOutputBuf(pRuntimeEnv);
- resetSlidingWindowInfo(pRuntimeEnv, &pRuntimeEnv->swindowResInfo);
-
+ resetTimeWindowInfo(pRuntimeEnv, &pRuntimeEnv->windowResInfo);
+
while (pSupporter->meterIdx < pSupporter->numOfMeters) {
int32_t k = pSupporter->meterIdx;
@@ -692,9 +685,8 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
setQueryStatus(pQuery, QUERY_NO_DATA_TO_CHECK);
return;
}
-
- TSKEY skey = pQInfo->pMeterQuerySupporter->pMeterSidExtInfo[k]->key;
+ TSKEY skey = pQInfo->pTableQuerySupporter->pMeterSidExtInfo[k]->key;
if (skey > 0) {
pQuery->skey = skey;
}
@@ -747,10 +739,10 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
pSupporter->meterIdx = pSupporter->pSidSet->numOfSids;
break;
}
-
+
// enable execution for next table, when handling the projection query
enableExecutionForNextTable(pRuntimeEnv);
-
+
if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED)) {
/*
* query range is identical in terms of all meters involved in query,
@@ -762,7 +754,7 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
pQuery->ekey = pSupporter->rawEKey;
pSupporter->meterIdx++;
- pQInfo->pMeterQuerySupporter->pMeterSidExtInfo[k]->key = pQuery->lastKey;
+ pQInfo->pTableQuerySupporter->pMeterSidExtInfo[k]->key = pQuery->lastKey;
// if the buffer is full or group by each table, we need to jump out of the loop
if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL) ||
@@ -770,7 +762,7 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
break;
}
- } else { // forward query range
+ } else { // forward query range
pQuery->skey = pQuery->lastKey;
// all data in the result buffer are skipped due to the offset, continue to retrieve data from current meter
@@ -778,7 +770,7 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
assert(!Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL));
continue;
} else {
- pQInfo->pMeterQuerySupporter->pMeterSidExtInfo[k]->key = pQuery->lastKey;
+ pQInfo->pTableQuerySupporter->pMeterSidExtInfo[k]->key = pQuery->lastKey;
// buffer is full, wait for the next round to retrieve data from current meter
assert(Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL));
break;
@@ -808,20 +800,21 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
// todo refactor
if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
- SSlidingWindowInfo* pSlidingWindowInfo = &pRuntimeEnv->swindowResInfo;
-
- for (int32_t i = 0; i < pSlidingWindowInfo->size; ++i) {
- SOutputRes *buf = &pSlidingWindowInfo->pResult[i];
- pSlidingWindowInfo->pStatus[i].closed = true; // enable return all results for group by normal columns
-
+ SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
+
+ for (int32_t i = 0; i < pWindowResInfo->size; ++i) {
+ SWindowStatus *pStatus = &pWindowResInfo->pResult[i].status;
+ pStatus->closed = true; // enable return all results for group by normal columns
+
+ SWindowResult *pResult = &pWindowResInfo->pResult[i];
for (int32_t j = 0; j < pQuery->numOfOutputCols; ++j) {
- buf->numOfRows = MAX(buf->numOfRows, buf->resultInfo[j].numOfRes);
+ pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes);
}
}
- pQInfo->pMeterQuerySupporter->subgroupIdx = 0;
+ pQInfo->pTableQuerySupporter->subgroupIdx = 0;
pQuery->pointsRead = 0;
- copyFromGroupBuf(pQInfo, pSlidingWindowInfo->pResult);
+ copyFromWindowResToSData(pQInfo, pWindowResInfo->pResult);
}
pQInfo->pointsRead += pQuery->pointsRead;
@@ -830,12 +823,12 @@ static void vnodeSTableSeqProcessor(SQInfo *pQInfo) {
dTrace(
"QInfo %p vid:%d, numOfMeters:%d, index:%d, numOfGroups:%d, %d points returned, totalRead:%d totalReturn:%d,"
"next skey:%" PRId64 ", offset:%" PRId64,
- pQInfo, vid, pSids->numOfSids, pSupporter->meterIdx, pSids->numOfSubSet, pQuery->pointsRead,
- pQInfo->pointsRead, pQInfo->pointsReturned, pQuery->skey, pQuery->limit.offset);
+ pQInfo, vid, pSids->numOfSids, pSupporter->meterIdx, pSids->numOfSubSet, pQuery->pointsRead, pQInfo->pointsRead,
+ pQInfo->pointsReturned, pQuery->skey, pQuery->limit.offset);
}
static void doOrderedScan(SQInfo *pQInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQuery * pQuery = &pQInfo->query;
if (QUERY_IS_ASC_QUERY(pQuery)) {
@@ -855,17 +848,17 @@ static void doOrderedScan(SQInfo *pQInfo) {
}
}
-static void setupMeterQueryInfoForSupplementQuery(SMeterQuerySupportObj *pSupporter) {
+static void setupMeterQueryInfoForSupplementQuery(STableQuerySupportObj *pSupporter) {
+ SQuery *pQuery = pSupporter->runtimeEnv.pQuery;
+
for (int32_t i = 0; i < pSupporter->numOfMeters; ++i) {
SMeterQueryInfo *pMeterQueryInfo = pSupporter->pMeterDataInfo[i].pMeterQInfo;
- SQueryResultBuf* pResultBuf = pSupporter->runtimeEnv.pResultBuf;
-
- changeMeterQueryInfoForSuppleQuery(pResultBuf, pMeterQueryInfo, pSupporter->rawSKey, pSupporter->rawEKey);
+ changeMeterQueryInfoForSuppleQuery(pQuery, pMeterQueryInfo, pSupporter->rawSKey, pSupporter->rawEKey);
}
}
static void doMultiMeterSupplementaryScan(SQInfo *pQInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv *pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = &pQInfo->query;
@@ -876,17 +869,19 @@ static void doMultiMeterSupplementaryScan(SQInfo *pQInfo) {
}
SET_SUPPLEMENT_SCAN_FLAG(pRuntimeEnv);
- disableFunctForSuppleScan(pRuntimeEnv, pQuery->order.order);
+ disableFunctForSuppleScan(pSupporter, pQuery->order.order);
if (pRuntimeEnv->pTSBuf != NULL) {
- pRuntimeEnv->pTSBuf->cur.order = pRuntimeEnv->pTSBuf->cur.order ^ 1;
+ pRuntimeEnv->pTSBuf->cur.order = pRuntimeEnv->pTSBuf->cur.order ^ 1u;
}
SWAP(pSupporter->rawSKey, pSupporter->rawEKey, TSKEY);
setupMeterQueryInfoForSupplementQuery(pSupporter);
int64_t st = taosGetTimestampMs();
+
doOrderedScan(pQInfo);
+
int64_t et = taosGetTimestampMs();
dTrace("QInfo:%p supplementary scan completed, elapsed time: %lldms", pQInfo, et - st);
@@ -905,7 +900,8 @@ static void doMultiMeterSupplementaryScan(SQInfo *pQInfo) {
}
static void vnodeMultiMeterQueryProcessor(SQInfo *pQInfo) {
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
+ SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
SQuery * pQuery = &pQInfo->query;
if (pSupporter->subgroupIdx > 0) {
@@ -913,14 +909,14 @@ static void vnodeMultiMeterQueryProcessor(SQInfo *pQInfo) {
* if the subgroupIdx > 0, the query process must be completed yet, we only need to
* copy the data into output buffer
*/
- if (pQuery->nAggTimeInterval > 0) {
+ if (pQuery->intervalTime > 0) {
copyResToQueryResultBuf(pSupporter, pQuery);
#ifdef _DEBUG_VIEW
displayInterResult(pQuery->sdata, pQuery, pQuery->sdata[0]->len);
#endif
} else {
- copyFromGroupBuf(pQInfo, pSupporter->pResult);
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
}
pQInfo->pointsRead += pQuery->pointsRead;
@@ -941,22 +937,25 @@ static void vnodeMultiMeterQueryProcessor(SQInfo *pQInfo) {
return;
}
- dTrace("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", order:%d, group:%d", pQInfo, pSupporter->rawSKey, pSupporter->rawEKey,
- pQuery->order.order, pSupporter->pSidSet->numOfSubSet);
+ dTrace("QInfo:%p query start, qrange:%" PRId64 "-%" PRId64 ", order:%d, group:%d", pQInfo, pSupporter->rawSKey,
+ pSupporter->rawEKey, pQuery->order.order, pSupporter->pSidSet->numOfSubSet);
dTrace("QInfo:%p main query scan start", pQInfo);
int64_t st = taosGetTimestampMs();
doOrderedScan(pQInfo);
int64_t et = taosGetTimestampMs();
dTrace("QInfo:%p main scan completed, elapsed time: %lldms, supplementary scan start, order:%d", pQInfo, et - st,
- pQuery->order.order ^ 1);
+ pQuery->order.order ^ 1u);
- // failed to save all intermediate results into disk, abort further query processing
- if (doCloseAllOpenedResults(pSupporter) != TSDB_CODE_SUCCESS) {
- dError("QInfo:%p failed to save intermediate results, abort further query processing", pQInfo);
- return;
+ if (pQuery->intervalTime > 0) {
+ for (int32_t i = 0; i < pSupporter->numOfMeters; ++i) {
+ SMeterQueryInfo *pMeterQueryInfo = pSupporter->pMeterDataInfo[i].pMeterQInfo;
+ closeAllTimeWindow(&pMeterQueryInfo->windowResInfo);
+ }
+ } else { // close results for group result
+ closeAllTimeWindow(&pRuntimeEnv->windowResInfo);
}
-
+
doMultiMeterSupplementaryScan(pQInfo);
if (isQueryKilled(pQuery)) {
@@ -964,18 +963,18 @@ static void vnodeMultiMeterQueryProcessor(SQInfo *pQInfo) {
return;
}
- if (pQuery->nAggTimeInterval > 0 || isSumAvgRateQuery(pQuery)) {
+ if (pQuery->intervalTime > 0 || isSumAvgRateQuery(pQuery)) {
assert(pSupporter->subgroupIdx == 0 && pSupporter->numOfGroupResultPages == 0);
if (mergeMetersResultToOneGroups(pSupporter) == TSDB_CODE_SUCCESS) {
copyResToQueryResultBuf(pSupporter, pQuery);
-
+
#ifdef _DEBUG_VIEW
displayInterResult(pQuery->sdata, pQuery, pQuery->sdata[0]->len);
#endif
}
} else { // not a interval query
- copyFromGroupBuf(pQInfo, pSupporter->pResult);
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
}
// handle the limitation of output buffer
@@ -992,7 +991,7 @@ static void vnodeMultiMeterQueryProcessor(SQInfo *pQInfo) {
*/
static void vnodeSingleTableFixedOutputProcessor(SQInfo *pQInfo) {
SQuery * pQuery = &pQInfo->query;
- SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pMeterQuerySupporter->runtimeEnv;
+ SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pTableQuerySupporter->runtimeEnv;
assert(pQuery->slot >= 0 && pQuery->pos >= 0);
@@ -1023,7 +1022,7 @@ static void vnodeSingleTableMultiOutputProcessor(SQInfo *pQInfo) {
SQuery * pQuery = &pQInfo->query;
SMeterObj *pMeterObj = pQInfo->pObj;
- SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pMeterQuerySupporter->runtimeEnv;
+ SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pTableQuerySupporter->runtimeEnv;
// for ts_comp query, re-initialized is not allowed
if (!isTSCompQuery(pQuery)) {
@@ -1054,8 +1053,9 @@ static void vnodeSingleTableMultiOutputProcessor(SQInfo *pQInfo) {
TSKEY nextTimestamp = loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->nextPos);
assert(nextTimestamp > 0 || ((nextTimestamp < 0) && Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)));
- dTrace("QInfo:%p vid:%d sid:%d id:%s, skip current result, offset:%" PRId64 ", next qrange:%" PRId64 "-%" PRId64, pQInfo,
- pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->limit.offset, pQuery->lastKey, pQuery->ekey);
+ dTrace("QInfo:%p vid:%d sid:%d id:%s, skip current result, offset:%" PRId64 ", next qrange:%" PRId64 "-%" PRId64,
+ pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->limit.offset, pQuery->lastKey,
+ pQuery->ekey);
resetCtxOutputBuf(pRuntimeEnv);
}
@@ -1067,8 +1067,8 @@ static void vnodeSingleTableMultiOutputProcessor(SQInfo *pQInfo) {
TSKEY nextTimestamp = loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->nextPos);
assert(nextTimestamp > 0 || ((nextTimestamp < 0) && Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)));
- dTrace("QInfo:%p vid:%d sid:%d id:%s, query abort due to buffer limitation, next qrange:%" PRId64 "-%" PRId64, pQInfo,
- pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->lastKey, pQuery->ekey);
+ dTrace("QInfo:%p vid:%d sid:%d id:%s, query abort due to buffer limitation, next qrange:%" PRId64 "-%" PRId64,
+ pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->lastKey, pQuery->ekey);
}
dTrace("QInfo:%p vid:%d sid:%d id:%s, %d points returned, totalRead:%d totalReturn:%d", pQInfo, pMeterObj->vnode,
@@ -1080,58 +1080,39 @@ static void vnodeSingleTableMultiOutputProcessor(SQInfo *pQInfo) {
}
}
-static void vnodeSingleMeterIntervalMainLooper(SMeterQuerySupportObj *pSupporter, SQueryRuntimeEnv *pRuntimeEnv) {
+static void vnodeSingleMeterIntervalMainLooper(STableQuerySupportObj *pSupporter, SQueryRuntimeEnv *pRuntimeEnv) {
SQuery *pQuery = pRuntimeEnv->pQuery;
while (1) {
- assert((pQuery->skey <= pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) ||
- (pQuery->skey >= pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery)));
-
initCtxOutputBuf(pRuntimeEnv);
- clearCompletedSlidingWindows(pRuntimeEnv);
-
vnodeScanAllData(pRuntimeEnv);
+
if (isQueryKilled(pQuery)) {
return;
}
assert(!Q_STATUS_EQUAL(pQuery->over, QUERY_NOT_COMPLETED));
-
- // clear tag, used to decide if the whole interval query is completed or not
- pQuery->over &= (~QUERY_COMPLETED);
doFinalizeResult(pRuntimeEnv);
- int64_t maxOutput = getNumOfResult(pRuntimeEnv);
-
// here we can ignore the records in case of no interpolation
+ // todo handle offset, in case of top/bottom interval query
if ((pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL) && pQuery->limit.offset > 0 &&
- pQuery->interpoType == TSDB_INTERPO_NONE) { // maxOutput <= 0, means current query does not generate any results
- // todo handle offset, in case of top/bottom interval query
- if (maxOutput > 0) {
- pQuery->limit.offset--;
- }
- } else {
- pQuery->pointsRead += maxOutput;
- forwardCtxOutputBuf(pRuntimeEnv, maxOutput);
- }
+ pQuery->interpoType == TSDB_INTERPO_NONE) {
+ // maxOutput <= 0, means current query does not generate any results
+ int32_t numOfClosed = numOfClosedTimeWindow(&pRuntimeEnv->windowResInfo);
- if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) {
- break;
+ int32_t c = MIN(numOfClosed, pQuery->limit.offset);
+ clearFirstNTimeWindow(pRuntimeEnv, c);
+ pQuery->limit.offset -= c;
}
- forwardIntervalQueryRange(pSupporter, pRuntimeEnv);
- if (Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED|QUERY_RESBUF_FULL)) {
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED)) {
break;
}
- /*
- * the scan limitation mechanism is upon here,
- * 1. since there is only one(k) record is generated in one scan operation
- * 2. remain space is not sufficient for next query output, abort
- */
- if ((pQuery->pointsRead % pQuery->pointsToRead == 0 && pQuery->pointsRead != 0) ||
- ((pQuery->pointsRead + maxOutput) > pQuery->pointsToRead)) {
- setQueryStatus(pQuery, QUERY_RESBUF_FULL);
+ // load the data block for the next retrieve
+ loadRequiredBlockIntoMem(pRuntimeEnv, &pRuntimeEnv->nextPos);
+ if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) {
break;
}
}
@@ -1142,7 +1123,7 @@ static void vnodeSingleTableIntervalProcessor(SQInfo *pQInfo) {
SQuery * pQuery = &(pQInfo->query);
SMeterObj *pMeterObj = pQInfo->pObj;
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
int32_t numOfInterpo = 0;
@@ -1151,6 +1132,14 @@ static void vnodeSingleTableIntervalProcessor(SQInfo *pQInfo) {
resetCtxOutputBuf(pRuntimeEnv);
vnodeSingleMeterIntervalMainLooper(pSupporter, pRuntimeEnv);
+ if (pQuery->intervalTime > 0) {
+ pSupporter->subgroupIdx = 0; // always start from 0
+ pQuery->pointsRead = 0;
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
+
+ clearFirstNTimeWindow(pRuntimeEnv, pSupporter->subgroupIdx);
+ }
+
// the offset is handled at prepare stage if no interpolation involved
if (pQuery->interpoType == TSDB_INTERPO_NONE) {
doRevisedResultsByLimit(pQInfo);
@@ -1177,11 +1166,13 @@ static void vnodeSingleTableIntervalProcessor(SQInfo *pQInfo) {
pQuery->pointsRead = 0;
}
}
-
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr) || (pQuery->slidingTime > 0 && pQuery->nAggTimeInterval > 0)) {
- pQInfo->pMeterQuerySupporter->subgroupIdx = 0;
+
+ // all data scanned, the group by normal column can return
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {//todo refactor with merge interval time result
+ pSupporter->subgroupIdx = 0;
pQuery->pointsRead = 0;
- copyFromGroupBuf(pQInfo, pRuntimeEnv->swindowResInfo.pResult);
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
+ clearFirstNTimeWindow(pRuntimeEnv, pSupporter->subgroupIdx);
}
pQInfo->pointsRead += pQuery->pointsRead;
@@ -1195,7 +1186,7 @@ static void vnodeSingleTableIntervalProcessor(SQInfo *pQInfo) {
void vnodeSingleTableQuery(SSchedMsg *pMsg) {
SQInfo *pQInfo = (SQInfo *)pMsg->ahandle;
- if (pQInfo == NULL || pQInfo->pMeterQuerySupporter == NULL) {
+ if (pQInfo == NULL || pQInfo->pTableQuerySupporter == NULL) {
dTrace("%p freed abort query", pQInfo);
return;
}
@@ -1203,21 +1194,22 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
if (pQInfo->killed) {
dTrace("QInfo:%p it is already killed, abort", pQInfo);
vnodeDecRefCount(pQInfo);
-
+
return;
}
assert(pQInfo->refCount >= 1);
- SQuery * pQuery = &pQInfo->query;
- SMeterObj *pMeterObj = pQInfo->pObj;
+ SQuery * pQuery = &pQInfo->query;
+ SMeterObj * pMeterObj = pQInfo->pObj;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
+ SQueryRuntimeEnv * pRuntimeEnv = &pSupporter->runtimeEnv;
+
+ assert(pRuntimeEnv->pMeterObj == pMeterObj);
dTrace("vid:%d sid:%d id:%s, query thread is created, numOfQueries:%d, QInfo:%p", pMeterObj->vnode, pMeterObj->sid,
pMeterObj->meterId, pMeterObj->numOfQueries, pQInfo);
- SQueryRuntimeEnv *pRuntimeEnv = &pQInfo->pMeterQuerySupporter->runtimeEnv;
- assert(pRuntimeEnv->pMeterObj == pMeterObj);
-
if (vnodeHasRemainResults(pQInfo)) {
/*
* There are remain results that are not returned due to result interpolation
@@ -1249,12 +1241,18 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
// here we have scan all qualified data in both data file and cache
if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED)) {
// continue to get push data from the group result
- if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) {
+ if (isGroupbyNormalCol(pQuery->pGroupbyExpr) ||
+ (pQuery->intervalTime > 0 && pQInfo->pointsReturned < pQuery->limit.limit)) {
+ //todo limit the output for interval query?
pQuery->pointsRead = 0;
- if (pQInfo->pMeterQuerySupporter->subgroupIdx > 0) {
- copyFromGroupBuf(pQInfo, pQInfo->pMeterQuerySupporter->pResult);
+ pSupporter->subgroupIdx = 0; // always start from 0
+
+ if (pRuntimeEnv->windowResInfo.size > 0) {
+ copyFromWindowResToSData(pQInfo, pRuntimeEnv->windowResInfo.pResult);
pQInfo->pointsRead += pQuery->pointsRead;
+ clearFirstNTimeWindow(pRuntimeEnv, pSupporter->subgroupIdx);
+
if (pQuery->pointsRead > 0) {
dTrace("QInfo:%p vid:%d sid:%d id:%s, %d points returned %d from group results, totalRead:%d totalReturn:%d",
pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->pointsRead, pQInfo->pointsRead,
@@ -1262,19 +1260,19 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
sem_post(&pQInfo->dataReady);
vnodeDecRefCount(pQInfo);
-
+
return;
}
}
}
pQInfo->over = 1;
- dTrace("QInfo:%p vid:%d sid:%d id:%s, query over, %d points are returned", pQInfo,
- pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQInfo->pointsRead);
+ dTrace("QInfo:%p vid:%d sid:%d id:%s, query over, %d points are returned", pQInfo, pMeterObj->vnode, pMeterObj->sid,
+ pMeterObj->meterId, pQInfo->pointsRead);
- vnodePrintQueryStatistics(pQInfo->pMeterQuerySupporter);
+ vnodePrintQueryStatistics(pSupporter);
sem_post(&pQInfo->dataReady);
-
+
vnodeDecRefCount(pQInfo);
return;
}
@@ -1286,7 +1284,7 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
int64_t st = taosGetTimestampUs();
// group by normal column, sliding window query, interval query are handled by interval query processor
- if (pQuery->nAggTimeInterval != 0 || isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // interval (down sampling operation)
+ if (pQuery->intervalTime != 0 || isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // interval (down sampling operation)
assert(pQuery->checkBufferInLoop == 0 && pQuery->pointsOffset == pQuery->pointsToRead);
vnodeSingleTableIntervalProcessor(pQInfo);
} else {
@@ -1307,8 +1305,8 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
dTrace("QInfo:%p query is killed", pQInfo);
pQInfo->over = 1;
} else {
- dTrace("QInfo:%p vid:%d sid:%d id:%s, meter query thread completed, %d points are returned",
- pQInfo, pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->pointsRead);
+ dTrace("QInfo:%p vid:%d sid:%d id:%s, meter query thread completed, %d points are returned", pQInfo,
+ pMeterObj->vnode, pMeterObj->sid, pMeterObj->meterId, pQuery->pointsRead);
}
sem_post(&pQInfo->dataReady);
@@ -1318,7 +1316,7 @@ void vnodeSingleTableQuery(SSchedMsg *pMsg) {
void vnodeMultiMeterQuery(SSchedMsg *pMsg) {
SQInfo *pQInfo = (SQInfo *)pMsg->ahandle;
- if (pQInfo == NULL || pQInfo->pMeterQuerySupporter == NULL) {
+ if (pQInfo == NULL || pQInfo->pTableQuerySupporter == NULL) {
return;
}
@@ -1334,12 +1332,12 @@ void vnodeMultiMeterQuery(SSchedMsg *pMsg) {
pQuery->pointsRead = 0;
int64_t st = taosGetTimestampUs();
- if (pQuery->nAggTimeInterval > 0 ||
+ if (pQuery->intervalTime > 0 ||
(isFixedOutputQuery(pQuery) && (!isPointInterpoQuery(pQuery)) && !isGroupbyNormalCol(pQuery->pGroupbyExpr))) {
assert(pQuery->checkBufferInLoop == 0);
vnodeMultiMeterQueryProcessor(pQInfo);
} else {
- assert((pQuery->checkBufferInLoop == 1 && pQuery->nAggTimeInterval == 0) || isPointInterpoQuery(pQuery) ||
+ assert((pQuery->checkBufferInLoop == 1 && pQuery->intervalTime == 0) || isPointInterpoQuery(pQuery) ||
isGroupbyNormalCol(pQuery->pGroupbyExpr));
vnodeSTableSeqProcessor(pQInfo);
@@ -1349,10 +1347,10 @@ void vnodeMultiMeterQuery(SSchedMsg *pMsg) {
pQInfo->useconds += (taosGetTimestampUs() - st);
pQInfo->over = isQueryKilled(pQuery) ? 1 : 0;
- taosInterpoSetStartInfo(&pQInfo->pMeterQuerySupporter->runtimeEnv.interpoInfo, pQuery->pointsRead,
+ taosInterpoSetStartInfo(&pQInfo->pTableQuerySupporter->runtimeEnv.interpoInfo, pQuery->pointsRead,
pQInfo->query.interpoType);
- SMeterQuerySupportObj *pSupporter = pQInfo->pMeterQuerySupporter;
+ STableQuerySupportObj *pSupporter = pQInfo->pTableQuerySupporter;
if (pQuery->pointsRead == 0) {
pQInfo->over = 1;
diff --git a/src/vnode/detail/src/vnodeRead.c b/src/vnode/detail/src/vnodeRead.c
index e4a8b898ec3266c0a89b24357a4eec08632644a1..fb7c85e61c61272159202a2bda4ef7f30fdd93d0 100644
--- a/src/vnode/detail/src/vnodeRead.c
+++ b/src/vnode/detail/src/vnodeRead.c
@@ -266,7 +266,7 @@ static SQInfo *vnodeAllocateQInfoEx(SQueryMeterMsg *pQueryMsg, SSqlGroupbyExpr *
}
pQuery->pGroupbyExpr = pGroupbyExpr;
- pQuery->nAggTimeInterval = pQueryMsg->nAggTimeInterval;
+ pQuery->intervalTime = pQueryMsg->intervalTime;
pQuery->slidingTime = pQueryMsg->slidingTime;
pQuery->interpoType = pQueryMsg->interpoType;
pQuery->intervalTimeUnit = pQueryMsg->intervalTimeUnit;
@@ -648,7 +648,7 @@ void *vnodeQueryOnSingleTable(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
goto _error;
}
- SMeterQuerySupportObj *pSupporter = (SMeterQuerySupportObj *)calloc(1, sizeof(SMeterQuerySupportObj));
+ STableQuerySupportObj *pSupporter = (STableQuerySupportObj *)calloc(1, sizeof(STableQuerySupportObj));
pSupporter->numOfMeters = 1;
pSupporter->pMetersHashTable = taosInitHashTable(pSupporter->numOfMeters, taosIntHash_32, false);
@@ -659,7 +659,7 @@ void *vnodeQueryOnSingleTable(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
pSupporter->subgroupIdx = -1;
pSupporter->pMeterSidExtInfo = NULL;
- pQInfo->pMeterQuerySupporter = pSupporter;
+ pQInfo->pTableQuerySupporter = pSupporter;
STSBuf *pTSBuf = NULL;
if (pQueryMsg->tsLen > 0) {
@@ -670,7 +670,7 @@ void *vnodeQueryOnSingleTable(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
tsBufNextPos(pTSBuf);
}
- if (((*code) = vnodeQuerySingleMeterPrepare(pQInfo, pQInfo->pObj, pSupporter, pTSBuf)) != TSDB_CODE_SUCCESS) {
+ if (((*code) = vnodeQueryTablePrepare(pQInfo, pQInfo->pObj, pSupporter, pTSBuf)) != TSDB_CODE_SUCCESS) {
goto _error;
}
@@ -739,7 +739,7 @@ void *vnodeQueryOnMultiMeters(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
SSchedMsg schedMsg = {0};
- SMeterQuerySupportObj *pSupporter = (SMeterQuerySupportObj *)calloc(1, sizeof(SMeterQuerySupportObj));
+ STableQuerySupportObj *pSupporter = (STableQuerySupportObj *)calloc(1, sizeof(STableQuerySupportObj));
pSupporter->numOfMeters = pQueryMsg->numOfSids;
pSupporter->pMetersHashTable = taosInitHashTable(pSupporter->numOfMeters, taosIntHash_32, false);
@@ -784,7 +784,7 @@ void *vnodeQueryOnMultiMeters(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
(SSchema *)pQueryMsg->pTagSchema, pQueryMsg->numOfTagsCols, NULL, 0);
}
- pQInfo->pMeterQuerySupporter = pSupporter;
+ pQInfo->pTableQuerySupporter = pSupporter;
STSBuf *pTSBuf = NULL;
if (pQueryMsg->tsLen > 0) {
@@ -794,7 +794,7 @@ void *vnodeQueryOnMultiMeters(SMeterObj **pMetersObj, SSqlGroupbyExpr *pGroupbyE
tsBufResetPos(pTSBuf);
}
- if (((*code) = vnodeMultiMeterQueryPrepare(pQInfo, pQuery, pTSBuf)) != TSDB_CODE_SUCCESS) {
+ if (((*code) = vnodeSTableQueryPrepare(pQInfo, pQuery, pTSBuf)) != TSDB_CODE_SUCCESS) {
goto _error;
}
@@ -898,8 +898,8 @@ int vnodeSaveQueryResult(void *handle, char *data, int32_t *size) {
SSchedMsg schedMsg = {0};
- if (pQInfo->pMeterQuerySupporter != NULL) {
- if (pQInfo->pMeterQuerySupporter->pSidSet == NULL) {
+ if (pQInfo->pTableQuerySupporter != NULL) {
+ if (pQInfo->pTableQuerySupporter->pSidSet == NULL) {
schedMsg.fp = vnodeSingleTableQuery;
} else { // group by tag
schedMsg.fp = vnodeMultiMeterQuery;
@@ -920,8 +920,8 @@ int vnodeSaveQueryResult(void *handle, char *data, int32_t *size) {
}
static int32_t validateQueryMeterMsg(SQueryMeterMsg *pQueryMsg) {
- if (pQueryMsg->nAggTimeInterval < 0) {
- dError("qmsg:%p illegal value of aggTimeInterval %" PRId64 "", pQueryMsg, pQueryMsg->nAggTimeInterval);
+ if (pQueryMsg->intervalTime < 0) {
+ dError("qmsg:%p illegal value of aggTimeInterval %" PRId64 "", pQueryMsg, pQueryMsg->intervalTime);
return -1;
}
@@ -975,7 +975,7 @@ int32_t vnodeConvertQueryMeterMsg(SQueryMeterMsg *pQueryMsg) {
pQueryMsg->queryType = htons(pQueryMsg->queryType);
- pQueryMsg->nAggTimeInterval = htobe64(pQueryMsg->nAggTimeInterval);
+ pQueryMsg->intervalTime = htobe64(pQueryMsg->intervalTime);
pQueryMsg->slidingTime = htobe64(pQueryMsg->slidingTime);
pQueryMsg->numOfTagsCols = htons(pQueryMsg->numOfTagsCols);
@@ -1146,7 +1146,7 @@ int32_t vnodeConvertQueryMeterMsg(SQueryMeterMsg *pQueryMsg) {
"offset:%" PRId64,
pQueryMsg, pQueryMsg->numOfSids, pQueryMsg->skey, pQueryMsg->ekey, pQueryMsg->numOfGroupCols,
pQueryMsg->numOfTagsCols, pQueryMsg->order, pQueryMsg->orderType, pQueryMsg->orderByIdx,
- pQueryMsg->numOfOutputCols, pQueryMsg->numOfCols, pQueryMsg->nAggTimeInterval, pQueryMsg->interpoType,
+ pQueryMsg->numOfOutputCols, pQueryMsg->numOfCols, pQueryMsg->intervalTime, pQueryMsg->interpoType,
pQueryMsg->tsLen, pQueryMsg->limit, pQueryMsg->offset);
return 0;
diff --git a/src/vnode/detail/src/vnodeUtil.c b/src/vnode/detail/src/vnodeUtil.c
index 17a94e5b9a392a250cf126c411d471fa5d010370..feef9ed47324c8c32b64f7c5fb156e5a7c52bf21 100644
--- a/src/vnode/detail/src/vnodeUtil.c
+++ b/src/vnode/detail/src/vnodeUtil.c
@@ -372,18 +372,22 @@ void vnodeUpdateFilterColumnIndex(SQuery* pQuery) {
}
// set the column index in buffer for arithmetic operation
- if (pQuery->pSelectExpr != NULL) {
- for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
- SSqlBinaryExprInfo* pBinExprInfo = &pQuery->pSelectExpr[i].pBinExprInfo;
- if (pBinExprInfo->pBinExpr != NULL) {
- for (int16_t j = 0; j < pBinExprInfo->numOfCols; ++j) {
- for (int32_t k = 0; k < pQuery->numOfCols; ++k) {
- if (pBinExprInfo->pReqColumns[j].colId == pQuery->colList[k].data.colId) {
- pBinExprInfo->pReqColumns[j].colIdxInBuf = pQuery->colList[k].colIdxInBuf;
- assert(pQuery->colList[k].colIdxInBuf == k);
- break;
- }
- }
+ if (pQuery->pSelectExpr == NULL) {
+ return;
+ }
+
+ for (int32_t i = 0; i < pQuery->numOfOutputCols; ++i) {
+ SSqlBinaryExprInfo* pBinExprInfo = &pQuery->pSelectExpr[i].pBinExprInfo;
+ if (pBinExprInfo->pBinExpr == NULL) {
+ continue;
+ }
+
+ for (int16_t j = 0; j < pBinExprInfo->numOfCols; ++j) {
+ for (int32_t k = 0; k < pQuery->numOfCols; ++k) {
+ if (pBinExprInfo->pReqColumns[j].colId == pQuery->colList[k].data.colId) {
+ pBinExprInfo->pReqColumns[j].colIdxInBuf = pQuery->colList[k].colIdxInBuf;
+ assert(pQuery->colList[k].colIdxInBuf == k);
+ break;
}
}
}