• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3546

03 Dec 2024 10:02AM UTC coverage: 60.691% (-0.1%) from 60.839%
#3546

push

travis-ci

web-flow
Merge pull request #29015 from taosdata/fix/TS-5668

[TS-5668] fix(keeper): fix endpoint value too long for column/tag and eliminate warnings

120577 of 253823 branches covered (47.5%)

Branch coverage included in aggregate %.

201666 of 277134 relevant lines covered (72.77%)

18719900.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.27
/source/libs/function/src/builtinsimpl.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "builtinsimpl.h"
17
#include "cJSON.h"
18
#include "function.h"
19
#include "functionResInfoInt.h"
20
#include "query.h"
21
#include "querynodes.h"
22
#include "tanalytics.h"
23
#include "tcompare.h"
24
#include "tdatablock.h"
25
#include "tdigest.h"
26
#include "tfunctionInt.h"
27
#include "tglobal.h"
28
#include "thistogram.h"
29
#include "tpercentile.h"
30

31
bool ignoreNegative(int8_t ignoreOption) { return (ignoreOption & 0x1) == 0x1; }
1,413,284,312✔
32
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
1,741,928✔
33

34
typedef enum {
35
  APERCT_ALGO_UNKNOWN = 0,
36
  APERCT_ALGO_DEFAULT,
37
  APERCT_ALGO_TDIGEST,
38
} EAPerctAlgoType;
39

40
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
41

42
typedef enum {
43
  STATE_OPER_INVALID = 0,
44
  STATE_OPER_LT,
45
  STATE_OPER_GT,
46
  STATE_OPER_LE,
47
  STATE_OPER_GE,
48
  STATE_OPER_NE,
49
  STATE_OPER_EQ,
50
} EStateOperType;
51

52
#define SET_VAL(_info, numOfElem, res) \
53
  do {                                 \
54
    if ((numOfElem) <= 0) {            \
55
      break;                           \
56
    }                                  \
57
    (_info)->numOfRes = (res);         \
58
  } while (0)
59

60
#define GET_TS_LIST(x)    ((TSKEY*)((x)->ptsList))
61
#define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)])
62

63
#define DO_UPDATE_SUBSID_RES(ctx, ts)                          \
64
  do {                                                         \
65
    for (int32_t _i = 0; _i < (ctx)->subsidiaries.num; ++_i) { \
66
      SqlFunctionCtx* __ctx = (ctx)->subsidiaries.pCtx[_i];    \
67
      if (__ctx->functionId == FUNCTION_TS_DUMMY) {            \
68
        __ctx->tag.i = (ts);                                   \
69
        __ctx->tag.nType = TSDB_DATA_TYPE_BIGINT;              \
70
      }                                                        \
71
      __ctx->fpSet.process(__ctx);                             \
72
    }                                                          \
73
  } while (0)
74

75
#define UPDATE_DATA(ctx, left, right, num, sign, _ts) \
76
  do {                                                \
77
    if (((left) < (right)) ^ (sign)) {                \
78
      (left) = (right);                               \
79
      DO_UPDATE_SUBSID_RES(ctx, _ts);                 \
80
      (num) += 1;                                     \
81
    }                                                 \
82
  } while (0)
83

84
#define LOOPCHECK_N(val, _col, ctx, _t, _nrow, _start, sign, num)        \
85
  do {                                                                   \
86
    _t* d = (_t*)((_col)->pData);                                        \
87
    for (int32_t i = (_start); i < (_nrow) + (_start); ++i) {            \
88
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
89
        continue;                                                        \
90
      }                                                                  \
91
      TSKEY ts = (ctx)->ptsList != NULL ? GET_TS_DATA(ctx, i) : 0;       \
92
      UPDATE_DATA(ctx, val, d[i], num, sign, ts);                        \
93
    }                                                                    \
94
  } while (0)
95

96
#define LIST_ADD_N(_res, _col, _start, _rows, _t, numOfElem)             \
97
  do {                                                                   \
98
    _t* d = (_t*)(_col->pData);                                          \
99
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {            \
100
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
101
        continue;                                                        \
102
      };                                                                 \
103
      (_res) += (d)[i];                                                  \
104
      (numOfElem)++;                                                     \
105
    }                                                                    \
106
  } while (0)
107

108
#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem)             \
109
  do {                                                                   \
110
    _t* d = (_t*)(_col->pData);                                          \
111
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {            \
112
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
113
        continue;                                                        \
114
      };                                                                 \
115
      (_res) -= (d)[i];                                                  \
116
      (numOfElem)++;                                                     \
117
    }                                                                    \
118
  } while (0)
119

120
//#define LIST_AVG_N(sumT, T)                                               \
121
//  do {                                                                    \
122
//    T* plist = (T*)pCol->pData;                                           \
123
//    for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
124
//      if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {        \
125
//        continue;                                                         \
126
//      }                                                                   \
127
//                                                                          \
128
//      numOfElem += 1;                                                     \
129
//      pAvgRes->count -= 1;                                                \
130
//      sumT -= plist[i];                                                   \
131
//    }                                                                     \
132
//  } while (0)
133

134
#define LIST_STDDEV_SUB_N(sumT, T)                                 \
135
  do {                                                             \
136
    T* plist = (T*)pCol->pData;                                    \
137
    for (int32_t i = start; i < numOfRows + start; ++i) {          \
138
      if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { \
139
        continue;                                                  \
140
      }                                                            \
141
      numOfElem += 1;                                              \
142
      pStddevRes->count -= 1;                                      \
143
      sumT -= plist[i];                                            \
144
      pStddevRes->quadraticISum -= (int64_t)(plist[i] * plist[i]); \
145
    }                                                              \
146
  } while (0)
147

148
#define LEASTSQR_CAL(p, x, y, index, step) \
149
  do {                                     \
150
    (p)[0][0] += (double)(x) * (x);        \
151
    (p)[0][1] += (double)(x);              \
152
    (p)[0][2] += (double)(x) * (y)[index]; \
153
    (p)[1][2] += (y)[index];               \
154
    (x) += step;                           \
155
  } while (0)
156

157
#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
158

159
#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
160

161
#define STATE_COMP_IMPL(_op, _lval, _rval) \
162
  do {                                     \
163
    switch (_op) {                         \
164
      case STATE_OPER_LT:                  \
165
        return ((_lval) < (_rval));        \
166
        break;                             \
167
      case STATE_OPER_GT:                  \
168
        return ((_lval) > (_rval));        \
169
        break;                             \
170
      case STATE_OPER_LE:                  \
171
        return ((_lval) <= (_rval));       \
172
        break;                             \
173
      case STATE_OPER_GE:                  \
174
        return ((_lval) >= (_rval));       \
175
        break;                             \
176
      case STATE_OPER_NE:                  \
177
        return ((_lval) != (_rval));       \
178
        break;                             \
179
      case STATE_OPER_EQ:                  \
180
        return ((_lval) == (_rval));       \
181
        break;                             \
182
      default:                             \
183
        break;                             \
184
    }                                      \
185
  } while (0)
186

187
#define INIT_INTP_POINT(_p, _k, _v) \
188
  do {                              \
189
    (_p).key = (_k);                \
190
    (_p).val = (_v);                \
191
  } while (0)
192

193
void funcInputUpdate(SqlFunctionCtx* pCtx) {
15,354,183✔
194
  SFuncInputRowIter* pIter = &pCtx->rowIter;
15,354,183✔
195

196
  if (!pCtx->bInputFinished) {
15,354,183!
197
    pIter->pInput = &pCtx->input;
15,354,212✔
198
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
15,354,212✔
199
    pIter->pDataCol = pIter->pInput->pData[0];
15,354,212✔
200
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
15,354,212✔
201
    pIter->rowIndex = pIter->pInput->startRowIndex;
15,354,212✔
202
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
15,354,212✔
203
    pIter->pSrcBlock = pCtx->pSrcBlock;
15,354,212✔
204
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
15,354,212✔
205
      pIter->hasGroupId = true;
179,797✔
206
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
179,797✔
207
      pIter->hasPrev = false;
179,797✔
208
    }
209
  } else {
210
    pIter->finalRow = true;
×
211
  }
212
}
15,354,183✔
213

214
int32_t funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow, bool* res) {
×
215
  if (pIter->finalRow) {
×
216
    if (pIter->hasPrev) {
×
217
      pRow->ts = pIter->prevBlockTsEnd;
×
218
      pRow->isDataNull = pIter->prevIsDataNull;
×
219
      pRow->pData = pIter->pPrevData;
×
220
      pRow->block = pIter->pPrevRowBlock;
×
221
      pRow->rowIndex = 0;
×
222

223
      pIter->hasPrev = false;
×
224
      *res = true;
×
225
      return TSDB_CODE_SUCCESS;
×
226
    } else {
227
      *res = false;
×
228
      return TSDB_CODE_SUCCESS;
×
229
    }
230
  }
231
  if (pIter->hasPrev) {
×
232
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
×
233
      blockDataDestroy(pIter->pPrevRowBlock);
×
234
      int32_t code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
235
      if (code) {
×
236
        return code;
×
237
      }
238

239
      pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex);
×
240

241
      pIter->pPrevData = taosMemoryMalloc(pIter->pDataCol->info.bytes);
×
242
      if (NULL == pIter->pPrevData) {
×
243
        qError("out of memory when function get input row.");
×
244
        return terrno;
×
245
      }
246
      char* srcData = colDataGetData(pIter->pDataCol, pIter->inputEndIndex);
×
247
      (void)memcpy(pIter->pPrevData, srcData, pIter->pDataCol->info.bytes);
×
248

249
      pIter->pPrevPk = taosMemoryMalloc(pIter->pPkCol->info.bytes);
×
250
      if (NULL == pIter->pPrevPk) {
×
251
        qError("out of memory when function get input row.");
×
252
        taosMemoryFree(pIter->pPrevData);
×
253
        return terrno;
×
254
      }
255
      char* pkData = colDataGetData(pIter->pPkCol, pIter->inputEndIndex);
×
256
      (void)memcpy(pIter->pPrevPk, pkData, pIter->pPkCol->info.bytes);
×
257

258
      code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
259
      pIter->hasPrev = true;
×
260
      *res = false;
×
261
      return code;
×
262
    } else {
263
      int32_t idx = pIter->rowIndex;
×
264
      while (pIter->tsList[idx] == pIter->prevBlockTsEnd) {
×
265
        ++idx;
×
266
      }
267
      pRow->ts = pIter->prevBlockTsEnd;
×
268
      if (idx == pIter->pInput->startRowIndex) {
×
269
        pRow->isDataNull = pIter->prevIsDataNull;
×
270
        pRow->pData = pIter->pPrevData;
×
271
        pRow->block = pIter->pPrevRowBlock;
×
272
        pRow->rowIndex = 0;
×
273
      } else {
274
        pRow->ts = pIter->tsList[idx - 1];
×
275
        pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, idx - 1);
×
276
        pRow->pData = colDataGetData(pIter->pDataCol, idx - 1);
×
277
        pRow->pPk = colDataGetData(pIter->pPkCol, idx - 1);
×
278
        pRow->block = pIter->pSrcBlock;
×
279
        pRow->rowIndex = idx - 1;
×
280
      }
281
      pIter->hasPrev = false;
×
282
      pIter->rowIndex = idx;
×
283
      *res = true;
×
284
      return TSDB_CODE_SUCCESS;
×
285
    }
286
  } else {
287
    TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
×
288
    if (pIter->tsList[pIter->rowIndex] != tsEnd) {
×
289
      int32_t idx = pIter->rowIndex;
×
290
      while (pIter->tsList[idx + 1] == pIter->tsList[pIter->rowIndex]) {
×
291
        ++idx;
×
292
      }
293
      pRow->ts = pIter->tsList[idx];
×
294
      pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, idx);
×
295
      pRow->pData = colDataGetData(pIter->pDataCol, idx);
×
296
      pRow->pPk = colDataGetData(pIter->pPkCol, idx);
×
297
      pRow->block = pIter->pSrcBlock;
×
298

299
      pIter->rowIndex = idx + 1;
×
300
      *res = true;
×
301
      return TSDB_CODE_SUCCESS;
×
302
    } else {
303
      pIter->hasPrev = true;
×
304
      pIter->prevBlockTsEnd = tsEnd;
×
305
      pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex);
×
306
      pIter->pPrevData = taosMemoryMalloc(pIter->pDataCol->info.bytes);
×
307
      if (NULL == pIter->pPrevData) {
×
308
        qError("out of memory when function get input row.");
×
309
        return terrno;
×
310
      }
311
      (void)memcpy(pIter->pPrevData, colDataGetData(pIter->pDataCol, pIter->inputEndIndex),
×
312
                   pIter->pDataCol->info.bytes);
×
313
      pIter->pPrevPk = taosMemoryMalloc(pIter->pPkCol->info.bytes);
×
314
      if (NULL == pIter->pPrevPk) {
×
315
        qError("out of memory when function get input row.");
×
316
        taosMemoryFree(pIter->pPrevData);
×
317
        return terrno;
×
318
      }
319
      (void)memcpy(pIter->pPrevPk, colDataGetData(pIter->pPkCol, pIter->inputEndIndex), pIter->pPkCol->info.bytes);
×
320

321
      int32_t code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
322
      *res = false;
×
323
      return code;
×
324
    }
325
  }
326
}
327

328
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
29,132✔
329
  int32_t idx = rowIndex + 1;
29,132✔
330
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
403,161!
331
    ++idx;
374,029✔
332
  }
333
  pIter->rowIndex = idx;
29,132✔
334
}
29,132✔
335

336
static void setInputRowInfo(SFuncInputRow* pRow, SFuncInputRowIter* pIter, int32_t rowIndex, bool setPk) {
1,449,727,336✔
337
  pRow->ts = pIter->tsList[rowIndex];
1,449,727,336✔
338
  pRow->ts = pIter->tsList[rowIndex];
1,449,727,336✔
339
  pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, rowIndex);
1,449,727,336✔
340
  pRow->pData = colDataGetData(pIter->pDataCol, rowIndex);
1,449,727,336!
341
  pRow->pPk = setPk ? colDataGetData(pIter->pPkCol, rowIndex) : NULL;
1,449,727,336!
342
  pRow->block = pIter->pSrcBlock;
1,449,727,336✔
343
  pRow->rowIndex = rowIndex;
1,449,727,336✔
344
}
1,449,727,336✔
345

346
bool funcInputGetNextRowAscPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
34,762✔
347
  if (pIter->hasPrev) {
34,762✔
348
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
1,404!
349
      pIter->hasPrev = true;
×
350
      return false;
×
351
    } else {
352
      int32_t idx = pIter->rowIndex;
1,404✔
353
      while (pIter->tsList[idx] == pIter->prevBlockTsEnd) {
1,404!
354
        ++idx;
×
355
      }
356

357
      pIter->hasPrev = false;
1,404✔
358
      setInputRowInfo(pRow, pIter, idx, true);
1,404✔
359
      forwardToNextDiffTsRow(pIter, idx);
1,404✔
360
      return true;
1,404✔
361
    }
362
  } else {
363
    if (pIter->rowIndex <= pIter->inputEndIndex) {
33,358✔
364
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
30,548✔
365

366
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
30,548✔
367
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
30,548✔
368
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
27,728✔
369
      } else {
370
        pIter->rowIndex = pIter->inputEndIndex + 1;
2,820✔
371
      }
372
      return true;
30,548✔
373
    } else {
374
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
2,810✔
375
      pIter->hasPrev = true;
2,810✔
376
      pIter->prevBlockTsEnd = tsEnd;
2,810✔
377
      return false;
2,810✔
378
    }
379
  }
380
}
381

382
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
1,464,909,705✔
383
  if (pIter->rowIndex <= pIter->inputEndIndex) {
1,464,909,705✔
384
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
1,449,711,800✔
385
    ++pIter->rowIndex;
1,449,624,285✔
386
    return true;
1,449,624,285✔
387
  } else {
388
    return false;
15,197,905✔
389
  }
390
}
391

392
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
1,464,976,463✔
393
  SFuncInputRowIter* pIter = &pCtx->rowIter;
1,464,976,463✔
394
  if (pCtx->hasPrimaryKey) {
1,464,976,463✔
395
    if (pCtx->order == TSDB_ORDER_ASC) {
34,762!
396
      *res = funcInputGetNextRowAscPk(pIter, pRow);
34,762✔
397
      return TSDB_CODE_SUCCESS;
34,762✔
398
    } else {
399
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
400
    }
401
  } else {
402
    *res = funcInputGetNextRowNoPk(pIter, pRow);
1,464,941,701✔
403
    return TSDB_CODE_SUCCESS;
1,464,807,648✔
404
  }
405
  return TSDB_CODE_SUCCESS;
406
}
407

408
// This function append the selectivity to subsidiaries function context directly, without fetching data
409
// from intermediate disk based buf page
410
int32_t appendSelectivityCols(SqlFunctionCtx* pCtx, SSDataBlock* pSrcBlock, int32_t rowIndex, int32_t pos) {
33,402,300✔
411
  if (pCtx->subsidiaries.num <= 0) {
33,402,300!
412
    return TSDB_CODE_SUCCESS;
×
413
  }
414

415
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
92,510,480✔
416
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
59,108,180✔
417

418
    // get data from source col
419
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
59,108,180✔
420
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
59,108,180✔
421

422
    SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
59,108,180✔
423
    if (NULL == pSrcCol) {
59,108,180!
424
      return TSDB_CODE_OUT_OF_RANGE;
×
425
    }
426

427
    char* pData = colDataGetData(pSrcCol, rowIndex);
59,108,180!
428

429
    // append to dest col
430
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
59,108,180✔
431

432
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
59,108,180✔
433
    if (NULL == pDstCol) {
59,108,180!
434
      return TSDB_CODE_OUT_OF_RANGE;
×
435
    }
436
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
118,216,360✔
437
      colDataSetNULL(pDstCol, pos);
2,580,095✔
438
    } else {
439
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
56,528,085✔
440
      if (TSDB_CODE_SUCCESS != code) {
56,528,085!
441
        return code;
×
442
      }
443
    }
444
  }
445
  return TSDB_CODE_SUCCESS;
33,402,300✔
446
}
447

448
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
449
                              int32_t* nextFrom);
450

451
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);
452

453
int32_t functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
774,442,910✔
454
  if (pResultInfo->initialized) {
774,442,910✔
455
    return TSDB_CODE_SUCCESS;  // already initialized
58,454✔
456
  }
457

458
  if (pCtx->pOutput != NULL) {
774,384,456!
459
    (void)memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes);
×
460
  }
461

462
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
774,384,456✔
463
  return TSDB_CODE_SUCCESS;
774,384,456✔
464
}
465

466
int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
193,271,150✔
467
  int32_t          code = TSDB_CODE_SUCCESS;
193,271,150✔
468
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
193,271,150✔
469
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
193,271,150✔
470
  if (NULL == pCol) {
192,678,298!
471
    return TSDB_CODE_OUT_OF_RANGE;
×
472
  }
473
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
192,678,298✔
474
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
192,678,298✔
475

476
  char* in = GET_ROWCELL_INTERBUF(pResInfo);
192,678,298✔
477
  code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
192,678,298✔
478

479
  return code;
193,903,545✔
480
}
481

482
int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
483
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
484
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
485
  int32_t              bytes = pDBuf->bytes;
3✔
486

487
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
488
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
489

490
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, true);
3✔
491

492
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
493
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
494
  return TSDB_CODE_SUCCESS;
3✔
495
}
496

497
int32_t functionFinalizeWithResultBuf(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, char* finalResult) {
1,085✔
498
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,085✔
499
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,085✔
500
  if (NULL == pCol) {
1,085!
501
    return TSDB_CODE_OUT_OF_RANGE;
×
502
  }
503
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,085✔
504
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
1,085✔
505

506
  char*   in = finalResult;
1,085✔
507
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
1,085✔
508

509
  return code;
1,085✔
510
}
511

512
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
199,251✔
513
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
199,251✔
514
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
199,288✔
515
    return FUNC_DATA_REQUIRED_NOT_LOAD;
147,822✔
516
  }
517
  return FUNC_DATA_REQUIRED_SMA_LOAD;
51,466✔
518
}
519

520
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,800,547✔
521
  pEnv->calcMemSize = sizeof(int64_t);
1,800,547✔
522
  return true;
1,800,547✔
523
}
524

525
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
123,195,630✔
526
  int64_t numOfElem = 0;
123,195,630✔
527

528
  /*
529
   * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true;
530
   * 2. for general non-primary key columns, pInputCol->hasNull may be true or false, pInput->colDataSMAIsSet == true;
531
   * 3. for primary key column, pInputCol->hasNull always be false, pInput->colDataSMAIsSet == false;
532
   */
533
  SInputColumnInfoData* pInput = &pCtx->input;
123,195,630✔
534
  SColumnInfoData*      pInputCol = pInput->pData[0];
123,195,630✔
535
  if (1 == pInput->numOfRows && pInput->blankFill) {
123,195,630✔
536
    return 0;
453,916✔
537
  }
538
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
122,741,714!
539
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
3,189✔
540
  } else {
541
    if (pInputCol->hasNull) {
122,738,525✔
542
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
360,968,452✔
543
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
657,872,150!
544
          continue;
4,324,684✔
545
        }
546
        numOfElem += 1;
324,611,391✔
547
      }
548
    } else {
549
      // when counting on the primary time stamp column and no statistics data is presented, use the size value
550
      // directly.
551
      numOfElem = pInput->numOfRows;
90,706,148✔
552
    }
553
  }
554
  return numOfElem;
122,741,714✔
555
}
556

557
/*
558
 * count function does need the finalize, if data is missing, the default value, which is 0, is used
559
 * count function does not use the pCtx->interResBuf to keep the intermediate buffer
560
 */
561
int32_t countFunction(SqlFunctionCtx* pCtx) {
123,199,215✔
562
  int64_t numOfElem = 0;
123,199,215✔
563

564
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
123,199,215✔
565
  SInputColumnInfoData* pInput = &pCtx->input;
123,199,215✔
566

567
  int32_t type = pInput->pData[0]->info.type;
123,199,215✔
568

569
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
123,199,215✔
570
  if (IS_NULL_TYPE(type)) {
123,199,215✔
571
    // select count(NULL) returns 0
572
    numOfElem = 1;
135,549✔
573
    *((int64_t*)buf) += 0;
135,549✔
574
  } else {
575
    numOfElem = getNumOfElems(pCtx);
123,063,666✔
576
    *((int64_t*)buf) += numOfElem;
122,773,247✔
577
  }
578

579
  if (tsCountAlwaysReturnValue) {
122,908,796!
580
    pResInfo->numOfRes = 1;
123,043,702✔
581
  } else {
582
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
583
  }
584

585
  return TSDB_CODE_SUCCESS;
122,908,796✔
586
}
587

588
#ifdef BUILD_NO_CALL
589
int32_t countInvertFunction(SqlFunctionCtx* pCtx) {
590
  int64_t numOfElem = getNumOfElems(pCtx);
591

592
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
593
  char*                buf = GET_ROWCELL_INTERBUF(pResInfo);
594
  *((int64_t*)buf) -= numOfElem;
595

596
  SET_VAL(pResInfo, *((int64_t*)buf), 1);
597
  return TSDB_CODE_SUCCESS;
598
}
599
#endif
600

601
int32_t combineFunction(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
18✔
602
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
18✔
603
  char*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
18✔
604

605
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
18✔
606
  char*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
18✔
607
  *((int64_t*)pDBuf) += *((int64_t*)pSBuf);
18✔
608

609
  SET_VAL(pDResInfo, *((int64_t*)pDBuf), 1);
18!
610
  return TSDB_CODE_SUCCESS;
18✔
611
}
612

613
int32_t sumFunction(SqlFunctionCtx* pCtx) {
92,783,515✔
614
  int32_t numOfElem = 0;
92,783,515✔
615

616
  // Only the pre-computing information loaded and actual data does not loaded
617
  SInputColumnInfoData* pInput = &pCtx->input;
92,783,515✔
618
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
92,783,515✔
619
  int32_t               type = pInput->pData[0]->info.type;
92,783,515✔
620

621
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
92,783,515✔
622
  pSumRes->type = type;
92,783,515✔
623

624
  if (IS_NULL_TYPE(type)) {
92,783,515✔
625
    numOfElem = 0;
233✔
626
    goto _sum_over;
233✔
627
  }
628

629
  if (pInput->colDataSMAIsSet) {
92,783,282✔
630
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
2,737✔
631

632
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
2,737!
633
      pSumRes->isum += pAgg->sum;
2,737✔
634
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
635
      pSumRes->usum += pAgg->sum;
×
636
    } else if (IS_FLOAT_TYPE(type)) {
×
637
      pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
×
638
    }
639
  } else {  // computing based on the true data block
640
    SColumnInfoData* pCol = pInput->pData[0];
92,780,545✔
641

642
    int32_t start = pInput->startRowIndex;
92,780,545✔
643
    int32_t numOfRows = pInput->numOfRows;
92,780,545✔
644

645
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
92,780,545✔
646
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
91,861,668!
647
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
1,584,341✔
648
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
91,480,037✔
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
853,387✔
650
      } else if (type == TSDB_DATA_TYPE_INT) {
91,433,490✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
414,742,654✔
652
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
21,779,988✔
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
82,430,138✔
654
      }
655
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
918,877!
656
      if (type == TSDB_DATA_TYPE_UTINYINT) {
787✔
657
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
658
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
748✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
660
      } else if (type == TSDB_DATA_TYPE_UINT) {
708✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
133,522!
662
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
440!
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
134,306✔
664
      }
665
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
918,090✔
666
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
2,346,568✔
667
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
820,755✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
1,967,933✔
669
    }
670
  }
671

672
  // check for overflow
673
  if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
92,783,282!
674
    numOfElem = 0;
×
675
  }
676

677
_sum_over:
93,129,812✔
678
  if (numOfElem == 0) {
92,783,515✔
679
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
104,327✔
680
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,806✔
681
      numOfElem = 1;
23✔
682
    }
683
  }
684
  // data in the check operation are all null, not output
685
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
92,783,515✔
686
  return TSDB_CODE_SUCCESS;
92,783,515✔
687
}
688

689
#ifdef BUILD_NO_CALL
690
int32_t sumInvertFunction(SqlFunctionCtx* pCtx) {
691
  int32_t numOfElem = 0;
692

693
  // Only the pre-computing information loaded and actual data does not loaded
694
  SInputColumnInfoData* pInput = &pCtx->input;
695
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
696
  int32_t               type = pInput->pData[0]->info.type;
697

698
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
699

700
  if (pInput->colDataSMAIsSet) {
701
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
702

703
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
704
      pSumRes->isum -= pAgg->sum;
705
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
706
      pSumRes->usum -= pAgg->sum;
707
    } else if (IS_FLOAT_TYPE(type)) {
708
      pSumRes->dsum -= GET_DOUBLE_VAL((const char*)&(pAgg->sum));
709
    }
710
  } else {  // computing based on the true data block
711
    SColumnInfoData* pCol = pInput->pData[0];
712

713
    int32_t start = pInput->startRowIndex;
714
    int32_t numOfRows = pInput->numOfRows;
715

716
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
717
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
718
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
719
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
720
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
721
      } else if (type == TSDB_DATA_TYPE_INT) {
722
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
723
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
724
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
725
      }
726
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
727
      if (type == TSDB_DATA_TYPE_UTINYINT) {
728
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
729
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
730
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
731
      } else if (type == TSDB_DATA_TYPE_UINT) {
732
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
733
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
734
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
735
      }
736
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
737
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
738
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
739
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
740
    }
741
  }
742

743
  // data in the check operation are all null, not output
744
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
745
  return TSDB_CODE_SUCCESS;
746
}
747
#endif
748

749
int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
47✔
750
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
47✔
751
  SSumRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
47✔
752

753
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
47✔
754
  SSumRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
47✔
755
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
47✔
756

757
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
47!
758
    pDBuf->isum += pSBuf->isum;
47✔
759
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
760
    pDBuf->usum += pSBuf->usum;
×
761
  } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
×
762
    pDBuf->dsum += pSBuf->dsum;
×
763
  }
764
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
47✔
765
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
47✔
766
  return TSDB_CODE_SUCCESS;
47✔
767
}
768

769
bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
277,237✔
770
  pEnv->calcMemSize = sizeof(SSumRes);
277,237✔
771
  return true;
277,237✔
772
}
773

774
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
156,723✔
775
  return FUNC_DATA_REQUIRED_SMA_LOAD;
156,723✔
776
}
777

778
int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
57,254,488✔
779
  if (pResultInfo->initialized) {
57,254,488!
780
    return TSDB_CODE_SUCCESS;
×
781
  }
782
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
57,254,488!
783
    return TSDB_CODE_FUNC_SETUP_ERROR;  // not initialized since it has been initialized
×
784
  }
785

786
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
57,274,688✔
787
  buf->assign = false;
57,274,688✔
788
  buf->tuplePos.pageId = -1;
57,274,688✔
789

790
  buf->nullTupleSaved = false;
57,274,688✔
791
  buf->nullTuplePos.pageId = -1;
57,274,688✔
792
  buf->str = NULL;
57,274,688✔
793
  return TSDB_CODE_SUCCESS;
57,274,688✔
794
}
795

796
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
500,569✔
797
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
500,569✔
798
  return true;
500,569✔
799
}
800

801
int32_t minFunction(SqlFunctionCtx* pCtx) {
45,385,705✔
802
  int32_t numOfElems = 0;
45,385,705✔
803
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
45,385,705✔
804
  if (code != TSDB_CODE_SUCCESS) {
45,482,588!
805
    return code;
×
806
  }
807
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
45,482,588✔
808
  return TSDB_CODE_SUCCESS;
45,482,588✔
809
}
810

811
int32_t maxFunction(SqlFunctionCtx* pCtx) {
19,135,396✔
812
  int32_t numOfElems = 0;
19,135,396✔
813
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
19,135,396✔
814
  if (code != TSDB_CODE_SUCCESS) {
19,213,150!
815
    return code;
×
816
  }
817
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
19,213,150✔
818
  return TSDB_CODE_SUCCESS;
19,213,150✔
819
}
820

821
static int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex);
822
static int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos,
823
                                   int32_t rowIndex);
824

825
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
55,500,680✔
826
  int32_t code = TSDB_CODE_SUCCESS;
55,500,680✔
827

828
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
55,500,680✔
829
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
55,500,680✔
830

831
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
55,500,680✔
832
  int32_t currentRow = pBlock->info.rows;
55,500,680✔
833

834
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
55,500,680✔
835
  if (NULL == pCol) {
55,504,216!
836
    return TSDB_CODE_OUT_OF_RANGE;
×
837
  }
838
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
55,504,216✔
839

840
  // NOTE: do nothing change it, for performance issue
841
  if (!pEntryInfo->isNullRes) {
55,504,216✔
842
    switch (pCol->info.type) {
48,678,262!
843
      case TSDB_DATA_TYPE_UBIGINT:
8,645,146✔
844
      case TSDB_DATA_TYPE_BIGINT:
845
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
8,645,146✔
846
        break;
8,645,146✔
847
      case TSDB_DATA_TYPE_UINT:
26,050,230✔
848
      case TSDB_DATA_TYPE_INT:
849
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
26,050,230✔
850
        break;
26,050,230✔
851
      case TSDB_DATA_TYPE_USMALLINT:
4,540,561✔
852
      case TSDB_DATA_TYPE_SMALLINT:
853
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
4,540,561✔
854
        break;
4,540,561✔
855
      case TSDB_DATA_TYPE_BOOL:
198,002✔
856
      case TSDB_DATA_TYPE_UTINYINT:
857
      case TSDB_DATA_TYPE_TINYINT:
858
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
198,002✔
859
        break;
198,002✔
860
      case TSDB_DATA_TYPE_DOUBLE:
214,795✔
861
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
214,795✔
862
        break;
214,795✔
863
      case TSDB_DATA_TYPE_FLOAT: {
4,009✔
864
        float v = GET_FLOAT_VAL(&pRes->v);
4,009✔
865
        colDataSetFloat(pCol, currentRow, &v);
4,009✔
866
        break;
4,009✔
867
      }
868
      case TSDB_DATA_TYPE_VARBINARY:
9,059,933✔
869
      case TSDB_DATA_TYPE_VARCHAR:
870
      case TSDB_DATA_TYPE_NCHAR: {
871
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
9,059,933✔
872
        if (TSDB_CODE_SUCCESS != code) {
9,059,933!
873
          return code;
×
874
        }
875
        break;
9,059,933✔
876
      }
877
    }
878
  } else {
879
    colDataSetNULL(pCol, currentRow);
6,825,954!
880
  }
881

882
  taosMemoryFreeClear(pRes->str);
55,504,216✔
883
  if (pCtx->subsidiaries.num > 0) {
55,504,216✔
884
    if (pEntryInfo->numOfRes > 0) {
17,355,334✔
885
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
17,352,607✔
886
    } else {
887
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
2,727✔
888
    }
889
  }
890

891
  return code;
55,519,401✔
892
}
893

894
#ifdef BUILD_NO_CALL
895
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
896
  if (pCtx->subsidiaries.num <= 0) {
897
    return TSDB_CODE_SUCCESS;
898
  }
899

900
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
901
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
902
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
903

904
    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
905
    colDataSetNULL(pDstCol, rowIndex);
906
  }
907

908
  return TSDB_CODE_SUCCESS;
909
}
910
#endif
911

912
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
278,664,943✔
913
  if (pCtx->subsidiaries.num <= 0) {
278,664,943✔
914
    return TSDB_CODE_SUCCESS;
110,859,855✔
915
  }
916

917
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
167,805,088!
918
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
919
    int32_t numOfCols = pCtx->subsidiaries.num;
167,817,182✔
920
    char*   p = NULL;
167,817,182✔
921
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
167,817,182✔
922
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
168,565,161!
923
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
924
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
925
      return TSDB_CODE_NOT_FOUND;
×
926
    }
927

928
    bool* nullList = (bool*)p;
168,568,467✔
929
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
168,568,467✔
930

931
    // todo set the offset value to optimize the performance.
932
    for (int32_t j = 0; j < numOfCols; ++j) {
336,684,835✔
933
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
168,609,006✔
934
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
168,609,006✔
935

936
      // group_key function has its own process function
937
      // do not process there
938
      if (fmIsGroupKeyFunc(pc->functionId)) {
168,609,006✔
939
        continue;
41,123✔
940
      }
941

942
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
168,573,518✔
943
      if (NULL == pDstCol) {
168,340,639!
944
        return TSDB_CODE_OUT_OF_RANGE;
×
945
      }
946
      if (nullList[j]) {
168,340,639✔
947
        colDataSetNULL(pDstCol, rowIndex);
327!
948
      } else {
949
        code = colDataSetVal(pDstCol, rowIndex, pStart, false);
168,340,312✔
950
        if (TSDB_CODE_SUCCESS != code) {
168,074,918!
951
          return code;
×
952
        }
953
      }
954
      pStart += pDstCol->info.bytes;
168,075,245✔
955
    }
956
  }
957

958
  return TSDB_CODE_SUCCESS;
168,063,735✔
959
}
960

961
// This function append the selectivity to subsidiaries function context directly, without fetching data
962
// from intermediate disk based buf page
963
int32_t appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) {
55,813,625✔
964
  if (pCtx->subsidiaries.num <= 0) {
55,813,625!
965
    return TSDB_CODE_SUCCESS;
×
966
  }
967

968
  int32_t code = TSDB_CODE_SUCCESS;
55,813,625✔
969
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
111,610,013✔
970
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
55,816,949✔
971

972
    // get data from source col
973
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
55,816,949✔
974
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
55,816,949✔
975

976
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
55,816,949✔
977
    if (NULL == pSrcCol) {
55,811,045!
978
      return TSDB_CODE_OUT_OF_RANGE;
×
979
    }
980

981
    char* pData = colDataGetData(pSrcCol, rowIndex);
55,811,045!
982

983
    // append to dest col
984
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
55,811,045✔
985

986
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
55,811,045✔
987
    if (NULL == pDstCol) {
55,797,699!
988
      return TSDB_CODE_OUT_OF_RANGE;
×
989
    }
990

991
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
111,595,398✔
992
      colDataSetNULL(pDstCol, pos);
560✔
993
    } else {
994
      code = colDataSetVal(pDstCol, pos, pData, false);
55,797,139✔
995
      if (TSDB_CODE_SUCCESS != code) {
55,795,828!
996
        return code;
×
997
      }
998
    }
999
  }
1000
  return code;
55,793,064✔
1001
}
1002

1003
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
32✔
1004

1005
#define COMPARE_MINMAX_DATA(type) (((*(type*)&pDBuf->v) < (*(type*)&pSBuf->v)) ^ isMinFunc)
1006
int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) {
58✔
1007
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
58✔
1008
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
58✔
1009

1010
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
58✔
1011
  SMinmaxResInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
58✔
1012
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
58✔
1013

1014
  switch (type) {
58!
1015
    case TSDB_DATA_TYPE_DOUBLE:
3✔
1016
    case TSDB_DATA_TYPE_UBIGINT:
1017
    case TSDB_DATA_TYPE_BIGINT:
1018
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int64_t) || !pDBuf->assign)) {
3!
1019
        pDBuf->v = pSBuf->v;
1✔
1020
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
1✔
1021
        pDBuf->assign = true;
1✔
1022
      }
1023
      break;
3✔
1024
    case TSDB_DATA_TYPE_UINT:
55✔
1025
    case TSDB_DATA_TYPE_INT:
1026
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int32_t) || !pDBuf->assign)) {
55!
1027
        pDBuf->v = pSBuf->v;
31✔
1028
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
31✔
1029
        pDBuf->assign = true;
31✔
1030
      }
1031
      break;
55✔
1032
    case TSDB_DATA_TYPE_USMALLINT:
×
1033
    case TSDB_DATA_TYPE_SMALLINT:
1034
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int16_t) || !pDBuf->assign)) {
×
1035
        pDBuf->v = pSBuf->v;
×
1036
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1037
        pDBuf->assign = true;
×
1038
      }
1039
      break;
×
1040
    case TSDB_DATA_TYPE_BOOL:
×
1041
    case TSDB_DATA_TYPE_UTINYINT:
1042
    case TSDB_DATA_TYPE_TINYINT:
1043
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int8_t) || !pDBuf->assign)) {
×
1044
        pDBuf->v = pSBuf->v;
×
1045
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1046
        pDBuf->assign = true;
×
1047
      }
1048
      break;
×
1049
    case TSDB_DATA_TYPE_FLOAT: {
×
1050
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(double) || !pDBuf->assign)) {
×
1051
        pDBuf->v = pSBuf->v;
×
1052
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1053
        pDBuf->assign = true;
×
1054
      }
1055
      break;
×
1056
    }
1057
    default:
×
1058
      if (pSBuf->assign && (strcmp((char*)&pDBuf->v, (char*)&pSBuf->v) || !pDBuf->assign)) {
×
1059
        pDBuf->v = pSBuf->v;
×
1060
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1061
        pDBuf->assign = true;
×
1062
      }
1063
      break;
×
1064
  }
1065
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
58✔
1066
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
58✔
1067
  return TSDB_CODE_SUCCESS;
58✔
1068
}
1069

1070
int32_t minCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
11✔
1071
  return minMaxCombine(pDestCtx, pSourceCtx, 1);
11✔
1072
}
1073
int32_t maxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
47✔
1074
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
47✔
1075
}
1076

1077
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
1,078,551✔
1078

1079
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
154,245✔
1080
  pEnv->calcMemSize = sizeof(SStdRes);
154,245✔
1081
  return true;
154,245✔
1082
}
1083

1084
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,153,483✔
1085
  if (pResultInfo->initialized) {
8,153,483!
1086
    return TSDB_CODE_SUCCESS;
×
1087
  }
1088
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,153,483!
1089
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1090
  }
1091

1092
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
8,153,478✔
1093
  (void)memset(pRes, 0, sizeof(SStdRes));
8,153,478✔
1094
  return TSDB_CODE_SUCCESS;
8,153,478✔
1095
}
1096

1097
int32_t stdFunction(SqlFunctionCtx* pCtx) {
8,134,956✔
1098
  int32_t numOfElem = 0;
8,134,956✔
1099

1100
  // Only the pre-computing information loaded and actual data does not loaded
1101
  SInputColumnInfoData* pInput = &pCtx->input;
8,134,956✔
1102
  int32_t               type = pInput->pData[0]->info.type;
8,134,956✔
1103

1104
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,134,956✔
1105
  pStdRes->type = type;
8,134,956✔
1106

1107
  // computing based on the true data block
1108
  SColumnInfoData* pCol = pInput->pData[0];
8,134,956✔
1109

1110
  int32_t start = pInput->startRowIndex;
8,134,956✔
1111
  int32_t numOfRows = pInput->numOfRows;
8,134,956✔
1112

1113
  if (IS_NULL_TYPE(type)) {
8,134,956✔
1114
    numOfElem = 0;
156✔
1115
    goto _stddev_over;
156✔
1116
  }
1117

1118
  switch (type) {
8,134,800!
1119
    case TSDB_DATA_TYPE_TINYINT: {
7,774,303✔
1120
      int8_t* plist = (int8_t*)pCol->pData;
7,774,303✔
1121
      for (int32_t i = start; i < numOfRows + start; ++i) {
25,960,719✔
1122
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
18,186,416✔
1123
          continue;
172,005✔
1124
        }
1125

1126
        numOfElem += 1;
18,014,411✔
1127
        pStdRes->count += 1;
18,014,411✔
1128
        pStdRes->isum += plist[i];
18,014,411✔
1129
        pStdRes->quadraticISum += plist[i] * plist[i];
18,014,411✔
1130
      }
1131

1132
      break;
7,774,303✔
1133
    }
1134

1135
    case TSDB_DATA_TYPE_SMALLINT: {
245,414✔
1136
      int16_t* plist = (int16_t*)pCol->pData;
245,414✔
1137
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
801,173✔
1138
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
555,759✔
1139
          continue;
47,594✔
1140
        }
1141

1142
        numOfElem += 1;
508,165✔
1143
        pStdRes->count += 1;
508,165✔
1144
        pStdRes->isum += plist[i];
508,165✔
1145
        pStdRes->quadraticISum += plist[i] * plist[i];
508,165✔
1146
      }
1147
      break;
245,414✔
1148
    }
1149

1150
    case TSDB_DATA_TYPE_INT: {
19,718✔
1151
      int32_t* plist = (int32_t*)pCol->pData;
19,718✔
1152
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,215,555✔
1153
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,195,837✔
1154
          continue;
23,572✔
1155
        }
1156

1157
        numOfElem += 1;
1,172,265✔
1158
        pStdRes->count += 1;
1,172,265✔
1159
        pStdRes->isum += plist[i];
1,172,265✔
1160
        pStdRes->quadraticISum += plist[i] * plist[i];
1,172,265✔
1161
      }
1162

1163
      break;
19,718✔
1164
    }
1165

1166
    case TSDB_DATA_TYPE_BIGINT: {
29,282✔
1167
      int64_t* plist = (int64_t*)pCol->pData;
29,282✔
1168
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,132,616✔
1169
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
2,103,334✔
1170
          continue;
103,353✔
1171
        }
1172

1173
        numOfElem += 1;
1,999,981✔
1174
        pStdRes->count += 1;
1,999,981✔
1175
        pStdRes->isum += plist[i];
1,999,981✔
1176
        pStdRes->quadraticISum += plist[i] * plist[i];
1,999,981✔
1177
      }
1178
      break;
29,282✔
1179
    }
1180

1181
    case TSDB_DATA_TYPE_UTINYINT: {
25✔
1182
      uint8_t* plist = (uint8_t*)pCol->pData;
25✔
1183
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,032✔
1184
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,007!
1185
          continue;
4✔
1186
        }
1187

1188
        numOfElem += 1;
80,003✔
1189
        pStdRes->count += 1;
80,003✔
1190
        pStdRes->usum += plist[i];
80,003✔
1191
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,003✔
1192
      }
1193

1194
      break;
25✔
1195
    }
1196

1197
    case TSDB_DATA_TYPE_USMALLINT: {
24✔
1198
      uint16_t* plist = (uint16_t*)pCol->pData;
24✔
1199
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,024✔
1200
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,000!
1201
          continue;
×
1202
        }
1203

1204
        numOfElem += 1;
80,000✔
1205
        pStdRes->count += 1;
80,000✔
1206
        pStdRes->usum += plist[i];
80,000✔
1207
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1208
      }
1209
      break;
24✔
1210
    }
1211

1212
    case TSDB_DATA_TYPE_UINT: {
25✔
1213
      uint32_t* plist = (uint32_t*)pCol->pData;
25✔
1214
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,030✔
1215
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,005!
1216
          continue;
×
1217
        }
1218

1219
        numOfElem += 1;
80,005✔
1220
        pStdRes->count += 1;
80,005✔
1221
        pStdRes->usum += plist[i];
80,005✔
1222
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,005✔
1223
      }
1224

1225
      break;
25✔
1226
    }
1227

1228
    case TSDB_DATA_TYPE_UBIGINT: {
24✔
1229
      uint64_t* plist = (uint64_t*)pCol->pData;
24✔
1230
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,024✔
1231
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,000!
1232
          continue;
×
1233
        }
1234

1235
        numOfElem += 1;
80,000✔
1236
        pStdRes->count += 1;
80,000✔
1237
        pStdRes->usum += plist[i];
80,000✔
1238
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1239
      }
1240
      break;
24✔
1241
    }
1242

1243
    case TSDB_DATA_TYPE_FLOAT: {
16,187✔
1244
      float* plist = (float*)pCol->pData;
16,187✔
1245
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
745,054✔
1246
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
728,867✔
1247
          continue;
113,767✔
1248
        }
1249

1250
        numOfElem += 1;
615,100✔
1251
        pStdRes->count += 1;
615,100✔
1252
        pStdRes->dsum += plist[i];
615,100✔
1253
        pStdRes->quadraticDSum += plist[i] * plist[i];
615,100✔
1254
      }
1255
      break;
16,187✔
1256
    }
1257

1258
    case TSDB_DATA_TYPE_DOUBLE: {
49,817✔
1259
      double* plist = (double*)pCol->pData;
49,817✔
1260
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
3,296,007✔
1261
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
3,246,190✔
1262
          continue;
831,573✔
1263
        }
1264

1265
        numOfElem += 1;
2,414,617✔
1266
        pStdRes->count += 1;
2,414,617✔
1267
        pStdRes->dsum += plist[i];
2,414,617✔
1268
        pStdRes->quadraticDSum += plist[i] * plist[i];
2,414,617✔
1269
      }
1270
      break;
49,817✔
1271
    }
1272

1273
    default:
×
1274
      break;
×
1275
  }
1276

1277
_stddev_over:
8,134,956✔
1278
  // data in the check operation are all null, not output
1279
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
8,134,956✔
1280
  return TSDB_CODE_SUCCESS;
8,134,956✔
1281
}
1282

1283
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
1,077,209✔
1284
  if (IS_NULL_TYPE(pInput->type)) {
1,077,209✔
1285
    return;
80✔
1286
  }
1287
  pOutput->type = pInput->type;
1,077,129✔
1288
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
1,077,129!
1289
    pOutput->quadraticISum += pInput->quadraticISum;
1,076,932✔
1290
    pOutput->isum += pInput->isum;
1,076,932✔
1291
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
197!
1292
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1293
    pOutput->usum += pInput->usum;
1✔
1294
  } else {
1295
    pOutput->quadraticDSum += pInput->quadraticDSum;
196✔
1296
    pOutput->dsum += pInput->dsum;
196✔
1297
  }
1298

1299
  pOutput->count += pInput->count;
1,077,129✔
1300
}
1301

1302
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
1,077,140✔
1303
  SInputColumnInfoData* pInput = &pCtx->input;
1,077,140✔
1304
  SColumnInfoData*      pCol = pInput->pData[0];
1,077,140✔
1305

1306
  if (IS_NULL_TYPE(pCol->info.type)) {
1,077,140!
1307
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1308
    return TSDB_CODE_SUCCESS;
×
1309
  }
1310

1311
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,077,140!
1312
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1313
  }
1314

1315
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,077,140✔
1316

1317
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,154,346✔
1318
    if (colDataIsNull_s(pCol, i)) continue;
2,154,412!
1319
    char*    data = colDataGetData(pCol, i);
1,077,206!
1320
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
1,077,206✔
1321
    stdTransferInfo(pInputInfo, pInfo);
1,077,206✔
1322
  }
1323

1324
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
1,077,140✔
1325
  return TSDB_CODE_SUCCESS;
1,077,140✔
1326
}
1327

1328
#ifdef BUILD_NO_CALL
1329
int32_t stdInvertFunction(SqlFunctionCtx* pCtx) {
1330
  int32_t numOfElem = 0;
1331

1332
  // Only the pre-computing information loaded and actual data does not loaded
1333
  SInputColumnInfoData* pInput = &pCtx->input;
1334
  int32_t               type = pInput->pData[0]->info.type;
1335

1336
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1337

1338
  // computing based on the true data block
1339
  SColumnInfoData* pCol = pInput->pData[0];
1340

1341
  int32_t start = pInput->startRowIndex;
1342
  int32_t numOfRows = pInput->numOfRows;
1343

1344
  switch (type) {
1345
    case TSDB_DATA_TYPE_TINYINT: {
1346
      LIST_STDDEV_SUB_N(pStdRes->isum, int8_t);
1347
      break;
1348
    }
1349
    case TSDB_DATA_TYPE_SMALLINT: {
1350
      LIST_STDDEV_SUB_N(pStdRes->isum, int16_t);
1351
      break;
1352
    }
1353
    case TSDB_DATA_TYPE_INT: {
1354
      LIST_STDDEV_SUB_N(pStdRes->isum, int32_t);
1355
      break;
1356
    }
1357
    case TSDB_DATA_TYPE_BIGINT: {
1358
      LIST_STDDEV_SUB_N(pStdRes->isum, int64_t);
1359
      break;
1360
    }
1361
    case TSDB_DATA_TYPE_UTINYINT: {
1362
      LIST_STDDEV_SUB_N(pStdRes->isum, uint8_t);
1363
      break;
1364
    }
1365
    case TSDB_DATA_TYPE_USMALLINT: {
1366
      LIST_STDDEV_SUB_N(pStdRes->isum, uint16_t);
1367
      break;
1368
    }
1369
    case TSDB_DATA_TYPE_UINT: {
1370
      LIST_STDDEV_SUB_N(pStdRes->isum, uint32_t);
1371
      break;
1372
    }
1373
    case TSDB_DATA_TYPE_UBIGINT: {
1374
      LIST_STDDEV_SUB_N(pStdRes->isum, uint64_t);
1375
      break;
1376
    }
1377
    case TSDB_DATA_TYPE_FLOAT: {
1378
      LIST_STDDEV_SUB_N(pStdRes->dsum, float);
1379
      break;
1380
    }
1381
    case TSDB_DATA_TYPE_DOUBLE: {
1382
      LIST_STDDEV_SUB_N(pStdRes->dsum, double);
1383
      break;
1384
    }
1385
    default:
1386
      break;
1387
  }
1388

1389
  // data in the check operation are all null, not output
1390
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1391
  return TSDB_CODE_SUCCESS;
1392
}
1393
#endif
1394

1395
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,037,633✔
1396
  SInputColumnInfoData* pInput = &pCtx->input;
7,037,633✔
1397
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,037,633✔
1398
  int32_t               type = pStddevRes->type;
7,037,633✔
1399
  double                avg;
1400

1401
  if (pStddevRes->count == 0) {
7,037,633✔
1402
    GET_RES_INFO(pCtx)->numOfRes = 0;
70,609✔
1403
    return functionFinalize(pCtx, pBlock);
70,609✔
1404
  }
1405

1406
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
6,967,024!
1407
    avg = pStddevRes->isum / ((double)pStddevRes->count);
6,940,591✔
1408
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
6,940,591✔
1409
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
26,433!
1410
    avg = pStddevRes->usum / ((double)pStddevRes->count);
10✔
1411
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
10✔
1412
  } else {
1413
    avg = pStddevRes->dsum / ((double)pStddevRes->count);
26,423✔
1414
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
26,423✔
1415
  }
1416

1417
  // check for overflow
1418
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
6,967,024!
1419
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1420
  }
1421

1422
  return functionFinalize(pCtx, pBlock);
6,967,024✔
1423
}
1424

1425
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
1426
  SInputColumnInfoData* pInput = &pCtx->input;
×
1427
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1428
  int32_t               type = pStdvarRes->type;
×
1429
  double                avg;
1430

1431
  if (pStdvarRes->count == 0) {
×
1432
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1433
    return functionFinalize(pCtx, pBlock);
×
1434
  }
1435

1436
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
1437
    avg = pStdvarRes->isum / ((double)pStdvarRes->count);
×
1438
    pStdvarRes->result = fabs(pStdvarRes->quadraticISum / ((double)pStdvarRes->count) - avg * avg);
×
1439
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1440
    avg = pStdvarRes->usum / ((double)pStdvarRes->count);
×
1441
    pStdvarRes->result = fabs(pStdvarRes->quadraticUSum / ((double)pStdvarRes->count) - avg * avg);
×
1442
  } else {
1443
    avg = pStdvarRes->dsum / ((double)pStdvarRes->count);
×
1444
    pStdvarRes->result = fabs(pStdvarRes->quadraticDSum / ((double)pStdvarRes->count) - avg * avg);
×
1445
  }
1446

1447
  // check for overflow
1448
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
×
1449
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1450
  }
1451

1452
  return functionFinalize(pCtx, pBlock);
×
1453
}
1454

1455
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,077,114✔
1456
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,077,114✔
1457
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,077,114✔
1458
  int32_t              resultBytes = getStdInfoSize();
1,077,114✔
1459
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,077,114✔
1460

1461
  if (NULL == res) {
1,077,115!
1462
    return terrno;
×
1463
  }
1464
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,077,115✔
1465
  varDataSetLen(res, resultBytes);
1,077,115✔
1466

1467
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,077,115✔
1468
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,077,115✔
1469
  if (NULL == pCol) {
1,077,114!
1470
    taosMemoryFree(res);
×
1471
    return TSDB_CODE_OUT_OF_RANGE;
×
1472
  }
1473

1474
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,077,114✔
1475

1476
  taosMemoryFree(res);
1,077,114✔
1477
  return code;
1,077,115✔
1478
}
1479

1480
int32_t stdCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
1481
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
1482
  SStdRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
1483

1484
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
1485
  SStdRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
1486
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
3!
1487

1488
  stdTransferInfo(pSBuf, pDBuf);
3✔
1489

1490
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
1491
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
1492
  return TSDB_CODE_SUCCESS;
3✔
1493
}
1494

1495
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
44,377✔
1496
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
44,377✔
1497
  return true;
44,377✔
1498
}
1499

1500
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
6,455,299✔
1501
  if (pResultInfo->initialized) {
6,455,299!
1502
    return TSDB_CODE_SUCCESS;
×
1503
  }
1504
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
6,455,299!
1505
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1506
  }
1507

1508
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6,455,298✔
1509

1510
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
6,455,298!
1511
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
6,455,298!
1512
  return TSDB_CODE_SUCCESS;
6,455,298✔
1513
}
1514

1515
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
7,764,961✔
1516
  int32_t numOfElem = 0;
7,764,961✔
1517

1518
  SInputColumnInfoData* pInput = &pCtx->input;
7,764,961✔
1519
  int32_t               type = pInput->pData[0]->info.type;
7,764,961✔
1520

1521
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,764,961✔
1522

1523
  SColumnInfoData* pCol = pInput->pData[0];
7,764,961✔
1524

1525
  double(*param)[3] = pInfo->matrix;
7,764,961✔
1526
  double x = pInfo->startVal;
7,764,961✔
1527

1528
  int32_t start = pInput->startRowIndex;
7,764,961✔
1529
  int32_t numOfRows = pInput->numOfRows;
7,764,961✔
1530

1531
  switch (type) {
7,764,961!
1532
    case TSDB_DATA_TYPE_TINYINT: {
10,103✔
1533
      int8_t* plist = (int8_t*)pCol->pData;
10,103✔
1534
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
379,220✔
1535
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
369,117✔
1536
          continue;
286,757✔
1537
        }
1538
        numOfElem++;
82,360✔
1539
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
82,360✔
1540
      }
1541
      break;
10,103✔
1542
    }
1543
    case TSDB_DATA_TYPE_SMALLINT: {
5,814✔
1544
      int16_t* plist = (int16_t*)pCol->pData;
5,814✔
1545
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
653,356✔
1546
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
647,542✔
1547
          continue;
2,660✔
1548
        }
1549

1550
        numOfElem++;
644,882✔
1551
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
644,882✔
1552
      }
1553
      break;
5,814✔
1554
    }
1555

1556
    case TSDB_DATA_TYPE_INT: {
2,431,128✔
1557
      int32_t* plist = (int32_t*)pCol->pData;
2,431,128✔
1558
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
7,534,435✔
1559
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
5,103,307✔
1560
          continue;
2,215✔
1561
        }
1562

1563
        numOfElem++;
5,101,092✔
1564
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
5,101,092✔
1565
      }
1566
      break;
2,431,128✔
1567
    }
1568

1569
    case TSDB_DATA_TYPE_BIGINT: {
11,164✔
1570
      int64_t* plist = (int64_t*)pCol->pData;
11,164✔
1571
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
616,446✔
1572
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
605,282✔
1573
          continue;
151,163✔
1574
        }
1575

1576
        numOfElem++;
454,119✔
1577
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
454,119✔
1578
      }
1579
      break;
11,164✔
1580
    }
1581

1582
    case TSDB_DATA_TYPE_UTINYINT: {
154✔
1583
      uint8_t* plist = (uint8_t*)pCol->pData;
154✔
1584
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1585
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1586
          continue;
110✔
1587
        }
1588
        numOfElem++;
80,310✔
1589
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,310✔
1590
      }
1591
      break;
154✔
1592
    }
1593
    case TSDB_DATA_TYPE_USMALLINT: {
154✔
1594
      uint16_t* plist = (uint16_t*)pCol->pData;
154✔
1595
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1596
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1597
          continue;
100✔
1598
        }
1599

1600
        numOfElem++;
80,320✔
1601
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1602
      }
1603
      break;
154✔
1604
    }
1605

1606
    case TSDB_DATA_TYPE_UINT: {
154✔
1607
      uint32_t* plist = (uint32_t*)pCol->pData;
154✔
1608
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1609
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1610
          continue;
100✔
1611
        }
1612

1613
        numOfElem++;
80,320✔
1614
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1615
      }
1616
      break;
154✔
1617
    }
1618

1619
    case TSDB_DATA_TYPE_UBIGINT: {
154✔
1620
      uint64_t* plist = (uint64_t*)pCol->pData;
154✔
1621
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1622
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1623
          continue;
100✔
1624
        }
1625

1626
        numOfElem++;
80,320✔
1627
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1628
      }
1629
      break;
154✔
1630
    }
1631

1632
    case TSDB_DATA_TYPE_FLOAT: {
5,292,978✔
1633
      float* plist = (float*)pCol->pData;
5,292,978✔
1634
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
17,663,745✔
1635
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
12,370,767✔
1636
          continue;
149,003✔
1637
        }
1638

1639
        numOfElem++;
12,221,764✔
1640
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
12,221,764✔
1641
      }
1642
      break;
5,292,978✔
1643
    }
1644

1645
    case TSDB_DATA_TYPE_DOUBLE: {
13,158✔
1646
      double* plist = (double*)pCol->pData;
13,158✔
1647
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
939,701✔
1648
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
926,543✔
1649
          continue;
150,328✔
1650
        }
1651

1652
        numOfElem++;
776,215✔
1653
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
776,215✔
1654
      }
1655
      break;
13,158✔
1656
    }
1657
    case TSDB_DATA_TYPE_NULL: {
×
1658
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1659
      numOfElem = 1;
×
1660
      break;
×
1661
    }
1662

1663
    default:
×
1664
      break;
×
1665
  }
1666

1667
  pInfo->startVal = x;
7,764,961✔
1668
  pInfo->num += numOfElem;
7,764,961✔
1669

1670
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
7,764,961✔
1671

1672
  return TSDB_CODE_SUCCESS;
7,764,961✔
1673
}
1674

1675
int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,440,055✔
1676
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,440,055✔
1677
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,440,055✔
1678
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
6,440,055✔
1679
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,440,055✔
1680

1681
  if (NULL == pCol) {
6,440,054!
1682
    return TSDB_CODE_OUT_OF_RANGE;
×
1683
  }
1684
  int32_t currentRow = pBlock->info.rows;
6,440,054✔
1685

1686
  if (0 == pInfo->num) {
6,440,054✔
1687
    colDataSetNULL(pCol, currentRow);
32,415!
1688
    return TSDB_CODE_SUCCESS;
32,415✔
1689
  }
1690

1691
  double(*param)[3] = pInfo->matrix;
6,407,639✔
1692

1693
  param[1][1] = (double)pInfo->num;
6,407,639✔
1694
  param[1][0] = param[0][1];
6,407,639✔
1695

1696
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
6,407,639✔
1697
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
6,407,639✔
1698

1699
  if (0 == param00) {
6,407,639✔
1700
    colDataSetNULL(pCol, currentRow);
4,377,690!
1701
    return TSDB_CODE_SUCCESS;
4,377,690✔
1702
  }
1703

1704
  // param[0][1] = 0;
1705
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
2,029,949✔
1706
  // param[1][0] = 0;
1707
  param02 /= param00;
2,029,949✔
1708

1709
  param12 /= param[1][1];
2,029,949✔
1710

1711
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
2,029,949✔
1712
  char slopBuf[64] = {0};
2,029,949✔
1713
  char interceptBuf[64] = {0};
2,029,949✔
1714
  int  n = tsnprintf(slopBuf, 64, "%.6lf", param02);
2,029,949✔
1715
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
2,029,948✔
1716
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
34✔
1717
  }
1718
  n = tsnprintf(interceptBuf, 64, "%.6lf", param12);
2,029,948✔
1719
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
2,029,949✔
1720
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
1,168✔
1721
  }
1722
  size_t len =
2,029,949✔
1723
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
2,029,949✔
1724
  varDataSetLen(buf, len);
2,029,949✔
1725

1726
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
2,029,949✔
1727

1728
  return code;
2,029,949✔
1729
}
1730

1731
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1732
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1733
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1734
  int32_t              type = pDestCtx->input.pData[0]->info.type;
×
1735
  double(*pDparam)[3] = pDBuf->matrix;
×
1736

1737
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
1738
  SLeastSQRInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
1739
  double(*pSparam)[3] = pSBuf->matrix;
×
1740
  for (int32_t i = 0; i < pSBuf->num; i++) {
×
1741
    pDparam[0][0] += pDBuf->startVal * pDBuf->startVal;
×
1742
    pDparam[0][1] += pDBuf->startVal;
×
1743
    pDBuf->startVal += pDBuf->stepVal;
×
1744
  }
1745
  pDparam[0][2] += pSparam[0][2] + pDBuf->num * pDBuf->stepVal * pSparam[1][2];
×
1746
  pDparam[1][2] += pSparam[1][2];
