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

taosdata / TDengine / #3581

15 Jan 2025 01:12AM UTC coverage: 63.809% (+0.3%) from 63.556%
#3581

push

travis-ci

web-flow
Merge pull request #29561 from taosdata/fix/TD-33504

fix:[TD-33504]add test case

141492 of 284535 branches covered (49.73%)

Branch coverage included in aggregate %.

219814 of 281694 relevant lines covered (78.03%)

19173854.68 hits per line

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

73.41
/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,389,468,344✔
32
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
1,713,759✔
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) {
16,161,712✔
194
  SFuncInputRowIter* pIter = &pCtx->rowIter;
16,161,712✔
195

196
  if (!pCtx->bInputFinished) {
16,161,712!
197
    pIter->pInput = &pCtx->input;
16,162,084✔
198
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
16,162,084✔
199
    pIter->pDataCol = pIter->pInput->pData[0];
16,162,084✔
200
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
16,162,084✔
201
    pIter->rowIndex = pIter->pInput->startRowIndex;
16,162,084✔
202
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
16,162,084✔
203
    pIter->pSrcBlock = pCtx->pSrcBlock;
16,162,084✔
204
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
16,162,084✔
205
      pIter->hasGroupId = true;
216,384✔
206
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
216,384✔
207
      pIter->hasPrev = false;
216,384✔
208
    }
209
  } else {
210
    pIter->finalRow = true;
×
211
  }
212
}
16,161,712✔
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) {
23,330✔
329
  int32_t idx = rowIndex + 1;
23,330✔
330
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
325,779!
331
    ++idx;
302,449✔
332
  }
333
  pIter->rowIndex = idx;
23,330✔
334
}
23,330✔
335

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

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

357
      pIter->hasPrev = false;
1,854✔
358
      setInputRowInfo(pRow, pIter, idx, true);
1,854✔
359
      forwardToNextDiffTsRow(pIter, idx);
1,854✔
360
      return true;
1,854✔
361
    }
362
  } else {
363
    if (pIter->rowIndex <= pIter->inputEndIndex) {
27,530✔
364
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
24,506✔
365

366
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
24,506✔
367
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
24,506✔
368
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
21,476✔
369
      } else {
370
        pIter->rowIndex = pIter->inputEndIndex + 1;
3,030✔
371
      }
372
      return true;
24,506✔
373
    } else {
374
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,024✔
375
      pIter->hasPrev = true;
3,024✔
376
      pIter->prevBlockTsEnd = tsEnd;
3,024✔
377
      return false;
3,024✔
378
    }
379
  }
380
}
381

382
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
1,433,625,005✔
383
  if (pIter->rowIndex <= pIter->inputEndIndex) {
1,433,625,005✔
384
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
1,417,520,330✔
385
    ++pIter->rowIndex;
1,417,549,294✔
386
    return true;
1,417,549,294✔
387
  } else {
388
    return false;
16,104,675✔
389
  }
390
}
391

392
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
1,433,619,098✔
393
  SFuncInputRowIter* pIter = &pCtx->rowIter;
1,433,619,098✔
394
  if (pCtx->hasPrimaryKey) {
1,433,619,098✔
395
    if (pCtx->order == TSDB_ORDER_ASC) {
29,384!
396
      *res = funcInputGetNextRowAscPk(pIter, pRow);
29,384✔
397
      return TSDB_CODE_SUCCESS;
29,384✔
398
    } else {
399
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
400
    }
401
  } else {
402
    *res = funcInputGetNextRowNoPk(pIter, pRow);
1,433,589,714✔
403
    return TSDB_CODE_SUCCESS;
1,433,559,241✔
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) {
36,370,574✔
411
  if (pCtx->subsidiaries.num <= 0) {
36,370,574!
412
    return TSDB_CODE_SUCCESS;
×
413
  }
414

415
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
98,445,928✔
416
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
62,075,354✔
417

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

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

427
    char* pData = colDataGetData(pSrcCol, rowIndex);
62,075,354!
428

429
    // append to dest col
430
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
62,075,354✔
431

432
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
62,075,354✔
433
    if (NULL == pDstCol) {
62,075,354!
434
      return TSDB_CODE_OUT_OF_RANGE;
×
435
    }
436
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
124,150,708✔
437
      colDataSetNULL(pDstCol, pos);
2,580,095✔
438
    } else {
439
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
59,495,259✔
440
      if (TSDB_CODE_SUCCESS != code) {
59,495,259!
441
        return code;
×
442
      }
443
    }
444
  }
445
  return TSDB_CODE_SUCCESS;
36,370,574✔
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) {
709,169,659✔
454
  if (pResultInfo->initialized) {
709,169,659✔
455
    return TSDB_CODE_SUCCESS;  // already initialized
63,155✔
456
  }
457

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

462
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
709,106,504✔
463
  return TSDB_CODE_SUCCESS;
709,106,504✔
464
}
465

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

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

479
  return code;
186,227,748✔
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) {
39✔
498
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
39✔
499
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
39✔
500
  if (NULL == pCol) {
39!
501
    return TSDB_CODE_OUT_OF_RANGE;
×
502
  }
503
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
39✔
504
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
39✔
505

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

509
  return code;
39✔
510
}
511

512
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
203,913✔
513
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
203,913✔
514
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
203,950!
515
    return FUNC_DATA_REQUIRED_NOT_LOAD;
147,674✔
516
  }
517
  return FUNC_DATA_REQUIRED_SMA_LOAD;
56,276✔
518
}
519

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

525
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
117,906,744✔
526
  int64_t numOfElem = 0;
117,906,744✔
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;
117,906,744✔
534
  SColumnInfoData*      pInputCol = pInput->pData[0];
117,906,744✔
535
  if (1 == pInput->numOfRows && pInput->blankFill) {
117,906,744✔
536
    return 0;
447,418✔
537
  }
538
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
117,459,326!
539
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
5,985✔
540
  } else {
541
    if (pInputCol->hasNull) {
117,453,341✔
542
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
417,039,361✔
543
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
771,207,630!
544
          continue;
4,083,794✔
545
        }
546
        numOfElem += 1;
381,520,021✔
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;
86,017,795✔
552
    }
553
  }
554
  return numOfElem;
117,459,326✔
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) {
118,133,418✔
562
  int64_t numOfElem = 0;
118,133,418✔
563

564
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
118,133,418✔
565
  SInputColumnInfoData* pInput = &pCtx->input;
118,133,418✔
566

567
  int32_t type = pInput->pData[0]->info.type;
118,133,418✔
568

569
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
118,133,418✔
570
  if (IS_NULL_TYPE(type)) {
118,133,418✔
571
    // select count(NULL) returns 0
572
    numOfElem = 1;
138,804✔
573
    *((int64_t*)buf) += 0;
138,804✔
574
  } else {
575
    numOfElem = getNumOfElems(pCtx);
117,994,614✔
576
    *((int64_t*)buf) += numOfElem;
117,628,409✔
577
  }
578

579
  if (tsCountAlwaysReturnValue) {
117,767,213!
580
    pResInfo->numOfRes = 1;
117,785,909✔
581
  } else {
582
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
583
  }
584

585
  return TSDB_CODE_SUCCESS;
117,767,213✔
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) {
90,683,487✔
614
  int32_t numOfElem = 0;
90,683,487✔
615

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

621
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
90,683,487✔
622
  pSumRes->type = type;
90,683,487✔
623

624
  if (IS_NULL_TYPE(type)) {
90,683,487✔
625
    numOfElem = 0;
209✔
626
    goto _sum_over;
209✔
627
  }
628

629
  if (pInput->colDataSMAIsSet) {
90,683,278✔
630
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
3,039✔
631

632
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
3,039!
633
      pSumRes->isum += pAgg->sum;
3,039✔
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];
90,680,239✔
641

642
    int32_t start = pInput->startRowIndex;
90,680,239✔
643
    int32_t numOfRows = pInput->numOfRows;
90,680,239✔
644

645
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
90,680,239!
646
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
89,764,034!
647
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
8,871,910✔
648
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
87,279,438✔
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
357,755✔
650
      } else if (type == TSDB_DATA_TYPE_INT) {
87,232,228✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
397,438,822✔
652
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
21,695,031!
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
80,058,960✔
654
      }
655
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
916,205!
656
      if (type == TSDB_DATA_TYPE_UTINYINT) {
555✔
657
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
658
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
516✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
660
      } else if (type == TSDB_DATA_TYPE_UINT) {
476✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
133,471!
662
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
294!
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
134,157✔
664
      }
665
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
915,650✔
666
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
2,102,711✔
667
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
816,946✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
1,909,229✔
669
    }
670
  }
671

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

677
_sum_over:
91,019,556✔
678
  if (numOfElem == 0) {
90,683,487✔
679
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
88,139✔
680
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,467✔
681
      numOfElem = 1;
13✔
682
    }
683
  }
684
  // data in the check operation are all null, not output
685
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
90,683,487✔
686
  return TSDB_CODE_SUCCESS;
90,683,487✔
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) {
46✔
750
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
46✔
751
  SSumRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
46✔
752

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

757
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
46!
758
    pDBuf->isum += pSBuf->isum;
46✔
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);
46✔
765
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
46✔
766
  return TSDB_CODE_SUCCESS;
46✔
767
}
768

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

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

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

786
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
58,732,697✔
787
  buf->assign = false;
58,732,697✔
788
  buf->tuplePos.pageId = -1;
58,732,697✔
789

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

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

801
int32_t minFunction(SqlFunctionCtx* pCtx) {
26,123,495✔
802
  int32_t numOfElems = 0;
26,123,495✔
803
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
26,123,495✔
804
  if (code != TSDB_CODE_SUCCESS) {
26,254,611!
805
    return code;
×
806
  }
807
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
26,254,611✔
808
  return TSDB_CODE_SUCCESS;
26,254,611✔
809
}
810

811
int32_t maxFunction(SqlFunctionCtx* pCtx) {
39,945,444✔
812
  int32_t numOfElems = 0;
39,945,444✔
813
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
39,945,444✔
814
  if (code != TSDB_CODE_SUCCESS) {
40,050,943!
815
    return code;
×
816
  }
817
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
40,050,943✔
818
  return TSDB_CODE_SUCCESS;
40,050,943✔
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) {
57,211,267✔
826
  int32_t code = TSDB_CODE_SUCCESS;
57,211,267✔
827

828
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
57,211,267✔
829
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
57,211,267✔
830

831
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
57,211,267✔
832
  int32_t currentRow = pBlock->info.rows;
57,211,267✔
833

834
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
57,211,267✔
835
  if (NULL == pCol) {
57,253,443!
836
    return TSDB_CODE_OUT_OF_RANGE;
×
837
  }
838
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
57,253,443✔
839

840
  // NOTE: do nothing change it, for performance issue
841
  if (!pEntryInfo->isNullRes) {
57,253,443✔
842
    switch (pCol->info.type) {
50,009,736!
843
      case TSDB_DATA_TYPE_UBIGINT:
12,262,099✔
844
      case TSDB_DATA_TYPE_BIGINT:
845
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
12,262,099✔
846
        break;
12,262,099✔
847
      case TSDB_DATA_TYPE_UINT:
19,992,216✔
848
      case TSDB_DATA_TYPE_INT:
849
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
19,992,216✔
850
        break;
19,992,216✔
851
      case TSDB_DATA_TYPE_USMALLINT:
2,803,386✔
852
      case TSDB_DATA_TYPE_SMALLINT:
853
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
2,803,386✔
854
        break;
2,803,386✔
855
      case TSDB_DATA_TYPE_BOOL:
210,170✔
856
      case TSDB_DATA_TYPE_UTINYINT:
857
      case TSDB_DATA_TYPE_TINYINT:
858
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
210,170✔
859
        break;
210,170✔
860
      case TSDB_DATA_TYPE_DOUBLE:
9,179,422✔
861
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
9,179,422✔
862
        break;
9,179,422✔
863
      case TSDB_DATA_TYPE_FLOAT: {
3,767✔
864
        float v = GET_FLOAT_VAL(&pRes->v);
3,767✔
865
        colDataSetFloat(pCol, currentRow, &v);
3,767✔
866
        break;
3,767✔
867
      }
868
      case TSDB_DATA_TYPE_VARBINARY:
5,622,881✔
869
      case TSDB_DATA_TYPE_VARCHAR:
870
      case TSDB_DATA_TYPE_NCHAR: {
871
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
5,622,881✔
872
        if (TSDB_CODE_SUCCESS != code) {
5,622,881!
873
          return code;
×
874
        }
875
        break;
5,622,881✔
876
      }
877
    }
878
  } else {
879
    colDataSetNULL(pCol, currentRow);
7,243,707!
880
  }
881

882
  taosMemoryFreeClear(pRes->str);
57,253,443!
883
  if (pCtx->subsidiaries.num > 0) {
57,253,443✔
884
    if (pEntryInfo->numOfRes > 0) {
14,085,367✔
885
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
14,082,899✔
886
    } else {
887
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
2,468✔
888
    }
889
  }
890

891
  return code;
57,260,711✔
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) {
249,917,990✔
913
  if (pCtx->subsidiaries.num <= 0) {
249,917,990✔
914
    return TSDB_CODE_SUCCESS;
129,222,037✔
915
  }
916

917
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
120,695,953!
918
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
919
    int32_t numOfCols = pCtx->subsidiaries.num;
120,704,236✔
920
    char*   p = NULL;
120,704,236✔
921
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
120,704,236✔
922
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
121,693,909!
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;
121,695,258✔
929
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
121,695,258✔
930

931
    // todo set the offset value to optimize the performance.
932
    for (int32_t j = 0; j < numOfCols; ++j) {
243,004,103✔
933
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
121,727,345✔
934
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
121,727,345✔
935

936
      // group_key function has its own process function
937
      // do not process there
938
      if (fmIsGroupKeyFunc(pc->functionId)) {
121,727,345✔
939
        continue;
38,100✔
940
      }
941

942
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
121,687,749✔
943
      if (NULL == pDstCol) {
121,583,368!
944
        return TSDB_CODE_OUT_OF_RANGE;
×
945
      }
946
      if (nullList[j]) {
121,583,368✔
947
        colDataSetNULL(pDstCol, rowIndex);
252!
948
      } else {
949
        code = colDataSetVal(pDstCol, rowIndex, pStart, false);
121,583,116✔
950
        if (TSDB_CODE_SUCCESS != code) {
121,270,493!
951
          return code;
×
952
        }
953
      }
954
      pStart += pDstCol->info.bytes;
121,270,745✔
955
    }
956
  }
957

958
  return TSDB_CODE_SUCCESS;
121,268,475✔
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) {
56,596,950✔
964
  if (pCtx->subsidiaries.num <= 0) {
56,596,950!
965
    return TSDB_CODE_SUCCESS;
×
966
  }
967

968
  int32_t code = TSDB_CODE_SUCCESS;
56,596,950✔
969
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
113,197,385✔
970
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
56,601,635✔
971

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

976
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
56,601,635✔
977
    if (NULL == pSrcCol) {
56,598,880!
978
      return TSDB_CODE_OUT_OF_RANGE;
×
979
    }
980

981
    char* pData = colDataGetData(pSrcCol, rowIndex);
56,598,880!
982

983
    // append to dest col
984
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
56,598,880✔
985

986
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
56,598,880✔
987
    if (NULL == pDstCol) {
56,595,395!
988
      return TSDB_CODE_OUT_OF_RANGE;
×
989
    }
990

991
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
113,190,790✔
992
      colDataSetNULL(pDstCol, pos);
560✔
993
    } else {
994
      code = colDataSetVal(pDstCol, pos, pData, false);
56,594,835✔
995
      if (TSDB_CODE_SUCCESS != code) {
56,599,875!
996
        return code;
×
997
      }
998
    }
999
  }
1000
  return code;
56,595,750✔
1001
}
1002

1003
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
31✔
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) {
57✔
1007
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
57✔
1008
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
57✔
1009

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

1014
  switch (type) {
57!
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:
54✔
1025
    case TSDB_DATA_TYPE_INT:
1026
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int32_t) || !pDBuf->assign)) {
54!
1027
        pDBuf->v = pSBuf->v;
30✔
1028
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
30✔
1029
        pDBuf->assign = true;
30✔
1030
      }
1031
      break;
54✔
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);
57✔
1066
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
57✔
1067
  return TSDB_CODE_SUCCESS;
57✔
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) {
46✔
1074
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
46✔
1075
}
1076

1077
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
1,236,566✔
1078

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

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

1092
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
6,637,454✔
1093
  (void)memset(pRes, 0, sizeof(SStdRes));
6,637,454✔
1094
  return TSDB_CODE_SUCCESS;
6,637,454✔
1095
}
1096

1097
int32_t stdFunction(SqlFunctionCtx* pCtx) {
5,429,315✔
1098
  int32_t numOfElem = 0;
5,429,315✔
1099

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

1104
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,429,315✔
1105
  pStdRes->type = type;
5,429,315✔
1106

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

1110
  int32_t start = pInput->startRowIndex;
5,429,315✔
1111
  int32_t numOfRows = pInput->numOfRows;
5,429,315✔
1112

1113
  if (IS_NULL_TYPE(type)) {
5,429,315✔
1114
    numOfElem = 0;
140✔
1115
    goto _stddev_over;
140✔
1116
  }
1117

1118
  switch (type) {
5,429,175!
1119
    case TSDB_DATA_TYPE_TINYINT: {
19,408✔
1120
      int8_t* plist = (int8_t*)pCol->pData;
19,408✔
1121
      for (int32_t i = start; i < numOfRows + start; ++i) {
388,148✔
1122
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
368,740✔
1123
          continue;
34,808✔
1124
        }
1125

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

1132
      break;
19,408✔
1133
    }
1134

1135
    case TSDB_DATA_TYPE_SMALLINT: {
261,724✔
1136
      int16_t* plist = (int16_t*)pCol->pData;
261,724✔
1137
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,545,774✔
1138
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,284,050✔
1139
          continue;
46,981✔
1140
        }
1141

1142
        numOfElem += 1;
1,237,069✔
1143
        pStdRes->count += 1;
1,237,069✔
1144
        pStdRes->isum += plist[i];
1,237,069✔
1145
        pStdRes->quadraticISum += plist[i] * plist[i];
1,237,069✔
1146
      }
1147
      break;
261,724✔
1148
    }
1149

1150
    case TSDB_DATA_TYPE_INT: {
2,468,966✔
1151
      int32_t* plist = (int32_t*)pCol->pData;
2,468,966✔
1152
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
7,378,391✔
1153
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
4,909,425✔
1154
          continue;
42,797✔
1155
        }
1156

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

1163
      break;
2,468,966✔
1164
    }
1165

1166
    case TSDB_DATA_TYPE_BIGINT: {
26,362✔
1167
      int64_t* plist = (int64_t*)pCol->pData;
26,362✔
1168
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,507,893✔
1169
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,481,531✔
1170
          continue;
25,745✔
1171
        }
1172

1173
        numOfElem += 1;
1,455,786✔
1174
        pStdRes->count += 1;
1,455,786✔
1175
        pStdRes->isum += plist[i];
1,455,786✔
1176
        pStdRes->quadraticISum += plist[i] * plist[i];
1,455,786✔
1177
      }
1178
      break;
26,362✔
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: {
17,939✔
1244
      float* plist = (float*)pCol->pData;
17,939✔
1245
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,386,528✔
1246
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
2,368,589✔
1247
          continue;
93,787✔
1248
        }
1249

1250
        numOfElem += 1;
2,274,802✔
1251
        pStdRes->count += 1;
2,274,802✔
1252
        pStdRes->dsum += plist[i];
2,274,802✔
1253
        pStdRes->quadraticDSum += plist[i] * plist[i];
2,274,802✔
1254
      }
1255
      break;
17,939✔
1256
    }
1257

1258
    case TSDB_DATA_TYPE_DOUBLE: {
2,634,766✔
1259
      double* plist = (double*)pCol->pData;
2,634,766✔
1260
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
10,714,324✔
1261
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
8,079,558✔
1262
          continue;
163,234✔
1263
        }
1264

1265
        numOfElem += 1;
7,916,324✔
1266
        pStdRes->count += 1;
7,916,324✔
1267
        pStdRes->dsum += plist[i];
7,916,324✔
1268
        pStdRes->quadraticDSum += plist[i] * plist[i];
7,916,324✔
1269
      }
1270
      break;
2,634,766✔
1271
    }
1272

1273
    default:
×
1274
      break;
×
1275
  }
1276

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

1283
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
1,226,815✔
1284
  if (IS_NULL_TYPE(pInput->type)) {
1,226,815✔
1285
    return;
80✔
1286
  }
1287
  pOutput->type = pInput->type;
1,226,735✔
1288
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
1,226,735!
1289
    pOutput->quadraticISum += pInput->quadraticISum;
7,941✔
1290
    pOutput->isum += pInput->isum;
7,941✔
1291
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
1,218,794!
1292
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1293
    pOutput->usum += pInput->usum;
1✔
1294
  } else {
1295
    pOutput->quadraticDSum += pInput->quadraticDSum;
1,218,793✔
1296
    pOutput->dsum += pInput->dsum;
1,218,793✔
1297
  }
1298

1299
  pOutput->count += pInput->count;
1,226,735✔
1300
}
1301

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

1306
  if (IS_NULL_TYPE(pCol->info.type)) {
1,226,756!
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,226,756!
1312
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1313
  }
1314

1315
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,226,756✔
1316

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

1324
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
1,226,756✔
1325
  return TSDB_CODE_SUCCESS;
1,226,756✔
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) {
5,342,200✔
1396
  SInputColumnInfoData* pInput = &pCtx->input;
5,342,200✔
1397
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,342,200✔
1398
  int32_t               type = pStddevRes->type;
5,342,200✔
1399
  double                avg;
1400

1401
  if (pStddevRes->count == 0) {
5,342,200✔
1402
    GET_RES_INFO(pCtx)->numOfRes = 0;
40,931✔
1403
    return functionFinalize(pCtx, pBlock);
40,931✔
1404
  }
1405

1406
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
5,301,269!
1407
    avg = pStddevRes->isum / ((double)pStddevRes->count);
2,692,069✔
1408
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
2,692,069✔
1409
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,609,200!
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);
2,609,190✔
1414
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
2,609,190✔
1415
  }
1416

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

1422
  return functionFinalize(pCtx, pBlock);
5,301,269✔
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,235,024✔
1456
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,235,024✔
1457
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,235,024✔
1458
  int32_t              resultBytes = getStdInfoSize();
1,235,024✔
1459
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,235,024!
1460

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

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

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

1476
  taosMemoryFree(res);
1,235,023!
1477
  return code;
1,235,024✔
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) {
43,585✔
1496
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
43,585✔
1497
  return true;
43,585✔
1498
}
1499

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

1508
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,633,727✔
1509

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

1515
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
6,595,075✔
1516
  int32_t numOfElem = 0;
6,595,075✔
1517

1518
  SInputColumnInfoData* pInput = &pCtx->input;
6,595,075✔
1519
  int32_t               type = pInput->pData[0]->info.type;
6,595,075✔
1520

1521
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,595,075✔
1522

1523
  SColumnInfoData* pCol = pInput->pData[0];
6,595,075✔
1524

1525
  double(*param)[3] = pInfo->matrix;
6,595,075✔
1526
  double x = pInfo->startVal;
6,595,075✔
1527

1528
  int32_t start = pInput->startRowIndex;
6,595,075✔
1529
  int32_t numOfRows = pInput->numOfRows;
6,595,075✔
1530

1531
  switch (type) {
6,595,075!
1532
    case TSDB_DATA_TYPE_TINYINT: {
17,423✔
1533
      int8_t* plist = (int8_t*)pCol->pData;
17,423✔
1534
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
543,473✔
1535
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
526,050✔
1536
          continue;
1,860✔
1537
        }
1538
        numOfElem++;
524,190✔
1539
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
524,190✔
1540
      }
1541
      break;
17,423✔
1542
    }
1543
    case TSDB_DATA_TYPE_SMALLINT: {
4,551,372✔
1544
      int16_t* plist = (int16_t*)pCol->pData;
4,551,372✔
1545
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
17,378,318✔
1546
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
12,826,946✔
1547
          continue;
2,060✔
1548
        }
1549

1550
        numOfElem++;
12,824,886✔
1551
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
12,824,886✔
1552
      }
1553
      break;
4,551,372✔
1554
    }
1555

1556
    case TSDB_DATA_TYPE_INT: {
9,220✔
1557
      int32_t* plist = (int32_t*)pCol->pData;
9,220✔
1558
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
253,497✔
1559
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
244,277✔
1560
          continue;
3,272✔
1561
        }
1562

1563
        numOfElem++;
241,005✔
1564
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
241,005✔
1565
      }
1566
      break;
9,220✔
1567
    }
1568

1569
    case TSDB_DATA_TYPE_BIGINT: {
10,283✔
1570
      int64_t* plist = (int64_t*)pCol->pData;
10,283✔
1571
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,116,403✔
1572
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,106,120✔
1573
          continue;
2,860✔
1574
        }
1575

1576
        numOfElem++;
1,103,260✔
1577
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
1,103,260✔
1578
      }
1579
      break;
10,283✔
1580
    }
1581

1582
    case TSDB_DATA_TYPE_UTINYINT: {
144✔
1583
      uint8_t* plist = (uint8_t*)pCol->pData;
144✔
1584
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,564✔
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;
144✔
1592
    }
1593
    case TSDB_DATA_TYPE_USMALLINT: {
144✔
1594
      uint16_t* plist = (uint16_t*)pCol->pData;
144✔
1595
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,564✔
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;
144✔
1604
    }
1605

1606
    case TSDB_DATA_TYPE_UINT: {
144✔
1607
      uint32_t* plist = (uint32_t*)pCol->pData;
144✔
1608
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,564✔
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;
144✔
1617
    }
1618

1619
    case TSDB_DATA_TYPE_UBIGINT: {
144✔
1620
      uint64_t* plist = (uint64_t*)pCol->pData;
144✔
1621
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,564✔
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;
144✔
1630
    }
1631

1632
    case TSDB_DATA_TYPE_FLOAT: {
10,158✔
1633
      float* plist = (float*)pCol->pData;
10,158✔
1634
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
808,758✔
1635
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
798,600✔
1636
          continue;
138,968✔
1637
        }
1638

1639
        numOfElem++;
659,632✔
1640
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
659,632✔
1641
      }
1642
      break;
10,158✔
1643
    }
1644

1645
    case TSDB_DATA_TYPE_DOUBLE: {
1,996,050✔
1646
      double* plist = (double*)pCol->pData;
1,996,050✔
1647
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
6,570,420✔
1648
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
4,574,370✔
1649
          continue;
1,860✔
1650
        }
1651

1652
        numOfElem++;
4,572,510✔
1653
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
4,572,510✔
1654
      }
1655
      break;
1,996,050✔
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;
6,595,075✔
1668
  pInfo->num += numOfElem;
6,595,075✔
1669

1670
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,595,075✔
1671

1672
  return TSDB_CODE_SUCCESS;
6,595,075✔
1673
}
1674

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

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

1686
  if (0 == pInfo->num) {
5,625,240✔
1687
    colDataSetNULL(pCol, currentRow);
12,922!
1688
    return TSDB_CODE_SUCCESS;
12,922✔
1689
  }
1690

1691
  double(*param)[3] = pInfo->matrix;
5,612,318✔
1692

1693
  param[1][1] = (double)pInfo->num;
5,612,318✔
1694
  param[1][0] = param[0][1];
5,612,318✔
1695

1696
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
5,612,318✔
1697
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
5,612,318✔
1698

1699
  if (0 == param00) {
5,612,318✔
1700
    colDataSetNULL(pCol, currentRow);
4,044,694!
1701
    return TSDB_CODE_SUCCESS;
4,044,694✔
1702
  }
1703

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

1709
  param12 /= param[1][1];
1,567,624✔
1710

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

1726
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,567,636✔
1727

1728
  return code;
1,567,635✔
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) {
927✔
1754
  pEnv->calcMemSize = sizeof(SPercentileInfo);
927✔
1755
  return true;
927✔
1756
}
1757

1758
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,697✔
1759
  if (pResultInfo->initialized) {
4,697!
1760
    return TSDB_CODE_SUCCESS;
×
1761
  }
1762
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,697!
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,697✔
1768
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
4,697✔
1769
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
4,697✔
1770
  pInfo->numOfElems = 0;
4,697✔
1771

1772
  return TSDB_CODE_SUCCESS;
4,697✔
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,308,784✔
1787
  int32_t              code = TSDB_CODE_SUCCESS;
2,308,784✔
1788
  int32_t              numOfElems = 0;
2,308,784✔
1789
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,308,784✔
1790

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

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

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

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

1814
  // the first stage, only acquire the min/max value
1815
  if (pInfo->stage == 0) {
2,306,648✔
1816
    if (pCtx->input.colDataSMAIsSet) {
1,154,426✔
1817
      double tmin = 0.0, tmax = 0.0;
1,145,291✔
1818
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
1,145,291!
1819
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
1820
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
1821
      } else if (IS_FLOAT_TYPE(type)) {
1,145,291!
1822
        tmin = GET_DOUBLE_VAL(&pAgg->min);
1,145,291✔
1823
        tmax = GET_DOUBLE_VAL(&pAgg->max);
1,145,291✔
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,145,291✔
1830
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
14✔
1831
      }
1832

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

1837
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
1,145,291✔
1838
    } else {
1839
      // check the valid data one by one
1840
      int32_t start = pInput->startRowIndex;
9,135✔
1841
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,242,958✔
1842
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
14,233,823✔
1843
          continue;
2,800✔
1844
        }
1845

1846
        char* data = colDataGetData(pCol, i);
14,231,023!
1847

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

1854
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
14,231,023✔
1855
          SET_DOUBLE_VAL(&pInfo->maxval, v);
409,819✔
1856
        }
1857

1858
        pInfo->numOfElems += 1;
14,231,023✔
1859
      }
1860
    }
1861
  } else {
1862
    // the second stage, calculate the true percentile value
1863
    int32_t start = pInput->startRowIndex;
1,152,222✔
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,152,222!
1879
  }
1880

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

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

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

1892
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
4,697✔
1893
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
4,697!
1894
    if (pCtx->numOfParams > 2) {
2,561✔
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,527✔
1935

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

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

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

1950
_fin_error:
×
1951

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

1956
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
72,938✔
1957
  int32_t bytesHist =
72,938✔
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,938✔
1960
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
72,938✔
1961
  return true;
72,938✔
1962
}
1963

1964
int32_t getApercentileMaxSize() {
9,625✔
1965
  int32_t bytesHist =
9,625✔
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,625✔
1968
  return TMAX(bytesHist, bytesDigest);
9,625✔
1969
}
1970

1971
static int8_t getApercentileAlgo(char* algoStr) {
23,643✔
1972
  int8_t algoType;
1973
  if (strcasecmp(algoStr, "default") == 0) {
23,643✔
1974
    algoType = APERCT_ALGO_DEFAULT;
11,153✔
1975
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
12,490!
1976
    algoType = APERCT_ALGO_TDIGEST;
12,494✔
1977
  } else {
1978
    algoType = APERCT_ALGO_UNKNOWN;
×
1979
  }
1980

1981
  return algoType;
23,643✔
1982
}
1983

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

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

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

2001
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
331,090✔
2002

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

2007
  if (pCtx->numOfParams == 2) {
331,090✔
2008
    pInfo->algo = APERCT_ALGO_DEFAULT;
307,441✔
2009
  } else if (pCtx->numOfParams == 3) {
23,649✔
2010
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
23,646✔
2011
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
23,647!
2012
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2013
    }
2014
  }
2015

2016
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
331,091✔
2017
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
331,091✔
2018
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
12,497✔
2019
  } else {
2020
    buildHistogramInfo(pInfo);
318,594✔
2021
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
318,590✔
2022
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
318,596✔
2023
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2024
  }
2025

2026
  return TSDB_CODE_SUCCESS;
331,093✔
2027
}
2028

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

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

2037
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
335,983✔
2038

2039
  int32_t start = pInput->startRowIndex;
335,983✔
2040
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
335,983✔
2041
    buildTDigestInfo(pInfo);
12,476✔
2042
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
12,476✔
2043
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
979,823✔
2044
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
967,314✔
2045
        continue;
68,232✔
2046
      }
2047
      numOfElems += 1;
899,082✔
2048
      char* data = colDataGetData(pCol, i);
899,082!
2049

2050
      double  v = 0;  // value
899,082✔
2051
      int64_t w = 1;  // weigth
899,082✔
2052
      GET_TYPED_DATA(v, double, type, data);
899,082!
2053
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
899,082✔
2054
      if (code != TSDB_CODE_SUCCESS) {
899,115!
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);
323,507✔
2062
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
323,492✔
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) {
4,706,396✔
2066
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
4,382,964✔
2067
        continue;
382,544✔
2068
      }
2069
      numOfElems += 1;
4,000,420✔
2070
      char* data = colDataGetData(pCol, i);
4,000,420!
2071

2072
      double v = 0;
4,000,420✔
2073
      GET_TYPED_DATA(v, double, type, data);
4,000,420!
2074
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
4,000,420✔
2075
      if (code != TSDB_CODE_SUCCESS) {
4,000,359!
2076
        return code;
×
2077
      }
2078
    }
2079

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

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

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

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

2100
    if (hasRes) {
93✔
2101
      *hasRes = true;
91✔
2102
    }
2103

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

2108
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
93!
2109
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
91✔
2110
      tdigestAutoFill(pTDigest, COMPRESSION);
91✔
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);
8,281✔
2119
    if (pInput->pHisto->numOfElems <= 0) {
8,281✔
2120
      return TSDB_CODE_SUCCESS;
164✔
2121
    }
2122

2123
    if (hasRes) {
8,117✔
2124
      *hasRes = true;
8,115✔
2125
    }
2126

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2198
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
289,789✔
2199
    buildTDigestInfo(pInfo);
12,403✔
2200
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
12,402✔
2201
    if (pInfo->pTDigest->size > 0) {
12,401!
2202
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
12,401✔
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);
277,386✔
2209
    if (pInfo->pHisto->numOfElems > 0) {
277,383✔
2210
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
233,698✔
2211
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2212

2213
      double  ratio[] = {pInfo->percent};
233,698✔
2214
      double* res = NULL;
233,698✔
2215
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
233,698✔
2216
      if (TSDB_CODE_SUCCESS != code) {
233,703!
2217
        taosMemoryFree(res);
×
2218
        return code;
×
2219
      }
2220
      pInfo->result = *res;
233,703✔
2221
      // memcpy(pCtx->pOutput, res, sizeof(double));
2222
      taosMemoryFree(res);
233,703✔
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__,
43,685✔
2227
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2228
    }
2229
  }
2230

2231
  return functionFinalize(pCtx, pBlock);
289,798✔
2232
}
2233

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

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

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

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

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

2261
  taosMemoryFree(res);
8,051!
2262
  return code;
8,051✔
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) {
3,968✔
2285
  char numVal[8] = {0};
3,968✔
2286
  switch (pkType) {
3,968✔
2287
    case TSDB_DATA_TYPE_INT:
739✔
2288
      *(int32_t*)numVal = (int32_t)pVal->val;
739✔
2289
      break;
739✔
2290
    case TSDB_DATA_TYPE_UINT:
636✔
2291
      *(uint32_t*)numVal = (uint32_t)pVal->val;
636✔
2292
      break;
636✔
2293
    case TSDB_DATA_TYPE_BIGINT:
745✔
2294
      *(int64_t*)numVal = (int64_t)pVal->val;
745✔
2295
      break;
745✔
2296
    case TSDB_DATA_TYPE_UBIGINT:
708✔
2297
      *(uint64_t*)numVal = (uint64_t)pVal->val;
708✔
2298
      break;
708✔
2299
    default:
1,140✔
2300
      break;
1,140✔
2301
  }
2302
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
3,968!
2303
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
3,968✔
2304
  return fn(pkData, blockData);
3,968✔
2305
}
2306

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

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

2315
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
13,098✔
2316
  if (pResult->hasResult) {
13,098✔
2317
    if (pResult->pkBytes > 0) {
13,040✔
2318
      pResult->pkData = pResult->buf + pResult->bytes;
3,453✔
2319
    } else {
2320
      pResult->pkData = NULL;
9,587✔
2321
    }
2322
    if (pResult->ts < pBlockInfo->window.skey) {
13,040✔
2323
      return FUNC_DATA_REQUIRED_NOT_LOAD;
8,231✔
2324
    } else if (pResult->ts == pBlockInfo->window.skey) {
4,809✔
2325
      if (NULL == pResult->pkData) {
2,252✔
2326
        return FUNC_DATA_REQUIRED_NOT_LOAD;
194✔
2327
      }
2328
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
2,058✔
2329
        return FUNC_DATA_REQUIRED_NOT_LOAD;
396✔
2330
      }
2331
    }
2332
    return FUNC_DATA_REQUIRED_DATA_LOAD;
4,219✔
2333
  } else {
2334
    return FUNC_DATA_REQUIRED_DATA_LOAD;
58✔
2335
  }
2336
}
2337

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

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

2346
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
32,256✔
2347
  if (pResult->hasResult) {
32,256✔
2348
    if (pResult->pkBytes > 0) {
32,174✔
2349
      pResult->pkData = pResult->buf + pResult->bytes;
3,109✔
2350
    } else {
2351
      pResult->pkData = NULL;
29,065✔
2352
    }
2353
    if (pResult->ts > pBlockInfo->window.ekey) {
32,174✔
2354
      return FUNC_DATA_REQUIRED_NOT_LOAD;
27,944✔
2355
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
4,230✔
2356
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
1,911✔
2357
        return FUNC_DATA_REQUIRED_NOT_LOAD;
570✔
2358
      }
2359
    }
2360
    return FUNC_DATA_REQUIRED_DATA_LOAD;
3,659✔
2361
  } else {
2362
    return FUNC_DATA_REQUIRED_DATA_LOAD;
82✔
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; }
75,563,588✔
2368

2369
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,952,493✔
2370
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,952,493✔
2371
  // TODO: change SFunctionNode to add pk info
2372
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
1,954,650✔
2373
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
1,954,650✔
2374
  return true;
1,956,103✔
2375
}
2376

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

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

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

2394
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
374,966,727!
2395
}
2396

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

2405
  SFirstLastRes*        pRes = GET_ROWCELL_INTERBUF(pResInfo);
14,131,225✔
2406
  SInputColumnInfoData* pInput = &pCtx->input;
14,131,225✔
2407

2408
  pRes->nullTupleSaved = false;
14,131,225✔
2409
  pRes->nullTuplePos.pageId = -1;
14,131,225✔
2410
  return TSDB_CODE_SUCCESS;
14,131,225✔
2411
}
2412

2413
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
233,615,006✔
2414
  if (pCtx->subsidiaries.rowLen == 0) {
233,615,006✔
2415
    int32_t rowLen = 0;
658,114✔
2416
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,324,300✔
2417
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
666,186✔
2418
      rowLen += pc->pExpr->base.resSchema.bytes;
666,186✔
2419
    }
2420

2421
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
658,114✔
2422
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
658,114!
2423
    if (NULL == pCtx->subsidiaries.buf) {
657,476!
2424
      return terrno;
×
2425
    }
2426
  }
2427
  return TSDB_CODE_SUCCESS;
233,614,368✔
2428
}
2429

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

2434
  if (pCtx->subsidiaries.num <= 0) {
231,504,876✔
2435
    return TSDB_CODE_SUCCESS;
123,440,898✔
2436
  }
2437

2438
  if (!pInfo->hasResult) {
108,063,978✔
2439
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
86,102,542✔
2440
  } else {
2441
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
21,961,436✔
2442
  }
2443

2444
  return code;
107,993,393✔
2445
}
2446

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

2452
  if (IS_VAR_DATA_TYPE(type)) {
109,928,220!
2453
    if (type == TSDB_DATA_TYPE_JSON) {
11,108,824!
2454
      pInfo->bytes = getJsonValueLen(pData);
×
2455
    } else {
2456
      pInfo->bytes = varDataTLen(pData);
11,108,824✔
2457
    }
2458
  }
2459

2460
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
109,928,220✔
2461
  if (pkData != NULL) {
109,928,220✔
2462
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
1,146,106!
2463
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
371,833!
2464
        pInfo->pkBytes = getJsonValueLen(pkData);
×
2465
      } else {
2466
        pInfo->pkBytes = varDataTLen(pkData);
371,833✔
2467
      }
2468
    }
2469
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
1,146,106✔
2470
    pInfo->pkData = pInfo->buf + pInfo->bytes;
1,146,106✔
2471
  }
2472

2473
  pInfo->ts = currentTs;
109,928,220✔
2474
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
109,928,220✔
2475
  if (code != TSDB_CODE_SUCCESS) {
109,965,572!
2476
    return code;
×
2477
  }
2478

2479
  pInfo->hasResult = true;
109,965,572✔
2480
  return TSDB_CODE_SUCCESS;
109,965,572✔
2481
}
2482

2483
// This ordinary first function does not care if current scan is ascending order or descending order scan
2484
// the OPTIMIZED version of first function will only handle the ascending order scan
2485
int32_t firstFunction(SqlFunctionCtx* pCtx) {
52,925,364✔
2486
  int32_t numOfElems = 0;
52,925,364✔
2487

2488
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
52,925,364✔
2489
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
52,925,364✔
2490

2491
  SInputColumnInfoData* pInput = &pCtx->input;
52,925,364✔
2492
  SColumnInfoData*      pInputCol = pInput->pData[0];
52,925,364✔
2493

2494
  pInfo->bytes = pInputCol->info.bytes;
52,925,364✔
2495

2496
  if (IS_NULL_TYPE(pInputCol->info.type)) {
52,925,364✔
2497
    return TSDB_CODE_SUCCESS;
4,753✔
2498
  }
2499

2500
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
52,920,611✔
2501
  pInfo->pkType = -1;
52,920,611✔
2502
  __compar_fn_t pkCompareFn = NULL;
52,920,611✔
2503
  if (pCtx->hasPrimaryKey) {
52,920,611✔
2504
    pInfo->pkType = pkCol->info.type;
240,556✔
2505
    pInfo->pkBytes = pkCol->info.bytes;
240,556✔
2506
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
240,556✔
2507
  }
2508

2509
  // All null data column, return directly.
2510
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
52,978,415!
2511
      pInputCol->hasNull == true) {
×
2512
    // save selectivity value for column consisted of all null values
2513
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2514
    if (code != TSDB_CODE_SUCCESS) {
×
2515
      return code;
×
2516
    }
2517
    pInfo->nullTupleSaved = true;
×
2518
    return TSDB_CODE_SUCCESS;
×
2519
  }
2520

2521
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
52,978,415!
2522

2523
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
52,978,415✔
2524
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
52,978,415!
2525

2526
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
52,978,415✔
2527

2528
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
2529
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2530
#if 0
2531
  if (blockDataOrder == TSDB_ORDER_ASC) {
2532
    // filter according to current result firstly
2533
    if (pResInfo->numOfRes > 0) {
2534
      if (pInfo->ts < startKey) {
2535
        return TSDB_CODE_SUCCESS;
2536
      }
2537
    }
2538

2539
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2540
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2541
        continue;
2542
      }
2543

2544
      numOfElems++;
2545

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

2562
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2563
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2564
        continue;
2565
      }
2566

2567
      numOfElems++;
2568

2569
      char* data = colDataGetData(pInputCol, i);
2570
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2571

2572
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2573
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2574
        break;
2575
      }
2576
    }
2577
  }
2578
#else
2579
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
52,978,415✔
2580

2581
  int     from = -1;
52,978,415✔
2582
  int32_t i = -1;
52,978,415✔
2583
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
198,092,250✔
2584
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
199,646,175!
2585
      continue;
6,865,588✔
2586
    }
2587

2588
    numOfElems++;
138,326,940✔
2589
    char* data = colDataGetData(pInputCol, i);
138,326,940!
2590
    char* pkData = NULL;
138,326,940✔
2591
    if (pCtx->hasPrimaryKey) {
138,326,940✔
2592
      pkData = colDataGetData(pkCol, i);
1,130,746!
2593
    }
2594
    TSKEY cts = pts[i];
138,326,940✔
2595
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
138,326,940✔
2596
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
93,169,447!
2597
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
45,157,493✔
2598
      if (code != TSDB_CODE_SUCCESS) {
45,078,801!
2599
        return code;
×
2600
      }
2601
      pResInfo->numOfRes = 1;
45,078,801✔
2602
    }
2603
  }
2604
#endif
2605

2606
  if (numOfElems == 0) {
52,403,429✔
2607
    // save selectivity value for column consisted of all null values
2608
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
38,585✔
2609
    if (code != TSDB_CODE_SUCCESS) {
38,587!
2610
      return code;
×
2611
    }
2612
    pInfo->nullTupleSaved = true;
38,587✔
2613
  }
2614
  SET_VAL(pResInfo, numOfElems, 1);
52,403,431✔
2615
  return TSDB_CODE_SUCCESS;
52,403,431✔
2616
}
2617

2618
int32_t lastFunction(SqlFunctionCtx* pCtx) {
55,097,092✔
2619
  int32_t numOfElems = 0;
55,097,092✔
2620

2621
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
55,097,092✔
2622
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
55,097,092✔
2623

2624
  SInputColumnInfoData* pInput = &pCtx->input;
55,097,092✔
2625
  SColumnInfoData*      pInputCol = pInput->pData[0];
55,097,092✔
2626

2627
  int32_t type = pInputCol->info.type;
55,097,092✔
2628
  int32_t bytes = pInputCol->info.bytes;
55,097,092✔
2629
  pInfo->bytes = bytes;
55,097,092✔
2630

2631
  if (IS_NULL_TYPE(type)) {
55,097,092✔
2632
    return TSDB_CODE_SUCCESS;
4,753✔
2633
  }
2634

2635
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
55,092,339✔
2636
  pInfo->pkType = -1;
55,092,339✔
2637
  __compar_fn_t pkCompareFn = NULL;
55,092,339✔
2638
  if (pCtx->hasPrimaryKey) {
55,092,339✔
2639
    pInfo->pkType = pkCol->info.type;
288,567✔
2640
    pInfo->pkBytes = pkCol->info.bytes;
288,567✔
2641
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
288,567✔
2642
  }
2643

2644
  // All null data column, return directly.
2645
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
55,182,447!
2646
      pInputCol->hasNull == true) {
×
2647
    // save selectivity value for column consisted of all null values
2648
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2649
    if (code != TSDB_CODE_SUCCESS) {
×
2650
      return code;
×
2651
    }
2652
    pInfo->nullTupleSaved = true;
×
2653
    return TSDB_CODE_SUCCESS;
×
2654
  }
2655

2656
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
55,182,447!
2657

2658
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
55,182,447!
2659
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
55,182,447!
2660

2661
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
55,182,447✔
2662

2663
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2664
#if 0
2665
  if (blockDataOrder == TSDB_ORDER_ASC) {
2666
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2667
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2668
        continue;
2669
      }
2670

2671
      numOfElems++;
2672

2673
      char* data = colDataGetData(pInputCol, i);
2674
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2675
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2676
        doSaveCurrentVal(pCtx, i, cts, type, data);
2677
      }
2678

2679
      break;
2680
    }
2681
  } else {  // descending order
2682
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2683
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2684
        continue;
2685
      }
2686

2687
      numOfElems++;
2688

2689
      char* data = colDataGetData(pInputCol, i);
2690
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2691
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2692
        doSaveCurrentVal(pCtx, i, cts, type, data);
2693
      }
2694
      break;
2695
    }
2696
  }
2697
#else
2698
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
55,182,447✔
2699

2700
#if 0
2701
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2702
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2703
        continue;
2704
      }
2705

2706
      numOfElems++;
2707
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2708
        char* data = colDataGetData(pInputCol, i);
2709
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2710
        pResInfo->numOfRes = 1;
2711
      }
2712
    }
2713
#else
2714

2715
  // todo refactor
2716
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
87,367,799✔
2717
    numOfElems = 1;
32,225,106✔
2718

2719
    int32_t round = pInput->numOfRows >> 2;
32,225,106✔
2720
    int32_t reminder = pInput->numOfRows & 0x03;
32,225,106✔
2721

2722
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
51,374,753✔
2723
      int64_t cts = pts[i];
19,150,813✔
2724
      int32_t chosen = i;
19,150,813✔
2725

2726
      if (cts < pts[i + 1]) {
19,150,813✔
2727
        cts = pts[i + 1];
4,888,468✔
2728
        chosen = i + 1;
4,888,468✔
2729
      }
2730

2731
      if (cts < pts[i + 2]) {
19,150,813✔
2732
        cts = pts[i + 2];
4,888,667✔
2733
        chosen = i + 2;
4,888,667✔
2734
      }
2735

2736
      if (cts < pts[i + 3]) {
19,150,813✔
2737
        cts = pts[i + 3];
4,888,491✔
2738
        chosen = i + 3;
4,888,491✔
2739
      }
2740

2741
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
19,150,813✔
2742
        char*   data = colDataGetData(pInputCol, chosen);
4,487,078!
2743
        int32_t code = doSaveCurrentVal(pCtx, i, cts, NULL, type, data);
4,487,078✔
2744
        if (code != TSDB_CODE_SUCCESS) {
4,485,912!
2745
          return code;
×
2746
        }
2747
        pResInfo->numOfRes = 1;
4,485,912✔
2748
      }
2749
    }
2750

2751
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
73,400,780✔
2752
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
41,215,428✔
2753
        char*   data = colDataGetData(pInputCol, i);
24,342,028!
2754
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
24,342,028✔
2755
        if (code != TSDB_CODE_SUCCESS) {
24,303,440!
2756
          return code;
×
2757
        }
2758
        pResInfo->numOfRes = 1;
24,303,440✔
2759
      }
2760
    }
2761
  } else {
2762
    int     from = -1;
22,957,341✔
2763
    int32_t i = -1;
22,957,341✔
2764
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
248,829,120✔
2765
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
451,789,196✔
2766
        continue;
9,356,360✔
2767
      }
2768

2769
      numOfElems++;
216,538,238✔
2770
      char* pkData = NULL;
216,538,238✔
2771
      if (pCtx->hasPrimaryKey) {
216,538,238✔
2772
        pkData = colDataGetData(pkCol, i);
101,146,325!
2773
      }
2774
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
216,538,238✔
2775
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
180,902,392!
2776
        char*   data = colDataGetData(pInputCol, i);
35,929,740!
2777
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
35,929,740✔
2778
        if (code != TSDB_CODE_SUCCESS) {
35,906,920!
2779
          return code;
×
2780
        }
2781
        pResInfo->numOfRes = 1;
35,906,920✔
2782
      }
2783
    }
2784
  }
2785
#endif
2786

2787
#endif
2788

2789
  // save selectivity value for column consisted of all null values
2790
  if (numOfElems == 0) {
55,160,864✔
2791
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
4,090,369✔
2792
    if (code != TSDB_CODE_SUCCESS) {
4,081,667!
2793
      return code;
×
2794
    }
2795
    pInfo->nullTupleSaved = true;
4,081,667✔
2796
  }
2797

2798
  return TSDB_CODE_SUCCESS;
55,152,162✔
2799
}
2800

2801
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
70,018,431✔
2802
  if (!pInput->hasResult) {
70,018,431✔
2803
    return false;
2✔
2804
  }
2805
  __compar_fn_t pkCompareFn = NULL;
70,018,429✔
2806
  if (pInput->pkData) {
70,018,429✔
2807
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
22,892✔
2808
  }
2809
  if (pOutput->hasResult) {
70,021,208✔
2810
    if (isFirst) {
22,682,059✔
2811
      if (pInput->ts > pOutput->ts ||
8,583,786✔
2812
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,583,209✔
2813
        return false;
744✔
2814
      }
2815
    } else {
2816
      if (pInput->ts < pOutput->ts ||
14,098,273✔
2817
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
9,194,415✔
2818
        return false;
4,905,512✔
2819
      }
2820
    }
2821
  }
2822

2823
  pOutput->isNull = pInput->isNull;
65,114,952✔
2824
  pOutput->ts = pInput->ts;
65,114,952✔
2825
  pOutput->bytes = pInput->bytes;
65,114,952✔
2826
  pOutput->pkType = pInput->pkType;
65,114,952✔
2827

2828
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
65,114,952✔
2829
  if (pInput->pkData) {
65,114,952✔
2830
    pOutput->pkBytes = pInput->pkBytes;
21,486✔
2831
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
21,486✔
2832
    pOutput->pkData = pOutput->buf + pOutput->bytes;
21,486✔
2833
  }
2834
  return true;
65,114,952✔
2835
}
2836

2837
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
70,017,639✔
2838
                                     int32_t rowIndex) {
2839
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
70,017,639✔
2840
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
65,114,654✔
2841
    if (TSDB_CODE_SUCCESS != code) {
65,106,448!
2842
      return code;
×
2843
    }
2844
    pOutput->hasResult = true;
65,106,448✔
2845
  }
2846
  return TSDB_CODE_SUCCESS;
70,008,795✔
2847
}
2848

2849
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
47,372,657✔
2850
  SInputColumnInfoData* pInput = &pCtx->input;
47,372,657✔
2851
  SColumnInfoData*      pCol = pInput->pData[0];
47,372,657✔
2852

2853
  if (IS_NULL_TYPE(pCol->info.type)) {
47,372,657!
2854
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
2855
    return TSDB_CODE_SUCCESS;
×
2856
  }
2857

2858
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
47,372,657!
2859
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2860
  }
2861

2862
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
47,372,657✔
2863

2864
  int32_t start = pInput->startRowIndex;
47,372,657✔
2865
  int32_t numOfElems = 0;
47,372,657✔
2866

2867
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
119,671,748✔
2868
    if (colDataIsNull_s(pCol, i)) {
144,626,594✔
2869
      continue;
2,291,359✔
2870
    }
2871
    char*          data = colDataGetData(pCol, i);
70,021,938!
2872
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
70,021,938✔
2873
    if (pCtx->hasPrimaryKey) {
70,021,938✔
2874
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
22,892✔
2875
    } else {
2876
      pInputInfo->pkData = NULL;
69,999,046✔
2877
    }
2878

2879
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
70,021,938✔
2880
    if (code != TSDB_CODE_SUCCESS) {
70,007,732!
2881
      return code;
×
2882
    }
2883
    if (!numOfElems) {
70,007,732✔
2884
      numOfElems = pInputInfo->hasResult ? 1 : 0;
47,354,840✔
2885
    }
2886
  }
2887

2888
  if (numOfElems == 0) {
47,358,451✔
2889
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
14,013✔
2890
    if (code != TSDB_CODE_SUCCESS) {
14,013!
2891
      return code;
×
2892
    }
2893
    pInfo->nullTupleSaved = true;
14,013✔
2894
  }
2895

2896
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
47,358,451✔
2897
  return TSDB_CODE_SUCCESS;
47,358,451✔
2898
}
2899

2900
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
9,939,682✔
2901

2902
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
37,439,149✔
2903

2904
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
95,202,878✔
2905
  int32_t          code = TSDB_CODE_SUCCESS;
95,202,878✔
2906
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
95,202,878✔
2907
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
95,202,878✔
2908
  if (NULL == pCol) {
95,157,209!
2909
    return TSDB_CODE_OUT_OF_RANGE;
×
2910
  }
2911

2912
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
95,157,209✔
2913
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
95,157,209✔
2914

2915
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
95,157,209✔
2916

2917
  if (pResInfo->isNullRes) {
95,157,209✔
2918
    colDataSetNULL(pCol, pBlock->info.rows);
49,024✔
2919
    return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
49,024✔
2920
  }
2921
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
95,108,185!
2922
  if (TSDB_CODE_SUCCESS != code) {
94,895,826!
2923
    return code;
×
2924
  }
2925

2926
  // handle selectivity
2927
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
94,895,826✔
2928

2929
  return code;
94,880,119✔
2930
}
2931

2932
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
73,582,034✔
2933
  int32_t code = TSDB_CODE_SUCCESS;
73,582,034✔
2934

2935
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
73,582,034✔
2936
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
73,582,034✔
2937

2938
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
73,582,034✔
2939

2940
  // todo check for failure
2941
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
73,529,473!
2942
  if (NULL == res) {
74,569,686!
2943
    return terrno;
×
2944
  }
2945
  (void)memcpy(varDataVal(res), pRes, resultBytes);
74,569,686✔
2946

2947
  varDataSetLen(res, resultBytes);
74,569,686✔
2948

2949
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
74,569,686✔
2950
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
74,569,686✔
2951
  if (NULL == pCol) {
74,161,772!
2952
    taosMemoryFree(res);
×
2953
    return TSDB_CODE_OUT_OF_RANGE;
×
2954
  }
2955

2956
  if (pEntryInfo->numOfRes == 0) {
74,199,477✔
2957
    colDataSetNULL(pCol, pBlock->info.rows);
2,386,783!
2958
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
2,386,783✔
2959
  } else {
2960
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
71,812,694✔
2961
    if (TSDB_CODE_SUCCESS != code) {
71,104,336!
2962
      taosMemoryFree(res);
×
2963
      return code;
×
2964
    }
2965
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
71,104,336✔
2966
  }
2967
  taosMemoryFree(res);
73,441,784!
2968
  return code;
74,278,046✔
2969
}
2970

2971
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
2972
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
2973
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
2974
  int32_t              bytes = pDBuf->bytes;
3✔
2975

2976
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
2977
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
2978

2979
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
3✔
2980
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
2981
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
2982
  return TSDB_CODE_SUCCESS;
3✔
2983
}
2984

2985
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
52,476,674✔
2986
  SInputColumnInfoData* pInput = &pCtx->input;
52,476,674✔
2987
  SColumnInfoData*      pInputCol = pInput->pData[0];
52,476,674✔
2988
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
52,476,674✔
2989

2990
  if (colDataIsNull_s(pInputCol, rowIndex)) {
104,953,348✔
2991
    pInfo->isNull = true;
13,315✔
2992
  } else {
2993
    pInfo->isNull = false;
52,463,359✔
2994

2995
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
52,463,359!
2996
      if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
21,498!
2997
        pInfo->bytes = getJsonValueLen(pData);
×
2998
      } else {
2999
        pInfo->bytes = varDataTLen(pData);
21,498✔
3000
      }
3001
    }
3002

3003
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
52,463,359✔
3004
  }
3005

3006
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
52,531,030!
3007
    char* pkData = colDataGetData(pkCol, rowIndex);
54,357!
3008
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
54,357!
3009
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
18,006!
3010
        pInfo->pkBytes = getJsonValueLen(pkData);
×
3011
      } else {
3012
        pInfo->pkBytes = varDataTLen(pkData);
18,006✔
3013
      }
3014
    }
3015
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
54,357✔
3016
    pInfo->pkData = pInfo->buf + pInfo->bytes;
54,357✔
3017
  }
3018
  pInfo->ts = cts;
52,476,674✔
3019
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
52,476,674✔
3020
  if (code != TSDB_CODE_SUCCESS) {
52,474,437!
3021
    return code;
×
3022
  }
3023

3024
  pInfo->hasResult = true;
52,474,437✔
3025

3026
  return TSDB_CODE_SUCCESS;
52,474,437✔
3027
}
3028

3029
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
52,802,888✔
3030
  int32_t numOfElems = 0;
52,802,888✔
3031

3032
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
52,802,888✔
3033
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
52,802,888✔
3034

3035
  SInputColumnInfoData* pInput = &pCtx->input;
52,802,888✔
3036
  SColumnInfoData*      pInputCol = pInput->pData[0];
52,802,888✔
3037

3038
  int32_t type = pInputCol->info.type;
52,802,888✔
3039
  int32_t bytes = pInputCol->info.bytes;
52,802,888✔
3040
  pInfo->bytes = bytes;
52,802,888✔
3041

3042
  if (IS_NULL_TYPE(type)) {
52,802,888✔
3043
    return TSDB_CODE_SUCCESS;
24✔
3044
  }
3045
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
52,802,864✔
3046
  pInfo->pkType = -1;
52,802,864✔
3047
  __compar_fn_t pkCompareFn = NULL;
52,802,864✔
3048
  if (pCtx->hasPrimaryKey) {
52,802,864✔
3049
    pInfo->pkType = pkCol->info.type;
247,001✔
3050
    pInfo->pkBytes = pkCol->info.bytes;
247,001✔
3051
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
247,001✔
3052
  }
3053
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
52,809,445!
3054
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
52,809,445!
3055

3056
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
52,809,445!
3057
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
47,700,234!
3058
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
23,851,285✔
3059
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
23,851,285!
3060
      TSKEY cts = getRowPTs(pInput->pPTS, i);
23,851,285!
3061
      numOfElems++;
23,851,285✔
3062

3063
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
23,851,285✔
3064
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
23,605,376✔
3065
        if (code != TSDB_CODE_SUCCESS) return code;
23,603,365!
3066
      }
3067

3068
      break;
23,849,274✔
3069
    }
3070
  } else if (!pCtx->hasPrimaryKey && pCtx->order == TSDB_ORDER_DESC) {
28,958,485✔
3071
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3072
    // this assumption is NOT always works if project operator exists in downstream.
3073
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
57,466,227!
3074
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
28,744,197✔
3075
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
28,744,197!
3076
      TSKEY cts = getRowPTs(pInput->pPTS, i);
28,744,197!
3077
      numOfElems++;
28,744,197✔
3078

3079
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
28,744,197✔
3080
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
28,521,596✔
3081
        if (code != TSDB_CODE_SUCCESS) return code;
28,508,732!
3082
      }
3083
      break;
28,731,333✔
3084
    }
3085
  } else {
3086
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
223,591✔
3087
    int      from = -1;
223,591✔
3088
    int32_t  i = -1;
223,591✔
3089
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
1,791,165✔
3090
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
1,567,474✔
3091
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
1,567,474!
3092
      TSKEY cts = pts[i];
1,567,474✔
3093

3094
      numOfElems++;
1,567,474✔
3095
      char* pkData = NULL;
1,567,474✔
3096
      if (pCtx->hasPrimaryKey) {
1,567,474✔
3097
        pkData = colDataGetData(pkCol, i);
1,089,151!
3098
      }
3099
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
1,567,474✔
3100
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
1,215,003✔
3101
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
352,477✔
3102
        if (code != TSDB_CODE_SUCCESS) {
352,579!
3103
          return code;
×
3104
        }
3105
        pResInfo->numOfRes = 1;
352,579✔
3106
      }
3107
    }
3108
  }
3109

3110
  SET_VAL(pResInfo, numOfElems, 1);
52,818,270!
3111
  return TSDB_CODE_SUCCESS;
52,818,270✔
3112
}
3113

3114
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
29,384✔
3115
  pEnv->calcMemSize = sizeof(SDiffInfo);
29,384✔
3116
  return true;
29,384✔
3117
}
3118

3119
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,743,143✔
3120
  if (pResInfo->initialized) {
1,743,143✔
3121
    return TSDB_CODE_SUCCESS;
1,661,605✔
3122
  }
3123
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
81,538!
3124
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3125
  }
3126
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
81,538✔
3127
  pDiffInfo->hasPrev = false;
81,538✔
3128
  pDiffInfo->isFirstRow = true;
81,538✔
3129
  pDiffInfo->prev.i64 = 0;
81,538✔
3130
  pDiffInfo->prevTs = -1;
81,538✔
3131
  if (pCtx->numOfParams > 1) {
81,538!
3132
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
81,538✔
3133
  } else {
3134
    pDiffInfo->ignoreOption = 0;
×
3135
  }
3136
  return TSDB_CODE_SUCCESS;
81,538✔
3137
}
3138

3139
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
1,839,116✔
3140
  switch (type) {
1,839,116!
3141
    case TSDB_DATA_TYPE_BOOL:
28✔
3142
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
28✔
3143
      break;
28✔
3144
    case TSDB_DATA_TYPE_UTINYINT:
314✔
3145
    case TSDB_DATA_TYPE_TINYINT:
3146
      pDiffInfo->prev.i64 = *(int8_t*)pv;
314✔
3147
      break;
314✔
3148
    case TSDB_DATA_TYPE_UINT:
53,600✔
3149
    case TSDB_DATA_TYPE_INT:
3150
      pDiffInfo->prev.i64 = *(int32_t*)pv;
53,600✔
3151
      break;
53,600✔
3152
    case TSDB_DATA_TYPE_USMALLINT:
1,658,246✔
3153
    case TSDB_DATA_TYPE_SMALLINT:
3154
      pDiffInfo->prev.i64 = *(int16_t*)pv;
1,658,246✔
3155
      break;
1,658,246✔
3156
    case TSDB_DATA_TYPE_TIMESTAMP:
580✔
3157
    case TSDB_DATA_TYPE_UBIGINT:
3158
    case TSDB_DATA_TYPE_BIGINT:
3159
      pDiffInfo->prev.i64 = *(int64_t*)pv;
580✔
3160
      break;
580✔
3161
    case TSDB_DATA_TYPE_FLOAT:
239✔
3162
      pDiffInfo->prev.d64 = *(float*)pv;
239✔
3163
      break;
239✔
3164
    case TSDB_DATA_TYPE_DOUBLE:
126,109✔
3165
      pDiffInfo->prev.d64 = *(double*)pv;
126,109✔
3166
      break;
126,109✔
3167
    default:
×
3168
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3169
  }
3170
  pDiffInfo->prevTs = ts;
1,839,116✔
3171
  pDiffInfo->hasPrev = true;
1,839,116✔
3172
  return TSDB_CODE_SUCCESS;
1,839,116✔
3173
}
3174

3175
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
6,645,966✔
3176
  switch (type) {
6,645,966!
3177
    case TSDB_DATA_TYPE_UINT: {
×
3178
      int64_t v = *(uint32_t*)pv;
×
3179
      return v < pDiffInfo->prev.i64;
×
3180
    }
3181
    case TSDB_DATA_TYPE_INT: {
5,136✔
3182
      int64_t v = *(int32_t*)pv;
5,136✔
3183
      return v < pDiffInfo->prev.i64;
5,136✔
3184
    }
3185
    case TSDB_DATA_TYPE_BOOL: {
×
3186
      int64_t v = *(bool*)pv;
×
3187
      return v < pDiffInfo->prev.i64;
×
3188
    }
3189
    case TSDB_DATA_TYPE_UTINYINT: {
×
3190
      int64_t v = *(uint8_t*)pv;
×
3191
      return v < pDiffInfo->prev.i64;
×
3192
    }
3193
    case TSDB_DATA_TYPE_TINYINT: {
6,403✔
3194
      int64_t v = *(int8_t*)pv;
6,403✔
3195
      return v < pDiffInfo->prev.i64;
6,403✔
3196
    }
3197
    case TSDB_DATA_TYPE_USMALLINT: {
×
3198
      int64_t v = *(uint16_t*)pv;
×
3199
      return v < pDiffInfo->prev.i64;
×
3200
    }
3201
    case TSDB_DATA_TYPE_SMALLINT: {
6,204,941✔
3202
      int64_t v = *(int16_t*)pv;
6,204,941✔
3203
      return v < pDiffInfo->prev.i64;
6,204,941✔
3204
    }
3205
    case TSDB_DATA_TYPE_UBIGINT: {
24✔
3206
      uint64_t v = *(uint64_t*)pv;
24✔
3207
      return v < (uint64_t)pDiffInfo->prev.i64;
24✔
3208
    }
3209
    case TSDB_DATA_TYPE_TIMESTAMP:
6,712✔
3210
    case TSDB_DATA_TYPE_BIGINT: {
3211
      int64_t v = *(int64_t*)pv;
6,712✔
3212
      return v < pDiffInfo->prev.i64;
6,712✔
3213
    }
3214
    case TSDB_DATA_TYPE_FLOAT: {
5,774✔
3215
      float v = *(float*)pv;
5,774✔
3216
      return v < pDiffInfo->prev.d64;
5,774✔
3217
    }
3218
    case TSDB_DATA_TYPE_DOUBLE: {
416,976✔
3219
      double v = *(double*)pv;
416,976✔
3220
      return v < pDiffInfo->prev.d64;
416,976✔
3221
    }
3222
    default:
×
3223
      return false;
×
3224
  }
3225

3226
  return false;
3227
}
3228

3229
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
1,379,487,365✔
3230
  bool isNegative = v < pDiffInfo->prev.i64;
1,379,487,365✔
3231
  if (type == TSDB_DATA_TYPE_UBIGINT) {
1,379,487,365✔
3232
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
2,983✔
3233
  }
3234
  int64_t delta = v - pDiffInfo->prev.i64;
1,379,487,365✔
3235
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
1,379,487,365✔
3236
    colDataSetNull_f_s(pOutput, pos);
1,585,411✔
3237
    pOutput->hasNull = true;
1,585,411✔
3238
  } else {
3239
    colDataSetInt64(pOutput, pos, &delta);
1,377,901,954✔
3240
  }
3241
  pDiffInfo->prev.i64 = v;
1,379,487,365✔
3242
}
1,379,487,365✔
3243

3244
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
386,262✔
3245
  double delta = v - pDiffInfo->prev.d64;
386,262✔
3246
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
386,262✔
3247
    colDataSetNull_f_s(pOutput, pos);
66,934✔
3248
  } else {
3249
    colDataSetDouble(pOutput, pos, &delta);
319,328✔
3250
  }
3251
  pDiffInfo->prev.d64 = v;
386,262✔
3252
}
386,262✔
3253

3254
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
1,379,874,196✔
3255
                            int64_t ts) {
3256
  if (!pDiffInfo->hasPrev) {
1,379,874,196✔
3257
    colDataSetNull_f_s(pOutput, pos);
569✔
3258
    return doSetPrevVal(pDiffInfo, type, pv, ts);
569✔
3259
  }
3260
  pDiffInfo->prevTs = ts;
1,379,873,627✔
3261
  switch (type) {
1,379,873,627!
3262
    case TSDB_DATA_TYPE_UINT: {
2,941✔
3263
      int64_t v = *(uint32_t*)pv;
2,941✔
3264
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,941✔
3265
      break;
2,941✔
3266
    }
3267
    case TSDB_DATA_TYPE_INT: {
26,251,306✔
3268
      int64_t v = *(int32_t*)pv;
26,251,306✔
3269
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
26,251,306✔
3270
      break;
26,251,306✔
3271
    }
3272
    case TSDB_DATA_TYPE_BOOL: {
10,617✔
3273
      int64_t v = *(bool*)pv;
10,617✔
3274
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,617✔
3275
      break;
10,617✔
3276
    }
3277
    case TSDB_DATA_TYPE_UTINYINT: {
405✔
3278
      int64_t v = *(uint8_t*)pv;
405✔
3279
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3280
      break;
405✔
3281
    }
3282
    case TSDB_DATA_TYPE_TINYINT: {
35,621✔
3283
      int64_t v = *(int8_t*)pv;
35,621✔
3284
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
35,621✔
3285
      break;
35,621✔
3286
    }
3287
    case TSDB_DATA_TYPE_USMALLINT: {
405✔
3288
      int64_t v = *(uint16_t*)pv;
405✔
3289
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3290
      break;
405✔
3291
    }
3292
    case TSDB_DATA_TYPE_SMALLINT: {
4,599,610✔
3293
      int64_t v = *(int16_t*)pv;
4,599,610✔
3294
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,599,610✔
3295
      break;
4,599,610✔
3296
    }
3297
    case TSDB_DATA_TYPE_TIMESTAMP:
1,348,586,460✔
3298
    case TSDB_DATA_TYPE_UBIGINT:
3299
    case TSDB_DATA_TYPE_BIGINT: {
3300
      int64_t v = *(int64_t*)pv;
1,348,586,460✔
3301
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,348,586,460✔
3302
      break;
1,348,586,460✔
3303
    }
3304
    case TSDB_DATA_TYPE_FLOAT: {
48,449✔
3305
      double v = *(float*)pv;
48,449✔
3306
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
48,449✔
3307
      break;
48,449✔
3308
    }
3309
    case TSDB_DATA_TYPE_DOUBLE: {
337,813✔
3310
      double v = *(double*)pv;
337,813✔
3311
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
337,813✔
3312
      break;
337,813✔
3313
    }
3314
    default:
×
3315
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3316
  }
3317
  pDiffInfo->hasPrev = true;
1,379,873,627✔
3318
  return TSDB_CODE_SUCCESS;
1,379,873,627✔
3319
}
3320

3321
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3322
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3323
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
447,967,724✔
3324
                              int32_t* nextFrom) {
3325
  if (pInput->pPrimaryKey == NULL) {
447,967,724✔
3326
    if (from == -1) {
343,931,420✔
3327
      from = pInput->startRowIndex;
76,683,135✔
3328
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
267,248,285✔
3329
      return false;
76,291,819✔
3330
    }
3331
    *pRowIndex = from;
267,639,601✔
3332
    *nextFrom = from + 1;
267,639,601✔
3333
    return true;
267,639,601✔
3334
  } else {
3335
    if (from == -1) {
104,036,304✔
3336
      from = pInput->startRowIndex;
775,787✔
3337
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
103,260,517✔
3338
      return false;
775,726✔
3339
    }
3340
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
103,260,578✔
3341
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
103,260,578✔
3342
    int8_t           pkType = pkCol->info.type;
103,260,578✔
3343
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
103,260,578✔
3344
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
103,260,578✔
3345
    int32_t          select = from;
103,357,118✔
3346
    char*            val = colDataGetData(pkCol, select);
103,357,118!
3347
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
108,414,858✔
3348
      char* val1 = colDataGetData(pkCol, from + 1);
5,058,833!
3349
      if (compareFunc(val1, val) < 0) {
5,058,833✔
3350
        select = from + 1;
1,578,663✔
3351
        val = val1;
1,578,663✔
3352
      }
3353
      from = from + 1;
5,057,740✔
3354
    }
3355
    *pRowIndex = select;
103,356,025✔
3356
    *nextFrom = from + 1;
103,356,025✔
3357
    return true;
103,356,025✔
3358
  }
3359
}
3360

3361
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
26✔
3362
  pEnv->calcMemSize = sizeof(float);
26✔
3363
  return true;
26✔
3364
}
3365

3366
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,381,809,072✔
3367
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,381,809,072✔
3368
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,381,809,072✔
3369

3370
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
1,381,809,072✔
3371
    return true;
176,651✔
3372
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
1,381,632,421✔
3373
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
6,645,966✔
3374
  }
3375
  return false;
1,374,986,455✔
3376
}
3377

3378
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,380,036,731✔
3379
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,380,036,731✔
3380
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,380,036,731✔
3381
  return pDiffInfo->isFirstRow;
1,380,036,731✔
3382
}
3383

3384
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,840,367✔
3385
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,840,367✔
3386
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,840,367✔
3387
  pDiffInfo->isFirstRow = false;
1,840,367✔
3388
  if (pRow->isDataNull) {
1,840,367✔
3389
    return TSDB_CODE_SUCCESS;
1,820✔
3390
  }
3391

3392
  SInputColumnInfoData* pInput = &pCtx->input;
1,838,547✔
3393
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,838,547✔
3394
  int8_t                inputType = pInputCol->info.type;
1,838,547✔
3395

3396
  char* pv = pRow->pData;
1,838,547✔
3397
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
1,838,547✔
3398
}
3399

3400
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
1,379,968,705✔
3401
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,379,968,705✔
3402
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,379,968,705✔
3403

3404
  SInputColumnInfoData* pInput = &pCtx->input;
1,379,968,705✔
3405
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,379,968,705✔
3406
  int8_t                inputType = pInputCol->info.type;
1,379,968,705✔
3407
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
1,379,968,705✔
3408
  int32_t               code = TSDB_CODE_SUCCESS;
1,379,968,705✔
3409
  if (pRow->isDataNull) {
1,379,968,705✔
3410
    colDataSetNull_f_s(pOutput, pos);
94,488✔
3411
    pOutput->hasNull = true;
94,488✔
3412

3413
    // handle selectivity
3414
    if (pCtx->subsidiaries.num > 0) {
94,488✔
3415
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
774✔
3416
      if (code != TSDB_CODE_SUCCESS) {
774!
3417
        return code;
×
3418
      }
3419
    }
3420
    return TSDB_CODE_SUCCESS;
94,488✔
3421
  }
3422

3423
  char* pv = pRow->pData;
1,379,874,217✔
3424

3425
  if (pRow->ts == pDiffInfo->prevTs) {
1,379,874,217✔
3426
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
21✔
3427
  }
3428
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
1,379,874,196✔
3429
  if (code != TSDB_CODE_SUCCESS) {
1,379,874,196!
3430
    return code;
×
3431
  }
3432
  // handle selectivity
3433
  if (pCtx->subsidiaries.num > 0) {
1,379,874,196✔
3434
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
34,616,643✔
3435
    if (code != TSDB_CODE_SUCCESS) {
34,616,643!
3436
      return code;
×
3437
    }
3438
  }
3439

3440
  return TSDB_CODE_SUCCESS;
1,379,874,196✔
3441
}
3442

3443
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
1,713,759✔
3444

3445
int32_t diffFunctionByRow(SArray* pCtxArray) {
1,713,603✔
3446
  int32_t code = TSDB_CODE_SUCCESS;
1,713,603✔
3447
  int     diffColNum = pCtxArray->size;
1,713,603✔
3448
  if (diffColNum == 0) {
1,713,603!
3449
    return TSDB_CODE_SUCCESS;
×
3450
  }
3451
  int32_t numOfElems = 0;
1,713,603✔
3452

3453
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
1,713,603✔
3454
  if (NULL == pRows) {
1,713,603!
3455
    return terrno;
×
3456
  }
3457

3458
  bool keepNull = false;
1,713,603✔
3459
  for (int i = 0; i < diffColNum; ++i) {
3,427,362✔
3460
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,713,759✔
3461
    if (NULL == pCtx) {
1,713,759!
3462
      code = terrno;
×
3463
      goto _exit;
×
3464
    }
3465
    funcInputUpdate(pCtx);
1,713,759✔
3466
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,713,759✔
3467
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,713,759✔
3468
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
1,713,759✔
3469
      keepNull = true;
1,700,302✔
3470
    }
3471
  }
3472

3473
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
1,713,603✔
3474
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
1,713,603✔
3475
  if (NULL == pCtx0 || NULL == pRow0) {
1,713,603!
3476
    code = terrno;
×
3477
    goto _exit;
×
3478
  }
3479
  int32_t startOffset = pCtx0->offset;
1,713,603✔
3480
  bool    result = false;
1,713,603✔
3481
  while (1) {
1,381,794,557✔
3482
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
1,383,508,160✔
3483
    if (TSDB_CODE_SUCCESS != code) {
1,383,508,160!
3484
      goto _exit;
×
3485
    }
3486
    if (!result) {
1,383,508,160✔
3487
      break;
1,713,582✔
3488
    }
3489
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
1,381,794,578✔
3490
    for (int i = 1; i < diffColNum; ++i) {
1,381,809,072✔
3491
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
14,494✔
3492
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
14,494✔
3493
      if (NULL == pCtx || NULL == pRow) {
14,494!
3494
        code = terrno;
×
3495
        goto _exit;
×
3496
      }
3497
      code = funcInputGetNextRow(pCtx, pRow, &result);
14,494✔
3498
      if (TSDB_CODE_SUCCESS != code) {
14,494!
3499
        goto _exit;
×
3500
      }
3501
      if (!result) {
14,494!
3502
        // rows are not equal
3503
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3504
        goto _exit;
×
3505
      }
3506
      if (!diffResultIsNull(pCtx, pRow)) {
14,494✔
3507
        hasNotNullValue = true;
14,052✔
3508
      }
3509
    }
3510
    int32_t pos = startOffset + numOfElems;
1,381,794,578✔
3511

3512
    bool newRow = false;
1,381,794,578✔
3513
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3514
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,381,809,072✔
3515
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
1,381,809,072✔
3516
      if (NULL == pCtx || NULL == pRow) {
1,381,809,072!
3517
        code = terrno;
×
3518
        goto _exit;
×
3519
      }
3520
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
1,381,809,072✔
3521
        code = setDoDiffResult(pCtx, pRow, pos);
1,379,968,705✔
3522
        if (code != TSDB_CODE_SUCCESS) {
1,379,968,705✔
3523
          goto _exit;
21✔
3524
        }
3525
        newRow = true;
1,379,968,684✔
3526
      } else {
3527
        code = trySetPreVal(pCtx, pRow);
1,840,367✔
3528
        if (code != TSDB_CODE_SUCCESS) {
1,840,367!
3529
          goto _exit;
×
3530
        }
3531
      }
3532
    }
3533
    if (newRow) ++numOfElems;
1,381,794,557✔
3534
  }
3535

3536
  for (int i = 0; i < diffColNum; ++i) {
3,427,317✔
3537
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,713,735✔
3538
    if (NULL == pCtx) {
1,713,735!
3539
      code = terrno;
×
3540
      goto _exit;
×
3541
    }
3542
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,713,735✔
3543
    pResInfo->numOfRes = numOfElems;
1,713,735✔
3544
  }
3545

3546
_exit:
1,713,582✔
3547
  if (pRows) {
1,713,603!
3548
    taosArrayDestroy(pRows);
1,713,603✔
3549
    pRows = NULL;
1,713,603✔
3550
  }
3551
  return code;
1,713,603✔
3552
}
3553

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

3556
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
76,479✔
3557
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
76,479✔
3558
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
76,533✔
3559
  return true;
76,533✔
3560
}
3561

3562
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
31,592,448✔
3563
  if (pResInfo->initialized) {
31,592,448!
3564
    return TSDB_CODE_SUCCESS;
×
3565
  }
3566
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,592,448!
3567
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3568
  }
3569

3570
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
31,606,332✔
3571
  SInputColumnInfoData* pInput = &pCtx->input;
31,606,332✔
3572

3573
  pRes->maxSize = pCtx->param[1].param.i;
31,606,332✔
3574

3575
  pRes->nullTupleSaved = false;
31,606,332✔
3576
  pRes->nullTuplePos.pageId = -1;
31,606,332✔
3577
  return TSDB_CODE_SUCCESS;
31,606,332✔
3578
}
3579

3580
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
143,630,734✔
3581
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
143,630,734✔
3582
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
143,630,734✔
3583
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
143,630,734✔
3584

3585
  return pRes;
143,630,734✔
3586
}
3587

3588
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
3589
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
3590

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

3593
int32_t topFunction(SqlFunctionCtx* pCtx) {
2,792,680✔
3594
  int32_t              numOfElems = 0;
2,792,680✔
3595
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,792,680✔
3596

3597
  SInputColumnInfoData* pInput = &pCtx->input;
2,792,680✔
3598
  SColumnInfoData*      pCol = pInput->pData[0];
2,792,680✔
3599

3600
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
2,792,680✔
3601
  pRes->type = pInput->pData[0]->info.type;
2,792,682✔
3602

3603
  int32_t start = pInput->startRowIndex;
2,792,682✔
3604
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,902,068✔
3605
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
12,108,839✔
3606
      continue;
24,792✔
3607
    }
3608

3609
    numOfElems++;
12,084,047✔
3610
    char*   data = colDataGetData(pCol, i);
12,084,047!
3611
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
12,084,047✔
3612
    if (code != TSDB_CODE_SUCCESS) {
12,084,594!
3613
      return code;
×
3614
    }
3615
  }
3616

3617
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
2,793,229✔
3618
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
103✔
3619
    if (code != TSDB_CODE_SUCCESS) {
103!
3620
      return code;
×
3621
    }
3622
    pRes->nullTupleSaved = true;
103✔
3623
  }
3624
  return TSDB_CODE_SUCCESS;
2,793,229✔
3625
}
3626

3627
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
29,375,053✔
3628
  int32_t              numOfElems = 0;
29,375,053✔
3629
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
29,375,053✔
3630

3631
  SInputColumnInfoData* pInput = &pCtx->input;
29,375,053✔
3632
  SColumnInfoData*      pCol = pInput->pData[0];
29,375,053✔
3633

3634
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
29,375,053✔
3635
  pRes->type = pInput->pData[0]->info.type;
29,374,460✔
3636

3637
  int32_t start = pInput->startRowIndex;
29,374,460✔
3638
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
97,422,019✔
3639
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
68,037,723✔
3640
      continue;
32,449✔
3641
    }
3642

3643
    numOfElems++;
68,005,274✔
3644
    char*   data = colDataGetData(pCol, i);
68,005,274!
3645
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
68,005,274✔
3646
    if (code != TSDB_CODE_SUCCESS) {
68,015,110!
3647
      return code;
×
3648
    }
3649
  }
3650

3651
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
29,384,296✔
3652
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
148✔
3653
    if (code != TSDB_CODE_SUCCESS) {
148!
3654
      return code;
×
3655
    }
3656
    pRes->nullTupleSaved = true;
148✔
3657
  }
3658

3659
  return TSDB_CODE_SUCCESS;
29,384,296✔
3660
}
3661

3662
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
380,772,027✔
3663
  uint16_t type = *(uint16_t*)param;
380,772,027✔
3664

3665
  STopBotResItem* val1 = (STopBotResItem*)p1;
380,772,027✔
3666
  STopBotResItem* val2 = (STopBotResItem*)p2;
380,772,027✔
3667

3668
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
380,772,027!
3669
    if (val1->v.i == val2->v.i) {
218,806,158✔
3670
      return 0;
218,370✔
3671
    }
3672

3673
    return (val1->v.i > val2->v.i) ? 1 : -1;
218,587,788✔
3674
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
161,965,869!
3675
    if (val1->v.u == val2->v.u) {
674,015✔
3676
      return 0;
144,426✔
3677
    }
3678

3679
    return (val1->v.u > val2->v.u) ? 1 : -1;
529,589✔
3680
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
161,291,854✔
3681
    if (val1->v.f == val2->v.f) {
20,585,295✔
3682
      return 0;
63✔
3683
    }
3684

3685
    return (val1->v.f > val2->v.f) ? 1 : -1;
20,585,232✔
3686
  }
3687

3688
  if (val1->v.d == val2->v.d) {
140,706,559✔
3689
    return 0;
11✔
3690
  }
3691

3692
  return (val1->v.d > val2->v.d) ? 1 : -1;
140,706,548✔
3693
}
3694

3695
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
80,096,193✔
3696
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3697
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
80,096,193✔
3698
  int32_t     code = TSDB_CODE_SUCCESS;
80,091,235✔
3699

3700
  SVariant val = {0};
80,091,235✔
3701
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
80,091,235!
3702

3703
  STopBotResItem* pItems = pRes->pItems;
80,106,654✔
3704

3705
  // not full yet
3706
  if (pEntryInfo->numOfRes < pRes->maxSize) {
80,106,654✔
3707
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
53,739,856✔
3708
    pItem->v = val;
53,739,856✔
3709
    pItem->uid = uid;
53,739,856✔
3710

3711
    // save the data of this tuple
3712
    if (pCtx->subsidiaries.num > 0) {
53,739,856✔
3713
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
20,506,856✔
3714
      if (code != TSDB_CODE_SUCCESS) {
20,506,021!
3715
        return code;
×
3716
      }
3717
    }
3718
#ifdef BUF_PAGE_DEBUG
3719
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3720
           pItem->tuplePos.offset);
3721
#endif
3722
    // allocate the buffer and keep the data of this row into the new allocated buffer
3723
    pEntryInfo->numOfRes++;
53,739,021✔
3724
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
53,739,021✔
3725
                        topBotResComparFn, !isTopQuery);
53,739,021✔
3726
    if (code != TSDB_CODE_SUCCESS) {
53,747,735!
3727
      return code;
×
3728
    }
3729
  } else {  // replace the minimum value in the result
3730
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
26,366,798✔
3731
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
6,766,313!
3732
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
6,672,886✔
3733
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
6,033,052✔
3734
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
24,750,885!
3735
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
15,027,445✔
3736
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
15,024,803✔
3737
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
15,024,027✔
3738
      // replace the old data and the coresponding tuple data
3739
      STopBotResItem* pItem = &pItems[0];
6,864,908✔
3740
      pItem->v = val;
6,864,908✔
3741
      pItem->uid = uid;
6,864,908✔
3742

3743
      // save the data of this tuple by over writing the old data
3744
      if (pCtx->subsidiaries.num > 0) {
6,864,908✔
3745
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
3,985,685✔
3746
        if (code != TSDB_CODE_SUCCESS) {
3,984,818!
3747
          return code;
×
3748
        }
3749
      }
3750
#ifdef BUF_PAGE_DEBUG
3751
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3752
#endif
3753
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
6,864,041✔
3754
                            topBotResComparFn, NULL, !isTopQuery);
6,864,041✔
3755
      if (code != TSDB_CODE_SUCCESS) {
6,847,417!
3756
        return code;
×
3757
      }
3758
    }
3759
  }
3760

3761
  return TSDB_CODE_SUCCESS;
80,097,042✔
3762
}
3763

3764
/*
3765
 * +------------------------------------+--------------+--------------+
3766
 * |            null bitmap             |              |              |
3767
 * |(n columns, one bit for each column)| src column #1| src column #2|
3768
 * +------------------------------------+--------------+--------------+
3769
 */
3770
int32_t serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
233,608,889✔
3771
                           char* buf, char** res) {
3772
  char* nullList = buf;
233,608,889✔
3773
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
233,608,889✔
3774

3775
  int32_t offset = 0;
233,608,889✔
3776
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
467,135,381✔
3777
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
233,703,080✔
3778

3779
    // group_key function has its own process function
3780
    // do not process there
3781
    if (fmIsGroupKeyFunc(pc->functionId)) {
233,703,080✔
3782
      continue;
8,380,147✔
3783
    }
3784

3785
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
225,301,488✔
3786
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
225,301,488✔
3787

3788
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
225,301,488✔
3789
    if (NULL == pCol) {
225,146,345!
3790
      return TSDB_CODE_OUT_OF_RANGE;
×
3791
    }
3792
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
450,292,690✔
3793
      offset += pCol->info.bytes;
327✔
3794
      continue;
327✔
3795
    }
3796

3797
    char* p = colDataGetData(pCol, rowIndex);
225,146,018!
3798
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
225,146,018!
3799
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
42,624!
3800
    } else {
3801
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
225,103,394✔
3802
    }
3803

3804
    offset += pCol->info.bytes;
225,146,018✔
3805
  }
3806

3807
  *res = buf;
233,432,301✔
3808
  return TSDB_CODE_SUCCESS;
233,432,301✔
3809
}
3810

3811
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
316,838,176✔
3812
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3813
  STuplePos p = {0};
316,838,176✔
3814
  if (pHandle->pBuf != NULL) {
316,838,176✔
3815
    SFilePage* pPage = NULL;
316,779,102✔
3816

3817
    if (pHandle->currentPage == -1) {
316,779,102✔
3818
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
666,687✔
3819
      if (pPage == NULL) {
666,702✔
3820
        return terrno;
4✔
3821
      }
3822
      pPage->num = sizeof(SFilePage);
666,698✔
3823
    } else {
3824
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
316,112,415✔
3825
      if (pPage == NULL) {
316,106,425!
3826
        return terrno;
×
3827
      }
3828
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
316,106,425✔
3829
        // current page is all used, let's prepare a new buffer page
3830
        releaseBufPage(pHandle->pBuf, pPage);
2,481,082✔
3831
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
2,481,080✔
3832
        if (pPage == NULL) {
2,481,082!
3833
          return terrno;
×
3834
        }
3835
        pPage->num = sizeof(SFilePage);
2,481,082✔
3836
      }
3837
    }
3838

3839
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
316,766,415✔
3840
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
316,766,415✔
3841

3842
    pPage->num += length;
316,766,415✔
3843
    setBufPageDirty(pPage, true);
316,766,415✔
3844
    releaseBufPage(pHandle->pBuf, pPage);
316,768,606✔
3845
  } else {  // other tuple save policy
3846
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
59,074!
3847
      p.streamTupleKey = *key;
71,971✔
3848
    }
3849
  }
3850

3851
  *pPos = p;
316,778,407✔
3852
  return TSDB_CODE_SUCCESS;
316,778,407✔
3853
}
3854

3855
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
200,164,557✔
3856
  int32_t code = prepareBuf(pCtx);
200,164,557✔
3857
  if (TSDB_CODE_SUCCESS != code) {
200,152,215!
3858
    return code;
×
3859
  }
3860

3861
  SWinKey key = {0};
200,152,215✔
3862
  if (pCtx->saveHandle.pBuf == NULL) {
200,152,215✔
3863
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
71,973✔
3864
    if (NULL == pColInfo) {
71,973!
3865
      return TSDB_CODE_OUT_OF_RANGE;
×
3866
    }
3867
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
71,973!
3868
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3869
    }
3870
    key.groupId = pSrcBlock->info.id.groupId;
71,973✔
3871
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
71,973!
3872
  }
3873

3874
  char* buf = NULL;
200,152,215✔
3875
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
200,152,215✔
3876
  if (TSDB_CODE_SUCCESS != code) {
200,077,557!
3877
    return code;
×
3878
  }
3879
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
200,077,557✔
3880
}
3881

3882
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
33,481,107✔
3883
                                 SFunctionStateStore* pStore) {
3884
  if (pHandle->pBuf != NULL) {
33,481,107✔
3885
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
33,356,328✔
3886
    if (pPage == NULL) {
33,356,158!
3887
      return terrno;
×
3888
    }
3889
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
33,356,158✔
3890
    setBufPageDirty(pPage, true);
33,356,158✔
3891
    releaseBufPage(pHandle->pBuf, pPage);
33,355,350✔
3892
  } else {
3893
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
124,779✔
3894
    if (TSDB_CODE_SUCCESS != code) {
124,902!
3895
      return code;
×
3896
    }
3897
  }
3898

3899
  return TSDB_CODE_SUCCESS;
33,478,586✔
3900
}
3901

3902
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
33,483,656✔
3903
  int32_t code = prepareBuf(pCtx);
33,483,656✔
3904
  if (TSDB_CODE_SUCCESS != code) {
33,483,444!
3905
    return code;
×
3906
  }
3907

3908
  char* buf = NULL;
33,483,444✔
3909
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
33,483,444✔
3910
  if (TSDB_CODE_SUCCESS != code) {
33,481,060!
3911
    return code;
×
3912
  }
3913
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
33,481,060✔
3914
}
3915

3916
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
121,574,131✔
3917
                               char** value) {
3918
  if (pHandle->pBuf != NULL) {
121,574,131✔
3919
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
121,506,379✔
3920
    if (pPage == NULL) {
121,680,251!
3921
      *value = NULL;
×
3922
      return terrno;
×
3923
    }
3924
    *value = pPage->data + pPos->offset;
121,680,251✔
3925
    releaseBufPage(pHandle->pBuf, pPage);
121,680,251✔
3926
    return TSDB_CODE_SUCCESS;
121,648,971✔
3927
  } else {
3928
    *value = NULL;
67,752✔
3929
    int32_t vLen;
3930
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
67,752✔
3931
    if (TSDB_CODE_SUCCESS != code) {
72,322!
3932
      return code;
×
3933
    }
3934
    return TSDB_CODE_SUCCESS;
72,322✔
3935
  }
3936
}
3937

3938
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
121,434,428✔
3939
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
121,434,428✔
3940
}
3941

3942
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
31,465,144✔
3943
  int32_t code = TSDB_CODE_SUCCESS;
31,465,144✔
3944

3945
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
31,465,144✔
3946
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
31,465,144✔
3947

3948
  int16_t type = pCtx->pExpr->base.resSchema.type;
31,464,170✔
3949
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
31,464,170✔
3950

3951
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
31,464,170✔
3952
  if (NULL == pCol) {
31,454,710!
3953
    return TSDB_CODE_OUT_OF_RANGE;
×
3954
  }
3955

3956
  // todo assign the tag value and the corresponding row data
3957
  int32_t currentRow = pBlock->info.rows;
31,454,710✔
3958
  if (pEntryInfo->numOfRes <= 0) {
31,454,710✔
3959
    colDataSetNULL(pCol, currentRow);
596!
3960
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
596✔
3961
    return code;
596✔
3962
  }
3963
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
84,736,911✔
3964
    STopBotResItem* pItem = &pRes->pItems[i];
53,308,899✔
3965
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
53,308,899✔
3966
    if (TSDB_CODE_SUCCESS != code) {
53,284,910!
3967
      return code;
×
3968
    }
3969
#ifdef BUF_PAGE_DEBUG
3970
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3971
           pItem->tuplePos.offset);
3972
#endif
3973
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
53,284,910✔
3974
    if (TSDB_CODE_SUCCESS != code) {
53,282,797!
3975
      return code;
×
3976
    }
3977
    currentRow += 1;
53,282,797✔
3978
  }
3979

3980
  return code;
31,428,012✔
3981
}
3982

3983
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
3984
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
3985
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
3986
  STopBotResItem*      pItems = pRes->pItems;
×
3987
  int32_t              code = TSDB_CODE_SUCCESS;
×
3988

3989
  // not full yet
3990
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
3991
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
3992
    pItem->v = pSourceItem->v;
×
3993
    pItem->uid = pSourceItem->uid;
×
3994
    pItem->tuplePos.pageId = -1;
×
3995
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
3996
    pEntryInfo->numOfRes++;
×
3997
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
3998
                        topBotResComparFn, !isTopQuery);
×
3999
    if (TSDB_CODE_SUCCESS != code) {
×
4000
      return code;
×
4001
    }
4002
  } else {  // replace the minimum value in the result
4003
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
4004
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
4005
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
4006
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
4007
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
4008
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
4009
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
4010
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
4011
      // replace the old data and the coresponding tuple data
4012
      STopBotResItem* pItem = &pItems[0];
×
4013
      pItem->v = pSourceItem->v;
×
4014
      pItem->uid = pSourceItem->uid;
×
4015

4016
      // save the data of this tuple by over writing the old data
4017
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4018
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4019
                            topBotResComparFn, NULL, !isTopQuery);
×
4020
      if (TSDB_CODE_SUCCESS != code) {
×
4021
        return code;
×
4022
      }
4023
    }
4024
  }
4025
  return code;
×
4026
}
4027

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

4042
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4043
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4044
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4045
  int16_t              type = pSBuf->type;
×
4046
  int32_t              code = TSDB_CODE_SUCCESS;
×
4047
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4048
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4049
    if (TSDB_CODE_SUCCESS != code) {
×
4050
      return code;
×
4051
    }
4052
  }
4053
  return TSDB_CODE_SUCCESS;
×
4054
}
4055

4056
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
768,125✔
4057

4058
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
102,467✔
4059
  pEnv->calcMemSize = sizeof(SSpreadInfo);
102,467✔
4060
  return true;
102,467✔
4061
}
4062

4063
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,793,809✔
4064
  if (pResultInfo->initialized) {
2,793,809!
4065
    return TSDB_CODE_SUCCESS;
×
4066
  }
4067
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,793,809!
4068
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4069
  }
4070

4071
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
2,793,849✔
4072
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
2,793,849✔
4073
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
2,793,849✔
4074
  pInfo->hasResult = false;
2,793,849✔
4075
  return TSDB_CODE_SUCCESS;
2,793,849✔
4076
}
4077

4078
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
2,077,879✔
4079
  int32_t numOfElems = 0;
2,077,879✔
4080

4081
  // Only the pre-computing information loaded and actual data does not loaded
4082
  SInputColumnInfoData* pInput = &pCtx->input;
2,077,879✔
4083
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,077,879✔
4084
  int32_t               type = pInput->pData[0]->info.type;
2,077,879✔
4085

4086
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,077,879✔
4087

4088
  if (pInput->colDataSMAIsSet) {
2,077,879!
4089
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
×
4090
    if (numOfElems == 0) {
×
4091
      goto _spread_over;
×
4092
    }
4093
    double tmin = 0.0, tmax = 0.0;
×
4094
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
×
4095
      tmin = (double)GET_INT64_VAL(&pAgg->min);
×
4096
      tmax = (double)GET_INT64_VAL(&pAgg->max);
×
4097
    } else if (IS_FLOAT_TYPE(type)) {
×
4098
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4099
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4100
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
4101
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
4102
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
4103
    }
4104

4105
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
×
4106
      SET_DOUBLE_VAL(&pInfo->min, tmin);
×
4107
    }
4108

4109
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
×
4110
      SET_DOUBLE_VAL(&pInfo->max, tmax);
×
4111
    }
4112

4113
  } else {  // computing based on the true data block
4114
    SColumnInfoData* pCol = pInput->pData[0];
2,077,879✔
4115

4116
    int32_t start = pInput->startRowIndex;
2,077,879✔
4117
    // check the valid data one by one
4118
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
11,536,450✔
4119
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
9,458,571✔
4120
        continue;
945,682✔
4121
      }
4122

4123
      char* data = colDataGetData(pCol, i);
8,512,889!
4124

4125
      double v = 0;
8,512,889✔
4126
      GET_TYPED_DATA(v, double, type, data);
8,512,889!
4127
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
8,512,889✔
4128
        SET_DOUBLE_VAL(&pInfo->min, v);
2,110,808✔
4129
      }
4130

4131
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
8,512,889✔
4132
        SET_DOUBLE_VAL(&pInfo->max, v);
4,357,886✔
4133
      }
4134

4135
      numOfElems += 1;
8,512,889✔
4136
    }
4137
  }
4138

4139
_spread_over:
2,077,879✔
4140
  // data in the check operation are all null, not output
4141
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,077,879✔
4142
  if (numOfElems > 0) {
2,077,879✔
4143
    pInfo->hasResult = true;
2,061,891✔
4144
  }
4145

4146
  return TSDB_CODE_SUCCESS;
2,077,879✔
4147
}
4148

4149
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
766,590✔
4150
  pOutput->hasResult = pInput->hasResult;
766,590✔
4151
  if (pInput->max > pOutput->max) {
766,590✔
4152
    pOutput->max = pInput->max;
762,051✔
4153
  }
4154

4155
  if (pInput->min < pOutput->min) {
766,590✔
4156
    pOutput->min = pInput->min;
762,071✔
4157
  }
4158
}
766,590✔
4159

4160
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
762,654✔
4161
  SInputColumnInfoData* pInput = &pCtx->input;
762,654✔
4162
  SColumnInfoData*      pCol = pInput->pData[0];
762,654✔
4163

4164
  if (IS_NULL_TYPE(pCol->info.type)) {
762,654!
4165
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4166
    return TSDB_CODE_SUCCESS;
×
4167
  }
4168

4169
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
762,654!
4170
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4171
  }
4172

4173
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
762,654✔
4174

4175
  int32_t start = pInput->startRowIndex;
762,654✔
4176
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,529,485✔
4177
    if (colDataIsNull_s(pCol, i)) continue;
1,533,662!
4178
    char*        data = colDataGetData(pCol, i);
766,831!
4179
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
766,831✔
4180
    if (pInputInfo->hasResult) {
766,831✔
4181
      spreadTransferInfo(pInputInfo, pInfo);
766,589✔
4182
    }
4183
  }
4184

4185
  if (pInfo->hasResult) {
762,654✔
4186
    GET_RES_INFO(pCtx)->numOfRes = 1;
762,484✔
4187
  }
4188

4189
  return TSDB_CODE_SUCCESS;
762,654✔
4190
}
4191

4192
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,009,454✔
4193
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,009,454✔
4194
  if (pInfo->hasResult == true) {
2,009,454✔
4195
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
1,993,909✔
4196
  } else {
4197
    GET_RES_INFO(pCtx)->isNullRes = 1;
15,545✔
4198
  }
4199
  return functionFinalize(pCtx, pBlock);
2,009,454✔
4200
}
4201

4202
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
766,625✔
4203
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
766,625✔
4204
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
766,625✔
4205
  int32_t              resultBytes = getSpreadInfoSize();
766,625✔
4206
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
766,625!
4207

4208
  if (NULL == res) {
766,625!
4209
    return terrno;
×
4210
  }
4211
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
766,625✔
4212
  varDataSetLen(res, resultBytes);
766,625✔
4213

4214
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
766,625✔
4215
  int32_t          code = TSDB_CODE_SUCCESS;
766,625✔
4216
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
766,625✔
4217
  if (NULL == pCol) {
766,625!
4218
    code = terrno;
×
4219
    goto _exit;
×
4220
  }
4221

4222
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
766,625✔
4223
  if (TSDB_CODE_SUCCESS != code) {
766,624!
4224
    goto _exit;
×
4225
  }
4226

4227
_exit:
766,624✔
4228
  taosMemoryFree(res);
766,624!
4229
  return code;
766,625✔
4230
}
4231

4232
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
4233
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
4234
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
4235

4236
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
4237
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
4238
  spreadTransferInfo(pSBuf, pDBuf);
1✔
4239
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
4240
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
4241
  return TSDB_CODE_SUCCESS;
1✔
4242
}
4243

4244
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4245

4246
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
103,742✔
4247
  pEnv->calcMemSize = sizeof(SElapsedInfo);
103,742✔
4248
  return true;
103,742✔
4249
}
4250

4251
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
11,843,587✔
4252
  if (pResultInfo->initialized) {
11,843,587!
4253
    return TSDB_CODE_SUCCESS;
×
4254
  }
4255
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
11,843,587!
4256
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4257
  }
4258

4259
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
11,843,597✔
4260
  pInfo->result = 0;
11,843,597✔
4261
  pInfo->min = TSKEY_MAX;
11,843,597✔
4262
  pInfo->max = 0;
11,843,597✔
4263

4264
  if (pCtx->numOfParams > 1) {
11,843,597✔
4265
    pInfo->timeUnit = pCtx->param[1].param.i;
24,143✔
4266
  } else {
4267
    pInfo->timeUnit = 1;
11,819,454✔
4268
  }
4269

4270
  return TSDB_CODE_SUCCESS;
11,843,597✔
4271
}
4272

4273
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
11,865,724✔
4274
  int32_t numOfElems = 0;
11,865,724✔
4275

4276
  // Only the pre-computing information loaded and actual data does not loaded
4277
  SInputColumnInfoData* pInput = &pCtx->input;
11,865,724✔
4278
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
11,865,724✔
4279

4280
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
11,865,724✔
4281

4282
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
11,865,724✔
4283
  if (numOfElems == 0) {
11,865,724✔
4284
    // for stream
4285
    if (pCtx->end.key != INT64_MIN) {
1,660✔
4286
      pInfo->max = pCtx->end.key + 1;
56✔
4287
    }
4288
    goto _elapsed_over;
1,660✔
4289
  }
4290

4291
  if (pInput->colDataSMAIsSet) {
11,864,064!
4292
    if (pInfo->min == TSKEY_MAX) {
×
4293
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4294
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4295
    } else {
4296
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4297
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4298
      } else {
4299
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4300
      }
4301
    }
4302
  } else {  // computing based on the true data block
4303
    if (0 == pInput->numOfRows) {
11,864,064!
4304
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4305
        if (pCtx->end.key != INT64_MIN) {
×
4306
          pInfo->min = pCtx->end.key;
×
4307
        }
4308
      } else {
4309
        if (pCtx->end.key != INT64_MIN) {
×
4310
          pInfo->max = pCtx->end.key + 1;
×
4311
        }
4312
      }
4313
      goto _elapsed_over;
×
4314
    }
4315

4316
    SColumnInfoData* pCol = pInput->pData[0];
11,864,064✔
4317

4318
    int32_t start = pInput->startRowIndex;
11,864,064✔
4319
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
11,864,064!
4320
    if (pCtx->order == TSDB_ORDER_DESC) {
11,864,064✔
4321
      if (pCtx->start.key == INT64_MIN) {
692!
4322
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
692✔
4323
      } else {
4324
        pInfo->max = pCtx->start.key + 1;
×
4325
      }
4326

4327
      if (pCtx->end.key == INT64_MIN) {
692!
4328
        pInfo->min =
692✔
4329
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
692✔
4330
      } else {
4331
        pInfo->min = pCtx->end.key;
×
4332
      }
4333
    } else {
4334
      if (pCtx->start.key == INT64_MIN) {
11,863,372✔
4335
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
7,687,662✔
4336
      } else {
4337
        pInfo->min = pCtx->start.key;
4,175,710✔
4338
      }
4339

4340
      if (pCtx->end.key == INT64_MIN) {
11,863,372✔
4341
        pInfo->max =
7,535,955✔
4342
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
7,535,955✔
4343
      } else {
4344
        pInfo->max = pCtx->end.key + 1;
4,327,417✔
4345
      }
4346
    }
4347
  }
4348

4349
_elapsed_over:
11,865,724✔
4350
  // data in the check operation are all null, not output
4351
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
11,865,724✔
4352

4353
  return TSDB_CODE_SUCCESS;
11,865,724✔
4354
}
4355

4356
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4357
  pOutput->timeUnit = pInput->timeUnit;
×
4358
  if (pOutput->min > pInput->min) {
×
4359
    pOutput->min = pInput->min;
×
4360
  }
4361

4362
  if (pOutput->max < pInput->max) {
×
4363
    pOutput->max = pInput->max;
×
4364
  }
4365
}
×
4366

4367
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4368
  SInputColumnInfoData* pInput = &pCtx->input;
×
4369
  SColumnInfoData*      pCol = pInput->pData[0];
×
4370
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4371
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4372
  }
4373

4374
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4375

4376
  int32_t start = pInput->startRowIndex;
×
4377

4378
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4379
    char*         data = colDataGetData(pCol, i);
×
4380
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4381
    elapsedTransferInfo(pInputInfo, pInfo);
×
4382
  }
4383

4384
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4385
  return TSDB_CODE_SUCCESS;
×
4386
}
4387

4388
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
11,839,419✔
4389
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
11,839,419✔
4390
  double        result = (double)pInfo->max - (double)pInfo->min;
11,839,419✔
4391
  result = (result >= 0) ? result : -result;
11,839,419✔
4392
  pInfo->result = result / pInfo->timeUnit;
11,839,419✔
4393
  return functionFinalize(pCtx, pBlock);
11,839,419✔
4394
}
4395

4396
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4397
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4398
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4399
  int32_t              resultBytes = getElapsedInfoSize();
×
4400
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4401

4402
  if (NULL == res) {
×
4403
    return terrno;
×
4404
  }
4405
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4406
  varDataSetLen(res, resultBytes);
×
4407

4408
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4409
  int32_t          code = TSDB_CODE_SUCCESS;
×
4410
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4411
  if (NULL == pCol) {
×
4412
    code = terrno;
×
4413
    goto _exit;
×
4414
  }
4415

4416
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4417
  if (TSDB_CODE_SUCCESS != code) {
×
4418
    goto _exit;
×
4419
  }
4420
_exit:
×
4421
  taosMemoryFree(res);
×
4422
  return code;
×
4423
}
4424

4425
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4426
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4427
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4428

4429
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4430
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4431

4432
  elapsedTransferInfo(pSBuf, pDBuf);
×
4433
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4434
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4435
  return TSDB_CODE_SUCCESS;
×
4436
}
4437

4438
int32_t getHistogramInfoSize() {
2,329,662✔
4439
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
2,329,662✔
4440
}
4441

4442
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
109,983✔
4443
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
109,983✔
4444
  return true;
109,983✔
4445
}
4446

4447
static int8_t getHistogramBinType(char* binTypeStr) {
13,171,314✔
4448
  int8_t binType;
4449
  if (strcasecmp(binTypeStr, "user_input") == 0) {
13,171,314✔
4450
    binType = USER_INPUT_BIN;
2,887✔
4451
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
13,168,427✔
4452
    binType = LINEAR_BIN;
3,360✔
4453
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
13,165,067!
4454
    binType = LOG_BIN;
13,165,229✔
4455
  } else {
4456
    binType = UNKNOWN_BIN;
×
4457
  }
4458

4459
  return binType;
13,171,314✔
4460
}
4461

4462
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
13,171,460✔
4463
  cJSON*  binDesc = cJSON_Parse(binDescStr);
13,171,460✔
4464
  int32_t numOfBins;
4465
  double* intervals;
4466
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
13,171,512✔
4467
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
13,168,598✔
4468
    int32_t startIndex;
4469
    if (numOfParams != 4) {
13,168,545!
4470
      cJSON_Delete(binDesc);
×
4471
      return TSDB_CODE_FAILED;
×
4472
    }
4473

4474
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
13,168,545✔
4475
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
13,168,651✔
4476
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
13,168,719✔
4477
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
13,168,255✔
4478
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
13,168,596✔
4479

4480
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
13,168,627!
4481
      cJSON_Delete(binDesc);
3✔
4482
      return TSDB_CODE_FAILED;
×
4483
    }
4484

4485
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
13,168,546!
4486
      cJSON_Delete(binDesc);
×
4487
      return TSDB_CODE_FAILED;
×
4488
    }
4489

4490
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
13,168,550!
4491
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
13,168,550!
4492
      cJSON_Delete(binDesc);
×
4493
      return TSDB_CODE_FAILED;
×
4494
    }
4495

4496
    int32_t counter = (int32_t)count->valueint;
13,168,550✔
4497
    if (infinity->valueint == false) {
13,168,550✔
4498
      startIndex = 0;
3,185,320✔
4499
      numOfBins = counter + 1;
3,185,320✔
4500
    } else {
4501
      startIndex = 1;
9,983,230✔
4502
      numOfBins = counter + 3;
9,983,230✔
4503
    }
4504

4505
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
13,168,550!
4506
    if (NULL == intervals) {
13,168,730!
4507
      cJSON_Delete(binDesc);
×
4508
      qError("histogram function out of memory");
×
4509
      return terrno;
×
4510
    }
4511
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
13,168,730!
4512
      // linear bin process
4513
      if (width->valuedouble == 0) {
3,360!
4514
        taosMemoryFree(intervals);
×
4515
        cJSON_Delete(binDesc);
×
4516
        return TSDB_CODE_FAILED;
×
4517
      }
4518
      for (int i = 0; i < counter + 1; ++i) {
21,216✔
4519
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
17,856✔
4520
        if (isinf(intervals[startIndex])) {
17,856!
4521
          taosMemoryFree(intervals);
×
4522
          cJSON_Delete(binDesc);
×
4523
          return TSDB_CODE_FAILED;
×
4524
        }
4525
        startIndex++;
17,856✔
4526
      }
4527
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
13,165,360!
4528
      // log bin process
4529
      if (start->valuedouble == 0) {
13,165,351!
4530
        taosMemoryFree(intervals);
×
4531
        cJSON_Delete(binDesc);
×
4532
        return TSDB_CODE_FAILED;
×
4533
      }
4534
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
13,165,351!
4535
        taosMemoryFree(intervals);
4!
4536
        cJSON_Delete(binDesc);
×
4537
        return TSDB_CODE_FAILED;
×
4538
      }
4539
      for (int i = 0; i < counter + 1; ++i) {
92,149,352✔
4540
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
78,984,005✔
4541
        if (isinf(intervals[startIndex])) {
78,984,005!
4542
          taosMemoryFree(intervals);
×
4543
          cJSON_Delete(binDesc);
×
4544
          return TSDB_CODE_FAILED;
×
4545
        }
4546
        startIndex++;
78,984,005✔
4547
      }
4548
    } else {
4549
      taosMemoryFree(intervals);
×
4550
      cJSON_Delete(binDesc);
×
4551
      return TSDB_CODE_FAILED;
×
4552
    }
4553

4554
    if (infinity->valueint == true) {
13,168,707✔
4555
      intervals[0] = -INFINITY;
9,983,593✔
4556
      intervals[numOfBins - 1] = INFINITY;
9,983,593✔
4557
      // in case of desc bin orders, -inf/inf should be swapped
4558
      if (numOfBins < 4) {
9,983,593!
4559
        return TSDB_CODE_FAILED;
×
4560
      }
4561
      if (intervals[1] > intervals[numOfBins - 2]) {
9,983,593✔
4562
        TSWAP(intervals[0], intervals[numOfBins - 1]);
9,983,485✔
4563
      }
4564
    }
4565
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
2,887!
4566
    if (binType != USER_INPUT_BIN) {
2,887!
4567
      cJSON_Delete(binDesc);
×
4568
      return TSDB_CODE_FAILED;
×
4569
    }
4570
    numOfBins = cJSON_GetArraySize(binDesc);
2,887✔
4571
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
2,887!
4572
    if (NULL == intervals) {
2,887!
4573
      cJSON_Delete(binDesc);
×
4574
      qError("histogram function out of memory");
×
4575
      return terrno;
×
4576
    }
4577
    cJSON* bin = binDesc->child;
2,887✔
4578
    if (bin == NULL) {
2,887!
4579
      taosMemoryFree(intervals);
×
4580
      cJSON_Delete(binDesc);
×
4581
      return TSDB_CODE_FAILED;
×
4582
    }
4583
    int i = 0;
2,887✔
4584
    while (bin) {
12,130✔
4585
      intervals[i] = bin->valuedouble;
9,243✔
4586
      if (!cJSON_IsNumber(bin)) {
9,243!
4587
        taosMemoryFree(intervals);
×
4588
        cJSON_Delete(binDesc);
×
4589
        return TSDB_CODE_FAILED;
×
4590
      }
4591
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
9,243!
4592
        taosMemoryFree(intervals);
×
4593
        cJSON_Delete(binDesc);
×
4594
        return TSDB_CODE_FAILED;
×
4595
      }
4596
      bin = bin->next;
9,243✔
4597
      i++;
9,243✔
4598
    }
4599
  } else {
4600
    cJSON_Delete(binDesc);
×
4601
    return TSDB_CODE_FAILED;
×
4602
  }
4603

4604
  pInfo->numOfBins = numOfBins - 1;
13,171,594✔
4605
  pInfo->normalized = normalized;
13,171,594✔
4606
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
98,981,400✔
4607
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
85,809,806✔
4608
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
85,809,806✔
4609
    pInfo->bins[i].count = 0;
85,809,806✔
4610
  }
4611

4612
  taosMemoryFree(intervals);
13,171,594✔
4613
  cJSON_Delete(binDesc);
13,171,492✔
4614

4615
  return TSDB_CODE_SUCCESS;
13,171,527✔
4616
}
4617

4618
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
13,171,351✔
4619
  if (pResultInfo->initialized) {
13,171,351!
4620
    return TSDB_CODE_SUCCESS;
×
4621
  }
4622
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
13,171,351!
4623
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4624
  }
4625

4626
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
13,171,385✔
4627
  pInfo->numOfBins = 0;
13,171,385✔
4628
  pInfo->totalCount = 0;
13,171,385✔
4629
  pInfo->normalized = 0;
13,171,385✔
4630

4631
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
13,171,385!
4632
  if (binTypeStr == NULL) {
13,171,339!
4633
    return terrno;
×
4634
  }
4635
  int8_t binType = getHistogramBinType(binTypeStr);
13,171,339✔
4636
  taosMemoryFree(binTypeStr);
13,171,425!
4637

4638
  if (binType == UNKNOWN_BIN) {
13,171,293!
4639
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4640
  }
4641
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
13,171,293!
4642
  if (binDesc == NULL) {
13,171,433!
4643
    return terrno;
×
4644
  }
4645
  int64_t normalized = pCtx->param[3].param.i;
13,171,433✔
4646
  if (normalized != 0 && normalized != 1) {
13,171,433!
4647
    taosMemoryFree(binDesc);
×
4648
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4649
  }
4650
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
13,171,433✔
4651
  if (TSDB_CODE_SUCCESS != code) {
13,171,523!
4652
    taosMemoryFree(binDesc);
×
4653
    return code;
×
4654
  }
4655
  taosMemoryFree(binDesc);
13,171,523✔
4656

4657
  return TSDB_CODE_SUCCESS;
13,171,521✔
4658
}
4659

4660
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
15,400,739✔
4661
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
15,400,739✔
4662

4663
  SInputColumnInfoData* pInput = &pCtx->input;
15,400,739✔
4664
  SColumnInfoData*      pCol = pInput->pData[0];
15,400,739✔
4665

4666
  int32_t type = pInput->pData[0]->info.type;
15,400,739✔
4667

4668
  int32_t start = pInput->startRowIndex;
15,400,739✔
4669
  int32_t numOfRows = pInput->numOfRows;
15,400,739✔
4670

4671
  int32_t numOfElems = 0;
15,400,739✔
4672
  for (int32_t i = start; i < numOfRows + start; ++i) {
58,479,198✔
4673
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
43,078,459✔
4674
      continue;
363,525✔
4675
    }
4676

4677
    numOfElems++;
42,714,934✔
4678

4679
    char*  data = colDataGetData(pCol, i);
42,714,934!
4680
    double v;
4681
    GET_TYPED_DATA(v, double, type, data);
42,714,934!
4682

4683
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
131,404,113✔
4684
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
123,687,067✔
4685
        pInfo->bins[k].count++;
34,997,888✔
4686
        pInfo->totalCount++;
34,997,888✔
4687
        break;
34,997,888✔
4688
      }
4689
    }
4690
  }
4691

4692
  if (!isPartial) {
15,400,739✔
4693
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
10,848,517✔
4694
  } else {
4695
    GET_RES_INFO(pCtx)->numOfRes = 1;
4,552,222✔
4696
  }
4697
  return TSDB_CODE_SUCCESS;
15,400,739✔
4698
}
4699

4700
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
10,848,528✔
4701

4702
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
4,552,296✔
4703

4704
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
2,282,095✔
4705
  pOutput->normalized = pInput->normalized;
2,282,095✔
4706
  pOutput->numOfBins = pInput->numOfBins;
2,282,095✔
4707
  pOutput->totalCount += pInput->totalCount;
2,282,095✔
4708
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
18,249,783✔
4709
    pOutput->bins[k].lower = pInput->bins[k].lower;
15,967,688✔
4710
    pOutput->bins[k].upper = pInput->bins[k].upper;
15,967,688✔
4711
    pOutput->bins[k].count += pInput->bins[k].count;
15,967,688✔
4712
  }
4713
}
2,282,095✔
4714

4715
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
2,282,095✔
4716
  SInputColumnInfoData* pInput = &pCtx->input;
2,282,095✔
4717
  SColumnInfoData*      pCol = pInput->pData[0];
2,282,095✔
4718
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
2,282,095!
4719
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4720
  }
4721

4722
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,282,095✔
4723

4724
  int32_t start = pInput->startRowIndex;
2,282,095✔
4725

4726
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
4,564,190✔
4727
    char*           data = colDataGetData(pCol, i);
2,282,095!
4728
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
2,282,095✔
4729
    histogramTransferInfo(pInputInfo, pInfo);
2,282,095✔
4730
  }
4731

4732
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
2,282,095!
4733
  return TSDB_CODE_SUCCESS;
2,282,095✔
4734
}
4735

4736
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
13,065,636✔
4737
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,065,636✔
4738
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
13,065,636✔
4739
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
13,065,636✔
4740
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
13,065,636✔
4741
  int32_t              code = TSDB_CODE_SUCCESS;
13,065,528✔
4742

4743
  int32_t currentRow = pBlock->info.rows;
13,065,528✔
4744
  if (NULL == pCol) {
13,065,528!
4745
    return TSDB_CODE_OUT_OF_RANGE;
×
4746
  }
4747

4748
  if (pInfo->normalized) {
13,065,528✔
4749
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
18,938,404✔
4750
      if (pInfo->totalCount != 0) {
15,781,064✔
4751
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
5,822,228✔
4752
      } else {
4753
        pInfo->bins[k].percentage = 0;
9,958,836✔
4754
      }
4755
    }
4756
  }
4757

4758
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
98,169,185✔
4759
    int32_t len;
4760
    char    buf[512] = {0};
85,129,410✔
4761
    if (!pInfo->normalized) {
85,129,410✔
4762
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
69,348,348✔
4763
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
4764
                      pInfo->bins[i].upper, pInfo->bins[i].count);
4765
    } else {
4766
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
15,781,062✔
4767
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
4768
                      pInfo->bins[i].percentage);
4769
    }
4770
    varDataSetLen(buf, len);
85,129,405✔
4771
    code = colDataSetVal(pCol, currentRow, buf, false);
85,129,405✔
4772
    if (TSDB_CODE_SUCCESS != code) {
85,103,657!
4773
      return code;
×
4774
    }
4775
    currentRow++;
85,103,657✔
4776
  }
4777

4778
  return code;
13,039,775✔
4779
}
4780

4781
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,323,536✔
4782
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,323,536✔
4783
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,323,536✔
4784
  int32_t              resultBytes = getHistogramInfoSize();
2,323,536✔
4785
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
2,323,537!
4786

4787
  if (NULL == res) {
2,323,537!
4788
    return terrno;
×
4789
  }
4790
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
2,323,537✔
4791
  varDataSetLen(res, resultBytes);
2,323,537✔
4792

4793
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,323,537✔
4794
  int32_t          code = TSDB_CODE_SUCCESS;
2,323,537✔
4795
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,323,537✔
4796
  if (NULL == pCol) {
2,323,537!
4797
    code = terrno;
×
4798
    goto _exit;
×
4799
  }
4800
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
2,323,537✔
4801

4802
_exit:
2,323,537✔
4803
  taosMemoryFree(res);
2,323,537!
4804
  return code;
2,323,537✔
4805
}
4806

4807
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4808
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4809
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4810

4811
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4812
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4813

4814
  histogramTransferInfo(pSBuf, pDBuf);
×
4815
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4816
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4817
  return TSDB_CODE_SUCCESS;
×
4818
}
4819

4820
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,274✔
4821

4822
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
66,782✔
4823
  pEnv->calcMemSize = sizeof(SHLLInfo);
66,782✔
4824
  return true;
66,782✔
4825
}
4826

4827
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
4,140,858✔
4828
  uint64_t hash = MurmurHash3_64(data, bytes);
4,140,858✔
4829
  int32_t  index = hash & HLL_BUCKET_MASK;
4,139,999✔
4830
  hash >>= HLL_BUCKET_BITS;
4,139,999✔
4831
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
4,139,999✔
4832
  uint64_t bit = 1;
4,139,999✔
4833
  uint8_t  count = 1;
4,139,999✔
4834
  while ((hash & bit) == 0) {
8,554,622✔
4835
    count++;
4,414,623✔
4836
    bit <<= 1;
4,414,623✔
4837
  }
4838
  *buk = index;
4,139,999✔
4839
  return count;
4,139,999✔
4840
}
4841

4842
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
254,784✔
4843
  uint64_t* word = (uint64_t*)buckets;
254,784✔
4844
  uint8_t*  bytes;
4845

4846
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
513,911,936✔
4847
    if (*word == 0) {
513,657,152✔
4848
      bucketHisto[0] += 8;
512,713,844✔
4849
    } else {
4850
      bytes = (uint8_t*)word;
943,308✔
4851
      bucketHisto[bytes[0]]++;
943,308✔
4852
      bucketHisto[bytes[1]]++;
943,308✔
4853
      bucketHisto[bytes[2]]++;
943,308✔
4854
      bucketHisto[bytes[3]]++;
943,308✔
4855
      bucketHisto[bytes[4]]++;
943,308✔
4856
      bucketHisto[bytes[5]]++;
943,308✔
4857
      bucketHisto[bytes[6]]++;
943,308✔
4858
      bucketHisto[bytes[7]]++;
943,308✔
4859
    }
4860
    word++;
513,657,152✔
4861
  }
4862
}
254,784✔
4863
static double hllTau(double x) {
254,782✔
4864
  if (x == 0. || x == 1.) return 0.;
254,782!
4865
  double zPrime;
4866
  double y = 1.0;
×
4867
  double z = 1 - x;
×
4868
  do {
4869
    x = sqrt(x);
×
4870
    zPrime = z;
×
4871
    y *= 0.5;
×
4872
    z -= pow(1 - x, 2) * y;
×
4873
  } while (zPrime != z);
×
4874
  return z / 3;
×
4875
}
4876

4877
static double hllSigma(double x) {
254,801✔
4878
  if (x == 1.0) return INFINITY;
254,801✔
4879
  double zPrime;
4880
  double y = 1;
239,317✔
4881
  double z = x;
239,317✔
4882
  do {
4883
    x *= x;
4,692,909✔
4884
    zPrime = z;
4,692,909✔
4885
    z += x * y;
4,692,909✔
4886
    y += y;
4,692,909✔
4887
  } while (zPrime != z);
4,692,909✔
4888
  return z;
239,317✔
4889
}
4890

4891
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
4892
// sketches"
4893
static uint64_t hllCountCnt(uint8_t* buckets) {
254,764✔
4894
  double  m = HLL_BUCKETS;
254,764✔
4895
  int32_t buckethisto[64] = {0};
254,764✔
4896
  hllBucketHisto(buckets, buckethisto);
254,764✔
4897

4898
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
254,784✔
4899
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
12,991,010✔
4900
    z += buckethisto[j];
12,736,210✔
4901
    z *= 0.5;
12,736,210✔
4902
  }
4903

4904
  z += m * hllSigma(buckethisto[0] / (double)m);
254,800✔
4905
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
254,803✔
4906

4907
  return (uint64_t)E;
254,803✔
4908
}
4909

4910
int32_t hllFunction(SqlFunctionCtx* pCtx) {
279,484✔
4911
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
279,484✔
4912

4913
  SInputColumnInfoData* pInput = &pCtx->input;
279,484✔
4914
  SColumnInfoData*      pCol = pInput->pData[0];
279,484✔
4915

4916
  int32_t type = pCol->info.type;
279,484✔
4917
  int32_t bytes = pCol->info.bytes;
279,484✔
4918

4919
  int32_t start = pInput->startRowIndex;
279,484✔
4920
  int32_t numOfRows = pInput->numOfRows;
279,484✔
4921

4922
  int32_t numOfElems = 0;
279,484✔
4923
  if (IS_NULL_TYPE(type)) {
279,484✔
4924
    goto _hll_over;
1,568✔
4925
  }
4926

4927
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,880,731✔
4928
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
5,899,781!
4929
      continue;
461,541✔
4930
    }
4931

4932
    numOfElems++;
4,142,369✔
4933

4934
    char* data = colDataGetData(pCol, i);
4,142,369!
4935
    if (IS_VAR_DATA_TYPE(type)) {
4,142,369!
4936
      bytes = varDataLen(data);
1,043,749✔
4937
      data = varDataVal(data);
1,043,749✔
4938
    }
4939

4940
    int32_t index = 0;
4,142,369✔
4941
    uint8_t count = hllCountNum(data, bytes, &index);
4,142,369✔
4942
    uint8_t oldcount = pInfo->buckets[index];
4,141,274✔
4943
    if (count > oldcount) {
4,141,274✔
4944
      pInfo->buckets[index] = count;
964,543✔
4945
    }
4946
  }
4947

4948
_hll_over:
276,821✔
4949
  pInfo->totalCount += numOfElems;
278,389✔
4950

4951
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
278,389✔
4952
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
938✔
4953
  } else {
4954
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
277,451✔
4955
  }
4956

4957
  return TSDB_CODE_SUCCESS;
278,389✔
4958
}
4959

4960
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
10,553✔
4961
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
169,026,137✔
4962
    if (pOutput->buckets[k] < pInput->buckets[k]) {
169,015,584✔
4963
      pOutput->buckets[k] = pInput->buckets[k];
172,303✔
4964
    }
4965
  }
4966
  pOutput->totalCount += pInput->totalCount;
10,553✔
4967
}
10,553✔
4968

4969
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
10,500✔
4970
  SInputColumnInfoData* pInput = &pCtx->input;
10,500✔
4971
  SColumnInfoData*      pCol = pInput->pData[0];
10,500✔
4972

4973
  if (IS_NULL_TYPE(pCol->info.type)) {
10,500!
4974
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4975
    return TSDB_CODE_SUCCESS;
×
4976
  }
4977

4978
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
10,500!
4979
    return TSDB_CODE_SUCCESS;
×
4980
  }
4981

4982
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,500✔
4983

4984
  int32_t start = pInput->startRowIndex;
10,500✔
4985

4986
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
21,052✔
4987
    if (colDataIsNull_s(pCol, i)) continue;
21,104!
4988
    char*     data = colDataGetData(pCol, i);
10,552!
4989
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
10,552✔
4990
    hllTransferInfo(pInputInfo, pInfo);
10,552✔
4991
  }
4992

4993
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,500✔
4994
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
3✔
4995
  } else {
4996
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,497✔
4997
  }
4998

4999
  return TSDB_CODE_SUCCESS;
10,500✔
5000
}
5001

5002
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
254,764✔
5003
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
254,764✔
5004

5005
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
254,764✔
5006
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
254,764✔
5007
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
254,804✔
5008
    pInfo->numOfRes = 1;
14,566✔
5009
  }
5010

5011
  return functionFinalize(pCtx, pBlock);
254,804✔
5012
}
5013

5014
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,274✔
5015
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,274✔
5016
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,274✔
5017
  int32_t              resultBytes = getHLLInfoSize();
10,274✔
5018
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
10,274!
5019

5020
  if (NULL == res) {
10,276!
5021
    return terrno;
×
5022
  }
5023
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
10,276✔
5024
  varDataSetLen(res, resultBytes);
10,276✔
5025

5026
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
10,276✔
5027
  int32_t          code = TSDB_CODE_SUCCESS;
10,276✔
5028
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
10,276✔
5029
  if (NULL == pCol) {
10,275!
5030
    code = terrno;
×
5031
    goto _exit;
×
5032
  }
5033

5034
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
10,275✔
5035

5036
_exit:
10,276✔
5037
  taosMemoryFree(res);
10,276!
5038
  return code;
10,277✔
5039
}
5040

5041
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
5042
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
5043
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
5044

5045
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
5046
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
5047

5048
  hllTransferInfo(pSBuf, pDBuf);
1✔
5049
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
5050
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
5051
  return TSDB_CODE_SUCCESS;
1✔
5052
}
5053

5054
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,366✔
5055
  pEnv->calcMemSize = sizeof(SStateInfo);
22,366✔
5056
  return true;
22,366✔
5057
}
5058

5059
static int8_t getStateOpType(char* opStr) {
40,736✔
5060
  int8_t opType;
5061
  if (strncasecmp(opStr, "LT", 2) == 0) {
40,736✔
5062
    opType = STATE_OPER_LT;
2,008✔
5063
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
38,728✔
5064
    opType = STATE_OPER_GT;
20,739✔
5065
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
17,989✔
5066
    opType = STATE_OPER_LE;
984✔
5067
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
17,005✔
5068
    opType = STATE_OPER_GE;
6,380✔
5069
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
10,625✔
5070
    opType = STATE_OPER_NE;
1,839✔
5071
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
8,786!
5072
    opType = STATE_OPER_EQ;
8,786✔
5073
  } else {
5074
    opType = STATE_OPER_INVALID;
×
5075
  }
5076

5077
  return opType;
40,736✔
5078
}
5079

5080
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
34,913,965✔
5081
  char* data = colDataGetData(pCol, index);
34,913,965!
5082
  switch (pCol->info.type) {
34,913,965!
5083
    case TSDB_DATA_TYPE_TINYINT: {
64,512✔
5084
      int8_t v = *(int8_t*)data;
64,512✔
5085
      STATE_COMP(op, v, param);
64,512!
5086
      break;
×
5087
    }
5088
    case TSDB_DATA_TYPE_UTINYINT: {
5,760✔
5089
      uint8_t v = *(uint8_t*)data;
5,760✔
5090
      STATE_COMP(op, v, param);
5,760!
5091
      break;
×
5092
    }
5093
    case TSDB_DATA_TYPE_SMALLINT: {
5,210,851✔
5094
      int16_t v = *(int16_t*)data;
5,210,851✔
5095
      STATE_COMP(op, v, param);
5,210,851!
5096
      break;
×
5097
    }
5098
    case TSDB_DATA_TYPE_USMALLINT: {
5,760✔
5099
      uint16_t v = *(uint16_t*)data;
5,760✔
5100
      STATE_COMP(op, v, param);
5,760!
5101
      break;
×
5102
    }
5103
    case TSDB_DATA_TYPE_INT: {
26,370✔
5104
      int32_t v = *(int32_t*)data;
26,370✔
5105
      STATE_COMP(op, v, param);
26,370!
5106
      break;
×
5107
    }
5108
    case TSDB_DATA_TYPE_UINT: {
5,760✔
5109
      uint32_t v = *(uint32_t*)data;
5,760✔
5110
      STATE_COMP(op, v, param);
5,760!
5111
      break;
×
5112
    }
5113
    case TSDB_DATA_TYPE_BIGINT: {
43,566✔
5114
      int64_t v = *(int64_t*)data;
43,566✔
5115
      STATE_COMP(op, v, param);
43,566!
5116
      break;
×
5117
    }
5118
    case TSDB_DATA_TYPE_UBIGINT: {
5,760✔
5119
      uint64_t v = *(uint64_t*)data;
5,760✔
5120
      STATE_COMP(op, v, param);
5,760!
5121
      break;
×
5122
    }
5123
    case TSDB_DATA_TYPE_FLOAT: {
29,473,901✔
5124
      float v = *(float*)data;
29,473,901✔
5125
      STATE_COMP(op, v, param);
29,473,901!
5126
      break;
×
5127
    }
5128
    case TSDB_DATA_TYPE_DOUBLE: {
71,966✔
5129
      double v = *(double*)data;
71,966✔
5130
      STATE_COMP(op, v, param);
71,966!
5131
      break;
×
5132
    }
5133
    default: {
×
5134
      return false;
×
5135
    }
5136
  }
5137
  return false;
×
5138
}
5139

5140
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
8,126✔
5141
  int32_t              code = TSDB_CODE_SUCCESS;
8,126✔
5142
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,126✔
5143
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,126✔
5144

5145
  SInputColumnInfoData* pInput = &pCtx->input;
8,126✔
5146
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
8,126✔
5147

5148
  SColumnInfoData* pInputCol = pInput->pData[0];
8,126✔
5149

5150
  int32_t          numOfElems = 0;
8,126✔
5151
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
8,126✔
5152

5153
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
8,126✔
5154
  if (STATE_OPER_INVALID == op) {
8,126!
5155
    return 0;
×
5156
  }
5157

5158
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
5,710,560✔
5159
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
5,702,429!
5160
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5161
    } else {
5162
      pInfo->prevTs = tsList[i];
5,702,429✔
5163
    }
5164

5165
    pInfo->isPrevTsSet = true;
5,702,429✔
5166
    numOfElems++;
5,702,429✔
5167

5168
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
5,702,429✔
5169
      colDataSetNULL(pOutput, i);
258,924!
5170
      // handle selectivity
5171
      if (pCtx->subsidiaries.num > 0) {
258,924✔
5172
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
44✔
5173
        if (TSDB_CODE_SUCCESS != code) {
44!
5174
          return code;
×
5175
        }
5176
      }
5177
      continue;
258,924✔
5178
    }
5179

5180
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
5,443,505✔
5181

5182
    int64_t output = -1;
5,443,493✔
5183
    if (ret) {
5,443,493✔
5184
      output = ++pInfo->count;
2,631,567✔
5185
    } else {
5186
      pInfo->count = 0;
2,811,926✔
5187
    }
5188
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
5,443,493✔
5189
    if (TSDB_CODE_SUCCESS != code) {
5,443,510!
5190
      return code;
×
5191
    }
5192

5193
    // handle selectivity
5194
    if (pCtx->subsidiaries.num > 0) {
5,443,510✔
5195
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
528✔
5196
      if (TSDB_CODE_SUCCESS != code) {
528!
5197
        return code;
×
5198
      }
5199
    }
5200
  }
5201

5202
  pResInfo->numOfRes = numOfElems;
8,131✔
5203
  return TSDB_CODE_SUCCESS;
8,131✔
5204
}
5205

5206
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
32,610✔
5207
  int32_t              code = TSDB_CODE_SUCCESS;
32,610✔
5208
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,610✔
5209
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
32,610✔
5210

5211
  SInputColumnInfoData* pInput = &pCtx->input;
32,610✔
5212
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
32,610✔
5213

5214
  SColumnInfoData* pInputCol = pInput->pData[0];
32,610✔
5215

5216
  int32_t          numOfElems = 0;
32,610✔
5217
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
32,610✔
5218

5219
  // TODO: process timeUnit for different db precisions
5220
  int32_t timeUnit = 1;
32,610✔
5221
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
32,610✔
5222
    timeUnit = pCtx->param[3].param.i;
30,650✔
5223
  }
5224

5225
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
32,610✔
5226
  if (STATE_OPER_INVALID == op) {
32,610!
5227
    return TSDB_CODE_INVALID_PARA;
×
5228
  }
5229

5230
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
29,766,082✔
5231
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
29,733,472!
5232
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5233
    } else {
5234
      pInfo->prevTs = tsList[i];
29,733,472✔
5235
    }
5236

5237
    pInfo->isPrevTsSet = true;
29,733,472✔
5238
    numOfElems++;
29,733,472✔
5239

5240
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
29,733,472✔
5241
      colDataSetNULL(pOutput, i);
263,005✔
5242
      // handle selectivity
5243
      if (pCtx->subsidiaries.num > 0) {
263,005✔
5244
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
48✔
5245
        if (TSDB_CODE_SUCCESS != code) {
48!
5246
          return code;
×
5247
        }
5248
      }
5249
      continue;
263,005✔
5250
    }
5251

5252
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
29,470,467✔
5253
    int64_t output = -1;
29,470,467✔
5254
    if (ret) {
29,470,467✔
5255
      if (pInfo->durationStart == 0) {
9,502,871✔
5256
        output = 0;
5,597,856✔
5257
        pInfo->durationStart = tsList[i];
5,597,856✔
5258
      } else {
5259
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
3,905,015✔
5260
      }
5261
    } else {
5262
      pInfo->durationStart = 0;
19,967,596✔
5263
    }
5264
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
29,470,467✔
5265
    if (TSDB_CODE_SUCCESS != code) {
29,470,467!
5266
      return code;
×
5267
    }
5268

5269
    // handle selectivity
5270
    if (pCtx->subsidiaries.num > 0) {
29,470,467✔
5271
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
20,095,578✔
5272
      if (TSDB_CODE_SUCCESS != code) {
20,095,578!
5273
        return code;
×
5274
      }
5275
    }
5276
  }
5277

5278
  pResInfo->numOfRes = numOfElems;
32,610✔
5279
  return TSDB_CODE_SUCCESS;
32,610✔
5280
}
5281

5282
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
15,632✔
5283
  pEnv->calcMemSize = sizeof(SSumRes);
15,632✔
5284
  return true;
15,632✔
5285
}
5286

5287
int32_t csumFunction(SqlFunctionCtx* pCtx) {
23,573✔
5288
  int32_t              code = TSDB_CODE_SUCCESS;
23,573✔
5289
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
23,573✔
5290
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
23,573✔
5291

5292
  SInputColumnInfoData* pInput = &pCtx->input;
23,573✔
5293
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
23,573✔
5294

5295
  SColumnInfoData* pInputCol = pInput->pData[0];
23,573✔
5296
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
23,573✔
5297

5298
  int32_t numOfElems = 0;
23,573✔
5299
  int32_t type = pInputCol->info.type;
23,573✔
5300
  int32_t startOffset = pCtx->offset;
23,573✔
5301
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
3,998,505✔
5302
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,974,950✔
5303
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5304
    } else {
5305
      pSumRes->prevTs = tsList[i];
3,974,932✔
5306
    }
5307
    pSumRes->isPrevTsSet = true;
3,974,932✔
5308

5309
    int32_t pos = startOffset + numOfElems;
3,974,932✔
5310
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,974,932✔
5311
      // colDataSetNULL(pOutput, i);
5312
      continue;
545,672✔
5313
    }
5314

5315
    char* data = colDataGetData(pInputCol, i);
3,429,260!
5316
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
6,091,656✔
5317
      int64_t v;
5318
      GET_TYPED_DATA(v, int64_t, type, data);
2,662,396!
5319
      pSumRes->isum += v;
2,662,396✔
5320
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
2,662,396✔
5321
      if (TSDB_CODE_SUCCESS != code) {
2,662,396!
5322
        return code;
×
5323
      }
5324
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
767,544!
5325
      uint64_t v;
5326
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5327
      pSumRes->usum += v;
680✔
5328
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5329
      if (TSDB_CODE_SUCCESS != code) {
680!
5330
        return code;
×
5331
      }
5332
    } else if (IS_FLOAT_TYPE(type)) {
766,184!
5333
      double v;
5334
      GET_TYPED_DATA(v, double, type, data);
766,670!
5335
      pSumRes->dsum += v;
766,670✔
5336
      // check for overflow
5337
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
766,670!
5338
        colDataSetNULL(pOutput, pos);
8!
5339
      } else {
5340
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
766,662✔
5341
        if (TSDB_CODE_SUCCESS != code) {
766,662!
5342
          return code;
×
5343
        }
5344
      }
5345
    }
5346

5347
    // handle selectivity
5348
    if (pCtx->subsidiaries.num > 0) {
3,429,260✔
5349
      code = appendSelectivityValue(pCtx, i, pos);
2,004,824✔
5350
      if (TSDB_CODE_SUCCESS != code) {
2,004,824!
5351
        return code;
×
5352
      }
5353
    }
5354

5355
    numOfElems++;
3,429,260✔
5356
  }
5357

5358
  pResInfo->numOfRes = numOfElems;
23,555✔
5359
  return TSDB_CODE_SUCCESS;
23,555✔
5360
}
5361

5362
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
13,721✔
5363
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
13,721✔
5364
  return true;
13,721✔
5365
}
5366

5367
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
264,857✔
5368
  if (pResultInfo->initialized) {
264,857✔
5369
    return TSDB_CODE_SUCCESS;
250,125✔
5370
  }
5371
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,732!
5372
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5373
  }
5374

5375
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
14,733✔
5376
  pInfo->pos = 0;
14,733✔
5377
  pInfo->sum = 0;
14,733✔
5378
  pInfo->prevTs = -1;
14,733✔
5379
  pInfo->isPrevTsSet = false;
14,733✔
5380
  pInfo->numOfPoints = pCtx->param[1].param.i;
14,733✔
5381
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
14,733!
5382
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5383
  }
5384
  pInfo->pointsMeet = false;
14,733✔
5385

5386
  return TSDB_CODE_SUCCESS;
14,733✔
5387
}
5388

5389
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
251,133✔
5390
  int32_t              code = TSDB_CODE_SUCCESS;
251,133✔
5391
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
251,133✔
5392
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
251,133✔
5393

5394
  SInputColumnInfoData* pInput = &pCtx->input;
251,133✔
5395
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
251,133✔
5396

5397
  SColumnInfoData* pInputCol = pInput->pData[0];
251,133✔
5398
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
251,133✔
5399
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
251,133✔
5400

5401
  int32_t numOfElems = 0;
251,133✔
5402
  int32_t type = pInputCol->info.type;
251,133✔
5403
  int32_t startOffset = pCtx->offset;
251,133✔
5404
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
59,367,861✔
5405
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
59,116,720!
5406
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5407
    } else {
5408
      pInfo->prevTs = tsList[i];
59,116,720✔
5409
    }
5410
    pInfo->isPrevTsSet = true;
59,116,720✔
5411

5412
    int32_t pos = startOffset + numOfElems;
59,116,720✔
5413
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
59,116,720✔
5414
      // colDataSetNULL(pOutput, i);
5415
      continue;
104,725✔
5416
    }
5417

5418
    char*  data = colDataGetData(pInputCol, i);
59,011,995!
5419
    double v;
5420
    GET_TYPED_DATA(v, double, type, data);
59,011,995!
5421

5422
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
59,011,995✔
5423
      pInfo->points[pInfo->pos] = v;
5,271,406✔
5424
      pInfo->sum += v;
5,271,406✔
5425
    } else {
5426
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
53,740,589!
5427
        pInfo->sum += v;
11,027✔
5428
        pInfo->pointsMeet = true;
11,027✔
5429
      } else {
5430
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
53,729,562✔
5431
      }
5432

5433
      pInfo->points[pInfo->pos] = v;
53,740,589✔
5434
      double result = pInfo->sum / pInfo->numOfPoints;
53,740,589✔
5435
      // check for overflow
5436
      if (isinf(result) || isnan(result)) {
53,740,589!
5437
        colDataSetNULL(pOutput, pos);
×
5438
      } else {
5439
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
53,741,009✔
5440
        if (TSDB_CODE_SUCCESS != code) {
53,741,017!
5441
          return code;
×
5442
        }
5443
      }
5444

5445
      // handle selectivity
5446
      if (pCtx->subsidiaries.num > 0) {
53,740,597✔
5447
        code = appendSelectivityValue(pCtx, i, pos);
34,530,074✔
5448
        if (TSDB_CODE_SUCCESS != code) {
34,530,074!
5449
          return code;
×
5450
        }
5451
      }
5452

5453
      numOfElems++;
53,740,597✔
5454
    }
5455

5456
    pInfo->pos++;
59,012,003✔
5457
    if (pInfo->pos == pInfo->numOfPoints) {
59,012,003✔
5458
      pInfo->pos = 0;
168,984✔
5459
    }
5460
  }
5461

5462
  pResInfo->numOfRes = numOfElems;
251,141✔
5463
  return TSDB_CODE_SUCCESS;
251,141✔
5464
}
5465

5466
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
14,497,845✔
5467
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
14,497,845✔
5468
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
14,497,845✔
5469

5470
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
14,497,845✔
5471
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
14,497,845✔
5472

5473
  return pInfo;
14,497,845✔
5474
}
5475

5476
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
24,800✔
5477
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
24,800✔
5478
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
24,806✔
5479
  int32_t      numOfSamples = pVal->datum.i;
24,814✔
5480
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
24,814✔
5481
  return true;
24,814✔
5482
}
5483

5484
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,312,871✔
5485
  if (pResultInfo->initialized) {
7,312,871!
5486
    return TSDB_CODE_SUCCESS;
×
5487
  }
5488
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,312,871!
5489
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5490
  }
5491

5492
  taosSeedRand(taosSafeRand());
7,312,873✔
5493

5494
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
7,312,876✔
5495
  pInfo->samples = pCtx->param[1].param.i;
7,312,876✔
5496
  pInfo->totalPoints = 0;
7,312,876✔
5497
  pInfo->numSampled = 0;
7,312,876✔
5498
  pInfo->colType = pCtx->resDataInfo.type;
7,312,876✔
5499
  pInfo->colBytes = pCtx->resDataInfo.bytes;
7,312,876✔
5500
  pInfo->nullTuplePos.pageId = -1;
7,312,876✔
5501
  pInfo->nullTupleSaved = false;
7,312,876✔
5502
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
7,312,876✔
5503
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
7,312,876✔
5504

5505
  return TSDB_CODE_SUCCESS;
7,312,876✔
5506
}
5507

5508
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
15,961,008✔
5509
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
15,961,008✔
5510
}
15,960,937✔
5511

5512
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
16,296,145✔
5513
  pInfo->totalPoints++;
16,296,145✔
5514
  if (pInfo->numSampled < pInfo->samples) {
16,296,145✔
5515
    sampleAssignResult(pInfo, data, pInfo->numSampled);
15,240,555✔
5516
    if (pCtx->subsidiaries.num > 0) {
15,240,412✔
5517
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,158,087✔
5518
      if (code != TSDB_CODE_SUCCESS) {
1,158,064!
5519
        return code;
×
5520
      }
5521
    }
5522
    pInfo->numSampled++;
15,240,389✔
5523
  } else {
5524
    int32_t j = taosRand() % (pInfo->totalPoints);
1,055,590✔
5525
    if (j < pInfo->samples) {
1,056,247✔
5526
      sampleAssignResult(pInfo, data, j);
721,072✔
5527
      if (pCtx->subsidiaries.num > 0) {
721,070✔
5528
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
494,767✔
5529
        if (code != TSDB_CODE_SUCCESS) {
493,980!
5530
          return code;
×
5531
        }
5532
      }
5533
    }
5534
  }
5535

5536
  return TSDB_CODE_SUCCESS;
16,295,847✔
5537
}
5538

5539
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
7,316,402✔
5540
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,316,402✔
5541
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
7,316,402✔
5542

5543
  SInputColumnInfoData* pInput = &pCtx->input;
7,316,402✔
5544

5545
  SColumnInfoData* pInputCol = pInput->pData[0];
7,316,402✔
5546
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
24,004,472✔
5547
    if (colDataIsNull_s(pInputCol, i)) {
33,375,144✔
5548
      continue;
392,277✔
5549
    }
5550

5551
    char*   data = colDataGetData(pInputCol, i);
16,295,295!
5552
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
16,295,295✔
5553
    if (code != TSDB_CODE_SUCCESS) {
16,295,793!
5554
      return code;
×
5555
    }
5556
  }
5557

5558
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
7,316,900✔
5559
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
35✔
5560
    if (code != TSDB_CODE_SUCCESS) {
35!
5561
      return code;
×
5562
    }
5563
    pInfo->nullTupleSaved = true;
35✔
5564
  }
5565

5566
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
7,316,900✔
5567
  return TSDB_CODE_SUCCESS;
7,316,900✔
5568
}
5569

5570
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,181,445✔
5571
  int32_t              code = TSDB_CODE_SUCCESS;
7,181,445✔
5572
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
7,181,445✔
5573

5574
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
7,181,445✔
5575
  pEntryInfo->complete = true;
7,181,446✔
5576

5577
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,181,446✔
5578
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,181,446✔
5579
  if (NULL == pCol) {
7,181,446!
5580
    return TSDB_CODE_OUT_OF_RANGE;
×
5581
  }
5582

5583
  int32_t currentRow = pBlock->info.rows;
7,181,446✔
5584
  if (pInfo->numSampled == 0) {
7,181,446✔
5585
    colDataSetNULL(pCol, currentRow);
2,319✔
5586
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,319✔
5587
    return code;
2,319✔
5588
  }
5589
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
22,115,899✔
5590
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
14,937,020✔
5591
    if (TSDB_CODE_SUCCESS != code) {
14,936,633!
5592
      return code;
×
5593
    }
5594
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
14,936,633✔
5595
    if (TSDB_CODE_SUCCESS != code) {
14,936,772!
5596
      return code;
×
5597
    }
5598
  }
5599

5600
  return code;
7,178,879✔
5601
}
5602

5603
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5604
#if 0
5605
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
5606
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
5607
  int32_t      numOfPoints = pVal->datum.i;
5608
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
5609
#endif
5610
  return true;
×
5611
}
5612

5613
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
5614
#if 0
5615
  if (!functionSetup(pCtx, pResultInfo)) {
5616
    return false;
5617
  }
5618

5619
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5620
  pInfo->numAdded = 0;
5621
  pInfo->numOfPoints = pCtx->param[1].param.i;
5622
  if (pCtx->numOfParams == 4) {
5623
    pInfo->offset = pCtx->param[2].param.i;
5624
  } else {
5625
    pInfo->offset = 0;
5626
  }
5627
  pInfo->colType = pCtx->resDataInfo.type;
5628
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5629
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
5630
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
5631
    return false;
5632
  }
5633

5634
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
5635
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
5636

5637
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
5638
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5639
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
5640
    pInfo->pItems[i]->isNull = false;
5641
  }
5642
#endif
5643

5644
  return TSDB_CODE_SUCCESS;
×
5645
}
5646

5647
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
5648
#if 0
5649
  pItem->timestamp = ts;
5650
  if (isNull) {
5651
    pItem->isNull = true;
5652
  } else {
5653
    pItem->isNull = false;
5654
    memcpy(pItem->data, data, colBytes);
5655
  }
5656
#endif
5657
}
×
5658

5659
#if 0
5660
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
5661
  STailItem* d1 = *(STailItem**)p1;
5662
  STailItem* d2 = *(STailItem**)p2;
5663
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
5664
}
5665

5666
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5667
  STailItem** pList = pInfo->pItems;
5668
  if (pInfo->numAdded < pInfo->numOfPoints) {
5669
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
5670
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
5671
    pInfo->numAdded++;
5672
  } else if (pList[0]->timestamp < ts) {
5673
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
5674
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
5675
  }
5676
}
5677
#endif
5678

5679
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
5680
#if 0
5681
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5682
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5683

5684
  SInputColumnInfoData* pInput = &pCtx->input;
5685
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5686

5687
  SColumnInfoData* pInputCol = pInput->pData[0];
5688
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5689

5690
  int32_t startOffset = pCtx->offset;
5691
  if (pInfo->offset >= pInput->numOfRows) {
5692
    return 0;
5693
  } else {
5694
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
5695
  }
5696
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
5697
    char* data = colDataGetData(pInputCol, i);
5698
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5699
  }
5700

5701
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
5702

5703
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5704
    int32_t    pos = startOffset + i;
5705
    STailItem* pItem = pInfo->pItems[i];
5706
    if (pItem->isNull) {
5707
      colDataSetNULL(pOutput, pos);
5708
    } else {
5709
      colDataSetVal(pOutput, pos, pItem->data, false);
5710
    }
5711
  }
5712

5713
  return pInfo->numOfPoints;
5714
#endif
5715
  return 0;
×
5716
}
5717

5718
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
5719
#if 0
5720
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
5721
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
5722
  pEntryInfo->complete = true;
5723

5724
  int32_t type = pCtx->input.pData[0]->info.type;
5725
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
5726

5727
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5728

5729
  // todo assign the tag value and the corresponding row data
5730
  int32_t currentRow = pBlock->info.rows;
5731
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
5732
    STailItem* pItem = pInfo->pItems[i];
5733
    colDataSetVal(pCol, currentRow, pItem->data, false);
5734
    currentRow += 1;
5735
  }
5736

5737
  return pEntryInfo->numOfRes;
5738
#endif
5739
  return 0;
×
5740
}
5741

5742
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5743
#if 0
5744
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
5745
#endif
5746
  return true;
×
5747
}
5748

5749
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
5750
#if 0
5751
  if (!functionSetup(pCtx, pResInfo)) {
5752
    return false;
5753
  }
5754

5755
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5756
  pInfo->numOfPoints = 0;
5757
  pInfo->colType = pCtx->resDataInfo.type;
5758
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5759
  if (pInfo->pHash != NULL) {
5760
    taosHashClear(pInfo->pHash);
5761
  } else {
5762
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
5763
  }
5764
#endif
5765
  return TSDB_CODE_SUCCESS;
×
5766
}
5767

5768
#if 0
5769
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5770
  // handle null elements
5771
  if (isNull == true) {
5772
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5773
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5774
    if (pInfo->hasNull == false && pItem->isNull == false) {
5775
      pItem->timestamp = ts;
5776
      pItem->isNull = true;
5777
      pInfo->numOfPoints++;
5778
      pInfo->hasNull = true;
5779
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
5780
      pItem->timestamp = ts;
5781
    }
5782
    return;
5783
  }
5784

5785
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
5786
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
5787
  if (pHashItem == NULL) {
5788
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5789
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5790
    pItem->timestamp = ts;
5791
    memcpy(pItem->data, data, pInfo->colBytes);
5792

5793
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
5794
    pInfo->numOfPoints++;
5795
  } else if (pHashItem->timestamp > ts) {
5796
    pHashItem->timestamp = ts;
5797
  }
5798
}
5799
#endif
5800

5801
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
5802
#if 0
5803
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5804
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5805

5806
  SInputColumnInfoData* pInput = &pCtx->input;
5807
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5808

5809
  SColumnInfoData* pInputCol = pInput->pData[0];
5810
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
5811
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5812

5813
  int32_t startOffset = pCtx->offset;
5814
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5815
    char* data = colDataGetData(pInputCol, i);
5816
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5817

5818
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
5819
      taosHashCleanup(pInfo->pHash);
5820
      return 0;
5821
    }
5822
  }
5823

5824
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5825
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
5826
    if (pItem->isNull == true) {
5827
      colDataSetNULL(pOutput, i);
5828
    } else {
5829
      colDataSetVal(pOutput, i, pItem->data, false);
5830
    }
5831
    if (pTsOutput != NULL) {
5832
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
5833
    }
5834
  }
5835

5836
  return pInfo->numOfPoints;
5837
#endif
5838
  return 0;
×
5839
}
5840

5841
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
24,801✔
5842
  pEnv->calcMemSize = sizeof(SModeInfo);
24,801✔
5843
  return true;
24,801✔
5844
}
5845

5846
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
25,584✔
5847
  if (pResInfo->initialized) {
25,584!
5848
    return TSDB_CODE_SUCCESS;
×
5849
  }
5850
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
25,584!
5851
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5852
  }
5853

5854
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
25,584✔
5855
  pInfo->colType = pCtx->resDataInfo.type;
25,584✔
5856
  pInfo->colBytes = pCtx->resDataInfo.bytes;
25,584✔
5857
  if (pInfo->pHash != NULL) {
25,584!
5858
    taosHashClear(pInfo->pHash);
×
5859
  } else {
5860
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
25,584✔
5861
    if (NULL == pInfo->pHash) {
25,584!
5862
      return terrno;
×
5863
    }
5864
  }
5865
  pInfo->nullTupleSaved = false;
25,584✔
5866
  pInfo->nullTuplePos.pageId = -1;
25,584✔
5867

5868
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
25,584!
5869
  if (NULL == pInfo->buf) {
25,584!
5870
    taosHashCleanup(pInfo->pHash);
×
5871
    pInfo->pHash = NULL;
×
5872
    return terrno;
×
5873
  }
5874
  pCtx->needCleanup = true;
25,584✔
5875
  return TSDB_CODE_SUCCESS;
25,584✔
5876
}
5877

5878
static void modeFunctionCleanup(SModeInfo* pInfo) {
25,584✔
5879
  taosHashCleanup(pInfo->pHash);
25,584✔
5880
  pInfo->pHash = NULL;
25,584✔
5881
  taosMemoryFreeClear(pInfo->buf);
25,584!
5882
}
25,584✔
5883

5884
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5885
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5886
    return;
×
5887
  }
5888
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5889
}
5890

5891
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
116,736,656✔
5892
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
116,736,656!
5893
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
20,927,800!
5894
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
×
5895
    } else {
5896
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
20,927,800✔
5897
    }
5898
  } else {
5899
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
95,808,856✔
5900
  }
5901

5902
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
116,736,656✔
5903
}
5904

5905
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
122,873,698✔
5906
  int32_t code = TSDB_CODE_SUCCESS;
122,873,698✔
5907
  int32_t hashKeyBytes;
5908
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
122,873,698✔
5909
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
20,928,210!
5910
      hashKeyBytes = getJsonValueLen(data);
×
5911
    } else {
5912
      hashKeyBytes = varDataTLen(data);
20,928,210✔
5913
    }
5914
  } else {
5915
    hashKeyBytes = pInfo->colBytes;
101,945,488✔
5916
  }
5917

5918
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
122,874,151✔
5919
  if (pHashItem == NULL) {
122,872,678✔
5920
    int32_t   size = sizeof(SModeItem);
116,736,073✔
5921
    SModeItem item = {0};
116,736,073✔
5922

5923
    item.count += 1;
116,736,073✔
5924
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
116,736,073✔
5925
    if (code != TSDB_CODE_SUCCESS) {
116,735,937!
5926
      return code;
×
5927
    }
5928

5929
    if (pCtx->subsidiaries.num > 0) {
116,735,937✔
5930
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
76,727,319✔
5931
      if (code != TSDB_CODE_SUCCESS) {
76,727,319!
5932
        return code;
×
5933
      }
5934
    }
5935

5936
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
116,735,937✔
5937
    if (code != TSDB_CODE_SUCCESS) {
116,737,732!
5938
      return code;
×
5939
    }
5940
  } else {
5941
    pHashItem->count += 1;
6,136,605✔
5942
    if (pCtx->subsidiaries.num > 0) {
6,136,605✔
5943
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,523,841✔
5944
      if (code != TSDB_CODE_SUCCESS) {
3,523,841!
5945
        return code;
×
5946
      }
5947
    }
5948
  }
5949

5950
  return code;
122,874,337✔
5951
}
5952

5953
int32_t modeFunction(SqlFunctionCtx* pCtx) {
2,556,422✔
5954
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,556,422✔
5955
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,556,422✔
5956

5957
  SInputColumnInfoData* pInput = &pCtx->input;
2,556,422✔
5958

5959
  SColumnInfoData* pInputCol = pInput->pData[0];
2,556,422✔
5960
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,556,422✔
5961

5962
  int32_t numOfElems = 0;
2,556,422✔
5963
  int32_t startOffset = pCtx->offset;
2,556,422✔
5964
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
125,832,075✔
5965
    if (colDataIsNull_s(pInputCol, i)) {
246,551,338✔
5966
      continue;
401,463✔
5967
    }
5968
    numOfElems++;
122,874,206✔
5969

5970
    char*   data = colDataGetData(pInputCol, i);
122,874,206!
5971
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
122,874,206✔
5972
    if (code != TSDB_CODE_SUCCESS) {
122,874,268✔
5973
      modeFunctionCleanup(pInfo);
78✔
5974
      return code;
×
5975
    }
5976
  }
5977

5978
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,556,406!
5979
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
5980
    if (code != TSDB_CODE_SUCCESS) {
50!
5981
      modeFunctionCleanup(pInfo);
×
5982
      return code;
×
5983
    }
5984
    pInfo->nullTupleSaved = true;
50✔
5985
  }
5986

5987
  SET_VAL(pResInfo, numOfElems, 1);
2,556,406✔
5988

5989
  return TSDB_CODE_SUCCESS;
2,556,406✔
5990
}
5991

5992
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
25,584✔
5993
  int32_t              code = TSDB_CODE_SUCCESS;
25,584✔
5994
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
25,584✔
5995
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
25,584✔
5996
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
25,584✔
5997
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
25,584✔
5998
  int32_t              currentRow = pBlock->info.rows;
25,584✔
5999
  if (NULL == pCol) {
25,584!
6000
    modeFunctionCleanup(pInfo);
×
6001
    return TSDB_CODE_OUT_OF_RANGE;
×
6002
  }
6003

6004
  STuplePos resDataPos, resTuplePos;
6005
  int32_t   maxCount = 0;
25,584✔
6006

6007
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
25,584✔
6008
  while (pIter != NULL) {
116,763,682✔
6009
    SModeItem* pItem = (SModeItem*)pIter;
116,738,098✔
6010
    if (pItem->count >= maxCount) {
116,738,098✔
6011
      maxCount = pItem->count;
113,443,985✔
6012
      resDataPos = pItem->dataPos;
113,443,985✔
6013
      resTuplePos = pItem->tuplePos;
113,443,985✔
6014
    }
6015

6016
    pIter = taosHashIterate(pInfo->pHash, pIter);
116,738,098✔
6017
  }
6018

6019
  if (maxCount != 0) {
25,584✔
6020
    char* pData = NULL;
23,291✔
6021
    code = loadTupleData(pCtx, &resDataPos, &pData);
23,291✔
6022
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
23,291!
6023
      code = terrno = TSDB_CODE_NOT_FOUND;
×
6024
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
6025
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
6026
      modeFunctionCleanup(pInfo);
×
6027
      return code;
×
6028
    }
6029

6030
    code = colDataSetVal(pCol, currentRow, pData, false);
23,291✔
6031
    if (TSDB_CODE_SUCCESS != code) {
23,291!
6032
      modeFunctionCleanup(pInfo);
×
6033
      return code;
×
6034
    }
6035
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
23,291✔
6036
  } else {
6037
    colDataSetNULL(pCol, currentRow);
2,293!
6038
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,293✔
6039
  }
6040

6041
  modeFunctionCleanup(pInfo);
25,584✔
6042

6043
  return code;
25,584✔
6044
}
6045

6046
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
78,896✔
6047
  pEnv->calcMemSize = sizeof(STwaInfo);
78,896✔
6048
  return true;
78,896✔
6049
}
6050

6051
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,656,718✔
6052
  if (pResultInfo->initialized) {
7,656,718!
6053
    return TSDB_CODE_SUCCESS;
×
6054
  }
6055
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,656,718!
6056
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6057
  }
6058

6059
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,656,726✔
6060
  pInfo->numOfElems = 0;
7,656,726✔
6061
  pInfo->p.key = INT64_MIN;
7,656,726✔
6062
  pInfo->win = TSWINDOW_INITIALIZER;
7,656,726✔
6063
  return TSDB_CODE_SUCCESS;
7,656,726✔
6064
}
6065

6066
static double twa_get_area(SPoint1 s, SPoint1 e) {
17,216,464✔
6067
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
17,216,464!
6068
    return 0;
×
6069
  }
6070

6071
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
17,216,603✔
6072
    return (s.val + e.val) * (e.key - s.key) / 2;
12,787,546✔
6073
  }
6074

6075
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
4,429,057✔
6076
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
4,429,057✔
6077
  return val;
4,429,057✔
6078
}
6079

6080
int32_t twaFunction(SqlFunctionCtx* pCtx) {
7,657,681✔
6081
  int32_t               code = TSDB_CODE_SUCCESS;
7,657,681✔
6082
  SInputColumnInfoData* pInput = &pCtx->input;
7,657,681✔
6083
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,657,681✔
6084

6085
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,657,681✔
6086
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,657,681✔
6087
  SPoint1*             last = &pInfo->p;
7,657,681✔
6088

6089
  if (IS_NULL_TYPE(pInputCol->info.type)) {
7,657,681!
6090
    pInfo->numOfElems = 0;
×
6091
    goto _twa_over;
×
6092
  }
6093

6094
  funcInputUpdate(pCtx);
7,657,681✔
6095
  SFuncInputRow row = {0};
7,657,714✔
6096
  bool          result = false;
7,657,714✔
6097
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
7,657,714✔
6098
    while (1) {
6099
      code = funcInputGetNextRow(pCtx, &row, &result);
4,118,353✔
6100
      if (TSDB_CODE_SUCCESS != code) {
4,118,355!
6101
        return code;
×
6102
      }
6103
      if (!result) {
4,118,355✔
6104
        break;
2✔
6105
      }
6106
      if (row.isDataNull) {
4,118,353✔
6107
        continue;
2✔
6108
      }
6109

6110
      last->key = row.ts;
4,118,351✔
6111

6112
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
4,118,351!
6113

6114
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
4,118,351✔
6115
      pInfo->win.skey = pCtx->start.key;
4,118,349✔
6116
      pInfo->numOfElems++;
4,118,349✔
6117
      break;
4,118,349✔
6118
    }
6119
  } else if (pInfo->p.key == INT64_MIN) {
3,539,363✔
6120
    while (1) {
6121
      code = funcInputGetNextRow(pCtx, &row, &result);
3,672,374✔
6122
      if (TSDB_CODE_SUCCESS != code) {
3,672,315!
6123
        return code;
×
6124
      }
6125
      if (!result) {
3,672,315✔
6126
        break;
16,669✔
6127
      }
6128
      if (row.isDataNull) {
3,655,646✔
6129
        continue;
133,305✔
6130
      }
6131

6132
      last->key = row.ts;
3,522,341✔
6133

6134
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,522,341!
6135

6136
      pInfo->win.skey = last->key;
3,522,341✔
6137
      pInfo->numOfElems++;
3,522,341✔
6138
      break;
3,522,341✔
6139
    }
6140
  }
6141

6142
  SPoint1 st = {0};
7,657,655✔
6143

6144
  // calculate the value of
6145
  while (1) {
6146
    code = funcInputGetNextRow(pCtx, &row, &result);
16,384,639✔
6147
    if (TSDB_CODE_SUCCESS != code) {
16,384,490!
6148
      return code;
×
6149
    }
6150
    if (!result) {
16,384,490✔
6151
      break;
7,657,682✔
6152
    }
6153
    if (row.isDataNull) {
8,726,808✔
6154
      continue;
630✔
6155
    }
6156
    pInfo->numOfElems++;
8,726,178✔
6157
    switch (pInputCol->info.type) {
8,726,178✔
6158
      case TSDB_DATA_TYPE_TINYINT: {
89,472✔
6159
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
89,472✔
6160
        break;
89,472✔
6161
      }
6162
      case TSDB_DATA_TYPE_SMALLINT: {
2,375,384✔
6163
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
2,375,384✔
6164
        break;
2,375,384✔
6165
      }
6166
      case TSDB_DATA_TYPE_INT: {
5,459,861✔
6167
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
5,459,861✔
6168
        break;
5,459,861✔
6169
      }
6170
      case TSDB_DATA_TYPE_BIGINT: {
96,062✔
6171
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
96,062✔
6172
        break;
96,062✔
6173
      }
6174
      case TSDB_DATA_TYPE_FLOAT: {
351,377✔
6175
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
351,377✔
6176
        break;
351,377✔
6177
      }
6178
      case TSDB_DATA_TYPE_DOUBLE: {
87,877✔
6179
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
87,877✔
6180
        break;
87,877✔
6181
      }
6182
      case TSDB_DATA_TYPE_UTINYINT: {
68,038✔
6183
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
68,038✔
6184
        break;
68,038✔
6185
      }
6186
      case TSDB_DATA_TYPE_USMALLINT: {
68,642✔
6187
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
68,642✔
6188
        break;
68,642✔
6189
      }
6190
      case TSDB_DATA_TYPE_UINT: {
70,512✔
6191
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
70,512✔
6192
        break;
70,512✔
6193
      }
6194
      case TSDB_DATA_TYPE_UBIGINT: {
58,868✔
6195
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
58,868✔
6196
        break;
58,868✔
6197
      }
6198
      default: {
85✔
6199
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
85✔
6200
      }
6201
    }
6202
    if (pInfo->p.key == st.key) {
8,726,093!
6203
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6204
    }
6205

6206
    pInfo->dOutput += twa_get_area(pInfo->p, st);
8,726,093✔
6207
    pInfo->p = st;
8,726,354✔
6208
  }
6209

6210
  // the last interpolated time window value
6211
  if (pCtx->end.key != INT64_MIN) {
7,657,682✔
6212
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
4,372,203✔
6213
    pInfo->p = pCtx->end;
4,372,200✔
6214
    pInfo->numOfElems += 1;
4,372,200✔
6215
  }
6216

6217
  pInfo->win.ekey = pInfo->p.key;
7,657,679✔
6218

6219
_twa_over:
7,657,679✔
6220
  SET_VAL(pResInfo, 1, 1);
7,657,679✔
6221
  return TSDB_CODE_SUCCESS;
7,657,679✔
6222
}
6223

6224
/*
6225
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6226
 * by next input data. The TWA function only applies to each table, so no merge procedure
6227
 * is required, we simply copy to the resut ot interResBuffer.
6228
 */
6229
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6230
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6231
//
6232
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6233
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6234
// }
6235

6236
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,642,063✔
6237
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,642,063✔
6238

6239
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,642,063✔
6240
  if (pInfo->numOfElems == 0) {
7,642,063✔
6241
    pResInfo->numOfRes = 0;
16,087✔
6242
  } else {
6243
    if (pInfo->win.ekey == pInfo->win.skey) {
7,625,976✔
6244
      pInfo->dTwaRes = pInfo->p.val;
2,846,898✔
6245
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
4,779,078!
6246
      pInfo->dTwaRes = 0;
×
6247
    } else {
6248
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
4,779,123✔
6249
    }
6250

6251
    pResInfo->numOfRes = 1;
7,625,976✔
6252
  }
6253

6254
  return functionFinalize(pCtx, pBlock);
7,642,063✔
6255
}
6256

6257
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,628✔
6258
  if (pResultInfo->initialized) {
1,628!
6259
    return TSDB_CODE_SUCCESS;
×
6260
  }
6261
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,628!
6262
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6263
  }
6264

6265
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,628✔
6266
  pInfo->minRows = INT32_MAX;
1,628✔
6267
  return TSDB_CODE_SUCCESS;
1,628✔
6268
}
6269

6270
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,253✔
6271
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,253✔
6272

6273
  SInputColumnInfoData* pInput = &pCtx->input;
3,253✔
6274
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,253✔
6275
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,253✔
6276
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,253✔
6277

6278
  STableBlockDistInfo p1 = {0};
3,253✔
6279
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,253!
6280
    qError("failed to deserialize block dist info");
×
6281
    return TSDB_CODE_FAILED;
×
6282
  }
6283

6284
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,253✔
6285
  pDistInfo->numOfTables += p1.numOfTables;
3,253✔
6286
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,253✔
6287
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,253✔
6288
  pDistInfo->totalSize += p1.totalSize;
3,253✔
6289
  pDistInfo->totalRows += p1.totalRows;
3,253✔
6290
  pDistInfo->numOfFiles += p1.numOfFiles;
3,253✔
6291

6292
  pDistInfo->defMinRows = p1.defMinRows;
3,253✔
6293
  pDistInfo->defMaxRows = p1.defMaxRows;
3,253✔
6294
  pDistInfo->rowSize = p1.rowSize;
3,253✔
6295

6296
  if (pDistInfo->minRows > p1.minRows) {
3,253✔
6297
    pDistInfo->minRows = p1.minRows;
2✔
6298
  }
6299
  if (pDistInfo->maxRows < p1.maxRows) {
3,253✔
6300
    pDistInfo->maxRows = p1.maxRows;
2✔
6301
  }
6302
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,253✔
6303
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,313✔
6304
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,060✔
6305
  }
6306

6307
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,253✔
6308
  return TSDB_CODE_SUCCESS;
3,253✔
6309
}
6310

6311
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,498✔
6312
  SEncoder encoder = {0};
6,498✔
6313
  int32_t  code = 0;
6,498✔
6314
  int32_t  lino;
6315
  int32_t  tlen;
6316
  tEncoderInit(&encoder, buf, bufLen);
6,498✔
6317

6318
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,501!
6319
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
13,002!
6320

6321
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
13,002!
6322
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
13,002!
6323
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
13,002!
6324

6325
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
13,002!
6326
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
13,002!
6327
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
13,002!
6328
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
13,002!
6329
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
13,002!
6330
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
13,002!
6331
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
13,002!
6332
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
13,002!
6333
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
13,002!
6334

6335
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,171✔
6336
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,340!
6337
  }
6338

6339
  tEndEncode(&encoder);
6,501✔
6340

6341
_exit:
6,496✔
6342
  if (code) {
6,496!
6343
    tlen = code;
×
6344
  } else {
6345
    tlen = encoder.pos;
6,496✔
6346
  }
6347
  tEncoderClear(&encoder);
6,496✔
6348
  return tlen;
6,497✔
6349
}
6350

6351
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,253✔
6352
  SDecoder decoder = {0};
3,253✔
6353
  int32_t  code = 0;
3,253✔
6354
  int32_t  lino;
6355
  tDecoderInit(&decoder, buf, bufLen);
3,253✔
6356

6357
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,253!
6358
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,506!
6359

6360
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,506!
6361
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,506!
6362
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,506!
6363

6364
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,506!
6365
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,506!
6366
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,506!
6367
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,506!
6368
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,506!
6369
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,506!
6370
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,506!
6371
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,506!
6372
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,506!
6373

6374
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,313✔
6375
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,120!
6376
  }
6377

6378
_exit:
3,253✔
6379
  tDecoderClear(&decoder);
3,253✔
6380
  return code;
3,253✔
6381
}
6382

6383
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,628✔
6384
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,628✔
6385
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,628✔
6386

6387
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,628✔
6388
  if (NULL == pColInfo) {
1,628!
6389
    return TSDB_CODE_OUT_OF_RANGE;
×
6390
  }
6391

6392
  if (pData->totalRows == 0) {
1,628✔
6393
    pData->minRows = 0;
1,626✔
6394
  }
6395

6396
  int32_t row = 0;
1,628✔
6397
  char    st[256] = {0};
1,628✔
6398
  double  averageSize = 0;
1,628✔
6399
  if (pData->numOfBlocks != 0) {
1,628✔
6400
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
2✔
6401
  }
6402
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,628✔
6403
  double   compRatio = 0;
1,628✔
6404
  if (totalRawSize != 0) {
1,628✔
6405
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
2✔
6406
  }
6407

6408
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6409
                          "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6410
                          pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,628✔
6411

6412
  varDataSetLen(st, len);
1,628✔
6413
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6414
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6415
    return code;
×
6416
  }
6417

6418
  int64_t avgRows = 0;
1,628✔
6419
  if (pData->numOfBlocks > 0) {
1,628✔
6420
    avgRows = pData->totalRows / pData->numOfBlocks;
2✔
6421
  }
6422

6423
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6424
                  "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6425
                  pData->minRows, pData->maxRows, avgRows);
6426
  varDataSetLen(st, len);
1,628✔
6427
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6428
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6429
    return code;
×
6430
  }
6431

6432
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
1,628✔
6433
                  pData->numOfInmemRows, pData->numOfSttRows);
6434
  varDataSetLen(st, len);
1,628✔
6435
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6436
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6437
    return code;
×
6438
  }
6439

6440
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6441
                  "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
1,628✔
6442
                  pData->numOfVgroups);
6443

6444
  varDataSetLen(st, len);
1,628✔
6445
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6446
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6447
    return code;
×
6448
  }
6449

6450
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6451
                  "--------------------------------------------------------------------------------");
6452
  varDataSetLen(st, len);
1,628✔
6453
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6454
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6455
    return code;
×
6456
  }
6457

6458
  int32_t maxVal = 0;
1,628✔
6459
  int32_t minVal = INT32_MAX;
1,628✔
6460
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6461
    if (maxVal < pData->blockRowsHisto[i]) {
32,560✔
6462
      maxVal = pData->blockRowsHisto[i];
4✔
6463
    }
6464

6465
    if (minVal > pData->blockRowsHisto[i]) {
32,560✔
6466
      minVal = pData->blockRowsHisto[i];
1,629✔
6467
    }
6468
  }
6469

6470
  // maximum number of step is 80
6471
  double factor = pData->numOfBlocks / 80.0;
1,628✔
6472

6473
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,628✔
6474
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,628✔
6475

6476
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6477
    len =
32,560✔
6478
        tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,560✔
6479

6480
    int32_t num = 0;
32,560✔
6481
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6482
      num = (pData->blockRowsHisto[i]) / factor;
4✔
6483
    }
6484

6485
    for (int32_t j = 0; j < num; ++j) {
32,719✔
6486
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
159✔
6487
      len += x;
159✔
6488
    }
6489

6490
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6491
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
4✔
6492
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
4✔
6493
                       pData->blockRowsHisto[i], v, '%');
6494
    }
6495

6496
    varDataSetLen(st, len);
32,560✔
6497
    code = colDataSetVal(pColInfo, row++, st, false);
32,560✔
6498
    if (TSDB_CODE_SUCCESS != code) {
32,560!
6499
      return code;
×
6500
    }
6501
  }
6502

6503
  return TSDB_CODE_SUCCESS;
1,628✔
6504
}
6505
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1✔
6506
  if (pResultInfo->initialized) {
1!
6507
    return TSDB_CODE_SUCCESS;
×
6508
  }
6509
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1!
6510
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6511
  }
6512

6513
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1✔
6514
  return TSDB_CODE_SUCCESS;
1✔
6515
}
6516
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
2✔
6517
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
2✔
6518

6519
  SInputColumnInfoData* pInput = &pCtx->input;
2✔
6520
  SColumnInfoData*      pInputCol = pInput->pData[0];
2✔
6521
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
2✔
6522
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
2✔
6523

6524
  SDBBlockUsageInfo p1 = {0};
2✔
6525
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
2!
6526
    qError("failed to deserialize block dist info");
×
6527
    return TSDB_CODE_FAILED;
×
6528
  }
6529

6530
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
2✔
6531
  pDistInfo->walInDiskSize += p1.walInDiskSize;
2✔
6532
  pDistInfo->rawDataSize += p1.rawDataSize;
2✔
6533
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
2✔
6534
  return TSDB_CODE_SUCCESS;
2✔
6535
}
6536

6537
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
4✔
6538
  SEncoder encoder = {0};
4✔
6539
  int32_t  code = 0;
4✔
6540
  int32_t  lino;
6541
  int32_t  tlen;
6542
  tEncoderInit(&encoder, buf, bufLen);
4✔
6543

6544
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
4!
6545

6546
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
8!
6547
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
8!
6548
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
8!
6549

6550
  tEndEncode(&encoder);
4✔
6551

6552
_exit:
4✔
6553
  if (code) {
4!
6554
    tlen = code;
×
6555
  } else {
6556
    tlen = encoder.pos;
4✔
6557
  }
6558
  tEncoderClear(&encoder);
4✔
6559
  return tlen;
4✔
6560
}
6561
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
2✔
6562
  SDecoder decoder = {0};
2✔
6563
  int32_t  code = 0;
2✔
6564
  int32_t  lino;
6565
  tDecoderInit(&decoder, buf, bufLen);
2✔
6566

6567
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
2!
6568
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
4!
6569
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
4!
6570
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
4!
6571

6572
_exit:
2✔
6573
  tDecoderClear(&decoder);
2✔
6574
  return code;
2✔
6575
}
6576
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1✔
6577
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1✔
6578
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
1✔
6579

6580
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1✔
6581
  if (NULL == pColInfo) {
1!
6582
    return TSDB_CODE_OUT_OF_RANGE;
×
6583
  }
6584
  int32_t len = 0;
1✔
6585
  int32_t row = 0;
1✔
6586
  char    st[256] = {0};
1✔
6587

6588
  uint64_t totalDiskSize = pData->dataInDiskSize;
1✔
6589
  uint64_t rawDataSize = pData->rawDataSize;
1✔
6590
  double   compressRadio = 0;
1✔
6591
  if (rawDataSize != 0) {
1!
6592
    compressRadio = totalDiskSize * 100 / (double)rawDataSize;
1✔
6593
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[%.2f]", compressRadio);
1✔
6594
  } else {
6595
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[NULL]");
×
6596
  }
6597

6598
  varDataSetLen(st, len);
1✔
6599
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1✔
6600
  if (TSDB_CODE_SUCCESS != code) {
1!
6601
    return code;
×
6602
  }
6603

6604
  len =
1✔
6605
      tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
1✔
6606
  varDataSetLen(st, len);
1✔
6607
  code = colDataSetVal(pColInfo, row++, st, false);
1✔
6608
  if (TSDB_CODE_SUCCESS != code) {
1!
6609
    return code;
×
6610
  }
6611
  return code;
1✔
6612
}
6613

6614
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,122✔
6615
  pEnv->calcMemSize = sizeof(SDerivInfo);
31,122✔
6616
  return true;
31,122✔
6617
}
6618

6619
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
63,342✔
6620
  if (pResInfo->initialized) {
63,342✔
6621
    return TSDB_CODE_SUCCESS;
32,094✔
6622
  }
6623
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,248!
6624
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6625
  }
6626

6627
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,248✔
6628

6629
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
31,248✔
6630
  pDerivInfo->prevTs = -1;
31,248✔
6631
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
31,248✔
6632
  pDerivInfo->valueSet = false;
31,248✔
6633
  return TSDB_CODE_SUCCESS;
31,248✔
6634
}
6635

6636
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
32,220✔
6637
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,220✔
6638
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
32,220✔
6639

6640
  SInputColumnInfoData* pInput = &pCtx->input;
32,220✔
6641
  SColumnInfoData*      pInputCol = pInput->pData[0];
32,220✔
6642

6643
  int32_t          numOfElems = 0;
32,220✔
6644
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
32,220✔
6645
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
32,220✔
6646
  int32_t          code = TSDB_CODE_SUCCESS;
32,220✔
6647

6648
  funcInputUpdate(pCtx);
32,220✔
6649

6650
  double v = 0;
32,220✔
6651
  if (pCtx->order == TSDB_ORDER_ASC) {
32,220✔
6652
    SFuncInputRow row = {0};
28,838✔
6653
    bool          result = false;
28,838✔
6654
    while (1) {
3,530,330✔
6655
      code = funcInputGetNextRow(pCtx, &row, &result);
3,559,168✔
6656
      if (TSDB_CODE_SUCCESS != code) {
3,559,168!
6657
        return code;
×
6658
      }
6659
      if (!result) {
3,559,168✔
6660
        break;
28,838✔
6661
      }
6662
      if (row.isDataNull) {
3,530,330✔
6663
        continue;
30,609✔
6664
      }
6665

6666
      char* d = row.pData;
3,499,721✔
6667
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
3,499,721!
6668

6669
      int32_t pos = pCtx->offset + numOfElems;
3,499,721✔
6670
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
3,499,721✔
6671
        pDerivInfo->valueSet = true;
27,526✔
6672
      } else {
6673
        if (row.ts == pDerivInfo->prevTs) {
3,472,195!
6674
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6675
        }
6676
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
3,472,195✔
6677
        if (pDerivInfo->ignoreNegative && r < 0) {
3,472,195✔
6678
        } else {
6679
          if (isinf(r) || isnan(r)) {
2,232,009!
6680
            colDataSetNULL(pOutput, pos);
×
6681
          } else {
6682
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
2,232,009✔
6683
            if (code != TSDB_CODE_SUCCESS) {
2,232,009!
6684
              return code;
×
6685
            }
6686
          }
6687

6688
          if (pTsOutput != NULL) {
2,232,009!
6689
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6690
          }
6691

6692
          // handle selectivity
6693
          if (pCtx->subsidiaries.num > 0) {
2,232,009✔
6694
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,700,777✔
6695
            if (code != TSDB_CODE_SUCCESS) {
1,700,777!
6696
              return code;
×
6697
            }
6698
          }
6699

6700
          numOfElems++;
2,232,009✔
6701
        }
6702
      }
6703

6704
      pDerivInfo->prevValue = v;
3,499,721✔
6705
      pDerivInfo->prevTs = row.ts;
3,499,721✔
6706
    }
6707
  } else {
6708
    SFuncInputRow row = {0};
3,382✔
6709
    bool          result = false;
3,382✔
6710
    while (1) {
334,638✔
6711
      code = funcInputGetNextRow(pCtx, &row, &result);
338,020✔
6712
      if (TSDB_CODE_SUCCESS != code) {
338,020!
6713
        return code;
×
6714
      }
6715
      if (!result) {
338,020✔
6716
        break;
3,382✔
6717
      }
6718
      if (row.isDataNull) {
334,638✔
6719
        continue;
40✔
6720
      }
6721

6722
      char* d = row.pData;
334,598✔
6723
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
334,598!
6724

6725
      int32_t pos = pCtx->offset + numOfElems;
334,598✔
6726
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
334,598✔
6727
        pDerivInfo->valueSet = true;
3,362✔
6728
      } else {
6729
        if (row.ts == pDerivInfo->prevTs) {
331,236!
6730
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6731
        }
6732
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
331,236✔
6733
        if (pDerivInfo->ignoreNegative && r < 0) {
331,236✔
6734
        } else {
6735
          if (isinf(r) || isnan(r)) {
150,567!
6736
            colDataSetNULL(pOutput, pos);
×
6737
          } else {
6738
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
150,567✔
6739
            if (code != TSDB_CODE_SUCCESS) {
150,567!
6740
              return code;
×
6741
            }
6742
          }
6743

6744
          if (pTsOutput != NULL) {
150,567!
6745
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6746
          }
6747

6748
          // handle selectivity
6749
          if (pCtx->subsidiaries.num > 0) {
150,567✔
6750
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
52,380✔
6751
            if (code != TSDB_CODE_SUCCESS) {
52,380!
6752
              return code;
×
6753
            }
6754
          }
6755
          numOfElems++;
150,567✔
6756
        }
6757
      }
6758

6759
      pDerivInfo->prevValue = v;
334,598✔
6760
      pDerivInfo->prevTs = row.ts;
334,598✔
6761
    }
6762
  }
6763

6764
  pResInfo->numOfRes = numOfElems;
32,220✔
6765

6766
  return TSDB_CODE_SUCCESS;
32,220✔
6767
}
6768

6769
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
1,608,788✔
6770

6771
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
122,107✔
6772
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
122,107✔
6773
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
122,107✔
6774
  return true;
122,292✔
6775
}
6776

6777
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
8,243,794✔
6778
  if (pResInfo->initialized) {
8,243,794!
6779
    return TSDB_CODE_SUCCESS;
×
6780
  }
6781
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
8,243,794!
6782
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6783
  }
6784

6785
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,243,800✔
6786

6787
  pInfo->firstKey = INT64_MIN;
8,243,800✔
6788
  pInfo->lastKey = INT64_MIN;
8,243,800✔
6789
  pInfo->firstValue = (double)INT64_MIN;
8,243,800✔
6790
  pInfo->lastValue = (double)INT64_MIN;
8,243,800✔
6791

6792
  pInfo->hasResult = 0;
8,243,800✔
6793
  return TSDB_CODE_SUCCESS;
8,243,800✔
6794
}
6795

6796
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
26,734,668✔
6797
  if (isFirst) {
26,734,668✔
6798
    pRateInfo->firstValue = v;
9,995,367✔
6799
    pRateInfo->firstKey = ts;
9,995,367✔
6800
    if (pRateInfo->firstPk) {
9,995,367✔
6801
      int32_t pkBytes;
6802
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
35!
6803
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
8!
6804
          pkBytes = getJsonValueLen(pk);
×
6805
        } else {
6806
          pkBytes = varDataTLen(pk);
8✔
6807
        }
6808
      } else {
6809
        pkBytes = pRateInfo->pkBytes;
27✔
6810
      }
6811
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6812
    }
6813
  } else {
6814
    pRateInfo->lastValue = v;
16,739,301✔
6815
    pRateInfo->lastKey = ts;
16,739,301✔
6816
    if (pRateInfo->lastPk) {
16,739,301✔
6817
      int32_t pkBytes;
6818
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
52!
6819
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
12!
6820
          pkBytes = getJsonValueLen(pk);
×
6821
        } else {
6822
          pkBytes = varDataTLen(pk);
12✔
6823
        }
6824
      } else {
6825
        pkBytes = pRateInfo->pkBytes;
40✔
6826
      }
6827
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6828
    }
6829
  }
6830
}
26,734,668✔
6831

6832
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
9,731,550✔
6833
  if (pCtx->hasPrimaryKey) {
9,731,550✔
6834
    if (!isMerge) {
19✔
6835
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6836
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6837
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6838
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6839
    } else {
6840
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6841
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6842
    }
6843
  } else {
6844
    pRateInfo->firstPk = NULL;
9,731,531✔
6845
    pRateInfo->lastPk = NULL;
9,731,531✔
6846
  }
6847
}
9,731,550✔
6848

6849
int32_t irateFunction(SqlFunctionCtx* pCtx) {
6,758,817✔
6850
  int32_t              code = TSDB_CODE_SUCCESS;
6,758,817✔
6851
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,758,817✔
6852
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,758,817✔
6853

6854
  SInputColumnInfoData* pInput = &pCtx->input;
6,758,817✔
6855
  SColumnInfoData*      pInputCol = pInput->pData[0];
6,758,817✔
6856

6857
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6,758,817✔
6858

6859
  funcInputUpdate(pCtx);
6,758,817✔
6860

6861
  initializeRateInfo(pCtx, pRateInfo, false);
6,758,830✔
6862

6863
  int32_t       numOfElems = 0;
6,758,802✔
6864
  int32_t       type = pInputCol->info.type;
6,758,802✔
6865
  SFuncInputRow row = {0};
6,758,802✔
6866
  bool          result = false;
6,758,802✔
6867
  while (1) {
15,513,122✔
6868
    code = funcInputGetNextRow(pCtx, &row, &result);
22,271,924✔
6869
    if (TSDB_CODE_SUCCESS != code) {
22,271,672!
6870
      return code;
×
6871
    }
6872
    if (!result) {
22,271,672✔
6873
      break;
6,758,827✔
6874
    }
6875
    if (row.isDataNull) {
15,512,845✔
6876
      continue;
119,658✔
6877
    }
6878

6879
    char*  data = row.pData;
15,393,187✔
6880
    double v = 0;
15,393,187✔
6881
    GET_TYPED_DATA(v, double, type, data);
15,393,187!
6882

6883
    if (INT64_MIN == pRateInfo->lastKey) {
15,393,187✔
6884
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
6,744,851✔
6885
      pRateInfo->hasResult = 1;
6,744,843✔
6886
      continue;
6,744,843✔
6887
    }
6888

6889
    if (row.ts > pRateInfo->lastKey) {
8,648,336✔
6890
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
8,508,463!
6891
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
8,508,464✔
6892
      }
6893
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
8,508,473✔
6894
      continue;
8,508,444✔
6895
    } else if (row.ts == pRateInfo->lastKey) {
139,873!
6896
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6897
    }
6898

6899
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
139,873!
6900
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
×
6901
    } else if (row.ts == pRateInfo->firstKey) {
139,877!
6902
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6903
    }
6904
  }
6905

6906
  numOfElems++;
6,758,827✔
6907

6908
  SET_VAL(pResInfo, numOfElems, 1);
6,758,827!
6909
  return TSDB_CODE_SUCCESS;
6,758,827✔
6910
}
6911

6912
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
6,739,552✔
6913
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
6,739,552✔
6914
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
895,202!
6915
    return 0.0;
5,844,350✔
6916
  }
6917

6918
  double diff = 0;
895,202✔
6919
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6920
  // value between two values.
6921
  diff = pRateInfo->lastValue;
895,202✔
6922
  if (diff >= pRateInfo->firstValue) {
895,202✔
6923
    diff -= pRateInfo->firstValue;
465,414✔
6924
  }
6925

6926
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
895,202✔
6927
  if (duration == 0) {
895,202!
6928
    return 0;
×
6929
  }
6930

6931
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
895,202!
6932
}
6933

6934
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
214✔
6935
  if (inputKey > pOutput->lastKey) {
214✔
6936
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
116✔
6937
    if (isFirstKey) {
116✔
6938
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
55✔
6939
    } else {
6940
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
61✔
6941
    }
6942
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
98!
6943
    if (isFirstKey) {
24✔
6944
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
12✔
6945
    } else {
6946
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
12✔
6947
    }
6948
  } else {
6949
    // inputKey < pOutput->firstKey
6950
  }
6951
}
214✔
6952

6953
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,486,273✔
6954
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,486,273✔
6955
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,486,273✔
6956
}
1,486,273✔
6957

6958
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,486,380✔
6959
  if ((pInput->firstKey != INT64_MIN &&
1,486,380✔
6960
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
261,943!
6961
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
1,486,380!
6962
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6963
  }
6964

6965
  if (pOutput->hasResult == 0) {
1,486,380✔
6966
    irateCopyInfo(pInput, pOutput);
1,486,273✔
6967
    pOutput->hasResult = pInput->hasResult;
1,486,273✔
6968
    return TSDB_CODE_SUCCESS;
1,486,273✔
6969
  }
6970

6971
  if (pInput->firstKey != INT64_MIN) {
107!
6972
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
107✔
6973
  }
6974

6975
  if (pInput->lastKey != INT64_MIN) {
107!
6976
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
107✔
6977
  }
6978

6979
  pOutput->hasResult = pInput->hasResult;
107✔
6980
  return TSDB_CODE_SUCCESS;
107✔
6981
}
6982

6983
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
1,486,392✔
6984
  SInputColumnInfoData* pInput = &pCtx->input;
1,486,392✔
6985
  SColumnInfoData*      pCol = pInput->pData[0];
1,486,392✔
6986
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,486,392!
6987
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6988
  }
6989

6990
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,486,392✔
6991
  initializeRateInfo(pCtx, pInfo, true);
1,486,392✔
6992

6993
  int32_t start = pInput->startRowIndex;
1,486,392✔
6994
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,972,784✔
6995
    char*      data = colDataGetData(pCol, i);
1,486,392!
6996
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
1,486,392✔
6997
    initializeRateInfo(pCtx, pInfo, true);
1,486,392✔
6998
    if (pInputInfo->hasResult) {
1,486,392✔
6999
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
1,486,380✔
7000
      if (code != TSDB_CODE_SUCCESS) {
1,486,380!
7001
        return code;
×
7002
      }
7003
    }
7004
  }
7005

7006
  if (pInfo->hasResult) {
1,486,392✔
7007
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,486,380✔
7008
  }
7009

7010
  return TSDB_CODE_SUCCESS;
1,486,392✔
7011
}
7012

7013
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,486,392✔
7014
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,486,392✔
7015
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,486,392✔
7016
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
1,486,392✔
7017
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,486,392!
7018

7019
  if (NULL == res) {
1,486,392!
7020
    return terrno;
×
7021
  }
7022
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,486,392✔
7023
  varDataSetLen(res, resultBytes);
1,486,392✔
7024

7025
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,486,392✔
7026
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,486,392✔
7027
  if (NULL == pCol) {
1,486,392!
7028
    taosMemoryFree(res);
×
7029
    return TSDB_CODE_OUT_OF_RANGE;
×
7030
  }
7031

7032
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,486,392✔
7033

7034
  taosMemoryFree(res);
1,486,392!
7035
  return code;
1,486,392✔
7036
}
7037

7038
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,739,696✔
7039
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
6,739,696✔
7040
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,739,696✔
7041
  if (NULL == pCol) {
6,739,565!
7042
    return TSDB_CODE_OUT_OF_RANGE;
×
7043
  }
7044

7045
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,739,565✔
7046
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
6,739,565✔
7047

7048
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,739,565✔
7049
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
6,739,565!
7050
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
6,739,562✔
7051

7052
  return code;
6,739,133✔
7053
}
7054

7055
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
108,029,686✔
7056
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
108,029,686✔
7057
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
108,029,686✔
7058

7059
  SInputColumnInfoData* pInput = &pCtx->input;
108,029,686✔
7060
  SColumnInfoData*      pInputCol = pInput->pData[0];
108,029,686✔
7061

7062
  int32_t startIndex = pInput->startRowIndex;
108,029,686✔
7063

7064
  // escape rest of data blocks to avoid first entry to be overwritten.
7065
  if (pInfo->hasResult) {
108,029,686✔
7066
    goto _group_value_over;
11,603,948✔
7067
  }
7068

7069
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
192,451,940✔
7070
    pInfo->isNull = true;
2,556,133✔
7071
    pInfo->hasResult = true;
2,556,133✔
7072
    goto _group_value_over;
2,556,133✔
7073
  }
7074

7075
  char* data = colDataGetData(pInputCol, startIndex);
93,869,605!
7076
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
93,869,605!
7077
    (void)memcpy(pInfo->data, data,
72,975,938✔
7078
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
72,975,938✔
7079
  } else {
7080
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
20,893,667✔
7081
  }
7082
  pInfo->hasResult = true;
93,869,605✔
7083

7084
_group_value_over:
108,029,686✔
7085

7086
  SET_VAL(pResInfo, 1, 1);
108,029,686✔
7087
  return TSDB_CODE_SUCCESS;
108,029,686✔
7088
}
7089

7090
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
107,013,095✔
7091

7092
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
94,858,257✔
7093
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
94,858,257✔
7094
  int32_t          code = TSDB_CODE_SUCCESS;
94,858,257✔
7095
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
94,858,257✔
7096
  if (NULL == pCol) {
94,758,317!
7097
    return TSDB_CODE_OUT_OF_RANGE;
×
7098
  }
7099

7100
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
94,758,317✔
7101

7102
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
94,758,317✔
7103

7104
  if (pInfo->hasResult) {
94,758,317!
7105
    int32_t currentRow = pBlock->info.rows;
94,794,992✔
7106
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
190,431,128✔
7107
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
94,814,961✔
7108
      if (TSDB_CODE_SUCCESS != code) {
95,636,136!
7109
        return code;
×
7110
      }
7111
    }
7112
  } else {
7113
    pResInfo->numOfRes = 0;
×
7114
  }
7115

7116
  return code;
95,579,492✔
7117
}
7118

7119
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
94,667,036✔
7120

7121
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7122
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7123
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7124

7125
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7126
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7127

7128
  // escape rest of data blocks to avoid first entry to be overwritten.
7129
  if (pDBuf->hasResult) {
×
7130
    goto _group_key_over;
×
7131
  }
7132

7133
  if (pSBuf->isNull) {
×
7134
    pDBuf->isNull = true;
×
7135
    pDBuf->hasResult = true;
×
7136
    goto _group_key_over;
×
7137
  }
7138

7139
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7140
    (void)memcpy(pDBuf->data, pSBuf->data,
×
7141
                 (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data)
×
7142
                                                                       : varDataTLen(pSBuf->data));
×
7143
  } else {
7144
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7145
  }
7146

7147
  pDBuf->hasResult = true;
×
7148

7149
_group_key_over:
×
7150

7151
  SET_VAL(pDResInfo, 1, 1);
×
7152
  return TSDB_CODE_SUCCESS;
×
7153
}
7154

7155
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
10,761✔
7156
  int32_t numOfElems = 0;
10,761✔
7157

7158
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,761✔
7159
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
10,761✔
7160

7161
  SInputColumnInfoData* pInput = &pCtx->input;
10,761✔
7162
  SColumnInfoData*      pInputCol = pInput->pData[0];
10,761✔
7163

7164
  int32_t bytes = pInputCol->info.bytes;
10,761✔
7165
  pInfo->bytes = bytes;
10,761✔
7166

7167
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
10,761✔
7168
  pInfo->pkType = -1;
10,761✔
7169
  __compar_fn_t pkCompareFn = NULL;
10,761✔
7170
  if (pCtx->hasPrimaryKey) {
10,761✔
7171
    pInfo->pkType = pkCol->info.type;
2,936✔
7172
    pInfo->pkBytes = pkCol->info.bytes;
2,936✔
7173
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
2,936✔
7174
  }
7175

7176
  // TODO it traverse the different way.
7177
  // last_row function does not ignore the null value
7178
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
21,533✔
7179
    numOfElems++;
10,772✔
7180

7181
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
10,772✔
7182
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
10,772!
7183

7184
    TSKEY cts = getRowPTs(pInput->pPTS, i);
10,772✔
7185
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
10,772✔
7186
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
9,102✔
7187
      if (code != TSDB_CODE_SUCCESS) {
9,101!
7188
        return code;
×
7189
      }
7190
      pResInfo->numOfRes = 1;
9,101✔
7191
    }
7192
  }
7193

7194
  SET_VAL(pResInfo, numOfElems, 1);
10,761!
7195
  return TSDB_CODE_SUCCESS;
10,761✔
7196
}
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

© 2026 Coveralls, Inc