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

taosdata / TDengine / #3543

29 Nov 2024 02:58AM UTC coverage: 60.842% (+0.02%) from 60.819%
#3543

push

travis-ci

web-flow
Merge pull request #28973 from taosdata/merge/mainto3.0

merge: from main to 3.0

120460 of 253224 branches covered (47.57%)

Branch coverage included in aggregate %.

706 of 908 new or added lines in 18 files covered. (77.75%)

2401 existing lines in 137 files now uncovered.

201633 of 276172 relevant lines covered (73.01%)

19045673.23 hits per line

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

74.25
/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){
1,645,936,693✔
32
  return (ignoreOption & 0x1) == 0x1;
1,645,936,693✔
33
}
34
bool ignoreNull(int8_t ignoreOption){
1,989,380✔
35
  return (ignoreOption & 0x2) == 0x2;
1,989,380✔
36
}
37

38
typedef enum {
39
  APERCT_ALGO_UNKNOWN = 0,
40
  APERCT_ALGO_DEFAULT,
41
  APERCT_ALGO_TDIGEST,
42
} EAPerctAlgoType;
43

44
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
45

46
typedef enum {
47
  STATE_OPER_INVALID = 0,
48
  STATE_OPER_LT,
49
  STATE_OPER_GT,
50
  STATE_OPER_LE,
51
  STATE_OPER_GE,
52
  STATE_OPER_NE,
53
  STATE_OPER_EQ,
54
} EStateOperType;
55

56
#define SET_VAL(_info, numOfElem, res) \
57
  do {                                 \
58
    if ((numOfElem) <= 0) {            \
59
      break;                           \
60
    }                                  \
61
    (_info)->numOfRes = (res);         \
62
  } while (0)
63

64
#define GET_TS_LIST(x)    ((TSKEY*)((x)->ptsList))
65
#define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)])
66

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

79
#define UPDATE_DATA(ctx, left, right, num, sign, _ts) \
80
  do {                                                \
81
    if (((left) < (right)) ^ (sign)) {                \
82
      (left) = (right);                               \
83
      DO_UPDATE_SUBSID_RES(ctx, _ts);                 \
84
      (num) += 1;                                     \
85
    }                                                 \
86
  } while (0)
87

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

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

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

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

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

152
#define LEASTSQR_CAL(p, x, y, index, step) \
153
  do {                                     \
154
    (p)[0][0] += (double)(x) * (x);        \
155
    (p)[0][1] += (double)(x);              \
156
    (p)[0][2] += (double)(x) * (y)[index]; \
157
    (p)[1][2] += (y)[index];               \
158
    (x) += step;                           \
159
  } while (0)
160

161
#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
162

163
#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
164

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

191
#define INIT_INTP_POINT(_p, _k, _v) \
192
  do {                              \
193
    (_p).key = (_k);                \
194
    (_p).val = (_v);                \
195
  } while (0)
196

197
void funcInputUpdate(SqlFunctionCtx* pCtx) {
19,265,285✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
19,265,285✔
199

200
  if (!pCtx->bInputFinished) {
19,265,285!
201
    pIter->pInput = &pCtx->input;
19,265,334✔
202
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
19,265,334✔
203
    pIter->pDataCol = pIter->pInput->pData[0];
19,265,334✔
204
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
19,265,334✔
205
    pIter->rowIndex = pIter->pInput->startRowIndex;
19,265,334✔
206
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
19,265,334✔
207
    pIter->pSrcBlock = pCtx->pSrcBlock;
19,265,334✔
208
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
19,265,334✔
209
      pIter->hasGroupId = true;
227,488✔
210
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
227,488✔
211
      pIter->hasPrev = false;
227,488✔
212
    }
213
  } else {
214
    pIter->finalRow = true;
×
215
  }
216
}
19,265,285✔
217

218
int32_t funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow, bool *res) {
×
219
  if (pIter->finalRow) {
×
220
    if (pIter->hasPrev) {
×
221
      pRow->ts = pIter->prevBlockTsEnd;
×
222
      pRow->isDataNull = pIter->prevIsDataNull;
×
223
      pRow->pData = pIter->pPrevData;
×
224
      pRow->block = pIter->pPrevRowBlock;
×
225
      pRow->rowIndex = 0;
×
226
      
227
      pIter->hasPrev = false;
×
228
      *res = true;
×
229
      return TSDB_CODE_SUCCESS;
×
230
    } else {
231
      *res = false;
×
232
      return TSDB_CODE_SUCCESS;
×
233
    }
234
  }
235
  if (pIter->hasPrev) {
×
236
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
×
237
      blockDataDestroy(pIter->pPrevRowBlock);
×
238
      int32_t code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
239
      if (code) {
×
240
        return code;
×
241
      }
242

243
      pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex);
×
244

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

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

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

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

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

331
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
28,898✔
332
  int32_t idx = rowIndex + 1;
28,898✔
333
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
405,024!
334
    ++idx;
376,126✔
335
  }
336
  pIter->rowIndex = idx;
28,898✔
337
}
28,898✔
338

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

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

360
      pIter->hasPrev = false;
1,638✔
361
      setInputRowInfo(pRow, pIter, idx, true);
1,638✔
362
      forwardToNextDiffTsRow(pIter, idx);
1,638✔
363
      return true;
1,638✔
364
    }
365
  } else {
366
    if (pIter->rowIndex <= pIter->inputEndIndex) { 
33,358✔
367
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
30,314✔
368

369
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
30,314✔
370
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
30,314✔
371
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
27,260✔
372
      } else {
373
        pIter->rowIndex = pIter->inputEndIndex + 1;
3,054✔
374
      }
375
      return true;
30,314✔
376
    } else {
377
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,044✔
378
      pIter->hasPrev = true;
3,044✔
379
      pIter->prevBlockTsEnd = tsEnd;
3,044✔
380
      return false;
3,044✔
381
    }
382
  }
383
}
384

385
bool funcInputGetNextRowNoPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) {
1,708,221,592✔
386
  if (pIter->rowIndex <= pIter->inputEndIndex) {
1,708,221,592✔
387
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
1,689,100,679✔
388
    ++pIter->rowIndex;
1,689,110,520✔
389
    return true;    
1,689,110,520✔
390
  } else {
391
    return false;    
19,120,913✔
392
  }
393
}
394

395
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool *res) {
1,708,216,942✔
396
  SFuncInputRowIter* pIter = &pCtx->rowIter;
1,708,216,942✔
397
  if (pCtx->hasPrimaryKey) {
1,708,216,942✔
398
    if (pCtx->order == TSDB_ORDER_ASC) {
34,996!
399
      *res = funcInputGetNextRowAscPk(pIter, pRow);
34,996✔
400
      return TSDB_CODE_SUCCESS;
34,996✔
401
    } else {
402
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
403
    }
404
  } else {
405
    *res = funcInputGetNextRowNoPk(pIter, pRow);
1,708,181,946✔
406
    return TSDB_CODE_SUCCESS;
1,708,182,794✔
407
  }
408
  return TSDB_CODE_SUCCESS;
409
}
410

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

418
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
92,554,482✔
419
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
59,130,181✔
420

421
    // get data from source col
422
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
59,130,181✔
423
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
59,130,181✔
424

425
    SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
59,130,181✔
426
    if (NULL == pSrcCol) {
59,130,181!
427
      return TSDB_CODE_OUT_OF_RANGE;
×
428
    }
429

430
    char* pData = colDataGetData(pSrcCol, rowIndex);
59,130,181!
431

432
    // append to dest col
433
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
59,130,181✔
434

435
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
59,130,181✔
436
    if (NULL == pDstCol) {
59,130,181!
437
      return TSDB_CODE_OUT_OF_RANGE;
×
438
    }
439
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
118,260,362✔
440
      colDataSetNULL(pDstCol, pos);
2,580,095✔
441
    } else {
442
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
56,550,086✔
443
      if (TSDB_CODE_SUCCESS != code) {
56,550,086!
444
        return code;
×
445
      }
446
    }
447
  }
448
  return TSDB_CODE_SUCCESS;
33,424,301✔
449
}
450

451
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex, int32_t* nextFrom);
452

453
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);
454

455
int32_t functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
785,633,277✔
456
  if (pResultInfo->initialized) {
785,633,277✔
457
    return TSDB_CODE_SUCCESS;  // already initialized
58,909✔
458
  }
459

460
  if (pCtx->pOutput != NULL) {
785,574,368!
461
    (void)memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes);
×
462
  }
463

464
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
785,574,368✔
465
  return TSDB_CODE_SUCCESS;
785,574,368✔
466
}
467

468
int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
194,553,170✔
469
  int32_t          code = TSDB_CODE_SUCCESS;
194,553,170✔
470
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
194,553,170✔
471
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
194,553,170✔
472
  if (NULL == pCol) {
193,945,849!
473
    return TSDB_CODE_OUT_OF_RANGE;
×
474
  }
475
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
193,945,849✔
476
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
193,945,849✔
477

478
  char* in = GET_ROWCELL_INTERBUF(pResInfo);
193,945,849✔
479
  code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
193,945,849✔
480

481
  return code;
195,464,969✔
482
}
483

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

489
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
490
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
491

492
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, true);
3✔
493

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

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

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

511
  return code;
1,084✔
512
}
513

514
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
200,972✔
515
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
200,972✔
516
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
201,004!
517
    return FUNC_DATA_REQUIRED_NOT_LOAD;
147,711✔
518
  }
519
  return FUNC_DATA_REQUIRED_SMA_LOAD;
53,293✔
520
}
521

522
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,523,242✔
523
  pEnv->calcMemSize = sizeof(int64_t);
1,523,242✔
524
  return true;
1,523,242✔
525
}
526

527
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
121,870,802✔
528
  int64_t numOfElem = 0;
121,870,802✔
529

530
  /*
531
   * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true;
532
   * 2. for general non-primary key columns, pInputCol->hasNull may be true or false, pInput->colDataSMAIsSet == true;
533
   * 3. for primary key column, pInputCol->hasNull always be false, pInput->colDataSMAIsSet == false;
534
   */
535
  SInputColumnInfoData* pInput = &pCtx->input;
121,870,802✔
536
  SColumnInfoData*      pInputCol = pInput->pData[0];
121,870,802✔
537
  if(1 == pInput->numOfRows && pInput->blankFill) {
121,870,802✔
538
    return 0;
453,992✔
539
  }
540
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
121,416,810!
541
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
3,476✔
542
  } else {
543
    if (pInputCol->hasNull) {
121,413,334✔
544
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
350,195,359✔
545
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
638,317,060!
546
          continue;
4,318,757✔
547
        }
548
        numOfElem += 1;
314,839,773✔
549
      }
550
    } else {
551
      // when counting on the primary time stamp column and no statistics data is presented, use the size value
552
      // directly.
553
      numOfElem = pInput->numOfRows;
90,376,505✔
554
    }
555
  }
556
  return numOfElem;
121,416,810✔
557
}
558

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

566
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
121,794,073✔
567
  SInputColumnInfoData* pInput = &pCtx->input;
121,794,073✔
568

569
  int32_t type = pInput->pData[0]->info.type;
121,794,073✔
570

571
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
121,794,073✔
572
  if (IS_NULL_TYPE(type)) {
121,794,073✔
573
    // select count(NULL) returns 0
574
    numOfElem = 1;
113,247✔
575
    *((int64_t*)buf) += 0;
113,247✔
576
  } else {
577
    numOfElem = getNumOfElems(pCtx);
121,680,826✔
578
    *((int64_t*)buf) += numOfElem;
121,640,241✔
579
  }
580

581
  if (tsCountAlwaysReturnValue) {
121,753,488!
582
    pResInfo->numOfRes = 1;
121,868,031✔
583
  } else {
584
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
585
  }
586

587
  return TSDB_CODE_SUCCESS;
121,753,488✔
588
}
589

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

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

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

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

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

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

615
int32_t sumFunction(SqlFunctionCtx* pCtx) {
93,744,117✔
616
  int32_t numOfElem = 0;
93,744,117✔
617

618
  // Only the pre-computing information loaded and actual data does not loaded
619
  SInputColumnInfoData* pInput = &pCtx->input;
93,744,117✔
620
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
93,744,117✔
621
  int32_t               type = pInput->pData[0]->info.type;
93,744,117✔
622

623
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
93,744,117✔
624
  pSumRes->type = type;
93,744,117✔
625

626
  if (IS_NULL_TYPE(type)) {
93,744,117✔
627
    numOfElem = 0;
254✔
628
    goto _sum_over;
254✔
629
  }
630

631
  if (pInput->colDataSMAIsSet) {
93,743,863✔
632
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
2,962✔
633

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

644
    int32_t start = pInput->startRowIndex;
93,740,901✔
645
    int32_t numOfRows = pInput->numOfRows;
93,740,901✔
646

647
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
93,740,901!
648
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
93,550,203!
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
18,026,712✔
650
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
88,194,380✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
492,207✔
652
      } else if (type == TSDB_DATA_TYPE_INT) {
88,145,294✔
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
399,745,981✔
654
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
22,084,602✔
655
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
82,656,964✔
656
      }
657
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
190,698!
658
      if (type == TSDB_DATA_TYPE_UTINYINT) {
465✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
660
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
426✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
662
      } else if (type == TSDB_DATA_TYPE_UINT) {
386✔
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
133,438!
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
248!
665
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
134,131✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
190,233✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
2,202,283✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
93,618✔
670
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
982,733✔
671
    }
672
  }
673

674
  // check for overflow
675
  if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
93,743,863!
676
    numOfElem = 0;
×
677
  }
678

679
_sum_over:
93,980,334✔
680
  if (numOfElem == 0) {
93,744,117✔
681
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
86,759✔
682
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,811✔
683
      numOfElem = 1;
22✔
684
    }
685
  }
686
  // data in the check operation are all null, not output
687
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
93,744,117✔
688
  return TSDB_CODE_SUCCESS;
93,744,117✔
689
}
690

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

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

700
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
701

702
  if (pInput->colDataSMAIsSet) {
703
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
704

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

715
    int32_t start = pInput->startRowIndex;
716
    int32_t numOfRows = pInput->numOfRows;
717

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

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

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

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

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

771
bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
288,054✔
772
  pEnv->calcMemSize = sizeof(SSumRes);
288,054✔
773
  return true;
288,054✔
774
}
775

776
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
163,601✔
777
  return FUNC_DATA_REQUIRED_SMA_LOAD;
163,601✔
778
}
779

780
int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
70,339,268✔
781
  if (pResultInfo->initialized) {
70,339,268!
782
    return TSDB_CODE_SUCCESS;
×
783
  }
784
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
70,339,268!
785
    return TSDB_CODE_FUNC_SETUP_ERROR;  // not initialized since it has been initialized
×
786
  }
787

788
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
70,360,884✔
789
  buf->assign = false;
70,360,884✔
790
  buf->tuplePos.pageId = -1;
70,360,884✔
791

792
  buf->nullTupleSaved = false;
70,360,884✔
793
  buf->nullTuplePos.pageId = -1;
70,360,884✔
794
  buf->str = NULL;
70,360,884✔
795
  return TSDB_CODE_SUCCESS;
70,360,884✔
796
}
797

798
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
507,360✔
799
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
507,360✔
800
  return true;
507,360✔
801
}
802

803
int32_t minFunction(SqlFunctionCtx* pCtx) {
36,617,164✔
804
  int32_t numOfElems = 0;
36,617,164✔
805
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
36,617,164✔
806
  if (code != TSDB_CODE_SUCCESS) {
36,700,281!
807
    return code;
×
808
  }
809
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
36,700,281✔
810
  return TSDB_CODE_SUCCESS;
36,700,281✔
811
}
812

813
int32_t maxFunction(SqlFunctionCtx* pCtx) {
41,953,358✔
814
  int32_t numOfElems = 0;
41,953,358✔
815
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
41,953,358✔
816
  if (code != TSDB_CODE_SUCCESS) {
42,010,122!
817
    return code;
×
818
  }
819
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
42,010,122✔
820
  return TSDB_CODE_SUCCESS;
42,010,122✔
821
}
822

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

827
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
68,480,830✔
828
  int32_t code = TSDB_CODE_SUCCESS;
68,480,830✔
829

830
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
68,480,830✔
831
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
68,480,830✔
832

833
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
68,480,830✔
834
  int32_t currentRow = pBlock->info.rows;
68,480,830✔
835

836
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
68,480,830✔
837
  if (NULL == pCol) {
68,477,232!
838
    return TSDB_CODE_OUT_OF_RANGE;
×
839
  }
840
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
68,477,232✔
841

842
  // NOTE: do nothing change it, for performance issue
843
  if (!pEntryInfo->isNullRes) {
68,477,232✔
844
    switch (pCol->info.type) {
61,251,067!
845
      case TSDB_DATA_TYPE_UBIGINT:
19,308,302✔
846
      case TSDB_DATA_TYPE_BIGINT:
847
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
19,308,302✔
848
        break;
19,308,302✔
849
      case TSDB_DATA_TYPE_UINT:
22,438,888✔
850
      case TSDB_DATA_TYPE_INT:
851
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
22,438,888✔
852
        break;
22,438,888✔
853
      case TSDB_DATA_TYPE_USMALLINT:
201,478✔
854
      case TSDB_DATA_TYPE_SMALLINT:
855
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
201,478✔
856
        break;
201,478✔
857
      case TSDB_DATA_TYPE_BOOL:
187,913✔
858
      case TSDB_DATA_TYPE_UTINYINT:
859
      case TSDB_DATA_TYPE_TINYINT:
860
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
187,913✔
861
        break;
187,913✔
862
      case TSDB_DATA_TYPE_DOUBLE:
14,295,848✔
863
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
14,295,848✔
864
        break;
14,295,848✔
865
      case TSDB_DATA_TYPE_FLOAT: {
4,845,771✔
866
        float v = GET_FLOAT_VAL(&pRes->v);
4,845,771✔
867
        colDataSetFloat(pCol, currentRow, &v);
4,845,771✔
868
        break;
4,845,771✔
869
      }
870
      case TSDB_DATA_TYPE_VARBINARY:
1,240✔
871
      case TSDB_DATA_TYPE_VARCHAR:
872
      case TSDB_DATA_TYPE_NCHAR: {
873
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
1,240✔
874
        if (TSDB_CODE_SUCCESS != code) {
1,240!
875
          return code;
×
876
        }
877
        break;
1,240✔
878
      }
879
    }
880
  } else {
881
    colDataSetNULL(pCol, currentRow);
7,226,165!
882
  }
883

884
  taosMemoryFreeClear(pRes->str);
68,477,232✔
885
  if (pCtx->subsidiaries.num > 0) {
68,477,232✔
886
    if (pEntryInfo->numOfRes > 0) {
18,429,576✔
887
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
18,426,880✔
888
    } else {
889
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
2,696✔
890
    }
891
  }
892

893
  return code;
68,485,150✔
894
}
895

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

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

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

910
  return TSDB_CODE_SUCCESS;
911
}
912
#endif
913

914
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
303,730,331✔
915
  if (pCtx->subsidiaries.num <= 0) {
303,730,331✔
916
    return TSDB_CODE_SUCCESS;
137,674,581✔
917
  }
918

919
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
166,055,750!
920
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
921
    int32_t     numOfCols = pCtx->subsidiaries.num;
166,061,480✔
922
    char* p = NULL;
166,061,480✔
923
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
166,061,480✔
924
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
167,218,190!
925
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
926
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
927
      return TSDB_CODE_NOT_FOUND;
×
928
    }
929

930
    bool* nullList = (bool*)p;
167,224,064✔
931
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
167,224,064✔
932

933
    // todo set the offset value to optimize the performance.
934
    for (int32_t j = 0; j < numOfCols; ++j) {
333,666,517✔
935
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
167,254,995✔
936
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
167,254,995✔
937

938
      // group_key function has its own process function
939
      // do not process there
940
      if (fmIsGroupKeyFunc(pc->functionId)) {
167,254,995✔
941
        continue;
41,325✔
942
      }
943

944
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
167,210,360✔
945
      if (NULL == pDstCol) {
166,826,600!
946
        return TSDB_CODE_OUT_OF_RANGE;
×
947
      }
948
      if (nullList[j]) {
166,826,600✔
949
        colDataSetNULL(pDstCol, rowIndex);
332!
950
      } else {
951
        code = colDataSetVal(pDstCol, rowIndex, pStart, false);
166,826,268✔
952
        if (TSDB_CODE_SUCCESS != code) {
166,400,796!
953
          return code;
×
954
        }
955
      }
956
      pStart += pDstCol->info.bytes;
166,401,128✔
957
    }
958
  }
959

960
  return TSDB_CODE_SUCCESS;
166,405,792✔
961
}
962

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

970
  int32_t code = TSDB_CODE_SUCCESS;
54,902,190✔
971
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
109,752,071✔
972
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
54,912,013✔
973

974
    // get data from source col
975
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
54,912,013✔
976
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
54,912,013✔
977

978
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
54,912,013✔
979
    if (NULL == pSrcCol) {
54,873,579!
980
      return TSDB_CODE_OUT_OF_RANGE;
×
981
    }
982

983
    char* pData = colDataGetData(pSrcCol, rowIndex);
54,873,579!
984

985
    // append to dest col
986
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
54,873,579✔
987

988
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
54,873,579✔
989
    if (NULL == pDstCol) {
54,840,723!
990
      return TSDB_CODE_OUT_OF_RANGE;
×
991
    }
992

993
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
109,681,446✔
994
      colDataSetNULL(pDstCol, pos);
560✔
995
    } else {
996
      code = colDataSetVal(pDstCol, pos, pData, false);
54,840,163✔
997
      if (TSDB_CODE_SUCCESS != code) {
54,849,321!
998
        return code;
×
999
      }
1000
    }
1001
  }
1002
  return code;
54,840,058✔
1003
}
1004

1005
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
32✔
1006

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

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

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

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

1079
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
948,160✔
1080

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

1086
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,820,984✔
1087
  if (pResultInfo->initialized) {
5,820,984!
1088
    return TSDB_CODE_SUCCESS;
×
1089
  }
1090
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,820,984!
1091
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1092
  }
1093

1094
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
5,821,004✔
1095
  (void)memset(pRes, 0, sizeof(SStdRes));
5,821,004✔
1096
  return TSDB_CODE_SUCCESS;
5,821,004✔
1097
}
1098

1099
int32_t stdFunction(SqlFunctionCtx* pCtx) {
4,896,864✔
1100
  int32_t numOfElem = 0;
4,896,864✔
1101

1102
  // Only the pre-computing information loaded and actual data does not loaded
1103
  SInputColumnInfoData* pInput = &pCtx->input;
4,896,864✔
1104
  int32_t               type = pInput->pData[0]->info.type;
4,896,864✔
1105

1106
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,896,864✔
1107
  pStdRes->type = type;
4,896,864✔
1108

1109
  // computing based on the true data block
1110
  SColumnInfoData* pCol = pInput->pData[0];
4,896,864✔
1111

1112
  int32_t start = pInput->startRowIndex;
4,896,864✔
1113
  int32_t numOfRows = pInput->numOfRows;
4,896,864✔
1114

1115
  if (IS_NULL_TYPE(type)) {
4,896,864✔
1116
    numOfElem = 0;
149✔
1117
    goto _stddev_over;
149✔
1118
  }
1119

1120
  switch (type) {
4,896,715!
1121
    case TSDB_DATA_TYPE_TINYINT: {
15,736✔
1122
      int8_t* plist = (int8_t*)pCol->pData;
15,736✔
1123
      for (int32_t i = start; i < numOfRows + start; ++i) {
508,788✔
1124
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
493,052✔
1125
          continue;
31,621✔
1126
        }
1127

1128
        numOfElem += 1;
461,431✔
1129
        pStdRes->count += 1;
461,431✔
1130
        pStdRes->isum += plist[i];
461,431✔
1131
        pStdRes->quadraticISum += plist[i] * plist[i];
461,431✔
1132
      }
1133

1134
      break;
15,736✔
1135
    }
1136

1137
    case TSDB_DATA_TYPE_SMALLINT: {
234,776✔
1138
      int16_t* plist = (int16_t*)pCol->pData;
234,776✔
1139
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
895,004✔
1140
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
660,228✔
1141
          continue;
113,121✔
1142
        }
1143

1144
        numOfElem += 1;
547,107✔
1145
        pStdRes->count += 1;
547,107✔
1146
        pStdRes->isum += plist[i];
547,107✔
1147
        pStdRes->quadraticISum += plist[i] * plist[i];
547,107✔
1148
      }
1149
      break;
234,776✔
1150
    }
1151

1152
    case TSDB_DATA_TYPE_INT: {
20,911✔
1153
      int32_t* plist = (int32_t*)pCol->pData;
20,911✔
1154
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,556,842✔
1155
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,535,931✔
1156
          continue;
26,886✔
1157
        }
1158

1159
        numOfElem += 1;
1,509,045✔
1160
        pStdRes->count += 1;
1,509,045✔
1161
        pStdRes->isum += plist[i];
1,509,045✔
1162
        pStdRes->quadraticISum += plist[i] * plist[i];
1,509,045✔
1163
      }
1164

1165
      break;
20,911✔
1166
    }
1167

1168
    case TSDB_DATA_TYPE_BIGINT: {
21,880✔
1169
      int64_t* plist = (int64_t*)pCol->pData;
21,880✔
1170
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,230,339✔
1171
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,208,459✔
1172
          continue;
98,043✔
1173
        }
1174

1175
        numOfElem += 1;
1,110,416✔
1176
        pStdRes->count += 1;
1,110,416✔
1177
        pStdRes->isum += plist[i];
1,110,416✔
1178
        pStdRes->quadraticISum += plist[i] * plist[i];
1,110,416✔
1179
      }
1180
      break;
21,880✔
1181
    }
1182

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

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

1196
      break;
25✔
1197
    }
1198

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

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

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

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

1227
      break;
25✔
1228
    }
1229

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

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

1245
    case TSDB_DATA_TYPE_FLOAT: {
4,556,431✔
1246
      float* plist = (float*)pCol->pData;
4,556,431✔
1247
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
15,410,290✔
1248
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
10,853,859✔
1249
          continue;
167,634✔
1250
        }
1251

1252
        numOfElem += 1;
10,686,225✔
1253
        pStdRes->count += 1;
10,686,225✔
1254
        pStdRes->dsum += plist[i];
10,686,225✔
1255
        pStdRes->quadraticDSum += plist[i] * plist[i];
10,686,225✔
1256
      }
1257
      break;
4,556,431✔
1258
    }
1259

1260
    case TSDB_DATA_TYPE_DOUBLE: {
46,885✔
1261
      double* plist = (double*)pCol->pData;
46,885✔
1262
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
3,140,429✔
1263
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
3,093,544✔
1264
          continue;
593,891✔
1265
        }
1266

1267
        numOfElem += 1;
2,499,653✔
1268
        pStdRes->count += 1;
2,499,653✔
1269
        pStdRes->dsum += plist[i];
2,499,653✔
1270
        pStdRes->quadraticDSum += plist[i] * plist[i];
2,499,653✔
1271
      }
1272
      break;
46,885✔
1273
    }
1274

1275
    default:
×
1276
      break;
×
1277
  }
1278

1279
_stddev_over:
4,896,864✔
1280
  // data in the check operation are all null, not output
1281
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
4,896,864✔
1282
  return TSDB_CODE_SUCCESS;
4,896,864✔
1283
}
1284

1285
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
946,815✔
1286
  if (IS_NULL_TYPE(pInput->type)) {
946,815✔
1287
    return;
80✔
1288
  }
1289
  pOutput->type = pInput->type;
946,735✔
1290
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
946,735!
1291
    pOutput->quadraticISum += pInput->quadraticISum;
10,109✔
1292
    pOutput->isum += pInput->isum;
10,109✔
1293
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
936,626!
1294
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1295
    pOutput->usum += pInput->usum;
1✔
1296
  } else {
1297
    pOutput->quadraticDSum += pInput->quadraticDSum;
936,625✔
1298
    pOutput->dsum += pInput->dsum;
936,625✔
1299
  }
1300

1301
  pOutput->count += pInput->count;
946,735✔
1302
}
1303

1304
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
946,742✔
1305
  SInputColumnInfoData* pInput = &pCtx->input;
946,742✔
1306
  SColumnInfoData*      pCol = pInput->pData[0];
946,742✔
1307

1308
  if (IS_NULL_TYPE(pCol->info.type)) {
946,742!
1309
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1310
    return TSDB_CODE_SUCCESS;
×
1311
  }
1312

1313
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
946,742!
1314
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1315
  }
1316

1317
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
946,742✔
1318

1319
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
1,893,554✔
1320
    if (colDataIsNull_s(pCol, i)) continue;
1,893,624!
1321
    char*       data = colDataGetData(pCol, i);
946,812!
1322
    SStdRes*    pInputInfo = (SStdRes*)varDataVal(data);
946,812✔
1323
    stdTransferInfo(pInputInfo, pInfo);
946,812✔
1324
  }
1325

1326
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
946,742✔
1327
  return TSDB_CODE_SUCCESS;
946,742✔
1328
}
1329

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

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

1338
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1339

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

1343
  int32_t start = pInput->startRowIndex;
1344
  int32_t numOfRows = pInput->numOfRows;
1345

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

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

1397
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,840,250✔
1398
  SInputColumnInfoData* pInput = &pCtx->input;
4,840,250✔
1399
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,840,250✔
1400
  int32_t               type = pStddevRes->type;
4,840,250✔
1401
  double                avg;
1402

1403
  if (pStddevRes->count == 0) {
4,840,250✔
1404
    GET_RES_INFO(pCtx)->numOfRes = 0;
47,006✔
1405
    return functionFinalize(pCtx, pBlock);
47,006✔
1406
  }
1407

1408
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,793,244!
1409
    avg = pStddevRes->isum / ((double)pStddevRes->count);
220,687✔
1410
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
220,687✔
1411
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
4,572,557!
1412
    avg = pStddevRes->usum / ((double)pStddevRes->count);
10✔
1413
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
10✔
1414
  } else {
1415
    avg = pStddevRes->dsum / ((double)pStddevRes->count);
4,572,547✔
1416
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
4,572,547✔
1417
  }
1418

1419
  // check for overflow
1420
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
4,793,244!
1421
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1422
  }
1423

1424
  return functionFinalize(pCtx, pBlock);
4,793,244✔
1425
}
1426

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

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

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

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

1454
  return functionFinalize(pCtx, pBlock);
×
1455
}
1456

1457
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
946,714✔
1458
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
946,714✔
1459
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
946,714✔
1460
  int32_t              resultBytes = getStdInfoSize();
946,714✔
1461
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
946,714✔
1462

1463
  if (NULL == res) {
946,715!
1464
    return terrno;
×
1465
  }
1466
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
946,715✔
1467
  varDataSetLen(res, resultBytes);
946,715✔
1468

1469
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
946,715✔
1470
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
946,715✔
1471
  if (NULL == pCol) {
946,713!
1472
    taosMemoryFree(res);
×
1473
    return TSDB_CODE_OUT_OF_RANGE;
×
1474
  }
1475

1476
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
946,713✔
1477

1478
  taosMemoryFree(res);
946,714✔
1479
  return code;
946,715✔
1480
}
1481

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

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

1490
  stdTransferInfo(pSBuf, pDBuf);
3✔
1491

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

1497
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
43,455✔
1498
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
43,455✔
1499
  return true;
43,455✔
1500
}
1501

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

1510
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,366,913✔
1511

1512
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
5,366,913!
1513
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
5,366,913!
1514
  return TSDB_CODE_SUCCESS;
5,366,913✔
1515
}
1516

1517
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
6,272,659✔
1518
  int32_t numOfElem = 0;
6,272,659✔
1519

1520
  SInputColumnInfoData* pInput = &pCtx->input;
6,272,659✔
1521
  int32_t               type = pInput->pData[0]->info.type;
6,272,659✔
1522

1523
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,272,659✔
1524

1525
  SColumnInfoData* pCol = pInput->pData[0];
6,272,659✔
1526

1527
  double(*param)[3] = pInfo->matrix;
6,272,659✔
1528
  double x = pInfo->startVal;
6,272,659✔
1529

1530
  int32_t start = pInput->startRowIndex;
6,272,659✔
1531
  int32_t numOfRows = pInput->numOfRows;
6,272,659✔
1532

1533
  switch (type) {
6,272,659!
1534
    case TSDB_DATA_TYPE_TINYINT: {
7,585✔
1535
      int8_t* plist = (int8_t*)pCol->pData;
7,585✔
1536
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
238,890✔
1537
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
231,305✔
1538
          continue;
2,460✔
1539
        }
1540
        numOfElem++;
228,845✔
1541
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
228,845✔
1542
      }
1543
      break;
7,585✔
1544
    }
1545
    case TSDB_DATA_TYPE_SMALLINT: {
11,377✔
1546
      int16_t* plist = (int16_t*)pCol->pData;
11,377✔
1547
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
620,687✔
1548
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
609,310✔
1549
          continue;
139,460✔
1550
        }
1551

1552
        numOfElem++;
469,850✔
1553
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
469,850✔
1554
      }
1555
      break;
11,377✔
1556
    }
1557

1558
    case TSDB_DATA_TYPE_INT: {
1,828,866✔
1559
      int32_t* plist = (int32_t*)pCol->pData;
1,828,866✔
1560
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
5,464,310✔
1561
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
3,635,444✔
1562
          continue;
2,015✔
1563
        }
1564

1565
        numOfElem++;
3,633,429✔
1566
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
3,633,429✔
1567
      }
1568
      break;
1,828,866✔
1569
    }
1570

1571
    case TSDB_DATA_TYPE_BIGINT: {
10,006✔
1572
      int64_t* plist = (int64_t*)pCol->pData;
10,006✔
1573
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
805,237✔
1574
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
795,231✔
1575
          continue;
139,385✔
1576
        }
1577

1578
        numOfElem++;
655,846✔
1579
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
655,846✔
1580
      }
1581
      break;
10,006✔
1582
    }
1583

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

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

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

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

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

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

1634
    case TSDB_DATA_TYPE_FLOAT: {
16,490✔
1635
      float* plist = (float*)pCol->pData;
16,490✔
1636
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
952,737✔
1637
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
936,247✔
1638
          continue;
288,209✔
1639
        }
1640

1641
        numOfElem++;
648,038✔
1642
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
648,038✔
1643
      }
1644
      break;
16,490✔
1645
    }
1646

1647
    case TSDB_DATA_TYPE_DOUBLE: {
4,397,722✔
1648
      double* plist = (double*)pCol->pData;
4,397,722✔
1649
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
14,555,716✔
1650
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
10,157,994✔
1651
          continue;
4,060✔
1652
        }
1653

1654
        numOfElem++;
10,153,934✔
1655
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
10,153,934✔
1656
      }
1657
      break;
4,397,722✔
1658
    }
1659
    case TSDB_DATA_TYPE_NULL: {
×
1660
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1661
      numOfElem = 1;
×
1662
      break;
×
1663
    }
1664

1665
    default:
×
1666
      break;
×
1667
  }
1668

1669
  pInfo->startVal = x;
6,272,659✔
1670
  pInfo->num += numOfElem;
6,272,659✔
1671

1672
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,272,659✔
1673

1674
  return TSDB_CODE_SUCCESS;
6,272,659✔
1675
}
1676

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

1683
  if (NULL == pCol) {
5,364,317!
1684
    return TSDB_CODE_OUT_OF_RANGE;
×
1685
  }
1686
  int32_t currentRow = pBlock->info.rows;
5,364,317✔
1687

1688
  if (0 == pInfo->num) {
5,364,317✔
1689
    colDataSetNULL(pCol, currentRow);
21,691!
1690
    return TSDB_CODE_SUCCESS;
21,691✔
1691
  }
1692

1693
  double(*param)[3] = pInfo->matrix;
5,342,626✔
1694

1695
  param[1][1] = (double)pInfo->num;
5,342,626✔
1696
  param[1][0] = param[0][1];
5,342,626✔
1697

1698
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
5,342,626✔
1699
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
5,342,626✔
1700

1701
  if (0 == param00) {
5,342,626✔
1702
    colDataSetNULL(pCol, currentRow);
3,927,978!
1703
    return TSDB_CODE_SUCCESS;
3,927,978✔
1704
  }
1705

1706
  // param[0][1] = 0;
1707
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
1,414,648✔
1708
  // param[1][0] = 0;
1709
  param02 /= param00;
1,414,648✔
1710

1711
  param12 /= param[1][1];
1,414,648✔
1712

1713
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
1,414,648✔
1714
  char slopBuf[64] = {0};
1,414,648✔
1715
  char interceptBuf[64] = {0};
1,414,648✔
1716
  int  n = tsnprintf(slopBuf, 64, "%.6lf", param02);
1,414,648✔
1717
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,414,657✔
1718
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
72✔
1719
  }
1720
  n = tsnprintf(interceptBuf, 64, "%.6lf", param12);
1,414,657✔
1721
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,414,658✔
1722
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
92✔
1723
  }
1724
  size_t len =
1,414,658✔
1725
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
1,414,658✔
1726
  varDataSetLen(buf, len);
1,414,658✔
1727

1728
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,414,658✔
1729

1730
  return code;
1,414,658✔
1731
}
1732

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

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

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

1760
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,196✔
1761
  if (pResultInfo->initialized) {
5,196!
1762
    return TSDB_CODE_SUCCESS;
×
1763
  }
1764
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,196!
1765
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1766
  }
1767

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

1774
  return TSDB_CODE_SUCCESS;
5,196✔
1775
}
1776

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

1788
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
2,906,388✔
1789
  int32_t              code = TSDB_CODE_SUCCESS;
2,906,388✔
1790
  int32_t              numOfElems = 0;
2,906,388✔
1791
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,906,388✔
1792

1793
  SInputColumnInfoData* pInput = &pCtx->input;
2,906,388✔
1794
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,906,388✔
1795

1796
  SColumnInfoData* pCol = pInput->pData[0];
2,906,388✔
1797
  int32_t          type = pCol->info.type;
2,906,388✔
1798

1799
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,906,388✔
1800
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
2,906,388✔
1801
    pInfo->stage += 1;
5,196✔
1802

1803
    // all data are null, set it completed
1804
    if (pInfo->numOfElems == 0) {
5,196✔
1805
      pResInfo->complete = true;
1,804✔
1806
      return TSDB_CODE_SUCCESS;
1,804✔
1807
    } else {
1808
      code = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup, &pInfo->pMemBucket, pInfo->numOfElems);
3,392✔
1809
      if (TSDB_CODE_SUCCESS != code) {
3,392!
1810
        return code;
×
1811
      }
1812
    }
1813
  }
1814

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

1830
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
1,443,582✔
1831
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
14✔
1832
      }
1833

1834
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
1,443,582✔
1835
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
14✔
1836
      }
1837

1838
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
1,443,582✔
1839
    } else {
1840
      // check the valid data one by one
1841
      int32_t start = pInput->startRowIndex;
9,612✔
1842
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,524,430✔
1843
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
14,514,818✔
1844
          continue;
2,200✔
1845
        }
1846

1847
        char* data = colDataGetData(pCol, i);
14,512,618!
1848

1849
        double v = 0;
14,512,618✔
1850
        GET_TYPED_DATA(v, double, type, data);
14,512,618!
1851
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
14,512,618✔
1852
          SET_DOUBLE_VAL(&pInfo->minval, v);
3,632✔
1853
        }
1854

1855
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
14,512,618✔
1856
          SET_DOUBLE_VAL(&pInfo->maxval, v);
410,670✔
1857
        }
1858

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

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

1879
    SET_VAL(pResInfo, numOfElems, 1);
1,451,390!
1880
  }
1881

1882
  pCtx->needCleanup = true;
2,904,584✔
1883
  return TSDB_CODE_SUCCESS;
2,904,584✔
1884
}
1885

1886
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,196✔
1887
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,196✔
1888
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
5,196✔
1889

1890
  int32_t code = 0;
5,196✔
1891
  double  v = 0;
5,196✔
1892

1893
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
5,196✔
1894
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
5,196!
1895
    if (pCtx->numOfParams > 2) {
3,392✔
1896
      char   buf[3200] = {0};
34✔
1897
      // max length of double num is 317, e.g. use %.6lf to print -1.0e+308, consider the comma and bracket, 3200 is 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;
3,358✔
1935

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

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

1943
      tMemBucketDestroy(pMemBucket);
3,358✔
1944
      return functionFinalize(pCtx, pBlock);
3,358✔
1945
    }
1946
  } else {
1947
    return functionFinalize(pCtx, pBlock);
1,804✔
1948
  }
1949

1950
_fin_error:
×
1951

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

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

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

1971
static int8_t getApercentileAlgo(char* algoStr) {
25,804✔
1972
  int8_t algoType;
1973
  if (strcasecmp(algoStr, "default") == 0) {
25,804✔
1974
    algoType = APERCT_ALGO_DEFAULT;
11,451✔
1975
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
14,353✔
1976
    algoType = APERCT_ALGO_TDIGEST;
14,352✔
1977
  } else {
1978
    algoType = APERCT_ALGO_UNKNOWN;
1✔
1979
  }
1980

1981
  return algoType;
25,804✔
1982
}
1983

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

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

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

2001
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
2,379,272✔
2002

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

2007
  if (pCtx->numOfParams == 2) {
2,379,272✔
2008
    pInfo->algo = APERCT_ALGO_DEFAULT;
2,353,461✔
2009
  } else if (pCtx->numOfParams == 3) {
25,811✔
2010
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
25,804✔
2011
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
25,798!
2012
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2013
    }
2014
  }
2015

2016
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
2,379,266✔
2017
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
2,379,266✔
2018
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
14,349✔
2019
  } else {
2020
    buildHistogramInfo(pInfo);
2,364,917✔
2021
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
2,364,908✔
2022
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
2,364,856✔
2023
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2024
  }
2025

2026
  return TSDB_CODE_SUCCESS;
2,379,211✔
2027
}
2028

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

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

2037
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,378,765✔
2038

2039
  int32_t start = pInput->startRowIndex;
2,378,765✔
2040
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
2,378,765✔
2041
    buildTDigestInfo(pInfo);
17,996✔
2042
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
17,994✔
2043
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,212,507✔
2044
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,194,518✔
2045
        continue;
278,575✔
2046
      }
2047
      numOfElems += 1;
915,943✔
2048
      char* data = colDataGetData(pCol, i);
915,943!
2049

2050
      double  v = 0;  // value
915,943✔
2051
      int64_t w = 1;  // weigth
915,943✔
2052
      GET_TYPED_DATA(v, double, type, data);
915,943✔
2053
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
915,943✔
2054
      if (code != TSDB_CODE_SUCCESS) {
915,937!
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);
2,360,769✔
2062
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
2,360,764✔
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) {
9,836,275✔
2066
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
7,474,941✔
2067
        continue;
808,269✔
2068
      }
2069
      numOfElems += 1;
6,666,672✔
2070
      char* data = colDataGetData(pCol, i);
6,666,672!
2071

2072
      double v = 0;
6,666,672✔
2073
      GET_TYPED_DATA(v, double, type, data);
6,666,672!
2074
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
6,666,672✔
2075
      if (code != TSDB_CODE_SUCCESS) {
6,667,238!
2076
        return code;
×
2077
      }
2078
    }
2079

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

2085
  SET_VAL(pResInfo, numOfElems, 1);
2,378,780✔
2086
  return TSDB_CODE_SUCCESS;
2,378,780✔
2087
}
2088

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

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

2100
    if (hasRes) {
962✔
2101
      *hasRes = true;
960✔
2102
    }
2103

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

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

2123
    if (hasRes) {
69,909✔
2124
      *hasRes = true;
69,907✔
2125
    }
2126

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

2130
    if (pHisto->numOfElems <= 0) {
69,909✔
2131
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
38,126✔
2132
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
38,126✔
2133

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

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

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

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

2161
  SInputColumnInfoData* pInput = &pCtx->input;
39,785✔
2162

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

2168
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
39,785✔
2169

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

2172
  bool hasRes = false;
39,785✔
2173
  int32_t start = pInput->startRowIndex;
39,785✔
2174
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
110,838✔
2175
    char* data = colDataGetData(pCol, i);
71,053!
2176

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

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

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

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

2198
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
2,283,692✔
2199
    buildTDigestInfo(pInfo);
13,386✔
2200
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
13,384✔
2201
    if (pInfo->pTDigest->size > 0) {
13,384!
2202
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
13,384✔
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);
2,270,306✔
2209
    if (pInfo->pHisto->numOfElems > 0) {
2,270,307✔
2210
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
2,227,354✔
2211
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2212

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

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

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

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

2244
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
70,651✔
2245
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
961✔
2246
    varDataSetLen(res, resultBytes);
961✔
2247
  } else {
2248
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
69,690✔
2249
    varDataSetLen(res, resultBytes);
69,690✔
2250
  }
2251

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

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

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

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

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

2315
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
12,982✔
2316
  if (pResult->hasResult) {
12,982✔
2317
    if (pResult->pkBytes > 0) {
12,933✔
2318
      pResult->pkData = pResult->buf + pResult->bytes;
1,775✔
2319
    } else {
2320
      pResult->pkData = NULL;
11,158✔
2321
    }    
2322
    if (pResult->ts < pBlockInfo->window.skey) {
12,933✔
2323
      return FUNC_DATA_REQUIRED_NOT_LOAD;
9,149✔
2324
    } else if (pResult->ts == pBlockInfo->window.skey) {
3,784✔
2325
      if (NULL == pResult->pkData) {
1,818✔
2326
        return FUNC_DATA_REQUIRED_NOT_LOAD;
186✔
2327
      }
2328
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
1,632✔
2329
        return FUNC_DATA_REQUIRED_NOT_LOAD;
264✔
2330
      }
2331
    }
2332
    return FUNC_DATA_REQUIRED_DATA_LOAD;
3,335✔
2333
  } else {
2334
    return FUNC_DATA_REQUIRED_DATA_LOAD;
49✔
2335
  }
2336
}
2337

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

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

2346
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
16,144✔
2347
  if (pResult->hasResult) {
16,144✔
2348
    if (pResult->pkBytes > 0) {
16,076✔
2349
      pResult->pkData = pResult->buf + pResult->bytes;
5,150✔
2350
    } else {
2351
      pResult->pkData = NULL;
10,926✔
2352
    }
2353
    if (pResult->ts > pBlockInfo->window.ekey) {
16,076✔
2354
      return FUNC_DATA_REQUIRED_NOT_LOAD;
10,525✔
2355
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
5,551✔
2356
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
2,896✔
2357
        return FUNC_DATA_REQUIRED_NOT_LOAD;
956✔
2358
      }
2359
    }
2360
    return FUNC_DATA_REQUIRED_DATA_LOAD;
4,598✔
2361
  } else {
2362
    return FUNC_DATA_REQUIRED_DATA_LOAD;
68✔
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; }
86,274,411✔
2368

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

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

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

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

2394
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
437,517,129!
2395
}
2396

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

2405
  SFirstLastRes *       pRes = GET_ROWCELL_INTERBUF(pResInfo);
11,983,233✔
2406
  SInputColumnInfoData* pInput = &pCtx->input;
11,983,233✔
2407

2408
  pRes->nullTupleSaved = false;
11,983,233✔
2409
  pRes->nullTuplePos.pageId = -1;
11,983,233✔
2410
  return TSDB_CODE_SUCCESS;
11,983,233✔
2411
}
2412

2413
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
286,378,526✔
2414
  if (pCtx->subsidiaries.rowLen == 0) {
286,378,526✔
2415
    int32_t rowLen = 0;
699,273✔
2416
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,408,486✔
2417
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
709,213✔
2418
      rowLen += pc->pExpr->base.resSchema.bytes;
709,213✔
2419
    }
2420

2421
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
699,273✔
2422
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
699,273✔
2423
    if (NULL == pCtx->subsidiaries.buf) {
699,273!
2424
      return terrno;
×
2425
    }
2426
  }
2427
  return TSDB_CODE_SUCCESS;
286,381,302✔
2428
}
2429

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

2434
  if (pCtx->subsidiaries.num <= 0) {
252,754,676✔
2435
    return TSDB_CODE_SUCCESS;
122,665,901✔
2436
  }
2437

2438
  if (!pInfo->hasResult) {
130,088,775✔
2439
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
106,899,495✔
2440
  } else {
2441
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
23,189,280✔
2442
  }
2443

2444
  return code;
129,771,029✔
2445
}
2446

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

2451
  if (IS_VAR_DATA_TYPE(type)) {
103,865,019!
2452
    pInfo->bytes = varDataTLen(pData);
11,481,989✔
2453
  }
2454

2455
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
103,865,019✔
2456
  if (pkData != NULL) {
103,865,019✔
2457
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
1,404,626!
2458
      pInfo->pkBytes = varDataTLen(pkData);
457,508✔
2459
    }
2460
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
1,404,626✔
2461
    pInfo->pkData = pInfo->buf + pInfo->bytes;
1,404,626✔
2462
  }
2463

2464
  pInfo->ts = currentTs;
103,865,019✔
2465
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
103,865,019✔
2466
  if (code != TSDB_CODE_SUCCESS) {
103,861,826!
2467
    return code;
×
2468
  }
2469

2470
  pInfo->hasResult = true;
103,861,826✔
2471
  return TSDB_CODE_SUCCESS;
103,861,826✔
2472
}
2473

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

2479
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
55,674,810✔
2480
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
55,674,810✔
2481

2482
  SInputColumnInfoData* pInput = &pCtx->input;
55,674,810✔
2483
  SColumnInfoData*      pInputCol = pInput->pData[0];
55,674,810✔
2484

2485
  pInfo->bytes = pInputCol->info.bytes;
55,674,810✔
2486

2487
  if (IS_NULL_TYPE(pInputCol->info.type)) {
55,674,810✔
2488
    return TSDB_CODE_SUCCESS;
4,855✔
2489
  }
2490

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

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

2512
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
55,663,697!
2513

2514
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
55,663,697!
2515
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
55,663,697!
2516

2517
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
55,663,697✔
2518

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

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

2535
      numOfElems++;
2536

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

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

2558
      numOfElems++;
2559

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

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

2572
  int from = -1;
55,663,697✔
2573
  int32_t i = -1;
55,663,697✔
2574
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
170,803,779✔
2575
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
155,752,192!
2576
      continue;
76,651✔
2577
    }
2578

2579
    numOfElems++;
115,041,840✔
2580
    char* data = colDataGetData(pInputCol, i);
115,041,840!
2581
    char* pkData = NULL;
115,041,840✔
2582
    if (pCtx->hasPrimaryKey) {
115,041,840✔
2583
      pkData = colDataGetData(pkCol, i);
1,400,640!
2584
    }
2585
    TSKEY cts = pts[i];
115,041,840✔
2586
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts || 
115,041,840✔
2587
         (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
66,536,620!
2588
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
48,505,220✔
2589
      if (code != TSDB_CODE_SUCCESS) {
48,526,811!
2590
        return code;
×
2591
      }
2592
      pResInfo->numOfRes = 1;
48,526,811✔
2593
    }
2594
  }
2595
#endif
2596

2597
  if (numOfElems == 0) {
55,233,895✔
2598
    // save selectivity value for column consisted of all null values
2599
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
25,067✔
2600
    if (code != TSDB_CODE_SUCCESS) {
25,066!
2601
      return code;
×
2602
    }
2603
    pInfo->nullTupleSaved = true;
25,066✔
2604
  }
2605
  SET_VAL(pResInfo, numOfElems, 1);
55,233,894✔
2606
  return TSDB_CODE_SUCCESS;
55,233,894✔
2607
}
2608

2609
int32_t lastFunction(SqlFunctionCtx* pCtx) {
50,768,779✔
2610
  int32_t numOfElems = 0;
50,768,779✔
2611

2612
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
50,768,779✔
2613
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
50,768,779✔
2614

2615
  SInputColumnInfoData* pInput = &pCtx->input;
50,768,779✔
2616
  SColumnInfoData*      pInputCol = pInput->pData[0];
50,768,779✔
2617

2618
  int32_t type = pInputCol->info.type;
50,768,779✔
2619
  int32_t bytes = pInputCol->info.bytes;
50,768,779✔
2620
  pInfo->bytes = bytes;
50,768,779✔
2621

2622
  if (IS_NULL_TYPE(type)) {
50,768,779✔
2623
    return TSDB_CODE_SUCCESS;
4,852✔
2624
  }
2625

2626
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
50,763,927✔
2627
  pInfo->pkType = -1;
50,763,927✔
2628
  __compar_fn_t  pkCompareFn = NULL;
50,763,927✔
2629
  if (pCtx->hasPrimaryKey) {
50,763,927✔
2630
    pInfo->pkType = pkCol->info.type;
312,765✔
2631
    pInfo->pkBytes = pkCol->info.bytes;
312,765✔
2632
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
312,765✔
2633
  }
2634

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

2647
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
50,854,157!
2648

2649
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
50,854,157!
2650
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
50,854,157!
2651

2652
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
50,854,157✔
2653

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

2662
      numOfElems++;
2663

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

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

2678
      numOfElems++;
2679

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

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

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

2706
// todo refactor
2707
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
79,246,211✔
2708
    numOfElems = 1;
28,482,195✔
2709

2710
    int32_t round = pInput->numOfRows >> 2;
28,482,195✔
2711
    int32_t reminder = pInput->numOfRows & 0x03;
28,482,195✔
2712

2713
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
43,298,643✔
2714
      int64_t cts = pts[i];
14,816,530✔
2715
      int32_t chosen = i;
14,816,530✔
2716

2717
      if (cts < pts[i + 1]) {
14,816,530✔
2718
        cts = pts[i + 1];
4,383,297✔
2719
        chosen = i + 1;
4,383,297✔
2720
      }
2721

2722
      if (cts < pts[i + 2]) {
14,816,530✔
2723
        cts = pts[i + 2];
4,383,738✔
2724
        chosen = i + 2;
4,383,738✔
2725
      }
2726

2727
      if (cts < pts[i + 3]) {
14,816,530✔
2728
        cts = pts[i + 3];
4,384,041✔
2729
        chosen = i + 3;
4,384,041✔
2730
      }
2731

2732
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
14,816,530✔
2733
        char*   data = colDataGetData(pInputCol, chosen);
3,882,342!
2734
        int32_t code = doSaveCurrentVal(pCtx, i, cts, NULL, type, data);
3,882,342✔
2735
        if (code != TSDB_CODE_SUCCESS) {
3,882,260!
2736
          return code;
×
2737
        }
2738
        pResInfo->numOfRes = 1;
3,882,260✔
2739
      }
2740
    }
2741

2742
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
64,884,227✔
2743
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
36,492,173✔
2744
        char*   data = colDataGetData(pInputCol, i);
20,342,606!
2745
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
20,342,606✔
2746
        if (code != TSDB_CODE_SUCCESS) {
20,252,547!
2747
          return code;
×
2748
        }
2749
        pResInfo->numOfRes = 1;
20,252,547✔
2750
      }
2751
    }
2752
  } else {
2753
    int from = -1;
22,371,962✔
2754
    int32_t i = -1;
22,371,962✔
2755
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
245,015,831✔
2756
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
445,321,106✔
2757
        continue;
9,366,346✔
2758
      }
2759

2760
      numOfElems++;
213,294,207✔
2761
      char* pkData = NULL;
213,294,207✔
2762
      if (pCtx->hasPrimaryKey) {
213,294,207✔
2763
        pkData = colDataGetData(pkCol, i);
101,448,753!
2764
      }
2765
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
213,294,207✔
2766
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
182,321,550!
2767
        char*   data = colDataGetData(pInputCol, i);
31,138,391!
2768
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
31,138,391✔
2769
        if (code != TSDB_CODE_SUCCESS) {
31,121,707!
2770
          return code;
×
2771
        }
2772
        pResInfo->numOfRes = 1;
31,121,707✔
2773
      }
2774
    }
2775
  }
2776
#endif
2777

2778
#endif
2779

2780
  // save selectivity value for column consisted of all null values
2781
  if (numOfElems == 0) {
50,858,372✔
2782
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
4,098,320✔
2783
    if (code != TSDB_CODE_SUCCESS) {
4,089,382!
2784
      return code;
×
2785
    }
2786
    pInfo->nullTupleSaved = true;
4,089,382✔
2787
  }
2788

2789
  return TSDB_CODE_SUCCESS;
50,849,434✔
2790
}
2791

2792
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
80,927,953✔
2793
  if (!pInput->hasResult) {
80,927,953✔
2794
    return false;
2✔
2795
  }
2796
  __compar_fn_t pkCompareFn = NULL;
80,927,951✔
2797
  if (pInput->pkData) {
80,927,951✔
2798
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
44,171✔
2799
  }
2800
  if (pOutput->hasResult) {
80,935,186✔
2801
    if (isFirst) {
31,889,143✔
2802
      if (pInput->ts > pOutput->ts ||
8,595,519✔
2803
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,594,728✔
2804
        return false;
1,128✔
2805
      }
2806
    } else {
2807
      if (pInput->ts < pOutput->ts ||
23,293,624✔
2808
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
13,673,082✔
2809
        return false;
9,624,626✔
2810
      }
2811
    }
2812
  }
2813

2814
  pOutput->isNull = pInput->isNull;
71,309,432✔
2815
  pOutput->ts = pInput->ts;
71,309,432✔
2816
  pOutput->bytes = pInput->bytes;
71,309,432✔
2817
  pOutput->pkType = pInput->pkType;
71,309,432✔
2818

2819
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
71,309,432✔
2820
  if (pInput->pkData) {
71,309,432✔
2821
    pOutput->pkBytes = pInput->pkBytes;
40,974✔
2822
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
40,974✔
2823
    pOutput->pkData = pOutput->buf + pOutput->bytes;
40,974✔
2824
  }
2825
  return true;
71,309,432✔
2826
}
2827

2828
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
80,927,819✔
2829
                                     int32_t rowIndex) {
2830
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
80,927,819✔
2831
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
71,309,225✔
2832
    if (TSDB_CODE_SUCCESS != code) {
71,301,853!
2833
      return code;
×
2834
    }
2835
    pOutput->hasResult = true;
71,301,853✔
2836
  }
2837
  return TSDB_CODE_SUCCESS;
80,920,608✔
2838
}
2839

2840
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
49,089,419✔
2841
  SInputColumnInfoData* pInput = &pCtx->input;
49,089,419✔
2842
  SColumnInfoData*      pCol = pInput->pData[0];
49,089,419✔
2843

2844
  if (IS_NULL_TYPE(pCol->info.type)) {
49,089,419!
2845
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
2846
    return TSDB_CODE_SUCCESS;
×
2847
  }
2848

2849
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
49,089,419!
2850
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2851
  }
2852

2853
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
49,089,419✔
2854

2855
  int32_t start = pInput->startRowIndex;
49,089,419✔
2856
  int32_t numOfElems = 0;
49,089,419✔
2857

2858
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
132,294,669✔
2859
    if (colDataIsNull_s(pCol, i)) {
166,444,066✔
2860
      continue;
2,285,521✔
2861
    }
2862
    char*          data = colDataGetData(pCol, i);
80,936,512!
2863
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
80,936,512✔
2864
    if (pCtx->hasPrimaryKey) {
80,936,512✔
2865
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
44,172✔
2866
    } else {
2867
      pInputInfo->pkData = NULL;
80,892,340✔
2868
    }
2869

2870
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
80,936,512✔
2871
    if (code != TSDB_CODE_SUCCESS) {
80,919,729!
2872
      return code;
×
2873
    }
2874
    if (!numOfElems) {
80,919,729✔
2875
      numOfElems = pInputInfo->hasResult ? 1 : 0;
49,081,839✔
2876
    }
2877
  }
2878

2879
  if (numOfElems == 0) {
49,072,636✔
2880
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
8,189✔
2881
    if (code != TSDB_CODE_SUCCESS) {
8,189!
2882
      return code;
×
2883
    }
2884
    pInfo->nullTupleSaved = true;
8,189✔
2885
  }
2886

2887
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
49,072,636✔
2888
  return TSDB_CODE_SUCCESS;
49,072,636✔
2889
}
2890

2891
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
13,795,662✔
2892

2893
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
35,301,039✔
2894

2895
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
107,298,409✔
2896
  int32_t          code = TSDB_CODE_SUCCESS;
107,298,409✔
2897
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
107,298,409✔
2898
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
107,298,409✔
2899
  if (NULL == pCol) {
107,212,236!
2900
    return TSDB_CODE_OUT_OF_RANGE;
×
2901
  }
2902

2903
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
107,212,236✔
2904
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
107,212,236✔
2905

2906
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
107,212,236✔
2907

2908
  if (pResInfo->isNullRes) {
107,212,236✔
2909
    colDataSetNULL(pCol, pBlock->info.rows);
42,416✔
2910
    return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
42,416✔
2911
  }
2912
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
107,169,820!
2913
  if (TSDB_CODE_SUCCESS != code) {
107,032,295!
2914
    return code;
×
2915
  }
2916

2917
  // handle selectivity
2918
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
107,032,295✔
2919

2920
  return code;
107,013,382✔
2921
}
2922

2923
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
84,275,319✔
2924
  int32_t code = TSDB_CODE_SUCCESS;
84,275,319✔
2925

2926
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
84,275,319✔
2927
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
84,275,319✔
2928

2929
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
84,275,319✔
2930

2931
  // todo check for failure
2932
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
84,157,459✔
2933
  if (NULL == res) {
85,319,202!
2934
    return terrno;
×
2935
  }
2936
  (void)memcpy(varDataVal(res), pRes, resultBytes);
85,319,202✔
2937

2938
  varDataSetLen(res, resultBytes);
85,319,202✔
2939

2940
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
85,319,202✔
2941
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
85,319,202✔
2942
  if (NULL == pCol) {
84,689,154✔
2943
    taosMemoryFree(res);
15,336✔
2944
    return TSDB_CODE_OUT_OF_RANGE;
×
2945
  }
2946

2947
  if (pEntryInfo->numOfRes == 0) {
84,673,818✔
2948
    colDataSetNULL(pCol, pBlock->info.rows);
2,375,086!
2949
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
2,375,086✔
2950
  } else {
2951
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
82,298,732✔
2952
    if (TSDB_CODE_SUCCESS != code) {
81,426,366!
2953
      taosMemoryFree(res);
×
2954
      return code;
×
2955
    }
2956
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
81,426,366✔
2957
  }
2958
  taosMemoryFree(res);
83,711,098✔
2959
  return code;
85,279,434✔
2960
}
2961

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

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

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

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

2981

2982
  if (colDataIsNull_s(pInputCol, rowIndex)) {
147,236,274✔
2983
    pInfo->isNull = true;
3,551✔
2984
  } else {
2985
    pInfo->isNull = false;
73,614,586✔
2986

2987
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
73,614,586!
2988
      pInfo->bytes = varDataTLen(pData);
10,235,053✔
2989
    }
2990

2991
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
73,614,586✔
2992
  }
2993

2994
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
73,691,254✔
2995
    char* pkData = colDataGetData(pkCol, rowIndex);
73,111!
2996
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
73,111!
2997
      pInfo->pkBytes = varDataTLen(pkData);
24,046✔
2998
    }
2999
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
73,111✔
3000
    pInfo->pkData = pInfo->buf + pInfo->bytes;
73,111✔
3001
  }
3002
  pInfo->ts = cts;
73,618,137✔
3003
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
73,618,137✔
3004
  if (code != TSDB_CODE_SUCCESS) {
73,419,871!
3005
    return code;
×
3006
  }
3007

3008
  pInfo->hasResult = true;
73,419,871✔
3009

3010
  return TSDB_CODE_SUCCESS;
73,419,871✔
3011
}
3012

3013
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
74,598,966✔
3014
  int32_t numOfElems = 0;
74,598,966✔
3015

3016
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
74,598,966✔
3017
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
74,598,966✔
3018

3019
  SInputColumnInfoData* pInput = &pCtx->input;
74,598,966✔
3020
  SColumnInfoData*      pInputCol = pInput->pData[0];
74,598,966✔
3021

3022
  int32_t type = pInputCol->info.type;
74,598,966✔
3023
  int32_t bytes = pInputCol->info.bytes;
74,598,966✔
3024
  pInfo->bytes = bytes;
74,598,966✔
3025

3026
  if (IS_NULL_TYPE(type)) {
74,598,966✔
3027
    return TSDB_CODE_SUCCESS;
40✔
3028
  }
3029
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
74,598,926✔
3030
  pInfo->pkType = -1;
74,598,926✔
3031
  __compar_fn_t  pkCompareFn = NULL;
74,598,926✔
3032
  if (pCtx->hasPrimaryKey) {
74,598,926✔
3033
    pInfo->pkType = pkCol->info.type;
264,002✔
3034
    pInfo->pkBytes = pkCol->info.bytes;
264,002✔
3035
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
264,002✔
3036
  }
3037
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
74,688,726!
3038
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
74,688,726!
3039

3040
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
74,688,726!
3041
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
74,499,025!
3042
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
37,254,395✔
3043
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
37,254,395!
3044
      TSKEY cts = getRowPTs(pInput->pPTS, i);
37,254,395!
3045
      numOfElems++;
37,254,395✔
3046

3047
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
37,254,395✔
3048
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
36,340,783✔
3049
        if (code != TSDB_CODE_SUCCESS) return code;
36,332,733!
3050
      }
3051

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

3063
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
37,314,368!
3064
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
37,201,587✔
3065
        if (code != TSDB_CODE_SUCCESS) return code;
37,024,392!
3066
      }
3067
      break;
37,137,173✔
3068
    }
3069
  } else {
3070
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
160,680✔
3071
    int from = -1;
160,680✔
3072
    int32_t i = -1;
160,680✔
3073
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
1,576,346✔
3074
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
1,415,398✔
3075
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
1,415,398!
3076
      TSKEY cts = pts[i];
1,415,398✔
3077

3078
      numOfElems++;
1,415,398✔
3079
      char* pkData = NULL;
1,415,398✔
3080
      if (pCtx->hasPrimaryKey) {
1,415,398✔
3081
        pkData = colDataGetData(pkCol, i);
1,400,941!
3082
      }
3083
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
1,415,398✔
3084
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
1,343,592✔
3085
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
71,812✔
3086
        if (code != TSDB_CODE_SUCCESS) {
72,088!
3087
          return code;
×
3088
        }
3089
        pResInfo->numOfRes = 1;
72,088✔
3090
      }
3091
    }
3092

3093
  }
3094

3095
  SET_VAL(pResInfo, numOfElems, 1);
74,605,743!
3096
  return TSDB_CODE_SUCCESS;
74,605,743✔
3097
}
3098

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

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

3124
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
811,156✔
3125
  switch (type) {
811,156!
3126
    case TSDB_DATA_TYPE_BOOL:
38✔
3127
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
38✔
3128
      break;
38✔
3129
    case TSDB_DATA_TYPE_UTINYINT:
605,477✔
3130
    case TSDB_DATA_TYPE_TINYINT:
3131
      pDiffInfo->prev.i64 = *(int8_t*)pv;
605,477✔
3132
      break;
605,477✔
3133
    case TSDB_DATA_TYPE_UINT:
53,660✔
3134
    case TSDB_DATA_TYPE_INT:
3135
      pDiffInfo->prev.i64 = *(int32_t*)pv;
53,660✔
3136
      break;
53,660✔
3137
    case TSDB_DATA_TYPE_USMALLINT:
79,834✔
3138
    case TSDB_DATA_TYPE_SMALLINT:
3139
      pDiffInfo->prev.i64 = *(int16_t*)pv;
79,834✔
3140
      break;
79,834✔
3141
    case TSDB_DATA_TYPE_TIMESTAMP:
648✔
3142
    case TSDB_DATA_TYPE_UBIGINT:
3143
    case TSDB_DATA_TYPE_BIGINT:
3144
      pDiffInfo->prev.i64 = *(int64_t*)pv;
648✔
3145
      break;
648✔
3146
    case TSDB_DATA_TYPE_FLOAT:
223✔
3147
      pDiffInfo->prev.d64 = *(float*)pv;
223✔
3148
      break;
223✔
3149
    case TSDB_DATA_TYPE_DOUBLE:
71,276✔
3150
      pDiffInfo->prev.d64 = *(double*)pv;
71,276✔
3151
      break;
71,276✔
3152
    default:
×
3153
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3154
  }
3155
  pDiffInfo->prevTs = ts;
811,156✔
3156
  pDiffInfo->hasPrev = true;
811,156✔
3157
  return TSDB_CODE_SUCCESS;
811,156✔
3158
}
3159

3160
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
2,640,716✔
3161
  switch (type) {
2,640,716!
3162
    case TSDB_DATA_TYPE_UINT: {
×
3163
      int64_t v = *(uint32_t*)pv;
×
3164
      return v < pDiffInfo->prev.i64;
×
3165
    }
3166
    case TSDB_DATA_TYPE_INT: {
4,788✔
3167
      int64_t v = *(int32_t*)pv;
4,788✔
3168
      return v < pDiffInfo->prev.i64;
4,788✔
3169
    }
3170
    case TSDB_DATA_TYPE_BOOL: {
×
3171
      int64_t v = *(bool*)pv;
×
3172
      return v < pDiffInfo->prev.i64;
×
3173
    }
3174
    case TSDB_DATA_TYPE_UTINYINT: {
×
3175
      int64_t v = *(uint8_t*)pv;
×
3176
      return v < pDiffInfo->prev.i64;
×
3177
    }
3178
    case TSDB_DATA_TYPE_TINYINT: {
2,062,212✔
3179
      int64_t v = *(int8_t*)pv;
2,062,212✔
3180
      return v < pDiffInfo->prev.i64;
2,062,212✔
3181
    }
3182
    case TSDB_DATA_TYPE_USMALLINT: {
×
3183
      int64_t v = *(uint16_t*)pv;
×
3184
      return v < pDiffInfo->prev.i64;
×
3185
    }
3186
    case TSDB_DATA_TYPE_SMALLINT: {
284,531✔
3187
      int64_t v = *(int16_t*)pv;
284,531✔
3188
      return v < pDiffInfo->prev.i64;
284,531✔
3189
    }
3190
    case TSDB_DATA_TYPE_UBIGINT:{
40✔
3191
      uint64_t v = *(uint64_t*)pv;
40✔
3192
      return v < (uint64_t)pDiffInfo->prev.i64;
40✔
3193
    }
3194
    case TSDB_DATA_TYPE_TIMESTAMP:
7,595✔
3195
    case TSDB_DATA_TYPE_BIGINT: {
3196
      int64_t v = *(int64_t*)pv;
7,595✔
3197
      return v < pDiffInfo->prev.i64;
7,595✔
3198
    }
3199
    case TSDB_DATA_TYPE_FLOAT: {
2,712✔
3200
      float v = *(float*)pv;
2,712✔
3201
      return v < pDiffInfo->prev.d64;
2,712✔
3202
    }
3203
    case TSDB_DATA_TYPE_DOUBLE: {
278,838✔
3204
      double v = *(double*)pv;
278,838✔
3205
      return v < pDiffInfo->prev.d64;
278,838✔
3206
    }
3207
    default:
×
3208
      return false;
×
3209
  }
3210

3211
  return false;
3212
}
3213

3214
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
1,637,626,991✔
3215
  bool isNegative = v < pDiffInfo->prev.i64;
1,637,626,991✔
3216
  if(type == TSDB_DATA_TYPE_UBIGINT){
1,637,626,991✔
3217
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
3,745✔
3218
  }
3219
  int64_t delta = v - pDiffInfo->prev.i64;
1,637,626,991✔
3220
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
1,637,626,991✔
3221
    colDataSetNull_f_s(pOutput, pos);
510,396✔
3222
    pOutput->hasNull = true;
510,396✔
3223
  } else {
3224
    colDataSetInt64(pOutput, pos, &delta);
1,637,116,595✔
3225
  }
3226
  pDiffInfo->prev.i64 = v;
1,637,626,991✔
3227
}
1,637,626,991✔
3228

3229
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
435,652✔
3230
  double delta = v - pDiffInfo->prev.d64;
435,652✔
3231
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
435,652✔
3232
    colDataSetNull_f_s(pOutput, pos);
69,982✔
3233
  } else {
3234
    colDataSetDouble(pOutput, pos, &delta);
365,670✔
3235
  }
3236
  pDiffInfo->prev.d64 = v;
435,652✔
3237
}
435,652✔
3238

3239
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
1,638,063,256✔
3240
                            int64_t ts) {
3241
  if (!pDiffInfo->hasPrev) {
1,638,063,256✔
3242
    colDataSetNull_f_s(pOutput, pos);
613✔
3243
    return doSetPrevVal(pDiffInfo, type, pv, ts);
613✔
3244
  }
3245
  pDiffInfo->prevTs = ts;
1,638,062,643✔
3246
  switch (type) {
1,638,062,643!
3247
    case TSDB_DATA_TYPE_UINT: {
3,675✔
3248
      int64_t v = *(uint32_t*)pv;
3,675✔
3249
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,675✔
3250
      break;
3,675✔
3251
    }
3252
    case TSDB_DATA_TYPE_INT: {
26,249,530✔
3253
      int64_t v = *(int32_t*)pv;
26,249,530✔
3254
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
26,249,530✔
3255
      break;
26,249,530✔
3256
    }
3257
    case TSDB_DATA_TYPE_BOOL: {
10,877✔
3258
      int64_t v = *(bool*)pv;
10,877✔
3259
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,877✔
3260
      break;
10,877✔
3261
    }
3262
    case TSDB_DATA_TYPE_UTINYINT: {
675✔
3263
      int64_t v = *(uint8_t*)pv;
675✔
3264
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3265
      break;
675✔
3266
    }
3267
    case TSDB_DATA_TYPE_TINYINT: {
2,061,217✔
3268
      int64_t v = *(int8_t*)pv;
2,061,217✔
3269
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,061,217✔
3270
      break;
2,061,217✔
3271
    }
3272
    case TSDB_DATA_TYPE_USMALLINT:{
675✔
3273
      int64_t v = *(uint16_t*)pv;
675✔
3274
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3275
      break;
675✔
3276
    }
3277
    case TSDB_DATA_TYPE_SMALLINT: {
380,255✔
3278
      int64_t v = *(int16_t*)pv;
380,255✔
3279
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
380,255✔
3280
      break;
380,255✔
3281
    }
3282
    case TSDB_DATA_TYPE_TIMESTAMP:
1,608,920,087✔
3283
    case TSDB_DATA_TYPE_UBIGINT:
3284
    case TSDB_DATA_TYPE_BIGINT: {
3285
      int64_t v = *(int64_t*)pv;
1,608,920,087✔
3286
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,608,920,087✔
3287
      break;
1,608,920,087✔
3288
    }
3289
    case TSDB_DATA_TYPE_FLOAT: {
41,935✔
3290
      double v = *(float*)pv;
41,935✔
3291
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
41,935✔
3292
      break;
41,935✔
3293
    }
3294
    case TSDB_DATA_TYPE_DOUBLE: {
393,717✔
3295
      double v = *(double*)pv;
393,717✔
3296
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
393,717✔
3297
      break;
393,717✔
3298
    }
3299
    default:
×
3300
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3301
  }
3302
  pDiffInfo->hasPrev = true;
1,638,062,643✔
3303
  return TSDB_CODE_SUCCESS;
1,638,062,643✔
3304
}
3305

3306
//TODO: the primary key compare can be skipped for ordered pk if knonwn before
3307
//TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3308
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex, int32_t* nextFrom) {
416,797,945✔
3309
  if (pInput->pPrimaryKey == NULL) {
416,797,945✔
3310
    if (from == -1) {
311,830,746✔
3311
      from = pInput->startRowIndex;
78,484,357✔
3312
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
233,346,389✔
3313
      return false;
78,220,888✔
3314
    }
3315
    *pRowIndex = from;
233,609,858✔
3316
    *nextFrom = from + 1;
233,609,858✔
3317
    return true;
233,609,858✔
3318
  } else {
3319
    if (from == -1) {
104,967,199✔
3320
      from = pInput->startRowIndex;
828,709✔
3321
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
104,138,490✔
3322
      return false;
828,988✔
3323
    }
3324
    TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
104,138,211✔
3325
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
104,138,211✔
3326
    int8_t pkType = pkCol->info.type;
104,138,211✔
3327
    int32_t order = (firstOccur) ? TSDB_ORDER_ASC: TSDB_ORDER_DESC;
104,138,211✔
3328
    __compar_fn_t compareFunc = getKeyComparFunc(pkType, order);
104,138,211✔
3329
    int32_t select = from;
104,238,388✔
3330
    char* val = colDataGetData(pkCol, select);
104,238,388!
3331
    while (from < pInput->numOfRows + pInput->startRowIndex - 1  &&  tsList[from + 1] == tsList[from]) {
110,585,869✔
3332
      char* val1 = colDataGetData(pkCol, from + 1);
6,348,901!
3333
      if (compareFunc(val1, val) < 0)  {
6,348,901✔
3334
        select = from + 1;
1,925,278✔
3335
        val = val1;
1,925,278✔
3336
      }
3337
      from = from + 1;
6,347,481✔
3338
    }
3339
    *pRowIndex = select;
104,236,968✔
3340
    *nextFrom = from + 1;
104,236,968✔
3341
    return true;
104,236,968✔
3342
  }
3343
}
3344

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

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

3354
  if (pRow->isDataNull || !pDiffInfo->hasPrev ) {
1,638,966,452✔
3355
    return true;
183,023✔
3356
  }  else if (ignoreNegative(pDiffInfo->ignoreOption)){
1,638,783,429✔
3357
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
2,640,716✔
3358
  }
3359
  return false;
1,636,142,713✔
3360
}
3361

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

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

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

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

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

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

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

3407
  char* pv = pRow->pData;
1,638,063,279✔
3408

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

3424
  return TSDB_CODE_SUCCESS;
1,638,063,256✔
3425
}
3426

3427
int32_t diffFunction(SqlFunctionCtx* pCtx) {
1,989,380✔
3428
  return TSDB_CODE_SUCCESS;
1,989,380✔
3429
}
3430

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

3439
  SArray*  pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
1,989,122✔
3440
  if (NULL == pRows) {
1,989,122!
3441
    return terrno;
×
3442
  }
3443

3444
  bool keepNull = false;
1,989,122✔
3445
  for (int i = 0; i < diffColNum; ++i) {
3,978,502✔
3446
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,989,380✔
3447
    if (NULL == pCtx) {
1,989,380!
3448
      code = terrno;
×
3449
      goto _exit;
×
3450
    }
3451
    funcInputUpdate(pCtx);
1,989,380✔
3452
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,989,380✔
3453
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,989,380✔
3454
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
1,989,380✔
3455
      keepNull = true;
1,967,216✔
3456
    }
3457
  }
3458

3459
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
1,989,122✔
3460
  SFuncInputRow* pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
1,989,122✔
3461
  if (NULL == pCtx0 || NULL == pRow0) {
1,989,122!
3462
    code = terrno;
×
3463
    goto _exit;
×
3464
  }
3465
  int32_t startOffset = pCtx0->offset;
1,989,122✔
3466
  bool    result = false;
1,989,122✔
3467
  while (1) {
1,638,948,939✔
3468
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
1,640,938,061✔
3469
    if (TSDB_CODE_SUCCESS != code) {
1,640,938,061!
3470
      goto _exit;
×
3471
    }
3472
    if (!result) {
1,640,938,061✔
3473
      break;
1,989,099✔
3474
    }
3475
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
1,638,948,962✔
3476
    for (int i = 1; i < diffColNum; ++i) {
1,638,966,452✔
3477
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
17,490✔
3478
      SFuncInputRow* pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
17,490✔
3479
      if (NULL == pCtx || NULL == pRow) {
17,490!
3480
        code = terrno;
×
3481
        goto _exit;
×
3482
      }
3483
      code = funcInputGetNextRow(pCtx, pRow, &result);
17,490✔
3484
      if (TSDB_CODE_SUCCESS != code) {
17,490!
3485
        goto _exit;
×
3486
      }
3487
      if (!result) {
17,490!
3488
        // rows are not equal
3489
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3490
        goto _exit;
×
3491
      }
3492
      if (!diffResultIsNull(pCtx, pRow)) {
17,490✔
3493
        hasNotNullValue = true;
16,754✔
3494
      }
3495
    }
3496
    int32_t pos = startOffset + numOfElems;
1,638,948,962✔
3497

3498
    bool newRow = false;
1,638,948,962✔
3499
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3500
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,638,966,452✔
3501
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
1,638,966,452✔
3502
      if (NULL == pCtx || NULL == pRow) {
1,638,966,452!
3503
        code = terrno;
×
3504
        goto _exit;
×
3505
      }
3506
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)){
1,638,966,452✔
3507
        code = setDoDiffResult(pCtx, pRow, pos);
1,638,153,986✔
3508
        if (code != TSDB_CODE_SUCCESS) {
1,638,153,986✔
3509
          goto _exit;
23✔
3510
        }
3511
        newRow = true;
1,638,153,963✔
3512
      } else {
3513
        code = trySetPreVal(pCtx, pRow);
812,466✔
3514
        if (code != TSDB_CODE_SUCCESS) {
812,466!
3515
          goto _exit;
×
3516
        } 
3517
      }
3518
    }
3519
    if (newRow) ++numOfElems;
1,638,948,939✔
3520
  }
3521

3522
  for (int i = 0; i < diffColNum; ++i) {
3,978,451✔
3523
    SqlFunctionCtx*      pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,989,352✔
3524
    if (NULL == pCtx) {
1,989,352!
3525
      code = terrno;
×
3526
      goto _exit;
×
3527
    }
3528
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,989,352✔
3529
    pResInfo->numOfRes = numOfElems;
1,989,352✔
3530
  }
3531

3532
_exit:
1,989,099✔
3533
  if (pRows) {
1,989,122!
3534
    taosArrayDestroy(pRows);
1,989,122✔
3535
    pRows = NULL;
1,989,122✔
3536
  }
3537
  return code;
1,989,122✔
3538
}
3539

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

3542
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
89,061✔
3543
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
89,061✔
3544
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
89,103✔
3545
  return true;
89,103✔
3546
}
3547

3548
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
44,589,241✔
3549
  if (pResInfo->initialized) {
44,589,241!
3550
    return TSDB_CODE_SUCCESS;
×
3551
  }
3552
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
44,589,241!
3553
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3554
  }
3555

3556
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
44,616,240✔
3557
  SInputColumnInfoData* pInput = &pCtx->input;
44,616,240✔
3558

3559
  pRes->maxSize = pCtx->param[1].param.i;
44,616,240✔
3560

3561
  pRes->nullTupleSaved = false;
44,616,240✔
3562
  pRes->nullTuplePos.pageId = -1;
44,616,240✔
3563
  return TSDB_CODE_SUCCESS;
44,616,240✔
3564
}
3565

3566
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
211,990,484✔
3567
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
211,990,484✔
3568
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
211,990,484✔
3569
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
211,990,484✔
3570

3571
  return pRes;
211,990,484✔
3572
}
3573

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

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

3579
int32_t topFunction(SqlFunctionCtx* pCtx) {
40,664,138✔
3580
  int32_t              numOfElems = 0;
40,664,138✔
3581
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
40,664,138✔
3582

3583
  SInputColumnInfoData* pInput = &pCtx->input;
40,664,138✔
3584
  SColumnInfoData*      pCol = pInput->pData[0];
40,664,138✔
3585

3586
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
40,664,138✔
3587
  pRes->type = pInput->pData[0]->info.type;
40,663,634✔
3588

3589
  int32_t start = pInput->startRowIndex;
40,663,634✔
3590
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
139,089,308✔
3591
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
98,400,927✔
3592
      continue;
25,844✔
3593
    }
3594

3595
    numOfElems++;
98,375,083✔
3596
    char*   data = colDataGetData(pCol, i);
98,375,083!
3597
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
98,375,083✔
3598
    if (code != TSDB_CODE_SUCCESS) {
98,399,830!
3599
      return code;
×
3600
    }
3601
  }
3602

3603
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
40,688,381✔
3604
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
2,770✔
3605
    if (code != TSDB_CODE_SUCCESS) {
2,770!
3606
      return code;
×
3607
    }
3608
    pRes->nullTupleSaved = true;
2,770✔
3609
  }
3610
  return TSDB_CODE_SUCCESS;
40,688,381✔
3611
}
3612

3613
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
5,131,385✔
3614
  int32_t              numOfElems = 0;
5,131,385✔
3615
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,131,385✔
3616

3617
  SInputColumnInfoData* pInput = &pCtx->input;
5,131,385✔
3618
  SColumnInfoData*      pCol = pInput->pData[0];
5,131,385✔
3619

3620
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
5,131,385✔
3621
  pRes->type = pInput->pData[0]->info.type;
5,131,396✔
3622

3623
  int32_t start = pInput->startRowIndex;
5,131,396✔
3624
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
28,675,661✔
3625
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
23,544,077✔
3626
      continue;
30,812✔
3627
    }
3628

3629
    numOfElems++;
23,513,265✔
3630
    char*   data = colDataGetData(pCol, i);
23,513,265!
3631
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
23,513,265✔
3632
    if (code != TSDB_CODE_SUCCESS) {
23,513,453!
3633
      return code;
×
3634
    }
3635
  }
3636

3637
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
5,131,584✔
3638
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
1,092✔
3639
    if (code != TSDB_CODE_SUCCESS) {
1,092!
3640
      return code;
×
3641
    }
3642
    pRes->nullTupleSaved = true;
1,092✔
3643
  }
3644

3645
  return TSDB_CODE_SUCCESS;
5,131,584✔
3646
}
3647

3648
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
583,474,834✔
3649
  uint16_t type = *(uint16_t*)param;
583,474,834✔
3650

3651
  STopBotResItem* val1 = (STopBotResItem*)p1;
583,474,834✔
3652
  STopBotResItem* val2 = (STopBotResItem*)p2;
583,474,834✔
3653

3654
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
583,474,834!
3655
    if (val1->v.i == val2->v.i) {
186,489,404✔
3656
      return 0;
284,828✔
3657
    }
3658

3659
    return (val1->v.i > val2->v.i) ? 1 : -1;
186,204,576✔
3660
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
396,985,430✔
3661
    if (val1->v.u == val2->v.u) {
820,384✔
3662
      return 0;
177,471✔
3663
    }
3664

3665
    return (val1->v.u > val2->v.u) ? 1 : -1;
642,913✔
3666
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
396,165,046✔
3667
    if (val1->v.f == val2->v.f) {
364,367,311✔
3668
      return 0;
63✔
3669
    }
3670

3671
    return (val1->v.f > val2->v.f) ? 1 : -1;
364,367,248✔
3672
  }
3673

3674
  if (val1->v.d == val2->v.d) {
31,797,735✔
3675
    return 0;
11✔
3676
  }
3677

3678
  return (val1->v.d > val2->v.d) ? 1 : -1;
31,797,724✔
3679
}
3680

3681
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
121,885,176✔
3682
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3683
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
121,885,176✔
3684
  int32_t     code = TSDB_CODE_SUCCESS;
121,868,242✔
3685

3686
  SVariant val = {0};
121,868,242✔
3687
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
121,868,242!
3688

3689
  STopBotResItem* pItems = pRes->pItems;
121,910,400✔
3690

3691
  // not full yet
3692
  if (pEntryInfo->numOfRes < pRes->maxSize) {
121,910,400✔
3693
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
81,950,149✔
3694
    pItem->v = val;
81,950,149✔
3695
    pItem->uid = uid;
81,950,149✔
3696

3697
    // save the data of this tuple
3698
    if (pCtx->subsidiaries.num > 0) {
81,950,149✔
3699
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
41,078,483✔
3700
      if (code != TSDB_CODE_SUCCESS) {
41,036,325!
3701
        return code;
×
3702
      }
3703
    }
3704
#ifdef BUF_PAGE_DEBUG
3705
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3706
           pItem->tuplePos.offset);
3707
#endif
3708
    // allocate the buffer and keep the data of this row into the new allocated buffer
3709
    pEntryInfo->numOfRes++;
81,907,991✔
3710
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
81,907,991✔
3711
                        topBotResComparFn, !isTopQuery);
81,907,991✔
3712
    if (code != TSDB_CODE_SUCCESS) {
81,983,908!
3713
      return code;
×
3714
    }
3715
  } else {  // replace the minimum value in the result
3716
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
39,960,251✔
3717
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
22,165,134!
3718
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
22,070,909✔
3719
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
17,146,053✔
3720
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
32,297,056!
3721
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
14,542,020!
3722
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
14,538,070✔
3723
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
13,861,842✔
3724
      // replace the old data and the coresponding tuple data
3725
      STopBotResItem* pItem = &pItems[0];
10,154,414✔
3726
      pItem->v = val;
10,154,414✔
3727
      pItem->uid = uid;
10,154,414✔
3728

3729
      // save the data of this tuple by over writing the old data
3730
      if (pCtx->subsidiaries.num > 0) {
10,154,414✔
3731
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
5,789,542✔
3732
        if (code != TSDB_CODE_SUCCESS) {
5,786,657!
3733
          return code;
×
3734
        }
3735
      }
3736
#ifdef BUF_PAGE_DEBUG
3737
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3738
#endif
3739
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
10,151,529✔
3740
                     topBotResComparFn, NULL, !isTopQuery);
10,151,529✔
3741
      if (code != TSDB_CODE_SUCCESS) {
10,116,729!
3742
        return code;
×
3743
      }
3744
    }
3745
  }
3746

3747
  return TSDB_CODE_SUCCESS;
121,906,474✔
3748
}
3749

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

3761
  int32_t offset = 0;
286,348,186✔
3762
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
572,182,359✔
3763
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
286,455,436✔
3764

3765
    // group_key function has its own process function
3766
    // do not process there
3767
    if (fmIsGroupKeyFunc(pc->functionId)) {
286,455,436✔
3768
      continue;
8,355,653✔
3769
    }
3770

3771
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
278,006,081✔
3772
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
278,006,081✔
3773

3774
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
278,006,081✔
3775
    if (NULL == pCol) {
277,478,520!
3776
      return TSDB_CODE_OUT_OF_RANGE;
×
3777
    }
3778
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
554,957,040✔
3779
      offset += pCol->info.bytes;
441✔
3780
      continue;
441✔
3781
    }
3782

3783
    char* p = colDataGetData(pCol, rowIndex);
277,478,079!
3784
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
277,478,079!
3785
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
40,011!
3786
    } else {
3787
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
277,438,068✔
3788
    }
3789

3790
    offset += pCol->info.bytes;
277,478,079✔
3791
  }
3792

3793
  *res = buf;
285,726,923✔
3794
  return TSDB_CODE_SUCCESS;
285,726,923✔
3795
}
3796