×
1747
  pDBuf->num += pSBuf->num;
×
1748
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
1749
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
1750
  return TSDB_CODE_SUCCESS;
×
1751
}
1752

1753
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
930✔
1754
  pEnv->calcMemSize = sizeof(SPercentileInfo);
930✔
1755
  return true;
930✔
1756
}
1757

1758
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,958✔
1759
  if (pResultInfo->initialized) {
4,958!
1760
    return TSDB_CODE_SUCCESS;
×
1761
  }
1762
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,958!
1763
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1764
  }
1765

1766
  // in the first round, get the min-max value of all involved data
1767
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,958✔
1768
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
4,958✔
1769
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
4,958✔
1770
  pInfo->numOfElems = 0;
4,958✔
1771

1772
  return TSDB_CODE_SUCCESS;
4,958✔
1773
}
1774

1775
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
1776
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
1777
    return;
×
1778
  }
1779
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1780
  if (pInfo->pMemBucket != NULL) {
×
1781
    tMemBucketDestroy(&(pInfo->pMemBucket));
×
1782
    pInfo->pMemBucket = NULL;
×
1783
  }
1784
}
1785

1786
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
2,359,888✔
1787
  int32_t              code = TSDB_CODE_SUCCESS;
2,359,888✔
1788
  int32_t              numOfElems = 0;
2,359,888✔
1789
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,359,888✔
1790

1791
  SInputColumnInfoData* pInput = &pCtx->input;
2,359,888✔
1792
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,359,888✔
1793

1794
  SColumnInfoData* pCol = pInput->pData[0];
2,359,888✔
1795
  int32_t          type = pCol->info.type;
2,359,888✔
1796

1797
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,359,888✔
1798
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
2,359,888✔
1799
    pInfo->stage += 1;
4,958✔
1800

1801
    // all data are null, set it completed
1802
    if (pInfo->numOfElems == 0) {
4,958✔
1803
      pResInfo->complete = true;
2,372✔
1804
      return TSDB_CODE_SUCCESS;
2,372✔
1805
    } else {
1806
      code = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup,
2,586✔
1807
                              &pInfo->pMemBucket, pInfo->numOfElems);
2,586✔
1808
      if (TSDB_CODE_SUCCESS != code) {
2,586!
1809
        return code;
×
1810
      }
1811
    }
1812
  }
1813

1814
  // the first stage, only acquire the min/max value
1815
  if (pInfo->stage == 0) {
2,357,516✔
1816
    if (pCtx->input.colDataSMAIsSet) {
1,179,960✔
1817
      double tmin = 0.0, tmax = 0.0;
1,170,666✔
1818
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
1,170,666!
1819
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
1820
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
1821
      } else if (IS_FLOAT_TYPE(type)) {
1,170,666!
1822
        tmin = GET_DOUBLE_VAL(&pAgg->min);
1,170,666✔
1823
        tmax = GET_DOUBLE_VAL(&pAgg->max);
1,170,666✔
1824
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1825
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
1826
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
1827
      }
1828

1829
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
1,170,666✔
1830
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
14✔
1831
      }
1832

1833
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
1,170,666✔
1834
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
14✔
1835
      }
1836

1837
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
1,170,666✔
1838
    } else {
1839
      // check the valid data one by one
1840
      int32_t start = pInput->startRowIndex;
9,294✔
1841
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,103,512✔
1842
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
14,094,218✔
1843
          continue;
3,000✔
1844
        }
1845

1846
        char* data = colDataGetData(pCol, i);
14,091,218!
1847

1848
        double v = 0;
14,091,218✔
1849
        GET_TYPED_DATA(v, double, type, data);
14,091,218!
1850
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
14,091,218✔
1851
          SET_DOUBLE_VAL(&pInfo->minval, v);
2,802✔
1852
        }
1853

1854
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
14,091,218✔
1855
          SET_DOUBLE_VAL(&pInfo->maxval, v);
409,832✔
1856
        }
1857

1858
        pInfo->numOfElems += 1;
14,091,218✔
1859
      }
1860
    }
1861
  } else {
1862
    // the second stage, calculate the true percentile value
1863
    int32_t start = pInput->startRowIndex;
1,177,556✔
1864
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
1865
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
2,147,483,647!
1866
        continue;
×
1867
      }
1868

1869
      char* data = colDataGetData(pCol, i);
2,147,483,647!
1870
      numOfElems += 1;
2,147,483,647✔
1871
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
2,147,483,647✔
1872
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
1873
        tMemBucketDestroy(&(pInfo->pMemBucket));
×
1874
        return code;
×
1875
      }
1876
    }
1877

1878
    SET_VAL(pResInfo, numOfElems, 1);
1,177,556!
1879
  }
1880

1881
  pCtx->needCleanup = true;
2,357,516✔
1882
  return TSDB_CODE_SUCCESS;
2,357,516✔
1883
}
1884

1885
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,958✔
1886
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,958✔
1887
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
4,958✔
1888

1889
  int32_t code = 0;
4,958✔
1890
  double  v = 0;
4,958✔
1891

1892
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
4,958✔
1893
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
4,958!
1894
    if (pCtx->numOfParams > 2) {
2,586✔
1895
      char buf[3200] = {0};
34✔
1896
      // max length of double num is 317, e.g. use %.6lf to print -1.0e+308, consider the comma and bracket, 3200 is
1897
      // enough.
1898
      size_t len = 1;
34✔
1899

1900
      varDataVal(buf)[0] = '[';
34✔
1901
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
342✔
1902
        SVariant* pVal = &pCtx->param[i].param;
308✔
1903

1904
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
308!
1905

1906
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
308✔
1907
        if (code != TSDB_CODE_SUCCESS) {
308!
1908
          goto _fin_error;
×
1909
        }
1910

1911
        if (i == pCtx->numOfParams - 1) {
308✔
1912
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
34✔
1913
        } else {
1914
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
274✔
1915
        }
1916
      }
1917

1918
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
34✔
1919
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
34✔
1920
      if (NULL == pCol) {
34!
1921
        code = terrno;
×
1922
        goto _fin_error;
×
1923
      }
1924

1925
      varDataSetLen(buf, len);
34✔
1926
      code = colDataSetVal(pCol, pBlock->info.rows, buf, false);
34✔
1927
      if (code != TSDB_CODE_SUCCESS) {
34!
1928
        goto _fin_error;
×
1929
      }
1930

1931
      tMemBucketDestroy(pMemBucket);
34✔
1932
      return TSDB_CODE_SUCCESS;
34✔
1933
    } else {
1934
      SVariant* pVal = &pCtx->param[1].param;
2,552✔
1935

1936
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
2,552!
1937

1938
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
2,552✔
1939
      if (code != TSDB_CODE_SUCCESS) {
2,552!
1940
        goto _fin_error;
×
1941
      }
1942

1943
      tMemBucketDestroy(pMemBucket);
2,552✔
1944
      return functionFinalize(pCtx, pBlock);
2,552✔
1945
    }
1946
  } else {
1947
    return functionFinalize(pCtx, pBlock);
2,372✔
1948
  }
1949

1950
_fin_error:
×
1951

1952
  tMemBucketDestroy(pMemBucket);
×
1953
  return code;
×
1954
}
1955

1956
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
72,449✔
1957
  int32_t bytesHist =
72,449✔
1958
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1959
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
72,449✔
1960
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
72,449✔
1961
  return true;
72,449✔
1962
}
1963

1964
int32_t getApercentileMaxSize() {
9,754✔
1965
  int32_t bytesHist =
9,754✔
1966
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1967
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
9,754✔
1968
  return TMAX(bytesHist, bytesDigest);
9,754✔
1969
}
1970

1971
static int8_t getApercentileAlgo(char* algoStr) {
26,463✔
1972
  int8_t algoType;
1973
  if (strcasecmp(algoStr, "default") == 0) {
26,463✔
1974
    algoType = APERCT_ALGO_DEFAULT;
11,453✔
1975
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
15,010✔
1976
    algoType = APERCT_ALGO_TDIGEST;
15,007✔
1977
  } else {
1978
    algoType = APERCT_ALGO_UNKNOWN;
3✔
1979
  }
1980

1981
  return algoType;
26,463✔
1982
}
1983

1984
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
916,226✔
1985
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
916,226✔
1986
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
916,226✔
1987
}
916,226✔
1988

1989
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
35,002✔
1990
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
35,002✔
1991
}
35,002✔
1992

1993
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
321,842✔
1994
  if (pResultInfo->initialized) {
321,842!
1995
    return TSDB_CODE_SUCCESS;
×
1996
  }
1997
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
321,842!
1998
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1999
  }
2000

2001
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
321,889✔
2002

2003
  SVariant* pVal = &pCtx->param[1].param;
321,889✔
2004
  pInfo->percent = 0;
321,889✔
2005
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i);
321,889!
2006

2007
  if (pCtx->numOfParams == 2) {
321,889✔
2008
    pInfo->algo = APERCT_ALGO_DEFAULT;
295,425✔
2009
  } else if (pCtx->numOfParams == 3) {
26,464✔
2010
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
26,463✔
2011
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
26,456!
2012
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2013
    }
2014
  }
2015

2016
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
321,882✔
2017
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
321,882✔
2018
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
15,007✔
2019
  } else {
2020
    buildHistogramInfo(pInfo);
306,875✔
2021
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
306,870✔
2022
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
306,867✔
2023
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2024
  }
2025

2026
  return TSDB_CODE_SUCCESS;
321,881✔
2027
}
2028

2029
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
337,136✔
2030
  int32_t               numOfElems = 0;
337,136✔
2031
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
337,136✔
2032
  SInputColumnInfoData* pInput = &pCtx->input;
337,136✔
2033

2034
  SColumnInfoData* pCol = pInput->pData[0];
337,136✔
2035
  int32_t          type = pCol->info.type;
337,136✔
2036

2037
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
337,136✔
2038

2039
  int32_t start = pInput->startRowIndex;
337,136✔
2040
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
337,136✔
2041
    buildTDigestInfo(pInfo);
19,044✔
2042
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
19,044✔
2043
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,415,245✔
2044
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,396,183✔
2045
        continue;
362,554✔
2046
      }
2047
      numOfElems += 1;
1,033,629✔
2048
      char* data = colDataGetData(pCol, i);
1,033,629!
2049

2050
      double  v = 0;  // value
1,033,629✔
2051
      int64_t w = 1;  // weigth
1,033,629✔
2052
      GET_TYPED_DATA(v, double, type, data);
1,033,629✔
2053
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
1,033,629✔
2054
      if (code != TSDB_CODE_SUCCESS) {
1,033,650!
2055
        return code;
×
2056
      }
2057
    }
2058
  } else {
2059
    // might be a race condition here that pHisto can be overwritten or setup function
2060
    // has not been called, need to relink the buffer pHisto points to.
2061
    buildHistogramInfo(pInfo);
318,092✔
2062
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
318,092✔
2063
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2064
           pInfo->pHisto->elems);
2065
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,848,239✔
2066
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
2,529,988✔
2067
        continue;
1,032,104✔
2068
      }
2069
      numOfElems += 1;
1,497,884✔
2070
      char* data = colDataGetData(pCol, i);
1,497,884!
2071

2072
      double v = 0;
1,497,884✔
2073
      GET_TYPED_DATA(v, double, type, data);
1,497,884!
2074
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
1,497,884✔
2075
      if (code != TSDB_CODE_SUCCESS) {
1,498,043!
2076
        return code;
×
2077
      }
2078
    }
2079

2080
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
318,251✔
2081
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2082
           pInfo->pHisto->elems);
2083
  }
2084

2085
  SET_VAL(pResInfo, numOfElems, 1);
337,140✔
2086
  return TSDB_CODE_SUCCESS;
337,140✔
2087
}
2088

2089
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
8,452✔
2090
  pOutput->percent = pInput->percent;
8,452✔
2091
  pOutput->algo = pInput->algo;
8,452✔
2092
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
8,452✔
2093
    buildTDigestInfo(pInput);
951✔
2094
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
951✔
2095

2096
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
951✔
2097
      return TSDB_CODE_SUCCESS;
1✔
2098
    }
2099

2100
    if (hasRes) {
950✔
2101
      *hasRes = true;
948✔
2102
    }
2103

2104
    buildTDigestInfo(pOutput);
950✔
2105
    TDigest* pTDigest = pOutput->pTDigest;
950✔
2106
    tdigestAutoFill(pTDigest, COMPRESSION);
950✔
2107

2108
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
950!
2109
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
948✔
2110
      tdigestAutoFill(pTDigest, COMPRESSION);
948✔
2111
    } else {
2112
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
2✔
2113
      if (TSDB_CODE_SUCCESS != code) {
2!
2114
        return code;
×
2115
      }
2116
    }
2117
  } else {
2118
    buildHistogramInfo(pInput);
7,501✔
2119
    if (pInput->pHisto->numOfElems <= 0) {
7,501✔
2120
      return TSDB_CODE_SUCCESS;
223✔
2121
    }
2122

2123
    if (hasRes) {
7,278✔
2124
      *hasRes = true;
7,276✔
2125
    }
2126

2127
    buildHistogramInfo(pOutput);
7,278✔
2128
    SHistogramInfo* pHisto = pOutput->pHisto;
7,278✔
2129

2130
    if (pHisto->numOfElems <= 0) {
7,278✔
2131
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
6,684✔
2132
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
6,684✔
2133

2134
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
6,684✔
2135
             pHisto);
2136
    } else {
2137
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
594✔
2138
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
594✔
2139
             pHisto->numOfEntries, pInput->pHisto);
2140

2141
      SHistogramInfo* pRes = NULL;
594✔
2142
      int32_t         code = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN, &pRes);
594✔
2143
      if (TSDB_CODE_SUCCESS != code) {
594!
2144
        tHistogramDestroy(&pRes);
×
2145
        return code;
×
2146
      }
2147
      (void)memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
594✔
2148
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
594✔
2149

2150
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
594✔
2151
             pHisto);
2152
      tHistogramDestroy(&pRes);
594✔
2153
    }
2154
  }
2155
  return TSDB_CODE_SUCCESS;
8,228✔
2156
}
2157

2158
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
8,378✔
2159
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,378✔
2160

2161
  SInputColumnInfoData* pInput = &pCtx->input;
8,378✔
2162

2163
  SColumnInfoData* pCol = pInput->pData[0];
8,378✔
2164
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
8,378!
2165
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2166
  }
2167

2168
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,378✔
2169

2170
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
8,378✔
2171

2172
  bool    hasRes = false;
8,378✔
2173
  int32_t start = pInput->startRowIndex;
8,378✔
2174
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
16,826✔
2175
    char* data = colDataGetData(pCol, i);
8,448!
2176

2177
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
8,448✔
2178
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
8,448✔
2179
    if (TSDB_CODE_SUCCESS != code) {
8,448!
2180
      return code;
×
2181
    }
2182
  }
2183

2184
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
8,378✔
2185
    buildHistogramInfo(pInfo);
7,429✔
2186
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
7,429✔
2187
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2188
  }
2189

2190
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
8,378✔
2191
  return TSDB_CODE_SUCCESS;
8,378✔
2192
}
2193

2194
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
283,173✔
2195
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
283,173✔
2196
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
283,173✔
2197

2198
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
283,173✔
2199
    buildTDigestInfo(pInfo);
14,064✔
2200
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
14,064✔
2201
    if (pInfo->pTDigest->size > 0) {
14,063!
2202
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
14,063✔
2203
    } else {  // no need to free
2204
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2205
      return TSDB_CODE_SUCCESS;
×
2206
    }
2207
  } else {
2208
    buildHistogramInfo(pInfo);
269,109✔
2209
    if (pInfo->pHisto->numOfElems > 0) {
269,115✔
2210
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
204,559✔
2211
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2212

2213
      double  ratio[] = {pInfo->percent};
204,559✔
2214
      double* res = NULL;
204,559✔
2215
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
204,559✔
2216
      if (TSDB_CODE_SUCCESS != code) {
204,570!
2217
        taosMemoryFree(res);
×
2218
        return code;
×
2219
      }
2220
      pInfo->result = *res;
204,570✔
2221
      // memcpy(pCtx->pOutput, res, sizeof(double));
2222
      taosMemoryFree(res);
204,570✔
2223
    } else {  // no need to free
2224
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2225
      // return TSDB_CODE_SUCCESS;
2226
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
64,556✔
2227
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2228
    }
2229
  }
2230

2231
  return functionFinalize(pCtx, pBlock);
283,190✔
2232
}
2233

2234
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,117✔
2235
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,117✔
2236
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
8,117✔
2237

2238
  int32_t resultBytes = getApercentileMaxSize();
8,117✔
2239
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
8,117✔
2240
  if (NULL == res) {
8,117!
2241
    return terrno;
×
2242
  }
2243

2244
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
8,117✔
2245
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
949✔
2246
    varDataSetLen(res, resultBytes);
949✔
2247
  } else {
2248
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
7,168✔
2249
    varDataSetLen(res, resultBytes);
7,168✔
2250
  }
2251

2252
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
8,117✔
2253
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,117✔
2254
  if (NULL == pCol) {
8,117!
2255
    taosMemoryFree(res);
×
2256
    return TSDB_CODE_OUT_OF_RANGE;
×
2257
  }
2258

2259
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
8,117✔
2260

2261
  taosMemoryFree(res);
8,117✔
2262
  return code;
8,117✔
2263
}
2264

2265
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
4✔
2266
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
4✔
2267
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
4✔
2268

2269
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
4✔
2270
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
4✔
2271

2272
  qDebug("%s start to combine apercentile, %p", __FUNCTION__, pDBuf->pHisto);
4!
2273

2274
  int32_t code = apercentileTransferInfo(pSBuf, pDBuf, NULL);
4✔
2275
  if (TSDB_CODE_SUCCESS != code) {
4!
2276
    return code;
×
2277
  }
2278
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
4✔
2279
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
4✔
2280
  return TSDB_CODE_SUCCESS;
4✔
2281
}
2282

2283
// TODO: change this function when block data info pks changed
2284
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
5,393✔
2285
  char numVal[8] = {0};
5,393✔
2286
  switch (pkType) {
5,393✔
2287
    case TSDB_DATA_TYPE_INT:
916✔
2288
      *(int32_t*)numVal = (int32_t)pVal->val;
916✔
2289
      break;
916✔
2290
    case TSDB_DATA_TYPE_UINT:
886✔
2291
      *(uint32_t*)numVal = (uint32_t)pVal->val;
886✔
2292
      break;
886✔
2293
    case TSDB_DATA_TYPE_BIGINT:
1,003✔
2294
      *(int64_t*)numVal = (int64_t)pVal->val;
1,003✔
2295
      break;
1,003✔
2296
    case TSDB_DATA_TYPE_UBIGINT:
983✔
2297
      *(uint64_t*)numVal = (uint64_t)pVal->val;
983✔
2298
      break;
983✔
2299
    default:
1,605✔
2300
      break;
1,605✔
2301
  }
2302
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
5,393!
2303
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
5,393✔
2304
  return fn(pkData, blockData);
5,394✔
2305
}
2306

2307
EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
9,712✔
2308
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
9,712✔
2309

2310
  // not initialized yet, data is required
2311
  if (pEntry == NULL) {
9,712!
2312
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2313
  }
2314

2315
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
9,712✔
2316
  if (pResult->hasResult) {
9,712✔
2317
    if (pResult->pkBytes > 0) {
9,640✔
2318
      pResult->pkData = pResult->buf + pResult->bytes;
5,131✔
2319
    } else {
2320
      pResult->pkData = NULL;
4,509✔
2321
    }
2322
    if (pResult->ts < pBlockInfo->window.skey) {
9,640✔
2323
      return FUNC_DATA_REQUIRED_NOT_LOAD;
6,067✔
2324
    } else if (pResult->ts == pBlockInfo->window.skey) {
3,573✔
2325
      if (NULL == pResult->pkData) {
2,067✔
2326
        return FUNC_DATA_REQUIRED_NOT_LOAD;
196✔
2327
      }
2328
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
1,871✔
2329
        return FUNC_DATA_REQUIRED_NOT_LOAD;
316✔
2330
      }
2331
    }
2332
    return FUNC_DATA_REQUIRED_DATA_LOAD;
3,061✔
2333
  } else {
2334
    return FUNC_DATA_REQUIRED_DATA_LOAD;
72✔
2335
  }
2336
}
2337

2338
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
16,931✔
2339
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
16,931✔
2340

2341
  // not initialized yet, data is required
2342
  if (pEntry == NULL) {
16,931!
2343
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2344
  }
2345

2346
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
16,931✔
2347
  if (pResult->hasResult) {
16,931✔
2348
    if (pResult->pkBytes > 0) {
16,846✔
2349
      pResult->pkData = pResult->buf + pResult->bytes;
10,000✔
2350
    } else {
2351
      pResult->pkData = NULL;
6,846✔
2352
    }
2353
    if (pResult->ts > pBlockInfo->window.ekey) {
16,846✔
2354
      return FUNC_DATA_REQUIRED_NOT_LOAD;
10,056✔
2355
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
6,790✔
2356
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
3,525✔
2357
        return FUNC_DATA_REQUIRED_NOT_LOAD;
1,084✔
2358
      }
2359
    }
2360
    return FUNC_DATA_REQUIRED_DATA_LOAD;
5,706✔
2361
  } else {
2362
    return FUNC_DATA_REQUIRED_DATA_LOAD;
85✔
2363
  }
2364
}
2365

2366
// TODO modify it to include primary key bytes
2367
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
84,750,462✔
2368

2369
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,029,114✔
2370
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
2,029,114✔
2371
  // TODO: change SFunctionNode to add pk info
2372
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
2,030,873✔
2373
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
2,030,873✔
2374
  return true;
2,030,224✔
2375
}
2376

2377
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,410,358✔
2378
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,410,358✔
2379
  pEnv->calcMemSize = pNode->node.resType.bytes;
1,411,550✔
2380
  return true;
1,411,550✔
2381
}
2382

2383
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
303,537✔
2384
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
303,537✔
2385
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
303,787✔
2386
  return true;
303,787✔
2387
}
2388

2389
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2390
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
456,769,124!
2391
    return 0;
×
2392
  }
2393

2394
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
456,867,874!
2395
}
2396

2397
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
9,671,708✔
2398
  if (pResInfo->initialized) {
9,671,708!
2399
    return TSDB_CODE_SUCCESS;
×
2400
  }
2401
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
9,671,708!
2402
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2403
  }
2404

2405
  SFirstLastRes*        pRes = GET_ROWCELL_INTERBUF(pResInfo);
9,673,216✔
2406
  SInputColumnInfoData* pInput = &pCtx->input;
9,673,216✔
2407

2408
  pRes->nullTupleSaved = false;
9,673,216✔
2409
  pRes->nullTuplePos.pageId = -1;
9,673,216✔
2410
  return TSDB_CODE_SUCCESS;
9,673,216✔
2411
}
2412

2413
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
230,608,291✔
2414
  if (pCtx->subsidiaries.rowLen == 0) {
230,608,291✔
2415
    int32_t rowLen = 0;
674,960✔
2416
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,359,772✔
2417
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
684,812✔
2418
      rowLen += pc->pExpr->base.resSchema.bytes;
684,812✔
2419
    }
2420

2421
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
674,960✔
2422
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
674,960✔
2423
    if (NULL == pCtx->subsidiaries.buf) {
674,968✔
2424
      return terrno;
7✔
2425
    }
2426
  }
2427
  return TSDB_CODE_SUCCESS;
230,608,292✔
2428
}
2429

2430
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
249,157,914✔
2431
                                      SFirstLastRes* pInfo, bool noElements) {
2432
  int32_t code = TSDB_CODE_SUCCESS;
249,157,914✔
2433

2434
  if (pCtx->subsidiaries.num <= 0) {
249,157,914✔
2435
    return TSDB_CODE_SUCCESS;
123,823,418✔
2436
  }
2437

2438
  if (!pInfo->hasResult) {
125,334,496✔
2439
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
110,395,981✔
2440
  } else {
2441
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
14,938,515✔
2442
  }
2443

2444
  return code;
124,999,541✔
2445
}
2446

2447
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
89,511,543✔
2448
                                char* pData) {
2449
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
89,511,543✔
2450
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
89,511,543✔
2451

2452
  if (IS_VAR_DATA_TYPE(type)) {
89,511,543!
2453
    pInfo->bytes = varDataTLen(pData);
6,212,257✔
2454
  }
2455

2456
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
89,511,543✔
2457
  if (pkData != NULL) {
89,511,543✔
2458
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
1,399,970!
2459
      pInfo->pkBytes = varDataTLen(pkData);
455,947✔
2460
    }
2461
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
1,399,970✔
2462
    pInfo->pkData = pInfo->buf + pInfo->bytes;
1,399,970✔
2463
  }
2464

2465
  pInfo->ts = currentTs;
89,511,543✔
2466
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
89,511,543✔
2467
  if (code != TSDB_CODE_SUCCESS) {
89,602,468!
2468
    return code;
×
2469
  }
2470

2471
  pInfo->hasResult = true;
89,602,468✔
2472
  return TSDB_CODE_SUCCESS;
89,602,468✔
2473
}
2474

2475
// This ordinary first function does not care if current scan is ascending order or descending order scan
2476
// the OPTIMIZED version of first function will only handle the ascending order scan
2477
int32_t firstFunction(SqlFunctionCtx* pCtx) {
55,044,693✔
2478
  int32_t numOfElems = 0;
55,044,693✔
2479

2480
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
55,044,693✔
2481
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
55,044,693✔
2482

2483
  SInputColumnInfoData* pInput = &pCtx->input;
55,044,693✔
2484
  SColumnInfoData*      pInputCol = pInput->pData[0];
55,044,693✔
2485

2486
  pInfo->bytes = pInputCol->info.bytes;
55,044,693✔
2487

2488
  if (IS_NULL_TYPE(pInputCol->info.type)) {
55,044,693✔
2489
    return TSDB_CODE_SUCCESS;
4,696✔
2490
  }
2491

2492
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
55,039,997✔
2493
  pInfo->pkType = -1;
55,039,997✔
2494
  __compar_fn_t pkCompareFn = NULL;
55,039,997✔
2495
  if (pCtx->hasPrimaryKey) {
55,039,997✔
2496
    pInfo->pkType = pkCol->info.type;
188,978✔
2497
    pInfo->pkBytes = pkCol->info.bytes;
188,978✔
2498
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
188,978✔
2499
  }
2500

2501
  // All null data column, return directly.
2502
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
55,116,745!
2503
      pInputCol->hasNull == true) {
×
2504
    // save selectivity value for column consisted of all null values
2505
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2506
    if (code != TSDB_CODE_SUCCESS) {
×
2507
      return code;
×
2508
    }
2509
    pInfo->nullTupleSaved = true;
×
2510
    return TSDB_CODE_SUCCESS;
×
2511
  }
2512

2513
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
55,116,745!
2514

2515
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
55,116,745!
2516
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
55,116,745!
2517

2518
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
55,116,745✔
2519

2520
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
2521
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2522
#if 0
2523
  if (blockDataOrder == TSDB_ORDER_ASC) {
2524
    // filter according to current result firstly
2525
    if (pResInfo->numOfRes > 0) {
2526
      if (pInfo->ts < startKey) {
2527
        return TSDB_CODE_SUCCESS;
2528
      }
2529
    }
2530

2531
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2532
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2533
        continue;
2534
      }
2535

2536
      numOfElems++;
2537

2538
      char* data = colDataGetData(pInputCol, i);
2539
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2540
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2541
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2542
        break;
2543
      }
2544
    }
2545
  } else {
2546
    // in case of descending order time stamp serial, which usually happens as the results of the nest query,
2547
    // all data needs to be check.
2548
    if (pResInfo->numOfRes > 0) {
2549
      if (pInfo->ts < endKey) {
2550
        return TSDB_CODE_SUCCESS;
2551
      }
2552
    }
2553

2554
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2555
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2556
        continue;
2557
      }
2558

2559
      numOfElems++;
2560

2561
      char* data = colDataGetData(pInputCol, i);
2562
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2563

2564
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2565
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2566
        break;
2567
      }
2568
    }
2569
  }
2570
#else
2571
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
55,116,745✔
2572

2573
  int     from = -1;
55,116,745✔
2574
  int32_t i = -1;
55,116,745✔
2575
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
173,141,777✔
2576
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
157,067,975!
2577
      continue;
85,772✔
2578
    }
2579

2580
    numOfElems++;
118,009,603✔
2581
    char* data = colDataGetData(pInputCol, i);
118,009,603!
2582
    char* pkData = NULL;
118,009,603✔
2583
    if (pCtx->hasPrimaryKey) {
118,009,603✔
2584
      pkData = colDataGetData(pkCol, i);
1,329,428!
2585
    }
2586
    TSKEY cts = pts[i];
118,009,603✔
2587
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
118,009,603✔
2588
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
69,772,758!
2589
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
48,236,845✔
2590
      if (code != TSDB_CODE_SUCCESS) {
48,166,504!
2591
        return code;
×
2592
      }
2593
      pResInfo->numOfRes = 1;
48,166,504✔
2594
    }
2595
  }
2596
#endif
2597

2598
  if (numOfElems == 0) {
54,762,356✔
2599
    // save selectivity value for column consisted of all null values
2600
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
24,685✔
2601
    if (code != TSDB_CODE_SUCCESS) {
24,685!
2602
      return code;
×
2603
    }
2604
    pInfo->nullTupleSaved = true;
24,685✔
2605
  }
2606
  SET_VAL(pResInfo, numOfElems, 1);
54,762,356✔
2607
  return TSDB_CODE_SUCCESS;
54,762,356✔
2608
}
2609

2610
int32_t lastFunction(SqlFunctionCtx* pCtx) {
42,459,439✔
2611
  int32_t numOfElems = 0;
42,459,439✔
2612

2613
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
42,459,439✔
2614
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
42,459,439✔
2615

2616
  SInputColumnInfoData* pInput = &pCtx->input;
42,459,439✔
2617
  SColumnInfoData*      pInputCol = pInput->pData[0];
42,459,439✔
2618

2619
  int32_t type = pInputCol->info.type;
42,459,439✔
2620
  int32_t bytes = pInputCol->info.bytes;
42,459,439✔
2621
  pInfo->bytes = bytes;
42,459,439✔
2622

2623
  if (IS_NULL_TYPE(type)) {
42,459,439✔
2624
    return TSDB_CODE_SUCCESS;
4,695✔
2625
  }
2626

2627
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
42,454,744✔
2628
  pInfo->pkType = -1;
42,454,744✔
2629
  __compar_fn_t pkCompareFn = NULL;
42,454,744✔
2630
  if (pCtx->hasPrimaryKey) {
42,454,744✔
2631
    pInfo->pkType = pkCol->info.type;
248,117✔
2632
    pInfo->pkBytes = pkCol->info.bytes;
248,117✔
2633
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
248,117✔
2634
  }
2635

2636
  // All null data column, return directly.
2637
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
42,491,722!
2638
      pInputCol->hasNull == true) {
×
2639
    // save selectivity value for column consisted of all null values
2640
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2641
    if (code != TSDB_CODE_SUCCESS) {
×
2642
      return code;
×
2643
    }
2644
    pInfo->nullTupleSaved = true;
×
2645
    return TSDB_CODE_SUCCESS;
×
2646
  }
2647

2648
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
42,491,722!
2649

2650
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
42,491,722!
2651
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
42,491,722!
2652

2653
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
42,491,722✔
2654

2655
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2656
#if 0
2657
  if (blockDataOrder == TSDB_ORDER_ASC) {
2658
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2659
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2660
        continue;
2661
      }
2662

2663
      numOfElems++;
2664

2665
      char* data = colDataGetData(pInputCol, i);
2666
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2667
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2668
        doSaveCurrentVal(pCtx, i, cts, type, data);
2669
      }
2670

2671
      break;
2672
    }
2673
  } else {  // descending order
2674
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2675
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2676
        continue;
2677
      }
2678

2679
      numOfElems++;
2680

2681
      char* data = colDataGetData(pInputCol, i);
2682
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2683
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2684
        doSaveCurrentVal(pCtx, i, cts, type, data);
2685
      }
2686
      break;
2687
    }
2688
  }
2689
#else
2690
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
42,491,722✔
2691

2692
#if 0
2693
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2694
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2695
        continue;
2696
      }
2697

2698
      numOfElems++;
2699
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2700
        char* data = colDataGetData(pInputCol, i);
2701
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2702
        pResInfo->numOfRes = 1;
2703
      }
2704
    }
2705
#else
2706

2707
  // todo refactor
2708
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
67,219,624✔
2709
    numOfElems = 1;
24,738,935✔
2710

2711
    int32_t round = pInput->numOfRows >> 2;
24,738,935✔
2712
    int32_t reminder = pInput->numOfRows & 0x03;
24,738,935✔
2713

2714
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
38,362,396✔
2715
      int64_t cts = pts[i];
13,619,508✔
2716
      int32_t chosen = i;
13,619,508✔
2717

2718
      if (cts < pts[i + 1]) {
13,619,508✔
2719
        cts = pts[i + 1];
4,911,171✔
2720
        chosen = i + 1;
4,911,171✔
2721
      }
2722

2723
      if (cts < pts[i + 2]) {
13,619,508✔
2724
        cts = pts[i + 2];
4,911,020✔
2725
        chosen = i + 2;
4,911,020✔
2726
      }
2727

2728
      if (cts < pts[i + 3]) {
13,619,508✔
2729
        cts = pts[i + 3];
4,910,382✔
2730
        chosen = i + 3;
4,910,382✔
2731
      }
2732

2733
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
13,619,508✔
2734
        char*   data = colDataGetData(pInputCol, chosen);
3,972,670!
2735
        int32_t code = doSaveCurrentVal(pCtx, i, cts, NULL, type, data);
3,972,670✔
2736
        if (code != TSDB_CODE_SUCCESS) {
3,976,623!
2737
          return code;
×
2738
        }
2739
        pResInfo->numOfRes = 1;
3,976,623✔
2740
      }
2741
    }
2742

2743
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
51,600,378✔
2744
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
26,872,476✔
2745
        char*   data = colDataGetData(pInputCol, i);
17,358,875!
2746
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
17,358,875✔
2747
        if (code != TSDB_CODE_SUCCESS) {
17,343,889!
2748
          return code;
×
2749
        }
2750
        pResInfo->numOfRes = 1;
17,343,889✔
2751
      }
2752
    }
2753
  } else {
2754
    int     from = -1;
17,752,787✔
2755
    int32_t i = -1;
17,752,787✔
2756
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
229,208,164✔
2757
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
422,955,864✔
2758
        continue;
11,649,715✔
2759
      }
2760

2761
      numOfElems++;
199,828,217✔
2762
      char* pkData = NULL;
199,828,217✔
2763
      if (pCtx->hasPrimaryKey) {
199,828,217✔
2764
        pkData = colDataGetData(pkCol, i);
101,402,239!
2765
      }
2766
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
199,828,217✔
2767
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
180,133,779!
2768
        char*   data = colDataGetData(pInputCol, i);
19,945,478!
2769
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
19,945,478✔
2770
        if (code != TSDB_CODE_SUCCESS) {
19,922,928!
2771
          return code;
×
2772
        }
2773
        pResInfo->numOfRes = 1;
19,922,928✔
2774
      }
2775
    }
2776
  }
2777
#endif
2778

2779
#endif
2780

2781
  // save selectivity value for column consisted of all null values
2782
  if (numOfElems == 0) {
42,608,331✔
2783
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
4,091,470✔
2784
    if (code != TSDB_CODE_SUCCESS) {
4,085,818!
2785
      return code;
×
2786
    }
2787
    pInfo->nullTupleSaved = true;
4,085,818✔
2788
  }
2789

2790
  return TSDB_CODE_SUCCESS;
42,602,679✔
2791
}
2792

2793
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
79,285,476✔
2794
  if (!pInput->hasResult) {
79,285,476✔
2795
    return false;
2✔
2796
  }
2797
  __compar_fn_t pkCompareFn = NULL;
79,285,474✔
2798
  if (pInput->pkData) {
79,285,474✔
2799
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
37,995✔
2800
  }
2801
  if (pOutput->hasResult) {
79,291,161✔
2802
    if (isFirst) {
31,229,893✔
2803
      if (pInput->ts > pOutput->ts ||
8,591,400✔
2804
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,590,576✔
2805
        return false;
1,284✔
2806
      }
2807
    } else {
2808
      if (pInput->ts < pOutput->ts ||
22,638,493✔
2809
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
13,273,925✔
2810
        return false;
9,368,094✔
2811
      }
2812
    }
2813
  }
2814

2815
  pOutput->isNull = pInput->isNull;
69,921,783✔
2816
  pOutput->ts = pInput->ts;
69,921,783✔
2817
  pOutput->bytes = pInput->bytes;
69,921,783✔
2818
  pOutput->pkType = pInput->pkType;
69,921,783✔
2819

2820
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
69,921,783✔
2821
  if (pInput->pkData) {
69,921,783✔
2822
    pOutput->pkBytes = pInput->pkBytes;
34,950✔
2823
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
34,950✔
2824
    pOutput->pkData = pOutput->buf + pOutput->bytes;
34,950✔
2825
  }
2826
  return true;
69,921,783✔
2827
}
2828

2829
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
79,285,448✔
2830
                                     int32_t rowIndex) {
2831
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
79,285,448✔
2832
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
69,921,132✔
2833
    if (TSDB_CODE_SUCCESS != code) {
69,907,973!
2834
      return code;
×
2835
    }
2836
    pOutput->hasResult = true;
69,907,973✔
2837
  }
2838
  return TSDB_CODE_SUCCESS;
79,273,170✔
2839
}
2840

2841
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
48,108,659✔
2842
  SInputColumnInfoData* pInput = &pCtx->input;
48,108,659✔
2843
  SColumnInfoData*      pCol = pInput->pData[0];
48,108,659✔
2844

2845
  if (IS_NULL_TYPE(pCol->info.type)) {
48,108,659!
2846
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
2847
    return TSDB_CODE_SUCCESS;
×
2848
  }
2849

2850
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
48,108,659!
2851
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2852
  }
2853

2854
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
48,108,659✔
2855

2856
  int32_t start = pInput->startRowIndex;
48,108,659✔
2857
  int32_t numOfElems = 0;
48,108,659✔
2858

2859
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
129,672,671✔
2860
    if (colDataIsNull_s(pCol, i)) {
163,168,408✔
2861
      continue;
2,291,537✔
2862
    }
2863
    char*          data = colDataGetData(pCol, i);
79,292,667!
2864
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
79,292,667✔
2865
    if (pCtx->hasPrimaryKey) {
79,292,667✔
2866
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
37,994✔
2867
    } else {
2868
      pInputInfo->pkData = NULL;
79,254,673✔
2869
    }
2870

2871
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
79,292,667✔
2872
    if (code != TSDB_CODE_SUCCESS) {
79,272,475!
2873
      return code;
×
2874
    }
2875
    if (!numOfElems) {
79,272,475✔
2876
      numOfElems = pInputInfo->hasResult ? 1 : 0;
48,088,044✔
2877
    }
2878
  }
2879

2880
  if (numOfElems == 0) {
48,088,467✔
2881
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
14,213✔
2882
    if (code != TSDB_CODE_SUCCESS) {
14,213!
2883
      return code;
×
2884
    }
2885
    pInfo->nullTupleSaved = true;
14,213✔
2886
  }
2887

2888
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
48,088,467✔
2889
  return TSDB_CODE_SUCCESS;
48,088,467✔
2890
}
2891

2892
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
14,699,043✔
2893

2894
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
33,416,670✔
2895

2896
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
112,244,937✔
2897
  int32_t          code = TSDB_CODE_SUCCESS;
112,244,937✔
2898
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
112,244,937✔
2899
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
112,244,937✔
2900
  if (NULL == pCol) {
112,198,030!
2901
    return TSDB_CODE_OUT_OF_RANGE;
×
2902
  }
2903

2904
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
112,198,030✔
2905
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
112,198,030✔
2906

2907
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
112,198,030✔
2908

2909
  if (pResInfo->isNullRes) {
112,198,030✔
2910
    colDataSetNULL(pCol, pBlock->info.rows);
49,203✔
2911
    return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
49,203✔
2912
  }
2913
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
112,148,827!
2914
  if (TSDB_CODE_SUCCESS != code) {
112,029,615!
2915
    return code;
×
2916
  }
2917

2918
  // handle selectivity
2919
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
112,029,615✔
2920

2921
  return code;
112,032,553✔
2922
}
2923

2924
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
82,661,224✔
2925
  int32_t code = TSDB_CODE_SUCCESS;
82,661,224✔
2926

2927
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
82,661,224✔
2928
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
82,661,224✔
2929

2930
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
82,661,224✔
2931

2932
  // todo check for failure
2933
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
82,604,901✔
2934
  if (NULL == res) {
83,681,311!
2935
    return terrno;
×
2936
  }
2937
  (void)memcpy(varDataVal(res), pRes, resultBytes);
83,681,311✔
2938

2939
  varDataSetLen(res, resultBytes);
83,681,311✔
2940

2941
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
83,681,311✔
2942
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
83,681,311✔
2943
  if (NULL == pCol) {
83,364,247!
2944
    taosMemoryFree(res);
×
2945
    return TSDB_CODE_OUT_OF_RANGE;
×
2946
  }
2947

2948
  if (pEntryInfo->numOfRes == 0) {
83,378,152✔
2949
    colDataSetNULL(pCol, pBlock->info.rows);
2,392,270!
2950
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
2,392,270✔
2951
  } else {
2952
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
80,985,882✔
2953
    if (TSDB_CODE_SUCCESS != code) {
80,132,656!
2954
      taosMemoryFree(res);
×
2955
      return code;
×
2956
    }
2957
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
80,132,656✔
2958
  }
2959
  taosMemoryFree(res);
82,434,462✔
2960
  return code;
83,645,237✔
2961
}
2962

2963
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
2964
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
2965
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
2966
  int32_t              bytes = pDBuf->bytes;
3✔
2967

2968
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
2969
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
2970

2971
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
3✔
2972
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
2973
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
2974
  return TSDB_CODE_SUCCESS;
3✔
2975
}
2976

2977
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
85,762,160✔
2978
  SInputColumnInfoData* pInput = &pCtx->input;
85,762,160✔
2979
  SColumnInfoData*      pInputCol = pInput->pData[0];
85,762,160✔
2980
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
85,762,160✔
2981

2982
  if (colDataIsNull_s(pInputCol, rowIndex)) {
171,524,320✔
2983
    pInfo->isNull = true;
14,764✔
2984
  } else {
2985
    pInfo->isNull = false;
85,747,396✔
2986

2987
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
85,747,396!
2988
      pInfo->bytes = varDataTLen(pData);
40,093,872✔
2989
    }
2990

2991
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
85,747,396✔
2992
  }
2993

2994
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
85,833,590✔
2995
    char* pkData = colDataGetData(pkCol, rowIndex);
71,427!
2996
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
71,427!
2997
      pInfo->pkBytes = varDataTLen(pkData);
23,655✔
2998
    }
2999
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
71,427✔
3000
    pInfo->pkData = pInfo->buf + pInfo->bytes;
71,427✔
3001
  }
3002
  pInfo->ts = cts;
85,762,160✔
3003
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
85,762,160✔
3004
  if (code != TSDB_CODE_SUCCESS) {
85,543,565!
3005
    return code;
×
3006
  }
3007

3008
  pInfo->hasResult = true;
85,543,565✔
3009

3010
  return TSDB_CODE_SUCCESS;
85,543,565✔
3011
}
3012

3013
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
86,958,132✔
3014
  int32_t numOfElems = 0;
86,958,132✔
3015

3016
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
86,958,132✔
3017
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
86,958,132✔
3018

3019
  SInputColumnInfoData* pInput = &pCtx->input;
86,958,132✔
3020
  SColumnInfoData*      pInputCol = pInput->pData[0];
86,958,132✔
3021

3022
  int32_t type = pInputCol->info.type;
86,958,132✔
3023
  int32_t bytes = pInputCol->info.bytes;
86,958,132✔
3024
  pInfo->bytes = bytes;
86,958,132✔
3025

3026
  if (IS_NULL_TYPE(type)) {
86,958,132✔
3027
    return TSDB_CODE_SUCCESS;
40✔
3028
  }
3029
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
86,958,092✔
3030
  pInfo->pkType = -1;
86,958,092✔
3031
  __compar_fn_t pkCompareFn = NULL;
86,958,092✔
3032
  if (pCtx->hasPrimaryKey) {
86,958,092✔
3033
    pInfo->pkType = pkCol->info.type;
203,753✔
3034
    pInfo->pkBytes = pkCol->info.bytes;
203,753✔
3035
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
203,753✔
3036
  }
3037
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
87,048,167✔
3038
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
87,048,167!
3039

3040
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
87,048,167!
3041
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
98,899,680!
3042
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
49,456,562✔
3043
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
49,456,562!
3044
      TSKEY cts = getRowPTs(pInput->pPTS, i);
49,456,562!
3045
      numOfElems++;
49,456,562✔
3046

3047
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
49,456,562✔
3048
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
48,394,106✔
3049
        if (code != TSDB_CODE_SUCCESS) return code;
48,383,173!
3050
      }
3051

3052
      break;
49,445,629✔
3053
    }
3054
  } else if (!pCtx->hasPrimaryKey && pCtx->order == TSDB_ORDER_DESC) {
37,594,116!
3055
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3056
    // this assumption is NOT always works if project operator exists in downstream.
3057
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
74,783,997!
3058
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
37,503,037✔
3059
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
37,503,037!
3060
      TSKEY cts = getRowPTs(pInput->pPTS, i);
37,503,037!
3061
      numOfElems++;
37,503,037✔
3062

3063
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
37,503,037!
3064
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
37,302,660✔
3065
        if (code != TSDB_CODE_SUCCESS) return code;
37,102,369!
3066
      }
3067
      break;
37,302,746✔
3068
    }
3069
  } else {
3070
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
112,865✔
3071
    int      from = -1;
112,865✔
3072
    int32_t  i = -1;
112,865✔
3073
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
1,503,275✔
3074
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
1,390,032✔
3075
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
1,390,032!
3076
      TSKEY cts = pts[i];
1,390,032✔
3077

3078
      numOfElems++;
1,390,032✔
3079
      char* pkData = NULL;
1,390,032✔
3080
      if (pCtx->hasPrimaryKey) {
1,390,032✔
3081
        pkData = colDataGetData(pkCol, i);
1,375,545!
3082
      }
3083
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
1,390,032✔
3084
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
1,319,984✔
3085
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
70,054✔
3086
        if (code != TSDB_CODE_SUCCESS) {
70,432!
3087
          return code;
×
3088
        }
3089
        pResInfo->numOfRes = 1;
70,432✔
3090
      }
3091
    }
3092
  }
3093

3094
  SET_VAL(pResInfo, numOfElems, 1);
86,927,019!
3095
  return TSDB_CODE_SUCCESS;
86,927,019✔
3096
}
3097

3098
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,829✔
3099
  pEnv->calcMemSize = sizeof(SDiffInfo);
22,829✔
3100
  return true;
22,829✔
3101
}
3102

3103
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,764,757✔
3104
  if (pResInfo->initialized) {
1,764,757✔
3105
    return TSDB_CODE_SUCCESS;
1,689,774✔
3106
  }
3107
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
74,983!
3108
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3109
  }
3110
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
74,983✔
3111
  pDiffInfo->hasPrev = false;
74,983✔
3112
  pDiffInfo->isFirstRow = true;
74,983✔
3113
  pDiffInfo->prev.i64 = 0;
74,983✔
3114
  pDiffInfo->prevTs = -1;
74,983✔
3115
  if (pCtx->numOfParams > 1) {
74,983!
3116
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
74,983✔
3117
  } else {
3118
    pDiffInfo->ignoreOption = 0;
×
3119
  }
3120
  return TSDB_CODE_SUCCESS;
74,983✔
3121
}
3122

3123
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
448,821✔
3124
  switch (type) {
448,821!
3125
    case TSDB_DATA_TYPE_BOOL:
38✔
3126
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
38✔
3127
      break;
38✔
3128
    case TSDB_DATA_TYPE_UTINYINT:
371✔
3129
    case TSDB_DATA_TYPE_TINYINT:
3130
      pDiffInfo->prev.i64 = *(int8_t*)pv;
371✔
3131
      break;
371✔
3132
    case TSDB_DATA_TYPE_UINT:
233,773✔
3133
    case TSDB_DATA_TYPE_INT:
3134
      pDiffInfo->prev.i64 = *(int32_t*)pv;
233,773✔
3135
      break;
233,773✔
3136
    case TSDB_DATA_TYPE_USMALLINT:
66,011✔
3137
    case TSDB_DATA_TYPE_SMALLINT:
3138
      pDiffInfo->prev.i64 = *(int16_t*)pv;
66,011✔
3139
      break;
66,011✔
3140
    case TSDB_DATA_TYPE_TIMESTAMP:
612✔
3141
    case TSDB_DATA_TYPE_UBIGINT:
3142
    case TSDB_DATA_TYPE_BIGINT:
3143
      pDiffInfo->prev.i64 = *(int64_t*)pv;
612✔
3144
      break;
612✔
3145
    case TSDB_DATA_TYPE_FLOAT:
147,558✔
3146
      pDiffInfo->prev.d64 = *(float*)pv;
147,558✔
3147
      break;
147,558✔
3148
    case TSDB_DATA_TYPE_DOUBLE:
458✔
3149
      pDiffInfo->prev.d64 = *(double*)pv;
458✔
3150
      break;
458✔
3151
    default:
×
3152
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3153
  }
3154
  pDiffInfo->prevTs = ts;
448,821✔
3155
  pDiffInfo->hasPrev = true;
448,821✔
3156
  return TSDB_CODE_SUCCESS;
448,821✔
3157
}
3158

3159
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
1,358,768✔
3160
  switch (type) {
1,358,768!
3161
    case TSDB_DATA_TYPE_UINT: {
×
3162
      int64_t v = *(uint32_t*)pv;
×
3163
      return v < pDiffInfo->prev.i64;
×
3164
    }
3165
    case TSDB_DATA_TYPE_INT: {
646,163✔
3166
      int64_t v = *(int32_t*)pv;
646,163✔
3167
      return v < pDiffInfo->prev.i64;
646,163✔
3168
    }
3169
    case TSDB_DATA_TYPE_BOOL: {
×
3170
      int64_t v = *(bool*)pv;
×
3171
      return v < pDiffInfo->prev.i64;
×
3172
    }
3173
    case TSDB_DATA_TYPE_UTINYINT: {
×
3174
      int64_t v = *(uint8_t*)pv;
×
3175
      return v < pDiffInfo->prev.i64;
×
3176
    }
3177
    case TSDB_DATA_TYPE_TINYINT: {
5,592✔
3178
      int64_t v = *(int8_t*)pv;
5,592✔
3179
      return v < pDiffInfo->prev.i64;
5,592✔
3180
    }
3181
    case TSDB_DATA_TYPE_USMALLINT: {
×
3182
      int64_t v = *(uint16_t*)pv;
×
3183
      return v < pDiffInfo->prev.i64;
×
3184
    }
3185
    case TSDB_DATA_TYPE_SMALLINT: {
279,098✔
3186
      int64_t v = *(int16_t*)pv;
279,098✔
3187
      return v < pDiffInfo->prev.i64;
279,098✔
3188
    }
3189
    case TSDB_DATA_TYPE_UBIGINT: {
40✔
3190
      uint64_t v = *(uint64_t*)pv;
40✔
3191
      return v < (uint64_t)pDiffInfo->prev.i64;
40✔
3192
    }
3193
    case TSDB_DATA_TYPE_TIMESTAMP:
4,731✔
3194
    case TSDB_DATA_TYPE_BIGINT: {
3195
      int64_t v = *(int64_t*)pv;
4,731✔
3196
      return v < pDiffInfo->prev.i64;
4,731✔
3197
    }
3198
    case TSDB_DATA_TYPE_FLOAT: {
418,849✔
3199
      float v = *(float*)pv;
418,849✔
3200
      return v < pDiffInfo->prev.d64;
418,849✔
3201
    }
3202
    case TSDB_DATA_TYPE_DOUBLE: {
4,295✔
3203
      double v = *(double*)pv;
4,295✔
3204
      return v < pDiffInfo->prev.d64;
4,295✔
3205
    }
3206
    default:
×
3207
      return false;
×
3208
  }
3209

3210
  return false;
3211
}
3212

3213
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
1,405,804,831✔
3214
  bool isNegative = v < pDiffInfo->prev.i64;
1,405,804,831✔
3215
  if (type == TSDB_DATA_TYPE_UBIGINT) {
1,405,804,831✔
3216
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
3,745✔
3217
  }
3218
  int64_t delta = v - pDiffInfo->prev.i64;
1,405,804,831✔
3219
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
1,405,804,831✔
3220
    colDataSetNull_f_s(pOutput, pos);
243,035✔
3221
    pOutput->hasNull = true;
243,035✔
3222
  } else {
3223
    colDataSetInt64(pOutput, pos, &delta);
1,405,561,796✔
3224
  }
3225
  pDiffInfo->prev.i64 = v;
1,405,804,831✔
3226
}
1,405,804,831✔
3227

3228
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
367,827✔
3229
  double delta = v - pDiffInfo->prev.d64;
367,827✔
3230
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
367,827✔
3231
    colDataSetNull_f_s(pOutput, pos);
74,757✔
3232
  } else {
3233
    colDataSetDouble(pOutput, pos, &delta);
293,070✔
3234
  }
3235
  pDiffInfo->prev.d64 = v;
367,827✔
3236
}
367,827✔
3237

3238
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
1,406,173,271✔
3239
                            int64_t ts) {
3240
  if (!pDiffInfo->hasPrev) {
1,406,173,271✔
3241
    colDataSetNull_f_s(pOutput, pos);
613✔
3242
    return doSetPrevVal(pDiffInfo, type, pv, ts);
613✔
3243
  }
3244
  pDiffInfo->prevTs = ts;
1,406,172,658✔
3245
  switch (type) {
1,406,172,658!
3246
    case TSDB_DATA_TYPE_UINT: {
3,675✔
3247
      int64_t v = *(uint32_t*)pv;
3,675✔
3248
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,675✔
3249
      break;
3,675✔
3250
    }
3251
    case TSDB_DATA_TYPE_INT: {
27,041,660✔
3252
      int64_t v = *(int32_t*)pv;
27,041,660✔
3253
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
27,041,660✔
3254
      break;
27,041,660✔
3255
    }
3256
    case TSDB_DATA_TYPE_BOOL: {
10,877✔
3257
      int64_t v = *(bool*)pv;
10,877✔
3258
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,877✔
3259
      break;
10,877✔
3260
    }
3261
    case TSDB_DATA_TYPE_UTINYINT: {
675✔
3262
      int64_t v = *(uint8_t*)pv;
675✔
3263
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3264
      break;
675✔
3265
    }
3266
    case TSDB_DATA_TYPE_TINYINT: {
34,822✔
3267
      int64_t v = *(int8_t*)pv;
34,822✔
3268
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
34,822✔
3269
      break;
34,822✔
3270
    }
3271
    case TSDB_DATA_TYPE_USMALLINT: {
675✔
3272
      int64_t v = *(uint16_t*)pv;
675✔
3273
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3274
      break;
675✔
3275
    }
3276
    case TSDB_DATA_TYPE_SMALLINT: {
387,705✔
3277
      int64_t v = *(int16_t*)pv;
387,705✔
3278
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
387,705✔
3279
      break;
387,705✔
3280
    }
3281
    case TSDB_DATA_TYPE_TIMESTAMP:
1,378,324,742✔
3282
    case TSDB_DATA_TYPE_UBIGINT:
3283
    case TSDB_DATA_TYPE_BIGINT: {
3284
      int64_t v = *(int64_t*)pv;
1,378,324,742✔
3285
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,378,324,742✔
3286
      break;
1,378,324,742✔
3287
    }
3288
    case TSDB_DATA_TYPE_FLOAT: {
317,968✔
3289
      double v = *(float*)pv;
317,968✔
3290
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
317,968✔
3291
      break;
317,968✔
3292
    }
3293
    case TSDB_DATA_TYPE_DOUBLE: {
49,859✔
3294
      double v = *(double*)pv;
49,859✔
3295
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
49,859✔
3296
      break;
49,859✔
3297
    }
3298
    default:
×
3299
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3300
  }
3301
  pDiffInfo->hasPrev = true;
1,406,172,658✔
3302
  return TSDB_CODE_SUCCESS;
1,406,172,658✔
3303
}
3304

3305
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3306
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3307
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
403,431,528✔
3308
                              int32_t* nextFrom) {
3309
  if (pInput->pPrimaryKey == NULL) {
403,431,528✔
3310
    if (from == -1) {
298,789,570✔
3311
      from = pInput->startRowIndex;
73,832,171✔
3312
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
224,957,399✔
3313
      return false;
73,454,062✔
3314
    }
3315
    *pRowIndex = from;
225,335,508✔
3316
    *nextFrom = from + 1;
225,335,508✔
3317
    return true;
225,335,508✔
3318
  } else {
3319
    if (from == -1) {
104,641,958✔
3320
      from = pInput->startRowIndex;
640,720✔
3321
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
104,001,238✔
3322
      return false;
640,865✔
3323
    }
3324
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
104,001,093✔
3325
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
104,001,093✔
3326
    int8_t           pkType = pkCol->info.type;
104,001,093✔
3327
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
104,001,093✔
3328
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
104,001,093✔
3329
    int32_t          select = from;
104,092,653✔
3330
    char*            val = colDataGetData(pkCol, select);
104,092,653!
3331
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
110,265,252✔
3332
      char* val1 = colDataGetData(pkCol, from + 1);
6,175,133!
3333
      if (compareFunc(val1, val) < 0) {
6,175,133✔
3334
        select = from + 1;
1,924,144✔
3335
        val = val1;
1,924,144✔
3336
      }
3337
      from = from + 1;
6,172,599✔
3338
    }
3339
    *pRowIndex = select;
104,090,119✔
3340
    *nextFrom = from + 1;
104,090,119✔
3341
    return true;
104,090,119✔
3342
  }
3343
}
3344

3345
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
×
3346
  pEnv->calcMemSize = sizeof(float);
×
3347
  return true;
×
3348
}
3349

3350
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,406,717,816✔
3351
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,406,717,816✔
3352
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,406,717,816✔
3353

3354
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
1,406,717,816✔
3355
    return true;
170,081✔
3356
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
1,406,547,735✔
3357
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
1,358,768✔
3358
  }
3359
  return false;
1,405,188,967✔
3360
}
3361

3362
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,406,330,341✔
3363
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,406,330,341✔
3364
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,406,330,341✔
3365
  return pDiffInfo->isFirstRow;
1,406,330,341✔
3366
}
3367

3368
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
450,173✔
3369
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
450,173✔
3370
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
450,173✔
3371
  pDiffInfo->isFirstRow = false;
450,173✔
3372
  if (pRow->isDataNull) {
450,173✔
3373
    return TSDB_CODE_SUCCESS;
1,965✔
3374
  }
3375

3376
  SInputColumnInfoData* pInput = &pCtx->input;
448,208✔
3377
  SColumnInfoData*      pInputCol = pInput->pData[0];
448,208✔
3378
  int8_t                inputType = pInputCol->info.type;
448,208✔
3379

3380
  char* pv = pRow->pData;
448,208✔
3381
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
448,208✔
3382
}
3383

3384
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
1,406,267,643✔
3385
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,406,267,643✔
3386
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,406,267,643✔
3387

3388
  SInputColumnInfoData* pInput = &pCtx->input;
1,406,267,643✔
3389
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,406,267,643✔
3390
  int8_t                inputType = pInputCol->info.type;
1,406,267,643✔
3391
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
1,406,267,643✔
3392
  int32_t               code = TSDB_CODE_SUCCESS;
1,406,267,643✔
3393
  if (pRow->isDataNull) {
1,406,267,643✔
3394
    colDataSetNull_f_s(pOutput, pos);
94,349✔
3395
    pOutput->hasNull = true;
94,349✔
3396

3397
    // handle selectivity
3398
    if (pCtx->subsidiaries.num > 0) {
94,349✔
3399
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
860✔
3400
      if (code != TSDB_CODE_SUCCESS) {
860!
3401
        return code;
×
3402
      }
3403
    }
3404
    return TSDB_CODE_SUCCESS;
94,349✔
3405
  }
3406

3407
  char* pv = pRow->pData;
1,406,173,294✔
3408

3409
  if (pRow->ts == pDiffInfo->prevTs) {
1,406,173,294✔
3410
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
23✔
3411
  }
3412
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
1,406,173,271✔
3413
  if (code != TSDB_CODE_SUCCESS) {
1,406,173,271!
3414
    return code;
×
3415
  }
3416
  // handle selectivity
3417
  if (pCtx->subsidiaries.num > 0) {
1,406,173,271✔
3418
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
31,863,894✔
3419
    if (code != TSDB_CODE_SUCCESS) {
31,863,894!
3420
      return code;
×
3421
    }
3422
  }
3423

3424
  return TSDB_CODE_SUCCESS;
1,406,173,271✔
3425
}
3426

3427
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
1,741,928✔
3428

3429
int32_t diffFunctionByRow(SArray* pCtxArray) {
1,741,670✔
3430
  int32_t code = TSDB_CODE_SUCCESS;
1,741,670✔
3431
  int     diffColNum = pCtxArray->size;
1,741,670✔
3432
  if (diffColNum == 0) {
1,741,670!
3433
    return TSDB_CODE_SUCCESS;
×
3434
  }
3435
  int32_t numOfElems = 0;
1,741,670✔
3436

3437
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
1,741,670✔
3438
  if (NULL == pRows) {
1,741,670!
3439
    return terrno;
×
3440
  }
3441

3442
  bool keepNull = false;
1,741,670✔
3443
  for (int i = 0; i < diffColNum; ++i) {
3,483,598✔
3444
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,741,928✔
3445
    if (NULL == pCtx) {
1,741,928!
3446
      code = terrno;
×
3447
      goto _exit;
×
3448
    }
3449
    funcInputUpdate(pCtx);
1,741,928✔
3450
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,741,928✔
3451
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,741,928✔
3452
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
1,741,928✔
3453
      keepNull = true;
1,725,724✔
3454
    }
3455
  }
3456

3457
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
1,741,670✔
3458
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
1,741,670✔
3459
  if (NULL == pCtx0 || NULL == pRow0) {
1,741,670!
3460
    code = terrno;
×
3461
    goto _exit;
×
3462
  }
3463
  int32_t startOffset = pCtx0->offset;
1,741,670✔
3464
  bool    result = false;
1,741,670✔
3465
  while (1) {
1,406,700,303✔
3466
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
1,408,441,973✔
3467
    if (TSDB_CODE_SUCCESS != code) {
1,408,441,973!
3468
      goto _exit;
×
3469
    }
3470
    if (!result) {
1,408,441,973✔
3471
      break;
1,741,647✔
3472
    }
3473
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
1,406,700,326✔
3474
    for (int i = 1; i < diffColNum; ++i) {
1,406,717,816✔
3475
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
17,490✔
3476
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
17,490✔
3477
      if (NULL == pCtx || NULL == pRow) {
17,490!
3478
        code = terrno;
×
3479
        goto _exit;
×
3480
      }
3481
      code = funcInputGetNextRow(pCtx, pRow, &result);
17,490✔
3482
      if (TSDB_CODE_SUCCESS != code) {
17,490!
3483
        goto _exit;
×
3484
      }
3485
      if (!result) {
17,490!
3486
        // rows are not equal
3487
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3488
        goto _exit;
×
3489
      }
3490
      if (!diffResultIsNull(pCtx, pRow)) {
17,490✔
3491
        hasNotNullValue = true;
16,754✔
3492
      }
3493
    }
3494
    int32_t pos = startOffset + numOfElems;
1,406,700,326✔
3495

3496
    bool newRow = false;
1,406,700,326✔
3497
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3498
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,406,717,816✔
3499
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
1,406,717,816✔
3500
      if (NULL == pCtx || NULL == pRow) {
1,406,717,816!
3501
        code = terrno;
×
3502
        goto _exit;
×
3503
      }
3504
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
1,406,717,816✔
3505
        code = setDoDiffResult(pCtx, pRow, pos);
1,406,267,643✔
3506
        if (code != TSDB_CODE_SUCCESS) {
1,406,267,643✔
3507
          goto _exit;
23✔
3508
        }
3509
        newRow = true;
1,406,267,620✔
3510
      } else {
3511
        code = trySetPreVal(pCtx, pRow);
450,173✔
3512
        if (code != TSDB_CODE_SUCCESS) {
450,173!
3513
          goto _exit;
×
3514
        }
3515
      }
3516
    }
3517
    if (newRow) ++numOfElems;
1,406,700,303✔
3518
  }
3519

3520
  for (int i = 0; i < diffColNum; ++i) {
3,483,547✔
3521
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,741,900✔
3522
    if (NULL == pCtx) {
1,741,900!
3523
      code = terrno;
×
3524
      goto _exit;
×
3525
    }
3526
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,741,900✔
3527
    pResInfo->numOfRes = numOfElems;
1,741,900✔
3528
  }
3529

3530
_exit:
1,741,647✔
3531
  if (pRows) {
1,741,670!
3532
    taosArrayDestroy(pRows);
1,741,670✔
3533
    pRows = NULL;
1,741,670✔
3534
  }
3535
  return code;
1,741,670✔
3536
}
3537

3538
int32_t getTopBotInfoSize(int64_t numOfItems) { return sizeof(STopBotRes) + numOfItems * sizeof(STopBotResItem); }
×
3539

3540
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
75,724✔
3541
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
75,724✔
3542
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
75,759✔
3543
  return true;
75,759✔
3544
}
3545

3546
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
33,654,150✔
3547
  if (pResInfo->initialized) {
33,654,150!
3548
    return TSDB_CODE_SUCCESS;
×
3549
  }
3550
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
33,654,150!
3551
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3552
  }
3553

3554
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
33,672,693✔
3555
  SInputColumnInfoData* pInput = &pCtx->input;
33,672,693✔
3556

3557
  pRes->maxSize = pCtx->param[1].param.i;
33,672,693✔
3558

3559
  pRes->nullTupleSaved = false;
33,672,693✔
3560
  pRes->nullTuplePos.pageId = -1;
33,672,693✔
3561
  return TSDB_CODE_SUCCESS;
33,672,693✔
3562
}
3563

3564
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
153,692,647✔
3565
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
153,692,647✔
3566
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
153,692,647✔
3567
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
153,692,647✔
3568

3569
  return pRes;
153,692,647✔
3570
}
3571

3572
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
3573
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
3574

3575
static int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery);
3576

3577
int32_t topFunction(SqlFunctionCtx* pCtx) {
15,715,806✔
3578
  int32_t              numOfElems = 0;
15,715,806✔
3579
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
15,715,806✔
3580

3581
  SInputColumnInfoData* pInput = &pCtx->input;
15,715,806✔
3582
  SColumnInfoData*      pCol = pInput->pData[0];
15,715,806✔
3583

3584
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
15,715,806✔
3585
  pRes->type = pInput->pData[0]->info.type;
15,715,412✔
3586

3587
  int32_t start = pInput->startRowIndex;
15,715,412✔
3588
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
57,272,038✔
3589
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
41,535,210✔
3590
      continue;
32,664✔
3591
    }
3592

3593
    numOfElems++;
41,502,546✔
3594
    char*   data = colDataGetData(pCol, i);
41,502,546!
3595
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
41,502,546✔
3596
    if (code != TSDB_CODE_SUCCESS) {
41,523,962!
3597
      return code;
×
3598
    }
3599
  }
3600

3601
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
15,736,828✔
3602
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
1,674✔
3603
    if (code != TSDB_CODE_SUCCESS) {
1,674!
3604
      return code;
×
3605
    }
3606
    pRes->nullTupleSaved = true;
1,674✔
3607
  }
3608
  return TSDB_CODE_SUCCESS;
15,736,828✔
3609
}
3610

3611
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
18,676,744✔
3612
  int32_t              numOfElems = 0;
18,676,744✔
3613
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
18,676,744✔
3614

3615
  SInputColumnInfoData* pInput = &pCtx->input;
18,676,744✔
3616
  SColumnInfoData*      pCol = pInput->pData[0];
18,676,744✔
3617

3618
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
18,676,744✔
3619
  pRes->type = pInput->pData[0]->info.type;
18,676,751✔
3620

3621
  int32_t start = pInput->startRowIndex;
18,676,751✔
3622
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
63,002,728✔
3623
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
44,325,431✔
3624
      continue;
22,171✔
3625
    }
3626

3627
    numOfElems++;
44,303,260✔
3628
    char*   data = colDataGetData(pCol, i);
44,303,260!
3629
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
44,303,260✔
3630
    if (code != TSDB_CODE_SUCCESS) {
44,303,806!
3631
      return code;
×
3632
    }
3633
  }
3634

3635
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
18,677,297✔
3636
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
2,299✔
3637
    if (code != TSDB_CODE_SUCCESS) {
2,299!
3638
      return code;
×
3639
    }
3640
    pRes->nullTupleSaved = true;
2,299✔
3641
  }
3642

3643
  return TSDB_CODE_SUCCESS;
18,677,297✔
3644
}
3645

3646
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
238,455,959✔
3647
  uint16_t type = *(uint16_t*)param;
238,455,959✔
3648

3649
  STopBotResItem* val1 = (STopBotResItem*)p1;
238,455,959✔
3650
  STopBotResItem* val2 = (STopBotResItem*)p2;
238,455,959✔
3651

3652
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
238,455,959!
3653
    if (val1->v.i == val2->v.i) {
174,117,983✔
3654
      return 0;
239,709✔
3655
    }
3656

3657
    return (val1->v.i > val2->v.i) ? 1 : -1;
173,878,274✔
3658
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
64,337,976!
3659
    if (val1->v.u == val2->v.u) {
827,923✔
3660
      return 0;
179,429✔
3661
    }
3662

3663
    return (val1->v.u > val2->v.u) ? 1 : -1;
648,494✔
3664
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
63,510,053✔
3665
    if (val1->v.f == val2->v.f) {
63,319,268✔
3666
      return 0;
63✔
3667
    }
3668

3669
    return (val1->v.f > val2->v.f) ? 1 : -1;
63,319,205✔
3670
  }
3671

3672
  if (val1->v.d == val2->v.d) {
190,785✔
3673
    return 0;
11✔
3674
  }
3675

3676
  return (val1->v.d > val2->v.d) ? 1 : -1;
190,774✔
3677
}
3678

3679
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
85,792,745✔
3680
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3681
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
85,792,745✔
3682
  int32_t     code = TSDB_CODE_SUCCESS;
85,782,440✔
3683

3684
  SVariant val = {0};
85,782,440✔
3685
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
85,782,440!
3686

3687
  STopBotResItem* pItems = pRes->pItems;
85,799,483✔
3688

3689
  // not full yet
3690
  if (pEntryInfo->numOfRes < pRes->maxSize) {
85,799,483✔
3691
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
54,171,448✔
3692
    pItem->v = val;
54,171,448✔
3693
    pItem->uid = uid;
54,171,448✔
3694

3695
    // save the data of this tuple
3696
    if (pCtx->subsidiaries.num > 0) {
54,171,448✔
3697
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
39,787,148✔
3698
      if (code != TSDB_CODE_SUCCESS) {
39,740,375!
3699
        return code;
×
3700
      }
3701
    }
3702
#ifdef BUF_PAGE_DEBUG
3703
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3704
           pItem->tuplePos.offset);
3705
#endif
3706
    // allocate the buffer and keep the data of this row into the new allocated buffer
3707
    pEntryInfo->numOfRes++;
54,124,675✔
3708
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
54,124,675✔
3709
                        topBotResComparFn, !isTopQuery);
54,124,675✔
3710
    if (code != TSDB_CODE_SUCCESS) {
54,202,791!
3711
      return code;
×
3712
    }
3713
  } else {  // replace the minimum value in the result
3714
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
31,628,035!
3715
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
9,891,146✔
3716
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
9,797,246✔
3717
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
9,795,941✔
3718
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
28,504,878!
3719
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
17,608,343!
3720
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
17,604,467✔
3721
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
15,390,209!
3722
      // replace the old data and the coresponding tuple data
3723
      STopBotResItem* pItem = &pItems[0];
6,483,006✔
3724
      pItem->v = val;
6,483,006✔
3725
      pItem->uid = uid;
6,483,006✔
3726

3727
      // save the data of this tuple by over writing the old data
3728
      if (pCtx->subsidiaries.num > 0) {
6,483,006✔
3729
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
5,488,897✔
3730
        if (code != TSDB_CODE_SUCCESS) {
5,484,678!
3731
          return code;
×
3732
        }
3733
      }
3734
#ifdef BUF_PAGE_DEBUG
3735
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3736
#endif
3737
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
6,478,787✔
3738
                            topBotResComparFn, NULL, !isTopQuery);
6,478,787✔
3739
      if (code != TSDB_CODE_SUCCESS) {
6,476,317!
3740
        return code;
×
3741
      }
3742
    }
3743
  }
3744

3745
  return TSDB_CODE_SUCCESS;
85,824,137✔
3746
}
3747

3748
/*
3749
 * +------------------------------------+--------------+--------------+
3750
 * |            null bitmap             |              |              |
3751
 * |(n columns, one bit for each column)| src column #1| src column #2|
3752
 * +------------------------------------+--------------+--------------+
3753
 */
3754
int32_t serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
230,582,056✔
3755
                           char* buf, char** res) {
3756
  char* nullList = buf;
230,582,056✔
3757
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
230,582,056✔
3758

3759
  int32_t offset = 0;
230,582,056✔
3760
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
460,964,588✔
3761
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
230,681,659✔
3762

3763
    // group_key function has its own process function
3764
    // do not process there
3765
    if (fmIsGroupKeyFunc(pc->functionId)) {
230,681,659✔
3766
      continue;
2,884,331✔
3767
    }
3768

3769
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
227,763,013✔
3770
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
227,763,013✔
3771

3772
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
227,763,013✔
3773
    if (NULL == pCol) {
227,498,201!
3774
      return TSDB_CODE_OUT_OF_RANGE;
×
3775
    }
3776
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
454,996,402✔
3777
      offset += pCol->info.bytes;
429✔
3778
      continue;
429✔
3779
    }
3780

3781
    char* p = colDataGetData(pCol, rowIndex);
227,497,772!
3782
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
227,497,772!
3783
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
58,817!
3784
    } else {
3785
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
227,438,955✔
3786
    }
3787

3788
    offset += pCol->info.bytes;
227,497,772✔
3789
  }
3790

3791
  *res = buf;
230,282,929✔
3792
  return TSDB_CODE_SUCCESS;
230,282,929✔
3793
}
3794

3795
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
248,810,750✔
3796
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3797
  STuplePos p = {0};
248,810,750✔
3798
  if (pHandle->pBuf != NULL) {
248,810,750✔
3799
    SFilePage* pPage = NULL;
248,689,784✔
3800

3801
    if (pHandle->currentPage == -1) {
248,689,784✔
3802
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
683,009✔
3803
      if (pPage == NULL) {
683,021!
3804
        return terrno;
×
3805
      }
3806
      pPage->num = sizeof(SFilePage);
683,021✔
3807
    } else {
3808
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
248,006,775✔
3809
      if (pPage == NULL) {
248,008,019!
3810
        return terrno;
×
3811
      }
3812
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
248,008,019✔
3813
        // current page is all used, let's prepare a new buffer page
3814
        releaseBufPage(pHandle->pBuf, pPage);
2,329,793✔
3815
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
2,329,792✔
3816
        if (pPage == NULL) {
2,329,794!
3817
          return terrno;
×
3818
        }
3819
        pPage->num = sizeof(SFilePage);
2,329,794✔
3820
      }
3821
    }
3822

3823
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
248,690,690✔
3824
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
248,690,690✔
3825

3826
    pPage->num += length;
248,690,690✔
3827
    setBufPageDirty(pPage, true);
248,690,690✔
3828
    releaseBufPage(pHandle->pBuf, pPage);
248,587,112✔
3829
  } else {  // other tuple save policy
3830
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
120,966!
3831
      p.streamTupleKey = *key;
130,149✔
3832
    }
3833
  }
3834

3835
  *pPos = p;
248,541,571✔
3836
  return TSDB_CODE_SUCCESS;
248,541,571✔
3837
}
3838

3839
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
203,275,973✔
3840
  int32_t code = prepareBuf(pCtx);
203,275,973✔
3841
  if (TSDB_CODE_SUCCESS != code) {
203,250,603!
3842
    return code;
×
3843
  }
3844

3845
  SWinKey key = {0};
203,250,603✔
3846
  if (pCtx->saveHandle.pBuf == NULL) {
203,250,603✔
3847
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
130,155✔
3848
    if (NULL == pColInfo) {
130,154!
3849
      return TSDB_CODE_OUT_OF_RANGE;
×
3850
    }
3851
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
130,154!
3852
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3853
    }
3854
    key.groupId = pSrcBlock->info.id.groupId;
130,154✔
3855
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
130,154!
3856
  }
3857

3858
  char* buf = NULL;
203,250,602✔
3859
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
203,250,602✔
3860
  if (TSDB_CODE_SUCCESS != code) {
203,056,562!
3861
    return code;
×
3862
  }
3863
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
203,056,562✔
3864
}
3865

3866
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
27,369,269✔
3867
                                 SFunctionStateStore* pStore) {
3868
  if (pHandle->pBuf != NULL) {
27,369,269✔
3869
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
27,108,385✔
3870
    if (pPage == NULL) {
27,108,070!
3871
      return terrno;
×
3872
    }
3873
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
27,108,070✔
3874
    setBufPageDirty(pPage, true);
27,108,070✔
3875
    releaseBufPage(pHandle->pBuf, pPage);
27,105,880✔
3876
  } else {
3877
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
260,884✔
3878
    if (TSDB_CODE_SUCCESS != code) {
260,989!
3879
      return code;
×
3880
    }
3881
  }
3882

3883
  return TSDB_CODE_SUCCESS;
27,364,031✔
3884
}
3885

3886
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
27,371,793✔
3887
  int32_t code = prepareBuf(pCtx);
27,371,793✔
3888
  if (TSDB_CODE_SUCCESS != code) {
27,371,391!
3889
    return code;
×
3890
  }
3891

3892
  char* buf = NULL;
27,371,391✔
3893
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
27,371,391✔
3894
  if (TSDB_CODE_SUCCESS != code) {
27,369,200!
3895
    return code;
×
3896
  }
3897
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
27,369,200✔
3898
}
3899

3900
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
168,521,043✔
3901
                               char** value) {
3902
  if (pHandle->pBuf != NULL) {
168,521,043✔
3903
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
168,423,399✔
3904
    if (pPage == NULL) {
168,579,491!
3905
      *value = NULL;
×
3906
      return terrno;
×
3907
    }
3908
    *value = pPage->data + pPos->offset;
168,579,491✔
3909
    releaseBufPage(pHandle->pBuf, pPage);
168,579,491✔
3910
    return TSDB_CODE_SUCCESS;
168,456,711✔
3911
  } else {
3912
    *value = NULL;
97,644✔
3913
    int32_t vLen;
3914
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
97,644✔
3915
    if (TSDB_CODE_SUCCESS != code) {
143,527!
3916
      return code;
×
3917
    }
3918
    return TSDB_CODE_SUCCESS;
143,527✔
3919
  }
3920
}
3921

3922
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
168,291,552✔
3923
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
168,291,552✔
3924
}
3925

3926
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
33,634,742✔
3927
  int32_t code = TSDB_CODE_SUCCESS;
33,634,742✔
3928

3929
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
33,634,742✔
3930
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
33,634,742✔
3931

3932
  int16_t type = pCtx->pExpr->base.resSchema.type;
33,633,962✔
3933
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
33,633,962✔
3934

3935
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
33,633,962✔
3936
  if (NULL == pCol) {
33,625,099!
3937
    return TSDB_CODE_OUT_OF_RANGE;
×
3938
  }
3939

3940
  // todo assign the tag value and the corresponding row data
3941
  int32_t currentRow = pBlock->info.rows;
33,625,099✔
3942
  if (pEntryInfo->numOfRes <= 0) {
33,625,099✔
3943
    colDataSetNULL(pCol, currentRow);
561!
3944
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
561✔
3945
    return code;
561✔
3946
  }
3947
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
87,696,369✔
3948
    STopBotResItem* pItem = &pRes->pItems[i];
54,087,389✔
3949
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
54,087,389✔
3950
    if (TSDB_CODE_SUCCESS != code) {
54,071,231!
3951
      return code;
×
3952
    }
3953
#ifdef BUF_PAGE_DEBUG
3954
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3955
           pItem->tuplePos.offset);
3956
#endif
3957
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
54,071,231✔
3958
    if (TSDB_CODE_SUCCESS != code) {
54,071,831!
3959
      return code;
×
3960
    }
3961
    currentRow += 1;
54,071,831✔
3962
  }
3963

3964
  return code;
33,608,980✔
3965
}
3966

3967
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
3968
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
3969
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
3970
  STopBotResItem*      pItems = pRes->pItems;
×
3971
  int32_t              code = TSDB_CODE_SUCCESS;
×
3972

3973
  // not full yet
3974
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
3975
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
3976
    pItem->v = pSourceItem->v;
×
3977
    pItem->uid = pSourceItem->uid;
×
3978
    pItem->tuplePos.pageId = -1;
×
3979
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
3980
    pEntryInfo->numOfRes++;
×
3981
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
3982
                        topBotResComparFn, !isTopQuery);
×
3983
    if (TSDB_CODE_SUCCESS != code) {
×
3984
      return code;
×
3985
    }
3986
  } else {  // replace the minimum value in the result
3987
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
3988
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
3989
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
3990
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
3991
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
3992
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
3993
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
3994
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
3995
      // replace the old data and the coresponding tuple data
3996
      STopBotResItem* pItem = &pItems[0];
×
3997
      pItem->v = pSourceItem->v;
×
3998
      pItem->uid = pSourceItem->uid;
×
3999

4000
      // save the data of this tuple by over writing the old data
4001
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4002
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4003
                            topBotResComparFn, NULL, !isTopQuery);
×
4004
      if (TSDB_CODE_SUCCESS != code) {
×
4005
        return code;
×
4006
      }
4007
    }
4008
  }
4009
  return code;
×
4010
}
4011

4012
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4013
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4014
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4015
  int16_t              type = pSBuf->type;
×
4016
  int32_t              code = TSDB_CODE_SUCCESS;
×
4017
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4018
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
4019
    if (TSDB_CODE_SUCCESS != code) {
×
4020
      return code;
×
4021
    }
4022
  }
4023
  return TSDB_CODE_SUCCESS;
×
4024
}
4025

4026
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4027
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4028
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4029
  int16_t              type = pSBuf->type;
×
4030
  int32_t              code = TSDB_CODE_SUCCESS;
×
4031
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4032
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4033
    if (TSDB_CODE_SUCCESS != code) {
×
4034
      return code;
×
4035
    }
4036
  }
4037
  return TSDB_CODE_SUCCESS;
×
4038
}
4039

4040
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
616,437✔
4041

4042
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
101,439✔
4043
  pEnv->calcMemSize = sizeof(SSpreadInfo);
101,439✔
4044
  return true;
101,439✔
4045
}
4046

4047
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,457,633✔
4048
  if (pResultInfo->initialized) {
2,457,633!
4049
    return TSDB_CODE_SUCCESS;
×
4050
  }
4051
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,457,633!
4052
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4053
  }
4054

4055
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
2,457,727✔
4056
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
2,457,727✔
4057
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
2,457,727✔
4058
  pInfo->hasResult = false;
2,457,727✔
4059
  return TSDB_CODE_SUCCESS;
2,457,727✔
4060
}
4061

4062
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
1,879,374✔
4063
  int32_t numOfElems = 0;
1,879,374✔
4064

4065
  // Only the pre-computing information loaded and actual data does not loaded
4066
  SInputColumnInfoData* pInput = &pCtx->input;
1,879,374✔
4067
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
1,879,374✔
4068
  int32_t               type = pInput->pData[0]->info.type;
1,879,374✔
4069

4070
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,879,374✔
4071

4072
  if (pInput->colDataSMAIsSet) {
1,879,374!
4073
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
×
4074
    if (numOfElems == 0) {
×
4075
      goto _spread_over;
×
4076
    }
4077
    double tmin = 0.0, tmax = 0.0;
×
4078
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
×
4079
      tmin = (double)GET_INT64_VAL(&pAgg->min);
×
4080
      tmax = (double)GET_INT64_VAL(&pAgg->max);
×
4081
    } else if (IS_FLOAT_TYPE(type)) {
×
4082
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4083
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4084
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
4085
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
4086
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
4087
    }
4088

4089
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
×
4090
      SET_DOUBLE_VAL(&pInfo->min, tmin);
×
4091
    }
4092

4093
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
×
4094
      SET_DOUBLE_VAL(&pInfo->max, tmax);
×
4095
    }
4096

4097
  } else {  // computing based on the true data block
4098
    SColumnInfoData* pCol = pInput->pData[0];
1,879,374✔
4099

4100
    int32_t start = pInput->startRowIndex;
1,879,374✔
4101
    // check the valid data one by one
4102
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
11,953,528✔
4103
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
10,074,154✔
4104
        continue;
1,800,220✔
4105
      }
4106

4107
      char* data = colDataGetData(pCol, i);
8,273,934!
4108

4109
      double v = 0;
8,273,934✔
4110
      GET_TYPED_DATA(v, double, type, data);
8,273,934!
4111
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
8,273,934✔
4112
        SET_DOUBLE_VAL(&pInfo->min, v);
2,180,038✔
4113
      }
4114

4115
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
8,273,934✔
4116
        SET_DOUBLE_VAL(&pInfo->max, v);
2,568,965✔
4117
      }
4118

4119
      numOfElems += 1;
8,273,934✔
4120
    }
4121
  }
4122

4123
_spread_over:
1,879,374✔
4124
  // data in the check operation are all null, not output
4125
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
1,879,374✔
4126
  if (numOfElems > 0) {
1,879,374✔
4127
    pInfo->hasResult = true;
1,837,094✔
4128
  }
4129

4130
  return TSDB_CODE_SUCCESS;
1,879,374✔
4131
}
4132

4133
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
615,019✔
4134
  pOutput->hasResult = pInput->hasResult;
615,019✔
4135
  if (pInput->max > pOutput->max) {
615,019✔
4136
    pOutput->max = pInput->max;
610,307✔
4137
  }
4138

4139
  if (pInput->min < pOutput->min) {
615,019✔
4140
    pOutput->min = pInput->min;
610,322✔
4141
  }
4142
}
615,019✔
4143

4144
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
611,073✔
4145
  SInputColumnInfoData* pInput = &pCtx->input;
611,073✔
4146
  SColumnInfoData*      pCol = pInput->pData[0];
611,073✔
4147

4148
  if (IS_NULL_TYPE(pCol->info.type)) {
611,073!
4149
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4150
    return TSDB_CODE_SUCCESS;
×
4151
  }
4152

4153
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
611,073!
4154
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4155
  }
4156

4157
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
611,073✔
4158

4159
  int32_t start = pInput->startRowIndex;
611,073✔
4160
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,226,330✔
4161
    if (colDataIsNull_s(pCol, i)) continue;
1,230,514!
4162
    char*        data = colDataGetData(pCol, i);
615,257!
4163
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
615,257✔
4164
    if (pInputInfo->hasResult) {
615,257✔
4165
      spreadTransferInfo(pInputInfo, pInfo);
615,018✔
4166
    }
4167
  }
4168

4169
  if (pInfo->hasResult) {
611,073✔
4170
    GET_RES_INFO(pCtx)->numOfRes = 1;
610,897✔
4171
  }
4172

4173
  return TSDB_CODE_SUCCESS;
611,073✔
4174
}
4175

4176
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,828,595✔
4177
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,828,595✔
4178
  if (pInfo->hasResult == true) {
1,828,595✔
4179
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
1,786,681✔
4180
  } else {
4181
    GET_RES_INFO(pCtx)->isNullRes = 1;
41,914✔
4182
  }
4183
  return functionFinalize(pCtx, pBlock);
1,828,595✔
4184
}
4185

4186
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
615,040✔
4187
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
615,040✔
4188
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
615,040✔
4189
  int32_t              resultBytes = getSpreadInfoSize();
615,040✔
4190
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
615,040✔
4191

4192
  if (NULL == res) {
615,040!
4193
    return terrno;
×
4194
  }
4195
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
615,040✔
4196
  varDataSetLen(res, resultBytes);
615,040✔
4197

4198
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
615,040✔
4199
  int32_t          code = TSDB_CODE_SUCCESS;
615,040✔
4200
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
615,040✔
4201
  if (NULL == pCol) {
615,040!
4202
    code = terrno;
×
4203
    goto _exit;
×
4204
  }
4205

4206
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
615,040✔
4207
  if (TSDB_CODE_SUCCESS != code) {
615,038!
4208
    goto _exit;
×
4209
  }
4210

4211
_exit:
615,038✔
4212
  taosMemoryFree(res);
615,038✔
4213
  return code;
615,038✔
4214
}
4215

4216
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
4217
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
4218
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
4219

4220
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
4221
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
4222
  spreadTransferInfo(pSBuf, pDBuf);
1✔
4223
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
4224
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
4225
  return TSDB_CODE_SUCCESS;
1✔
4226
}
4227

4228
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4229

4230
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
103,770✔
4231
  pEnv->calcMemSize = sizeof(SElapsedInfo);
103,770✔
4232
  return true;
103,770✔
4233
}
4234

4235
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
10,237,176✔
4236
  if (pResultInfo->initialized) {
10,237,176!
4237
    return TSDB_CODE_SUCCESS;
×
4238
  }
4239
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
10,237,176!
4240
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4241
  }
4242

4243
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
10,237,183✔
4244
  pInfo->result = 0;
10,237,183✔
4245
  pInfo->min = TSKEY_MAX;
10,237,183✔
4246
  pInfo->max = 0;
10,237,183✔
4247

4248
  if (pCtx->numOfParams > 1) {
10,237,183✔
4249
    pInfo->timeUnit = pCtx->param[1].param.i;
10,218,325✔
4250
  } else {
4251
    pInfo->timeUnit = 1;
18,858✔
4252
  }
4253

4254
  return TSDB_CODE_SUCCESS;
10,237,183✔
4255
}
4256

4257
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
10,259,006✔
4258
  int32_t numOfElems = 0;
10,259,006✔
4259

4260
  // Only the pre-computing information loaded and actual data does not loaded
4261
  SInputColumnInfoData* pInput = &pCtx->input;
10,259,006✔
4262
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
10,259,006✔
4263

4264
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,259,006✔
4265

4266
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
10,259,006✔
4267
  if (numOfElems == 0) {
10,259,006✔
4268
    // for stream
4269
    if (pCtx->end.key != INT64_MIN) {
1,792✔
4270
      pInfo->max = pCtx->end.key + 1;
52✔
4271
    }
4272
    goto _elapsed_over;
1,792✔
4273
  }
4274

4275
  if (pInput->colDataSMAIsSet) {
10,257,214!
4276
    if (pInfo->min == TSKEY_MAX) {
×
4277
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4278
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4279
    } else {
4280
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4281
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4282
      } else {
4283
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4284
      }
4285
    }
4286
  } else {  // computing based on the true data block
4287
    if (0 == pInput->numOfRows) {
10,257,214!
4288
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4289
        if (pCtx->end.key != INT64_MIN) {
×
4290
          pInfo->min = pCtx->end.key;
×
4291
        }
4292
      } else {
4293
        if (pCtx->end.key != INT64_MIN) {
×
4294
          pInfo->max = pCtx->end.key + 1;
×
4295
        }
4296
      }
4297
      goto _elapsed_over;
×
4298
    }
4299

4300
    SColumnInfoData* pCol = pInput->pData[0];
10,257,214✔
4301

4302
    int32_t start = pInput->startRowIndex;
10,257,214✔
4303
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
10,257,214!
4304
    if (pCtx->order == TSDB_ORDER_DESC) {
10,257,214✔
4305
      if (pCtx->start.key == INT64_MIN) {
791!
4306
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
791✔
4307
      } else {
4308
        pInfo->max = pCtx->start.key + 1;
×
4309
      }
4310

4311
      if (pCtx->end.key == INT64_MIN) {
791!
4312
        pInfo->min =
791✔
4313
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
791✔
4314
      } else {
4315
        pInfo->min = pCtx->end.key;
×
4316
      }
4317
    } else {
4318
      if (pCtx->start.key == INT64_MIN) {
10,256,423✔
4319
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
4,190,636✔
4320
      } else {
4321
        pInfo->min = pCtx->start.key;
6,065,787✔
4322
      }
4323

4324
      if (pCtx->end.key == INT64_MIN) {
10,256,423✔
4325
        pInfo->max =
3,926,876✔
4326
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
3,926,876✔
4327
      } else {
4328
        pInfo->max = pCtx->end.key + 1;
6,329,547✔
4329
      }
4330
    }
4331
  }
4332

4333
_elapsed_over:
10,259,006✔
4334
  // data in the check operation are all null, not output
4335
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
10,259,006✔
4336

4337
  return TSDB_CODE_SUCCESS;
10,259,006✔
4338
}
4339

4340
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4341
  pOutput->timeUnit = pInput->timeUnit;
×
4342
  if (pOutput->min > pInput->min) {
×
4343
    pOutput->min = pInput->min;
×
4344
  }
4345

4346
  if (pOutput->max < pInput->max) {
×
4347
    pOutput->max = pInput->max;
×
4348
  }
4349
}
×
4350

4351
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4352
  SInputColumnInfoData* pInput = &pCtx->input;
×
4353
  SColumnInfoData*      pCol = pInput->pData[0];
×
4354
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4355
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4356
  }
4357

4358
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4359

4360
  int32_t start = pInput->startRowIndex;
×
4361

4362
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4363
    char*         data = colDataGetData(pCol, i);
×
4364
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4365
    elapsedTransferInfo(pInputInfo, pInfo);
×
4366
  }
4367

4368
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4369
  return TSDB_CODE_SUCCESS;
×
4370
}
4371

4372
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,211,770✔
4373
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,211,770✔
4374
  double        result = (double)pInfo->max - (double)pInfo->min;
10,211,770✔
4375
  result = (result >= 0) ? result : -result;
10,211,770✔
4376
  pInfo->result = result / pInfo->timeUnit;
10,211,770✔
4377
  return functionFinalize(pCtx, pBlock);
10,211,770✔
4378
}
4379

4380
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4381
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4382
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4383
  int32_t              resultBytes = getElapsedInfoSize();
×
4384
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4385

4386
  if (NULL == res) {
×
4387
    return terrno;
×
4388
  }
4389
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4390
  varDataSetLen(res, resultBytes);
×
4391

4392
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4393
  int32_t          code = TSDB_CODE_SUCCESS;
×
4394
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4395
  if (NULL == pCol) {
×
4396
    code = terrno;
×
4397
    goto _exit;
×
4398
  }
4399

4400
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4401
  if (TSDB_CODE_SUCCESS != code) {
×
4402
    goto _exit;
×
4403
  }
4404
_exit:
×
4405
  taosMemoryFree(res);
×
4406
  return code;
×
4407
}
4408

4409
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4410
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4411
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4412

4413
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4414
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4415

4416
  elapsedTransferInfo(pSBuf, pDBuf);
×
4417
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4418
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4419
  return TSDB_CODE_SUCCESS;
×
4420
}
4421

4422
int32_t getHistogramInfoSize() {
2,371,093✔
4423
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
2,371,093✔
4424
}
4425

4426
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
112,048✔
4427
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
112,048✔
4428
  return true;
112,048✔
4429
}
4430

4431
static int8_t getHistogramBinType(char* binTypeStr) {
8,896,817✔
4432
  int8_t binType;
4433
  if (strcasecmp(binTypeStr, "user_input") == 0) {
8,896,817✔
4434
    binType = USER_INPUT_BIN;
2,787✔
4435
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
8,894,030✔
4436
    binType = LINEAR_BIN;
1,560✔
4437
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
8,892,470!
4438
    binType = LOG_BIN;
8,892,720✔
4439
  } else {
4440
    binType = UNKNOWN_BIN;
×
4441
  }
4442

4443
  return binType;
8,896,817✔
4444
}
4445

4446
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
8,896,769✔
4447
  cJSON*  binDesc = cJSON_Parse(binDescStr);
8,896,769✔
4448
  int32_t numOfBins;
4449
  double* intervals;
4450
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
8,896,870✔
4451
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
8,894,056✔
4452
    int32_t startIndex;
4453
    if (numOfParams != 4) {
8,894,013!
4454
      cJSON_Delete(binDesc);
×
4455
      return TSDB_CODE_FAILED;
×
4456
    }
4457

4458
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
8,894,013✔
4459
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
8,894,143✔
4460
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
8,894,133✔
4461
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
8,893,411✔
4462
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
8,893,951✔
4463

4464
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
8,894,081!
4465
      cJSON_Delete(binDesc);
×
4466
      return TSDB_CODE_FAILED;
×
4467
    }
4468

4469
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
8,894,005!
4470
      cJSON_Delete(binDesc);
×
4471
      return TSDB_CODE_FAILED;
×
4472
    }
4473

4474
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
8,894,010!
4475
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
8,894,010!
4476
      cJSON_Delete(binDesc);
×
4477
      return TSDB_CODE_FAILED;
×
4478
    }
4479

4480
    int32_t counter = (int32_t)count->valueint;
8,894,010✔
4481
    if (infinity->valueint == false) {
8,894,010✔
4482
      startIndex = 0;
5,452,606✔
4483
      numOfBins = counter + 1;
5,452,606✔
4484
    } else {
4485
      startIndex = 1;
3,441,404✔
4486
      numOfBins = counter + 3;
3,441,404✔
4487
    }
4488

4489
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
8,894,010✔
4490
    if (NULL == intervals) {
8,894,208!
4491
      cJSON_Delete(binDesc);
×
4492
      qError("histogram function out of memory");
×
4493
      return terrno;
×
4494
    }
4495
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
8,894,208!
4496
      // linear bin process
4497
      if (width->valuedouble == 0) {
1,559!
4498
        taosMemoryFree(intervals);
×
4499
        cJSON_Delete(binDesc);
×
4500
        return TSDB_CODE_FAILED;
×
4501
      }
4502
      for (int i = 0; i < counter + 1; ++i) {
19,599✔
4503
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
18,040✔
4504
        if (isinf(intervals[startIndex])) {
18,040!
4505
          taosMemoryFree(intervals);
×
4506
          cJSON_Delete(binDesc);
×
4507
          return TSDB_CODE_FAILED;
×
4508
        }
4509
        startIndex++;
18,040✔
4510
      }
4511
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
8,892,646!
4512
      // log bin process
4513
      if (start->valuedouble == 0) {
8,892,631!
4514
        taosMemoryFree(intervals);
×
4515
        cJSON_Delete(binDesc);
×
4516
        return TSDB_CODE_FAILED;
×
4517
      }
4518
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
8,892,631!
4519
        taosMemoryFree(intervals);
×
4520
        cJSON_Delete(binDesc);
×
4521
        return TSDB_CODE_FAILED;
×
4522
      }
4523
      for (int i = 0; i < counter + 1; ++i) {
62,242,094✔
4524
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
53,349,459✔
4525
        if (isinf(intervals[startIndex])) {
53,349,459!
4526
          taosMemoryFree(intervals);
×
4527
          cJSON_Delete(binDesc);
×
4528
          return TSDB_CODE_FAILED;
×
4529
        }
4530
        startIndex++;
53,349,459✔
4531
      }
4532
    } else {
4533
      taosMemoryFree(intervals);
×
4534
      cJSON_Delete(binDesc);
×
4535
      return TSDB_CODE_FAILED;
×
4536
    }
4537

4538
    if (infinity->valueint == true) {
8,894,194✔
4539
      intervals[0] = -INFINITY;
3,441,777✔
4540
      intervals[numOfBins - 1] = INFINITY;
3,441,777✔
4541
      // in case of desc bin orders, -inf/inf should be swapped
4542
      if (numOfBins < 4) {
3,441,777!
4543
        return TSDB_CODE_FAILED;
×
4544
      }
4545
      if (intervals[1] > intervals[numOfBins - 2]) {
3,441,777✔
4546
        TSWAP(intervals[0], intervals[numOfBins - 1]);
3,440,949✔
4547
      }
4548
    }
4549
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
2,789!
4550
    if (binType != USER_INPUT_BIN) {
2,788!
4551
      cJSON_Delete(binDesc);
×
4552
      return TSDB_CODE_FAILED;
×
4553
    }
4554
    numOfBins = cJSON_GetArraySize(binDesc);
2,788✔
4555
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
2,790✔
4556
    if (NULL == intervals) {
2,788!
4557
      cJSON_Delete(binDesc);
×
4558
      qError("histogram function out of memory");
×
4559
      return terrno;
×
4560
    }
4561
    cJSON* bin = binDesc->child;
2,788✔
4562
    if (bin == NULL) {
2,788!
4563
      taosMemoryFree(intervals);
×
4564
      cJSON_Delete(binDesc);
×
4565
      return TSDB_CODE_FAILED;
×
4566
    }
4567
    int i = 0;
2,788✔
4568
    while (bin) {
11,986✔
4569
      intervals[i] = bin->valuedouble;
9,198✔
4570
      if (!cJSON_IsNumber(bin)) {
9,198!
4571
        taosMemoryFree(intervals);
×
4572
        cJSON_Delete(binDesc);
×
4573
        return TSDB_CODE_FAILED;
×
4574
      }
4575
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
9,198!
4576
        taosMemoryFree(intervals);
×
4577
        cJSON_Delete(binDesc);
×
4578
        return TSDB_CODE_FAILED;
×
4579
      }
4580
      bin = bin->next;
9,198✔
4581
      i++;
9,198✔
4582
    }
4583
  } else {
4584
    cJSON_Delete(binDesc);
×
4585
    return TSDB_CODE_FAILED;
×
4586
  }
4587

4588
  pInfo->numOfBins = numOfBins - 1;
8,896,982✔
4589
  pInfo->normalized = normalized;
8,896,982✔
4590
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
60,262,844✔
4591
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
51,365,862✔
4592
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
51,365,862✔
4593
    pInfo->bins[i].count = 0;
51,365,862✔
4594
  }
4595

4596
  taosMemoryFree(intervals);
8,896,982✔
4597
  cJSON_Delete(binDesc);
8,896,858✔
4598

4599
  return TSDB_CODE_SUCCESS;
8,896,815✔
4600
}
4601

4602
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,896,834✔
4603
  if (pResultInfo->initialized) {
8,896,834!
4604
    return TSDB_CODE_SUCCESS;
×
4605
  }
4606
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,896,834!
4607
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4608
  }
4609

4610
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
8,896,811✔
4611
  pInfo->numOfBins = 0;
8,896,811✔
4612
  pInfo->totalCount = 0;
8,896,811✔
4613
  pInfo->normalized = 0;
8,896,811✔
4614

4615
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
8,896,811✔
4616
  if (binTypeStr == NULL) {
8,896,827!
4617
    return terrno;
×
4618
  }
4619
  int8_t binType = getHistogramBinType(binTypeStr);
8,896,827✔
4620
  taosMemoryFree(binTypeStr);
8,896,961✔
4621

4622
  if (binType == UNKNOWN_BIN) {
8,896,811!
4623
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4624
  }
4625
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
8,896,811✔
4626
  if (binDesc == NULL) {
8,896,770!
4627
    return terrno;
×
4628
  }
4629
  int64_t normalized = pCtx->param[3].param.i;
8,896,770✔
4630
  if (normalized != 0 && normalized != 1) {
8,896,770!
4631
    taosMemoryFree(binDesc);
×
4632
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4633
  }
4634
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
8,896,770✔
4635
  if (TSDB_CODE_SUCCESS != code) {
8,896,812!
4636
    taosMemoryFree(binDesc);
×
4637
    return code;
×
4638
  }
4639
  taosMemoryFree(binDesc);
8,896,812✔
4640

4641
  return TSDB_CODE_SUCCESS;
8,896,956✔
4642
}
4643

4644
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
8,914,888✔
4645
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,914,888✔
4646

4647
  SInputColumnInfoData* pInput = &pCtx->input;
8,914,888✔
4648
  SColumnInfoData*      pCol = pInput->pData[0];
8,914,888✔
4649

4650
  int32_t type = pInput->pData[0]->info.type;
8,914,888✔
4651

4652
  int32_t start = pInput->startRowIndex;
8,914,888✔
4653
  int32_t numOfRows = pInput->numOfRows;
8,914,888✔
4654

4655
  int32_t numOfElems = 0;
8,914,888✔
4656
  for (int32_t i = start; i < numOfRows + start; ++i) {
29,012,888✔
4657
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
20,098,000✔
4658
      continue;
689,547✔
4659
    }
4660

4661
    numOfElems++;
19,408,453✔
4662

4663
    char*  data = colDataGetData(pCol, i);
19,408,453!
4664
    double v;
4665
    GET_TYPED_DATA(v, double, type, data);
19,408,453!
4666

4667
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
69,330,271✔
4668
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
60,911,699✔
4669
        pInfo->bins[k].count++;
10,989,881✔
4670
        pInfo->totalCount++;
10,989,881✔
4671
        break;
10,989,881✔
4672
      }
4673
    }
4674
  }
4675

4676
  if (!isPartial) {
8,914,888✔
4677
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
6,532,339✔
4678
  } else {
4679
    GET_RES_INFO(pCtx)->numOfRes = 1;
2,382,549✔
4680
  }
4681
  return TSDB_CODE_SUCCESS;
8,914,888✔
4682
}
4683

4684
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
6,532,370✔
4685

4686
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
2,382,631✔
4687

4688
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
2,326,920✔
4689
  pOutput->normalized = pInput->normalized;
2,326,920✔
4690
  pOutput->numOfBins = pInput->numOfBins;
2,326,920✔
4691
  pOutput->totalCount += pInput->totalCount;
2,326,920✔
4692
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
13,974,843✔
4693
    pOutput->bins[k].lower = pInput->bins[k].lower;
11,647,923✔
4694
    pOutput->bins[k].upper = pInput->bins[k].upper;
11,647,923✔
4695
    pOutput->bins[k].count += pInput->bins[k].count;
11,647,923✔
4696
  }
4697
}
2,326,920✔
4698

4699
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
2,326,920✔
4700
  SInputColumnInfoData* pInput = &pCtx->input;
2,326,920✔
4701
  SColumnInfoData*      pCol = pInput->pData[0];
2,326,920✔
4702
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
2,326,920!
4703
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4704
  }
4705

4706
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,326,920✔
4707

4708
  int32_t start = pInput->startRowIndex;
2,326,920✔
4709

4710
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
4,653,840✔
4711
    char*           data = colDataGetData(pCol, i);
2,326,920!
4712
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
2,326,920✔
4713
    histogramTransferInfo(pInputInfo, pInfo);
2,326,920✔
4714
  }
4715

4716
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
2,326,920!
4717
  return TSDB_CODE_SUCCESS;
2,326,920✔
4718
}
4719

4720
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,790,192✔
4721
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,790,192✔
4722
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,790,192✔
4723
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
8,790,192✔
4724
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,790,192✔
4725
  int32_t              code = TSDB_CODE_SUCCESS;
8,790,047✔
4726

4727
  int32_t currentRow = pBlock->info.rows;
8,790,047✔
4728
  if (NULL == pCol) {
8,790,047!
4729
    return TSDB_CODE_OUT_OF_RANGE;
×
4730
  }
4731

4732
  if (pInfo->normalized) {
8,790,047✔
4733
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
59,477,171✔
4734
      if (pInfo->totalCount != 0) {
50,694,992✔
4735
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
32,644,041✔
4736
      } else {
4737
        pInfo->bins[k].percentage = 0;
18,050,951✔
4738
      }
4739
    }
4740
  }
4741

4742
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
59,500,504✔
4743
    int32_t len;
4744
    char    buf[512] = {0};
50,736,314✔
4745
    if (!pInfo->normalized) {
50,736,314✔
4746
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
45,217✔
4747
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
4748
                      pInfo->bins[i].upper, pInfo->bins[i].count);
4749
    } else {
4750
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
50,691,097✔
4751
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
4752
                      pInfo->bins[i].percentage);
4753
    }
4754
    varDataSetLen(buf, len);
50,735,239✔
4755
    code = colDataSetVal(pCol, currentRow, buf, false);
50,735,239✔
4756
    if (TSDB_CODE_SUCCESS != code) {
50,710,457!
4757
      return code;
×
4758
    }
4759
    currentRow++;
50,710,457✔
4760
  }
4761

4762
  return code;
8,764,190✔
4763
}
4764

4765
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,364,576✔
4766
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,364,576✔
4767
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,364,576✔
4768
  int32_t              resultBytes = getHistogramInfoSize();
2,364,576✔
4769
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
2,364,576✔
4770

4771
  if (NULL == res) {
2,364,578!
4772
    return terrno;
×
4773
  }
4774
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
2,364,578✔
4775
  varDataSetLen(res, resultBytes);
2,364,578✔
4776

4777
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,364,578✔
4778
  int32_t          code = TSDB_CODE_SUCCESS;
2,364,578✔
4779
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,364,578✔
4780
  if (NULL == pCol) {
2,364,578!
4781
    code = terrno;
×
4782
    goto _exit;
×
4783
  }
4784
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
2,364,578✔
4785

4786
_exit:
2,364,576✔
4787
  taosMemoryFree(res);
2,364,576✔
4788
  return code;
2,364,580✔
4789
}
4790

4791
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4792
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4793
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4794

4795
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4796
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4797

4798
  histogramTransferInfo(pSBuf, pDBuf);
×
4799
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4800
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4801
  return TSDB_CODE_SUCCESS;
×
4802
}
4803

4804
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,691✔
4805

4806
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
65,744✔
4807
  pEnv->calcMemSize = sizeof(SHLLInfo);
65,744✔
4808
  return true;
65,744✔
4809
}
4810

4811
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
3,498,578✔
4812
  uint64_t hash = MurmurHash3_64(data, bytes);
3,498,578✔
4813
  int32_t  index = hash & HLL_BUCKET_MASK;
3,497,866✔
4814
  hash >>= HLL_BUCKET_BITS;
3,497,866✔
4815
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
3,497,866✔
4816
  uint64_t bit = 1;
3,497,866✔
4817
  uint8_t  count = 1;
3,497,866✔
4818
  while ((hash & bit) == 0) {
6,539,994✔
4819
    count++;
3,042,128✔
4820
    bit <<= 1;
3,042,128✔
4821
  }
4822
  *buk = index;
3,497,866✔
4823
  return count;
3,497,866✔
4824
}
4825

4826
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
244,401✔
4827
  uint64_t* word = (uint64_t*)buckets;
244,401✔
4828
  uint8_t*  bytes;
4829

4830
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
493,047,766✔
4831
    if (*word == 0) {
492,803,365✔
4832
      bucketHisto[0] += 8;
491,990,644✔
4833
    } else {
4834
      bytes = (uint8_t*)word;
812,721✔
4835
      bucketHisto[bytes[0]]++;
812,721✔
4836
      bucketHisto[bytes[1]]++;
812,721✔
4837
      bucketHisto[bytes[2]]++;
812,721✔
4838
      bucketHisto[bytes[3]]++;
812,721✔
4839
      bucketHisto[bytes[4]]++;
812,721✔
4840
      bucketHisto[bytes[5]]++;
812,721✔
4841
      bucketHisto[bytes[6]]++;
812,721✔
4842
      bucketHisto[bytes[7]]++;
812,721✔
4843
    }
4844
    word++;
492,803,365✔
4845
  }
4846
}
244,401✔
4847
static double hllTau(double x) {
244,401✔
4848
  if (x == 0. || x == 1.) return 0.;
244,401!
4849
  double zPrime;
4850
  double y = 1.0;
×
4851
  double z = 1 - x;
×
4852
  do {
4853
    x = sqrt(x);
×
4854
    zPrime = z;
×
4855
    y *= 0.5;
×
4856
    z -= pow(1 - x, 2) * y;
×
4857
  } while (zPrime != z);
×
4858
  return z / 3;
×
4859
}
4860

4861
static double hllSigma(double x) {
244,420✔
4862
  if (x == 1.0) return INFINITY;
244,420✔
4863
  double zPrime;
4864
  double y = 1;
211,030✔
4865
  double z = x;
211,030✔
4866
  do {
4867
    x *= x;
4,133,688✔
4868
    zPrime = z;
4,133,688✔
4869
    z += x * y;
4,133,688✔
4870
    y += y;
4,133,688✔
4871
  } while (zPrime != z);
4,133,688✔
4872
  return z;
211,030✔
4873
}
4874

4875
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
4876
// sketches"
4877
static uint64_t hllCountCnt(uint8_t* buckets) {
244,373✔
4878
  double  m = HLL_BUCKETS;
244,373✔
4879
  int32_t buckethisto[64] = {0};
244,373✔
4880
  hllBucketHisto(buckets, buckethisto);
244,373✔
4881

4882
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
244,401✔
4883
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
12,461,117✔
4884
    z += buckethisto[j];
12,216,696✔
4885
    z *= 0.5;
12,216,696✔
4886
  }
4887

4888
  z += m * hllSigma(buckethisto[0] / (double)m);
244,421✔
4889
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
244,421✔
4890

4891
  return (uint64_t)E;
244,421✔
4892
}
4893

4894
int32_t hllFunction(SqlFunctionCtx* pCtx) {
269,159✔
4895
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
269,159✔
4896

4897
  SInputColumnInfoData* pInput = &pCtx->input;
269,159✔
4898
  SColumnInfoData*      pCol = pInput->pData[0];
269,159✔
4899

4900
  int32_t type = pCol->info.type;
269,159✔
4901
  int32_t bytes = pCol->info.bytes;
269,159✔
4902

4903
  int32_t start = pInput->startRowIndex;
269,159✔
4904
  int32_t numOfRows = pInput->numOfRows;
269,159✔
4905

4906
  int32_t numOfElems = 0;
269,159✔
4907
  if (IS_NULL_TYPE(type)) {
269,159✔
4908
    goto _hll_over;
1,707✔
4909
  }
4910

4911
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,848,556✔
4912
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
6,371,727!
4913
      continue;
1,081,708✔
4914
    }
4915

4916
    numOfElems++;
3,500,098✔
4917

4918
    char* data = colDataGetData(pCol, i);
3,500,098!
4919
    if (IS_VAR_DATA_TYPE(type)) {
3,500,098!
4920
      bytes = varDataLen(data);
987,422✔
4921
      data = varDataVal(data);
987,422✔
4922
    }
4923

4924
    int32_t index = 0;
3,500,098✔
4925
    uint8_t count = hllCountNum(data, bytes, &index);
3,500,098✔
4926
    uint8_t oldcount = pInfo->buckets[index];
3,499,396✔
4927
    if (count > oldcount) {
3,499,396✔
4928
      pInfo->buckets[index] = count;
832,926✔
4929
    }
4930
  }
4931

4932
_hll_over:
266,750✔
4933
  pInfo->totalCount += numOfElems;
268,457✔
4934

4935
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
268,457✔
4936
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
957✔
4937
  } else {
4938
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
267,500✔
4939
  }
4940

4941
  return TSDB_CODE_SUCCESS;
268,457✔
4942
}
4943

4944
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
10,975✔
4945
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
175,736,492✔
4946
    if (pOutput->buckets[k] < pInput->buckets[k]) {
175,725,517✔
4947
      pOutput->buckets[k] = pInput->buckets[k];
136,616✔
4948
    }
4949
  }
4950
  pOutput->totalCount += pInput->totalCount;
10,975✔
4951
}
10,975✔
4952

4953
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
10,918✔
4954
  SInputColumnInfoData* pInput = &pCtx->input;
10,918✔
4955
  SColumnInfoData*      pCol = pInput->pData[0];
10,918✔
4956

4957
  if (IS_NULL_TYPE(pCol->info.type)) {
10,918!
4958
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4959
    return TSDB_CODE_SUCCESS;
×
4960
  }
4961

4962
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
10,918!
4963
    return TSDB_CODE_SUCCESS;
×
4964
  }
4965

4966
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,918✔
4967

4968
  int32_t start = pInput->startRowIndex;
10,918✔
4969

4970
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
21,895✔
4971
    if (colDataIsNull_s(pCol, i)) continue;
21,948!
4972
    char*     data = colDataGetData(pCol, i);
10,974!
4973
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
10,974✔
4974
    hllTransferInfo(pInputInfo, pInfo);
10,974✔
4975
  }
4976

4977
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,921✔
4978
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
5✔
4979
  } else {
4980
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,916✔
4981
  }
4982

4983
  return TSDB_CODE_SUCCESS;
10,921✔
4984
}
4985

4986
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
244,374✔
4987
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
244,374✔
4988

4989
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
244,374✔
4990
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
244,374✔
4991
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
244,422✔
4992
    pInfo->numOfRes = 1;
32,470✔
4993
  }
4994

4995
  return functionFinalize(pCtx, pBlock);
244,422✔
4996
}
4997

4998
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,691✔
4999
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,691✔
5000
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,691✔
5001
  int32_t              resultBytes = getHLLInfoSize();
10,691✔
5002
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
10,691✔
5003

5004
  if (NULL == res) {
10,689!
5005
    return terrno;
×
5006
  }
5007
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
10,689✔
5008
  varDataSetLen(res, resultBytes);
10,689✔
5009

5010
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
10,689✔
5011
  int32_t          code = TSDB_CODE_SUCCESS;
10,689✔
5012
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
10,689✔
5013
  if (NULL == pCol) {
10,691!
5014
    code = terrno;
×
5015
    goto _exit;
×
5016
  }
5017

5018
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
10,691✔
5019

5020
_exit:
10,690✔
5021
  taosMemoryFree(res);
10,690✔
5022
  return code;
10,691✔
5023
}
5024

5025
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
5026
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
5027
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
5028

5029
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
5030
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
5031

5032
  hllTransferInfo(pSBuf, pDBuf);
1✔
5033
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
5034
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
5035
  return TSDB_CODE_SUCCESS;
1✔
5036
}
5037

5038
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,572✔
5039
  pEnv->calcMemSize = sizeof(SStateInfo);
22,572✔
5040
  return true;
22,572✔
5041
}
5042

5043
static int8_t getStateOpType(char* opStr) {
41,031✔
5044
  int8_t opType;
5045
  if (strncasecmp(opStr, "LT", 2) == 0) {
41,031✔
5046
    opType = STATE_OPER_LT;
7,100✔
5047
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
33,931✔
5048
    opType = STATE_OPER_GT;
3,250✔
5049
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
30,681✔
5050
    opType = STATE_OPER_LE;
992✔
5051
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
29,689✔
5052
    opType = STATE_OPER_GE;
1,086✔
5053
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
28,603✔
5054
    opType = STATE_OPER_NE;
25,816✔
5055
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
2,787!
5056
    opType = STATE_OPER_EQ;
2,787✔
5057
  } else {
5058
    opType = STATE_OPER_INVALID;
×
5059
  }
5060

5061
  return opType;
41,031✔
5062
}
5063

5064
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
35,124,939✔
5065
  char* data = colDataGetData(pCol, index);
35,124,939!
5066
  switch (pCol->info.type) {
35,124,939!
5067
    case TSDB_DATA_TYPE_TINYINT: {
6,994,264✔
5068
      int8_t v = *(int8_t*)data;
6,994,264✔
5069
      STATE_COMP(op, v, param);
6,994,264!
5070
      break;
×
5071
    }
5072
    case TSDB_DATA_TYPE_UTINYINT: {
5,760✔
5073
      uint8_t v = *(uint8_t*)data;
5,760✔
5074
      STATE_COMP(op, v, param);
5,760!
5075
      break;
×
5076
    }
5077
    case TSDB_DATA_TYPE_SMALLINT: {
14,012✔
5078
      int16_t v = *(int16_t*)data;
14,012✔
5079
      STATE_COMP(op, v, param);
14,012!
5080
      break;
×
5081
    }
5082
    case TSDB_DATA_TYPE_USMALLINT: {
5,760✔
5083
      uint16_t v = *(uint16_t*)data;
5,760✔
5084
      STATE_COMP(op, v, param);
5,760!
5085
      break;
×
5086
    }
5087
    case TSDB_DATA_TYPE_INT: {
114,524✔
5088
      int32_t v = *(int32_t*)data;
114,524✔
5089
      STATE_COMP(op, v, param);
114,524!
5090
      break;
×
5091
    }
5092
    case TSDB_DATA_TYPE_UINT: {
5,760✔
5093
      uint32_t v = *(uint32_t*)data;
5,760✔
5094
      STATE_COMP(op, v, param);
5,760!
5095
      break;
×
5096
    }
5097
    case TSDB_DATA_TYPE_BIGINT: {
95,868✔
5098
      int64_t v = *(int64_t*)data;
95,868✔
5099
      STATE_COMP(op, v, param);
95,868!
5100
      break;
×
5101
    }
5102
    case TSDB_DATA_TYPE_UBIGINT: {
5,760✔
5103
      uint64_t v = *(uint64_t*)data;
5,760✔
5104
      STATE_COMP(op, v, param);
5,760!
5105
      break;
×
5106
    }
5107
    case TSDB_DATA_TYPE_FLOAT: {
173,212✔
5108
      float v = *(float*)data;
173,212✔
5109
      STATE_COMP(op, v, param);
173,212!
5110
      break;
×
5111
    }
5112
    case TSDB_DATA_TYPE_DOUBLE: {
27,711,228✔
5113
      double v = *(double*)data;
27,711,228✔
5114
      STATE_COMP(op, v, param);
27,711,228!
5115
      break;
×
5116
    }
5117
    default: {
×
5118
      return false;
×
5119
    }
5120
  }
5121
  return false;
×
5122
}
5123

5124
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
1,931✔
5125
  int32_t              code = TSDB_CODE_SUCCESS;
1,931✔
5126
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,931✔
5127
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,931✔
5128

5129
  SInputColumnInfoData* pInput = &pCtx->input;
1,931✔
5130
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,931✔
5131

5132
  SColumnInfoData* pInputCol = pInput->pData[0];
1,931✔
5133

5134
  int32_t          numOfElems = 0;
1,931✔
5135
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,931✔
5136

5137
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
1,931✔
5138
  if (STATE_OPER_INVALID == op) {
1,931!
5139
    return 0;
×
5140
  }
5141

5142
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
332,067✔
5143
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
330,136!
5144
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5145
    } else {
5146
      pInfo->prevTs = tsList[i];
330,136✔
5147
    }
5148

5149
    pInfo->isPrevTsSet = true;
330,136✔
5150
    numOfElems++;
330,136✔
5151

5152
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
330,136✔
5153
      colDataSetNULL(pOutput, i);
154,124!
5154
      // handle selectivity
5155
      if (pCtx->subsidiaries.num > 0) {
154,124✔
5156
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
44✔
5157
        if (TSDB_CODE_SUCCESS != code) {
44!
5158
          return code;
×
5159
        }
5160
      }
5161
      continue;
154,124✔
5162
    }
5163

5164
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
176,012✔
5165

5166
    int64_t output = -1;
176,012✔
5167
    if (ret) {
176,012✔
5168
      output = ++pInfo->count;
31,076✔
5169
    } else {
5170
      pInfo->count = 0;
144,936✔
5171
    }
5172
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
176,012✔
5173
    if (TSDB_CODE_SUCCESS != code) {
176,012!
5174
      return code;
×
5175
    }
5176

5177
    // handle selectivity
5178
    if (pCtx->subsidiaries.num > 0) {
176,012✔
5179
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
528✔
5180
      if (TSDB_CODE_SUCCESS != code) {
528!
5181
        return code;
×
5182
      }
5183
    }
5184
  }
5185

5186
  pResInfo->numOfRes = numOfElems;
1,931✔
5187
  return TSDB_CODE_SUCCESS;
1,931✔
5188
}
5189

5190
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
39,100✔
5191
  int32_t              code = TSDB_CODE_SUCCESS;
39,100✔
5192
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
39,100✔
5193
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
39,100✔
5194

5195
  SInputColumnInfoData* pInput = &pCtx->input;
39,100✔
5196
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
39,100✔
5197

5198
  SColumnInfoData* pInputCol = pInput->pData[0];
39,100✔
5199

5200
  int32_t          numOfElems = 0;
39,100✔
5201
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
39,100✔
5202

5203
  // TODO: process timeUnit for different db precisions
5204
  int32_t timeUnit = 1;
39,100✔
5205
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
39,100✔
5206
    timeUnit = pCtx->param[3].param.i;
37,140✔
5207
  }
5208

5209
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
39,100✔
5210
  if (STATE_OPER_INVALID == op) {
39,100!
5211
    return TSDB_CODE_INVALID_PARA;
×
5212
  }
5213

5214
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
35,195,041✔
5215
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
35,155,937!
5216
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5217
    } else {
5218
      pInfo->prevTs = tsList[i];
35,155,937✔
5219
    }
5220

5221
    pInfo->isPrevTsSet = true;
35,155,937✔
5222
    numOfElems++;
35,155,937✔
5223

5224
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
35,155,937✔
5225
      colDataSetNULL(pOutput, i);
206,884!
5226
      // handle selectivity
5227
      if (pCtx->subsidiaries.num > 0) {
206,884✔
5228
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
60✔
5229
        if (TSDB_CODE_SUCCESS != code) {
60!
5230
          return code;
×
5231
        }
5232
      }
5233
      continue;
206,884✔
5234
    }
5235

5236
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
34,949,053✔
5237
    int64_t output = -1;
34,948,996✔
5238
    if (ret) {
34,948,996✔
5239
      if (pInfo->durationStart == 0) {
34,798,512✔
5240
        output = 0;
79,500✔
5241
        pInfo->durationStart = tsList[i];
79,500✔
5242
      } else {
5243
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
34,719,012✔
5244
      }
5245
    } else {
5246
      pInfo->durationStart = 0;
150,484✔
5247
    }
5248
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
34,948,996✔
5249
    if (TSDB_CODE_SUCCESS != code) {
34,949,057!
5250
      return code;
×
5251
    }
5252

5253
    // handle selectivity
5254
    if (pCtx->subsidiaries.num > 0) {
34,949,057✔
5255
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
20,092,778✔
5256
      if (TSDB_CODE_SUCCESS != code) {
20,092,778!
5257
        return code;
×
5258
      }
5259
    }
5260
  }
5261

5262
  pResInfo->numOfRes = numOfElems;
39,104✔
5263
  return TSDB_CODE_SUCCESS;
39,104✔
5264
}
5265

5266
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
15,650✔
5267
  pEnv->calcMemSize = sizeof(SSumRes);
15,650✔
5268
  return true;
15,650✔
5269
}
5270

5271
int32_t csumFunction(SqlFunctionCtx* pCtx) {
18,590✔
5272
  int32_t              code = TSDB_CODE_SUCCESS;
18,590✔
5273
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
18,590✔
5274
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
18,590✔
5275

5276
  SInputColumnInfoData* pInput = &pCtx->input;
18,590✔
5277
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
18,590✔
5278

5279
  SColumnInfoData* pInputCol = pInput->pData[0];
18,590✔
5280
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
18,590✔
5281

5282
  int32_t numOfElems = 0;
18,590✔
5283
  int32_t type = pInputCol->info.type;
18,590✔
5284
  int32_t startOffset = pCtx->offset;
18,590✔
5285
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4,000,022✔
5286
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,981,305✔
5287
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5288
    } else {
5289
      pSumRes->prevTs = tsList[i];
3,981,287✔
5290
    }
5291
    pSumRes->isPrevTsSet = true;
3,981,287✔
5292

5293
    int32_t pos = startOffset + numOfElems;
3,981,287✔
5294
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,981,287✔
5295
      // colDataSetNULL(pOutput, i);
5296
      continue;
455,872✔
5297
    }
5298

5299
    char* data = colDataGetData(pInputCol, i);
3,525,415!
5300
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
6,667,549!
5301
      int64_t v;
5302
      GET_TYPED_DATA(v, int64_t, type, data);
3,141,989!
5303
      pSumRes->isum += v;
3,141,989✔
5304
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
3,141,989✔
5305
      if (TSDB_CODE_SUCCESS != code) {
3,142,134!
5306
        return code;
×
5307
      }
5308
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
384,106!
5309
      uint64_t v;
5310
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5311
      pSumRes->usum += v;
680✔
5312
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5313
      if (TSDB_CODE_SUCCESS != code) {
680!
5314
        return code;
×
5315
      }
5316
    } else if (IS_FLOAT_TYPE(type)) {
382,746!
5317
      double v;
5318
      GET_TYPED_DATA(v, double, type, data);
382,754!
5319
      pSumRes->dsum += v;
382,754✔
5320
      // check for overflow
5321
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
382,754!
5322
        colDataSetNULL(pOutput, pos);
8!
5323
      } else {
5324
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
382,746✔
5325
        if (TSDB_CODE_SUCCESS != code) {
382,746!
5326
          return code;
×
5327
        }
5328
      }
5329
    }
5330

5331
    // handle selectivity
5332
    if (pCtx->subsidiaries.num > 0) {
3,525,560✔
5333
      code = appendSelectivityValue(pCtx, i, pos);
2,005,422✔
5334
      if (TSDB_CODE_SUCCESS != code) {
2,005,422!
5335
        return code;
×
5336
      }
5337
    }
5338

5339
    numOfElems++;
3,525,560✔
5340
  }
5341

5342
  pResInfo->numOfRes = numOfElems;
18,717✔
5343
  return TSDB_CODE_SUCCESS;
18,717✔
5344
}
5345

5346
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
13,730✔
5347
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
13,730✔
5348
  return true;
13,730✔
5349
}
5350

5351
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
259,482✔
5352
  if (pResultInfo->initialized) {
259,482✔
5353
    return TSDB_CODE_SUCCESS;
244,745✔
5354
  }
5355
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,737!
5356
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5357
  }
5358

5359
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
14,737✔
5360
  pInfo->pos = 0;
14,737✔
5361
  pInfo->sum = 0;
14,737✔
5362
  pInfo->prevTs = -1;
14,737✔
5363
  pInfo->isPrevTsSet = false;
14,737✔
5364
  pInfo->numOfPoints = pCtx->param[1].param.i;
14,737✔
5365
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
14,737!
5366
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5367
  }
5368
  pInfo->pointsMeet = false;
14,738✔
5369

5370
  return TSDB_CODE_SUCCESS;
14,738✔
5371
}
5372

5373
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
245,751✔
5374
  int32_t              code = TSDB_CODE_SUCCESS;
245,751✔
5375
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
245,751✔
5376
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
245,751✔
5377

5378
  SInputColumnInfoData* pInput = &pCtx->input;
245,751✔
5379
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
245,751✔
5380

5381
  SColumnInfoData* pInputCol = pInput->pData[0];
245,751✔
5382
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
245,751✔
5383
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
245,751✔
5384

5385
  int32_t numOfElems = 0;
245,751✔
5386
  int32_t type = pInputCol->info.type;
245,751✔
5387
  int32_t startOffset = pCtx->offset;
245,751✔
5388
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
59,336,661✔
5389
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
59,090,910!
5390
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5391
    } else {
5392
      pInfo->prevTs = tsList[i];
59,090,910✔
5393
    }
5394
    pInfo->isPrevTsSet = true;
59,090,910✔
5395

5396
    int32_t pos = startOffset + numOfElems;
59,090,910✔
5397
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
59,090,910✔
5398
      // colDataSetNULL(pOutput, i);
5399
      continue;
311,125✔
5400
    }
5401

5402
    char*  data = colDataGetData(pInputCol, i);
58,779,785!
5403
    double v;
5404
    GET_TYPED_DATA(v, double, type, data);
58,779,785!
5405

5406
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
58,779,785✔
5407
      pInfo->points[pInfo->pos] = v;
5,286,301✔
5408
      pInfo->sum += v;
5,286,301✔
5409
    } else {
5410
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
53,493,484!
5411
        pInfo->sum += v;
10,740✔
5412
        pInfo->pointsMeet = true;
10,740✔
5413
      } else {
5414
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
53,482,744✔
5415
      }
5416

5417
      pInfo->points[pInfo->pos] = v;
53,493,484✔
5418
      double result = pInfo->sum / pInfo->numOfPoints;
53,493,484✔
5419
      // check for overflow
5420
      if (isinf(result) || isnan(result)) {
53,493,484!
5421
        colDataSetNULL(pOutput, pos);
1!
5422
      } else {
5423
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
53,493,483✔
5424
        if (TSDB_CODE_SUCCESS != code) {
53,493,483!
5425
          return code;
×
5426
        }
5427
      }
5428

5429
      // handle selectivity
5430
      if (pCtx->subsidiaries.num > 0) {
53,493,484✔
5431
        code = appendSelectivityValue(pCtx, i, pos);
33,751,443✔
5432
        if (TSDB_CODE_SUCCESS != code) {
33,751,443!
5433
          return code;
×
5434
        }
5435
      }
5436

5437
      numOfElems++;
53,493,484✔
5438
    }
5439

5440
    pInfo->pos++;
58,779,785✔
5441
    if (pInfo->pos == pInfo->numOfPoints) {
58,779,785✔
5442
      pInfo->pos = 0;
148,964✔
5443
    }
5444
  }
5445

5446
  pResInfo->numOfRes = numOfElems;
245,751✔
5447
  return TSDB_CODE_SUCCESS;
245,751✔
5448
}
5449

5450
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
15,407,642✔
5451
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
15,407,642✔
5452
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
15,407,642✔
5453

5454
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
15,407,642✔
5455
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
15,407,642✔
5456

5457
  return pInfo;
15,407,642✔
5458
}
5459

5460
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
30,756✔
5461
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
30,756✔
5462
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
30,764✔
5463
  int32_t      numOfSamples = pVal->datum.i;
30,767✔
5464
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
30,767✔
5465
  return true;
30,767✔
5466
}
5467

5468
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,743,576✔
5469
  if (pResultInfo->initialized) {
7,743,576!
5470
    return TSDB_CODE_SUCCESS;
×
5471
  }
5472
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,743,576!
5473
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5474
  }
5475

5476
  taosSeedRand(taosSafeRand());
7,743,577✔
5477

5478
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
7,743,581✔
5479
  pInfo->samples = pCtx->param[1].param.i;
7,743,581✔
5480
  pInfo->totalPoints = 0;
7,743,581✔
5481
  pInfo->numSampled = 0;
7,743,581✔
5482
  pInfo->colType = pCtx->resDataInfo.type;
7,743,581✔
5483
  pInfo->colBytes = pCtx->resDataInfo.bytes;
7,743,581✔
5484
  pInfo->nullTuplePos.pageId = -1;
7,743,581✔
5485
  pInfo->nullTupleSaved = false;
7,743,581✔
5486
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
7,743,581✔
5487
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
7,743,581✔
5488

5489
  return TSDB_CODE_SUCCESS;
7,743,581✔
5490
}
5491

5492
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
15,058,342✔
5493
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
15,058,342✔
5494
}
15,058,419✔
5495

5496
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
17,131,595✔
5497
  pInfo->totalPoints++;
17,131,595✔
5498
  if (pInfo->numSampled < pInfo->samples) {
17,131,595✔
5499
    sampleAssignResult(pInfo, data, pInfo->numSampled);
13,365,993✔
5500
    if (pCtx->subsidiaries.num > 0) {
13,365,982✔
5501
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,487,378✔
5502
      if (code != TSDB_CODE_SUCCESS) {
1,487,405!
5503
        return code;
×
5504
      }
5505
    }
5506
    pInfo->numSampled++;
13,366,009✔
5507
  } else {
5508
    int32_t j = taosRand() % (pInfo->totalPoints);
3,765,602✔
5509
    if (j < pInfo->samples) {
3,767,847✔
5510
      sampleAssignResult(pInfo, data, j);
1,693,706✔
5511
      if (pCtx->subsidiaries.num > 0) {
1,693,693✔
5512
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
807,024✔
5513
        if (code != TSDB_CODE_SUCCESS) {
805,063!
5514
          return code;
×
5515
        }
5516
      }
5517
    }
5518
  }
5519

5520
  return TSDB_CODE_SUCCESS;
17,131,882✔
5521
}
5522

5523
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
7,840,303✔
5524
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,840,303✔
5525
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
7,840,303✔
5526

5527
  SInputColumnInfoData* pInput = &pCtx->input;
7,840,303✔
5528

5529
  SColumnInfoData* pInputCol = pInput->pData[0];
7,840,303✔
5530
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
25,349,656✔
5531
    if (colDataIsNull_s(pInputCol, i)) {
35,018,994✔
5532
      continue;
377,698✔
5533
    }
5534

5535
    char*   data = colDataGetData(pInputCol, i);
17,131,799!
5536
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
17,131,799✔
5537
    if (code != TSDB_CODE_SUCCESS) {
17,131,655!
5538
      return code;
×
5539
    }
5540
  }
5541

5542
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
7,840,159✔
5543
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
35✔
5544
    if (code != TSDB_CODE_SUCCESS) {
35!
5545
      return code;
×
5546
    }
5547
    pInfo->nullTupleSaved = true;
35✔
5548
  }
5549

5550
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
7,840,159✔
5551
  return TSDB_CODE_SUCCESS;
7,840,159✔
5552
}
5553

5554
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,567,340✔
5555
  int32_t              code = TSDB_CODE_SUCCESS;
7,567,340✔
5556
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
7,567,340✔
5557

5558
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
7,567,340✔
5559
  pEntryInfo->complete = true;
7,567,341✔
5560

5561
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,567,341✔
5562
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,567,341✔
5563
  if (NULL == pCol) {
7,567,341!
5564
    return TSDB_CODE_OUT_OF_RANGE;
×
5565
  }
5566

5567
  int32_t currentRow = pBlock->info.rows;
7,567,341✔
5568
  if (pInfo->numSampled == 0) {
7,567,341✔
5569
    colDataSetNULL(pCol, currentRow);
2,438✔
5570
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,438✔
5571
    return code;
2,436✔
5572
  }
5573
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
20,699,787✔
5574
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
13,135,143✔
5575
    if (TSDB_CODE_SUCCESS != code) {
13,134,873!
5576
      return code;
×
5577
    }
5578
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
13,134,873✔
5579
    if (TSDB_CODE_SUCCESS != code) {
13,134,884!
5580
      return code;
×
5581
    }
5582
  }
5583

5584
  return code;
7,564,644✔
5585
}
5586

5587
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5588
#if 0
5589
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
5590
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
5591
  int32_t      numOfPoints = pVal->datum.i;
5592
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
5593
#endif
5594
  return true;
×
5595
}
5596

5597
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
5598
#if 0
5599
  if (!functionSetup(pCtx, pResultInfo)) {
5600
    return false;
5601
  }
5602

5603
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5604
  pInfo->numAdded = 0;
5605
  pInfo->numOfPoints = pCtx->param[1].param.i;
5606
  if (pCtx->numOfParams == 4) {
5607
    pInfo->offset = pCtx->param[2].param.i;
5608
  } else {
5609
    pInfo->offset = 0;
5610
  }
5611
  pInfo->colType = pCtx->resDataInfo.type;
5612
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5613
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
5614
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
5615
    return false;
5616
  }
5617

5618
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
5619
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
5620

5621
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
5622
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5623
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
5624
    pInfo->pItems[i]->isNull = false;
5625
  }
5626
#endif
5627

5628
  return TSDB_CODE_SUCCESS;
×
5629
}
5630

5631
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
5632
#if 0
5633
  pItem->timestamp = ts;
5634
  if (isNull) {
5635
    pItem->isNull = true;
5636
  } else {
5637
    pItem->isNull = false;
5638
    memcpy(pItem->data, data, colBytes);
5639
  }
5640
#endif
5641
}
×
5642

5643
#if 0
5644
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
5645
  STailItem* d1 = *(STailItem**)p1;
5646
  STailItem* d2 = *(STailItem**)p2;
5647
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
5648
}
5649

5650
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5651
  STailItem** pList = pInfo->pItems;
5652
  if (pInfo->numAdded < pInfo->numOfPoints) {
5653
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
5654
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
5655
    pInfo->numAdded++;
5656
  } else if (pList[0]->timestamp < ts) {
5657
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
5658
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
5659
  }
5660
}
5661
#endif
5662

5663
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
5664
#if 0
5665
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5666
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5667

5668
  SInputColumnInfoData* pInput = &pCtx->input;
5669
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5670

5671
  SColumnInfoData* pInputCol = pInput->pData[0];
5672
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5673

5674
  int32_t startOffset = pCtx->offset;
5675
  if (pInfo->offset >= pInput->numOfRows) {
5676
    return 0;
5677
  } else {
5678
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
5679
  }
5680
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
5681
    char* data = colDataGetData(pInputCol, i);
5682
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5683
  }
5684

5685
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
5686

5687
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5688
    int32_t    pos = startOffset + i;
5689
    STailItem* pItem = pInfo->pItems[i];
5690
    if (pItem->isNull) {
5691
      colDataSetNULL(pOutput, pos);
5692
    } else {
5693
      colDataSetVal(pOutput, pos, pItem->data, false);
5694
    }
5695
  }
5696

5697
  return pInfo->numOfPoints;
5698
#endif
5699
  return 0;
×
5700
}
5701

5702
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
5703
#if 0
5704
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
5705
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
5706
  pEntryInfo->complete = true;
5707

5708
  int32_t type = pCtx->input.pData[0]->info.type;
5709
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
5710

5711
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5712

5713
  // todo assign the tag value and the corresponding row data
5714
  int32_t currentRow = pBlock->info.rows;
5715
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
5716
    STailItem* pItem = pInfo->pItems[i];
5717
    colDataSetVal(pCol, currentRow, pItem->data, false);
5718
    currentRow += 1;
5719
  }
5720

5721
  return pEntryInfo->numOfRes;
5722
#endif
5723
  return 0;
×
5724
}
5725

5726
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5727
#if 0
5728
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
5729
#endif
5730
  return true;
×
5731
}
5732

5733
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
5734
#if 0
5735
  if (!functionSetup(pCtx, pResInfo)) {
5736
    return false;
5737
  }
5738

5739
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5740
  pInfo->numOfPoints = 0;
5741
  pInfo->colType = pCtx->resDataInfo.type;
5742
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5743
  if (pInfo->pHash != NULL) {
5744
    taosHashClear(pInfo->pHash);
5745
  } else {
5746
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
5747
  }
5748
#endif
5749
  return TSDB_CODE_SUCCESS;
×
5750
}
5751

5752
#if 0
5753
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5754
  // handle null elements
5755
  if (isNull == true) {
5756
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5757
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5758
    if (pInfo->hasNull == false && pItem->isNull == false) {
5759
      pItem->timestamp = ts;
5760
      pItem->isNull = true;
5761
      pInfo->numOfPoints++;
5762
      pInfo->hasNull = true;
5763
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
5764
      pItem->timestamp = ts;
5765
    }
5766
    return;
5767
  }
5768

5769
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
5770
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
5771
  if (pHashItem == NULL) {
5772
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5773
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5774
    pItem->timestamp = ts;
5775
    memcpy(pItem->data, data, pInfo->colBytes);
5776

5777
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
5778
    pInfo->numOfPoints++;
5779
  } else if (pHashItem->timestamp > ts) {
5780
    pHashItem->timestamp = ts;
5781
  }
5782
}
5783
#endif
5784

5785
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
5786
#if 0
5787
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5788
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5789

5790
  SInputColumnInfoData* pInput = &pCtx->input;
5791
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5792

5793
  SColumnInfoData* pInputCol = pInput->pData[0];
5794
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
5795
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5796

5797
  int32_t startOffset = pCtx->offset;
5798
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5799
    char* data = colDataGetData(pInputCol, i);
5800
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5801

5802
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
5803
      taosHashCleanup(pInfo->pHash);
5804
      return 0;
5805
    }
5806
  }
5807

5808
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5809
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
5810
    if (pItem->isNull == true) {
5811
      colDataSetNULL(pOutput, i);
5812
    } else {
5813
      colDataSetVal(pOutput, i, pItem->data, false);
5814
    }
5815
    if (pTsOutput != NULL) {
5816
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
5817
    }
5818
  }
5819

5820
  return pInfo->numOfPoints;
5821
#endif
5822
  return 0;
×
5823
}
5824

5825
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
25,065✔
5826
  pEnv->calcMemSize = sizeof(SModeInfo);
25,065✔
5827
  return true;
25,065✔
5828
}
5829

5830
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
22,062✔
5831
  if (pResInfo->initialized) {
22,062!
5832
    return TSDB_CODE_SUCCESS;
×
5833
  }
5834
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
22,062!
5835
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5836
  }
5837

5838
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
22,063✔
5839
  pInfo->colType = pCtx->resDataInfo.type;
22,063✔
5840
  pInfo->colBytes = pCtx->resDataInfo.bytes;
22,063✔
5841
  if (pInfo->pHash != NULL) {
22,063!
5842
    taosHashClear(pInfo->pHash);
×
5843
  } else {
5844
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
22,063✔
5845
    if (NULL == pInfo->pHash) {
22,065!
5846
      return terrno;
×
5847
    }
5848
  }
5849
  pInfo->nullTupleSaved = false;
22,065✔
5850
  pInfo->nullTuplePos.pageId = -1;
22,065✔
5851

5852
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
22,065✔
5853
  if (NULL == pInfo->buf) {
22,065!
5854
    taosHashCleanup(pInfo->pHash);
×
5855
    pInfo->pHash = NULL;
×
5856
    return terrno;
×
5857
  }
5858
  pCtx->needCleanup = true;
22,065✔
5859
  return TSDB_CODE_SUCCESS;
22,065✔
5860
}
5861

5862
static void modeFunctionCleanup(SModeInfo* pInfo) {
22,065✔
5863
  taosHashCleanup(pInfo->pHash);
22,065✔
5864
  pInfo->pHash = NULL;
22,065✔
5865
  taosMemoryFreeClear(pInfo->buf);
22,065!
5866
}
22,065✔
5867

5868
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5869
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5870
    return;
×
5871
  }
5872
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5873
}
5874

5875
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
45,741,602✔
5876
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
45,741,602!
5877
    (void)memcpy(pInfo->buf, data, varDataTLen(data));
24,263,381✔
5878
  } else {
5879
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
21,478,221✔
5880
  }
5881

5882
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
45,741,602✔
5883
}
5884

5885
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
49,721,751✔
5886
  int32_t code = TSDB_CODE_SUCCESS;
49,721,751✔
5887
  int32_t hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
49,721,751✔
5888

5889
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
49,721,751✔
5890
  if (pHashItem == NULL) {
49,721,471✔
5891
    int32_t   size = sizeof(SModeItem);
45,741,593✔
5892
    SModeItem item = {0};
45,741,593✔
5893

5894
    item.count += 1;
45,741,593✔
5895
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
45,741,593✔
5896
    if (code != TSDB_CODE_SUCCESS) {
45,741,401!
5897
      return code;
×
5898
    }
5899

5900
    if (pCtx->subsidiaries.num > 0) {
45,741,401✔
5901
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
31,391,324✔
5902
      if (code != TSDB_CODE_SUCCESS) {
31,391,324!
5903
        return code;
×
5904
      }
5905
    }
5906

5907
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
45,741,401✔
5908
    if (code != TSDB_CODE_SUCCESS) {
45,741,964!
5909
      return code;
×
5910
    }
5911
  } else {
5912
    pHashItem->count += 1;
3,979,878✔
5913
    if (pCtx->subsidiaries.num > 0) {
3,979,878✔
5914
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
161,285✔
5915
      if (code != TSDB_CODE_SUCCESS) {
161,285!
5916
        return code;
×
5917
      }
5918
    }
5919
  }
5920

5921
  return code;
49,721,842✔
5922
}
5923

5924
int32_t modeFunction(SqlFunctionCtx* pCtx) {
26,060✔
5925
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
26,060✔
5926
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
26,060✔
5927

5928
  SInputColumnInfoData* pInput = &pCtx->input;
26,060✔
5929

5930
  SColumnInfoData* pInputCol = pInput->pData[0];
26,060✔
5931
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
26,060✔
5932

5933
  int32_t numOfElems = 0;
26,060✔
5934
  int32_t startOffset = pCtx->offset;
26,060✔
5935
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
50,287,093✔
5936
    if (colDataIsNull_s(pInputCol, i)) {
100,522,158✔
5937
      continue;
539,967✔
5938
    }
5939
    numOfElems++;
49,721,112✔
5940

5941
    char*   data = colDataGetData(pInputCol, i);
49,721,112!
5942
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
49,721,112✔
5943
    if (code != TSDB_CODE_SUCCESS) {
49,721,840✔
5944
      modeFunctionCleanup(pInfo);
774✔
5945
      return code;
×
5946
    }
5947
  }
5948

5949
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
26,014!
5950
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
5951
    if (code != TSDB_CODE_SUCCESS) {
50!
5952
      modeFunctionCleanup(pInfo);
×
5953
      return code;
×
5954
    }
5955
    pInfo->nullTupleSaved = true;
50✔
5956
  }
5957

5958
  SET_VAL(pResInfo, numOfElems, 1);
26,014✔
5959

5960
  return TSDB_CODE_SUCCESS;
26,014✔
5961
}
5962

5963
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
22,065✔
5964
  int32_t              code = TSDB_CODE_SUCCESS;
22,065✔
5965
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
22,065✔
5966
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
22,065✔
5967
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
22,065✔
5968
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
22,065✔
5969
  int32_t              currentRow = pBlock->info.rows;
22,065✔
5970
  if (NULL == pCol) {
22,065!
5971
    modeFunctionCleanup(pInfo);
×
5972
    return TSDB_CODE_OUT_OF_RANGE;
×
5973
  }
5974

5975
  STuplePos resDataPos, resTuplePos;
5976
  int32_t   maxCount = 0;
22,065✔
5977

5978
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
22,065✔
5979
  while (pIter != NULL) {
45,764,095✔
5980
    SModeItem* pItem = (SModeItem*)pIter;
45,742,030✔
5981
    if (pItem->count >= maxCount) {
45,742,030✔
5982
      maxCount = pItem->count;
38,667,194✔
5983
      resDataPos = pItem->dataPos;
38,667,194✔
5984
      resTuplePos = pItem->tuplePos;
38,667,194✔
5985
    }
5986

5987
    pIter = taosHashIterate(pInfo->pHash, pIter);
45,742,030✔
5988
  }
5989

5990
  if (maxCount != 0) {
22,065✔
5991
    char* pData = NULL;
18,843✔
5992
    code = loadTupleData(pCtx, &resDataPos, &pData);
18,843✔
5993
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
18,843!
5994
      code = terrno = TSDB_CODE_NOT_FOUND;
×
5995
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
5996
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
5997
      modeFunctionCleanup(pInfo);
×
5998
      return code;
×
5999
    }
6000

6001
    code = colDataSetVal(pCol, currentRow, pData, false);
18,843✔
6002
    if (TSDB_CODE_SUCCESS != code) {
18,843!
6003
      modeFunctionCleanup(pInfo);
×
6004
      return code;
×
6005
    }
6006
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
18,843✔
6007
  } else {
6008
    colDataSetNULL(pCol, currentRow);
3,222✔
6009
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
3,222✔
6010
  }
6011

6012
  modeFunctionCleanup(pInfo);
22,065✔
6013

6014
  return code;
22,065✔
6015
}
6016

6017
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
79,419✔
6018
  pEnv->calcMemSize = sizeof(STwaInfo);
79,419✔
6019
  return true;
79,419✔
6020
}
6021

6022
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
10,646,634✔
6023
  if (pResultInfo->initialized) {
10,646,634!
6024
    return TSDB_CODE_SUCCESS;
×
6025
  }
6026
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
10,646,634!
6027
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6028
  }
6029

6030
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,646,663✔
6031
  pInfo->numOfElems = 0;
10,646,663✔
6032
  pInfo->p.key = INT64_MIN;
10,646,663✔
6033
  pInfo->win = TSWINDOW_INITIALIZER;
10,646,663✔
6034
  return TSDB_CODE_SUCCESS;
10,646,663✔
6035
}
6036

6037
static double twa_get_area(SPoint1 s, SPoint1 e) {
29,801,988✔
6038
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
29,801,988!
6039
    return 0;
×
6040
  }
6041

6042
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
29,802,373✔
6043
    return (s.val + e.val) * (e.key - s.key) / 2;
15,562,429✔
6044
  }
6045

6046
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
14,239,944✔
6047
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
14,239,944✔
6048
  return val;
14,239,944✔
6049
}
6050

6051
int32_t twaFunction(SqlFunctionCtx* pCtx) {
10,663,972✔
6052
  int32_t               code = TSDB_CODE_SUCCESS;
10,663,972✔
6053
  SInputColumnInfoData* pInput = &pCtx->input;
10,663,972✔
6054
  SColumnInfoData*      pInputCol = pInput->pData[0];
10,663,972✔
6055

6056
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,663,972✔
6057
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
10,663,972✔
6058
  SPoint1*             last = &pInfo->p;
10,663,972✔
6059

6060
  if (IS_NULL_TYPE(pInputCol->info.type)) {
10,663,972!
6061
    pInfo->numOfElems = 0;
×
6062
    goto _twa_over;
×
6063
  }
6064

6065
  funcInputUpdate(pCtx);
10,663,972✔
6066
  SFuncInputRow row = {0};
10,664,124✔
6067
  bool          result = false;
10,664,124✔
6068
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
10,664,124✔
6069
    while (1) {
6070
      code = funcInputGetNextRow(pCtx, &row, &result);
3,369,496✔
6071
      if (TSDB_CODE_SUCCESS != code) {
3,369,501!
6072
        return code;
×
6073
      }
6074
      if (!result) {
3,369,501✔
6075
        break;
2✔
6076
      }
6077
      if (row.isDataNull) {
3,369,499✔
6078
        continue;
2✔
6079
      }
6080

6081
      last->key = row.ts;
3,369,497✔
6082

6083
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,369,497!
6084

6085
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
3,369,497✔
6086
      pInfo->win.skey = pCtx->start.key;
3,369,496✔
6087
      pInfo->numOfElems++;
3,369,496✔
6088
      break;
3,369,496✔
6089
    }
6090
  } else if (pInfo->p.key == INT64_MIN) {
7,294,630✔
6091
    while (1) {
6092
      code = funcInputGetNextRow(pCtx, &row, &result);
7,406,025✔
6093
      if (TSDB_CODE_SUCCESS != code) {
7,405,549!
6094
        return code;
×
6095
      }
6096
      if (!result) {
7,405,549✔
6097
        break;
14,712✔
6098
      }
6099
      if (row.isDataNull) {
7,390,837✔
6100
        continue;
127,729✔
6101
      }
6102

6103
      last->key = row.ts;
7,263,108✔
6104

6105
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
7,263,108!
6106

6107
      pInfo->win.skey = last->key;
7,263,108✔
6108
      pInfo->numOfElems++;
7,263,108✔
6109
      break;
7,263,108✔
6110
    }
6111
  }
6112

6113
  SPoint1 st = {0};
10,663,652✔
6114

6115
  // calculate the value of
6116
  while (1) {
6117
    code = funcInputGetNextRow(pCtx, &row, &result);
33,609,886✔
6118
    if (TSDB_CODE_SUCCESS != code) {
33,607,943!
6119
      return code;
×
6120
    }
6121
    if (!result) {
33,607,943✔
6122
      break;
10,663,795✔
6123
    }
6124
    if (row.isDataNull) {
22,944,148✔
6125
      continue;
630✔
6126
    }
6127
    pInfo->numOfElems++;
22,943,518✔
6128
    switch (pInputCol->info.type) {
22,943,518!
6129
      case TSDB_DATA_TYPE_TINYINT: {
915,215✔
6130
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
915,215✔
6131
        break;
915,215✔
6132
      }
6133
      case TSDB_DATA_TYPE_SMALLINT: {
18,289,649✔
6134
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
18,289,649✔
6135
        break;
18,289,649✔
6136
      }
6137
      case TSDB_DATA_TYPE_INT: {
124,225✔
6138
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
124,225✔
6139
        break;
124,225✔
6140
      }
6141
      case TSDB_DATA_TYPE_BIGINT: {
3,201,046✔
6142
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
3,201,046✔
6143
        break;
3,201,046✔
6144
      }
6145
      case TSDB_DATA_TYPE_FLOAT: {
62,403✔
6146
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
62,403✔
6147
        break;
62,403✔
6148
      }
6149
      case TSDB_DATA_TYPE_DOUBLE: {
86,352✔
6150
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
86,352✔
6151
        break;
86,352✔
6152
      }
6153
      case TSDB_DATA_TYPE_UTINYINT: {
68,886✔
6154
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
68,886✔
6155
        break;
68,886✔
6156
      }
6157
      case TSDB_DATA_TYPE_USMALLINT: {
68,669✔
6158
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
68,669✔
6159
        break;
68,669✔
6160
      }
6161
      case TSDB_DATA_TYPE_UINT: {
71,223✔
6162
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
71,223✔
6163
        break;
71,223✔
6164
      }
6165
      case TSDB_DATA_TYPE_UBIGINT: {
59,016✔
6166
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
59,016✔
6167
        break;
59,016✔
6168
      }
6169
      default: {
×
6170
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6171
      }
6172
    }
6173
    if (pInfo->p.key == st.key) {
22,946,684!
6174
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6175
    }
6176

6177
    pInfo->dOutput += twa_get_area(pInfo->p, st);
22,946,684✔
6178
    pInfo->p = st;
22,945,604✔
6179
  }
6180

6181
  // the last interpolated time window value
6182
  if (pCtx->end.key != INT64_MIN) {
10,663,795✔
6183
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
3,488,350✔
6184
    pInfo->p = pCtx->end;
3,488,350✔
6185
    pInfo->numOfElems += 1;
3,488,350✔
6186
  }
6187

6188
  pInfo->win.ekey = pInfo->p.key;
10,663,795✔
6189

6190
_twa_over:
10,663,795✔
6191
  SET_VAL(pResInfo, 1, 1);
10,663,795✔
6192
  return TSDB_CODE_SUCCESS;
10,663,795✔
6193
}
6194

6195
/*
6196
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6197
 * by next input data. The TWA function only applies to each table, so no merge procedure
6198
 * is required, we simply copy to the resut ot interResBuffer.
6199
 */
6200
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6201
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6202
//
6203
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6204
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6205
// }
6206

6207
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,642,685✔
6208
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,642,685✔
6209

6210
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
10,642,685✔
6211
  if (pInfo->numOfElems == 0) {
10,642,685✔
6212
    pResInfo->numOfRes = 0;
14,414✔
6213
  } else {
6214
    if (pInfo->win.ekey == pInfo->win.skey) {
10,628,271✔
6215
      pInfo->dTwaRes = pInfo->p.val;
5,741,680✔
6216
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
4,886,591!
6217
      pInfo->dTwaRes = 0;
×
6218
    } else {
6219
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
4,886,785✔
6220
    }
6221

6222
    pResInfo->numOfRes = 1;
10,628,271✔
6223
  }
6224

6225
  return functionFinalize(pCtx, pBlock);
10,642,685✔
6226
}
6227

6228
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,627✔
6229
  if (pResultInfo->initialized) {
1,627!
6230
    return TSDB_CODE_SUCCESS;
×
6231
  }
6232
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,627!
6233
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6234
  }
6235

6236
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,627✔
6237
  pInfo->minRows = INT32_MAX;
1,627✔
6238
  return TSDB_CODE_SUCCESS;
1,627✔
6239
}
6240

6241
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,252✔
6242
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,252✔
6243

6244
  SInputColumnInfoData* pInput = &pCtx->input;
3,252✔
6245
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,252✔
6246
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,252✔
6247
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,252✔
6248

6249
  STableBlockDistInfo p1 = {0};
3,252✔
6250
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,252!
6251
    qError("failed to deserialize block dist info");
×
6252
    return TSDB_CODE_FAILED;
×
6253
  }
6254

6255
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,252✔
6256
  pDistInfo->numOfTables += p1.numOfTables;
3,252✔
6257
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,252✔
6258
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,252✔
6259
  pDistInfo->totalSize += p1.totalSize;
3,252✔
6260
  pDistInfo->totalRows += p1.totalRows;
3,252✔
6261
  pDistInfo->numOfFiles += p1.numOfFiles;
3,252✔
6262

6263
  pDistInfo->defMinRows = p1.defMinRows;
3,252✔
6264
  pDistInfo->defMaxRows = p1.defMaxRows;
3,252✔
6265
  pDistInfo->rowSize = p1.rowSize;
3,252✔
6266

6267
  if (pDistInfo->minRows > p1.minRows) {
3,252✔
6268
    pDistInfo->minRows = p1.minRows;
2✔
6269
  }
6270
  if (pDistInfo->maxRows < p1.maxRows) {
3,252✔
6271
    pDistInfo->maxRows = p1.maxRows;
2✔
6272
  }
6273
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,252✔
6274
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,292✔
6275
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,040✔
6276
  }
6277

6278
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,252✔
6279
  return TSDB_CODE_SUCCESS;
3,252✔
6280
}
6281

6282
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,491✔
6283
  SEncoder encoder = {0};
6,491✔
6284
  int32_t  code = 0;
6,491✔
6285
  int32_t  lino;
6286
  int32_t  tlen;
6287
  tEncoderInit(&encoder, buf, bufLen);
6,491✔
6288

6289
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,497!
6290
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
12,984!
6291

6292
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
12,984!
6293
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
12,984!
6294
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
12,984!
6295

6296
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
12,984!
6297
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
12,984!
6298
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
12,984!
6299
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
12,984!
6300
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
12,984!
6301
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
12,984!
6302
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
12,984!
6303
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
12,984!
6304
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
12,984!
6305

6306
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,128✔
6307
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,272!
6308
  }
6309

6310
  tEndEncode(&encoder);
6,492✔
6311

6312
_exit:
6,495✔
6313
  if (code) {
6,495!
6314
    tlen = code;
×
6315
  } else {
6316
    tlen = encoder.pos;
6,495✔
6317
  }
6318
  tEncoderClear(&encoder);
6,495✔
6319
  return tlen;
6,496✔
6320
}
6321

6322
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,252✔
6323
  SDecoder decoder = {0};
3,252✔
6324
  int32_t  code = 0;
3,252✔
6325
  int32_t  lino;
6326
  tDecoderInit(&decoder, buf, bufLen);
3,252✔
6327

6328
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,252!
6329
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,504!
6330

6331
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,504!
6332
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,504!
6333
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,504!
6334

6335
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,504!
6336
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,504!
6337
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,504!
6338
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,504!
6339
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,504!
6340
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,504!
6341
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,504!
6342
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,504!
6343
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,504!
6344

6345
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,292✔
6346
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,080!
6347
  }
6348

6349
_exit:
3,252✔
6350
  tDecoderClear(&decoder);
3,252✔
6351
  return code;
3,252✔
6352
}
6353

6354
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,627✔
6355
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,627✔
6356
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,627✔
6357

6358
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,627✔
6359
  if (NULL == pColInfo) {
1,627!
6360
    return TSDB_CODE_OUT_OF_RANGE;
×
6361
  }
6362

6363
  if (pData->totalRows == 0) {
1,627✔
6364
    pData->minRows = 0;
1,625✔
6365
  }
6366

6367
  int32_t row = 0;
1,627✔
6368
  char    st[256] = {0};
1,627✔
6369
  double  averageSize = 0;
1,627✔
6370
  if (pData->numOfBlocks != 0) {
1,627✔
6371
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
2✔
6372
  }
6373
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,627✔
6374
  double   compRatio = 0;
1,627✔
6375
  if (totalRawSize != 0) {
1,627✔
6376
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
2✔
6377
  }
6378

6379
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,254✔
6380
                          "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6381
                          pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,627✔
6382

6383
  varDataSetLen(st, len);
1,627✔
6384
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6385
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6386
    return code;
×
6387
  }
6388

6389
  int64_t avgRows = 0;
1,627✔
6390
  if (pData->numOfBlocks > 0) {
1,627✔
6391
    avgRows = pData->totalRows / pData->numOfBlocks;
2✔
6392
  }
6393

6394
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,627✔
6395
                  "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6396
                  pData->minRows, pData->maxRows, avgRows);
6397
  varDataSetLen(st, len);
1,627✔
6398
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6399
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6400
    return code;
×
6401
  }
6402

6403
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%d] Stt_Rows=[%d] ",
1,627✔
6404
                  pData->numOfInmemRows, pData->numOfSttRows);
6405
  varDataSetLen(st, len);
1,627✔
6406
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6407
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6408
    return code;
×
6409
  }
6410

6411
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,254✔
6412
                  "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
1,627✔
6413
                  pData->numOfVgroups);
6414

6415
  varDataSetLen(st, len);
1,627✔
6416
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6417
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6418
    return code;
×
6419
  }
6420

6421
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,627✔
6422
                  "--------------------------------------------------------------------------------");
6423
  varDataSetLen(st, len);
1,627✔
6424
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6425
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6426
    return code;
×
6427
  }
6428

6429
  int32_t maxVal = 0;
1,627✔
6430
  int32_t minVal = INT32_MAX;
1,627✔
6431
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,167✔
6432
    if (maxVal < pData->blockRowsHisto[i]) {
32,540✔
6433
      maxVal = pData->blockRowsHisto[i];
3✔
6434
    }
6435

6436
    if (minVal > pData->blockRowsHisto[i]) {
32,540✔
6437
      minVal = pData->blockRowsHisto[i];
1,628✔
6438
    }
6439
  }
6440

6441
  // maximum number of step is 80
6442
  double factor = pData->numOfBlocks / 80.0;
1,627✔
6443

6444
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,627✔
6445
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,627✔
6446

6447
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,167✔
6448
    len =
32,540✔
6449
        tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,540✔
6450

6451
    int32_t num = 0;
32,540✔
6452
    if (pData->blockRowsHisto[i] > 0) {
32,540✔
6453
      num = (pData->blockRowsHisto[i]) / factor;
3✔
6454
    }
6455

6456
    for (int32_t j = 0; j < num; ++j) {
32,699✔
6457
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
159✔
6458
      len += x;
159✔
6459
    }
6460

6461
    if (pData->blockRowsHisto[i] > 0) {
32,540✔
6462
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
3✔
6463
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
3✔
6464
                       pData->blockRowsHisto[i], v, '%');
6465
    }
6466

6467
    varDataSetLen(st, len);
32,540✔
6468
    code = colDataSetVal(pColInfo, row++, st, false);
32,540✔
6469
    if (TSDB_CODE_SUCCESS != code) {
32,540!
6470
      return code;
×
6471
    }
6472
  }
6473

6474
  return TSDB_CODE_SUCCESS;
1,627✔
6475
}
6476
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1✔
6477
  if (pResultInfo->initialized) {
1!
6478
    return TSDB_CODE_SUCCESS;
×
6479
  }
6480
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1!
6481
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6482
  }
6483

6484
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1✔
6485
  return TSDB_CODE_SUCCESS;
1✔
6486
}
6487
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
2✔
6488
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
2✔
6489

6490
  SInputColumnInfoData* pInput = &pCtx->input;
2✔
6491
  SColumnInfoData*      pInputCol = pInput->pData[0];
2✔
6492
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
2✔
6493
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
2✔
6494

6495
  SDBBlockUsageInfo p1 = {0};
2✔
6496
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
2!
6497
    qError("failed to deserialize block dist info");
×
6498
    return TSDB_CODE_FAILED;
×
6499
  }
6500

6501
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
2✔
6502
  pDistInfo->walInDiskSize += p1.walInDiskSize;
2✔
6503
  pDistInfo->rawDataSize += p1.rawDataSize;
2✔
6504
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
2✔
6505
  return TSDB_CODE_SUCCESS;
2✔
6506
}
6507

6508
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
3✔
6509
  SEncoder encoder = {0};
3✔
6510
  int32_t  code = 0;
3✔
6511
  int32_t  lino;
6512
  int32_t  tlen;
6513
  tEncoderInit(&encoder, buf, bufLen);
3✔
6514

6515
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
4!
6516

6517
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
8!
6518
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
8!
6519
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
8!
6520

6521
  tEndEncode(&encoder);
4✔
6522

6523
_exit:
4✔
6524
  if (code) {
4!
6525
    tlen = code;
×
6526
  } else {
6527
    tlen = encoder.pos;
4✔
6528
  }
6529
  tEncoderClear(&encoder);
4✔
6530
  return tlen;
4✔
6531
}
6532
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
2✔
6533
  SDecoder decoder = {0};
2✔
6534
  int32_t  code = 0;
2✔
6535
  int32_t  lino;
6536
  tDecoderInit(&decoder, buf, bufLen);
2✔
6537

6538
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
2!
6539
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
4!
6540
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
4!
6541
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
4!
6542

6543
_exit:
2✔
6544
  tDecoderClear(&decoder);
2✔
6545
  return code;
2✔
6546
}
6547
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1✔
6548
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1✔
6549
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
1✔
6550

6551
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1✔
6552
  if (NULL == pColInfo) {
1!
6553
    return TSDB_CODE_OUT_OF_RANGE;
×
6554
  }
6555
  int32_t len = 0;
1✔
6556
  int32_t row = 0;
1✔
6557
  char    st[256] = {0};
1✔
6558

6559
  uint64_t totalDiskSize = pData->dataInDiskSize;
1✔
6560
  uint64_t rawDataSize = pData->rawDataSize;
1✔
6561
  double   compressRadio = 0;
1✔
6562
  if (rawDataSize != 0) {
1!
6563
    compressRadio = totalDiskSize * 100 / (double)rawDataSize;
1✔
6564
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[%.2f]", compressRadio);
1✔
6565
  } else {
6566
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[NULL]");
×
6567
  }
6568

6569
  varDataSetLen(st, len);
1✔
6570
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1✔
6571
  if (TSDB_CODE_SUCCESS != code) {
1!
6572
    return code;
×
6573
  }
6574

6575
  len =
1✔
6576
      tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
1✔
6577
  varDataSetLen(st, len);
1✔
6578
  code = colDataSetVal(pColInfo, row++, st, false);
1✔
6579
  if (TSDB_CODE_SUCCESS != code) {
1!
6580
    return code;
×
6581
  }
6582
  return code;
1✔
6583
}
6584

6585
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,396✔
6586
  pEnv->calcMemSize = sizeof(SDerivInfo);
31,396✔
6587
  return true;
31,396✔
6588
}
6589

6590
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
86,597✔
6591
  if (pResInfo->initialized) {
86,597✔
6592
    return TSDB_CODE_SUCCESS;
55,058✔
6593
  }
6594
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,539!
6595
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6596
  }
6597

6598
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,539✔
6599

6600
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
31,539✔
6601
  pDerivInfo->prevTs = -1;
31,539✔
6602
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
31,539✔
6603
  pDerivInfo->valueSet = false;
31,539✔
6604
  return TSDB_CODE_SUCCESS;
31,539✔
6605
}
6606

6607
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
55,201✔
6608
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
55,201✔
6609
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
55,201✔
6610

6611
  SInputColumnInfoData* pInput = &pCtx->input;
55,201✔
6612
  SColumnInfoData*      pInputCol = pInput->pData[0];
55,201✔
6613

6614
  int32_t          numOfElems = 0;
55,201✔
6615
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
55,201✔
6616
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
55,201✔
6617
  int32_t          code = TSDB_CODE_SUCCESS;
55,201✔
6618

6619
  funcInputUpdate(pCtx);
55,201✔
6620

6621
  double v = 0;
55,201✔
6622
  if (pCtx->order == TSDB_ORDER_ASC) {
55,201✔
6623
    SFuncInputRow row = {0};
51,817✔
6624
    bool          result = false;
51,817✔
6625
    while (1) {
3,555,427✔
6626
      code = funcInputGetNextRow(pCtx, &row, &result);
3,607,244✔
6627
      if (TSDB_CODE_SUCCESS != code) {
3,607,244!
6628
        return code;
×
6629
      }
6630
      if (!result) {
3,607,244✔
6631
        break;
51,817✔
6632
      }
6633
      if (row.isDataNull) {
3,555,427✔
6634
        continue;
36,157✔
6635
      }
6636

6637
      char* d = row.pData;
3,519,270✔
6638
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
3,519,270!
6639

6640
      int32_t pos = pCtx->offset + numOfElems;
3,519,270✔
6641
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
3,519,270✔
6642
        pDerivInfo->valueSet = true;
27,786✔
6643
      } else {
6644
        if (row.ts == pDerivInfo->prevTs) {
3,491,484!
6645
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6646
        }
6647
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
3,491,484✔
6648
        if (pDerivInfo->ignoreNegative && r < 0) {
3,491,484✔
6649
        } else {
6650
          if (isinf(r) || isnan(r)) {
2,052,988!
6651
            colDataSetNULL(pOutput, pos);
×
6652
          } else {
6653
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
2,052,988✔
6654
            if (code != TSDB_CODE_SUCCESS) {
2,052,988!
6655
              return code;
×
6656
            }
6657
          }
6658

6659
          if (pTsOutput != NULL) {
2,052,988!
6660
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6661
          }
6662

6663
          // handle selectivity
6664
          if (pCtx->subsidiaries.num > 0) {
2,052,988✔
6665
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,460,550✔
6666
            if (code != TSDB_CODE_SUCCESS) {
1,460,550!
6667
              return code;
×
6668
            }
6669
          }
6670

6671
          numOfElems++;
2,052,988✔
6672
        }
6673
      }
6674

6675
      pDerivInfo->prevValue = v;
3,519,270✔
6676
      pDerivInfo->prevTs = row.ts;
3,519,270✔
6677
    }
6678
  } else {
6679
    SFuncInputRow row = {0};
3,384✔
6680
    bool          result = false;
3,384✔
6681
    while (1) {
333,894✔
6682
      code = funcInputGetNextRow(pCtx, &row, &result);
337,278✔
6683
      if (TSDB_CODE_SUCCESS != code) {
337,278!
6684
        return code;
×
6685
      }
6686
      if (!result) {
337,278✔
6687
        break;
3,384✔
6688
      }
6689
      if (row.isDataNull) {
333,894✔
6690
        continue;
866✔
6691
      }
6692

6693
      char* d = row.pData;
333,028✔
6694
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
333,028!
6695

6696
      int32_t pos = pCtx->offset + numOfElems;
333,028✔
6697
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
333,028✔
6698
        pDerivInfo->valueSet = true;
3,344✔
6699
      } else {
6700
        if (row.ts == pDerivInfo->prevTs) {
329,684!
6701
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6702
        }
6703
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
329,684✔
6704
        if (pDerivInfo->ignoreNegative && r < 0) {
329,684✔
6705
        } else {
6706
          if (isinf(r) || isnan(r)) {
256,478!
6707
            colDataSetNULL(pOutput, pos);
×
6708
          } else {
6709
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
256,478✔
6710
            if (code != TSDB_CODE_SUCCESS) {
256,478!
6711
              return code;
×
6712
            }
6713
          }
6714

6715
          if (pTsOutput != NULL) {
256,478!
6716
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6717
          }
6718

6719
          // handle selectivity
6720
          if (pCtx->subsidiaries.num > 0) {
256,478✔
6721
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
76,996✔
6722
            if (code != TSDB_CODE_SUCCESS) {
76,996!
6723
              return code;
×
6724
            }
6725
          }
6726
          numOfElems++;
256,478✔
6727
        }
6728
      }
6729

6730
      pDerivInfo->prevValue = v;
333,028✔
6731
      pDerivInfo->prevTs = row.ts;
333,028✔
6732
    }
6733
  }
6734

6735
  pResInfo->numOfRes = numOfElems;
55,201✔
6736

6737
  return TSDB_CODE_SUCCESS;
55,201✔
6738
}
6739

6740
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
29,035✔
6741

6742
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
28,513✔
6743
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
28,513✔
6744
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
28,513✔
6745
  return true;
28,529✔
6746
}
6747

6748
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,880,201✔
6749
  if (pResInfo->initialized) {
2,880,201!
6750
    return TSDB_CODE_SUCCESS;
×
6751
  }
6752
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,880,201!
6753
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6754
  }
6755

6756
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,880,202✔
6757

6758
  pInfo->firstKey = INT64_MIN;
2,880,202✔
6759
  pInfo->lastKey = INT64_MIN;
2,880,202✔
6760
  pInfo->firstValue = (double)INT64_MIN;
2,880,202✔
6761
  pInfo->lastValue = (double)INT64_MIN;
2,880,202✔
6762

6763
  pInfo->hasResult = 0;
2,880,202✔
6764
  return TSDB_CODE_SUCCESS;
2,880,202✔
6765
}
6766

6767
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
8,311,230✔
6768
  if (isFirst) {
8,311,230✔
6769
    pRateInfo->firstValue = v;
2,722,700✔
6770
    pRateInfo->firstKey = ts;
2,722,700✔
6771
    if (pRateInfo->firstPk) {
2,722,700✔
6772
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
35!
6773
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6774
    }
6775
  } else {
6776
    pRateInfo->lastValue = v;
5,588,530✔
6777
    pRateInfo->lastKey = ts;
5,588,530✔
6778
    if (pRateInfo->lastPk) {
5,588,530✔
6779
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
52!
6780
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6781
    }
6782
  }
6783
}
8,311,230✔
6784

6785
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,894,809✔
6786
  if (pCtx->hasPrimaryKey) {
2,894,809✔
6787
    if (!isMerge) {
19✔
6788
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6789
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6790
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6791
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6792
    } else {
6793
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6794
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6795
    }
6796
  } else {
6797
    pRateInfo->firstPk = NULL;
2,894,790✔
6798
    pRateInfo->lastPk = NULL;
2,894,790✔
6799
  }
6800
}
2,894,809✔
6801

6802
int32_t irateFunction(SqlFunctionCtx* pCtx) {
2,893,963✔
6803
  int32_t              code = TSDB_CODE_SUCCESS;
2,893,963✔
6804
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,893,963✔
6805
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,893,963✔
6806

6807
  SInputColumnInfoData* pInput = &pCtx->input;
2,893,963✔
6808
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,893,963✔
6809

6810
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,893,963✔
6811

6812
  funcInputUpdate(pCtx);
2,893,963✔
6813

6814
  initializeRateInfo(pCtx, pRateInfo, false);
2,893,965✔
6815

6816
  int32_t       numOfElems = 0;
2,893,966✔
6817
  int32_t       type = pInputCol->info.type;
2,893,966✔
6818
  SFuncInputRow row = {0};
2,893,966✔
6819
  bool          result = false;
2,893,966✔
6820
  while (1) {
5,833,871✔
6821
    code = funcInputGetNextRow(pCtx, &row, &result);
8,727,837✔
6822
    if (TSDB_CODE_SUCCESS != code) {
8,727,842!
6823
      return code;
×
6824
    }
6825
    if (!result) {
8,727,842✔
6826
      break;
2,893,971✔
6827
    }
6828
    if (row.isDataNull) {
5,833,871✔
6829
      continue;
104,799✔
6830
    }
6831

6832
    char*  data = row.pData;
5,729,072✔
6833
    double v = 0;
5,729,072✔
6834
    GET_TYPED_DATA(v, double, type, data);
5,729,072!
6835

6836
    if (INT64_MIN == pRateInfo->lastKey) {
5,729,072✔
6837
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
2,866,386✔
6838
      pRateInfo->hasResult = 1;
2,866,386✔
6839
      continue;
2,866,386✔
6840
    }
6841

6842
    if (row.ts > pRateInfo->lastKey) {
2,862,686✔
6843
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
2,721,737!
6844
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
2,721,738✔
6845
      }
6846
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
2,721,746✔
6847
      continue;
2,721,733✔
6848
    } else if (row.ts == pRateInfo->lastKey) {
140,949!
6849
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6850
    }
6851

6852
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
140,949!
6853
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
486✔
6854
    } else if (row.ts == pRateInfo->firstKey) {
140,463!
6855
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6856
    }
6857
  }
6858

6859
  numOfElems++;
2,893,971✔
6860

6861
  SET_VAL(pResInfo, numOfElems, 1);
2,893,971!
6862
  return TSDB_CODE_SUCCESS;
2,893,971✔
6863
}
6864

6865
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
2,877,580✔
6866
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
2,877,580✔
6867
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
220,116!
6868
    return 0.0;
2,657,464✔
6869
  }
6870

6871
  double diff = 0;
220,116✔
6872
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6873
  // value between two values.
6874
  diff = pRateInfo->lastValue;
220,116✔
6875
  if (diff >= pRateInfo->firstValue) {
220,116✔
6876
    diff -= pRateInfo->firstValue;
97,389✔
6877
  }
6878

6879
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
220,116✔
6880
  if (duration == 0) {
220,116!
6881
    return 0;
×
6882
  }
6883

6884
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
220,116!
6885
}
6886

6887
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
290✔
6888
  if (inputKey > pOutput->lastKey) {
290✔
6889
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
178✔
6890
    if (isFirstKey) {
178✔
6891
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
81✔
6892
    } else {
6893
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
97✔
6894
    }
6895
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
112!
6896
    if (isFirstKey) {
28✔
6897
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
14✔
6898
    } else {
6899
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
14✔
6900
    }
6901
  } else {
6902
    // inputKey < pOutput->firstKey
6903
  }
6904
}
290✔
6905

6906
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
265✔
6907
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
265✔
6908
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
265✔
6909
}
265✔
6910

6911
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
410✔
6912
  if ((pInput->firstKey != INT64_MIN &&
410✔
6913
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
405!
6914
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
410!
6915
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6916
  }
6917

6918
  if (pOutput->hasResult == 0) {
410✔
6919
    irateCopyInfo(pInput, pOutput);
265✔
6920
    pOutput->hasResult = pInput->hasResult;
265✔
6921
    return TSDB_CODE_SUCCESS;
265✔
6922
  }
6923

6924
  if (pInput->firstKey != INT64_MIN) {
145!
6925
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
145✔
6926
  }
6927

6928
  if (pInput->lastKey != INT64_MIN) {
145!
6929
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
145✔
6930
  }
6931

6932
  pOutput->hasResult = pInput->hasResult;
145✔
6933
  return TSDB_CODE_SUCCESS;
145✔
6934
}
6935

6936
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
422✔
6937
  SInputColumnInfoData* pInput = &pCtx->input;
422✔
6938
  SColumnInfoData*      pCol = pInput->pData[0];
422✔
6939
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
422!
6940
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6941
  }
6942

6943
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
422✔
6944
  initializeRateInfo(pCtx, pInfo, true);
422✔
6945

6946
  int32_t start = pInput->startRowIndex;
422✔
6947
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
844✔
6948
    char*      data = colDataGetData(pCol, i);
422!
6949
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
422✔
6950
    initializeRateInfo(pCtx, pInfo, true);
422✔
6951
    if (pInputInfo->hasResult) {
422✔
6952
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
410✔
6953
      if (code != TSDB_CODE_SUCCESS) {
410!
6954
        return code;
×
6955
      }
6956
    }
6957
  }
6958

6959
  if (pInfo->hasResult) {
422✔
6960
    GET_RES_INFO(pCtx)->numOfRes = 1;
410✔
6961
  }
6962

6963
  return TSDB_CODE_SUCCESS;
422✔
6964
}
6965

6966
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
422✔
6967
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
422✔
6968
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
422✔
6969
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
422✔
6970
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
422✔
6971

6972
  if (NULL == res) {
422!
6973
    return terrno;
×
6974
  }
6975
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
422✔
6976
  varDataSetLen(res, resultBytes);
422✔
6977

6978
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
422✔
6979
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
422✔
6980
  if (NULL == pCol) {
422!
6981
    taosMemoryFree(res);
×
6982
    return TSDB_CODE_OUT_OF_RANGE;
×
6983
  }
6984

6985
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
422✔
6986

6987
  taosMemoryFree(res);
422✔
6988
  return code;
422✔
6989
}
6990

6991
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,877,580✔
6992
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,877,580✔
6993
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,877,580✔
6994
  if (NULL == pCol) {
2,877,580!
6995
    return TSDB_CODE_OUT_OF_RANGE;
×
6996
  }
6997

6998
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,877,580✔
6999
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,877,580✔
7000

7001
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,877,580✔
7002
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
2,877,580!
7003
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
2,877,580✔
7004

7005
  return code;
2,877,580✔
7006
}
7007

7008
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
109,553,343✔
7009
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
109,553,343✔
7010
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
109,553,343✔
7011

7012
  SInputColumnInfoData* pInput = &pCtx->input;
109,553,343✔
7013
  SColumnInfoData*      pInputCol = pInput->pData[0];
109,553,343✔
7014

7015
  int32_t startIndex = pInput->startRowIndex;
109,553,343✔
7016

7017
  // escape rest of data blocks to avoid first entry to be overwritten.
7018
  if (pInfo->hasResult) {
109,553,343✔
7019
    goto _group_value_over;
11,309,416✔
7020
  }
7021

7022
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
196,069,799✔
7023
    pInfo->isNull = true;
2,534,148✔
7024
    pInfo->hasResult = true;
2,534,148✔
7025
    goto _group_value_over;
2,534,148✔
7026
  }
7027

7028
  char* data = colDataGetData(pInputCol, startIndex);
95,709,779!
7029
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
95,709,779!
7030
    (void)memcpy(pInfo->data, data,
72,990,085✔
7031
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
72,990,085✔
7032
  } else {
7033
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
22,719,694✔
7034
  }
7035
  pInfo->hasResult = true;
95,709,779✔
7036

7037
_group_value_over:
109,553,343✔
7038

7039
  SET_VAL(pResInfo, 1, 1);
109,553,343✔
7040
  return TSDB_CODE_SUCCESS;
109,553,343✔
7041
}
7042

7043
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
108,756,289✔
7044

7045
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
96,726,347✔
7046
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
96,726,347✔
7047
  int32_t          code = TSDB_CODE_SUCCESS;
96,726,347✔
7048
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
96,726,347✔
7049
  if (NULL == pCol) {
96,673,471!
7050
    return TSDB_CODE_OUT_OF_RANGE;
×
7051
  }
7052

7053
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
96,673,471✔
7054

7055
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
96,673,471✔
7056

7057
  if (pInfo->hasResult) {
96,673,471!
7058
    int32_t currentRow = pBlock->info.rows;
96,728,991✔
7059
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
193,731,675✔
7060
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
96,750,474✔
7061
      if (TSDB_CODE_SUCCESS != code) {
97,002,684!
7062
        return code;
×
7063
      }
7064
    }
7065
  } else {
7066
    pResInfo->numOfRes = 0;
×
7067
  }
7068

7069
  return code;
96,925,681✔
7070
}
7071

7072
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
96,478,114✔
7073

7074
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7075
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7076
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7077

7078
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7079
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7080

7081
  // escape rest of data blocks to avoid first entry to be overwritten.
7082
  if (pDBuf->hasResult) {
×
7083
    goto _group_key_over;
×
7084
  }
7085

7086
  if (pSBuf->isNull) {
×
7087
    pDBuf->isNull = true;
×
7088
    pDBuf->hasResult = true;
×
7089
    goto _group_key_over;
×
7090
  }
7091

7092
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7093
    (void)memcpy(pDBuf->data, pSBuf->data,
×
7094
                 (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data)
×
7095
                                                                       : varDataTLen(pSBuf->data));
×
7096
  } else {
7097
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7098
  }
7099

7100
  pDBuf->hasResult = true;
×
7101

7102
_group_key_over:
×
7103

7104
  SET_VAL(pDResInfo, 1, 1);
×
7105
  return TSDB_CODE_SUCCESS;
×
7106
}
7107

7108
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
13,479✔
7109
  int32_t numOfElems = 0;
13,479✔
7110

7111
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,479✔
7112
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
13,479✔
7113

7114
  SInputColumnInfoData* pInput = &pCtx->input;
13,479✔
7115
  SColumnInfoData*      pInputCol = pInput->pData[0];
13,479✔
7116

7117
  int32_t bytes = pInputCol->info.bytes;
13,479✔
7118
  pInfo->bytes = bytes;
13,479✔
7119

7120
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
13,479✔
7121
  pInfo->pkType = -1;
13,479✔
7122
  __compar_fn_t pkCompareFn = NULL;
13,479✔
7123
  if (pCtx->hasPrimaryKey) {
13,479✔
7124
    pInfo->pkType = pkCol->info.type;
2,684✔
7125
    pInfo->pkBytes = pkCol->info.bytes;
2,684✔
7126
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
2,684✔
7127
  }
7128

7129
  // TODO it traverse the different way.
7130
  // last_row function does not ignore the null value
7131
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
26,968✔
7132
    numOfElems++;
13,491✔
7133

7134
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
13,491✔
7135
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
13,491!
7136

7137
    TSKEY cts = getRowPTs(pInput->pPTS, i);
13,491✔
7138
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
13,491✔
7139
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
11,340✔
7140
      if (code != TSDB_CODE_SUCCESS) {
11,340!
7141
        return code;
×
7142
      }
7143
      pResInfo->numOfRes = 1;
11,340✔
7144
    }
7145
  }
7146

7147
  SET_VAL(pResInfo, numOfElems, 1);
13,477!
7148
  return TSDB_CODE_SUCCESS;
13,477✔
7149
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc