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

taosdata / TDengine / #3532

20 Nov 2024 07:11AM UTC coverage: 60.78% (+0.6%) from 60.213%
#3532

push

travis-ci

web-flow
Merge pull request #28823 from taosdata/fix/3.0/TD-32587

fix:[TD-32587]fix stmt segmentation fault

119943 of 252352 branches covered (47.53%)

Branch coverage included in aggregate %.

1 of 4 new or added lines in 1 file covered. (25.0%)

463 existing lines in 99 files now uncovered.

200682 of 275165 relevant lines covered (72.93%)

15642683.31 hits per line

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

73.98
/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){
41,361,402✔
32
  return (ignoreOption & 0x1) == 0x1;
41,361,402✔
33
}
34
bool ignoreNull(int8_t ignoreOption){
422,661✔
35
  return (ignoreOption & 0x2) == 0x2;
422,661✔
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,483,218✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
19,483,218✔
199

200
  if (!pCtx->bInputFinished) {
19,483,218!
201
    pIter->pInput = &pCtx->input;
19,483,257✔
202
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
19,483,257✔
203
    pIter->pDataCol = pIter->pInput->pData[0];
19,483,257✔
204
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
19,483,257✔
205
    pIter->rowIndex = pIter->pInput->startRowIndex;
19,483,257✔
206
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
19,483,257✔
207
    pIter->pSrcBlock = pCtx->pSrcBlock;
19,483,257✔
208
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
19,483,257✔
209
      pIter->hasGroupId = true;
228,018✔
210
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
228,018✔
211
      pIter->hasPrev = false;
228,018✔
212
    }
213
  } else {
214
    pIter->finalRow = true;
×
215
  }
216
}
19,483,218✔
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) {
29,204✔
332
  int32_t idx = rowIndex + 1;
29,204✔
333
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
406,401!
334
    ++idx;
377,197✔
335
  }
336
  pIter->rowIndex = idx;
29,204✔
337
}
29,204✔
338

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

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

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

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

385
bool funcInputGetNextRowNoPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) {
111,706,471✔
386
  if (pIter->rowIndex <= pIter->inputEndIndex) {
111,706,471✔
387
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
92,216,757✔
388
    ++pIter->rowIndex;
92,217,706✔
389
    return true;    
92,217,706✔
390
  } else {
391
    return false;    
19,489,714✔
392
  }
393
}
394

395
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool *res) {
111,743,039✔
396
  SFuncInputRowIter* pIter = &pCtx->rowIter;
111,743,039✔
397
  if (pCtx->hasPrimaryKey) {
111,743,039✔
398
    if (pCtx->order == TSDB_ORDER_ASC) {
34,690!
399
      *res = funcInputGetNextRowAscPk(pIter, pRow);
34,690✔
400
      return TSDB_CODE_SUCCESS;
34,690✔
401
    } else {
402
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
403
    }
404
  } else {
405
    *res = funcInputGetNextRowNoPk(pIter, pRow);
111,708,349✔
406
    return TSDB_CODE_SUCCESS;
111,707,517✔
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,036,930✔
414
  if (pCtx->subsidiaries.num <= 0) {
33,036,930!
415
    return TSDB_CODE_SUCCESS;
×
416
  }
417

418
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
91,779,740✔
419
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
58,742,810✔
420

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

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

430
    char* pData = colDataGetData(pSrcCol, rowIndex);
58,742,810!
431

432
    // append to dest col
433
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
58,742,810✔
434

435
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
58,742,810✔
436
    if (NULL == pDstCol) {
58,742,810!
437
      return TSDB_CODE_OUT_OF_RANGE;
×
438
    }
439
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
117,485,620✔
440
      colDataSetNULL(pDstCol, pos);
2,580,095✔
441
    } else {
442
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
56,162,715✔
443
      if (TSDB_CODE_SUCCESS != code) {
56,162,715!
444
        return code;
×
445
      }
446
    }
447
  }
448
  return TSDB_CODE_SUCCESS;
33,036,930✔
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) {
710,938,470✔
456
  if (pResultInfo->initialized) {
710,938,470✔
457
    return TSDB_CODE_SUCCESS;  // already initialized
165,625✔
458
  }
459

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

464
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
710,772,845✔
465
  return TSDB_CODE_SUCCESS;
710,772,845✔
466
}
467

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

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

481
  return code;
202,801,878✔
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) {
208,370✔
515
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
208,370✔
516
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
208,461✔
517
    return FUNC_DATA_REQUIRED_NOT_LOAD;
152,874✔
518
  }
519
  return FUNC_DATA_REQUIRED_SMA_LOAD;
55,587✔
520
}
521

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

527
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
116,165,296✔
528
  int64_t numOfElem = 0;
116,165,296✔
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;
116,165,296✔
536
  SColumnInfoData*      pInputCol = pInput->pData[0];
116,165,296✔
537
  if(1 == pInput->numOfRows && pInput->blankFill) {
116,165,296✔
538
    return 0;
456,572✔
539
  }
540
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
115,708,724!
541
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
2,663✔
542
  } else {
543
    if (pInputCol->hasNull) {
115,706,061✔
544
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
259,590,229✔
545
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
461,619,914!
546
          continue;
4,318,652✔
547
        }
548
        numOfElem += 1;
226,491,305✔
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;
86,925,789✔
554
    }
555
  }
556
  return numOfElem;
115,708,724✔
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) {
116,080,235✔
564
  int64_t numOfElem = 0;
116,080,235✔
565

566
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
116,080,235✔
567
  SInputColumnInfoData* pInput = &pCtx->input;
116,080,235✔
568

569
  int32_t type = pInput->pData[0]->info.type;
116,080,235✔
570

571
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
116,080,235✔
572
  if (IS_NULL_TYPE(type)) {
116,080,235✔
573
    // select count(NULL) returns 0
574
    numOfElem = 1;
18,115✔
575
    *((int64_t*)buf) += 0;
18,115✔
576
  } else {
577
    numOfElem = getNumOfElems(pCtx);
116,062,120✔
578
    *((int64_t*)buf) += numOfElem;
115,851,876✔
579
  }
580

581
  if (tsCountAlwaysReturnValue) {
115,869,991!
582
    pResInfo->numOfRes = 1;
115,958,613✔
583
  } else {
584
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
585
  }
586

587
  return TSDB_CODE_SUCCESS;
115,869,991✔
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,026,956✔
616
  int32_t numOfElem = 0;
93,026,956✔
617

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

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

626
  if (IS_NULL_TYPE(type)) {
93,026,956✔
627
    numOfElem = 0;
267✔
628
    goto _sum_over;
267✔
629
  }
630

631
  if (pInput->colDataSMAIsSet) {
93,026,689✔
632
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
2,678✔
633

634
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
2,678!
635
      pSumRes->isum += pAgg->sum;
2,678✔
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,024,011✔
643

644
    int32_t start = pInput->startRowIndex;
93,024,011✔
645
    int32_t numOfRows = pInput->numOfRows;
93,024,011✔
646

647
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
93,024,011✔
648
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
92,826,270!
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
1,722,727✔
650
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
92,447,104✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
545,804✔
652
      } else if (type == TSDB_DATA_TYPE_INT) {
92,400,605✔
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
417,342,393✔
654
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
21,431,429✔
655
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
79,530,300✔
656
      }
657
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
197,741!
658
      if (type == TSDB_DATA_TYPE_UTINYINT) {
797✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
660
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
758✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
662
      } else if (type == TSDB_DATA_TYPE_UINT) {
718✔
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
133,570!
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
448!
665
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
134,332✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
196,944✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
2,582,255✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
97,810✔
670
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
1,463,162✔
671
    }
672
  }
673

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

679
_sum_over:
93,399,650✔
680
  if (numOfElem == 0) {
93,026,956✔
681
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
98,059✔
682
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,750✔
683
      numOfElem = 1;
36✔
684
    }
685
  }
686
  // data in the check operation are all null, not output
687
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
93,026,956✔
688
  return TSDB_CODE_SUCCESS;
93,026,956✔
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) {
250,146✔
772
  pEnv->calcMemSize = sizeof(SSumRes);
250,146✔
773
  return true;
250,146✔
774
}
775

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

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

788
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
65,967,802✔
789
  buf->assign = false;
65,967,802✔
790
  buf->tuplePos.pageId = -1;
65,967,802✔
791

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

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

803
int32_t minFunction(SqlFunctionCtx* pCtx) {
33,656,874✔
804
  int32_t numOfElems = 0;
33,656,874✔
805
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
33,656,874✔
806
  if (code != TSDB_CODE_SUCCESS) {
33,723,956!
807
    return code;
×
808
  }
809
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
33,723,956✔
810
  return TSDB_CODE_SUCCESS;
33,723,956✔
811
}
812

813
int32_t maxFunction(SqlFunctionCtx* pCtx) {
40,106,523✔
814
  int32_t numOfElems = 0;
40,106,523✔
815
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
40,106,523✔
816
  if (code != TSDB_CODE_SUCCESS) {
40,180,636!
817
    return code;
×
818
  }
819
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
40,180,636✔
820
  return TSDB_CODE_SUCCESS;
40,180,636✔
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) {
63,281,008✔
828
  int32_t code = TSDB_CODE_SUCCESS;
63,281,008✔
829

830
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
63,281,008✔
831
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
63,281,008✔
832

833
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
63,281,008✔
834
  int32_t currentRow = pBlock->info.rows;
63,281,008✔
835

836
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
63,281,008✔
837
  if (NULL == pCol) {
63,283,121!
838
    return TSDB_CODE_OUT_OF_RANGE;
×
839
  }
840
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
63,283,121✔
841

842
  // NOTE: do nothing change it, for performance issue
843
  if (!pEntryInfo->isNullRes) {
63,283,121✔
844
    switch (pCol->info.type) {
57,055,996!
845
      case TSDB_DATA_TYPE_UBIGINT:
26,926,662✔
846
      case TSDB_DATA_TYPE_BIGINT:
847
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
26,926,662✔
848
        break;
26,926,662✔
849
      case TSDB_DATA_TYPE_UINT:
19,959,659✔
850
      case TSDB_DATA_TYPE_INT:
851
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
19,959,659✔
852
        break;
19,959,659✔
853
      case TSDB_DATA_TYPE_USMALLINT:
213,532✔
854
      case TSDB_DATA_TYPE_SMALLINT:
855
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
213,532✔
856
        break;
213,532✔
857
      case TSDB_DATA_TYPE_BOOL:
194,868✔
858
      case TSDB_DATA_TYPE_UTINYINT:
859
      case TSDB_DATA_TYPE_TINYINT:
860
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
194,868✔
861
        break;
194,868✔
862
      case TSDB_DATA_TYPE_DOUBLE:
218,923✔
863
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
218,923✔
864
        break;
218,923✔
865
      case TSDB_DATA_TYPE_FLOAT: {
3,921✔
866
        float v = GET_FLOAT_VAL(&pRes->v);
3,921✔
867
        colDataSetFloat(pCol, currentRow, &v);
3,921✔
868
        break;
3,921✔
869
      }
870
      case TSDB_DATA_TYPE_VARBINARY:
9,568,191✔
871
      case TSDB_DATA_TYPE_VARCHAR:
872
      case TSDB_DATA_TYPE_NCHAR: {
873
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
9,568,191✔
874
        if (TSDB_CODE_SUCCESS != code) {
9,566,333!
875
          return code;
×
876
        }
877
        break;
9,566,333✔
878
      }
879
    }
880
  } else {
881
    colDataSetNULL(pCol, currentRow);
6,227,125!
882
  }
883

884
  taosMemoryFreeClear(pRes->str);
63,281,263✔
885
  if (pCtx->subsidiaries.num > 0) {
63,303,751✔
886
    if (pEntryInfo->numOfRes > 0) {
18,305,095✔
887
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
18,302,084✔
888
    } else {
889
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
3,011✔
890
    }
891
  }
892

893
  return code;
63,306,566✔
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) {
249,975,679✔
915
  if (pCtx->subsidiaries.num <= 0) {
249,975,679✔
916
    return TSDB_CODE_SUCCESS;
107,276,224✔
917
  }
918

919
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
142,699,455!
920
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
102,850!
921
    int32_t     numOfCols = pCtx->subsidiaries.num;
142,711,094✔
922
    char* p = NULL;
142,711,094✔
923
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
142,711,094✔
924
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
142,966,159!
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;
142,968,791✔
931
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
142,968,791✔
932

933
    // todo set the offset value to optimize the performance.
934
    for (int32_t j = 0; j < numOfCols; ++j) {
285,856,702✔
935
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
143,008,818✔
936
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
143,008,818✔
937

938
      // group_key function has its own process function
939
      // do not process there
940
      if (fmIsGroupKeyFunc(pc->functionId)) {
143,008,818✔
941
        continue;
37,418✔
942
      }
943

944
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
142,977,306✔
945
      if (NULL == pDstCol) {
142,923,593!
946
        return TSDB_CODE_OUT_OF_RANGE;
×
947
      }
948
      if (nullList[j]) {
142,923,593✔
949
        colDataSetNULL(pDstCol, rowIndex);
339!
950
      } else {
951
        code = colDataSetVal(pDstCol, rowIndex, pStart, false);
142,923,254✔
952
        if (TSDB_CODE_SUCCESS != code) {
142,850,154!
953
          return code;
×
954
        }
955
      }
956
      pStart += pDstCol->info.bytes;
142,850,493✔
957
    }
958
  }
959

960
  return TSDB_CODE_SUCCESS;
142,836,245✔
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,320,580✔
966
  if (pCtx->subsidiaries.num <= 0) {
54,320,580!
967
    return TSDB_CODE_SUCCESS;
×
968
  }
969

970
  int32_t code = TSDB_CODE_SUCCESS;
54,320,580✔
971
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
108,642,851✔
972
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
54,323,551✔
973

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

978
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
54,323,551✔
979
    if (NULL == pSrcCol) {
54,322,758!
980
      return TSDB_CODE_OUT_OF_RANGE;
×
981
    }
982

983
    char* pData = colDataGetData(pSrcCol, rowIndex);
54,322,758!
984

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

988
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
54,322,758✔
989
    if (NULL == pDstCol) {
54,321,822!
990
      return TSDB_CODE_OUT_OF_RANGE;
×
991
    }
992

993
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
108,643,644✔
994
      colDataSetNULL(pDstCol, pos);
560✔
995
    } else {
996
      code = colDataSetVal(pDstCol, pos, pData, false);
54,321,262✔
997
      if (TSDB_CODE_SUCCESS != code) {
54,321,711!
998
        return code;
×
999
      }
1000
    }
1001
  }
1002
  return code;
54,319,300✔
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); }
728,504✔
1080

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

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

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

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

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

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

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

1112
  int32_t start = pInput->startRowIndex;
4,876,328✔
1113
  int32_t numOfRows = pInput->numOfRows;
4,876,328✔
1114

1115
  if (IS_NULL_TYPE(type)) {
4,876,328✔
1116
    numOfElem = 0;
55✔
1117
    goto _stddev_over;
55✔
1118
  }
1119

1120
  switch (type) {
4,876,273!
1121
    case TSDB_DATA_TYPE_TINYINT: {
1,908,615✔
1122
      int8_t* plist = (int8_t*)pCol->pData;
1,908,615✔
1123
      for (int32_t i = start; i < numOfRows + start; ++i) {
6,546,869✔
1124
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
4,638,254✔
1125
          continue;
236,995✔
1126
        }
1127

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

1134
      break;
1,908,615✔
1135
    }
1136

1137
    case TSDB_DATA_TYPE_SMALLINT: {
243,156✔
1138
      int16_t* plist = (int16_t*)pCol->pData;
243,156✔
1139
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
850,477✔
1140
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
607,321✔
1141
          continue;
113,090✔
1142
        }
1143

1144
        numOfElem += 1;
494,231✔
1145
        pStdRes->count += 1;
494,231✔
1146
        pStdRes->isum += plist[i];
494,231✔
1147
        pStdRes->quadraticISum += plist[i] * plist[i];
494,231✔
1148
      }
1149
      break;
243,156✔
1150
    }
1151

1152
    case TSDB_DATA_TYPE_INT: {
18,541✔
1153
      int32_t* plist = (int32_t*)pCol->pData;
18,541✔
1154
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,822,442✔
1155
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,803,901✔
1156
          continue;
19,168✔
1157
        }
1158

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

1165
      break;
18,541✔
1166
    }
1167

1168
    case TSDB_DATA_TYPE_BIGINT: {
2,647,738✔
1169
      int64_t* plist = (int64_t*)pCol->pData;
2,647,738✔
1170
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
8,595,536✔
1171
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
5,947,798✔
1172
          continue;
31,926✔
1173
        }
1174

1175
        numOfElem += 1;
5,915,872✔
1176
        pStdRes->count += 1;
5,915,872✔
1177
        pStdRes->isum += plist[i];
5,915,872✔
1178
        pStdRes->quadraticISum += plist[i] * plist[i];
5,915,872✔
1179
      }
1180
      break;
2,647,738✔
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: {
17,454✔
1246
      float* plist = (float*)pCol->pData;
17,454✔
1247
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,718,501✔
1248
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,701,047✔
1249
          continue;
95,566✔
1250
        }
1251

1252
        numOfElem += 1;
1,605,481✔
1253
        pStdRes->count += 1;
1,605,481✔
1254
        pStdRes->dsum += plist[i];
1,605,481✔
1255
        pStdRes->quadraticDSum += plist[i] * plist[i];
1,605,481✔
1256
      }
1257
      break;
17,454✔
1258
    }
1259

1260
    case TSDB_DATA_TYPE_DOUBLE: {
40,709✔
1261
      double* plist = (double*)pCol->pData;
40,709✔
1262
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,692,002✔
1263
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
2,651,293✔
1264
          continue;
734,427✔
1265
        }
1266

1267
        numOfElem += 1;
1,916,866✔
1268
        pStdRes->count += 1;
1,916,866✔
1269
        pStdRes->dsum += plist[i];
1,916,866✔
1270
        pStdRes->quadraticDSum += plist[i] * plist[i];
1,916,866✔
1271
      }
1272
      break;
40,709✔
1273
    }
1274

UNCOV
1275
    default:
×
UNCOV
1276
      break;
×
1277
  }
1278

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

1285
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
727,228✔
1286
  if (IS_NULL_TYPE(pInput->type)) {
727,228!
1287
    return;
×
1288
  }
1289
  pOutput->type = pInput->type;
727,228✔
1290
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
727,228!
1291
    pOutput->quadraticISum += pInput->quadraticISum;
726,894✔
1292
    pOutput->isum += pInput->isum;
726,894✔
1293
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
334!
1294
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1295
    pOutput->usum += pInput->usum;
1✔
1296
  } else {
1297
    pOutput->quadraticDSum += pInput->quadraticDSum;
333✔
1298
    pOutput->dsum += pInput->dsum;
333✔
1299
  }
1300

1301
  pOutput->count += pInput->count;
727,228✔
1302
}
1303

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

1308
  if (IS_NULL_TYPE(pCol->info.type)) {
727,153!
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) {
727,153!
1314
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1315
  }
1316

1317
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
727,153✔
1318

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

1326
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
727,153✔
1327
  return TSDB_CODE_SUCCESS;
727,153✔
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,803,071✔
1398
  SInputColumnInfoData* pInput = &pCtx->input;
4,803,071✔
1399
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,803,071✔
1400
  int32_t               type = pStddevRes->type;
4,803,071✔
1401
  double                avg;
1402

1403
  if (pStddevRes->count == 0) {
4,803,071✔
1404
    GET_RES_INFO(pCtx)->numOfRes = 0;
57,763✔
1405
    return functionFinalize(pCtx, pBlock);
57,763✔
1406
  }
1407

1408
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,745,308!
1409
    avg = pStddevRes->isum / ((double)pStddevRes->count);
4,715,524✔
1410
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
4,715,524✔
1411
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
29,784!
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);
29,774✔
1416
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
29,774✔
1417
  }
1418

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

1424
  return functionFinalize(pCtx, pBlock);
4,745,308✔
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) {
727,130✔
1458
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
727,130✔
1459
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
727,130✔
1460
  int32_t              resultBytes = getStdInfoSize();
727,130✔
1461
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
727,130✔
1462

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

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

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

1478
  taosMemoryFree(res);
727,131✔
1479
  return code;
727,131✔
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) {
44,083✔
1498
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
44,083✔
1499
  return true;
44,083✔
1500
}
1501

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

1510
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,914,286✔
1511

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

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

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

1523
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,909,208✔
1524

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

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

1530
  int32_t start = pInput->startRowIndex;
6,909,208✔
1531
  int32_t numOfRows = pInput->numOfRows;
6,909,208✔
1532

1533
  switch (type) {
6,909,208!
1534
    case TSDB_DATA_TYPE_TINYINT: {
17,053✔
1535
      int8_t* plist = (int8_t*)pCol->pData;
17,053✔
1536
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
672,526✔
1537
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
655,473✔
1538
          continue;
435,313✔
1539
        }
1540
        numOfElem++;
220,160✔
1541
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
220,160✔
1542
      }
1543
      break;
17,053✔
1544
    }
1545
    case TSDB_DATA_TYPE_SMALLINT: {
6,856,253✔
1546
      int16_t* plist = (int16_t*)pCol->pData;
6,856,253✔
1547
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
22,692,713✔
1548
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
15,836,460✔
1549
          continue;
151,006✔
1550
        }
1551

1552
        numOfElem++;
15,685,454✔
1553
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
15,685,454✔
1554
      }
1555
      break;
6,856,253✔
1556
    }
1557

1558
    case TSDB_DATA_TYPE_INT: {
5,753✔
1559
      int32_t* plist = (int32_t*)pCol->pData;
5,753✔
1560
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
301,720✔
1561
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
295,967✔
1562
          continue;
2,613✔
1563
        }
1564

1565
        numOfElem++;
293,354✔
1566
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
293,354✔
1567
      }
1568
      break;
5,753✔
1569
    }
1570

1571
    case TSDB_DATA_TYPE_BIGINT: {
17,278✔
1572
      int64_t* plist = (int64_t*)pCol->pData;
17,278✔
1573
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,340,793✔
1574
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,323,515✔
1575
          continue;
3,260✔
1576
        }
1577

1578
        numOfElem++;
1,320,255✔
1579
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
1,320,255✔
1580
      }
1581
      break;
17,278✔
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: {
5,074✔
1635
      float* plist = (float*)pCol->pData;
5,074✔
1636
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
227,026✔
1637
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
221,952✔
1638
          continue;
138,792✔
1639
        }
1640

1641
        numOfElem++;
83,160✔
1642
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
83,160✔
1643
      }
1644
      break;
5,074✔
1645
    }
1646

1647
    case TSDB_DATA_TYPE_DOUBLE: {
7,180✔
1648
      double* plist = (double*)pCol->pData;
7,180✔
1649
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
99,540✔
1650
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
92,360✔
1651
          continue;
2,660✔
1652
        }
1653

1654
        numOfElem++;
89,700✔
1655
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
89,700✔
1656
      }
1657
      break;
7,180✔
1658
    }
1659
    case TSDB_DATA_TYPE_NULL: {
×
1660
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1661
      numOfElem = 1;
×
1662
      break;
×
1663
    }
1664

1665
    default:
1✔
1666
      break;
1✔
1667
  }
1668

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

1672
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,909,208✔
1673

1674
  return TSDB_CODE_SUCCESS;
6,909,208✔
1675
}
1676

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

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

1688
  if (0 == pInfo->num) {
5,901,982✔
1689
    colDataSetNULL(pCol, currentRow);
30,048!
1690
    return TSDB_CODE_SUCCESS;
30,048✔
1691
  }
1692

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

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

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

1701
  if (0 == param00) {
5,871,934✔
1702
    colDataSetNULL(pCol, currentRow);
4,283,311!
1703
    return TSDB_CODE_SUCCESS;
4,283,311✔
1704
  }
1705

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

1711
  param12 /= param[1][1];
1,588,623✔
1712

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

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

1730
  return code;
1,588,625✔
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) {
922✔
1756
  pEnv->calcMemSize = sizeof(SPercentileInfo);
922✔
1757
  return true;
922✔
1758
}
1759

1760
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,752✔
1761
  if (pResultInfo->initialized) {
5,752!
1762
    return TSDB_CODE_SUCCESS;
×
1763
  }
1764
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,752!
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,752✔
1770
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
5,752✔
1771
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
5,752✔
1772
  pInfo->numOfElems = 0;
5,752✔
1773

1774
  return TSDB_CODE_SUCCESS;
5,752✔
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) {
13,552✔
1789
  int32_t              code = TSDB_CODE_SUCCESS;
13,552✔
1790
  int32_t              numOfElems = 0;
13,552✔
1791
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,552✔
1792

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

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

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

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

1815
  // the first stage, only acquire the min/max value
1816
  if (pInfo->stage == 0) {
11,350✔
1817
    if (pCtx->input.colDataSMAIsSet) {
6,776!
1818
      double tmin = 0.0, tmax = 0.0;
×
1819
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
1820
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
1821
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
1822
      } else if (IS_FLOAT_TYPE(type)) {
×
1823
        tmin = GET_DOUBLE_VAL(&pAgg->min);
×
1824
        tmax = GET_DOUBLE_VAL(&pAgg->max);
×
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) {
×
1831
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
×
1832
      }
1833

1834
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
×
1835
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
×
1836
      }
1837

1838
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
×
1839
    } else {
1840
      // check the valid data one by one
1841
      int32_t start = pInput->startRowIndex;
6,776✔
1842
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
521,594✔
1843
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
514,818✔
1844
          continue;
2,400✔
1845
        }
1846

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

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

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

1859
        pInfo->numOfElems += 1;
512,418✔
1860
      }
1861
    }
1862
  } else {
1863
    // the second stage, calculate the true percentile value
1864
    int32_t start = pInput->startRowIndex;
4,574✔
1865
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
516,992✔
1866
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
512,418!
1867
        continue;
×
1868
      }
1869

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

1879
    SET_VAL(pResInfo, numOfElems, 1);
4,574!
1880
  }
1881

1882
  pCtx->needCleanup = true;
11,350✔
1883
  return TSDB_CODE_SUCCESS;
11,350✔
1884
}
1885

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

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

1893
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
5,752✔
1894
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
5,752!
1895
    if (pCtx->numOfParams > 2) {
3,550✔
1896
      char   buf[3200] = {0};
30✔
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;
30✔
1899

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

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

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

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

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

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

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

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

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

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

1950
_fin_error:
×
1951

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

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

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

1971
static int8_t getApercentileAlgo(char* algoStr) {
27,137✔
1972
  int8_t algoType;
1973
  if (strcasecmp(algoStr, "default") == 0) {
27,137✔
1974
    algoType = APERCT_ALGO_DEFAULT;
11,443✔
1975
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
15,694✔
1976
    algoType = APERCT_ALGO_TDIGEST;
15,684✔
1977
  } else {
1978
    algoType = APERCT_ALGO_UNKNOWN;
10✔
1979
  }
1980

1981
  return algoType;
27,137✔
1982
}
1983

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

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

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

2001
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
15,539,180✔
2002

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

2007
  if (pCtx->numOfParams == 2) {
15,539,180✔
2008
    pInfo->algo = APERCT_ALGO_DEFAULT;
15,512,353✔
2009
  } else if (pCtx->numOfParams == 3) {
26,827!
2010
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
27,140✔
2011
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
27,125!
2012
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2013
    }
2014
  }
2015

2016
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
15,539,165✔
2017
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
15,539,165✔
2018
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
15,685✔
2019
  } else {
2020
    buildHistogramInfo(pInfo);
15,523,480✔
2021
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
15,523,347✔
2022
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
15,522,323✔
2023
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2024
  }
2025

2026
  return TSDB_CODE_SUCCESS;
15,538,171✔
2027
}
2028

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

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

2037
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
15,128,285✔
2038

2039
  int32_t start = pInput->startRowIndex;
15,128,285✔
2040
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
15,128,285✔
2041
    buildTDigestInfo(pInfo);
14,889✔
2042
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
14,888✔
2043
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,613,335✔
2044
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,598,450✔
2045
        continue;
357,938✔
2046
      }
2047
      numOfElems += 1;
1,240,512✔
2048
      char* data = colDataGetData(pCol, i);
1,240,512!
2049

2050
      double  v = 0;  // value
1,240,512✔
2051
      int64_t w = 1;  // weigth
1,240,512✔
2052
      GET_TYPED_DATA(v, double, type, data);
1,240,512✔
2053
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
1,240,512✔
2054
      if (code != TSDB_CODE_SUCCESS) {
1,240,510!
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);
15,113,396✔
2062
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
15,113,302✔
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) {
74,630,557✔
2066
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
59,508,762✔
2067
        continue;
1,009,617✔
2068
      }
2069
      numOfElems += 1;
58,499,145✔
2070
      char* data = colDataGetData(pCol, i);
58,499,145!
2071

2072
      double v = 0;
58,499,145✔
2073
      GET_TYPED_DATA(v, double, type, data);
58,499,145✔
2074
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
58,499,145✔
2075
      if (code != TSDB_CODE_SUCCESS) {
58,507,528!
2076
        return code;
×
2077
      }
2078
    }
2079

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

2085
  SET_VAL(pResInfo, numOfElems, 1);
15,130,702✔
2086
  return TSDB_CODE_SUCCESS;
15,130,702✔
2087
}
2088

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

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

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

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

2108
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
952!
2109
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
950✔
2110
      tdigestAutoFill(pTDigest, COMPRESSION);
950✔
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);
2,490,441✔
2119
    if (pInput->pHisto->numOfElems <= 0) {
2,490,441✔
2120
      return TSDB_CODE_SUCCESS;
163✔
2121
    }
2122

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

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

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

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

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

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

2158
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
1,253,114✔
2159
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,253,114✔
2160

2161
  SInputColumnInfoData* pInput = &pCtx->input;
1,253,114✔
2162

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

2168
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,253,114✔
2169

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

2172
  bool hasRes = false;
1,253,114✔
2173
  int32_t start = pInput->startRowIndex;
1,253,114✔
2174
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,744,504✔
2175
    char* data = colDataGetData(pCol, i);
2,491,390!
2176

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

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

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

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

2198
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
13,024,544✔
2199
    buildTDigestInfo(pInfo);
14,727✔
2200
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
14,728✔
2201
    if (pInfo->pTDigest->size > 0) {
14,727!
2202
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
14,727✔
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);
13,009,817✔
2209
    if (pInfo->pHisto->numOfElems > 0) {
13,009,818✔
2210
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
12,953,914✔
2211
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2212

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

2231
  return functionFinalize(pCtx, pBlock);
13,024,554✔
2232
}
2233

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

2238
  int32_t resultBytes = getApercentileMaxSize();
2,479,329✔
2239
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
2,478,799✔
2240
  if (NULL == res) {
2,486,256!
2241
    return terrno;
×
2242
  }
2243

2244
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
2,486,256✔
2245
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
951✔
2246
    varDataSetLen(res, resultBytes);
951✔
2247
  } else {
2248
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
2,485,305✔
2249
    varDataSetLen(res, resultBytes);
2,485,305✔
2250
  }
2251

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

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

2261
  taosMemoryFree(res);
2,477,176✔
2262
  return code;
2,487,669✔
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,183✔
2285
  char numVal[8] = {0};
4,183✔
2286
  switch (pkType) {
4,183✔
2287
    case TSDB_DATA_TYPE_INT:
659✔
2288
      *(int32_t*)numVal = (int32_t)pVal->val;
659✔
2289
      break;
659✔
2290
    case TSDB_DATA_TYPE_UINT:
675✔
2291
      *(uint32_t*)numVal = (uint32_t)pVal->val;
675✔
2292
      break;
675✔
2293
    case TSDB_DATA_TYPE_BIGINT:
821✔
2294
      *(int64_t*)numVal = (int64_t)pVal->val;
821✔
2295
      break;
821✔
2296
    case TSDB_DATA_TYPE_UBIGINT:
763✔
2297
      *(uint64_t*)numVal = (uint64_t)pVal->val;
763✔
2298
      break;
763✔
2299
    default:
1,265✔
2300
      break;
1,265✔
2301
  }
2302
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*) numVal : (char*)pVal->pData;
4,183!
2303
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
4,183✔
2304
  return fn(pkData, blockData);
4,185✔
2305
}
2306

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

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

2315
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
7,712✔
2316
  if (pResult->hasResult) {
7,712✔
2317
    if (pResult->pkBytes > 0) {
7,667✔
2318
      pResult->pkData = pResult->buf + pResult->bytes;
4,053✔
2319
    } else {
2320
      pResult->pkData = NULL;
3,614✔
2321
    }    
2322
    if (pResult->ts < pBlockInfo->window.skey) {
7,667✔
2323
      return FUNC_DATA_REQUIRED_NOT_LOAD;
4,125✔
2324
    } else if (pResult->ts == pBlockInfo->window.skey) {
3,542✔
2325
      if (NULL == pResult->pkData) {
1,578✔
2326
        return FUNC_DATA_REQUIRED_NOT_LOAD;
180✔
2327
      }
2328
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
1,398✔
2329
        return FUNC_DATA_REQUIRED_NOT_LOAD;
186✔
2330
      }
2331
    }
2332
    return FUNC_DATA_REQUIRED_DATA_LOAD;
3,177✔
2333
  } else {
2334
    return FUNC_DATA_REQUIRED_DATA_LOAD;
45✔
2335
  }
2336
}
2337

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

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

2346
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
13,794✔
2347
  if (pResult->hasResult) {
13,794✔
2348
    if (pResult->pkBytes > 0) {
13,707✔
2349
      pResult->pkData = pResult->buf + pResult->bytes;
7,135✔
2350
    } else {
2351
      pResult->pkData = NULL;
6,572✔
2352
    }
2353
    if (pResult->ts > pBlockInfo->window.ekey) {
13,707✔
2354
      return FUNC_DATA_REQUIRED_NOT_LOAD;
6,562✔
2355
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
7,145✔
2356
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
2,786✔
2357
        return FUNC_DATA_REQUIRED_NOT_LOAD;
863✔
2358
      }
2359
    }
2360
    return FUNC_DATA_REQUIRED_DATA_LOAD;
6,282✔
2361
  } else {
2362
    return FUNC_DATA_REQUIRED_DATA_LOAD;
87✔
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; }
61,741,679✔
2368

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

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

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

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

2394
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
266,281,920!
2395
}
2396

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

2405
  SFirstLastRes *       pRes = GET_ROWCELL_INTERBUF(pResInfo);
13,358,859✔
2406
  SInputColumnInfoData* pInput = &pCtx->input;
13,358,859✔
2407

2408
  pRes->nullTupleSaved = false;
13,358,859✔
2409
  pRes->nullTuplePos.pageId = -1;
13,358,859✔
2410
  return TSDB_CODE_SUCCESS;
13,358,859✔
2411
}
2412

2413
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
194,918,525✔
2414
  if (pCtx->subsidiaries.rowLen == 0) {
194,918,525✔
2415
    int32_t rowLen = 0;
636,372✔
2416
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,282,091✔
2417
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
645,719✔
2418
      rowLen += pc->pExpr->base.resSchema.bytes;
645,719✔
2419
    }
2420

2421
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
636,372✔
2422
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
636,372✔
2423
    if (NULL == pCtx->subsidiaries.buf) {
636,417✔
2424
      return terrno;
471✔
2425
    }
2426
  }
2427
  return TSDB_CODE_SUCCESS;
194,918,099✔
2428
}
2429

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

2434
  if (pCtx->subsidiaries.num <= 0) {
204,884,387✔
2435
    return TSDB_CODE_SUCCESS;
108,695,808✔
2436
  }
2437

2438
  if (!pInfo->hasResult) {
96,188,579✔
2439
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
69,449,548✔
2440
  } else {
2441
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
26,739,031✔
2442
  }
2443

2444
  return code;
96,000,489✔
2445
}
2446

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

2451
  if (IS_VAR_DATA_TYPE(type)) {
104,915,193!
2452
    pInfo->bytes = varDataTLen(pData);
4,301,592✔
2453
  }
2454

2455
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
104,915,193✔
2456
  if (pkData != NULL) {
104,915,193✔
2457
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
1,398,267!
2458
      pInfo->pkBytes = varDataTLen(pkData);
455,462✔
2459
    }
2460
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
1,398,267✔
2461
    pInfo->pkData = pInfo->buf + pInfo->bytes;
1,398,267✔
2462
  }
2463

2464
  pInfo->ts = currentTs;
104,915,193✔
2465
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
104,915,193✔
2466
  if (code != TSDB_CODE_SUCCESS) {
104,891,354!
2467
    return code;
×
2468
  }
2469

2470
  pInfo->hasResult = true;
104,891,354✔
2471
  return TSDB_CODE_SUCCESS;
104,891,354✔
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) {
44,998,273✔
2477
  int32_t numOfElems = 0;
44,998,273✔
2478

2479
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
44,998,273✔
2480
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
44,998,273✔
2481

2482
  SInputColumnInfoData* pInput = &pCtx->input;
44,998,273✔
2483
  SColumnInfoData*      pInputCol = pInput->pData[0];
44,998,273✔
2484

2485
  pInfo->bytes = pInputCol->info.bytes;
44,998,273✔
2486

2487
  if (IS_NULL_TYPE(pInputCol->info.type)) {
44,998,273✔
2488
    return TSDB_CODE_SUCCESS;
4,848✔
2489
  }
2490

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

2500
  // All null data column, return directly.
2501
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
45,047,406!
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;
45,047,406!
2513

2514
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
45,047,406!
2515
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
45,047,406!
2516

2517
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
45,047,406✔
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;
45,047,406✔
2571

2572
  int from = -1;
45,047,406✔
2573
  int32_t i = -1;
45,047,406✔
2574
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
137,545,645✔
2575
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
124,128,888!
2576
      continue;
79,405✔
2577
    }
2578

2579
    numOfElems++;
92,473,485✔
2580
    char* data = colDataGetData(pInputCol, i);
92,473,485!
2581
    char* pkData = NULL;
92,473,485✔
2582
    if (pCtx->hasPrimaryKey) {
92,473,485✔
2583
      pkData = colDataGetData(pkCol, i);
1,346,371!
2584
    }
2585
    TSKEY cts = pts[i];
92,473,485✔
2586
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts || 
92,473,485✔
2587
         (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
53,692,583!
2588
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
38,780,902✔
2589
      if (code != TSDB_CODE_SUCCESS) {
38,726,252!
2590
        return code;
×
2591
      }
2592
      pResInfo->numOfRes = 1;
38,726,252✔
2593
    }
2594
  }
2595
#endif
2596

2597
  if (numOfElems == 0) {
44,642,235✔
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,436✔
2600
    if (code != TSDB_CODE_SUCCESS) {
25,436!
2601
      return code;
×
2602
    }
2603
    pInfo->nullTupleSaved = true;
25,436✔
2604
  }
2605
  SET_VAL(pResInfo, numOfElems, 1);
44,642,235✔
2606
  return TSDB_CODE_SUCCESS;
44,642,235✔
2607
}
2608

2609
int32_t lastFunction(SqlFunctionCtx* pCtx) {
55,222,192✔
2610
  int32_t numOfElems = 0;
55,222,192✔
2611

2612
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
55,222,192✔
2613
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
55,222,192✔
2614

2615
  SInputColumnInfoData* pInput = &pCtx->input;
55,222,192✔
2616
  SColumnInfoData*      pInputCol = pInput->pData[0];
55,222,192✔
2617

2618
  int32_t type = pInputCol->info.type;
55,222,192✔
2619
  int32_t bytes = pInputCol->info.bytes;
55,222,192✔
2620
  pInfo->bytes = bytes;
55,222,192✔
2621

2622
  if (IS_NULL_TYPE(type)) {
55,222,192✔
2623
    return TSDB_CODE_SUCCESS;
4,851✔
2624
  }
2625

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

2635
  // All null data column, return directly.
2636
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
55,269,586!
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;
55,269,586!
2648

2649
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
55,269,586!
2650
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
55,269,586!
2651

2652
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
55,269,586✔
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;
55,269,586✔
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) {
86,494,472✔
2708
    numOfElems = 1;
31,349,905✔
2709

2710
    int32_t round = pInput->numOfRows >> 2;
31,349,905✔
2711
    int32_t reminder = pInput->numOfRows & 0x03;
31,349,905✔
2712

2713
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
53,238,900✔
2714
      int64_t cts = pts[i];
21,885,892✔
2715
      int32_t chosen = i;
21,885,892✔
2716

2717
      if (cts < pts[i + 1]) {
21,885,892✔
2718
        cts = pts[i + 1];
4,397,491✔
2719
        chosen = i + 1;
4,397,491✔
2720
      }
2721

2722
      if (cts < pts[i + 2]) {
21,885,892✔
2723
        cts = pts[i + 2];
4,396,482✔
2724
        chosen = i + 2;
4,396,482✔
2725
      }
2726

2727
      if (cts < pts[i + 3]) {
21,885,892✔
2728
        cts = pts[i + 3];
4,396,992✔
2729
        chosen = i + 3;
4,396,992✔
2730
      }
2731

2732
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
21,885,892✔
2733
        char*   data = colDataGetData(pInputCol, chosen);
4,092,454!
2734
        int32_t code = doSaveCurrentVal(pCtx, i, cts, NULL, type, data);
4,092,454✔
2735
        if (code != TSDB_CODE_SUCCESS) {
4,095,557!
2736
          return code;
×
2737
        }
2738
        pResInfo->numOfRes = 1;
4,095,557✔
2739
      }
2740
    }
2741

2742
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
71,095,478✔
2743
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
39,870,592✔
2744
        char*   data = colDataGetData(pInputCol, i);
23,204,764!
2745
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
23,204,764✔
2746
        if (code != TSDB_CODE_SUCCESS) {
23,076,642!
2747
          return code;
×
2748
        }
2749
        pResInfo->numOfRes = 1;
23,076,642✔
2750
      }
2751
    }
2752
  } else {
2753
    int from = -1;
23,919,681✔
2754
    int32_t i = -1;
23,919,681✔
2755
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
265,141,194✔
2756
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
482,459,478✔
2757
        continue;
14,867,577✔
2758
      }
2759

2760
      numOfElems++;
226,362,162✔
2761
      char* pkData = NULL;
226,362,162✔
2762
      if (pCtx->hasPrimaryKey) {
226,362,162✔
2763
        pkData = colDataGetData(pkCol, i);
101,445,262!
2764
      }
2765
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
226,362,162✔
2766
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
187,638,724!
2767
        char*   data = colDataGetData(pInputCol, i);
38,852,503!
2768
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
38,852,503✔
2769
        if (code != TSDB_CODE_SUCCESS) {
38,844,283!
2770
          return code;
×
2771
        }
2772
        pResInfo->numOfRes = 1;
38,844,283✔
2773
      }
2774
    }
2775
  }
2776
#endif
2777

2778
#endif
2779

2780
  // save selectivity value for column consisted of all null values
2781
  if (numOfElems == 0) {
55,336,379✔
2782
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
4,095,420✔
2783
    if (code != TSDB_CODE_SUCCESS) {
4,088,843!
2784
      return code;
×
2785
    }
2786
    pInfo->nullTupleSaved = true;
4,088,843✔
2787
  }
2788

2789
  return TSDB_CODE_SUCCESS;
55,329,802✔
2790
}
2791

2792
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
55,512,749✔
2793
  if (!pInput->hasResult) {
55,512,749✔
2794
    return false;
2✔
2795
  }
2796
  __compar_fn_t pkCompareFn = NULL;
55,512,747✔
2797
  if (pInput->pkData) {
55,512,747✔
2798
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
35,872✔
2799
  }
2800
  if (pOutput->hasResult) {
55,515,509✔
2801
    if (isFirst) {
16,953,267✔
2802
      if (pInput->ts > pOutput->ts ||
8,587,841✔
2803
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,587,032✔
2804
        return false;
1,332✔
2805
      }
2806
    } else {
2807
      if (pInput->ts < pOutput->ts ||
8,365,426✔
2808
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
6,396,620✔
2809
        return false;
1,970,564✔
2810
      }
2811
    }
2812
  }
2813

2814
  pOutput->isNull = pInput->isNull;
53,543,613✔
2815
  pOutput->ts = pInput->ts;
53,543,613✔
2816
  pOutput->bytes = pInput->bytes;
53,543,613✔
2817
  pOutput->pkType = pInput->pkType;
53,543,613✔
2818

2819
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
53,543,613✔
2820
  if (pInput->pkData) {
53,543,613✔
2821
    pOutput->pkBytes = pInput->pkBytes;
33,439✔
2822
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
33,439✔
2823
    pOutput->pkData = pOutput->buf + pOutput->bytes;
33,439✔
2824
  }
2825
  return true;
53,543,613✔
2826
}
2827

2828
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
55,512,769✔
2829
                                     int32_t rowIndex) {
2830
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
55,512,769✔
2831
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
53,542,939✔
2832
    if (TSDB_CODE_SUCCESS != code) {
53,531,698!
2833
      return code;
×
2834
    }
2835
    pOutput->hasResult = true;
53,531,698✔
2836
  }
2837
  return TSDB_CODE_SUCCESS;
55,502,113✔
2838
}
2839

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

2844
  if (IS_NULL_TYPE(pCol->info.type)) {
38,599,271!
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) {
38,599,271!
2850
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2851
  }
2852

2853
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
38,599,271✔
2854

2855
  int32_t start = pInput->startRowIndex;
38,599,271✔
2856
  int32_t numOfElems = 0;
38,599,271✔
2857

2858
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
96,390,560✔
2859
    if (colDataIsNull_s(pCol, i)) {
115,617,094✔
2860
      continue;
2,289,997✔
2861
    }
2862
    char*          data = colDataGetData(pCol, i);
55,518,550!
2863
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
55,518,550✔
2864
    if (pCtx->hasPrimaryKey) {
55,518,550✔
2865
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
35,871✔
2866
    } else {
2867
      pInputInfo->pkData = NULL;
55,482,679✔
2868
    }
2869

2870
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
55,518,550✔
2871
    if (code != TSDB_CODE_SUCCESS) {
55,501,292!
2872
      return code;
×
2873
    }
2874
    if (!numOfElems) {
55,501,292✔
2875
      numOfElems = pInputInfo->hasResult ? 1 : 0;
38,579,935✔
2876
    }
2877
  }
2878

2879
  if (numOfElems == 0) {
38,582,013✔
2880
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
12,651✔
2881
    if (code != TSDB_CODE_SUCCESS) {
12,651!
2882
      return code;
×
2883
    }
2884
    pInfo->nullTupleSaved = true;
12,651✔
2885
  }
2886

2887
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
38,582,013✔
2888
  return TSDB_CODE_SUCCESS;
38,582,013✔
2889
}
2890

2891
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
10,991,201✔
2892

2893
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
27,612,109✔
2894

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

2903
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
78,568,460✔
2904
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
78,568,460✔
2905

2906
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
78,568,460✔
2907

2908
  if (pResInfo->isNullRes) {
78,568,460✔
2909
    colDataSetNULL(pCol, pBlock->info.rows);
49,157✔
2910
    return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
49,157✔
2911
  }
2912
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
78,519,303!
2913
  if (TSDB_CODE_SUCCESS != code) {
78,471,824!
2914
    return code;
×
2915
  }
2916

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

2920
  return code;
78,468,585✔
2921
}
2922

2923
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
59,712,272✔
2924
  int32_t code = TSDB_CODE_SUCCESS;
59,712,272✔
2925

2926
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
59,712,272✔
2927
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
59,712,272✔
2928

2929
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
59,712,272✔
2930

2931
  // todo check for failure
2932
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
59,657,359✔
2933
  if (NULL == res) {
60,188,037!
2934
    return terrno;
×
2935
  }
2936
  (void)memcpy(varDataVal(res), pRes, resultBytes);
60,188,037✔
2937

2938
  varDataSetLen(res, resultBytes);
60,188,037✔
2939

2940
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
60,188,037✔
2941
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
60,188,037✔
2942
  if (NULL == pCol) {
60,098,748!
2943
    taosMemoryFree(res);
×
2944
    return TSDB_CODE_OUT_OF_RANGE;
×
2945
  }
2946

2947
  if (pEntryInfo->numOfRes == 0) {
60,111,493✔
2948
    colDataSetNULL(pCol, pBlock->info.rows);
2,389,676!
2949
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
2,389,676✔
2950
  } else {
2951
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
57,721,817✔
2952
    if (TSDB_CODE_SUCCESS != code) {
57,330,214!
2953
      taosMemoryFree(res);
×
2954
      return code;
×
2955
    }
2956
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
57,330,214✔
2957
  }
2958
  taosMemoryFree(res);
59,659,053✔
2959
  return code;
60,129,205✔
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) {
42,440,030✔
2977
  SInputColumnInfoData* pInput = &pCtx->input;
42,440,030✔
2978
  SColumnInfoData*      pInputCol = pInput->pData[0];
42,440,030✔
2979
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
42,440,030✔
2980

2981

2982
  if (colDataIsNull_s(pInputCol, rowIndex)) {
84,880,060✔
2983
    pInfo->isNull = true;
5,618✔
2984
  } else {
2985
    pInfo->isNull = false;
42,434,412✔
2986

2987
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
42,434,412!
2988
      pInfo->bytes = varDataTLen(pData);
16,982,503✔
2989
    }
2990

2991
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
42,434,412✔
2992
  }
2993

2994
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
42,511,195✔
2995
    char* pkData = colDataGetData(pkCol, rowIndex);
71,162!
2996
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
71,162!
2997
      pInfo->pkBytes = varDataTLen(pkData);
23,481✔
2998
    }
2999
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
71,162✔
3000
    pInfo->pkData = pInfo->buf + pInfo->bytes;
71,162✔
3001
  }
3002
  pInfo->ts = cts;
42,440,030✔
3003
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
42,440,030✔
3004
  if (code != TSDB_CODE_SUCCESS) {
42,434,544!
3005
    return code;
×
3006
  }
3007

3008
  pInfo->hasResult = true;
42,434,544✔
3009

3010
  return TSDB_CODE_SUCCESS;
42,434,544✔
3011
}
3012

3013
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
32,577,780✔
3014
  int32_t numOfElems = 0;
32,577,780✔
3015

3016
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,577,780✔
3017
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
32,577,780✔
3018

3019
  SInputColumnInfoData* pInput = &pCtx->input;
32,577,780✔
3020
  SColumnInfoData*      pInputCol = pInput->pData[0];
32,577,780✔
3021

3022
  int32_t type = pInputCol->info.type;
32,577,780✔
3023
  int32_t bytes = pInputCol->info.bytes;
32,577,780✔
3024
  pInfo->bytes = bytes;
32,577,780✔
3025

3026
  if (IS_NULL_TYPE(type)) {
32,577,780✔
3027
    return TSDB_CODE_SUCCESS;
40✔
3028
  }
3029
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
32,577,740✔
3030
  pInfo->pkType = -1;
32,577,740✔
3031
  __compar_fn_t  pkCompareFn = NULL;
32,577,740✔
3032
  if (pCtx->hasPrimaryKey) {
32,577,740✔
3033
    pInfo->pkType = pkCol->info.type;
207,205✔
3034
    pInfo->pkBytes = pkCol->info.bytes;
207,205✔
3035
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
207,205✔
3036
  }
3037
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
32,582,014✔
3038
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
32,582,014!
3039

3040
#if 0
3041
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
3042

3043
  // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3044
  // this assumption is NOT always works if project operator exists in downstream.
3045
  if (blockDataOrder == TSDB_ORDER_ASC) {
3046
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
3047
      char* data = colDataGetData(pInputCol, i);
3048
      TSKEY cts = getRowPTs(pInput->pPTS, i);
3049
      numOfElems++;
3050

3051
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
3052
        doSaveLastrow(pCtx, data, i, cts, pInfo);
3053
      }
3054

3055
      break;
3056
    }
3057
  } else {  // descending order
3058
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
3059
      char* data = colDataGetData(pInputCol, i);
3060
      TSKEY cts = getRowPTs(pInput->pPTS, i);
3061
      numOfElems++;
3062

3063
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
3064
        doSaveLastrow(pCtx, data, i, cts, pInfo);
3065
      }
3066
      break;
3067
    }
3068
  }
3069
#else
3070

3071
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
32,582,014✔
3072
  int from = -1;
32,582,014✔
3073
  int32_t i = -1;
32,582,014✔
3074
  while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
99,857,226✔
3075
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
67,296,869✔
3076
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
67,296,869!
3077
    TSKEY cts = pts[i];
67,296,869✔
3078

3079
    numOfElems++;
67,296,869✔
3080
    char* pkData = NULL;
67,296,869✔
3081
    if (pCtx->hasPrimaryKey) {
67,296,869✔
3082
      pkData = colDataGetData(pkCol, i);
1,414,993!
3083
    }
3084
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
67,296,869✔
3085
        (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
24,847,134✔
3086
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
42,449,741✔
3087
      if (code != TSDB_CODE_SUCCESS) {
42,428,085!
3088
        return code;
×
3089
      }
3090
      pResInfo->numOfRes = 1;
42,428,085✔
3091
    }
3092
  }
3093

3094
#endif
3095

3096
  SET_VAL(pResInfo, numOfElems, 1);
32,533,471!
3097
  return TSDB_CODE_SUCCESS;
32,533,471✔
3098
}
3099

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

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

3125
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
802,218✔
3126
  switch (type) {
802,218!
3127
    case TSDB_DATA_TYPE_BOOL:
38✔
3128
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
38✔
3129
      break;
38✔
3130
    case TSDB_DATA_TYPE_UTINYINT:
403✔
3131
    case TSDB_DATA_TYPE_TINYINT:
3132
      pDiffInfo->prev.i64 = *(int8_t*)pv;
403✔
3133
      break;
403✔
3134
    case TSDB_DATA_TYPE_UINT:
310,048✔
3135
    case TSDB_DATA_TYPE_INT:
3136
      pDiffInfo->prev.i64 = *(int32_t*)pv;
310,048✔
3137
      break;
310,048✔
3138
    case TSDB_DATA_TYPE_USMALLINT:
394✔
3139
    case TSDB_DATA_TYPE_SMALLINT:
3140
      pDiffInfo->prev.i64 = *(int16_t*)pv;
394✔
3141
      break;
394✔
3142
    case TSDB_DATA_TYPE_TIMESTAMP:
600✔
3143
    case TSDB_DATA_TYPE_UBIGINT:
3144
    case TSDB_DATA_TYPE_BIGINT:
3145
      pDiffInfo->prev.i64 = *(int64_t*)pv;
600✔
3146
      break;
600✔
3147
    case TSDB_DATA_TYPE_FLOAT:
366,096✔
3148
      pDiffInfo->prev.d64 = *(float*)pv;
366,096✔
3149
      break;
366,096✔
3150
    case TSDB_DATA_TYPE_DOUBLE:
124,639✔
3151
      pDiffInfo->prev.d64 = *(double*)pv;
124,639✔
3152
      break;
124,639✔
3153
    default:
×
3154
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3155
  }
3156
  pDiffInfo->prevTs = ts;
802,218✔
3157
  pDiffInfo->hasPrev = true;
802,218✔
3158
  return TSDB_CODE_SUCCESS;
802,218✔
3159
}
3160

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

3212
  return false;
3213
}
3214

3215
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
31,313,861✔
3216
  bool isNegative = v < pDiffInfo->prev.i64;
31,313,861✔
3217
  if(type == TSDB_DATA_TYPE_UBIGINT){
31,313,861✔
3218
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
3,745✔
3219
  }
3220
  int64_t delta = v - pDiffInfo->prev.i64;
31,313,861✔
3221
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
31,313,861✔
3222
    colDataSetNull_f_s(pOutput, pos);
184,584✔
3223
    pOutput->hasNull = true;
184,584✔
3224
  } else {
3225
    colDataSetInt64(pOutput, pos, &delta);
31,129,277✔
3226
  }
3227
  pDiffInfo->prev.i64 = v;
31,313,861✔
3228
}
31,313,861✔
3229

3230
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
2,121,985✔
3231
  double delta = v - pDiffInfo->prev.d64;
2,121,985✔
3232
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
2,121,985✔
3233
    colDataSetNull_f_s(pOutput, pos);
566,950✔
3234
  } else {
3235
    colDataSetDouble(pOutput, pos, &delta);
1,555,035✔
3236
  }
3237
  pDiffInfo->prev.d64 = v;
2,121,985✔
3238
}
2,121,985✔
3239

3240
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
33,436,459✔
3241
                            int64_t ts) {
3242
  if (!pDiffInfo->hasPrev) {
33,436,459✔
3243
    colDataSetNull_f_s(pOutput, pos);
613✔
3244
    return doSetPrevVal(pDiffInfo, type, pv, ts);
613✔
3245
  }
3246
  pDiffInfo->prevTs = ts;
33,435,846✔
3247
  switch (type) {
33,435,846!
3248
    case TSDB_DATA_TYPE_UINT: {
3,675✔
3249
      int64_t v = *(uint32_t*)pv;
3,675✔
3250
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,675✔
3251
      break;
3,675✔
3252
    }
3253
    case TSDB_DATA_TYPE_INT: {
26,978,284✔
3254
      int64_t v = *(int32_t*)pv;
26,978,284✔
3255
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
26,978,284✔
3256
      break;
26,978,284✔
3257
    }
3258
    case TSDB_DATA_TYPE_BOOL: {
10,877✔
3259
      int64_t v = *(bool*)pv;
10,877✔
3260
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,877✔
3261
      break;
10,877✔
3262
    }
3263
    case TSDB_DATA_TYPE_UTINYINT: {
675✔
3264
      int64_t v = *(uint8_t*)pv;
675✔
3265
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3266
      break;
675✔
3267
    }
3268
    case TSDB_DATA_TYPE_TINYINT: {
35,755✔
3269
      int64_t v = *(int8_t*)pv;
35,755✔
3270
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
35,755✔
3271
      break;
35,755✔
3272
    }
3273
    case TSDB_DATA_TYPE_USMALLINT:{
675✔
3274
      int64_t v = *(uint16_t*)pv;
675✔
3275
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
675✔
3276
      break;
675✔
3277
    }
3278
    case TSDB_DATA_TYPE_SMALLINT: {
39,709✔
3279
      int64_t v = *(int16_t*)pv;
39,709✔
3280
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
39,709✔
3281
      break;
39,709✔
3282
    }
3283
    case TSDB_DATA_TYPE_TIMESTAMP:
4,244,211✔
3284
    case TSDB_DATA_TYPE_UBIGINT:
3285
    case TSDB_DATA_TYPE_BIGINT: {
3286
      int64_t v = *(int64_t*)pv;
4,244,211✔
3287
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,244,211✔
3288
      break;
4,244,211✔
3289
    }
3290
    case TSDB_DATA_TYPE_FLOAT: {
1,774,566✔
3291
      double v = *(float*)pv;
1,774,566✔
3292
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
1,774,566✔
3293
      break;
1,774,566✔
3294
    }
3295
    case TSDB_DATA_TYPE_DOUBLE: {
347,419✔
3296
      double v = *(double*)pv;
347,419✔
3297
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
347,419✔
3298
      break;
347,419✔
3299
    }
3300
    default:
×
3301
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3302
  }
3303
  pDiffInfo->hasPrev = true;
33,435,846✔
3304
  return TSDB_CODE_SUCCESS;
33,435,846✔
3305
}
3306

3307
//TODO: the primary key compare can be skipped for ordered pk if knonwn before
3308
//TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3309
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex, int32_t* nextFrom) {
501,820,774✔
3310
  if (pInput->pPrimaryKey == NULL) {
501,820,774✔
3311
    if (from == -1) {
397,068,077✔
3312
      from = pInput->startRowIndex;
102,156,007✔
3313
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
294,912,070✔
3314
      return false;
101,775,537✔
3315
    }
3316
    *pRowIndex = from;
295,292,540✔
3317
    *nextFrom = from + 1;
295,292,540✔
3318
    return true;
295,292,540✔
3319
  } else {
3320
    if (from == -1) {
104,752,697✔
3321
      from = pInput->startRowIndex;
653,388✔
3322
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
104,099,309✔
3323
      return false;
653,541✔
3324
    }
3325
    TSKEY* tsList = (int64_t*)pInput->pPTS->pData;
104,099,156✔
3326
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
104,099,156✔
3327
    int8_t pkType = pkCol->info.type;
104,099,156✔
3328
    int32_t order = (firstOccur) ? TSDB_ORDER_ASC: TSDB_ORDER_DESC;
104,099,156✔
3329
    __compar_fn_t compareFunc = getKeyComparFunc(pkType, order);
104,099,156✔
3330
    int32_t select = from;
104,193,502✔
3331
    char* val = colDataGetData(pkCol, select);
104,193,502!
3332
    while (from < pInput->numOfRows + pInput->startRowIndex - 1  &&  tsList[from + 1] == tsList[from]) {
110,509,255✔
3333
      char* val1 = colDataGetData(pkCol, from + 1);
6,318,529!
3334
      if (compareFunc(val1, val) < 0)  {
6,318,529✔
3335
        select = from + 1;
1,923,963✔
3336
        val = val1;
1,923,963✔
3337
      }
3338
      from = from + 1;
6,315,753✔
3339
    }
3340
    *pRowIndex = select;
104,190,726✔
3341
    *nextFrom = from + 1;
104,190,726✔
3342
    return true;
104,190,726✔
3343
  }
3344
}
3345

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

3351
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow){
34,322,348✔
3352
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
34,322,348✔
3353
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
34,322,348✔
3354

3355
  if (pRow->isDataNull || !pDiffInfo->hasPrev ) {
34,322,348✔
3356
    return true;
174,999✔
3357
  }  else if (ignoreNegative(pDiffInfo->ignoreOption)){
34,147,349✔
3358
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
2,939,180✔
3359
  }
3360
  return false;
31,208,169✔
3361
}
3362

3363
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
33,590,417✔
3364
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
33,590,417✔
3365
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
33,590,417✔
3366
  return pDiffInfo->isFirstRow;
33,590,417✔
3367
}
3368

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

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

3381
  char*   pv = pRow->pData;
801,605✔
3382
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
801,605✔
3383
}
3384

3385
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
33,518,840✔
3386
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
33,518,840✔
3387
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
33,518,840✔
3388

3389
  SInputColumnInfoData* pInput = &pCtx->input;
33,518,840✔
3390
  SColumnInfoData*      pInputCol = pInput->pData[0];
33,518,840✔
3391
  int8_t                inputType = pInputCol->info.type;
33,518,840✔
3392
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
33,518,840✔
3393
  int32_t               code = TSDB_CODE_SUCCESS;
33,518,840✔
3394
  if (pRow->isDataNull) {
33,518,840✔
3395
    colDataSetNull_f_s(pOutput, pos);
82,358✔
3396
    pOutput->hasNull = true;
82,358✔
3397

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

3408
  char* pv = pRow->pData;
33,436,482✔
3409

3410
  if (pRow->ts == pDiffInfo->prevTs) {
33,436,482✔
3411
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
23✔
3412
  }
3413
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
33,436,459✔
3414
  if (code != TSDB_CODE_SUCCESS) {
33,436,459!
3415
    return code;
×
3416
  }
3417
  // handle selectivity
3418
  if (pCtx->subsidiaries.num > 0) {
33,436,459✔
3419
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
31,797,785✔
3420
    if (code != TSDB_CODE_SUCCESS) {
31,797,785!
3421
      return code;
×
3422
    }
3423
  }
3424

3425
  return TSDB_CODE_SUCCESS;
33,436,459✔
3426
}
3427

3428
int32_t diffFunction(SqlFunctionCtx* pCtx) {
422,661✔
3429
  return TSDB_CODE_SUCCESS;
422,661✔
3430
}
3431

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

3440
  SArray*  pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
422,403✔
3441
  if (NULL == pRows) {
422,403!
3442
    return terrno;
×
3443
  }
3444

3445
  bool keepNull = false;
422,403✔
3446
  for (int i = 0; i < diffColNum; ++i) {
845,064✔
3447
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
422,661✔
3448
    if (NULL == pCtx) {
422,661!
3449
      code = terrno;
×
3450
      goto _exit;
×
3451
    }
3452
    funcInputUpdate(pCtx);
422,661✔
3453
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
422,661✔
3454
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
422,661✔
3455
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
422,661✔
3456
      keepNull = true;
394,503✔
3457
    }
3458
  }
3459

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

3499
    bool newRow = false;
34,304,858✔
3500
    for (int i = 0; i < diffColNum; ++i) {
68,627,183✔
3501
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
34,322,348✔
3502
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
34,322,348✔
3503
      if (NULL == pCtx || NULL == pRow) {
34,322,348!
3504
        code = terrno;
×
3505
        goto _exit;
×
3506
      }
3507
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)){
34,322,348✔
3508
        code = setDoDiffResult(pCtx, pRow, pos);
33,518,840✔
3509
        if (code != TSDB_CODE_SUCCESS) {
33,518,840✔
3510
          goto _exit;
23✔
3511
        }
3512
        newRow = true;
33,518,817✔
3513
      } else {
3514
        code = trySetPreVal(pCtx, pRow);
803,508✔
3515
        if (code != TSDB_CODE_SUCCESS) {
803,508!
3516
          goto _exit;
×
3517
        } 
3518
      }
3519
    }
3520
    if (newRow) ++numOfElems;
34,304,835✔
3521
  }
3522

3523
  for (int i = 0; i < diffColNum; ++i) {
845,013✔
3524
    SqlFunctionCtx*      pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
422,633✔
3525
    if (NULL == pCtx) {
422,633!
3526
      code = terrno;
×
3527
      goto _exit;
×
3528
    }
3529
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
422,633✔
3530
    pResInfo->numOfRes = numOfElems;
422,633✔
3531
  }
3532

3533
_exit:
422,380✔
3534
  if (pRows) {
422,403!
3535
    taosArrayDestroy(pRows);
422,403✔
3536
    pRows = NULL;
422,403✔
3537
  }
3538
  return code;
422,403✔
3539
}
3540

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

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

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

3557
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
45,099,317✔
3558
  SInputColumnInfoData* pInput = &pCtx->input;
45,099,317✔
3559

3560
  pRes->maxSize = pCtx->param[1].param.i;
45,099,317✔
3561

3562
  pRes->nullTupleSaved = false;
45,099,317✔
3563
  pRes->nullTuplePos.pageId = -1;
45,099,317✔
3564
  return TSDB_CODE_SUCCESS;
45,099,317✔
3565
}
3566

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

3572
  return pRes;
211,615,541✔
3573
}
3574

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

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

3580
int32_t topFunction(SqlFunctionCtx* pCtx) {
43,181,784✔
3581
  int32_t              numOfElems = 0;
43,181,784✔
3582
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
43,181,784✔
3583

3584
  SInputColumnInfoData* pInput = &pCtx->input;
43,181,784✔
3585
  SColumnInfoData*      pCol = pInput->pData[0];
43,181,784✔
3586

3587
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
43,181,784✔
3588
  pRes->type = pInput->pData[0]->info.type;
43,183,837✔
3589

3590
  int32_t start = pInput->startRowIndex;
43,183,837✔
3591
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
148,725,209✔
3592
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
105,504,773✔
3593
      continue;
36,665✔
3594
    }
3595

3596
    numOfElems++;
105,468,108✔
3597
    char*   data = colDataGetData(pCol, i);
105,468,108!
3598
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
105,468,108✔
3599
    if (code != TSDB_CODE_SUCCESS) {
105,504,707!
3600
      return code;
×
3601
    }
3602
  }
3603

3604
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
43,220,436✔
3605
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
1,827✔
3606
    if (code != TSDB_CODE_SUCCESS) {
1,827!
3607
      return code;
×
3608
    }
3609
    pRes->nullTupleSaved = true;
1,827✔
3610
  }
3611
  return TSDB_CODE_SUCCESS;
43,220,436✔
3612
}
3613

3614
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
2,955,810✔
3615
  int32_t              numOfElems = 0;
2,955,810✔
3616
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,955,810✔
3617

3618
  SInputColumnInfoData* pInput = &pCtx->input;
2,955,810✔
3619
  SColumnInfoData*      pCol = pInput->pData[0];
2,955,810✔
3620

3621
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
2,955,810✔
3622
  pRes->type = pInput->pData[0]->info.type;
2,955,813✔
3623

3624
  int32_t start = pInput->startRowIndex;
2,955,813✔
3625
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,194,064✔
3626
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
15,237,823✔
3627
      continue;
27,924✔
3628
    }
3629

3630
    numOfElems++;
15,209,899✔
3631
    char*   data = colDataGetData(pCol, i);
15,209,899!
3632
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
15,209,899✔
3633
    if (code != TSDB_CODE_SUCCESS) {
15,210,327!
3634
      return code;
×
3635
    }
3636
  }
3637

3638
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
2,956,241✔
3639
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
144✔
3640
    if (code != TSDB_CODE_SUCCESS) {
144!
3641
      return code;
×
3642
    }
3643
    pRes->nullTupleSaved = true;
144✔
3644
  }
3645

3646
  return TSDB_CODE_SUCCESS;
2,956,241✔
3647
}
3648

3649
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
591,559,039✔
3650
  uint16_t type = *(uint16_t*)param;
591,559,039✔
3651

3652
  STopBotResItem* val1 = (STopBotResItem*)p1;
591,559,039✔
3653
  STopBotResItem* val2 = (STopBotResItem*)p2;
591,559,039✔
3654

3655
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
591,559,039!
3656
    if (val1->v.i == val2->v.i) {
519,153,703✔
3657
      return 0;
317,202✔
3658
    }
3659

3660
    return (val1->v.i > val2->v.i) ? 1 : -1;
518,836,501✔
3661
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
72,405,336✔
3662
    if (val1->v.u == val2->v.u) {
836,151✔
3663
      return 0;
179,915✔
3664
    }
3665

3666
    return (val1->v.u > val2->v.u) ? 1 : -1;
656,236✔
3667
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
71,569,185✔
3668
    if (val1->v.f == val2->v.f) {
35,443,746✔
3669
      return 0;
63✔
3670
    }
3671

3672
    return (val1->v.f > val2->v.f) ? 1 : -1;
35,443,683✔
3673
  }
3674

3675
  if (val1->v.d == val2->v.d) {
36,125,439✔
3676
    return 0;
11✔
3677
  }
3678

3679
  return (val1->v.d > val2->v.d) ? 1 : -1;
36,125,428✔
3680
}
3681

3682
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
120,676,485✔
3683
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3684
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
120,676,485✔
3685
  int32_t     code = TSDB_CODE_SUCCESS;
120,659,613✔
3686

3687
  SVariant val = {0};
120,659,613✔
3688
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
120,659,613!
3689

3690
  STopBotResItem* pItems = pRes->pItems;
120,690,738✔
3691

3692
  // not full yet
3693
  if (pEntryInfo->numOfRes < pRes->maxSize) {
120,690,738✔
3694
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
81,069,448✔
3695
    pItem->v = val;
81,069,448✔
3696
    pItem->uid = uid;
81,069,448✔
3697

3698
    // save the data of this tuple
3699
    if (pCtx->subsidiaries.num > 0) {
81,069,448✔
3700
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
54,052,336✔
3701
      if (code != TSDB_CODE_SUCCESS) {
53,964,515!
3702
        return code;
×
3703
      }
3704
    }
3705
#ifdef BUF_PAGE_DEBUG
3706
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3707
           pItem->tuplePos.offset);
3708
#endif
3709
    // allocate the buffer and keep the data of this row into the new allocated buffer
3710
    pEntryInfo->numOfRes++;
80,981,627✔
3711
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
80,981,627✔
3712
                        topBotResComparFn, !isTopQuery);
80,981,627✔
3713
    if (code != TSDB_CODE_SUCCESS) {
81,111,050!
3714
      return code;
×
3715
    }
3716
  } else {  // replace the minimum value in the result
3717
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
39,621,290!
3718
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
22,132,161✔
3719
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
22,037,818✔
3720
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
21,526,125✔
3721
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
31,354,991!
3722
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
8,590,649!
3723
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
8,586,497✔
3724
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
8,585,228!
3725
      // replace the old data and the coresponding tuple data
3726
      STopBotResItem* pItem = &pItems[0];
10,166,923✔
3727
      pItem->v = val;
10,166,923✔
3728
      pItem->uid = uid;
10,166,923✔
3729

3730
      // save the data of this tuple by over writing the old data
3731
      if (pCtx->subsidiaries.num > 0) {
10,166,923✔
3732
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
7,667,291✔
3733
        if (code != TSDB_CODE_SUCCESS) {
7,657,143!
3734
          return code;
×
3735
        }
3736
      }
3737
#ifdef BUF_PAGE_DEBUG
3738
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3739
#endif
3740
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
10,156,775✔
3741
                     topBotResComparFn, NULL, !isTopQuery);
10,156,775✔
3742
      if (code != TSDB_CODE_SUCCESS) {
10,144,648!
3743
        return code;
×
3744
      }
3745
    }
3746
  }
3747

3748
  return TSDB_CODE_SUCCESS;
120,710,065✔
3749
}
3750

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

3762
  int32_t offset = 0;
194,903,627✔
3763
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
389,791,544✔
3764
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
194,991,072✔
3765

3766
    // group_key function has its own process function
3767
    // do not process there
3768
    if (fmIsGroupKeyFunc(pc->functionId)) {
194,991,072✔
3769
      continue;
8,311,795✔
3770
    }
3771

3772
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
186,660,914✔
3773
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
186,660,914✔
3774

3775
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
186,660,914✔
3776
    if (NULL == pCol) {
186,576,122!
3777
      return TSDB_CODE_OUT_OF_RANGE;
×
3778
    }
3779
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
373,152,244✔
3780
      offset += pCol->info.bytes;
482✔
3781
      continue;
482✔
3782
    }
3783

3784
    char* p = colDataGetData(pCol, rowIndex);
186,575,640!
3785
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
186,575,640!
3786
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
57,143!
3787
    } else {
3788
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
186,518,497✔
3789
    }
3790

3791
    offset += pCol->info.bytes;
186,575,640✔
3792
  }
3793

3794
  *res = buf;
194,800,472✔
3795
  return TSDB_CODE_SUCCESS;
194,800,472✔
3796
}
3797

3798
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
146,459,717✔
3799
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3800
  STuplePos p = {0};
146,459,717✔
3801
  if (pHandle->pBuf != NULL) {
146,459,717✔
3802
    SFilePage* pPage = NULL;
146,221,100✔
3803

3804
    if (pHandle->currentPage == -1) {
146,221,100✔
3805
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
638,095✔
3806
      if (pPage == NULL) {
638,143!
3807
        return terrno;
×
3808
      }
3809
      pPage->num = sizeof(SFilePage);
638,146✔
3810
    } else {
3811
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
145,583,005✔
3812
      if (pPage == NULL) {
145,549,289!
3813
        return terrno;
×
3814
      }
3815
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
145,549,289✔
3816
        // current page is all used, let's prepare a new buffer page
3817
        releaseBufPage(pHandle->pBuf, pPage);
102,288✔
3818
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
102,288✔
3819
        if (pPage == NULL) {
102,287!
3820
          return terrno;
×
3821
        }
3822
        pPage->num = sizeof(SFilePage);
102,287✔
3823
      }
3824
    }
3825

3826
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
146,178,715✔
3827
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
146,178,715✔
3828

3829
    pPage->num += length;
146,178,715✔
3830
    setBufPageDirty(pPage, true);
146,178,715✔
3831
    releaseBufPage(pHandle->pBuf, pPage);
146,108,393✔
3832
  } else { // other tuple save policy
3833
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
238,617!
3834
      p.streamTupleKey = *key;
244,557✔
3835
    }
3836
  }
3837

3838
  *pPos = p;
146,261,932✔
3839
  return TSDB_CODE_SUCCESS;
146,261,932✔
3840
}
3841

3842
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
146,288,916✔
3843
  int32_t code = prepareBuf(pCtx);
146,288,916✔
3844
  if (TSDB_CODE_SUCCESS != code) {
146,271,325!
3845
    return code;
×
3846
  }
3847

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

3861
  char* buf = NULL;
146,271,325✔
3862
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
146,271,325✔
3863
  if (TSDB_CODE_SUCCESS != code) {
146,183,249!
3864
    return code;
×
3865
  }
3866
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
146,183,249✔
3867
}
3868

3869
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos, SFunctionStateStore* pStore) {
48,669,168✔
3870
  if (pHandle->pBuf != NULL) {
48,669,168✔
3871
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
48,086,111✔
3872
    if (pPage == NULL) {
48,085,040!
3873
      return terrno;
×
3874
    }
3875
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
48,085,040✔
3876
    setBufPageDirty(pPage, true);
48,085,040✔
3877
    releaseBufPage(pHandle->pBuf, pPage);
48,079,183✔
3878
  } else {
3879
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
583,057✔
3880
    if (TSDB_CODE_SUCCESS != code) {
583,351!
3881
      return code;
×
3882
    }
3883
  }
3884

3885
  return TSDB_CODE_SUCCESS;
48,656,608✔
3886
}
3887

3888
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
48,673,971✔
3889
  int32_t code = prepareBuf(pCtx);
48,673,971✔
3890
  if (TSDB_CODE_SUCCESS != code) {
48,672,968!
3891
    return code;
×
3892
  }
3893

3894
  char* buf = NULL;
48,672,968✔
3895
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
48,672,968✔
3896
  if (TSDB_CODE_SUCCESS != code) {
48,669,122!
3897
    return code;
×
3898
  }
3899
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
48,669,122✔
3900
}
3901

3902
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore, char** value) {
143,011,421✔
3903
  if (pHandle->pBuf != NULL) {
143,011,421✔
3904
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
142,700,340✔
3905
    if (pPage == NULL) {
142,739,395!
3906
      *value = NULL;
×
3907
      return terrno;
×
3908
    }
3909
    *value = pPage->data + pPos->offset;
142,739,395✔
3910
    releaseBufPage(pHandle->pBuf, pPage);
142,739,395✔
3911
    return TSDB_CODE_SUCCESS;
142,662,720✔
3912
  } else {
3913
    *value = NULL;
311,081✔
3914
    int32_t vLen;
3915
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void **)(value), &vLen);
311,081✔
3916
    if (TSDB_CODE_SUCCESS != code) {
317,826!
3917
      return code;
×
3918
    }
3919
    return TSDB_CODE_SUCCESS;
317,826✔
3920
  }
3921
}
3922

3923
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
142,926,378✔
3924
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
142,926,378✔
3925
}
3926

3927
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
44,964,811✔
3928
  int32_t code = TSDB_CODE_SUCCESS;
44,964,811✔
3929

3930
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
44,964,811✔
3931
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
44,964,811✔
3932

3933
  int16_t type = pCtx->pExpr->base.resSchema.type;
44,963,711✔
3934
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
44,963,711✔
3935

3936
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
44,963,711✔
3937
  if (NULL == pCol) {
44,959,147!
3938
    return TSDB_CODE_OUT_OF_RANGE;
×
3939
  }
3940

3941
  // todo assign the tag value and the corresponding row data
3942
  int32_t currentRow = pBlock->info.rows;
44,959,147✔
3943
  if (pEntryInfo->numOfRes <= 0) {
44,959,147✔
3944
    colDataSetNULL(pCol, currentRow);
608!
3945
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
608✔
3946
    return code;
608✔
3947
  }
3948
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
125,798,227✔
3949
    STopBotResItem* pItem = &pRes->pItems[i];
80,850,432✔
3950
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
80,850,432✔
3951
    if (TSDB_CODE_SUCCESS != code) {
80,843,428!
3952
      return code;
×
3953
    }
3954
#ifdef BUF_PAGE_DEBUG
3955
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3956
           pItem->tuplePos.offset);
3957
#endif
3958
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
80,843,428✔
3959
    if (TSDB_CODE_SUCCESS != code) {
80,839,688!
3960
      return code;
×
3961
    }
3962
    currentRow += 1;
80,839,688✔
3963
  }
3964

3965
  return code;
44,947,795✔
3966
}
3967

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

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

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

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

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

4041
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
743,932✔
4042

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

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

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

4063
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
4,179,665✔
4064
  int32_t numOfElems = 0;
4,179,665✔
4065

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

4071
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,179,665✔
4072

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

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

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

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

4101
    int32_t start = pInput->startRowIndex;
4,179,665✔
4102
    // check the valid data one by one
4103
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
21,535,082✔
4104
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
17,355,417✔
4105
        continue;
1,817,634✔
4106
      }
4107

4108
      char* data = colDataGetData(pCol, i);
15,537,783!
4109

4110
      double v = 0;
15,537,783✔
4111
      GET_TYPED_DATA(v, double, type, data);
15,537,783!
4112
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
15,537,783✔
4113
        SET_DOUBLE_VAL(&pInfo->min, v);
4,804,858✔
4114
      }
4115

4116
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
15,537,783✔
4117
        SET_DOUBLE_VAL(&pInfo->max, v);
5,287,839✔
4118
      }
4119

4120
      numOfElems += 1;
15,537,783✔
4121
    }
4122
  }
4123

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

4131
  return TSDB_CODE_SUCCESS;
4,179,665✔
4132
}
4133

4134
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
742,515✔
4135
  pOutput->hasResult = pInput->hasResult;
742,515✔
4136
  if (pInput->max > pOutput->max) {
742,515✔
4137
    pOutput->max = pInput->max;
737,803✔
4138
  }
4139

4140
  if (pInput->min < pOutput->min) {
742,515✔
4141
    pOutput->min = pInput->min;
737,792✔
4142
  }
4143
}
742,515✔
4144

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

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

4154
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
738,585!
4155
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4156
  }
4157

4158
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
738,585✔
4159

4160
  int32_t start = pInput->startRowIndex;
738,585✔
4161
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,481,362✔
4162
    if(colDataIsNull_s(pCol, i)) continue;
1,485,554!
4163
    char*        data = colDataGetData(pCol, i);
742,777!
4164
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
742,777✔
4165
    if (pInputInfo->hasResult) {
742,777✔
4166
      spreadTransferInfo(pInputInfo, pInfo);
742,514✔
4167
    }
4168
  }
4169

4170
  if (pInfo->hasResult) {
738,585✔
4171
    GET_RES_INFO(pCtx)->numOfRes = 1;
738,394✔
4172
  }
4173

4174
  return TSDB_CODE_SUCCESS;
738,585✔
4175
}
4176

4177
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,438,728✔
4178
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,438,728✔
4179
  if (pInfo->hasResult == true) {
3,438,728✔
4180
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
3,400,970✔
4181
  } else {
4182
    GET_RES_INFO(pCtx)->isNullRes = 1;
37,758✔
4183
  }
4184
  return functionFinalize(pCtx, pBlock);
3,438,728✔
4185
}
4186

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

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

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

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

4212
_exit:
742,556✔
4213
  taosMemoryFree(res);
742,556✔
4214
  return code;
742,556✔
4215
}
4216

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

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

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

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

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

4244
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
9,420,073✔
4245
  pInfo->result = 0;
9,420,073✔
4246
  pInfo->min = TSKEY_MAX;
9,420,073✔
4247
  pInfo->max = 0;
9,420,073✔
4248

4249
  if (pCtx->numOfParams > 1) {
9,420,073✔
4250
    pInfo->timeUnit = pCtx->param[1].param.i;
23,704✔
4251
  } else {
4252
    pInfo->timeUnit = 1;
9,396,369✔
4253
  }
4254

4255
  return TSDB_CODE_SUCCESS;
9,420,073✔
4256
}
4257

4258
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
9,420,225✔
4259
  int32_t numOfElems = 0;
9,420,225✔
4260

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

4265
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,420,225✔
4266

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

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

4301
    SColumnInfoData* pCol = pInput->pData[0];
9,420,173✔
4302

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

4312
      if (pCtx->end.key == INT64_MIN) {
768!
4313
        pInfo->min =
768✔
4314
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
768✔
4315
      } else {
4316
        pInfo->min = pCtx->end.key;
×
4317
      }
4318
    } else {
4319
      if (pCtx->start.key == INT64_MIN) {
9,419,405✔
4320
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
4,216,446✔
4321
      } else {
4322
        pInfo->min = pCtx->start.key;
5,202,959✔
4323
      }
4324

4325
      if (pCtx->end.key == INT64_MIN) {
9,419,405✔
4326
        pInfo->max =
3,911,549✔
4327
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
3,911,549✔
4328
      } else {
4329
        pInfo->max = pCtx->end.key + 1;
5,507,856✔
4330
      }
4331
    }
4332
  }
4333

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

4338
  return TSDB_CODE_SUCCESS;
9,420,225✔
4339
}
4340

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

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

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

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

4361
  int32_t start = pInput->startRowIndex;
×
4362

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

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

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

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

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

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

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

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

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

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

4423
int32_t getHistogramInfoSize() {
1,786,972✔
4424
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
1,786,972✔
4425
}
4426

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

4432
static int8_t getHistogramBinType(char* binTypeStr) {
8,579,193✔
4433
  int8_t binType;
4434
  if (strcasecmp(binTypeStr, "user_input") == 0) {
8,579,193✔
4435
    binType = USER_INPUT_BIN;
3,427✔
4436
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
8,575,766✔
4437
    binType = LINEAR_BIN;
3,054✔
4438
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
8,572,712!
4439
    binType = LOG_BIN;
8,572,877✔
4440
  } else {
4441
    binType = UNKNOWN_BIN;
×
4442
  }
4443

4444
  return binType;
8,579,193✔
4445
}
4446

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

4459
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
8,575,769✔
4460
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
8,575,816✔
4461
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
8,575,737✔
4462
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
8,574,999✔
4463
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
8,575,513✔
4464

4465
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
8,575,852!
4466
      cJSON_Delete(binDesc);
3✔
4467
      return TSDB_CODE_FAILED;
×
4468
    }
4469

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

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

4481
    int32_t counter = (int32_t)count->valueint;
8,575,748✔
4482
    if (infinity->valueint == false) {
8,575,748✔
4483
      startIndex = 0;
3,733,560✔
4484
      numOfBins = counter + 1;
3,733,560✔
4485
    } else {
4486
      startIndex = 1;
4,842,188✔
4487
      numOfBins = counter + 3;
4,842,188✔
4488
    }
4489

4490
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
8,575,748✔
4491
    if (NULL == intervals) {
8,575,905!
4492
      cJSON_Delete(binDesc);
×
4493
      qError("histogram function out of memory");
×
4494
      return terrno;
×
4495
    }
4496
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
8,575,905!
4497
      // linear bin process
4498
      if (width->valuedouble == 0) {
3,054!
4499
        taosMemoryFree(intervals);
×
4500
        cJSON_Delete(binDesc);
×
4501
        return TSDB_CODE_FAILED;
×
4502
      }
4503
      for (int i = 0; i < counter + 1; ++i) {
30,116✔
4504
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
27,062✔
4505
        if (isinf(intervals[startIndex])) {
27,062!
4506
          taosMemoryFree(intervals);
×
4507
          cJSON_Delete(binDesc);
×
4508
          return TSDB_CODE_FAILED;
×
4509
        }
4510
        startIndex++;
27,062✔
4511
      }
4512
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
8,572,816!
4513
      // log bin process
4514
      if (start->valuedouble == 0) {
8,572,776!
4515
        taosMemoryFree(intervals);
×
4516
        cJSON_Delete(binDesc);
×
4517
        return TSDB_CODE_FAILED;
×
4518
      }
4519
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
8,572,776!
4520
        taosMemoryFree(intervals);
1✔
4521
        cJSON_Delete(binDesc);
×
4522
        return TSDB_CODE_FAILED;
×
4523
      }
4524
      for (int i = 0; i < counter + 1; ++i) {
60,003,997✔
4525
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
51,431,222✔
4526
        if (isinf(intervals[startIndex])) {
51,431,222!
4527
          taosMemoryFree(intervals);
×
4528
          cJSON_Delete(binDesc);
×
4529
          return TSDB_CODE_FAILED;
×
4530
        }
4531
        startIndex++;
51,431,222✔
4532
      }
4533
    } else {
4534
      taosMemoryFree(intervals);
×
4535
      cJSON_Delete(binDesc);
×
4536
      return TSDB_CODE_FAILED;
×
4537
    }
4538

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

4589
  pInfo->numOfBins = numOfBins - 1;
8,579,256✔
4590
  pInfo->normalized = normalized;
8,579,256✔
4591
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
61,157,448✔
4592
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
52,578,192✔
4593
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
52,578,192✔
4594
    pInfo->bins[i].count = 0;
52,578,192✔
4595
  }
4596

4597
  taosMemoryFree(intervals);
8,579,256✔
4598
  cJSON_Delete(binDesc);
8,579,280✔
4599

4600
  return TSDB_CODE_SUCCESS;
8,579,297✔
4601
}
4602

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

4611
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
8,579,183✔
4612
  pInfo->numOfBins = 0;
8,579,183✔
4613
  pInfo->totalCount = 0;
8,579,183✔
4614
  pInfo->normalized = 0;
8,579,183✔
4615

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

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

4642
  return TSDB_CODE_SUCCESS;
8,579,349✔
4643
}
4644

4645
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
8,655,841✔
4646
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,655,841✔
4647

4648
  SInputColumnInfoData* pInput = &pCtx->input;
8,655,841✔
4649
  SColumnInfoData*      pCol = pInput->pData[0];
8,655,841✔
4650

4651
  int32_t type = pInput->pData[0]->info.type;
8,655,841✔
4652

4653
  int32_t start = pInput->startRowIndex;
8,655,841✔
4654
  int32_t numOfRows = pInput->numOfRows;
8,655,841✔
4655

4656
  int32_t numOfElems = 0;
8,655,841✔
4657
  for (int32_t i = start; i < numOfRows + start; ++i) {
29,156,646✔
4658
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
20,500,805✔
4659
      continue;
808,370✔
4660
    }
4661

4662
    numOfElems++;
19,692,435✔
4663

4664
    char*  data = colDataGetData(pCol, i);
19,692,435!
4665
    double v;
4666
    GET_TYPED_DATA(v, double, type, data);
19,692,435!
4667

4668
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
56,005,604✔
4669
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
49,468,284✔
4670
        pInfo->bins[k].count++;
13,155,115✔
4671
        pInfo->totalCount++;
13,155,115✔
4672
        break;
13,155,115✔
4673
      }
4674
    }
4675
  }
4676

4677
  if (!isPartial) {
8,655,841✔
4678
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
6,828,413✔
4679
  } else {
4680
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,827,428✔
4681
  }
4682
  return TSDB_CODE_SUCCESS;
8,655,841✔
4683
}
4684

4685
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
6,828,470✔
4686

4687
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
1,827,525✔
4688

4689
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
1,763,953✔
4690
  pOutput->normalized = pInput->normalized;
1,763,953✔
4691
  pOutput->numOfBins = pInput->numOfBins;
1,763,953✔
4692
  pOutput->totalCount += pInput->totalCount;
1,763,953✔
4693
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
14,116,499✔
4694
    pOutput->bins[k].lower = pInput->bins[k].lower;
12,352,546✔
4695
    pOutput->bins[k].upper = pInput->bins[k].upper;
12,352,546✔
4696
    pOutput->bins[k].count += pInput->bins[k].count;
12,352,546✔
4697
  }
4698
}
1,763,953✔
4699

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

4707
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,763,952✔
4708

4709
  int32_t start = pInput->startRowIndex;
1,763,952✔
4710

4711
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,527,905✔
4712
    char*           data = colDataGetData(pCol, i);
1,763,953!
4713
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
1,763,953✔
4714
    histogramTransferInfo(pInputInfo, pInfo);
1,763,953✔
4715
  }
4716

4717
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
1,763,952!
4718
  return TSDB_CODE_SUCCESS;
1,763,952✔
4719
}
4720

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

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

4733
  if (pInfo->normalized) {
8,508,291✔
4734
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
60,621,435✔
4735
      if (pInfo->totalCount != 0) {
52,118,434✔
4736
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
39,355,352✔
4737
      } else {
4738
        pInfo->bins[k].percentage = 0;
12,763,082✔
4739
      }
4740
    }
4741
  }
4742

4743
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
60,639,840✔
4744
    int32_t len;
4745
    char    buf[512] = {0};
52,148,354✔
4746
    if (!pInfo->normalized) {
52,148,354✔
4747
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}",
33,453✔
4748
                    pInfo->bins[i].lower, pInfo->bins[i].upper, pInfo->bins[i].count);
4749
    } else {
4750
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower,
52,114,901✔
4751
                    pInfo->bins[i].upper, pInfo->bins[i].percentage);
4752
    }
4753
    varDataSetLen(buf, len);
52,147,701✔
4754
    code = colDataSetVal(pCol, currentRow, buf, false);
52,147,701✔
4755
    if (TSDB_CODE_SUCCESS != code) {
52,131,549!
4756
      return code;
×
4757
    }
4758
    currentRow++;
52,131,549✔
4759
  }
4760

4761
  return code;
8,491,486✔
4762
}
4763

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

4770
  if (NULL == res) {
1,780,472!
4771
    return terrno;
×
4772
  }
4773
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,780,472✔
4774
  varDataSetLen(res, resultBytes);
1,780,472✔
4775

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

4785
_exit:
1,780,472✔
4786
  taosMemoryFree(res);
1,780,472✔
4787
  return code;
1,780,473✔
4788
}
4789

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

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

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

4803
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,615✔
4804

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

4810
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
3,490,755✔
4811
  uint64_t hash = MurmurHash3_64(data, bytes);
3,490,755✔
4812
  int32_t  index = hash & HLL_BUCKET_MASK;
3,490,145✔
4813
  hash >>= HLL_BUCKET_BITS;
3,490,145✔
4814
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
3,490,145✔
4815
  uint64_t bit = 1;
3,490,145✔
4816
  uint8_t  count = 1;
3,490,145✔
4817
  while ((hash & bit) == 0) {
6,815,015✔
4818
    count++;
3,324,870✔
4819
    bit <<= 1;
3,324,870✔
4820
  }
4821
  *buk = index;
3,490,145✔
4822
  return count;
3,490,145✔
4823
}
4824

4825
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
241,141✔
4826
  uint64_t* word = (uint64_t*)buckets;
241,141✔
4827
  uint8_t*  bytes;
4828

4829
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
486,811,320✔
4830
    if (*word == 0) {
486,570,179✔
4831
      bucketHisto[0] += 8;
485,853,830✔
4832
    } else {
4833
      bytes = (uint8_t*)word;
716,349✔
4834
      bucketHisto[bytes[0]]++;
716,349✔
4835
      bucketHisto[bytes[1]]++;
716,349✔
4836
      bucketHisto[bytes[2]]++;
716,349✔
4837
      bucketHisto[bytes[3]]++;
716,349✔
4838
      bucketHisto[bytes[4]]++;
716,349✔
4839
      bucketHisto[bytes[5]]++;
716,349✔
4840
      bucketHisto[bytes[6]]++;
716,349✔
4841
      bucketHisto[bytes[7]]++;
716,349✔
4842
    }
4843
    word++;
486,570,179✔
4844
  }
4845
}
241,141✔
4846
static double hllTau(double x) {
241,142✔
4847
  if (x == 0. || x == 1.) return 0.;
241,142!
4848
  double zPrime;
4849
  double y = 1.0;
×
4850
  double z = 1 - x;
×
4851
  do {
4852
    x = sqrt(x);
×
4853
    zPrime = z;
×
4854
    y *= 0.5;
×
4855
    z -= pow(1 - x, 2) * y;
×
4856
  } while (zPrime != z);
×
4857
  return z / 3;
×
4858
}
4859

4860
static double hllSigma(double x) {
241,150✔
4861
  if (x == 1.0) return INFINITY;
241,150✔
4862
  double zPrime;
4863
  double y = 1;
211,149✔
4864
  double z = x;
211,149✔
4865
  do {
4866
    x *= x;
4,143,141✔
4867
    zPrime = z;
4,143,141✔
4868
    z += x * y;
4,143,141✔
4869
    y += y;
4,143,141✔
4870
  } while (zPrime != z);
4,143,141✔
4871
  return z;
211,149✔
4872
}
4873

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

4881
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
241,143✔
4882
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
12,295,345✔
4883
    z += buckethisto[j];
12,054,195✔
4884
    z *= 0.5;
12,054,195✔
4885
  }
4886

4887
  z += m * hllSigma(buckethisto[0] / (double)m);
241,150✔
4888
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
241,155✔
4889

4890
  return (uint64_t)E;
241,155✔
4891
}
4892

4893
int32_t hllFunction(SqlFunctionCtx* pCtx) {
265,894✔
4894
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
265,894✔
4895

4896
  SInputColumnInfoData* pInput = &pCtx->input;
265,894✔
4897
  SColumnInfoData*      pCol = pInput->pData[0];
265,894✔
4898

4899
  int32_t type = pCol->info.type;
265,894✔
4900
  int32_t bytes = pCol->info.bytes;
265,894✔
4901

4902
  int32_t start = pInput->startRowIndex;
265,894✔
4903
  int32_t numOfRows = pInput->numOfRows;
265,894✔
4904

4905
  int32_t numOfElems = 0;
265,894✔
4906
  if (IS_NULL_TYPE(type)) {
265,894✔
4907
    goto _hll_over;
1,695✔
4908
  }
4909

4910
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,833,085✔
4911
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
6,376,570!
4912
      continue;
1,077,384✔
4913
    }
4914

4915
    numOfElems++;
3,492,052✔
4916

4917
    char* data = colDataGetData(pCol, i);
3,492,052!
4918
    if (IS_VAR_DATA_TYPE(type)) {
3,492,052!
4919
      bytes = varDataLen(data);
994,509✔
4920
      data = varDataVal(data);
994,509✔
4921
    }
4922

4923
    int32_t index = 0;
3,492,052✔
4924
    uint8_t count = hllCountNum(data, bytes, &index);
3,492,052✔
4925
    uint8_t oldcount = pInfo->buckets[index];
3,491,502✔
4926
    if (count > oldcount) {
3,491,502✔
4927
      pInfo->buckets[index] = count;
728,889✔
4928
    }
4929
  }
4930

4931
_hll_over:
263,649✔
4932
  pInfo->totalCount += numOfElems;
265,344✔
4933

4934
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
265,344✔
4935
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
1,868✔
4936
  } else {
4937
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
263,476✔
4938
  }
4939

4940
  return TSDB_CODE_SUCCESS;
265,344✔
4941
}
4942

4943
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
10,905✔
4944
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
175,065,075✔
4945
    if (pOutput->buckets[k] < pInput->buckets[k]) {
175,054,170✔
4946
      pOutput->buckets[k] = pInput->buckets[k];
85,669✔
4947
    }
4948
  }
4949
  pOutput->totalCount += pInput->totalCount;
10,905✔
4950
}
10,905✔
4951

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

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

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

4965
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,841✔
4966

4967
  int32_t start = pInput->startRowIndex;
10,841✔
4968

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

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

4982
  return TSDB_CODE_SUCCESS;
10,841✔
4983
}
4984

4985
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
241,111✔
4986
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
241,111✔
4987

4988
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
241,111✔
4989
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
241,111✔
4990
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
241,161✔
4991
    pInfo->numOfRes = 1;
28,167✔
4992
  }
4993

4994
  return functionFinalize(pCtx, pBlock);
241,161✔
4995
}
4996

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

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

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

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

5019
_exit:
10,616✔
5020
  taosMemoryFree(res);
10,616✔
5021
  return code;
10,616✔
5022
}
5023

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

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

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

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

5042
static int8_t getStateOpType(char* opStr) {
143,195✔
5043
  int8_t opType;
5044
  if (strncasecmp(opStr, "LT", 2) == 0) {
143,195✔
5045
    opType = STATE_OPER_LT;
1,081✔
5046
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
142,114✔
5047
    opType = STATE_OPER_GT;
110,525✔
5048
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
31,589✔
5049
    opType = STATE_OPER_LE;
992✔
5050
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
30,597✔
5051
    opType = STATE_OPER_GE;
1,941✔
5052
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
28,656✔
5053
    opType = STATE_OPER_NE;
1,847✔
5054
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
26,809!
5055
    opType = STATE_OPER_EQ;
26,810✔
5056
  } else {
5057
    opType = STATE_OPER_INVALID;
×
5058
  }
5059

5060
  return opType;
143,195✔
5061
}
5062

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

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

5128
  SInputColumnInfoData* pInput = &pCtx->input;
55,822✔
5129
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
55,822✔
5130

5131
  SColumnInfoData* pInputCol = pInput->pData[0];
55,822✔
5132

5133
  int32_t          numOfElems = 0;
55,822✔
5134
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
55,822✔
5135

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

5141
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
12,436,235✔
5142
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
12,380,413!
5143
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5144
    } else {
5145
      pInfo->prevTs = tsList[i];
12,380,413✔
5146
    }
5147

5148
    pInfo->isPrevTsSet = true;
12,380,413✔
5149
    numOfElems++;
12,380,413✔
5150

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

5163
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
12,297,089✔
5164

5165
    int64_t output = -1;
12,297,089✔
5166
    if (ret) {
12,297,089✔
5167
      output = ++pInfo->count;
3,591,215✔
5168
    } else {
5169
      pInfo->count = 0;
8,705,874✔
5170
    }
5171
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
12,297,089✔
5172
    if (TSDB_CODE_SUCCESS != code) {
12,297,089!
5173
      return code;
×
5174
    }
5175

5176
    // handle selectivity
5177
    if (pCtx->subsidiaries.num > 0) {
12,297,089✔
5178
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,647,312✔
5179
      if (TSDB_CODE_SUCCESS != code) {
3,647,312!
5180
        return code;
×
5181
      }
5182
    }
5183
  }
5184

5185
  pResInfo->numOfRes = numOfElems;
55,822✔
5186
  return TSDB_CODE_SUCCESS;
55,822✔
5187
}
5188

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

5194
  SInputColumnInfoData* pInput = &pCtx->input;
87,373✔
5195
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
87,373✔
5196

5197
  SColumnInfoData* pInputCol = pInput->pData[0];
87,373✔
5198

5199
  int32_t          numOfElems = 0;
87,373✔
5200
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
87,373✔
5201

5202
  // TODO: process timeUnit for different db precisions
5203
  int32_t timeUnit = 1;
87,373✔
5204
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
87,373✔
5205
    timeUnit = pCtx->param[3].param.i;
85,413✔
5206
  }
5207

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

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

5220
    pInfo->isPrevTsSet = true;
23,109,781✔
5221
    numOfElems++;
23,109,781✔
5222

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

5235
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
22,768,397✔
5236
    int64_t output = -1;
22,768,397✔
5237
    if (ret) {
22,768,397✔
5238
      if (pInfo->durationStart == 0) {
9,815,481✔
5239
        output = 0;
5,518,823✔
5240
        pInfo->durationStart = tsList[i];
5,518,823✔
5241
      } else {
5242
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
4,296,658✔
5243
      }
5244
    } else {
5245
      pInfo->durationStart = 0;
12,952,916✔
5246
    }
5247
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
22,768,397✔
5248
    if (TSDB_CODE_SUCCESS != code) {
22,768,397!
5249
      return code;
×
5250
    }
5251

5252
    // handle selectivity
5253
    if (pCtx->subsidiaries.num > 0) {
22,768,397✔
5254
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
16,417,246✔
5255
      if (TSDB_CODE_SUCCESS != code) {
16,417,246!
5256
        return code;
×
5257
      }
5258
    }
5259
  }
5260

5261
  pResInfo->numOfRes = numOfElems;
87,374✔
5262
  return TSDB_CODE_SUCCESS;
87,374✔
5263
}
5264

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

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

5275
  SInputColumnInfoData* pInput = &pCtx->input;
23,600✔
5276
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
23,600✔
5277

5278
  SColumnInfoData* pInputCol = pInput->pData[0];
23,600✔
5279
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
23,600✔
5280

5281
  int32_t numOfElems = 0;
23,600✔
5282
  int32_t type = pInputCol->info.type;
23,600✔
5283
  int32_t startOffset = pCtx->offset;
23,600✔
5284
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
3,999,969✔
5285
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,976,355✔
5286
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5287
    } else {
5288
      pSumRes->prevTs = tsList[i];
3,976,337✔
5289
    }
5290
    pSumRes->isPrevTsSet = true;
3,976,337✔
5291

5292
    int32_t pos = startOffset + numOfElems;
3,976,337✔
5293
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,976,337✔
5294
      // colDataSetNULL(pOutput, i);
5295
      continue;
317,372✔
5296
    }
5297

5298
    char* data = colDataGetData(pInputCol, i);
3,658,965!
5299
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
6,860,942!
5300
      int64_t v;
5301
      GET_TYPED_DATA(v, int64_t, type, data);
3,201,948!
5302
      pSumRes->isum += v;
3,201,948✔
5303
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
3,201,948✔
5304
      if (TSDB_CODE_SUCCESS != code) {
3,201,977!
5305
        return code;
×
5306
      }
5307
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
457,697!
5308
      uint64_t v;
5309
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5310
      pSumRes->usum += v;
680✔
5311
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5312
      if (TSDB_CODE_SUCCESS != code) {
680!
5313
        return code;
×
5314
      }
5315
    } else if (IS_FLOAT_TYPE(type)) {
456,337!
5316
      double v;
5317
      GET_TYPED_DATA(v, double, type, data);
456,440!
5318
      pSumRes->dsum += v;
456,440✔
5319
      // check for overflow
5320
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
456,440✔
5321
        colDataSetNULL(pOutput, pos);
109✔
5322
      } else {
5323
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
456,331✔
5324
        if (TSDB_CODE_SUCCESS != code) {
456,334!
5325
          return code;
×
5326
        }
5327
      }
5328
    }
5329

5330
    // handle selectivity
5331
    if (pCtx->subsidiaries.num > 0) {
3,658,997✔
5332
      code = appendSelectivityValue(pCtx, i, pos);
1,999,442✔
5333
      if (TSDB_CODE_SUCCESS != code) {
1,999,442!
5334
        return code;
×
5335
      }
5336
    }
5337

5338
    numOfElems++;
3,658,997✔
5339
  }
5340

5341
  pResInfo->numOfRes = numOfElems;
23,614✔
5342
  return TSDB_CODE_SUCCESS;
23,614✔
5343
}
5344

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

5350
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
253,215✔
5351
  if (pResultInfo->initialized) {
253,215✔
5352
    return TSDB_CODE_SUCCESS;
238,544✔
5353
  }
5354
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,671!
5355
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5356
  }
5357

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

5369
  return TSDB_CODE_SUCCESS;
14,673✔
5370
}
5371

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

5377
  SInputColumnInfoData* pInput = &pCtx->input;
239,549✔
5378
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
239,549✔
5379

5380
  SColumnInfoData* pInputCol = pInput->pData[0];
239,549✔
5381
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
239,549✔
5382
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
239,549✔
5383

5384
  int32_t numOfElems = 0;
239,549✔
5385
  int32_t type = pInputCol->info.type;
239,549✔
5386
  int32_t startOffset = pCtx->offset;
239,549✔
5387
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
58,958,314✔
5388
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
58,718,748!
5389
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5390
    } else {
5391
      pInfo->prevTs = tsList[i];
58,718,748✔
5392
    }
5393
    pInfo->isPrevTsSet = true;
58,718,748✔
5394

5395
    int32_t pos = startOffset + numOfElems;
58,718,748✔
5396
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
58,718,748✔
5397
      // colDataSetNULL(pOutput, i);
5398
      continue;
255,525✔
5399
    }
5400

5401
    char*  data = colDataGetData(pInputCol, i);
58,463,223!
5402
    double v;
5403
    GET_TYPED_DATA(v, double, type, data);
58,463,223!
5404

5405
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
58,463,223✔
5406
      pInfo->points[pInfo->pos] = v;
6,643,938✔
5407
      pInfo->sum += v;
6,643,938✔
5408
    } else {
5409
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
51,819,285!
5410
        pInfo->sum += v;
11,754✔
5411
        pInfo->pointsMeet = true;
11,754✔
5412
      } else {
5413
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
51,807,531✔
5414
      }
5415

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

5428
      // handle selectivity
5429
      if (pCtx->subsidiaries.num > 0) {
51,819,302✔
5430
        code = appendSelectivityValue(pCtx, i, pos);
32,260,406✔
5431
        if (TSDB_CODE_SUCCESS != code) {
32,260,406!
5432
          return code;
×
5433
        }
5434
      }
5435

5436
      numOfElems++;
51,819,302✔
5437
    }
5438

5439
    pInfo->pos++;
58,463,240✔
5440
    if (pInfo->pos == pInfo->numOfPoints) {
58,463,240✔
5441
      pInfo->pos = 0;
88,045✔
5442
    }
5443
  }
5444

5445
  pResInfo->numOfRes = numOfElems;
239,566✔
5446
  return TSDB_CODE_SUCCESS;
239,566✔
5447
}
5448

5449
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
13,586,759✔
5450
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,586,759✔
5451
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
13,586,759✔
5452

5453
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
13,586,759✔
5454
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
13,586,759✔
5455

5456
  return pInfo;
13,586,759✔
5457
}
5458

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

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

5475
  taosSeedRand(taosSafeRand());
6,816,496✔
5476

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

5488
  return TSDB_CODE_SUCCESS;
6,816,496✔
5489
}
5490

5491
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
14,922,490✔
5492
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
14,922,490✔
5493
}
14,922,390✔
5494

5495
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
17,013,852✔
5496
  pInfo->totalPoints++;
17,013,852✔
5497
  if (pInfo->numSampled < pInfo->samples) {
17,013,852✔
5498
    sampleAssignResult(pInfo, data, pInfo->numSampled);
13,062,278✔
5499
    if (pCtx->subsidiaries.num > 0) {
13,062,207✔
5500
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,440,844✔
5501
      if (code != TSDB_CODE_SUCCESS) {
1,440,990!
5502
        return code;
×
5503
      }
5504
    }
5505
    pInfo->numSampled++;
13,062,353✔
5506
  } else {
5507
    int32_t j = taosRand() % (pInfo->totalPoints);
3,951,574✔
5508
    if (j < pInfo->samples) {
3,956,282✔
5509
      sampleAssignResult(pInfo, data, j);
1,863,237✔
5510
      if (pCtx->subsidiaries.num > 0) {
1,863,218✔
5511
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
780,006✔
5512
        if (code != TSDB_CODE_SUCCESS) {
775,879!
5513
          return code;
×
5514
        }
5515
      }
5516
    }
5517
  }
5518

5519
  return TSDB_CODE_SUCCESS;
17,014,489✔
5520
}
5521

5522
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
6,937,493✔
5523
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,937,493✔
5524
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
6,937,493✔
5525

5526
  SInputColumnInfoData* pInput = &pCtx->input;
6,937,493✔
5527

5528
  SColumnInfoData* pInputCol = pInput->pData[0];
6,937,493✔
5529
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
24,089,103✔
5530
    if (colDataIsNull_s(pInputCol, i)) {
34,302,262✔
5531
      continue;
137,357✔
5532
    }
5533

5534
    char*   data = colDataGetData(pInputCol, i);
17,013,774!
5535
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
17,013,774✔
5536
    if (code != TSDB_CODE_SUCCESS) {
17,014,253!
5537
      return code;
×
5538
    }
5539
  }
5540

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

5549
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
6,937,972✔
5550
  return TSDB_CODE_SUCCESS;
6,937,972✔
5551
}
5552

5553
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,649,267✔
5554
  int32_t              code = TSDB_CODE_SUCCESS;
6,649,267✔
5555
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6,649,267✔
5556

5557
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
6,649,267✔
5558
  pEntryInfo->complete = true;
6,649,267✔
5559

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

5566
  int32_t currentRow = pBlock->info.rows;
6,649,266✔
5567
  if (pInfo->numSampled == 0) {
6,649,266✔
5568
    colDataSetNULL(pCol, currentRow);
1,065✔
5569
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
1,065✔
5570
    return code;
1,065✔
5571
  }
5572
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
19,509,502✔
5573
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
12,861,389✔
5574
    if (TSDB_CODE_SUCCESS != code) {
12,861,442!
5575
      return code;
×
5576
    }
5577
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
12,861,442✔
5578
    if (TSDB_CODE_SUCCESS != code) {
12,861,301!
5579
      return code;
×
5580
    }
5581
  }
5582

5583
  return code;
6,648,113✔
5584
}
5585

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

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

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

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

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

5627
  return TSDB_CODE_SUCCESS;
×
5628
}
5629

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5824
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
7,583✔
5825
  pEnv->calcMemSize = sizeof(SModeInfo);
7,583✔
5826
  return true;
7,583✔
5827
}
5828

5829
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
7,470✔
5830
  if (pResInfo->initialized) {
7,470!
5831
    return TSDB_CODE_SUCCESS;
×
5832
  }
5833
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
7,470!
5834
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5835
  }
5836

5837
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,470✔
5838
  pInfo->colType = pCtx->resDataInfo.type;
7,470✔
5839
  pInfo->colBytes = pCtx->resDataInfo.bytes;
7,470✔
5840
  if (pInfo->pHash != NULL) {
7,470!
5841
    taosHashClear(pInfo->pHash);
×
5842
  } else {
5843
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
7,470✔
5844
    if (NULL == pInfo->pHash) {
7,470!
5845
      return terrno;
×
5846
    }
5847
  }
5848
  pInfo->nullTupleSaved = false;
7,470✔
5849
  pInfo->nullTuplePos.pageId = -1;
7,470✔
5850

5851
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
7,470✔
5852
  if (NULL == pInfo->buf) {
7,471!
5853
    taosHashCleanup(pInfo->pHash);
×
5854
    pInfo->pHash = NULL;
×
5855
    return terrno;
×
5856
  }
5857
  pCtx->needCleanup = true;
7,471✔
5858
  return TSDB_CODE_SUCCESS;
7,471✔
5859
}
5860

5861
static void modeFunctionCleanup(SModeInfo * pInfo) {
7,471✔
5862
  taosHashCleanup(pInfo->pHash);
7,471✔
5863
  pInfo->pHash = NULL;
7,472✔
5864
  taosMemoryFreeClear(pInfo->buf);
7,472!
5865
}
7,472✔
5866

5867
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5868
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5869
    return;
×
5870
  }
5871
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5872
}
5873

5874
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo *pInfo, STuplePos* pPos) {
266,743✔
5875
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
266,743!
5876
    (void)memcpy(pInfo->buf, data, varDataTLen(data));
110✔
5877
  } else {
5878
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
266,633✔
5879
  }
5880

5881
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
266,743✔
5882
}
5883

5884
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
8,564,615✔
5885
  int32_t code = TSDB_CODE_SUCCESS;
8,564,615✔
5886
  int32_t hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
8,564,615✔
5887

5888
  SModeItem* pHashItem = (SModeItem *)taosHashGet(pInfo->pHash, data, hashKeyBytes);
8,564,615✔
5889
  if (pHashItem == NULL) {
8,564,347✔
5890
    int32_t    size = sizeof(SModeItem);
266,691✔
5891
    SModeItem  item = {0};
266,691✔
5892

5893
    item.count += 1;
266,691✔
5894
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
266,691✔
5895
    if (code != TSDB_CODE_SUCCESS) {
266,586!
5896
      return code;
×
5897
    }
5898

5899
    if (pCtx->subsidiaries.num > 0) {
266,586✔
5900
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
3,170✔
5901
      if (code != TSDB_CODE_SUCCESS) {
3,170!
5902
        return code;
×
5903
      }
5904
    }
5905

5906
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
266,586✔
5907
    if (code != TSDB_CODE_SUCCESS) {
267,058!
5908
      return code;
×
5909
    }
5910
  } else {
5911
    pHashItem->count += 1;
8,297,656✔
5912
    if (pCtx->subsidiaries.num > 0) {
8,297,656✔
5913
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
8,274,935✔
5914
      if (code != TSDB_CODE_SUCCESS) {
8,274,935!
5915
        return code;
×
5916
      }
5917
    }
5918
  }
5919

5920
  return code;
8,564,714✔
5921
}
5922

5923
int32_t modeFunction(SqlFunctionCtx* pCtx) {
42,694✔
5924
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
42,694✔
5925
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
42,694✔
5926

5927
  SInputColumnInfoData* pInput = &pCtx->input;
42,694✔
5928

5929
  SColumnInfoData* pInputCol = pInput->pData[0];
42,694✔
5930
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
42,694✔
5931

5932
  int32_t numOfElems = 0;
42,694✔
5933
  int32_t startOffset = pCtx->offset;
42,694✔
5934
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
9,279,689✔
5935
    if (colDataIsNull_s(pInputCol, i)) {
18,473,936✔
5936
      continue;
672,605✔
5937
    }
5938
    numOfElems++;
8,564,363✔
5939

5940
    char*   data = colDataGetData(pInputCol, i);
8,564,363!
5941
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
8,564,363✔
5942
    if (code != TSDB_CODE_SUCCESS) {
8,564,710✔
5943
      modeFunctionCleanup(pInfo);
320✔
5944
      return code;
×
5945
    }
5946
  }
5947

5948
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
42,721!
5949
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
5950
    if (code != TSDB_CODE_SUCCESS) {
50!
5951
      modeFunctionCleanup(pInfo);
×
5952
      return code;
×
5953
    }
5954
    pInfo->nullTupleSaved = true;
50✔
5955
  }
5956

5957
  SET_VAL(pResInfo, numOfElems, 1);
42,721✔
5958

5959
  return TSDB_CODE_SUCCESS;
42,721✔
5960
}
5961

5962
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,471✔
5963
  int32_t              code = TSDB_CODE_SUCCESS;
7,471✔
5964
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,471✔
5965
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,471✔
5966
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
7,471✔
5967
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,471✔
5968
  int32_t              currentRow = pBlock->info.rows;
7,470✔
5969
  if (NULL == pCol) {
7,470!
5970
    modeFunctionCleanup(pInfo);
×
5971
    return TSDB_CODE_OUT_OF_RANGE;
×
5972
  }
5973

5974
  STuplePos resDataPos, resTuplePos;
5975
  int32_t maxCount = 0;
7,470✔
5976

5977
  void *pIter = taosHashIterate(pInfo->pHash, NULL);
7,470✔
5978
  while (pIter != NULL) {
274,587✔
5979
    SModeItem *pItem = (SModeItem *)pIter;
267,116✔
5980
    if (pItem->count >= maxCount) {
267,116✔
5981
      maxCount = pItem->count;
260,147✔
5982
      resDataPos = pItem->dataPos;
260,147✔
5983
      resTuplePos = pItem->tuplePos;
260,147✔
5984
    }
5985

5986
    pIter = taosHashIterate(pInfo->pHash, pIter);
267,116✔
5987
  }
5988

5989
  if (maxCount != 0) {
7,471✔
5990
    char* pData = NULL;
3,840✔
5991
    code = loadTupleData(pCtx, &resDataPos, &pData);
3,840✔
5992
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
3,840!
5993
      code = terrno = TSDB_CODE_NOT_FOUND;
×
5994
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
5995
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
5996
      modeFunctionCleanup(pInfo);
×
5997
      return code;
×
5998
    }
5999

6000
    code = colDataSetVal(pCol, currentRow, pData, false);
3,840✔
6001
    if (TSDB_CODE_SUCCESS != code) {
3,840!
6002
      modeFunctionCleanup(pInfo);
×
6003
     return code;
×
6004
    }
6005
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
3,840✔
6006
  } else {
6007
    colDataSetNULL(pCol, currentRow);
3,631✔
6008
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
3,631✔
6009
  }
6010

6011
  modeFunctionCleanup(pInfo);
7,471✔
6012

6013
  return code;
7,472✔
6014
}
6015

6016
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
76,551✔
6017
  pEnv->calcMemSize = sizeof(STwaInfo);
76,551✔
6018
  return true;
76,551✔
6019
}
6020

6021
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
11,144,259✔
6022
  if (pResultInfo->initialized) {
11,144,259!
6023
    return TSDB_CODE_SUCCESS;
×
6024
  }
6025
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
11,144,259!
6026
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6027
  }
6028

6029
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
11,144,265✔
6030
  pInfo->numOfElems = 0;
11,144,265✔
6031
  pInfo->p.key = INT64_MIN;
11,144,265✔
6032
  pInfo->win = TSWINDOW_INITIALIZER;
11,144,265✔
6033
  return TSDB_CODE_SUCCESS;
11,144,265✔
6034
}
6035

6036
static double twa_get_area(SPoint1 s, SPoint1 e) {
33,512,629✔
6037
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
33,512,629!
6038
    return 0;
×
6039
  }
6040

6041
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
33,512,909✔
6042
    return (s.val + e.val) * (e.key - s.key) / 2;
19,681,782✔
6043
  }
6044

6045
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
13,831,127✔
6046
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
13,831,127✔
6047
  return val;
13,831,127✔
6048
}
6049

6050
int32_t twaFunction(SqlFunctionCtx* pCtx) {
11,144,748✔
6051
  int32_t               code = TSDB_CODE_SUCCESS;
11,144,748✔
6052
  SInputColumnInfoData* pInput = &pCtx->input;
11,144,748✔
6053
  SColumnInfoData*      pInputCol = pInput->pData[0];
11,144,748✔
6054

6055
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
11,144,748✔
6056
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
11,144,748✔
6057
  SPoint1*             last = &pInfo->p;
11,144,748✔
6058

6059
  if (IS_NULL_TYPE(pInputCol->info.type)) {
11,144,748!
6060
    pInfo->numOfElems = 0;
×
6061
    goto _twa_over;
×
6062
  }
6063

6064
  funcInputUpdate(pCtx);
11,144,748✔
6065
  SFuncInputRow row = {0};
11,144,764✔
6066
  bool          result = false;
11,144,764✔
6067
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
11,144,764!
6068
    while (1) {
6069
      code = funcInputGetNextRow(pCtx, &row, &result);
3,755,609✔
6070
      if (TSDB_CODE_SUCCESS != code) {
3,755,609!
6071
        return code;
×
6072
      }
6073
      if (!result) {
3,755,609✔
6074
        break;
2✔
6075
      }
6076
      if (row.isDataNull) {
3,755,607✔
6077
        continue;
2✔
6078
      }
6079

6080
      last->key = row.ts;
3,755,605✔
6081

6082
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,755,605!
6083

6084
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
3,755,605✔
6085
      pInfo->win.skey = pCtx->start.key;
3,755,605✔
6086
      pInfo->numOfElems++;
3,755,605✔
6087
      break;
3,755,605✔
6088
    }
6089
  } else if (pInfo->p.key == INT64_MIN) {
7,389,157✔
6090
    while (1) {
6091
      code = funcInputGetNextRow(pCtx, &row, &result);
7,498,530✔
6092
      if (TSDB_CODE_SUCCESS != code) {
7,498,461!
6093
        return code;
×
6094
      }
6095
      if (!result) {
7,498,461✔
6096
        break;
14,242✔
6097
      }
6098
      if (row.isDataNull) {
7,484,219✔
6099
        continue;
109,773✔
6100
      }
6101

6102
      last->key = row.ts;
7,374,446✔
6103

6104
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
7,374,446!
6105

6106
      pInfo->win.skey = last->key;
7,374,446✔
6107
      pInfo->numOfElems++;
7,374,446✔
6108
      break;
7,374,446✔
6109
    }
6110
  }
6111

6112
  SPoint1 st = {0};
11,144,695✔
6113

6114
  // calculate the value of
6115
  while (1) {
6116
    code = funcInputGetNextRow(pCtx, &row, &result);
37,041,844✔
6117
    if (TSDB_CODE_SUCCESS != code) {
37,041,611!
6118
      return code;
×
6119
    }
6120
    if (!result) {
37,041,611✔
6121
      break;
11,144,683✔
6122
    }
6123
    if (row.isDataNull) {
25,896,928✔
6124
      continue;
630✔
6125
    }
6126
    pInfo->numOfElems++;
25,896,298✔
6127
    switch (pInputCol->info.type) {
25,896,298!
6128
      case TSDB_DATA_TYPE_TINYINT: {
919,623✔
6129
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
919,623✔
6130
        break;
919,623✔
6131
      }
6132
      case TSDB_DATA_TYPE_SMALLINT: {
84,460✔
6133
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
84,460✔
6134
        break;
84,460✔
6135
      }
6136
      case TSDB_DATA_TYPE_INT: {
3,050,196✔
6137
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
3,050,196✔
6138
        break;
3,050,196✔
6139
      }
6140
      case TSDB_DATA_TYPE_BIGINT: {
94,411✔
6141
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
94,411✔
6142
        break;
94,411✔
6143
      }
6144
      case TSDB_DATA_TYPE_FLOAT: {
66,349✔
6145
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
66,349✔
6146
        break;
66,349✔
6147
      }
6148
      case TSDB_DATA_TYPE_DOUBLE: {
21,414,068✔
6149
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
21,414,068✔
6150
        break;
21,414,068✔
6151
      }
6152
      case TSDB_DATA_TYPE_UTINYINT: {
69,076✔
6153
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
69,076✔
6154
        break;
69,076✔
6155
      }
6156
      case TSDB_DATA_TYPE_USMALLINT: {
68,532✔
6157
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
68,532✔
6158
        break;
68,532✔
6159
      }
6160
      case TSDB_DATA_TYPE_UINT: {
70,997✔
6161
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
70,997✔
6162
        break;
70,997✔
6163
      }
6164
      case TSDB_DATA_TYPE_UBIGINT: {
59,154✔
6165
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
59,154✔
6166
        break;
59,154✔
6167
      }
6168
      default: {
×
6169
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6170
      }
6171
    }
6172
    if (pInfo->p.key == st.key) {
25,896,866!
6173
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6174
    }
6175

6176
    pInfo->dOutput += twa_get_area(pInfo->p, st);
25,896,866✔
6177
    pInfo->p = st;
25,896,519✔
6178
  }
6179

6180
  // the last interpolated time window value
6181
  if (pCtx->end.key != INT64_MIN) {
11,144,683✔
6182
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
3,861,157✔
6183
    pInfo->p = pCtx->end;
3,861,156✔
6184
    pInfo->numOfElems += 1;
3,861,156✔
6185
  }
6186

6187
  pInfo->win.ekey = pInfo->p.key;
11,144,682✔
6188

6189
_twa_over:
11,144,682✔
6190
  SET_VAL(pResInfo, 1, 1);
11,144,682✔
6191
  return TSDB_CODE_SUCCESS;
11,144,682✔
6192
}
6193

6194
/*
6195
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6196
 * by next input data. The TWA function only applies to each table, so no merge procedure
6197
 * is required, we simply copy to the resut ot interResBuffer.
6198
 */
6199
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6200
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6201
//
6202
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6203
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6204
// }
6205

6206
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
11,133,432✔
6207
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
11,133,432✔
6208

6209
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
11,133,432✔
6210
  if (pInfo->numOfElems == 0) {
11,133,432✔
6211
    pResInfo->numOfRes = 0;
14,181✔
6212
  } else {
6213
    if (pInfo->win.ekey == pInfo->win.skey) {
11,119,251✔
6214
      pInfo->dTwaRes = pInfo->p.val;
5,818,318✔
6215
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
5,300,933!
UNCOV
6216
      pInfo->dTwaRes = 0;
×
6217
    } else {
6218
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
5,300,983✔
6219
    }
6220

6221
    pResInfo->numOfRes = 1;
11,119,251✔
6222
  }
6223

6224
  return functionFinalize(pCtx, pBlock);
11,133,432✔
6225
}
6226

6227
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,626✔
6228
  if (pResultInfo->initialized) {
1,626!
6229
    return TSDB_CODE_SUCCESS;
×
6230
  }
6231
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,626!
6232
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6233
  }
6234

6235
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,626✔
6236
  pInfo->minRows = INT32_MAX;
1,626✔
6237
  return TSDB_CODE_SUCCESS;
1,626✔
6238
}
6239

6240
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,250✔
6241
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,250✔
6242

6243
  SInputColumnInfoData* pInput = &pCtx->input;
3,250✔
6244
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,250✔
6245
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,250✔
6246
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,250✔
6247

6248
  STableBlockDistInfo p1 = {0};
3,250✔
6249
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,250!
6250
    qError("failed to deserialize block dist info");
×
6251
    return TSDB_CODE_FAILED;
×
6252
  }
6253

6254
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,250✔
6255
  pDistInfo->numOfTables += p1.numOfTables;
3,250✔
6256
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,250✔
6257
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,250✔
6258
  pDistInfo->totalSize += p1.totalSize;
3,250✔
6259
  pDistInfo->totalRows += p1.totalRows;
3,250✔
6260
  pDistInfo->numOfFiles += p1.numOfFiles;
3,250✔
6261

6262
  pDistInfo->defMinRows = p1.defMinRows;
3,250✔
6263
  pDistInfo->defMaxRows = p1.defMaxRows;
3,250✔
6264
  pDistInfo->rowSize = p1.rowSize;
3,250✔
6265

6266
  if (pDistInfo->minRows > p1.minRows) {
3,250✔
6267
    pDistInfo->minRows = p1.minRows;
1✔
6268
  }
6269
  if (pDistInfo->maxRows < p1.maxRows) {
3,250✔
6270
    pDistInfo->maxRows = p1.maxRows;
1✔
6271
  }
6272
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,250✔
6273
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,250✔
6274
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,000✔
6275
  }
6276

6277
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,250✔
6278
  return TSDB_CODE_SUCCESS;
3,250✔
6279
}
6280

6281
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,486✔
6282
  SEncoder encoder = {0};
6,486✔
6283
  int32_t  code = 0;
6,486✔
6284
  int32_t  lino;
6285
  int32_t  tlen;
6286
  tEncoderInit(&encoder, buf, bufLen);
6,486✔
6287

6288
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,491!
6289
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
12,978!
6290

6291
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
12,978!
6292
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
12,978!
6293
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
12,978!
6294

6295
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
12,978!
6296
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
12,978!
6297
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
12,978!
6298
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
12,978!
6299
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
12,978!
6300
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
12,978!
6301
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
12,978!
6302
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
12,978!
6303
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
12,978!
6304

6305
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,066✔
6306
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,154!
6307
  }
6308

6309
  tEndEncode(&encoder);
6,489✔
6310

6311
_exit:
6,488✔
6312
  if (code) {
6,488!
6313
    tlen = code;
×
6314
  } else {
6315
    tlen = encoder.pos;
6,488✔
6316
  }
6317
  tEncoderClear(&encoder);
6,488✔
6318
  return tlen;
6,488✔
6319
}
6320

6321
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,250✔
6322
  SDecoder decoder = {0};
3,250✔
6323
  int32_t  code = 0;
3,250✔
6324
  int32_t  lino;
6325
  tDecoderInit(&decoder, buf, bufLen);
3,250✔
6326

6327
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,250!
6328
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,500!
6329

6330
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,500!
6331
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,500!
6332
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,500!
6333

6334
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,500!
6335
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,500!
6336
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,500!
6337
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,500!
6338
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,500!
6339
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,500!
6340
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,500!
6341
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,500!
6342
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,500!
6343

6344
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,250✔
6345
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,000!
6346
  }
6347

6348
_exit:
3,250✔
6349
  tDecoderClear(&decoder);
3,250✔
6350
  return code;
3,250✔
6351
}
6352

6353
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,626✔
6354
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,626✔
6355
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,626✔
6356

6357
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,626✔
6358
  if (NULL == pColInfo) {
1,626!
6359
    return TSDB_CODE_OUT_OF_RANGE;
×
6360
  }
6361

6362
  if (pData->totalRows == 0) {
1,626✔
6363
    pData->minRows = 0;
1,625✔
6364
  }
6365

6366
  int32_t row = 0;
1,626✔
6367
  char    st[256] = {0};
1,626✔
6368
  double  averageSize = 0;
1,626✔
6369
  if (pData->numOfBlocks != 0) {
1,626✔
6370
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1✔
6371
  }
6372
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,626✔
6373
  double   compRatio = 0;
1,626✔
6374
  if (totalRawSize != 0) {
1,626✔
6375
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1✔
6376
  }
6377

6378
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,252✔
6379
                        "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6380
                        pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,626✔
6381

6382
  varDataSetLen(st, len);
1,626✔
6383
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,626✔
6384
  if (TSDB_CODE_SUCCESS != code) {
1,626!
6385
    return code;
×
6386
  }
6387

6388
  int64_t avgRows = 0;
1,626✔
6389
  if (pData->numOfBlocks > 0) {
1,626✔
6390
    avgRows = pData->totalRows / pData->numOfBlocks;
1✔
6391
  }
6392

6393
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]",
1,626✔
6394
                pData->totalRows, pData->minRows, pData->maxRows, avgRows);
6395
  varDataSetLen(st, len);
1,626✔
6396
  code = colDataSetVal(pColInfo, row++, st, false);
1,626✔
6397
  if (TSDB_CODE_SUCCESS != code) {
1,626!
6398
    return code;
×
6399
  }
6400

6401
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%d] Stt_Rows=[%d] ", pData->numOfInmemRows, pData->numOfSttRows);
1,626✔
6402
  varDataSetLen(st, len);
1,626✔
6403
  code = colDataSetVal(pColInfo, row++, st, false);
1,626✔
6404
  if (TSDB_CODE_SUCCESS != code) {
1,626!
6405
    return code;
×
6406
  }
6407

6408
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables,
3,252✔
6409
                pData->numOfFiles, pData->numOfVgroups);
1,626✔
6410

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

6417
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,626✔
6418
                "--------------------------------------------------------------------------------");
6419
  varDataSetLen(st, len);
1,626✔
6420
  code = colDataSetVal(pColInfo, row++, st, false);
1,626✔
6421
  if (TSDB_CODE_SUCCESS != code) {
1,626!
6422
    return code;
×
6423
  }
6424

6425
  int32_t maxVal = 0;
1,626✔
6426
  int32_t minVal = INT32_MAX;
1,626✔
6427
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,146✔
6428
    if (maxVal < pData->blockRowsHisto[i]) {
32,520✔
6429
      maxVal = pData->blockRowsHisto[i];
1✔
6430
    }
6431

6432
    if (minVal > pData->blockRowsHisto[i]) {
32,520✔
6433
      minVal = pData->blockRowsHisto[i];
1,627✔
6434
    }
6435
  }
6436

6437
  // maximum number of step is 80
6438
  double factor = pData->numOfBlocks / 80.0;
1,626✔
6439

6440
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,626✔
6441
  int32_t bucketRange = ceil(((double) (pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,626✔
6442

6443
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,146✔
6444
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,520✔
6445

6446
    int32_t num = 0;
32,520✔
6447
    if (pData->blockRowsHisto[i] > 0) {
32,520✔
6448
      num = (pData->blockRowsHisto[i]) / factor;
1✔
6449
    }
6450

6451
    for (int32_t j = 0; j < num; ++j) {
32,600✔
6452
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
80✔
6453
      len += x;
80✔
6454
    }
6455

6456
    if (pData->blockRowsHisto[i] > 0) {
32,520✔
6457
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
1✔
6458
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)", pData->blockRowsHisto[i], v, '%');
1✔
6459
    }
6460

6461
    varDataSetLen(st, len);
32,520✔
6462
    code = colDataSetVal(pColInfo, row++, st, false);
32,520✔
6463
    if (TSDB_CODE_SUCCESS != code) {
32,520!
6464
      return code;
×
6465
    }
6466
  }
6467

6468
  return TSDB_CODE_SUCCESS;
1,626✔
6469
}
6470

6471
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,214✔
6472
  pEnv->calcMemSize = sizeof(SDerivInfo);
31,214✔
6473
  return true;
31,214✔
6474
}
6475

6476
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
86,136✔
6477
  if (pResInfo->initialized) {
86,136✔
6478
    return TSDB_CODE_SUCCESS;
54,792✔
6479
  }
6480
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,344!
6481
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6482
  }
6483

6484
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,344✔
6485

6486
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
31,344✔
6487
  pDerivInfo->prevTs = -1;
31,344✔
6488
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
31,344✔
6489
  pDerivInfo->valueSet = false;
31,344✔
6490
  return TSDB_CODE_SUCCESS;
31,344✔
6491
}
6492

6493
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
54,922✔
6494
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
54,922✔
6495
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
54,922✔
6496

6497
  SInputColumnInfoData* pInput = &pCtx->input;
54,922✔
6498
  SColumnInfoData*      pInputCol = pInput->pData[0];
54,922✔
6499

6500
  int32_t          numOfElems = 0;
54,922✔
6501
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
54,922✔
6502
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
54,922✔
6503
  int32_t          code = TSDB_CODE_SUCCESS;
54,922✔
6504

6505
  funcInputUpdate(pCtx);
54,922✔
6506

6507
  double v = 0;
54,922✔
6508
  if (pCtx->order == TSDB_ORDER_ASC) {
54,922✔
6509
    SFuncInputRow row = {0};
51,595✔
6510
    bool result = false;
51,595✔
6511
    while (1) {
2,746,091✔
6512
      code = funcInputGetNextRow(pCtx, &row, &result);
2,797,686✔
6513
      if (TSDB_CODE_SUCCESS != code) {
2,797,686!
6514
        return code;
×
6515
      }
6516
      if (!result) {
2,797,686✔
6517
        break;
51,595✔
6518
      }
6519
      if (row.isDataNull) {
2,746,091✔
6520
        continue;
32,524✔
6521
      }
6522

6523
      char* d = row.pData;
2,713,567✔
6524
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
2,713,567!
6525

6526
      int32_t pos = pCtx->offset + numOfElems;
2,713,567✔
6527
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
2,713,567✔
6528
        pDerivInfo->valueSet = true;
27,686✔
6529
      } else {
6530
        if (row.ts == pDerivInfo->prevTs) {
2,685,881!
6531
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6532
        }
6533
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
2,685,881✔
6534
        if (pDerivInfo->ignoreNegative && r < 0) {
2,685,881✔
6535
        } else {
6536
          if (isinf(r) || isnan(r)) {
1,635,749!
6537
            colDataSetNULL(pOutput, pos);
×
6538
          } else {
6539
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
1,635,749✔
6540
            if (code != TSDB_CODE_SUCCESS) {
1,635,749!
6541
              return code;
×
6542
            }
6543
          }
6544

6545
          if (pTsOutput != NULL) {
1,635,749!
6546
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6547
          }
6548

6549
          // handle selectivity
6550
          if (pCtx->subsidiaries.num > 0) {
1,635,749✔
6551
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,160,843✔
6552
            if (code != TSDB_CODE_SUCCESS) {
1,160,843!
6553
              return code;
×
6554
            }
6555
          }
6556

6557
          numOfElems++;
1,635,749✔
6558
        }
6559
      }
6560

6561
      pDerivInfo->prevValue = v;
2,713,567✔
6562
      pDerivInfo->prevTs = row.ts;
2,713,567✔
6563
    }
6564
  } else {
6565
    SFuncInputRow row = {0};
3,327✔
6566
    bool          result = false;
3,327✔
6567
    while (1) {
332,020✔
6568
      code = funcInputGetNextRow(pCtx, &row, &result);
335,347✔
6569
      if (TSDB_CODE_SUCCESS != code) {
335,347!
6570
        return code;
×
6571
      }
6572
      if (!result) {
335,347✔
6573
        break;
3,327✔
6574
      }
6575
      if (row.isDataNull) {
332,020✔
6576
        continue;
600✔
6577
      }
6578

6579
      char* d = row.pData;
331,420✔
6580
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
331,420!
6581

6582
      int32_t pos = pCtx->offset + numOfElems;
331,420✔
6583
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
331,420✔
6584
        pDerivInfo->valueSet = true;
3,324✔
6585
      } else {
6586
        if (row.ts == pDerivInfo->prevTs) {
328,096!
6587
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6588
        }
6589
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
328,096✔
6590
        if (pDerivInfo->ignoreNegative && r < 0) {
328,096✔
6591
        } else {
6592
          if (isinf(r) || isnan(r)) {
256,864!
6593
            colDataSetNULL(pOutput, pos);
×
6594
          } else {
6595
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
256,864✔
6596
            if (code != TSDB_CODE_SUCCESS) {
256,864!
6597
              return code;
×
6598
            }
6599
          }
6600

6601
          if (pTsOutput != NULL) {
256,864!
6602
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6603
          }
6604

6605
          // handle selectivity
6606
          if (pCtx->subsidiaries.num > 0) {
256,864✔
6607
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
77,442✔
6608
            if (code != TSDB_CODE_SUCCESS) {
77,442!
6609
              return code;
×
6610
            }
6611
          }
6612
          numOfElems++;
256,864✔
6613
        }
6614
      }
6615

6616
      pDerivInfo->prevValue = v;
331,420✔
6617
      pDerivInfo->prevTs = row.ts;
331,420✔
6618
    }
6619
  }
6620

6621
  pResInfo->numOfRes = numOfElems;
54,922✔
6622

6623
  return TSDB_CODE_SUCCESS;
54,922✔
6624
}
6625

6626
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
2,244,375✔
6627

6628
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
125,398✔
6629
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
125,398✔
6630
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
125,398✔
6631
  return true;
125,594✔
6632
}
6633

6634
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
9,974,846✔
6635
  if (pResInfo->initialized) {
9,974,846!
6636
    return TSDB_CODE_SUCCESS;
×
6637
  }
6638
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
9,974,846!
6639
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6640
  }
6641

6642
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
9,974,837✔
6643

6644
  pInfo->firstKey = INT64_MIN;
9,974,837✔
6645
  pInfo->lastKey = INT64_MIN;
9,974,837✔
6646
  pInfo->firstValue = (double)INT64_MIN;
9,974,837✔
6647
  pInfo->lastValue = (double)INT64_MIN;
9,974,837✔
6648

6649
  pInfo->hasResult = 0;
9,974,837✔
6650
  return TSDB_CODE_SUCCESS;
9,974,837✔
6651
}
6652

6653
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
30,719,044✔
6654
  if (isFirst) {
30,719,044✔
6655
    pRateInfo->firstValue = v;
11,436,402✔
6656
    pRateInfo->firstKey = ts;
11,436,402✔
6657
    if (pRateInfo->firstPk) {
11,436,402✔
6658
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
35!
6659
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6660
    }
6661
  } else {
6662
    pRateInfo->lastValue = v;
19,282,642✔
6663
    pRateInfo->lastKey = ts;
19,282,642✔
6664
    if (pRateInfo->lastPk) {
19,282,642✔
6665
      int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes;
52!
6666
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6667
    }
6668
  }
6669
}
30,719,044✔
6670

6671
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
12,090,667✔
6672
  if (pCtx->hasPrimaryKey) {
12,090,667✔
6673
    if (!isMerge) {
19✔
6674
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6675
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6676
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6677
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6678
    } else {
6679
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6680
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6681
    }
6682
  } else {
6683
    pRateInfo->firstPk = NULL;
12,090,648✔
6684
    pRateInfo->lastPk = NULL;
12,090,648✔
6685
  }  
6686
}
12,090,667✔
6687

6688
int32_t irateFunction(SqlFunctionCtx* pCtx) {
7,861,707✔
6689
  int32_t              code = TSDB_CODE_SUCCESS;
7,861,707✔
6690
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,861,707✔
6691
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,861,707✔
6692

6693
  SInputColumnInfoData* pInput = &pCtx->input;
7,861,707✔
6694
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,861,707✔
6695

6696
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7,861,707✔
6697

6698
  funcInputUpdate(pCtx);
7,861,707✔
6699
  
6700
  initializeRateInfo(pCtx, pRateInfo, false);
7,861,737✔
6701

6702
  int32_t numOfElems = 0;
7,861,701✔
6703
  int32_t type = pInputCol->info.type;
7,861,701✔
6704
  SFuncInputRow row = {0};
7,861,701✔
6705
  bool          result = false;
7,861,701✔
6706
  while (1)  {
17,716,526✔
6707
    code = funcInputGetNextRow(pCtx, &row, &result);
25,578,227✔
6708
    if (TSDB_CODE_SUCCESS != code) {
25,577,224!
6709
      return code;
×
6710
    }
6711
    if (!result) {
25,577,224✔
6712
      break;
7,861,599✔
6713
    }
6714
    if (row.isDataNull) {
17,715,625✔
6715
      continue;
129,972✔
6716
    }
6717

6718
    char*  data = row.pData;
17,585,653✔
6719
    double v = 0;
17,585,653✔
6720
    GET_TYPED_DATA(v, double, type, data);
17,585,653!
6721

6722
    if (INT64_MIN == pRateInfo->lastKey) {
17,585,653✔
6723
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
7,848,062✔
6724
      pRateInfo->hasResult = 1;
7,848,041✔
6725
      continue;
7,848,041✔
6726
    }
6727

6728
    if (row.ts > pRateInfo->lastKey) {
9,737,591✔
6729
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
9,321,286!
6730
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
9,321,288✔
6731
      }
6732
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
9,321,316✔
6733
      continue;
9,321,292✔
6734
    } else if (row.ts == pRateInfo->lastKey) {
416,305!
6735
        return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6736
    }
6737
    
6738

6739
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
416,305!
UNCOV
6740
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);    
×
6741
    } else if (row.ts == pRateInfo->firstKey) {
417,359!
6742
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6743
    }
6744
  }
6745

6746
  numOfElems++;
7,861,599✔
6747
  
6748
  SET_VAL(pResInfo, numOfElems, 1);
7,861,599!
6749
  return TSDB_CODE_SUCCESS;
7,861,599✔
6750
}
6751

6752
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
7,847,552✔
6753
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
7,847,552✔
6754
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
668,312!
6755
    return 0.0;
7,179,240✔
6756
  }
6757

6758
  double diff = 0;
668,312✔
6759
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6760
  // value between two values.
6761
  diff = pRateInfo->lastValue;
668,312✔
6762
  if (diff >= pRateInfo->firstValue) {
668,312✔
6763
    diff -= pRateInfo->firstValue;
332,548✔
6764
  }
6765

6766
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
668,312✔
6767
  if (duration == 0) {
668,312!
6768
    return 0;
×
6769
  }
6770

6771
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
668,312!
6772
}
6773

6774
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
518✔
6775
  if (inputKey > pOutput->lastKey) {
518✔
6776
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
214✔
6777
    if (isFirstKey) {
214✔
6778
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
60✔
6779
    } else {
6780
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
154✔
6781
    }
6782
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
304!
6783
    if (isFirstKey) {
154✔
6784
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
104✔
6785
    } else {
6786
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
50✔
6787
    }
6788
  } else {
6789
    // inputKey < pOutput->firstKey
6790
  }
6791
}
518✔
6792

6793
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
2,114,265✔
6794
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
2,114,265✔
6795
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
2,114,265✔
6796
}
2,114,265✔
6797

6798
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
2,114,524✔
6799
  if ((pInput->firstKey != INT64_MIN && (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
2,114,524!
6800
      (pInput->lastKey != INT64_MIN && (pInput->lastKey  == pOutput->firstKey || pInput->lastKey  == pOutput->lastKey))) {
2,114,524!
6801
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6802
  }
6803

6804
  if (pOutput->hasResult == 0) {
2,114,524✔
6805
    irateCopyInfo(pInput, pOutput);
2,114,265✔
6806
    pOutput->hasResult = pInput->hasResult;
2,114,265✔
6807
    return TSDB_CODE_SUCCESS;
2,114,265✔
6808
  }
6809

6810
  if (pInput->firstKey != INT64_MIN) {
259!
6811
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
259✔
6812
  }
6813

6814
  if (pInput->lastKey != INT64_MIN) {
259!
6815
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
259✔
6816
  }
6817

6818
  pOutput->hasResult = pInput->hasResult;
259✔
6819
  return TSDB_CODE_SUCCESS;
259✔
6820
}
6821

6822
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
2,114,536✔
6823
  SInputColumnInfoData* pInput = &pCtx->input;
2,114,536✔
6824
  SColumnInfoData*      pCol = pInput->pData[0];
2,114,536✔
6825
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
2,114,536!
6826
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6827
  }
6828

6829
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,114,536✔
6830
  initializeRateInfo(pCtx, pInfo, true);
2,114,536✔
6831

6832
  int32_t start = pInput->startRowIndex;
2,114,536✔
6833
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
4,229,072✔
6834
    char*        data = colDataGetData(pCol, i);
2,114,536!
6835
    SRateInfo*   pInputInfo = (SRateInfo*)varDataVal(data);
2,114,536✔
6836
    initializeRateInfo(pCtx, pInfo, true);
2,114,536✔
6837
    if (pInputInfo->hasResult) {
2,114,536✔
6838
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
2,114,524✔
6839
      if (code != TSDB_CODE_SUCCESS) {
2,114,524!
6840
        return code;
×
6841
      }
6842
    }
6843
  }
6844

6845
  if (pInfo->hasResult) {
2,114,536✔
6846
    GET_RES_INFO(pCtx)->numOfRes = 1;
2,114,524✔
6847
  }
6848

6849
  return TSDB_CODE_SUCCESS;
2,114,536✔
6850
}
6851

6852
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,118,692✔
6853
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,118,692✔
6854
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,118,692✔
6855
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
2,118,692✔
6856
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
2,118,692✔
6857

6858
  if (NULL == res) {
2,118,692!
6859
    return terrno;
×
6860
  }
6861
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
2,118,692✔
6862
  varDataSetLen(res, resultBytes);
2,118,692✔
6863

6864
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,118,692✔
6865
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,118,692✔
6866
  if (NULL == pCol) {
2,118,692!
6867
      taosMemoryFree(res);
×
6868
      return TSDB_CODE_OUT_OF_RANGE;
×
6869
  }
6870

6871
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
2,118,692✔
6872

6873
  taosMemoryFree(res);
2,118,692✔
6874
  return code;
2,118,692✔
6875
}
6876

6877
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,847,571✔
6878
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,847,571✔
6879
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,847,571✔
6880
  if (NULL == pCol) {
7,847,554!
6881
    return TSDB_CODE_OUT_OF_RANGE;
×
6882
  }
6883

6884
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,847,554✔
6885
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
7,847,554✔
6886

6887
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,847,554✔
6888
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
7,847,554!
6889
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
7,847,539✔
6890

6891
  return code;
7,847,412✔
6892
}
6893

6894
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
105,433,242✔
6895
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
105,433,242✔
6896
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
105,433,242✔
6897

6898
  SInputColumnInfoData* pInput = &pCtx->input;
105,433,242✔
6899
  SColumnInfoData*      pInputCol = pInput->pData[0];
105,433,242✔
6900

6901
  int32_t startIndex = pInput->startRowIndex;
105,433,242✔
6902

6903
  // escape rest of data blocks to avoid first entry to be overwritten.
6904
  if (pInfo->hasResult) {
105,433,242✔
6905
    goto _group_value_over;
11,359,787✔
6906
  }
6907

6908
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
187,747,145✔
6909
    pInfo->isNull = true;
2,606,303✔
6910
    pInfo->hasResult = true;
2,606,303✔
6911
    goto _group_value_over;
2,606,303✔
6912
  }
6913

6914
  char* data = colDataGetData(pInputCol, startIndex);
91,467,152!
6915
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
91,467,152!
6916
    (void)memcpy(pInfo->data, data,
71,786,487✔
6917
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
71,786,487✔
6918
  } else {
6919
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
19,680,665✔
6920
  }
6921
  pInfo->hasResult = true;
91,467,152✔
6922

6923
_group_value_over:
105,433,242✔
6924

6925
  SET_VAL(pResInfo, 1, 1);
105,433,242✔
6926
  return TSDB_CODE_SUCCESS;
105,433,242✔
6927
}
6928

6929
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) {
104,636,484✔
6930
  return groupConstValueFunction(pCtx);
104,636,484✔
6931
}
6932

6933
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
92,097,314✔
6934
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
92,097,314✔
6935
  int32_t          code = TSDB_CODE_SUCCESS;
92,097,314✔
6936
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
92,097,314✔
6937
  if (NULL == pCol) {
92,241,762!
6938
    return TSDB_CODE_OUT_OF_RANGE;
×
6939
  }
6940

6941
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
92,241,762✔
6942

6943
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
92,241,762✔
6944

6945
  if (pInfo->hasResult) {
92,241,762!
6946
    int32_t currentRow = pBlock->info.rows;
92,261,007✔
6947
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
185,191,105✔
6948
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
92,279,231✔
6949
      if (TSDB_CODE_SUCCESS != code) {
92,930,098!
6950
        return code;
×
6951
      }
6952
    }
6953
  } else {
6954
    pResInfo->numOfRes = 0;
×
6955
  }
6956

6957
  return code;
92,892,629✔
6958
}
6959

6960
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock){
91,895,029✔
6961
  return groupConstValueFinalize(pCtx, pBlock);
91,895,029✔
6962
}
6963

6964
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6965
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6966
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6967

6968
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6969
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6970

6971
  // escape rest of data blocks to avoid first entry to be overwritten.
6972
  if (pDBuf->hasResult) {
×
6973
    goto _group_key_over;
×
6974
  }
6975

6976
  if (pSBuf->isNull) {
×
6977
    pDBuf->isNull = true;
×
6978
    pDBuf->hasResult = true;
×
6979
    goto _group_key_over;
×
6980
  }
6981

6982
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
6983
    (void)memcpy(pDBuf->data, pSBuf->data,
×
6984
           (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data) : varDataTLen(pSBuf->data));
×
6985
  } else {
6986
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
6987
  }
6988

6989
  pDBuf->hasResult = true;
×
6990

6991
_group_key_over:
×
6992

6993
  SET_VAL(pDResInfo, 1, 1);
×
6994
  return TSDB_CODE_SUCCESS;
×
6995
}
6996

6997
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
6,024✔
6998
  int32_t numOfElems = 0;
6,024✔
6999

7000
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,024✔
7001
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,024✔
7002

7003
  SInputColumnInfoData* pInput = &pCtx->input;
6,024✔
7004
  SColumnInfoData*      pInputCol = pInput->pData[0];
6,024✔
7005

7006
  int32_t bytes = pInputCol->info.bytes;
6,024✔
7007
  pInfo->bytes = bytes;
6,024✔
7008

7009
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
6,024✔
7010
  pInfo->pkType = -1;
6,024✔
7011
  __compar_fn_t  pkCompareFn = NULL;
6,024✔
7012
  if (pCtx->hasPrimaryKey) {
6,024✔
7013
    pInfo->pkType = pkCol->info.type;
1,417✔
7014
    pInfo->pkBytes = pkCol->info.bytes;
1,417✔
7015
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
1,417✔
7016
  }
7017

7018
  // TODO it traverse the different way.
7019
  // last_row function does not ignore the null value
7020
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
12,060✔
7021
    numOfElems++;
6,035✔
7022

7023
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
6,035✔
7024
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
6,035!
7025

7026
    TSKEY cts = getRowPTs(pInput->pPTS, i);
6,035✔
7027
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
6,035✔
7028
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
4,881✔
7029
      if (code != TSDB_CODE_SUCCESS) {
4,881!
7030
        return code;
×
7031
      }
7032
      pResInfo->numOfRes = 1;
4,881✔
7033
    }
7034
  }
7035

7036
  SET_VAL(pResInfo, numOfElems, 1);
6,025!
7037
  return TSDB_CODE_SUCCESS;
6,025✔
7038
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc