diff --git a/src/query/inc/tdigest.h b/src/query/inc/tdigest.h new file mode 100644 index 0000000000000000000000000000000000000000..085e4ac55e0b63c8fd8ddfe8af96d213df7e9481 --- /dev/null +++ b/src/query/inc/tdigest.h @@ -0,0 +1,47 @@ +/* + * include/tdigest.c + * + * Copyright (c) 2016, Usman Masood + */ + +#ifndef TDIGEST_H +#define TDIGEST_H + +#define DEFAULT_COMPRESSION 400 + +typedef struct Centroid { + long long weight; + double mean; +}Centroid; + +typedef struct Point { + double value; + long long weight; + struct Point *next; +}Point; + +typedef struct TDigest { + double compression; + int threshold; + long long size; + + long long total_weight; + double min; + double max; + + int num_buffered_pts; + Point *buffered_pts; + + int num_centroids; + Centroid *centroids; +}TDigest; + +extern struct TDigest *tdigestNew(int compression); +extern void tdigestAdd(struct TDigest *t, double x, long long w); +extern void tdigestMerge(struct TDigest *t1, struct TDigest *t2); +extern double tdigestCDF(struct TDigest *t, double x); +extern double tdigestQuantile(struct TDigest *t, double q); +extern void tdigestCompress(struct TDigest *t); +extern void tdigestFree(struct TDigest *t); + +#endif /* TDIGEST_H */ diff --git a/src/query/src/qAggMain.c b/src/query/src/qAggMain.c index c0c6d7a1404dbef6bdb00bd676a30fcfc908671a..81c39d6fc7d66725508738f31382a36f8a05ee1d 100644 --- a/src/query/src/qAggMain.c +++ b/src/query/src/qAggMain.c @@ -16,28 +16,29 @@ #include "os.h" #include "taosdef.h" #include "taosmsg.h" +#include "tdigest.h" #include "texpr.h" -#include "ttype.h" -#include "tsdb.h" #include "tglobal.h" +#include "tsdb.h" +#include "ttype.h" #include "qAggMain.h" #include "qFill.h" #include "qHistogram.h" #include "qPercentile.h" #include "qTsbuf.h" -#include "queryLog.h" #include "qUdf.h" +#include "queryLog.h" #define GET_INPUT_DATA_LIST(x) ((char *)((x)->pInput)) #define GET_INPUT_DATA(x, y) (GET_INPUT_DATA_LIST(x) + (y) * (x)->inputBytes) -#define GET_TS_LIST(x) ((TSKEY*)((x)->ptsList)) +#define GET_TS_LIST(x) ((TSKEY *)((x)->ptsList)) #define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)]) #define GET_TRUE_DATA_TYPE() \ int32_t type = 0; \ - if (pCtx->currentStage == MERGE_STAGE) { \ + if (pCtx->currentStage == MERGE_STAGE) { \ type = pCtx->outputType; \ assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); \ } else { \ @@ -66,12 +67,12 @@ } \ } while (0) -#define DO_UPDATE_TAG_COLUMNS_WITHOUT_TS(ctx) \ - do { \ +#define DO_UPDATE_TAG_COLUMNS_WITHOUT_TS(ctx) \ + do { \ for (int32_t _i = 0; _i < (ctx)->tagInfo.numOfTagCols; ++_i) { \ - SQLFunctionCtx *__ctx = (ctx)->tagInfo.pTagCtxList[_i]; \ - aAggs[TSDB_FUNC_TAG].xFunction(__ctx); \ - } \ + SQLFunctionCtx *__ctx = (ctx)->tagInfo.pTagCtxList[_i]; \ + aAggs[TSDB_FUNC_TAG].xFunction(__ctx); \ + } \ } while (0); void noop1(SQLFunctionCtx *UNUSED_PARAM(pCtx)) {} @@ -145,6 +146,7 @@ typedef struct SLeastsquaresInfo { typedef struct SAPercentileInfo { SHistogramInfo *pHisto; + TDigest* pTDigest; } SAPercentileInfo; typedef struct STSCompInfo { @@ -152,31 +154,31 @@ typedef struct STSCompInfo { } STSCompInfo; typedef struct SRateInfo { - double correctionValue; - double firstValue; - TSKEY firstKey; - double lastValue; - TSKEY lastKey; - int8_t hasResult; // flag to denote has value - bool isIRate; // true for IRate functions, false for Rate functions + double correctionValue; + double firstValue; + TSKEY firstKey; + double lastValue; + TSKEY lastKey; + int8_t hasResult; // flag to denote has value + bool isIRate; // true for IRate functions, false for Rate functions } SRateInfo; typedef struct SDerivInfo { - double prevValue; // previous value - TSKEY prevTs; // previous timestamp - bool ignoreNegative;// ignore the negative value - int64_t tsWindow; // time window for derivative - bool valueSet; // the value has been set already + double prevValue; // previous value + TSKEY prevTs; // previous timestamp + bool ignoreNegative; // ignore the negative value + int64_t tsWindow; // time window for derivative + bool valueSet; // the value has been set already } SDerivInfo; int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionId, int32_t param, int16_t *type, - int16_t *bytes, int32_t *interBytes, int16_t extLength, bool isSuperTable, SUdfInfo* pUdfInfo) { + int16_t *bytes, int32_t *interBytes, int16_t extLength, bool isSuperTable, + SUdfInfo *pUdfInfo) { if (!isValidDataType(dataType)) { qError("Illegal data type %d or data type length %d", dataType, dataBytes); return TSDB_CODE_TSC_INVALID_OPERATION; } - if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TS_DUMMY || functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_INTERP) { @@ -191,11 +193,12 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } - + // (uid, tid) + VGID + TAGSIZE + VARSTR_HEADER_SIZE - if (functionId == TSDB_FUNC_TID_TAG) { // todo use struct + if (functionId == TSDB_FUNC_TID_TAG) { // todo use struct *type = TSDB_DATA_TYPE_BINARY; - *bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE); + *bytes = (int16_t)(dataBytes + sizeof(int16_t) + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + + VARSTR_HEADER_SIZE); *interBytes = 0; return TSDB_CODE_SUCCESS; } @@ -206,21 +209,21 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *interBytes = 0; return TSDB_CODE_SUCCESS; } - + if (functionId == TSDB_FUNC_COUNT) { *type = TSDB_DATA_TYPE_BIGINT; *bytes = sizeof(int64_t); *interBytes = 0; return TSDB_CODE_SUCCESS; } - + if (functionId == TSDB_FUNC_ARITHM) { *type = TSDB_DATA_TYPE_DOUBLE; *bytes = sizeof(double); *interBytes = 0; return TSDB_CODE_SUCCESS; } - + if (functionId == TSDB_FUNC_TS_COMP) { *type = TSDB_DATA_TYPE_BINARY; *bytes = 1; // this results is compressed ts data, only one byte @@ -254,20 +257,20 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *type = TSDB_DATA_TYPE_BINARY; *bytes = (int16_t)(dataBytes + DATA_SET_FLAG_SIZE); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_SUM) { *type = TSDB_DATA_TYPE_BINARY; *bytes = sizeof(SSumInfo); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_AVG) { *type = TSDB_DATA_TYPE_BINARY; *bytes = sizeof(SAvgInfo); *interBytes = *bytes; return TSDB_CODE_SUCCESS; - + } else if (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_IRATE) { *type = TSDB_DATA_TYPE_DOUBLE; *bytes = sizeof(SRateInfo); @@ -277,25 +280,25 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *type = TSDB_DATA_TYPE_BINARY; *bytes = (int16_t)(sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_SPREAD) { *type = TSDB_DATA_TYPE_BINARY; *bytes = sizeof(SSpreadInfo); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_APERCT) { *type = TSDB_DATA_TYPE_BINARY; *bytes = sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1) + sizeof(SHistogramInfo) + sizeof(SAPercentileInfo); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_LAST_ROW) { *type = TSDB_DATA_TYPE_BINARY; *bytes = (int16_t)(sizeof(SLastrowInfo) + dataBytes); *interBytes = *bytes; - + return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_TWA) { *type = TSDB_DATA_TYPE_DOUBLE; @@ -313,15 +316,14 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI } else { *type = TSDB_DATA_TYPE_DOUBLE; } - + *bytes = sizeof(int64_t); *interBytes = sizeof(SSumInfo); return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_APERCT) { *type = TSDB_DATA_TYPE_DOUBLE; *bytes = sizeof(double); - *interBytes = - sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1); + *interBytes = sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1); return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_TWA) { *type = TSDB_DATA_TYPE_DOUBLE; @@ -382,9 +384,9 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { *type = (int16_t)dataType; *bytes = (int16_t)dataBytes; - + size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; - + // the output column may be larger than sizeof(STopBotInfo) *interBytes = (int32_t)size; } else if (functionId == TSDB_FUNC_LAST_ROW) { @@ -399,14 +401,14 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI } else { return TSDB_CODE_TSC_INVALID_OPERATION; } - + return TSDB_CODE_SUCCESS; } // TODO use hash table -int32_t isValidFunction(const char* name, int32_t len) { - for(int32_t i = 0; i <= TSDB_FUNC_BLKINFO; ++i) { - int32_t nameLen = (int32_t) strlen(aAggs[i].name); +int32_t isValidFunction(const char *name, int32_t len) { + for (int32_t i = 0; i <= TSDB_FUNC_BLKINFO; ++i) { + int32_t nameLen = (int32_t)strlen(aAggs[i].name); if (len != nameLen) { continue; } @@ -419,11 +421,11 @@ int32_t isValidFunction(const char* name, int32_t len) { return -1; } -static bool function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { +static bool function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (pResultInfo->initialized) { return false; } - + memset(pCtx->pOutput, 0, (size_t)pCtx->outputBytes); initResultInfo(pResultInfo, pCtx->interBufBytes); return true; @@ -441,7 +443,7 @@ static void function_finalizer(SQLFunctionCtx *pCtx) { if (pResInfo->hasResult != DATA_SET_FLAG) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); } - + doFinalizer(pCtx); } @@ -451,7 +453,7 @@ static void function_finalizer(SQLFunctionCtx *pCtx) { */ static void count_function(SQLFunctionCtx *pCtx) { int32_t numOfElem = 0; - + /* * 1. column data missing (schema modified) causes pCtx->hasNull == true. pCtx->preAggVals.isSet == true; * 2. for general non-primary key columns, pCtx->hasNull may be true or false, pCtx->preAggVals.isSet == true; @@ -466,19 +468,20 @@ static void count_function(SQLFunctionCtx *pCtx) { if (isNull(val, pCtx->inputType)) { continue; } - + numOfElem += 1; } } else { - //when counting on the primary time stamp column and no statistics data is presented, use the size value directly. + // when counting on the primary time stamp column and no statistics data is presented, use the size value + // directly. numOfElem = pCtx->size; } } - + if (numOfElem > 0) { GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } - + *((int64_t *)pCtx->pOutput) += numOfElem; SET_VAL(pCtx, numOfElem, 1); } @@ -488,7 +491,7 @@ static void count_func_merge(SQLFunctionCtx *pCtx) { for (int32_t i = 0; i < pCtx->size; ++i) { *((int64_t *)pCtx->pOutput) += pData[i]; } - + SET_VAL(pCtx, pCtx->size, 1); } @@ -501,7 +504,7 @@ static void count_func_merge(SQLFunctionCtx *pCtx) { * @param filterCols * @return */ -int32_t countRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { +int32_t countRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { if (colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { return BLK_DATA_NO_NEEDED; } else { @@ -509,34 +512,32 @@ int32_t countRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { } } -int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { - return BLK_DATA_NO_NEEDED; -} -#define LIST_ADD_N_DOUBLE_FLOAT(x, ctx, p, t, numOfElem, tsdbType) \ - do { \ - t *d = (t *)(p); \ - for (int32_t i = 0; i < (ctx)->size; ++i) { \ - if (((ctx)->hasNull) && isNull((char *)&(d)[i], tsdbType)) { \ - continue; \ - }; \ - SET_DOUBLE_VAL(&(x) , GET_DOUBLE_VAL(&(x)) + GET_FLOAT_VAL(&(d)[i])); \ - (numOfElem)++; \ - } \ - } while(0) -#define LIST_ADD_N_DOUBLE(x, ctx, p, t, numOfElem, tsdbType) \ - do { \ +int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { return BLK_DATA_NO_NEEDED; } +#define LIST_ADD_N_DOUBLE_FLOAT(x, ctx, p, t, numOfElem, tsdbType) \ + do { \ + t *d = (t *)(p); \ + for (int32_t i = 0; i < (ctx)->size; ++i) { \ + if (((ctx)->hasNull) && isNull((char *)&(d)[i], tsdbType)) { \ + continue; \ + }; \ + SET_DOUBLE_VAL(&(x), GET_DOUBLE_VAL(&(x)) + GET_FLOAT_VAL(&(d)[i])); \ + (numOfElem)++; \ + } \ + } while (0) +#define LIST_ADD_N_DOUBLE(x, ctx, p, t, numOfElem, tsdbType) \ + do { \ t *d = (t *)(p); \ for (int32_t i = 0; i < (ctx)->size; ++i) { \ if (((ctx)->hasNull) && isNull((char *)&(d)[i], tsdbType)) { \ continue; \ }; \ - SET_DOUBLE_VAL(&(x) , (x) + (d)[i]); \ + SET_DOUBLE_VAL(&(x), (x) + (d)[i]); \ (numOfElem)++; \ } \ - } while(0) + } while (0) #define LIST_ADD_N(x, ctx, p, t, numOfElem, tsdbType) \ - do { \ + do { \ t *d = (t *)(p); \ for (int32_t i = 0; i < (ctx)->size; ++i) { \ if (((ctx)->hasNull) && isNull((char *)&(d)[i], tsdbType)) { \ @@ -545,7 +546,7 @@ int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { (x) += (d)[i]; \ (numOfElem)++; \ } \ - } while(0) + } while (0) #define UPDATE_DATA(ctx, left, right, num, sign, k) \ do { \ @@ -570,7 +571,7 @@ int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { if ((ctx)->hasNull && isNull((char *)&(list)[i], tsdbType)) { \ continue; \ } \ - TSKEY key = (ctx)->ptsList != NULL? GET_TS_DATA(ctx, i):0; \ + TSKEY key = (ctx)->ptsList != NULL ? GET_TS_DATA(ctx, i) : 0; \ UPDATE_DATA(ctx, val, (list)[i], num, sign, key); \ } @@ -583,12 +584,12 @@ int32_t noDataRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { static void do_sum(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; - + // Only the pre-computing information loaded and actual data does not loaded if (pCtx->preAggVals.isSet) { notNullElems = pCtx->size - pCtx->preAggVals.statis.numOfNull; assert(pCtx->size >= pCtx->preAggVals.statis.numOfNull); - + if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { int64_t *retVal = (int64_t *)pCtx->pOutput; *retVal += pCtx->preAggVals.statis.sum; @@ -596,8 +597,8 @@ static void do_sum(SQLFunctionCtx *pCtx) { uint64_t *retVal = (uint64_t *)pCtx->pOutput; *retVal += (uint64_t)pCtx->preAggVals.statis.sum; } else if (IS_FLOAT_TYPE(pCtx->inputType)) { - double *retVal = (double*) pCtx->pOutput; - SET_DOUBLE_VAL(retVal, *retVal + GET_DOUBLE_VAL((const char*)&(pCtx->preAggVals.statis.sum))); + double *retVal = (double *)pCtx->pOutput; + SET_DOUBLE_VAL(retVal, *retVal + GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.sum))); } } else { // computing based on the true data block void *pData = GET_INPUT_DATA_LIST(pCtx); @@ -635,10 +636,10 @@ static void do_sum(SQLFunctionCtx *pCtx) { LIST_ADD_N_DOUBLE_FLOAT(*retVal, pCtx, pData, float, notNullElems, pCtx->inputType); } } - + // data in the check operation are all null, not output SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } @@ -646,7 +647,7 @@ static void do_sum(SQLFunctionCtx *pCtx) { static void sum_function(SQLFunctionCtx *pCtx) { do_sum(pCtx); - + // keep the result data in output buffer, not in the intermediate buffer SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); if (pResInfo->hasResult == DATA_SET_FLAG && pCtx->stableQuery) { @@ -674,7 +675,7 @@ static void sum_func_merge(SQLFunctionCtx *pCtx) { if (IS_SIGNED_NUMERIC_TYPE(type)) { *(int64_t *)pCtx->pOutput += pInput->isum; } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { - *(uint64_t *) pCtx->pOutput += pInput->usum; + *(uint64_t *)pCtx->pOutput += pInput->usum; } else { SET_DOUBLE_VAL((double *)pCtx->pOutput, *(double *)pCtx->pOutput + pInput->dsum); } @@ -682,26 +683,22 @@ static void sum_func_merge(SQLFunctionCtx *pCtx) { SET_VAL(pCtx, notNullElems, 1); SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + if (notNullElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; } } -static int32_t statisRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { - return BLK_DATA_STATIS_NEEDED; -} +static int32_t statisRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { return BLK_DATA_STATIS_NEEDED; } -static int32_t dataBlockRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { - return BLK_DATA_ALL_NEEDED; -} +static int32_t dataBlockRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { return BLK_DATA_ALL_NEEDED; } // todo: if column in current data block are null, opt for this case -static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { +static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { if (pCtx->order == TSDB_ORDER_DESC) { return BLK_DATA_NO_NEEDED; } - + // no result for first query, data block is required if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) { return BLK_DATA_ALL_NEEDED; @@ -710,11 +707,11 @@ static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t c } } -static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { +static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { if (pCtx->order != pCtx->param[0].i64) { return BLK_DATA_NO_NEEDED; } - + if (GET_RES_INFO(pCtx) == NULL || GET_RES_INFO(pCtx)->numOfRes <= 0) { return BLK_DATA_ALL_NEEDED; } else { @@ -722,7 +719,7 @@ static int32_t lastFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t co } } -static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { +static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { if (pCtx->order == TSDB_ORDER_DESC) { return BLK_DATA_NO_NEEDED; } @@ -734,7 +731,7 @@ static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32 // the pCtx should be set to current Ctx and output buffer before call this function. Otherwise, pCtx->pOutput is // the previous windowRes output buffer, not current unloaded block. In this case, the following filter is invalid - SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->pOutput + pCtx->inputBytes); + SFirstLastInfo *pInfo = (SFirstLastInfo *)(pCtx->pOutput + pCtx->inputBytes); if (pInfo->hasResult != DATA_SET_FLAG) { return BLK_DATA_ALL_NEEDED; } else { // data in current block is not earlier than current result @@ -742,7 +739,7 @@ static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32 } } -static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t colId) { +static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow *w, int32_t colId) { if (pCtx->order != pCtx->param[0].i64) { return BLK_DATA_NO_NEEDED; } @@ -754,7 +751,7 @@ static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_ // the pCtx should be set to current Ctx and output buffer before call this function. Otherwise, pCtx->pOutput is // the previous windowRes output buffer, not current unloaded block. In this case, the following filter is invalid - SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->pOutput + pCtx->inputBytes); + SFirstLastInfo *pInfo = (SFirstLastInfo *)(pCtx->pOutput + pCtx->inputBytes); if (pInfo->hasResult != DATA_SET_FLAG) { return BLK_DATA_ALL_NEEDED; } else { @@ -770,27 +767,27 @@ static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_ */ static void avg_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; - + // NOTE: keep the intermediate result into the interResultBuf SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo); - double *pVal = &pAvgInfo->sum; - - if (pCtx->preAggVals.isSet) { // Pre-aggregation + double * pVal = &pAvgInfo->sum; + + if (pCtx->preAggVals.isSet) { // Pre-aggregation notNullElems = pCtx->size - pCtx->preAggVals.statis.numOfNull; assert(notNullElems >= 0); - + if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { *pVal += pCtx->preAggVals.statis.sum; - } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inputType)) { - *pVal += (uint64_t) pCtx->preAggVals.statis.sum; + } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inputType)) { + *pVal += (uint64_t)pCtx->preAggVals.statis.sum; } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { *pVal += GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.sum)); } } else { void *pData = GET_INPUT_DATA_LIST(pCtx); - + if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { LIST_ADD_N(*pVal, pCtx, pData, int8_t, notNullElems, pCtx->inputType); } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { @@ -813,18 +810,18 @@ static void avg_function(SQLFunctionCtx *pCtx) { LIST_ADD_N(*pVal, pCtx, pData, uint64_t, notNullElems, pCtx->inputType); } } - + if (!pCtx->hasNull) { assert(notNullElems == pCtx->size); } - + SET_VAL(pCtx, notNullElems, 1); pAvgInfo->num += notNullElems; - + if (notNullElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; } - + // keep the data into the final output buffer for super table query since this execution may be the last one if (pCtx->stableQuery) { memcpy(pCtx->pOutput, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SAvgInfo)); @@ -833,18 +830,18 @@ static void avg_function(SQLFunctionCtx *pCtx) { static void avg_func_merge(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - - double *sum = (double*) pCtx->pOutput; - char *input = GET_INPUT_DATA_LIST(pCtx); - + + double *sum = (double *)pCtx->pOutput; + char * input = GET_INPUT_DATA_LIST(pCtx); + for (int32_t i = 0; i < pCtx->size; ++i, input += pCtx->inputBytes) { SAvgInfo *pInput = (SAvgInfo *)input; if (pInput->num == 0) { // current input is null continue; } - + SET_DOUBLE_VAL(sum, *sum + pInput->sum); - + // keep the number of data into the temp buffer *(int64_t *)GET_ROWCELL_INTERBUF(pResInfo) += pInput->num; } @@ -855,28 +852,28 @@ static void avg_func_merge(SQLFunctionCtx *pCtx) { */ static void avg_finalizer(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + if (pCtx->currentStage == MERGE_STAGE) { assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); - + if (GET_INT64_VAL(GET_ROWCELL_INTERBUF(pResInfo)) <= 0) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - SET_DOUBLE_VAL((double *)pCtx->pOutput,(*(double *)pCtx->pOutput) / *(int64_t *)GET_ROWCELL_INTERBUF(pResInfo)); + SET_DOUBLE_VAL((double *)pCtx->pOutput, (*(double *)pCtx->pOutput) / *(int64_t *)GET_ROWCELL_INTERBUF(pResInfo)); } else { // this is the secondary merge, only in the secondary merge, the input type is TSDB_DATA_TYPE_BINARY assert(IS_NUMERIC_TYPE(pCtx->inputType)); SAvgInfo *pAvgInfo = (SAvgInfo *)GET_ROWCELL_INTERBUF(pResInfo); - + if (pAvgInfo->num == 0) { // all data are NULL or empty table setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - + SET_DOUBLE_VAL((double *)pCtx->pOutput, pAvgInfo->sum / pAvgInfo->num); } - + // cannot set the numOfIteratedElems again since it is set during previous iteration GET_RES_INFO(pCtx)->numOfRes = 1; doFinalizer(pCtx); @@ -894,9 +891,9 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, return; } - void* tval = NULL; + void * tval = NULL; int16_t index = 0; - + if (isMin) { tval = &pCtx->preAggVals.statis.min; index = pCtx->preAggVals.statis.minIndex; @@ -904,7 +901,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, tval = &pCtx->preAggVals.statis.max; index = pCtx->preAggVals.statis.maxIndex; } - + TSKEY key = TSKEY_INITIAL_VAL; if (pCtx->ptsList != NULL) { /** @@ -913,30 +910,30 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, * * The following codes of 3 lines will be removed later. */ -// if (index < 0 || index >= pCtx->size + pCtx->startOffset) { -// index = 0; -// } + // if (index < 0 || index >= pCtx->size + pCtx->startOffset) { + // index = 0; + // } // the index is the original position, not the relative position key = pCtx->ptsList[index]; } - + if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { int64_t val = GET_INT64_VAL(tval); if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { int8_t *data = (int8_t *)pOutput; - + UPDATE_DATA(pCtx, *data, (int8_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { int16_t *data = (int16_t *)pOutput; - + UPDATE_DATA(pCtx, *data, (int16_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { int32_t *data = (int32_t *)pOutput; #if defined(_DEBUG_VIEW) qDebug("max value updated according to pre-cal:%d", *data); #endif - + if ((*data < val) ^ isMin) { *data = (int32_t)val; for (int32_t i = 0; i < (pCtx)->tagInfo.numOfTagCols; ++i) { @@ -945,7 +942,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, __ctx->tag.i64 = key; __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; } - + aAggs[TSDB_FUNC_TAG].xFunction(__ctx); } } @@ -970,25 +967,25 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); } } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE) { - double *data = (double *)pOutput; - double val = GET_DOUBLE_VAL(tval); + double *data = (double *)pOutput; + double val = GET_DOUBLE_VAL(tval); - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { float *data = (float *)pOutput; double val = GET_DOUBLE_VAL(tval); - + UPDATE_DATA(pCtx, *data, (float)val, notNullElems, isMin, key); } - + return; } - - void *p = GET_INPUT_DATA_LIST(pCtx); + + void * p = GET_INPUT_DATA_LIST(pCtx); TSKEY *tsList = GET_TS_LIST(pCtx); *notNullElems = 0; - + if (IS_SIGNED_NUMERIC_TYPE(pCtx->inputType)) { if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { TYPED_LOOPCHECK_N(int8_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); @@ -996,20 +993,20 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, TYPED_LOOPCHECK_N(int16_t, pOutput, p, pCtx, pCtx->inputType, isMin, *notNullElems); } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { int32_t *pData = p; - int32_t *retVal = (int32_t*) pOutput; - + int32_t *retVal = (int32_t *)pOutput; + for (int32_t i = 0; i < pCtx->size; ++i) { - if (pCtx->hasNull && isNull((const char*)&pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } - + if ((*retVal < pData[i]) ^ isMin) { *retVal = pData[i]; TSKEY k = tsList[i]; - + DO_UPDATE_TAG_COLUMNS(pCtx, k); } - + *notNullElems += 1; } #if defined(_DEBUG_VIEW) @@ -1035,19 +1032,19 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, } } -static bool min_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { +static bool min_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; // not initialized since it has been initialized } - + GET_TRUE_DATA_TYPE(); - + switch (type) { case TSDB_DATA_TYPE_TINYINT: *((int8_t *)pCtx->pOutput) = INT8_MAX; break; case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *) pCtx->pOutput = UINT8_MAX; + *(uint8_t *)pCtx->pOutput = UINT8_MAX; break; case TSDB_DATA_TYPE_SMALLINT: *((int16_t *)pCtx->pOutput) = INT16_MAX; @@ -1080,13 +1077,13 @@ static bool min_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo return true; } -static bool max_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { +static bool max_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; // not initialized since it has been initialized } - + GET_TRUE_DATA_TYPE(); - + switch (type) { case TSDB_DATA_TYPE_INT: *((int32_t *)pCtx->pOutput) = INT32_MIN; @@ -1121,7 +1118,7 @@ static bool max_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo default: qError("illegal data type:%d in min/max query", pCtx->inputType); } - + return true; } @@ -1131,13 +1128,13 @@ static bool max_func_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo static void min_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; minMax_function(pCtx, pCtx->pOutput, 1, ¬NullElems); - + SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; - + // set the flag for super table query if (pCtx->stableQuery) { *(pCtx->pOutput + pCtx->inputBytes) = DATA_SET_FLAG; @@ -1148,13 +1145,13 @@ static void min_function(SQLFunctionCtx *pCtx) { static void max_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; minMax_function(pCtx, pCtx->pOutput, 0, ¬NullElems); - + SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; - + // set the flag for super table query if (pCtx->stableQuery) { *(pCtx->pOutput + pCtx->inputBytes) = DATA_SET_FLAG; @@ -1164,16 +1161,16 @@ static void max_function(SQLFunctionCtx *pCtx) { static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *output, bool isMin) { int32_t notNullElems = 0; - + GET_TRUE_DATA_TYPE(); assert(pCtx->stableQuery); - + for (int32_t i = 0; i < pCtx->size; ++i) { char *input = GET_INPUT_DATA(pCtx, i); if (input[bytes] != DATA_SET_FLAG) { continue; } - + switch (type) { case TSDB_DATA_TYPE_TINYINT: { int8_t v = GET_INT8_VAL(input); @@ -1189,12 +1186,12 @@ static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *outp int32_t v = GET_INT32_VAL(input); if ((*(int32_t *)output < v) ^ isMin) { *(int32_t *)output = v; - + for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { SQLFunctionCtx *__ctx = pCtx->tagInfo.pTagCtxList[j]; aAggs[TSDB_FUNC_TAG].xFunction(__ctx); } - + notNullElems++; } break; @@ -1243,15 +1240,15 @@ static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *outp break; } } - + return notNullElems; } static void min_func_merge(SQLFunctionCtx *pCtx) { int32_t notNullElems = minmax_merge_impl(pCtx, pCtx->outputBytes, pCtx->pOutput, 1); - + SET_VAL(pCtx, notNullElems, 1); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); if (notNullElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; @@ -1260,9 +1257,9 @@ static void min_func_merge(SQLFunctionCtx *pCtx) { static void max_func_merge(SQLFunctionCtx *pCtx) { int32_t numOfElem = minmax_merge_impl(pCtx, pCtx->outputBytes, pCtx->pOutput, 0); - + SET_VAL(pCtx, numOfElem, 1); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); if (numOfElem > 0) { pResInfo->hasResult = DATA_SET_FLAG; @@ -1280,13 +1277,13 @@ static void max_func_merge(SQLFunctionCtx *pCtx) { static void stddev_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SStddevInfo *pStd = GET_ROWCELL_INTERBUF(pResInfo); + SStddevInfo * pStd = GET_ROWCELL_INTERBUF(pResInfo); if (pCtx->currentStage == REPEAT_SCAN && pStd->stage == 0) { pStd->stage++; avg_finalizer(pCtx); - pResInfo->initialized = true; // set it initialized to avoid re-initialization + pResInfo->initialized = true; // set it initialized to avoid re-initialization // save average value into tmpBuf, for second stage scan SAvgInfo *pAvg = GET_ROWCELL_INTERBUF(pResInfo); @@ -1294,7 +1291,7 @@ static void stddev_function(SQLFunctionCtx *pCtx) { pStd->avg = GET_DOUBLE_VAL(pCtx->pOutput); assert((isnan(pAvg->sum) && pAvg->num == 0) || (pStd->num == pAvg->num && pStd->avg == pAvg->sum)); } - + if (pStd->stage == 0) { // the first stage is to calculate average value avg_function(pCtx); @@ -1303,14 +1300,14 @@ static void stddev_function(SQLFunctionCtx *pCtx) { // if pStd->num == 0, there are no numbers in the first round check. No need to do the second round double *retVal = &pStd->res; double avg = pStd->avg; - - void *pData = GET_INPUT_DATA_LIST(pCtx); + + void * pData = GET_INPUT_DATA_LIST(pCtx); int32_t num = 0; switch (pCtx->inputType) { case TSDB_DATA_TYPE_INT: { for (int32_t i = 0; i < pCtx->size; ++i) { - if (pCtx->hasNull && isNull((const char*) (&((int32_t *)pData)[i]), pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)(&((int32_t *)pData)[i]), pCtx->inputType)) { continue; } num += 1; @@ -1357,14 +1354,14 @@ static void stddev_function(SQLFunctionCtx *pCtx) { default: qError("stddev function not support data type:%d", pCtx->inputType); } - + SET_VAL(pCtx, 1, 1); } } static void stddev_finalizer(SQLFunctionCtx *pCtx) { SStddevInfo *pStd = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); - + if (pStd->num <= 0) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); } else { @@ -1372,19 +1369,19 @@ static void stddev_finalizer(SQLFunctionCtx *pCtx) { SET_DOUBLE_VAL(retValue, sqrt(pStd->res / pStd->num)); SET_VAL(pCtx, 1, 1); } - + doFinalizer(pCtx); } ////////////////////////////////////////////////////////////////////////////////////// -int32_t tsCompare(const void* p1, const void* p2) { - TSKEY k = *(TSKEY*)p1; - SResPair* pair = (SResPair*)p2; +int32_t tsCompare(const void *p1, const void *p2) { + TSKEY k = *(TSKEY *)p1; + SResPair *pair = (SResPair *)p2; if (k == pair->key) { return 0; } else { - return k < pair->key? -1:1; + return k < pair->key ? -1 : 1; } } @@ -1395,21 +1392,21 @@ static void stddev_dst_function(SQLFunctionCtx *pCtx) { double *retVal = &pStd->res; // all data are null, no need to proceed - SArray* resList = (SArray*) pCtx->param[0].pz; + SArray *resList = (SArray *)pCtx->param[0].pz; if (resList == NULL) { return; } // find the correct group average results according to the tag value - int32_t len = (int32_t) taosArrayGetSize(resList); + int32_t len = (int32_t)taosArrayGetSize(resList); assert(len > 0); double avg = 0; if (len == 1) { - SResPair* p = taosArrayGet(resList, 0); + SResPair *p = taosArrayGet(resList, 0); avg = p->avg; } else { // todo opt performance by using iterator since the timestamp lsit is matched with the output result - SResPair* p = bsearch(&pCtx->startTs, resList->pData, len, sizeof(SResPair), tsCompare); + SResPair *p = bsearch(&pCtx->startTs, resList->pData, len, sizeof(SResPair), tsCompare); if (p == NULL) { return; } @@ -1417,13 +1414,13 @@ static void stddev_dst_function(SQLFunctionCtx *pCtx) { avg = p->avg; } - void *pData = GET_INPUT_DATA_LIST(pCtx); + void * pData = GET_INPUT_DATA_LIST(pCtx); int32_t num = 0; switch (pCtx->inputType) { case TSDB_DATA_TYPE_INT: { for (int32_t i = 0; i < pCtx->size; ++i) { - if (pCtx->hasNull && isNull((const char*) (&((int32_t *)pData)[i]), pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)(&((int32_t *)pData)[i]), pCtx->inputType)) { continue; } num += 1; @@ -1480,9 +1477,9 @@ static void stddev_dst_function(SQLFunctionCtx *pCtx) { static void stddev_dst_merge(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SStddevdstInfo* pRes = GET_ROWCELL_INTERBUF(pResInfo); + SStddevdstInfo * pRes = GET_ROWCELL_INTERBUF(pResInfo); - char *input = GET_INPUT_DATA_LIST(pCtx); + char *input = GET_INPUT_DATA_LIST(pCtx); for (int32_t i = 0; i < pCtx->size; ++i, input += pCtx->inputBytes) { SStddevdstInfo *pInput = (SStddevdstInfo *)input; @@ -1510,15 +1507,15 @@ static void stddev_dst_finalizer(SQLFunctionCtx *pCtx) { } ////////////////////////////////////////////////////////////////////////////////////// -static bool first_last_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool first_last_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } - + // used to keep the timestamp for comparison pCtx->param[1].nType = 0; pCtx->param[1].i64 = 0; - + return true; } @@ -1527,16 +1524,16 @@ static void first_function(SQLFunctionCtx *pCtx) { if (pCtx->order == TSDB_ORDER_DESC) { return; } - + int32_t notNullElems = 0; - + // handle the null value for (int32_t i = 0; i < pCtx->size; ++i) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { continue; } - + memcpy(pCtx->pOutput, data, pCtx->inputBytes); if (pCtx->ptsList != NULL) { TSKEY k = GET_TS_DATA(pCtx, i); @@ -1546,24 +1543,24 @@ static void first_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pInfo = GET_RES_INFO(pCtx); pInfo->hasResult = DATA_SET_FLAG; pInfo->complete = true; - + notNullElems++; break; } - + SET_VAL(pCtx, notNullElems, 1); } static void first_data_assign_impl(SQLFunctionCtx *pCtx, char *pData, int32_t index) { int64_t *timestamp = GET_TS_LIST(pCtx); - + SFirstLastInfo *pInfo = (SFirstLastInfo *)(pCtx->pOutput + pCtx->inputBytes); - + if (pInfo->hasResult != DATA_SET_FLAG || timestamp[index] < pInfo->ts) { memcpy(pCtx->pOutput, pData, pCtx->inputBytes); pInfo->hasResult = DATA_SET_FLAG; pInfo->ts = timestamp[index]; - + DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); } } @@ -1578,10 +1575,10 @@ static void first_dist_function(SQLFunctionCtx *pCtx) { * 1. data block that are not loaded * 2. scan data files in desc order */ - if (pCtx->order == TSDB_ORDER_DESC/* || pCtx->preAggVals.dataBlockLoaded == false*/) { + if (pCtx->order == TSDB_ORDER_DESC /* || pCtx->preAggVals.dataBlockLoaded == false*/) { return; } - + int32_t notNullElems = 0; // find the first not null value @@ -1590,16 +1587,16 @@ static void first_dist_function(SQLFunctionCtx *pCtx) { if (pCtx->hasNull && isNull(data, pCtx->inputType)) { continue; } - + first_data_assign_impl(pCtx, data, i); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; - + notNullElems++; break; } - + SET_VAL(pCtx, notNullElems, 1); } @@ -1607,20 +1604,20 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) { assert(pCtx->stableQuery); char * pData = GET_INPUT_DATA_LIST(pCtx); - SFirstLastInfo *pInput = (SFirstLastInfo*) (pData + pCtx->outputBytes); + SFirstLastInfo *pInput = (SFirstLastInfo *)(pData + pCtx->outputBytes); if (pInput->hasResult != DATA_SET_FLAG) { return; } - + // The param[1] is used to keep the initial value of max ts value if (pCtx->param[1].nType != pCtx->outputType || pCtx->param[1].i64 > pInput->ts) { memcpy(pCtx->pOutput, pData, pCtx->outputBytes); pCtx->param[1].i64 = pInput->ts; pCtx->param[1].nType = pCtx->outputType; - + DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } - + SET_VAL(pCtx, 1, 1); GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } @@ -1638,11 +1635,10 @@ static void last_function(SQLFunctionCtx *pCtx) { return; } - SResultRowCellInfo* pResInfo = GET_RES_INFO(pCtx); + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); int32_t notNullElems = 0; if (pCtx->order == TSDB_ORDER_DESC) { - for (int32_t i = pCtx->size - 1; i >= 0; --i) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType) && (!pCtx->requireNull)) { @@ -1668,12 +1664,12 @@ static void last_function(SQLFunctionCtx *pCtx) { TSKEY ts = pCtx->ptsList ? GET_TS_DATA(pCtx, i) : 0; - char* buf = GET_ROWCELL_INTERBUF(pResInfo); - if (pResInfo->hasResult != DATA_SET_FLAG || (*(TSKEY*)buf) < ts) { + char *buf = GET_ROWCELL_INTERBUF(pResInfo); + if (pResInfo->hasResult != DATA_SET_FLAG || (*(TSKEY *)buf) < ts) { pResInfo->hasResult = DATA_SET_FLAG; memcpy(pCtx->pOutput, data, pCtx->inputBytes); - *(TSKEY*)buf = ts; + *(TSKEY *)buf = ts; DO_UPDATE_TAG_COLUMNS(pCtx, ts); } @@ -1687,18 +1683,18 @@ static void last_function(SQLFunctionCtx *pCtx) { static void last_data_assign_impl(SQLFunctionCtx *pCtx, char *pData, int32_t index) { int64_t *timestamp = GET_TS_LIST(pCtx); - + SFirstLastInfo *pInfo = (SFirstLastInfo *)(pCtx->pOutput + pCtx->inputBytes); - + if (pInfo->hasResult != DATA_SET_FLAG || pInfo->ts < timestamp[index]) { #if defined(_DEBUG_VIEW) qDebug("assign index:%d, ts:%" PRId64 ", val:%d, ", index, timestamp[index], *(int32_t *)pData); #endif - + memcpy(pCtx->pOutput, pData, pCtx->inputBytes); pInfo->hasResult = DATA_SET_FLAG; pInfo->ts = timestamp[index]; - + DO_UPDATE_TAG_COLUMNS(pCtx, pInfo->ts); } } @@ -1717,19 +1713,19 @@ static void last_dist_function(SQLFunctionCtx *pCtx) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { if (!pCtx->requireNull) { - continue; + continue; } } - + last_data_assign_impl(pCtx, data, i); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; - + notNullElems++; break; } - + SET_VAL(pCtx, notNullElems, 1); } @@ -1740,12 +1736,12 @@ static void last_dist_function(SQLFunctionCtx *pCtx) { */ static void last_dist_func_merge(SQLFunctionCtx *pCtx) { char *pData = GET_INPUT_DATA_LIST(pCtx); - - SFirstLastInfo *pInput = (SFirstLastInfo*) (pData + pCtx->outputBytes); + + SFirstLastInfo *pInput = (SFirstLastInfo *)(pData + pCtx->outputBytes); if (pInput->hasResult != DATA_SET_FLAG) { return; } - + /* * param[1] used to keep the corresponding timestamp to decide if current result is * the true last result @@ -1754,10 +1750,10 @@ static void last_dist_func_merge(SQLFunctionCtx *pCtx) { memcpy(pCtx->pOutput, pData, pCtx->outputBytes); pCtx->param[1].i64 = pInput->ts; pCtx->param[1].nType = pCtx->outputType; - + DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } - + SET_VAL(pCtx, 1, 1); GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } @@ -1772,16 +1768,16 @@ static void last_row_function(SQLFunctionCtx *pCtx) { // assign the last element in current data block assignVal(pCtx->pOutput, pData + (pCtx->size - 1) * pCtx->inputBytes, pCtx->inputBytes, pCtx->inputType); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; - + // set the result to final result buffer in case of super table query if (pCtx->stableQuery) { SLastrowInfo *pInfo1 = (SLastrowInfo *)(pCtx->pOutput + pCtx->inputBytes); pInfo1->ts = GET_TS_DATA(pCtx, pCtx->size - 1); pInfo1->hasResult = DATA_SET_FLAG; - + DO_UPDATE_TAG_COLUMNS(pCtx, pInfo1->ts); } else { TSKEY ts = GET_TS_DATA(pCtx, pCtx->size - 1); @@ -1798,7 +1794,7 @@ static void last_row_finalizer(SQLFunctionCtx *pCtx) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - + GET_RES_INFO(pCtx)->numOfRes = 1; doFinalizer(pCtx); } @@ -1809,18 +1805,18 @@ static void valuePairAssign(tValuePair *dst, int16_t type, const char *val, int6 dst->v.nType = type; dst->v.i64 = *(int64_t *)val; dst->timestamp = tsKey; - + int32_t size = 0; if (stage == MERGE_STAGE) { memcpy(dst->pTags, pTags, (size_t)pTagInfo->tagsLen); } else { // the tags are dumped from the ctx tag fields for (int32_t i = 0; i < pTagInfo->numOfTagCols; ++i) { - SQLFunctionCtx* ctx = pTagInfo->pTagCtxList[i]; + SQLFunctionCtx *ctx = pTagInfo->pTagCtxList[i]; if (ctx->functionId == TSDB_FUNC_TS_DUMMY) { ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; ctx->tag.i64 = tsKey; } - + tVariantDump(&ctx->tag, dst->pTags + size, ctx->tag.nType, true); size += pTagInfo->pTagCtxList[i]->outputBytes; } @@ -1834,11 +1830,10 @@ static void valuePairAssign(tValuePair *dst, int16_t type, const char *val, int6 memcpy((dst)->pTags, (src)->pTags, (size_t)(__l)); \ } while (0) -static int32_t topBotComparFn(const void *p1, const void *p2, const void *param) -{ - uint16_t type = *(uint16_t *) param; - tValuePair *val1 = *(tValuePair **) p1; - tValuePair *val2 = *(tValuePair **) p2; +static int32_t topBotComparFn(const void *p1, const void *p2, const void *param) { + uint16_t type = *(uint16_t *)param; + tValuePair *val1 = *(tValuePair **)p1; + tValuePair *val2 = *(tValuePair **)p2; if (IS_SIGNED_NUMERIC_TYPE(type)) { if (val1->v.i64 == val2->v.i64) { @@ -1846,12 +1841,12 @@ static int32_t topBotComparFn(const void *p1, const void *p2, const void *param) } return (val1->v.i64 > val2->v.i64) ? 1 : -1; - } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { - if (val1->v.u64 == val2->v.u64) { - return 0; - } + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + if (val1->v.u64 == val2->v.u64) { + return 0; + } - return (val1->v.u64 > val2->v.u64) ? 1 : -1; + return (val1->v.u64 > val2->v.u64) ? 1 : -1; } if (val1->v.dKey == val2->v.dKey) { @@ -1861,13 +1856,12 @@ static int32_t topBotComparFn(const void *p1, const void *p2, const void *param) return (val1->v.dKey > val2->v.dKey) ? 1 : -1; } -static void topBotSwapFn(void *dst, void *src, const void *param) -{ - char tag[32768]; - tValuePair temp; - uint16_t tagLen = *(uint16_t *) param; - tValuePair *vdst = *(tValuePair **) dst; - tValuePair *vsrc = *(tValuePair **) src; +static void topBotSwapFn(void *dst, void *src, const void *param) { + char tag[32768]; + tValuePair temp; + uint16_t tagLen = *(uint16_t *)param; + tValuePair *vdst = *(tValuePair **)dst; + tValuePair *vsrc = *(tValuePair **)src; memset(tag, 0, sizeof(tag)); temp.pTags = tag; @@ -1881,22 +1875,24 @@ static void do_top_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData, SExtTagsInfo *pTagInfo, char *pTags, int16_t stage) { tVariant val = {0}; tVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type); - + tValuePair **pList = pInfo->res; assert(pList != NULL); if (pInfo->num < maxLen) { valuePairAssign(pList[pInfo->num], type, (const char *)&val.i64, ts, pTags, pTagInfo, stage); - taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); - + taosheapsort((void *)pList, sizeof(tValuePair **), pInfo->num + 1, (const void *)&type, topBotComparFn, + (const void *)&pTagInfo->tagsLen, topBotSwapFn, 0); + pInfo->num++; } else { if ((IS_SIGNED_NUMERIC_TYPE(type) && val.i64 > pList[0]->v.i64) || (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u64 > pList[0]->v.u64) || (IS_FLOAT_TYPE(type) && val.dKey > pList[0]->v.dKey)) { valuePairAssign(pList[0], type, (const char *)&val.i64, ts, pTags, pTagInfo, stage); - taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 0); + taosheapadjust((void *)pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *)&type, topBotComparFn, + (const void *)&pTagInfo->tagsLen, topBotSwapFn, 0); } } } @@ -1912,7 +1908,8 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa if (pInfo->num < maxLen) { valuePairAssign(pList[pInfo->num], type, (const char *)&val.i64, ts, pTags, pTagInfo, stage); - taosheapsort((void *) pList, sizeof(tValuePair **), pInfo->num + 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); + taosheapsort((void *)pList, sizeof(tValuePair **), pInfo->num + 1, (const void *)&type, topBotComparFn, + (const void *)&pTagInfo->tagsLen, topBotSwapFn, 1); pInfo->num++; } else { @@ -1920,7 +1917,8 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u64 < pList[0]->v.u64) || (IS_FLOAT_TYPE(type) && val.dKey < pList[0]->v.dKey)) { valuePairAssign(pList[0], type, (const char *)&val.i64, ts, pTags, pTagInfo, stage); - taosheapadjust((void *) pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *) &type, topBotComparFn, (const void *) &pTagInfo->tagsLen, topBotSwapFn, 1); + taosheapadjust((void *)pList, sizeof(tValuePair **), 0, maxLen - 1, (const void *)&type, topBotComparFn, + (const void *)&pTagInfo->tagsLen, topBotSwapFn, 1); } } } @@ -1928,7 +1926,7 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa static int32_t resAscComparFn(const void *pLeft, const void *pRight) { tValuePair *pLeftElem = *(tValuePair **)pLeft; tValuePair *pRightElem = *(tValuePair **)pRight; - + if (pLeftElem->timestamp == pRightElem->timestamp) { return 0; } else { @@ -1941,14 +1939,14 @@ static int32_t resDescComparFn(const void *pLeft, const void *pRight) { return - static int32_t resDataAscComparFn(const void *pLeft, const void *pRight) { tValuePair *pLeftElem = *(tValuePair **)pLeft; tValuePair *pRightElem = *(tValuePair **)pRight; - + if (IS_FLOAT_TYPE(pLeftElem->v.nType)) { if (pLeftElem->v.dKey == pRightElem->v.dKey) { return 0; } else { return pLeftElem->v.dKey > pRightElem->v.dKey ? 1 : -1; } - } else if (IS_SIGNED_NUMERIC_TYPE(pLeftElem->v.nType)){ + } else if (IS_SIGNED_NUMERIC_TYPE(pLeftElem->v.nType)) { if (pLeftElem->v.i64 == pRightElem->v.i64) { return 0; } else { @@ -1967,13 +1965,13 @@ static int32_t resDataDescComparFn(const void *pLeft, const void *pRight) { retu static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - STopBotInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo); - + STopBotInfo * pRes = GET_ROWCELL_INTERBUF(pResInfo); + tValuePair **tvp = pRes->res; - + int32_t step = QUERY_ASC_FORWARD_STEP; int32_t len = (int32_t)(GET_RES_INFO(pCtx)->numOfRes); - + switch (type) { case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_INT: { @@ -2026,20 +2024,20 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { return; } } - + // set the output timestamp of each record. TSKEY *output = pCtx->ptsOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { *output = tvp[i]->timestamp; } - + // set the corresponding tag data for each record // todo check malloc failure char **pData = calloc(pCtx->tagInfo.numOfTagCols, POINTER_BYTES); for (int32_t i = 0; i < pCtx->tagInfo.numOfTagCols; ++i) { pData[i] = pCtx->tagInfo.pTagCtxList[i]->pOutput; } - + for (int32_t i = 0; i < len; ++i, output += step) { int16_t offset = 0; for (int32_t j = 0; j < pCtx->tagInfo.numOfTagCols; ++j) { @@ -2048,7 +2046,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { pData[j] += pCtx->tagInfo.pTagCtxList[j]->outputBytes; } } - + tfree(pData); } @@ -2065,13 +2063,13 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) { // only the first_stage_merge is directly written data into final output buffer if (pCtx->stableQuery && pCtx->currentStage != MERGE_STAGE) { - return (STopBotInfo*) pCtx->pOutput; - } else { // during normal table query and super table at the secondary_stage, result is written to intermediate buffer + return (STopBotInfo *)pCtx->pOutput; + } else { // during normal table query and super table at the secondary_stage, result is written to intermediate + // buffer return GET_ROWCELL_INTERBUF(pResInfo); } } - /* * keep the intermediate results during scan data blocks in the format of: * +-----------------------------------+-------------one value pair-----------+------------next value pair-----------+ @@ -2080,13 +2078,13 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) { */ static void buildTopBotStruct(STopBotInfo *pTopBotInfo, SQLFunctionCtx *pCtx) { char *tmp = (char *)pTopBotInfo + sizeof(STopBotInfo); - pTopBotInfo->res = (tValuePair**) tmp; + pTopBotInfo->res = (tValuePair **)tmp; tmp += POINTER_BYTES * pCtx->param[0].i64; size_t size = sizeof(tValuePair) + pCtx->tagInfo.tagsLen; for (int32_t i = 0; i < pCtx->param[0].i64; ++i) { - pTopBotInfo->res[i] = (tValuePair*) tmp; + pTopBotInfo->res[i] = (tValuePair *)tmp; pTopBotInfo->res[i]->pTags = tmp + sizeof(tValuePair); tmp += size; } @@ -2099,18 +2097,19 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const cha } STopBotInfo *pTopBotInfo = getTopBotOutputInfo(pCtx); - + // required number of results are not reached, continue load data block if (pTopBotInfo->num < pCtx->param[0].i64) { return true; } - - if ((void *)pTopBotInfo->res[0] != (void *)((char *)pTopBotInfo + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { + + if ((void *)pTopBotInfo->res[0] != + (void *)((char *)pTopBotInfo + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { buildTopBotStruct(pTopBotInfo, pCtx); } - tValuePair **pRes = (tValuePair**) pTopBotInfo->res; - + tValuePair **pRes = (tValuePair **)pTopBotInfo->res; + if (pCtx->functionId == TSDB_FUNC_TOP) { switch (pCtx->inputType) { case TSDB_DATA_TYPE_TINYINT: @@ -2148,11 +2147,11 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const cha } } -static bool top_bottom_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool top_bottom_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } - + STopBotInfo *pInfo = getTopBotOutputInfo(pCtx); buildTopBotStruct(pInfo, pCtx); return true; @@ -2167,27 +2166,27 @@ static void top_function(SQLFunctionCtx *pCtx) { if ((void *)pRes->res[0] != (void *)((char *)pRes + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { buildTopBotStruct(pRes, pCtx); } - + for (int32_t i = 0; i < pCtx->size; ++i) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { continue; } - + notNullElems++; // NOTE: Set the default timestamp if it is missing [todo refactor] - TSKEY ts = (pCtx->ptsList != NULL)? GET_TS_DATA(pCtx, i):0; + TSKEY ts = (pCtx->ptsList != NULL) ? GET_TS_DATA(pCtx, i) : 0; do_top_function_add(pRes, (int32_t)pCtx->param[0].i64, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); } - + if (!pCtx->hasNull) { assert(pCtx->size == notNullElems); } - + // treat the result as only one result SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; @@ -2196,21 +2195,21 @@ static void top_function(SQLFunctionCtx *pCtx) { static void top_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pInput = (STopBotInfo *)GET_INPUT_DATA_LIST(pCtx); - + // construct the input data struct from binary data buildTopBotStruct(pInput, pCtx); - + STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); - + // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { - int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->outputType; - do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64, &pInput->res[i]->v.i64, pInput->res[i]->timestamp, - type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); + int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT) ? TSDB_DATA_TYPE_DOUBLE : pCtx->outputType; + do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64, &pInput->res[i]->v.i64, pInput->res[i]->timestamp, type, + &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } - + SET_VAL(pCtx, pInput->num, pOutput->num); - + if (pOutput->num > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; @@ -2219,9 +2218,9 @@ static void top_func_merge(SQLFunctionCtx *pCtx) { static void bottom_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; - + STopBotInfo *pRes = getTopBotOutputInfo(pCtx); - + if ((void *)pRes->res[0] != (void *)((char *)pRes + sizeof(STopBotInfo) + POINTER_BYTES * pCtx->param[0].i64)) { buildTopBotStruct(pRes, pCtx); } @@ -2234,17 +2233,17 @@ static void bottom_function(SQLFunctionCtx *pCtx) { notNullElems++; // NOTE: Set the default timestamp if it is missing [todo refactor] - TSKEY ts = (pCtx->ptsList != NULL)? GET_TS_DATA(pCtx, i):0; + TSKEY ts = (pCtx->ptsList != NULL) ? GET_TS_DATA(pCtx, i) : 0; do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64, data, ts, pCtx->inputType, &pCtx->tagInfo, NULL, 0); } - + if (!pCtx->hasNull) { assert(pCtx->size == notNullElems); } - + // treat the result as only one result SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; @@ -2253,21 +2252,21 @@ static void bottom_function(SQLFunctionCtx *pCtx) { static void bottom_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pInput = (STopBotInfo *)GET_INPUT_DATA_LIST(pCtx); - + // construct the input data struct from binary data buildTopBotStruct(pInput, pCtx); - + STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); - + // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT) ? TSDB_DATA_TYPE_DOUBLE : pCtx->outputType; - do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64, &pInput->res[i]->v.i64, pInput->res[i]->timestamp, type, - &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); + do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64, &pInput->res[i]->v.i64, pInput->res[i]->timestamp, + type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } SET_VAL(pCtx, pInput->num, pOutput->num); - + if (pOutput->num > 0) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; @@ -2276,17 +2275,17 @@ static void bottom_func_merge(SQLFunctionCtx *pCtx) { static void top_bottom_func_finalizer(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + // data in temporary list is less than the required number of results, not enough qualified number of results STopBotInfo *pRes = GET_ROWCELL_INTERBUF(pResInfo); if (pRes->num == 0) { // no result assert(pResInfo->hasResult != DATA_SET_FLAG); // TODO: } - + GET_RES_INFO(pCtx)->numOfRes = pRes->num; tValuePair **tvp = pRes->res; - + // user specify the order of output by sort the result according to timestamp if (pCtx->param[1].i64 == PRIMARYKEY_TIMESTAMP_COL_INDEX) { __compar_fn_t comparator = (pCtx->param[2].i64 == TSDB_ORDER_ASC) ? resAscComparFn : resDescComparFn; @@ -2295,15 +2294,15 @@ static void top_bottom_func_finalizer(SQLFunctionCtx *pCtx) { __compar_fn_t comparator = (pCtx->param[2].i64 == TSDB_ORDER_ASC) ? resDataAscComparFn : resDataDescComparFn; qsort(tvp, (size_t)pResInfo->numOfRes, POINTER_BYTES, comparator); } - + GET_TRUE_DATA_TYPE(); copyTopBotRes(pCtx, type); - + doFinalizer(pCtx); } /////////////////////////////////////////////////////////////////////////////////////////////// -static bool percentile_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { +static bool percentile_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; } @@ -2319,9 +2318,9 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* static void percentile_function(SQLFunctionCtx *pCtx) { int32_t notNullElems = 0; - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SPercentileInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); + SPercentileInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo); if (pCtx->currentStage == REPEAT_SCAN && pInfo->stage == 0) { pInfo->stage += 1; @@ -2329,7 +2328,7 @@ static void percentile_function(SQLFunctionCtx *pCtx) { // all data are null, set it completed if (pInfo->numOfElems == 0) { pResInfo->complete = true; - + return; } else { pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval); @@ -2393,45 +2392,44 @@ static void percentile_function(SQLFunctionCtx *pCtx) { if (pCtx->hasNull && isNull(data, pCtx->inputType)) { continue; } - + notNullElems += 1; tMemBucketPut(pInfo->pMemBucket, data, 1); } - + SET_VAL(pCtx, notNullElems, 1); pResInfo->hasResult = DATA_SET_FLAG; } static void percentile_finalizer(SQLFunctionCtx *pCtx) { double v = pCtx->param[0].nType == TSDB_DATA_TYPE_INT ? pCtx->param[0].i64 : pCtx->param[0].dKey; - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SPercentileInfo* ppInfo = (SPercentileInfo *) GET_ROWCELL_INTERBUF(pResInfo); + SPercentileInfo * ppInfo = (SPercentileInfo *)GET_ROWCELL_INTERBUF(pResInfo); - tMemBucket * pMemBucket = ppInfo->pMemBucket; + tMemBucket *pMemBucket = ppInfo->pMemBucket; if (pMemBucket == NULL || pMemBucket->total == 0) { // check for null assert(ppInfo->numOfElems == 0); setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); } else { SET_DOUBLE_VAL((double *)pCtx->pOutput, getPercentile(pMemBucket, v)); } - + tMemBucketDestroy(pMemBucket); doFinalizer(pCtx); } -////////////////////////////////////////////////////////////////////////////////// -static void buildHistogramInfo(SAPercentileInfo* pInfo) { - pInfo->pHisto = (SHistogramInfo*) ((char*) pInfo + sizeof(SAPercentileInfo)); - pInfo->pHisto->elems = (SHistBin*) ((char*)pInfo->pHisto + sizeof(SHistogramInfo)); +static void buildHistogramInfo(SAPercentileInfo *pInfo) { + pInfo->pHisto = (SHistogramInfo *)((char *)pInfo + sizeof(SAPercentileInfo)); + pInfo->pHisto->elems = (SHistBin *)((char *)pInfo->pHisto + sizeof(SHistogramInfo)); } static SAPercentileInfo *getAPerctInfo(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SAPercentileInfo* pInfo = NULL; + SAPercentileInfo * pInfo = NULL; if (pCtx->stableQuery && pCtx->currentStage != MERGE_STAGE) { - pInfo = (SAPercentileInfo*) pCtx->pOutput; + pInfo = (SAPercentileInfo *)pCtx->pOutput; } else { pInfo = GET_ROWCELL_INTERBUF(pResInfo); } @@ -2440,72 +2438,192 @@ static SAPercentileInfo *getAPerctInfo(SQLFunctionCtx *pCtx) { return pInfo; } -static bool apercentile_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { + +// +// ----------------- tdigest ------------------- +// +////////////////////////////////////////////////////////////////////////////////// + +static bool tdigest_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; } + // new TDigest + SAPercentileInfo *pAPerc = getAPerctInfo(pCtx); + int compression = 5; + if(pAPerc) { + if(pAPerc->pTDigest == NULL) { + pAPerc->pTDigest = tdigestNew(compression); + } + } + return true; +} + +static void tdigest_do(SQLFunctionCtx *pCtx) { + int32_t notNullElems = 0; + + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SAPercentileInfo * pAPerc = getAPerctInfo(pCtx); + + assert(pAPerc->pTDigest != NULL); + if(pAPerc->pTDigest == NULL) { + qError("tdigest_do tdigest is null."); + return ; + } + + for (int32_t i = 0; i < pCtx->size; ++i) { + char *data = GET_INPUT_DATA(pCtx, i); + if (pCtx->hasNull && isNull(data, pCtx->inputType)) { + continue; + } + + notNullElems += 1; + + double v = 0; // value + long long w = 1; // weigth + GET_TYPED_DATA(v, double, pCtx->inputType, data); + tdigestAdd(pAPerc->pTDigest, v, w); + } + + tdigestCompress(pAPerc->pTDigest); + + if (!pCtx->hasNull) { + assert(pCtx->size == notNullElems); + } + + SET_VAL(pCtx, notNullElems, 1); + + if (notNullElems > 0) { + pResInfo->hasResult = DATA_SET_FLAG; + } +} + +static void tdigest_merge(SQLFunctionCtx *pCtx) { + SAPercentileInfo *pInput = (SAPercentileInfo *)GET_INPUT_DATA_LIST(pCtx); + assert(pInput->pTDigest); + + SAPercentileInfo *pOutput = getAPerctInfo(pCtx); + tdigestMerge(pOutput->pTDigest, pInput->pTDigest); + + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + pResInfo->hasResult = DATA_SET_FLAG; + SET_VAL(pCtx, 1, 1); +} + +static void tdigest_finalizer(SQLFunctionCtx *pCtx) { + double q = (pCtx->param[0].nType == TSDB_DATA_TYPE_INT) ? pCtx->param[0].i64 : pCtx->param[0].dKey; + + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SAPercentileInfo * pAPerc = getAPerctInfo(pCtx); + + if (pCtx->currentStage == MERGE_STAGE) { + if (pResInfo->hasResult == DATA_SET_FLAG) { // check for null + double res = tdigestQuantile(pAPerc->pTDigest, q); + memcpy(pCtx->pOutput, &res, sizeof(double)); + } else { + setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); + return; + } + } else { + if (pAPerc->pTDigest->size > 0) { + double res = tdigestQuantile(pAPerc->pTDigest, q); + memcpy(pCtx->pOutput, &res, sizeof(double)); + } else { // no need to free + setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); + return; + } + } + + tdigestFree(pAPerc->pTDigest); + pAPerc->pTDigest = NULL; + + doFinalizer(pCtx); +} + +////////////////////////////////////////////////////////////////////////////////// + +int algo = 1; +static bool apercentile_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { + if (algo == 1) { + return tdigest_setup(pCtx, pResultInfo); + } + + if (!function_setup(pCtx, pResultInfo)) { + return false; + } + SAPercentileInfo *pInfo = getAPerctInfo(pCtx); - + char *tmp = (char *)pInfo + sizeof(SAPercentileInfo); pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN); return true; } static void apercentile_function(SQLFunctionCtx *pCtx) { + if (algo == 1) { + tdigest_do(pCtx); + return; + } + int32_t notNullElems = 0; - - SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SAPercentileInfo *pInfo = getAPerctInfo(pCtx); + + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SAPercentileInfo * pInfo = getAPerctInfo(pCtx); assert(pInfo->pHisto->elems != NULL); - + for (int32_t i = 0; i < pCtx->size; ++i) { char *data = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(data, pCtx->inputType)) { continue; } - + notNullElems += 1; double v = 0; GET_TYPED_DATA(v, double, pCtx->inputType, data); tHistogramAdd(&pInfo->pHisto, v); } - + if (!pCtx->hasNull) { assert(pCtx->size == notNullElems); } - + SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; } } static void apercentile_func_merge(SQLFunctionCtx *pCtx) { + if (algo == 1) { + tdigest_merge(pCtx); + return; + } + SAPercentileInfo *pInput = (SAPercentileInfo *)GET_INPUT_DATA_LIST(pCtx); - - pInput->pHisto = (SHistogramInfo*) ((char *)pInput + sizeof(SAPercentileInfo)); - pInput->pHisto->elems = (SHistBin*) ((char *)pInput->pHisto + sizeof(SHistogramInfo)); + + pInput->pHisto = (SHistogramInfo *)((char *)pInput + sizeof(SAPercentileInfo)); + pInput->pHisto->elems = (SHistBin *)((char *)pInput->pHisto + sizeof(SHistogramInfo)); if (pInput->pHisto->numOfElems <= 0) { return; } - + SAPercentileInfo *pOutput = getAPerctInfo(pCtx); - SHistogramInfo *pHisto = pOutput->pHisto; - + SHistogramInfo * pHisto = pOutput->pHisto; + if (pHisto->numOfElems <= 0) { memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1)); - pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo)); + pHisto->elems = (SHistBin *)((char *)pHisto + sizeof(SHistogramInfo)); } else { - //TODO(dengyihao): avoid memcpy - pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo)); + // TODO(dengyihao): avoid memcpy + pHisto->elems = (SHistBin *)((char *)pHisto + sizeof(SHistogramInfo)); SHistogramInfo *pRes = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN); memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN); - pHisto->elems = (SHistBin*) ((char *)pHisto + sizeof(SHistogramInfo)); + pHisto->elems = (SHistBin *)((char *)pHisto + sizeof(SHistogramInfo)); tHistogramDestroy(&pRes); } @@ -2515,18 +2633,23 @@ static void apercentile_func_merge(SQLFunctionCtx *pCtx) { } static void apercentile_finalizer(SQLFunctionCtx *pCtx) { + if (algo == 1) { + tdigest_finalizer(pCtx); + return; + } + double v = (pCtx->param[0].nType == TSDB_DATA_TYPE_INT) ? pCtx->param[0].i64 : pCtx->param[0].dKey; - - SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SAPercentileInfo *pOutput = GET_ROWCELL_INTERBUF(pResInfo); + + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SAPercentileInfo * pOutput = GET_ROWCELL_INTERBUF(pResInfo); if (pCtx->currentStage == MERGE_STAGE) { if (pResInfo->hasResult == DATA_SET_FLAG) { // check for null assert(pOutput->pHisto->numOfElems > 0); - + double ratio[] = {v}; double *res = tHistogramUniform(pOutput->pHisto, ratio, 1); - + memcpy(pCtx->pOutput, res, sizeof(double)); free(res); } else { @@ -2536,7 +2659,7 @@ static void apercentile_finalizer(SQLFunctionCtx *pCtx) { } else { if (pOutput->pHisto->numOfElems > 0) { double ratio[] = {v}; - + double *res = tHistogramUniform(pOutput->pHisto, ratio, 1); memcpy(pCtx->pOutput, res, sizeof(double)); free(res); @@ -2545,18 +2668,18 @@ static void apercentile_finalizer(SQLFunctionCtx *pCtx) { return; } } - + doFinalizer(pCtx); } ///////////////////////////////////////////////////////////////////////////////// -static bool leastsquares_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool leastsquares_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + // 2*3 matrix pInfo->startVal = pCtx->param[0].dKey; return true; @@ -2581,29 +2704,29 @@ static bool leastsquares_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo } static void leastsquares_function(SQLFunctionCtx *pCtx) { - SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SLeastsquaresInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo); + double(*param)[3] = pInfo->mat; double x = pInfo->startVal; - + void *pData = GET_INPUT_DATA_LIST(pCtx); - + int32_t numOfElem = 0; switch (pCtx->inputType) { case TSDB_DATA_TYPE_INT: { int32_t *p = pData; // LEASTSQR_CAL_LOOP(pCtx, param, pParamData, p); for (int32_t i = 0; i < pCtx->size; ++i) { - if (pCtx->hasNull && isNull((const char*) p, pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)p, pCtx->inputType)) { continue; } - + param[0][0] += x * x; param[0][1] += x; param[0][2] += x * p[i]; param[1][2] += p[i]; - + x += pCtx->param[1].dKey; numOfElem++; } @@ -2655,45 +2778,45 @@ static void leastsquares_function(SQLFunctionCtx *pCtx) { break; } } - + pInfo->startVal = x; pInfo->num += numOfElem; - + if (pInfo->num > 0) { pResInfo->hasResult = DATA_SET_FLAG; } - + SET_VAL(pCtx, numOfElem, 1); } static void leastsquares_finalizer(SQLFunctionCtx *pCtx) { // no data in query - SResultRowCellInfo * pResInfo = GET_RES_INFO(pCtx); - SLeastsquaresInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SLeastsquaresInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo); + if (pInfo->num == 0) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - + double(*param)[3] = pInfo->mat; - + param[1][1] = (double)pInfo->num; param[1][0] = param[0][1]; - + param[0][0] -= param[1][0] * (param[0][1] / param[1][1]); param[0][2] -= param[1][2] * (param[0][1] / param[1][1]); param[0][1] = 0; param[1][2] -= param[0][2] * (param[1][0] / param[0][0]); param[1][0] = 0; param[0][2] /= param[0][0]; - + param[1][2] /= param[1][1]; - + int32_t maxOutputSize = TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE - VARSTR_HEADER_SIZE; - size_t n = snprintf(varDataVal(pCtx->pOutput), maxOutputSize, "{slop:%.6lf, intercept:%.6lf}", - param[0][2], param[1][2]); - + size_t n = + snprintf(varDataVal(pCtx->pOutput), maxOutputSize, "{slop:%.6lf, intercept:%.6lf}", param[0][2], param[1][2]); + varDataSetLen(pCtx->pOutput, n); doFinalizer(pCtx); } @@ -2718,12 +2841,11 @@ static void col_project_function(SQLFunctionCtx *pCtx) { char *pData = GET_INPUT_DATA_LIST(pCtx); if (pCtx->order == TSDB_ORDER_ASC) { - int32_t numOfRows = (pCtx->param[0].i64 == 1)? 1:pCtx->size; - memcpy(pCtx->pOutput, pData, (size_t) numOfRows * pCtx->inputBytes); + int32_t numOfRows = (pCtx->param[0].i64 == 1) ? 1 : pCtx->size; + memcpy(pCtx->pOutput, pData, (size_t)numOfRows * pCtx->inputBytes); } else { - for(int32_t i = 0; i < pCtx->size; ++i) { - memcpy(pCtx->pOutput + (pCtx->size - 1 - i) * pCtx->inputBytes, pData + i * pCtx->inputBytes, - pCtx->inputBytes); + for (int32_t i = 0; i < pCtx->size; ++i) { + memcpy(pCtx->pOutput + (pCtx->size - 1 - i) * pCtx->inputBytes, pData + i * pCtx->inputBytes, pCtx->inputBytes); } } } @@ -2735,11 +2857,11 @@ static void col_project_function(SQLFunctionCtx *pCtx) { */ static void tag_project_function(SQLFunctionCtx *pCtx) { INC_INIT_VAL(pCtx, pCtx->size); - + assert(pCtx->inputBytes == pCtx->outputBytes); tVariantDump(&pCtx->tag, pCtx->pOutput, pCtx->outputType, true); - char* data = pCtx->pOutput; + char *data = pCtx->pOutput; pCtx->pOutput += pCtx->outputBytes; // directly copy from the first one @@ -2769,7 +2891,7 @@ static void tag_function(SQLFunctionCtx *pCtx) { static void copy_function(SQLFunctionCtx *pCtx) { SET_VAL(pCtx, pCtx->size, 1); - + char *pData = GET_INPUT_DATA_LIST(pCtx); assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType); } @@ -2778,26 +2900,26 @@ enum { INITIAL_VALUE_NOT_ASSIGNED = 0, }; -static bool diff_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool diff_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } - + // diff function require the value is set to -1 pCtx->param[1].nType = INITIAL_VALUE_NOT_ASSIGNED; return false; } -static bool deriv_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResultInfo) { +static bool deriv_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResultInfo) { if (!function_setup(pCtx, pResultInfo)) { return false; } // diff function require the value is set to -1 - SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResultInfo); + SDerivInfo *pDerivInfo = GET_ROWCELL_INTERBUF(pResultInfo); pDerivInfo->ignoreNegative = pCtx->param[1].i64; - pDerivInfo->prevTs = -1; + pDerivInfo->prevTs = -1; pDerivInfo->tsWindow = pCtx->param[0].i64; pDerivInfo->valueSet = false; return false; @@ -2805,7 +2927,7 @@ static bool deriv_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResu static void deriv_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo); + SDerivInfo * pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo); void *data = GET_INPUT_DATA_LIST(pCtx); @@ -2827,20 +2949,21 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { - SET_DOUBLE_VAL(pOutput, ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs)); + SET_DOUBLE_VAL( + pOutput, ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs)); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } pDerivInfo->prevValue = pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevTs = tsList[i]; } break; @@ -2854,20 +2977,20 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { *pOutput = ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } - pDerivInfo->prevValue = (double) pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevValue = (double)pData[i]; + pDerivInfo->prevTs = tsList[i]; } break; } @@ -2880,20 +3003,20 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { *pOutput = ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } pDerivInfo->prevValue = pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevTs = tsList[i]; } break; } @@ -2907,20 +3030,20 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { *pOutput = ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } pDerivInfo->prevValue = pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevTs = tsList[i]; } break; } @@ -2933,20 +3056,20 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { *pOutput = ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } pDerivInfo->prevValue = pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevTs = tsList[i]; } break; } @@ -2959,21 +3082,21 @@ static void deriv_function(SQLFunctionCtx *pCtx) { } if (!pDerivInfo->valueSet) { // initial value is not set yet - pDerivInfo->valueSet = true; + pDerivInfo->valueSet = true; } else { *pOutput = ((pData[i] - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (tsList[i] - pDerivInfo->prevTs); if (pDerivInfo->ignoreNegative && *pOutput < 0) { } else { *pTimestamp = tsList[i]; - pOutput += 1; + pOutput += 1; pTimestamp += 1; notNullElems++; } } pDerivInfo->prevValue = pData[i]; - pDerivInfo->prevTs = tsList[i]; + pDerivInfo->prevTs = tsList[i]; } break; } @@ -2984,16 +3107,16 @@ static void deriv_function(SQLFunctionCtx *pCtx) { GET_RES_INFO(pCtx)->numOfRes += notNullElems; } -#define DIFF_IMPL(ctx, d, type) \ - do { \ - if ((ctx)->param[1].nType == INITIAL_VALUE_NOT_ASSIGNED) { \ - (ctx)->param[1].nType = (ctx)->inputType; \ - *(type *)&(ctx)->param[1].i64 = *(type *)(d); \ - } else { \ - *(type *)(ctx)->pOutput = *(type *)(d) - (*(type *)(&(ctx)->param[1].i64)); \ - *(type *)(&(ctx)->param[1].i64) = *(type *)(d); \ - *(int64_t *)(ctx)->ptsOutputBuf = GET_TS_DATA(ctx, index); \ - } \ +#define DIFF_IMPL(ctx, d, type) \ + do { \ + if ((ctx)->param[1].nType == INITIAL_VALUE_NOT_ASSIGNED) { \ + (ctx)->param[1].nType = (ctx)->inputType; \ + *(type *)&(ctx)->param[1].i64 = *(type *)(d); \ + } else { \ + *(type *)(ctx)->pOutput = *(type *)(d) - (*(type *)(&(ctx)->param[1].i64)); \ + *(type *)(&(ctx)->param[1].i64) = *(type *)(d); \ + *(int64_t *)(ctx)->ptsOutputBuf = GET_TS_DATA(ctx, index); \ + } \ } while (0); // TODO difference in date column @@ -3006,8 +3129,8 @@ static void diff_function(SQLFunctionCtx *pCtx) { int32_t step = GET_FORWARD_DIRECTION_FACTOR(pCtx->order); int32_t i = (pCtx->order == TSDB_ORDER_ASC) ? 0 : pCtx->size - 1; - TSKEY* pTimestamp = pCtx->ptsOutputBuf; - TSKEY* tsList = GET_TS_LIST(pCtx); + TSKEY *pTimestamp = pCtx->ptsOutputBuf; + TSKEY *tsList = GET_TS_LIST(pCtx); switch (pCtx->inputType) { case TSDB_DATA_TYPE_INT: { @@ -3015,14 +3138,14 @@ static void diff_function(SQLFunctionCtx *pCtx) { int32_t *pOutput = (int32_t *)pCtx->pOutput; for (; i < pCtx->size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet - *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3037,14 +3160,14 @@ static void diff_function(SQLFunctionCtx *pCtx) { int64_t *pOutput = (int64_t *)pCtx->pOutput; for (; i < pCtx->size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet - *pOutput = pData[i] - pCtx->param[1].i64; // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pOutput = pData[i] - pCtx->param[1].i64; // direct previous may be null + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3059,14 +3182,14 @@ static void diff_function(SQLFunctionCtx *pCtx) { double *pOutput = (double *)pCtx->pOutput; for (; i < pCtx->size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } - if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet + if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet SET_DOUBLE_VAL(pOutput, pData[i] - pCtx->param[1].dKey); // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3081,14 +3204,14 @@ static void diff_function(SQLFunctionCtx *pCtx) { float *pOutput = (float *)pCtx->pOutput; for (; i < pCtx->size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet - *pOutput = (float)(pData[i] - pCtx->param[1].dKey); // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pOutput = (float)(pData[i] - pCtx->param[1].dKey); // direct previous may be null + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3103,14 +3226,14 @@ static void diff_function(SQLFunctionCtx *pCtx) { int16_t *pOutput = (int16_t *)pCtx->pOutput; for (; i < pCtx->size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &pData[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&pData[i], pCtx->inputType)) { continue; } if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet - *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3131,9 +3254,9 @@ static void diff_function(SQLFunctionCtx *pCtx) { } if (pCtx->param[1].nType != INITIAL_VALUE_NOT_ASSIGNED) { // initial value is not set yet - *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null - *pTimestamp = (tsList != NULL)? tsList[i]:0; - pOutput += 1; + *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64); // direct previous may be null + *pTimestamp = (tsList != NULL) ? tsList[i] : 0; + pOutput += 1; pTimestamp += 1; } @@ -3161,9 +3284,9 @@ static void diff_function(SQLFunctionCtx *pCtx) { } } -char *getArithColumnData(void *param, const char* name, int32_t colId) { +char *getArithColumnData(void *param, const char *name, int32_t colId) { SArithmeticSupport *pSupport = (SArithmeticSupport *)param; - + int32_t index = -1; for (int32_t i = 0; i < pSupport->numOfCols; ++i) { if (colId == pSupport->colList[i].colId) { @@ -3171,7 +3294,7 @@ char *getArithColumnData(void *param, const char* name, int32_t colId) { break; } } - + assert(index >= 0); return pSupport->data[index] + pSupport->offset * pSupport->colList[index].bytes; } @@ -3179,7 +3302,7 @@ char *getArithColumnData(void *param, const char* name, int32_t colId) { static void arithmetic_function(SQLFunctionCtx *pCtx) { GET_RES_INFO(pCtx)->numOfRes += pCtx->size; SArithmeticSupport *sas = (SArithmeticSupport *)pCtx->param[1].pz; - + arithmeticTreeTraverse(sas->pExprInfo->pExpr, pCtx->size, pCtx->pOutput, sas, pCtx->order, getArithColumnData); } @@ -3191,23 +3314,23 @@ static void arithmetic_function(SQLFunctionCtx *pCtx) { continue; \ } \ if (inputData[i] < minOutput) { \ - minOutput = (double)inputData[i]; \ + minOutput = (double)inputData[i]; \ } \ if (inputData[i] > maxOutput) { \ - maxOutput = (double)inputData[i]; \ + maxOutput = (double)inputData[i]; \ } \ numOfNotNullElem++; \ } \ } ///////////////////////////////////////////////////////////////////////////////// -static bool spread_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool spread_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } - + SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + // this is the server-side setup function in client-side, the secondary merge do not need this procedure if (pCtx->currentStage == MERGE_STAGE) { pCtx->param[0].dKey = DBL_MAX; @@ -3216,21 +3339,21 @@ static bool spread_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pRes pInfo->min = DBL_MAX; pInfo->max = -DBL_MAX; } - + return true; } static void spread_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + SSpreadInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo); + int32_t numOfElems = 0; - + // todo : opt with pre-calculated result // column missing cause the hasNull to be true if (pCtx->preAggVals.isSet) { numOfElems = pCtx->size - pCtx->preAggVals.statis.numOfNull; - + // all data are null in current data block, ignore current data block if (numOfElems == 0) { goto _spread_over; @@ -3249,18 +3372,18 @@ static void spread_function(SQLFunctionCtx *pCtx) { if (pInfo->min > GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.min))) { pInfo->min = GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.min)); } - + if (pInfo->max < GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.max))) { pInfo->max = GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.max)); } } - + goto _spread_over; } - + void *pData = GET_INPUT_DATA_LIST(pCtx); numOfElems = 0; - + if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { LIST_MINMAX_N(pCtx, pInfo->min, pInfo->max, pCtx->size, pData, int8_t, pCtx->inputType, numOfElems); } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { @@ -3282,19 +3405,19 @@ static void spread_function(SQLFunctionCtx *pCtx) { } else if (pCtx->inputType == TSDB_DATA_TYPE_UBIGINT) { LIST_MINMAX_N(pCtx, pInfo->min, pInfo->max, pCtx->size, pData, uint64_t, pCtx->inputType, numOfElems); } - + if (!pCtx->hasNull) { assert(pCtx->size == numOfElems); } - - _spread_over: + +_spread_over: SET_VAL(pCtx, numOfElems, 1); - + if (numOfElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; pInfo->hasResult = DATA_SET_FLAG; } - + // keep the data into the final output buffer for super table query since this execution may be the last one if (pCtx->stableQuery) { memcpy(pCtx->pOutput, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SSpreadInfo)); @@ -3310,15 +3433,15 @@ void spread_func_merge(SQLFunctionCtx *pCtx) { if (pData->hasResult != DATA_SET_FLAG) { return; } - + if (pCtx->param[0].dKey > pData->min) { pCtx->param[0].dKey = pData->min; } - + if (pCtx->param[3].dKey < pData->max) { pCtx->param[3].dKey = pData->max; } - + GET_RES_INFO(pCtx)->hasResult = DATA_SET_FLAG; } @@ -3328,73 +3451,72 @@ void spread_function_finalizer(SQLFunctionCtx *pCtx) { * the type of intermediate data is binary */ SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + if (pCtx->currentStage == MERGE_STAGE) { assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); - + if (pResInfo->hasResult != DATA_SET_FLAG) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - + SET_DOUBLE_VAL((double *)pCtx->pOutput, pCtx->param[3].dKey - pCtx->param[0].dKey); } else { assert(IS_NUMERIC_TYPE(pCtx->inputType) || (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP)); - + SSpreadInfo *pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); if (pInfo->hasResult != DATA_SET_FLAG) { setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes); return; } - + SET_DOUBLE_VAL((double *)pCtx->pOutput, pInfo->max - pInfo->min); } - + GET_RES_INFO(pCtx)->numOfRes = 1; // todo add test case doFinalizer(pCtx); } - /** * param[1]: start time * param[2]: end time * @param pCtx */ -static bool twa_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool twa_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } STwaInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - pInfo->p.key = INT64_MIN; - pInfo->win = TSWINDOW_INITIALIZER; + pInfo->p.key = INT64_MIN; + pInfo->win = TSWINDOW_INITIALIZER; return true; } static double twa_get_area(SPoint1 s, SPoint1 e) { - if ((s.val >= 0 && e.val >= 0)|| (s.val <=0 && e.val <= 0)) { + if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) { return (s.val + e.val) * (e.key - s.key) / 2; } - double x = (s.key * e.val - e.key * s.val)/(e.val - s.val); + double x = (s.key * e.val - e.key * s.val) / (e.val - s.val); double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2; return val; } -static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t size) { - int32_t notNullElems = 0; +static int32_t twa_function_impl(SQLFunctionCtx *pCtx, int32_t index, int32_t size) { + int32_t notNullElems = 0; SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); STwaInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - TSKEY *tsList = GET_TS_LIST(pCtx); + TSKEY * tsList = GET_TS_LIST(pCtx); - int32_t i = index; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pCtx->order); - SPoint1* last = &pInfo->p; + int32_t i = index; + int32_t step = GET_FORWARD_DIRECTION_FACTOR(pCtx->order); + SPoint1 *last = &pInfo->p; if (pCtx->start.key != INT64_MIN) { assert((pCtx->start.key < tsList[i] && pCtx->order == TSDB_ORDER_ASC) || - (pCtx->start.key > tsList[i] && pCtx->order == TSDB_ORDER_DESC)); + (pCtx->start.key > tsList[i] && pCtx->order == TSDB_ORDER_DESC)); assert(last->key == INT64_MIN); @@ -3418,11 +3540,11 @@ static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t si } // calculate the value of - switch(pCtx->inputType) { + switch (pCtx->inputType) { case TSDB_DATA_TYPE_TINYINT: { - int8_t *val = (int8_t*) GET_INPUT_DATA(pCtx, 0); + int8_t *val = (int8_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } @@ -3432,111 +3554,111 @@ static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t si SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_SMALLINT: { - int16_t *val = (int16_t*) GET_INPUT_DATA(pCtx, 0); + int16_t *val = (int16_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 SPoint1 st = {.key = tsList[i], .val = val[i]}; #else SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_INT: { - int32_t *val = (int32_t*) GET_INPUT_DATA(pCtx, 0); + int32_t *val = (int32_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 SPoint1 st = {.key = tsList[i], .val = val[i]}; #else SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_BIGINT: { - int64_t *val = (int64_t*) GET_INPUT_DATA(pCtx, 0); + int64_t *val = (int64_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 - SPoint1 st = {.key = tsList[i], .val = (double) val[i]}; + SPoint1 st = {.key = tsList[i], .val = (double)val[i]}; #else SPoint1 st; st.key = tsList[i]; st.val = (double)val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_FLOAT: { - float *val = (float*) GET_INPUT_DATA(pCtx, 0); + float *val = (float *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 SPoint1 st = {.key = tsList[i], .val = val[i]}; #else SPoint1 st; st.key = tsList[i]; st.val = (double)val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_DOUBLE: { - double *val = (double*) GET_INPUT_DATA(pCtx, 0); + double *val = (double *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 SPoint1 st = {.key = tsList[i], .val = val[i]}; #else SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_UTINYINT: { - uint8_t *val = (uint8_t*) GET_INPUT_DATA(pCtx, 0); + uint8_t *val = (uint8_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } @@ -3546,16 +3668,16 @@ static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t si SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_USMALLINT: { - uint16_t *val = (uint16_t*) GET_INPUT_DATA(pCtx, 0); + uint16_t *val = (uint16_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } @@ -3565,16 +3687,16 @@ static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t si SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_UINT: { - uint32_t *val = (uint32_t*) GET_INPUT_DATA(pCtx, 0); + uint32_t *val = (uint32_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } @@ -3584,41 +3706,42 @@ static int32_t twa_function_impl(SQLFunctionCtx* pCtx, int32_t index, int32_t si SPoint1 st; st.key = tsList[i]; st.val = val[i]; -#endif +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } case TSDB_DATA_TYPE_UBIGINT: { - uint64_t *val = (uint64_t*) GET_INPUT_DATA(pCtx, 0); + uint64_t *val = (uint64_t *)GET_INPUT_DATA(pCtx, 0); for (; i < size && i >= 0; i += step) { - if (pCtx->hasNull && isNull((const char*) &val[i], pCtx->inputType)) { + if (pCtx->hasNull && isNull((const char *)&val[i], pCtx->inputType)) { continue; } - + #ifndef _TD_NINGSI_60 - SPoint1 st = {.key = tsList[i], .val = (double) val[i]}; + SPoint1 st = {.key = tsList[i], .val = (double)val[i]}; #else SPoint1 st; st.key = tsList[i]; - st.val = (double) val[i]; -#endif + st.val = (double)val[i]; +#endif pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } break; } - default: assert(0); + default: + assert(0); } // the last interpolated time window value if (pCtx->end.key != INT64_MIN) { - pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end); + pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end); pInfo->p = pCtx->end; } - pInfo->win.ekey = pInfo->p.key; + pInfo->win.ekey = pInfo->p.key; return notNullElems; } @@ -3626,11 +3749,11 @@ static void twa_function(SQLFunctionCtx *pCtx) { void *data = GET_INPUT_DATA_LIST(pCtx); SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - STwaInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); - + STwaInfo * pInfo = GET_ROWCELL_INTERBUF(pResInfo); + // skip null value int32_t step = GET_FORWARD_DIRECTION_FACTOR(pCtx->order); - int32_t i = (pCtx->order == TSDB_ORDER_ASC)? 0:(pCtx->size - 1); + int32_t i = (pCtx->order == TSDB_ORDER_ASC) ? 0 : (pCtx->size - 1); while (pCtx->hasNull && i < pCtx->size && i >= 0 && isNull((char *)data + pCtx->inputBytes * i, pCtx->inputType)) { i += step; } @@ -3641,11 +3764,11 @@ static void twa_function(SQLFunctionCtx *pCtx) { } SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { pResInfo->hasResult = DATA_SET_FLAG; } - + if (pCtx->stableQuery) { memcpy(pCtx->pOutput, pInfo, sizeof(STwaInfo)); } @@ -3659,14 +3782,14 @@ static void twa_function(SQLFunctionCtx *pCtx) { void twa_function_copy(SQLFunctionCtx *pCtx) { assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes); pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult; } void twa_function_finalizer(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + STwaInfo *pInfo = (STwaInfo *)GET_ROWCELL_INTERBUF(pResInfo); if (pInfo->hasResult != DATA_SET_FLAG) { setNull(pCtx->pOutput, TSDB_DATA_TYPE_DOUBLE, sizeof(double)); @@ -3677,9 +3800,9 @@ void twa_function_finalizer(SQLFunctionCtx *pCtx) { if (pInfo->win.ekey == pInfo->win.skey) { SET_DOUBLE_VAL((double *)pCtx->pOutput, pInfo->p.val); } else { - SET_DOUBLE_VAL((double *)pCtx->pOutput , pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey)); + SET_DOUBLE_VAL((double *)pCtx->pOutput, pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey)); } - + GET_RES_INFO(pCtx)->numOfRes = 1; doFinalizer(pCtx); } @@ -3690,7 +3813,7 @@ void twa_function_finalizer(SQLFunctionCtx *pCtx) { */ static void interp_function_impl(SQLFunctionCtx *pCtx) { - int32_t type = (int32_t) pCtx->param[2].i64; + int32_t type = (int32_t)pCtx->param[2].i64; if (type == TSDB_FILL_NONE) { return; } @@ -3704,7 +3827,9 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { } else if (type == TSDB_FILL_SET_VALUE) { tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true); } else { - if (pCtx->start.key != INT64_MIN && ((ascQuery && pCtx->start.key <= pCtx->startTs && pCtx->end.key >= pCtx->startTs) || ((!ascQuery) && pCtx->start.key >= pCtx->startTs && pCtx->end.key <= pCtx->startTs))) { + if (pCtx->start.key != INT64_MIN && + ((ascQuery && pCtx->start.key <= pCtx->startTs && pCtx->end.key >= pCtx->startTs) || + ((!ascQuery) && pCtx->start.key >= pCtx->startTs && pCtx->end.key <= pCtx->startTs))) { if (type == TSDB_FILL_PREV) { if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val); @@ -3720,7 +3845,7 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { } else if (type == TSDB_FILL_LINEAR) { SPoint point1 = {.key = pCtx->start.key, .val = &pCtx->start.val}; SPoint point2 = {.key = pCtx->end.key, .val = &pCtx->end.val}; - SPoint point = {.key = pCtx->startTs, .val = pCtx->pOutput}; + SPoint point = {.key = pCtx->startTs, .val = pCtx->pOutput}; int32_t srcType = pCtx->inputType; if (IS_NUMERIC_TYPE(srcType)) { // TODO should find the not null data? @@ -3749,16 +3874,16 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { if (pCtx->size > 1) { TSKEY ekey = GET_TS_DATA(pCtx, 1); - if ((ascQuery && ekey > skey && ekey <= pCtx->startTs) || - ((!ascQuery) && ekey < skey && ekey >= pCtx->startTs)){ + if ((ascQuery && ekey > skey && ekey <= pCtx->startTs) || + ((!ascQuery) && ekey < skey && ekey >= pCtx->startTs)) { skey = ekey; } } assignVal(pCtx->pOutput, pCtx->pInput, pCtx->outputBytes, pCtx->inputType); } else if (type == TSDB_FILL_NEXT) { TSKEY ekey = skey; - char* val = NULL; - + char *val = NULL; + if ((ascQuery && ekey < pCtx->startTs) || ((!ascQuery) && ekey > pCtx->startTs)) { if (pCtx->size > 1) { ekey = GET_TS_DATA(pCtx, 1); @@ -3766,28 +3891,28 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { return; } - val = ((char*)pCtx->pInput) + pCtx->inputBytes; + val = ((char *)pCtx->pInput) + pCtx->inputBytes; } else { return; } } else { - val = (char*)pCtx->pInput; + val = (char *)pCtx->pInput; } - + assignVal(pCtx->pOutput, val, pCtx->outputBytes, pCtx->inputType); } else if (type == TSDB_FILL_LINEAR) { if (pCtx->size <= 1) { return; } - + TSKEY ekey = GET_TS_DATA(pCtx, 1); - + // no data generated yet - if ((ascQuery && !(skey <= pCtx->startTs && ekey >= pCtx->startTs)) - || ((!ascQuery) && !(skey >= pCtx->startTs && ekey <= pCtx->startTs))) { + if ((ascQuery && !(skey <= pCtx->startTs && ekey >= pCtx->startTs)) || + ((!ascQuery) && !(skey >= pCtx->startTs && ekey <= pCtx->startTs))) { return; } - + char *start = GET_INPUT_DATA(pCtx, 0); char *end = GET_INPUT_DATA(pCtx, 1); @@ -3815,11 +3940,11 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { static void interp_function(SQLFunctionCtx *pCtx) { // at this point, the value is existed, return directly if (pCtx->size > 0) { - bool ascQuery = (pCtx->order == TSDB_ORDER_ASC); - TSKEY key; - char *pData; + bool ascQuery = (pCtx->order == TSDB_ORDER_ASC); + TSKEY key; + char * pData; int32_t typedData = 0; - + if (ascQuery) { key = GET_TS_DATA(pCtx, 0); pData = GET_INPUT_DATA(pCtx, 0); @@ -3828,7 +3953,7 @@ static void interp_function(SQLFunctionCtx *pCtx) { if (key == INT64_MIN) { key = GET_TS_DATA(pCtx, 0); pData = GET_INPUT_DATA(pCtx, 0); - } else { + } else { if (!(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL)) { pData = pCtx->start.ptr; } else { @@ -3837,25 +3962,26 @@ static void interp_function(SQLFunctionCtx *pCtx) { } } } - - //if (key == pCtx->startTs && (ascQuery || !(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL))) { + + // if (key == pCtx->startTs && (ascQuery || !(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == + // TSDB_DATA_TYPE_BOOL))) { if (key == pCtx->startTs) { if (typedData) { SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, *(double *)pData); } else { assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType); } - + SET_VAL(pCtx, 1, 1); } else { interp_function_impl(pCtx); } - } else { //no qualified data rows and interpolation is required + } else { // no qualified data rows and interpolation is required interp_function_impl(pCtx); } } -static bool ts_comp_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool ts_comp_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; // not initialized since it has been initialized } @@ -3868,10 +3994,10 @@ static bool ts_comp_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pRe static void ts_comp_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - STSBuf * pTSbuf = ((STSCompInfo *)(GET_ROWCELL_INTERBUF(pResInfo)))->pTSBuf; - + STSBuf * pTSbuf = ((STSCompInfo *)(GET_ROWCELL_INTERBUF(pResInfo)))->pTSBuf; + const char *input = GET_INPUT_DATA_LIST(pCtx); - + // primary ts must be existed, so no need to check its existance if (pCtx->order == TSDB_ORDER_ASC) { tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64, &pCtx->tag, input, pCtx->size * TSDB_KEYSIZE); @@ -3881,19 +4007,19 @@ static void ts_comp_function(SQLFunctionCtx *pCtx) { tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64, &pCtx->tag, d, (int32_t)TSDB_KEYSIZE); } } - + SET_VAL(pCtx, pCtx->size, 1); pResInfo->hasResult = DATA_SET_FLAG; } static void ts_comp_finalize(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + STSCompInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); STSBuf * pTSbuf = pInfo->pTSBuf; - + tsBufFlush(pTSbuf); - qDebug("total timestamp :%"PRId64, pTSbuf->numOfTotal); + qDebug("total timestamp :%" PRId64, pTSbuf->numOfTotal); // TODO refactor transfer ownership of current file *(FILE **)pCtx->pOutput = pTSbuf->f; @@ -3914,7 +4040,7 @@ static void ts_comp_finalize(SQLFunctionCtx *pCtx) { ////////////////////////////////////////////////////////////////////////////////////////////// // rate functions -static double do_calc_rate(const SRateInfo* pRateInfo, double tickPerSec) { +static double do_calc_rate(const SRateInfo *pRateInfo, double tickPerSec) { if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) || (pRateInfo->firstKey >= pRateInfo->lastKey)) { return 0.0; @@ -3929,31 +4055,31 @@ static double do_calc_rate(const SRateInfo* pRateInfo, double tickPerSec) { diff -= pRateInfo->firstValue; } } else { - diff = pRateInfo->correctionValue + pRateInfo->lastValue - pRateInfo->firstValue; + diff = pRateInfo->correctionValue + pRateInfo->lastValue - pRateInfo->firstValue; if (diff <= 0) { return 0; } } - + int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey; if (duration == 0) { return 0; } - return (duration > 0)? ((double)diff) / (duration/tickPerSec):0.0; + return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0; } -static bool rate_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResInfo) { +static bool rate_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo *pResInfo) { if (!function_setup(pCtx, pResInfo)) { return false; } - + SRateInfo *pInfo = GET_ROWCELL_INTERBUF(pResInfo); pInfo->correctionValue = 0; - pInfo->firstKey = INT64_MIN; - pInfo->lastKey = INT64_MIN; - pInfo->firstValue = (double) INT64_MIN; - pInfo->lastValue = (double) INT64_MIN; + pInfo->firstKey = INT64_MIN; + pInfo->lastKey = INT64_MIN; + pInfo->firstValue = (double)INT64_MIN; + pInfo->lastValue = (double)INT64_MIN; pInfo->hasResult = 0; pInfo->isIRate = (pCtx->functionId == TSDB_FUNC_IRATE); @@ -3962,51 +4088,51 @@ static bool rate_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResIn static void rate_function(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - + int32_t notNullElems = 0; SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo); - TSKEY *primaryKey = GET_TS_LIST(pCtx); - + TSKEY * primaryKey = GET_TS_LIST(pCtx); + qDebug("%p rate_function() size:%d, hasNull:%d", pCtx, pCtx->size, pCtx->hasNull); - + for (int32_t i = 0; i < pCtx->size; ++i) { char *pData = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(pData, pCtx->inputType)) { qDebug("%p rate_function() index of null data:%d", pCtx, i); continue; } - + notNullElems++; - + double v = 0; GET_TYPED_DATA(v, double, pCtx->inputType, pData); - + if ((INT64_MIN == pRateInfo->firstValue) || (INT64_MIN == pRateInfo->firstKey)) { pRateInfo->firstValue = v; pRateInfo->firstKey = primaryKey[i]; } - + if (INT64_MIN == pRateInfo->lastValue) { pRateInfo->lastValue = v; } else if (v < pRateInfo->lastValue) { pRateInfo->correctionValue += pRateInfo->lastValue; } - + pRateInfo->lastValue = v; - pRateInfo->lastKey = primaryKey[i]; + pRateInfo->lastKey = primaryKey[i]; } - + if (!pCtx->hasNull) { assert(pCtx->size == notNullElems); } - + SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { pRateInfo->hasResult = DATA_SET_FLAG; - pResInfo->hasResult = DATA_SET_FLAG; + pResInfo->hasResult = DATA_SET_FLAG; } - + // keep the data into the final output buffer for super table query since this execution may be the last one if (pCtx->stableQuery) { memcpy(pCtx->pOutput, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo)); @@ -4015,90 +4141,90 @@ static void rate_function(SQLFunctionCtx *pCtx) { static void rate_func_copy(SQLFunctionCtx *pCtx) { assert(pCtx->inputType == TSDB_DATA_TYPE_BINARY); - + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes); - pResInfo->hasResult = ((SRateInfo*)pCtx->pInput)->hasResult; + pResInfo->hasResult = ((SRateInfo *)pCtx->pInput)->hasResult; } static void rate_finalizer(SQLFunctionCtx *pCtx) { - SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo); + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SRateInfo * pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo); if (pRateInfo->hasResult != DATA_SET_FLAG) { setNull(pCtx->pOutput, TSDB_DATA_TYPE_DOUBLE, sizeof(double)); return; } - - SET_DOUBLE_VAL((double*) pCtx->pOutput, do_calc_rate(pRateInfo, (double) TSDB_TICK_PER_SECOND(pCtx->param[0].i64))); + + SET_DOUBLE_VAL((double *)pCtx->pOutput, do_calc_rate(pRateInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[0].i64))); // cannot set the numOfIteratedElems again since it is set during previous iteration - pResInfo->numOfRes = 1; + pResInfo->numOfRes = 1; pResInfo->hasResult = DATA_SET_FLAG; - + doFinalizer(pCtx); } static void irate_function(SQLFunctionCtx *pCtx) { - SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); + SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); int32_t notNullElems = 0; - SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo); - TSKEY *primaryKey = GET_TS_LIST(pCtx); + SRateInfo *pRateInfo = (SRateInfo *)GET_ROWCELL_INTERBUF(pResInfo); + TSKEY * primaryKey = GET_TS_LIST(pCtx); for (int32_t i = pCtx->size - 1; i >= 0; --i) { char *pData = GET_INPUT_DATA(pCtx, i); if (pCtx->hasNull && isNull(pData, pCtx->inputType)) { continue; } - + notNullElems++; - + double v = 0; GET_TYPED_DATA(v, double, pCtx->inputType, pData); if ((INT64_MIN == pRateInfo->lastKey) || primaryKey[i] > pRateInfo->lastKey) { pRateInfo->lastValue = v; - pRateInfo->lastKey = primaryKey[i]; + pRateInfo->lastKey = primaryKey[i]; continue; } - + if ((INT64_MIN == pRateInfo->firstKey) || primaryKey[i] > pRateInfo->firstKey) { pRateInfo->firstValue = v; pRateInfo->firstKey = primaryKey[i]; break; } } - + SET_VAL(pCtx, notNullElems, 1); - + if (notNullElems > 0) { pRateInfo->hasResult = DATA_SET_FLAG; - pResInfo->hasResult = DATA_SET_FLAG; + pResInfo->hasResult = DATA_SET_FLAG; } - + // keep the data into the final output buffer for super table query since this execution may be the last one if (pCtx->stableQuery) { memcpy(pCtx->pOutput, GET_ROWCELL_INTERBUF(pResInfo), sizeof(SRateInfo)); } } -void blockInfo_func(SQLFunctionCtx* pCtx) { +void blockInfo_func(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); + STableBlockDist * pDist = (STableBlockDist *)GET_ROWCELL_INTERBUF(pResInfo); - int32_t len = *(int32_t*) pCtx->pInput; - blockDistInfoFromBinary((char*)pCtx->pInput + sizeof(int32_t), len, pDist); + int32_t len = *(int32_t *)pCtx->pInput; + blockDistInfoFromBinary((char *)pCtx->pInput + sizeof(int32_t), len, pDist); pDist->rowSize = (uint16_t)pCtx->param[0].i64; memcpy(pCtx->pOutput, pCtx->pInput, sizeof(int32_t) + len); - pResInfo->numOfRes = 1; + pResInfo->numOfRes = 1; pResInfo->hasResult = DATA_SET_FLAG; } -static void mergeTableBlockDist(SResultRowCellInfo* pResInfo, const STableBlockDist* pSrc) { - STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); +static void mergeTableBlockDist(SResultRowCellInfo *pResInfo, const STableBlockDist *pSrc) { + STableBlockDist *pDist = (STableBlockDist *)GET_ROWCELL_INTERBUF(pResInfo); assert(pDist != NULL && pSrc != NULL); pDist->numOfTables += pSrc->numOfTables; @@ -4115,7 +4241,7 @@ static void mergeTableBlockDist(SResultRowCellInfo* pResInfo, const STableBlockD pDist->maxRows = pSrc->maxRows; pDist->minRows = pSrc->minRows; - int32_t maxSteps = TSDB_MAX_MAX_ROW_FBLOCK/TSDB_BLOCK_DIST_STEP_ROWS; + int32_t maxSteps = TSDB_MAX_MAX_ROW_FBLOCK / TSDB_BLOCK_DIST_STEP_ROWS; if (TSDB_MAX_MAX_ROW_FBLOCK % TSDB_BLOCK_DIST_STEP_ROWS != 0) { ++maxSteps; } @@ -4125,26 +4251,26 @@ static void mergeTableBlockDist(SResultRowCellInfo* pResInfo, const STableBlockD size_t steps = taosArrayGetSize(pSrc->dataBlockInfos); for (int32_t i = 0; i < steps; ++i) { - int32_t srcNumBlocks = ((SFileBlockInfo*)taosArrayGet(pSrc->dataBlockInfos, i))->numBlocksOfStep; - SFileBlockInfo* blockInfo = (SFileBlockInfo*)taosArrayGet(pDist->dataBlockInfos, i); + int32_t srcNumBlocks = ((SFileBlockInfo *)taosArrayGet(pSrc->dataBlockInfos, i))->numBlocksOfStep; + SFileBlockInfo *blockInfo = (SFileBlockInfo *)taosArrayGet(pDist->dataBlockInfos, i); blockInfo->numBlocksOfStep += srcNumBlocks; } } -void block_func_merge(SQLFunctionCtx* pCtx) { +void block_func_merge(SQLFunctionCtx *pCtx) { STableBlockDist info = {0}; - int32_t len = *(int32_t*) pCtx->pInput; - blockDistInfoFromBinary(((char*)pCtx->pInput) + sizeof(int32_t), len, &info); + int32_t len = *(int32_t *)pCtx->pInput; + blockDistInfoFromBinary(((char *)pCtx->pInput) + sizeof(int32_t), len, &info); SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); mergeTableBlockDist(pResInfo, &info); - taosArrayDestroy(info.dataBlockInfos); + taosArrayDestroy(info.dataBlockInfos); pResInfo->numOfRes = 1; pResInfo->hasResult = DATA_SET_FLAG; } -void getPercentiles(STableBlockDist *pTableBlockDist, int64_t totalBlocks, int32_t numOfPercents, - double* percents, int32_t* percentiles) { +void getPercentiles(STableBlockDist *pTableBlockDist, int64_t totalBlocks, int32_t numOfPercents, double *percents, + int32_t *percentiles) { if (totalBlocks == 0) { for (int32_t i = 0; i < numOfPercents; ++i) { percentiles[i] = 0; @@ -4174,28 +4300,28 @@ void getPercentiles(STableBlockDist *pTableBlockDist, int64_t totalBlocks, int32 } for (int32_t i = 0; i < numOfPercents; ++i) { - percentiles[i] = (percentiles[i]+1) * TSDB_BLOCK_DIST_STEP_ROWS - TSDB_BLOCK_DIST_STEP_ROWS/2; + percentiles[i] = (percentiles[i] + 1) * TSDB_BLOCK_DIST_STEP_ROWS - TSDB_BLOCK_DIST_STEP_ROWS / 2; } } -void generateBlockDistResult(STableBlockDist *pTableBlockDist, char* result) { +void generateBlockDistResult(STableBlockDist *pTableBlockDist, char *result) { if (pTableBlockDist == NULL) { return; } - SArray* blockInfos = pTableBlockDist->dataBlockInfos; + SArray * blockInfos = pTableBlockDist->dataBlockInfos; uint64_t totalRows = pTableBlockDist->totalRows; size_t numSteps = taosArrayGetSize(blockInfos); - int64_t totalBlocks = 0; - int64_t min = -1, max = -1, avg = 0; + int64_t totalBlocks = 0; + int64_t min = -1, max = -1, avg = 0; for (int32_t i = 0; i < numSteps; i++) { SFileBlockInfo *blockInfo = taosArrayGet(blockInfos, i); - int64_t blocks = blockInfo->numBlocksOfStep; + int64_t blocks = blockInfo->numBlocksOfStep; totalBlocks += blocks; } - avg = totalBlocks > 0 ? (int64_t)(totalRows/totalBlocks) : 0; + avg = totalBlocks > 0 ? (int64_t)(totalRows / totalBlocks) : 0; min = totalBlocks > 0 ? pTableBlockDist->minRows : 0; max = totalBlocks > 0 ? pTableBlockDist->maxRows : 0; @@ -4212,34 +4338,35 @@ void generateBlockDistResult(STableBlockDist *pTableBlockDist, char* result) { stdDev = sqrt(variance); } - double percents[] = {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.95, 0.99}; + double percents[] = {0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 0.95, 0.99}; int32_t percentiles[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - assert(sizeof(percents)/sizeof(double) == sizeof(percentiles)/sizeof(int32_t)); - getPercentiles(pTableBlockDist, totalBlocks, sizeof(percents)/sizeof(double), percents, percentiles); + assert(sizeof(percents) / sizeof(double) == sizeof(percentiles) / sizeof(int32_t)); + getPercentiles(pTableBlockDist, totalBlocks, sizeof(percents) / sizeof(double), percents, percentiles); uint64_t totalLen = pTableBlockDist->totalSize; - int32_t rowSize = pTableBlockDist->rowSize; - int32_t smallBlocks = pTableBlockDist->numOfSmallBlocks; - double compRatio = (totalRows>0) ? ((double)(totalLen)/(rowSize*totalRows)) : 1; - int sz = sprintf(result + VARSTR_HEADER_SIZE, + int32_t rowSize = pTableBlockDist->rowSize; + int32_t smallBlocks = pTableBlockDist->numOfSmallBlocks; + double compRatio = (totalRows > 0) ? ((double)(totalLen) / (rowSize * totalRows)) : 1; + int sz = sprintf(result + VARSTR_HEADER_SIZE, "summary: \n\t " "5th=[%d], 10th=[%d], 20th=[%d], 30th=[%d], 40th=[%d], 50th=[%d]\n\t " "60th=[%d], 70th=[%d], 80th=[%d], 90th=[%d], 95th=[%d], 99th=[%d]\n\t " - "Min=[%"PRId64"(Rows)] Max=[%"PRId64"(Rows)] Avg=[%"PRId64"(Rows)] Stddev=[%.2f] \n\t " - "Rows=[%"PRIu64"], Blocks=[%"PRId64"], SmallBlocks=[%d], Size=[%.3f(Kb)] Comp=[%.2f]\n\t " + "Min=[%" PRId64 "(Rows)] Max=[%" PRId64 "(Rows)] Avg=[%" PRId64 + "(Rows)] Stddev=[%.2f] \n\t " + "Rows=[%" PRIu64 "], Blocks=[%" PRId64 + "], SmallBlocks=[%d], Size=[%.3f(Kb)] Comp=[%.2f]\n\t " "RowsInMem=[%d] \n\t", percentiles[0], percentiles[1], percentiles[2], percentiles[3], percentiles[4], percentiles[5], percentiles[6], percentiles[7], percentiles[8], percentiles[9], percentiles[10], percentiles[11], - min, max, avg, stdDev, - totalRows, totalBlocks, smallBlocks, totalLen/1024.0, compRatio, + min, max, avg, stdDev, totalRows, totalBlocks, smallBlocks, totalLen / 1024.0, compRatio, pTableBlockDist->numOfRowsInMemTable); varDataSetLen(result, sz); UNUSED(sz); } -void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) { +void blockinfo_func_finalizer(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); - STableBlockDist* pDist = (STableBlockDist*) GET_ROWCELL_INTERBUF(pResInfo); + STableBlockDist * pDist = (STableBlockDist *)GET_ROWCELL_INTERBUF(pResInfo); pDist->rowSize = (uint16_t)pCtx->param[0].i64; generateBlockDistResult(pDist, pCtx->pOutput); @@ -4250,7 +4377,7 @@ void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) { } // cannot set the numOfIteratedElems again since it is set during previous iteration - pResInfo->numOfRes = 1; + pResInfo->numOfRes = 1; pResInfo->hasResult = DATA_SET_FLAG; doFinalizer(pCtx); @@ -4269,423 +4396,455 @@ void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) { */ int32_t functionCompatList[] = { // count, sum, avg, min, max, stddev, percentile, apercentile, first, last - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, // last_row,top, bottom, spread, twa, leastsqr, ts, ts_dummy, tag_dummy, ts_comp - 4, -1, -1, 1, 1, 1, 1, 1, 1, -1, + 4, + -1, + -1, + 1, + 1, + 1, + 1, + 1, + 1, + -1, // tag, colprj, tagprj, arithmetic, diff, first_dist, last_dist, stddev_dst, interp rate irate - 1, 1, 1, 1, -1, 1, 1, 1, 5, 1, 1, + 1, + 1, + 1, + 1, + -1, + 1, + 1, + 1, + 5, + 1, + 1, // tid_tag, derivative, blk_info - 6, 8, 7, + 6, + 8, + 7, }; -SAggFunctionInfo aAggs[] = {{ - // 0, count function does not invoke the finalize function - "count", - TSDB_FUNC_COUNT, - TSDB_FUNC_COUNT, - TSDB_BASE_FUNC_SO, - function_setup, - count_function, - doFinalizer, - count_func_merge, - countRequired, - }, - { - // 1 - "sum", - TSDB_FUNC_SUM, - TSDB_FUNC_SUM, - TSDB_BASE_FUNC_SO, - function_setup, - sum_function, - function_finalizer, - sum_func_merge, - statisRequired, - }, - { - // 2 - "avg", - TSDB_FUNC_AVG, - TSDB_FUNC_AVG, - TSDB_BASE_FUNC_SO, - function_setup, - avg_function, - avg_finalizer, - avg_func_merge, - statisRequired, - }, - { - // 3 - "min", - TSDB_FUNC_MIN, - TSDB_FUNC_MIN, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, - min_func_setup, - min_function, - function_finalizer, - min_func_merge, - statisRequired, - }, - { - // 4 - "max", - TSDB_FUNC_MAX, - TSDB_FUNC_MAX, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, - max_func_setup, - max_function, - function_finalizer, - max_func_merge, - statisRequired, - }, - { - // 5 - "stddev", - TSDB_FUNC_STDDEV, - TSDB_FUNC_STDDEV_DST, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, - function_setup, - stddev_function, - stddev_finalizer, - noop1, - dataBlockRequired, - }, - { - // 6 - "percentile", - TSDB_FUNC_PERCT, - TSDB_FUNC_INVALID_ID, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, - percentile_function_setup, - percentile_function, - percentile_finalizer, - noop1, - dataBlockRequired, - }, - { - // 7 - "apercentile", - TSDB_FUNC_APERCT, - TSDB_FUNC_APERCT, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE, - apercentile_function_setup, - apercentile_function, - apercentile_finalizer, - apercentile_func_merge, - dataBlockRequired, - }, - { - // 8 - "first", - TSDB_FUNC_FIRST, - TSDB_FUNC_FIRST_DST, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, - function_setup, - first_function, - function_finalizer, - noop1, - firstFuncRequired, - }, - { - // 9 - "last", - TSDB_FUNC_LAST, - TSDB_FUNC_LAST_DST, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, - function_setup, - last_function, - function_finalizer, - noop1, - lastFuncRequired, - }, - { - // 10 - "last_row", - TSDB_FUNC_LAST_ROW, - TSDB_FUNC_LAST_ROW, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | - TSDB_FUNCSTATE_SELECTIVITY, - first_last_function_setup, - last_row_function, - last_row_finalizer, - last_dist_func_merge, - dataBlockRequired, - }, - { - // 11 - "top", - TSDB_FUNC_TOP, - TSDB_FUNC_TOP, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_NEED_TS | - TSDB_FUNCSTATE_SELECTIVITY, - top_bottom_function_setup, - top_function, - top_bottom_func_finalizer, - top_func_merge, - dataBlockRequired, - }, - { - // 12 - "bottom", - TSDB_FUNC_BOTTOM, - TSDB_FUNC_BOTTOM, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_NEED_TS | - TSDB_FUNCSTATE_SELECTIVITY, - top_bottom_function_setup, - bottom_function, - top_bottom_func_finalizer, - bottom_func_merge, - dataBlockRequired, - }, - { - // 13 - "spread", - TSDB_FUNC_SPREAD, - TSDB_FUNC_SPREAD, - TSDB_BASE_FUNC_SO, - spread_function_setup, - spread_function, - spread_function_finalizer, - spread_func_merge, - countRequired, - }, - { - // 14 - "twa", - TSDB_FUNC_TWA, - TSDB_FUNC_TWA, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, - twa_function_setup, - twa_function, - twa_function_finalizer, - twa_function_copy, - dataBlockRequired, - }, - { - // 15 - "leastsquares", - TSDB_FUNC_LEASTSQR, - TSDB_FUNC_INVALID_ID, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, - leastsquares_function_setup, - leastsquares_function, - leastsquares_finalizer, - noop1, - dataBlockRequired, - }, - { - // 16 - "ts", - TSDB_FUNC_TS, - TSDB_FUNC_TS, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, - function_setup, - date_col_output_function, - doFinalizer, - copy_function, - noDataRequired, - }, - { - // 17 - "ts", - TSDB_FUNC_TS_DUMMY, - TSDB_FUNC_TS_DUMMY, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, - function_setup, - noop1, - doFinalizer, - copy_function, - dataBlockRequired, - }, - { - // 18 - "tag_dummy", - TSDB_FUNC_TAG_DUMMY, - TSDB_FUNC_TAG_DUMMY, - TSDB_BASE_FUNC_SO, - function_setup, - tag_function, - doFinalizer, - copy_function, - noDataRequired, - }, - { - // 19 - "ts", - TSDB_FUNC_TS_COMP, - TSDB_FUNC_TS_COMP, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_NEED_TS, - ts_comp_function_setup, - ts_comp_function, - ts_comp_finalize, - copy_function, - dataBlockRequired, - }, - { - // 20 - "tag", - TSDB_FUNC_TAG, - TSDB_FUNC_TAG, - TSDB_BASE_FUNC_SO, - function_setup, - tag_function, - doFinalizer, - copy_function, - noDataRequired, - }, - { - // 21, column project sql function - "colprj", - TSDB_FUNC_PRJ, - TSDB_FUNC_PRJ, - TSDB_BASE_FUNC_MO | TSDB_FUNCSTATE_NEED_TS, - function_setup, - col_project_function, - doFinalizer, - copy_function, - dataBlockRequired, - }, - { - // 22, multi-output, tag function has only one result - "tagprj", - TSDB_FUNC_TAGPRJ, - TSDB_FUNC_TAGPRJ, - TSDB_BASE_FUNC_MO, - function_setup, - tag_project_function, - doFinalizer, - copy_function, - noDataRequired, - }, - { - // 23 - "arithmetic", - TSDB_FUNC_ARITHM, - TSDB_FUNC_ARITHM, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS, - function_setup, - arithmetic_function, - doFinalizer, - copy_function, - dataBlockRequired, - }, - { - // 24 - "diff", - TSDB_FUNC_DIFF, - TSDB_FUNC_INVALID_ID, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, - diff_function_setup, - diff_function, - doFinalizer, - noop1, - dataBlockRequired, - }, +SAggFunctionInfo aAggs[] = { + { + // 0, count function does not invoke the finalize function + "count", + TSDB_FUNC_COUNT, + TSDB_FUNC_COUNT, + TSDB_BASE_FUNC_SO, + function_setup, + count_function, + doFinalizer, + count_func_merge, + countRequired, + }, + { + // 1 + "sum", + TSDB_FUNC_SUM, + TSDB_FUNC_SUM, + TSDB_BASE_FUNC_SO, + function_setup, + sum_function, + function_finalizer, + sum_func_merge, + statisRequired, + }, + { + // 2 + "avg", + TSDB_FUNC_AVG, + TSDB_FUNC_AVG, + TSDB_BASE_FUNC_SO, + function_setup, + avg_function, + avg_finalizer, + avg_func_merge, + statisRequired, + }, + { + // 3 + "min", + TSDB_FUNC_MIN, + TSDB_FUNC_MIN, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, + min_func_setup, + min_function, + function_finalizer, + min_func_merge, + statisRequired, + }, + { + // 4 + "max", + TSDB_FUNC_MAX, + TSDB_FUNC_MAX, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, + max_func_setup, + max_function, + function_finalizer, + max_func_merge, + statisRequired, + }, + { + // 5 + "stddev", + TSDB_FUNC_STDDEV, + TSDB_FUNC_STDDEV_DST, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, + function_setup, + stddev_function, + stddev_finalizer, + noop1, + dataBlockRequired, + }, + { + // 6 + "percentile", + TSDB_FUNC_PERCT, + TSDB_FUNC_INVALID_ID, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, + percentile_function_setup, + percentile_function, + percentile_finalizer, + noop1, + dataBlockRequired, + }, + { + // 7 + "apercentile", + TSDB_FUNC_APERCT, + TSDB_FUNC_APERCT, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE, + apercentile_function_setup, + apercentile_function, + apercentile_finalizer, + apercentile_func_merge, + dataBlockRequired, + }, + { + // 8 + "first", + TSDB_FUNC_FIRST, + TSDB_FUNC_FIRST_DST, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, + function_setup, + first_function, + function_finalizer, + noop1, + firstFuncRequired, + }, + { + // 9 + "last", + TSDB_FUNC_LAST, + TSDB_FUNC_LAST_DST, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_SELECTIVITY, + function_setup, + last_function, + function_finalizer, + noop1, + lastFuncRequired, + }, + { + // 10 + "last_row", + TSDB_FUNC_LAST_ROW, + TSDB_FUNC_LAST_ROW, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | + TSDB_FUNCSTATE_SELECTIVITY, + first_last_function_setup, + last_row_function, + last_row_finalizer, + last_dist_func_merge, + dataBlockRequired, + }, + { + // 11 + "top", + TSDB_FUNC_TOP, + TSDB_FUNC_TOP, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_NEED_TS | + TSDB_FUNCSTATE_SELECTIVITY, + top_bottom_function_setup, + top_function, + top_bottom_func_finalizer, + top_func_merge, + dataBlockRequired, + }, + { + // 12 + "bottom", + TSDB_FUNC_BOTTOM, + TSDB_FUNC_BOTTOM, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_NEED_TS | + TSDB_FUNCSTATE_SELECTIVITY, + top_bottom_function_setup, + bottom_function, + top_bottom_func_finalizer, + bottom_func_merge, + dataBlockRequired, + }, + { + // 13 + "spread", + TSDB_FUNC_SPREAD, + TSDB_FUNC_SPREAD, + TSDB_BASE_FUNC_SO, + spread_function_setup, + spread_function, + spread_function_finalizer, + spread_func_merge, + countRequired, + }, + { + // 14 + "twa", + TSDB_FUNC_TWA, + TSDB_FUNC_TWA, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, + twa_function_setup, + twa_function, + twa_function_finalizer, + twa_function_copy, + dataBlockRequired, + }, + { + // 15 + "leastsquares", + TSDB_FUNC_LEASTSQR, + TSDB_FUNC_INVALID_ID, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STREAM | TSDB_FUNCSTATE_OF, + leastsquares_function_setup, + leastsquares_function, + leastsquares_finalizer, + noop1, + dataBlockRequired, + }, + { + // 16 + "ts", + TSDB_FUNC_TS, + TSDB_FUNC_TS, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, + function_setup, + date_col_output_function, + doFinalizer, + copy_function, + noDataRequired, + }, + { + // 17 + "ts", + TSDB_FUNC_TS_DUMMY, + TSDB_FUNC_TS_DUMMY, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, + function_setup, + noop1, + doFinalizer, + copy_function, + dataBlockRequired, + }, + { + // 18 + "tag_dummy", + TSDB_FUNC_TAG_DUMMY, + TSDB_FUNC_TAG_DUMMY, + TSDB_BASE_FUNC_SO, + function_setup, + tag_function, + doFinalizer, + copy_function, + noDataRequired, + }, + { + // 19 + "ts", + TSDB_FUNC_TS_COMP, + TSDB_FUNC_TS_COMP, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_NEED_TS, + ts_comp_function_setup, + ts_comp_function, + ts_comp_finalize, + copy_function, + dataBlockRequired, + }, + { + // 20 + "tag", + TSDB_FUNC_TAG, + TSDB_FUNC_TAG, + TSDB_BASE_FUNC_SO, + function_setup, + tag_function, + doFinalizer, + copy_function, + noDataRequired, + }, + { + // 21, column project sql function + "colprj", + TSDB_FUNC_PRJ, + TSDB_FUNC_PRJ, + TSDB_BASE_FUNC_MO | TSDB_FUNCSTATE_NEED_TS, + function_setup, + col_project_function, + doFinalizer, + copy_function, + dataBlockRequired, + }, + { + // 22, multi-output, tag function has only one result + "tagprj", + TSDB_FUNC_TAGPRJ, + TSDB_FUNC_TAGPRJ, + TSDB_BASE_FUNC_MO, + function_setup, + tag_project_function, + doFinalizer, + copy_function, + noDataRequired, + }, + { + // 23 + "arithmetic", + TSDB_FUNC_ARITHM, + TSDB_FUNC_ARITHM, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS, + function_setup, + arithmetic_function, + doFinalizer, + copy_function, + dataBlockRequired, + }, + { + // 24 + "diff", + TSDB_FUNC_DIFF, + TSDB_FUNC_INVALID_ID, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, + diff_function_setup, + diff_function, + doFinalizer, + noop1, + dataBlockRequired, + }, // distributed version used in two-stage aggregation processes - { - // 25 - "first_dist", - TSDB_FUNC_FIRST_DST, - TSDB_FUNC_FIRST_DST, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, - first_last_function_setup, - first_dist_function, - function_finalizer, - first_dist_func_merge, - firstDistFuncRequired, - }, - { - // 26 - "last_dist", - TSDB_FUNC_LAST_DST, - TSDB_FUNC_LAST_DST, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, - first_last_function_setup, - last_dist_function, - function_finalizer, - last_dist_func_merge, - lastDistFuncRequired, - }, - { - // 27 - "stddev", // return table id and the corresponding tags for join match and subscribe - TSDB_FUNC_STDDEV_DST, - TSDB_FUNC_AVG, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STABLE, - function_setup, - stddev_dst_function, - stddev_dst_finalizer, - stddev_dst_merge, - dataBlockRequired, - }, - { - // 28 - "interp", - TSDB_FUNC_INTERP, - TSDB_FUNC_INTERP, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS , - function_setup, - interp_function, - doFinalizer, - copy_function, - dataBlockRequired, - }, - { - // 29 - "rate", - TSDB_FUNC_RATE, - TSDB_FUNC_RATE, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, - rate_function_setup, - rate_function, - rate_finalizer, - rate_func_copy, - dataBlockRequired, - }, - { - // 30 - "irate", - TSDB_FUNC_IRATE, - TSDB_FUNC_IRATE, - TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, - rate_function_setup, - irate_function, - rate_finalizer, - rate_func_copy, - dataBlockRequired, - }, - { - // 31 - "tbid", // return table id and the corresponding tags for join match and subscribe - TSDB_FUNC_TID_TAG, - TSDB_FUNC_TID_TAG, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE, - function_setup, - noop1, - noop1, - noop1, - dataBlockRequired, - }, - { //32 - "derivative", // return table id and the corresponding tags for join match and subscribe - TSDB_FUNC_DERIVATIVE, - TSDB_FUNC_INVALID_ID, - TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, - deriv_function_setup, - deriv_function, - doFinalizer, - noop1, - dataBlockRequired, - }, - { - // 33 - "_block_dist", // return table id and the corresponding tags for join match and subscribe - TSDB_FUNC_BLKINFO, - TSDB_FUNC_BLKINFO, - TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STABLE, - function_setup, - blockInfo_func, - blockinfo_func_finalizer, - block_func_merge, - dataBlockRequired, - }}; + { + // 25 + "first_dist", + TSDB_FUNC_FIRST_DST, + TSDB_FUNC_FIRST_DST, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, + first_last_function_setup, + first_dist_function, + function_finalizer, + first_dist_func_merge, + firstDistFuncRequired, + }, + { + // 26 + "last_dist", + TSDB_FUNC_LAST_DST, + TSDB_FUNC_LAST_DST, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, + first_last_function_setup, + last_dist_function, + function_finalizer, + last_dist_func_merge, + lastDistFuncRequired, + }, + { + // 27 + "stddev", // return table id and the corresponding tags for join match and subscribe + TSDB_FUNC_STDDEV_DST, + TSDB_FUNC_AVG, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STABLE, + function_setup, + stddev_dst_function, + stddev_dst_finalizer, + stddev_dst_merge, + dataBlockRequired, + }, + { + // 28 + "interp", + TSDB_FUNC_INTERP, + TSDB_FUNC_INTERP, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_OF | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS, + function_setup, + interp_function, + doFinalizer, + copy_function, + dataBlockRequired, + }, + { + // 29 + "rate", + TSDB_FUNC_RATE, + TSDB_FUNC_RATE, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, + rate_function_setup, + rate_function, + rate_finalizer, + rate_func_copy, + dataBlockRequired, + }, + { + // 30 + "irate", + TSDB_FUNC_IRATE, + TSDB_FUNC_IRATE, + TSDB_BASE_FUNC_SO | TSDB_FUNCSTATE_NEED_TS, + rate_function_setup, + irate_function, + rate_finalizer, + rate_func_copy, + dataBlockRequired, + }, + { + // 31 + "tbid", // return table id and the corresponding tags for join match and subscribe + TSDB_FUNC_TID_TAG, + TSDB_FUNC_TID_TAG, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE, + function_setup, + noop1, + noop1, + noop1, + dataBlockRequired, + }, + { + // 32 + "derivative", // return table id and the corresponding tags for join match and subscribe + TSDB_FUNC_DERIVATIVE, + TSDB_FUNC_INVALID_ID, + TSDB_FUNCSTATE_MO | TSDB_FUNCSTATE_STABLE | TSDB_FUNCSTATE_NEED_TS | TSDB_FUNCSTATE_SELECTIVITY, + deriv_function_setup, + deriv_function, + doFinalizer, + noop1, + dataBlockRequired, + }, + { + // 33 + "_block_dist", // return table id and the corresponding tags for join match and subscribe + TSDB_FUNC_BLKINFO, + TSDB_FUNC_BLKINFO, + TSDB_FUNCSTATE_SO | TSDB_FUNCSTATE_STABLE, + function_setup, + blockInfo_func, + blockinfo_func_finalizer, + block_func_merge, + dataBlockRequired, + }}; diff --git a/src/query/src/tdigest.c b/src/query/src/tdigest.c new file mode 100644 index 0000000000000000000000000000000000000000..17eb57760129eb9b615b5d1d664cfcfb94176f66 --- /dev/null +++ b/src/query/src/tdigest.c @@ -0,0 +1,345 @@ +/* + * src/tdigest.c + * + * Implementation of the t-digest data structure used to compute accurate percentiles. + * + * It is based on the MergingDigest implementation found at: + * https://github.com/tdunning/t-digest/blob/master/src/main/java/com/tdunning/math/stats/MergingDigest.java + * + * Copyright (c) 2016, Usman Masood + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "tdigest.h" + +#define INTERPOLATE(x, x0, x1) (((x) - (x0)) / ((x1) - (x0))) +#define INTEGRATED_LOCATION(compression, q) ((compression) * (asin(2 * (q) - 1) + M_PI / 2) / M_PI) +#define FLOAT_EQ(f1, f2) (fabs((f1) - (f2)) <= FLT_EPSILON) + +/* From http://stackoverflow.com/questions/3437404/min-and-max-in-c */ +#define MAX(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) +#define MIN(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +struct TDigest *tdigestNew(int compression) { + struct TDigest *t = malloc(sizeof(struct TDigest)); + + memset(t, 0, sizeof(struct TDigest)); + + t->compression = compression; + t->size = ceil(compression * M_PI / 2) + 1; + t->threshold = 7.5 + 0.37 * compression - 2e-4 * pow(compression, 2); + t->min = INFINITY; + + return t; +} + +static int centroid_cmp(const void *a, const void *b) { + struct Centroid *c1 = (struct Centroid *) a; + struct Centroid *c2 = (struct Centroid *) b; + if (c1->mean < c2->mean) + return -1; + if (c1->mean > c2->mean) + return 1; + return 0; +} + +struct MergeArgs { + struct TDigest *t; + struct Centroid *centroids; + int idx; + double weight_so_far; + double k1; + double min; + double max; +}; + +static void merge_centroid(struct MergeArgs *args, struct Centroid *merge) { + double k2; + struct Centroid *c = &args->centroids[args->idx]; + + args->weight_so_far += merge->weight; + k2 = INTEGRATED_LOCATION(args->t->compression, + args->weight_so_far / args->t->total_weight); + + if (k2 - args->k1 > 1 && c->weight > 0) { + args->idx++; + args->k1 = INTEGRATED_LOCATION(args->t->compression, + (args->weight_so_far - merge->weight) / args->t->total_weight); + } + + c = &args->centroids[args->idx]; + c->weight += merge->weight; + c->mean += (merge->mean - c->mean) * merge->weight / c->weight; + + if (merge->weight > 0) { + args->min = MIN(merge->mean, args->min); + args->max = MAX(merge->mean, args->max); + } +} + +void tdigestCompress(struct TDigest *t) { + struct Centroid *unmerged_centroids; + long long unmerged_weight = 0; + int num_unmerged = t->num_buffered_pts; + int old_num_centroids = t->num_centroids; + int i, j; + struct MergeArgs args; + + if (!t->num_buffered_pts) + return; + + unmerged_centroids = malloc(sizeof(struct Centroid) * t->num_buffered_pts); + + i = 0; + for (i = 0; i < num_unmerged; i++) { + struct Point *p = t->buffered_pts; + struct Centroid *c = &unmerged_centroids[i]; + + c->mean = p->value; + c->weight = p->weight; + + unmerged_weight += c->weight; + + t->buffered_pts = p->next; + free(p); + } + + t->num_buffered_pts = 0; + t->total_weight += unmerged_weight; + + qsort(unmerged_centroids, num_unmerged, sizeof(struct Centroid), + centroid_cmp); + + memset(&args, 0, sizeof(struct MergeArgs)); + + args.centroids = malloc(sizeof(struct Centroid) * t->size); + memset(args.centroids, 0, sizeof(struct Centroid) * t->size); + + args.t = t; + args.min = INFINITY; + + i = 0; + j = 0; + while (i < num_unmerged && j < t->num_centroids) { + struct Centroid *a = &unmerged_centroids[i]; + struct Centroid *b = &t->centroids[j]; + + if (a->mean <= b->mean) { + merge_centroid(&args, a); + i++; + } else { + merge_centroid(&args, b); + j++; + } + } + + while (i < num_unmerged) + merge_centroid(&args, &unmerged_centroids[i++]); + + free(unmerged_centroids); + + while (j < t->num_centroids) + merge_centroid(&args, &t->centroids[j++]); + + if (t->total_weight > 0) { + t->min = MIN(t->min, args.min); + + if (args.centroids[args.idx].weight <= 0) + args.idx--; + + t->num_centroids = args.idx + 1; + t->max = MAX(t->max, args.max); + } + + if (t->num_centroids > old_num_centroids) { + t->centroids = realloc(t->centroids, + sizeof(struct Centroid) * t->num_centroids); + } + + memcpy(t->centroids, args.centroids, + sizeof(struct Centroid) * t->num_centroids); + + free(args.centroids); +} + +void tdigestAdd(struct TDigest *t, double x, long long w) { + if (w == 0) + return; + + struct Point *p = malloc(sizeof(struct Point)); + + p->value = x; + p->weight = w; + p->next = t->buffered_pts; + + t->buffered_pts = p; + t->num_buffered_pts++; + + if (t->num_buffered_pts > t->threshold) + tdigestCompress(t); +} + +double tdigestCDF(struct TDigest *t, double x) { + if (t == NULL) + return 0; + + int i; + double left, right; + long long weight_so_far; + struct Centroid *a, *b, tmp; + + tdigestCompress(t); + + if (t->num_centroids == 0) + return NAN; + + if (x < t->min) + return 0; + if (x > t->max) + return 1; + + if (t->num_centroids == 1) { + if (FLOAT_EQ(t->max, t->min)) + return 0.5; + + return INTERPOLATE(x, t->min, t->max); + } + + weight_so_far = 0; + a = b = &tmp; + b->mean = t->min; + b->weight = 0; + right = 0; + + for (i = 0; i < t->num_centroids; i++) { + struct Centroid *c = &t->centroids[i]; + + left = b->mean - (a->mean + right); + a = b; + b = c; + right = (b->mean - a->mean) * a->weight / (a->weight + b->weight); + + if (x < a->mean + right) { + double cdf = (weight_so_far + + a->weight + * INTERPOLATE(x, a->mean - left, a->mean + right)) + / t->total_weight; + return MAX(cdf, 0.0); + } + + weight_so_far += a->weight; + } + + left = b->mean - (a->mean + right); + a = b; + right = t->max - a->mean; + + if (x < a->mean + right) + return (weight_so_far + + a->weight * INTERPOLATE(x, a->mean - left, a->mean + right)) + / t->total_weight; + + return 1; +} + +double tdigestQuantile(struct TDigest *t, double q) { + if (t == NULL) + return 0; + + int i; + double left, right, idx; + long long weight_so_far; + struct Centroid *a, *b, tmp; + + tdigestCompress(t); + + if (t->num_centroids == 0) + return NAN; + + if (t->num_centroids == 1) + return t->centroids[0].mean; + + if (FLOAT_EQ(q, 0.0)) + return t->min; + + if (FLOAT_EQ(q, 1.0)) + return t->max; + + idx = q * t->total_weight; + + weight_so_far = 0; + b = &tmp; + b->mean = t->min; + b->weight = 0; + right = t->min; + + for (i = 0; i < t->num_centroids; i++) { + struct Centroid *c = &t->centroids[i]; + a = b; + left = right; + + b = c; + right = (b->weight * a->mean + a->weight * b->mean) + / (a->weight + b->weight); + + if (idx < weight_so_far + a->weight) { + double p = (idx - weight_so_far) / a->weight; + return left * (1 - p) + right * p; + } + + weight_so_far += a->weight; + } + + left = right; + a = b; + right = t->max; + + if (idx < weight_so_far + a->weight) { + double p = (idx - weight_so_far) / a->weight; + return left * (1 - p) + right * p; + } + + return t->max; +} + +void tdigestMerge(struct TDigest *t1, struct TDigest *t2) { + int i = t2->num_buffered_pts; + struct Point *p = t2->buffered_pts; + + while (i) { + tdigestAdd(t1, p->value, p->weight); + p = p->next; + i--; + } + + for (i = 0; i < t2->num_centroids; i++) { + tdigestAdd(t1, t2->centroids[i].mean, t2->centroids[i].weight); + } +} + +void tdigestFree(struct TDigest *t) { + while (t->buffered_pts) { + struct Point *p = t->buffered_pts; + t->buffered_pts = t->buffered_pts->next; + free(p); + } + + if (t->centroids) + free(t->centroids); + + free(t); +} +