3797
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
357,916,958✔
3798
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3799
  STuplePos p = {0};
357,916,958✔
3800
  if (pHandle->pBuf != NULL) {
357,916,958✔
3801
    SFilePage* pPage = NULL;
357,801,184✔
3802

3803
    if (pHandle->currentPage == -1) {
357,801,184✔
3804
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
707,027✔
3805
      if (pPage == NULL) {
707,045✔
3806
        return terrno;
1✔
3807
      }
3808
      pPage->num = sizeof(SFilePage);
707,044✔
3809
    } else {
3810
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
357,094,157✔
3811
      if (pPage == NULL) {
357,224,353!
3812
        return terrno;
×
3813
      }
3814
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
357,224,353✔
3815
        // current page is all used, let's prepare a new buffer page
3816
        releaseBufPage(pHandle->pBuf, pPage);
1,529,420✔
3817
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
1,529,419✔
3818
        if (pPage == NULL) {
1,529,418!
3819
          return terrno;
×
3820
        }
3821
        pPage->num = sizeof(SFilePage);
1,529,418✔
3822
      }
3823
    }
3824

3825
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
357,868,446✔
3826
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
357,868,446✔
3827

3828
    pPage->num += length;
357,868,446✔
3829
    setBufPageDirty(pPage, true);
357,868,446✔
3830
    releaseBufPage(pHandle->pBuf, pPage);
357,702,743✔
3831
  } else { // other tuple save policy
3832
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
115,774!
3833
      p.streamTupleKey = *key;
140,355✔
3834
    }
3835
  }
3836

3837
  *pPos = p;
357,681,611✔
3838
  return TSDB_CODE_SUCCESS;
357,681,611✔
3839
}
3840

3841
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
244,787,162✔
3842
  int32_t code = prepareBuf(pCtx);
244,787,162✔
3843
  if (TSDB_CODE_SUCCESS != code) {
244,760,170!
3844
    return code;
×
3845
  }
3846

3847
  SWinKey key = {0};
244,760,170✔
3848
  if (pCtx->saveHandle.pBuf == NULL) {
244,760,170✔
3849
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
140,356✔
3850
    if (NULL == pColInfo) {
140,352!
3851
      return TSDB_CODE_OUT_OF_RANGE;
×
3852
    }
3853
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
140,352!
3854
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3855
    }
3856
    key.groupId = pSrcBlock->info.id.groupId;
140,352✔
3857
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
140,352!
3858
  }
3859

3860
  char* buf = NULL;
244,760,166✔
3861
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
244,760,166✔
3862
  if (TSDB_CODE_SUCCESS != code) {
244,471,644!
3863
    return code;
×
3864
  }
3865
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
244,471,644✔
3866
}
3867

3868
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos, SFunctionStateStore* pStore) {
41,637,078✔
3869
  if (pHandle->pBuf != NULL) {
41,637,078✔
3870
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
41,333,507✔
3871
    if (pPage == NULL) {
41,334,952!
3872
      return terrno;
×
3873
    }
3874
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
41,334,952✔
3875
    setBufPageDirty(pPage, true);
41,334,952✔
3876
    releaseBufPage(pHandle->pBuf, pPage);
41,332,477✔
3877
  } else {
3878
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
303,571✔
3879
    if (TSDB_CODE_SUCCESS != code) {
303,802!
3880
      return code;
×
3881
    }
3882
  }
3883

3884
  return TSDB_CODE_SUCCESS;
41,633,369✔
3885
}
3886

3887
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
41,641,895✔
3888
  int32_t code = prepareBuf(pCtx);
41,641,895✔
3889
  if (TSDB_CODE_SUCCESS != code) {
41,641,241!
3890
    return code;
×
3891
  }
3892

3893
  char* buf = NULL;
41,641,241✔
3894
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
41,641,241✔
3895
  if (TSDB_CODE_SUCCESS != code) {
41,636,890!
3896
    return code;
×
3897
  }
3898
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
41,636,890✔
3899
}
3900

3901
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore, char** value) {
167,034,866✔
3902
  if (pHandle->pBuf != NULL) {
167,034,866✔
3903
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
166,883,113✔
3904
    if (pPage == NULL) {
167,256,550!
3905
      *value = NULL;
×
3906
      return terrno;
×
3907
    }
3908
    *value = pPage->data + pPos->offset;
167,256,550✔
3909
    releaseBufPage(pHandle->pBuf, pPage);
167,256,550✔
3910
    return TSDB_CODE_SUCCESS;
167,097,583✔
3911
  } else {
3912
    *value = NULL;
151,753✔
3913
    int32_t vLen;
3914
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void **)(value), &vLen);
151,753✔
3915
    if (TSDB_CODE_SUCCESS != code) {
159,529!
3916
      return code;
×
3917
    }
3918
    return TSDB_CODE_SUCCESS;
159,529✔
3919
  }
3920
}
3921

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

3926
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
44,517,426✔
3927
  int32_t code = TSDB_CODE_SUCCESS;
44,517,426✔
3928

3929
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
44,517,426✔
3930
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
44,517,426✔
3931

3932
  int16_t type = pCtx->pExpr->base.resSchema.type;
44,514,031✔
3933
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
44,514,031✔
3934

3935
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
44,514,031✔
3936
  if (NULL == pCol) {
44,496,406!
3937
    return TSDB_CODE_OUT_OF_RANGE;
×
3938
  }
3939

3940
  // todo assign the tag value and the corresponding row data
3941
  int32_t currentRow = pBlock->info.rows;
44,496,406✔
3942
  if (pEntryInfo->numOfRes <= 0) {
44,496,406✔
3943
    colDataSetNULL(pCol, currentRow);
594!
3944
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
594✔
3945
    return code;
594✔
3946
  }
3947
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
125,998,117✔
3948
    STopBotResItem* pItem = &pRes->pItems[i];
81,528,633✔
3949
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
81,528,633✔
3950
    if (TSDB_CODE_SUCCESS != code) {
81,498,483!
3951
      return code;
×
3952
    }
3953
#ifdef BUF_PAGE_DEBUG
3954
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3955
           pItem->tuplePos.offset);
3956
#endif
3957
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
81,498,483✔
3958
    if (TSDB_CODE_SUCCESS != code) {
81,502,305!
3959
      return code;
×
3960
    }
3961
    currentRow += 1;
81,502,305✔
3962
  }
3963

3964
  return code;
44,469,484✔
3965
}
3966

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

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

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

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

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

4040
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
982,130✔
4041

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

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

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

4062
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
4,663,193✔
4063
  int32_t numOfElems = 0;
4,663,193✔
4064

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

4070
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,663,193✔
4071

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

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

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

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

4100
    int32_t start = pInput->startRowIndex;
4,663,193✔
4101
    // check the valid data one by one
4102
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
22,739,080✔
4103
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
18,075,887✔
4104
        continue;
1,566,775✔
4105
      }
4106

4107
      char* data = colDataGetData(pCol, i);
16,509,112!
4108

4109
      double v = 0;
16,509,112✔
4110
      GET_TYPED_DATA(v, double, type, data);
16,509,112!
4111
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
16,509,112✔
4112
        SET_DOUBLE_VAL(&pInfo->min, v);
4,609,964✔
4113
      }
4114

4115
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
16,509,112✔
4116
        SET_DOUBLE_VAL(&pInfo->max, v);
8,856,956✔
4117
      }
4118

4119
      numOfElems += 1;
16,509,112✔
4120
    }
4121
  }
4122

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

4130
  return TSDB_CODE_SUCCESS;
4,663,193✔
4131
}
4132

4133
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
980,742✔
4134
  pOutput->hasResult = pInput->hasResult;
980,742✔
4135
  if (pInput->max > pOutput->max) {
980,742✔
4136
    pOutput->max = pInput->max;
976,035✔
4137
  }
4138

4139
  if (pInput->min < pOutput->min) {
980,742✔
4140
    pOutput->min = pInput->min;
976,027✔
4141
  }
4142
}
980,742✔
4143

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

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

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

4157
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
976,780✔
4158

4159
  int32_t start = pInput->startRowIndex;
976,780✔
4160
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,957,753✔
4161
    if(colDataIsNull_s(pCol, i)) continue;
1,961,946!
4162
    char*        data = colDataGetData(pCol, i);
980,973!
4163
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
980,973✔
4164
    if (pInputInfo->hasResult) {
980,973✔
4165
      spreadTransferInfo(pInputInfo, pInfo);
980,741✔
4166
    }
4167
  }
4168

4169
  if (pInfo->hasResult) {
976,780✔
4170
    GET_RES_INFO(pCtx)->numOfRes = 1;
976,617✔
4171
  }
4172

4173
  return TSDB_CODE_SUCCESS;
976,780✔
4174
}
4175

4176
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,694,499✔
4177
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,694,499✔
4178
  if (pInfo->hasResult == true) {
3,694,499✔
4179
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
3,670,615✔
4180
  } else {
4181
    GET_RES_INFO(pCtx)->isNullRes = 1;
23,884✔
4182
  }
4183
  return functionFinalize(pCtx, pBlock);
3,694,499✔
4184
}
4185

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

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

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

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

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

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

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

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

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

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

4243
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
9,961,207✔
4244
  pInfo->result = 0;
9,961,207✔
4245
  pInfo->min = TSKEY_MAX;
9,961,207✔
4246
  pInfo->max = 0;
9,961,207✔
4247

4248
  if (pCtx->numOfParams > 1) {
9,961,207✔
4249
    pInfo->timeUnit = pCtx->param[1].param.i;
24,201✔
4250
  } else {
4251
    pInfo->timeUnit = 1;
9,937,006✔
4252
  }
4253

4254
  return TSDB_CODE_SUCCESS;
9,961,207✔
4255
}
4256

4257
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
9,979,965✔
4258
  int32_t numOfElems = 0;
9,979,965✔
4259

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

4264
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,979,965✔
4265

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

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

4300
    SColumnInfoData* pCol = pInput->pData[0];
9,978,273✔
4301

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

4311
      if (pCtx->end.key == INT64_MIN) {
778!
4312
        pInfo->min =
778✔
4313
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
778✔
4314
      } else {
4315
        pInfo->min = pCtx->end.key;
×
4316
      }
4317
    } else {
4318
      if (pCtx->start.key == INT64_MIN) {
9,977,495✔
4319
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
4,151,356✔
4320
      } else {
4321
        pInfo->min = pCtx->start.key;
5,826,139✔
4322
      }
4323

4324
      if (pCtx->end.key == INT64_MIN) {
9,977,495✔
4325
        pInfo->max =
3,834,609✔
4326
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
3,834,609✔
4327
      } else {
4328
        pInfo->max = pCtx->end.key + 1;
6,142,886✔
4329
      }
4330
    }
4331
  }
4332

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

4337
  return TSDB_CODE_SUCCESS;
9,979,965✔
4338
}
4339

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

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

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

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

4360
  int32_t start = pInput->startRowIndex;
×
4361

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

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

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

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

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

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

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

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

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

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

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

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

4431
static int8_t getHistogramBinType(char* binTypeStr) {
3,600,163✔
4432
  int8_t binType;
4433
  if (strcasecmp(binTypeStr, "user_input") == 0) {
3,600,163✔
4434
    binType = USER_INPUT_BIN;
3,532✔
4435
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
3,596,631✔
4436
    binType = LINEAR_BIN;
2,420✔
4437
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
3,594,211✔
4438
    binType = LOG_BIN;
3,594,210✔
4439
  } else {
4440
    binType = UNKNOWN_BIN;
1✔
4441
  }
4442

4443
  return binType;
3,600,163✔
4444
}
4445

4446
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
3,600,163✔
4447
  cJSON*  binDesc = cJSON_Parse(binDescStr);
3,600,163✔
4448
  int32_t numOfBins;
4449
  double* intervals;
4450
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
3,600,162✔
4451
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
3,596,628✔
4452
    int32_t startIndex;
4453
    if (numOfParams != 4) {
3,596,629!
4454
      cJSON_Delete(binDesc);
×
4455
      return TSDB_CODE_FAILED;
×
4456
    }
4457

4458
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
3,596,629✔
4459
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
3,596,629✔
4460
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
3,596,629✔
4461
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
3,596,629✔
4462
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
3,596,631✔
4463

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

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

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

4480
    int32_t counter = (int32_t)count->valueint;
3,596,630✔
4481
    if (infinity->valueint == false) {
3,596,630✔
4482
      startIndex = 0;
3,594,836✔
4483
      numOfBins = counter + 1;
3,594,836✔
4484
    } else {
4485
      startIndex = 1;
1,794✔
4486
      numOfBins = counter + 3;
1,794✔
4487
    }
4488

4489
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
3,596,630✔
4490
    if (NULL == intervals) {
3,596,630!
4491
      cJSON_Delete(binDesc);
×
4492
      qError("histogram function out of memory");
×
4493
      return terrno;
×
4494
    }
4495
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
3,596,630!
4496
      // linear bin process
4497
      if (width->valuedouble == 0) {
2,418!
4498
        taosMemoryFree(intervals);
×
4499
        cJSON_Delete(binDesc);
×
4500
        return TSDB_CODE_FAILED;
×
4501
      }
4502
      for (int i = 0; i < counter + 1; ++i) {
25,663✔
4503
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
23,245✔
4504
        if (isinf(intervals[startIndex])) {
23,245!
4505
          taosMemoryFree(intervals);
×
4506
          cJSON_Delete(binDesc);
×
4507
          return TSDB_CODE_FAILED;
×
4508
        }
4509
        startIndex++;
23,245✔
4510
      }
4511
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
3,594,209!
4512
      // log bin process
4513
      if (start->valuedouble == 0) {
3,594,208!
4514
        taosMemoryFree(intervals);
×
4515
        cJSON_Delete(binDesc);
×
4516
        return TSDB_CODE_FAILED;
×
4517
      }
4518
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
3,594,208!
UNCOV
4519
        taosMemoryFree(intervals);
×
4520
        cJSON_Delete(binDesc);
×
4521
        return TSDB_CODE_FAILED;
×
4522
      }
4523
      for (int i = 0; i < counter + 1; ++i) {
25,157,857✔
4524
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
21,563,646✔
4525
        if (isinf(intervals[startIndex])) {
21,563,646!
4526
          taosMemoryFree(intervals);
×
4527
          cJSON_Delete(binDesc);
×
4528
          return TSDB_CODE_FAILED;
×
4529
        }
4530
        startIndex++;
21,563,646✔
4531
      }
4532
    } else {
4533
      taosMemoryFree(intervals);
×
4534
      cJSON_Delete(binDesc);
×
4535
      return TSDB_CODE_FAILED;
×
4536
    }
4537

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

4588
  pInfo->numOfBins = numOfBins - 1;
3,600,159✔
4589
  pInfo->normalized = normalized;
3,600,159✔
4590
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
21,602,640✔
4591
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
18,002,481✔
4592
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
18,002,481✔
4593
    pInfo->bins[i].count = 0;
18,002,481✔
4594
  }
4595

4596
  taosMemoryFree(intervals);
3,600,159✔
4597
  cJSON_Delete(binDesc);
3,600,163✔
4598

4599
  return TSDB_CODE_SUCCESS;
3,600,163✔
4600
}
4601

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

4610
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
3,600,164✔
4611
  pInfo->numOfBins = 0;
3,600,164✔
4612
  pInfo->totalCount = 0;
3,600,164✔
4613
  pInfo->normalized = 0;
3,600,164✔
4614

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

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

4641
  return TSDB_CODE_SUCCESS;
3,600,163✔
4642
}
4643

4644
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
3,619,721✔
4645
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,619,721✔
4646

4647
  SInputColumnInfoData* pInput = &pCtx->input;
3,619,721✔
4648
  SColumnInfoData*      pCol = pInput->pData[0];
3,619,721✔
4649

4650
  int32_t type = pInput->pData[0]->info.type;
3,619,721✔
4651

4652
  int32_t start = pInput->startRowIndex;
3,619,721✔
4653
  int32_t numOfRows = pInput->numOfRows;
3,619,721✔
4654

4655
  int32_t numOfElems = 0;
3,619,721✔
4656
  for (int32_t i = start; i < numOfRows + start; ++i) {
13,197,468✔
4657
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
9,577,747✔
4658
      continue;
663,005✔
4659
    }
4660

4661
    numOfElems++;
8,914,742✔
4662

4663
    char*  data = colDataGetData(pCol, i);
8,914,742!
4664
    double v;
4665
    GET_TYPED_DATA(v, double, type, data);
8,914,742✔
4666

4667
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
44,612,327✔
4668
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
38,533,234✔
4669
        pInfo->bins[k].count++;
2,835,649✔
4670
        pInfo->totalCount++;
2,835,649✔
4671
        break;
2,835,649✔
4672
      }
4673
    }
4674
  }
4675

4676
  if (!isPartial) {
3,619,721✔
4677
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
3,596,786✔
4678
  } else {
4679
    GET_RES_INFO(pCtx)->numOfRes = 1;
22,935✔
4680
  }
4681
  return TSDB_CODE_SUCCESS;
3,619,721✔
4682
}
4683

4684
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
3,596,781✔
4685

4686
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
22,939✔
4687

4688
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
3,899✔
4689
  pOutput->normalized = pInput->normalized;
3,899✔
4690
  pOutput->numOfBins = pInput->numOfBins;
3,899✔
4691
  pOutput->totalCount += pInput->totalCount;
3,899✔
4692
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
35,523✔
4693
    pOutput->bins[k].lower = pInput->bins[k].lower;
31,624✔
4694
    pOutput->bins[k].upper = pInput->bins[k].upper;
31,624✔
4695
    pOutput->bins[k].count += pInput->bins[k].count;
31,624✔
4696
  }
4697
}
3,899✔
4698

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

4706
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,899✔
4707

4708
  int32_t start = pInput->startRowIndex;
3,899✔
4709

4710
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
7,798✔
4711
    char*           data = colDataGetData(pCol, i);
3,899!
4712
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
3,899✔
4713
    histogramTransferInfo(pInputInfo, pInfo);
3,899✔
4714
  }
4715

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

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

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

4732
  if (pInfo->normalized) {
3,561,161✔
4733
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
34,334✔
4734
      if (pInfo->totalCount != 0) {
27,730✔
4735
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
24,138✔
4736
      } else {
4737
        pInfo->bins[k].percentage = 0;
3,592✔
4738
      }
4739
    }
4740
  }
4741

4742
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
21,362,325✔
4743
    int32_t len;
4744
    char    buf[512] = {0};
17,801,171✔
4745
    if (!pInfo->normalized) {
17,801,171✔
4746
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}",
17,773,442✔
4747
                    pInfo->bins[i].lower, pInfo->bins[i].upper, pInfo->bins[i].count);
4748
    } else {
4749
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower,
27,729✔
4750
                    pInfo->bins[i].upper, pInfo->bins[i].percentage);
4751
    }
4752
    varDataSetLen(buf, len);
17,801,171✔
4753
    code = colDataSetVal(pCol, currentRow, buf, false);
17,801,171✔
4754
    if (TSDB_CODE_SUCCESS != code) {
17,801,164!
4755
      return code;
×
4756
    }
4757
    currentRow++;
17,801,164✔
4758
  }
4759

4760
  return code;
3,561,154✔
4761
}
4762

4763
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,899✔
4764
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,899✔
4765
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,899✔
4766
  int32_t              resultBytes = getHistogramInfoSize();
3,899✔
4767
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
3,899✔
4768

4769
  if (NULL == res) {
3,897!
4770
    return terrno;
×
4771
  }
4772
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
3,897✔
4773
  varDataSetLen(res, resultBytes);
3,897✔
4774

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

4784
_exit:
3,898✔
4785
  taosMemoryFree(res);
3,898✔
4786
  return code;
3,898✔
4787
}
4788

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

4793
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4794
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4795

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

4802
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,810✔
4803

4804
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
64,852✔
4805
  pEnv->calcMemSize = sizeof(SHLLInfo);
64,852✔
4806
  return true;
64,852✔
4807
}
4808

4809
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
3,689,056✔
4810
  uint64_t hash = MurmurHash3_64(data, bytes);
3,689,056✔
4811
  int32_t  index = hash & HLL_BUCKET_MASK;
3,688,562✔
4812
  hash >>= HLL_BUCKET_BITS;
3,688,562✔
4813
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
3,688,562✔
4814
  uint64_t bit = 1;
3,688,562✔
4815
  uint8_t  count = 1;
3,688,562✔
4816
  while ((hash & bit) == 0) {
6,941,905✔
4817
    count++;
3,253,343✔
4818
    bit <<= 1;
3,253,343✔
4819
  }
4820
  *buk = index;
3,688,562✔
4821
  return count;
3,688,562✔
4822
}
4823

4824
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
233,145✔
4825
  uint64_t* word = (uint64_t*)buckets;
233,145✔
4826
  uint8_t*  bytes;
4827

4828
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
469,966,659✔
4829
    if (*word == 0) {
469,733,514✔
4830
      bucketHisto[0] += 8;
468,908,710✔
4831
    } else {
4832
      bytes = (uint8_t*)word;
824,804✔
4833
      bucketHisto[bytes[0]]++;
824,804✔
4834
      bucketHisto[bytes[1]]++;
824,804✔
4835
      bucketHisto[bytes[2]]++;
824,804✔
4836
      bucketHisto[bytes[3]]++;
824,804✔
4837
      bucketHisto[bytes[4]]++;
824,804✔
4838
      bucketHisto[bytes[5]]++;
824,804✔
4839
      bucketHisto[bytes[6]]++;
824,804✔
4840
      bucketHisto[bytes[7]]++;
824,804✔
4841
    }
4842
    word++;
469,733,514✔
4843
  }
4844
}
233,145✔
4845
static double hllTau(double x) {
233,149✔
4846
  if (x == 0. || x == 1.) return 0.;
233,149!
4847
  double zPrime;
4848
  double y = 1.0;
×
4849
  double z = 1 - x;
×
4850
  do {
4851
    x = sqrt(x);
×
4852
    zPrime = z;
×
4853
    y *= 0.5;
×
4854
    z -= pow(1 - x, 2) * y;
×
4855
  } while (zPrime != z);
×
4856
  return z / 3;
×
4857
}
4858

4859
static double hllSigma(double x) {
233,154✔
4860
  if (x == 1.0) return INFINITY;
233,154✔
4861
  double zPrime;
4862
  double y = 1;
210,569✔
4863
  double z = x;
210,569✔
4864
  do {
4865
    x *= x;
4,134,403✔
4866
    zPrime = z;
4,134,403✔
4867
    z += x * y;
4,134,403✔
4868
    y += y;
4,134,403✔
4869
  } while (zPrime != z);
4,134,403✔
4870
  return z;
210,569✔
4871
}
4872

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

4880
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
233,155✔
4881
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
11,886,601✔
4882
    z += buckethisto[j];
11,653,445✔
4883
    z *= 0.5;
11,653,445✔
4884
  }
4885

4886
  z += m * hllSigma(buckethisto[0] / (double)m);
233,156✔
4887
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
233,163✔
4888

4889
  return (uint64_t)E;
233,163✔
4890
}
4891

4892
int32_t hllFunction(SqlFunctionCtx* pCtx) {
258,183✔
4893
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
258,183✔
4894

4895
  SInputColumnInfoData* pInput = &pCtx->input;
258,183✔
4896
  SColumnInfoData*      pCol = pInput->pData[0];
258,183✔
4897

4898
  int32_t type = pCol->info.type;
258,183✔
4899
  int32_t bytes = pCol->info.bytes;
258,183✔
4900

4901
  int32_t start = pInput->startRowIndex;
258,183✔
4902
  int32_t numOfRows = pInput->numOfRows;
258,183✔
4903

4904
  int32_t numOfElems = 0;
258,183✔
4905
  if (IS_NULL_TYPE(type)) {
258,183✔
4906
    goto _hll_over;
1,715✔
4907
  }
4908

4909
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,797,804✔
4910
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
6,185,149!
4911
      continue;
851,754✔
4912
    }
4913

4914
    numOfElems++;
3,689,972✔
4915

4916
    char* data = colDataGetData(pCol, i);
3,689,972!
4917
    if (IS_VAR_DATA_TYPE(type)) {
3,689,972!
4918
      bytes = varDataLen(data);
982,229✔
4919
      data = varDataVal(data);
982,229✔
4920
    }
4921

4922
    int32_t index = 0;
3,689,972✔
4923
    uint8_t count = hllCountNum(data, bytes, &index);
3,689,972✔
4924
    uint8_t oldcount = pInfo->buckets[index];
3,689,582✔
4925
    if (count > oldcount) {
3,689,582✔
4926
      pInfo->buckets[index] = count;
843,978✔
4927
    }
4928
  }
4929

4930
_hll_over:
256,078✔
4931
  pInfo->totalCount += numOfElems;
257,793✔
4932

4933
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
257,793✔
4934
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
2,780✔
4935
  } else {
4936
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
255,013✔
4937
  }
4938

4939
  return TSDB_CODE_SUCCESS;
257,793✔
4940
}
4941

4942
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
11,108✔
4943
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
178,381,720✔
4944
    if (pOutput->buckets[k] < pInput->buckets[k]) {
178,370,612✔
4945
      pOutput->buckets[k] = pInput->buckets[k];
176,776✔
4946
    }
4947
  }
4948
  pOutput->totalCount += pInput->totalCount;
11,108✔
4949
}
11,108✔
4950

4951
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
11,044✔
4952
  SInputColumnInfoData* pInput = &pCtx->input;
11,044✔
4953
  SColumnInfoData*      pCol = pInput->pData[0];
11,044✔
4954

4955
  if (IS_NULL_TYPE(pCol->info.type)) {
11,044!
4956
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4957
    return TSDB_CODE_SUCCESS;
×
4958
  }
4959

4960
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
11,044!
4961
    return TSDB_CODE_SUCCESS;
×
4962
  }
4963

4964
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
11,044✔
4965

4966
  int32_t start = pInput->startRowIndex;
11,044✔
4967

4968
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
22,151✔
4969
    if (colDataIsNull_s(pCol, i)) continue;
22,212!
4970
    char*     data = colDataGetData(pCol, i);
11,106!
4971
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
11,106✔
4972
    hllTransferInfo(pInputInfo, pInfo);
11,106✔
4973
  }
4974

4975
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
11,045✔
4976
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
5✔
4977
  } else {
4978
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
11,040✔
4979
  }
4980

4981
  return TSDB_CODE_SUCCESS;
11,045✔
4982
}
4983

4984
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
233,122✔
4985
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
233,122✔
4986

4987
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
233,122✔
4988
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
233,122✔
4989
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
233,159✔
4990
    pInfo->numOfRes = 1;
19,840✔
4991
  }
4992

4993
  return functionFinalize(pCtx, pBlock);
233,159✔
4994
}
4995

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

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

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

5016
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
10,814✔
5017

5018
_exit:
10,814✔
5019
  taosMemoryFree(res);
10,814✔
5020
  return code;
10,815✔
5021
}
5022

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

5027
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
5028
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
5029

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

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

5041
static int8_t getStateOpType(char* opStr) {
40,766✔
5042
  int8_t opType;
5043
  if (strncasecmp(opStr, "LT", 2) == 0) {
40,766✔
5044
    opType = STATE_OPER_LT;
20,524✔
5045
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
20,242✔
5046
    opType = STATE_OPER_GT;
7,550✔
5047
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
12,692✔
5048
    opType = STATE_OPER_LE;
992✔
5049
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
11,700✔
5050
    opType = STATE_OPER_GE;
1,087✔
5051
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
10,613✔
5052
    opType = STATE_OPER_NE;
8,766✔
5053
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
1,847!
5054
    opType = STATE_OPER_EQ;
1,847✔
5055
  } else {
5056
    opType = STATE_OPER_INVALID;
×
5057
  }
5058

5059
  return opType;
40,766✔
5060
}
5061

5062
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
34,964,561✔
5063
  char* data = colDataGetData(pCol, index);
34,964,561!
5064
  switch (pCol->info.type) {
34,964,561!
5065
    case TSDB_DATA_TYPE_TINYINT: {
88,496✔
5066
      int8_t v = *(int8_t*)data;
88,496✔
5067
      STATE_COMP(op, v, param);
88,496!
5068
      break;
×
5069
    }
5070
    case TSDB_DATA_TYPE_UTINYINT: {
5,760✔
5071
      uint8_t v = *(uint8_t*)data;
5,760✔
5072
      STATE_COMP(op, v, param);
5,760!
5073
      break;
×
5074
    }
5075
    case TSDB_DATA_TYPE_SMALLINT: {
6,112✔
5076
      int16_t v = *(int16_t*)data;
6,112✔
5077
      STATE_COMP(op, v, param);
6,112!
5078
      break;
×
5079
    }
5080
    case TSDB_DATA_TYPE_USMALLINT: {
5,760✔
5081
      uint16_t v = *(uint16_t*)data;
5,760✔
5082
      STATE_COMP(op, v, param);
5,760!
5083
      break;
×
5084
    }
5085
    case TSDB_DATA_TYPE_INT: {
22,514,599✔
5086
      int32_t v = *(int32_t*)data;
22,514,599✔
5087
      STATE_COMP(op, v, param);
22,514,599!
5088
      break;
×
5089
    }
5090
    case TSDB_DATA_TYPE_UINT: {
5,760✔
5091
      uint32_t v = *(uint32_t*)data;
5,760✔
5092
      STATE_COMP(op, v, param);
5,760!
5093
      break;
×
5094
    }
5095
    case TSDB_DATA_TYPE_BIGINT: {
5,228,473✔
5096
      int64_t v = *(int64_t*)data;
5,228,473✔
5097
      STATE_COMP(op, v, param);
5,228,473!
5098
      break;
×
5099
    }
5100
    case TSDB_DATA_TYPE_UBIGINT: {
5,760✔
5101
      uint64_t v = *(uint64_t*)data;
5,760✔
5102
      STATE_COMP(op, v, param);
5,760!
5103
      break;
×
5104
    }
5105
    case TSDB_DATA_TYPE_FLOAT: {
7,017,812✔
5106
      float v = *(float*)data;
7,017,812✔
5107
      STATE_COMP(op, v, param);
7,017,812!
5108
      break;
×
5109
    }
5110
    case TSDB_DATA_TYPE_DOUBLE: {
88,956✔
5111
      double v = *(double*)data;
88,956✔
5112
      STATE_COMP(op, v, param);
88,956!
5113
      break;
×
5114
    }
5115
    default: {
×
5116
      return false;
×
5117
    }
5118
  }
5119
  return false;
×
5120
}
5121

5122
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
3,438✔
5123
  int32_t              code = TSDB_CODE_SUCCESS;
3,438✔
5124
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,438✔
5125
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,438✔
5126

5127
  SInputColumnInfoData* pInput = &pCtx->input;
3,438✔
5128
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
3,438✔
5129

5130
  SColumnInfoData* pInputCol = pInput->pData[0];
3,438✔
5131

5132
  int32_t          numOfElems = 0;
3,438✔
5133
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
3,438✔
5134

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

5140
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
563,997✔
5141
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
560,569!
5142
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5143
    } else {
5144
      pInfo->prevTs = tsList[i];
560,569✔
5145
    }
5146

5147
    pInfo->isPrevTsSet = true;
560,569✔
5148
    numOfElems++;
560,569✔
5149

5150
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
560,569✔
5151
      colDataSetNULL(pOutput, i);
257,624!
5152
      // handle selectivity
5153
      if (pCtx->subsidiaries.num > 0) {
257,624✔
5154
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
44✔
5155
        if (TSDB_CODE_SUCCESS != code) {
44!
5156
          return code;
×
5157
        }
5158
      }
5159
      continue;
257,624✔
5160
    }
5161

5162
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
302,945✔
5163

5164
    int64_t output = -1;
302,757✔
5165
    if (ret) {
302,757✔
5166
      output = ++pInfo->count;
150,006✔
5167
    } else {
5168
      pInfo->count = 0;
152,751✔
5169
    }
5170
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
302,757✔
5171
    if (TSDB_CODE_SUCCESS != code) {
302,935!
5172
      return code;
×
5173
    }
5174

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

5184
  pResInfo->numOfRes = numOfElems;
3,428✔
5185
  return TSDB_CODE_SUCCESS;
3,428✔
5186
}
5187

5188
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
37,327✔
5189
  int32_t              code = TSDB_CODE_SUCCESS;
37,327✔
5190
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
37,327✔
5191
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
37,327✔
5192

5193
  SInputColumnInfoData* pInput = &pCtx->input;
37,327✔
5194
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
37,327✔
5195

5196
  SColumnInfoData* pInputCol = pInput->pData[0];
37,327✔
5197

5198
  int32_t          numOfElems = 0;
37,327✔
5199
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
37,327✔
5200

5201
  // TODO: process timeUnit for different db precisions
5202
  int32_t timeUnit = 1;
37,327✔
5203
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
37,327✔
5204
    timeUnit = pCtx->param[3].param.i;
35,368✔
5205
  }
5206

5207
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
37,327✔
5208
  if (STATE_OPER_INVALID == op) {
37,327!
5209
    return TSDB_CODE_INVALID_PARA;
×
5210
  }
5211

5212
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
34,805,286✔
5213
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
34,767,960!
5214
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5215
    } else {
5216
      pInfo->prevTs = tsList[i];
34,767,960✔
5217
    }
5218

5219
    pInfo->isPrevTsSet = true;
34,767,960✔
5220
    numOfElems++;
34,767,960✔
5221

5222
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
34,767,960✔
5223
      colDataSetNULL(pOutput, i);
105,684!
5224
      // handle selectivity
5225
      if (pCtx->subsidiaries.num > 0) {
105,684✔
5226
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
60✔
5227
        if (TSDB_CODE_SUCCESS != code) {
60!
5228
          return code;
×
5229
        }
5230
      }
5231
      continue;
105,684✔
5232
    }
5233

5234
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
34,662,276✔
5235
    int64_t output = -1;
34,662,276✔
5236
    if (ret) {
34,662,276✔
5237
      if (pInfo->durationStart == 0) {
20,811,734✔
5238
        output = 0;
7,070,147✔
5239
        pInfo->durationStart = tsList[i];
7,070,147✔
5240
      } else {
5241
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
13,741,587✔
5242
      }
5243
    } else {
5244
      pInfo->durationStart = 0;
13,850,542✔
5245
    }
5246
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
34,662,276✔
5247
    if (TSDB_CODE_SUCCESS != code) {
34,662,275!
5248
      return code;
×
5249
    }
5250

5251
    // handle selectivity
5252
    if (pCtx->subsidiaries.num > 0) {
34,662,275✔
5253
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
19,935,440✔
5254
      if (TSDB_CODE_SUCCESS != code) {
19,935,440!
5255
        return code;
×
5256
      }
5257
    }
5258
  }
5259

5260
  pResInfo->numOfRes = numOfElems;
37,326✔
5261
  return TSDB_CODE_SUCCESS;
37,326✔
5262
}
5263

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

5269
int32_t csumFunction(SqlFunctionCtx* pCtx) {
19,312✔
5270
  int32_t              code = TSDB_CODE_SUCCESS;
19,312✔
5271
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
19,312✔
5272
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
19,312✔
5273

5274
  SInputColumnInfoData* pInput = &pCtx->input;
19,312✔
5275
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
19,312✔
5276

5277
  SColumnInfoData* pInputCol = pInput->pData[0];
19,312✔
5278
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
19,312✔
5279

5280
  int32_t numOfElems = 0;
19,312✔
5281
  int32_t type = pInputCol->info.type;
19,312✔
5282
  int32_t startOffset = pCtx->offset;
19,312✔
5283
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4,002,402✔
5284
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,983,108✔
5285
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5286
    } else {
5287
      pSumRes->prevTs = tsList[i];
3,983,090✔
5288
    }
5289
    pSumRes->isPrevTsSet = true;
3,983,090✔
5290

5291
    int32_t pos = startOffset + numOfElems;
3,983,090✔
5292
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,983,090✔
5293
      // colDataSetNULL(pOutput, i);
5294
      continue;
492,600✔
5295
    }
5296

5297
    char* data = colDataGetData(pInputCol, i);
3,490,490!
5298
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,815,360✔
5299
      int64_t v;
5300
      GET_TYPED_DATA(v, int64_t, type, data);
1,324,870!
5301
      pSumRes->isum += v;
1,324,870✔
5302
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
1,324,870✔
5303
      if (TSDB_CODE_SUCCESS != code) {
1,324,870!
5304
        return code;
×
5305
      }
5306
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,166,300!
5307
      uint64_t v;
5308
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5309
      pSumRes->usum += v;
680✔
5310
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5311
      if (TSDB_CODE_SUCCESS != code) {
680!
5312
        return code;
×
5313
      }
5314
    } else if (IS_FLOAT_TYPE(type)) {
2,164,940!
5315
      double v;
5316
      GET_TYPED_DATA(v, double, type, data);
2,165,892!
5317
      pSumRes->dsum += v;
2,165,892✔
5318
      // check for overflow
5319
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
2,165,892!
5320
        colDataSetNULL(pOutput, pos);
8!
5321
      } else {
5322
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
2,165,884✔
5323
        if (TSDB_CODE_SUCCESS != code) {
2,165,884!
5324
          return code;
×
5325
        }
5326
      }
5327
    }
5328

5329
    // handle selectivity
5330
    if (pCtx->subsidiaries.num > 0) {
3,490,490✔
5331
      code = appendSelectivityValue(pCtx, i, pos);
2,006,020✔
5332
      if (TSDB_CODE_SUCCESS != code) {
2,006,020!
5333
        return code;
×
5334
      }
5335
    }
5336

5337
    numOfElems++;
3,490,490✔
5338
  }
5339

5340
  pResInfo->numOfRes = numOfElems;
19,294✔
5341
  return TSDB_CODE_SUCCESS;
19,294✔
5342
}
5343

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

5349
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
67,673✔
5350
  if (pResultInfo->initialized) {
67,673✔
5351
    return TSDB_CODE_SUCCESS;
52,937✔
5352
  }
5353
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,736!
5354
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5355
  }
5356

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

5368
  return TSDB_CODE_SUCCESS;
14,737✔
5369
}
5370

5371
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
53,948✔
5372
  int32_t              code = TSDB_CODE_SUCCESS;
53,948✔
5373
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
53,948✔
5374
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
53,948✔
5375

5376
  SInputColumnInfoData* pInput = &pCtx->input;
53,948✔
5377
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
53,948✔
5378

5379
  SColumnInfoData* pInputCol = pInput->pData[0];
53,948✔
5380
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
53,948✔
5381
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
53,948✔
5382

5383
  int32_t numOfElems = 0;
53,948✔
5384
  int32_t type = pInputCol->info.type;
53,948✔
5385
  int32_t startOffset = pCtx->offset;
53,948✔
5386
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
59,150,051✔
5387
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
59,096,103!
5388
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5389
    } else {
5390
      pInfo->prevTs = tsList[i];
59,096,103✔
5391
    }
5392
    pInfo->isPrevTsSet = true;
59,096,103✔
5393

5394
    int32_t pos = startOffset + numOfElems;
59,096,103✔
5395
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
59,096,103✔
5396
      // colDataSetNULL(pOutput, i);
5397
      continue;
255,699✔
5398
    }
5399

5400
    char*  data = colDataGetData(pInputCol, i);
58,840,404!
5401
    double v;
5402
    GET_TYPED_DATA(v, double, type, data);
58,840,404!
5403

5404
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
58,840,404✔
5405
      pInfo->points[pInfo->pos] = v;
5,967,833✔
5406
      pInfo->sum += v;
5,967,833✔
5407
    } else {
5408
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
52,872,571!
5409
        pInfo->sum += v;
10,946✔
5410
        pInfo->pointsMeet = true;
10,946✔
5411
      } else {
5412
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
52,861,625✔
5413
      }
5414

5415
      pInfo->points[pInfo->pos] = v;
52,872,571✔
5416
      double result = pInfo->sum / pInfo->numOfPoints;
52,872,571✔
5417
      // check for overflow
5418
      if (isinf(result) || isnan(result)) {
52,872,571!
5419
        colDataSetNULL(pOutput, pos);
×
5420
      } else {
5421
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
52,872,590✔
5422
        if (TSDB_CODE_SUCCESS != code) {
52,872,590!
5423
          return code;
×
5424
        }
5425
      }
5426

5427
      // handle selectivity
5428
      if (pCtx->subsidiaries.num > 0) {
52,872,571✔
5429
        code = appendSelectivityValue(pCtx, i, pos);
33,104,416✔
5430
        if (TSDB_CODE_SUCCESS != code) {
33,104,416!
5431
          return code;
×
5432
        }
5433
      }
5434

5435
      numOfElems++;
52,872,571✔
5436
    }
5437

5438
    pInfo->pos++;
58,840,404✔
5439
    if (pInfo->pos == pInfo->numOfPoints) {
58,840,404✔
5440
      pInfo->pos = 0;
112,853✔
5441
    }
5442
  }
5443

5444
  pResInfo->numOfRes = numOfElems;
53,948✔
5445
  return TSDB_CODE_SUCCESS;
53,948✔
5446
}
5447

5448
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
13,660,122✔
5449
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,660,122✔
5450
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
13,660,122✔
5451

5452
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
13,660,122✔
5453
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
13,660,122✔
5454

5455
  return pInfo;
13,660,122✔
5456
}
5457

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

5466
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
6,891,172✔
5467
  if (pResultInfo->initialized) {
6,891,172!
5468
    return TSDB_CODE_SUCCESS;
×
5469
  }
5470
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
6,891,172!
5471
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5472
  }
5473

5474
  taosSeedRand(taosSafeRand());
6,891,173✔
5475

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

5487
  return TSDB_CODE_SUCCESS;
6,891,174✔
5488
}
5489

5490
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
15,204,852✔
5491
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
15,204,852✔
5492
}
15,204,865✔
5493

5494
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
16,488,369✔
5495
  pInfo->totalPoints++;
16,488,369✔
5496
  if (pInfo->numSampled < pInfo->samples) {
16,488,369✔
5497
    sampleAssignResult(pInfo, data, pInfo->numSampled);
13,682,606✔
5498
    if (pCtx->subsidiaries.num > 0) {
13,682,616✔
5499
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,273,137✔
5500
      if (code != TSDB_CODE_SUCCESS) {
1,273,162!
5501
        return code;
×
5502
      }
5503
    }
5504
    pInfo->numSampled++;
13,682,641✔
5505
  } else {
5506
    int32_t j = taosRand() % (pInfo->totalPoints);
2,805,763✔
5507
    if (j < pInfo->samples) {
2,806,658✔
5508
      sampleAssignResult(pInfo, data, j);
1,522,642✔
5509
      if (pCtx->subsidiaries.num > 0) {
1,522,639✔
5510
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
723,180✔
5511
        if (code != TSDB_CODE_SUCCESS) {
722,390!
5512
          return code;
×
5513
        }
5514
      }
5515
    }
5516
  }
5517

5518
  return TSDB_CODE_SUCCESS;
16,488,506✔
5519
}
5520

5521
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
6,894,101✔
5522
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,894,101✔
5523
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
6,894,101✔
5524

5525
  SInputColumnInfoData* pInput = &pCtx->input;
6,894,099✔
5526

5527
  SColumnInfoData* pInputCol = pInput->pData[0];
6,894,099✔
5528
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
23,804,853✔
5529
    if (colDataIsNull_s(pInputCol, i)) {
33,817,734✔
5530
      continue;
422,363✔
5531
    }
5532

5533
    char*   data = colDataGetData(pInputCol, i);
16,486,504!
5534
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
16,486,504✔
5535
    if (code != TSDB_CODE_SUCCESS) {
16,488,391!
5536
      return code;
×
5537
    }
5538
  }
5539

5540
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
6,895,986✔
5541
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
35✔
5542
    if (code != TSDB_CODE_SUCCESS) {
35!
5543
      return code;
×
5544
    }
5545
    pInfo->nullTupleSaved = true;
35✔
5546
  }
5547

5548
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
6,895,986✔
5549
  return TSDB_CODE_SUCCESS;
6,895,986✔
5550
}
5551

5552
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,766,024✔
5553
  int32_t              code = TSDB_CODE_SUCCESS;
6,766,024✔
5554
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6,766,024✔
5555

5556
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
6,766,024✔
5557
  pEntryInfo->complete = true;
6,766,024✔
5558

5559
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
6,766,024✔
5560
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,766,024✔
5561
  if (NULL == pCol) {
6,766,024!
5562
    return TSDB_CODE_OUT_OF_RANGE;
×
5563
  }
5564

5565
  int32_t currentRow = pBlock->info.rows;
6,766,024✔
5566
  if (pInfo->numSampled == 0) {
6,766,024✔
5567
    colDataSetNULL(pCol, currentRow);
2,562✔
5568
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,562✔
5569
    return code;
2,562✔
5570
  }
5571
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
20,199,636✔
5572
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
13,436,294✔
5573
    if (TSDB_CODE_SUCCESS != code) {
13,435,395!
5574
      return code;
×
5575
    }
5576
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
13,435,395✔
5577
    if (TSDB_CODE_SUCCESS != code) {
13,436,174!
5578
      return code;
×
5579
    }
5580
  }
5581

5582
  return code;
6,763,342✔
5583
}
5584

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

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

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

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

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

5626
  return TSDB_CODE_SUCCESS;
×
5627
}
5628

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

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

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

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

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

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

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

5683
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
5684

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

5695
  return pInfo->numOfPoints;
5696
#endif
5697
  return 0;
×
5698
}
5699

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

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

5709
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5710

5711
  // todo assign the tag value and the corresponding row data
5712
  int32_t currentRow = pBlock->info.rows;
5713
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
5714
    STailItem* pItem = pInfo->pItems[i];
5715
    colDataSetVal(pCol, currentRow, pItem->data, false);
5716
    currentRow += 1;
5717
  }
5718

5719
  return pEntryInfo->numOfRes;
5720
#endif
5721
  return 0;
×
5722
}
5723

5724
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5725
#if 0
5726
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
5727
#endif
5728
  return true;
×
5729
}
5730

5731
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
5732
#if 0
5733
  if (!functionSetup(pCtx, pResInfo)) {
5734
    return false;
5735
  }
5736

5737
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5738
  pInfo->numOfPoints = 0;
5739
  pInfo->colType = pCtx->resDataInfo.type;
5740
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5741
  if (pInfo->pHash != NULL) {
5742
    taosHashClear(pInfo->pHash);
5743
  } else {
5744
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
5745
  }
5746
#endif
5747
  return TSDB_CODE_SUCCESS;
×
5748
}
5749

5750
#if 0
5751
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5752
  // handle null elements
5753
  if (isNull == true) {
5754
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5755
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5756
    if (pInfo->hasNull == false && pItem->isNull == false) {
5757
      pItem->timestamp = ts;
5758
      pItem->isNull = true;
5759
      pInfo->numOfPoints++;
5760
      pInfo->hasNull = true;
5761
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
5762
      pItem->timestamp = ts;
5763
    }
5764
    return;
5765
  }
5766

5767
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
5768
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
5769
  if (pHashItem == NULL) {
5770
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5771
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5772
    pItem->timestamp = ts;
5773
    memcpy(pItem->data, data, pInfo->colBytes);
5774

5775
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
5776
    pInfo->numOfPoints++;
5777
  } else if (pHashItem->timestamp > ts) {
5778
    pHashItem->timestamp = ts;
5779
  }
5780
}
5781
#endif
5782

5783
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
5784
#if 0
5785
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5786
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5787

5788
  SInputColumnInfoData* pInput = &pCtx->input;
5789
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5790

5791
  SColumnInfoData* pInputCol = pInput->pData[0];
5792
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
5793
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5794

5795
  int32_t startOffset = pCtx->offset;
5796
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5797
    char* data = colDataGetData(pInputCol, i);
5798
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5799

5800
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
5801
      taosHashCleanup(pInfo->pHash);
5802
      return 0;
5803
    }
5804
  }
5805

5806
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5807
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
5808
    if (pItem->isNull == true) {
5809
      colDataSetNULL(pOutput, i);
5810
    } else {
5811
      colDataSetVal(pOutput, i, pItem->data, false);
5812
    }
5813
    if (pTsOutput != NULL) {
5814
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
5815
    }
5816
  }
5817

5818
  return pInfo->numOfPoints;
5819
#endif
5820
  return 0;
×
5821
}
5822

5823
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
25,122✔
5824
  pEnv->calcMemSize = sizeof(SModeInfo);
25,122✔
5825
  return true;
25,122✔
5826
}
5827

5828
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
26,092✔
5829
  if (pResInfo->initialized) {
26,092!
5830
    return TSDB_CODE_SUCCESS;
×
5831
  }
5832
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
26,092!
5833
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5834
  }
5835

5836
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
26,091✔
5837
  pInfo->colType = pCtx->resDataInfo.type;
26,091✔
5838
  pInfo->colBytes = pCtx->resDataInfo.bytes;
26,091✔
5839
  if (pInfo->pHash != NULL) {
26,091!
5840
    taosHashClear(pInfo->pHash);
×
5841
  } else {
5842
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
26,091✔
5843
    if (NULL == pInfo->pHash) {
26,093!
5844
      return terrno;
×
5845
    }
5846
  }
5847
  pInfo->nullTupleSaved = false;
26,093✔
5848
  pInfo->nullTuplePos.pageId = -1;
26,093✔
5849

5850
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
26,093✔
5851
  if (NULL == pInfo->buf) {
26,092!
5852
    taosHashCleanup(pInfo->pHash);
×
5853
    pInfo->pHash = NULL;
×
5854
    return terrno;
×
5855
  }
5856
  pCtx->needCleanup = true;
26,092✔
5857
  return TSDB_CODE_SUCCESS;
26,092✔
5858
}
5859

5860
static void modeFunctionCleanup(SModeInfo * pInfo) {
26,093✔
5861
  taosHashCleanup(pInfo->pHash);
26,093✔
5862
  pInfo->pHash = NULL;
26,093✔
5863
  taosMemoryFreeClear(pInfo->buf);
26,093!
5864
}
26,093✔
5865

5866
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5867
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5868
    return;
×
5869
  }
5870
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5871
}
5872

5873
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo *pInfo, STuplePos* pPos) {
113,408,898✔
5874
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
113,408,898!
5875
    (void)memcpy(pInfo->buf, data, varDataTLen(data));
23,490,833✔
5876
  } else {
5877
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
89,918,065✔
5878
  }
5879

5880
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
113,408,898✔
5881
}
5882

5883
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
122,345,661✔
5884
  int32_t code = TSDB_CODE_SUCCESS;
122,345,661✔
5885
  int32_t hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
122,345,661✔
5886

5887
  SModeItem* pHashItem = (SModeItem *)taosHashGet(pInfo->pHash, data, hashKeyBytes);
122,345,661✔
5888
  if (pHashItem == NULL) {
122,345,209✔
5889
    int32_t    size = sizeof(SModeItem);
113,408,897✔
5890
    SModeItem  item = {0};
113,408,897✔
5891

5892
    item.count += 1;
113,408,897✔
5893
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
113,408,897✔
5894
    if (code != TSDB_CODE_SUCCESS) {
113,408,241!
5895
      return code;
×
5896
    }
5897

5898
    if (pCtx->subsidiaries.num > 0) {
113,408,241✔
5899
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
73,908,044✔
5900
      if (code != TSDB_CODE_SUCCESS) {
73,908,044!
5901
        return code;
×
5902
      }
5903
    }
5904

5905
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
113,408,241✔
5906
    if (code != TSDB_CODE_SUCCESS) {
113,409,629!
5907
      return code;
×
5908
    }
5909
  } else {
5910
    pHashItem->count += 1;
8,936,312✔
5911
    if (pCtx->subsidiaries.num > 0) {
8,936,312✔
5912
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
6,453,477✔
5913
      if (code != TSDB_CODE_SUCCESS) {
6,453,477!
5914
        return code;
×
5915
      }
5916
    }
5917
  }
5918

5919
  return code;
122,345,941✔
5920
}
5921

5922
int32_t modeFunction(SqlFunctionCtx* pCtx) {
2,465,772✔
5923
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,465,772✔
5924
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,465,772✔
5925

5926
  SInputColumnInfoData* pInput = &pCtx->input;
2,465,772✔
5927

5928
  SColumnInfoData* pInputCol = pInput->pData[0];
2,465,772✔
5929
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,465,772✔
5930

5931
  int32_t numOfElems = 0;
2,465,772✔
5932
  int32_t startOffset = pCtx->offset;
2,465,772✔
5933
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
125,415,579✔
5934
    if (colDataIsNull_s(pInputCol, i)) {
245,899,570✔
5935
      continue;
604,050✔
5936
    }
5937
    numOfElems++;
122,345,735✔
5938

5939
    char*   data = colDataGetData(pInputCol, i);
122,345,735!
5940
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
122,345,735✔
5941
    if (code != TSDB_CODE_SUCCESS) {
122,345,935✔
5942
      modeFunctionCleanup(pInfo);
178✔
5943
      return code;
×
5944
    }
5945
  }
5946

5947
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,465,794!
5948
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
5949
    if (code != TSDB_CODE_SUCCESS) {
50!
5950
      modeFunctionCleanup(pInfo);
×
5951
      return code;
×
5952
    }
5953
    pInfo->nullTupleSaved = true;
50✔
5954
  }
5955

5956
  SET_VAL(pResInfo, numOfElems, 1);
2,465,794✔
5957

5958
  return TSDB_CODE_SUCCESS;
2,465,794✔
5959
}
5960

5961
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
26,092✔
5962
  int32_t              code = TSDB_CODE_SUCCESS;
26,092✔
5963
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
26,092✔
5964
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
26,092✔
5965
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
26,092✔
5966
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
26,092✔
5967
  int32_t              currentRow = pBlock->info.rows;
26,092✔
5968
  if (NULL == pCol) {
26,092!
5969
    modeFunctionCleanup(pInfo);
×
5970
    return TSDB_CODE_OUT_OF_RANGE;
×
5971
  }
5972

5973
  STuplePos resDataPos, resTuplePos;
5974
  int32_t maxCount = 0;
26,092✔
5975

5976
  void *pIter = taosHashIterate(pInfo->pHash, NULL);
26,092✔
5977
  while (pIter != NULL) {
113,435,841✔
5978
    SModeItem *pItem = (SModeItem *)pIter;
113,409,749✔
5979
    if (pItem->count >= maxCount) {
113,409,749✔
5980
      maxCount = pItem->count;
57,234,766✔
5981
      resDataPos = pItem->dataPos;
57,234,766✔
5982
      resTuplePos = pItem->tuplePos;
57,234,766✔
5983
    }
5984

5985
    pIter = taosHashIterate(pInfo->pHash, pIter);
113,409,749✔
5986
  }
5987

5988
  if (maxCount != 0) {
26,092✔
5989
    char* pData = NULL;
22,631✔
5990
    code = loadTupleData(pCtx, &resDataPos, &pData);
22,631✔
5991
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
22,631!
5992
      code = terrno = TSDB_CODE_NOT_FOUND;
×
5993
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
5994
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
5995
      modeFunctionCleanup(pInfo);
×
5996
      return code;
×
5997
    }
5998

5999
    code = colDataSetVal(pCol, currentRow, pData, false);
22,631✔
6000
    if (TSDB_CODE_SUCCESS != code) {
22,631!
6001
      modeFunctionCleanup(pInfo);
×
6002
     return code;
×
6003
    }
6004
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
22,631✔
6005
  } else {
6006
    colDataSetNULL(pCol, currentRow);
3,461✔
6007
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
3,461✔
6008
  }
6009

6010
  modeFunctionCleanup(pInfo);
26,093✔
6011

6012
  return code;
26,093✔
6013
}
6014

6015
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
79,812✔
6016
  pEnv->calcMemSize = sizeof(STwaInfo);
79,812✔
6017
  return true;
79,812✔
6018
}
6019

6020
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
10,618,942✔
6021
  if (pResultInfo->initialized) {
10,618,942!
6022
    return TSDB_CODE_SUCCESS;
×
6023
  }
6024
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
10,618,942!
6025
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6026
  }
6027

6028
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,618,951✔
6029
  pInfo->numOfElems = 0;
10,618,951✔
6030
  pInfo->p.key = INT64_MIN;
10,618,951✔
6031
  pInfo->win = TSWINDOW_INITIALIZER;
10,618,951✔
6032
  return TSDB_CODE_SUCCESS;
10,618,951✔
6033
}
6034

6035
static double twa_get_area(SPoint1 s, SPoint1 e) {
27,931,611✔
6036
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
27,931,611!
6037
    return 0;
×
6038
  }
6039

6040
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
27,931,888✔
6041
    return (s.val + e.val) * (e.key - s.key) / 2;
15,027,556✔
6042
  }
6043

6044
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
12,904,332✔
6045
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
12,904,332✔
6046
  return val;
12,904,332✔
6047
}
6048

6049
int32_t twaFunction(SqlFunctionCtx* pCtx) {
10,624,855✔
6050
  int32_t               code = TSDB_CODE_SUCCESS;
10,624,855✔
6051
  SInputColumnInfoData* pInput = &pCtx->input;
10,624,855✔
6052
  SColumnInfoData*      pInputCol = pInput->pData[0];
10,624,855✔
6053

6054
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,624,855✔
6055
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
10,624,855✔
6056
  SPoint1*             last = &pInfo->p;
10,624,855✔
6057

6058
  if (IS_NULL_TYPE(pInputCol->info.type)) {
10,624,855!
6059
    pInfo->numOfElems = 0;
×
6060
    goto _twa_over;
×
6061
  }
6062

6063
  funcInputUpdate(pCtx);
10,624,855✔
6064
  SFuncInputRow row = {0};
10,624,890✔
6065
  bool          result = false;
10,624,890✔
6066
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
10,624,890✔
6067
    while (1) {
6068
      code = funcInputGetNextRow(pCtx, &row, &result);
3,387,211✔
6069
      if (TSDB_CODE_SUCCESS != code) {
3,387,219!
6070
        return code;
×
6071
      }
6072
      if (!result) {
3,387,219✔
6073
        break;
2✔
6074
      }
6075
      if (row.isDataNull) {
3,387,217✔
6076
        continue;
2✔
6077
      }
6078

6079
      last->key = row.ts;
3,387,215✔
6080

6081
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,387,215!
6082

6083
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
3,387,215✔
6084
      pInfo->win.skey = pCtx->start.key;
3,387,210✔
6085
      pInfo->numOfElems++;
3,387,210✔
6086
      break;
3,387,210✔
6087
    }
6088
  } else if (pInfo->p.key == INT64_MIN) {
7,237,681✔
6089
    while (1) {
6090
      code = funcInputGetNextRow(pCtx, &row, &result);
7,345,698✔
6091
      if (TSDB_CODE_SUCCESS != code) {
7,345,678!
6092
        return code;
×
6093
      }
6094
      if (!result) {
7,345,678✔
6095
        break;
15,450✔
6096
      }
6097
      if (row.isDataNull) {
7,330,228✔
6098
        continue;
113,573✔
6099
      }
6100

6101
      last->key = row.ts;
7,216,655✔
6102

6103
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
7,216,655!
6104

6105
      pInfo->win.skey = last->key;
7,216,655✔
6106
      pInfo->numOfElems++;
7,216,655✔
6107
      break;
7,216,655✔
6108
    }
6109
  }
6110

6111
  SPoint1 st = {0};
10,624,873✔
6112

6113
  // calculate the value of
6114
  while (1) {
6115
    code = funcInputGetNextRow(pCtx, &row, &result);
31,717,269✔
6116
    if (TSDB_CODE_SUCCESS != code) {
31,717,294!
6117
      return code;
×
6118
    }
6119
    if (!result) {
31,717,294✔
6120
      break;
10,624,865✔
6121
    }
6122
    if (row.isDataNull) {
21,092,429✔
6123
      continue;
630✔
6124
    }
6125
    pInfo->numOfElems++;
21,091,799✔
6126
    switch (pInputCol->info.type) {
21,091,799!
6127
      case TSDB_DATA_TYPE_TINYINT: {
95,800✔
6128
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
95,800✔
6129
        break;
95,800✔
6130
      }
6131
      case TSDB_DATA_TYPE_SMALLINT: {
16,623,823✔
6132
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
16,623,823✔
6133
        break;
16,623,823✔
6134
      }
6135
      case TSDB_DATA_TYPE_INT: {
2,754,883✔
6136
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
2,754,883✔
6137
        break;
2,754,883✔
6138
      }
6139
      case TSDB_DATA_TYPE_BIGINT: {
919,912✔
6140
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
919,912✔
6141
        break;
919,912✔
6142
      }
6143
      case TSDB_DATA_TYPE_FLOAT: {
342,703✔
6144
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
342,703✔
6145
        break;
342,703✔
6146
      }
6147
      case TSDB_DATA_TYPE_DOUBLE: {
87,125✔
6148
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
87,125✔
6149
        break;
87,125✔
6150
      }
6151
      case TSDB_DATA_TYPE_UTINYINT: {
68,968✔
6152
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
68,968✔
6153
        break;
68,968✔
6154
      }
6155
      case TSDB_DATA_TYPE_USMALLINT: {
68,429✔
6156
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
68,429✔
6157
        break;
68,429✔
6158
      }
6159
      case TSDB_DATA_TYPE_UINT: {
71,011✔
6160
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
71,011✔
6161
        break;
71,011✔
6162
      }
6163
      case TSDB_DATA_TYPE_UBIGINT: {
59,438✔
6164
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
59,438✔
6165
        break;
59,438✔
6166
      }
6167
      default: {
×
6168
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6169
      }
6170
    }
6171
    if (pInfo->p.key == st.key) {
21,092,092!
6172
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6173
    }
6174

6175
    pInfo->dOutput += twa_get_area(pInfo->p, st);
21,092,092✔
6176
    pInfo->p = st;
21,091,766✔
6177
  }
6178

6179
  // the last interpolated time window value
6180
  if (pCtx->end.key != INT64_MIN) {
10,624,865✔
6181
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
3,453,495✔
6182
    pInfo->p = pCtx->end;
3,453,494✔
6183
    pInfo->numOfElems += 1;
3,453,494✔
6184
  }
6185

6186
  pInfo->win.ekey = pInfo->p.key;
10,624,864✔
6187

6188
_twa_over:
10,624,864✔
6189
  SET_VAL(pResInfo, 1, 1);
10,624,864✔
6190
  return TSDB_CODE_SUCCESS;
10,624,864✔
6191
}
6192

6193
/*
6194
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6195
 * by next input data. The TWA function only applies to each table, so no merge procedure
6196
 * is required, we simply copy to the resut ot interResBuffer.
6197
 */
6198
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6199
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6200
//
6201
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6202
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6203
// }
6204

6205
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,612,915✔
6206
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,612,915✔
6207

6208
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
10,612,915✔
6209
  if (pInfo->numOfElems == 0) {
10,612,915✔
6210
    pResInfo->numOfRes = 0;
15,198✔
6211
  } else {
6212
    if (pInfo->win.ekey == pInfo->win.skey) {
10,597,717✔
6213
      pInfo->dTwaRes = pInfo->p.val;
5,823,088✔
6214
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
4,774,629!
6215
      pInfo->dTwaRes = 0;
×
6216
    } else {
6217
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
4,774,839✔
6218
    }
6219

6220
    pResInfo->numOfRes = 1;
10,597,717✔
6221
  }
6222

6223
  return functionFinalize(pCtx, pBlock);
10,612,915✔
6224
}
6225

6226
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,627✔
6227
  if (pResultInfo->initialized) {
1,627!
6228
    return TSDB_CODE_SUCCESS;
×
6229
  }
6230
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,627!
6231
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6232
  }
6233

6234
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,627✔
6235
  pInfo->minRows = INT32_MAX;
1,627✔
6236
  return TSDB_CODE_SUCCESS;
1,627✔
6237
}
6238

6239
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,252✔
6240
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,252✔
6241

6242
  SInputColumnInfoData* pInput = &pCtx->input;
3,252✔
6243
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,252✔
6244
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,252✔
6245
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,252✔
6246

6247
  STableBlockDistInfo p1 = {0};
3,252✔
6248
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,252!
6249
    qError("failed to deserialize block dist info");
×
6250
    return TSDB_CODE_FAILED;
×
6251
  }
6252

6253
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,252✔
6254
  pDistInfo->numOfTables += p1.numOfTables;
3,252✔
6255
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,252✔
6256
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,252✔
6257
  pDistInfo->totalSize += p1.totalSize;
3,252✔
6258
  pDistInfo->totalRows += p1.totalRows;
3,252✔
6259
  pDistInfo->numOfFiles += p1.numOfFiles;
3,252✔
6260

6261
  pDistInfo->defMinRows = p1.defMinRows;
3,252✔
6262
  pDistInfo->defMaxRows = p1.defMaxRows;
3,252✔
6263
  pDistInfo->rowSize = p1.rowSize;
3,252✔
6264

6265
  if (pDistInfo->minRows > p1.minRows) {
3,252✔
6266
    pDistInfo->minRows = p1.minRows;
2✔
6267
  }
6268
  if (pDistInfo->maxRows < p1.maxRows) {
3,252✔
6269
    pDistInfo->maxRows = p1.maxRows;
2✔
6270
  }
6271
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,252✔
6272
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,292✔
6273
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,040✔
6274
  }
6275

6276
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,252✔
6277
  return TSDB_CODE_SUCCESS;
3,252✔
6278
}
6279

6280
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,499✔
6281
  SEncoder encoder = {0};
6,499✔
6282
  int32_t  code = 0;
6,499✔
6283
  int32_t  lino;
6284
  int32_t  tlen;
6285
  tEncoderInit(&encoder, buf, bufLen);
6,499✔
6286

6287
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,499!
6288
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
12,992!
6289

6290
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
12,992!
6291
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
12,992!
6292
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
12,992!
6293

6294
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
12,992!
6295
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
12,992!
6296
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
12,992!
6297
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
12,992!
6298
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
12,992!
6299
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
12,992!
6300
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
12,992!
6301
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
12,992!
6302
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
12,992!
6303

6304
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,355✔
6305
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,718!
6306
  }
6307

6308
  tEndEncode(&encoder);
6,496✔
6309

6310
_exit:
6,500✔
6311
  if (code) {
6,500!
6312
    tlen = code;
×
6313
  } else {
6314
    tlen = encoder.pos;
6,500✔
6315
  }
6316
  tEncoderClear(&encoder);
6,500✔
6317
  return tlen;
6,498✔
6318
}
6319

6320
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,252✔
6321
  SDecoder decoder = {0};
3,252✔
6322
  int32_t  code = 0;
3,252✔
6323
  int32_t  lino;
6324
  tDecoderInit(&decoder, buf, bufLen);
3,252✔
6325

6326
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,252!
6327
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,504!
6328

6329
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,504!
6330
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,504!
6331
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,504!
6332

6333
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,504!
6334
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,504!
6335
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,504!
6336
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,504!
6337
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,504!
6338
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,504!
6339
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,504!
6340
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,504!
6341
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,504!
6342

6343
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,292✔
6344
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,080!
6345
  }
6346

6347
_exit:
3,252✔
6348
  tDecoderClear(&decoder);
3,252✔
6349
  return code;
3,252✔
6350
}
6351

6352
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,627✔
6353
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,627✔
6354
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,627✔
6355

6356
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,627✔
6357
  if (NULL == pColInfo) {
1,627!
6358
    return TSDB_CODE_OUT_OF_RANGE;
×
6359
  }
6360

6361
  if (pData->totalRows == 0) {
1,627✔
6362
    pData->minRows = 0;
1,625✔
6363
  }
6364

6365
  int32_t row = 0;
1,627✔
6366
  char    st[256] = {0};
1,627✔
6367
  double  averageSize = 0;
1,627✔
6368
  if (pData->numOfBlocks != 0) {
1,627✔
6369
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
2✔
6370
  }
6371
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,627✔
6372
  double   compRatio = 0;
1,627✔
6373
  if (totalRawSize != 0) {
1,627✔
6374
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
2✔
6375
  }
6376

6377
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,254✔
6378
                        "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6379
                        pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,627✔
6380

6381
  varDataSetLen(st, len);
1,627✔
6382
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6383
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6384
    return code;
×
6385
  }
6386

6387
  int64_t avgRows = 0;
1,627✔
6388
  if (pData->numOfBlocks > 0) {
1,627✔
6389
    avgRows = pData->totalRows / pData->numOfBlocks;
2✔
6390
  }
6391

6392
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]",
1,627✔
6393
                pData->totalRows, pData->minRows, pData->maxRows, avgRows);
6394
  varDataSetLen(st, len);
1,627✔
6395
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6396
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6397
    return code;
×
6398
  }
6399

6400
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%d] Stt_Rows=[%d] ", pData->numOfInmemRows, pData->numOfSttRows);
1,627✔
6401
  varDataSetLen(st, len);
1,627✔
6402
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6403
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6404
    return code;
×
6405
  }
6406

6407
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables,
3,254✔
6408
                pData->numOfFiles, pData->numOfVgroups);
1,627✔
6409

6410
  varDataSetLen(st, len);
1,627✔
6411
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6412
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6413
    return code;
×
6414
  }
6415

6416
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,627✔
6417
                "--------------------------------------------------------------------------------");
6418
  varDataSetLen(st, len);
1,627✔
6419
  code = colDataSetVal(pColInfo, row++, st, false);
1,627✔
6420
  if (TSDB_CODE_SUCCESS != code) {
1,627!
6421
    return code;
×
6422
  }
6423

6424
  int32_t maxVal = 0;
1,627✔
6425
  int32_t minVal = INT32_MAX;
1,627✔
6426
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,167✔
6427
    if (maxVal < pData->blockRowsHisto[i]) {
32,540✔
6428
      maxVal = pData->blockRowsHisto[i];
3✔
6429
    }
6430

6431
    if (minVal > pData->blockRowsHisto[i]) {
32,540✔
6432
      minVal = pData->blockRowsHisto[i];
1,628✔
6433
    }
6434
  }
6435

6436
  // maximum number of step is 80
6437
  double factor = pData->numOfBlocks / 80.0;
1,627✔
6438

6439
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,627✔
6440
  int32_t bucketRange = ceil(((double) (pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,627✔
6441

6442
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,167✔
6443
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,540✔
6444

6445
    int32_t num = 0;
32,540✔
6446
    if (pData->blockRowsHisto[i] > 0) {
32,540✔
6447
      num = (pData->blockRowsHisto[i]) / factor;
3✔
6448
    }
6449

6450
    for (int32_t j = 0; j < num; ++j) {
32,699✔
6451
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
159✔
6452
      len += x;
159✔
6453
    }
6454

6455
    if (pData->blockRowsHisto[i] > 0) {
32,540✔
6456
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
3✔
6457
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)", pData->blockRowsHisto[i], v, '%');
3✔
6458
    }
6459

6460
    varDataSetLen(st, len);
32,540✔
6461
    code = colDataSetVal(pColInfo, row++, st, false);
32,540✔
6462
    if (TSDB_CODE_SUCCESS != code) {
32,540!
6463
      return code;
×
6464
    }
6465
  }
6466

6467
  return TSDB_CODE_SUCCESS;
1,627✔
6468
}
6469

6470
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,300✔
6471
  pEnv->calcMemSize = sizeof(SDerivInfo);
31,300✔
6472
  return true;
31,300✔
6473
}
6474

6475
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
63,692✔
6476
  if (pResInfo->initialized) {
63,692✔
6477
    return TSDB_CODE_SUCCESS;
32,262✔
6478
  }
6479
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,430!
6480
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6481
  }
6482

6483
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,430✔
6484

6485
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
31,430✔
6486
  pDerivInfo->prevTs = -1;
31,430✔
6487
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
31,430✔
6488
  pDerivInfo->valueSet = false;
31,430✔
6489
  return TSDB_CODE_SUCCESS;
31,430✔
6490
}
6491

6492
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
32,392✔
6493
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,392✔
6494
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
32,392✔
6495

6496
  SInputColumnInfoData* pInput = &pCtx->input;
32,392✔
6497
  SColumnInfoData*      pInputCol = pInput->pData[0];
32,392✔
6498

6499
  int32_t          numOfElems = 0;
32,392✔
6500
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
32,392✔
6501
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
32,392✔
6502
  int32_t          code = TSDB_CODE_SUCCESS;
32,392✔
6503

6504
  funcInputUpdate(pCtx);
32,392✔
6505

6506
  double v = 0;
32,392✔
6507
  if (pCtx->order == TSDB_ORDER_ASC) {
32,392✔
6508
    SFuncInputRow row = {0};
29,058✔
6509
    bool result = false;
29,058✔
6510
    while (1) {
3,544,718✔
6511
      code = funcInputGetNextRow(pCtx, &row, &result);
3,573,776✔
6512
      if (TSDB_CODE_SUCCESS != code) {
3,573,776!
6513
        return code;
×
6514
      }
6515
      if (!result) {
3,573,776✔
6516
        break;
29,058✔
6517
      }
6518
      if (row.isDataNull) {
3,544,718✔
6519
        continue;
35,138✔
6520
      }
6521

6522
      char* d = row.pData;
3,509,580✔
6523
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
3,509,580!
6524

6525
      int32_t pos = pCtx->offset + numOfElems;
3,509,580✔
6526
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
3,509,580✔
6527
        pDerivInfo->valueSet = true;
27,724✔
6528
      } else {
6529
        if (row.ts == pDerivInfo->prevTs) {
3,481,856!
6530
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6531
        }
6532
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
3,481,856✔
6533
        if (pDerivInfo->ignoreNegative && r < 0) {
3,481,856✔
6534
        } else {
6535
          if (isinf(r) || isnan(r)) {
2,013,540!
6536
            colDataSetNULL(pOutput, pos);
×
6537
          } else {
6538
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
2,013,540✔
6539
            if (code != TSDB_CODE_SUCCESS) {
2,013,540!
6540
              return code;
×
6541
            }
6542
          }
6543

6544
          if (pTsOutput != NULL) {
2,013,540!
6545
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6546
          }
6547

6548
          // handle selectivity
6549
          if (pCtx->subsidiaries.num > 0) {
2,013,540✔
6550
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,516,030✔
6551
            if (code != TSDB_CODE_SUCCESS) {
1,516,030!
6552
              return code;
×
6553
            }
6554
          }
6555

6556
          numOfElems++;
2,013,540✔
6557
        }
6558
      }
6559

6560
      pDerivInfo->prevValue = v;
3,509,580✔
6561
      pDerivInfo->prevTs = row.ts;
3,509,580✔
6562
    }
6563
  } else {
6564
    SFuncInputRow row = {0};
3,334✔
6565
    bool          result = false;
3,334✔
6566
    while (1) {
331,886✔
6567
      code = funcInputGetNextRow(pCtx, &row, &result);
335,220✔
6568
      if (TSDB_CODE_SUCCESS != code) {
335,220!
6569
        return code;
×
6570
      }
6571
      if (!result) {
335,220✔
6572
        break;
3,334✔
6573
      }
6574
      if (row.isDataNull) {
331,886✔
6575
        continue;
86✔
6576
      }
6577

6578
      char* d = row.pData;
331,800✔
6579
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
331,800!
6580

6581
      int32_t pos = pCtx->offset + numOfElems;
331,800✔
6582
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
331,800✔
6583
        pDerivInfo->valueSet = true;
3,318✔
6584
      } else {
6585
        if (row.ts == pDerivInfo->prevTs) {
328,482!
6586
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6587
        }
6588
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
328,482✔
6589
        if (pDerivInfo->ignoreNegative && r < 0) {
328,482✔
6590
        } else {
6591
          if (isinf(r) || isnan(r)) {
254,382!
6592
            colDataSetNULL(pOutput, pos);
×
6593
          } else {
6594
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
254,382✔
6595
            if (code != TSDB_CODE_SUCCESS) {
254,382!
6596
              return code;
×
6597
            }
6598
          }
6599

6600
          if (pTsOutput != NULL) {
254,382!
6601
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6602
          }
6603

6604
          // handle selectivity
6605
          if (pCtx->subsidiaries.num > 0) {
254,382✔
6606
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
77,142✔
6607
            if (code != TSDB_CODE_SUCCESS) {
77,142!
6608
              return code;
×
6609
            }
6610
          }
6611
          numOfElems++;
254,382✔
6612
        }
6613
      }
6614

6615
      pDerivInfo->prevValue = v;
331,800✔
6616
      pDerivInfo->prevTs = row.ts;
331,800✔
6617
    }
6618
  }
6619

6620
  pResInfo->numOfRes = numOfElems;
32,392✔
6621

6622
  return TSDB_CODE_SUCCESS;
32,392✔
6623
}
6624

6625
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
1,666,450✔
6626

6627
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
125,238✔
6628
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
125,238✔
6629
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
125,238✔
6630
  return true;
125,441✔
6631
}
6632

6633
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
8,137,546✔
6634
  if (pResInfo->initialized) {
8,137,546!
6635
    return TSDB_CODE_SUCCESS;
×
6636
  }
6637
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
8,137,546!
6638
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6639
  }
6640

6641
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,137,608✔
6642

6643
  pInfo->firstKey = INT64_MIN;
8,137,608✔
6644
  pInfo->lastKey = INT64_MIN;
8,137,608✔
6645
  pInfo->firstValue = (double)INT64_MIN;
8,137,608✔
6646
  pInfo->lastValue = (double)INT64_MIN;
8,137,608✔
6647

6648
  pInfo->hasResult = 0;
8,137,608✔
6649
  return TSDB_CODE_SUCCESS;
8,137,608✔
6650
}
6651

6652
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
25,930,354✔
6653
  if (isFirst) {
25,930,354✔
6654
    pRateInfo->firstValue = v;
9,674,208✔
6655
    pRateInfo->firstKey = ts;
9,674,208✔
6656
    if (pRateInfo->firstPk) {
9,674,208✔
6657
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
35!
6658
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6659
    }
6660
  } else {
6661
    pRateInfo->lastValue = v;
16,256,146✔
6662
    pRateInfo->lastKey = ts;
16,256,146✔
6663
    if (pRateInfo->lastPk) {
16,256,146✔
6664
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
52!
6665
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6666
    }
6667
  }
6668
}
25,930,354✔
6669

6670
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
9,701,434✔
6671
  if (pCtx->hasPrimaryKey) {
9,701,434✔
6672
    if (!isMerge) {
19✔
6673
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6674
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6675
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6676
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6677
    } else {
6678
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6679
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6680
    }
6681
  } else {
6682
    pRateInfo->firstPk = NULL;
9,701,415✔
6683
    pRateInfo->lastPk = NULL;
9,701,415✔
6684
  }  
6685
}
9,701,434✔
6686

6687
int32_t irateFunction(SqlFunctionCtx* pCtx) {
6,619,779✔
6688
  int32_t              code = TSDB_CODE_SUCCESS;
6,619,779✔
6689
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,619,779✔
6690
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,619,779✔
6691

6692
  SInputColumnInfoData* pInput = &pCtx->input;
6,619,779✔
6693
  SColumnInfoData*      pInputCol = pInput->pData[0];
6,619,779✔
6694

6695
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6,619,779✔
6696

6697
  funcInputUpdate(pCtx);
6,619,779✔
6698
  
6699
  initializeRateInfo(pCtx, pRateInfo, false);
6,619,816✔
6700

6701
  int32_t numOfElems = 0;
6,619,824✔
6702
  int32_t type = pInputCol->info.type;
6,619,824✔
6703
  SFuncInputRow row = {0};
6,619,824✔
6704
  bool          result = false;
6,619,824✔
6705
  while (1)  {
14,963,334✔
6706
    code = funcInputGetNextRow(pCtx, &row, &result);
21,583,158✔
6707
    if (TSDB_CODE_SUCCESS != code) {
21,582,383!
6708
      return code;
×
6709
    }
6710
    if (!result) {
21,582,383✔
6711
      break;
6,619,652✔
6712
    }
6713
    if (row.isDataNull) {
14,962,731✔
6714
      continue;
111,047✔
6715
    }
6716

6717
    char*  data = row.pData;
14,851,684✔
6718
    double v = 0;
14,851,684✔
6719
    GET_TYPED_DATA(v, double, type, data);
14,851,684!
6720

6721
    if (INT64_MIN == pRateInfo->lastKey) {
14,851,684✔
6722
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
6,582,832✔
6723
      pRateInfo->hasResult = 1;
6,582,806✔
6724
      continue;
6,582,806✔
6725
    }
6726

6727
    if (row.ts > pRateInfo->lastKey) {
8,268,852✔
6728
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
8,132,892!
6729
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
8,132,892✔
6730
      }
6731
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
8,132,886✔
6732
      continue;
8,132,882✔
6733
    } else if (row.ts == pRateInfo->lastKey) {
135,960!
6734
        return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6735
    }
6736
    
6737

6738
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
135,960!
6739
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);    
×
6740
    } else if (row.ts == pRateInfo->firstKey) {
136,315!
6741
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6742
    }
6743
  }
6744

6745
  numOfElems++;
6,619,652✔
6746
  
6747
  SET_VAL(pResInfo, numOfElems, 1);
6,619,652!
6748
  return TSDB_CODE_SUCCESS;
6,619,652✔
6749
}
6750

6751
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
6,593,283✔
6752
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
6,593,283✔
6753
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
603,803!
6754
    return 0.0;
5,989,480✔
6755
  }
6756

6757
  double diff = 0;
603,803✔
6758
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6759
  // value between two values.
6760
  diff = pRateInfo->lastValue;
603,803✔
6761
  if (diff >= pRateInfo->firstValue) {
603,803✔
6762
    diff -= pRateInfo->firstValue;
302,354✔
6763
  }
6764

6765
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
603,803✔
6766
  if (duration == 0) {
603,803!
6767
    return 0;
×
6768
  }
6769

6770
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
603,803!
6771
}
6772

6773
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
290✔
6774
  if (inputKey > pOutput->lastKey) {
290✔
6775
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
117✔
6776
    if (isFirstKey) {
117✔
6777
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
51✔
6778
    } else {
6779
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
66✔
6780
    }
6781
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
173!
6782
    if (isFirstKey) {
30✔
6783
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
15✔
6784
    } else {
6785
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
15✔
6786
    }
6787
  } else {
6788
    // inputKey < pOutput->firstKey
6789
  }
6790
}
290✔
6791

6792
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,540,725✔
6793
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,540,725✔
6794
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,540,725✔
6795
}
1,540,725✔
6796

6797
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,540,870✔
6798
  if ((pInput->firstKey != INT64_MIN && (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
1,540,870!
6799
      (pInput->lastKey != INT64_MIN && (pInput->lastKey  == pOutput->firstKey || pInput->lastKey  == pOutput->lastKey))) {
1,540,870!
6800
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6801
  }
6802

6803
  if (pOutput->hasResult == 0) {
1,540,870✔
6804
    irateCopyInfo(pInput, pOutput);
1,540,725✔
6805
    pOutput->hasResult = pInput->hasResult;
1,540,725✔
6806
    return TSDB_CODE_SUCCESS;
1,540,725✔
6807
  }
6808

6809
  if (pInput->firstKey != INT64_MIN) {
145!
6810
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
145✔
6811
  }
6812

6813
  if (pInput->lastKey != INT64_MIN) {
145!
6814
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
145✔
6815
  }
6816

6817
  pOutput->hasResult = pInput->hasResult;
145✔
6818
  return TSDB_CODE_SUCCESS;
145✔
6819
}
6820

6821
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
1,540,882✔
6822
  SInputColumnInfoData* pInput = &pCtx->input;
1,540,882✔
6823
  SColumnInfoData*      pCol = pInput->pData[0];
1,540,882✔
6824
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,540,882!
6825
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6826
  }
6827

6828
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,540,882✔
6829
  initializeRateInfo(pCtx, pInfo, true);
1,540,882✔
6830

6831
  int32_t start = pInput->startRowIndex;
1,540,882✔
6832
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,081,764✔
6833
    char*        data = colDataGetData(pCol, i);
1,540,882!
6834
    SRateInfo*   pInputInfo = (SRateInfo*)varDataVal(data);
1,540,882✔
6835
    initializeRateInfo(pCtx, pInfo, true);
1,540,882✔
6836
    if (pInputInfo->hasResult) {
1,540,882✔
6837
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
1,540,870✔
6838
      if (code != TSDB_CODE_SUCCESS) {
1,540,870!
6839
        return code;
×
6840
      }
6841
    }
6842
  }
6843

6844
  if (pInfo->hasResult) {
1,540,882✔
6845
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,540,870✔
6846
  }
6847

6848
  return TSDB_CODE_SUCCESS;
1,540,882✔
6849
}
6850

6851
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,540,881✔
6852
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,540,881✔
6853
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,540,881✔
6854
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
1,540,881✔
6855
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,540,881✔
6856

6857
  if (NULL == res) {
1,540,882!
6858
    return terrno;
×
6859
  }
6860
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,540,882✔
6861
  varDataSetLen(res, resultBytes);
1,540,882✔
6862

6863
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,540,882✔
6864
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,540,882✔
6865
  if (NULL == pCol) {
1,540,882!
6866
      taosMemoryFree(res);
×
6867
      return TSDB_CODE_OUT_OF_RANGE;
×
6868
  }
6869

6870
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,540,882✔
6871

6872
  taosMemoryFree(res);
1,540,882✔
6873
  return code;
1,540,882✔
6874
}
6875

6876
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,593,599✔
6877
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
6,593,599✔
6878
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,593,599✔
6879
  if (NULL == pCol) {
6,593,275!
6880
    return TSDB_CODE_OUT_OF_RANGE;
×
6881
  }
6882

6883
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,593,275✔
6884
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
6,593,275✔
6885

6886
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,593,275✔
6887
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
6,593,275!
6888
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
6,593,292✔
6889

6890
  return code;
6,593,173✔
6891
}
6892

6893
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
107,998,569✔
6894
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
107,998,569✔
6895
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
107,998,569✔
6896

6897
  SInputColumnInfoData* pInput = &pCtx->input;
107,998,569✔
6898
  SColumnInfoData*      pInputCol = pInput->pData[0];
107,998,569✔
6899

6900
  int32_t startIndex = pInput->startRowIndex;
107,998,569✔
6901

6902
  // escape rest of data blocks to avoid first entry to be overwritten.
6903
  if (pInfo->hasResult) {
107,998,569✔
6904
    goto _group_value_over;
11,679,442✔
6905
  }
6906

6907
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
192,205,416✔
6908
    pInfo->isNull = true;
2,666,769✔
6909
    pInfo->hasResult = true;
2,666,769✔
6910
    goto _group_value_over;
2,666,769✔
6911
  }
6912

6913
  char* data = colDataGetData(pInputCol, startIndex);
93,652,358!
6914
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
93,652,358!
6915
    (void)memcpy(pInfo->data, data,
73,410,208✔
6916
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
73,410,208✔
6917
  } else {
6918
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
20,242,150✔
6919
  }
6920
  pInfo->hasResult = true;
93,652,358✔
6921

6922
_group_value_over:
107,998,569✔
6923

6924
  SET_VAL(pResInfo, 1, 1);
107,998,569✔
6925
  return TSDB_CODE_SUCCESS;
107,998,569✔
6926
}
6927

6928
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) {
106,974,727✔
6929
  return groupConstValueFunction(pCtx);
106,974,727✔
6930
}
6931

6932
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
94,322,737✔
6933
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
94,322,737✔
6934
  int32_t          code = TSDB_CODE_SUCCESS;
94,322,737✔
6935
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
94,322,737✔
6936
  if (NULL == pCol) {
94,204,034!
6937
    return TSDB_CODE_OUT_OF_RANGE;
×
6938
  }
6939

6940
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
94,204,034✔
6941

6942
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
94,204,034✔
6943

6944
  if (pInfo->hasResult) {
94,204,034!
6945
    int32_t currentRow = pBlock->info.rows;
94,279,510✔
6946
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
189,506,721✔
6947
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
94,311,233✔
6948
      if (TSDB_CODE_SUCCESS != code) {
95,227,211!
6949
        return code;
×
6950
      }
6951
    }
6952
  } else {
6953
    pResInfo->numOfRes = 0;
×
6954
  }
6955

6956
  return code;
95,120,012✔
6957
}
6958

6959
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock){
94,059,885✔
6960
  return groupConstValueFinalize(pCtx, pBlock);
94,059,885✔
6961
}
6962

6963
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6964
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6965
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6966

6967
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6968
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6969

6970
  // escape rest of data blocks to avoid first entry to be overwritten.
6971
  if (pDBuf->hasResult) {
×
6972
    goto _group_key_over;
×
6973
  }
6974

6975
  if (pSBuf->isNull) {
×
6976
    pDBuf->isNull = true;
×
6977
    pDBuf->hasResult = true;
×
6978
    goto _group_key_over;
×
6979
  }
6980

6981
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
6982
    (void)memcpy(pDBuf->data, pSBuf->data,
×
6983
           (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data) : varDataTLen(pSBuf->data));
×
6984
  } else {
6985
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
6986
  }
6987

6988
  pDBuf->hasResult = true;
×
6989

6990
_group_key_over:
×
6991

6992
  SET_VAL(pDResInfo, 1, 1);
×
6993
  return TSDB_CODE_SUCCESS;
×
6994
}
6995

6996
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
7,785✔
6997
  int32_t numOfElems = 0;
7,785✔
6998

6999
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,785✔
7000
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,785✔
7001

7002
  SInputColumnInfoData* pInput = &pCtx->input;
7,785✔
7003
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,785✔
7004

7005
  int32_t bytes = pInputCol->info.bytes;
7,785✔
7006
  pInfo->bytes = bytes;
7,785✔
7007

7008
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
7,785✔
7009
  pInfo->pkType = -1;
7,785✔
7010
  __compar_fn_t  pkCompareFn = NULL;
7,785✔
7011
  if (pCtx->hasPrimaryKey) {
7,785✔
7012
    pInfo->pkType = pkCol->info.type;
2,816✔
7013
    pInfo->pkBytes = pkCol->info.bytes;
2,816✔
7014
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
2,816✔
7015
  }
7016

7017
  // TODO it traverse the different way.
7018
  // last_row function does not ignore the null value
7019
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
15,585✔
7020
    numOfElems++;
7,797✔
7021

7022
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
7,797✔
7023
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
7,797!
7024

7025
    TSKEY cts = getRowPTs(pInput->pPTS, i);
7,797!
7026
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
7,797✔
7027
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
5,637✔
7028
      if (code != TSDB_CODE_SUCCESS) {
5,639!
7029
        return code;
×
7030
      }
7031
      pResInfo->numOfRes = 1;
5,639✔
7032
    }
7033
  }
7034

7035
  SET_VAL(pResInfo, numOfElems, 1);
7,788!
7036
  return TSDB_CODE_SUCCESS;
7,788✔
7037
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc