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

taosdata / TDengine / #5048

10 May 2026 03:11AM UTC coverage: 73.222% (+0.07%) from 73.152%
#5048

push

travis-ci

web-flow
merge: from main to 3.0 branch #35290

353 of 452 new or added lines in 9 files covered. (78.1%)

587 existing lines in 140 files now uncovered.

278189 of 379928 relevant lines covered (73.22%)

135206397.85 hits per line

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

75.78
/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 "decimal.h"
19
#include "function.h"
20
#include "functionResInfoInt.h"
21
#include "geosWrapper.h"
22
#include "query.h"
23
#include "querynodes.h"
24
#include "tanalytics.h"
25
#include "tarray.h"
26
#include "tcompare.h"
27
#include "tdatablock.h"
28
#include "tdigest.h"
29
#include "tfunctionInt.h"
30
#include "tglobal.h"
31
#include "thistogram.h"
32
#include "tpercentile.h"
33
#include "ttime.h"
34
#include "ttypes.h"
35

36
bool ignoreNegative(int8_t ignoreOption) { return (ignoreOption & 0x1) == 0x1; }
2,147,483,647✔
37
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
58,845,910✔
38

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

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

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

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

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

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

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

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

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

113
#define LIST_ADD_DECIMAL_N(_res, _col, _start, _rows, _t, numOfElem)                                  \
114
  do {                                                                                                \
115
    _t*                d = (_t*)(_col->pData);                                                        \
116
    const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);                                  \
117
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {                                         \
118
      if (((_col)->hasNull) && colDataIsNull_f(_col, i)) {                                            \
119
        continue;                                                                                     \
120
      };                                                                                              \
121
      overflow = overflow || decimal128AddCheckOverflow((Decimal*)_res, d + i, DECIMAL_WORD_NUM(_t)); \
122
      if (overflow) break;                                                                            \
123
      pOps->add(_res, d + i, DECIMAL_WORD_NUM(_t));                                                   \
124
      (numOfElem)++;                                                                                  \
125
    }                                                                                                 \
126
  } while (0)
127

128
#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem)  \
129
  do {                                                        \
130
    _t* d = (_t*)(_col->pData);                               \
131
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \
132
      if (((_col)->hasNull) && colDataIsNull_f(_col, i)) {    \
133
        continue;                                             \
134
      };                                                      \
135
      (_res) -= (d)[i];                                       \
136
      (numOfElem)++;                                          \
137
    }                                                         \
138
  } while (0)
139

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

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

163
#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
164

165
#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
166

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

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

199
void funcInputUpdate(SqlFunctionCtx* pCtx) {
69,835,658✔
200
  SFuncInputRowIter* pIter = &pCtx->rowIter;
69,835,658✔
201

202
  if (!pCtx->bInputFinished) {
69,836,169✔
203
    pIter->pInput = &pCtx->input;
69,836,169✔
204
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
69,837,150✔
205
    pIter->pDataCol = pIter->pInput->pData[0];
69,837,150✔
206
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
69,837,150✔
207
    pIter->rowIndex = pIter->pInput->startRowIndex;
69,837,150✔
208
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
69,837,150✔
209
    pIter->pSrcBlock = pCtx->pSrcBlock;
69,836,680✔
210
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
69,836,169✔
211
      pIter->hasGroupId = true;
7,405,682✔
212
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
7,405,171✔
213
      pIter->hasPrev = false;
7,405,682✔
214
    }
215
  } else {
216
    pIter->finalRow = true;
×
217
  }
218
}
69,836,639✔
219

220
int32_t funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow, bool* res) {
×
221
  if (pIter->finalRow) {
×
222
    if (pIter->hasPrev) {
×
223
      pRow->ts = pIter->prevBlockTsEnd;
×
224
      pRow->isDataNull = pIter->prevIsDataNull;
×
225
      pRow->pData = pIter->pPrevData;
×
226
      pRow->block = pIter->pPrevRowBlock;
×
227
      pRow->rowIndex = 0;
×
228

229
      pIter->hasPrev = false;
×
230
      *res = true;
×
231
      return TSDB_CODE_SUCCESS;
×
232
    } else {
233
      *res = false;
×
234
      return TSDB_CODE_SUCCESS;
×
235
    }
236
  }
237
  if (pIter->hasPrev) {
×
238
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
×
239
      blockDataDestroy(pIter->pPrevRowBlock);
×
240
      int32_t code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
241
      if (code) {
×
242
        return code;
×
243
      }
244

245
      pIter->prevIsDataNull = colDataIsNull_s(pIter->pDataCol, pIter->inputEndIndex);
×
246

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

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

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

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

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

334
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
3,741,452✔
335
  int32_t idx = rowIndex + 1;
3,741,452✔
336
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
53,186,018✔
337
    ++idx;
49,444,566✔
338
  }
339
  pIter->rowIndex = idx;
3,741,452✔
340
}
3,741,452✔
341

342
static void setInputRowInfo(SFuncInputRow* pRow, SFuncInputRowIter* pIter, int32_t rowIndex, bool setPk) {
2,147,483,647✔
343
  pRow->ts = pIter->tsList[rowIndex];
2,147,483,647✔
344
  pRow->ts = pIter->tsList[rowIndex];
2,147,483,647✔
345
  pRow->isDataNull = colDataIsNull_s(pIter->pDataCol, rowIndex);
2,147,483,647✔
346
  pRow->pData = colDataGetData(pIter->pDataCol, rowIndex);
2,147,483,647✔
347
  pRow->pPk = setPk ? colDataGetData(pIter->pPkCol, rowIndex) : NULL;
2,147,483,647✔
348
  pRow->block = pIter->pSrcBlock;
2,147,483,647✔
349
  pRow->rowIndex = rowIndex;
2,147,483,647✔
350
}
2,147,483,647✔
351

352
bool funcInputGetNextRowAscPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
4,983,766✔
353
  if (pIter->hasPrev) {
4,983,766✔
354
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
394,452✔
355
      pIter->hasPrev = true;
×
356
      return false;
×
357
    } else {
358
      int32_t idx = pIter->rowIndex;
394,452✔
359
      while (pIter->tsList[idx] == pIter->prevBlockTsEnd) {
394,452✔
360
        ++idx;
×
361
      }
362

363
      pIter->hasPrev = false;
394,452✔
364
      setInputRowInfo(pRow, pIter, idx, true);
394,452✔
365
      forwardToNextDiffTsRow(pIter, idx);
394,452✔
366
      return true;
394,452✔
367
    }
368
  } else {
369
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,589,314✔
370
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
3,968,628✔
371

372
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,968,628✔
373
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
3,968,628✔
374
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
3,347,000✔
375
      } else {
376
        pIter->rowIndex = pIter->inputEndIndex + 1;
621,628✔
377
      }
378
      return true;
3,968,628✔
379
    } else {
380
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
620,686✔
381
      pIter->hasPrev = true;
620,686✔
382
      pIter->prevBlockTsEnd = tsEnd;
620,686✔
383
      return false;
620,686✔
384
    }
385
  }
386
}
387

388
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
2,147,483,647✔
389
  if (pIter->rowIndex <= pIter->inputEndIndex) {
2,147,483,647✔
390
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
2,147,483,647✔
391
    ++pIter->rowIndex;
2,147,483,647✔
392
    return true;
2,147,483,647✔
393
  } else {
394
    return false;
69,944,203✔
395
  }
396
}
397

398
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
2,147,483,647✔
399
  SFuncInputRowIter* pIter = &pCtx->rowIter;
2,147,483,647✔
400
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
401
    if (pCtx->order == TSDB_ORDER_DESC) {
4,983,766✔
402
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
403
      return TSDB_CODE_SUCCESS;
404
    } else {
405
      *res = funcInputGetNextRowAscPk(pIter, pRow);
4,983,766✔
406
    }
407
  } else {
408
    *res = funcInputGetNextRowNoPk(pIter, pRow);
2,147,483,647✔
409
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
410
  }
411
  return TSDB_CODE_SUCCESS;
4,983,766✔
412
}
413

414
// This function append the selectivity to subsidiaries function context directly, without fetching data
415
// from intermediate disk based buf page
416
int32_t appendSelectivityCols(SqlFunctionCtx* pCtx, SSDataBlock* pSrcBlock, int32_t rowIndex, int32_t pos) {
2,147,483,647✔
417
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
418
    return TSDB_CODE_SUCCESS;
×
419
  }
420

421
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,147,483,647✔
422
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
2,147,483,647✔
423

424
    // get data from source col
425
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
2,147,483,647✔
426
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
2,147,483,647✔
427

428
    SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
2,147,483,647✔
429
    if (NULL == pSrcCol) {
2,147,483,647✔
430
      return TSDB_CODE_OUT_OF_RANGE;
×
431
    }
432

433
    char* pData = colDataGetData(pSrcCol, rowIndex);
2,147,483,647✔
434

435
    // append to dest col
436
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
2,147,483,647✔
437

438
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
2,147,483,647✔
439
    if (NULL == pDstCol) {
2,147,483,647✔
440
      return TSDB_CODE_OUT_OF_RANGE;
×
441
    }
442
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,147,483,647✔
443
      colDataSetNULL(pDstCol, pos);
4,281✔
444
    } else {
445
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
2,147,483,647✔
446
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
447
        return code;
×
448
      }
449
    }
450
  }
451
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
452
}
453

454
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
455
                              int32_t* nextFrom);
456

457
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);
458

459
int32_t functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,147,483,647✔
460
  if (pResultInfo->initialized) {
2,147,483,647✔
461
    return TSDB_CODE_SUCCESS;  // already initialized
2,728,445✔
462
  }
463

464
  if (pCtx->pOutput != NULL) {
2,147,483,647✔
465
    (void)memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes);
×
466
  }
467

468
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
2,147,483,647✔
469
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
470
}
471

472
int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
473
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
474
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
475
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
476
  if (NULL == pCol) {
2,147,483,647✔
477
    return TSDB_CODE_OUT_OF_RANGE;
×
478
  }
479
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
480
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,147,483,647✔
481

482
  char* in = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
483
  code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
2,147,483,647✔
484

485
  return code;
2,147,483,647✔
486
}
487

488
int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
489
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
490
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
491
  int32_t              bytes = pDBuf->bytes;
×
492

493
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
494
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
495

496
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, true);
×
497

498
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
499
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
500
  return TSDB_CODE_SUCCESS;
×
501
}
502

503
int32_t functionFinalizeWithResultBuf(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, char* finalResult) {
89,624✔
504
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
89,624✔
505
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
89,624✔
506
  if (NULL == pCol) {
89,624✔
507
    return TSDB_CODE_OUT_OF_RANGE;
×
508
  }
509
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
89,624✔
510
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
89,624✔
511

512
  char*   in = finalResult;
89,624✔
513
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
89,624✔
514

515
  return code;
89,624✔
516
}
517

518
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
16,183,407✔
519
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
16,183,407✔
520
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
16,184,129✔
521
    return FUNC_DATA_REQUIRED_NOT_LOAD;
11,890,755✔
522
  }
523
  return FUNC_DATA_REQUIRED_SMA_LOAD;
4,293,329✔
524
}
525

526
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
61,307,510✔
527
  pEnv->calcMemSize = sizeof(int64_t);
61,307,510✔
528
  return true;
61,318,849✔
529
}
530

531
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
2,147,483,647✔
532
  int64_t numOfElem = 0;
2,147,483,647✔
533

534
  /*
535
   * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true;
536
   * 2. for general non-primary key columns, pInputCol->hasNull may be true or false, pInput->colDataSMAIsSet == true;
537
   * 3. for primary key column, pInputCol->hasNull always be false, pInput->colDataSMAIsSet == false;
538
   */
539
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
540
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
541
  if (1 == pInput->numOfRows && pInput->blankFill) {
2,147,483,647✔
542
    return 0;
57,764,492✔
543
  }
544
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
2,147,483,647✔
545
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
879,763✔
546
  } else {
547
    if (pInputCol->hasNull) {
2,147,483,647✔
548
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,147,483,647✔
549
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
2,147,483,647✔
550
          continue;
2,147,483,647✔
551
        }
552
        numOfElem += 1;
2,147,483,647✔
553
      }
554
    } else {
555
      // when counting on the primary time stamp column and no statistics data is presented, use the size value
556
      // directly.
557
      numOfElem = pInput->numOfRows;
2,147,483,647✔
558
    }
559
  }
560
  return numOfElem;
2,147,483,647✔
561
}
562

563
/*
564
 * count function does need the finalize, if data is missing, the default value, which is 0, is used
565
 * count function does not use the pCtx->interResBuf to keep the intermediate buffer
566
 */
567
int32_t countFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
568
  int64_t numOfElem = 0;
2,147,483,647✔
569

570
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
571
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
572

573
  int32_t type = pInput->pData[0]->info.type;
2,147,483,647✔
574

575
  char*   buf = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
576
  int64_t val = *((int64_t*)buf);
2,147,483,647✔
577
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
578
    // select count(NULL) returns 0
579
    numOfElem = 1;
37,822,537✔
580
    val += 0;
37,822,537✔
581
  } else {
582
    numOfElem = getNumOfElems(pCtx);
2,147,483,647✔
583
    val += numOfElem;
2,147,483,647✔
584
  }
585
  taosSetInt64Aligned((int64_t*)buf, val);
586

587
  if (tsCountAlwaysReturnValue) {
2,147,483,647✔
588
    pResInfo->numOfRes = 1;
2,147,483,647✔
589
  } else {
590
    SET_VAL(pResInfo, val, 1);
8,963,566✔
591
  }
592

593
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
594
}
595

596
int32_t combineFunction(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
597
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
598
  char*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
599

600
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
601
  char*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
602
  *((int64_t*)pDBuf) += *((int64_t*)pSBuf);
×
603

604
  SET_VAL(pDResInfo, *((int64_t*)pDBuf), 1);
×
605
  return TSDB_CODE_SUCCESS;
×
606
}
607

608
int32_t sumFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
609
  int32_t numOfElem = 0;
2,147,483,647✔
610

611
  // Only the pre-computing information loaded and actual data does not loaded
612
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
613
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,147,483,647✔
614
  int32_t               type = pInput->pData[0]->info.type;
2,147,483,647✔
615
  pCtx->inputType = type;
2,147,483,647✔
616

617
  void* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,147,483,647✔
618
  SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, type);
2,147,483,647✔
619

620
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
621
    numOfElem = 0;
435,477✔
622
    goto _sum_over;
435,477✔
623
  }
624

625
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
626
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
30,348,604✔
627

628
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
30,349,926✔
629
      SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
15,523,597✔
630
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
14,826,329✔
631
      SUM_RES_INC_USUM(pSumRes, pAgg->sum);
14,826,990✔
UNCOV
632
    } else if (IS_FLOAT_TYPE(type)) {
×
633
      SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
×
UNCOV
634
    } else if (IS_DECIMAL_TYPE(type)) {
×
UNCOV
635
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
×
UNCOV
636
      const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
×
UNCOV
637
      if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
×
UNCOV
638
                                                       &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
×
UNCOV
639
        return TSDB_CODE_DECIMAL_OVERFLOW;
×
640
      }
UNCOV
641
      pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
×
642
    }
643
  } else {  // computing based on the true data block
644
    SColumnInfoData* pCol = pInput->pData[0];
2,147,483,647✔
645

646
    int32_t start = pInput->startRowIndex;
2,147,483,647✔
647
    int32_t numOfRows = pInput->numOfRows;
2,147,483,647✔
648

649
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
650
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
651
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int8_t, numOfElem);
1,004,789,331✔
652
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
2,147,483,647✔
653
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
613,549,159✔
654
      } else if (type == TSDB_DATA_TYPE_INT) {
2,147,483,647✔
655
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int32_t, numOfElem);
2,147,483,647✔
656
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
1,344,738,032✔
657
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int64_t, numOfElem);
2,147,483,647✔
658
      }
659
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,147,483,647✔
660
      if (type == TSDB_DATA_TYPE_UTINYINT) {
2,147,483,647✔
661
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint8_t, numOfElem);
626,461,047✔
662
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
2,147,483,647✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint16_t, numOfElem);
2,147,483,647✔
664
      } else if (type == TSDB_DATA_TYPE_UINT) {
74,057,225✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
657,171,961✔
666
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
2,813,467✔
667
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
520,325,777✔
668
      }
669
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
257,186,683✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
607,771,582✔
671
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
146,044,887✔
672
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
399,688,609✔
673
    } else if (IS_DECIMAL_TYPE(type)) {
42,458✔
674
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
42,458✔
675
      int32_t overflow = false;
38,357✔
676
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
38,357✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
8,883,256✔
678
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
24,150✔
679
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
17,791,305✔
680
      }
681
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
38,357✔
682
    }
683
  }
684

685
  // check for overflow
686
  if (IS_FLOAT_TYPE(type) && (isinf(SUM_RES_GET_DSUM(pSumRes)) || isnan(SUM_RES_GET_DSUM(pSumRes)))) {
2,147,483,647✔
687
    numOfElem = 0;
×
688
  }
689

690
_sum_over:
2,147,483,647✔
691
  if (numOfElem == 0) {
2,147,483,647✔
692
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
1,393,240,363✔
693
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
123,884,892✔
694
      numOfElem = 1;
×
695
    }
696
  }
697
  // data in the check operation are all null, not output
698
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
2,147,483,647✔
699
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
700
}
701

702
int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
703
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
704
  void*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
705
  int16_t              type = SUM_RES_GET_TYPE(pDBuf, pDestCtx->inputType);
×
706

707
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
708
  void*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
709
  type = (type == TSDB_DATA_TYPE_NULL) ? SUM_RES_GET_TYPE(pSBuf, pDestCtx->inputType) : type;
×
710

711
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
×
712
    SUM_RES_INC_ISUM(pDBuf, SUM_RES_GET_ISUM(pSBuf));
×
713
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
714
    SUM_RES_INC_USUM(pDBuf, SUM_RES_GET_USUM(pSBuf));
×
715
  } else if (IS_DECIMAL_TYPE(type)) {
×
716
    bool overflow = false;
×
717
    SUM_RES_INC_DECIMAL_SUM(pDBuf, &SUM_RES_GET_DECIMAL_SUM(pSBuf), type);
×
718
  } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
×
719
    SUM_RES_INC_DSUM(pDBuf, SUM_RES_GET_DSUM(pSBuf));
×
720
  }
721
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
722
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
723
  return TSDB_CODE_SUCCESS;
×
724
}
725

726
bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
30,855,344✔
727
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
30,855,344✔
728
  return true;
30,855,034✔
729
}
730

731
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
26,675,506✔
732
  SNode* pParam;
733
  switch (pFunc->funcType) {
26,675,506✔
734
    case FUNCTION_TYPE_MAX:
26,674,992✔
735
    case FUNCTION_TYPE_MIN:
736
    case FUNCTION_TYPE_SUM:
737
    case FUNCTION_TYPE_AVG:
738
    case FUNCTION_TYPE_AVG_PARTIAL:
739
    case FUNCTION_TYPE_PERCENTILE:
740
    case FUNCTION_TYPE_SPREAD:
741
    case FUNCTION_TYPE_SPREAD_PARTIAL:
742
    case FUNCTION_TYPE_SPREAD_MERGE:
743
    case FUNCTION_TYPE_TWA:
744
    case FUNCTION_TYPE_ELAPSED:
745
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
26,674,992✔
746
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
26,678,120✔
747
        return true;
1,595,180✔
748
      }
749
      break;
25,078,576✔
750
    default:
514✔
751
      break;
514✔
752
  }
753
  return false;
25,079,090✔
754
}
755

756
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
26,672,535✔
757
  if (funcNotSupportStringSma(pFunc)) {
26,672,535✔
758
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,595,180✔
759
  }
760
  return FUNC_DATA_REQUIRED_SMA_LOAD;
25,080,153✔
761
}
762

763
int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,052,688,763✔
764
  if (pResultInfo->initialized) {
2,052,688,763✔
765
    return TSDB_CODE_SUCCESS;
×
766
  }
767
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,052,700,713✔
768
    return TSDB_CODE_FUNC_SETUP_ERROR;  // not initialized since it has been initialized
×
769
  }
770

771
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
2,052,705,446✔
772
  buf->assign = false;
2,052,707,479✔
773
  buf->tuplePos.pageId = -1;
2,052,708,067✔
774

775
  buf->nullTupleSaved = false;
2,052,698,672✔
776
  buf->nullTuplePos.pageId = -1;
2,052,700,737✔
777
  buf->str = NULL;
2,052,703,726✔
778
  return TSDB_CODE_SUCCESS;
2,052,706,822✔
779
}
780

781
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
49,326,306✔
782
  COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
783
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
49,326,306✔
784
  return true;
49,329,263✔
785
}
786

787
int32_t minFunction(SqlFunctionCtx* pCtx) {
2,068,984,280✔
788
  int32_t numOfElems = 0;
2,068,984,280✔
789
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
2,069,362,821✔
790
  if (code != TSDB_CODE_SUCCESS) {
2,069,538,971✔
791
    return code;
×
792
  }
793
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,069,538,971✔
794
  return TSDB_CODE_SUCCESS;
2,069,554,838✔
795
}
796

797
int32_t maxFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
798
  int32_t numOfElems = 0;
2,147,483,647✔
799
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
2,147,483,647✔
800
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
801
    return code;
×
802
  }
803
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,147,483,647✔
804
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
805
}
806

807
static int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex);
808
static int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos,
809
                                   int32_t rowIndex);
810

811
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,016,352,551✔
812
  int32_t code = TSDB_CODE_SUCCESS;
2,016,352,551✔
813

814
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2,016,352,551✔
815
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2,016,351,889✔
816

817
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
2,016,352,551✔
818
  int32_t currentRow = pBlock->info.rows;
2,016,351,889✔
819

820
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,016,351,353✔
821
  if (NULL == pCol) {
2,016,350,133✔
822
    return TSDB_CODE_OUT_OF_RANGE;
×
823
  }
824
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
2,016,350,133✔
825

826
  // NOTE: do nothing change it, for performance issue
827
  if (!pEntryInfo->isNullRes) {
2,016,349,297✔
828
    switch (pCol->info.type) {
1,752,589,053✔
829
      case TSDB_DATA_TYPE_UBIGINT:
149,217,510✔
830
      case TSDB_DATA_TYPE_BIGINT:
831
      case TSDB_DATA_TYPE_TIMESTAMP:
832
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
149,217,510✔
833
        break;
149,215,676✔
834
      case TSDB_DATA_TYPE_UINT:
1,471,728,226✔
835
      case TSDB_DATA_TYPE_INT:
836
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
1,471,728,226✔
837
        break;
1,471,728,226✔
838
      case TSDB_DATA_TYPE_USMALLINT:
25,411,767✔
839
      case TSDB_DATA_TYPE_SMALLINT:
840
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
25,411,767✔
841
        break;
25,411,767✔
842
      case TSDB_DATA_TYPE_BOOL:
45,457,880✔
843
      case TSDB_DATA_TYPE_UTINYINT:
844
      case TSDB_DATA_TYPE_TINYINT:
845
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
45,457,880✔
846
        break;
45,457,880✔
847
      case TSDB_DATA_TYPE_DOUBLE:
27,674,519✔
848
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
27,674,519✔
849
        break;
27,674,519✔
850
      case TSDB_DATA_TYPE_FLOAT: {
27,325,748✔
851
        float v = GET_FLOAT_VAL(&pRes->v);
27,325,748✔
852
        colDataSetFloat(pCol, currentRow, &v);
27,325,748✔
853
        break;
27,325,748✔
854
      }
855
      case TSDB_DATA_TYPE_VARBINARY:
5,037,352✔
856
      case TSDB_DATA_TYPE_VARCHAR:
857
      case TSDB_DATA_TYPE_NCHAR: {
858
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
5,037,352✔
859
        if (TSDB_CODE_SUCCESS != code) {
5,037,352✔
860
          return code;
×
861
        }
862
        break;
5,037,352✔
863
      }
864
      case TSDB_DATA_TYPE_DECIMAL64:
697,439✔
865
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
697,439✔
866
        break;
697,439✔
867
      case TSDB_DATA_TYPE_DECIMAL:
37,184✔
868
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
37,184✔
869
        break;
37,184✔
870
    }
871
  } else {
872
    colDataSetNULL(pCol, currentRow);
263,762,940✔
873
  }
874

875
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
2,016,321,739✔
876
  if (pCtx->subsidiaries.num > 0) {
2,016,349,297✔
877
    if (pEntryInfo->numOfRes > 0) {
2,355,810✔
878
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
2,157,946✔
879
    } else {
880
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
197,864✔
881
    }
882
  }
883

884
  return code;
2,016,345,653✔
885
}
886

887
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
2,147,483,647✔
888
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
889
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
890
  }
891

892
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
703,681✔
893
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
424,974✔
894
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
424,974✔
895

896
    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
424,974✔
897
    if (NULL == pDstCol) {
424,974✔
898
      return terrno;
×
899
    }
900
    colDataSetNULL(pDstCol, rowIndex);
424,974✔
901
  }
902

903
  return TSDB_CODE_SUCCESS;
278,707✔
904
}
905

906
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
2,147,483,647✔
907
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
908
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
909
  }
910

911
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
81,216,809✔
912
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
913
    int32_t numOfCols = pCtx->subsidiaries.num;
81,216,809✔
914
    char*   p = NULL;
81,216,809✔
915
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
81,216,339✔
916
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
81,216,809✔
UNCOV
917
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
918
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
919
      return TSDB_CODE_NOT_FOUND;
×
920
    }
921

922
    bool* nullList = (bool*)p;
81,216,809✔
923
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
81,216,809✔
924

925
    // todo set the offset value to optimize the performance.
926
    for (int32_t j = 0; j < numOfCols; ++j) {
263,037,834✔
927
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
181,821,463✔
928
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
181,821,463✔
929

930
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
181,821,463✔
931
      if (NULL == pDstCol) {
181,821,463✔
932
        return terrno;
×
933
      }
934
      if (nullList[j]) {
181,821,463✔
935
        colDataSetNULL(pDstCol, rowIndex);
57,851,784✔
936
      } else {
937
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
123,969,209✔
938
        if (TSDB_CODE_SUCCESS != code) {
123,969,241✔
939
          return code;
×
940
        }
941
      }
942
      pStart += pDstCol->info.bytes;
181,821,025✔
943
    }
944
  }
945

946
  return TSDB_CODE_SUCCESS;
81,216,371✔
947
}
948

949
// This function append the selectivity to subsidiaries function context directly, without fetching data
950
// from intermediate disk based buf page
951
int32_t appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) {
1,085,092✔
952
  if (pCtx->subsidiaries.num <= 0) {
1,085,092✔
953
    return TSDB_CODE_SUCCESS;
×
954
  }
955

956
  int32_t code = TSDB_CODE_SUCCESS;
1,085,092✔
957
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,455,256✔
958
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
1,370,164✔
959

960
    // get data from source col
961
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
1,370,164✔
962
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
1,370,164✔
963

964
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
1,370,164✔
965
    if (NULL == pSrcCol) {
1,370,164✔
966
      return TSDB_CODE_OUT_OF_RANGE;
×
967
    }
968

969
    char* pData = colDataGetData(pSrcCol, rowIndex);
1,370,164✔
970

971
    // append to dest col
972
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
1,370,164✔
973

974
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
1,370,164✔
975
    if (NULL == pDstCol) {
1,370,164✔
976
      return TSDB_CODE_OUT_OF_RANGE;
×
977
    }
978

979
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,740,328✔
980
      colDataSetNULL(pDstCol, pos);
56,508✔
981
    } else {
982
      code = colDataSetVal(pDstCol, pos, pData, false);
1,313,656✔
983
      if (TSDB_CODE_SUCCESS != code) {
1,313,656✔
984
        return code;
×
985
      }
986
    }
987
  }
988
  return code;
1,085,092✔
989
}
990

991
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
×
992

993
#define COMPARE_MINMAX_DATA(type) (((*(type*)&pDBuf->v) < (*(type*)&pSBuf->v)) ^ isMinFunc)
994
int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) {
×
995
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
996
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
997

998
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
999
  SMinmaxResInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
1000
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
×
1001

1002
  switch (type) {
×
1003
    case TSDB_DATA_TYPE_UBIGINT:
×
1004
    case TSDB_DATA_TYPE_BIGINT:
1005
    case TSDB_DATA_TYPE_TIMESTAMP:
1006
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int64_t) || !pDBuf->assign)) {
×
1007
        pDBuf->v = pSBuf->v;
×
1008
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1009
        pDBuf->assign = true;
×
1010
      }
1011
      break;
×
1012
    case TSDB_DATA_TYPE_UINT:
×
1013
    case TSDB_DATA_TYPE_INT:
1014
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int32_t) || !pDBuf->assign)) {
×
1015
        pDBuf->v = pSBuf->v;
×
1016
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1017
        pDBuf->assign = true;
×
1018
      }
1019
      break;
×
1020
    case TSDB_DATA_TYPE_USMALLINT:
×
1021
    case TSDB_DATA_TYPE_SMALLINT:
1022
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int16_t) || !pDBuf->assign)) {
×
1023
        pDBuf->v = pSBuf->v;
×
1024
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1025
        pDBuf->assign = true;
×
1026
      }
1027
      break;
×
1028
    case TSDB_DATA_TYPE_BOOL:
×
1029
    case TSDB_DATA_TYPE_UTINYINT:
1030
    case TSDB_DATA_TYPE_TINYINT:
1031
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int8_t) || !pDBuf->assign)) {
×
1032
        pDBuf->v = pSBuf->v;
×
1033
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1034
        pDBuf->assign = true;
×
1035
      }
1036
      break;
×
1037
    case TSDB_DATA_TYPE_DOUBLE:
×
1038
    case TSDB_DATA_TYPE_FLOAT: {
1039
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(double) || !pDBuf->assign)) {
×
1040
        pDBuf->v = pSBuf->v;
×
1041
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1042
        pDBuf->assign = true;
×
1043
      }
1044
      break;
×
1045
    }
1046
    case TSDB_DATA_TYPE_DECIMAL64: {
×
1047
      const SDecimalOps* pOps = getDecimalOps(type);
×
1048
      if (pSBuf->assign &&
×
1049
          ((pOps->lt(&pDBuf->v, &pSBuf->v, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) || !pDBuf->assign)) {
×
1050
        pDBuf->v = pSBuf->v;
×
1051
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1052
        pDBuf->assign = true;
×
1053
      }
1054
    } break;
×
1055
    case TSDB_DATA_TYPE_DECIMAL: {
×
1056
      const SDecimalOps* pOps = getDecimalOps(type);
×
1057
      if (pSBuf->assign && (pOps->lt(pDBuf->dec, pSBuf->dec, DECIMAL_WORD_NUM(Decimal)) ^ isMinFunc) ||
×
1058
          !pDBuf->assign) {
×
1059
        memcpy(pDBuf->dec, pSBuf->dec, DECIMAL128_BYTES);
×
1060
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1061
        pDBuf->assign = true;
×
1062
      }
1063
    } break;
×
1064
    default:
×
1065
      if (pSBuf->assign && (strcmp(pDBuf->str, pSBuf->str) || !pDBuf->assign)) {
×
1066
        memcpy(pDBuf->str, pSBuf->str, varDataLen(pSBuf->str));
×
1067
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1068
        pDBuf->assign = true;
×
1069
      }
1070
      break;
×
1071
  }
1072
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
1073
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
1074
  return TSDB_CODE_SUCCESS;
×
1075
}
1076

1077
int32_t minCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1078
  return minMaxCombine(pDestCtx, pSourceCtx, 1);
×
1079
}
1080
int32_t maxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1081
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
×
1082
}
1083

1084
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
18,963,513✔
1085

1086
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
4,214,097✔
1087
  pEnv->calcMemSize = sizeof(SStdRes);
4,214,097✔
1088
  return true;
4,215,832✔
1089
}
1090

1091
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
516,554,176✔
1092
  if (pResultInfo->initialized) {
516,554,176✔
1093
    return TSDB_CODE_SUCCESS;
×
1094
  }
1095
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
516,554,751✔
1096
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1097
  }
1098

1099
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
516,553,575✔
1100
  (void)memset(pRes, 0, sizeof(SStdRes));
516,552,914✔
1101
  return TSDB_CODE_SUCCESS;
516,552,914✔
1102
}
1103

1104
int32_t stdFunction(SqlFunctionCtx* pCtx) {
1,072,963,086✔
1105
  int32_t numOfElem = 0;
1,072,963,086✔
1106

1107
  // Only the pre-computing information loaded and actual data does not loaded
1108
  SInputColumnInfoData* pInput = &pCtx->input;
1,072,963,086✔
1109
  int32_t               type = pInput->pData[0]->info.type;
1,072,966,804✔
1110

1111
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,072,961,952✔
1112
  pStdRes->type = type;
1,072,960,107✔
1113

1114
  // computing based on the true data block
1115
  SColumnInfoData* pCol = pInput->pData[0];
1,072,962,341✔
1116

1117
  int32_t start = pInput->startRowIndex;
1,072,960,891✔
1118
  int32_t numOfRows = pInput->numOfRows;
1,072,962,642✔
1119

1120
  if (IS_NULL_TYPE(type)) {
1,072,959,362✔
1121
    numOfElem = 0;
90,187✔
1122
    goto _stddev_over;
90,187✔
1123
  }
1124

1125
  switch (type) {
1,072,869,175✔
1126
    case TSDB_DATA_TYPE_TINYINT: {
16,417,279✔
1127
      int8_t* plist = (int8_t*)pCol->pData;
16,417,279✔
1128
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1129
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1130
          continue;
1,527,141,637✔
1131
        }
1132

1133
        numOfElem += 1;
735,452,990✔
1134
        pStdRes->count += 1;
735,452,990✔
1135
        double nr = (double)plist[i];
740,484,822✔
1136
        if (pStdRes->count == 1) {
740,494,092✔
1137
          pStdRes->dsum = nr;
4,674,026✔
1138
        } else {
1139
          double          s_kminusone = pStdRes->dsum;
735,758,749✔
1140
          volatile double diff = nr - s_kminusone;
735,768,011✔
1141
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
735,768,011✔
1142
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
735,890,200✔
1143
        }
1144
      }
1145

1146
      break;
15,934,139✔
1147
    }
1148

1149
    case TSDB_DATA_TYPE_SMALLINT: {
947,734,260✔
1150
      int16_t* plist = (int16_t*)pCol->pData;
947,734,260✔
1151
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1152
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1153
          continue;
2,147,483,647✔
1154
        }
1155

1156
        numOfElem += 1;
1,264,654,735✔
1157
        pStdRes->count += 1;
1,264,654,735✔
1158
        double nr = (double)plist[i];
1,271,120,551✔
1159
        if (pStdRes->count == 1) {
1,271,094,636✔
1160
          pStdRes->dsum = nr;
383,647,458✔
1161
        } else {
1162
          double          s_kminusone = pStdRes->dsum;
887,459,737✔
1163
          volatile double diff = nr - s_kminusone;
887,460,406✔
1164
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
887,460,406✔
1165
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
887,361,032✔
1166
        }
1167
      }
1168
      break;
947,734,260✔
1169
    }
1170

1171
    case TSDB_DATA_TYPE_INT: {
17,851,967✔
1172
      int32_t* plist = (int32_t*)pCol->pData;
17,851,967✔
1173
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1174
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1175
          continue;
801,272,592✔
1176
        }
1177

1178
        numOfElem += 1;
2,147,483,647✔
1179
        pStdRes->count += 1;
2,147,483,647✔
1180
        double nr = (double)plist[i];
2,147,483,647✔
1181
        if (pStdRes->count == 1) {
2,147,483,647✔
1182
          pStdRes->dsum = nr;
10,335,750✔
1183
        } else {
1184
          double          s_kminusone = pStdRes->dsum;
2,147,483,647✔
1185
          volatile double diff = nr - s_kminusone;
2,147,483,647✔
1186
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,147,483,647✔
1187
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,147,483,647✔
1188
        }
1189
      }
1190

1191
      break;
17,851,805✔
1192
    }
1193

1194
    case TSDB_DATA_TYPE_BIGINT: {
38,100,260✔
1195
      int64_t* plist = (int64_t*)pCol->pData;
38,100,260✔
1196
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1197
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1198
          continue;
1,436,598,951✔
1199
        }
1200

1201
        numOfElem += 1;
940,693,845✔
1202
        pStdRes->count += 1;
940,693,845✔
1203
        double nr = (double)plist[i];
946,999,991✔
1204
        if (pStdRes->count == 1) {
947,033,626✔
1205
          pStdRes->dsum = nr;
25,170,433✔
1206
        } else {
1207
          double          s_kminusone = pStdRes->dsum;
921,765,201✔
1208
          volatile double diff = nr - s_kminusone;
921,779,082✔
1209
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
921,779,082✔
1210
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
921,858,558✔
1211
        }
1212
      }
1213
      break;
38,099,591✔
1214
    }
1215

1216
    case TSDB_DATA_TYPE_UTINYINT: {
13,629,776✔
1217
      uint8_t* plist = (uint8_t*)pCol->pData;
13,629,776✔
1218
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1219
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1220
          continue;
1,657,170,209✔
1221
        }
1222

1223
        numOfElem += 1;
1,076,997,987✔
1224
        pStdRes->count += 1;
1,076,997,987✔
1225
        double nr = (double)plist[i];
1,082,369,081✔
1226
        if (pStdRes->count == 1) {
1,082,330,767✔
1227
          pStdRes->dsum = nr;
78,277✔
1228
        } else {
1229
          double          s_kminusone = pStdRes->dsum;
1,082,263,727✔
1230
          volatile double diff = nr - s_kminusone;
1,081,484,626✔
1231
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,081,484,626✔
1232
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,078,658,515✔
1233
        }
1234
      }
1235

1236
      break;
13,249,826✔
1237
    }
1238

1239
    case TSDB_DATA_TYPE_USMALLINT: {
10,978,891✔
1240
      uint16_t* plist = (uint16_t*)pCol->pData;
10,978,891✔
1241
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1242
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1243
          continue;
1,657,516,307✔
1244
        }
1245

1246
        numOfElem += 1;
544,612,570✔
1247
        pStdRes->count += 1;
544,612,570✔
1248
        double nr = (double)plist[i];
551,576,907✔
1249
        if (pStdRes->count == 1) {
551,582,195✔
1250
          pStdRes->dsum = nr;
34,216✔
1251
        } else {
1252
          double          s_kminusone = pStdRes->dsum;
551,558,555✔
1253
          volatile double diff = nr - s_kminusone;
551,553,928✔
1254
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
551,553,928✔
1255
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
551,565,826✔
1256
        }
1257
      }
1258
      break;
10,978,891✔
1259
    }
1260

1261
    case TSDB_DATA_TYPE_UINT: {
5,991,799✔
1262
      uint32_t* plist = (uint32_t*)pCol->pData;
5,991,799✔
1263
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,217,692,835✔
1264
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,211,725,115✔
1265
          continue;
862,133,581✔
1266
        }
1267

1268
        numOfElem += 1;
349,492,949✔
1269
        pStdRes->count += 1;
349,492,949✔
1270
        double nr = (double)plist[i];
352,042,605✔
1271
        if (pStdRes->count == 1) {
352,045,910✔
1272
          pStdRes->dsum = nr;
25,322✔
1273
        } else {
1274
          double          s_kminusone = pStdRes->dsum;
351,999,929✔
1275
          volatile double diff = nr - s_kminusone;
352,003,234✔
1276
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
352,003,234✔
1277
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
352,001,872✔
1278
        }
1279
      }
1280

1281
      break;
5,991,799✔
1282
    }
1283

1284
    case TSDB_DATA_TYPE_UBIGINT: {
5,991,391✔
1285
      uint64_t* plist = (uint64_t*)pCol->pData;
5,991,391✔
1286
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,216,281,580✔
1287
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,210,348,016✔
1288
          continue;
926,495,510✔
1289
        }
1290

1291
        numOfElem += 1;
283,859,393✔
1292
        pStdRes->count += 1;
283,859,393✔
1293
        double nr = (double)plist[i];
285,622,516✔
1294
        if (pStdRes->count == 1) {
285,623,177✔
1295
          pStdRes->dsum = nr;
22,262✔
1296
        } else {
1297
          double          s_kminusone = pStdRes->dsum;
285,601,576✔
1298
          volatile double diff = nr - s_kminusone;
285,601,576✔
1299
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
285,601,576✔
1300
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
285,574,475✔
1301
        }
1302
      }
1303
      break;
5,991,391✔
1304
    }
1305

1306
    case TSDB_DATA_TYPE_FLOAT: {
9,992,695✔
1307
      float* plist = (float*)pCol->pData;
9,992,695✔
1308
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,930,692,763✔
1309
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,920,700,068✔
1310
          continue;
4,909,068✔
1311
        }
1312

1313
        numOfElem += 1;
1,915,184,792✔
1314
        pStdRes->count += 1;
1,915,184,792✔
1315
        double nr = (double)plist[i];
1,915,791,000✔
1316
        if (pStdRes->count == 1) {
1,915,791,000✔
1317
          pStdRes->dsum = nr;
9,192,574✔
1318
        } else {
1319
          double          s_kminusone = pStdRes->dsum;
1,906,598,426✔
1320
          volatile double diff = nr - s_kminusone;
1,906,598,426✔
1321
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,906,598,426✔
1322
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,906,598,426✔
1323
        }
1324
      }
1325
      break;
9,992,695✔
1326
    }
1327

1328
    case TSDB_DATA_TYPE_DOUBLE: {
6,180,857✔
1329
      double* plist = (double*)pCol->pData;
6,180,857✔
1330
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
277,597,606✔
1331
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
271,429,399✔
1332
          continue;
86,865,953✔
1333
        }
1334

1335
        numOfElem += 1;
184,576,671✔
1336
        pStdRes->count += 1;
184,576,671✔
1337
        double nr = (double)plist[i];
184,578,971✔
1338
        if (pStdRes->count == 1) {
184,579,546✔
1339
          pStdRes->dsum = nr;
2,971,322✔
1340
        } else {
1341
          double          s_kminusone = pStdRes->dsum;
181,558,774✔
1342
          volatile double diff = nr - s_kminusone;
181,560,499✔
1343
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
181,560,499✔
1344
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
181,567,974✔
1345
        }
1346
      }
1347
      break;
6,184,882✔
1348
    }
1349

1350
    default:
×
1351
      break;
×
1352
  }
1353

1354
_stddev_over:
1,072,099,466✔
1355
  // data in the check operation are all null, not output
1356
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1,072,099,466✔
1357
  return TSDB_CODE_SUCCESS;
1,072,954,245✔
1358
}
1359

1360
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
18,270,208✔
1361
  if (IS_NULL_TYPE(pInput->type)) {
18,270,208✔
1362
    return;
25,795✔
1363
  }
1364
  pOutput->type = pInput->type;
18,244,413✔
1365
  if (pOutput->count == 0) {
18,244,413✔
1366
    pOutput->quadraticDSum += pInput->quadraticDSum;
17,928,870✔
1367
    pOutput->dsum += pInput->dsum;
17,928,870✔
1368
    pOutput->count = pInput->count;
17,928,870✔
1369
  } else if (pInput->count > 0) {
315,543✔
1370
    double totalCount = pOutput->count + pInput->count;
146,007✔
1371
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
146,007✔
1372
    double mean = totalSum / totalCount;
146,007✔
1373

1374
    /*
1375
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pInput->dsum * pInput->dsum +
1376
                              pOutput->count * pOutput->dsum * pOutput->dsum - totalSum * mean;
1377
    */
1378

1379
    double diff = pInput->dsum - pOutput->dsum;
146,007✔
1380
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pOutput->count * (diff * diff) / totalCount;
146,007✔
1381
    pOutput->dsum = mean;
146,007✔
1382
    pOutput->count += pInput->count;
146,007✔
1383
  }
1384
}
1385

1386
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
18,240,524✔
1387
  SInputColumnInfoData* pInput = &pCtx->input;
18,240,524✔
1388
  SColumnInfoData*      pCol = pInput->pData[0];
18,240,524✔
1389

1390
  if (IS_NULL_TYPE(pCol->info.type)) {
18,240,524✔
1391
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1392
    return TSDB_CODE_SUCCESS;
×
1393
  }
1394

1395
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
18,240,524✔
1396
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1397
  }
1398

1399
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
18,240,524✔
1400

1401
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
36,510,732✔
1402
    if (colDataIsNull_s(pCol, i)) continue;
36,540,416✔
1403
    char*    data = colDataGetData(pCol, i);
18,270,208✔
1404
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
18,270,208✔
1405
    stdTransferInfo(pInputInfo, pInfo);
18,270,208✔
1406
  }
1407

1408
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
18,240,524✔
1409
  return TSDB_CODE_SUCCESS;
18,240,524✔
1410
}
1411

1412
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
473,715,695✔
1413
  SInputColumnInfoData* pInput = &pCtx->input;
473,715,695✔
1414
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
473,715,695✔
1415
  int32_t               type = pStddevRes->type;
473,715,695✔
1416
  double                avg;
1417

1418
  if (pStddevRes->count == 0) {
473,715,695✔
1419
    GET_RES_INFO(pCtx)->numOfRes = 0;
61,274,299✔
1420

1421
    return functionFinalize(pCtx, pBlock);
61,274,299✔
1422
  }
1423

1424
  if (pStddevRes->count == 1) {
412,441,396✔
1425
    pStddevRes->result = 0.0;
289,250,131✔
1426
  } else {
1427
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
123,191,265✔
1428
  }
1429

1430
  // check for overflow
1431
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
412,441,396✔
1432
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1433
  }
1434

1435
  return functionFinalize(pCtx, pBlock);
412,441,396✔
1436
}
1437

1438
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,069,273✔
1439
  SInputColumnInfoData* pInput = &pCtx->input;
7,069,273✔
1440
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,069,273✔
1441
  int32_t               type = pStdvarRes->type;
7,069,273✔
1442
  double                avg;
1443

1444
  if (pStdvarRes->count == 0) {
7,069,273✔
1445
    GET_RES_INFO(pCtx)->numOfRes = 0;
8,978✔
1446
    return functionFinalize(pCtx, pBlock);
8,978✔
1447
  }
1448

1449
  if (pStdvarRes->count == 1) {
7,060,295✔
1450
    pStdvarRes->result = 0.0;
998✔
1451
  } else {
1452
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
7,059,297✔
1453
  }
1454

1455
  // check for overflow
1456
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
7,060,295✔
1457
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1458
  }
1459

1460
  return functionFinalize(pCtx, pBlock);
7,060,295✔
1461
}
1462

1463
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
18,274,648✔
1464
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
18,274,648✔
1465
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
18,274,648✔
1466
  int32_t              resultBytes = getStdInfoSize();
18,274,648✔
1467
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
18,274,648✔
1468

1469
  if (NULL == res) {
18,274,648✔
1470
    return terrno;
×
1471
  }
1472
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
18,274,648✔
1473
  varDataSetLen(res, resultBytes);
18,274,648✔
1474

1475
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
18,274,648✔
1476
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
18,274,648✔
1477
  if (NULL == pCol) {
18,274,648✔
1478
    taosMemoryFree(res);
×
1479
    return TSDB_CODE_OUT_OF_RANGE;
×
1480
  }
1481

1482
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
18,274,648✔
1483

1484
  taosMemoryFree(res);
18,274,648✔
1485
  return code;
18,274,648✔
1486
}
1487

1488
int32_t stdCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1489
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1490
  SStdRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1491

1492
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
1493
  SStdRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
1494
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
×
1495

1496
  stdTransferInfo(pSBuf, pDBuf);
×
1497

1498
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
1499
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
1500
  return TSDB_CODE_SUCCESS;
×
1501
}
1502

1503
int32_t stddevsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,482,740✔
1504
  SInputColumnInfoData* pInput = &pCtx->input;
3,482,740✔
1505
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,482,740✔
1506
  double                avg;
1507

1508
  if (pStddevRes->count == 0) {
3,482,740✔
1509
    GET_RES_INFO(pCtx)->numOfRes = 0;
499✔
1510
    return functionFinalize(pCtx, pBlock);
499✔
1511
  }
1512

1513
  if (pStddevRes->count == 1) {
3,482,241✔
1514
    pStddevRes->result = 0.0;
499✔
1515
  } else {
1516
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / (pStddevRes->count - 1));
3,481,742✔
1517
  }
1518

1519
  // check for overflow
1520
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
3,482,241✔
1521
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1522
  }
1523

1524
  return functionFinalize(pCtx, pBlock);
3,482,241✔
1525
}
1526

1527
int32_t stdvarsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,481,742✔
1528
  SInputColumnInfoData* pInput = &pCtx->input;
3,481,742✔
1529
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,481,742✔
1530
  double                avg;
1531

1532
  if (pStddevRes->count == 0) {
3,481,742✔
1533
    GET_RES_INFO(pCtx)->numOfRes = 0;
499✔
1534
    return functionFinalize(pCtx, pBlock);
499✔
1535
  }
1536

1537
  if (pStddevRes->count == 1) {
3,481,243✔
1538
    pStddevRes->result = 0.0;
499✔
1539
  } else {
1540
    pStddevRes->result = pStddevRes->quadraticDSum / (pStddevRes->count - 1);
3,480,744✔
1541
  }
1542

1543
  // check for overflow
1544
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
3,481,243✔
1545
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1546
  }
1547

1548
  return functionFinalize(pCtx, pBlock);
3,481,243✔
1549
}
1550

1551
bool gconcatGetFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
28,530✔
1552
  pEnv->calcMemSize = sizeof(SGconcatRes);
28,530✔
1553
  return true;
28,530✔
1554
}
1555

1556
int32_t gconcatFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
49,998✔
1557
  if (pResultInfo->initialized) {
49,998✔
1558
    return TSDB_CODE_SUCCESS;
×
1559
  }
1560
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
49,998✔
1561
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1562
  }
1563

1564
  SGconcatRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
49,998✔
1565
  (void)memset(pRes, 0, sizeof(SGconcatRes));
49,998✔
1566

1567
  // pRes->separator = varDataVal(pCtx->param[0].param.pz);
1568

1569
  int32_t sepParamIdx = pCtx->numOfParams - 1;
49,998✔
1570
  pRes->separator = pCtx->param[sepParamIdx].param.pz;
49,998✔
1571
  pRes->type = pCtx->param[sepParamIdx].param.nType;
49,998✔
1572

1573
  /*
1574
  SInputColumnInfoData* pInput = &pCtx->input;
1575
  int32_t               type = pInput->pData[0]->info.type;
1576

1577
  pRes->nchar = (type == TSDB_DATA_TYPE_NCHAR);
1578
  */
1579

1580
  return TSDB_CODE_SUCCESS;
49,998✔
1581
}
1582

1583
static int32_t gconcatHelper(const char* input, char* output, bool hasNchar, int32_t type, VarDataLenT* dataLen,
138,030✔
1584
                             void* charsetCxt) {
1585
  if (input == NULL) {
138,030✔
1586
    return TSDB_CODE_SUCCESS;
3,416✔
1587
  }
1588
  if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) {
148,882✔
1589
    TdUcs4* newBuf = taosMemoryCalloc((varDataLen(input) + 1) * TSDB_NCHAR_SIZE, 1);
14,268✔
1590
    if (NULL == newBuf) {
14,268✔
1591
      return terrno;
×
1592
    }
1593
    int32_t len = varDataLen(input);
14,268✔
1594
    bool    ret =
1595
        taosMbsToUcs4(varDataVal(input), len, newBuf, (varDataLen(input) + 1) * TSDB_NCHAR_SIZE, &len, charsetCxt);
14,268✔
1596
    if (!ret) {
14,268✔
1597
      taosMemoryFree(newBuf);
×
1598
      return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1599
    }
1600
    (void)memcpy(varDataVal(output) + *dataLen, newBuf, len);
14,268✔
1601
    *dataLen += len;
14,268✔
1602
    taosMemoryFree(newBuf);
14,268✔
1603
  } else {
1604
    (void)memcpy(varDataVal(output) + *dataLen, varDataVal(input), varDataLen(input));
120,346✔
1605
    *dataLen += varDataLen(input);
120,346✔
1606
  }
1607

1608
  return TSDB_CODE_SUCCESS;
134,614✔
1609
}
1610

1611
int32_t gconcatFunction(SqlFunctionCtx* pCtx) {
49,490✔
1612
  int32_t               code = 0, numOfElem = 0;
49,490✔
1613
  SInputColumnInfoData* pInput = &pCtx->input;
49,490✔
1614
  int32_t               rowStart = pInput->startRowIndex;
49,490✔
1615
  int32_t               numOfRows = pInput->numOfRows;
49,490✔
1616
  int32_t               numOfCols = pInput->numOfInputCols;
49,490✔
1617
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
49,490✔
1618
  SGconcatRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
49,490✔
1619
  char*                 sep = pRes->separator;
49,490✔
1620
  bool                  hasNchar = pRes->nchar;
49,490✔
1621
  VarDataLenT           dataLen = 0;
49,490✔
1622
  bool                  hasResultValue = (pResInfo->numOfRes > 0);
49,490✔
1623

1624
  if (!pRes->result) {
49,490✔
1625
    pRes->result = taosMemoryCalloc(1, TSDB_MAX_FIELD_LEN);
49,490✔
1626
    if (!pRes->result) {
49,490✔
1627
      return terrno;
×
1628
    }
1629

1630
    varDataSetLen(pRes->result, 0);
49,490✔
1631

1632
    for (int c = 0; c < numOfCols - 1; ++c) {
100,504✔
1633
      SColumnInfoData* pCol = pInput->pData[c];
51,014✔
1634
      int32_t          type = pCol->info.type;
51,014✔
1635

1636
      if (TSDB_DATA_TYPE_NCHAR == type) {
51,014✔
1637
        pRes->nchar = true;
32,040✔
1638
      }
1639
    }
1640
  } else {
1641
    dataLen = varDataLen(pRes->result);
×
1642
  }
1643

1644
  hasNchar = pRes->nchar;
49,490✔
1645

1646
  // computing based on the true data block
1647
  char*            buf = pRes->result;
49,490✔
1648
  SColumnInfoData* pCol = pInput->pData[numOfCols - 1];
49,490✔
1649

1650
  sep = colDataGetData(pCol, 0);
49,490✔
1651
  pRes->type = pCol->info.type;
49,490✔
1652
  for (int r = rowStart; r < rowStart + numOfRows; ++r) {
143,758✔
1653
    bool rowHasValue = false;
94,268✔
1654

1655
    for (int c = 0; c < numOfCols - 1; ++c) {
192,600✔
1656
      SColumnInfoData* pCol = pInput->pData[c];
98,332✔
1657
      int32_t          type = pCol->info.type;
98,332✔
1658

1659
      if (IS_NULL_TYPE(type) || colDataIsNull_s(pCol, r)) {
196,664✔
1660
        continue;
3,048✔
1661
      }
1662

1663
      if (!rowHasValue && hasResultValue) {
95,284✔
1664
        // concat the separator before the first non-null value of this row
1665
        code = gconcatHelper(sep, buf, hasNchar, pRes->type, &dataLen, NULL);
42,746✔
1666
        if (code) {
42,746✔
1667
          goto _over;
×
1668
        }
1669
      }
1670

1671
      // concat this row's all columns
1672
      code = gconcatHelper(colDataGetData(pCol, r), buf, hasNchar, pInput->pData[c]->info.type, &dataLen, NULL);
95,284✔
1673
      if (code) {
95,284✔
1674
        goto _over;
×
1675
      }
1676

1677
      rowHasValue = true;
95,284✔
1678
    }
1679

1680
    hasResultValue |= rowHasValue;
94,268✔
1681
  }
1682

1683
  varDataSetLen(buf, dataLen);
49,490✔
1684
  if (hasResultValue) {
49,490✔
1685
    numOfElem += 1;
48,474✔
1686
  }
1687

1688
_over:
49,490✔
1689
  // data in the check operation are all null, not output
1690
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
49,490✔
1691
  return code;
49,490✔
1692
}
1693

1694
int32_t gconcatFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
49,490✔
1695
  int32_t               code = 0;
49,490✔
1696
  SInputColumnInfoData* pInput = &pCtx->input;
49,490✔
1697
  SGconcatRes*          pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
49,490✔
1698
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
49,490✔
1699
  int32_t               slotId = pCtx->pExpr->base.resSchema.slotId;
49,490✔
1700
  SColumnInfoData*      pCol = taosArrayGet(pBlock->pDataBlock, slotId);
49,490✔
1701

1702
  if (NULL == pCol) {
49,490✔
1703
    taosMemoryFree(pRes->result);
×
1704
    return TSDB_CODE_OUT_OF_RANGE;
×
1705
  }
1706

1707
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
49,490✔
1708
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->result, pResInfo->isNullRes);
49,490✔
1709

1710
  taosMemoryFree(pRes->result);
49,490✔
1711

1712
  return code;
49,490✔
1713
}
1714

1715
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,180,866✔
1716
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
1,180,866✔
1717
  return true;
1,180,866✔
1718
}
1719

1720
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,140,214✔
1721
  if (pResultInfo->initialized) {
5,140,214✔
1722
    return TSDB_CODE_SUCCESS;
×
1723
  }
1724
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,140,725✔
1725
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1726
  }
1727

1728
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,140,150✔
1729

1730
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
5,140,150✔
1731
                 typeGetTypeModFromCol(pCtx->param[1].pCol));
1732
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
5,140,725✔
1733
                 typeGetTypeModFromCol(pCtx->param[2].pCol));
1734
  return TSDB_CODE_SUCCESS;
5,140,725✔
1735
}
1736

1737
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
6,051,996✔
1738
  int32_t numOfElem = 0;
6,051,996✔
1739

1740
  SInputColumnInfoData* pInput = &pCtx->input;
6,051,996✔
1741
  int32_t               type = pInput->pData[0]->info.type;
6,052,507✔
1742

1743
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,052,507✔
1744

1745
  SColumnInfoData* pCol = pInput->pData[0];
6,051,932✔
1746

1747
  double(*param)[3] = pInfo->matrix;
6,051,357✔
1748
  double x = pInfo->startVal;
6,051,357✔
1749

1750
  int32_t start = pInput->startRowIndex;
6,052,507✔
1751
  int32_t numOfRows = pInput->numOfRows;
6,051,357✔
1752

1753
  switch (type) {
6,051,357✔
1754
    case TSDB_DATA_TYPE_TINYINT: {
822,970✔
1755
      int8_t* plist = (int8_t*)pCol->pData;
822,970✔
1756
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
99,439,072✔
1757
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
98,616,102✔
1758
          continue;
231,636✔
1759
        }
1760
        numOfElem++;
98,382,741✔
1761
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
98,382,741✔
1762
      }
1763
      break;
822,970✔
1764
    }
1765
    case TSDB_DATA_TYPE_SMALLINT: {
188,170✔
1766
      int16_t* plist = (int16_t*)pCol->pData;
188,170✔
1767
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,039,622✔
1768
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,851,452✔
1769
          continue;
118,836✔
1770
        }
1771

1772
        numOfElem++;
19,732,616✔
1773
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,732,616✔
1774
      }
1775
      break;
188,170✔
1776
    }
1777

1778
    case TSDB_DATA_TYPE_INT: {
403,665✔
1779
      int32_t* plist = (int32_t*)pCol->pData;
403,665✔
1780
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
96,648,716✔
1781
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
96,245,051✔
1782
          continue;
310,817✔
1783
        }
1784

1785
        numOfElem++;
95,934,234✔
1786
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
95,934,234✔
1787
      }
1788
      break;
403,154✔
1789
    }
1790

1791
    case TSDB_DATA_TYPE_BIGINT: {
2,909,220✔
1792
      int64_t* plist = (int64_t*)pCol->pData;
2,909,220✔
1793
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
107,730,297✔
1794
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
104,821,652✔
1795
          continue;
85,030,911✔
1796
        }
1797

1798
        numOfElem++;
19,789,591✔
1799
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,789,591✔
1800
      }
1801
      break;
2,910,370✔
1802
    }
1803

1804
    case TSDB_DATA_TYPE_UTINYINT: {
18,970✔
1805
      uint8_t* plist = (uint8_t*)pCol->pData;
18,970✔
1806
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,701,222✔
1807
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,682,252✔
1808
          continue;
11,066✔
1809
        }
1810
        numOfElem++;
19,671,186✔
1811
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,671,186✔
1812
      }
1813
      break;
18,970✔
1814
    }
1815
    case TSDB_DATA_TYPE_USMALLINT: {
18,970✔
1816
      uint16_t* plist = (uint16_t*)pCol->pData;
18,970✔
1817
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,701,222✔
1818
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,682,252✔
1819
          continue;
10,060✔
1820
        }
1821

1822
        numOfElem++;
19,672,192✔
1823
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,672,192✔
1824
      }
1825
      break;
18,970✔
1826
    }
1827

1828
    case TSDB_DATA_TYPE_UINT: {
18,970✔
1829
      uint32_t* plist = (uint32_t*)pCol->pData;
18,970✔
1830
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,701,222✔
1831
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,682,252✔
1832
          continue;
10,060✔
1833
        }
1834

1835
        numOfElem++;
19,672,192✔
1836
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,672,192✔
1837
      }
1838
      break;
18,970✔
1839
    }
1840

1841
    case TSDB_DATA_TYPE_UBIGINT: {
18,970✔
1842
      uint64_t* plist = (uint64_t*)pCol->pData;
18,970✔
1843
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,701,222✔
1844
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,682,252✔
1845
          continue;
10,060✔
1846
        }
1847

1848
        numOfElem++;
19,672,192✔
1849
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,672,192✔
1850
      }
1851
      break;
18,970✔
1852
    }
1853

1854
    case TSDB_DATA_TYPE_FLOAT: {
1,081,370✔
1855
      float* plist = (float*)pCol->pData;
1,081,370✔
1856
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
21,826,022✔
1857
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,744,652✔
1858
          continue;
285,636✔
1859
        }
1860

1861
        numOfElem++;
20,459,016✔
1862
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,459,016✔
1863
      }
1864
      break;
1,081,370✔
1865
    }
1866

1867
    case TSDB_DATA_TYPE_DOUBLE: {
570,082✔
1868
      double* plist = (double*)pCol->pData;
570,082✔
1869
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
21,291,498✔
1870
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,721,416✔
1871
          continue;
118,836✔
1872
        }
1873

1874
        numOfElem++;
20,602,580✔
1875
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,602,580✔
1876
      }
1877
      break;
570,082✔
1878
    }
1879
    case TSDB_DATA_TYPE_NULL: {
×
1880
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1881
      numOfElem = 1;
×
1882
      break;
×
1883
    }
1884

1885
    default:
×
1886
      break;
×
1887
  }
1888

1889
  pInfo->startVal = x;
6,051,996✔
1890
  pInfo->num += numOfElem;
6,051,996✔
1891

1892
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,051,421✔
1893

1894
  return TSDB_CODE_SUCCESS;
6,051,421✔
1895
}
1896

1897
int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,140,725✔
1898
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,140,725✔
1899
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,140,725✔
1900
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
5,140,725✔
1901
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5,140,725✔
1902

1903
  if (NULL == pCol) {
5,140,725✔
1904
    return TSDB_CODE_OUT_OF_RANGE;
×
1905
  }
1906
  int32_t currentRow = pBlock->info.rows;
5,140,725✔
1907

1908
  if (0 == pInfo->num) {
5,140,725✔
1909
    colDataSetNULL(pCol, currentRow);
3,732,369✔
1910
    return TSDB_CODE_SUCCESS;
3,732,369✔
1911
  }
1912

1913
  double(*param)[3] = pInfo->matrix;
1,408,356✔
1914

1915
  param[1][1] = (double)pInfo->num;
1,408,356✔
1916
  param[1][0] = param[0][1];
1,408,356✔
1917

1918
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
1,408,356✔
1919
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
1,408,356✔
1920

1921
  if (0 == param00) {
1,408,356✔
1922
    colDataSetNULL(pCol, currentRow);
739,774✔
1923
    return TSDB_CODE_SUCCESS;
739,774✔
1924
  }
1925

1926
  // param[0][1] = 0;
1927
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
668,582✔
1928
  // param[1][0] = 0;
1929
  param02 /= param00;
668,582✔
1930

1931
  param12 /= param[1][1];
668,582✔
1932

1933
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
668,582✔
1934
  char slopBuf[64] = {0};
668,582✔
1935
  char interceptBuf[64] = {0};
668,582✔
1936
  int  n = snprintf(slopBuf, 64, "%.6lf", param02);
668,582✔
1937
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
668,582✔
1938
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
1,006✔
1939
  }
1940
  n = snprintf(interceptBuf, 64, "%.6lf", param12);
668,582✔
1941
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
668,582✔
1942
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
2,012✔
1943
  }
1944
  size_t len =
668,582✔
1945
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
668,582✔
1946
  varDataSetLen(buf, len);
668,582✔
1947

1948
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
668,582✔
1949

1950
  return code;
668,582✔
1951
}
1952

1953
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1954
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1955
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1956
  int32_t              type = pDestCtx->input.pData[0]->info.type;
×
1957
  double(*pDparam)[3] = pDBuf->matrix;
×
1958

1959
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
1960
  SLeastSQRInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
1961
  double(*pSparam)[3] = pSBuf->matrix;
×
1962
  for (int32_t i = 0; i < pSBuf->num; i++) {
×
1963
    pDparam[0][0] += pDBuf->startVal * pDBuf->startVal;
×
1964
    pDparam[0][1] += pDBuf->startVal;
×
1965
    pDBuf->startVal += pDBuf->stepVal;
×
1966
  }
1967
  pDparam[0][2] += pSparam[0][2] + pDBuf->num * pDBuf->stepVal * pSparam[1][2];
×
1968
  pDparam[1][2] += pSparam[1][2];
×
1969
  pDBuf->num += pSBuf->num;
×
1970
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
1971
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
1972
  return TSDB_CODE_SUCCESS;
×
1973
}
1974

1975
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
96,010✔
1976
  pEnv->calcMemSize = sizeof(SPercentileInfo);
96,010✔
1977
  return true;
96,010✔
1978
}
1979

1980
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
273,765✔
1981
  if (pResultInfo->initialized) {
273,765✔
1982
    return TSDB_CODE_SUCCESS;
×
1983
  }
1984
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
273,765✔
1985
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1986
  }
1987

1988
  // in the first round, get the min-max value of all involved data
1989
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
273,765✔
1990
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
273,765✔
1991
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
273,765✔
1992
  pInfo->numOfElems = 0;
273,765✔
1993

1994
  return TSDB_CODE_SUCCESS;
273,765✔
1995
}
1996

1997
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
96,010✔
1998
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
96,010✔
1999
    return;
×
2000
  }
2001
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
96,010✔
2002
  if (pInfo->pMemBucket != NULL) {
96,010✔
2003
    tMemBucketDestroy(&(pInfo->pMemBucket));
×
2004
    pInfo->pMemBucket = NULL;
×
2005
  }
2006
}
2007

2008
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
1,663,050✔
2009
  int32_t              code = TSDB_CODE_SUCCESS;
1,663,050✔
2010
  int32_t              numOfElems = 0;
1,663,050✔
2011
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,663,050✔
2012

2013
  SInputColumnInfoData* pInput = &pCtx->input;
1,663,050✔
2014
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
1,663,050✔
2015

2016
  SColumnInfoData* pCol = pInput->pData[0];
1,663,050✔
2017
  int32_t          type = pCol->info.type;
1,663,050✔
2018

2019
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,663,050✔
2020
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
1,663,050✔
2021
    pInfo->stage += 1;
273,765✔
2022

2023
    // all data are null, set it completed
2024
    if (pInfo->numOfElems == 0) {
273,765✔
2025
      pResInfo->complete = true;
58,632✔
2026
      return TSDB_CODE_SUCCESS;
58,632✔
2027
    } else {
2028
      code = tMemBucketCreate(pCol->info.bytes, type, typeGetTypeModFromColInfo(&pCol->info), pInfo->minval,
215,133✔
2029
                              pInfo->maxval, pCtx->hasWindowOrGroup, &pInfo->pMemBucket, pInfo->numOfElems);
215,133✔
2030
      if (TSDB_CODE_SUCCESS != code) {
215,133✔
2031
        return code;
×
2032
      }
2033
    }
2034
  }
2035

2036
  // the first stage, only acquire the min/max value
2037
  if (pInfo->stage == 0) {
1,604,418✔
2038
    if (pCtx->input.colDataSMAIsSet) {
831,525✔
2039
      double tmin = 0.0, tmax = 0.0;
×
2040
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
2041
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
2042
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
2043
      } else if (IS_FLOAT_TYPE(type)) {
×
2044
        tmin = GET_DOUBLE_VAL(&pAgg->min);
×
2045
        tmax = GET_DOUBLE_VAL(&pAgg->max);
×
2046
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
2047
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
2048
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
2049
      }
2050

2051
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
×
2052
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
×
2053
      }
2054

2055
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
×
2056
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
×
2057
      }
2058

2059
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
×
2060
    } else {
2061
      // check the valid data one by one
2062
      int32_t start = pInput->startRowIndex;
831,525✔
2063
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
19,504,960✔
2064
        if (colDataIsNull_f(pCol, i)) {
18,673,435✔
2065
          continue;
279,600✔
2066
        }
2067

2068
        char* data = colDataGetData(pCol, i);
18,393,835✔
2069

2070
        double v = 0;
18,393,835✔
2071
        GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
18,393,835✔
2072
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
18,393,835✔
2073
          SET_DOUBLE_VAL(&pInfo->minval, v);
242,079✔
2074
        }
2075

2076
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
18,393,835✔
2077
          SET_DOUBLE_VAL(&pInfo->maxval, v);
14,795,385✔
2078
        }
2079

2080
        pInfo->numOfElems += 1;
18,393,835✔
2081
      }
2082
    }
2083
  } else {
2084
    // the second stage, calculate the true percentile value
2085
    int32_t start = pInput->startRowIndex;
772,893✔
2086
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
19,166,728✔
2087
      if (colDataIsNull_f(pCol, i)) {
18,393,835✔
2088
        continue;
×
2089
      }
2090

2091
      char* data = colDataGetData(pCol, i);
18,393,835✔
2092
      numOfElems += 1;
18,393,835✔
2093
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
18,393,835✔
2094
      if (code != TSDB_CODE_SUCCESS) {
18,393,835✔
2095
        tMemBucketDestroy(&(pInfo->pMemBucket));
×
2096
        return code;
×
2097
      }
2098
    }
2099

2100
    SET_VAL(pResInfo, numOfElems, 1);
772,893✔
2101
  }
2102

2103
  pCtx->needCleanup = true;
1,604,418✔
2104
  return TSDB_CODE_SUCCESS;
1,604,418✔
2105
}
2106

2107
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
273,765✔
2108
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
273,765✔
2109
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
273,765✔
2110

2111
  int32_t code = 0;
273,765✔
2112
  double  v = 0;
273,765✔
2113

2114
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
273,765✔
2115
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
273,765✔
2116
    if (pCtx->numOfParams > 2) {
215,133✔
2117
      char buf[3200] = {0};
3,012✔
2118
      // max length of double num is 317, e.g. use %.6lf to print -1.0e+308, consider the comma and bracket, 3200 is
2119
      // enough.
2120
      size_t len = 1;
3,012✔
2121

2122
      varDataVal(buf)[0] = '[';
3,012✔
2123
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
33,132✔
2124
        SVariant* pVal = &pCtx->param[i].param;
30,120✔
2125

2126
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[i].pCol));
30,120✔
2127

2128
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
30,120✔
2129
        if (code != TSDB_CODE_SUCCESS) {
30,120✔
2130
          goto _fin_error;
×
2131
        }
2132

2133
        if (i == pCtx->numOfParams - 1) {
30,120✔
2134
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
3,012✔
2135
        } else {
2136
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
27,108✔
2137
        }
2138
      }
2139

2140
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
3,012✔
2141
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
3,012✔
2142
      if (NULL == pCol) {
3,012✔
2143
        code = terrno;
×
2144
        goto _fin_error;
×
2145
      }
2146

2147
      varDataSetLen(buf, len);
3,012✔
2148
      code = colDataSetVal(pCol, pBlock->info.rows, buf, false);
3,012✔
2149
      if (code != TSDB_CODE_SUCCESS) {
3,012✔
2150
        goto _fin_error;
×
2151
      }
2152

2153
      tMemBucketDestroy(pMemBucket);
3,012✔
2154
      return TSDB_CODE_SUCCESS;
3,012✔
2155
    } else {
2156
      SVariant* pVal = &pCtx->param[1].param;
212,121✔
2157

2158
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
212,121✔
2159

2160
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
212,121✔
2161
      if (code != TSDB_CODE_SUCCESS) {
212,121✔
2162
        goto _fin_error;
×
2163
      }
2164

2165
      tMemBucketDestroy(pMemBucket);
212,121✔
2166
      return functionFinalize(pCtx, pBlock);
212,121✔
2167
    }
2168
  } else {
2169
    return functionFinalize(pCtx, pBlock);
58,632✔
2170
  }
2171

2172
_fin_error:
×
2173

2174
  tMemBucketDestroy(pMemBucket);
×
2175
  return code;
×
2176
}
2177

2178
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
3,574,825✔
2179
  int32_t bytesHist =
3,574,825✔
2180
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2181
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
3,574,825✔
2182
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
3,574,825✔
2183
  return true;
3,575,975✔
2184
}
2185

2186
int32_t getApercentileMaxSize() {
413,541✔
2187
  int32_t bytesHist =
413,541✔
2188
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2189
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
413,541✔
2190
  return TMAX(bytesHist, bytesDigest);
413,541✔
2191
}
2192

2193
static int8_t getApercentileAlgo(char* algoStr) {
3,231,375✔
2194
  int8_t algoType;
2195
  if (strcasecmp(algoStr, "default") == 0) {
3,231,375✔
2196
    algoType = APERCT_ALGO_DEFAULT;
1,614,450✔
2197
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,616,925✔
2198
    algoType = APERCT_ALGO_TDIGEST;
1,616,925✔
2199
  } else {
UNCOV
2200
    algoType = APERCT_ALGO_UNKNOWN;
×
2201
  }
2202

2203
  return algoType;
3,231,375✔
2204
}
2205

2206
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
196,843,597✔
2207
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
196,843,597✔
2208
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
196,844,102✔
2209
}
196,844,172✔
2210

2211
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
3,249,070✔
2212
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
3,249,070✔
2213
}
3,249,070✔
2214

2215
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
64,759,740✔
2216
  if (pResultInfo->initialized) {
64,759,740✔
2217
    return TSDB_CODE_SUCCESS;
×
2218
  }
2219
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
64,759,740✔
2220
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2221
  }
2222

2223
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
64,760,385✔
2224

2225
  SVariant* pVal = &pCtx->param[1].param;
64,760,385✔
2226
  pInfo->percent = 0;
64,759,165✔
2227
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
64,759,740✔
2228

2229
  if (pCtx->numOfParams == 2) {
64,759,810✔
2230
    pInfo->algo = APERCT_ALGO_DEFAULT;
61,528,940✔
2231
  } else if (pCtx->numOfParams == 3) {
3,231,950✔
2232
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
3,231,950✔
2233
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
3,227,350✔
2234
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2235
    }
2236
  }
2237

2238
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
64,759,740✔
2239
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
64,759,235✔
2240
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,616,350✔
2241
  } else {
2242
    buildHistogramInfo(pInfo);
63,142,885✔
2243
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
63,142,885✔
2244
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
63,138,215✔
2245
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2246
  }
2247

2248
  return TSDB_CODE_SUCCESS;
64,759,740✔
2249
}
2250

2251
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
74,832,856✔
2252
  int32_t               numOfElems = 0;
74,832,856✔
2253
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
74,832,856✔
2254
  SInputColumnInfoData* pInput = &pCtx->input;
74,832,856✔
2255

2256
  SColumnInfoData* pCol = pInput->pData[0];
74,832,856✔
2257
  int32_t          type = pCol->info.type;
74,832,856✔
2258

2259
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
74,832,856✔
2260

2261
  int32_t start = pInput->startRowIndex;
74,825,671✔
2262
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
74,832,281✔
2263
    buildTDigestInfo(pInfo);
1,615,845✔
2264
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,616,420✔
2265
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
84,094,723✔
2266
      if (colDataIsNull_f(pCol, i)) {
82,478,878✔
2267
        continue;
42,401,654✔
2268
      }
2269
      numOfElems += 1;
40,078,374✔
2270
      char* data = colDataGetData(pCol, i);
40,078,374✔
2271

2272
      double  v = 0;  // value
40,088,724✔
2273
      int64_t w = 1;  // weigth
40,088,724✔
2274
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
40,088,724✔
2275
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
40,088,149✔
2276
      if (code != TSDB_CODE_SUCCESS) {
40,076,074✔
2277
        return code;
×
2278
      }
2279
    }
2280
  } else {
2281
    // might be a race condition here that pHisto can be overwritten or setup function
2282
    // has not been called, need to relink the buffer pHisto points to.
2283
    buildHistogramInfo(pInfo);
73,215,775✔
2284
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
73,215,775✔
2285
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2286
           pInfo->pHisto->elems);
2287
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
2288
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
2289
        continue;
1,541,955,662✔
2290
      }
2291
      numOfElems += 1;
957,894,056✔
2292
      char* data = colDataGetData(pCol, i);
957,894,056✔
2293

2294
      double v = 0;
958,716,138✔
2295
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
958,716,138✔
2296
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
958,658,244✔
2297
      if (code != TSDB_CODE_SUCCESS) {
957,345,199✔
2298
        return code;
×
2299
      }
2300
    }
2301

2302
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
73,216,436✔
2303
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2304
           pInfo->pHisto->elems);
2305
  }
2306

2307
  SET_VAL(pResInfo, numOfElems, 1);
74,832,856✔
2308
  return TSDB_CODE_SUCCESS;
74,832,856✔
2309
}
2310

2311
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
268,734✔
2312
  pOutput->percent = pInput->percent;
268,734✔
2313
  pOutput->algo = pInput->algo;
268,734✔
2314
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
268,734✔
2315
    buildTDigestInfo(pInput);
15,655✔
2316
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
15,655✔
2317

2318
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
15,655✔
2319
      return TSDB_CODE_SUCCESS;
505✔
2320
    }
2321

2322
    if (hasRes) {
15,150✔
2323
      *hasRes = true;
15,150✔
2324
    }
2325

2326
    buildTDigestInfo(pOutput);
15,150✔
2327
    TDigest* pTDigest = pOutput->pTDigest;
15,150✔
2328
    tdigestAutoFill(pTDigest, COMPRESSION);
15,150✔
2329

2330
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
15,150✔
2331
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
15,150✔
2332
      tdigestAutoFill(pTDigest, COMPRESSION);
15,150✔
2333
    } else {
2334
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
×
2335
      if (TSDB_CODE_SUCCESS != code) {
×
2336
        return code;
×
2337
      }
2338
    }
2339
  } else {
2340
    buildHistogramInfo(pInput);
253,079✔
2341
    if (pInput->pHisto->numOfElems <= 0) {
253,079✔
2342
      return TSDB_CODE_SUCCESS;
114,645✔
2343
    }
2344

2345
    if (hasRes) {
138,434✔
2346
      *hasRes = true;
138,434✔
2347
    }
2348

2349
    buildHistogramInfo(pOutput);
138,434✔
2350
    SHistogramInfo* pHisto = pOutput->pHisto;
138,434✔
2351

2352
    if (pHisto->numOfElems <= 0) {
138,434✔
2353
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
121,500✔
2354
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
121,500✔
2355

2356
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
121,500✔
2357
             pHisto);
2358
    } else {
2359
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
16,934✔
2360
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
16,934✔
2361
             pHisto->numOfEntries, pInput->pHisto);
2362

2363
      SHistogramInfo* pRes = NULL;
16,934✔
2364
      int32_t         code = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN, &pRes);
16,934✔
2365
      if (TSDB_CODE_SUCCESS != code) {
16,934✔
2366
        tHistogramDestroy(&pRes);
×
2367
        return code;
×
2368
      }
2369
      (void)memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
16,934✔
2370
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
16,934✔
2371

2372
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
16,934✔
2373
             pHisto);
2374
      tHistogramDestroy(&pRes);
16,934✔
2375
    }
2376
  }
2377
  return TSDB_CODE_SUCCESS;
153,584✔
2378
}
2379

2380
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
264,222✔
2381
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
264,222✔
2382

2383
  SInputColumnInfoData* pInput = &pCtx->input;
264,222✔
2384

2385
  SColumnInfoData* pCol = pInput->pData[0];
264,222✔
2386
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
264,222✔
2387
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2388
  }
2389

2390
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
264,222✔
2391

2392
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
264,222✔
2393

2394
  bool    hasRes = false;
264,222✔
2395
  int32_t start = pInput->startRowIndex;
264,222✔
2396
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
532,956✔
2397
    char* data = colDataGetData(pCol, i);
268,734✔
2398

2399
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
268,734✔
2400
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
268,734✔
2401
    if (TSDB_CODE_SUCCESS != code) {
268,734✔
2402
      return code;
×
2403
    }
2404
  }
2405

2406
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
264,222✔
2407
    buildHistogramInfo(pInfo);
248,567✔
2408
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
248,567✔
2409
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2410
  }
2411

2412
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
264,222✔
2413
  return TSDB_CODE_SUCCESS;
264,222✔
2414
}
2415

2416
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
61,445,552✔
2417
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
61,445,552✔
2418
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
61,447,852✔
2419

2420
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
61,447,852✔
2421
    buildTDigestInfo(pInfo);
1,601,845✔
2422
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,601,845✔
2423
    if (pInfo->pTDigest->size > 0) {
1,601,845✔
2424
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,601,845✔
2425
    } else {  // no need to free
2426
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2427
      return TSDB_CODE_SUCCESS;
×
2428
    }
2429
  } else {
2430
    buildHistogramInfo(pInfo);
59,846,007✔
2431
    if (pInfo->pHisto->numOfElems > 0) {
59,846,007✔
2432
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
27,806,049✔
2433
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2434

2435
      double  ratio[] = {pInfo->percent};
27,806,049✔
2436
      double* res = NULL;
27,806,049✔
2437
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
27,806,049✔
2438
      if (TSDB_CODE_SUCCESS != code) {
27,806,049✔
2439
        taosMemoryFree(res);
×
2440
        return code;
×
2441
      }
2442
      pInfo->result = *res;
27,806,049✔
2443
      // memcpy(pCtx->pOutput, res, sizeof(double));
2444
      taosMemoryFree(res);
27,806,049✔
2445
    } else {  // no need to free
2446
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2447
      // return TSDB_CODE_SUCCESS;
2448
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
32,039,958✔
2449
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2450
    }
2451
  }
2452

2453
  return functionFinalize(pCtx, pBlock);
61,447,852✔
2454
}
2455

2456
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
268,734✔
2457
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
268,734✔
2458
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
268,734✔
2459

2460
  int32_t resultBytes = getApercentileMaxSize();
268,734✔
2461
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
268,734✔
2462
  if (NULL == res) {
268,734✔
2463
    return terrno;
×
2464
  }
2465

2466
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
268,734✔
2467
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
15,655✔
2468
    varDataSetLen(res, resultBytes);
15,655✔
2469
  } else {
2470
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
253,079✔
2471
    varDataSetLen(res, resultBytes);
253,079✔
2472
  }
2473

2474
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
268,734✔
2475
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
268,734✔
2476
  if (NULL == pCol) {
268,734✔
2477
    taosMemoryFree(res);
×
2478
    return TSDB_CODE_OUT_OF_RANGE;
×
2479
  }
2480

2481
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
268,734✔
2482

2483
  taosMemoryFree(res);
268,734✔
2484
  return code;
268,734✔
2485
}
2486

2487
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
2488
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
2489
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
2490

2491
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
2492
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
2493

2494
  qDebug("%s start to combine apercentile, %p", __FUNCTION__, pDBuf->pHisto);
×
2495

2496
  int32_t code = apercentileTransferInfo(pSBuf, pDBuf, NULL);
×
2497
  if (TSDB_CODE_SUCCESS != code) {
×
2498
    return code;
×
2499
  }
2500
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
2501
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
2502
  return TSDB_CODE_SUCCESS;
×
2503
}
2504

2505
// TODO: change this function when block data info pks changed
2506
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
231,516✔
2507
  char numVal[8] = {0};
231,516✔
2508
  switch (pkType) {
231,516✔
2509
    case TSDB_DATA_TYPE_INT:
36,287✔
2510
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
36,287✔
2511
      break;
36,287✔
2512
    case TSDB_DATA_TYPE_UINT:
39,494✔
2513
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
39,494✔
2514
      break;
39,494✔
2515
    case TSDB_DATA_TYPE_BIGINT:
51,716✔
2516
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
51,716✔
2517
      break;
51,716✔
2518
    case TSDB_DATA_TYPE_UBIGINT:
37,457✔
2519
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
37,457✔
2520
      break;
37,457✔
2521
    default:
66,562✔
2522
      break;
66,562✔
2523
  }
2524
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
231,516✔
2525
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
231,516✔
2526
  return fn(pkData, blockData);
231,516✔
2527
}
2528

2529
EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
2,147,483,647✔
2530
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
2,147,483,647✔
2531

2532
  // not initialized yet, data is required
2533
  if (pEntry == NULL) {
2,147,483,647✔
2534
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2535
  }
2536

2537
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
2,147,483,647✔
2538
  if (pResult->hasResult) {
2,147,483,647✔
2539
    if (pResult->pkBytes > 0) {
2,147,483,647✔
2540
      pResult->pkData = pResult->buf + pResult->bytes;
838,012✔
2541
    } else {
2542
      pResult->pkData = NULL;
2,147,483,647✔
2543
    }
2544
    if (pResult->ts < pBlockInfo->window.skey) {
2,147,483,647✔
2545
      return FUNC_DATA_REQUIRED_NOT_LOAD;
3,622,496✔
2546
    } else if (pResult->ts == pBlockInfo->window.skey) {
2,147,483,647✔
2547
      if (NULL == pResult->pkData) {
2,147,483,647✔
2548
        return FUNC_DATA_REQUIRED_NOT_LOAD;
2,147,483,647✔
2549
      }
2550
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
168,896✔
2551
        return FUNC_DATA_REQUIRED_NOT_LOAD;
11,200✔
2552
      }
2553
    }
2554
    return FUNC_DATA_REQUIRED_DATA_LOAD;
460,669✔
2555
  } else {
2556
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,337,825✔
2557
  }
2558
}
2559

2560
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
30,452,224✔
2561
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
30,452,224✔
2562

2563
  // not initialized yet, data is required
2564
  if (pEntry == NULL) {
30,452,224✔
2565
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2566
  }
2567

2568
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
30,452,224✔
2569
  if (pResult->hasResult) {
30,460,666✔
2570
    if (pResult->pkBytes > 0) {
28,159,641✔
2571
      pResult->pkData = pResult->buf + pResult->bytes;
452,940✔
2572
    } else {
2573
      pResult->pkData = NULL;
27,706,099✔
2574
    }
2575
    if (pResult->ts > pBlockInfo->window.ekey) {
28,158,918✔
2576
      return FUNC_DATA_REQUIRED_NOT_LOAD;
8,309,537✔
2577
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
19,848,061✔
2578
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
62,620✔
2579
        return FUNC_DATA_REQUIRED_NOT_LOAD;
10,828✔
2580
      }
2581
    }
2582
    return FUNC_DATA_REQUIRED_DATA_LOAD;
19,837,233✔
2583
  } else {
2584
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,301,095✔
2585
  }
2586
}
2587

2588
// TODO modify it to include primary key bytes
2589
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
1,948,697,322✔
2590

2591
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
69,449,945✔
2592
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
69,449,945✔
2593
  // TODO: change SFunctionNode to add pk info
2594
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
69,454,994✔
2595
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
69,447,218✔
2596
  return true;
69,448,925✔
2597
}
2598

2599
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
16,343,424✔
2600
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
16,343,424✔
2601
  pEnv->calcMemSize = pNode->node.resType.bytes;
16,344,458✔
2602
  return true;
16,342,717✔
2603
}
2604

2605

2606
bool getHasNullFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
22,834,716✔
2607
  pEnv->calcMemSize = pFunc->node.resType.bytes;
22,834,716✔
2608
  return true;
22,834,716✔
2609
}
2610

2611
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
73,117,885✔
2612
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
73,117,885✔
2613
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
73,120,784✔
2614
  return true;
73,108,107✔
2615
}
2616

2617
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2618
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
2,147,483,647✔
2619
    return 0;
×
2620
  }
2621

2622
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
2,147,483,647✔
2623
}
2624

2625
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,147,483,647✔
2626
  if (pResInfo->initialized) {
2,147,483,647✔
2627
    return TSDB_CODE_SUCCESS;
×
2628
  }
2629
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,147,483,647✔
2630
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2631
  }
2632

2633
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2634
  pRes->nullTupleSaved = false;
2,147,483,647✔
2635
  pRes->nullTuplePos.pageId = -1;
2,147,483,647✔
2636
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2637
}
2638

2639
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
125,486,079✔
2640
  if (pCtx->subsidiaries.rowLen == 0) {
125,486,079✔
2641
    int32_t rowLen = 0;
5,413,509✔
2642
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
12,474,647✔
2643
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
7,060,092✔
2644
      rowLen += pc->pExpr->base.resSchema.bytes;
7,054,947✔
2645
    }
2646

2647
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
5,410,288✔
2648
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
5,409,616✔
2649
    if (NULL == pCtx->subsidiaries.buf) {
5,412,353✔
2650
      return terrno;
×
2651
    }
2652
  }
2653
  return TSDB_CODE_SUCCESS;
125,487,508✔
2654
}
2655

2656
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
2,147,483,647✔
2657
                                      SFirstLastRes* pInfo, bool noElements) {
2658
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
2659

2660
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
2661
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
2662
  }
2663

2664
  if (!pInfo->hasResult) {
79,171,661✔
2665
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
64,657,925✔
2666
  } else if (!noElements) {
14,509,950✔
2667
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
14,496,999✔
2668
  } else {
2669
  }  // dothing
2670

2671
  return code;
79,171,974✔
2672
}
2673

2674
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
2,147,483,647✔
2675
                                char* pData) {
2676
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2677
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2678

2679
  if (IS_VAR_DATA_TYPE(type)) {
2,147,483,647✔
2680
    pInfo->bytes = calcStrBytesByType(type, pData);
2,147,483,647✔
2681
    // if (type == TSDB_DATA_TYPE_JSON) {
2682
    //   pInfo->bytes = getJsonValueLen(pData);
2683
    // } else {
2684
    //   pInfo->bytes = varDataTLen(pData);
2685
    // }
2686
  }
2687

2688
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
2,147,483,647✔
2689
  if (pkData != NULL) {
2,147,483,647✔
2690
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
187,622,278✔
2691
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
62,396,768✔
2692
      // if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
2693
      //   pInfo->pkBytes = getJsonValueLen(pkData);
2694
      // } else {
2695
      //   pInfo->pkBytes = varDataTLen(pkData);
2696
      // }
2697
    }
2698
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
187,618,317✔
2699
    pInfo->pkData = pInfo->buf + pInfo->bytes;
187,612,410✔
2700
  }
2701

2702
  pInfo->ts = currentTs;
2,147,483,647✔
2703
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
2,147,483,647✔
2704
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2705
    return code;
×
2706
  }
2707

2708
  pInfo->hasResult = true;
2,147,483,647✔
2709
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2710
}
2711

2712
// This ordinary first function does not care if current scan is ascending order or descending order scan
2713
// the OPTIMIZED version of first function will only handle the ascending order scan
2714
int32_t firstFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
2715
  int32_t numOfElems = 0;
2,147,483,647✔
2716

2717
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2718
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2719

2720
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2721
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2722

2723
  pInfo->bytes = pInputCol->info.bytes;
2,147,483,647✔
2724

2725
  if (IS_NULL_TYPE(pInputCol->info.type)) {
2,147,483,647✔
2726
    return TSDB_CODE_SUCCESS;
700,919✔
2727
  }
2728

2729
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2730
  pInfo->pkType = -1;
2,147,483,647✔
2731
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2732
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2733
    pInfo->pkType = pkCol->info.type;
50,822,365✔
2734
    pInfo->pkBytes = pkCol->info.bytes;
50,835,729✔
2735
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
50,834,371✔
2736
  }
2737

2738
  // All null data column, return directly.
2739
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
2,147,483,647✔
2740
      pInputCol->hasNull == true) {
×
2741
    // save selectivity value for column consisted of all null values
2742
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2743
    if (code != TSDB_CODE_SUCCESS) {
×
2744
      return code;
×
2745
    }
2746
    pInfo->nullTupleSaved = true;
×
2747
    return TSDB_CODE_SUCCESS;
×
2748
  }
2749

2750
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
2,147,483,647✔
2751

2752
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2753
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2754

2755
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
2,147,483,647✔
2756

2757
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
2758
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2759
#if 0
2760
  if (blockDataOrder == TSDB_ORDER_ASC) {
2761
    // filter according to current result firstly
2762
    if (pResInfo->numOfRes > 0) {
2763
      if (pInfo->ts < startKey) {
2764
        return TSDB_CODE_SUCCESS;
2765
      }
2766
    }
2767

2768
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2769
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2770
        continue;
2771
      }
2772

2773
      numOfElems++;
2774

2775
      char* data = colDataGetData(pInputCol, i);
2776
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2777
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2778
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2779
        break;
2780
      }
2781
    }
2782
  } else {
2783
    // in case of descending order time stamp serial, which usually happens as the results of the nest query,
2784
    // all data needs to be check.
2785
    if (pResInfo->numOfRes > 0) {
2786
      if (pInfo->ts < endKey) {
2787
        return TSDB_CODE_SUCCESS;
2788
      }
2789
    }
2790

2791
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2792
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2793
        continue;
2794
      }
2795

2796
      numOfElems++;
2797

2798
      char* data = colDataGetData(pInputCol, i);
2799
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2800

2801
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2802
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2803
        break;
2804
      }
2805
    }
2806
  }
2807
#else
2808
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2809

2810
  int     from = -1;
2,147,483,647✔
2811
  int32_t i = -1;
2,147,483,647✔
2812
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
2,147,483,647✔
2813
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2,147,483,647✔
2814
      continue;
2,147,483,647✔
2815
    }
2816

2817
    numOfElems++;
2,147,483,647✔
2818
    char* data = colDataGetData(pInputCol, i);
2,147,483,647✔
2819
    char* pkData = NULL;
2,147,483,647✔
2820
    if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2821
      pkData = colDataGetData(pkCol, i);
181,094,161✔
2822
    }
2823
    TSKEY cts = pts[i];
2,147,483,647✔
2824
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
2,147,483,647✔
2825
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
2,147,483,647✔
2826
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
2,147,483,647✔
2827
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2828
        return code;
×
2829
      }
2830
      pResInfo->numOfRes = 1;
2,147,483,647✔
2831
    }
2832
  }
2833
#endif
2834

2835
  if (numOfElems == 0) {
2,147,483,647✔
2836
    // save selectivity value for column consisted of all null values
2837
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
2,147,483,647✔
2838
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2839
      return code;
×
2840
    }
2841
    pInfo->nullTupleSaved = true;
2,147,483,647✔
2842
  }
2843
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
2844
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2845
}
2846

2847
int32_t lastFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
2848
  int32_t numOfElems = 0;
2,147,483,647✔
2849

2850
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2851
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2852

2853
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2854
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2855

2856
  int32_t type = pInputCol->info.type;
2,147,483,647✔
2857
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
2858

2859
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
2860
    return TSDB_CODE_SUCCESS;
681,755✔
2861
  }
2862
  pInfo->bytes = bytes;
2,147,483,647✔
2863

2864
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2865
  pInfo->pkType = -1;
2,147,483,647✔
2866
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2867
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2868
    pInfo->pkType = pkCol->info.type;
50,988,349✔
2869
    pInfo->pkBytes = pkCol->info.bytes;
50,990,997✔
2870
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
50,989,628✔
2871
  }
2872

2873
  // All null data column, return directly.
2874
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
2,147,483,647✔
2875
      pInputCol->hasNull == true) {
×
2876
    // save selectivity value for column consisted of all null values
2877
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2878
    if (code != TSDB_CODE_SUCCESS) {
×
2879
      return code;
×
2880
    }
2881
    pInfo->nullTupleSaved = true;
×
2882
    return TSDB_CODE_SUCCESS;
×
2883
  }
2884

2885
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
2,147,483,647✔
2886

2887
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2888
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2889

2890
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
2,147,483,647✔
2891

2892
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2893
#if 0
2894
  if (blockDataOrder == TSDB_ORDER_ASC) {
2895
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2896
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2897
        continue;
2898
      }
2899

2900
      numOfElems++;
2901

2902
      char* data = colDataGetData(pInputCol, i);
2903
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2904
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2905
        doSaveCurrentVal(pCtx, i, cts, type, data);
2906
      }
2907

2908
      break;
2909
    }
2910
  } else {  // descending order
2911
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2912
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2913
        continue;
2914
      }
2915

2916
      numOfElems++;
2917

2918
      char* data = colDataGetData(pInputCol, i);
2919
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2920
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2921
        doSaveCurrentVal(pCtx, i, cts, type, data);
2922
      }
2923
      break;
2924
    }
2925
  }
2926
#else
2927
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2928

2929
#if 0
2930
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2931
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2932
        continue;
2933
      }
2934

2935
      numOfElems++;
2936
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2937
        char* data = colDataGetData(pInputCol, i);
2938
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2939
        pResInfo->numOfRes = 1;
2940
      }
2941
    }
2942
#else
2943

2944
  // todo refactor
2945
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
2,147,483,647✔
2946
    numOfElems = 1;
2,147,483,647✔
2947

2948
    int32_t round = pInput->numOfRows >> 2;
2,147,483,647✔
2949
    int32_t reminder = pInput->numOfRows & 0x03;
2,147,483,647✔
2950

2951
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
2,147,483,647✔
2952
      int64_t cts = pts[i];
498,666,397✔
2953
      int32_t chosen = i;
498,660,177✔
2954

2955
      if (cts < pts[i + 1]) {
498,660,177✔
2956
        cts = pts[i + 1];
147,639,939✔
2957
        chosen = i + 1;
147,639,939✔
2958
      }
2959

2960
      if (cts < pts[i + 2]) {
498,660,027✔
2961
        cts = pts[i + 2];
147,640,229✔
2962
        chosen = i + 2;
147,640,229✔
2963
      }
2964

2965
      if (cts < pts[i + 3]) {
498,660,179✔
2966
        cts = pts[i + 3];
147,638,521✔
2967
        chosen = i + 3;
147,638,521✔
2968
      }
2969

2970
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
498,661,886✔
2971
        char*   data = colDataGetData(pInputCol, chosen);
177,759,726✔
2972
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
177,759,731✔
2973
        if (code != TSDB_CODE_SUCCESS) {
177,762,605✔
2974
          return code;
×
2975
        }
2976
        pResInfo->numOfRes = 1;
177,762,605✔
2977
      }
2978
    }
2979

2980
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,147,483,647✔
2981
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2,147,483,647✔
2982
        char*   data = colDataGetData(pInputCol, i);
984,143,275✔
2983
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
981,778,015✔
2984
        if (code != TSDB_CODE_SUCCESS) {
981,567,628✔
2985
          return code;
×
2986
        }
2987
        pResInfo->numOfRes = 1;
981,567,628✔
2988
      }
2989
    }
2990
  } else {
2991
    int     from = -1;
2,147,483,647✔
2992
    int32_t i = -1;
2,147,483,647✔
2993
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
2,147,483,647✔
2994
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2,147,483,647✔
2995
        continue;
2,147,483,647✔
2996
      }
2997

2998
      numOfElems++;
2,147,483,647✔
2999
      char* pkData = NULL;
2,147,483,647✔
3000
      if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, i)) {
2,147,483,647✔
3001
        // pkCol[i] might be null when using cachemodel
3002
        // however, if using cachemodel, we don't need pk to determine the order
3003
        // because ts is enough
3004
        pkData = colDataGetData(pkCol, i);
181,313,259✔
3005
      }
3006
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
2,147,483,647✔
3007
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
2,147,483,647✔
3008
        char*   data = colDataGetData(pInputCol, i);
2,147,483,647✔
3009
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
2,147,483,647✔
3010
        if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3011
          return code;
×
3012
        }
3013
        pResInfo->numOfRes = 1;
2,147,483,647✔
3014
      }
3015
    }
3016
  }
3017
#endif
3018

3019
#endif
3020

3021
  // save selectivity value for column consisted of all null values
3022
  if (numOfElems == 0) {
2,147,483,647✔
3023
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
2,147,483,647✔
3024
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3025
      return code;
×
3026
    }
3027
    pInfo->nullTupleSaved = true;
2,147,483,647✔
3028
  }
3029

3030
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3031
}
3032

3033
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
1,497,574,022✔
3034
  if (!pInput->hasResult) {
1,497,574,022✔
3035
    return false;
×
3036
  }
3037
  __compar_fn_t pkCompareFn = NULL;
1,497,574,280✔
3038
  if (pInput->pkData) {
1,497,574,280✔
3039
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
4,450,892✔
3040
  }
3041
  if (pOutput->hasResult) {
1,497,574,796✔
3042
    if (isFirst) {
818,237,782✔
3043
      if (pInput->ts > pOutput->ts ||
714,766,594✔
3044
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
714,036,395✔
3045
        return false;
862,604✔
3046
      }
3047
    } else {
3048
      if (pInput->ts < pOutput->ts ||
103,471,188✔
3049
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
100,875,893✔
3050
        return false;
2,827,548✔
3051
      }
3052
    }
3053
  }
3054

3055
  pOutput->isNull = pInput->isNull;
1,493,884,421✔
3056
  pOutput->ts = pInput->ts;
1,493,885,453✔
3057
  pOutput->bytes = pInput->bytes;
1,493,885,453✔
3058
  pOutput->pkType = pInput->pkType;
1,493,885,195✔
3059

3060
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,493,885,676✔
3061
  if (pInput->pkData) {
1,493,885,711✔
3062
    pOutput->pkBytes = pInput->pkBytes;
3,973,149✔
3063
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
3,973,149✔
3064
    pOutput->pkData = pOutput->buf + pOutput->bytes;
3,973,149✔
3065
  }
3066
  return true;
1,493,886,297✔
3067
}
3068

3069
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,497,574,022✔
3070
                                     int32_t rowIndex) {
3071
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,497,574,022✔
3072
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,493,886,555✔
3073
    if (TSDB_CODE_SUCCESS != code) {
1,493,886,555✔
3074
      return code;
×
3075
    }
3076
    pOutput->hasResult = true;
1,493,886,555✔
3077
  }
3078
  return TSDB_CODE_SUCCESS;
1,497,576,707✔
3079
}
3080

3081
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
695,974,838✔
3082
  SInputColumnInfoData* pInput = &pCtx->input;
695,974,838✔
3083
  SColumnInfoData*      pCol = pInput->pData[0];
695,974,838✔
3084

3085
  if (IS_NULL_TYPE(pCol->info.type)) {
695,974,838✔
3086
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
3087
    return TSDB_CODE_SUCCESS;
×
3088
  }
3089

3090
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
695,975,096✔
3091
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3092
  }
3093

3094
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
695,975,577✔
3095

3096
  int32_t start = pInput->startRowIndex;
695,975,284✔
3097
  int32_t numOfElems = 0;
695,975,319✔
3098

3099
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,147,483,647✔
3100
    if (colDataIsNull_s(pCol, i)) {
2,147,483,647✔
3101
      continue;
255,489,683✔
3102
    }
3103
    char*          data = colDataGetData(pCol, i);
1,497,576,344✔
3104
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,497,575,863✔
3105
    if (pCtx->hasPrimaryKey) {
1,497,575,828✔
3106
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
4,450,892✔
3107
    } else {
3108
      pInputInfo->pkData = NULL;
1,493,124,713✔
3109
    }
3110

3111
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,497,574,022✔
3112
    if (code != TSDB_CODE_SUCCESS) {
1,497,576,449✔
3113
      return code;
×
3114
    }
3115
    if (!numOfElems) {
1,497,576,449✔
3116
      numOfElems = pInputInfo->hasResult ? 1 : 0;
691,756,712✔
3117
    }
3118
  }
3119

3120
  if (numOfElems == 0) {
695,973,583✔
3121
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
4,218,419✔
3122
    if (code != TSDB_CODE_SUCCESS) {
4,218,419✔
3123
      return code;
×
3124
    }
3125
    pInfo->nullTupleSaved = true;
4,218,419✔
3126
  }
3127

3128
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
695,972,809✔
3129
  return TSDB_CODE_SUCCESS;
695,973,806✔
3130
}
3131

3132
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
406,222,921✔
3133

3134
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
289,752,433✔
3135

3136
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
3137
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3138
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
3139
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
3140
  if (NULL == pCol) {
2,147,483,647✔
3141
    return TSDB_CODE_OUT_OF_RANGE;
×
3142
  }
3143

3144
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3145
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,147,483,647✔
3146

3147
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3148

3149
  if (pResInfo->isNullRes) {
2,147,483,647✔
3150
    colDataSetNULL(pCol, pBlock->info.rows);
2,147,483,647✔
3151
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,147,483,647✔
3152
  }
3153
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
2,147,483,647✔
3154
  if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3155
    return code;
×
3156
  }
3157

3158
  // handle selectivity
3159
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
2,147,483,647✔
3160
  if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3161
    qError("%s failed at %d, msg:%s", __func__, __LINE__, tstrerror(code));
×
3162
  }
3163

3164
  return code;
2,147,483,647✔
3165
}
3166

3167
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,862,248,763✔
3168
  int32_t code = TSDB_CODE_SUCCESS;
1,862,248,763✔
3169

3170
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,862,248,763✔
3171
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,862,640,630✔
3172

3173
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,862,581,620✔
3174

3175
  // todo check for failure
3176
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,862,182,717✔
3177
  if (NULL == res) {
1,859,148,791✔
3178
    return terrno;
×
3179
  }
3180
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,859,148,791✔
3181

3182
  varDataSetLen(res, resultBytes);
1,859,205,013✔
3183

3184
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,861,872,441✔
3185
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,862,603,028✔
3186
  if (NULL == pCol) {
1,862,108,685✔
3187
    taosMemoryFree(res);
×
3188
    return TSDB_CODE_OUT_OF_RANGE;
×
3189
  }
3190

3191
  if (pEntryInfo->numOfRes == 0) {
1,862,108,685✔
3192
    colDataSetNULL(pCol, pBlock->info.rows);
266,326,103✔
3193
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
266,306,237✔
3194
  } else {
3195
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,595,554,824✔
3196
    if (TSDB_CODE_SUCCESS != code) {
1,595,273,585✔
3197
      taosMemoryFree(res);
×
3198
      return code;
×
3199
    }
3200
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,595,273,585✔
3201
  }
3202
  taosMemoryFree(res);
1,861,688,350✔
3203
  return code;
1,861,754,532✔
3204
}
3205

3206
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
3207
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
3208
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
3209
  int32_t              bytes = pDBuf->bytes;
×
3210

3211
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
3212
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
3213

3214
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
×
3215
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
3216
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
3217
  return TSDB_CODE_SUCCESS;
×
3218
}
3219

3220
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
24,458,015✔
3221
  SInputColumnInfoData* pInput = &pCtx->input;
24,458,015✔
3222
  SColumnInfoData*      pInputCol = pInput->pData[0];
24,484,136✔
3223
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
24,537,754✔
3224

3225
  if (colDataIsNull_s(pInputCol, rowIndex)) {
48,995,808✔
3226
    pInfo->isNull = true;
2,948,147✔
3227
  } else {
3228
    pInfo->isNull = false;
21,535,269✔
3229

3230
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
21,542,635✔
3231
      pInfo->bytes = calcStrBytesByType(pInputCol->info.type, pData);
3,725,940✔
3232
      // if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
3233
      //   pInfo->bytes = getJsonValueLen(pData);
3234
      // } else {
3235
      //   pInfo->bytes = varDataTLen(pData);
3236
      // }
3237
    }
3238

3239
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
21,594,555✔
3240
  }
3241

3242
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
34,380,283✔
3243
    char* pkData = colDataGetData(pkCol, rowIndex);
9,860,376✔
3244
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
9,860,466✔
3245
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
3,233,389✔
3246
    }
3247
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
9,861,128✔
3248
    pInfo->pkData = pInfo->buf + pInfo->bytes;
9,859,759✔
3249
  }
3250
  pInfo->ts = cts;
24,530,398✔
3251
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
24,498,746✔
3252
  if (code != TSDB_CODE_SUCCESS) {
24,536,671✔
3253
    return code;
×
3254
  }
3255

3256
  pInfo->hasResult = true;
24,536,671✔
3257

3258
  return TSDB_CODE_SUCCESS;
24,539,552✔
3259
}
3260

3261
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
3262
  int32_t numOfElems = 0;
2,147,483,647✔
3263

3264
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3265
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3266

3267
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3268
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3269

3270
  int32_t type = pInputCol->info.type;
2,147,483,647✔
3271
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
3272
  pInfo->bytes = bytes;
2,147,483,647✔
3273

3274
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
3275
    return TSDB_CODE_SUCCESS;
21,106✔
3276
  }
3277
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
3278
  pInfo->pkType = -1;
2,147,483,647✔
3279
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
3280
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
3281
    pInfo->pkType = pkCol->info.type;
50,214,639✔
3282
    pInfo->pkBytes = pkCol->info.bytes;
50,216,670✔
3283
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
50,218,656✔
3284
  }
3285
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
3286
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
3287

3288
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3289
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
22,701,517✔
3290
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
11,349,756✔
3291
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
11,351,219✔
3292
      TSKEY cts = getRowPTs(pInput->pPTS, i);
11,353,083✔
3293
      numOfElems++;
11,352,079✔
3294

3295
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
11,352,079✔
3296
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
3,182,884✔
3297
        if (code != TSDB_CODE_SUCCESS) return code;
3,180,789✔
3298
      }
3299

3300
      break;
11,351,475✔
3301
    }
3302
  } else if (pCtx->order == TSDB_ORDER_DESC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3303
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3304
    // this assumption is NOT always works if project operator exists in downstream.
3305
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
3306
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
2,147,483,647✔
3307
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
2,147,483,647✔
3308
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2,147,483,647✔
3309
      numOfElems++;
2,147,483,647✔
3310

3311
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2,147,483,647✔
3312
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
8,771,827✔
3313
        if (code != TSDB_CODE_SUCCESS) return code;
9,133,444✔
3314
      }
3315
      break;
2,147,483,647✔
3316
    }
3317
  } else {
3318
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
42,980,622✔
3319
    int      from = -1;
50,872,825✔
3320
    int32_t  i = -1;
50,869,515✔
3321
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
235,849,748✔
3322
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
184,971,307✔
3323
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
184,988,581✔
3324
      TSKEY cts = pts[i];
184,988,518✔
3325

3326
      numOfElems++;
184,981,023✔
3327
      char* pkData = NULL;
184,981,023✔
3328
      if (pCtx->hasPrimaryKey) {
184,981,023✔
3329
        pkData = colDataGetData(pkCol, i);
180,093,616✔
3330
      }
3331
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
185,027,818✔
3332
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
173,304,959✔
3333
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
11,678,478✔
3334
        if (code != TSDB_CODE_SUCCESS) {
11,682,119✔
3335
          return code;
×
3336
        }
3337
        pResInfo->numOfRes = 1;
11,682,119✔
3338
      }
3339
    }
3340
  }
3341

3342
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
3343
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3344
}
3345

3346
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
589,788✔
3347
  pEnv->calcMemSize = sizeof(SDiffInfo);
589,788✔
3348
  return true;
589,788✔
3349
}
3350

3351
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
69,413,282✔
3352
  if (pResInfo->initialized) {
69,413,282✔
3353
    return TSDB_CODE_SUCCESS;
53,274,512✔
3354
  }
3355
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
16,138,770✔
3356
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3357
  }
3358
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
16,138,770✔
3359
  pDiffInfo->hasPrev = false;
16,138,770✔
3360
  pDiffInfo->isFirstRow = true;
16,138,770✔
3361
  pDiffInfo->prev.i64 = 0;
16,138,770✔
3362
  pDiffInfo->prevTs = -1;
16,138,770✔
3363
  if (pCtx->numOfParams > 1) {
16,138,770✔
3364
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
16,138,770✔
3365
  } else {
3366
    pDiffInfo->ignoreOption = 0;
×
3367
  }
3368
  return TSDB_CODE_SUCCESS;
16,138,770✔
3369
}
3370

3371
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
16,014,077✔
3372
  switch (type) {
16,014,077✔
3373
    case TSDB_DATA_TYPE_BOOL:
4,238✔
3374
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
4,238✔
3375
      break;
4,238✔
3376
    case TSDB_DATA_TYPE_UTINYINT:
37,735✔
3377
    case TSDB_DATA_TYPE_TINYINT:
3378
      pDiffInfo->prev.i64 = *(int8_t*)pv;
37,735✔
3379
      break;
37,735✔
3380
    case TSDB_DATA_TYPE_UINT:
15,726,037✔
3381
    case TSDB_DATA_TYPE_INT:
3382
      pDiffInfo->prev.i64 = *(int32_t*)pv;
15,726,037✔
3383
      break;
15,726,037✔
3384
    case TSDB_DATA_TYPE_USMALLINT:
38,863✔
3385
    case TSDB_DATA_TYPE_SMALLINT:
3386
      pDiffInfo->prev.i64 = *(int16_t*)pv;
38,863✔
3387
      break;
38,863✔
3388
    case TSDB_DATA_TYPE_TIMESTAMP:
124,953✔
3389
    case TSDB_DATA_TYPE_UBIGINT:
3390
    case TSDB_DATA_TYPE_BIGINT:
3391
      pDiffInfo->prev.i64 = *(int64_t*)pv;
124,953✔
3392
      break;
124,953✔
3393
    case TSDB_DATA_TYPE_FLOAT:
17,676✔
3394
      pDiffInfo->prev.d64 = *(float*)pv;
17,676✔
3395
      break;
17,676✔
3396
    case TSDB_DATA_TYPE_DOUBLE:
64,575✔
3397
      pDiffInfo->prev.d64 = *(double*)pv;
64,575✔
3398
      break;
64,575✔
3399
    default:
×
3400
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3401
  }
3402
  pDiffInfo->prevTs = ts;
16,014,077✔
3403
  pDiffInfo->hasPrev = true;
16,014,077✔
3404
  return TSDB_CODE_SUCCESS;
16,014,077✔
3405
}
3406

3407
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
2,122,722✔
3408
  switch (type) {
2,122,722✔
3409
    case TSDB_DATA_TYPE_UINT: {
×
3410
      int64_t v = *(uint32_t*)pv;
×
3411
      return v < pDiffInfo->prev.i64;
×
3412
    }
3413
    case TSDB_DATA_TYPE_INT: {
397,464✔
3414
      int64_t v = *(int32_t*)pv;
397,464✔
3415
      return v < pDiffInfo->prev.i64;
397,464✔
3416
    }
3417
    case TSDB_DATA_TYPE_BOOL: {
×
3418
      int64_t v = *(bool*)pv;
×
3419
      return v < pDiffInfo->prev.i64;
×
3420
    }
3421
    case TSDB_DATA_TYPE_UTINYINT: {
×
3422
      int64_t v = *(uint8_t*)pv;
×
3423
      return v < pDiffInfo->prev.i64;
×
3424
    }
3425
    case TSDB_DATA_TYPE_TINYINT: {
499,602✔
3426
      int64_t v = *(int8_t*)pv;
499,602✔
3427
      return v < pDiffInfo->prev.i64;
499,602✔
3428
    }
3429
    case TSDB_DATA_TYPE_USMALLINT: {
×
3430
      int64_t v = *(uint16_t*)pv;
×
3431
      return v < pDiffInfo->prev.i64;
×
3432
    }
3433
    case TSDB_DATA_TYPE_SMALLINT: {
522,372✔
3434
      int64_t v = *(int16_t*)pv;
522,372✔
3435
      return v < pDiffInfo->prev.i64;
522,372✔
3436
    }
3437
    case TSDB_DATA_TYPE_UBIGINT: {
3,768✔
3438
      uint64_t v = *(uint64_t*)pv;
3,768✔
3439
      return v < (uint64_t)pDiffInfo->prev.i64;
3,768✔
3440
    }
3441
    case TSDB_DATA_TYPE_TIMESTAMP:
283,956✔
3442
    case TSDB_DATA_TYPE_BIGINT: {
3443
      int64_t v = *(int64_t*)pv;
283,956✔
3444
      return v < pDiffInfo->prev.i64;
283,956✔
3445
    }
3446
    case TSDB_DATA_TYPE_FLOAT: {
226,170✔
3447
      float v = *(float*)pv;
226,170✔
3448
      return v < pDiffInfo->prev.d64;
226,170✔
3449
    }
3450
    case TSDB_DATA_TYPE_DOUBLE: {
189,390✔
3451
      double v = *(double*)pv;
189,390✔
3452
      return v < pDiffInfo->prev.d64;
189,390✔
3453
    }
3454
    default:
×
3455
      return false;
×
3456
  }
3457

3458
  return false;
3459
}
3460

3461
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
2,147,483,647✔
3462
  bool isNegative = v < pDiffInfo->prev.i64;
2,147,483,647✔
3463
  if (type == TSDB_DATA_TYPE_UBIGINT) {
2,147,483,647✔
3464
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
470,271✔
3465
  }
3466
  int64_t delta = v - pDiffInfo->prev.i64;
2,147,483,647✔
3467
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3468
    colDataSetNull_f_s(pOutput, pos);
851,952✔
3469
    pOutput->hasNull = true;
851,952✔
3470
  } else {
3471
    colDataSetInt64(pOutput, pos, &delta);
2,147,483,647✔
3472
  }
3473
  pDiffInfo->prev.i64 = v;
2,147,483,647✔
3474
}
2,147,483,647✔
3475

3476
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
30,276,501✔
3477
  double delta = v - pDiffInfo->prev.d64;
30,276,501✔
3478
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
30,276,501✔
3479
    colDataSetNull_f_s(pOutput, pos);
203,115✔
3480
  } else {
3481
    colDataSetDouble(pOutput, pos, &delta);
30,073,386✔
3482
  }
3483
  pDiffInfo->prev.d64 = v;
30,276,501✔
3484
}
30,276,501✔
3485

3486
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2,147,483,647✔
3487
                            int64_t ts) {
3488
  if (!pDiffInfo->hasPrev) {
2,147,483,647✔
3489
    colDataSetNull_f_s(pOutput, pos);
70,120✔
3490
    return doSetPrevVal(pDiffInfo, type, pv, ts);
70,120✔
3491
  }
3492
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3493
  switch (type) {
2,147,483,647✔
3494
    case TSDB_DATA_TYPE_UINT: {
463,677✔
3495
      int64_t v = *(uint32_t*)pv;
463,677✔
3496
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
463,677✔
3497
      break;
463,677✔
3498
    }
3499
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
3500
      int64_t v = *(int32_t*)pv;
2,147,483,647✔
3501
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3502
      break;
2,147,483,647✔
3503
    }
3504
    case TSDB_DATA_TYPE_BOOL: {
4,797,587✔
3505
      int64_t v = *(bool*)pv;
4,797,587✔
3506
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,797,587✔
3507
      break;
4,797,587✔
3508
    }
3509
    case TSDB_DATA_TYPE_UTINYINT: {
64,513✔
3510
      int64_t v = *(uint8_t*)pv;
64,513✔
3511
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
64,513✔
3512
      break;
64,513✔
3513
    }
3514
    case TSDB_DATA_TYPE_TINYINT: {
10,426,869✔
3515
      int64_t v = *(int8_t*)pv;
10,426,869✔
3516
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,426,869✔
3517
      break;
10,426,869✔
3518
    }
3519
    case TSDB_DATA_TYPE_USMALLINT: {
64,513✔
3520
      int64_t v = *(uint16_t*)pv;
64,513✔
3521
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
64,513✔
3522
      break;
64,513✔
3523
    }
3524
    case TSDB_DATA_TYPE_SMALLINT: {
11,114,613✔
3525
      int64_t v = *(int16_t*)pv;
11,114,613✔
3526
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
11,114,613✔
3527
      break;
11,114,613✔
3528
    }
3529
    case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
3530
    case TSDB_DATA_TYPE_UBIGINT:
3531
    case TSDB_DATA_TYPE_BIGINT: {
3532
      int64_t v = *(int64_t*)pv;
2,147,483,647✔
3533
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3534
      break;
2,147,483,647✔
3535
    }
3536
    case TSDB_DATA_TYPE_FLOAT: {
14,826,948✔
3537
      double v = *(float*)pv;
14,826,948✔
3538
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
14,826,948✔
3539
      break;
14,826,948✔
3540
    }
3541
    case TSDB_DATA_TYPE_DOUBLE: {
15,449,553✔
3542
      double v = *(double*)pv;
15,449,553✔
3543
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
15,449,553✔
3544
      break;
15,449,553✔
3545
    }
3546
    default:
×
3547
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3548
  }
3549
  pDiffInfo->hasPrev = true;
2,147,483,647✔
3550
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3551
}
3552

3553
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3554
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3555
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
2,147,483,647✔
3556
                              int32_t* nextFrom) {
3557
  if (pInput->pPrimaryKey == NULL) {
2,147,483,647✔
3558
    if (pInput->numOfRows == 0) {
2,147,483,647✔
3559
      return false;
×
3560
    }
3561
    if (from == -1) {
2,147,483,647✔
3562
      from = pInput->startRowIndex;
2,147,483,647✔
3563
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
2,147,483,647✔
3564
      return false;
2,147,483,647✔
3565
    }
3566
    *pRowIndex = from;
2,147,483,647✔
3567
    *nextFrom = from + 1;
2,147,483,647✔
3568
    return true;
2,147,483,647✔
3569
  } else {
3570
    if (from == -1) {
695,180,614✔
3571
      from = pInput->startRowIndex;
152,005,797✔
3572
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
543,174,817✔
3573
      return false;
152,068,805✔
3574
    }
3575
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
543,149,751✔
3576
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
543,216,692✔
3577
    int8_t           pkType = pkCol->info.type;
543,183,575✔
3578
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
543,255,564✔
3579
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
543,255,564✔
3580
    int32_t          select = from;
543,050,719✔
3581
    char*            val = colDataGetData(pkCol, select);
543,050,719✔
3582
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,359,566,143✔
3583
      char* val1 = colDataGetData(pkCol, from + 1);
816,372,869✔
3584
      if (compareFunc(val1, val) < 0) {
816,437,224✔
3585
        select = from + 1;
261,919,262✔
3586
        val = val1;
261,919,262✔
3587
      }
3588
      from = from + 1;
816,347,062✔
3589
    }
3590
    *pRowIndex = select;
542,766,305✔
3591
    *nextFrom = from + 1;
543,232,563✔
3592
    return true;
543,243,862✔
3593
  }
3594
}
3595

3596
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
×
3597
  pEnv->calcMemSize = sizeof(double);
×
3598
  return true;
×
3599
}
3600

3601
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3602
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3603
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3604

3605
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
2,147,483,647✔
3606
    return true;
25,384,696✔
3607
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3608
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
2,122,722✔
3609
  }
3610
  return false;
2,147,483,647✔
3611
}
3612

3613
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3614
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3615
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3616
  return pDiffInfo->isFirstRow;
2,147,483,647✔
3617
}
3618

3619
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
16,148,835✔
3620
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,148,835✔
3621
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
16,148,835✔
3622
  pDiffInfo->isFirstRow = false;
16,148,835✔
3623
  if (pRow->isDataNull) {
16,148,835✔
3624
    return TSDB_CODE_SUCCESS;
204,878✔
3625
  }
3626

3627
  SInputColumnInfoData* pInput = &pCtx->input;
15,943,957✔
3628
  SColumnInfoData*      pInputCol = pInput->pData[0];
15,943,957✔
3629
  int8_t                inputType = pInputCol->info.type;
15,943,957✔
3630

3631
  char* pv = pRow->pData;
15,943,957✔
3632
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
15,943,957✔
3633
}
3634

3635
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
2,147,483,647✔
3636
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3637
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3638

3639
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3640
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3641
  int8_t                inputType = pInputCol->info.type;
2,147,483,647✔
3642
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
2,147,483,647✔
3643
  int32_t               code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3644
  if (pRow->isDataNull) {
2,147,483,647✔
3645
    colDataSetNull_f_s(pOutput, pos);
9,173,748✔
3646
    pOutput->hasNull = true;
9,173,748✔
3647

3648
    // handle selectivity
3649
    if (pCtx->subsidiaries.num > 0) {
9,173,748✔
3650
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
22,606✔
3651
      if (code != TSDB_CODE_SUCCESS) {
22,606✔
3652
        return code;
×
3653
      }
3654
    }
3655
    return TSDB_CODE_SUCCESS;
9,173,748✔
3656
  }
3657

3658
  char* pv = pRow->pData;
2,147,483,647✔
3659

3660
  if (pRow->ts == pDiffInfo->prevTs) {
2,147,483,647✔
3661
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
8,487✔
3662
  }
3663
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
2,147,483,647✔
3664
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3665
    return code;
×
3666
  }
3667
  // handle selectivity
3668
  if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
3669
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
2,147,483,647✔
3670
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3671
      return code;
×
3672
    }
3673
  }
3674

3675
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3676
}
3677

3678
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
58,845,910✔
3679

3680
int32_t diffFunctionByRow(SArray* pCtxArray) {
58,812,124✔
3681
  int32_t code = TSDB_CODE_SUCCESS;
58,812,124✔
3682
  int     diffColNum = pCtxArray->size;
58,812,124✔
3683
  if (diffColNum == 0) {
58,812,124✔
3684
    return TSDB_CODE_SUCCESS;
×
3685
  }
3686
  int32_t numOfElems = 0;
58,812,124✔
3687

3688
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
58,812,124✔
3689
  if (NULL == pRows) {
58,812,124✔
3690
    return terrno;
×
3691
  }
3692

3693
  bool keepNull = false;
58,812,124✔
3694
  for (int i = 0; i < diffColNum; ++i) {
117,658,034✔
3695
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
58,845,910✔
3696
    if (NULL == pCtx) {
58,845,910✔
3697
      code = terrno;
×
3698
      goto _exit;
×
3699
    }
3700
    funcInputUpdate(pCtx);
58,845,910✔
3701
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
58,845,910✔
3702
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
58,845,910✔
3703
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
58,845,910✔
3704
      keepNull = true;
58,826,599✔
3705
    }
3706
  }
3707

3708
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
58,812,124✔
3709
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
58,812,124✔
3710
  if (NULL == pCtx0 || NULL == pRow0) {
58,812,124✔
3711
    code = terrno;
×
3712
    goto _exit;
×
3713
  }
3714
  int32_t startOffset = pCtx0->offset;
58,812,124✔
3715
  bool    result = false;
58,812,124✔
3716
  while (1) {
2,147,483,647✔
3717
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
2,147,483,647✔
3718
    if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3719
      goto _exit;
×
3720
    }
3721
    if (!result) {
2,147,483,647✔
3722
      break;
58,803,637✔
3723
    }
3724
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
2,147,483,647✔
3725
    for (int i = 1; i < diffColNum; ++i) {
2,147,483,647✔
3726
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
5,432,262✔
3727
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
5,432,262✔
3728
      if (NULL == pCtx || NULL == pRow) {
5,432,262✔
3729
        code = terrno;
×
3730
        goto _exit;
×
3731
      }
3732
      code = funcInputGetNextRow(pCtx, pRow, &result);
5,432,262✔
3733
      if (TSDB_CODE_SUCCESS != code) {
5,432,262✔
3734
        goto _exit;
×
3735
      }
3736
      if (!result) {
5,432,262✔
3737
        // rows are not equal
3738
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3739
        goto _exit;
×
3740
      }
3741
      if (!diffResultIsNull(pCtx, pRow)) {
5,432,262✔
3742
        hasNotNullValue = true;
5,354,202✔
3743
      }
3744
    }
3745
    int32_t pos = startOffset + numOfElems;
2,147,483,647✔
3746

3747
    bool newRow = false;
2,147,483,647✔
3748
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3749
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,147,483,647✔
3750
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
2,147,483,647✔
3751
      if (NULL == pCtx || NULL == pRow) {
2,147,483,647✔
3752
        code = terrno;
×
3753
        goto _exit;
×
3754
      }
3755
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
2,147,483,647✔
3756
        code = setDoDiffResult(pCtx, pRow, pos);
2,147,483,647✔
3757
        if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3758
          goto _exit;
8,487✔
3759
        }
3760
        newRow = true;
2,147,483,647✔
3761
      } else {
3762
        code = trySetPreVal(pCtx, pRow);
16,148,835✔
3763
        if (code != TSDB_CODE_SUCCESS) {
16,148,835✔
3764
          goto _exit;
×
3765
        }
3766
      }
3767
    }
3768
    if (newRow) ++numOfElems;
2,147,483,647✔
3769
  }
3770

3771
  for (int i = 0; i < diffColNum; ++i) {
117,640,589✔
3772
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
58,836,952✔
3773
    if (NULL == pCtx) {
58,836,952✔
3774
      code = terrno;
×
3775
      goto _exit;
×
3776
    }
3777
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
58,836,952✔
3778
    pResInfo->numOfRes = numOfElems;
58,836,952✔
3779
  }
3780

3781
_exit:
58,812,124✔
3782
  if (pRows) {
58,812,124✔
3783
    taosArrayDestroy(pRows);
58,812,124✔
3784
    pRows = NULL;
58,812,124✔
3785
  }
3786
  return code;
58,812,124✔
3787
}
3788

3789
typedef struct {
3790
  SArray* pLagTail;
3791
  SArray* pLeadPending;
3792
} SLagLeadState;
3793

3794
bool getLagFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,923✔
3795
  pEnv->calcMemSize = sizeof(SLagLeadState);
22,923✔
3796
  return true;
22,923✔
3797
}
3798

3799
int32_t lagFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
58,126✔
3800
  if (pResInfo->initialized) {
58,126✔
3801
    return TSDB_CODE_SUCCESS;
30,027✔
3802
  }
3803
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
28,099✔
3804
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3805
  }
3806

3807
  SLagLeadState* pState = GET_ROWCELL_INTERBUF(pResInfo);
28,099✔
3808
  if (pState != NULL) {
28,099✔
3809
    pState->pLagTail = NULL;
28,099✔
3810
    pState->pLeadPending = NULL;
28,099✔
3811
  }
3812

3813
  return TSDB_CODE_SUCCESS;
28,099✔
3814
}
3815

3816
int32_t lagFunction(SqlFunctionCtx* UNUSED_PARAM(pCtx)) { return TSDB_CODE_SUCCESS; }
30,991✔
3817

3818
typedef struct {
3819
  bool        isDataNull;
3820
  char*       pData;
3821
  int32_t     dataLen;
3822
  SSDataBlock* block;
3823
  int32_t     rowIndex;
3824
} SLagLeadRowValue;
3825

3826
typedef struct {
3827
  int32_t outputPos;
3828
  int64_t needIdx;
3829
} SLeadPendingItem;
3830

3831
static void cleanupLagLeadRowValueArray(SArray* pValues) {
100,659✔
3832
  if (pValues == NULL) {
100,659✔
3833
    return;
×
3834
  }
3835

3836
  int32_t size = taosArrayGetSize(pValues);
100,659✔
3837
  for (int32_t i = 0; i < size; ++i) {
50,723,043✔
3838
    SLagLeadRowValue* pValue = (SLagLeadRowValue*)taosArrayGet(pValues, i);
50,622,384✔
3839
    if (pValue != NULL && pValue->pData != NULL) {
50,622,384✔
3840
      taosMemoryFree(pValue->pData);
50,617,564✔
3841
      pValue->pData = NULL;
50,617,564✔
3842
    }
3843
  }
3844

3845
  taosArrayDestroy(pValues);
100,659✔
3846
}
3847

3848
static void cleanupLagLeadValueArrays(SArray* pValueArrays) {
66,569✔
3849
  if (pValueArrays == NULL) {
66,569✔
3850
    return;
×
3851
  }
3852

3853
  int32_t size = taosArrayGetSize(pValueArrays);
66,569✔
3854
  for (int32_t i = 0; i < size; ++i) {
136,237✔
3855
    SArray** ppValues = (SArray**)taosArrayGet(pValueArrays, i);
69,668✔
3856
    if (ppValues != NULL && *ppValues != NULL) {
69,668✔
3857
      cleanupLagLeadRowValueArray(*ppValues);
69,668✔
3858
    }
3859
  }
3860

3861
  taosArrayDestroy(pValueArrays);
66,569✔
3862
}
3863

3864
static int32_t copyLagLeadRowValue(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, SLagLeadRowValue* pValue) {
38,742,442✔
3865
  pValue->isDataNull = pRow->isDataNull;
38,742,442✔
3866
  pValue->pData = NULL;
38,742,442✔
3867
  pValue->dataLen = 0;
38,742,442✔
3868
  pValue->block = pRow->block;
38,742,442✔
3869
  pValue->rowIndex = pRow->rowIndex;
38,742,442✔
3870

3871
  if (pRow->isDataNull) {
38,742,442✔
3872
    return TSDB_CODE_SUCCESS;
3,856✔
3873
  }
3874

3875
  SColumnInfoData* pInputCol = pCtx->input.pData[0];
38,738,586✔
3876
  int32_t          dataLen = pInputCol->info.bytes;
38,738,586✔
3877
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
38,738,586✔
3878
    dataLen = IS_STR_DATA_BLOB(pInputCol->info.type) ? blobDataTLen(pRow->pData) : varDataTLen(pRow->pData);
4,831,568✔
3879
  }
3880
  pValue->dataLen = dataLen;
38,738,586✔
3881
  pValue->pData = taosMemoryMalloc(dataLen);
38,738,586✔
3882
  if (pValue->pData == NULL) {
38,738,586✔
3883
    return terrno;
×
3884
  }
3885

3886
  (void)memcpy(pValue->pData, pRow->pData, dataLen);
38,738,586✔
3887
  return TSDB_CODE_SUCCESS;
38,738,586✔
3888
}
3889

3890
static int32_t setLagLeadDefaultValue(SqlFunctionCtx* pCtx, int32_t pos) {
13,661,476✔
3891
  if (pCtx->numOfParams < 3) {
13,661,476✔
3892
    colDataSetNULL((SColumnInfoData*)pCtx->pOutput, pos);
×
3893
    return TSDB_CODE_SUCCESS;
×
3894
  }
3895

3896
  SVariant* pDefault = &pCtx->param[2].param;
13,661,476✔
3897

3898
  if (IS_NULL_TYPE(pDefault->nType)) {
13,661,476✔
3899
    colDataSetNULL((SColumnInfoData*)pCtx->pOutput, pos);
24,530✔
3900
    return TSDB_CODE_SUCCESS;
24,530✔
3901
  }
3902

3903
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
13,636,946✔
3904
  uint8_t          type = pOutput->info.type;
13,636,946✔
3905
  STypeMod         inputTypeMod = pCtx->param[2].pCol == NULL ? 0 : typeGetTypeModFromCol(pCtx->param[2].pCol);
13,636,946✔
3906
  int32_t          retCode = TSDB_CODE_SUCCESS;
13,636,946✔
3907

3908
  switch (type) {
13,636,946✔
3909
    case TSDB_DATA_TYPE_BOOL: {
×
3910
      bool v = false;
×
3911
      GET_TYPED_DATA(v, bool, pDefault->nType, &pDefault->i, inputTypeMod);
×
3912
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3913
      break;
×
3914
    }
3915
    case TSDB_DATA_TYPE_TINYINT: {
×
3916
      int8_t v = 0;
×
3917
      GET_TYPED_DATA(v, int8_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3918
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3919
      break;
×
3920
    }
3921
    case TSDB_DATA_TYPE_UTINYINT: {
×
3922
      uint8_t v = 0;
×
3923
      GET_TYPED_DATA(v, uint8_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3924
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3925
      break;
×
3926
    }
3927
    case TSDB_DATA_TYPE_SMALLINT: {
×
3928
      int16_t v = 0;
×
3929
      GET_TYPED_DATA(v, int16_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3930
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3931
      break;
×
3932
    }
3933
    case TSDB_DATA_TYPE_USMALLINT: {
×
3934
      uint16_t v = 0;
×
3935
      GET_TYPED_DATA(v, uint16_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3936
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3937
      break;
×
3938
    }
3939
    case TSDB_DATA_TYPE_INT: {
13,626,080✔
3940
      int32_t v = 0;
13,626,080✔
3941
      GET_TYPED_DATA(v, int32_t, pDefault->nType, &pDefault->i, inputTypeMod);
13,626,080✔
3942
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
13,626,080✔
3943
      break;
13,626,080✔
3944
    }
3945
    case TSDB_DATA_TYPE_UINT: {
×
3946
      uint32_t v = 0;
×
3947
      GET_TYPED_DATA(v, uint32_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3948
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3949
      break;
×
3950
    }
3951
    case TSDB_DATA_TYPE_BIGINT:
2,672✔
3952
    case TSDB_DATA_TYPE_TIMESTAMP: {
3953
      if (type == TSDB_DATA_TYPE_TIMESTAMP && IS_STR_DATA_TYPE(pDefault->nType)) {
2,672✔
3954
        int64_t tsVal = 0;
1,763✔
3955
        int32_t cvtCode = convertStringToTimestamp(pDefault->nType, pDefault->pz, pOutput->info.precision, &tsVal,
1,763✔
3956
                     NULL, NULL);
3957
        if (cvtCode != TSDB_CODE_SUCCESS) {
1,763✔
3958
          retCode = cvtCode;
×
3959
          break;
×
3960
        }
3961
        retCode = colDataSetVal(pOutput, pos, (const char*)&tsVal, false);
1,763✔
3962
        break;
1,763✔
3963
      }
3964

3965
      int64_t v = 0;
909✔
3966
      GET_TYPED_DATA(v, int64_t, pDefault->nType, &pDefault->i, inputTypeMod);
909✔
3967
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
909✔
3968
      break;
909✔
3969
    }
3970
    case TSDB_DATA_TYPE_UBIGINT: {
×
3971
      uint64_t v = 0;
×
3972
      GET_TYPED_DATA(v, uint64_t, pDefault->nType, &pDefault->i, inputTypeMod);
×
3973
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3974
      break;
×
3975
    }
3976
    case TSDB_DATA_TYPE_FLOAT: {
×
3977
      float v = 0;
×
3978
      GET_TYPED_DATA(v, float, pDefault->nType, &pDefault->i, inputTypeMod);
×
3979
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3980
      break;
×
3981
    }
3982
    case TSDB_DATA_TYPE_DOUBLE: {
×
3983
      double v = 0;
×
3984
      GET_TYPED_DATA(v, double, pDefault->nType, &pDefault->i, inputTypeMod);
×
3985
      retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
3986
      break;
×
3987
    }
3988
    case TSDB_DATA_TYPE_DECIMAL64: {
1,928✔
3989
      Decimal64 v = {0};
1,928✔
3990
      switch (pDefault->nType) {
1,928✔
3991
        case TSDB_DATA_TYPE_BOOL:
×
3992
          retCode = TEST_decimal64From_uint64_t(&v, pOutput->info.precision, pOutput->info.scale, (uint64_t)pDefault->i);
×
3993
          break;
×
3994
        case TSDB_DATA_TYPE_TINYINT:
×
3995
        case TSDB_DATA_TYPE_SMALLINT:
3996
        case TSDB_DATA_TYPE_INT:
3997
        case TSDB_DATA_TYPE_BIGINT:
3998
        case TSDB_DATA_TYPE_TIMESTAMP:
3999
          retCode = TEST_decimal64From_int64_t(&v, pOutput->info.precision, pOutput->info.scale, pDefault->i);
×
4000
          break;
×
4001
        case TSDB_DATA_TYPE_UTINYINT:
×
4002
        case TSDB_DATA_TYPE_USMALLINT:
4003
        case TSDB_DATA_TYPE_UINT:
4004
        case TSDB_DATA_TYPE_UBIGINT:
4005
          retCode = TEST_decimal64From_uint64_t(&v, pOutput->info.precision, pOutput->info.scale, pDefault->u);
×
4006
          break;
×
4007
        case TSDB_DATA_TYPE_FLOAT:
×
4008
          retCode = TEST_decimal64From_double(&v, pOutput->info.precision, pOutput->info.scale, pDefault->f);
×
4009
          break;
×
4010
        case TSDB_DATA_TYPE_DOUBLE:
1,928✔
4011
          retCode = TEST_decimal64From_double(&v, pOutput->info.precision, pOutput->info.scale, pDefault->d);
1,928✔
4012
          break;
1,928✔
4013
        case TSDB_DATA_TYPE_DECIMAL64: {
×
4014
          uint8_t inputPrecision = 0, inputScale = 0;
×
4015
          extractTypeFromTypeMod(pDefault->nType, inputTypeMod, &inputPrecision, &inputScale, NULL);
×
4016
          retCode = TEST_decimal64FromDecimal64((Decimal64*)&pDefault->i, inputPrecision, inputScale, &v,
×
4017
                                                pOutput->info.precision, pOutput->info.scale);
×
4018
          break;
×
4019
        }
4020
        case TSDB_DATA_TYPE_DECIMAL: {
×
4021
          uint8_t inputPrecision = 0, inputScale = 0;
×
4022
          extractTypeFromTypeMod(pDefault->nType, inputTypeMod, &inputPrecision, &inputScale, NULL);
×
4023
          retCode = TEST_decimal64FromDecimal128((Decimal128*)pDefault->pz, inputPrecision, inputScale, &v,
×
4024
                                                 pOutput->info.precision, pOutput->info.scale);
×
4025
          break;
×
4026
        }
4027
        default:
×
4028
          retCode = TSDB_CODE_OPS_NOT_SUPPORT;
×
4029
          break;
×
4030
      }
4031

4032
      if (retCode == TSDB_CODE_SUCCESS) {
1,928✔
4033
        retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
1,928✔
4034
      }
4035
      break;
1,928✔
4036
    }
4037
    case TSDB_DATA_TYPE_DECIMAL: {
×
4038
      Decimal128 v = {0};
×
4039
      switch (pDefault->nType) {
×
4040
        case TSDB_DATA_TYPE_BOOL:
×
4041
          retCode =
4042
              TEST_decimal128From_uint64_t(&v, pOutput->info.precision, pOutput->info.scale, (uint64_t)pDefault->i);
×
4043
          break;
×
4044
        case TSDB_DATA_TYPE_TINYINT:
×
4045
        case TSDB_DATA_TYPE_SMALLINT:
4046
        case TSDB_DATA_TYPE_INT:
4047
        case TSDB_DATA_TYPE_BIGINT:
4048
        case TSDB_DATA_TYPE_TIMESTAMP:
4049
          retCode = TEST_decimal128From_int64_t(&v, pOutput->info.precision, pOutput->info.scale, pDefault->i);
×
4050
          break;
×
4051
        case TSDB_DATA_TYPE_UTINYINT:
×
4052
        case TSDB_DATA_TYPE_USMALLINT:
4053
        case TSDB_DATA_TYPE_UINT:
4054
        case TSDB_DATA_TYPE_UBIGINT:
4055
          retCode = TEST_decimal128From_uint64_t(&v, pOutput->info.precision, pOutput->info.scale, pDefault->u);
×
4056
          break;
×
4057
        case TSDB_DATA_TYPE_FLOAT:
×
4058
          retCode = TEST_decimal128From_double(&v, pOutput->info.precision, pOutput->info.scale, pDefault->f);
×
4059
          break;
×
4060
        case TSDB_DATA_TYPE_DOUBLE:
×
4061
          retCode = TEST_decimal128From_double(&v, pOutput->info.precision, pOutput->info.scale, pDefault->d);
×
4062
          break;
×
4063
        case TSDB_DATA_TYPE_DECIMAL64: {
×
4064
          uint8_t inputPrecision = 0, inputScale = 0;
×
4065
          extractTypeFromTypeMod(pDefault->nType, inputTypeMod, &inputPrecision, &inputScale, NULL);
×
4066
          retCode = TEST_decimal128FromDecimal64((Decimal64*)&pDefault->i, inputPrecision, inputScale, &v,
×
4067
                                                 pOutput->info.precision, pOutput->info.scale);
×
4068
          break;
×
4069
        }
4070
        case TSDB_DATA_TYPE_DECIMAL: {
×
4071
          uint8_t inputPrecision = 0, inputScale = 0;
×
4072
          extractTypeFromTypeMod(pDefault->nType, inputTypeMod, &inputPrecision, &inputScale, NULL);
×
4073
          retCode = TEST_decimal128FromDecimal128((Decimal128*)pDefault->pz, inputPrecision, inputScale, &v,
×
4074
                                                  pOutput->info.precision, pOutput->info.scale);
×
4075
          break;
×
4076
        }
4077
        default:
×
4078
          retCode = TSDB_CODE_OPS_NOT_SUPPORT;
×
4079
          break;
×
4080
      }
4081

4082
      if (retCode == TSDB_CODE_SUCCESS) {
×
4083
        retCode = colDataSetVal(pOutput, pos, (const char*)&v, false);
×
4084
      }
4085
      break;
×
4086
    }
4087
    case TSDB_DATA_TYPE_GEOMETRY:
1,928✔
4088
      if (pDefault->pz == NULL) {
1,928✔
4089
        colDataSetNULL(pOutput, pos);
×
4090
        retCode = TSDB_CODE_SUCCESS;
×
4091
        break;
×
4092
      }
4093

4094
      if (pDefault->nType == TSDB_DATA_TYPE_GEOMETRY) {
1,928✔
4095
        retCode = colDataSetVal(pOutput, pos, pDefault->pz, false);
×
4096
        break;
×
4097
      }
4098

4099
      if (IS_STR_DATA_TYPE(pDefault->nType)) {
1,928✔
4100
#ifdef USE_GEOS
4101
        size_t         len = 0;
1,928✔
4102
        unsigned char* geom = NULL;
1,928✔
4103
        char*          output = NULL;
1,928✔
4104
        char*          inputWkt = NULL;
1,928✔
4105

4106
        retCode = initCtxGeomFromText();
1,928✔
4107
        if (retCode != TSDB_CODE_SUCCESS) {
1,928✔
4108
          break;
×
4109
        }
4110

4111
        if (pDefault->nType == TSDB_DATA_TYPE_NCHAR) {
1,928✔
4112
          int32_t charLen = varDataLen(pDefault->pz);
×
4113
          inputWkt = taosMemoryCalloc(1, charLen + TSDB_NCHAR_SIZE);
×
4114
          if (inputWkt == NULL) {
×
4115
            retCode = terrno;
×
4116
            break;
×
4117
          }
4118

4119
          int32_t cvtLen = taosUcs4ToMbs((TdUcs4*)varDataVal(pDefault->pz), charLen, inputWkt, NULL);
×
4120
          if (cvtLen < 0) {
×
4121
            taosMemoryFree(inputWkt);
×
4122
            retCode = TSDB_CODE_FAILED;
×
4123
            break;
×
4124
          }
4125
          inputWkt[cvtLen] = 0;
×
4126
        } else {
4127
          int32_t charLen = varDataLen(pDefault->pz);
1,928✔
4128
          inputWkt = taosMemoryCalloc(1, charLen + 1);
1,928✔
4129
          if (inputWkt == NULL) {
1,928✔
4130
            retCode = terrno;
×
4131
            break;
×
4132
          }
4133
          (void)memcpy(inputWkt, varDataVal(pDefault->pz), charLen);
1,928✔
4134
        }
4135

4136
        retCode = doGeomFromText(inputWkt, &geom, &len);
1,928✔
4137
        taosMemoryFree(inputWkt);
1,928✔
4138
        if (retCode != TSDB_CODE_SUCCESS) {
1,928✔
4139
          break;
×
4140
        }
4141

4142
        output = taosMemoryCalloc(1, len + VARSTR_HEADER_SIZE);
1,928✔
4143
        if (output == NULL) {
1,928✔
4144
          geosFreeBuffer(geom);
×
4145
          retCode = terrno;
×
4146
          break;
×
4147
        }
4148

4149
        (void)memcpy(output + VARSTR_HEADER_SIZE, geom, len);
1,928✔
4150
        varDataSetLen(output, len);
1,928✔
4151
        geosFreeBuffer(geom);
1,928✔
4152

4153
        retCode = colDataSetVal(pOutput, pos, output, false);
1,928✔
4154
        taosMemoryFree(output);
1,928✔
4155
        break;
1,928✔
4156
#else
4157
        retCode = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
4158
        break;
4159
#endif
4160
      }
4161

4162
      retCode = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4163
      break;
×
4164
    case TSDB_DATA_TYPE_VARCHAR:
4,338✔
4165
    case TSDB_DATA_TYPE_VARBINARY:
4166
    case TSDB_DATA_TYPE_NCHAR:
4167
    case TSDB_DATA_TYPE_BLOB:
4168
      if (pDefault->pz == NULL) {
4,338✔
4169
        colDataSetNULL(pOutput, pos);
×
4170
        retCode = TSDB_CODE_SUCCESS;
×
4171
        break;
×
4172
      }
4173
      retCode = colDataSetVal(pOutput, pos, pDefault->pz, false);
4,338✔
4174
      break;
4,338✔
4175
    default:
×
4176
      colDataSetNULL(pOutput, pos);
×
4177
      retCode = TSDB_CODE_SUCCESS;
×
4178
      break;
×
4179
  }
4180

4181
  return retCode;
13,636,946✔
4182
}
4183

4184
static int32_t cloneLagLeadRowValue(const SLagLeadRowValue* pSrc, SLagLeadRowValue* pDst) {
11,879,942✔
4185
  pDst->isDataNull = pSrc->isDataNull;
11,879,942✔
4186
  pDst->pData = NULL;
11,879,942✔
4187
  pDst->dataLen = pSrc->dataLen;
11,879,942✔
4188
  pDst->block = pSrc->block;
11,879,942✔
4189
  pDst->rowIndex = pSrc->rowIndex;
11,879,942✔
4190

4191
  if (pSrc->isDataNull || pSrc->pData == NULL) {
11,879,942✔
4192
    return TSDB_CODE_SUCCESS;
964✔
4193
  }
4194

4195
  int32_t dataLen = pSrc->dataLen;
11,878,978✔
4196

4197
  if (dataLen <= 0) {
11,878,978✔
4198
    return TSDB_CODE_SUCCESS;
×
4199
  }
4200

4201
  pDst->pData = taosMemoryMalloc(dataLen);
11,878,978✔
4202
  if (pDst->pData == NULL) {
11,878,978✔
4203
    return terrno;
×
4204
  }
4205

4206
  (void)memcpy(pDst->pData, pSrc->pData, dataLen);
11,878,978✔
4207
  return TSDB_CODE_SUCCESS;
11,878,978✔
4208
}
4209

4210
static int32_t setLagLeadOutputFromValue(SqlFunctionCtx* pCtx, int32_t pos, SLagLeadRowValue* pValue) {
30,773,868✔
4211
  if (pValue->isDataNull) {
30,773,868✔
4212
    colDataSetNULL((SColumnInfoData*)pCtx->pOutput, pos);
2,892✔
4213
    return TSDB_CODE_SUCCESS;
2,892✔
4214
  }
4215

4216
  return colDataSetVal((SColumnInfoData*)pCtx->pOutput, pos, pValue->pData, false);
30,770,976✔
4217
}
4218

4219
static int32_t resolveLeadPendingRows(SqlFunctionCtx* pCtx, SLagLeadState* pState, SArray* pCurrValues) {
38,677✔
4220
  if (pState->pLeadPending == NULL || taosArrayGetSize(pState->pLeadPending) == 0) {
38,677✔
4221
    return TSDB_CODE_SUCCESS;
34,821✔
4222
  }
4223

4224
  int32_t code = TSDB_CODE_SUCCESS;
3,856✔
4225
  int32_t currSize = taosArrayGetSize(pCurrValues);
3,856✔
4226
  int32_t pendingSize = taosArrayGetSize(pState->pLeadPending);
3,856✔
4227
  SArray* pRemain = taosArrayInit(TMAX(pendingSize, 1), sizeof(SLeadPendingItem));
3,856✔
4228
  if (pRemain == NULL) {
3,856✔
4229
    return terrno;
×
4230
  }
4231

4232
  for (int32_t i = 0; i < pendingSize; ++i) {
7,903,354✔
4233
    SLeadPendingItem* pItem = taosArrayGet(pState->pLeadPending, i);
7,899,498✔
4234
    if (pItem == NULL) {
7,899,498✔
4235
      code = terrno;
×
4236
      goto cleanup;
×
4237
    }
4238

4239
    if (pItem->needIdx < currSize) {
7,899,498✔
4240
      SLagLeadRowValue* pTarget = taosArrayGet(pCurrValues, pItem->needIdx);
5,692,902✔
4241
      if (pTarget == NULL) {
5,692,902✔
4242
        code = terrno;
×
4243
        goto cleanup;
×
4244
      }
4245

4246
      code = setLagLeadOutputFromValue(pCtx, pItem->outputPos, pTarget);
5,692,902✔
4247
      if (code != TSDB_CODE_SUCCESS) {
5,692,902✔
4248
        goto cleanup;
×
4249
      }
4250
    } else {
4251
      pItem->needIdx -= currSize;
2,206,596✔
4252
      if (NULL == taosArrayPush(pRemain, pItem)) {
2,206,596✔
4253
        code = terrno;
×
4254
        goto cleanup;
×
4255
      }
4256
    }
4257
  }
4258

4259
  taosArrayDestroy(pState->pLeadPending);
3,856✔
4260
  pState->pLeadPending = pRemain;
3,856✔
4261

4262
cleanup:
3,856✔
4263
  if (code != TSDB_CODE_SUCCESS) {
3,856✔
4264
    taosArrayDestroy(pRemain);
×
4265
  }
4266

4267
  return code;
3,856✔
4268
}
4269

4270
static int32_t refreshLagTailValues(SLagLeadState* pState, SArray* pCurrValues, int64_t offset) {
30,991✔
4271
  int32_t currSize = taosArrayGetSize(pCurrValues);
30,991✔
4272
  if (offset <= 0 || currSize <= 0) {
30,991✔
4273
    return TSDB_CODE_SUCCESS;
×
4274
  }
4275

4276
  int32_t oldSize = (pState->pLagTail == NULL) ? 0 : taosArrayGetSize(pState->pLagTail);
30,991✔
4277
  int32_t keep = (int32_t)TMIN(offset, oldSize + currSize);
30,991✔
4278

4279
  SArray* pNewTail = taosArrayInit(TMAX(keep, 1), sizeof(SLagLeadRowValue));
30,991✔
4280
  if (pNewTail == NULL) {
30,991✔
4281
    return terrno;
×
4282
  }
4283

4284
  int32_t start = oldSize + currSize - keep;
30,991✔
4285
  for (int32_t idx = start; idx < oldSize + currSize; ++idx) {
11,910,933✔
4286
    SLagLeadRowValue* pSrc = NULL;
11,879,942✔
4287
    if (idx < oldSize) {
11,879,942✔
4288
      pSrc = taosArrayGet(pState->pLagTail, idx);
2,206,596✔
4289
    } else {
4290
      pSrc = taosArrayGet(pCurrValues, idx - oldSize);
9,673,346✔
4291
    }
4292

4293
    if (pSrc == NULL) {
11,879,942✔
4294
      cleanupLagLeadRowValueArray(pNewTail);
×
4295
      return terrno;
×
4296
    }
4297

4298
    SLagLeadRowValue newVal = {0};
11,879,942✔
4299
    int32_t code = cloneLagLeadRowValue(pSrc, &newVal);
11,879,942✔
4300
    if (code != TSDB_CODE_SUCCESS) {
11,879,942✔
4301
      cleanupLagLeadRowValueArray(pNewTail);
×
4302
      return code;
×
4303
    }
4304

4305
    if (NULL == taosArrayPush(pNewTail, &newVal)) {
11,879,942✔
4306
      if (newVal.pData != NULL) {
×
4307
        taosMemoryFree(newVal.pData);
×
4308
      }
4309
      cleanupLagLeadRowValueArray(pNewTail);
×
4310
      return terrno;
×
4311
    }
4312
  }
4313

4314
  if (pState->pLagTail != NULL) {
30,991✔
4315
    cleanupLagLeadRowValueArray(pState->pLagTail);
3,856✔
4316
  }
4317
  pState->pLagTail = pNewTail;
30,991✔
4318
  return TSDB_CODE_SUCCESS;
30,991✔
4319
}
4320

4321
static int32_t lagLeadFunctionByRowImpl(SArray* pCtxArray, bool isLead) {
66,569✔
4322
  int32_t code = TSDB_CODE_SUCCESS;
66,569✔
4323
  int32_t colNum = pCtxArray->size;
66,569✔
4324
  if (colNum == 0) {
66,569✔
4325
    return TSDB_CODE_SUCCESS;
×
4326
  }
4327

4328
  int32_t numOfElems = 0;
66,569✔
4329
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), colNum);
66,569✔
4330
  if (NULL == pRows) {
66,569✔
4331
    return terrno;
×
4332
  }
4333

4334
  SArray* pValueArrays = taosArrayInit(colNum, sizeof(SArray*));
66,569✔
4335
  if (NULL == pValueArrays) {
66,569✔
4336
    code = terrno;
×
4337
    goto _exit;
×
4338
  }
4339

4340
  for (int32_t i = 0; i < colNum; ++i) {
136,237✔
4341
    SArray* pValues = taosArrayInit(32, sizeof(SLagLeadRowValue));
69,668✔
4342
    if (NULL == pValues) {
69,668✔
4343
      code = terrno;
×
4344
      goto _exit;
×
4345
    }
4346

4347
    if (NULL == taosArrayPush(pValueArrays, &pValues)) {
69,668✔
4348
      cleanupLagLeadRowValueArray(pValues);
×
4349
      code = terrno;
×
4350
      goto _exit;
×
4351
    }
4352
  }
4353

4354
  for (int32_t i = 0; i < colNum; ++i) {
136,237✔
4355
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
69,668✔
4356
    if (NULL == pCtx) {
69,668✔
4357
      code = terrno;
×
4358
      goto _exit;
×
4359
    }
4360
    funcInputUpdate(pCtx);
69,668✔
4361
  }
4362

4363
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
66,569✔
4364
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
66,569✔
4365
  if (NULL == pCtx0 || NULL == pRow0) {
66,569✔
4366
    code = terrno;
×
4367
    goto _exit;
×
4368
  }
4369

4370
  int32_t startOffset = pCtx0->offset;
66,569✔
4371
  bool    result = false;
66,569✔
4372
  while (1) {
4373
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
38,795,444✔
4374
    if (TSDB_CODE_SUCCESS != code) {
38,795,444✔
4375
      goto _exit;
×
4376
    }
4377
    if (!result) {
38,795,444✔
4378
      break;
66,569✔
4379
    }
4380

4381
    {
4382
      SArray*          pValues0 = *(SArray**)taosArrayGet(pValueArrays, 0);
38,728,875✔
4383
      SLagLeadRowValue rowValue = {0};
38,728,875✔
4384
      code = copyLagLeadRowValue(pCtx0, pRow0, &rowValue);
38,728,875✔
4385
      if (code != TSDB_CODE_SUCCESS) {
38,728,875✔
4386
        goto _exit;
×
4387
      }
4388

4389
      if (NULL == taosArrayPush(pValues0, &rowValue)) {
38,728,875✔
4390
        if (rowValue.pData != NULL) {
×
4391
          taosMemoryFree(rowValue.pData);
×
4392
        }
4393
        code = terrno;
×
4394
        goto _exit;
×
4395
      }
4396
    }
4397

4398
    for (int32_t i = 1; i < colNum; ++i) {
38,742,442✔
4399
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
13,567✔
4400
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
13,567✔
4401
      if (NULL == pCtx || NULL == pRow) {
13,567✔
4402
        code = terrno;
×
4403
        goto _exit;
×
4404
      }
4405

4406
      code = funcInputGetNextRow(pCtx, pRow, &result);
13,567✔
4407
      if (TSDB_CODE_SUCCESS != code) {
13,567✔
4408
        goto _exit;
×
4409
      }
4410
      if (!result) {
13,567✔
4411
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4412
        goto _exit;
×
4413
      }
4414

4415
      SArray*          pValues = *(SArray**)taosArrayGet(pValueArrays, i);
13,567✔
4416
      SLagLeadRowValue rowValue = {0};
13,567✔
4417
      code = copyLagLeadRowValue(pCtx, pRow, &rowValue);
13,567✔
4418
      if (code != TSDB_CODE_SUCCESS) {
13,567✔
4419
        goto _exit;
×
4420
      }
4421

4422
      if (NULL == taosArrayPush(pValues, &rowValue)) {
13,567✔
4423
        if (rowValue.pData != NULL) {
×
4424
          taosMemoryFree(rowValue.pData);
×
4425
        }
4426
        code = terrno;
×
4427
        goto _exit;
×
4428
      }
4429
    }
4430

4431
    ++numOfElems;
38,728,875✔
4432
  }
4433

4434
  for (int32_t i = 0; i < colNum; ++i) {
136,237✔
4435
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
69,668✔
4436
    SArray*         pValues = *(SArray**)taosArrayGet(pValueArrays, i);
69,668✔
4437
    if (NULL == pCtx || NULL == pValues) {
69,668✔
4438
      code = terrno;
×
4439
      goto _exit;
×
4440
    }
4441

4442
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
69,668✔
4443
    SLagLeadState*       pState = GET_ROWCELL_INTERBUF(pResInfo);
69,668✔
4444
    if (pState == NULL) {
69,668✔
4445
      code = terrno;
×
4446
      goto _exit;
×
4447
    }
4448

4449
    int64_t offset = pCtx->param[1].param.i;
69,668✔
4450
    if (offset <= 0) {
69,668✔
4451
      code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4452
      goto _exit;
×
4453
    }
4454

4455
    if (isLead) {
69,668✔
4456
      if (pState->pLeadPending == NULL) {
38,677✔
4457
        pState->pLeadPending = taosArrayInit(8, sizeof(SLeadPendingItem));
34,821✔
4458
        if (pState->pLeadPending == NULL) {
34,821✔
4459
          code = terrno;
×
4460
          goto _exit;
×
4461
        }
4462
      }
4463

4464
      code = resolveLeadPendingRows(pCtx, pState, pValues);
38,677✔
4465
      if (code != TSDB_CODE_SUCCESS) {
38,677✔
4466
        goto _exit;
×
4467
      }
4468
    }
4469

4470
    for (int32_t rowIdx = 0; rowIdx < numOfElems; ++rowIdx) {
38,812,110✔
4471
      int32_t pos = startOffset + rowIdx;
38,742,442✔
4472
      SLagLeadRowValue* pCurRowValue = taosArrayGet(pValues, rowIdx);
38,742,442✔
4473
      if (pCurRowValue == NULL) {
38,742,442✔
4474
        code = terrno;
×
4475
        goto _exit;
×
4476
      }
4477

4478
      if (isLead) {
38,742,442✔
4479
        int64_t targetIdx = (int64_t)rowIdx + offset;
19,387,020✔
4480
        if (targetIdx < numOfElems) {
19,387,020✔
4481
          SLagLeadRowValue* pTargetRowValue = taosArrayGet(pValues, targetIdx);
9,705,988✔
4482
          if (pTargetRowValue == NULL) {
9,705,988✔
4483
            code = terrno;
×
4484
            goto _exit;
×
4485
          }
4486
          code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
9,705,988✔
4487
        } else {
4488
          code = setLagLeadDefaultValue(pCtx, pos);
9,681,032✔
4489
          if (code == TSDB_CODE_SUCCESS) {
9,681,032✔
4490
            SLeadPendingItem pending = {.outputPos = pos, .needIdx = targetIdx - numOfElems};
9,681,032✔
4491
            if (NULL == taosArrayPush(pState->pLeadPending, &pending)) {
19,362,064✔
4492
              code = terrno;
×
4493
            }
4494
          }
4495
        }
4496
      } else {
4497
        int64_t targetIdx = (int64_t)rowIdx - offset;
19,355,422✔
4498
        if (targetIdx >= 0) {
19,355,422✔
4499
          SLagLeadRowValue* pTargetRowValue = taosArrayGet(pValues, targetIdx);
9,682,076✔
4500
          if (pTargetRowValue == NULL) {
9,682,076✔
4501
            code = terrno;
×
4502
            goto _exit;
×
4503
          }
4504
          code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
9,682,076✔
4505
        } else {
4506
          int32_t tailSize = (pState->pLagTail == NULL) ? 0 : taosArrayGetSize(pState->pLagTail);
9,673,346✔
4507
          int64_t tailIdx = tailSize + targetIdx;
9,673,346✔
4508
          if (tailIdx >= 0 && tailIdx < tailSize) {
15,366,248✔
4509
            SLagLeadRowValue* pTargetRowValue = taosArrayGet(pState->pLagTail, tailIdx);
5,692,902✔
4510
            if (pTargetRowValue == NULL) {
5,692,902✔
4511
              code = terrno;
×
4512
              goto _exit;
×
4513
            }
4514
            code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
5,692,902✔
4515
          } else {
4516
            code = setLagLeadDefaultValue(pCtx, pos);
3,980,444✔
4517
          }
4518
        }
4519
      }
4520

4521
      if (code != TSDB_CODE_SUCCESS) {
38,742,442✔
4522
        goto _exit;
×
4523
      }
4524

4525
      if (pCtx->subsidiaries.num > 0) {
38,742,442✔
4526
        code = appendSelectivityCols(pCtx, pCurRowValue->block, pCurRowValue->rowIndex, pos);
19,385,363✔
4527
        if (code != TSDB_CODE_SUCCESS) {
19,385,363✔
4528
          goto _exit;
×
4529
        }
4530
      }
4531
    }
4532

4533
    if (!isLead) {
69,668✔
4534
      code = refreshLagTailValues(pState, pValues, offset);
30,991✔
4535
      if (code != TSDB_CODE_SUCCESS) {
30,991✔
4536
        goto _exit;
×
4537
      }
4538
    }
4539
  }
4540

4541
_exit:
66,569✔
4542
  for (int32_t i = 0; i < colNum; ++i) {
136,237✔
4543
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
69,668✔
4544
    if (!pCtx) {
69,668✔
4545
      break;
×
4546
    }
4547

4548
    if (!code) {
69,668✔
4549
      SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
69,668✔
4550
      pResInfo->numOfRes = numOfElems;
69,668✔
4551
    }
4552
  }
4553

4554
  if (pRows) {
66,569✔
4555
    taosArrayDestroy(pRows);
66,569✔
4556
    pRows = NULL;
66,569✔
4557
  }
4558

4559
  cleanupLagLeadValueArrays(pValueArrays);
66,569✔
4560

4561
  return code;
66,569✔
4562
}
4563

4564
int32_t lagFunctionByRow(SArray* pCtxArray) {
30,082✔
4565
  return lagLeadFunctionByRowImpl(pCtxArray, false);
30,082✔
4566
}
4567

4568
bool getLeadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
30,182✔
4569
  pEnv->calcMemSize = sizeof(SLagLeadState);
30,182✔
4570
  return true;
30,182✔
4571
}
4572

4573
int32_t leadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
73,071✔
4574
  if (pResInfo->initialized) {
73,071✔
4575
    return TSDB_CODE_SUCCESS;
37,286✔
4576
  }
4577
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
35,785✔
4578
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4579
  }
4580

4581
  SLagLeadState* pState = GET_ROWCELL_INTERBUF(pResInfo);
35,785✔
4582
  if (pState != NULL) {
35,785✔
4583
    pState->pLagTail = NULL;
35,785✔
4584
    pState->pLeadPending = NULL;
35,785✔
4585
  }
4586

4587
  return TSDB_CODE_SUCCESS;
35,785✔
4588
}
4589

4590
int32_t leadFunction(SqlFunctionCtx* UNUSED_PARAM(pCtx)) { return TSDB_CODE_SUCCESS; }
38,677✔
4591

4592
int32_t leadFunctionByRow(SArray* pCtxArray) {
36,487✔
4593
  return lagLeadFunctionByRowImpl(pCtxArray, true);
36,487✔
4594
}
4595

4596
void lagLeadFunctionCleanupExt(SqlFunctionCtx* pCtx) {
69,488✔
4597
  if (pCtx == NULL || pCtx->resultInfo == NULL) {
69,488✔
4598
    return;
5,604✔
4599
  }
4600

4601
  SLagLeadState* pState = GET_ROWCELL_INTERBUF(pCtx->resultInfo);
63,884✔
4602
  if (pState == NULL) {
63,884✔
4603
    return;
×
4604
  }
4605

4606
  if (pState->pLagTail != NULL) {
63,884✔
4607
    cleanupLagLeadRowValueArray(pState->pLagTail);
27,135✔
4608
    pState->pLagTail = NULL;
27,135✔
4609
  }
4610

4611
  if (pState->pLeadPending != NULL) {
63,884✔
4612
    taosArrayDestroy(pState->pLeadPending);
34,821✔
4613
    pState->pLeadPending = NULL;
34,821✔
4614
  }
4615
}
4616

4617
bool getFillforwardFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
38,936✔
4618
  pEnv->calcMemSize = sizeof(SFillforwardInfo);
38,936✔
4619
  return true;
38,936✔
4620
}
4621

4622
int32_t fillforwardFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
80,656✔
4623
  if (pResInfo->initialized) {
80,656✔
4624
    return TSDB_CODE_SUCCESS;
38,936✔
4625
  }
4626
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
41,720✔
4627
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4628
  }
4629
  SFillforwardInfo* pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
41,720✔
4630
  pFillforwardInfo->nonnull = false;
41,720✔
4631

4632
  return TSDB_CODE_SUCCESS;
41,720✔
4633
}
4634

4635
int32_t fillforwardFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
41,720✔
4636

4637
static int32_t doHandleFillforward(SFillforwardInfo* pFillforwardInfo, int32_t type, SColumnInfoData* pOutput, int32_t pos) {
135,328✔
4638
  if (!pFillforwardInfo->nonnull) {
135,328✔
4639
    colDataSetNULL(pOutput, pos);
15,312✔
4640

4641
    return TSDB_CODE_SUCCESS;
15,312✔
4642
  }
4643

4644
  switch (type) {
120,016✔
4645
    case TSDB_DATA_TYPE_BOOL:
57,840✔
4646
    case TSDB_DATA_TYPE_UTINYINT:
4647
    case TSDB_DATA_TYPE_TINYINT:
4648
    case TSDB_DATA_TYPE_USMALLINT:
4649
    case TSDB_DATA_TYPE_SMALLINT:
4650
    case TSDB_DATA_TYPE_UINT:
4651
    case TSDB_DATA_TYPE_INT:
4652
    case TSDB_DATA_TYPE_UBIGINT:
4653
    case TSDB_DATA_TYPE_BIGINT:
4654
    case TSDB_DATA_TYPE_TIMESTAMP:
4655
      colDataSetInt64(pOutput, pos, &pFillforwardInfo->v);
57,840✔
4656
      break;
57,840✔
4657
    case TSDB_DATA_TYPE_FLOAT:
22,272✔
4658
      colDataSetFloat(pOutput, pos, &pFillforwardInfo->fv);
22,272✔
4659
      break;
22,272✔
4660
    case TSDB_DATA_TYPE_DOUBLE:
25,056✔
4661
      colDataSetDouble(pOutput, pos, &pFillforwardInfo->dv);
25,056✔
4662
      break;
25,056✔
4663
    case TSDB_DATA_TYPE_DECIMAL64:
5,104✔
4664
      return colDataSetVal(pOutput, pos, (const char*)&pFillforwardInfo->v, false);
5,104✔
4665
    case TSDB_DATA_TYPE_DECIMAL:
×
4666
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->dec, false);
×
4667
    case TSDB_DATA_TYPE_VARCHAR:
9,744✔
4668
    case TSDB_DATA_TYPE_VARBINARY:
4669
    case TSDB_DATA_TYPE_NCHAR:
4670
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->str, false);
9,744✔
4671
    default:
×
4672
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4673
  }
4674

4675
  return TSDB_CODE_SUCCESS;
105,168✔
4676
}
4677

4678
static int32_t setFillforwardResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
135,328✔
4679
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
135,328✔
4680
  SFillforwardInfo*            pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
135,328✔
4681

4682
  SInputColumnInfoData* pInput = &pCtx->input;
135,328✔
4683
  SColumnInfoData*      pInputCol = pInput->pData[0];
135,328✔
4684
  int8_t                inputType = pInputCol->info.type;
135,328✔
4685
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
135,328✔
4686
  int32_t               code = TSDB_CODE_SUCCESS;
135,328✔
4687

4688
  code = doHandleFillforward(pFillforwardInfo, inputType, pOutput, pos);
135,328✔
4689
  if (code != TSDB_CODE_SUCCESS) {
135,328✔
4690
    return code;
×
4691
  }
4692

4693
  // handle selectivity
4694
  if (pCtx->subsidiaries.num > 0) {
135,328✔
4695
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
36,960✔
4696
    if (code != TSDB_CODE_SUCCESS) {
36,960✔
4697
      return code;
×
4698
    }
4699
  }
4700

4701
  return TSDB_CODE_SUCCESS;
135,328✔
4702
}
4703

4704
int32_t fillforwardFunctionByRow(SArray* pCtxArray) {
12,024✔
4705
  int32_t code = TSDB_CODE_SUCCESS;
12,024✔
4706
  int     fillforwardColNum = pCtxArray->size;
12,024✔
4707
  if (fillforwardColNum == 0) {
12,024✔
4708
    return TSDB_CODE_SUCCESS;
×
4709
  }
4710
  int32_t numOfElems = 0;
12,024✔
4711

4712
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), fillforwardColNum);
12,024✔
4713
  if (NULL == pRows) {
12,024✔
4714
    return terrno;
×
4715
  }
4716

4717
  for (int i = 0; i < fillforwardColNum; ++i) {
53,744✔
4718
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
41,720✔
4719
    if (NULL == pCtx) {
41,720✔
4720
      code = terrno;
×
4721
      goto _exit;
×
4722
    }
4723
    funcInputUpdate(pCtx);
41,720✔
4724
  }
4725

4726
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
12,024✔
4727
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
12,024✔
4728
  if (NULL == pCtx0 || NULL == pRow0) {
12,024✔
4729
    code = terrno;
×
4730
    goto _exit;
×
4731
  }
4732
  int32_t startOffset = pCtx0->offset;
12,024✔
4733
  bool    result = false;
12,024✔
4734
  while (1) {
36,960✔
4735
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
48,984✔
4736
    if (TSDB_CODE_SUCCESS != code) {
48,984✔
4737
      goto _exit;
×
4738
    }
4739
    if (!result) {
48,984✔
4740
      break;
11,560✔
4741
    }
4742

4743
    for (int i = 1; i < fillforwardColNum; ++i) {
135,792✔
4744
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
98,368✔
4745
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
98,368✔
4746
      if (NULL == pCtx || NULL == pRow) {
98,368✔
4747
        code = terrno;
×
4748
        goto _exit;
×
4749
      }
4750
      code = funcInputGetNextRow(pCtx, pRow, &result);
98,368✔
4751
      if (TSDB_CODE_SUCCESS != code) {
98,368✔
4752
        goto _exit;
×
4753
      }
4754
      if (!result) {
98,368✔
4755
        // rows are not equal
4756
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4757
        goto _exit;
×
4758
      }
4759
    }
4760

4761
    int32_t pos = startOffset + numOfElems;
37,424✔
4762

4763
    for (int i = 0; i < fillforwardColNum; ++i) {
172,752✔
4764
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
135,792✔
4765
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
135,792✔
4766
      if (NULL == pCtx || NULL == pRow) {
135,792✔
4767
        code = terrno;
×
4768
        goto _exit;
×
4769
      }
4770

4771
      if (!colDataIsNull_s(pCtx->input.pData[0], pCtx->rowIter.rowIndex - 1)) {
271,584✔
4772
        SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
83,360✔
4773
        SFillforwardInfo*             pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
83,360✔
4774
        SInputColumnInfoData* pInput = &pCtx->input;
83,360✔
4775
        SColumnInfoData*      pInputCol = pInput->pData[0];
83,360✔
4776
        int8_t                inputType = pInputCol->info.type;
83,360✔
4777

4778
        char* pv = pRow->pData;
83,360✔
4779
        switch (inputType) {
83,360✔
4780
          case TSDB_DATA_TYPE_BOOL:
16,240✔
4781
            pFillforwardInfo->v = *(bool*)pv ? 1 : 0;
16,240✔
4782
            break;
16,240✔
4783
          case TSDB_DATA_TYPE_UTINYINT:
464✔
4784
          case TSDB_DATA_TYPE_TINYINT:
4785
            pFillforwardInfo->v = *(int8_t*)pv;
464✔
4786
            break;
464✔
4787
          case TSDB_DATA_TYPE_UINT:
23,968✔
4788
          case TSDB_DATA_TYPE_INT:
4789
            pFillforwardInfo->v = *(int32_t*)pv;
23,968✔
4790
            break;
23,968✔
4791
          case TSDB_DATA_TYPE_USMALLINT:
464✔
4792
          case TSDB_DATA_TYPE_SMALLINT:
4793
            pFillforwardInfo->v = *(int16_t*)pv;
464✔
4794
            break;
464✔
4795
          case TSDB_DATA_TYPE_TIMESTAMP:
464✔
4796
          case TSDB_DATA_TYPE_UBIGINT:
4797
          case TSDB_DATA_TYPE_BIGINT:
4798
            pFillforwardInfo->v = *(int64_t*)pv;
464✔
4799
            break;
464✔
4800
          case TSDB_DATA_TYPE_FLOAT:
16,240✔
4801
            pFillforwardInfo->fv = *(float*)pv;
16,240✔
4802
            break;
16,240✔
4803
          case TSDB_DATA_TYPE_DOUBLE:
18,096✔
4804
            pFillforwardInfo->dv = *(double*)pv;
18,096✔
4805
            break;
18,096✔
4806
          case TSDB_DATA_TYPE_DECIMAL64:
2,784✔
4807
            DECIMAL64_SET_VALUE((Decimal64*)&pFillforwardInfo->v, *(int64_t*)pv);
2,784✔
4808
            break;
2,784✔
4809
          case TSDB_DATA_TYPE_DECIMAL:
×
4810
            DECIMAL128_CLONE((Decimal128*)pFillforwardInfo->dec, (Decimal128*)pv);
×
4811
            break;
×
4812
          case TSDB_DATA_TYPE_VARCHAR:
4,176✔
4813
          case TSDB_DATA_TYPE_VARBINARY:
4814
          case TSDB_DATA_TYPE_NCHAR: {
4815
            if (!pFillforwardInfo->nonnull) {
4,176✔
4816
              pFillforwardInfo->str = taosMemoryMalloc(pInputCol->info.bytes);
2,784✔
4817
              if (!pFillforwardInfo->str) {
2,784✔
4818
                code = terrno;
×
4819
                goto _exit;
×
4820
              }
4821
            }
4822

4823
            (void)memcpy(pFillforwardInfo->str, pv, varDataTLen(pv));
4,176✔
4824
          } break;
4,176✔
4825
          default: {
464✔
4826
            code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
464✔
4827
            goto _exit;
464✔
4828
          }
4829
        }
4830

4831
        if (!pFillforwardInfo->nonnull) {
82,896✔
4832
          pFillforwardInfo->nonnull = true;
40,792✔
4833
        }
4834
      }
4835

4836
      code = setFillforwardResult(pCtx, pRow, pos);
135,328✔
4837
      if (code) {
135,328✔
4838
        goto _exit;
×
4839
      }
4840
    }
4841

4842
    ++numOfElems;
36,960✔
4843
  }
4844

4845
_exit:
12,024✔
4846
  for (int i = 0; i < fillforwardColNum; ++i) {
53,744✔
4847
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
41,720✔
4848
    if (!pCtx) {
41,720✔
4849
      break;
×
4850
    }
4851

4852
    SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
41,720✔
4853
    SFillforwardInfo*             pRes = GET_ROWCELL_INTERBUF(pResInfo);
41,720✔
4854
    SInputColumnInfoData* pInput = &pCtx->input;
41,720✔
4855
    SColumnInfoData*      pInputCol = pInput->pData[0];
41,720✔
4856

4857
    if (IS_VAR_DATA_TYPE(pInputCol->info.type) && pRes->nonnull) {
41,720✔
4858
      taosMemoryFree(pRes->str);
2,784✔
4859
    }
4860

4861
    if (!code) {
41,720✔
4862
      pResInfo->numOfRes = numOfElems;
41,256✔
4863
    }
4864
  }
4865

4866
  if (pRows) {
12,024✔
4867
    taosArrayDestroy(pRows);
12,024✔
4868
    pRows = NULL;
12,024✔
4869
  }
4870
  return code;
12,024✔
4871
}
4872

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

4875
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,331,386✔
4876
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2,331,386✔
4877
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2,335,277✔
4878
  return true;
2,334,598✔
4879
}
4880

4881
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
8,276,523✔
4882
  if (pResInfo->initialized) {
8,276,523✔
4883
    return TSDB_CODE_SUCCESS;
×
4884
  }
4885
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
8,277,116✔
4886
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4887
  }
4888

4889
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
8,277,116✔
4890
  SInputColumnInfoData* pInput = &pCtx->input;
8,276,523✔
4891

4892
  pRes->maxSize = pCtx->param[1].param.i;
8,277,116✔
4893

4894
  pRes->nullTupleSaved = false;
8,276,523✔
4895
  pRes->nullTuplePos.pageId = -1;
8,276,523✔
4896
  return TSDB_CODE_SUCCESS;
8,277,091✔
4897
}
4898

4899
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
2,147,483,647✔
4900
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
4901
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
4902
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
2,147,483,647✔
4903

4904
  return pRes;
2,147,483,647✔
4905
}
4906

4907
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
4908
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
4909

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

4912
int32_t topFunction(SqlFunctionCtx* pCtx) {
9,618,848✔
4913
  int32_t              numOfElems = 0;
9,618,848✔
4914
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
9,618,848✔
4915

4916
  SInputColumnInfoData* pInput = &pCtx->input;
9,620,120✔
4917
  SColumnInfoData*      pCol = pInput->pData[0];
9,619,067✔
4918

4919
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
9,620,120✔
4920
  pRes->type = pInput->pData[0]->info.type;
9,619,153✔
4921

4922
  int32_t start = pInput->startRowIndex;
9,620,120✔
4923
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,336,150,356✔
4924
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,326,590,557✔
4925
      continue;
3,746,294✔
4926
    }
4927

4928
    numOfElems++;
1,322,910,003✔
4929
    char*   data = colDataGetData(pCol, i);
1,322,910,003✔
4930
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
1,323,951,054✔
4931
    if (code != TSDB_CODE_SUCCESS) {
1,322,785,587✔
4932
      return code;
×
4933
    }
4934
  }
4935

4936
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
9,620,799✔
4937
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
13,932✔
4938
    if (code != TSDB_CODE_SUCCESS) {
13,932✔
4939
      return code;
×
4940
    }
4941
    pRes->nullTupleSaved = true;
13,932✔
4942
  }
4943
  return TSDB_CODE_SUCCESS;
9,620,799✔
4944
}
4945

4946
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
3,421,802✔
4947
  int32_t              numOfElems = 0;
3,421,802✔
4948
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,421,802✔
4949

4950
  SInputColumnInfoData* pInput = &pCtx->input;
3,424,464✔
4951
  SColumnInfoData*      pCol = pInput->pData[0];
3,424,464✔
4952

4953
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
3,424,464✔
4954
  pRes->type = pInput->pData[0]->info.type;
3,422,481✔
4955

4956
  int32_t start = pInput->startRowIndex;
3,423,785✔
4957
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
912,730,003✔
4958
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
909,313,310✔
4959
      continue;
2,884,794✔
4960
    }
4961

4962
    numOfElems++;
905,973,977✔
4963
    char*   data = colDataGetData(pCol, i);
905,973,977✔
4964
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
906,844,206✔
4965
    if (code != TSDB_CODE_SUCCESS) {
906,422,746✔
4966
      return code;
×
4967
    }
4968
  }
4969

4970
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
3,424,464✔
4971
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
5,592✔
4972
    if (code != TSDB_CODE_SUCCESS) {
5,592✔
4973
      return code;
×
4974
    }
4975
    pRes->nullTupleSaved = true;
5,592✔
4976
  }
4977

4978
  return TSDB_CODE_SUCCESS;
3,424,464✔
4979
}
4980

4981
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
540,913,901✔
4982
  uint16_t type = *(uint16_t*)param;
540,913,901✔
4983

4984
  STopBotResItem* val1 = (STopBotResItem*)p1;
540,915,037✔
4985
  STopBotResItem* val2 = (STopBotResItem*)p2;
540,915,037✔
4986

4987
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
540,915,037✔
4988
    if (val1->v.i == val2->v.i) {
345,221,912✔
4989
      return 0;
60,565,117✔
4990
    }
4991

4992
    return (val1->v.i > val2->v.i) ? 1 : -1;
285,167,200✔
4993
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
195,693,125✔
4994
    if (val1->v.u == val2->v.u) {
95,959,926✔
4995
      return 0;
19,898,730✔
4996
    }
4997

4998
    return (val1->v.u > val2->v.u) ? 1 : -1;
76,241,892✔
4999
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
99,733,199✔
5000
    if (val1->v.f == val2->v.f) {
5,107,567✔
5001
      return 0;
29,799✔
5002
    }
5003

5004
    return (val1->v.f > val2->v.f) ? 1 : -1;
5,077,768✔
5005
  }
5006

5007
  if (val1->v.d == val2->v.d) {
94,625,632✔
5008
    return 0;
5,203✔
5009
  }
5010

5011
  return (val1->v.d > val2->v.d) ? 1 : -1;
94,633,515✔
5012
}
5013

5014
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
2,147,483,647✔
5015
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
5016
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
2,147,483,647✔
5017
  int32_t     code = TSDB_CODE_SUCCESS;
2,147,483,647✔
5018

5019
  SVariant val = {0};
2,147,483,647✔
5020
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
2,147,483,647✔
5021

5022
  STopBotResItem* pItems = pRes->pItems;
2,147,483,647✔
5023

5024
  // not full yet
5025
  if (pEntryInfo->numOfRes < pRes->maxSize) {
2,147,483,647✔
5026
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
48,097,576✔
5027
    pItem->v = val;
48,098,629✔
5028
    pItem->uid = uid;
48,097,008✔
5029

5030
    // save the data of this tuple
5031
    if (pCtx->subsidiaries.num > 0) {
48,099,222✔
5032
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
13,354,361✔
5033
      if (code != TSDB_CODE_SUCCESS) {
13,355,766✔
5034
        return code;
×
5035
      }
5036
    }
5037
#ifdef BUF_PAGE_DEBUG
5038
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
5039
           pItem->tuplePos.offset);
5040
#endif
5041
    // allocate the buffer and keep the data of this row into the new allocated buffer
5042
    pEntryInfo->numOfRes++;
48,099,574✔
5043
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
48,099,330✔
5044
                        topBotResComparFn, !isTopQuery);
48,098,302✔
5045
    if (code != TSDB_CODE_SUCCESS) {
48,089,297✔
5046
      return code;
×
5047
    }
5048
  } else {  // replace the minimum value in the result
5049
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
2,147,483,647✔
5050
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
1,268,691,282✔
5051
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
1,258,851,528✔
5052
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
1,258,536,795✔
5053
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
2,144,828,005✔
5054
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
893,907,776✔
5055
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
892,146,416✔
5056
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
892,585,502✔
5057
      // replace the old data and the coresponding tuple data
5058
      STopBotResItem* pItem = &pItems[0];
40,501,019✔
5059
      pItem->v = val;
40,501,019✔
5060
      pItem->uid = uid;
40,464,288✔
5061

5062
      // save the data of this tuple by over writing the old data
5063
      if (pCtx->subsidiaries.num > 0) {
40,465,424✔
5064
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
21,762,858✔
5065
        if (code != TSDB_CODE_SUCCESS) {
21,752,390✔
5066
          return code;
×
5067
        }
5068
      }
5069
#ifdef BUF_PAGE_DEBUG
5070
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
5071
#endif
5072
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
40,454,388✔
5073
                            topBotResComparFn, NULL, !isTopQuery);
40,454,956✔
5074
      if (code != TSDB_CODE_SUCCESS) {
40,465,167✔
5075
        return code;
×
5076
      }
5077
    }
5078
  }
5079

5080
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
5081
}
5082

5083

5084
bool hasNullFunc(  SColumnInfoData *pData,   SColumnDataAgg *pAgg, int32_t startIdx, int64_t rows) {
×
5085
  if (NULL != pAgg) {
×
5086
    return pAgg->numOfNull > 0 ? true : false;
×
5087
  }
5088

5089
  if (!pData->hasNull) {
×
5090
    return false;
×
5091
  }
5092

5093
  int64_t endIdx = startIdx + rows;
×
5094
  for (int64_t i = startIdx; i < endIdx; ++i) {
×
5095
    if (colDataIsNull_s(pData, i)) {
×
5096
      return true;
×
5097
    }
5098
  }
5099

5100
  return false;
×
5101
}
5102

5103

5104
/*
5105
 * +------------------------------------+--------------+--------------+
5106
 * |            null bitmap             |              |              |
5107
 * |(n columns, one bit for each column)| src column #1| src column #2|
5108
 * +------------------------------------+--------------+--------------+
5109
 */
5110
int32_t serializeTupleData(SqlFunctionCtx* pCtx, const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
125,489,710✔
5111
                           char* buf, char** res) {
5112
  char* nullList = buf;
125,489,710✔
5113
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
125,489,710✔
5114

5115
  int32_t offset = 0;
125,483,804✔
5116
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
388,360,558✔
5117
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
262,868,784✔
5118

5119
    // group_key function has its own process function
5120
    // do not process there
5121
    if (fmIsGroupKeyFunc(pc->functionId)) {
262,870,857✔
5122
      continue;
×
5123
    }
5124

5125
    if (fmIsSelectValueFunc(pc->functionId)) {
262,862,990✔
5126
      SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
262,861,565✔
5127
      int32_t      srcSlotId = pFuncParam->pCol->slotId;
262,866,299✔
5128

5129
      SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
262,866,491✔
5130
      if (NULL == pCol) {
262,859,697✔
5131
        return TSDB_CODE_OUT_OF_RANGE;
×
5132
      }
5133
      if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
525,724,619✔
5134
        offset += pCol->info.bytes;
68,238,741✔
5135
        continue;
68,238,741✔
5136
      }
5137

5138
      char* p = colDataGetData(pCol, rowIndex);
194,627,272✔
5139
      if (IS_VAR_DATA_TYPE(pCol->info.type)) {
194,640,085✔
5140
        int32_t bytes = calcStrBytesByType(pCol->info.type, p);
9,550,880✔
5141
        (void)memcpy(pStart + offset, p, bytes);
9,554,986✔
5142
      } else {
5143
        (void)memcpy(pStart + offset, p, pCol->info.bytes);
185,085,552✔
5144
      }
5145

5146
      offset += pCol->info.bytes;
194,643,640✔
5147
      continue;
194,638,013✔
5148
    }
5149
  }
5150

5151
  *res = buf;
125,477,874✔
5152
  return TSDB_CODE_SUCCESS;
125,488,759✔
5153
}
5154

5155
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
253,749,175✔
5156
                               STuplePos* pPos, SFunctionStateStore* pStore) {
5157
  STuplePos p = {0};
253,749,175✔
5158
  if (pHandle->pBuf != NULL) {
253,749,175✔
5159
    SFilePage* pPage = NULL;
253,759,431✔
5160

5161
    if (pHandle->currentPage == -1) {
253,759,431✔
5162
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
5,985,105✔
5163
      if (pPage == NULL) {
5,986,035✔
5164
        return terrno;
×
5165
      }
5166
      pPage->num = sizeof(SFilePage);
5,986,035✔
5167
    } else {
5168
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
247,776,714✔
5169
      if (pPage == NULL) {
247,775,288✔
5170
        return terrno;
×
5171
      }
5172
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
247,775,288✔
5173
        // current page is all used, let's prepare a new buffer page
5174
        releaseBufPage(pHandle->pBuf, pPage);
429,730✔
5175
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
429,730✔
5176
        if (pPage == NULL) {
429,730✔
5177
          return terrno;
×
5178
        }
5179
        pPage->num = sizeof(SFilePage);
429,730✔
5180
      }
5181
    }
5182

5183
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
253,760,466✔
5184
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
253,758,730✔
5185

5186
    pPage->num += length;
253,759,273✔
5187
    setBufPageDirty(pPage, true);
253,760,294✔
5188
    releaseBufPage(pHandle->pBuf, pPage);
253,753,268✔
5189
  } else {  // other tuple save policy
5190
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
2,179✔
5191
      p.streamTupleKey = *key;
×
5192
    }
5193
  }
5194

5195
  *pPos = p;
253,748,313✔
5196
  return TSDB_CODE_SUCCESS;
253,746,768✔
5197
}
5198

5199
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
82,892,596✔
5200
  int32_t code = prepareBuf(pCtx);
82,892,596✔
5201
  if (TSDB_CODE_SUCCESS != code) {
82,889,409✔
5202
    return code;
×
5203
  }
5204

5205
  SWinKey key = {0};
82,889,409✔
5206
  if (pCtx->saveHandle.pBuf == NULL) {
82,889,409✔
5207
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
×
5208
    if (NULL == pColInfo) {
×
5209
      return TSDB_CODE_OUT_OF_RANGE;
×
5210
    }
5211
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
×
5212
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
5213
    }
5214
    key.groupId = pSrcBlock->info.id.groupId;
×
5215
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
×
5216
    key.numInGroup = pCtx->pExpr->pExpr->_function.bindExprID;
×
5217
  }
5218

5219
  char* buf = NULL;
82,891,796✔
5220
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
82,893,388✔
5221
  if (TSDB_CODE_SUCCESS != code) {
82,891,101✔
5222
    return code;
×
5223
  }
5224
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
82,891,101✔
5225
}
5226

5227
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
42,596,519✔
5228
                                 SFunctionStateStore* pStore) {
5229
  if (pHandle->pBuf != NULL) {
42,596,519✔
5230
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
42,597,655✔
5231
    if (pPage == NULL) {
42,598,572✔
5232
      return terrno;
×
5233
    }
5234
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
42,598,572✔
5235
    setBufPageDirty(pPage, true);
42,598,572✔
5236
    releaseBufPage(pHandle->pBuf, pPage);
42,591,975✔
5237
  } else {
5238
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
×
5239
    if (TSDB_CODE_SUCCESS != code) {
×
5240
      return code;
×
5241
    }
5242
  }
5243

5244
  return TSDB_CODE_SUCCESS;
42,588,783✔
5245
}
5246

5247
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
42,595,951✔
5248
  int32_t code = prepareBuf(pCtx);
42,595,951✔
5249
  if (TSDB_CODE_SUCCESS != code) {
42,596,979✔
5250
    return code;
×
5251
  }
5252

5253
  char* buf = NULL;
42,596,979✔
5254
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
42,596,979✔
5255
  if (TSDB_CODE_SUCCESS != code) {
42,596,979✔
5256
    return code;
×
5257
  }
5258
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
42,596,979✔
5259
}
5260

5261
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
82,079,530✔
5262
                               char** value) {
5263
  if (pHandle->pBuf != NULL) {
82,079,530✔
5264
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
82,080,000✔
5265
    if (pPage == NULL) {
82,079,321✔
5266
      *value = NULL;
×
5267
      return terrno;
×
5268
    }
5269
    *value = pPage->data + pPos->offset;
82,079,321✔
5270
    releaseBufPage(pHandle->pBuf, pPage);
82,079,321✔
5271
    return TSDB_CODE_SUCCESS;
82,080,000✔
5272
  } else {
5273
    *value = NULL;
×
5274
    int32_t vLen;
×
5275
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
×
5276
    if (TSDB_CODE_SUCCESS != code) {
×
5277
      return code;
×
5278
    }
5279
    return TSDB_CODE_SUCCESS;
×
5280
  }
5281
}
5282

5283
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
82,080,000✔
5284
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
82,080,000✔
5285
}
5286

5287
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,266,196✔
5288
  int32_t code = TSDB_CODE_SUCCESS;
8,266,196✔
5289

5290
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
8,266,196✔
5291
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
8,266,196✔
5292

5293
  int16_t type = pCtx->pExpr->base.resSchema.type;
8,266,196✔
5294
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
8,266,196✔
5295

5296
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,266,196✔
5297
  if (NULL == pCol) {
8,265,535✔
5298
    return TSDB_CODE_OUT_OF_RANGE;
×
5299
  }
5300

5301
  // todo assign the tag value and the corresponding row data
5302
  int32_t currentRow = pBlock->info.rows;
8,265,535✔
5303
  if (pEntryInfo->numOfRes <= 0) {
8,266,196✔
5304
    colDataSetNULL(pCol, currentRow);
58,812✔
5305
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
58,812✔
5306
    return code;
58,812✔
5307
  }
5308
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
56,296,303✔
5309
    STopBotResItem* pItem = &pRes->pItems[i];
48,089,566✔
5310
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
48,089,566✔
5311
    if (TSDB_CODE_SUCCESS != code) {
48,090,874✔
5312
      return code;
×
5313
    }
5314
#ifdef BUF_PAGE_DEBUG
5315
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
5316
           pItem->tuplePos.offset);
5317
#endif
5318
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
48,090,874✔
5319
    if (TSDB_CODE_SUCCESS != code) {
48,088,919✔
5320
      return code;
×
5321
    }
5322
    currentRow += 1;
48,088,919✔
5323
  }
5324

5325
  return code;
8,207,384✔
5326
}
5327

5328
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
5329
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
5330
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
5331
  STopBotResItem*      pItems = pRes->pItems;
×
5332
  int32_t              code = TSDB_CODE_SUCCESS;
×
5333

5334
  // not full yet
5335
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
5336
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
5337
    pItem->v = pSourceItem->v;
×
5338
    pItem->uid = pSourceItem->uid;
×
5339
    pItem->tuplePos.pageId = -1;
×
5340
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
5341
    pEntryInfo->numOfRes++;
×
5342
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
5343
                        topBotResComparFn, !isTopQuery);
×
5344
    if (TSDB_CODE_SUCCESS != code) {
×
5345
      return code;
×
5346
    }
5347
  } else {  // replace the minimum value in the result
5348
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
5349
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
5350
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
5351
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
5352
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
5353
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
5354
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
5355
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
5356
      // replace the old data and the coresponding tuple data
5357
      STopBotResItem* pItem = &pItems[0];
×
5358
      pItem->v = pSourceItem->v;
×
5359
      pItem->uid = pSourceItem->uid;
×
5360

5361
      // save the data of this tuple by over writing the old data
5362
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
5363
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
5364
                            topBotResComparFn, NULL, !isTopQuery);
×
5365
      if (TSDB_CODE_SUCCESS != code) {
×
5366
        return code;
×
5367
      }
5368
    }
5369
  }
5370
  return code;
×
5371
}
5372

5373
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5374
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5375
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
5376
  int16_t              type = pSBuf->type;
×
5377
  int32_t              code = TSDB_CODE_SUCCESS;
×
5378
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
5379
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
5380
    if (TSDB_CODE_SUCCESS != code) {
×
5381
      return code;
×
5382
    }
5383
  }
5384
  return TSDB_CODE_SUCCESS;
×
5385
}
5386

5387
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5388
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5389
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
5390
  int16_t              type = pSBuf->type;
×
5391
  int32_t              code = TSDB_CODE_SUCCESS;
×
5392
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
5393
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
5394
    if (TSDB_CODE_SUCCESS != code) {
×
5395
      return code;
×
5396
    }
5397
  }
5398
  return TSDB_CODE_SUCCESS;
×
5399
}
5400

5401
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
8,951,631✔
5402

5403
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
4,052,922✔
5404
  pEnv->calcMemSize = sizeof(SSpreadInfo);
4,052,922✔
5405
  return true;
4,054,061✔
5406
}
5407

5408
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
122,022,366✔
5409
  if (pResultInfo->initialized) {
122,022,366✔
5410
    return TSDB_CODE_SUCCESS;
×
5411
  }
5412
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
122,022,941✔
5413
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5414
  }
5415

5416
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
122,021,791✔
5417
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
122,021,791✔
5418
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
122,022,366✔
5419
  pInfo->hasResult = false;
122,022,272✔
5420
  return TSDB_CODE_SUCCESS;
122,021,791✔
5421
}
5422

5423
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
175,098,142✔
5424
  int32_t numOfElems = 0;
175,098,142✔
5425

5426
  // Only the pre-computing information loaded and actual data does not loaded
5427
  SInputColumnInfoData* pInput = &pCtx->input;
175,098,142✔
5428
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
175,118,124✔
5429
  int32_t               type = pInput->pData[0]->info.type;
175,141,347✔
5430

5431
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
175,148,556✔
5432

5433
  if (pInput->colDataSMAIsSet) {
175,144,045✔
5434
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
49,188,139✔
5435
    if (numOfElems == 0) {
49,190,114✔
5436
      goto _spread_over;
34,895,266✔
5437
    }
5438
    double tmin = 0.0, tmax = 0.0;
14,294,848✔
5439
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
14,294,848✔
5440
      tmin = (double)GET_INT64_VAL(&pAgg->min);
7,318,345✔
5441
      tmax = (double)GET_INT64_VAL(&pAgg->max);
7,314,339✔
5442
    } else if (IS_FLOAT_TYPE(type)) {
6,976,503✔
UNCOV
5443
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
5444
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
5445
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
6,976,503✔
5446
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
6,974,504✔
5447
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
6,979,832✔
5448
    }
5449

5450
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
14,296,178✔
5451
      SET_DOUBLE_VAL(&pInfo->min, tmin);
649,341✔
5452
    }
5453

5454
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
14,294,187✔
5455
      SET_DOUBLE_VAL(&pInfo->max, tmax);
692,482✔
5456
    }
5457

5458
  } else {  // computing based on the true data block
5459
    SColumnInfoData* pCol = pInput->pData[0];
125,960,949✔
5460

5461
    int32_t start = pInput->startRowIndex;
125,963,249✔
5462
    // check the valid data one by one
5463
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,090,346,692✔
5464
      if (colDataIsNull_f(pCol, i)) {
964,392,206✔
5465
        continue;
173,655,474✔
5466
      }
5467

5468
      char* data = colDataGetData(pCol, i);
790,722,287✔
5469

5470
      double v = 0;
790,763,652✔
5471
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
790,763,652✔
5472
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
790,753,137✔
5473
        SET_DOUBLE_VAL(&pInfo->min, v);
131,195,220✔
5474
      }
5475

5476
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
790,731,091✔
5477
        SET_DOUBLE_VAL(&pInfo->max, v);
145,794,432✔
5478
      }
5479

5480
      numOfElems += 1;
790,727,969✔
5481
    }
5482
  }
5483

5484
_spread_over:
125,946,138✔
5485
  // data in the check operation are all null, not output
5486
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
175,133,359✔
5487
  if (numOfElems > 0) {
175,141,277✔
5488
    pInfo->hasResult = true;
135,030,853✔
5489
  }
5490

5491
  return TSDB_CODE_SUCCESS;
175,123,336✔
5492
}
5493

5494
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
8,190,610✔
5495
  pOutput->hasResult = pInput->hasResult;
8,190,610✔
5496
  if (pInput->max > pOutput->max) {
8,190,610✔
5497
    pOutput->max = pInput->max;
5,731,309✔
5498
  }
5499

5500
  if (pInput->min < pOutput->min) {
8,190,610✔
5501
    pOutput->min = pInput->min;
5,730,981✔
5502
  }
5503
}
8,190,610✔
5504

5505
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
6,070,564✔
5506
  SInputColumnInfoData* pInput = &pCtx->input;
6,070,564✔
5507
  SColumnInfoData*      pCol = pInput->pData[0];
6,070,564✔
5508

5509
  if (IS_NULL_TYPE(pCol->info.type)) {
6,070,564✔
5510
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
5511
    return TSDB_CODE_SUCCESS;
×
5512
  }
5513

5514
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
6,070,564✔
5515
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
5516
  }
5517

5518
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,070,564✔
5519

5520
  int32_t start = pInput->startRowIndex;
6,070,564✔
5521
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
14,545,106✔
5522
    if (colDataIsNull_s(pCol, i)) continue;
16,949,084✔
5523
    char*        data = colDataGetData(pCol, i);
8,474,542✔
5524
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
8,474,542✔
5525
    if (pInputInfo->hasResult) {
8,474,542✔
5526
      spreadTransferInfo(pInputInfo, pInfo);
8,190,610✔
5527
    }
5528
  }
5529

5530
  if (pInfo->hasResult) {
6,070,564✔
5531
    GET_RES_INFO(pCtx)->numOfRes = 1;
5,919,596✔
5532
  }
5533

5534
  return TSDB_CODE_SUCCESS;
6,070,564✔
5535
}
5536

5537
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
105,212,306✔
5538
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
105,212,306✔
5539
  if (pInfo->hasResult == true) {
105,212,306✔
5540
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
100,038,061✔
5541
  } else {
5542
    GET_RES_INFO(pCtx)->isNullRes = 1;
5,174,245✔
5543
  }
5544
  return functionFinalize(pCtx, pBlock);
105,212,306✔
5545
}
5546

5547
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,489,182✔
5548
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,489,182✔
5549
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,489,182✔
5550
  int32_t              resultBytes = getSpreadInfoSize();
8,489,182✔
5551
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
8,489,182✔
5552

5553
  if (NULL == res) {
8,489,182✔
5554
    return terrno;
×
5555
  }
5556
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
8,489,182✔
5557
  varDataSetLen(res, resultBytes);
8,489,182✔
5558

5559
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
8,489,182✔
5560
  int32_t          code = TSDB_CODE_SUCCESS;
8,489,182✔
5561
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,489,182✔
5562
  if (NULL == pCol) {
8,489,182✔
5563
    code = terrno;
×
5564
    goto _exit;
×
5565
  }
5566

5567
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
8,489,182✔
5568
  if (TSDB_CODE_SUCCESS != code) {
8,489,182✔
5569
    goto _exit;
×
5570
  }
5571

5572
_exit:
8,489,182✔
5573
  taosMemoryFree(res);
8,489,182✔
5574
  return code;
8,489,182✔
5575
}
5576

5577
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5578
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5579
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5580

5581
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5582
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5583
  spreadTransferInfo(pSBuf, pDBuf);
×
5584
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5585
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5586
  return TSDB_CODE_SUCCESS;
×
5587
}
5588

5589
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
5590

5591
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
2,661,644✔
5592
  pEnv->calcMemSize = sizeof(SElapsedInfo);
2,661,644✔
5593
  return true;
2,662,219✔
5594
}
5595

5596
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,057,153✔
5597
  if (pResultInfo->initialized) {
5,057,153✔
5598
    return TSDB_CODE_SUCCESS;
×
5599
  }
5600
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,057,652✔
5601
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5602
  }
5603

5604
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,057,153✔
5605
  pInfo->result = 0;
5,057,153✔
5606
  pInfo->min = TSKEY_MAX;
5,057,153✔
5607
  pInfo->max = 0;
5,056,654✔
5608

5609
  if (pCtx->numOfParams > 1) {
5,057,153✔
5610
    pInfo->timeUnit = pCtx->param[1].param.i;
3,256,263✔
5611
  } else {
5612
    pInfo->timeUnit = 1;
1,800,315✔
5613
  }
5614

5615
  return TSDB_CODE_SUCCESS;
5,057,077✔
5616
}
5617

5618
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
5,120,614✔
5619
  int32_t numOfElems = 0;
5,120,614✔
5620

5621
  // Only the pre-computing information loaded and actual data does not loaded
5622
  SInputColumnInfoData* pInput = &pCtx->input;
5,120,614✔
5623
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
5,120,614✔
5624

5625
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,121,113✔
5626

5627
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
5,120,614✔
5628
  if (numOfElems == 0) {
5,118,530✔
5629
    // for stream
5630
    if (pCtx->end.key != INT64_MIN) {
×
5631
      pInfo->max = pCtx->end.key + 1;
×
5632
    }
5633
    goto _elapsed_over;
×
5634
  }
5635

5636
  if (pInput->colDataSMAIsSet) {
5,118,530✔
5637
    if (pInfo->min == TSKEY_MAX) {
×
5638
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
5639
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
5640
    } else {
5641
      if (pCtx->order == TSDB_ORDER_ASC) {
×
5642
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
5643
      } else {
5644
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
5645
      }
5646
    }
5647
  } else {  // computing based on the true data block
5648
    if (0 == pInput->numOfRows) {
5,119,029✔
5649
      if (pCtx->order == TSDB_ORDER_DESC) {
×
5650
        if (pCtx->end.key != INT64_MIN) {
×
5651
          pInfo->min = pCtx->end.key;
×
5652
        }
5653
      } else {
5654
        if (pCtx->end.key != INT64_MIN) {
×
5655
          pInfo->max = pCtx->end.key + 1;
×
5656
        }
5657
      }
5658
      goto _elapsed_over;
×
5659
    }
5660

5661
    SColumnInfoData* pCol = pInput->pData[0];
5,120,039✔
5662

5663
    int32_t start = pInput->startRowIndex;
5,120,039✔
5664
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
5,119,464✔
5665
    if (pCtx->order == TSDB_ORDER_DESC) {
5,117,955✔
5666
      if (pCtx->start.key == INT64_MIN) {
37,166✔
5667
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
37,166✔
5668
      } else {
5669
        pInfo->max = pCtx->start.key + 1;
×
5670
      }
5671

5672
      if (pCtx->end.key == INT64_MIN) {
37,166✔
5673
        pInfo->min =
37,166✔
5674
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
37,166✔
5675
      } else {
5676
        pInfo->min = pCtx->end.key;
×
5677
      }
5678
    } else {
5679
      if (pCtx->start.key == INT64_MIN) {
5,081,364✔
5680
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
5,081,288✔
5681
      } else {
5682
        pInfo->min = pCtx->start.key;
×
5683
      }
5684

5685
      if (pCtx->end.key == INT64_MIN) {
5,083,947✔
5686
        pInfo->max =
5,017,449✔
5687
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
5,017,513✔
5688
      } else {
5689
        pInfo->max = pCtx->end.key + 1;
65,424✔
5690
      }
5691
    }
5692
  }
5693

5694
_elapsed_over:
5,119,540✔
5695
  // data in the check operation are all null, not output
5696
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
5,119,540✔
5697

5698
  return TSDB_CODE_SUCCESS;
5,119,464✔
5699
}
5700

5701
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
5702
  pOutput->timeUnit = pInput->timeUnit;
×
5703
  if (pOutput->min > pInput->min) {
×
5704
    pOutput->min = pInput->min;
×
5705
  }
5706

5707
  if (pOutput->max < pInput->max) {
×
5708
    pOutput->max = pInput->max;
×
5709
  }
5710
}
×
5711

5712
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
5713
  SInputColumnInfoData* pInput = &pCtx->input;
×
5714
  SColumnInfoData*      pCol = pInput->pData[0];
×
5715
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
5716
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
5717
  }
5718

5719
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
5720

5721
  int32_t start = pInput->startRowIndex;
×
5722

5723
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
5724
    char*         data = colDataGetData(pCol, i);
×
5725
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
5726
    elapsedTransferInfo(pInputInfo, pInfo);
×
5727
  }
5728

5729
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
5730
  return TSDB_CODE_SUCCESS;
×
5731
}
5732

5733
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,057,112✔
5734
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,057,112✔
5735
  double        result = (double)(pInfo->max - pInfo->min);
5,057,112✔
5736
  pInfo->result = fabs(result) / pInfo->timeUnit;
5,057,112✔
5737
  return functionFinalize(pCtx, pBlock);
5,057,652✔
5738
}
5739

5740
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
5741
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
5742
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
5743
  int32_t              resultBytes = getElapsedInfoSize();
×
5744
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
5745

5746
  if (NULL == res) {
×
5747
    return terrno;
×
5748
  }
5749
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
5750
  varDataSetLen(res, resultBytes);
×
5751

5752
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
5753
  int32_t          code = TSDB_CODE_SUCCESS;
×
5754
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
5755
  if (NULL == pCol) {
×
5756
    code = terrno;
×
5757
    goto _exit;
×
5758
  }
5759

5760
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
5761
  if (TSDB_CODE_SUCCESS != code) {
×
5762
    goto _exit;
×
5763
  }
5764
_exit:
×
5765
  taosMemoryFree(res);
×
5766
  return code;
×
5767
}
5768

5769
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5770
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5771
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5772

5773
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5774
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5775

5776
  elapsedTransferInfo(pSBuf, pDBuf);
×
5777
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5778
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5779
  return TSDB_CODE_SUCCESS;
×
5780
}
5781

5782
int32_t getHistogramInfoSize() {
805,917✔
5783
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
805,917✔
5784
}
5785

5786
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,451,503✔
5787
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
1,451,503✔
5788
  return true;
1,452,469✔
5789
}
5790

5791
static int8_t getHistogramBinType(char* binTypeStr) {
998,908✔
5792
  int8_t binType;
5793
  if (strcasecmp(binTypeStr, "user_input") == 0) {
998,908✔
5794
    binType = USER_INPUT_BIN;
405,968✔
5795
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
592,940✔
5796
    binType = LINEAR_BIN;
404,280✔
5797
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
188,660✔
5798
    binType = LOG_BIN;
188,660✔
5799
  } else {
5800
    binType = UNKNOWN_BIN;
×
5801
  }
5802

5803
  return binType;
998,908✔
5804
}
5805

5806
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
998,908✔
5807
  cJSON*  binDesc = cJSON_Parse(binDescStr);
998,908✔
5808
  int32_t numOfBins;
5809
  double* intervals;
5810
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
998,908✔
5811
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
592,940✔
5812
    int32_t startIndex;
5813
    if (numOfParams != 4) {
592,376✔
5814
      cJSON_Delete(binDesc);
×
5815
      return TSDB_CODE_FAILED;
×
5816
    }
5817

5818
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
592,376✔
5819
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
592,376✔
5820
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
592,940✔
5821
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
592,940✔
5822
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
592,940✔
5823

5824
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
592,940✔
5825
      cJSON_Delete(binDesc);
×
5826
      return TSDB_CODE_FAILED;
×
5827
    }
5828

5829
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
592,400✔
5830
      cJSON_Delete(binDesc);
540✔
5831
      return TSDB_CODE_FAILED;
×
5832
    }
5833

5834
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
591,836✔
5835
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
592,940✔
5836
      cJSON_Delete(binDesc);
×
5837
      return TSDB_CODE_FAILED;
×
5838
    }
5839

5840
    int32_t counter = (int32_t)count->valueint;
592,940✔
5841
    if (infinity->valueint == false) {
592,376✔
5842
      startIndex = 0;
486,516✔
5843
      numOfBins = counter + 1;
486,516✔
5844
    } else {
5845
      startIndex = 1;
105,320✔
5846
      numOfBins = counter + 3;
105,320✔
5847
    }
5848

5849
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
591,836✔
5850
    if (NULL == intervals) {
592,940✔
5851
      cJSON_Delete(binDesc);
×
5852
      qError("histogram function out of memory");
×
5853
      return terrno;
×
5854
    }
5855
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
592,940✔
5856
      // linear bin process
5857
      if (width->valuedouble == 0) {
404,280✔
5858
        taosMemoryFree(intervals);
×
5859
        cJSON_Delete(binDesc);
×
5860
        return TSDB_CODE_FAILED;
×
5861
      }
5862
      for (int i = 0; i < counter + 1; ++i) {
2,495,940✔
5863
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
2,091,660✔
5864
        if (isinf(intervals[startIndex])) {
2,092,224✔
5865
          taosMemoryFree(intervals);
×
5866
          cJSON_Delete(binDesc);
×
5867
          return TSDB_CODE_FAILED;
×
5868
        }
5869
        startIndex++;
2,092,224✔
5870
      }
5871
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
188,096✔
5872
      // log bin process
5873
      if (start->valuedouble == 0) {
188,660✔
5874
        taosMemoryFree(intervals);
×
5875
        cJSON_Delete(binDesc);
×
5876
        return TSDB_CODE_FAILED;
×
5877
      }
5878
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
188,660✔
5879
        taosMemoryFree(intervals);
1,080✔
5880
        cJSON_Delete(binDesc);
×
5881
        return TSDB_CODE_FAILED;
×
5882
      }
5883
      for (int i = 0; i < counter + 1; ++i) {
986,570✔
5884
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
798,040✔
5885
        if (isinf(intervals[startIndex])) {
797,910✔
5886
          taosMemoryFree(intervals);
×
5887
          cJSON_Delete(binDesc);
×
5888
          return TSDB_CODE_FAILED;
×
5889
        }
5890
        startIndex++;
798,450✔
5891
      }
5892
    } else {
5893
      taosMemoryFree(intervals);
×
5894
      cJSON_Delete(binDesc);
×
5895
      return TSDB_CODE_FAILED;
×
5896
    }
5897

5898
    if (infinity->valueint == true) {
592,810✔
5899
      intervals[0] = -INFINITY;
104,910✔
5900
      intervals[numOfBins - 1] = INFINITY;
105,860✔
5901
      // in case of desc bin orders, -inf/inf should be swapped
5902
      if (numOfBins < 4) {
104,910✔
5903
        return TSDB_CODE_FAILED;
×
5904
      }
5905
      if (intervals[1] > intervals[numOfBins - 2]) {
104,910✔
5906
        TSWAP(intervals[0], intervals[numOfBins - 1]);
105,320✔
5907
      }
5908
    }
5909
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
405,566✔
5910
    if (binType != USER_INPUT_BIN) {
405,968✔
5911
      cJSON_Delete(binDesc);
×
5912
      return TSDB_CODE_FAILED;
×
5913
    }
5914
    numOfBins = cJSON_GetArraySize(binDesc);
405,968✔
5915
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
405,968✔
5916
    if (NULL == intervals) {
405,968✔
5917
      cJSON_Delete(binDesc);
×
5918
      qError("histogram function out of memory");
×
5919
      return terrno;
×
5920
    }
5921
    cJSON* bin = binDesc->child;
405,968✔
5922
    if (bin == NULL) {
405,968✔
5923
      taosMemoryFree(intervals);
×
5924
      cJSON_Delete(binDesc);
×
5925
      return TSDB_CODE_FAILED;
×
5926
    }
5927
    int i = 0;
405,968✔
5928
    while (bin) {
1,696,718✔
5929
      intervals[i] = bin->valuedouble;
1,291,152✔
5930
      if (!cJSON_IsNumber(bin)) {
1,290,750✔
5931
        taosMemoryFree(intervals);
×
5932
        cJSON_Delete(binDesc);
×
5933
        return TSDB_CODE_FAILED;
×
5934
      }
5935
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
1,290,750✔
5936
        taosMemoryFree(intervals);
×
5937
        cJSON_Delete(binDesc);
×
5938
        return TSDB_CODE_FAILED;
×
5939
      }
5940
      bin = bin->next;
1,291,152✔
5941
      i++;
1,290,750✔
5942
    }
5943
  } else {
5944
    cJSON_Delete(binDesc);
×
5945
    return TSDB_CODE_FAILED;
×
5946
  }
5947

5948
  pInfo->numOfBins = numOfBins - 1;
998,096✔
5949
  pInfo->normalized = normalized;
997,966✔
5950
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
4,392,434✔
5951
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
3,396,554✔
5952
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
3,396,586✔
5953
    pInfo->bins[i].count = 0;
3,397,520✔
5954
  }
5955

5956
  taosMemoryFree(intervals);
996,444✔
5957
  cJSON_Delete(binDesc);
998,908✔
5958

5959
  return TSDB_CODE_SUCCESS;
998,498✔
5960
}
5961

5962
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
998,908✔
5963
  if (pResultInfo->initialized) {
998,908✔
5964
    return TSDB_CODE_SUCCESS;
×
5965
  }
5966
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
998,908✔
5967
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5968
  }
5969

5970
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
998,908✔
5971
  pInfo->numOfBins = 0;
998,908✔
5972
  pInfo->totalCount = 0;
998,908✔
5973
  pInfo->normalized = 0;
998,908✔
5974

5975
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
998,908✔
5976
  if (binTypeStr == NULL) {
998,908✔
5977
    return terrno;
×
5978
  }
5979
  int8_t binType = getHistogramBinType(binTypeStr);
998,908✔
5980
  taosMemoryFree(binTypeStr);
998,908✔
5981

5982
  if (binType == UNKNOWN_BIN) {
998,908✔
5983
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5984
  }
5985
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
998,908✔
5986
  if (binDesc == NULL) {
998,908✔
5987
    return terrno;
×
5988
  }
5989
  int64_t normalized = pCtx->param[3].param.i;
998,908✔
5990
  if (normalized != 0 && normalized != 1) {
998,908✔
5991
    taosMemoryFree(binDesc);
×
5992
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5993
  }
5994
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
998,908✔
5995
  if (TSDB_CODE_SUCCESS != code) {
998,908✔
5996
    taosMemoryFree(binDesc);
×
5997
    return code;
×
5998
  }
5999
  taosMemoryFree(binDesc);
998,908✔
6000

6001
  return TSDB_CODE_SUCCESS;
998,368✔
6002
}
6003

6004
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
1,164,292✔
6005
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,164,292✔
6006

6007
  SInputColumnInfoData* pInput = &pCtx->input;
1,163,890✔
6008
  SColumnInfoData*      pCol = pInput->pData[0];
1,163,866✔
6009

6010
  int32_t type = pInput->pData[0]->info.type;
1,163,882✔
6011

6012
  int32_t start = pInput->startRowIndex;
1,164,832✔
6013
  int32_t numOfRows = pInput->numOfRows;
1,163,866✔
6014

6015
  int32_t numOfElems = 0;
1,171,838✔
6016
  for (int32_t i = start; i < numOfRows + start; ++i) {
168,161,686✔
6017
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
166,996,854✔
6018
      continue;
32,247,868✔
6019
    }
6020

6021
    numOfElems++;
134,748,342✔
6022

6023
    char*  data = colDataGetData(pCol, i);
134,748,342✔
6024
    double v;
6025
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
134,933,330✔
6026

6027
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
542,907,341✔
6028
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
437,649,879✔
6029
        pInfo->bins[k].count++;
29,717,938✔
6030
        pInfo->totalCount++;
29,723,468✔
6031
        break;
29,716,068✔
6032
      }
6033
    }
6034
  }
6035

6036
  if (!isPartial) {
1,164,832✔
6037
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
789,276✔
6038
  } else {
6039
    GET_RES_INFO(pCtx)->numOfRes = 1;
375,556✔
6040
  }
6041
  return TSDB_CODE_SUCCESS;
1,164,268✔
6042
}
6043

6044
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
789,276✔
6045

6046
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
375,556✔
6047

6048
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
239,676✔
6049
  pOutput->normalized = pInput->normalized;
239,676✔
6050
  pOutput->numOfBins = pInput->numOfBins;
239,676✔
6051
  pOutput->totalCount += pInput->totalCount;
239,676✔
6052
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
1,380,864✔
6053
    pOutput->bins[k].lower = pInput->bins[k].lower;
1,140,060✔
6054
    pOutput->bins[k].upper = pInput->bins[k].upper;
1,140,624✔
6055
    pOutput->bins[k].count += pInput->bins[k].count;
1,141,752✔
6056
  }
6057
}
240,240✔
6058

6059
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
239,676✔
6060
  SInputColumnInfoData* pInput = &pCtx->input;
239,676✔
6061
  SColumnInfoData*      pCol = pInput->pData[0];
239,676✔
6062
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
239,676✔
6063
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6064
  }
6065

6066
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
239,676✔
6067

6068
  int32_t start = pInput->startRowIndex;
239,676✔
6069

6070
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
478,788✔
6071
    char*           data = colDataGetData(pCol, i);
239,676✔
6072
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
239,676✔
6073
    histogramTransferInfo(pInputInfo, pInfo);
239,112✔
6074
  }
6075

6076
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
239,676✔
6077
  return TSDB_CODE_SUCCESS;
239,676✔
6078
}
6079

6080
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
975,571✔
6081
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
975,571✔
6082
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
975,571✔
6083
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
975,571✔
6084
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
975,169✔
6085
  int32_t              code = TSDB_CODE_SUCCESS;
975,571✔
6086

6087
  int32_t currentRow = pBlock->info.rows;
975,571✔
6088
  if (NULL == pCol) {
975,571✔
6089
    return TSDB_CODE_OUT_OF_RANGE;
×
6090
  }
6091

6092
  if (pInfo->normalized) {
975,571✔
6093
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
3,671,722✔
6094
      if (pInfo->totalCount != 0) {
2,826,914✔
6095
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
430,036✔
6096
      } else {
6097
        pInfo->bins[k].percentage = 0;
2,396,074✔
6098
      }
6099
    }
6100
  }
6101

6102
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
4,214,503✔
6103
    int32_t len;
6104
    char    buf[512] = {0};
3,238,932✔
6105
    if (!pInfo->normalized) {
3,238,770✔
6106
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
412,018✔
6107
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
6108
                     pInfo->bins[i].upper, pInfo->bins[i].count);
6109
    } else {
6110
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
2,826,914✔
6111
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
6112
                     pInfo->bins[i].percentage);
6113
    }
6114
    varDataSetLen(buf, len);
3,238,770✔
6115
    code = colDataSetVal(pCol, currentRow, buf, false);
3,238,770✔
6116
    if (TSDB_CODE_SUCCESS != code) {
3,239,334✔
6117
      return code;
×
6118
    }
6119
    currentRow++;
3,239,334✔
6120
  }
6121

6122
  return code;
975,571✔
6123
}
6124

6125
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
239,676✔
6126
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
239,676✔
6127
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
239,676✔
6128
  int32_t              resultBytes = getHistogramInfoSize();
239,676✔
6129
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
239,676✔
6130

6131
  if (NULL == res) {
239,676✔
6132
    return terrno;
×
6133
  }
6134
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
239,676✔
6135
  varDataSetLen(res, resultBytes);
239,676✔
6136

6137
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
239,676✔
6138
  int32_t          code = TSDB_CODE_SUCCESS;
239,676✔
6139
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
239,676✔
6140
  if (NULL == pCol) {
239,676✔
6141
    code = terrno;
×
6142
    goto _exit;
×
6143
  }
6144
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
239,676✔
6145

6146
_exit:
239,676✔
6147
  taosMemoryFree(res);
239,676✔
6148
  return code;
239,676✔
6149
}
6150

6151
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6152
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6153
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6154

6155
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6156
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6157

6158
  histogramTransferInfo(pSBuf, pDBuf);
×
6159
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
6160
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
6161
  return TSDB_CODE_SUCCESS;
×
6162
}
6163

6164
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
286,831✔
6165

6166
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
4,118,543✔
6167
  pEnv->calcMemSize = sizeof(SHLLInfo);
4,118,543✔
6168
  return true;
4,119,760✔
6169
}
6170

6171
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
659,853,443✔
6172
  uint64_t hash = MurmurHash3_64(data, bytes);
659,853,443✔
6173
  int32_t  index = hash & HLL_BUCKET_MASK;
659,817,218✔
6174
  hash >>= HLL_BUCKET_BITS;
659,817,218✔
6175
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
659,817,218✔
6176
  uint64_t bit = 1;
659,817,218✔
6177
  uint8_t  count = 1;
659,817,218✔
6178
  while ((hash & bit) == 0) {
1,296,963,245✔
6179
    count++;
637,146,027✔
6180
    bit <<= 1;
637,146,027✔
6181
  }
6182
  *buk = index;
659,817,218✔
6183
  return count;
659,854,018✔
6184
}
6185

6186
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
9,814,887✔
6187
  uint64_t* word = (uint64_t*)buckets;
9,814,887✔
6188
  uint8_t*  bytes;
6189

6190
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
2,147,483,647✔
6191
    if (*word == 0) {
2,147,483,647✔
6192
      bucketHisto[0] += 8;
2,147,483,647✔
6193
    } else {
6194
      bytes = (uint8_t*)word;
94,910,055✔
6195
      bucketHisto[bytes[0]]++;
94,910,055✔
6196
      bucketHisto[bytes[1]]++;
96,752,460✔
6197
      bucketHisto[bytes[2]]++;
96,752,460✔
6198
      bucketHisto[bytes[3]]++;
96,752,460✔
6199
      bucketHisto[bytes[4]]++;
96,751,885✔
6200
      bucketHisto[bytes[5]]++;
96,751,885✔
6201
      bucketHisto[bytes[6]]++;
96,751,885✔
6202
      bucketHisto[bytes[7]]++;
96,751,885✔
6203
    }
6204
    word++;
2,147,483,647✔
6205
  }
6206
}
693,092✔
6207
static double hllTau(double x) {
9,815,462✔
6208
  if (x == 0. || x == 1.) return 0.;
9,815,462✔
6209
  double zPrime;
6210
  double y = 1.0;
×
6211
  double z = 1 - x;
×
6212
  do {
6213
    x = sqrt(x);
×
6214
    zPrime = z;
×
6215
    y *= 0.5;
×
6216
    z -= pow(1 - x, 2) * y;
×
6217
  } while (zPrime != z);
×
6218
  return z / 3;
×
6219
}
6220

6221
static double hllSigma(double x) {
9,815,462✔
6222
  if (x == 1.0) return INFINITY;
9,815,462✔
6223
  double zPrime;
6224
  double y = 1;
6,108,125✔
6225
  double z = x;
6,108,125✔
6226
  do {
6227
    x *= x;
117,201,277✔
6228
    zPrime = z;
117,201,277✔
6229
    z += x * y;
117,201,277✔
6230
    y += y;
117,201,277✔
6231
  } while (zPrime != z);
117,201,277✔
6232
  return z;
6,108,125✔
6233
}
6234

6235
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
6236
// sketches"
6237
static uint64_t hllCountCnt(uint8_t* buckets) {
9,814,887✔
6238
  double  m = HLL_BUCKETS;
9,814,887✔
6239
  int32_t buckethisto[64] = {0};
9,814,887✔
6240
  hllBucketHisto(buckets, buckethisto);
9,814,347✔
6241

6242
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
9,815,462✔
6243
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
500,563,182✔
6244
    z += buckethisto[j];
490,748,260✔
6245
    z *= 0.5;
490,747,720✔
6246
  }
6247

6248
  z += m * hllSigma(buckethisto[0] / (double)m);
9,814,922✔
6249
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
9,815,462✔
6250

6251
  return (uint64_t)E;
9,815,462✔
6252
}
6253

6254
int32_t hllFunction(SqlFunctionCtx* pCtx) {
10,088,354✔
6255
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,088,354✔
6256

6257
  SInputColumnInfoData* pInput = &pCtx->input;
10,088,929✔
6258
  SColumnInfoData*      pCol = pInput->pData[0];
10,088,929✔
6259

6260
  int32_t type = pCol->info.type;
10,087,779✔
6261
  int32_t bytes = pCol->info.bytes;
10,086,640✔
6262

6263
  int32_t start = pInput->startRowIndex;
10,087,779✔
6264
  int32_t numOfRows = pInput->numOfRows;
10,087,215✔
6265

6266
  int32_t numOfElems = 0;
10,084,950✔
6267
  if (IS_NULL_TYPE(type)) {
10,084,950✔
6268
    goto _hll_over;
151,570✔
6269
  }
6270

6271
  for (int32_t i = start; i < numOfRows + start; ++i) {
773,410,782✔
6272
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
877,265,785✔
6273
      continue;
103,623,784✔
6274
    }
6275

6276
    numOfElems++;
659,850,708✔
6277

6278
    char* data = colDataGetData(pCol, i);
659,850,708✔
6279
    if (IS_VAR_DATA_TYPE(type)) {
659,863,218✔
6280
      if (IS_STR_DATA_BLOB(type)) {
81,728,699✔
UNCOV
6281
        bytes = blobDataLen(data);
×
6282
        data = blobDataVal(data);
×
6283
      } else {
6284
        bytes = varDataLen(data);
81,730,999✔
6285
        data = varDataVal(data);
81,731,574✔
6286
      }
6287
    }
6288

6289
    int32_t index = 0;
659,866,093✔
6290
    uint8_t count = hllCountNum(data, bytes, &index);
659,857,468✔
6291
    uint8_t oldcount = pInfo->buckets[index];
659,854,593✔
6292
    if (count > oldcount) {
659,855,168✔
6293
      pInfo->buckets[index] = count;
141,822,792✔
6294
    }
6295
  }
6296

6297
_hll_over:
9,933,415✔
6298
  pInfo->totalCount += numOfElems;
10,084,985✔
6299

6300
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,089,504✔
6301
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
639✔
6302
  } else {
6303
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,088,865✔
6304
  }
6305

6306
  return TSDB_CODE_SUCCESS;
10,088,929✔
6307
}
6308

6309
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
286,831✔
6310
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
2,147,483,647✔
6311
    if (pOutput->buckets[k] < pInput->buckets[k]) {
2,147,483,647✔
6312
      pOutput->buckets[k] = pInput->buckets[k];
47,280,899✔
6313
    }
6314
  }
6315
  pOutput->totalCount += pInput->totalCount;
7,282✔
6316
}
286,831✔
6317

6318
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
285,123✔
6319
  SInputColumnInfoData* pInput = &pCtx->input;
285,123✔
6320
  SColumnInfoData*      pCol = pInput->pData[0];
285,123✔
6321

6322
  if (IS_NULL_TYPE(pCol->info.type)) {
285,123✔
6323
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
6324
    return TSDB_CODE_SUCCESS;
×
6325
  }
6326

6327
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
285,123✔
6328
    return TSDB_CODE_SUCCESS;
×
6329
  }
6330

6331
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
285,123✔
6332

6333
  int32_t start = pInput->startRowIndex;
285,123✔
6334

6335
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
571,954✔
6336
    if (colDataIsNull_s(pCol, i)) continue;
573,662✔
6337
    char*     data = colDataGetData(pCol, i);
286,831✔
6338
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
286,831✔
6339
    hllTransferInfo(pInputInfo, pInfo);
286,831✔
6340
  }
6341

6342
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
285,123✔
6343
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
71✔
6344
  } else {
6345
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
285,052✔
6346
  }
6347

6348
  return TSDB_CODE_SUCCESS;
285,123✔
6349
}
6350

6351
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
9,814,887✔
6352
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
9,814,887✔
6353

6354
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,814,887✔
6355
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
9,814,887✔
6356
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
9,815,462✔
6357
    pInfo->numOfRes = 1;
3,707,195✔
6358
  }
6359

6360
  return functionFinalize(pCtx, pBlock);
9,814,922✔
6361
}
6362

6363
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
286,831✔
6364
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
286,831✔
6365
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
286,831✔
6366
  int32_t              resultBytes = getHLLInfoSize();
286,831✔
6367
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
286,831✔
6368

6369
  if (NULL == res) {
286,831✔
6370
    return terrno;
×
6371
  }
6372
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
286,831✔
6373
  varDataSetLen(res, resultBytes);
286,831✔
6374

6375
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
286,831✔
6376
  int32_t          code = TSDB_CODE_SUCCESS;
286,831✔
6377
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
286,831✔
6378
  if (NULL == pCol) {
286,831✔
6379
    code = terrno;
×
6380
    goto _exit;
×
6381
  }
6382

6383
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
286,831✔
6384

6385
_exit:
286,831✔
6386
  taosMemoryFree(res);
286,831✔
6387
  return code;
286,831✔
6388
}
6389

6390
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6391
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6392
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6393

6394
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6395
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6396

6397
  hllTransferInfo(pSBuf, pDBuf);
×
6398
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
6399
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
6400
  return TSDB_CODE_SUCCESS;
×
6401
}
6402

6403
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,464,971✔
6404
  pEnv->calcMemSize = sizeof(SStateInfo);
1,464,971✔
6405
  return true;
1,465,535✔
6406
}
6407

6408
static int8_t getStateOpType(char* opStr) {
1,749,155✔
6409
  int8_t opType;
6410
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,749,155✔
6411
    opType = STATE_OPER_LT;
440,616✔
6412
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
1,308,539✔
6413
    opType = STATE_OPER_GT;
268,584✔
6414
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
1,039,955✔
6415
    opType = STATE_OPER_LE;
194,721✔
6416
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
845,234✔
6417
    opType = STATE_OPER_GE;
344,418✔
6418
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
500,816✔
6419
    opType = STATE_OPER_NE;
118,208✔
6420
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
382,608✔
6421
    opType = STATE_OPER_EQ;
382,608✔
6422
  } else {
6423
    opType = STATE_OPER_INVALID;
×
6424
  }
6425

6426
  return opType;
1,749,155✔
6427
}
6428

6429
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
217,172,582✔
6430
  char* data = colDataGetData(pCol, index);
217,172,582✔
6431
  switch (pCol->info.type) {
217,181,828✔
6432
    case TSDB_DATA_TYPE_TINYINT: {
735,744✔
6433
      int8_t v = *(int8_t*)data;
735,744✔
6434
      STATE_COMP(op, v, param);
735,744✔
6435
      break;
×
6436
    }
6437
    case TSDB_DATA_TYPE_UTINYINT: {
32,696,448✔
6438
      uint8_t v = *(uint8_t*)data;
32,696,448✔
6439
      STATE_COMP(op, v, param);
32,696,448✔
6440
      break;
×
6441
    }
6442
    case TSDB_DATA_TYPE_SMALLINT: {
4,059,688✔
6443
      int16_t v = *(int16_t*)data;
4,059,688✔
6444
      STATE_COMP(op, v, param);
4,059,688✔
6445
      break;
×
6446
    }
6447
    case TSDB_DATA_TYPE_USMALLINT: {
673,920✔
6448
      uint16_t v = *(uint16_t*)data;
673,920✔
6449
      STATE_COMP(op, v, param);
673,920✔
6450
      break;
×
6451
    }
6452
    case TSDB_DATA_TYPE_INT: {
170,444,814✔
6453
      int32_t v = *(int32_t*)data;
170,444,814✔
6454
      STATE_COMP(op, v, param);
170,444,412✔
6455
      break;
×
6456
    }
6457
    case TSDB_DATA_TYPE_UINT: {
673,920✔
6458
      uint32_t v = *(uint32_t*)data;
673,920✔
6459
      STATE_COMP(op, v, param);
673,920✔
6460
      break;
×
6461
    }
6462
    case TSDB_DATA_TYPE_BIGINT: {
751,800✔
6463
      int64_t v = *(int64_t*)data;
751,800✔
6464
      STATE_COMP(op, v, param);
751,800✔
6465
      break;
×
6466
    }
6467
    case TSDB_DATA_TYPE_UBIGINT: {
673,920✔
6468
      uint64_t v = *(uint64_t*)data;
673,920✔
6469
      STATE_COMP(op, v, param);
673,920✔
6470
      break;
×
6471
    }
6472
    case TSDB_DATA_TYPE_FLOAT: {
5,436,688✔
6473
      float v = *(float*)data;
5,436,688✔
6474
      STATE_COMP(op, v, param);
5,436,688✔
6475
      break;
×
6476
    }
6477
    case TSDB_DATA_TYPE_DOUBLE: {
1,035,690✔
6478
      double v = *(double*)data;
1,035,690✔
6479
      STATE_COMP(op, v, param);
1,035,690✔
6480
      break;
×
6481
    }
6482
    default: {
×
6483
      return false;
×
6484
    }
6485
  }
6486
  return false;
×
6487
}
6488

6489
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
363,329✔
6490
  int32_t              code = TSDB_CODE_SUCCESS;
363,329✔
6491
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
363,329✔
6492
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
363,329✔
6493

6494
  SInputColumnInfoData* pInput = &pCtx->input;
363,329✔
6495
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
363,329✔
6496

6497
  SColumnInfoData* pInputCol = pInput->pData[0];
363,329✔
6498

6499
  int32_t          numOfElems = 0;
363,329✔
6500
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
363,329✔
6501

6502
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
363,329✔
6503
  if (STATE_OPER_INVALID == op) {
363,329✔
6504
    return 0;
×
6505
  }
6506

6507
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
94,758,479✔
6508
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
94,396,986✔
6509
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,836✔
6510
    } else {
6511
      pInfo->prevTs = tsList[i];
94,395,150✔
6512
    }
6513

6514
    pInfo->isPrevTsSet = true;
94,395,150✔
6515
    numOfElems++;
94,395,150✔
6516

6517
    if (colDataIsNull_f(pInputCol, i)) {
94,395,150✔
6518
      colDataSetNULL(pOutput, i);
830,256✔
6519
      // handle selectivity
6520
      if (pCtx->subsidiaries.num > 0) {
830,256✔
6521
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4,230✔
6522
        if (TSDB_CODE_SUCCESS != code) {
4,230✔
6523
          return code;
×
6524
        }
6525
      }
6526
      continue;
830,256✔
6527
    }
6528

6529
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
93,564,894✔
6530

6531
    int64_t output = -1;
93,564,894✔
6532
    if (ret) {
93,564,894✔
6533
      output = ++pInfo->count;
36,618,597✔
6534
    } else {
6535
      pInfo->count = 0;
56,946,297✔
6536
    }
6537
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
93,564,894✔
6538
    if (TSDB_CODE_SUCCESS != code) {
93,564,894✔
6539
      return code;
×
6540
    }
6541

6542
    // handle selectivity
6543
    if (pCtx->subsidiaries.num > 0) {
93,564,894✔
6544
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
910,646✔
6545
      if (TSDB_CODE_SUCCESS != code) {
910,646✔
6546
        return code;
×
6547
      }
6548
    }
6549
  }
6550

6551
  pResInfo->numOfRes = numOfElems;
361,493✔
6552
  return TSDB_CODE_SUCCESS;
361,493✔
6553
}
6554

6555
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
1,385,826✔
6556
  int32_t              code = TSDB_CODE_SUCCESS;
1,385,826✔
6557
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,385,826✔
6558
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,385,826✔
6559

6560
  SInputColumnInfoData* pInput = &pCtx->input;
1,385,826✔
6561
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,385,826✔
6562

6563
  SColumnInfoData* pInputCol = pInput->pData[0];
1,385,826✔
6564

6565
  int32_t          numOfElems = 0;
1,385,826✔
6566
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,385,826✔
6567

6568
  // TODO: process timeUnit for different db precisions
6569
  int32_t timeUnit = 1;
1,385,826✔
6570
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
1,385,826✔
6571
    timeUnit = pCtx->param[3].param.i;
1,118,397✔
6572
  }
6573

6574
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
1,385,826✔
6575
  if (STATE_OPER_INVALID == op) {
1,385,826✔
6576
    return TSDB_CODE_INVALID_PARA;
×
6577
  }
6578

6579
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
160,466,598✔
6580
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
159,084,864✔
6581
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,836✔
6582
    } else {
6583
      pInfo->prevTs = tsList[i];
159,082,464✔
6584
    }
6585

6586
    pInfo->isPrevTsSet = true;
159,083,028✔
6587
    numOfElems++;
159,081,900✔
6588

6589
    if (colDataIsNull_f(pInputCol, i)) {
159,081,900✔
6590
      colDataSetNULL(pOutput, i);
35,449,612✔
6591
      // handle selectivity
6592
      if (pCtx->subsidiaries.num > 0) {
35,453,560✔
6593
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
8,238✔
6594
        if (TSDB_CODE_SUCCESS != code) {
8,238✔
6595
          return code;
×
6596
        }
6597
      }
6598
      continue;
35,453,560✔
6599
    }
6600

6601
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
123,633,416✔
6602
    int64_t output = -1;
123,633,416✔
6603
    if (ret) {
123,633,416✔
6604
      if (pInfo->durationStart == 0) {
51,613,677✔
6605
        output = 0;
14,221,547✔
6606
        pInfo->durationStart = tsList[i];
14,221,547✔
6607
      } else {
6608
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
37,392,130✔
6609
      }
6610
    } else {
6611
      pInfo->durationStart = 0;
72,019,739✔
6612
    }
6613
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
123,633,416✔
6614
    if (TSDB_CODE_SUCCESS != code) {
123,633,416✔
6615
      return code;
×
6616
    }
6617

6618
    // handle selectivity
6619
    if (pCtx->subsidiaries.num > 0) {
123,633,416✔
6620
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
102,248✔
6621
      if (TSDB_CODE_SUCCESS != code) {
102,248✔
6622
        return code;
×
6623
      }
6624
    }
6625
  }
6626

6627
  pResInfo->numOfRes = numOfElems;
1,383,990✔
6628
  return TSDB_CODE_SUCCESS;
1,383,990✔
6629
}
6630

6631
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
759,382✔
6632
  pEnv->calcMemSize = sizeof(SSumRes);
759,382✔
6633
  return true;
759,382✔
6634
}
6635

6636
int32_t csumFunction(SqlFunctionCtx* pCtx) {
1,140,492✔
6637
  int32_t              code = TSDB_CODE_SUCCESS;
1,140,492✔
6638
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,140,492✔
6639
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
1,140,492✔
6640

6641
  SInputColumnInfoData* pInput = &pCtx->input;
1,139,928✔
6642
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,140,492✔
6643

6644
  SColumnInfoData* pInputCol = pInput->pData[0];
1,139,928✔
6645
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,140,492✔
6646

6647
  int32_t numOfElems = 0;
1,140,492✔
6648
  int32_t type = pInputCol->info.type;
1,140,492✔
6649
  int32_t startOffset = pCtx->offset;
1,140,492✔
6650
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
209,090,560✔
6651
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
207,949,198✔
6652
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
8,154✔
6653
    } else {
6654
      pSumRes->prevTs = tsList[i];
207,928,072✔
6655
    }
6656
    pSumRes->isPrevTsSet = true;
207,942,736✔
6657

6658
    int32_t pos = startOffset + numOfElems;
207,936,532✔
6659
    if (colDataIsNull_f(pInputCol, i)) {
207,936,532✔
6660
      // colDataSetNULL(pOutput, i);
6661
      continue;
96,720,047✔
6662
    }
6663

6664
    char* data = colDataGetData(pInputCol, i);
111,230,021✔
6665
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
211,050,260✔
6666
      int64_t v;
6667
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
99,820,239✔
6668
      pSumRes->isum += v;
99,820,239✔
6669
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
99,820,239✔
6670
      if (TSDB_CODE_SUCCESS != code) {
99,820,239✔
6671
        return code;
×
6672
      }
6673
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
22,229,204✔
6674
      uint64_t v;
6675
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
10,819,422✔
6676
      pSumRes->usum += v;
10,819,422✔
6677
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
10,819,422✔
6678
      if (TSDB_CODE_SUCCESS != code) {
10,819,422✔
6679
        return code;
×
6680
      }
6681
    } else if (IS_FLOAT_TYPE(type)) {
590,360✔
6682
      double v;
6683
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
590,360✔
6684
      pSumRes->dsum += v;
590,360✔
6685
      // check for overflow
6686
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
590,360✔
6687
        colDataSetNULL(pOutput, pos);
950✔
6688
      } else {
6689
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
589,410✔
6690
        if (TSDB_CODE_SUCCESS != code) {
589,410✔
6691
          return code;
×
6692
        }
6693
      }
6694
    }
6695

6696
    // handle selectivity
6697
    if (pCtx->subsidiaries.num > 0) {
111,230,021✔
6698
      code = appendSelectivityValue(pCtx, i, pos);
24,286✔
6699
      if (TSDB_CODE_SUCCESS != code) {
24,286✔
6700
        return code;
×
6701
      }
6702
    }
6703

6704
    numOfElems++;
111,230,021✔
6705
  }
6706

6707
  pResInfo->numOfRes = numOfElems;
1,132,338✔
6708
  return TSDB_CODE_SUCCESS;
1,132,338✔
6709
}
6710

6711
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
435,047✔
6712
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
435,047✔
6713
  return true;
435,047✔
6714
}
6715

6716
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,186,044✔
6717
  if (pResultInfo->initialized) {
1,186,044✔
6718
    return TSDB_CODE_SUCCESS;
557,036✔
6719
  }
6720
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
629,008✔
6721
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6722
  }
6723

6724
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
629,162✔
6725
  pInfo->pos = 0;
629,162✔
6726
  pInfo->sum = 0;
629,162✔
6727
  pInfo->prevTs = -1;
628,468✔
6728
  pInfo->isPrevTsSet = false;
628,468✔
6729
  pInfo->numOfPoints = pCtx->param[1].param.i;
629,008✔
6730
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
628,622✔
6731
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
6732
  }
6733
  pInfo->pointsMeet = false;
628,468✔
6734

6735
  return TSDB_CODE_SUCCESS;
629,008✔
6736
}
6737

6738
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
654,376✔
6739
  int32_t              code = TSDB_CODE_SUCCESS;
654,376✔
6740
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
654,376✔
6741
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
654,376✔
6742

6743
  SInputColumnInfoData* pInput = &pCtx->input;
653,966✔
6744
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
653,966✔
6745

6746
  SColumnInfoData* pInputCol = pInput->pData[0];
654,376✔
6747
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
653,966✔
6748
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
654,376✔
6749

6750
  int32_t numOfElems = 0;
653,966✔
6751
  int32_t type = pInputCol->info.type;
653,966✔
6752
  int32_t startOffset = pCtx->offset;
654,376✔
6753
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
167,780,457✔
6754
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
167,139,807✔
6755
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,836✔
6756
    } else {
6757
      pInfo->prevTs = tsList[i];
167,135,872✔
6758
    }
6759
    pInfo->isPrevTsSet = true;
167,136,692✔
6760

6761
    int32_t pos = startOffset + numOfElems;
167,139,660✔
6762
    if (colDataIsNull_f(pInputCol, i)) {
167,139,660✔
6763
      // colDataSetNULL(pOutput, i);
6764
      continue;
44,563,686✔
6765
    }
6766

6767
    char*  data = colDataGetData(pInputCol, i);
122,593,604✔
6768
    double v;
6769
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
122,593,604✔
6770

6771
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
122,593,604✔
6772
      pInfo->points[pInfo->pos] = v;
28,476,410✔
6773
      pInfo->sum += v;
28,476,410✔
6774
    } else {
6775
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
94,117,194✔
6776
        pInfo->sum += v;
249,896✔
6777
        pInfo->pointsMeet = true;
249,896✔
6778
      } else {
6779
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
93,867,298✔
6780
      }
6781

6782
      pInfo->points[pInfo->pos] = v;
94,117,194✔
6783
      double result = pInfo->sum / pInfo->numOfPoints;
94,116,735✔
6784
      // check for overflow
6785
      if (isinf(result) || isnan(result)) {
94,116,276✔
UNCOV
6786
        colDataSetNULL(pOutput, pos);
×
6787
      } else {
6788
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
94,116,276✔
6789
        if (TSDB_CODE_SUCCESS != code) {
94,117,194✔
6790
          return code;
×
6791
        }
6792
      }
6793

6794
      // handle selectivity
6795
      if (pCtx->subsidiaries.num > 0) {
94,117,194✔
6796
        code = appendSelectivityValue(pCtx, i, pos);
35,444✔
6797
        if (TSDB_CODE_SUCCESS != code) {
35,444✔
6798
          return code;
×
6799
        }
6800
      }
6801

6802
      numOfElems++;
94,117,194✔
6803
    }
6804

6805
    pInfo->pos++;
122,593,604✔
6806
    if (pInfo->pos == pInfo->numOfPoints) {
122,593,604✔
6807
      pInfo->pos = 0;
17,930,933✔
6808
    }
6809
  }
6810

6811
  pResInfo->numOfRes = numOfElems;
652,540✔
6812
  return TSDB_CODE_SUCCESS;
652,540✔
6813
}
6814

6815
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
4,516,954✔
6816
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,516,954✔
6817
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
4,517,518✔
6818

6819
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
4,517,518✔
6820
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
4,517,977✔
6821

6822
  return pInfo;
4,517,977✔
6823
}
6824

6825
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
857,617✔
6826
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
857,617✔
6827
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
858,583✔
6828
  int32_t      numOfSamples = pVal->datum.i;
856,651✔
6829
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
856,087✔
6830
  return true;
856,651✔
6831
}
6832

6833
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,882,557✔
6834
  if (pResultInfo->initialized) {
1,882,557✔
6835
    return TSDB_CODE_SUCCESS;
×
6836
  }
6837
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,882,557✔
6838
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6839
  }
6840

6841
  taosSeedRand(taosSafeRand());
1,882,557✔
6842

6843
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,882,557✔
6844
  pInfo->samples = pCtx->param[1].param.i;
1,882,557✔
6845
  pInfo->totalPoints = 0;
1,882,557✔
6846
  pInfo->numSampled = 0;
1,882,557✔
6847
  pInfo->colType = pCtx->resDataInfo.type;
1,882,557✔
6848
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,882,557✔
6849
  pInfo->nullTuplePos.pageId = -1;
1,882,557✔
6850
  pInfo->nullTupleSaved = false;
1,882,557✔
6851
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
1,882,557✔
6852
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
1,882,557✔
6853

6854
  return TSDB_CODE_SUCCESS;
1,882,557✔
6855
}
6856

6857
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
81,574,184✔
6858
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
81,574,184✔
6859
}
81,581,975✔
6860

6861
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
130,482,859✔
6862
  pInfo->totalPoints++;
130,482,859✔
6863
  if (pInfo->numSampled < pInfo->samples) {
130,482,400✔
6864
    sampleAssignResult(pInfo, data, pInfo->numSampled);
63,184,597✔
6865
    if (pCtx->subsidiaries.num > 0) {
63,185,056✔
6866
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,084,576✔
6867
      if (code != TSDB_CODE_SUCCESS) {
1,084,576✔
6868
        return code;
×
6869
      }
6870
    }
6871
    pInfo->numSampled++;
63,185,056✔
6872
  } else {
6873
    int32_t j = (int32_t)(taosRand() % (uint64_t)pInfo->totalPoints);
67,299,285✔
6874
    if (j < pInfo->samples) {
67,299,744✔
6875
      sampleAssignResult(pInfo, data, j);
18,404,710✔
6876
      if (pCtx->subsidiaries.num > 0) {
18,404,710✔
6877
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
354,330✔
6878
        if (code != TSDB_CODE_SUCCESS) {
347,877✔
6879
          return code;
×
6880
        }
6881
      }
6882
    }
6883
  }
6884

6885
  return TSDB_CODE_SUCCESS;
130,478,452✔
6886
}
6887

6888
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
2,639,566✔
6889
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,639,566✔
6890
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
2,639,107✔
6891

6892
  SInputColumnInfoData* pInput = &pCtx->input;
2,639,107✔
6893

6894
  SColumnInfoData* pInputCol = pInput->pData[0];
2,639,107✔
6895
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
164,381,929✔
6896
    if (colDataIsNull_s(pInputCol, i)) {
323,480,268✔
6897
      continue;
31,264,370✔
6898
    }
6899

6900
    char*   data = colDataGetData(pInputCol, i);
130,476,406✔
6901
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
130,484,341✔
6902
    if (code != TSDB_CODE_SUCCESS) {
130,478,452✔
6903
      return code;
×
6904
    }
6905
  }
6906

6907
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,639,566✔
6908
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
1,880✔
6909
    if (code != TSDB_CODE_SUCCESS) {
1,880✔
6910
      return code;
×
6911
    }
6912
    pInfo->nullTupleSaved = true;
1,880✔
6913
  }
6914

6915
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
2,639,566✔
6916
  return TSDB_CODE_SUCCESS;
2,639,566✔
6917
}
6918

6919
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,877,847✔
6920
  int32_t              code = TSDB_CODE_SUCCESS;
1,877,847✔
6921
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,877,847✔
6922

6923
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
1,877,847✔
6924
  pEntryInfo->complete = true;
1,878,411✔
6925

6926
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,878,411✔
6927
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,877,847✔
6928
  if (NULL == pCol) {
1,877,847✔
6929
    return TSDB_CODE_OUT_OF_RANGE;
×
6930
  }
6931

6932
  int32_t currentRow = pBlock->info.rows;
1,877,847✔
6933
  if (pInfo->numSampled == 0) {
1,877,847✔
6934
    colDataSetNULL(pCol, currentRow);
236,794✔
6935
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
236,794✔
6936
    return code;
236,794✔
6937
  }
6938
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
64,825,650✔
6939
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
63,185,056✔
6940
    if (TSDB_CODE_SUCCESS != code) {
63,185,620✔
6941
      return code;
×
6942
    }
6943
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
63,185,620✔
6944
    if (TSDB_CODE_SUCCESS != code) {
63,185,056✔
6945
      return code;
×
6946
    }
6947
  }
6948

6949
  return code;
1,641,617✔
6950
}
6951

6952
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6953
#if 0
6954
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
6955
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
6956
  int32_t      numOfPoints = pVal->datum.i;
6957
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
6958
#endif
6959
  return true;
×
6960
}
6961

6962
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
6963
#if 0
6964
  if (!functionSetup(pCtx, pResultInfo)) {
6965
    return false;
6966
  }
6967

6968
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6969
  pInfo->numAdded = 0;
6970
  pInfo->numOfPoints = pCtx->param[1].param.i;
6971
  if (pCtx->numOfParams == 4) {
6972
    pInfo->offset = pCtx->param[2].param.i;
6973
  } else {
6974
    pInfo->offset = 0;
6975
  }
6976
  pInfo->colType = pCtx->resDataInfo.type;
6977
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6978
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
6979
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
6980
    return false;
6981
  }
6982

6983
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
6984
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
6985

6986
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
6987
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6988
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
6989
    pInfo->pItems[i]->isNull = false;
6990
  }
6991
#endif
6992
  return TSDB_CODE_SUCCESS;
×
6993
}
6994

6995
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
6996
#if 0
6997
  pItem->timestamp = ts;
6998
  if (isNull) {
6999
    pItem->isNull = true;
7000
  } else {
7001
    pItem->isNull = false;
7002
    memcpy(pItem->data, data, colBytes);
7003
  }
7004
#endif
7005
}
×
7006

7007
#if 0
7008
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
7009
  STailItem* d1 = *(STailItem**)p1;
7010
  STailItem* d2 = *(STailItem**)p2;
7011
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
7012
}
7013

7014
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
7015
  STailItem** pList = pInfo->pItems;
7016
  if (pInfo->numAdded < pInfo->numOfPoints) {
7017
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
7018
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
7019
    pInfo->numAdded++;
7020
  } else if (pList[0]->timestamp < ts) {
7021
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
7022
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
7023
  }
7024
}
7025
#endif
7026

7027
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
7028
#if 0
7029
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7030
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7031

7032
  SInputColumnInfoData* pInput = &pCtx->input;
7033
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
7034

7035
  SColumnInfoData* pInputCol = pInput->pData[0];
7036
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7037

7038
  int32_t startOffset = pCtx->offset;
7039
  if (pInfo->offset >= pInput->numOfRows) {
7040
    return 0;
7041
  } else {
7042
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
7043
  }
7044
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
7045
    char* data = colDataGetData(pInputCol, i);
7046
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
7047
  }
7048

7049
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
7050

7051
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
7052
    int32_t    pos = startOffset + i;
7053
    STailItem* pItem = pInfo->pItems[i];
7054
    if (pItem->isNull) {
7055
      colDataSetNULL(pOutput, pos);
7056
    } else {
7057
      colDataSetVal(pOutput, pos, pItem->data, false);
7058
    }
7059
  }
7060

7061
  return pInfo->numOfPoints;
7062
#endif
7063
  return 0;
×
7064
}
7065

7066
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
7067
#if 0
7068
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
7069
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
7070
  pEntryInfo->complete = true;
7071

7072
  int32_t type = pCtx->input.pData[0]->info.type;
7073
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
7074

7075
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7076

7077
  // todo assign the tag value and the corresponding row data
7078
  int32_t currentRow = pBlock->info.rows;
7079
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
7080
    STailItem* pItem = pInfo->pItems[i];
7081
    colDataSetVal(pCol, currentRow, pItem->data, false);
7082
    currentRow += 1;
7083
  }
7084

7085
  return pEntryInfo->numOfRes;
7086
#endif
7087
  return 0;
×
7088
}
7089

7090
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
7091
#if 0
7092
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
7093
#endif
7094
  return true;
×
7095
}
7096

7097
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
7098
#if 0
7099
  if (!functionSetup(pCtx, pResInfo)) {
7100
    return false;
7101
  }
7102

7103
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7104
  pInfo->numOfPoints = 0;
7105
  pInfo->colType = pCtx->resDataInfo.type;
7106
  pInfo->colBytes = pCtx->resDataInfo.bytes;
7107
  if (pInfo->pHash != NULL) {
7108
    taosHashClear(pInfo->pHash);
7109
  } else {
7110
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
7111
  }
7112
#endif
7113
  return TSDB_CODE_SUCCESS;
×
7114
}
7115

7116
#if 0
7117
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
7118
  // handle null elements
7119
  if (isNull == true) {
7120
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
7121
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
7122
    if (pInfo->hasNull == false && pItem->isNull == false) {
7123
      pItem->timestamp = ts;
7124
      pItem->isNull = true;
7125
      pInfo->numOfPoints++;
7126
      pInfo->hasNull = true;
7127
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
7128
      pItem->timestamp = ts;
7129
    }
7130
    return;
7131
  }
7132

7133
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
7134
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
7135
  if (pHashItem == NULL) {
7136
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
7137
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
7138
    pItem->timestamp = ts;
7139
    memcpy(pItem->data, data, pInfo->colBytes);
7140

7141
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
7142
    pInfo->numOfPoints++;
7143
  } else if (pHashItem->timestamp > ts) {
7144
    pHashItem->timestamp = ts;
7145
  }
7146
}
7147
#endif
7148

7149
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
7150
#if 0
7151
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7152
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7153

7154
  SInputColumnInfoData* pInput = &pCtx->input;
7155
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
7156

7157
  SColumnInfoData* pInputCol = pInput->pData[0];
7158
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
7159
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7160

7161
  int32_t startOffset = pCtx->offset;
7162
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
7163
    char* data = colDataGetData(pInputCol, i);
7164
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
7165

7166
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
7167
      taosHashCleanup(pInfo->pHash);
7168
      return 0;
7169
    }
7170
  }
7171

7172
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
7173
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
7174
    if (pItem->isNull == true) {
7175
      colDataSetNULL(pOutput, i);
7176
    } else {
7177
      colDataSetVal(pOutput, i, pItem->data, false);
7178
    }
7179
    if (pTsOutput != NULL) {
7180
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
7181
    }
7182
  }
7183

7184
  return pInfo->numOfPoints;
7185
#endif
7186
  return 0;
×
7187
}
7188

7189
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
826,494✔
7190
  pEnv->calcMemSize = sizeof(SModeInfo);
826,494✔
7191
  return true;
826,904✔
7192
}
7193

7194
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,008,968✔
7195
  if (pResInfo->initialized) {
1,008,968✔
7196
    return TSDB_CODE_SUCCESS;
×
7197
  }
7198
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
1,008,968✔
7199
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7200
  }
7201

7202
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,008,968✔
7203
  pInfo->colType = pCtx->resDataInfo.type;
1,008,968✔
7204
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,008,968✔
7205
  if (pInfo->pHash != NULL) {
1,008,968✔
7206
    taosHashClear(pInfo->pHash);
×
7207
  } else {
7208
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
1,008,566✔
7209
    if (NULL == pInfo->pHash) {
1,008,968✔
7210
      return terrno;
×
7211
    }
7212
  }
7213
  pInfo->nullTupleSaved = false;
1,008,566✔
7214
  pInfo->nullTuplePos.pageId = -1;
1,008,566✔
7215

7216
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
1,008,968✔
7217
  if (NULL == pInfo->buf) {
1,008,968✔
7218
    taosHashCleanup(pInfo->pHash);
×
7219
    pInfo->pHash = NULL;
×
7220
    return terrno;
×
7221
  }
7222
  pCtx->needCleanup = true;
1,008,566✔
7223
  return TSDB_CODE_SUCCESS;
1,008,566✔
7224
}
7225

7226
static void modeFunctionCleanup(SModeInfo* pInfo) {
1,759,641✔
7227
  taosHashCleanup(pInfo->pHash);
1,759,641✔
7228
  pInfo->pHash = NULL;
1,760,043✔
7229
  taosMemoryFreeClear(pInfo->buf);
1,760,043✔
7230
}
1,760,043✔
7231

7232
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
827,468✔
7233
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
827,468✔
7234
    return;
75,418✔
7235
  }
7236
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
752,050✔
7237
}
7238

7239
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
170,859,843✔
7240
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
170,859,843✔
7241
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
4,033,789✔
7242
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
294,030✔
7243
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
3,742,141✔
7244
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
×
7245
    } else {
7246
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
3,742,141✔
7247
    }
7248
  } else {
7249
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
166,829,150✔
7250
  }
7251

7252
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
170,872,401✔
7253
}
7254

7255
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
308,091,628✔
7256
  int32_t code = TSDB_CODE_SUCCESS;
308,091,628✔
7257
  int32_t hashKeyBytes;
7258
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
308,091,628✔
7259
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
4,199,299✔
7260
  } else {
7261
    hashKeyBytes = pInfo->colBytes;
303,893,502✔
7262
  }
7263

7264
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
308,093,320✔
7265
  if (pHashItem == NULL) {
308,081,002✔
7266
    int32_t   size = sizeof(SModeItem);
170,859,279✔
7267
    SModeItem item = {0};
170,859,279✔
7268

7269
    item.count += 1;
170,859,279✔
7270
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
170,859,279✔
7271
    if (code != TSDB_CODE_SUCCESS) {
170,855,655✔
7272
      return code;
×
7273
    }
7274

7275
    if (pCtx->subsidiaries.num > 0) {
170,855,655✔
7276
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
276,046✔
7277
      if (code != TSDB_CODE_SUCCESS) {
276,046✔
7278
        return code;
×
7279
      }
7280
    }
7281

7282
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
170,855,655✔
7283
    if (code != TSDB_CODE_SUCCESS) {
170,868,375✔
7284
      return code;
×
7285
    }
7286
  } else {
7287
    pHashItem->count += 1;
137,221,723✔
7288
    if (pCtx->subsidiaries.num > 0) {
137,221,723✔
7289
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,495,230✔
7290
      if (code != TSDB_CODE_SUCCESS) {
3,495,230✔
7291
        return code;
×
7292
      }
7293
    }
7294
  }
7295

7296
  return code;
308,090,098✔
7297
}
7298

7299
int32_t modeFunction(SqlFunctionCtx* pCtx) {
2,058,100✔
7300
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,058,100✔
7301
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,058,100✔
7302

7303
  SInputColumnInfoData* pInput = &pCtx->input;
2,058,100✔
7304

7305
  SColumnInfoData* pInputCol = pInput->pData[0];
2,058,100✔
7306
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,057,698✔
7307

7308
  int32_t numOfElems = 0;
2,058,100✔
7309
  int32_t startOffset = pCtx->offset;
2,058,100✔
7310
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
335,464,410✔
7311
    if (colDataIsNull_s(pInputCol, i)) {
666,835,984✔
7312
      continue;
25,336,324✔
7313
    }
7314
    numOfElems++;
308,090,824✔
7315

7316
    char*   data = colDataGetData(pInputCol, i);
308,090,824✔
7317
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
308,092,756✔
7318
    if (code != TSDB_CODE_SUCCESS) {
308,090,098✔
7319
      modeFunctionCleanup(pInfo);
19,710✔
7320
      return code;
×
7321
    }
7322
  }
7323

7324
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,058,100✔
7325
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
4,820✔
7326
    if (code != TSDB_CODE_SUCCESS) {
4,820✔
7327
      modeFunctionCleanup(pInfo);
×
7328
      return code;
×
7329
    }
7330
    pInfo->nullTupleSaved = true;
4,820✔
7331
  }
7332

7333
  SET_VAL(pResInfo, numOfElems, 1);
2,058,100✔
7334

7335
  return TSDB_CODE_SUCCESS;
2,058,100✔
7336
}
7337

7338
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,007,591✔
7339
  int32_t              code = TSDB_CODE_SUCCESS;
1,007,591✔
7340
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,007,591✔
7341
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,007,591✔
7342
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
1,007,591✔
7343
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,007,591✔
7344
  int32_t              currentRow = pBlock->info.rows;
1,007,591✔
7345
  if (NULL == pCol) {
1,007,591✔
7346
    modeFunctionCleanup(pInfo);
×
7347
    return TSDB_CODE_OUT_OF_RANGE;
×
7348
  }
7349

7350
  STuplePos resDataPos, resTuplePos;
1,007,591✔
7351
  int32_t   maxCount = 0;
1,007,591✔
7352

7353
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
1,007,591✔
7354
  while (pIter != NULL) {
171,881,600✔
7355
    SModeItem* pItem = (SModeItem*)pIter;
170,874,009✔
7356
    if (pItem->count >= maxCount) {
170,874,009✔
7357
      maxCount = pItem->count;
165,986,771✔
7358
      resDataPos = pItem->dataPos;
165,986,771✔
7359
      resTuplePos = pItem->tuplePos;
165,986,771✔
7360
    }
7361

7362
    pIter = taosHashIterate(pInfo->pHash, pIter);
170,874,009✔
7363
  }
7364

7365
  if (maxCount != 0) {
1,007,591✔
7366
    char* pData = NULL;
863,191✔
7367
    code = loadTupleData(pCtx, &resDataPos, &pData);
863,191✔
7368
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
863,191✔
7369
      code = terrno = TSDB_CODE_NOT_FOUND;
×
7370
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
7371
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
7372
      modeFunctionCleanup(pInfo);
×
7373
      return code;
×
7374
    }
7375

7376
    code = colDataSetVal(pCol, currentRow, pData, false);
863,191✔
7377
    if (TSDB_CODE_SUCCESS != code) {
863,191✔
7378
      modeFunctionCleanup(pInfo);
×
7379
      return code;
×
7380
    }
7381
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
863,191✔
7382
  } else {
7383
    colDataSetNULL(pCol, currentRow);
144,400✔
7384
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
144,400✔
7385
  }
7386

7387
  modeFunctionCleanup(pInfo);
1,007,591✔
7388

7389
  return code;
1,007,591✔
7390
}
7391

7392
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
352,568✔
7393
  pEnv->calcMemSize = sizeof(STwaInfo);
352,568✔
7394
  return true;
353,038✔
7395
}
7396

7397
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,976,689✔
7398
  if (pResultInfo->initialized) {
7,976,689✔
7399
    return TSDB_CODE_SUCCESS;
×
7400
  }
7401
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,977,159✔
7402
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7403
  }
7404

7405
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,977,159✔
7406
  pInfo->numOfElems = 0;
7,977,159✔
7407
  pInfo->p.key = INT64_MIN;
7,977,159✔
7408
  pInfo->win = TSWINDOW_INITIALIZER;
7,977,159✔
7409
  return TSDB_CODE_SUCCESS;
7,977,159✔
7410
}
7411

7412
static double twa_get_area(SPoint1 s, SPoint1 e) {
202,911,155✔
7413
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
202,911,155✔
7414
    return 0;
×
7415
  }
7416

7417
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
202,911,749✔
7418
    return (s.val + e.val) * (e.key - s.key) / 2;
184,816,490✔
7419
  }
7420

7421
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
18,095,259✔
7422
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
18,095,259✔
7423
  return val;
18,095,259✔
7424
}
7425

7426
int32_t twaFunction(SqlFunctionCtx* pCtx) {
8,061,247✔
7427
  int32_t               code = TSDB_CODE_SUCCESS;
8,061,247✔
7428
  SInputColumnInfoData* pInput = &pCtx->input;
8,061,247✔
7429
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,062,228✔
7430

7431
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,062,228✔
7432
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,062,228✔
7433
  SPoint1*             last = &pInfo->p;
8,062,228✔
7434

7435
  if (IS_NULL_TYPE(pInputCol->info.type)) {
8,061,758✔
7436
    pInfo->numOfElems = 0;
×
7437
    goto _twa_over;
×
7438
  }
7439

7440
  funcInputUpdate(pCtx);
8,061,758✔
7441
  SFuncInputRow row = {0};
8,061,717✔
7442
  bool          result = false;
8,061,717✔
7443
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
8,061,717✔
7444
    while (1) {
7445
      code = funcInputGetNextRow(pCtx, &row, &result);
5,620,137✔
7446
      if (TSDB_CODE_SUCCESS != code) {
5,620,137✔
7447
        return code;
×
7448
      }
7449
      if (!result) {
5,620,137✔
7450
        break;
816✔
7451
      }
7452
      if (row.isDataNull) {
5,619,321✔
7453
        continue;
816✔
7454
      }
7455

7456
      last->key = row.ts;
5,618,505✔
7457

7458
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
5,618,505✔
7459

7460
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
5,618,505✔
7461
      pInfo->win.skey = pCtx->start.key;
5,618,505✔
7462
      pInfo->numOfElems++;
5,618,505✔
7463
      break;
5,618,505✔
7464
    }
7465
  } else if (pInfo->p.key == INT64_MIN) {
2,442,396✔
7466
    while (1) {
7467
      code = funcInputGetNextRow(pCtx, &row, &result);
12,914,144✔
7468
      if (TSDB_CODE_SUCCESS != code) {
12,914,144✔
7469
        return code;
×
7470
      }
7471
      if (!result) {
12,914,144✔
7472
        break;
803,477✔
7473
      }
7474
      if (row.isDataNull) {
12,110,667✔
7475
        continue;
10,523,528✔
7476
      }
7477

7478
      last->key = row.ts;
1,587,139✔
7479

7480
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
1,586,628✔
7481

7482
      pInfo->win.skey = last->key;
1,587,098✔
7483
      pInfo->numOfElems++;
1,587,098✔
7484
      break;
1,587,098✔
7485
    }
7486
  }
7487

7488
  SPoint1 st = {0};
8,061,717✔
7489

7490
  // calculate the value of
7491
  while (1) {
7492
    code = funcInputGetNextRow(pCtx, &row, &result);
199,769,866✔
7493
    if (TSDB_CODE_SUCCESS != code) {
199,772,686✔
7494
      return code;
×
7495
    }
7496
    if (!result) {
199,772,686✔
7497
      break;
8,061,717✔
7498
    }
7499
    if (row.isDataNull) {
191,710,969✔
7500
      continue;
59,220✔
7501
    }
7502
    pInfo->numOfElems++;
191,651,749✔
7503
    switch (pInputCol->info.type) {
191,651,749✔
7504
      case TSDB_DATA_TYPE_TINYINT: {
14,736,457✔
7505
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
14,736,457✔
7506
        break;
14,736,457✔
7507
      }
7508
      case TSDB_DATA_TYPE_SMALLINT: {
15,027,857✔
7509
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
15,027,857✔
7510
        break;
15,027,387✔
7511
      }
7512
      case TSDB_DATA_TYPE_INT: {
82,075,104✔
7513
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
82,075,104✔
7514
        break;
82,075,104✔
7515
      }
7516
      case TSDB_DATA_TYPE_BIGINT: {
14,958,389✔
7517
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
14,958,389✔
7518
        break;
14,958,389✔
7519
      }
7520
      case TSDB_DATA_TYPE_FLOAT: {
13,156,727✔
7521
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
13,156,727✔
7522
        break;
13,156,727✔
7523
      }
7524
      case TSDB_DATA_TYPE_DOUBLE: {
14,284,761✔
7525
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
14,284,761✔
7526
        break;
14,284,761✔
7527
      }
7528
      case TSDB_DATA_TYPE_UTINYINT: {
9,562,509✔
7529
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
9,562,509✔
7530
        break;
9,562,509✔
7531
      }
7532
      case TSDB_DATA_TYPE_USMALLINT: {
9,554,049✔
7533
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
9,554,049✔
7534
        break;
9,554,049✔
7535
      }
7536
      case TSDB_DATA_TYPE_UINT: {
9,633,693✔
7537
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
9,633,693✔
7538
        break;
9,630,403✔
7539
      }
7540
      case TSDB_DATA_TYPE_UBIGINT: {
8,660,323✔
7541
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
8,660,323✔
7542
        break;
8,660,323✔
7543
      }
7544
      default: {
×
7545
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7546
      }
7547
    }
7548
    if (pInfo->p.key == st.key) {
191,646,109✔
7549
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7550
    }
7551

7552
    pInfo->dOutput += twa_get_area(pInfo->p, st);
191,647,049✔
7553
    pInfo->p = st;
191,651,749✔
7554
  }
7555

7556
  // the last interpolated time window value
7557
  if (pCtx->end.key != INT64_MIN) {
8,061,717✔
7558
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5,631,501✔
7559
    pInfo->p = pCtx->end;
5,631,501✔
7560
    pInfo->numOfElems += 1;
5,631,501✔
7561
  }
7562

7563
  pInfo->win.ekey = pInfo->p.key;
8,061,717✔
7564

7565
_twa_over:
8,062,228✔
7566
  SET_VAL(pResInfo, 1, 1);
8,062,228✔
7567
  return TSDB_CODE_SUCCESS;
8,062,228✔
7568
}
7569

7570
/*
7571
 * To copy the input to interResBuf to avoid the input buffer space be over writen
7572
 * by next input data. The TWA function only applies to each table, so no merge procedure
7573
 * is required, we simply copy to the resut ot interResBuffer.
7574
 */
7575
// void twa_function_copy(SQLFunctionCtx *pCtx) {
7576
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
7577
//
7578
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
7579
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
7580
// }
7581

7582
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,976,231✔
7583
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,976,231✔
7584

7585
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,976,231✔
7586
  if (pInfo->numOfElems == 0) {
7,976,231✔
7587
    pResInfo->numOfRes = 0;
769,812✔
7588
  } else {
7589
    if (pInfo->win.ekey == pInfo->win.skey) {
7,206,419✔
7590
      pInfo->dTwaRes = pInfo->p.val;
658,363✔
7591
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
6,548,056✔
7592
      pInfo->dTwaRes = 0;
816✔
7593
    } else {
7594
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
6,547,240✔
7595
    }
7596

7597
    pResInfo->numOfRes = 1;
7,206,419✔
7598
  }
7599

7600
  return functionFinalize(pCtx, pBlock);
7,976,231✔
7601
}
7602

7603
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3,105✔
7604
  if (pResultInfo->initialized) {
3,105✔
7605
    return TSDB_CODE_SUCCESS;
×
7606
  }
7607
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
3,105✔
7608
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7609
  }
7610

7611
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,105✔
7612
  pInfo->minRows = INT32_MAX;
3,105✔
7613
  return TSDB_CODE_SUCCESS;
3,105✔
7614
}
7615

7616
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
5,924✔
7617
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
5,924✔
7618

7619
  SInputColumnInfoData* pInput = &pCtx->input;
5,924✔
7620
  SColumnInfoData*      pInputCol = pInput->pData[0];
5,924✔
7621
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
5,924✔
7622
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,924✔
7623

7624
  STableBlockDistInfo p1 = {0};
5,924✔
7625
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
5,924✔
7626
    qError("failed to deserialize block dist info");
×
7627
    return TSDB_CODE_FAILED;
×
7628
  }
7629

7630
  pDistInfo->numOfBlocks += p1.numOfBlocks;
5,924✔
7631
  pDistInfo->numOfTables += p1.numOfTables;
5,924✔
7632
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
5,924✔
7633
  pDistInfo->numOfSttRows += p1.numOfSttRows;
5,924✔
7634
  pDistInfo->totalSize += p1.totalSize;
5,924✔
7635
  pDistInfo->totalRows += p1.totalRows;
5,924✔
7636
  pDistInfo->numOfFiles += p1.numOfFiles;
5,924✔
7637

7638
  pDistInfo->defMinRows = p1.defMinRows;
5,924✔
7639
  pDistInfo->defMaxRows = p1.defMaxRows;
5,924✔
7640
  pDistInfo->rowSize = p1.rowSize;
5,924✔
7641

7642
  if (pDistInfo->minRows > p1.minRows) {
5,924✔
7643
    pDistInfo->minRows = p1.minRows;
1,369✔
7644
  }
7645
  if (pDistInfo->maxRows < p1.maxRows) {
5,924✔
7646
    pDistInfo->maxRows = p1.maxRows;
1,369✔
7647
  }
7648
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
5,924✔
7649
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
124,404✔
7650
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
118,480✔
7651
  }
7652
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHistoFixed); ++i) {
53,316✔
7653
    pDistInfo->blockRowsHistoFixed[i] += p1.blockRowsHistoFixed[i];
47,392✔
7654
  }
7655

7656
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
5,924✔
7657
  return TSDB_CODE_SUCCESS;
5,924✔
7658
}
7659

7660
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
11,647✔
7661
  SEncoder encoder = {0};
11,647✔
7662
  int32_t  code = 0;
11,848✔
7663
  int32_t  lino;
7664
  int32_t  tlen;
7665
  tEncoderInit(&encoder, buf, bufLen);
11,848✔
7666

7667
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
11,848✔
7668
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
23,696✔
7669

7670
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
23,495✔
7671
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
23,294✔
7672
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
23,468✔
7673

7674
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
23,441✔
7675
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
23,468✔
7676
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
23,669✔
7677
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
23,642✔
7678
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
23,669✔
7679
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
23,669✔
7680
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
23,669✔
7681
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
23,696✔
7682
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
23,495✔
7683

7684
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
247,827✔
7685
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
472,186✔
7686
  }
7687

7688
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHistoFixed); ++i) {
106,416✔
7689
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHistoFixed[i]));
189,217✔
7690
  }
7691

7692
  tEndEncode(&encoder);
11,794✔
7693

7694
_exit:
11,848✔
7695
  if (code) {
11,848✔
7696
    tlen = code;
×
7697
  } else {
7698
    tlen = encoder.pos;
11,848✔
7699
  }
7700
  tEncoderClear(&encoder);
11,848✔
7701
  return tlen;
11,848✔
7702
}
7703

7704
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
5,924✔
7705
  SDecoder decoder = {0};
5,924✔
7706
  int32_t  code = 0;
5,924✔
7707
  int32_t  lino;
7708
  tDecoderInit(&decoder, buf, bufLen);
5,924✔
7709

7710
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
5,924✔
7711
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
11,848✔
7712

7713
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
11,848✔
7714
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
11,848✔
7715
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
11,848✔
7716

7717
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
11,848✔
7718
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
11,848✔
7719
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
11,848✔
7720
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
11,848✔
7721
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
11,848✔
7722
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
11,848✔
7723
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
11,848✔
7724
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
11,848✔
7725
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
11,848✔
7726

7727
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
124,404✔
7728
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
236,960✔
7729
  }
7730

7731
  if (!tDecodeIsEnd(&decoder)) {
5,924✔
7732
    for (int32_t i = 0; i < tListLen(pInfo->blockRowsHistoFixed); ++i) {
53,316✔
7733
      TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHistoFixed[i]));
94,784✔
7734
    }
7735
  }
7736

7737
_exit:
5,924✔
7738
  tDecoderClear(&decoder);
5,924✔
7739
  return code;
5,924✔
7740
}
7741

7742
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,105✔
7743
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,105✔
7744
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
3,105✔
7745

7746
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
3,105✔
7747
  if (NULL == pColInfo) {
3,105✔
7748
    return TSDB_CODE_OUT_OF_RANGE;
×
7749
  }
7750

7751
  if (pData->totalRows == 0) {
3,105✔
7752
    pData->minRows = 0;
1,736✔
7753
  }
7754

7755
  int32_t row = 0;
3,105✔
7756
  char    st[256] = {0};
3,105✔
7757
  double  averageSize = 0;
3,105✔
7758
  if (pData->numOfBlocks != 0) {
3,105✔
7759
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1,369✔
7760
  }
7761
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
3,105✔
7762
  double   compRatio = 0;
3,105✔
7763
  if (totalRawSize != 0) {
3,105✔
7764
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1,369✔
7765
  }
7766

7767
  int32_t len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,105✔
7768
                         "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
7769
                         pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
3,105✔
7770

7771
  varDataSetLen(st, len);
3,105✔
7772
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
3,105✔
7773
  if (TSDB_CODE_SUCCESS != code) {
3,105✔
7774
    return code;
×
7775
  }
7776

7777
  int64_t avgRows = 0;
3,105✔
7778
  if (pData->numOfBlocks > 0) {
3,105✔
7779
    avgRows = pData->totalRows / pData->numOfBlocks;
1,369✔
7780
  }
7781

7782
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,105✔
7783
                 "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
7784
                 pData->minRows, pData->maxRows, avgRows);
7785
  varDataSetLen(st, len);
3,105✔
7786
  code = colDataSetVal(pColInfo, row++, st, false);
3,105✔
7787
  if (TSDB_CODE_SUCCESS != code) {
3,105✔
7788
    return code;
×
7789
  }
7790

7791
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
3,105✔
7792
                 pData->numOfInmemRows, pData->numOfSttRows);
7793
  varDataSetLen(st, len);
3,105✔
7794
  code = colDataSetVal(pColInfo, row++, st, false);
3,105✔
7795
  if (TSDB_CODE_SUCCESS != code) {
3,105✔
7796
    return code;
×
7797
  }
7798

7799
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
6,210✔
7800
                 "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
3,105✔
7801
                 pData->numOfVgroups);
7802

7803
  varDataSetLen(st, len);
3,105✔
7804
  code = colDataSetVal(pColInfo, row++, st, false);
3,105✔
7805
  if (TSDB_CODE_SUCCESS != code) {
3,105✔
7806
    return code;
×
7807
  }
7808

7809
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,105✔
7810
                 "--------------------------------------------------------------------------------");
7811
  varDataSetLen(st, len);
3,105✔
7812
  code = colDataSetVal(pColInfo, row++, st, false);
3,105✔
7813
  if (TSDB_CODE_SUCCESS != code) {
3,105✔
7814
    return code;
×
7815
  }
7816

7817
  int32_t maxVal = 0;
3,105✔
7818
  int32_t minVal = INT32_MAX;
3,105✔
7819
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
65,205✔
7820
    if (maxVal < pData->blockRowsHisto[i]) {
62,100✔
7821
      maxVal = pData->blockRowsHisto[i];
1,963✔
7822
    }
7823

7824
    if (minVal > pData->blockRowsHisto[i]) {
62,100✔
7825
      minVal = pData->blockRowsHisto[i];
3,880✔
7826
    }
7827
  }
7828

7829
  // maximum number of step is 80
7830
  double factor = pData->numOfBlocks / 80.0;
3,105✔
7831

7832
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
3,105✔
7833
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
3,105✔
7834

7835
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
65,205✔
7836
    len =
7837
        snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
62,100✔
7838

7839
    int32_t num = 0;
62,100✔
7840
    if (pData->blockRowsHisto[i] > 0) {
62,100✔
7841
      num = (pData->blockRowsHisto[i]) / factor;
3,151✔
7842
    }
7843

7844
    for (int32_t j = 0; j < num; ++j) {
171,026✔
7845
      int32_t x = snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
108,926✔
7846
      len += x;
108,926✔
7847
    }
7848

7849
    if (pData->blockRowsHisto[i] > 0) {
62,100✔
7850
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
3,151✔
7851
      len += snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
3,151✔
7852
                      pData->blockRowsHisto[i], v, '%');
3,151✔
7853
    }
7854

7855
    varDataSetLen(st, len);
62,100✔
7856
    code = colDataSetVal(pColInfo, row++, st, false);
62,100✔
7857
    if (TSDB_CODE_SUCCESS != code) {
62,100✔
7858
      return code;
×
7859
    }
7860
  }
7861

7862
  return TSDB_CODE_SUCCESS;
3,105✔
7863
}
7864
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
395✔
7865
  if (pResultInfo->initialized) {
395✔
7866
    return TSDB_CODE_SUCCESS;
×
7867
  }
7868
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
395✔
7869
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7870
  }
7871

7872
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
395✔
7873
  return TSDB_CODE_SUCCESS;
395✔
7874
}
7875
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
790✔
7876
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
790✔
7877

7878
  SInputColumnInfoData* pInput = &pCtx->input;
790✔
7879
  SColumnInfoData*      pInputCol = pInput->pData[0];
790✔
7880
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
790✔
7881
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
790✔
7882

7883
  SDBBlockUsageInfo p1 = {0};
790✔
7884
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
790✔
7885
    qError("failed to deserialize block dist info");
×
7886
    return TSDB_CODE_FAILED;
×
7887
  }
7888

7889
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
790✔
7890
  pDistInfo->walInDiskSize += p1.walInDiskSize;
790✔
7891
  pDistInfo->rawDataSize += p1.rawDataSize;
790✔
7892
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
790✔
7893
  return TSDB_CODE_SUCCESS;
790✔
7894
}
7895

7896
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
1,580✔
7897
  SEncoder encoder = {0};
1,580✔
7898
  int32_t  code = 0;
1,580✔
7899
  int32_t  lino;
7900
  int32_t  tlen;
7901
  tEncoderInit(&encoder, buf, bufLen);
1,580✔
7902

7903
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
1,580✔
7904

7905
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
3,160✔
7906
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
3,160✔
7907
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
3,160✔
7908

7909
  tEndEncode(&encoder);
1,580✔
7910

7911
_exit:
1,580✔
7912
  if (code) {
1,580✔
7913
    tlen = code;
×
7914
  } else {
7915
    tlen = encoder.pos;
1,580✔
7916
  }
7917
  tEncoderClear(&encoder);
1,580✔
7918
  return tlen;
1,580✔
7919
}
7920
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
790✔
7921
  SDecoder decoder = {0};
790✔
7922
  int32_t  code = 0;
790✔
7923
  int32_t  lino;
7924
  tDecoderInit(&decoder, buf, bufLen);
790✔
7925

7926
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
790✔
7927
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
1,580✔
7928
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
1,580✔
7929
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
1,580✔
7930

7931
_exit:
790✔
7932
  tDecoderClear(&decoder);
790✔
7933
  return code;
790✔
7934
}
7935
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
395✔
7936
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
395✔
7937
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
395✔
7938

7939
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
395✔
7940
  if (NULL == pColInfo) {
395✔
7941
    return TSDB_CODE_OUT_OF_RANGE;
×
7942
  }
7943
  int32_t len = 0;
395✔
7944
  int32_t row = 0;
395✔
7945
  char    st[256] = {0};
395✔
7946

7947
  uint64_t totalDiskSize = pData->dataInDiskSize;
395✔
7948
  uint64_t rawDataSize = pData->rawDataSize;
395✔
7949
  double   compressRatio = 0;
395✔
7950
  if (rawDataSize != 0) {
395✔
7951
    compressRatio = totalDiskSize * 100 / (double)rawDataSize;
203✔
7952
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[%.2f%]", compressRatio);
203✔
7953
  } else {
7954
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[NULL]");
192✔
7955
  }
7956

7957
  varDataSetLen(st, len);
395✔
7958
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
395✔
7959
  if (TSDB_CODE_SUCCESS != code) {
395✔
7960
    return code;
×
7961
  }
7962

7963
  len =
7964
      snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
395✔
7965
  varDataSetLen(st, len);
395✔
7966
  code = colDataSetVal(pColInfo, row++, st, false);
395✔
7967
  if (TSDB_CODE_SUCCESS != code) {
395✔
7968
    return code;
×
7969
  }
7970
  return code;
395✔
7971
}
7972

7973
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
230,382✔
7974
  pEnv->calcMemSize = sizeof(SDerivInfo);
230,382✔
7975
  return true;
230,382✔
7976
}
7977

7978
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
906,728✔
7979
  if (pResInfo->initialized) {
906,728✔
7980
    return TSDB_CODE_SUCCESS;
573,151✔
7981
  }
7982
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
333,577✔
7983
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7984
  }
7985

7986
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
333,577✔
7987

7988
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
333,577✔
7989
  pDerivInfo->prevTs = -1;
333,577✔
7990
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
333,577✔
7991
  pDerivInfo->valueSet = false;
333,577✔
7992
  return TSDB_CODE_SUCCESS;
333,577✔
7993
}
7994

7995
int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
606,298✔
7996

7997
static int32_t DoDerivativeFunction(SqlFunctionCtx* pCtx) {
606,298✔
7998
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
606,298✔
7999
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
606,298✔
8000

8001
  SInputColumnInfoData* pInput = &pCtx->input;
606,298✔
8002
  SColumnInfoData*      pInputCol = pInput->pData[0];
606,298✔
8003

8004
  int32_t          numOfElems = 0;
606,298✔
8005
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
606,298✔
8006
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
606,298✔
8007
  int32_t          code = TSDB_CODE_SUCCESS;
606,298✔
8008

8009
  funcInputUpdate(pCtx);
606,298✔
8010

8011
  double v = 0;
606,298✔
8012
  if (pCtx->order == TSDB_ORDER_ASC) {
606,298✔
8013
    SFuncInputRow row = {0};
522,426✔
8014
    bool          result = false;
522,426✔
8015
    while (1) {
134,907,322✔
8016
      code = funcInputGetNextRow(pCtx, &row, &result);
135,429,748✔
8017
      if (TSDB_CODE_SUCCESS != code) {
135,429,748✔
8018
        return code;
×
8019
      }
8020
      if (!result) {
135,429,748✔
8021
        break;
522,426✔
8022
      }
8023
      if (row.isDataNull) {
134,907,322✔
8024
        continue;
3,658,172✔
8025
      }
8026

8027
      char* d = row.pData;
131,249,150✔
8028
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
131,249,150✔
8029

8030
      int32_t pos = pCtx->offset + numOfElems;
131,249,150✔
8031
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
131,249,150✔
8032
        pDerivInfo->valueSet = true;
238,391✔
8033
      } else {
8034
        if (row.ts == pDerivInfo->prevTs) {
131,010,759✔
8035
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8036
        }
8037
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
131,010,759✔
8038
        if (pDerivInfo->ignoreNegative && r < 0) {
131,010,759✔
8039
        } else {
8040
          if (isinf(r) || isnan(r)) {
119,702,175✔
8041
            colDataSetNULL(pOutput, pos);
×
8042
          } else {
8043
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
119,702,175✔
8044
            if (code != TSDB_CODE_SUCCESS) {
119,702,175✔
8045
              return code;
×
8046
            }
8047
          }
8048

8049
          if (pTsOutput != NULL) {
119,702,175✔
8050
            colDataSetInt64(pTsOutput, pos, &row.ts);
3,287,768✔
8051
          }
8052

8053
          // handle selectivity
8054
          if (pCtx->subsidiaries.num > 0) {
119,702,175✔
8055
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
2,039,140✔
8056
            if (code != TSDB_CODE_SUCCESS) {
2,039,140✔
8057
              return code;
×
8058
            }
8059
          }
8060

8061
          numOfElems++;
119,702,175✔
8062
        }
8063
      }
8064

8065
      pDerivInfo->prevValue = v;
131,249,150✔
8066
      pDerivInfo->prevTs = row.ts;
131,249,150✔
8067
    }
8068
  } else {
8069
    SFuncInputRow row = {0};
83,872✔
8070
    bool          result = false;
83,872✔
8071
    while (1) {
30,417,684✔
8072
      code = funcInputGetNextRow(pCtx, &row, &result);
30,501,556✔
8073
      if (TSDB_CODE_SUCCESS != code) {
30,501,556✔
8074
        return code;
×
8075
      }
8076
      if (!result) {
30,501,556✔
8077
        break;
83,872✔
8078
      }
8079
      if (row.isDataNull) {
30,417,684✔
8080
        continue;
1,080✔
8081
      }
8082

8083
      char* d = row.pData;
30,416,604✔
8084
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
30,416,604✔
8085

8086
      int32_t pos = pCtx->offset + numOfElems;
30,416,604✔
8087
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
30,416,604✔
8088
        pDerivInfo->valueSet = true;
55,492✔
8089
      } else {
8090
        if (row.ts == pDerivInfo->prevTs) {
30,361,112✔
8091
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8092
        }
8093
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
30,361,112✔
8094
        if (pDerivInfo->ignoreNegative && r < 0) {
30,361,112✔
8095
        } else {
8096
          if (isinf(r) || isnan(r)) {
30,361,112✔
8097
            colDataSetNULL(pOutput, pos);
×
8098
          } else {
8099
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
30,361,112✔
8100
            if (code != TSDB_CODE_SUCCESS) {
30,361,112✔
8101
              return code;
×
8102
            }
8103
          }
8104

8105
          if (pTsOutput != NULL) {
30,361,112✔
8106
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
30,356,736✔
8107
          }
8108

8109
          // handle selectivity
8110
          if (pCtx->subsidiaries.num > 0) {
30,361,112✔
8111
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
×
8112
            if (code != TSDB_CODE_SUCCESS) {
×
8113
              return code;
×
8114
            }
8115
          }
8116
          numOfElems++;
30,361,112✔
8117
        }
8118
      }
8119

8120
      pDerivInfo->prevValue = v;
30,416,604✔
8121
      pDerivInfo->prevTs = row.ts;
30,416,604✔
8122
    }
8123
  }
8124

8125
  pResInfo->numOfRes = numOfElems;
606,298✔
8126

8127
  return TSDB_CODE_SUCCESS;
606,298✔
8128
}
8129

8130
int32_t derivativeFunctionByRow(SArray* pCtxArray) {
606,298✔
8131
  for (int32_t i = 0; i < taosArrayGetSize(pCtxArray); ++i) {
1,212,596✔
8132
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
606,298✔
8133
    int32_t         code = DoDerivativeFunction(pCtx);
606,298✔
8134
    if (code != TSDB_CODE_SUCCESS) {
606,298✔
8135
      return code;
×
8136
    }
8137
  }
8138
  return TSDB_CODE_SUCCESS;
606,298✔
8139
}
8140

8141
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
270,685✔
8142

8143
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
226,065✔
8144
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
226,065✔
8145
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
226,065✔
8146
  return true;
225,501✔
8147
}
8148

8149
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,069,790✔
8150
  if (pResInfo->initialized) {
2,069,790✔
8151
    return TSDB_CODE_SUCCESS;
×
8152
  }
8153
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,069,790✔
8154
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
8155
  }
8156

8157
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,069,790✔
8158

8159
  pInfo->firstKey = INT64_MIN;
2,069,790✔
8160
  pInfo->lastKey = INT64_MIN;
2,069,790✔
8161
  pInfo->firstValue = (double)INT64_MIN;
2,069,790✔
8162
  pInfo->lastValue = (double)INT64_MIN;
2,069,790✔
8163

8164
  pInfo->hasResult = 0;
2,069,790✔
8165
  return TSDB_CODE_SUCCESS;
2,069,790✔
8166
}
8167

8168
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
321,822,191✔
8169
  if (isFirst) {
321,822,191✔
8170
    pRateInfo->firstValue = v;
160,221,459✔
8171
    pRateInfo->firstKey = ts;
160,221,459✔
8172
    if (pRateInfo->firstPk) {
160,221,459✔
8173
      int32_t pkBytes;
8174
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
25,725✔
8175
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
5,880✔
8176
      } else {
8177
        pkBytes = pRateInfo->pkBytes;
19,845✔
8178
      }
8179
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
25,725✔
8180
    }
8181
  } else {
8182
    pRateInfo->lastValue = v;
161,600,732✔
8183
    pRateInfo->lastKey = ts;
161,600,732✔
8184
    if (pRateInfo->lastPk) {
161,600,732✔
8185
      int32_t pkBytes;
8186
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
38,220✔
8187
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
8,820✔
8188
      } else {
8189
        pkBytes = pRateInfo->pkBytes;
29,400✔
8190
      }
8191
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
38,220✔
8192
    }
8193
  }
8194
}
321,822,191✔
8195

8196
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,276,928✔
8197
  if (pCtx->hasPrimaryKey) {
2,276,928✔
8198
    if (!isMerge) {
13,965✔
8199
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
12,495✔
8200
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
12,495✔
8201
      pRateInfo->firstPk = pRateInfo->pkData;
12,495✔
8202
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
12,495✔
8203
    } else {
8204
      pRateInfo->firstPk = pRateInfo->pkData;
1,470✔
8205
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,470✔
8206
    }
8207
  } else {
8208
    pRateInfo->firstPk = NULL;
2,262,963✔
8209
    pRateInfo->lastPk = NULL;
2,262,452✔
8210
  }
8211
}
2,276,928✔
8212

8213
int32_t irateFunction(SqlFunctionCtx* pCtx) {
2,211,326✔
8214
  int32_t              code = TSDB_CODE_SUCCESS;
2,211,326✔
8215
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,211,326✔
8216
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,210,815✔
8217

8218
  SInputColumnInfoData* pInput = &pCtx->input;
2,210,815✔
8219
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,211,326✔
8220

8221
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,211,326✔
8222

8223
  funcInputUpdate(pCtx);
2,210,815✔
8224

8225
  initializeRateInfo(pCtx, pRateInfo, false);
2,211,326✔
8226

8227
  int32_t       numOfElems = 0;
2,210,815✔
8228
  int32_t       type = pInputCol->info.type;
2,210,815✔
8229
  SFuncInputRow row = {0};
2,210,815✔
8230
  bool          result = false;
2,210,815✔
8231
  while (1) {
212,132,563✔
8232
    code = funcInputGetNextRow(pCtx, &row, &result);
214,343,378✔
8233
    if (TSDB_CODE_SUCCESS != code) {
214,343,378✔
8234
      return code;
×
8235
    }
8236
    if (!result) {
214,343,378✔
8237
      break;
2,210,815✔
8238
    }
8239
    if (row.isDataNull) {
212,132,563✔
8240
      continue;
7,261,813✔
8241
    }
8242

8243
    char*  data = row.pData;
204,870,750✔
8244
    double v = 0;
204,870,750✔
8245
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
204,870,750✔
8246

8247
    if (INT64_MIN == pRateInfo->lastKey) {
204,870,750✔
8248
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
1,384,367✔
8249
      pRateInfo->hasResult = 1;
1,384,367✔
8250
      continue;
1,384,367✔
8251
    }
8252

8253
    if (row.ts > pRateInfo->lastKey) {
203,486,383✔
8254
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
160,184,002✔
8255
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
160,184,002✔
8256
      }
8257
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
160,184,002✔
8258
      continue;
160,184,002✔
8259
    } else if (row.ts == pRateInfo->lastKey) {
43,302,381✔
8260
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8261
    }
8262

8263
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
43,302,381✔
8264
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
2,256✔
8265
    } else if (row.ts == pRateInfo->firstKey) {
43,300,125✔
8266
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8267
    }
8268
  }
8269

8270
  numOfElems++;
2,210,815✔
8271

8272
  SET_VAL(pResInfo, numOfElems, 1);
2,210,815✔
8273
  return TSDB_CODE_SUCCESS;
2,210,815✔
8274
}
8275

8276
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
2,036,061✔
8277
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
2,036,061✔
8278
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
206,749✔
8279
    return 0.0;
1,829,312✔
8280
  }
8281

8282
  double diff = 0;
206,749✔
8283
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
8284
  // value between two values.
8285
  diff = pRateInfo->lastValue;
206,749✔
8286
  if (diff >= pRateInfo->firstValue) {
206,749✔
8287
    diff -= pRateInfo->firstValue;
139,180✔
8288
  }
8289

8290
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
206,749✔
8291
  if (duration == 0) {
206,749✔
8292
    return 0;
×
8293
  }
8294

8295
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
206,749✔
8296
}
8297

8298
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
27,054✔
8299
  if (inputKey > pOutput->lastKey) {
27,054✔
8300
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
15,229✔
8301
    if (isFirstKey) {
15,229✔
8302
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
6,905✔
8303
    } else {
8304
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
8,324✔
8305
    }
8306
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
11,825✔
8307
    if (isFirstKey) {
2,838✔
8308
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,419✔
8309
    } else {
8310
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,419✔
8311
    }
8312
  } else {
8313
    // inputKey < pOutput->firstKey
8314
  }
8315
}
27,054✔
8316

8317
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
17,134✔
8318
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
17,134✔
8319
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
17,134✔
8320
}
17,134✔
8321

8322
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
30,661✔
8323
  if ((pInput->firstKey != INT64_MIN &&
30,661✔
8324
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
27,789✔
8325
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
30,661✔
8326
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8327
  }
8328

8329
  if (pOutput->hasResult == 0) {
30,661✔
8330
    irateCopyInfo(pInput, pOutput);
17,134✔
8331
    pOutput->hasResult = pInput->hasResult;
17,134✔
8332
    return TSDB_CODE_SUCCESS;
17,134✔
8333
  }
8334

8335
  if (pInput->firstKey != INT64_MIN) {
13,527✔
8336
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
13,527✔
8337
  }
8338

8339
  if (pInput->lastKey != INT64_MIN) {
13,527✔
8340
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
13,527✔
8341
  }
8342

8343
  pOutput->hasResult = pInput->hasResult;
13,527✔
8344
  return TSDB_CODE_SUCCESS;
13,527✔
8345
}
8346

8347
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
32,801✔
8348
  SInputColumnInfoData* pInput = &pCtx->input;
32,801✔
8349
  SColumnInfoData*      pCol = pInput->pData[0];
32,801✔
8350
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
32,801✔
8351
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
8352
  }
8353

8354
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
32,801✔
8355
  initializeRateInfo(pCtx, pInfo, true);
32,801✔
8356

8357
  int32_t start = pInput->startRowIndex;
32,801✔
8358
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
65,602✔
8359
    char*      data = colDataGetData(pCol, i);
32,801✔
8360
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
32,801✔
8361
    initializeRateInfo(pCtx, pInfo, true);
32,801✔
8362
    if (pInputInfo->hasResult) {
32,801✔
8363
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
30,661✔
8364
      if (code != TSDB_CODE_SUCCESS) {
30,661✔
8365
        return code;
×
8366
      }
8367
    }
8368
  }
8369

8370
  if (pInfo->hasResult) {
32,801✔
8371
    GET_RES_INFO(pCtx)->numOfRes = 1;
30,661✔
8372
  }
8373

8374
  return TSDB_CODE_SUCCESS;
32,801✔
8375
}
8376

8377
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
32,801✔
8378
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,801✔
8379
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
32,801✔
8380
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
32,801✔
8381
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
32,801✔
8382

8383
  if (NULL == res) {
32,801✔
8384
    return terrno;
×
8385
  }
8386
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
32,801✔
8387
  varDataSetLen(res, resultBytes);
32,801✔
8388

8389
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
32,801✔
8390
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
32,801✔
8391
  if (NULL == pCol) {
32,801✔
8392
    taosMemoryFree(res);
×
8393
    return TSDB_CODE_OUT_OF_RANGE;
×
8394
  }
8395

8396
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
32,801✔
8397

8398
  taosMemoryFree(res);
32,801✔
8399
  return code;
32,801✔
8400
}
8401

8402
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,036,061✔
8403
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,036,061✔
8404
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,036,061✔
8405
  if (NULL == pCol) {
2,036,061✔
8406
    return TSDB_CODE_OUT_OF_RANGE;
×
8407
  }
8408

8409
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,036,061✔
8410
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,036,061✔
8411

8412
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,036,061✔
8413
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
2,036,061✔
8414
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
2,036,061✔
8415

8416
  return code;
2,036,061✔
8417
}
8418

8419
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
8420
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
8421
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
8422
  bool                 isWindow = pCtx->hasWindowOrGroup && pCtx->hasWindow;
2,147,483,647✔
8423

8424
  if (pInfo->hasResult && (!isWindow || !pInfo->isNull)) {
2,147,483,647✔
8425
    // If already has result for 'group by' or
8426
    // has non-null result for 'window', we can skip left data blocks.
8427
    goto _group_value_over;
2,147,483,647✔
8428
  }
8429

8430
  int32_t               valueRowIndex = -1;
2,147,483,647✔
8431
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
8432
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
8433

8434
  // try to find a non-null value
8435
  if (NULL != pInputCol->pData) {
2,147,483,647✔
8436
    if (isWindow) {
2,147,483,647✔
8437
      // for 'window', non-null value can appear at any row of any data block
8438
      int64_t startIndex = pInput->startRowIndex;
2,147,483,647✔
8439
      int64_t endIndex = pInput->startRowIndex + pInput->numOfRows - 1;
2,147,483,647✔
8440
      for (int64_t i = startIndex; i <= endIndex; ++i) {
2,147,483,647✔
8441
        if (!colDataIsNull_s(pInputCol, i)) {
2,147,483,647✔
8442
          valueRowIndex = i;
2,147,483,647✔
8443
          break;
2,147,483,647✔
8444
        }
8445
      }
8446
    } else {
8447
      // for 'group by', just take the first row
8448
      if (!colDataIsNull_s(pInputCol, pInput->startRowIndex)) {
436,578,526✔
8449
        valueRowIndex = pInput->startRowIndex;
215,944,887✔
8450
      }
8451
    }
8452
  }
8453

8454
  if (valueRowIndex != -1) {
2,147,483,647✔
8455
    // found a non-null value
8456
    char* data = colDataGetData(pInputCol, valueRowIndex);
2,147,483,647✔
8457
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
2,147,483,647✔
8458
      int32_t bytes = calcStrBytesByType(pInputCol->info.type, data);
2,147,483,647✔
8459
      (void)memcpy(pInfo->data, data, bytes);
2,147,483,647✔
8460
    } else {
8461
      (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
2,147,483,647✔
8462
    }
8463
    pInfo->isNull = false;
2,147,483,647✔
8464
  } else {
8465
    // all values are null or first value is null for group by
8466
    pInfo->isNull = true;
1,413,203,604✔
8467
  }
8468
  pInfo->hasResult = true;
2,147,483,647✔
8469

8470
_group_value_over:
2,147,483,647✔
8471
  SET_VAL(pResInfo, 1, 1);
2,147,483,647✔
8472
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
8473
}
8474

8475
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
2,147,483,647✔
8476

8477
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
8478
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
8479
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
8480
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
8481
  if (NULL == pCol) {
2,147,483,647✔
8482
    return TSDB_CODE_OUT_OF_RANGE;
×
8483
  }
8484

8485
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
8486

8487
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
8488

8489
  if (pInfo->hasResult) {
2,147,483,647✔
8490
    int32_t currentRow = pBlock->info.rows;
2,147,483,647✔
8491
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
2,147,483,647✔
8492
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
2,147,483,647✔
8493
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
8494
        return code;
×
8495
      }
8496
    }
8497
  } else {
8498
    pResInfo->numOfRes = 0;
×
8499
  }
8500

8501
  return code;
2,147,483,647✔
8502
}
8503

8504
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
2,147,483,647✔
8505

8506
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
8507
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
8508
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
8509

8510
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
8511
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
8512

8513
  // escape rest of data blocks to avoid first entry to be overwritten.
8514
  if (pDBuf->hasResult) {
×
8515
    goto _group_key_over;
×
8516
  }
8517

8518
  if (pSBuf->isNull) {
×
8519
    pDBuf->isNull = true;
×
8520
    pDBuf->hasResult = true;
×
8521
    goto _group_key_over;
×
8522
  }
8523

8524
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
8525
    int32_t bytes = calcStrBytesByType(pSourceCtx->resDataInfo.type, pSBuf->data);
×
8526
    (void)memcpy(pDBuf->data, pSBuf->data, bytes);
×
8527
  } else {
8528
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
8529
  }
8530

8531
  pDBuf->hasResult = true;
×
8532

8533
_group_key_over:
×
8534

8535
  SET_VAL(pDResInfo, 1, 1);
×
8536
  return TSDB_CODE_SUCCESS;
×
8537
}
8538

8539
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
868,776✔
8540
  int32_t numOfElems = 0;
868,776✔
8541

8542
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
868,776✔
8543
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
868,776✔
8544

8545
  SInputColumnInfoData* pInput = &pCtx->input;
868,776✔
8546
  SColumnInfoData*      pInputCol = pInput->pData[0];
868,776✔
8547

8548
  int32_t bytes = pInputCol->info.bytes;
868,776✔
8549
  pInfo->bytes = bytes;
868,776✔
8550

8551
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
868,776✔
8552
  pInfo->pkType = -1;
868,776✔
8553
  __compar_fn_t pkCompareFn = NULL;
868,776✔
8554
  if (pCtx->hasPrimaryKey) {
868,776✔
8555
    pInfo->pkType = pkCol->info.type;
439,318✔
8556
    pInfo->pkBytes = pkCol->info.bytes;
439,318✔
8557
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
439,318✔
8558
  }
8559

8560
  // data is guaranteed to be in descending order
8561
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
1,801,052✔
8562
    numOfElems++;
932,276✔
8563

8564
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
932,276✔
8565
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
932,276✔
8566

8567
    TSKEY cts = getRowPTs(pInput->pPTS, i);
932,276✔
8568
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
932,276✔
8569
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
540,523✔
8570
      if (code != TSDB_CODE_SUCCESS) {
540,523✔
8571
        return code;
×
8572
      }
8573
      pResInfo->numOfRes = 1;
540,523✔
8574
    }
8575
  }
8576

8577
  SET_VAL(pResInfo, numOfElems, 1);
868,776✔
8578
  return TSDB_CODE_SUCCESS;
868,776✔
8579
}
8580

8581
bool getCorrFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
8582
  pEnv->calcMemSize = sizeof(SCorrRes);
×
8583
  return true;
×
8584
}
8585

8586
int32_t corrFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
8587
  if (pResultInfo->initialized) {
×
8588
    return TSDB_CODE_SUCCESS;
×
8589
  }
8590
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
×
8591
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
8592
  }
8593

8594
  SCorrRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
×
8595
  (void)memset(pRes, 0, sizeof(SCorrRes));
×
8596
  return TSDB_CODE_SUCCESS;
×
8597
}
8598

8599
int32_t corrFunction(SqlFunctionCtx* pCtx) {
×
8600
  int32_t               numOfElem = 0;
×
8601
  SInputColumnInfoData* pInput = &pCtx->input;
×
8602
  int32_t               xType = pInput->pData[0]->info.type;
×
8603
  int32_t               yType = pInput->pData[1]->info.type;
×
8604
  SCorrRes*             pCorrRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8605

8606
  // computing based on the true data block
8607
  SColumnInfoData* pLeft = pInput->pData[0];   // left
×
8608
  SColumnInfoData* pRight = pInput->pData[1];  // right
×
8609

8610
  int32_t leftMod = typeGetTypeModFromColInfo(&pLeft->info);
×
8611
  int32_t rightMod = typeGetTypeModFromColInfo(&pRight->info);
×
8612
  int32_t start = pInput->startRowIndex;
×
8613
  int32_t numOfRows = pInput->numOfRows;
×
8614

8615
  if (IS_NULL_TYPE(xType) || IS_NULL_TYPE(yType)) {
×
8616
    numOfElem = 0;
×
8617
    goto _over;
×
8618
  }
8619

8620
  for (int32_t i = 0; i < numOfRows; ++i) {
×
8621
    double pInputX = 0, pInputY = 0;
×
8622

8623
    if (colDataIsNull_f(pLeft, i) || colDataIsNull_f(pRight, i)) {
×
8624
      continue;
×
8625
    }
8626

8627
    char* pXVal = colDataGetData(pLeft, i);
×
8628
    char* pYVal = colDataGetData(pRight, i);
×
8629

8630
    GET_TYPED_DATA(pInputX, double, xType, pXVal, leftMod);
×
8631
    GET_TYPED_DATA(pInputY, double, yType, pYVal, rightMod);
×
8632

8633
    pCorrRes->sumLeft += pInputX;
×
8634
    pCorrRes->sumRight += pInputY;
×
8635

8636
    pCorrRes->quadLeft += pInputX * pInputX;
×
8637
    pCorrRes->quadRight += pInputY * pInputY;
×
8638

8639
    pCorrRes->productVal += pInputX * pInputY;
×
8640

8641
    pCorrRes->count += 1;
×
8642
    numOfElem += 1;
×
8643
  }
8644

8645
_over:
×
8646
  // data in the check operation are all null, not output
8647
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
×
8648
  return TSDB_CODE_SUCCESS;
×
8649
}
8650

8651
int32_t corrFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
8652
  SInputColumnInfoData* pInput = &pCtx->input;
×
8653
  SCorrRes*             pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8654
  double                avg;
8655

8656
  if (pRes->count == 0) {
×
8657
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
8658
    return functionFinalize(pCtx, pBlock);
×
8659
  }
8660

8661
  /**
8662
    numerator = sum_xy - (sum_x * sum_y) / n
8663
    denominator_x = math.sqrt(sum_x2 - (sum_x**2) / n)
8664
    denominator_y = math.sqrt(sum_y2 - (sum_y**2) / n)
8665

8666
    if denominator_x == 0 or denominator_y == 0:
8667
        return 0.0
8668
    res = numerator / (denominator_x * denominator_y)
8669
  */
8670

8671
  if (pRes->count == 1) {
×
8672
    pRes->result = 0.0;
×
8673
  } else {
8674
    double numerator = pRes->productVal - (pRes->sumLeft * pRes->sumRight) / pRes->count;
×
8675
    double dnmX = sqrt(pRes->quadLeft - pRes->sumLeft * pRes->sumLeft / pRes->count);
×
8676
    double dnmY = sqrt(pRes->quadRight - pRes->sumRight * pRes->sumRight / pRes->count);
×
8677

8678
    if (DBL_EQUAL(dnmX, 0.0) || DBL_EQUAL(dnmY, 0.0)) {
×
8679
      pRes->result = 0.0;
×
8680
    } else {
8681
      pRes->result = numerator / (dnmX * dnmY);
×
8682

8683
      if (pRes->result > 1 || pRes->result < -1) {
×
8684
        qError("invalid corr results, %.4f, numerator:%.4f, dnmX:%.4f, dnmY:%.4f", pRes->result, numerator, dnmX, dnmY);
×
8685
        if (pRes->result > 1) {
×
8686
          pRes->result = 1;
×
8687
        } else if (pRes->result < -1) {
×
8688
          pRes->result = -1;
×
8689
        }
8690
      }
8691
    }
8692
  }
8693

8694
  return functionFinalize(pCtx, pBlock);
×
8695
}
8696

8697
int32_t getCorrInfoSize() { return sizeof(SCorrRes); }
×
8698

8699
int32_t corrPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
8700
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
8701
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8702
  int32_t              resultBytes = getCorrInfoSize();
×
8703
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
8704
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
×
8705
  int32_t              code = 0;
×
8706

8707
  if (NULL == res) {
×
8708
    return terrno;
×
8709
  }
8710

8711
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
8712
  varDataSetLen(res, resultBytes);
×
8713

8714
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
8715
  if (NULL == pCol) {
×
8716
    taosMemoryFree(res);
×
8717
    return TSDB_CODE_OUT_OF_RANGE;
×
8718
  }
8719

8720
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
8721

8722
  taosMemoryFree(res);
×
8723
  return code;
×
8724
}
8725

8726
int32_t corrFuncMerge(SqlFunctionCtx* pCtx) {
×
8727
  SInputColumnInfoData* pInput = &pCtx->input;
×
8728
  SColumnInfoData*      pCol = pInput->pData[0];
×
8729

8730
  if (IS_NULL_TYPE(pCol->info.type)) {
×
8731
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
8732
    return TSDB_CODE_SUCCESS;
×
8733
  }
8734

8735
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
8736
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
8737
  }
8738

8739
  SCorrRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8740

8741
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
×
8742
    if (colDataIsNull_s(pCol, i)) {
×
8743
      continue;
×
8744
    }
8745

8746
    char*     data = colDataGetData(pCol, i);
×
8747
    SCorrRes* pInputInfo = (SCorrRes*)varDataVal(data);
×
8748

8749
    if (pInputInfo->count == 0) {
×
8750
      continue;
×
8751
    }
8752

8753
    // pOutput->type = pInput->type;
8754
    if (pInfo->count == 0) {
×
8755
      TAOS_MEMCPY(pInfo, pInputInfo, sizeof(SCorrRes));
×
8756
    } else if (pInfo->count > 0) {
×
8757
      pInfo->productVal += pInputInfo->productVal;
×
8758
      pInfo->quadLeft += pInputInfo->quadLeft;
×
8759
      pInfo->quadRight += pInputInfo->quadRight;
×
8760
      pInfo->sumLeft += pInputInfo->sumLeft;
×
8761
      pInfo->sumRight += pInputInfo->sumRight;
×
8762
      pInfo->count += pInputInfo->count;
×
8763
    }
8764
  }
8765

8766
  SET_VAL(GET_RES_INFO(pCtx), pInfo->count, 1);
×
8767
  return TSDB_CODE_SUCCESS;
×
8768
}
8769

8770
int32_t hasNullFunction(SqlFunctionCtx* pCtx) {
16,930,260✔
8771
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,930,260✔
8772
  bool* pRes = GET_ROWCELL_INTERBUF(pResInfo);
16,930,260✔
8773
  if (*pRes) {
16,930,260✔
8774
    return TSDB_CODE_SUCCESS;
×
8775
  }
8776

8777
  SInputColumnInfoData* pInput = &pCtx->input;
16,930,260✔
8778
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
16,930,260✔
8779
  SColumnInfoData* pCol = pInput->pData[0];
16,930,260✔
8780

8781
  if (pInput->numOfRows > 0) {
16,930,260✔
8782
    pResInfo->numOfRes = 1;
16,930,260✔
8783
  }
8784

8785
  if (IS_NULL_TYPE(pCol->info.type) && pInput->numOfRows > 0) {
16,930,260✔
8786
    *pRes = true;
×
8787
    return TSDB_CODE_SUCCESS;
×
8788
  }
8789

8790
  if (pInput->colDataSMAIsSet) {
16,930,260✔
8791
    if (pAgg->numOfNull > 0) {
×
8792
      *pRes = true;
×
8793
      return TSDB_CODE_SUCCESS;
×
8794
    }
8795

8796
    if (pInput->numOfRows <= INT16_MAX) {
×
8797
      return TSDB_CODE_SUCCESS;
×
8798
    }
8799
  }
8800

8801
  int32_t start = pInput->startRowIndex;
16,930,260✔
8802
  int32_t end = start + pInput->numOfRows;
16,930,260✔
8803

8804
  if (pCol->hasNull) {
16,930,260✔
8805
    for (int32_t i = start; i < end; ++i) {
40,304,889✔
8806
      if (colDataIsNull_s(pCol, i)) {
68,339,166✔
8807
        *pRes = true;
10,698,342✔
8808
        break;
10,698,342✔
8809
      }
8810
    }
8811
  }  
8812

8813
  return TSDB_CODE_SUCCESS;
16,930,260✔
8814
}
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