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

taosdata / TDengine / #5006

29 Mar 2026 04:32AM UTC coverage: 72.274% (+0.1%) from 72.152%
#5006

push

travis-ci

web-flow
refactor: do some internal refactor for TDgpt. (#34955)

253711 of 351039 relevant lines covered (72.27%)

131490495.89 hits per line

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

77.04
/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 "query.h"
22
#include "querynodes.h"
23
#include "tanalytics.h"
24
#include "tarray.h"
25
#include "tcompare.h"
26
#include "tdatablock.h"
27
#include "tdigest.h"
28
#include "tfunctionInt.h"
29
#include "tglobal.h"
30
#include "thistogram.h"
31
#include "tpercentile.h"
32
#include "ttypes.h"
33

34
bool ignoreNegative(int8_t ignoreOption) { return (ignoreOption & 0x1) == 0x1; }
2,147,483,647✔
35
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
45,850,217✔
36

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

197
void funcInputUpdate(SqlFunctionCtx* pCtx) {
56,292,069✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
56,292,069✔
199

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

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

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

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

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

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

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

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

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

332
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
4,004,176✔
333
  int32_t idx = rowIndex + 1;
4,004,176✔
334
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
53,243,570✔
335
    ++idx;
49,239,394✔
336
  }
337
  pIter->rowIndex = idx;
4,004,176✔
338
}
4,004,176✔
339

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

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

361
      pIter->hasPrev = false;
×
362
      setInputRowInfo(pRow, pIter, idx, true);
×
363
      forwardToNextDiffTsRow(pIter, idx);
×
364
      return true;
×
365
    }
366
  } else {
367
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,440,498✔
368
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
4,222,776✔
369

370
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
4,222,776✔
371
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
4,222,776✔
372
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
4,004,176✔
373
      } else {
374
        pIter->rowIndex = pIter->inputEndIndex + 1;
218,600✔
375
      }
376
      return true;
4,222,776✔
377
    } else {
378
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
217,722✔
379
      pIter->hasPrev = true;
217,722✔
380
      pIter->prevBlockTsEnd = tsEnd;
217,722✔
381
      return false;
217,722✔
382
    }
383
  }
384
}
385

386
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
2,147,483,647✔
387
  if (pIter->rowIndex <= pIter->inputEndIndex) {
2,147,483,647✔
388
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
2,147,483,647✔
389
    ++pIter->rowIndex;
2,147,483,647✔
390
    return true;
2,147,483,647✔
391
  } else {
392
    return false;
56,804,100✔
393
  }
394
}
395

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

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

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

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

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

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

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

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

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

455
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);
456

457
int32_t functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,147,483,647✔
458
  if (pResultInfo->initialized) {
2,147,483,647✔
459
    return TSDB_CODE_SUCCESS;  // already initialized
1,957,748✔
460
  }
461

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

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

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

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

483
  return code;
2,147,483,647✔
484
}
485

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

491
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
492
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
493

494
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, true);
×
495

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

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

510
  char*   in = finalResult;
83,020✔
511
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
83,020✔
512

513
  return code;
83,020✔
514
}
515

516
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
15,214,639✔
517
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
15,214,639✔
518
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
15,215,199✔
519
    return FUNC_DATA_REQUIRED_NOT_LOAD;
11,180,640✔
520
  }
521
  return FUNC_DATA_REQUIRED_SMA_LOAD;
4,034,464✔
522
}
523

524
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
54,542,563✔
525
  pEnv->calcMemSize = sizeof(int64_t);
54,542,563✔
526
  return true;
54,551,027✔
527
}
528

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

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

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

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

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

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

585
  if (tsCountAlwaysReturnValue) {
2,147,483,647✔
586
    pResInfo->numOfRes = 1;
2,147,483,647✔
587
  } else {
588
    SET_VAL(pResInfo, val, 1);
8,893,271✔
589
  }
590

591
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
592
}
593

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

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

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

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

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

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

618
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
619
    numOfElem = 0;
1,126,835,319✔
620
    goto _sum_over;
1,126,835,319✔
621
  }
622

623
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
624
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
31,807,429✔
625

626
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
31,801,423✔
627
      SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
16,188,110✔
628
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
15,613,313✔
629
      SUM_RES_INC_USUM(pSumRes, pAgg->sum);
15,609,804✔
630
    } else if (IS_FLOAT_TYPE(type)) {
3,817✔
631
      SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
×
632
    } else if (IS_DECIMAL_TYPE(type)) {
8,283✔
633
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
8,283✔
634
      const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
8,283✔
635
      if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
15,060✔
636
                                                       &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
6,777✔
637
        return TSDB_CODE_DECIMAL_OVERFLOW;
1,506✔
638
      }
639
      pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
6,777✔
640
    }
641
  } else {  // computing based on the true data block
642
    SColumnInfoData* pCol = pInput->pData[0];
2,147,483,647✔
643

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

647
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
648
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
649
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int8_t, numOfElem);
770,585,725✔
650
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
2,147,483,647✔
651
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
510,318,488✔
652
      } else if (type == TSDB_DATA_TYPE_INT) {
2,147,483,647✔
653
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int32_t, numOfElem);
2,147,483,647✔
654
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
1,266,114,646✔
655
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int64_t, numOfElem);
2,147,483,647✔
656
      }
657
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,147,483,647✔
658
      if (type == TSDB_DATA_TYPE_UTINYINT) {
2,147,483,647✔
659
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint8_t, numOfElem);
483,160,472✔
660
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
2,147,483,647✔
661
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint16_t, numOfElem);
2,147,483,647✔
662
      } else if (type == TSDB_DATA_TYPE_UINT) {
4,074,508✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
396,102,840✔
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
2,142,558✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
396,770,321✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
240,678,553✔
668
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
530,523,698✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
148,589,801✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
459,094,268✔
671
    } else if (IS_DECIMAL_TYPE(type)) {
23,683✔
672
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
23,683✔
673
      int32_t overflow = false;
22,590✔
674
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
22,590✔
675
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
6,030,024✔
676
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
16,566✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
12,069,084✔
678
      }
679
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
22,590✔
680
    }
681
  }
682

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

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

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

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

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

724
bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
27,801,820✔
725
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
27,801,820✔
726
  return true;
27,806,199✔
727
}
728

729
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
25,303,437✔
730
  SNode* pParam;
731
  switch (pFunc->funcType) {
25,303,437✔
732
    case FUNCTION_TYPE_MAX:
25,303,018✔
733
    case FUNCTION_TYPE_MIN:
734
    case FUNCTION_TYPE_SUM:
735
    case FUNCTION_TYPE_AVG:
736
    case FUNCTION_TYPE_AVG_PARTIAL:
737
    case FUNCTION_TYPE_PERCENTILE:
738
    case FUNCTION_TYPE_SPREAD:
739
    case FUNCTION_TYPE_SPREAD_PARTIAL:
740
    case FUNCTION_TYPE_SPREAD_MERGE:
741
    case FUNCTION_TYPE_TWA:
742
    case FUNCTION_TYPE_ELAPSED:
743
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
25,303,018✔
744
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
25,305,772✔
745
        return true;
1,515,394✔
746
      }
747
      break;
23,788,710✔
748
    default:
419✔
749
      break;
419✔
750
  }
751
  return false;
23,789,129✔
752
}
753

754
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
25,302,031✔
755
  if (funcNotSupportStringSma(pFunc)) {
25,302,031✔
756
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,515,394✔
757
  }
758
  return FUNC_DATA_REQUIRED_SMA_LOAD;
23,789,053✔
759
}
760

761
int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,080,143,882✔
762
  if (pResultInfo->initialized) {
2,080,143,882✔
763
    return TSDB_CODE_SUCCESS;
×
764
  }
765
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,080,148,826✔
766
    return TSDB_CODE_FUNC_SETUP_ERROR;  // not initialized since it has been initialized
×
767
  }
768

769
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
2,080,153,002✔
770
  buf->assign = false;
2,080,143,236✔
771
  buf->tuplePos.pageId = -1;
2,080,152,612✔
772

773
  buf->nullTupleSaved = false;
2,080,148,714✔
774
  buf->nullTuplePos.pageId = -1;
2,080,155,797✔
775
  buf->str = NULL;
2,080,156,610✔
776
  return TSDB_CODE_SUCCESS;
2,080,153,904✔
777
}
778

779
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
44,185,496✔
780
  COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
781
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
44,185,496✔
782
  return true;
44,187,198✔
783
}
784

785
int32_t minFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
786
  int32_t numOfElems = 0;
2,147,483,647✔
787
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
2,147,483,647✔
788
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
789
    return code;
×
790
  }
791
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,147,483,647✔
792
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
793
}
794

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

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

809
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,046,246,174✔
810
  int32_t code = TSDB_CODE_SUCCESS;
2,046,246,174✔
811

812
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2,046,246,174✔
813
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2,046,246,620✔
814

815
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
2,046,246,620✔
816
  int32_t currentRow = pBlock->info.rows;
2,046,246,093✔
817

818
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,046,245,340✔
819
  if (NULL == pCol) {
2,046,246,021✔
820
    return TSDB_CODE_OUT_OF_RANGE;
×
821
  }
822
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
2,046,246,021✔
823

824
  // NOTE: do nothing change it, for performance issue
825
  if (!pEntryInfo->isNullRes) {
2,046,246,661✔
826
    switch (pCol->info.type) {
1,608,090,227✔
827
      case TSDB_DATA_TYPE_UBIGINT:
146,663,342✔
828
      case TSDB_DATA_TYPE_BIGINT:
829
      case TSDB_DATA_TYPE_TIMESTAMP:
830
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
146,663,342✔
831
        break;
146,663,342✔
832
      case TSDB_DATA_TYPE_UINT:
1,328,765,361✔
833
      case TSDB_DATA_TYPE_INT:
834
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
1,328,765,361✔
835
        break;
1,328,765,433✔
836
      case TSDB_DATA_TYPE_USMALLINT:
14,556,377✔
837
      case TSDB_DATA_TYPE_SMALLINT:
838
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
14,556,377✔
839
        break;
14,556,377✔
840
      case TSDB_DATA_TYPE_BOOL:
42,953,821✔
841
      case TSDB_DATA_TYPE_UTINYINT:
842
      case TSDB_DATA_TYPE_TINYINT:
843
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
42,953,821✔
844
        break;
42,953,821✔
845
      case TSDB_DATA_TYPE_DOUBLE:
32,998,697✔
846
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
32,998,697✔
847
        break;
32,998,697✔
848
      case TSDB_DATA_TYPE_FLOAT: {
36,743,631✔
849
        float v = GET_FLOAT_VAL(&pRes->v);
36,743,631✔
850
        colDataSetFloat(pCol, currentRow, &v);
36,743,631✔
851
        break;
36,743,631✔
852
      }
853
      case TSDB_DATA_TYPE_VARBINARY:
4,715,150✔
854
      case TSDB_DATA_TYPE_VARCHAR:
855
      case TSDB_DATA_TYPE_NCHAR: {
856
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
4,715,150✔
857
        if (TSDB_CODE_SUCCESS != code) {
4,715,150✔
858
          return code;
×
859
        }
860
        break;
4,715,150✔
861
      }
862
      case TSDB_DATA_TYPE_DECIMAL64:
660,348✔
863
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
660,348✔
864
        break;
660,348✔
865
      case TSDB_DATA_TYPE_DECIMAL:
31,206✔
866
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
31,206✔
867
        break;
31,206✔
868
    }
869
  } else {
870
    colDataSetNULL(pCol, currentRow);
438,156,321✔
871
  }
872

873
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
2,046,244,398✔
874
  if (pCtx->subsidiaries.num > 0) {
2,046,244,971✔
875
    if (pEntryInfo->numOfRes > 0) {
2,191,945✔
876
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
1,913,299✔
877
    } else {
878
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
278,646✔
879
    }
880
  }
881

882
  return code;
2,046,244,331✔
883
}
884

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

890
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
883,702✔
891
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
530,228✔
892
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
530,228✔
893

894
    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
530,228✔
895
    if (NULL == pDstCol) {
530,228✔
896
      return terrno;
×
897
    }
898
    colDataSetNULL(pDstCol, rowIndex);
530,228✔
899
  }
900

901
  return TSDB_CODE_SUCCESS;
353,474✔
902
}
903

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

909
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
76,113,046✔
910
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
911
    int32_t numOfCols = pCtx->subsidiaries.num;
76,113,046✔
912
    char*   p = NULL;
76,112,611✔
913
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
76,113,046✔
914
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
76,111,943✔
915
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
7✔
916
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
917
      return TSDB_CODE_NOT_FOUND;
×
918
    }
919

920
    bool* nullList = (bool*)p;
76,111,936✔
921
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
76,111,936✔
922

923
    // todo set the offset value to optimize the performance.
924
    for (int32_t j = 0; j < numOfCols; ++j) {
247,111,827✔
925
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
170,999,884✔
926
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
170,999,884✔
927

928
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
170,999,442✔
929
      if (NULL == pDstCol) {
170,999,884✔
930
        return terrno;
×
931
      }
932
      if (nullList[j]) {
170,999,884✔
933
        colDataSetNULL(pDstCol, rowIndex);
54,366,621✔
934
      } else {
935
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
116,632,821✔
936
        if (TSDB_CODE_SUCCESS != code) {
116,633,698✔
937
          return code;
×
938
        }
939
      }
940
      pStart += pDstCol->info.bytes;
171,000,319✔
941
    }
942
  }
943

944
  return TSDB_CODE_SUCCESS;
76,111,943✔
945
}
946

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

954
  int32_t code = TSDB_CODE_SUCCESS;
1,003,382✔
955
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,272,006✔
956
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
1,268,624✔
957

958
    // get data from source col
959
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
1,268,624✔
960
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
1,268,624✔
961

962
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
1,268,624✔
963
    if (NULL == pSrcCol) {
1,268,624✔
964
      return TSDB_CODE_OUT_OF_RANGE;
×
965
    }
966

967
    char* pData = colDataGetData(pSrcCol, rowIndex);
1,268,624✔
968

969
    // append to dest col
970
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
1,268,624✔
971

972
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
1,268,624✔
973
    if (NULL == pDstCol) {
1,268,624✔
974
      return TSDB_CODE_OUT_OF_RANGE;
×
975
    }
976

977
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,537,248✔
978
      colDataSetNULL(pDstCol, pos);
52,620✔
979
    } else {
980
      code = colDataSetVal(pDstCol, pos, pData, false);
1,216,004✔
981
      if (TSDB_CODE_SUCCESS != code) {
1,216,004✔
982
        return code;
×
983
      }
984
    }
985
  }
986
  return code;
1,003,382✔
987
}
988

989
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
×
990

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

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

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

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

1082
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
17,543,202✔
1083

1084
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
3,909,129✔
1085
  pEnv->calcMemSize = sizeof(SStdRes);
3,909,129✔
1086
  return true;
3,909,667✔
1087
}
1088

1089
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
544,868,901✔
1090
  if (pResultInfo->initialized) {
544,868,901✔
1091
    return TSDB_CODE_SUCCESS;
×
1092
  }
1093
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
544,869,977✔
1094
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1095
  }
1096

1097
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
544,869,439✔
1098
  (void)memset(pRes, 0, sizeof(SStdRes));
544,866,749✔
1099
  return TSDB_CODE_SUCCESS;
544,866,749✔
1100
}
1101

1102
int32_t stdFunction(SqlFunctionCtx* pCtx) {
1,065,830,042✔
1103
  int32_t numOfElem = 0;
1,065,830,042✔
1104

1105
  // Only the pre-computing information loaded and actual data does not loaded
1106
  SInputColumnInfoData* pInput = &pCtx->input;
1,065,830,042✔
1107
  int32_t               type = pInput->pData[0]->info.type;
1,065,912,541✔
1108

1109
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,065,915,479✔
1110
  pStdRes->type = type;
1,065,916,095✔
1111

1112
  // computing based on the true data block
1113
  SColumnInfoData* pCol = pInput->pData[0];
1,065,916,173✔
1114

1115
  int32_t start = pInput->startRowIndex;
1,065,903,429✔
1116
  int32_t numOfRows = pInput->numOfRows;
1,065,900,342✔
1117

1118
  if (IS_NULL_TYPE(type)) {
1,065,906,000✔
1119
    numOfElem = 0;
169,776,542✔
1120
    goto _stddev_over;
169,776,542✔
1121
  }
1122

1123
  switch (type) {
896,129,458✔
1124
    case TSDB_DATA_TYPE_TINYINT: {
12,094,992✔
1125
      int8_t* plist = (int8_t*)pCol->pData;
12,094,992✔
1126
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,077,146,746✔
1127
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,065,122,818✔
1128
          continue;
1,422,264,795✔
1129
        }
1130

1131
        numOfElem += 1;
643,042,270✔
1132
        pStdRes->count += 1;
643,042,270✔
1133
        double nr = (double)plist[i];
643,370,766✔
1134
        if (pStdRes->count == 1) {
643,372,628✔
1135
          pStdRes->dsum = nr;
1,349,076✔
1136
        } else {
1137
          double          s_kminusone = pStdRes->dsum;
642,040,338✔
1138
          volatile double diff = nr - s_kminusone;
642,028,536✔
1139
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
642,028,536✔
1140
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
642,045,315✔
1141
        }
1142
      }
1143

1144
      break;
12,023,928✔
1145
    }
1146

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

1154
        numOfElem += 1;
1,196,548,944✔
1155
        pStdRes->count += 1;
1,196,548,944✔
1156
        double nr = (double)plist[i];
1,202,570,190✔
1157
        if (pStdRes->count == 1) {
1,202,591,127✔
1158
          pStdRes->dsum = nr;
368,813,176✔
1159
        } else {
1160
          double          s_kminusone = pStdRes->dsum;
833,808,751✔
1161
          volatile double diff = nr - s_kminusone;
833,806,875✔
1162
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
833,806,875✔
1163
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
833,796,403✔
1164
        }
1165
      }
1166
      break;
801,845,277✔
1167
    }
1168

1169
    case TSDB_DATA_TYPE_INT: {
19,376,714✔
1170
      int32_t* plist = (int32_t*)pCol->pData;
19,376,714✔
1171
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1172
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1173
          continue;
755,460,659✔
1174
        }
1175

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

1189
      break;
19,377,790✔
1190
    }
1191

1192
    case TSDB_DATA_TYPE_BIGINT: {
13,943,230✔
1193
      int64_t* plist = (int64_t*)pCol->pData;
13,943,230✔
1194
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1195
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,145,568,695✔
1196
          continue;
1,295,472,231✔
1197
        }
1198

1199
        numOfElem += 1;
855,341,520✔
1200
        pStdRes->count += 1;
855,341,520✔
1201
        double nr = (double)plist[i];
849,750,521✔
1202
        if (pStdRes->count == 1) {
849,771,093✔
1203
          pStdRes->dsum = nr;
2,709,718✔
1204
        } else {
1205
          double          s_kminusone = pStdRes->dsum;
847,072,837✔
1206
          volatile double diff = nr - s_kminusone;
847,059,314✔
1207
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
847,059,314✔
1208
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
847,071,563✔
1209
        }
1210
      }
1211
      break;
13,943,230✔
1212
    }
1213

1214
    case TSDB_DATA_TYPE_UTINYINT: {
12,700,854✔
1215
      uint8_t* plist = (uint8_t*)pCol->pData;
12,700,854✔
1216
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1217
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1218
          continue;
1,543,906,038✔
1219
        }
1220

1221
        numOfElem += 1;
1,005,044,402✔
1222
        pStdRes->count += 1;
1,005,044,402✔
1223
        double nr = (double)plist[i];
1,008,598,148✔
1224
        if (pStdRes->count == 1) {
1,008,614,871✔
1225
          pStdRes->dsum = nr;
73,545✔
1226
        } else {
1227
          double          s_kminusone = pStdRes->dsum;
1,008,492,739✔
1228
          volatile double diff = nr - s_kminusone;
1,008,521,964✔
1229
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,008,521,964✔
1230
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,008,501,475✔
1231
        }
1232
      }
1233

1234
      break;
13,501,829✔
1235
    }
1236

1237
    case TSDB_DATA_TYPE_USMALLINT: {
10,227,473✔
1238
      uint16_t* plist = (uint16_t*)pCol->pData;
10,227,473✔
1239
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,061,878,278✔
1240
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,051,805,820✔
1241
          continue;
1,541,813,105✔
1242
        }
1243

1244
        numOfElem += 1;
506,822,065✔
1245
        pStdRes->count += 1;
506,822,065✔
1246
        double nr = (double)plist[i];
513,742,510✔
1247
        if (pStdRes->count == 1) {
513,742,510✔
1248
          pStdRes->dsum = nr;
32,321✔
1249
        } else {
1250
          double          s_kminusone = pStdRes->dsum;
513,710,189✔
1251
          volatile double diff = nr - s_kminusone;
513,710,189✔
1252
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
513,710,189✔
1253
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
513,710,189✔
1254
        }
1255
      }
1256
      break;
10,226,857✔
1257
    }
1258

1259
    case TSDB_DATA_TYPE_UINT: {
5,581,763✔
1260
      uint32_t* plist = (uint32_t*)pCol->pData;
5,581,763✔
1261
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,134,035,036✔
1262
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,128,548,599✔
1263
          continue;
803,647,467✔
1264
        }
1265

1266
        numOfElem += 1;
324,727,735✔
1267
        pStdRes->count += 1;
324,727,735✔
1268
        double nr = (double)plist[i];
327,674,462✔
1269
        if (pStdRes->count == 1) {
327,673,846✔
1270
          pStdRes->dsum = nr;
23,579✔
1271
        } else {
1272
          double          s_kminusone = pStdRes->dsum;
327,650,883✔
1273
          volatile double diff = nr - s_kminusone;
327,645,955✔
1274
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
327,645,955✔
1275
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
327,657,659✔
1276
        }
1277
      }
1278

1279
      break;
5,581,763✔
1280
    }
1281

1282
    case TSDB_DATA_TYPE_UBIGINT: {
5,581,379✔
1283
      uint64_t* plist = (uint64_t*)pCol->pData;
5,581,379✔
1284
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,134,915,537✔
1285
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,129,247,295✔
1286
          continue;
865,026,351✔
1287
        }
1288

1289
        numOfElem += 1;
263,279,017✔
1290
        pStdRes->count += 1;
263,279,017✔
1291
        double nr = (double)plist[i];
265,880,854✔
1292
        if (pStdRes->count == 1) {
265,880,854✔
1293
          pStdRes->dsum = nr;
20,724✔
1294
        } else {
1295
          double          s_kminusone = pStdRes->dsum;
265,859,514✔
1296
          volatile double diff = nr - s_kminusone;
265,855,818✔
1297
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
265,855,818✔
1298
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
265,857,666✔
1299
        }
1300
      }
1301
      break;
5,581,379✔
1302
    }
1303

1304
    case TSDB_DATA_TYPE_FLOAT: {
9,636,142✔
1305
      float* plist = (float*)pCol->pData;
9,636,142✔
1306
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,820,954,670✔
1307
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,811,317,793✔
1308
          continue;
37,914,096✔
1309
        }
1310

1311
        numOfElem += 1;
1,773,402,618✔
1312
        pStdRes->count += 1;
1,773,402,618✔
1313
        double nr = (double)plist[i];
1,773,405,117✔
1314
        if (pStdRes->count == 1) {
1,773,405,117✔
1315
          pStdRes->dsum = nr;
8,769,378✔
1316
        } else {
1317
          double          s_kminusone = pStdRes->dsum;
1,764,635,445✔
1318
          volatile double diff = nr - s_kminusone;
1,764,635,298✔
1319
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,764,635,298✔
1320
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,764,635,886✔
1321
        }
1322
      }
1323
      break;
9,636,680✔
1324
    }
1325

1326
    case TSDB_DATA_TYPE_DOUBLE: {
5,141,011✔
1327
      double* plist = (double*)pCol->pData;
5,141,011✔
1328
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
256,912,028✔
1329
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
251,775,321✔
1330
          continue;
75,458,825✔
1331
        }
1332

1333
        numOfElem += 1;
176,320,800✔
1334
        pStdRes->count += 1;
176,320,800✔
1335
        double nr = (double)plist[i];
176,299,818✔
1336
        if (pStdRes->count == 1) {
176,300,356✔
1337
          pStdRes->dsum = nr;
4,095,056✔
1338
        } else {
1339
          double          s_kminusone = pStdRes->dsum;
172,211,756✔
1340
          volatile double diff = nr - s_kminusone;
172,210,142✔
1341
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
172,210,142✔
1342
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
172,210,680✔
1343
        }
1344
      }
1345
      break;
5,145,853✔
1346
    }
1347

1348
    default:
×
1349
      break;
×
1350
  }
1351

1352
_stddev_over:
1,066,641,128✔
1353
  // data in the check operation are all null, not output
1354
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1,066,641,128✔
1355
  return TSDB_CODE_SUCCESS;
1,065,911,677✔
1356
}
1357

1358
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
16,893,084✔
1359
  if (IS_NULL_TYPE(pInput->type)) {
16,893,084✔
1360
    return;
24,640✔
1361
  }
1362
  pOutput->type = pInput->type;
16,868,444✔
1363
  if (pOutput->count == 0) {
16,868,444✔
1364
    pOutput->quadraticDSum += pInput->quadraticDSum;
16,586,773✔
1365
    pOutput->dsum += pInput->dsum;
16,586,773✔
1366
    pOutput->count = pInput->count;
16,586,773✔
1367
  } else if (pInput->count > 0) {
281,671✔
1368
    double totalCount = pOutput->count + pInput->count;
122,442✔
1369
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
122,442✔
1370
    double mean = totalSum / totalCount;
122,442✔
1371

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

1377
    double diff = pInput->dsum - pOutput->dsum;
122,442✔
1378
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pOutput->count * (diff * diff) / totalCount;
122,442✔
1379
    pOutput->dsum = mean;
122,442✔
1380
    pOutput->count += pInput->count;
122,442✔
1381
  }
1382
}
1383

1384
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
16,879,346✔
1385
  SInputColumnInfoData* pInput = &pCtx->input;
16,879,346✔
1386
  SColumnInfoData*      pCol = pInput->pData[0];
16,879,346✔
1387

1388
  if (IS_NULL_TYPE(pCol->info.type)) {
16,879,346✔
1389
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1390
    return TSDB_CODE_SUCCESS;
×
1391
  }
1392

1393
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
16,879,346✔
1394
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1395
  }
1396

1397
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
16,879,346✔
1398

1399
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
33,772,430✔
1400
    if (colDataIsNull_s(pCol, i)) continue;
33,786,168✔
1401
    char*    data = colDataGetData(pCol, i);
16,893,084✔
1402
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
16,893,084✔
1403
    stdTransferInfo(pInputInfo, pInfo);
16,893,084✔
1404
  }
1405

1406
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
16,879,346✔
1407
  return TSDB_CODE_SUCCESS;
16,879,346✔
1408
}
1409

1410
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
503,108,567✔
1411
  SInputColumnInfoData* pInput = &pCtx->input;
503,108,567✔
1412
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
503,108,567✔
1413
  int32_t               type = pStddevRes->type;
503,108,567✔
1414
  double                avg;
1415

1416
  if (pStddevRes->count == 0) {
503,108,567✔
1417
    GET_RES_INFO(pCtx)->numOfRes = 0;
129,018,452✔
1418

1419
    return functionFinalize(pCtx, pBlock);
129,018,452✔
1420
  }
1421

1422
  if (pStddevRes->count == 1) {
374,090,115✔
1423
    pStddevRes->result = 0.0;
265,107,699✔
1424
  } else {
1425
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
108,982,416✔
1426
  }
1427

1428
  // check for overflow
1429
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
374,090,115✔
1430
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1431
  }
1432

1433
  return functionFinalize(pCtx, pBlock);
374,090,115✔
1434
}
1435

1436
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,542,588✔
1437
  SInputColumnInfoData* pInput = &pCtx->input;
6,542,588✔
1438
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,542,588✔
1439
  int32_t               type = pStdvarRes->type;
6,542,588✔
1440
  double                avg;
1441

1442
  if (pStdvarRes->count == 0) {
6,542,588✔
1443
    GET_RES_INFO(pCtx)->numOfRes = 0;
8,358✔
1444
    return functionFinalize(pCtx, pBlock);
8,358✔
1445
  }
1446

1447
  if (pStdvarRes->count == 1) {
6,534,230✔
1448
    pStdvarRes->result = 0.0;
924✔
1449
  } else {
1450
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
6,533,306✔
1451
  }
1452

1453
  // check for overflow
1454
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
6,534,230✔
1455
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1456
  }
1457

1458
  return functionFinalize(pCtx, pBlock);
6,534,230✔
1459
}
1460

1461
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
16,897,494✔
1462
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,897,494✔
1463
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
16,897,494✔
1464
  int32_t              resultBytes = getStdInfoSize();
16,897,494✔
1465
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
16,897,494✔
1466

1467
  if (NULL == res) {
16,897,494✔
1468
    return terrno;
×
1469
  }
1470
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
16,897,494✔
1471
  varDataSetLen(res, resultBytes);
16,897,494✔
1472

1473
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
16,897,494✔
1474
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
16,897,494✔
1475
  if (NULL == pCol) {
16,897,494✔
1476
    taosMemoryFree(res);
×
1477
    return TSDB_CODE_OUT_OF_RANGE;
×
1478
  }
1479

1480
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
16,897,494✔
1481

1482
  taosMemoryFree(res);
16,897,494✔
1483
  return code;
16,897,494✔
1484
}
1485

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

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

1494
  stdTransferInfo(pSBuf, pDBuf);
×
1495

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

1501
int32_t stddevsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,222,925✔
1502
  SInputColumnInfoData* pInput = &pCtx->input;
3,222,925✔
1503
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,222,925✔
1504
  double                avg;
1505

1506
  if (pStddevRes->count == 0) {
3,222,925✔
1507
    GET_RES_INFO(pCtx)->numOfRes = 0;
462✔
1508
    return functionFinalize(pCtx, pBlock);
462✔
1509
  }
1510

1511
  if (pStddevRes->count == 1) {
3,222,463✔
1512
    pStddevRes->result = 0.0;
462✔
1513
  } else {
1514
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / (pStddevRes->count - 1));
3,222,001✔
1515
  }
1516

1517
  // check for overflow
1518
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
3,222,463✔
1519
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1520
  }
1521

1522
  return functionFinalize(pCtx, pBlock);
3,222,463✔
1523
}
1524

1525
int32_t stdvarsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,222,001✔
1526
  SInputColumnInfoData* pInput = &pCtx->input;
3,222,001✔
1527
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,222,001✔
1528
  double                avg;
1529

1530
  if (pStddevRes->count == 0) {
3,222,001✔
1531
    GET_RES_INFO(pCtx)->numOfRes = 0;
462✔
1532
    return functionFinalize(pCtx, pBlock);
462✔
1533
  }
1534

1535
  if (pStddevRes->count == 1) {
3,221,539✔
1536
    pStddevRes->result = 0.0;
462✔
1537
  } else {
1538
    pStddevRes->result = pStddevRes->quadraticDSum / (pStddevRes->count - 1);
3,221,077✔
1539
  }
1540

1541
  // check for overflow
1542
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
3,221,539✔
1543
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1544
  }
1545

1546
  return functionFinalize(pCtx, pBlock);
3,221,539✔
1547
}
1548

1549
bool gconcatGetFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,431✔
1550
  pEnv->calcMemSize = sizeof(SGconcatRes);
1,431✔
1551
  return true;
1,431✔
1552
}
1553

1554
int32_t gconcatFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,431✔
1555
  if (pResultInfo->initialized) {
1,431✔
1556
    return TSDB_CODE_SUCCESS;
×
1557
  }
1558
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,431✔
1559
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1560
  }
1561

1562
  SGconcatRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
1,431✔
1563
  (void)memset(pRes, 0, sizeof(SGconcatRes));
1,431✔
1564

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

1567
  int32_t sepParamIdx = pCtx->numOfParams - 1;
1,431✔
1568
  pRes->separator = pCtx->param[sepParamIdx].param.pz;
1,431✔
1569
  pRes->type = pCtx->param[sepParamIdx].param.nType;
1,431✔
1570

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

1575
  pRes->nchar = (type == TSDB_DATA_TYPE_NCHAR);
1576
  */
1577

1578
  return TSDB_CODE_SUCCESS;
1,431✔
1579
}
1580

1581
static int32_t gconcatHelper(const char* input, char* output, bool hasNchar, int32_t type, VarDataLenT* dataLen,
18,107✔
1582
                             void* charsetCxt) {
1583
  if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) {
18,107✔
1584
    TdUcs4* newBuf = taosMemoryCalloc((varDataLen(input) + 1) * TSDB_NCHAR_SIZE, 1);
×
1585
    if (NULL == newBuf) {
×
1586
      return terrno;
×
1587
    }
1588
    int32_t len = varDataLen(input);
×
1589
    bool    ret =
1590
        taosMbsToUcs4(varDataVal(input), len, newBuf, (varDataLen(input) + 1) * TSDB_NCHAR_SIZE, &len, charsetCxt);
×
1591
    if (!ret) {
×
1592
      taosMemoryFree(newBuf);
×
1593
      return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1594
    }
1595
    (void)memcpy(varDataVal(output) + *dataLen, newBuf, len);
×
1596
    *dataLen += len;
×
1597
    taosMemoryFree(newBuf);
×
1598
  } else {
1599
    (void)memcpy(varDataVal(output) + *dataLen, varDataVal(input), varDataLen(input));
18,107✔
1600
    *dataLen += varDataLen(input);
18,107✔
1601
  }
1602

1603
  return TSDB_CODE_SUCCESS;
18,107✔
1604
}
1605

1606
int32_t gconcatFunction(SqlFunctionCtx* pCtx) {
953✔
1607
  int32_t               code = 0, numOfElem = 0;
953✔
1608
  SInputColumnInfoData* pInput = &pCtx->input;
953✔
1609
  int32_t               rowStart = pInput->startRowIndex;
953✔
1610
  int32_t               numOfRows = pInput->numOfRows;
953✔
1611
  int32_t               numOfCols = pInput->numOfInputCols;
953✔
1612
  SGconcatRes*          pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
953✔
1613
  char*                 sep = pRes->separator;
953✔
1614
  bool                  hasNchar = pRes->nchar;
953✔
1615
  VarDataLenT           dataLen = 0;
953✔
1616
  bool                  prefixSep = false;
953✔
1617

1618
  if (!pRes->result) {
953✔
1619
    pRes->result = taosMemoryCalloc(1, TSDB_MAX_FIELD_LEN);
953✔
1620
    if (!pRes->result) {
953✔
1621
      return terrno;
×
1622
    }
1623

1624
    varDataSetLen(pRes->result, 0);
953✔
1625

1626
    for (int c = 0; c < numOfCols - 1; ++c) {
1,906✔
1627
      SColumnInfoData* pCol = pInput->pData[c];
953✔
1628
      int32_t          type = pCol->info.type;
953✔
1629

1630
      if (TSDB_DATA_TYPE_NCHAR == type) {
953✔
1631
        pRes->nchar = true;
×
1632
      }
1633
    }
1634
  } else {
1635
    dataLen = varDataLen(pRes->result);
×
1636

1637
    prefixSep = true;
×
1638
    /*
1639
    code = gconcatHelper(sep, pRes->result, hasNchar, pRes->type, &dataLen, NULL);
1640
    if (code) {
1641
      goto _over;
1642
    }
1643
    */
1644
  }
1645

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

1650
  sep = colDataGetData(pCol, 0);
953✔
1651
  pRes->type = pCol->info.type;
953✔
1652
  for (int r = rowStart; r < rowStart + numOfRows; ++r) {
10,483✔
1653
    if (prefixSep) {
9,530✔
1654
      // concat the separator
1655
      // setup sepatator's charset instead of the default: pRes->charsetCxt
1656

1657
      code = gconcatHelper(sep, buf, hasNchar, pRes->type, &dataLen, NULL);
8,577✔
1658
      if (code) {
8,577✔
1659
        goto _over;
×
1660
      }
1661
    }
1662

1663
    for (int c = 0; c < numOfCols - 1; ++c) {
19,060✔
1664
      SColumnInfoData* pCol = pInput->pData[c];
9,530✔
1665
      int32_t          type = pCol->info.type;
9,530✔
1666

1667
      if (IS_NULL_TYPE(type) || (pCol->hasNull && colDataIsNull_f(pCol, r))) {
9,530✔
1668
        continue;
×
1669
      }
1670

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

1678
    prefixSep = true;
9,530✔
1679
  }
1680

1681
  varDataSetLen(buf, dataLen);
953✔
1682
  numOfElem += 1;
953✔
1683

1684
_over:
953✔
1685
  // data in the check operation are all null, not output
1686
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
953✔
1687
  return code;
953✔
1688
}
1689

1690
int32_t gconcatFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
953✔
1691
  int32_t               code = 0;
953✔
1692
  SInputColumnInfoData* pInput = &pCtx->input;
953✔
1693
  SGconcatRes*          pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
953✔
1694
  int32_t               slotId = pCtx->pExpr->base.resSchema.slotId;
953✔
1695
  SColumnInfoData*      pCol = taosArrayGet(pBlock->pDataBlock, slotId);
953✔
1696

1697
  if (NULL == pCol) {
953✔
1698
    taosMemoryFree(pRes->result);
×
1699
    return TSDB_CODE_OUT_OF_RANGE;
×
1700
  }
1701

1702
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->result, NULL == pRes->result);
953✔
1703

1704
  taosMemoryFree(pRes->result);
953✔
1705

1706
  return code;
953✔
1707
}
1708

1709
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,107,850✔
1710
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
1,107,850✔
1711
  return true;
1,107,850✔
1712
}
1713

1714
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,138,091✔
1715
  if (pResultInfo->initialized) {
5,138,091✔
1716
    return TSDB_CODE_SUCCESS;
×
1717
  }
1718
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,138,091✔
1719
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1720
  }
1721

1722
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,138,629✔
1723

1724
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
5,138,091✔
1725
                 typeGetTypeModFromCol(pCtx->param[1].pCol));
1726
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
5,138,091✔
1727
                 typeGetTypeModFromCol(pCtx->param[2].pCol));
1728
  return TSDB_CODE_SUCCESS;
5,138,629✔
1729
}
1730

1731
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
6,015,987✔
1732
  int32_t numOfElem = 0;
6,015,987✔
1733

1734
  SInputColumnInfoData* pInput = &pCtx->input;
6,015,987✔
1735
  int32_t               type = pInput->pData[0]->info.type;
6,016,472✔
1736

1737
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,017,010✔
1738

1739
  SColumnInfoData* pCol = pInput->pData[0];
6,015,934✔
1740

1741
  double(*param)[3] = pInfo->matrix;
6,015,396✔
1742
  double x = pInfo->startVal;
6,015,934✔
1743

1744
  int32_t start = pInput->startRowIndex;
6,016,472✔
1745
  int32_t numOfRows = pInput->numOfRows;
6,016,525✔
1746

1747
  switch (type) {
6,014,373✔
1748
    case TSDB_DATA_TYPE_TINYINT: {
436,828✔
1749
      int8_t* plist = (int8_t*)pCol->pData;
436,828✔
1750
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,034,528✔
1751
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,597,700✔
1752
          continue;
270,020✔
1753
        }
1754
        numOfElem++;
18,327,680✔
1755
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,327,680✔
1756
      }
1757
      break;
436,828✔
1758
    }
1759
    case TSDB_DATA_TYPE_SMALLINT: {
436,363✔
1760
      int16_t* plist = (int16_t*)pCol->pData;
436,363✔
1761
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,077,703✔
1762
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,641,340✔
1763
          continue;
369,520✔
1764
        }
1765

1766
        numOfElem++;
18,271,820✔
1767
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,271,820✔
1768
      }
1769
      break;
436,363✔
1770
    }
1771

1772
    case TSDB_DATA_TYPE_INT: {
2,810,146✔
1773
      int32_t* plist = (int32_t*)pCol->pData;
2,810,146✔
1774
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
172,051,837✔
1775
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
169,240,077✔
1776
          continue;
239,354✔
1777
        }
1778

1779
        numOfElem++;
169,000,670✔
1780
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
169,000,670✔
1781
      }
1782
      break;
2,812,783✔
1783
    }
1784

1785
    case TSDB_DATA_TYPE_BIGINT: {
438,944✔
1786
      int64_t* plist = (int64_t*)pCol->pData;
438,944✔
1787
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,036,644✔
1788
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,597,700✔
1789
          continue;
320,820✔
1790
        }
1791

1792
        numOfElem++;
18,276,880✔
1793
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,276,880✔
1794
      }
1795
      break;
438,944✔
1796
    }
1797

1798
    case TSDB_DATA_TYPE_UTINYINT: {
17,384✔
1799
      uint8_t* plist = (uint8_t*)pCol->pData;
17,384✔
1800
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,136,024✔
1801
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,118,640✔
1802
          continue;
10,120✔
1803
        }
1804
        numOfElem++;
18,108,520✔
1805
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,108,520✔
1806
      }
1807
      break;
17,384✔
1808
    }
1809
    case TSDB_DATA_TYPE_USMALLINT: {
17,384✔
1810
      uint16_t* plist = (uint16_t*)pCol->pData;
17,384✔
1811
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,136,024✔
1812
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,118,640✔
1813
          continue;
9,200✔
1814
        }
1815

1816
        numOfElem++;
18,109,440✔
1817
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,109,440✔
1818
      }
1819
      break;
17,384✔
1820
    }
1821

1822
    case TSDB_DATA_TYPE_UINT: {
17,384✔
1823
      uint32_t* plist = (uint32_t*)pCol->pData;
17,384✔
1824
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,136,024✔
1825
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,118,640✔
1826
          continue;
9,200✔
1827
        }
1828

1829
        numOfElem++;
18,109,440✔
1830
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,109,440✔
1831
      }
1832
      break;
17,384✔
1833
    }
1834

1835
    case TSDB_DATA_TYPE_UBIGINT: {
17,384✔
1836
      uint64_t* plist = (uint64_t*)pCol->pData;
17,384✔
1837
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,136,024✔
1838
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,118,640✔
1839
          continue;
9,200✔
1840
        }
1841

1842
        numOfElem++;
18,109,440✔
1843
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,109,440✔
1844
      }
1845
      break;
17,384✔
1846
    }
1847

1848
    case TSDB_DATA_TYPE_FLOAT: {
1,496,903✔
1849
      float* plist = (float*)pCol->pData;
1,496,903✔
1850
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
94,256,743✔
1851
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
92,759,840✔
1852
          continue;
73,815,520✔
1853
        }
1854

1855
        numOfElem++;
18,944,320✔
1856
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,944,320✔
1857
      }
1858
      break;
1,496,903✔
1859
    }
1860

1861
    case TSDB_DATA_TYPE_DOUBLE: {
325,653✔
1862
      double* plist = (double*)pCol->pData;
325,653✔
1863
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,202,373✔
1864
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,876,720✔
1865
          continue;
5,520✔
1866
        }
1867

1868
        numOfElem++;
18,871,200✔
1869
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,871,200✔
1870
      }
1871
      break;
325,653✔
1872
    }
1873
    case TSDB_DATA_TYPE_NULL: {
×
1874
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1875
      numOfElem = 1;
×
1876
      break;
×
1877
    }
1878

1879
    default:
×
1880
      break;
×
1881
  }
1882

1883
  pInfo->startVal = x;
6,017,010✔
1884
  pInfo->num += numOfElem;
6,016,525✔
1885

1886
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,016,525✔
1887

1888
  return TSDB_CODE_SUCCESS;
6,016,525✔
1889
}
1890

1891
int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,137,709✔
1892
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,137,709✔
1893
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,137,709✔
1894
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
5,137,709✔
1895
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5,137,709✔
1896

1897
  if (NULL == pCol) {
5,137,709✔
1898
    return TSDB_CODE_OUT_OF_RANGE;
×
1899
  }
1900
  int32_t currentRow = pBlock->info.rows;
5,137,709✔
1901

1902
  if (0 == pInfo->num) {
5,137,709✔
1903
    colDataSetNULL(pCol, currentRow);
1,642,185✔
1904
    return TSDB_CODE_SUCCESS;
1,642,185✔
1905
  }
1906

1907
  double(*param)[3] = pInfo->matrix;
3,495,524✔
1908

1909
  param[1][1] = (double)pInfo->num;
3,495,524✔
1910
  param[1][0] = param[0][1];
3,495,524✔
1911

1912
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
3,495,524✔
1913
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
3,495,524✔
1914

1915
  if (0 == param00) {
3,495,524✔
1916
    colDataSetNULL(pCol, currentRow);
2,824,204✔
1917
    return TSDB_CODE_SUCCESS;
2,824,204✔
1918
  }
1919

1920
  // param[0][1] = 0;
1921
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
671,320✔
1922
  // param[1][0] = 0;
1923
  param02 /= param00;
671,320✔
1924

1925
  param12 /= param[1][1];
671,320✔
1926

1927
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
671,320✔
1928
  char slopBuf[64] = {0};
671,320✔
1929
  char interceptBuf[64] = {0};
671,320✔
1930
  int  n = snprintf(slopBuf, 64, "%.6lf", param02);
671,320✔
1931
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
671,320✔
1932
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
920✔
1933
  }
1934
  n = snprintf(interceptBuf, 64, "%.6lf", param12);
671,320✔
1935
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
671,320✔
1936
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
1,840✔
1937
  }
1938
  size_t len =
671,320✔
1939
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
671,320✔
1940
  varDataSetLen(buf, len);
671,320✔
1941

1942
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
671,320✔
1943

1944
  return code;
671,320✔
1945
}
1946

1947
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1948
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1949
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1950
  int32_t              type = pDestCtx->input.pData[0]->info.type;
×
1951
  double(*pDparam)[3] = pDBuf->matrix;
×
1952

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

1969
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
87,989✔
1970
  pEnv->calcMemSize = sizeof(SPercentileInfo);
87,989✔
1971
  return true;
87,989✔
1972
}
1973

1974
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
348,318✔
1975
  if (pResultInfo->initialized) {
348,318✔
1976
    return TSDB_CODE_SUCCESS;
×
1977
  }
1978
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
348,318✔
1979
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1980
  }
1981

1982
  // in the first round, get the min-max value of all involved data
1983
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
348,318✔
1984
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
348,318✔
1985
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
348,318✔
1986
  pInfo->numOfElems = 0;
348,318✔
1987

1988
  return TSDB_CODE_SUCCESS;
348,318✔
1989
}
1990

1991
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
88,449✔
1992
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
88,449✔
1993
    return;
×
1994
  }
1995
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
88,449✔
1996
  if (pInfo->pMemBucket != NULL) {
88,449✔
1997
    tMemBucketDestroy(&(pInfo->pMemBucket));
460✔
1998
    pInfo->pMemBucket = NULL;
460✔
1999
  }
2000
}
2001

2002
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
1,741,816✔
2003
  int32_t              code = TSDB_CODE_SUCCESS;
1,741,816✔
2004
  int32_t              numOfElems = 0;
1,741,816✔
2005
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,741,816✔
2006

2007
  SInputColumnInfoData* pInput = &pCtx->input;
1,741,816✔
2008
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
1,741,816✔
2009

2010
  SColumnInfoData* pCol = pInput->pData[0];
1,741,816✔
2011
  int32_t          type = pCol->info.type;
1,741,816✔
2012

2013
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,741,816✔
2014
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
1,741,816✔
2015
    pInfo->stage += 1;
348,318✔
2016

2017
    // all data are null, set it completed
2018
    if (pInfo->numOfElems == 0) {
348,318✔
2019
      pResInfo->complete = true;
43,180✔
2020
      return TSDB_CODE_SUCCESS;
43,180✔
2021
    } else {
2022
      code = tMemBucketCreate(pCol->info.bytes, type, typeGetTypeModFromColInfo(&pCol->info), pInfo->minval,
305,138✔
2023
                              pInfo->maxval, pCtx->hasWindowOrGroup, &pInfo->pMemBucket, pInfo->numOfElems);
305,138✔
2024
      if (TSDB_CODE_SUCCESS != code) {
305,138✔
2025
        return code;
×
2026
      }
2027
    }
2028
  }
2029

2030
  // the first stage, only acquire the min/max value
2031
  if (pInfo->stage == 0) {
1,698,636✔
2032
    if (pCtx->input.colDataSMAIsSet) {
874,718✔
2033
      double tmin = 0.0, tmax = 0.0;
×
2034
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
2035
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
2036
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
2037
      } else if (IS_FLOAT_TYPE(type)) {
×
2038
        tmin = GET_DOUBLE_VAL(&pAgg->min);
×
2039
        tmax = GET_DOUBLE_VAL(&pAgg->max);
×
2040
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
2041
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
2042
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
2043
      }
2044

2045
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
×
2046
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
×
2047
      }
2048

2049
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
×
2050
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
×
2051
      }
2052

2053
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
×
2054
    } else {
2055
      // check the valid data one by one
2056
      int32_t start = pInput->startRowIndex;
874,718✔
2057
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,018,042✔
2058
        if (colDataIsNull_f(pCol, i)) {
17,143,324✔
2059
          continue;
81,160✔
2060
        }
2061

2062
        char* data = colDataGetData(pCol, i);
17,062,164✔
2063

2064
        double v = 0;
17,062,164✔
2065
        GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
17,062,164✔
2066
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
17,062,164✔
2067
          SET_DOUBLE_VAL(&pInfo->minval, v);
331,304✔
2068
        }
2069

2070
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
17,062,164✔
2071
          SET_DOUBLE_VAL(&pInfo->maxval, v);
13,677,502✔
2072
        }
2073

2074
        pInfo->numOfElems += 1;
17,062,164✔
2075
      }
2076
    }
2077
  } else {
2078
    // the second stage, calculate the true percentile value
2079
    int32_t start = pInput->startRowIndex;
823,918✔
2080
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
17,858,482✔
2081
      if (colDataIsNull_f(pCol, i)) {
17,035,024✔
2082
        continue;
×
2083
      }
2084

2085
      char* data = colDataGetData(pCol, i);
17,035,024✔
2086
      numOfElems += 1;
17,035,024✔
2087
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
17,035,024✔
2088
      if (code != TSDB_CODE_SUCCESS) {
17,035,024✔
2089
        tMemBucketDestroy(&(pInfo->pMemBucket));
460✔
2090
        return code;
460✔
2091
      }
2092
    }
2093

2094
    SET_VAL(pResInfo, numOfElems, 1);
823,458✔
2095
  }
2096

2097
  pCtx->needCleanup = true;
1,698,176✔
2098
  return TSDB_CODE_SUCCESS;
1,698,176✔
2099
}
2100

2101
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
347,398✔
2102
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
347,398✔
2103
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
347,398✔
2104

2105
  int32_t code = 0;
347,398✔
2106
  double  v = 0;
347,398✔
2107

2108
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
347,398✔
2109
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
347,398✔
2110
    if (pCtx->numOfParams > 2) {
304,218✔
2111
      char buf[3200] = {0};
2,760✔
2112
      // max length of double num is 317, e.g. use %.6lf to print -1.0e+308, consider the comma and bracket, 3200 is
2113
      // enough.
2114
      size_t len = 1;
2,760✔
2115

2116
      varDataVal(buf)[0] = '[';
2,760✔
2117
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
30,360✔
2118
        SVariant* pVal = &pCtx->param[i].param;
27,600✔
2119

2120
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[i].pCol));
27,600✔
2121

2122
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
27,600✔
2123
        if (code != TSDB_CODE_SUCCESS) {
27,600✔
2124
          goto _fin_error;
×
2125
        }
2126

2127
        if (i == pCtx->numOfParams - 1) {
27,600✔
2128
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
2,760✔
2129
        } else {
2130
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
24,840✔
2131
        }
2132
      }
2133

2134
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,760✔
2135
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,760✔
2136
      if (NULL == pCol) {
2,760✔
2137
        code = terrno;
×
2138
        goto _fin_error;
×
2139
      }
2140

2141
      varDataSetLen(buf, len);
2,760✔
2142
      code = colDataSetVal(pCol, pBlock->info.rows, buf, false);
2,760✔
2143
      if (code != TSDB_CODE_SUCCESS) {
2,760✔
2144
        goto _fin_error;
×
2145
      }
2146

2147
      tMemBucketDestroy(pMemBucket);
2,760✔
2148
      return TSDB_CODE_SUCCESS;
2,760✔
2149
    } else {
2150
      SVariant* pVal = &pCtx->param[1].param;
301,458✔
2151

2152
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
301,458✔
2153

2154
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
301,458✔
2155
      if (code != TSDB_CODE_SUCCESS) {
301,458✔
2156
        goto _fin_error;
×
2157
      }
2158

2159
      tMemBucketDestroy(pMemBucket);
301,458✔
2160
      return functionFinalize(pCtx, pBlock);
301,458✔
2161
    }
2162
  } else {
2163
    return functionFinalize(pCtx, pBlock);
43,180✔
2164
  }
2165

2166
_fin_error:
×
2167

2168
  tMemBucketDestroy(pMemBucket);
×
2169
  return code;
×
2170
}
2171

2172
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
3,329,758✔
2173
  int32_t bytesHist =
3,329,758✔
2174
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2175
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
3,329,758✔
2176
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
3,329,758✔
2177
  return true;
3,330,296✔
2178
}
2179

2180
int32_t getApercentileMaxSize() {
379,810✔
2181
  int32_t bytesHist =
379,810✔
2182
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2183
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
379,810✔
2184
  return TMAX(bytesHist, bytesDigest);
379,810✔
2185
}
2186

2187
static int8_t getApercentileAlgo(char* algoStr) {
3,022,186✔
2188
  int8_t algoType;
2189
  if (strcasecmp(algoStr, "default") == 0) {
3,022,186✔
2190
    algoType = APERCT_ALGO_DEFAULT;
1,509,438✔
2191
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,512,748✔
2192
    algoType = APERCT_ALGO_TDIGEST;
1,512,748✔
2193
  } else {
2194
    algoType = APERCT_ALGO_UNKNOWN;
×
2195
  }
2196

2197
  return algoType;
3,022,186✔
2198
}
2199

2200
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
100,279,509✔
2201
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
100,279,509✔
2202
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
100,298,813✔
2203
}
100,300,845✔
2204

2205
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
3,038,521✔
2206
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
3,038,521✔
2207
}
3,038,521✔
2208

2209
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
32,399,829✔
2210
  if (pResultInfo->initialized) {
32,399,829✔
2211
    return TSDB_CODE_SUCCESS;
×
2212
  }
2213
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
32,404,909✔
2214
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2215
  }
2216

2217
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
32,407,957✔
2218

2219
  SVariant* pVal = &pCtx->param[1].param;
32,408,465✔
2220
  pInfo->percent = 0;
32,411,005✔
2221
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
32,411,005✔
2222

2223
  if (pCtx->numOfParams == 2) {
32,413,037✔
2224
    pInfo->algo = APERCT_ALGO_DEFAULT;
29,389,835✔
2225
  } else if (pCtx->numOfParams == 3) {
3,022,186✔
2226
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
3,022,186✔
2227
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
3,022,186✔
2228
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2229
    }
2230
  }
2231

2232
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
32,412,021✔
2233
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
32,401,861✔
2234
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,512,748✔
2235
  } else {
2236
    buildHistogramInfo(pInfo);
30,886,065✔
2237
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
30,895,602✔
2238
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
30,898,257✔
2239
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2240
  }
2241

2242
  return TSDB_CODE_SUCCESS;
32,413,545✔
2243
}
2244

2245
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
42,037,392✔
2246
  int32_t               numOfElems = 0;
42,037,392✔
2247
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
42,037,392✔
2248
  SInputColumnInfoData* pInput = &pCtx->input;
42,037,392✔
2249

2250
  SColumnInfoData* pCol = pInput->pData[0];
42,037,392✔
2251
  int32_t          type = pCol->info.type;
42,037,392✔
2252

2253
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
42,037,392✔
2254

2255
  int32_t start = pInput->startRowIndex;
42,037,392✔
2256
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
42,037,392✔
2257
    buildTDigestInfo(pInfo);
1,511,745✔
2258
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,512,283✔
2259
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
78,733,762✔
2260
      if (colDataIsNull_f(pCol, i)) {
77,225,245✔
2261
        continue;
36,800,817✔
2262
      }
2263
      numOfElems += 1;
40,423,352✔
2264
      char* data = colDataGetData(pCol, i);
40,423,352✔
2265

2266
      double  v = 0;  // value
40,423,890✔
2267
      int64_t w = 1;  // weigth
40,423,890✔
2268
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
40,423,890✔
2269
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
40,423,352✔
2270
      if (code != TSDB_CODE_SUCCESS) {
40,420,662✔
2271
        return code;
×
2272
      }
2273
    }
2274
  } else {
2275
    // might be a race condition here that pHisto can be overwritten or setup function
2276
    // has not been called, need to relink the buffer pHisto points to.
2277
    buildHistogramInfo(pInfo);
40,525,109✔
2278
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
40,525,109✔
2279
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2280
           pInfo->pHisto->elems);
2281
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
2282
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
2283
        continue;
1,413,416,712✔
2284
      }
2285
      numOfElems += 1;
889,952,500✔
2286
      char* data = colDataGetData(pCol, i);
889,952,500✔
2287

2288
      double v = 0;
890,779,487✔
2289
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
890,779,487✔
2290
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
890,779,487✔
2291
      if (code != TSDB_CODE_SUCCESS) {
887,337,920✔
2292
        return code;
×
2293
      }
2294
    }
2295

2296
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
40,525,109✔
2297
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2298
           pInfo->pHisto->elems);
2299
  }
2300

2301
  SET_VAL(pResInfo, numOfElems, 1);
41,998,276✔
2302
  return TSDB_CODE_SUCCESS;
42,037,392✔
2303
}
2304

2305
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
245,288✔
2306
  pOutput->percent = pInput->percent;
245,288✔
2307
  pOutput->algo = pInput->algo;
245,288✔
2308
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
245,288✔
2309
    buildTDigestInfo(pInput);
14,415✔
2310
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
14,415✔
2311

2312
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
14,415✔
2313
      return TSDB_CODE_SUCCESS;
465✔
2314
    }
2315

2316
    if (hasRes) {
13,950✔
2317
      *hasRes = true;
13,950✔
2318
    }
2319

2320
    buildTDigestInfo(pOutput);
13,950✔
2321
    TDigest* pTDigest = pOutput->pTDigest;
13,950✔
2322
    tdigestAutoFill(pTDigest, COMPRESSION);
13,950✔
2323

2324
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
13,950✔
2325
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
13,950✔
2326
      tdigestAutoFill(pTDigest, COMPRESSION);
13,950✔
2327
    } else {
2328
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
×
2329
      if (TSDB_CODE_SUCCESS != code) {
×
2330
        return code;
×
2331
      }
2332
    }
2333
  } else {
2334
    buildHistogramInfo(pInput);
230,873✔
2335
    if (pInput->pHisto->numOfElems <= 0) {
230,873✔
2336
      return TSDB_CODE_SUCCESS;
107,892✔
2337
    }
2338

2339
    if (hasRes) {
122,981✔
2340
      *hasRes = true;
122,981✔
2341
    }
2342

2343
    buildHistogramInfo(pOutput);
122,981✔
2344
    SHistogramInfo* pHisto = pOutput->pHisto;
122,981✔
2345

2346
    if (pHisto->numOfElems <= 0) {
122,981✔
2347
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
109,373✔
2348
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
109,373✔
2349

2350
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
109,373✔
2351
             pHisto);
2352
    } else {
2353
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
13,608✔
2354
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
13,608✔
2355
             pHisto->numOfEntries, pInput->pHisto);
2356

2357
      SHistogramInfo* pRes = NULL;
13,608✔
2358
      int32_t         code = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN, &pRes);
13,608✔
2359
      if (TSDB_CODE_SUCCESS != code) {
13,608✔
2360
        tHistogramDestroy(&pRes);
×
2361
        return code;
×
2362
      }
2363
      (void)memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
13,608✔
2364
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
13,608✔
2365

2366
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
13,608✔
2367
             pHisto);
2368
      tHistogramDestroy(&pRes);
13,608✔
2369
    }
2370
  }
2371
  return TSDB_CODE_SUCCESS;
136,931✔
2372
}
2373

2374
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
242,662✔
2375
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
242,662✔
2376

2377
  SInputColumnInfoData* pInput = &pCtx->input;
242,662✔
2378

2379
  SColumnInfoData* pCol = pInput->pData[0];
242,662✔
2380
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
242,662✔
2381
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2382
  }
2383

2384
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
242,662✔
2385

2386
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
242,662✔
2387

2388
  bool    hasRes = false;
242,662✔
2389
  int32_t start = pInput->startRowIndex;
242,662✔
2390
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
487,950✔
2391
    char* data = colDataGetData(pCol, i);
245,288✔
2392

2393
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
245,288✔
2394
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
245,288✔
2395
    if (TSDB_CODE_SUCCESS != code) {
245,288✔
2396
      return code;
×
2397
    }
2398
  }
2399

2400
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
242,662✔
2401
    buildHistogramInfo(pInfo);
228,247✔
2402
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
228,247✔
2403
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2404
  }
2405

2406
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
242,662✔
2407
  return TSDB_CODE_SUCCESS;
242,662✔
2408
}
2409

2410
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
29,799,855✔
2411
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
29,799,855✔
2412
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
29,800,363✔
2413

2414
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
29,800,871✔
2415
    buildTDigestInfo(pInfo);
1,497,873✔
2416
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,497,873✔
2417
    if (pInfo->pTDigest->size > 0) {
1,497,873✔
2418
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,497,873✔
2419
    } else {  // no need to free
2420
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2421
      return TSDB_CODE_SUCCESS;
×
2422
    }
2423
  } else {
2424
    buildHistogramInfo(pInfo);
28,302,998✔
2425
    if (pInfo->pHisto->numOfElems > 0) {
28,297,918✔
2426
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
18,601,529✔
2427
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2428

2429
      double  ratio[] = {pInfo->percent};
18,607,625✔
2430
      double* res = NULL;
18,608,133✔
2431
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
18,608,133✔
2432
      if (TSDB_CODE_SUCCESS != code) {
18,607,117✔
2433
        taosMemoryFree(res);
×
2434
        return code;
×
2435
      }
2436
      pInfo->result = *res;
18,607,117✔
2437
      // memcpy(pCtx->pOutput, res, sizeof(double));
2438
      taosMemoryFree(res);
18,607,625✔
2439
    } else {  // no need to free
2440
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2441
      // return TSDB_CODE_SUCCESS;
2442
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
9,698,929✔
2443
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2444
    }
2445
  }
2446

2447
  return functionFinalize(pCtx, pBlock);
29,804,427✔
2448
}
2449

2450
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
245,288✔
2451
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
245,288✔
2452
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
245,288✔
2453

2454
  int32_t resultBytes = getApercentileMaxSize();
245,288✔
2455
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
245,288✔
2456
  if (NULL == res) {
245,288✔
2457
    return terrno;
×
2458
  }
2459

2460
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
245,288✔
2461
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
14,415✔
2462
    varDataSetLen(res, resultBytes);
14,415✔
2463
  } else {
2464
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
230,873✔
2465
    varDataSetLen(res, resultBytes);
230,873✔
2466
  }
2467

2468
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
245,288✔
2469
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
245,288✔
2470
  if (NULL == pCol) {
245,288✔
2471
    taosMemoryFree(res);
×
2472
    return TSDB_CODE_OUT_OF_RANGE;
×
2473
  }
2474

2475
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
245,288✔
2476

2477
  taosMemoryFree(res);
245,288✔
2478
  return code;
245,288✔
2479
}
2480

2481
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
2482
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
2483
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
2484

2485
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
2486
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
2487

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

2490
  int32_t code = apercentileTransferInfo(pSBuf, pDBuf, NULL);
×
2491
  if (TSDB_CODE_SUCCESS != code) {
×
2492
    return code;
×
2493
  }
2494
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
2495
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
2496
  return TSDB_CODE_SUCCESS;
×
2497
}
2498

2499
// TODO: change this function when block data info pks changed
2500
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
398,638✔
2501
  char numVal[8] = {0};
398,638✔
2502
  switch (pkType) {
398,638✔
2503
    case TSDB_DATA_TYPE_INT:
81,056✔
2504
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
81,056✔
2505
      break;
81,056✔
2506
    case TSDB_DATA_TYPE_UINT:
54,788✔
2507
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
54,788✔
2508
      break;
54,788✔
2509
    case TSDB_DATA_TYPE_BIGINT:
72,156✔
2510
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
72,156✔
2511
      break;
72,156✔
2512
    case TSDB_DATA_TYPE_UBIGINT:
72,156✔
2513
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
72,156✔
2514
      break;
72,156✔
2515
    default:
118,482✔
2516
      break;
118,482✔
2517
  }
2518
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
398,638✔
2519
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
398,638✔
2520
  return fn(pkData, blockData);
398,638✔
2521
}
2522

2523
EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
2,147,483,647✔
2524
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
2,147,483,647✔
2525

2526
  // not initialized yet, data is required
2527
  if (pEntry == NULL) {
2,147,483,647✔
2528
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2529
  }
2530

2531
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
2,147,483,647✔
2532
  if (pResult->hasResult) {
2,147,483,647✔
2533
    if (pResult->pkBytes > 0) {
2,147,483,647✔
2534
      pResult->pkData = pResult->buf + pResult->bytes;
288,496✔
2535
    } else {
2536
      pResult->pkData = NULL;
2,147,483,647✔
2537
    }
2538
    if (pResult->ts < pBlockInfo->window.skey) {
2,147,483,647✔
2539
      return FUNC_DATA_REQUIRED_NOT_LOAD;
2,796,901✔
2540
    } else if (pResult->ts == pBlockInfo->window.skey) {
2,147,483,647✔
2541
      if (NULL == pResult->pkData) {
2,147,483,647✔
2542
        return FUNC_DATA_REQUIRED_NOT_LOAD;
2,147,483,647✔
2543
      }
2544
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
191,872✔
2545
        return FUNC_DATA_REQUIRED_NOT_LOAD;
24,186✔
2546
      }
2547
    }
2548
    return FUNC_DATA_REQUIRED_DATA_LOAD;
375,713✔
2549
  } else {
2550
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,188,035✔
2551
  }
2552
}
2553

2554
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
28,339,533✔
2555
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
28,339,533✔
2556

2557
  // not initialized yet, data is required
2558
  if (pEntry == NULL) {
28,339,533✔
2559
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2560
  }
2561

2562
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
28,339,533✔
2563
  if (pResult->hasResult) {
28,361,607✔
2564
    if (pResult->pkBytes > 0) {
26,233,602✔
2565
      pResult->pkData = pResult->buf + pResult->bytes;
448,326✔
2566
    } else {
2567
      pResult->pkData = NULL;
25,785,263✔
2568
    }
2569
    if (pResult->ts > pBlockInfo->window.ekey) {
26,234,460✔
2570
      return FUNC_DATA_REQUIRED_NOT_LOAD;
7,601,860✔
2571
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
18,632,158✔
2572
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
206,766✔
2573
        return FUNC_DATA_REQUIRED_NOT_LOAD;
64,133✔
2574
      }
2575
    }
2576
    return FUNC_DATA_REQUIRED_DATA_LOAD;
18,566,296✔
2577
  } else {
2578
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,128,813✔
2579
  }
2580
}
2581

2582
// TODO modify it to include primary key bytes
2583
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
1,830,472,606✔
2584

2585
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
61,429,797✔
2586
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
61,429,797✔
2587
  // TODO: change SFunctionNode to add pk info
2588
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
61,435,872✔
2589
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
61,434,220✔
2590
  return true;
61,434,000✔
2591
}
2592

2593
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
15,728,963✔
2594
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
15,728,963✔
2595
  pEnv->calcMemSize = pNode->node.resType.bytes;
15,730,299✔
2596
  return true;
15,728,521✔
2597
}
2598

2599

2600
bool getHasNullFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
21,663,094✔
2601
  pEnv->calcMemSize = pFunc->node.resType.bytes;
21,663,094✔
2602
  return true;
21,663,094✔
2603
}
2604

2605
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
62,022,204✔
2606
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
62,022,204✔
2607
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
62,025,665✔
2608
  return true;
62,017,630✔
2609
}
2610

2611
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2612
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
2,147,483,647✔
2613
    return 0;
×
2614
  }
2615

2616
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
2,147,483,647✔
2617
}
2618

2619
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,147,483,647✔
2620
  if (pResInfo->initialized) {
2,147,483,647✔
2621
    return TSDB_CODE_SUCCESS;
×
2622
  }
2623
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,147,483,647✔
2624
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2625
  }
2626

2627
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2628
  pRes->nullTupleSaved = false;
2,147,483,647✔
2629
  pRes->nullTuplePos.pageId = -1;
2,147,483,647✔
2630
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2631
}
2632

2633
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
118,061,491✔
2634
  if (pCtx->subsidiaries.rowLen == 0) {
118,061,491✔
2635
    int32_t rowLen = 0;
5,331,190✔
2636
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
12,451,753✔
2637
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
7,121,401✔
2638
      rowLen += pc->pExpr->base.resSchema.bytes;
7,120,120✔
2639
    }
2640

2641
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
5,332,720✔
2642
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
5,333,790✔
2643
    if (NULL == pCtx->subsidiaries.buf) {
5,334,470✔
2644
      return terrno;
×
2645
    }
2646
  }
2647
  return TSDB_CODE_SUCCESS;
118,061,717✔
2648
}
2649

2650
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
2,147,483,647✔
2651
                                      SFirstLastRes* pInfo, bool noElements) {
2652
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
2653

2654
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
2655
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
2656
  }
2657

2658
  if (!pInfo->hasResult) {
75,236,203✔
2659
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
60,975,065✔
2660
  } else if (!noElements) {
14,261,138✔
2661
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
14,246,348✔
2662
  } else {
2663
  }  // dothing
2664

2665
  return code;
75,235,532✔
2666
}
2667

2668
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
2,147,483,647✔
2669
                                char* pData) {
2670
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2671
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2672

2673
  if (IS_VAR_DATA_TYPE(type)) {
2,147,483,647✔
2674
    pInfo->bytes = calcStrBytesByType(type, pData);
2,147,483,647✔
2675
    // if (type == TSDB_DATA_TYPE_JSON) {
2676
    //   pInfo->bytes = getJsonValueLen(pData);
2677
    // } else {
2678
    //   pInfo->bytes = varDataTLen(pData);
2679
    // }
2680
  }
2681

2682
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
2,147,483,647✔
2683
  if (pkData != NULL) {
2,147,483,647✔
2684
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
181,147,767✔
2685
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
60,258,507✔
2686
      // if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
2687
      //   pInfo->pkBytes = getJsonValueLen(pkData);
2688
      // } else {
2689
      //   pInfo->pkBytes = varDataTLen(pkData);
2690
      // }
2691
    }
2692
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
181,143,958✔
2693
    pInfo->pkData = pInfo->buf + pInfo->bytes;
181,134,998✔
2694
  }
2695

2696
  pInfo->ts = currentTs;
2,147,483,647✔
2697
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
2,147,483,647✔
2698
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2699
    return code;
×
2700
  }
2701

2702
  pInfo->hasResult = true;
2,147,483,647✔
2703
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2704
}
2705

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

2711
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2712
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2713

2714
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2715
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2716

2717
  pInfo->bytes = pInputCol->info.bytes;
2,147,483,647✔
2718

2719
  if (IS_NULL_TYPE(pInputCol->info.type)) {
2,147,483,647✔
2720
    return TSDB_CODE_SUCCESS;
170,596,292✔
2721
  }
2722

2723
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2724
  pInfo->pkType = -1;
2,147,483,647✔
2725
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2726
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2727
    pInfo->pkType = pkCol->info.type;
10,454,810✔
2728
    pInfo->pkBytes = pkCol->info.bytes;
10,453,530✔
2729
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
10,455,481✔
2730
  }
2731

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

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

2746
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2747
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2748

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

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

2762
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2763
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2764
        continue;
2765
      }
2766

2767
      numOfElems++;
2768

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

2785
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2786
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2787
        continue;
2788
      }
2789

2790
      numOfElems++;
2791

2792
      char* data = colDataGetData(pInputCol, i);
2793
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2794

2795
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2796
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2797
        break;
2798
      }
2799
    }
2800
  }
2801
#else
2802
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2803

2804
  int     from = -1;
2,147,483,647✔
2805
  int32_t i = -1;
2,147,483,647✔
2806
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
2,147,483,647✔
2807
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2,147,483,647✔
2808
      continue;
2,147,483,647✔
2809
    }
2810

2811
    numOfElems++;
2,147,483,647✔
2812
    char* data = colDataGetData(pInputCol, i);
2,147,483,647✔
2813
    char* pkData = NULL;
2,147,483,647✔
2814
    if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2815
      pkData = colDataGetData(pkCol, i);
187,212,910✔
2816
    }
2817
    TSKEY cts = pts[i];
2,147,483,647✔
2818
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
2,147,483,647✔
2819
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
2,147,483,647✔
2820
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
2,147,483,647✔
2821
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2822
        return code;
×
2823
      }
2824
      pResInfo->numOfRes = 1;
2,147,483,647✔
2825
    }
2826
  }
2827
#endif
2828

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

2841
int32_t lastFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
2842
  int32_t numOfElems = 0;
2,147,483,647✔
2843

2844
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2845
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2846

2847
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2848
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2849

2850
  int32_t type = pInputCol->info.type;
2,147,483,647✔
2851
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
2852

2853
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
2854
    return TSDB_CODE_SUCCESS;
170,580,669✔
2855
  }
2856
  pInfo->bytes = bytes;
2,147,483,647✔
2857

2858
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2859
  pInfo->pkType = -1;
2,147,483,647✔
2860
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2861
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2862
    pInfo->pkType = pkCol->info.type;
10,544,920✔
2863
    pInfo->pkBytes = pkCol->info.bytes;
10,546,809✔
2864
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
10,544,889✔
2865
  }
2866

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

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

2881
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2882
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2883

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

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

2894
      numOfElems++;
2895

2896
      char* data = colDataGetData(pInputCol, i);
2897
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2898
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2899
        doSaveCurrentVal(pCtx, i, cts, type, data);
2900
      }
2901

2902
      break;
2903
    }
2904
  } else {  // descending order
2905
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2906
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2907
        continue;
2908
      }
2909

2910
      numOfElems++;
2911

2912
      char* data = colDataGetData(pInputCol, i);
2913
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2914
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2915
        doSaveCurrentVal(pCtx, i, cts, type, data);
2916
      }
2917
      break;
2918
    }
2919
  }
2920
#else
2921
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2922

2923
#if 0
2924
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2925
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2926
        continue;
2927
      }
2928

2929
      numOfElems++;
2930
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2931
        char* data = colDataGetData(pInputCol, i);
2932
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2933
        pResInfo->numOfRes = 1;
2934
      }
2935
    }
2936
#else
2937

2938
  // todo refactor
2939
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
2,147,483,647✔
2940
    numOfElems = 1;
2,147,483,647✔
2941

2942
    int32_t round = pInput->numOfRows >> 2;
2,147,483,647✔
2943
    int32_t reminder = pInput->numOfRows & 0x03;
2,147,483,647✔
2944

2945
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
2,147,483,647✔
2946
      int64_t cts = pts[i];
410,781,983✔
2947
      int32_t chosen = i;
410,781,663✔
2948

2949
      if (cts < pts[i + 1]) {
410,781,663✔
2950
        cts = pts[i + 1];
137,245,247✔
2951
        chosen = i + 1;
137,245,247✔
2952
      }
2953

2954
      if (cts < pts[i + 2]) {
410,784,332✔
2955
        cts = pts[i + 2];
137,245,514✔
2956
        chosen = i + 2;
137,245,514✔
2957
      }
2958

2959
      if (cts < pts[i + 3]) {
410,774,548✔
2960
        cts = pts[i + 3];
137,243,928✔
2961
        chosen = i + 3;
137,243,928✔
2962
      }
2963

2964
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
410,781,797✔
2965
        char*   data = colDataGetData(pInputCol, chosen);
165,561,280✔
2966
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
165,563,503✔
2967
        if (code != TSDB_CODE_SUCCESS) {
165,561,175✔
2968
          return code;
×
2969
        }
2970
        pResInfo->numOfRes = 1;
165,561,175✔
2971
      }
2972
    }
2973

2974
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,147,483,647✔
2975
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2,147,483,647✔
2976
        char*   data = colDataGetData(pInputCol, i);
918,406,569✔
2977
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
914,444,141✔
2978
        if (code != TSDB_CODE_SUCCESS) {
914,512,159✔
2979
          return code;
×
2980
        }
2981
        pResInfo->numOfRes = 1;
914,512,159✔
2982
      }
2983
    }
2984
  } else {
2985
    int     from = -1;
2,147,483,647✔
2986
    int32_t i = -1;
2,147,483,647✔
2987
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
2,147,483,647✔
2988
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2,147,483,647✔
2989
        continue;
2,147,483,647✔
2990
      }
2991

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

3013
#endif
3014

3015
  // save selectivity value for column consisted of all null values
3016
  if (numOfElems == 0) {
2,147,483,647✔
3017
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
2,147,483,647✔
3018
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3019
      return code;
×
3020
    }
3021
    pInfo->nullTupleSaved = true;
2,147,483,647✔
3022
  }
3023

3024
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3025
}
3026

3027
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
1,408,726,049✔
3028
  if (!pInput->hasResult) {
1,408,726,049✔
3029
    return false;
×
3030
  }
3031
  __compar_fn_t pkCompareFn = NULL;
1,408,726,049✔
3032
  if (pInput->pkData) {
1,408,726,049✔
3033
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
4,306,481✔
3034
  }
3035
  if (pOutput->hasResult) {
1,408,727,017✔
3036
    if (isFirst) {
769,799,623✔
3037
      if (pInput->ts > pOutput->ts ||
672,416,288✔
3038
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
671,499,393✔
3039
        return false;
1,043,153✔
3040
      }
3041
    } else {
3042
      if (pInput->ts < pOutput->ts ||
97,383,335✔
3043
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
95,896,976✔
3044
        return false;
1,642,671✔
3045
      }
3046
    }
3047
  }
3048

3049
  pOutput->isNull = pInput->isNull;
1,406,040,951✔
3050
  pOutput->ts = pInput->ts;
1,406,040,467✔
3051
  pOutput->bytes = pInput->bytes;
1,406,041,193✔
3052
  pOutput->pkType = pInput->pkType;
1,406,040,709✔
3053

3054
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,406,041,193✔
3055
  if (pInput->pkData) {
1,406,041,435✔
3056
    pOutput->pkBytes = pInput->pkBytes;
3,917,222✔
3057
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
3,917,222✔
3058
    pOutput->pkData = pOutput->buf + pOutput->bytes;
3,917,222✔
3059
  }
3060
  return true;
1,406,042,403✔
3061
}
3062

3063
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,408,725,081✔
3064
                                     int32_t rowIndex) {
3065
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,408,725,081✔
3066
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,406,042,403✔
3067
    if (TSDB_CODE_SUCCESS != code) {
1,406,043,371✔
3068
      return code;
×
3069
    }
3070
    pOutput->hasResult = true;
1,406,043,371✔
3071
  }
3072
  return TSDB_CODE_SUCCESS;
1,408,729,195✔
3073
}
3074

3075
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
654,447,559✔
3076
  SInputColumnInfoData* pInput = &pCtx->input;
654,447,559✔
3077
  SColumnInfoData*      pCol = pInput->pData[0];
654,448,043✔
3078

3079
  if (IS_NULL_TYPE(pCol->info.type)) {
654,448,769✔
3080
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
3081
    return TSDB_CODE_SUCCESS;
×
3082
  }
3083

3084
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
654,448,527✔
3085
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3086
  }
3087

3088
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
654,448,527✔
3089

3090
  int32_t start = pInput->startRowIndex;
654,448,285✔
3091
  int32_t numOfElems = 0;
654,448,527✔
3092

3093
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,147,483,647✔
3094
    if (colDataIsNull_s(pCol, i)) {
2,147,483,647✔
3095
      continue;
240,368,804✔
3096
    }
3097
    char*          data = colDataGetData(pCol, i);
1,408,725,807✔
3098
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,408,727,017✔
3099
    if (pCtx->hasPrimaryKey) {
1,408,726,291✔
3100
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
4,306,481✔
3101
    } else {
3102
      pInputInfo->pkData = NULL;
1,404,420,294✔
3103
    }
3104

3105
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,408,725,323✔
3106
    if (code != TSDB_CODE_SUCCESS) {
1,408,729,195✔
3107
      return code;
×
3108
    }
3109
    if (!numOfElems) {
1,408,729,195✔
3110
      numOfElems = pInputInfo->hasResult ? 1 : 0;
650,511,519✔
3111
    }
3112
  }
3113

3114
  if (numOfElems == 0) {
654,445,623✔
3115
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
3,937,250✔
3116
    if (code != TSDB_CODE_SUCCESS) {
3,937,250✔
3117
      return code;
×
3118
    }
3119
    pInfo->nullTupleSaved = true;
3,937,250✔
3120
  }
3121

3122
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
654,445,139✔
3123
  return TSDB_CODE_SUCCESS;
654,445,623✔
3124
}
3125

3126
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
381,901,479✔
3127

3128
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
272,547,048✔
3129

3130
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
3131
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3132
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
3133
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
3134
  if (NULL == pCol) {
2,147,483,647✔
3135
    return TSDB_CODE_OUT_OF_RANGE;
×
3136
  }
3137

3138
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3139
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,147,483,647✔
3140

3141
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3142

3143
  if (pResInfo->isNullRes) {
2,147,483,647✔
3144
    colDataSetNULL(pCol, pBlock->info.rows);
2,004,640,714✔
3145
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,004,640,714✔
3146
  }
3147
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
2,147,483,647✔
3148
  if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3149
    return code;
×
3150
  }
3151

3152
  // handle selectivity
3153
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
2,147,483,647✔
3154
  if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3155
    qError("%s failed at %d, msg:%s", __func__, __LINE__, tstrerror(code));
×
3156
  }
3157

3158
  return code;
2,147,483,647✔
3159
}
3160

3161
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,752,055,922✔
3162
  int32_t code = TSDB_CODE_SUCCESS;
1,752,055,922✔
3163

3164
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,752,055,922✔
3165
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,752,711,356✔
3166

3167
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,752,711,740✔
3168

3169
  // todo check for failure
3170
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,752,479,256✔
3171
  if (NULL == res) {
1,748,600,894✔
3172
    return terrno;
×
3173
  }
3174
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,748,600,894✔
3175

3176
  varDataSetLen(res, resultBytes);
1,748,613,440✔
3177

3178
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,752,203,808✔
3179
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,752,435,802✔
3180
  if (NULL == pCol) {
1,752,244,407✔
3181
    taosMemoryFree(res);
×
3182
    return TSDB_CODE_OUT_OF_RANGE;
×
3183
  }
3184

3185
  if (pEntryInfo->numOfRes == 0) {
1,752,244,407✔
3186
    colDataSetNULL(pCol, pBlock->info.rows);
250,630,816✔
3187
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
250,621,358✔
3188
  } else {
3189
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,501,745,953✔
3190
    if (TSDB_CODE_SUCCESS != code) {
1,501,824,691✔
3191
      taosMemoryFree(res);
×
3192
      return code;
×
3193
    }
3194
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,501,824,691✔
3195
  }
3196
  taosMemoryFree(res);
1,752,039,657✔
3197
  return code;
1,752,270,151✔
3198
}
3199

3200
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
3201
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
3202
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
3203
  int32_t              bytes = pDBuf->bytes;
×
3204

3205
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
3206
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
3207

3208
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
×
3209
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
3210
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
3211
  return TSDB_CODE_SUCCESS;
×
3212
}
3213

3214
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
23,218,504✔
3215
  SInputColumnInfoData* pInput = &pCtx->input;
23,218,504✔
3216
  SColumnInfoData*      pInputCol = pInput->pData[0];
23,249,476✔
3217
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
23,192,882✔
3218

3219
  if (colDataIsNull_s(pInputCol, rowIndex)) {
46,484,301✔
3220
    pInfo->isNull = true;
2,814,146✔
3221
  } else {
3222
    pInfo->isNull = false;
20,423,118✔
3223

3224
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
20,382,620✔
3225
      pInfo->bytes = calcStrBytesByType(pInputCol->info.type, pData);
3,727,299✔
3226
      // if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
3227
      //   pInfo->bytes = getJsonValueLen(pData);
3228
      // } else {
3229
      //   pInfo->bytes = varDataTLen(pData);
3230
      // }
3231
    }
3232

3233
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
20,423,930✔
3234
  }
3235

3236
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
32,920,370✔
3237
    char* pkData = colDataGetData(pkCol, rowIndex);
9,709,852✔
3238
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
9,710,520✔
3239
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
3,196,500✔
3240
    }
3241
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
9,709,178✔
3242
    pInfo->pkData = pInfo->buf + pInfo->bytes;
9,705,369✔
3243
  }
3244
  pInfo->ts = cts;
23,155,717✔
3245
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
23,191,906✔
3246
  if (code != TSDB_CODE_SUCCESS) {
23,164,340✔
3247
    return code;
×
3248
  }
3249

3250
  pInfo->hasResult = true;
23,164,340✔
3251

3252
  return TSDB_CODE_SUCCESS;
23,188,493✔
3253
}
3254

3255
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
3256
  int32_t numOfElems = 0;
2,147,483,647✔
3257

3258
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3259
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3260

3261
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3262
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3263

3264
  int32_t type = pInputCol->info.type;
2,147,483,647✔
3265
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
3266
  pInfo->bytes = bytes;
2,147,483,647✔
3267

3268
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
3269
    return TSDB_CODE_SUCCESS;
18,655✔
3270
  }
3271
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
3272
  pInfo->pkType = -1;
2,147,483,647✔
3273
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
3274
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
3275
    pInfo->pkType = pkCol->info.type;
10,380,774✔
3276
    pInfo->pkBytes = pkCol->info.bytes;
10,389,765✔
3277
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
10,384,645✔
3278
  }
3279
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
3280
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
3281

3282
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3283
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
21,100,459✔
3284
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
10,552,715✔
3285
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
10,551,449✔
3286
      TSKEY cts = getRowPTs(pInput->pPTS, i);
10,552,307✔
3287
      numOfElems++;
10,553,144✔
3288

3289
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
10,553,144✔
3290
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
2,963,084✔
3291
        if (code != TSDB_CODE_SUCCESS) return code;
2,959,034✔
3292
      }
3293

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

3305
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2,147,483,647✔
3306
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
8,289,993✔
3307
        if (code != TSDB_CODE_SUCCESS) return code;
8,510,521✔
3308
      }
3309
      break;
2,147,483,647✔
3310
    }
3311
  } else {
3312
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
10,643,281✔
3313
    int      from = -1;
10,940,642✔
3314
    int32_t  i = -1;
10,938,051✔
3315
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
202,995,111✔
3316
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
192,052,577✔
3317
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
192,057,728✔
3318
      TSKEY cts = pts[i];
192,054,870✔
3319

3320
      numOfElems++;
192,058,132✔
3321
      char* pkData = NULL;
192,058,132✔
3322
      if (pCtx->hasPrimaryKey) {
192,058,132✔
3323
        pkData = colDataGetData(pkCol, i);
186,598,299✔
3324
      }
3325
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
192,068,406✔
3326
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
180,698,467✔
3327
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
11,366,980✔
3328
        if (code != TSDB_CODE_SUCCESS) {
11,369,869✔
3329
          return code;
×
3330
        }
3331
        pResInfo->numOfRes = 1;
11,369,869✔
3332
      }
3333
    }
3334
  }
3335

3336
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
3337
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3338
}
3339

3340
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
525,958✔
3341
  pEnv->calcMemSize = sizeof(SDiffInfo);
525,958✔
3342
  return true;
525,958✔
3343
}
3344

3345
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
46,376,175✔
3346
  if (pResInfo->initialized) {
46,376,175✔
3347
    return TSDB_CODE_SUCCESS;
40,594,490✔
3348
  }
3349
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
5,781,685✔
3350
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3351
  }
3352
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,781,685✔
3353
  pDiffInfo->hasPrev = false;
5,781,685✔
3354
  pDiffInfo->isFirstRow = true;
5,781,685✔
3355
  pDiffInfo->prev.i64 = 0;
5,781,685✔
3356
  pDiffInfo->prevTs = -1;
5,781,685✔
3357
  if (pCtx->numOfParams > 1) {
5,781,685✔
3358
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
5,781,685✔
3359
  } else {
3360
    pDiffInfo->ignoreOption = 0;
×
3361
  }
3362
  return TSDB_CODE_SUCCESS;
5,781,685✔
3363
}
3364

3365
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
5,678,301✔
3366
  switch (type) {
5,678,301✔
3367
    case TSDB_DATA_TYPE_BOOL:
3,950✔
3368
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
3,950✔
3369
      break;
3,950✔
3370
    case TSDB_DATA_TYPE_UTINYINT:
31,461✔
3371
    case TSDB_DATA_TYPE_TINYINT:
3372
      pDiffInfo->prev.i64 = *(int8_t*)pv;
31,461✔
3373
      break;
31,461✔
3374
    case TSDB_DATA_TYPE_UINT:
5,412,879✔
3375
    case TSDB_DATA_TYPE_INT:
3376
      pDiffInfo->prev.i64 = *(int32_t*)pv;
5,412,879✔
3377
      break;
5,412,879✔
3378
    case TSDB_DATA_TYPE_USMALLINT:
35,143✔
3379
    case TSDB_DATA_TYPE_SMALLINT:
3380
      pDiffInfo->prev.i64 = *(int16_t*)pv;
35,143✔
3381
      break;
35,143✔
3382
    case TSDB_DATA_TYPE_TIMESTAMP:
118,107✔
3383
    case TSDB_DATA_TYPE_UBIGINT:
3384
    case TSDB_DATA_TYPE_BIGINT:
3385
      pDiffInfo->prev.i64 = *(int64_t*)pv;
118,107✔
3386
      break;
118,107✔
3387
    case TSDB_DATA_TYPE_FLOAT:
18,836✔
3388
      pDiffInfo->prev.d64 = *(float*)pv;
18,836✔
3389
      break;
18,836✔
3390
    case TSDB_DATA_TYPE_DOUBLE:
57,925✔
3391
      pDiffInfo->prev.d64 = *(double*)pv;
57,925✔
3392
      break;
57,925✔
3393
    default:
×
3394
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3395
  }
3396
  pDiffInfo->prevTs = ts;
5,678,301✔
3397
  pDiffInfo->hasPrev = true;
5,678,301✔
3398
  return TSDB_CODE_SUCCESS;
5,678,301✔
3399
}
3400

3401
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
3,348,728✔
3402
  switch (type) {
3,348,728✔
3403
    case TSDB_DATA_TYPE_UINT: {
×
3404
      int64_t v = *(uint32_t*)pv;
×
3405
      return v < pDiffInfo->prev.i64;
×
3406
    }
3407
    case TSDB_DATA_TYPE_INT: {
577,736✔
3408
      int64_t v = *(int32_t*)pv;
577,736✔
3409
      return v < pDiffInfo->prev.i64;
577,736✔
3410
    }
3411
    case TSDB_DATA_TYPE_BOOL: {
×
3412
      int64_t v = *(bool*)pv;
×
3413
      return v < pDiffInfo->prev.i64;
×
3414
    }
3415
    case TSDB_DATA_TYPE_UTINYINT: {
×
3416
      int64_t v = *(uint8_t*)pv;
×
3417
      return v < pDiffInfo->prev.i64;
×
3418
    }
3419
    case TSDB_DATA_TYPE_TINYINT: {
247,746✔
3420
      int64_t v = *(int8_t*)pv;
247,746✔
3421
      return v < pDiffInfo->prev.i64;
247,746✔
3422
    }
3423
    case TSDB_DATA_TYPE_USMALLINT: {
×
3424
      int64_t v = *(uint16_t*)pv;
×
3425
      return v < pDiffInfo->prev.i64;
×
3426
    }
3427
    case TSDB_DATA_TYPE_SMALLINT: {
857,612✔
3428
      int64_t v = *(int16_t*)pv;
857,612✔
3429
      return v < pDiffInfo->prev.i64;
857,612✔
3430
    }
3431
    case TSDB_DATA_TYPE_UBIGINT: {
3,512✔
3432
      uint64_t v = *(uint64_t*)pv;
3,512✔
3433
      return v < (uint64_t)pDiffInfo->prev.i64;
3,512✔
3434
    }
3435
    case TSDB_DATA_TYPE_TIMESTAMP:
653,124✔
3436
    case TSDB_DATA_TYPE_BIGINT: {
3437
      int64_t v = *(int64_t*)pv;
653,124✔
3438
      return v < pDiffInfo->prev.i64;
653,124✔
3439
    }
3440
    case TSDB_DATA_TYPE_FLOAT: {
643,930✔
3441
      float v = *(float*)pv;
643,930✔
3442
      return v < pDiffInfo->prev.d64;
643,930✔
3443
    }
3444
    case TSDB_DATA_TYPE_DOUBLE: {
365,068✔
3445
      double v = *(double*)pv;
365,068✔
3446
      return v < pDiffInfo->prev.d64;
365,068✔
3447
    }
3448
    default:
×
3449
      return false;
×
3450
  }
3451

3452
  return false;
3453
}
3454

3455
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
2,147,483,647✔
3456
  bool isNegative = v < pDiffInfo->prev.i64;
2,147,483,647✔
3457
  if (type == TSDB_DATA_TYPE_UBIGINT) {
2,147,483,647✔
3458
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
452,873✔
3459
  }
3460
  int64_t delta = v - pDiffInfo->prev.i64;
2,147,483,647✔
3461
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3462
    colDataSetNull_f_s(pOutput, pos);
1,153,220✔
3463
    pOutput->hasNull = true;
1,153,220✔
3464
  } else {
3465
    colDataSetInt64(pOutput, pos, &delta);
2,147,483,647✔
3466
  }
3467
  pDiffInfo->prev.i64 = v;
2,147,483,647✔
3468
}
2,147,483,647✔
3469

3470
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
28,381,811✔
3471
  double delta = v - pDiffInfo->prev.d64;
28,381,811✔
3472
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
28,381,811✔
3473
    colDataSetNull_f_s(pOutput, pos);
506,577✔
3474
  } else {
3475
    colDataSetDouble(pOutput, pos, &delta);
27,875,234✔
3476
  }
3477
  pDiffInfo->prev.d64 = v;
28,381,811✔
3478
}
28,381,811✔
3479

3480
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2,147,483,647✔
3481
                            int64_t ts) {
3482
  if (!pDiffInfo->hasPrev) {
2,147,483,647✔
3483
    colDataSetNull_f_s(pOutput, pos);
65,357✔
3484
    return doSetPrevVal(pDiffInfo, type, pv, ts);
65,357✔
3485
  }
3486
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3487
  switch (type) {
2,147,483,647✔
3488
    case TSDB_DATA_TYPE_UINT: {
446,727✔
3489
      int64_t v = *(uint32_t*)pv;
446,727✔
3490
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
446,727✔
3491
      break;
446,727✔
3492
    }
3493
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
3494
      int64_t v = *(int32_t*)pv;
2,147,483,647✔
3495
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3496
      break;
2,147,483,647✔
3497
    }
3498
    case TSDB_DATA_TYPE_BOOL: {
4,471,635✔
3499
      int64_t v = *(bool*)pv;
4,471,635✔
3500
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,471,635✔
3501
      break;
4,471,635✔
3502
    }
3503
    case TSDB_DATA_TYPE_UTINYINT: {
59,265✔
3504
      int64_t v = *(uint8_t*)pv;
59,265✔
3505
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
59,265✔
3506
      break;
59,265✔
3507
    }
3508
    case TSDB_DATA_TYPE_TINYINT: {
9,875,143✔
3509
      int64_t v = *(int8_t*)pv;
9,875,143✔
3510
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
9,875,143✔
3511
      break;
9,875,143✔
3512
    }
3513
    case TSDB_DATA_TYPE_USMALLINT: {
59,265✔
3514
      int64_t v = *(uint16_t*)pv;
59,265✔
3515
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
59,265✔
3516
      break;
59,265✔
3517
    }
3518
    case TSDB_DATA_TYPE_SMALLINT: {
10,366,549✔
3519
      int64_t v = *(int16_t*)pv;
10,366,549✔
3520
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,366,549✔
3521
      break;
10,366,549✔
3522
    }
3523
    case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
3524
    case TSDB_DATA_TYPE_UBIGINT:
3525
    case TSDB_DATA_TYPE_BIGINT: {
3526
      int64_t v = *(int64_t*)pv;
2,147,483,647✔
3527
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3528
      break;
2,147,483,647✔
3529
    }
3530
    case TSDB_DATA_TYPE_FLOAT: {
13,949,124✔
3531
      double v = *(float*)pv;
13,949,124✔
3532
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
13,949,124✔
3533
      break;
13,949,124✔
3534
    }
3535
    case TSDB_DATA_TYPE_DOUBLE: {
14,432,687✔
3536
      double v = *(double*)pv;
14,432,687✔
3537
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
14,432,687✔
3538
      break;
14,432,687✔
3539
    }
3540
    default:
×
3541
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3542
  }
3543
  pDiffInfo->hasPrev = true;
2,147,483,647✔
3544
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3545
}
3546

3547
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3548
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3549
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
2,147,483,647✔
3550
                              int32_t* nextFrom) {
3551
  if (pInput->pPrimaryKey == NULL) {
2,147,483,647✔
3552
    if (pInput->numOfRows == 0) {
2,147,483,647✔
3553
      return false;
29,255,382✔
3554
    }
3555
    if (from == -1) {
2,147,483,647✔
3556
      from = pInput->startRowIndex;
2,147,483,647✔
3557
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
2,147,483,647✔
3558
      return false;
2,147,483,647✔
3559
    }
3560
    *pRowIndex = from;
2,147,483,647✔
3561
    *nextFrom = from + 1;
2,147,483,647✔
3562
    return true;
2,147,483,647✔
3563
  } else {
3564
    if (from == -1) {
580,558,776✔
3565
      from = pInput->startRowIndex;
31,380,566✔
3566
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
549,178,210✔
3567
      return false;
31,404,246✔
3568
    }
3569
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
549,172,301✔
3570
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
549,216,153✔
3571
    int8_t           pkType = pkCol->info.type;
549,214,780✔
3572
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
549,248,669✔
3573
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
549,248,669✔
3574
    int32_t          select = from;
549,164,736✔
3575
    char*            val = colDataGetData(pkCol, select);
549,164,736✔
3576
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,366,314,703✔
3577
      char* val1 = colDataGetData(pkCol, from + 1);
817,104,888✔
3578
      if (compareFunc(val1, val) < 0) {
817,254,129✔
3579
        select = from + 1;
253,150,964✔
3580
        val = val1;
253,150,964✔
3581
      }
3582
      from = from + 1;
817,082,674✔
3583
    }
3584
    *pRowIndex = select;
548,628,820✔
3585
    *nextFrom = from + 1;
549,188,636✔
3586
    return true;
549,205,273✔
3587
  }
3588
}
3589

3590
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
×
3591
  pEnv->calcMemSize = sizeof(double);
×
3592
  return true;
×
3593
}
3594

3595
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3596
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3597
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3598

3599
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
2,147,483,647✔
3600
    return true;
13,007,447✔
3601
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3602
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
3,348,728✔
3603
  }
3604
  return false;
2,147,483,647✔
3605
}
3606

3607
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3608
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3609
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3610
  return pDiffInfo->isFirstRow;
2,147,483,647✔
3611
}
3612

3613
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
5,790,870✔
3614
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,790,870✔
3615
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,790,870✔
3616
  pDiffInfo->isFirstRow = false;
5,790,870✔
3617
  if (pRow->isDataNull) {
5,790,870✔
3618
    return TSDB_CODE_SUCCESS;
177,926✔
3619
  }
3620

3621
  SInputColumnInfoData* pInput = &pCtx->input;
5,612,944✔
3622
  SColumnInfoData*      pInputCol = pInput->pData[0];
5,612,944✔
3623
  int8_t                inputType = pInputCol->info.type;
5,612,944✔
3624

3625
  char* pv = pRow->pData;
5,612,944✔
3626
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
5,612,944✔
3627
}
3628

3629
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
2,147,483,647✔
3630
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3631
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3632

3633
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3634
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3635
  int8_t                inputType = pInputCol->info.type;
2,147,483,647✔
3636
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
2,147,483,647✔
3637
  int32_t               code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3638
  if (pRow->isDataNull) {
2,147,483,647✔
3639
    colDataSetNull_f_s(pOutput, pos);
7,158,683✔
3640
    pOutput->hasNull = true;
7,158,683✔
3641

3642
    // handle selectivity
3643
    if (pCtx->subsidiaries.num > 0) {
7,158,683✔
3644
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
21,070✔
3645
      if (code != TSDB_CODE_SUCCESS) {
21,070✔
3646
        return code;
×
3647
      }
3648
    }
3649
    return TSDB_CODE_SUCCESS;
7,158,683✔
3650
  }
3651

3652
  char* pv = pRow->pData;
2,147,483,647✔
3653

3654
  if (pRow->ts == pDiffInfo->prevTs) {
2,147,483,647✔
3655
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
7,895✔
3656
  }
3657
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
2,147,483,647✔
3658
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3659
    return code;
×
3660
  }
3661
  // handle selectivity
3662
  if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
3663
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
2,147,483,647✔
3664
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3665
      return code;
×
3666
    }
3667
  }
3668

3669
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3670
}
3671

3672
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
45,850,217✔
3673

3674
int32_t diffFunctionByRow(SArray* pCtxArray) {
45,826,511✔
3675
  int32_t code = TSDB_CODE_SUCCESS;
45,826,511✔
3676
  int     diffColNum = pCtxArray->size;
45,826,511✔
3677
  if (diffColNum == 0) {
45,826,511✔
3678
    return TSDB_CODE_SUCCESS;
×
3679
  }
3680
  int32_t numOfElems = 0;
45,826,511✔
3681

3682
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
45,826,511✔
3683
  if (NULL == pRows) {
45,826,511✔
3684
    return terrno;
×
3685
  }
3686

3687
  bool keepNull = false;
45,826,511✔
3688
  for (int i = 0; i < diffColNum; ++i) {
91,676,728✔
3689
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
45,850,217✔
3690
    if (NULL == pCtx) {
45,850,217✔
3691
      code = terrno;
×
3692
      goto _exit;
×
3693
    }
3694
    funcInputUpdate(pCtx);
45,850,217✔
3695
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
45,850,217✔
3696
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
45,850,217✔
3697
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
45,850,217✔
3698
      keepNull = true;
45,832,218✔
3699
    }
3700
  }
3701

3702
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
45,826,511✔
3703
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
45,826,511✔
3704
  if (NULL == pCtx0 || NULL == pRow0) {
45,826,511✔
3705
    code = terrno;
×
3706
    goto _exit;
×
3707
  }
3708
  int32_t startOffset = pCtx0->offset;
45,826,511✔
3709
  bool    result = false;
45,826,511✔
3710
  while (1) {
2,147,483,647✔
3711
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
2,147,483,647✔
3712
    if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3713
      goto _exit;
×
3714
    }
3715
    if (!result) {
2,147,483,647✔
3716
      break;
45,818,616✔
3717
    }
3718
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
2,147,483,647✔
3719
    for (int i = 1; i < diffColNum; ++i) {
2,147,483,647✔
3720
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
5,047,622✔
3721
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
5,047,622✔
3722
      if (NULL == pCtx || NULL == pRow) {
5,047,622✔
3723
        code = terrno;
×
3724
        goto _exit;
×
3725
      }
3726
      code = funcInputGetNextRow(pCtx, pRow, &result);
5,047,622✔
3727
      if (TSDB_CODE_SUCCESS != code) {
5,047,622✔
3728
        goto _exit;
×
3729
      }
3730
      if (!result) {
5,047,622✔
3731
        // rows are not equal
3732
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3733
        goto _exit;
×
3734
      }
3735
      if (!diffResultIsNull(pCtx, pRow)) {
5,047,622✔
3736
        hasNotNullValue = true;
4,982,650✔
3737
      }
3738
    }
3739
    int32_t pos = startOffset + numOfElems;
2,147,483,647✔
3740

3741
    bool newRow = false;
2,147,483,647✔
3742
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3743
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,147,483,647✔
3744
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
2,147,483,647✔
3745
      if (NULL == pCtx || NULL == pRow) {
2,147,483,647✔
3746
        code = terrno;
×
3747
        goto _exit;
×
3748
      }
3749
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
2,147,483,647✔
3750
        code = setDoDiffResult(pCtx, pRow, pos);
2,147,483,647✔
3751
        if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3752
          goto _exit;
7,895✔
3753
        }
3754
        newRow = true;
2,147,483,647✔
3755
      } else {
3756
        code = trySetPreVal(pCtx, pRow);
5,790,870✔
3757
        if (code != TSDB_CODE_SUCCESS) {
5,790,870✔
3758
          goto _exit;
×
3759
        }
3760
      }
3761
    }
3762
    if (newRow) ++numOfElems;
2,147,483,647✔
3763
  }
3764

3765
  for (int i = 0; i < diffColNum; ++i) {
91,660,499✔
3766
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
45,841,883✔
3767
    if (NULL == pCtx) {
45,841,883✔
3768
      code = terrno;
×
3769
      goto _exit;
×
3770
    }
3771
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
45,841,883✔
3772
    pResInfo->numOfRes = numOfElems;
45,841,883✔
3773
  }
3774

3775
_exit:
45,826,511✔
3776
  if (pRows) {
45,826,511✔
3777
    taosArrayDestroy(pRows);
45,826,511✔
3778
    pRows = NULL;
45,826,511✔
3779
  }
3780
  return code;
45,826,511✔
3781
}
3782

3783
bool getFillforwardFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
36,002✔
3784
  pEnv->calcMemSize = sizeof(SFillforwardInfo);
36,002✔
3785
  return true;
36,002✔
3786
}
3787

3788
int32_t fillforwardFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
74,578✔
3789
  if (pResInfo->initialized) {
74,578✔
3790
    return TSDB_CODE_SUCCESS;
36,002✔
3791
  }
3792
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
38,576✔
3793
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3794
  }
3795
  SFillforwardInfo* pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
38,576✔
3796
  pFillforwardInfo->nonnull = false;
38,576✔
3797

3798
  return TSDB_CODE_SUCCESS;
38,576✔
3799
}
3800

3801
int32_t fillforwardFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
38,576✔
3802

3803
static int32_t doHandleFillforward(SFillforwardInfo* pFillforwardInfo, int32_t type, SColumnInfoData* pOutput, int32_t pos) {
125,132✔
3804
  if (!pFillforwardInfo->nonnull) {
125,132✔
3805
    colDataSetNULL(pOutput, pos);
14,157✔
3806

3807
    return TSDB_CODE_SUCCESS;
14,157✔
3808
  }
3809

3810
  switch (type) {
110,975✔
3811
    case TSDB_DATA_TYPE_BOOL:
53,489✔
3812
    case TSDB_DATA_TYPE_UTINYINT:
3813
    case TSDB_DATA_TYPE_TINYINT:
3814
    case TSDB_DATA_TYPE_USMALLINT:
3815
    case TSDB_DATA_TYPE_SMALLINT:
3816
    case TSDB_DATA_TYPE_UINT:
3817
    case TSDB_DATA_TYPE_INT:
3818
    case TSDB_DATA_TYPE_UBIGINT:
3819
    case TSDB_DATA_TYPE_BIGINT:
3820
    case TSDB_DATA_TYPE_TIMESTAMP:
3821
      colDataSetInt64(pOutput, pos, &pFillforwardInfo->v);
53,489✔
3822
      break;
53,489✔
3823
    case TSDB_DATA_TYPE_FLOAT:
20,592✔
3824
      colDataSetFloat(pOutput, pos, &pFillforwardInfo->fv);
20,592✔
3825
      break;
20,592✔
3826
    case TSDB_DATA_TYPE_DOUBLE:
23,166✔
3827
      colDataSetDouble(pOutput, pos, &pFillforwardInfo->dv);
23,166✔
3828
      break;
23,166✔
3829
    case TSDB_DATA_TYPE_DECIMAL64:
4,719✔
3830
      return colDataSetVal(pOutput, pos, (const char*)&pFillforwardInfo->v, false);
4,719✔
3831
    case TSDB_DATA_TYPE_DECIMAL:
×
3832
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->dec, false);
×
3833
    case TSDB_DATA_TYPE_VARCHAR:
9,009✔
3834
    case TSDB_DATA_TYPE_VARBINARY:
3835
    case TSDB_DATA_TYPE_NCHAR:
3836
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->str, false);
9,009✔
3837
    default:
×
3838
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3839
  }
3840

3841
  return TSDB_CODE_SUCCESS;
97,247✔
3842
}
3843

3844
static int32_t setFillforwardResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
125,132✔
3845
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
125,132✔
3846
  SFillforwardInfo*            pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
125,132✔
3847

3848
  SInputColumnInfoData* pInput = &pCtx->input;
125,132✔
3849
  SColumnInfoData*      pInputCol = pInput->pData[0];
125,132✔
3850
  int8_t                inputType = pInputCol->info.type;
125,132✔
3851
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
125,132✔
3852
  int32_t               code = TSDB_CODE_SUCCESS;
125,132✔
3853

3854
  code = doHandleFillforward(pFillforwardInfo, inputType, pOutput, pos);
125,132✔
3855
  if (code != TSDB_CODE_SUCCESS) {
125,132✔
3856
    return code;
×
3857
  }
3858

3859
  // handle selectivity
3860
  if (pCtx->subsidiaries.num > 0) {
125,132✔
3861
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
34,184✔
3862
    if (code != TSDB_CODE_SUCCESS) {
34,184✔
3863
      return code;
×
3864
    }
3865
  }
3866

3867
  return TSDB_CODE_SUCCESS;
125,132✔
3868
}
3869

3870
int32_t fillforwardFunctionByRow(SArray* pCtxArray) {
11,120✔
3871
  int32_t code = TSDB_CODE_SUCCESS;
11,120✔
3872
  int     fillforwardColNum = pCtxArray->size;
11,120✔
3873
  if (fillforwardColNum == 0) {
11,120✔
3874
    return TSDB_CODE_SUCCESS;
×
3875
  }
3876
  int32_t numOfElems = 0;
11,120✔
3877

3878
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), fillforwardColNum);
11,120✔
3879
  if (NULL == pRows) {
11,120✔
3880
    return terrno;
×
3881
  }
3882

3883
  for (int i = 0; i < fillforwardColNum; ++i) {
49,696✔
3884
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
38,576✔
3885
    if (NULL == pCtx) {
38,576✔
3886
      code = terrno;
×
3887
      goto _exit;
×
3888
    }
3889
    funcInputUpdate(pCtx);
38,576✔
3890
  }
3891

3892
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
11,120✔
3893
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
11,120✔
3894
  if (NULL == pCtx0 || NULL == pRow0) {
11,120✔
3895
    code = terrno;
×
3896
    goto _exit;
×
3897
  }
3898
  int32_t startOffset = pCtx0->offset;
11,120✔
3899
  bool    result = false;
11,120✔
3900
  while (1) {
34,184✔
3901
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
45,304✔
3902
    if (TSDB_CODE_SUCCESS != code) {
45,304✔
3903
      goto _exit;
×
3904
    }
3905
    if (!result) {
45,304✔
3906
      break;
10,691✔
3907
    }
3908

3909
    for (int i = 1; i < fillforwardColNum; ++i) {
125,561✔
3910
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
90,948✔
3911
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
90,948✔
3912
      if (NULL == pCtx || NULL == pRow) {
90,948✔
3913
        code = terrno;
×
3914
        goto _exit;
×
3915
      }
3916
      code = funcInputGetNextRow(pCtx, pRow, &result);
90,948✔
3917
      if (TSDB_CODE_SUCCESS != code) {
90,948✔
3918
        goto _exit;
×
3919
      }
3920
      if (!result) {
90,948✔
3921
        // rows are not equal
3922
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3923
        goto _exit;
×
3924
      }
3925
    }
3926

3927
    int32_t pos = startOffset + numOfElems;
34,613✔
3928

3929
    for (int i = 0; i < fillforwardColNum; ++i) {
159,745✔
3930
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
125,561✔
3931
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
125,561✔
3932
      if (NULL == pCtx || NULL == pRow) {
125,561✔
3933
        code = terrno;
×
3934
        goto _exit;
×
3935
      }
3936

3937
      if (!colDataIsNull_s(pCtx->input.pData[0], pCtx->rowIter.rowIndex - 1)) {
251,122✔
3938
        SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
77,084✔
3939
        SFillforwardInfo*             pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
77,084✔
3940
        SInputColumnInfoData* pInput = &pCtx->input;
77,084✔
3941
        SColumnInfoData*      pInputCol = pInput->pData[0];
77,084✔
3942
        int8_t                inputType = pInputCol->info.type;
77,084✔
3943

3944
        char* pv = pRow->pData;
77,084✔
3945
        switch (inputType) {
77,084✔
3946
          case TSDB_DATA_TYPE_BOOL:
15,015✔
3947
            pFillforwardInfo->v = *(bool*)pv ? 1 : 0;
15,015✔
3948
            break;
15,015✔
3949
          case TSDB_DATA_TYPE_UTINYINT:
429✔
3950
          case TSDB_DATA_TYPE_TINYINT:
3951
            pFillforwardInfo->v = *(int8_t*)pv;
429✔
3952
            break;
429✔
3953
          case TSDB_DATA_TYPE_UINT:
22,172✔
3954
          case TSDB_DATA_TYPE_INT:
3955
            pFillforwardInfo->v = *(int32_t*)pv;
22,172✔
3956
            break;
22,172✔
3957
          case TSDB_DATA_TYPE_USMALLINT:
429✔
3958
          case TSDB_DATA_TYPE_SMALLINT:
3959
            pFillforwardInfo->v = *(int16_t*)pv;
429✔
3960
            break;
429✔
3961
          case TSDB_DATA_TYPE_TIMESTAMP:
429✔
3962
          case TSDB_DATA_TYPE_UBIGINT:
3963
          case TSDB_DATA_TYPE_BIGINT:
3964
            pFillforwardInfo->v = *(int64_t*)pv;
429✔
3965
            break;
429✔
3966
          case TSDB_DATA_TYPE_FLOAT:
15,015✔
3967
            pFillforwardInfo->fv = *(float*)pv;
15,015✔
3968
            break;
15,015✔
3969
          case TSDB_DATA_TYPE_DOUBLE:
16,731✔
3970
            pFillforwardInfo->dv = *(double*)pv;
16,731✔
3971
            break;
16,731✔
3972
          case TSDB_DATA_TYPE_DECIMAL64:
2,574✔
3973
            DECIMAL64_SET_VALUE((Decimal64*)&pFillforwardInfo->v, *(int64_t*)pv);
2,574✔
3974
            break;
2,574✔
3975
          case TSDB_DATA_TYPE_DECIMAL:
×
3976
            DECIMAL128_CLONE((Decimal128*)pFillforwardInfo->dec, (Decimal128*)pv);
×
3977
            break;
×
3978
          case TSDB_DATA_TYPE_VARCHAR:
3,861✔
3979
          case TSDB_DATA_TYPE_VARBINARY:
3980
          case TSDB_DATA_TYPE_NCHAR: {
3981
            if (!pFillforwardInfo->nonnull) {
3,861✔
3982
              pFillforwardInfo->str = taosMemoryMalloc(pInputCol->info.bytes);
2,574✔
3983
              if (!pFillforwardInfo->str) {
2,574✔
3984
                code = terrno;
×
3985
                goto _exit;
×
3986
              }
3987
            }
3988

3989
            (void)memcpy(pFillforwardInfo->str, pv, varDataTLen(pv));
3,861✔
3990
          } break;
3,861✔
3991
          default: {
429✔
3992
            code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
429✔
3993
            goto _exit;
429✔
3994
          }
3995
        }
3996

3997
        if (!pFillforwardInfo->nonnull) {
76,655✔
3998
          pFillforwardInfo->nonnull = true;
37,718✔
3999
        }
4000
      }
4001

4002
      code = setFillforwardResult(pCtx, pRow, pos);
125,132✔
4003
      if (code) {
125,132✔
4004
        goto _exit;
×
4005
      }
4006
    }
4007

4008
    ++numOfElems;
34,184✔
4009
  }
4010

4011
_exit:
11,120✔
4012
  for (int i = 0; i < fillforwardColNum; ++i) {
49,696✔
4013
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
38,576✔
4014
    if (!pCtx) {
38,576✔
4015
      break;
×
4016
    }
4017

4018
    SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
38,576✔
4019
    SFillforwardInfo*             pRes = GET_ROWCELL_INTERBUF(pResInfo);
38,576✔
4020
    SInputColumnInfoData* pInput = &pCtx->input;
38,576✔
4021
    SColumnInfoData*      pInputCol = pInput->pData[0];
38,576✔
4022

4023
    if (IS_VAR_DATA_TYPE(pInputCol->info.type) && pRes->nonnull) {
38,576✔
4024
      taosMemoryFree(pRes->str);
2,574✔
4025
    }
4026

4027
    if (!code) {
38,576✔
4028
      pResInfo->numOfRes = numOfElems;
38,147✔
4029
    }
4030
  }
4031

4032
  if (pRows) {
11,120✔
4033
    taosArrayDestroy(pRows);
11,120✔
4034
    pRows = NULL;
11,120✔
4035
  }
4036
  return code;
11,120✔
4037
}
4038

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

4041
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,113,499✔
4042
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2,113,499✔
4043
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2,114,495✔
4044
  return true;
2,114,053✔
4045
}
4046

4047
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
7,672,606✔
4048
  if (pResInfo->initialized) {
7,672,606✔
4049
    return TSDB_CODE_SUCCESS;
×
4050
  }
4051
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
7,673,036✔
4052
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4053
  }
4054

4055
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
7,673,478✔
4056
  SInputColumnInfoData* pInput = &pCtx->input;
7,673,478✔
4057

4058
  pRes->maxSize = pCtx->param[1].param.i;
7,673,478✔
4059

4060
  pRes->nullTupleSaved = false;
7,673,036✔
4061
  pRes->nullTuplePos.pageId = -1;
7,672,618✔
4062
  return TSDB_CODE_SUCCESS;
7,672,606✔
4063
}
4064

4065
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
2,048,025,827✔
4066
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,048,025,827✔
4067
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,048,023,092✔
4068
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
2,048,162,653✔
4069

4070
  return pRes;
2,048,316,322✔
4071
}
4072

4073
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
4074
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
4075

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

4078
int32_t topFunction(SqlFunctionCtx* pCtx) {
8,563,595✔
4079
  int32_t              numOfElems = 0;
8,563,595✔
4080
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,563,595✔
4081

4082
  SInputColumnInfoData* pInput = &pCtx->input;
8,563,595✔
4083
  SColumnInfoData*      pCol = pInput->pData[0];
8,563,595✔
4084

4085
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
8,564,025✔
4086
  pRes->type = pInput->pData[0]->info.type;
8,564,025✔
4087

4088
  int32_t start = pInput->startRowIndex;
8,564,025✔
4089
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,218,343,516✔
4090
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,212,390,064✔
4091
      continue;
1,618,940✔
4092
    }
4093

4094
    numOfElems++;
1,211,262,170✔
4095
    char*   data = colDataGetData(pCol, i);
1,211,262,170✔
4096
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
1,211,529,367✔
4097
    if (code != TSDB_CODE_SUCCESS) {
1,208,160,551✔
4098
      return code;
×
4099
    }
4100
  }
4101

4102
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
8,564,554✔
4103
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
3,682✔
4104
    if (code != TSDB_CODE_SUCCESS) {
3,682✔
4105
      return code;
×
4106
    }
4107
    pRes->nullTupleSaved = true;
3,682✔
4108
  }
4109
  return TSDB_CODE_SUCCESS;
8,564,124✔
4110
}
4111

4112
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
2,784,959✔
4113
  int32_t              numOfElems = 0;
2,784,959✔
4114
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,784,959✔
4115

4116
  SInputColumnInfoData* pInput = &pCtx->input;
2,785,843✔
4117
  SColumnInfoData*      pCol = pInput->pData[0];
2,785,843✔
4118

4119
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
2,785,843✔
4120
  pRes->type = pInput->pData[0]->info.type;
2,784,959✔
4121

4122
  int32_t start = pInput->startRowIndex;
2,785,401✔
4123
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
822,679,126✔
4124
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
820,183,887✔
4125
      continue;
2,924,456✔
4126
    }
4127

4128
    numOfElems++;
817,209,774✔
4129
    char*   data = colDataGetData(pCol, i);
817,209,774✔
4130
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
817,418,555✔
4131
    if (code != TSDB_CODE_SUCCESS) {
816,968,827✔
4132
      return code;
×
4133
    }
4134
  }
4135

4136
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
2,786,727✔
4137
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
10,030✔
4138
    if (code != TSDB_CODE_SUCCESS) {
10,030✔
4139
      return code;
×
4140
    }
4141
    pRes->nullTupleSaved = true;
10,030✔
4142
  }
4143

4144
  return TSDB_CODE_SUCCESS;
2,786,727✔
4145
}
4146

4147
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
498,314,083✔
4148
  uint16_t type = *(uint16_t*)param;
498,314,083✔
4149

4150
  STopBotResItem* val1 = (STopBotResItem*)p1;
498,312,216✔
4151
  STopBotResItem* val2 = (STopBotResItem*)p2;
498,312,216✔
4152

4153
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
498,312,216✔
4154
    if (val1->v.i == val2->v.i) {
318,873,592✔
4155
      return 0;
54,046,317✔
4156
    }
4157

4158
    return (val1->v.i > val2->v.i) ? 1 : -1;
265,174,865✔
4159
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
179,438,624✔
4160
    if (val1->v.u == val2->v.u) {
89,839,188✔
4161
      return 0;
18,675,155✔
4162
    }
4163

4164
    return (val1->v.u > val2->v.u) ? 1 : -1;
71,269,241✔
4165
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
89,599,436✔
4166
    if (val1->v.f == val2->v.f) {
2,342,573✔
4167
      return 0;
27,783✔
4168
    }
4169

4170
    return (val1->v.f > val2->v.f) ? 1 : -1;
2,314,790✔
4171
  }
4172

4173
  if (val1->v.d == val2->v.d) {
87,256,863✔
4174
    return 0;
4,851✔
4175
  }
4176

4177
  return (val1->v.d > val2->v.d) ? 1 : -1;
87,248,201✔
4178
}
4179

4180
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
2,026,713,026✔
4181
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
4182
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
2,026,713,026✔
4183
  int32_t     code = TSDB_CODE_SUCCESS;
2,029,014,608✔
4184

4185
  SVariant val = {0};
2,029,014,608✔
4186
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
2,029,435,749✔
4187

4188
  STopBotResItem* pItems = pRes->pItems;
2,029,075,681✔
4189

4190
  // not full yet
4191
  if (pEntryInfo->numOfRes < pRes->maxSize) {
2,029,279,698✔
4192
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
44,410,110✔
4193
    pItem->v = val;
44,409,837✔
4194
    pItem->uid = uid;
44,409,837✔
4195

4196
    // save the data of this tuple
4197
    if (pCtx->subsidiaries.num > 0) {
44,411,168✔
4198
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
12,255,236✔
4199
      if (code != TSDB_CODE_SUCCESS) {
12,254,806✔
4200
        return code;
×
4201
      }
4202
    }
4203
#ifdef BUF_PAGE_DEBUG
4204
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
4205
           pItem->tuplePos.offset);
4206
#endif
4207
    // allocate the buffer and keep the data of this row into the new allocated buffer
4208
    pEntryInfo->numOfRes++;
44,412,767✔
4209
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
44,414,069✔
4210
                        topBotResComparFn, !isTopQuery);
44,414,069✔
4211
    if (code != TSDB_CODE_SUCCESS) {
44,415,400✔
4212
      return code;
×
4213
    }
4214
  } else {  // replace the minimum value in the result
4215
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
1,983,277,754✔
4216
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
1,160,988,335✔
4217
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
1,150,656,599✔
4218
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
1,151,573,745✔
4219
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
1,950,463,811✔
4220
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
806,125,741✔
4221
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
804,990,434✔
4222
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
804,780,354✔
4223
      // replace the old data and the coresponding tuple data
4224
      STopBotResItem* pItem = &pItems[0];
38,957,135✔
4225
      pItem->v = val;
38,957,135✔
4226
      pItem->uid = uid;
37,525,080✔
4227

4228
      // save the data of this tuple by over writing the old data
4229
      if (pCtx->subsidiaries.num > 0) {
37,525,080✔
4230
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
20,162,205✔
4231
        if (code != TSDB_CODE_SUCCESS) {
20,161,048✔
4232
          return code;
×
4233
        }
4234
      }
4235
#ifdef BUF_PAGE_DEBUG
4236
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
4237
#endif
4238
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
37,524,022✔
4239
                            topBotResComparFn, NULL, !isTopQuery);
37,524,353✔
4240
      if (code != TSDB_CODE_SUCCESS) {
37,522,976✔
4241
        return code;
×
4242
      }
4243
    }
4244
  }
4245

4246
  return TSDB_CODE_SUCCESS;
2,026,574,318✔
4247
}
4248

4249

4250
bool hasNullFunc(  SColumnInfoData *pData,   SColumnDataAgg *pAgg, int32_t startIdx, int64_t rows) {
×
4251
  if (NULL != pAgg) {
×
4252
    return pAgg->numOfNull > 0 ? true : false;
×
4253
  }
4254

4255
  if (!pData->hasNull) {
×
4256
    return false;
×
4257
  }
4258

4259
  int64_t endIdx = startIdx + rows;
×
4260
  for (int64_t i = startIdx; i < endIdx; ++i) {
×
4261
    if (colDataIsNull_s(pData, i)) {
×
4262
      return true;
×
4263
    }
4264
  }
4265

4266
  return false;
×
4267
}
4268

4269

4270
/*
4271
 * +------------------------------------+--------------+--------------+
4272
 * |            null bitmap             |              |              |
4273
 * |(n columns, one bit for each column)| src column #1| src column #2|
4274
 * +------------------------------------+--------------+--------------+
4275
 */
4276
int32_t serializeTupleData(SqlFunctionCtx* pCtx, const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
118,058,412✔
4277
                           char* buf, char** res) {
4278
  char* nullList = buf;
118,058,412✔
4279
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
118,058,412✔
4280

4281
  int32_t offset = 0;
118,060,913✔
4282
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
366,098,136✔
4283
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
248,036,771✔
4284

4285
    // group_key function has its own process function
4286
    // do not process there
4287
    if (fmIsGroupKeyFunc(pc->functionId)) {
248,035,838✔
4288
      continue;
×
4289
    }
4290

4291
    if (fmIsSelectValueFunc(pc->functionId)) {
248,033,298✔
4292
      SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
248,035,009✔
4293
      int32_t      srcSlotId = pFuncParam->pCol->slotId;
248,035,991✔
4294

4295
      SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
248,038,688✔
4296
      if (NULL == pCol) {
248,037,484✔
4297
        return TSDB_CODE_OUT_OF_RANGE;
×
4298
      }
4299
      if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
496,074,731✔
4300
        offset += pCol->info.bytes;
64,189,479✔
4301
        continue;
64,189,479✔
4302
      }
4303

4304
      char* p = colDataGetData(pCol, rowIndex);
183,845,915✔
4305
      if (IS_VAR_DATA_TYPE(pCol->info.type)) {
183,849,174✔
4306
        int32_t bytes = calcStrBytesByType(pCol->info.type, p);
9,077,234✔
4307
        (void)memcpy(pStart + offset, p, bytes);
9,080,087✔
4308
      } else {
4309
        (void)memcpy(pStart + offset, p, pCol->info.bytes);
174,767,686✔
4310
      }
4311

4312
      offset += pCol->info.bytes;
183,846,953✔
4313
      continue;
183,849,676✔
4314
    }
4315
  }
4316

4317
  *res = buf;
118,058,642✔
4318
  return TSDB_CODE_SUCCESS;
118,065,355✔
4319
}
4320

4321
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
181,410,885✔
4322
                               STuplePos* pPos, SFunctionStateStore* pStore) {
4323
  STuplePos p = {0};
181,410,885✔
4324
  if (pHandle->pBuf != NULL) {
181,410,885✔
4325
    SFilePage* pPage = NULL;
181,411,515✔
4326

4327
    if (pHandle->currentPage == -1) {
181,411,515✔
4328
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
5,578,744✔
4329
      if (pPage == NULL) {
5,581,149✔
4330
        return terrno;
×
4331
      }
4332
      pPage->num = sizeof(SFilePage);
5,581,149✔
4333
    } else {
4334
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
175,832,577✔
4335
      if (pPage == NULL) {
175,829,309✔
4336
        return terrno;
×
4337
      }
4338
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
175,829,309✔
4339
        // current page is all used, let's prepare a new buffer page
4340
        releaseBufPage(pHandle->pBuf, pPage);
71,245✔
4341
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
71,245✔
4342
        if (pPage == NULL) {
71,245✔
4343
          return terrno;
×
4344
        }
4345
        pPage->num = sizeof(SFilePage);
71,245✔
4346
      }
4347
    }
4348

4349
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
181,412,528✔
4350
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
181,412,551✔
4351

4352
    pPage->num += length;
181,412,116✔
4353
    setBufPageDirty(pPage, true);
181,413,032✔
4354
    releaseBufPage(pHandle->pBuf, pPage);
181,412,567✔
4355
  } else {  // other tuple save policy
4356
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
236✔
4357
      p.streamTupleKey = *key;
×
4358
    }
4359
  }
4360

4361
  *pPos = p;
181,413,268✔
4362
  return TSDB_CODE_SUCCESS;
181,412,838✔
4363
}
4364

4365
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
77,718,719✔
4366
  int32_t code = prepareBuf(pCtx);
77,718,719✔
4367
  if (TSDB_CODE_SUCCESS != code) {
77,718,945✔
4368
    return code;
×
4369
  }
4370

4371
  SWinKey key = {0};
77,718,945✔
4372
  if (pCtx->saveHandle.pBuf == NULL) {
77,719,810✔
4373
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
×
4374
    if (NULL == pColInfo) {
×
4375
      return TSDB_CODE_OUT_OF_RANGE;
×
4376
    }
4377
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
×
4378
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4379
    }
4380
    key.groupId = pSrcBlock->info.id.groupId;
×
4381
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
×
4382
    key.numInGroup = pCtx->pExpr->pExpr->_function.bindExprID;
×
4383
  }
4384

4385
  char* buf = NULL;
77,717,868✔
4386
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
77,717,383✔
4387
  if (TSDB_CODE_SUCCESS != code) {
77,720,229✔
4388
    return code;
×
4389
  }
4390
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
77,720,229✔
4391
}
4392

4393
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
40,343,394✔
4394
                                 SFunctionStateStore* pStore) {
4395
  if (pHandle->pBuf != NULL) {
40,343,394✔
4396
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
40,343,824✔
4397
    if (pPage == NULL) {
40,343,626✔
4398
      return terrno;
×
4399
    }
4400
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
40,343,626✔
4401
    setBufPageDirty(pPage, true);
40,342,766✔
4402
    releaseBufPage(pHandle->pBuf, pPage);
40,343,824✔
4403
  } else {
4404
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
×
4405
    if (TSDB_CODE_SUCCESS != code) {
×
4406
      return code;
×
4407
    }
4408
  }
4409

4410
  return TSDB_CODE_SUCCESS;
40,342,667✔
4411
}
4412

4413
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
40,344,254✔
4414
  int32_t code = prepareBuf(pCtx);
40,344,254✔
4415
  if (TSDB_CODE_SUCCESS != code) {
40,343,824✔
4416
    return code;
×
4417
  }
4418

4419
  char* buf = NULL;
40,343,824✔
4420
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
40,343,824✔
4421
  if (TSDB_CODE_SUCCESS != code) {
40,344,254✔
4422
    return code;
×
4423
  }
4424
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
40,344,254✔
4425
}
4426

4427
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
76,600,647✔
4428
                               char** value) {
4429
  if (pHandle->pBuf != NULL) {
76,600,647✔
4430
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
76,600,647✔
4431
    if (pPage == NULL) {
76,600,414✔
4432
      *value = NULL;
×
4433
      return terrno;
×
4434
    }
4435
    *value = pPage->data + pPos->offset;
76,600,414✔
4436
    releaseBufPage(pHandle->pBuf, pPage);
76,598,494✔
4437
    return TSDB_CODE_SUCCESS;
76,599,979✔
4438
  } else {
4439
    *value = NULL;
×
4440
    int32_t vLen;
×
4441
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
×
4442
    if (TSDB_CODE_SUCCESS != code) {
×
4443
      return code;
×
4444
    }
4445
    return TSDB_CODE_SUCCESS;
×
4446
  }
4447
}
4448

4449
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
76,600,647✔
4450
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
76,600,647✔
4451
}
4452

4453
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,662,810✔
4454
  int32_t code = TSDB_CODE_SUCCESS;
7,662,810✔
4455

4456
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
7,662,810✔
4457
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
7,662,810✔
4458

4459
  int16_t type = pCtx->pExpr->base.resSchema.type;
7,662,810✔
4460
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
7,662,810✔
4461

4462
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,662,810✔
4463
  if (NULL == pCol) {
7,662,810✔
4464
    return TSDB_CODE_OUT_OF_RANGE;
×
4465
  }
4466

4467
  // todo assign the tag value and the corresponding row data
4468
  int32_t currentRow = pBlock->info.rows;
7,662,810✔
4469
  if (pEntryInfo->numOfRes <= 0) {
7,662,810✔
4470
    colDataSetNULL(pCol, currentRow);
45,918✔
4471
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
45,918✔
4472
    return code;
45,918✔
4473
  }
4474
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
52,029,224✔
4475
    STopBotResItem* pItem = &pRes->pItems[i];
44,412,332✔
4476
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
44,412,332✔
4477
    if (TSDB_CODE_SUCCESS != code) {
44,412,332✔
4478
      return code;
×
4479
    }
4480
#ifdef BUF_PAGE_DEBUG
4481
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
4482
           pItem->tuplePos.offset);
4483
#endif
4484
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
44,412,332✔
4485
    if (TSDB_CODE_SUCCESS != code) {
44,412,332✔
4486
      return code;
×
4487
    }
4488
    currentRow += 1;
44,412,332✔
4489
  }
4490

4491
  return code;
7,616,892✔
4492
}
4493

4494
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
4495
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
4496
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
4497
  STopBotResItem*      pItems = pRes->pItems;
×
4498
  int32_t              code = TSDB_CODE_SUCCESS;
×
4499

4500
  // not full yet
4501
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
4502
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
4503
    pItem->v = pSourceItem->v;
×
4504
    pItem->uid = pSourceItem->uid;
×
4505
    pItem->tuplePos.pageId = -1;
×
4506
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4507
    pEntryInfo->numOfRes++;
×
4508
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
4509
                        topBotResComparFn, !isTopQuery);
×
4510
    if (TSDB_CODE_SUCCESS != code) {
×
4511
      return code;
×
4512
    }
4513
  } else {  // replace the minimum value in the result
4514
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
4515
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
4516
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
4517
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
4518
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
4519
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
4520
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
4521
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
4522
      // replace the old data and the coresponding tuple data
4523
      STopBotResItem* pItem = &pItems[0];
×
4524
      pItem->v = pSourceItem->v;
×
4525
      pItem->uid = pSourceItem->uid;
×
4526

4527
      // save the data of this tuple by over writing the old data
4528
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4529
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4530
                            topBotResComparFn, NULL, !isTopQuery);
×
4531
      if (TSDB_CODE_SUCCESS != code) {
×
4532
        return code;
×
4533
      }
4534
    }
4535
  }
4536
  return code;
×
4537
}
4538

4539
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4540
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4541
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4542
  int16_t              type = pSBuf->type;
×
4543
  int32_t              code = TSDB_CODE_SUCCESS;
×
4544
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4545
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
4546
    if (TSDB_CODE_SUCCESS != code) {
×
4547
      return code;
×
4548
    }
4549
  }
4550
  return TSDB_CODE_SUCCESS;
×
4551
}
4552

4553
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4554
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4555
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4556
  int16_t              type = pSBuf->type;
×
4557
  int32_t              code = TSDB_CODE_SUCCESS;
×
4558
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4559
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4560
    if (TSDB_CODE_SUCCESS != code) {
×
4561
      return code;
×
4562
    }
4563
  }
4564
  return TSDB_CODE_SUCCESS;
×
4565
}
4566

4567
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
8,348,901✔
4568

4569
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
3,758,595✔
4570
  pEnv->calcMemSize = sizeof(SSpreadInfo);
3,758,595✔
4571
  return true;
3,759,662✔
4572
}
4573

4574
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
87,668,735✔
4575
  if (pResultInfo->initialized) {
87,668,735✔
4576
    return TSDB_CODE_SUCCESS;
×
4577
  }
4578
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
87,675,519✔
4579
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4580
  }
4581

4582
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
87,673,019✔
4583
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
87,672,471✔
4584
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
87,674,623✔
4585
  pInfo->hasResult = false;
87,674,553✔
4586
  return TSDB_CODE_SUCCESS;
87,677,123✔
4587
}
4588

4589
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
137,155,649✔
4590
  int32_t numOfElems = 0;
137,155,649✔
4591

4592
  // Only the pre-computing information loaded and actual data does not loaded
4593
  SInputColumnInfoData* pInput = &pCtx->input;
137,155,649✔
4594
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
137,157,419✔
4595
  int32_t               type = pInput->pData[0]->info.type;
137,171,452✔
4596

4597
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
137,160,662✔
4598

4599
  if (pInput->colDataSMAIsSet) {
137,164,535✔
4600
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
45,836,805✔
4601
    if (numOfElems == 0) {
45,841,761✔
4602
      goto _spread_over;
32,523,134✔
4603
    }
4604
    double tmin = 0.0, tmax = 0.0;
13,318,627✔
4605
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
13,318,627✔
4606
      tmin = (double)GET_INT64_VAL(&pAgg->min);
6,813,877✔
4607
      tmax = (double)GET_INT64_VAL(&pAgg->max);
6,814,500✔
4608
    } else if (IS_FLOAT_TYPE(type)) {
6,504,750✔
4609
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4610
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4611
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
6,504,750✔
4612
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
6,504,750✔
4613
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
6,504,750✔
4614
    }
4615

4616
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
13,319,250✔
4617
      SET_DOUBLE_VAL(&pInfo->min, tmin);
606,158✔
4618
    }
4619

4620
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
13,318,634✔
4621
      SET_DOUBLE_VAL(&pInfo->max, tmax);
645,722✔
4622
    }
4623

4624
  } else {  // computing based on the true data block
4625
    SColumnInfoData* pCol = pInput->pData[0];
91,309,105✔
4626

4627
    int32_t start = pInput->startRowIndex;
91,310,221✔
4628
    // check the valid data one by one
4629
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
947,162,682✔
4630
      if (colDataIsNull_f(pCol, i)) {
855,849,858✔
4631
        continue;
168,385,663✔
4632
      }
4633

4634
      char* data = colDataGetData(pCol, i);
687,448,362✔
4635

4636
      double v = 0;
687,420,794✔
4637
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
687,420,794✔
4638
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
687,447,747✔
4639
        SET_DOUBLE_VAL(&pInfo->min, v);
88,197,321✔
4640
      }
4641

4642
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
687,459,916✔
4643
        SET_DOUBLE_VAL(&pInfo->max, v);
100,087,360✔
4644
      }
4645

4646
      numOfElems += 1;
687,467,366✔
4647
    }
4648
  }
4649

4650
_spread_over:
91,324,195✔
4651
  // data in the check operation are all null, not output
4652
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
137,166,579✔
4653
  if (numOfElems > 0) {
137,164,955✔
4654
    pInfo->hasResult = true;
101,911,189✔
4655
  }
4656

4657
  return TSDB_CODE_SUCCESS;
137,149,754✔
4658
}
4659

4660
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
7,636,661✔
4661
  pOutput->hasResult = pInput->hasResult;
7,636,661✔
4662
  if (pInput->max > pOutput->max) {
7,636,661✔
4663
    pOutput->max = pInput->max;
5,339,526✔
4664
  }
4665

4666
  if (pInput->min < pOutput->min) {
7,636,661✔
4667
    pOutput->min = pInput->min;
5,337,182✔
4668
  }
4669
}
7,636,661✔
4670

4671
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
5,658,318✔
4672
  SInputColumnInfoData* pInput = &pCtx->input;
5,658,318✔
4673
  SColumnInfoData*      pCol = pInput->pData[0];
5,658,318✔
4674

4675
  if (IS_NULL_TYPE(pCol->info.type)) {
5,658,318✔
4676
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4677
    return TSDB_CODE_SUCCESS;
×
4678
  }
4679

4680
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
5,658,318✔
4681
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4682
  }
4683

4684
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,658,318✔
4685

4686
  int32_t start = pInput->startRowIndex;
5,658,318✔
4687
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
13,559,201✔
4688
    if (colDataIsNull_s(pCol, i)) continue;
15,801,766✔
4689
    char*        data = colDataGetData(pCol, i);
7,900,883✔
4690
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
7,900,883✔
4691
    if (pInputInfo->hasResult) {
7,900,883✔
4692
      spreadTransferInfo(pInputInfo, pInfo);
7,636,661✔
4693
    }
4694
  }
4695

4696
  if (pInfo->hasResult) {
5,658,318✔
4697
    GET_RES_INFO(pCtx)->numOfRes = 1;
5,519,172✔
4698
  }
4699

4700
  return TSDB_CODE_SUCCESS;
5,658,318✔
4701
}
4702

4703
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
71,998,197✔
4704
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
71,998,197✔
4705
  if (pInfo->hasResult == true) {
71,998,705✔
4706
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
69,363,115✔
4707
  } else {
4708
    GET_RES_INFO(pCtx)->isNullRes = 1;
2,635,082✔
4709
  }
4710
  return functionFinalize(pCtx, pBlock);
71,998,705✔
4711
}
4712

4713
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,913,838✔
4714
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,913,838✔
4715
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,914,454✔
4716
  int32_t              resultBytes = getSpreadInfoSize();
7,914,454✔
4717
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
7,913,838✔
4718

4719
  if (NULL == res) {
7,913,838✔
4720
    return terrno;
×
4721
  }
4722
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
7,913,838✔
4723
  varDataSetLen(res, resultBytes);
7,913,838✔
4724

4725
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,913,838✔
4726
  int32_t          code = TSDB_CODE_SUCCESS;
7,913,838✔
4727
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,913,838✔
4728
  if (NULL == pCol) {
7,913,838✔
4729
    code = terrno;
×
4730
    goto _exit;
×
4731
  }
4732

4733
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
7,913,838✔
4734
  if (TSDB_CODE_SUCCESS != code) {
7,913,838✔
4735
    goto _exit;
×
4736
  }
4737

4738
_exit:
7,913,838✔
4739
  taosMemoryFree(res);
7,913,838✔
4740
  return code;
7,913,838✔
4741
}
4742

4743
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4744
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4745
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4746

4747
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4748
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4749
  spreadTransferInfo(pSBuf, pDBuf);
×
4750
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4751
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4752
  return TSDB_CODE_SUCCESS;
×
4753
}
4754

4755
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4756

4757
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
2,479,947✔
4758
  pEnv->calcMemSize = sizeof(SElapsedInfo);
2,479,947✔
4759
  return true;
2,480,406✔
4760
}
4761

4762
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,718,200✔
4763
  if (pResultInfo->initialized) {
4,718,200✔
4764
    return TSDB_CODE_SUCCESS;
×
4765
  }
4766
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,718,200✔
4767
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4768
  }
4769

4770
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,718,659✔
4771
  pInfo->result = 0;
4,718,200✔
4772
  pInfo->min = TSKEY_MAX;
4,718,200✔
4773
  pInfo->max = 0;
4,719,197✔
4774

4775
  if (pCtx->numOfParams > 1) {
4,717,583✔
4776
    pInfo->timeUnit = pCtx->param[1].param.i;
2,886,613✔
4777
  } else {
4778
    pInfo->timeUnit = 1;
1,831,049✔
4779
  }
4780

4781
  return TSDB_CODE_SUCCESS;
4,718,200✔
4782
}
4783

4784
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
4,778,574✔
4785
  int32_t numOfElems = 0;
4,778,574✔
4786

4787
  // Only the pre-computing information loaded and actual data does not loaded
4788
  SInputColumnInfoData* pInput = &pCtx->input;
4,778,574✔
4789
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
4,778,574✔
4790

4791
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,779,033✔
4792

4793
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
4,778,574✔
4794
  if (numOfElems == 0) {
4,778,036✔
4795
    // for stream
4796
    if (pCtx->end.key != INT64_MIN) {
×
4797
      pInfo->max = pCtx->end.key + 1;
×
4798
    }
4799
    goto _elapsed_over;
×
4800
  }
4801

4802
  if (pInput->colDataSMAIsSet) {
4,778,036✔
4803
    if (pInfo->min == TSKEY_MAX) {
×
4804
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4805
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4806
    } else {
4807
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4808
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4809
      } else {
4810
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4811
      }
4812
    }
4813
  } else {  // computing based on the true data block
4814
    if (0 == pInput->numOfRows) {
4,778,089✔
4815
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4816
        if (pCtx->end.key != INT64_MIN) {
×
4817
          pInfo->min = pCtx->end.key;
×
4818
        }
4819
      } else {
4820
        if (pCtx->end.key != INT64_MIN) {
×
4821
          pInfo->max = pCtx->end.key + 1;
×
4822
        }
4823
      }
4824
      goto _elapsed_over;
×
4825
    }
4826

4827
    SColumnInfoData* pCol = pInput->pData[0];
4,777,472✔
4828

4829
    int32_t start = pInput->startRowIndex;
4,778,574✔
4830
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
4,779,033✔
4831
    if (pCtx->order == TSDB_ORDER_DESC) {
4,776,960✔
4832
      if (pCtx->start.key == INT64_MIN) {
34,486✔
4833
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
34,486✔
4834
      } else {
4835
        pInfo->max = pCtx->start.key + 1;
×
4836
      }
4837

4838
      if (pCtx->end.key == INT64_MIN) {
34,486✔
4839
        pInfo->min =
34,486✔
4840
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
34,486✔
4841
      } else {
4842
        pInfo->min = pCtx->end.key;
×
4843
      }
4844
    } else {
4845
      if (pCtx->start.key == INT64_MIN) {
4,741,989✔
4846
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
4,743,524✔
4847
      } else {
4848
        pInfo->min = pCtx->start.key;
×
4849
      }
4850

4851
      if (pCtx->end.key == INT64_MIN) {
4,744,088✔
4852
        pInfo->max =
4,682,749✔
4853
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
4,684,310✔
4854
      } else {
4855
        pInfo->max = pCtx->end.key + 1;
60,237✔
4856
      }
4857
    }
4858
  }
4859

4860
_elapsed_over:
4,777,551✔
4861
  // data in the check operation are all null, not output
4862
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
4,777,551✔
4863

4864
  return TSDB_CODE_SUCCESS;
4,778,495✔
4865
}
4866

4867
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4868
  pOutput->timeUnit = pInput->timeUnit;
×
4869
  if (pOutput->min > pInput->min) {
×
4870
    pOutput->min = pInput->min;
×
4871
  }
4872

4873
  if (pOutput->max < pInput->max) {
×
4874
    pOutput->max = pInput->max;
×
4875
  }
4876
}
×
4877

4878
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4879
  SInputColumnInfoData* pInput = &pCtx->input;
×
4880
  SColumnInfoData*      pCol = pInput->pData[0];
×
4881
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4882
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4883
  }
4884

4885
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4886

4887
  int32_t start = pInput->startRowIndex;
×
4888

4889
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4890
    char*         data = colDataGetData(pCol, i);
×
4891
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4892
    elapsedTransferInfo(pInputInfo, pInfo);
×
4893
  }
4894

4895
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4896
  return TSDB_CODE_SUCCESS;
×
4897
}
4898

4899
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,719,197✔
4900
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,719,197✔
4901
  double        result = (double)(pInfo->max - pInfo->min);
4,719,197✔
4902
  pInfo->result = fabs(result) / pInfo->timeUnit;
4,719,197✔
4903
  return functionFinalize(pCtx, pBlock);
4,718,738✔
4904
}
4905

4906
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4907
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4908
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4909
  int32_t              resultBytes = getElapsedInfoSize();
×
4910
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4911

4912
  if (NULL == res) {
×
4913
    return terrno;
×
4914
  }
4915
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4916
  varDataSetLen(res, resultBytes);
×
4917

4918
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4919
  int32_t          code = TSDB_CODE_SUCCESS;
×
4920
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4921
  if (NULL == pCol) {
×
4922
    code = terrno;
×
4923
    goto _exit;
×
4924
  }
4925

4926
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4927
  if (TSDB_CODE_SUCCESS != code) {
×
4928
    goto _exit;
×
4929
  }
4930
_exit:
×
4931
  taosMemoryFree(res);
×
4932
  return code;
×
4933
}
4934

4935
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4936
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4937
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4938

4939
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4940
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4941

4942
  elapsedTransferInfo(pSBuf, pDBuf);
×
4943
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4944
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4945
  return TSDB_CODE_SUCCESS;
×
4946
}
4947

4948
int32_t getHistogramInfoSize() {
755,832✔
4949
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
755,832✔
4950
}
4951

4952
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,360,925✔
4953
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
1,360,925✔
4954
  return true;
1,363,119✔
4955
}
4956

4957
static int8_t getHistogramBinType(char* binTypeStr) {
935,560✔
4958
  int8_t binType;
4959
  if (strcasecmp(binTypeStr, "user_input") == 0) {
935,560✔
4960
    binType = USER_INPUT_BIN;
478,640✔
4961
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
456,920✔
4962
    binType = LINEAR_BIN;
77,472✔
4963
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
379,448✔
4964
    binType = LOG_BIN;
379,572✔
4965
  } else {
4966
    binType = UNKNOWN_BIN;
×
4967
  }
4968

4969
  return binType;
935,560✔
4970
}
4971

4972
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
935,560✔
4973
  cJSON*  binDesc = cJSON_Parse(binDescStr);
935,560✔
4974
  int32_t numOfBins;
4975
  double* intervals;
4976
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
936,452✔
4977
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
457,044✔
4978
    int32_t startIndex;
4979
    if (numOfParams != 4) {
457,044✔
4980
      cJSON_Delete(binDesc);
×
4981
      return TSDB_CODE_FAILED;
×
4982
    }
4983

4984
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
457,044✔
4985
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
457,044✔
4986
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
457,044✔
4987
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
457,044✔
4988
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
457,044✔
4989

4990
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
457,044✔
4991
      cJSON_Delete(binDesc);
×
4992
      return TSDB_CODE_FAILED;
×
4993
    }
4994

4995
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
457,044✔
4996
      cJSON_Delete(binDesc);
×
4997
      return TSDB_CODE_FAILED;
×
4998
    }
4999

5000
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
457,044✔
5001
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
457,044✔
5002
      cJSON_Delete(binDesc);
×
5003
      return TSDB_CODE_FAILED;
×
5004
    }
5005

5006
    int32_t counter = (int32_t)count->valueint;
457,044✔
5007
    if (infinity->valueint == false) {
457,044✔
5008
      startIndex = 0;
457,044✔
5009
      numOfBins = counter + 1;
457,044✔
5010
    } else {
5011
      startIndex = 1;
×
5012
      numOfBins = counter + 3;
×
5013
    }
5014

5015
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
457,044✔
5016
    if (NULL == intervals) {
457,044✔
5017
      cJSON_Delete(binDesc);
×
5018
      qError("histogram function out of memory");
×
5019
      return terrno;
×
5020
    }
5021
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
457,044✔
5022
      // linear bin process
5023
      if (width->valuedouble == 0) {
77,472✔
5024
        taosMemoryFree(intervals);
×
5025
        cJSON_Delete(binDesc);
×
5026
        return TSDB_CODE_FAILED;
×
5027
      }
5028
      for (int i = 0; i < counter + 1; ++i) {
232,416✔
5029
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
154,944✔
5030
        if (isinf(intervals[startIndex])) {
154,944✔
5031
          taosMemoryFree(intervals);
×
5032
          cJSON_Delete(binDesc);
×
5033
          return TSDB_CODE_FAILED;
×
5034
        }
5035
        startIndex++;
154,944✔
5036
      }
5037
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
379,572✔
5038
      // log bin process
5039
      if (start->valuedouble == 0) {
379,572✔
5040
        taosMemoryFree(intervals);
×
5041
        cJSON_Delete(binDesc);
×
5042
        return TSDB_CODE_FAILED;
×
5043
      }
5044
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
379,572✔
5045
        taosMemoryFree(intervals);
×
5046
        cJSON_Delete(binDesc);
×
5047
        return TSDB_CODE_FAILED;
×
5048
      }
5049
      for (int i = 0; i < counter + 1; ++i) {
2,347,116✔
5050
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
1,967,544✔
5051
        if (isinf(intervals[startIndex])) {
1,967,544✔
5052
          taosMemoryFree(intervals);
×
5053
          cJSON_Delete(binDesc);
×
5054
          return TSDB_CODE_FAILED;
×
5055
        }
5056
        startIndex++;
1,967,544✔
5057
      }
5058
    } else {
5059
      taosMemoryFree(intervals);
×
5060
      cJSON_Delete(binDesc);
×
5061
      return TSDB_CODE_FAILED;
×
5062
    }
5063

5064
    if (infinity->valueint == true) {
457,044✔
5065
      intervals[0] = -INFINITY;
×
5066
      intervals[numOfBins - 1] = INFINITY;
×
5067
      // in case of desc bin orders, -inf/inf should be swapped
5068
      if (numOfBins < 4) {
×
5069
        return TSDB_CODE_FAILED;
×
5070
      }
5071
      if (intervals[1] > intervals[numOfBins - 2]) {
×
5072
        TSWAP(intervals[0], intervals[numOfBins - 1]);
×
5073
      }
5074
    }
5075
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
478,640✔
5076
    if (binType != USER_INPUT_BIN) {
479,408✔
5077
      cJSON_Delete(binDesc);
×
5078
      return TSDB_CODE_FAILED;
×
5079
    }
5080
    numOfBins = cJSON_GetArraySize(binDesc);
479,408✔
5081
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
479,024✔
5082
    if (NULL == intervals) {
479,024✔
5083
      cJSON_Delete(binDesc);
×
5084
      qError("histogram function out of memory");
×
5085
      return terrno;
×
5086
    }
5087
    cJSON* bin = binDesc->child;
479,024✔
5088
    if (bin == NULL) {
479,024✔
5089
      taosMemoryFree(intervals);
×
5090
      cJSON_Delete(binDesc);
×
5091
      return TSDB_CODE_FAILED;
×
5092
    }
5093
    int i = 0;
479,024✔
5094
    while (bin) {
2,082,294✔
5095
      intervals[i] = bin->valuedouble;
1,604,416✔
5096
      if (!cJSON_IsNumber(bin)) {
1,604,416✔
5097
        taosMemoryFree(intervals);
×
5098
        cJSON_Delete(binDesc);
×
5099
        return TSDB_CODE_FAILED;
×
5100
      }
5101
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
1,603,654✔
5102
        taosMemoryFree(intervals);
×
5103
        cJSON_Delete(binDesc);
×
5104
        return TSDB_CODE_FAILED;
×
5105
      }
5106
      bin = bin->next;
1,602,886✔
5107
      i++;
1,603,270✔
5108
    }
5109
  } else {
5110
    cJSON_Delete(binDesc);
×
5111
    return TSDB_CODE_FAILED;
×
5112
  }
5113

5114
  pInfo->numOfBins = numOfBins - 1;
934,922✔
5115
  pInfo->normalized = normalized;
936,452✔
5116
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
3,729,580✔
5117
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
2,792,750✔
5118
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
2,791,982✔
5119
    pInfo->bins[i].count = 0;
2,791,982✔
5120
  }
5121

5122
  taosMemoryFree(intervals);
936,068✔
5123
  cJSON_Delete(binDesc);
935,684✔
5124

5125
  return TSDB_CODE_SUCCESS;
936,074✔
5126
}
5127

5128
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
936,068✔
5129
  if (pResultInfo->initialized) {
936,068✔
5130
    return TSDB_CODE_SUCCESS;
×
5131
  }
5132
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
936,452✔
5133
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5134
  }
5135

5136
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
936,068✔
5137
  pInfo->numOfBins = 0;
936,452✔
5138
  pInfo->totalCount = 0;
936,452✔
5139
  pInfo->normalized = 0;
936,452✔
5140

5141
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
936,452✔
5142
  if (binTypeStr == NULL) {
935,560✔
5143
    return terrno;
×
5144
  }
5145
  int8_t binType = getHistogramBinType(binTypeStr);
935,560✔
5146
  taosMemoryFree(binTypeStr);
935,300✔
5147

5148
  if (binType == UNKNOWN_BIN) {
936,068✔
5149
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5150
  }
5151
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
936,068✔
5152
  if (binDesc == NULL) {
935,176✔
5153
    return terrno;
×
5154
  }
5155
  int64_t normalized = pCtx->param[3].param.i;
935,176✔
5156
  if (normalized != 0 && normalized != 1) {
936,452✔
5157
    taosMemoryFree(binDesc);
×
5158
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5159
  }
5160
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
936,452✔
5161
  if (TSDB_CODE_SUCCESS != code) {
936,068✔
5162
    taosMemoryFree(binDesc);
×
5163
    return code;
×
5164
  }
5165
  taosMemoryFree(binDesc);
936,068✔
5166

5167
  return TSDB_CODE_SUCCESS;
935,690✔
5168
}
5169

5170
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
1,090,446✔
5171
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,090,446✔
5172

5173
  SInputColumnInfoData* pInput = &pCtx->input;
1,090,954✔
5174
  SColumnInfoData*      pCol = pInput->pData[0];
1,091,716✔
5175

5176
  int32_t type = pInput->pData[0]->info.type;
1,091,332✔
5177

5178
  int32_t start = pInput->startRowIndex;
1,091,208✔
5179
  int32_t numOfRows = pInput->numOfRows;
1,092,100✔
5180

5181
  int32_t numOfElems = 0;
1,094,398✔
5182
  for (int32_t i = start; i < numOfRows + start; ++i) {
157,834,871✔
5183
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
156,742,771✔
5184
      continue;
85,992,810✔
5185
    }
5186

5187
    numOfElems++;
70,749,025✔
5188

5189
    char*  data = colDataGetData(pCol, i);
70,749,025✔
5190
    double v;
5191
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
70,762,897✔
5192

5193
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
264,347,884✔
5194
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
215,700,477✔
5195
        pInfo->bins[k].count++;
22,151,296✔
5196
        pInfo->totalCount++;
22,151,296✔
5197
        break;
22,151,296✔
5198
      }
5199
    }
5200
  }
5201

5202
  if (!isPartial) {
1,092,100✔
5203
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
739,592✔
5204
  } else {
5205
    GET_RES_INFO(pCtx)->numOfRes = 1;
352,508✔
5206
  }
5207
  return TSDB_CODE_SUCCESS;
1,092,100✔
5208
}
5209

5210
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
739,592✔
5211

5212
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
351,232✔
5213

5214
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
225,068✔
5215
  pOutput->normalized = pInput->normalized;
225,068✔
5216
  pOutput->numOfBins = pInput->numOfBins;
225,068✔
5217
  pOutput->totalCount += pInput->totalCount;
225,068✔
5218
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
1,090,420✔
5219
    pOutput->bins[k].lower = pInput->bins[k].lower;
865,352✔
5220
    pOutput->bins[k].upper = pInput->bins[k].upper;
865,352✔
5221
    pOutput->bins[k].count += pInput->bins[k].count;
865,352✔
5222
  }
5223
}
225,068✔
5224

5225
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
225,068✔
5226
  SInputColumnInfoData* pInput = &pCtx->input;
225,068✔
5227
  SColumnInfoData*      pCol = pInput->pData[0];
225,068✔
5228
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
225,068✔
5229
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
5230
  }
5231

5232
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
225,068✔
5233

5234
  int32_t start = pInput->startRowIndex;
225,068✔
5235

5236
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
450,136✔
5237
    char*           data = colDataGetData(pCol, i);
225,068✔
5238
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
225,068✔
5239
    histogramTransferInfo(pInputInfo, pInfo);
225,068✔
5240
  }
5241

5242
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
225,068✔
5243
  return TSDB_CODE_SUCCESS;
225,068✔
5244
}
5245

5246
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
914,555✔
5247
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
914,555✔
5248
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
914,555✔
5249
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
914,555✔
5250
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
914,555✔
5251
  int32_t              code = TSDB_CODE_SUCCESS;
914,555✔
5252

5253
  int32_t currentRow = pBlock->info.rows;
914,555✔
5254
  if (NULL == pCol) {
914,555✔
5255
    return TSDB_CODE_OUT_OF_RANGE;
×
5256
  }
5257

5258
  if (pInfo->normalized) {
914,555✔
5259
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
812,608✔
5260
      if (pInfo->totalCount != 0) {
493,248✔
5261
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
217,908✔
5262
      } else {
5263
        pInfo->bins[k].percentage = 0;
275,340✔
5264
      }
5265
    }
5266
  }
5267

5268
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
3,642,481✔
5269
    int32_t len;
5270
    char    buf[512] = {0};
2,727,926✔
5271
    if (!pInfo->normalized) {
2,727,926✔
5272
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
2,234,300✔
5273
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
5274
                     pInfo->bins[i].upper, pInfo->bins[i].count);
5275
    } else {
5276
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
493,248✔
5277
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
5278
                     pInfo->bins[i].percentage);
5279
    }
5280
    varDataSetLen(buf, len);
2,727,926✔
5281
    code = colDataSetVal(pCol, currentRow, buf, false);
2,727,926✔
5282
    if (TSDB_CODE_SUCCESS != code) {
2,727,926✔
5283
      return code;
×
5284
    }
5285
    currentRow++;
2,727,926✔
5286
  }
5287

5288
  return code;
914,555✔
5289
}
5290

5291
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
225,068✔
5292
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
225,068✔
5293
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
225,068✔
5294
  int32_t              resultBytes = getHistogramInfoSize();
225,068✔
5295
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
225,068✔
5296

5297
  if (NULL == res) {
225,068✔
5298
    return terrno;
×
5299
  }
5300
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
225,068✔
5301
  varDataSetLen(res, resultBytes);
225,068✔
5302

5303
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
225,068✔
5304
  int32_t          code = TSDB_CODE_SUCCESS;
225,068✔
5305
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
225,068✔
5306
  if (NULL == pCol) {
225,068✔
5307
    code = terrno;
×
5308
    goto _exit;
×
5309
  }
5310
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
225,068✔
5311

5312
_exit:
225,068✔
5313
  taosMemoryFree(res);
225,068✔
5314
  return code;
225,068✔
5315
}
5316

5317
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5318
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5319
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5320

5321
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5322
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5323

5324
  histogramTransferInfo(pSBuf, pDBuf);
×
5325
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5326
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5327
  return TSDB_CODE_SUCCESS;
×
5328
}
5329

5330
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
264,522✔
5331

5332
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
3,851,343✔
5333
  pEnv->calcMemSize = sizeof(SHLLInfo);
3,851,343✔
5334
  return true;
3,851,343✔
5335
}
5336

5337
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
607,796,527✔
5338
  uint64_t hash = MurmurHash3_64(data, bytes);
607,796,527✔
5339
  int32_t  index = hash & HLL_BUCKET_MASK;
607,691,895✔
5340
  hash >>= HLL_BUCKET_BITS;
607,691,895✔
5341
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
607,691,895✔
5342
  uint64_t bit = 1;
607,691,895✔
5343
  uint8_t  count = 1;
607,691,895✔
5344
  while ((hash & bit) == 0) {
1,245,932,549✔
5345
    count++;
638,240,654✔
5346
    bit <<= 1;
638,240,654✔
5347
  }
5348
  *buk = index;
607,691,895✔
5349
  return count;
607,793,689✔
5350
}
5351

5352
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
9,179,743✔
5353
  uint64_t* word = (uint64_t*)buckets;
9,179,743✔
5354
  uint8_t*  bytes;
5355

5356
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
2,147,483,647✔
5357
    if (*word == 0) {
2,147,483,647✔
5358
      bucketHisto[0] += 8;
2,147,483,647✔
5359
    } else {
5360
      bytes = (uint8_t*)word;
93,358,616✔
5361
      bucketHisto[bytes[0]]++;
93,358,616✔
5362
      bucketHisto[bytes[1]]++;
108,324,631✔
5363
      bucketHisto[bytes[2]]++;
108,328,397✔
5364
      bucketHisto[bytes[3]]++;
108,331,625✔
5365
      bucketHisto[bytes[4]]++;
108,339,695✔
5366
      bucketHisto[bytes[5]]++;
108,341,309✔
5367
      bucketHisto[bytes[6]]++;
108,345,613✔
5368
      bucketHisto[bytes[7]]++;
108,347,765✔
5369
    }
5370
    word++;
2,147,483,647✔
5371
  }
5372
}
736✔
5373
static double hllTau(double x) {
9,179,743✔
5374
  if (x == 0. || x == 1.) return 0.;
9,179,743✔
5375
  double zPrime;
5376
  double y = 1.0;
×
5377
  double z = 1 - x;
×
5378
  do {
5379
    x = sqrt(x);
×
5380
    zPrime = z;
×
5381
    y *= 0.5;
×
5382
    z -= pow(1 - x, 2) * y;
×
5383
  } while (zPrime != z);
×
5384
  return z / 3;
×
5385
}
5386

5387
static double hllSigma(double x) {
9,180,281✔
5388
  if (x == 1.0) return INFINITY;
9,180,281✔
5389
  double zPrime;
5390
  double y = 1;
7,531,417✔
5391
  double z = x;
7,531,417✔
5392
  do {
5393
    x *= x;
144,787,222✔
5394
    zPrime = z;
144,787,222✔
5395
    z += x * y;
144,787,222✔
5396
    y += y;
144,787,222✔
5397
  } while (zPrime != z);
144,787,222✔
5398
  return z;
7,531,417✔
5399
}
5400

5401
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
5402
// sketches"
5403
static uint64_t hllCountCnt(uint8_t* buckets) {
9,179,743✔
5404
  double  m = HLL_BUCKETS;
9,179,743✔
5405
  int32_t buckethisto[64] = {0};
9,179,743✔
5406
  hllBucketHisto(buckets, buckethisto);
9,179,754✔
5407

5408
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
9,179,743✔
5409
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
468,162,051✔
5410
    z += buckethisto[j];
458,981,770✔
5411
    z *= 0.5;
458,982,308✔
5412
  }
5413

5414
  z += m * hllSigma(buckethisto[0] / (double)m);
9,180,281✔
5415
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
9,180,281✔
5416

5417
  return (uint64_t)E;
9,180,281✔
5418
}
5419

5420
int32_t hllFunction(SqlFunctionCtx* pCtx) {
9,435,797✔
5421
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,435,797✔
5422

5423
  SInputColumnInfoData* pInput = &pCtx->input;
9,435,797✔
5424
  SColumnInfoData*      pCol = pInput->pData[0];
9,436,335✔
5425

5426
  int32_t type = pCol->info.type;
9,435,797✔
5427
  int32_t bytes = pCol->info.bytes;
9,435,797✔
5428

5429
  int32_t start = pInput->startRowIndex;
9,434,799✔
5430
  int32_t numOfRows = pInput->numOfRows;
9,435,797✔
5431

5432
  int32_t numOfElems = 0;
9,434,799✔
5433
  if (IS_NULL_TYPE(type)) {
9,434,799✔
5434
    goto _hll_over;
140,807✔
5435
  }
5436

5437
  for (int32_t i = start; i < numOfRows + start; ++i) {
724,786,019✔
5438
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
828,252,596✔
5439
      continue;
107,712,594✔
5440
    }
5441

5442
    numOfElems++;
607,779,947✔
5443

5444
    char* data = colDataGetData(pCol, i);
607,779,947✔
5445
    if (IS_VAR_DATA_TYPE(type)) {
607,805,945✔
5446
      if (IS_STR_DATA_BLOB(type)) {
76,530,920✔
5447
        bytes = blobDataLen(data);
2,178✔
5448
        data = blobDataVal(data);
×
5449
      } else {
5450
        bytes = varDataLen(data);
76,528,742✔
5451
        data = varDataVal(data);
76,528,742✔
5452
      }
5453
    }
5454

5455
    int32_t index = 0;
607,803,767✔
5456
    uint8_t count = hllCountNum(data, bytes, &index);
607,799,893✔
5457
    uint8_t oldcount = pInfo->buckets[index];
607,767,305✔
5458
    if (count > oldcount) {
607,774,655✔
5459
      pInfo->buckets[index] = count;
151,353,721✔
5460
    }
5461
  }
5462

5463
_hll_over:
9,290,878✔
5464
  pInfo->totalCount += numOfElems;
9,431,685✔
5465

5466
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
9,435,797✔
5467
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
491,205✔
5468
  } else {
5469
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
8,944,592✔
5470
  }
5471

5472
  return TSDB_CODE_SUCCESS;
9,435,797✔
5473
}
5474

5475
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
264,685✔
5476
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
2,147,483,647✔
5477
    if (pOutput->buckets[k] < pInput->buckets[k]) {
2,147,483,647✔
5478
      pOutput->buckets[k] = pInput->buckets[k];
31,058,032✔
5479
    }
5480
  }
5481
  pOutput->totalCount += pInput->totalCount;
330✔
5482
}
264,685✔
5483

5484
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
264,685✔
5485
  SInputColumnInfoData* pInput = &pCtx->input;
264,685✔
5486
  SColumnInfoData*      pCol = pInput->pData[0];
264,685✔
5487

5488
  if (IS_NULL_TYPE(pCol->info.type)) {
264,685✔
5489
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
5490
    return TSDB_CODE_SUCCESS;
×
5491
  }
5492

5493
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
264,685✔
5494
    return TSDB_CODE_SUCCESS;
×
5495
  }
5496

5497
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
264,685✔
5498

5499
  int32_t start = pInput->startRowIndex;
264,685✔
5500

5501
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
529,370✔
5502
    if (colDataIsNull_s(pCol, i)) continue;
528,843✔
5503
    char*     data = colDataGetData(pCol, i);
264,158✔
5504
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
264,158✔
5505
    hllTransferInfo(pInputInfo, pInfo);
264,685✔
5506
  }
5507

5508
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
264,685✔
5509
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
61✔
5510
  } else {
5511
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
264,624✔
5512
  }
5513

5514
  return TSDB_CODE_SUCCESS;
264,685✔
5515
}
5516

5517
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
9,179,743✔
5518
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
9,179,743✔
5519

5520
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,179,743✔
5521
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
9,179,743✔
5522
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
9,180,281✔
5523
    pInfo->numOfRes = 1;
1,158,086✔
5524
  }
5525

5526
  return functionFinalize(pCtx, pBlock);
9,180,281✔
5527
}
5528

5529
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
264,685✔
5530
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
264,685✔
5531
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
264,685✔
5532
  int32_t              resultBytes = getHLLInfoSize();
264,522✔
5533
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
264,522✔
5534

5535
  if (NULL == res) {
264,522✔
5536
    return terrno;
×
5537
  }
5538
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
264,522✔
5539
  varDataSetLen(res, resultBytes);
264,522✔
5540

5541
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
264,685✔
5542
  int32_t          code = TSDB_CODE_SUCCESS;
264,685✔
5543
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
264,685✔
5544
  if (NULL == pCol) {
264,685✔
5545
    code = terrno;
×
5546
    goto _exit;
×
5547
  }
5548

5549
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
264,685✔
5550

5551
_exit:
264,685✔
5552
  taosMemoryFree(res);
264,685✔
5553
  return code;
264,685✔
5554
}
5555

5556
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5557
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5558
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5559

5560
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5561
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5562

5563
  hllTransferInfo(pSBuf, pDBuf);
×
5564
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5565
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5566
  return TSDB_CODE_SUCCESS;
×
5567
}
5568

5569
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,332,105✔
5570
  pEnv->calcMemSize = sizeof(SStateInfo);
1,332,105✔
5571
  return true;
1,332,105✔
5572
}
5573

5574
static int8_t getStateOpType(char* opStr) {
1,354,029✔
5575
  int8_t opType;
5576
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,354,029✔
5577
    opType = STATE_OPER_LT;
109,120✔
5578
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
1,244,909✔
5579
    opType = STATE_OPER_GT;
209,409✔
5580
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
1,035,500✔
5581
    opType = STATE_OPER_LE;
112,820✔
5582
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
922,680✔
5583
    opType = STATE_OPER_GE;
154,624✔
5584
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
768,056✔
5585
    opType = STATE_OPER_NE;
443,476✔
5586
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
324,580✔
5587
    opType = STATE_OPER_EQ;
324,580✔
5588
  } else {
5589
    opType = STATE_OPER_INVALID;
×
5590
  }
5591

5592
  return opType;
1,354,029✔
5593
}
5594

5595
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
117,600,136✔
5596
  char* data = colDataGetData(pCol, index);
117,600,136✔
5597
  switch (pCol->info.type) {
117,600,136✔
5598
    case TSDB_DATA_TYPE_TINYINT: {
24,977,200✔
5599
      int8_t v = *(int8_t*)data;
24,977,200✔
5600
      STATE_COMP(op, v, param);
24,977,200✔
5601
      break;
×
5602
    }
5603
    case TSDB_DATA_TYPE_UTINYINT: {
30,703,104✔
5604
      uint8_t v = *(uint8_t*)data;
30,703,104✔
5605
      STATE_COMP(op, v, param);
30,703,104✔
5606
      break;
×
5607
    }
5608
    case TSDB_DATA_TYPE_SMALLINT: {
681,920✔
5609
      int16_t v = *(int16_t*)data;
681,920✔
5610
      STATE_COMP(op, v, param);
681,920✔
5611
      break;
×
5612
    }
5613
    case TSDB_DATA_TYPE_USMALLINT: {
622,080✔
5614
      uint16_t v = *(uint16_t*)data;
622,080✔
5615
      STATE_COMP(op, v, param);
622,080✔
5616
      break;
×
5617
    }
5618
    case TSDB_DATA_TYPE_INT: {
50,681,549✔
5619
      int32_t v = *(int32_t*)data;
50,681,549✔
5620
      STATE_COMP(op, v, param);
50,681,549✔
5621
      break;
×
5622
    }
5623
    case TSDB_DATA_TYPE_UINT: {
622,080✔
5624
      uint32_t v = *(uint32_t*)data;
622,080✔
5625
      STATE_COMP(op, v, param);
622,080✔
5626
      break;
×
5627
    }
5628
    case TSDB_DATA_TYPE_BIGINT: {
691,440✔
5629
      int64_t v = *(int64_t*)data;
691,440✔
5630
      STATE_COMP(op, v, param);
691,440✔
5631
      break;
×
5632
    }
5633
    case TSDB_DATA_TYPE_UBIGINT: {
622,080✔
5634
      uint64_t v = *(uint64_t*)data;
622,080✔
5635
      STATE_COMP(op, v, param);
622,080✔
5636
      break;
×
5637
    }
5638
    case TSDB_DATA_TYPE_FLOAT: {
681,920✔
5639
      float v = *(float*)data;
681,920✔
5640
      STATE_COMP(op, v, param);
681,920✔
5641
      break;
×
5642
    }
5643
    case TSDB_DATA_TYPE_DOUBLE: {
7,316,763✔
5644
      double v = *(double*)data;
7,316,763✔
5645
      STATE_COMP(op, v, param);
7,316,763✔
5646
      break;
×
5647
    }
5648
    default: {
×
5649
      return false;
×
5650
    }
5651
  }
5652
  return false;
×
5653
}
5654

5655
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
141,938✔
5656
  int32_t              code = TSDB_CODE_SUCCESS;
141,938✔
5657
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
141,938✔
5658
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
141,938✔
5659

5660
  SInputColumnInfoData* pInput = &pCtx->input;
141,938✔
5661
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
141,938✔
5662

5663
  SColumnInfoData* pInputCol = pInput->pData[0];
141,938✔
5664

5665
  int32_t          numOfElems = 0;
141,938✔
5666
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
141,938✔
5667

5668
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
141,938✔
5669
  if (STATE_OPER_INVALID == op) {
141,938✔
5670
    return 0;
×
5671
  }
5672

5673
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
38,995,890✔
5674
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
38,854,800✔
5675
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
848✔
5676
    } else {
5677
      pInfo->prevTs = tsList[i];
38,853,952✔
5678
    }
5679

5680
    pInfo->isPrevTsSet = true;
38,853,952✔
5681
    numOfElems++;
38,853,952✔
5682

5683
    if (colDataIsNull_f(pInputCol, i)) {
38,853,952✔
5684
      colDataSetNULL(pOutput, i);
2,410,572✔
5685
      // handle selectivity
5686
      if (pCtx->subsidiaries.num > 0) {
2,410,572✔
5687
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,933✔
5688
        if (TSDB_CODE_SUCCESS != code) {
3,933✔
5689
          return code;
×
5690
        }
5691
      }
5692
      continue;
2,410,572✔
5693
    }
5694

5695
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
36,443,380✔
5696

5697
    int64_t output = -1;
36,443,380✔
5698
    if (ret) {
36,443,380✔
5699
      output = ++pInfo->count;
24,782,761✔
5700
    } else {
5701
      pInfo->count = 0;
11,660,619✔
5702
    }
5703
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
36,443,380✔
5704
    if (TSDB_CODE_SUCCESS != code) {
36,443,380✔
5705
      return code;
×
5706
    }
5707

5708
    // handle selectivity
5709
    if (pCtx->subsidiaries.num > 0) {
36,443,380✔
5710
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
841,540✔
5711
      if (TSDB_CODE_SUCCESS != code) {
841,540✔
5712
        return code;
×
5713
      }
5714
    }
5715
  }
5716

5717
  pResInfo->numOfRes = numOfElems;
141,090✔
5718
  return TSDB_CODE_SUCCESS;
141,090✔
5719
}
5720

5721
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
1,212,091✔
5722
  int32_t              code = TSDB_CODE_SUCCESS;
1,212,091✔
5723
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,212,091✔
5724
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,212,091✔
5725

5726
  SInputColumnInfoData* pInput = &pCtx->input;
1,211,713✔
5727
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,212,091✔
5728

5729
  SColumnInfoData* pInputCol = pInput->pData[0];
1,212,091✔
5730

5731
  int32_t          numOfElems = 0;
1,212,091✔
5732
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,212,091✔
5733

5734
  // TODO: process timeUnit for different db precisions
5735
  int32_t timeUnit = 1;
1,212,091✔
5736
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
1,212,091✔
5737
    timeUnit = pCtx->param[3].param.i;
998,298✔
5738
  }
5739

5740
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
1,212,091✔
5741
  if (STATE_OPER_INVALID == op) {
1,212,091✔
5742
    return TSDB_CODE_INVALID_PARA;
×
5743
  }
5744

5745
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
130,501,949✔
5746
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
129,291,840✔
5747
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
848✔
5748
    } else {
5749
      pInfo->prevTs = tsList[i];
129,290,992✔
5750
    }
5751

5752
    pInfo->isPrevTsSet = true;
129,291,370✔
5753
    numOfElems++;
129,291,996✔
5754

5755
    if (colDataIsNull_f(pInputCol, i)) {
129,291,996✔
5756
      colDataSetNULL(pOutput, i);
48,155,274✔
5757
      // handle selectivity
5758
      if (pCtx->subsidiaries.num > 0) {
48,185,644✔
5759
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
7,625✔
5760
        if (TSDB_CODE_SUCCESS != code) {
7,625✔
5761
          return code;
×
5762
        }
5763
      }
5764
      continue;
48,185,644✔
5765
    }
5766

5767
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
81,156,756✔
5768
    int64_t output = -1;
81,156,756✔
5769
    if (ret) {
81,156,756✔
5770
      if (pInfo->durationStart == 0) {
46,094,962✔
5771
        output = 0;
2,100,472✔
5772
        pInfo->durationStart = tsList[i];
2,100,472✔
5773
      } else {
5774
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
43,994,490✔
5775
      }
5776
    } else {
5777
      pInfo->durationStart = 0;
35,061,794✔
5778
    }
5779
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
81,156,756✔
5780
    if (TSDB_CODE_SUCCESS != code) {
81,156,756✔
5781
      return code;
×
5782
    }
5783

5784
    // handle selectivity
5785
    if (pCtx->subsidiaries.num > 0) {
81,156,756✔
5786
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
94,660✔
5787
      if (TSDB_CODE_SUCCESS != code) {
94,660✔
5788
        return code;
×
5789
      }
5790
    }
5791
  }
5792

5793
  pResInfo->numOfRes = numOfElems;
1,211,243✔
5794
  return TSDB_CODE_SUCCESS;
1,211,243✔
5795
}
5796

5797
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
671,992✔
5798
  pEnv->calcMemSize = sizeof(SSumRes);
671,992✔
5799
  return true;
671,992✔
5800
}
5801

5802
int32_t csumFunction(SqlFunctionCtx* pCtx) {
753,595✔
5803
  int32_t              code = TSDB_CODE_SUCCESS;
753,595✔
5804
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
753,595✔
5805
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
753,217✔
5806

5807
  SInputColumnInfoData* pInput = &pCtx->input;
753,595✔
5808
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
753,973✔
5809

5810
  SColumnInfoData* pInputCol = pInput->pData[0];
753,595✔
5811
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
753,217✔
5812

5813
  int32_t numOfElems = 0;
753,595✔
5814
  int32_t type = pInputCol->info.type;
753,595✔
5815
  int32_t startOffset = pCtx->offset;
753,217✔
5816
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
126,626,137✔
5817
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
125,849,469✔
5818
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
7,137✔
5819
    } else {
5820
      pSumRes->prevTs = tsList[i];
125,839,986✔
5821
    }
5822
    pSumRes->isPrevTsSet = true;
125,841,576✔
5823

5824
    int32_t pos = startOffset + numOfElems;
125,843,544✔
5825
    if (colDataIsNull_f(pInputCol, i)) {
125,843,544✔
5826
      // colDataSetNULL(pOutput, i);
5827
      continue;
47,527,691✔
5828
    }
5829

5830
    char* data = colDataGetData(pInputCol, i);
78,344,473✔
5831
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
125,568,230✔
5832
      int64_t v;
5833
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
47,223,379✔
5834
      pSumRes->isum += v;
47,223,379✔
5835
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
47,223,379✔
5836
      if (TSDB_CODE_SUCCESS != code) {
47,223,379✔
5837
        return code;
×
5838
      }
5839
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
41,244,100✔
5840
      uint64_t v;
5841
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
10,122,628✔
5842
      pSumRes->usum += v;
10,122,628✔
5843
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
10,122,628✔
5844
      if (TSDB_CODE_SUCCESS != code) {
10,122,628✔
5845
        return code;
×
5846
      }
5847
    } else if (IS_FLOAT_TYPE(type)) {
20,998,844✔
5848
      double v;
5849
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
20,999,600✔
5850
      pSumRes->dsum += v;
20,999,600✔
5851
      // check for overflow
5852
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
20,999,600✔
5853
        colDataSetNULL(pOutput, pos);
884✔
5854
      } else {
5855
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
20,998,716✔
5856
        if (TSDB_CODE_SUCCESS != code) {
20,998,716✔
5857
          return code;
×
5858
        }
5859
      }
5860
    }
5861

5862
    // handle selectivity
5863
    if (pCtx->subsidiaries.num > 0) {
78,344,851✔
5864
      code = appendSelectivityValue(pCtx, i, pos);
22,664✔
5865
      if (TSDB_CODE_SUCCESS != code) {
22,664✔
5866
        return code;
×
5867
      }
5868
    }
5869

5870
    numOfElems++;
78,345,607✔
5871
  }
5872

5873
  pResInfo->numOfRes = numOfElems;
746,836✔
5874
  return TSDB_CODE_SUCCESS;
746,836✔
5875
}
5876

5877
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
390,675✔
5878
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
390,675✔
5879
  return true;
390,675✔
5880
}
5881

5882
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
865,154✔
5883
  if (pResultInfo->initialized) {
865,154✔
5884
    return TSDB_CODE_SUCCESS;
384,283✔
5885
  }
5886
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
480,871✔
5887
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5888
  }
5889

5890
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
480,871✔
5891
  pInfo->pos = 0;
480,871✔
5892
  pInfo->sum = 0;
480,871✔
5893
  pInfo->prevTs = -1;
480,871✔
5894
  pInfo->isPrevTsSet = false;
480,871✔
5895
  pInfo->numOfPoints = pCtx->param[1].param.i;
480,871✔
5896
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
480,871✔
5897
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5898
  }
5899
  pInfo->pointsMeet = false;
480,871✔
5900

5901
  return TSDB_CODE_SUCCESS;
480,871✔
5902
}
5903

5904
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
474,479✔
5905
  int32_t              code = TSDB_CODE_SUCCESS;
474,479✔
5906
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
474,479✔
5907
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
474,479✔
5908

5909
  SInputColumnInfoData* pInput = &pCtx->input;
474,479✔
5910
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
474,479✔
5911

5912
  SColumnInfoData* pInputCol = pInput->pData[0];
474,479✔
5913
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
474,479✔
5914
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
474,479✔
5915

5916
  int32_t numOfElems = 0;
474,479✔
5917
  int32_t type = pInputCol->info.type;
474,479✔
5918
  int32_t startOffset = pCtx->offset;
474,479✔
5919
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
122,794,497✔
5920
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
122,320,866✔
5921
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
848✔
5922
    } else {
5923
      pInfo->prevTs = tsList[i];
122,320,018✔
5924
    }
5925
    pInfo->isPrevTsSet = true;
122,320,018✔
5926

5927
    int32_t pos = startOffset + numOfElems;
122,320,018✔
5928
    if (colDataIsNull_f(pInputCol, i)) {
122,320,018✔
5929
      // colDataSetNULL(pOutput, i);
5930
      continue;
65,673,455✔
5931
    }
5932

5933
    char*  data = colDataGetData(pInputCol, i);
56,646,563✔
5934
    double v;
5935
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
56,646,563✔
5936

5937
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
56,646,563✔
5938
      pInfo->points[pInfo->pos] = v;
4,968,571✔
5939
      pInfo->sum += v;
4,968,571✔
5940
    } else {
5941
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
51,677,992✔
5942
        pInfo->sum += v;
85,792✔
5943
        pInfo->pointsMeet = true;
85,792✔
5944
      } else {
5945
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
51,592,200✔
5946
      }
5947

5948
      pInfo->points[pInfo->pos] = v;
51,677,992✔
5949
      double result = pInfo->sum / pInfo->numOfPoints;
51,677,992✔
5950
      // check for overflow
5951
      if (isinf(result) || isnan(result)) {
51,677,992✔
5952
        colDataSetNULL(pOutput, pos);
×
5953
      } else {
5954
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
51,677,992✔
5955
        if (TSDB_CODE_SUCCESS != code) {
51,677,992✔
5956
          return code;
×
5957
        }
5958
      }
5959

5960
      // handle selectivity
5961
      if (pCtx->subsidiaries.num > 0) {
51,677,992✔
5962
        code = appendSelectivityValue(pCtx, i, pos);
32,960✔
5963
        if (TSDB_CODE_SUCCESS != code) {
32,960✔
5964
          return code;
×
5965
        }
5966
      }
5967

5968
      numOfElems++;
51,677,992✔
5969
    }
5970

5971
    pInfo->pos++;
56,646,563✔
5972
    if (pInfo->pos == pInfo->numOfPoints) {
56,646,563✔
5973
      pInfo->pos = 0;
711,226✔
5974
    }
5975
  }
5976

5977
  pResInfo->numOfRes = numOfElems;
473,631✔
5978
  return TSDB_CODE_SUCCESS;
473,631✔
5979
}
5980

5981
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
3,823,988✔
5982
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,823,988✔
5983
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,823,988✔
5984

5985
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
3,823,988✔
5986
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
3,824,496✔
5987

5988
  return pInfo;
3,823,988✔
5989
}
5990

5991
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
800,726✔
5992
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
800,726✔
5993
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
800,574✔
5994
  int32_t      numOfSamples = pVal->datum.i;
800,528✔
5995
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
800,528✔
5996
  return true;
799,288✔
5997
}
5998

5999
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,745,513✔
6000
  if (pResultInfo->initialized) {
1,745,513✔
6001
    return TSDB_CODE_SUCCESS;
×
6002
  }
6003
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,745,513✔
6004
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6005
  }
6006

6007
  taosSeedRand(taosSafeRand());
1,745,513✔
6008

6009
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,745,513✔
6010
  pInfo->samples = pCtx->param[1].param.i;
1,745,513✔
6011
  pInfo->totalPoints = 0;
1,745,513✔
6012
  pInfo->numSampled = 0;
1,745,513✔
6013
  pInfo->colType = pCtx->resDataInfo.type;
1,745,513✔
6014
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,745,513✔
6015
  pInfo->nullTuplePos.pageId = -1;
1,745,513✔
6016
  pInfo->nullTupleSaved = false;
1,745,513✔
6017
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
1,745,513✔
6018
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
1,745,513✔
6019

6020
  return TSDB_CODE_SUCCESS;
1,745,513✔
6021
}
6022

6023
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
53,659,685✔
6024
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
53,659,685✔
6025
}
53,658,837✔
6026

6027
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
93,470,794✔
6028
  pInfo->totalPoints++;
93,470,794✔
6029
  if (pInfo->numSampled < pInfo->samples) {
93,470,370✔
6030
    sampleAssignResult(pInfo, data, pInfo->numSampled);
46,340,971✔
6031
    if (pCtx->subsidiaries.num > 0) {
46,340,547✔
6032
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,014,345✔
6033
      if (code != TSDB_CODE_SUCCESS) {
1,014,345✔
6034
        return code;
×
6035
      }
6036
    }
6037
    pInfo->numSampled++;
46,340,971✔
6038
  } else {
6039
    int32_t j = (int32_t)(taosRand() % (uint64_t)pInfo->totalPoints);
47,129,823✔
6040
    if (j < pInfo->samples) {
47,127,703✔
6041
      sampleAssignResult(pInfo, data, j);
7,318,290✔
6042
      if (pCtx->subsidiaries.num > 0) {
7,318,290✔
6043
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
345,987✔
6044
        if (code != TSDB_CODE_SUCCESS) {
344,715✔
6045
          return code;
×
6046
        }
6047
      }
6048
    }
6049
  }
6050

6051
  return TSDB_CODE_SUCCESS;
93,469,098✔
6052
}
6053

6054
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
2,081,527✔
6055
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,081,527✔
6056
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
2,081,527✔
6057

6058
  SInputColumnInfoData* pInput = &pCtx->input;
2,081,527✔
6059

6060
  SColumnInfoData* pInputCol = pInput->pData[0];
2,081,527✔
6061
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
151,699,780✔
6062
    if (colDataIsNull_s(pInputCol, i)) {
299,186,476✔
6063
      continue;
56,149,155✔
6064
    }
6065

6066
    char*   data = colDataGetData(pInputCol, i);
93,467,742✔
6067
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
93,470,794✔
6068
    if (code != TSDB_CODE_SUCCESS) {
93,469,098✔
6069
      return code;
×
6070
    }
6071
  }
6072

6073
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,081,527✔
6074
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
1,748✔
6075
    if (code != TSDB_CODE_SUCCESS) {
1,748✔
6076
      return code;
×
6077
    }
6078
    pInfo->nullTupleSaved = true;
1,748✔
6079
  }
6080

6081
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
2,081,527✔
6082
  return TSDB_CODE_SUCCESS;
2,081,527✔
6083
}
6084

6085
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,742,969✔
6086
  int32_t              code = TSDB_CODE_SUCCESS;
1,742,969✔
6087
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,742,969✔
6088

6089
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
1,742,969✔
6090
  pEntryInfo->complete = true;
1,742,461✔
6091

6092
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,742,461✔
6093
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,742,969✔
6094
  if (NULL == pCol) {
1,742,461✔
6095
    return TSDB_CODE_OUT_OF_RANGE;
×
6096
  }
6097

6098
  int32_t currentRow = pBlock->info.rows;
1,742,461✔
6099
  if (pInfo->numSampled == 0) {
1,742,461✔
6100
    colDataSetNULL(pCol, currentRow);
326,379✔
6101
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
326,379✔
6102
    return code;
325,871✔
6103
  }
6104
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
47,757,985✔
6105
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
46,341,395✔
6106
    if (TSDB_CODE_SUCCESS != code) {
46,341,395✔
6107
      return code;
×
6108
    }
6109
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
46,341,395✔
6110
    if (TSDB_CODE_SUCCESS != code) {
46,341,395✔
6111
      return code;
×
6112
    }
6113
  }
6114

6115
  return code;
1,416,590✔
6116
}
6117

6118
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6119
#if 0
6120
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
6121
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
6122
  int32_t      numOfPoints = pVal->datum.i;
6123
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
6124
#endif
6125
  return true;
×
6126
}
6127

6128
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
6129
#if 0
6130
  if (!functionSetup(pCtx, pResultInfo)) {
6131
    return false;
6132
  }
6133

6134
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6135
  pInfo->numAdded = 0;
6136
  pInfo->numOfPoints = pCtx->param[1].param.i;
6137
  if (pCtx->numOfParams == 4) {
6138
    pInfo->offset = pCtx->param[2].param.i;
6139
  } else {
6140
    pInfo->offset = 0;
6141
  }
6142
  pInfo->colType = pCtx->resDataInfo.type;
6143
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6144
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
6145
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
6146
    return false;
6147
  }
6148

6149
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
6150
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
6151

6152
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
6153
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6154
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
6155
    pInfo->pItems[i]->isNull = false;
6156
  }
6157
#endif
6158
  return TSDB_CODE_SUCCESS;
×
6159
}
6160

6161
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
6162
#if 0
6163
  pItem->timestamp = ts;
6164
  if (isNull) {
6165
    pItem->isNull = true;
6166
  } else {
6167
    pItem->isNull = false;
6168
    memcpy(pItem->data, data, colBytes);
6169
  }
6170
#endif
6171
}
×
6172

6173
#if 0
6174
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
6175
  STailItem* d1 = *(STailItem**)p1;
6176
  STailItem* d2 = *(STailItem**)p2;
6177
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
6178
}
6179

6180
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
6181
  STailItem** pList = pInfo->pItems;
6182
  if (pInfo->numAdded < pInfo->numOfPoints) {
6183
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
6184
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
6185
    pInfo->numAdded++;
6186
  } else if (pList[0]->timestamp < ts) {
6187
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
6188
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
6189
  }
6190
}
6191
#endif
6192

6193
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
6194
#if 0
6195
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6196
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6197

6198
  SInputColumnInfoData* pInput = &pCtx->input;
6199
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
6200

6201
  SColumnInfoData* pInputCol = pInput->pData[0];
6202
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6203

6204
  int32_t startOffset = pCtx->offset;
6205
  if (pInfo->offset >= pInput->numOfRows) {
6206
    return 0;
6207
  } else {
6208
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
6209
  }
6210
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
6211
    char* data = colDataGetData(pInputCol, i);
6212
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
6213
  }
6214

6215
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
6216

6217
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6218
    int32_t    pos = startOffset + i;
6219
    STailItem* pItem = pInfo->pItems[i];
6220
    if (pItem->isNull) {
6221
      colDataSetNULL(pOutput, pos);
6222
    } else {
6223
      colDataSetVal(pOutput, pos, pItem->data, false);
6224
    }
6225
  }
6226

6227
  return pInfo->numOfPoints;
6228
#endif
6229
  return 0;
×
6230
}
6231

6232
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
6233
#if 0
6234
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6235
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
6236
  pEntryInfo->complete = true;
6237

6238
  int32_t type = pCtx->input.pData[0]->info.type;
6239
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
6240

6241
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6242

6243
  // todo assign the tag value and the corresponding row data
6244
  int32_t currentRow = pBlock->info.rows;
6245
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
6246
    STailItem* pItem = pInfo->pItems[i];
6247
    colDataSetVal(pCol, currentRow, pItem->data, false);
6248
    currentRow += 1;
6249
  }
6250

6251
  return pEntryInfo->numOfRes;
6252
#endif
6253
  return 0;
×
6254
}
6255

6256
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6257
#if 0
6258
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
6259
#endif
6260
  return true;
×
6261
}
6262

6263
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
6264
#if 0
6265
  if (!functionSetup(pCtx, pResInfo)) {
6266
    return false;
6267
  }
6268

6269
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6270
  pInfo->numOfPoints = 0;
6271
  pInfo->colType = pCtx->resDataInfo.type;
6272
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6273
  if (pInfo->pHash != NULL) {
6274
    taosHashClear(pInfo->pHash);
6275
  } else {
6276
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
6277
  }
6278
#endif
6279
  return TSDB_CODE_SUCCESS;
×
6280
}
6281

6282
#if 0
6283
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
6284
  // handle null elements
6285
  if (isNull == true) {
6286
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
6287
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
6288
    if (pInfo->hasNull == false && pItem->isNull == false) {
6289
      pItem->timestamp = ts;
6290
      pItem->isNull = true;
6291
      pInfo->numOfPoints++;
6292
      pInfo->hasNull = true;
6293
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
6294
      pItem->timestamp = ts;
6295
    }
6296
    return;
6297
  }
6298

6299
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
6300
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
6301
  if (pHashItem == NULL) {
6302
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
6303
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
6304
    pItem->timestamp = ts;
6305
    memcpy(pItem->data, data, pInfo->colBytes);
6306

6307
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
6308
    pInfo->numOfPoints++;
6309
  } else if (pHashItem->timestamp > ts) {
6310
    pHashItem->timestamp = ts;
6311
  }
6312
}
6313
#endif
6314

6315
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
6316
#if 0
6317
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6318
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6319

6320
  SInputColumnInfoData* pInput = &pCtx->input;
6321
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
6322

6323
  SColumnInfoData* pInputCol = pInput->pData[0];
6324
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
6325
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6326

6327
  int32_t startOffset = pCtx->offset;
6328
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
6329
    char* data = colDataGetData(pInputCol, i);
6330
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
6331

6332
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
6333
      taosHashCleanup(pInfo->pHash);
6334
      return 0;
6335
    }
6336
  }
6337

6338
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6339
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
6340
    if (pItem->isNull == true) {
6341
      colDataSetNULL(pOutput, i);
6342
    } else {
6343
      colDataSetVal(pOutput, i, pItem->data, false);
6344
    }
6345
    if (pTsOutput != NULL) {
6346
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
6347
    }
6348
  }
6349

6350
  return pInfo->numOfPoints;
6351
#endif
6352
  return 0;
×
6353
}
6354

6355
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
777,574✔
6356
  pEnv->calcMemSize = sizeof(SModeInfo);
777,574✔
6357
  return true;
777,574✔
6358
}
6359

6360
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
944,638✔
6361
  if (pResInfo->initialized) {
944,638✔
6362
    return TSDB_CODE_SUCCESS;
×
6363
  }
6364
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
944,638✔
6365
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6366
  }
6367

6368
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
944,638✔
6369
  pInfo->colType = pCtx->resDataInfo.type;
944,638✔
6370
  pInfo->colBytes = pCtx->resDataInfo.bytes;
944,638✔
6371
  if (pInfo->pHash != NULL) {
944,638✔
6372
    taosHashClear(pInfo->pHash);
×
6373
  } else {
6374
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
944,638✔
6375
    if (NULL == pInfo->pHash) {
944,638✔
6376
      return terrno;
×
6377
    }
6378
  }
6379
  pInfo->nullTupleSaved = false;
944,638✔
6380
  pInfo->nullTuplePos.pageId = -1;
944,638✔
6381

6382
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
944,254✔
6383
  if (NULL == pInfo->buf) {
944,638✔
6384
    taosHashCleanup(pInfo->pHash);
×
6385
    pInfo->pHash = NULL;
×
6386
    return terrno;
×
6387
  }
6388
  pCtx->needCleanup = true;
944,638✔
6389
  return TSDB_CODE_SUCCESS;
944,254✔
6390
}
6391

6392
static void modeFunctionCleanup(SModeInfo* pInfo) {
1,651,768✔
6393
  taosHashCleanup(pInfo->pHash);
1,651,768✔
6394
  pInfo->pHash = NULL;
1,651,768✔
6395
  taosMemoryFreeClear(pInfo->buf);
1,651,768✔
6396
}
1,651,768✔
6397

6398
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
777,044✔
6399
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
777,044✔
6400
    return;
69,172✔
6401
  }
6402
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
708,402✔
6403
}
6404

6405
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
103,693,887✔
6406
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
103,693,887✔
6407
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
278,004✔
6408
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
268,488✔
6409
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
9,900✔
6410
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
×
6411
    } else {
6412
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
9,900✔
6413
    }
6414
  } else {
6415
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
103,415,923✔
6416
  }
6417

6418
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
103,694,271✔
6419
}
6420

6421
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
232,495,819✔
6422
  int32_t code = TSDB_CODE_SUCCESS;
232,495,819✔
6423
  int32_t hashKeyBytes;
6424
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
232,495,819✔
6425
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
427,152✔
6426
  } else {
6427
    hashKeyBytes = pInfo->colBytes;
232,068,283✔
6428
  }
6429

6430
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
232,495,819✔
6431
  if (pHashItem == NULL) {
232,495,011✔
6432
    int32_t   size = sizeof(SModeItem);
103,693,887✔
6433
    SModeItem item = {0};
103,693,887✔
6434

6435
    item.count += 1;
103,693,887✔
6436
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
103,693,887✔
6437
    if (code != TSDB_CODE_SUCCESS) {
103,694,695✔
6438
      return code;
×
6439
    }
6440

6441
    if (pCtx->subsidiaries.num > 0) {
103,694,695✔
6442
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
262,890✔
6443
      if (code != TSDB_CODE_SUCCESS) {
262,890✔
6444
        return code;
×
6445
      }
6446
    }
6447

6448
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
103,694,695✔
6449
    if (code != TSDB_CODE_SUCCESS) {
103,693,887✔
6450
      return code;
×
6451
    }
6452
  } else {
6453
    pHashItem->count += 1;
128,801,124✔
6454
    if (pCtx->subsidiaries.num > 0) {
128,801,124✔
6455
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,437,650✔
6456
      if (code != TSDB_CODE_SUCCESS) {
3,437,650✔
6457
        return code;
×
6458
      }
6459
    }
6460
  }
6461

6462
  return code;
232,495,011✔
6463
}
6464

6465
int32_t modeFunction(SqlFunctionCtx* pCtx) {
1,547,632✔
6466
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,547,632✔
6467
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,547,254✔
6468

6469
  SInputColumnInfoData* pInput = &pCtx->input;
1,547,632✔
6470

6471
  SColumnInfoData* pInputCol = pInput->pData[0];
1,547,254✔
6472
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,546,870✔
6473

6474
  int32_t numOfElems = 0;
1,547,632✔
6475
  int32_t startOffset = pCtx->offset;
1,547,632✔
6476
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
316,036,951✔
6477
    if (colDataIsNull_s(pInputCol, i)) {
628,990,008✔
6478
      continue;
82,005,526✔
6479
    }
6480
    numOfElems++;
232,494,627✔
6481

6482
    char*   data = colDataGetData(pInputCol, i);
232,494,627✔
6483
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
232,495,819✔
6484
    if (code != TSDB_CODE_SUCCESS) {
232,495,011✔
6485
      modeFunctionCleanup(pInfo);
10,456✔
6486
      return code;
×
6487
    }
6488
  }
6489

6490
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
1,547,632✔
6491
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
4,500✔
6492
    if (code != TSDB_CODE_SUCCESS) {
4,500✔
6493
      modeFunctionCleanup(pInfo);
×
6494
      return code;
×
6495
    }
6496
    pInfo->nullTupleSaved = true;
4,500✔
6497
  }
6498

6499
  SET_VAL(pResInfo, numOfElems, 1);
1,547,632✔
6500

6501
  return TSDB_CODE_SUCCESS;
1,547,632✔
6502
}
6503

6504
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
943,366✔
6505
  int32_t              code = TSDB_CODE_SUCCESS;
943,366✔
6506
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
943,366✔
6507
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
943,366✔
6508
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
943,366✔
6509
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
943,366✔
6510
  int32_t              currentRow = pBlock->info.rows;
943,366✔
6511
  if (NULL == pCol) {
943,366✔
6512
    modeFunctionCleanup(pInfo);
×
6513
    return TSDB_CODE_OUT_OF_RANGE;
×
6514
  }
6515

6516
  STuplePos resDataPos, resTuplePos;
943,366✔
6517
  int32_t   maxCount = 0;
943,366✔
6518

6519
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
943,366✔
6520
  while (pIter != NULL) {
104,636,525✔
6521
    SModeItem* pItem = (SModeItem*)pIter;
103,693,159✔
6522
    if (pItem->count >= maxCount) {
103,693,159✔
6523
      maxCount = pItem->count;
103,551,960✔
6524
      resDataPos = pItem->dataPos;
103,551,960✔
6525
      resTuplePos = pItem->tuplePos;
103,551,576✔
6526
    }
6527

6528
    pIter = taosHashIterate(pInfo->pHash, pIter);
103,693,159✔
6529
  }
6530

6531
  if (maxCount != 0) {
943,366✔
6532
    char* pData = NULL;
488,036✔
6533
    code = loadTupleData(pCtx, &resDataPos, &pData);
488,036✔
6534
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
488,036✔
6535
      code = terrno = TSDB_CODE_NOT_FOUND;
×
6536
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
6537
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
6538
      modeFunctionCleanup(pInfo);
×
6539
      return code;
×
6540
    }
6541

6542
    code = colDataSetVal(pCol, currentRow, pData, false);
488,036✔
6543
    if (TSDB_CODE_SUCCESS != code) {
488,036✔
6544
      modeFunctionCleanup(pInfo);
×
6545
      return code;
×
6546
    }
6547
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
488,036✔
6548
  } else {
6549
    colDataSetNULL(pCol, currentRow);
455,330✔
6550
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
455,330✔
6551
  }
6552

6553
  modeFunctionCleanup(pInfo);
943,366✔
6554

6555
  return code;
943,366✔
6556
}
6557

6558
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
310,963✔
6559
  pEnv->calcMemSize = sizeof(STwaInfo);
310,963✔
6560
  return true;
310,963✔
6561
}
6562

6563
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,999,881✔
6564
  if (pResultInfo->initialized) {
7,999,881✔
6565
    return TSDB_CODE_SUCCESS;
×
6566
  }
6567
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,999,881✔
6568
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6569
  }
6570

6571
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,999,881✔
6572
  pInfo->numOfElems = 0;
7,999,881✔
6573
  pInfo->p.key = INT64_MIN;
7,999,881✔
6574
  pInfo->win = TSWINDOW_INITIALIZER;
7,999,881✔
6575
  return TSDB_CODE_SUCCESS;
7,999,881✔
6576
}
6577

6578
static double twa_get_area(SPoint1 s, SPoint1 e) {
188,178,482✔
6579
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
188,178,482✔
6580
    return 0;
×
6581
  }
6582

6583
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
188,241,365✔
6584
    return (s.val + e.val) * (e.key - s.key) / 2;
169,467,596✔
6585
  }
6586

6587
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
18,773,769✔
6588
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
18,773,769✔
6589
  return val;
18,773,769✔
6590
}
6591

6592
int32_t twaFunction(SqlFunctionCtx* pCtx) {
8,040,895✔
6593
  int32_t               code = TSDB_CODE_SUCCESS;
8,040,895✔
6594
  SInputColumnInfoData* pInput = &pCtx->input;
8,040,895✔
6595
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,040,895✔
6596

6597
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,030,555✔
6598
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,041,380✔
6599
  SPoint1*             last = &pInfo->p;
8,041,380✔
6600

6601
  if (IS_NULL_TYPE(pInputCol->info.type)) {
8,040,895✔
6602
    pInfo->numOfElems = 0;
×
6603
    goto _twa_over;
×
6604
  }
6605

6606
  funcInputUpdate(pCtx);
8,040,895✔
6607
  SFuncInputRow row = {0};
8,041,380✔
6608
  bool          result = false;
8,040,895✔
6609
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
8,040,895✔
6610
    while (1) {
6611
      code = funcInputGetNextRow(pCtx, &row, &result);
5,277,894✔
6612
      if (TSDB_CODE_SUCCESS != code) {
5,277,894✔
6613
        return code;
×
6614
      }
6615
      if (!result) {
5,277,894✔
6616
        break;
768✔
6617
      }
6618
      if (row.isDataNull) {
5,277,126✔
6619
        continue;
768✔
6620
      }
6621

6622
      last->key = row.ts;
5,276,358✔
6623

6624
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
5,276,358✔
6625

6626
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
5,276,358✔
6627
      pInfo->win.skey = pCtx->start.key;
5,276,358✔
6628
      pInfo->numOfElems++;
5,276,358✔
6629
      break;
5,276,358✔
6630
    }
6631
  } else if (pInfo->p.key == INT64_MIN) {
2,763,769✔
6632
    while (1) {
6633
      code = funcInputGetNextRow(pCtx, &row, &result);
8,936,938✔
6634
      if (TSDB_CODE_SUCCESS != code) {
8,937,908✔
6635
        return code;
×
6636
      }
6637
      if (!result) {
8,937,908✔
6638
        break;
787,501✔
6639
      }
6640
      if (row.isDataNull) {
8,150,407✔
6641
        continue;
6,208,320✔
6642
      }
6643

6644
      last->key = row.ts;
1,942,087✔
6645

6646
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
1,941,602✔
6647

6648
      pInfo->win.skey = last->key;
1,941,602✔
6649
      pInfo->numOfElems++;
1,941,602✔
6650
      break;
1,941,602✔
6651
    }
6652
  }
6653

6654
  SPoint1 st = {0};
8,041,380✔
6655

6656
  // calculate the value of
6657
  while (1) {
6658
    code = funcInputGetNextRow(pCtx, &row, &result);
185,779,793✔
6659
    if (TSDB_CODE_SUCCESS != code) {
185,782,824✔
6660
      return code;
×
6661
    }
6662
    if (!result) {
185,782,824✔
6663
      break;
8,040,895✔
6664
    }
6665
    if (row.isDataNull) {
177,741,929✔
6666
      continue;
54,558✔
6667
    }
6668
    pInfo->numOfElems++;
177,687,371✔
6669
    switch (pInputCol->info.type) {
177,686,886✔
6670
      case TSDB_DATA_TYPE_TINYINT: {
13,391,193✔
6671
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
13,391,193✔
6672
        break;
13,391,193✔
6673
      }
6674
      case TSDB_DATA_TYPE_SMALLINT: {
13,652,215✔
6675
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
13,652,215✔
6676
        break;
13,652,215✔
6677
      }
6678
      case TSDB_DATA_TYPE_INT: {
74,958,995✔
6679
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
74,958,995✔
6680
        break;
74,958,995✔
6681
      }
6682
      case TSDB_DATA_TYPE_BIGINT: {
15,878,663✔
6683
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
15,878,663✔
6684
        break;
15,878,230✔
6685
      }
6686
      case TSDB_DATA_TYPE_FLOAT: {
12,516,884✔
6687
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
12,516,884✔
6688
        break;
12,516,884✔
6689
      }
6690
      case TSDB_DATA_TYPE_DOUBLE: {
12,816,961✔
6691
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
12,816,961✔
6692
        break;
12,816,961✔
6693
      }
6694
      case TSDB_DATA_TYPE_UTINYINT: {
8,805,815✔
6695
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
8,805,815✔
6696
        break;
8,805,815✔
6697
      }
6698
      case TSDB_DATA_TYPE_USMALLINT: {
8,806,248✔
6699
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
8,806,248✔
6700
        break;
8,806,248✔
6701
      }
6702
      case TSDB_DATA_TYPE_UINT: {
8,879,843✔
6703
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
8,879,843✔
6704
        break;
8,879,843✔
6705
      }
6706
      case TSDB_DATA_TYPE_UBIGINT: {
7,979,636✔
6707
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
7,979,636✔
6708
        break;
7,979,636✔
6709
      }
6710
      default: {
×
6711
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6712
      }
6713
    }
6714
    if (pInfo->p.key == st.key) {
177,686,020✔
6715
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6716
    }
6717

6718
    pInfo->dOutput += twa_get_area(pInfo->p, st);
177,686,020✔
6719
    pInfo->p = st;
177,683,855✔
6720
  }
6721

6722
  // the last interpolated time window value
6723
  if (pCtx->end.key != INT64_MIN) {
8,040,895✔
6724
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5,279,322✔
6725
    pInfo->p = pCtx->end;
5,279,322✔
6726
    pInfo->numOfElems += 1;
5,279,322✔
6727
  }
6728

6729
  pInfo->win.ekey = pInfo->p.key;
8,040,895✔
6730

6731
_twa_over:
8,041,380✔
6732
  SET_VAL(pResInfo, 1, 1);
8,041,380✔
6733
  return TSDB_CODE_SUCCESS;
8,040,895✔
6734
}
6735

6736
/*
6737
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6738
 * by next input data. The TWA function only applies to each table, so no merge procedure
6739
 * is required, we simply copy to the resut ot interResBuffer.
6740
 */
6741
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6742
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6743
//
6744
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6745
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6746
// }
6747

6748
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,999,881✔
6749
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,999,881✔
6750

6751
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,999,881✔
6752
  if (pInfo->numOfElems == 0) {
7,999,881✔
6753
    pResInfo->numOfRes = 0;
781,153✔
6754
  } else {
6755
    if (pInfo->win.ekey == pInfo->win.skey) {
7,218,728✔
6756
      pInfo->dTwaRes = pInfo->p.val;
1,085,012✔
6757
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
6,133,716✔
6758
      pInfo->dTwaRes = 0;
768✔
6759
    } else {
6760
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
6,132,948✔
6761
    }
6762

6763
    pResInfo->numOfRes = 1;
7,218,728✔
6764
  }
6765

6766
  return functionFinalize(pCtx, pBlock);
7,999,881✔
6767
}
6768

6769
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,868✔
6770
  if (pResultInfo->initialized) {
2,868✔
6771
    return TSDB_CODE_SUCCESS;
×
6772
  }
6773
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,868✔
6774
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6775
  }
6776

6777
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,868✔
6778
  pInfo->minRows = INT32_MAX;
2,868✔
6779
  return TSDB_CODE_SUCCESS;
2,868✔
6780
}
6781

6782
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
5,481✔
6783
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
5,481✔
6784

6785
  SInputColumnInfoData* pInput = &pCtx->input;
5,481✔
6786
  SColumnInfoData*      pInputCol = pInput->pData[0];
5,481✔
6787
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
5,481✔
6788
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,481✔
6789

6790
  STableBlockDistInfo p1 = {0};
5,481✔
6791
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
5,481✔
6792
    qError("failed to deserialize block dist info");
×
6793
    return TSDB_CODE_FAILED;
×
6794
  }
6795

6796
  pDistInfo->numOfBlocks += p1.numOfBlocks;
5,481✔
6797
  pDistInfo->numOfTables += p1.numOfTables;
5,481✔
6798
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
5,481✔
6799
  pDistInfo->numOfSttRows += p1.numOfSttRows;
5,481✔
6800
  pDistInfo->totalSize += p1.totalSize;
5,481✔
6801
  pDistInfo->totalRows += p1.totalRows;
5,481✔
6802
  pDistInfo->numOfFiles += p1.numOfFiles;
5,481✔
6803

6804
  pDistInfo->defMinRows = p1.defMinRows;
5,481✔
6805
  pDistInfo->defMaxRows = p1.defMaxRows;
5,481✔
6806
  pDistInfo->rowSize = p1.rowSize;
5,481✔
6807

6808
  if (pDistInfo->minRows > p1.minRows) {
5,481✔
6809
    pDistInfo->minRows = p1.minRows;
1,285✔
6810
  }
6811
  if (pDistInfo->maxRows < p1.maxRows) {
5,481✔
6812
    pDistInfo->maxRows = p1.maxRows;
1,285✔
6813
  }
6814
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
5,481✔
6815
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
115,101✔
6816
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
109,620✔
6817
  }
6818

6819
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
5,481✔
6820
  return TSDB_CODE_SUCCESS;
5,481✔
6821
}
6822

6823
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
10,962✔
6824
  SEncoder encoder = {0};
10,962✔
6825
  int32_t  code = 0;
10,962✔
6826
  int32_t  lino;
6827
  int32_t  tlen;
6828
  tEncoderInit(&encoder, buf, bufLen);
10,962✔
6829

6830
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
10,962✔
6831
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
21,924✔
6832

6833
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
21,924✔
6834
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
21,924✔
6835
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
21,924✔
6836

6837
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
21,924✔
6838
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
21,924✔
6839
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
21,924✔
6840
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
21,924✔
6841
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
21,924✔
6842
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
21,924✔
6843
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
21,924✔
6844
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
21,924✔
6845
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
21,924✔
6846

6847
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
230,202✔
6848
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
438,480✔
6849
  }
6850

6851
  tEndEncode(&encoder);
10,962✔
6852

6853
_exit:
10,962✔
6854
  if (code) {
10,962✔
6855
    tlen = code;
×
6856
  } else {
6857
    tlen = encoder.pos;
10,962✔
6858
  }
6859
  tEncoderClear(&encoder);
10,962✔
6860
  return tlen;
10,962✔
6861
}
6862

6863
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
5,481✔
6864
  SDecoder decoder = {0};
5,481✔
6865
  int32_t  code = 0;
5,481✔
6866
  int32_t  lino;
6867
  tDecoderInit(&decoder, buf, bufLen);
5,481✔
6868

6869
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
5,481✔
6870
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
10,962✔
6871

6872
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
10,962✔
6873
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
10,962✔
6874
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
10,962✔
6875

6876
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
10,962✔
6877
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
10,962✔
6878
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
10,962✔
6879
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
10,962✔
6880
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
10,962✔
6881
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
10,962✔
6882
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
10,962✔
6883
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
10,962✔
6884
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
10,962✔
6885

6886
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
115,101✔
6887
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
219,240✔
6888
  }
6889

6890
_exit:
5,481✔
6891
  tDecoderClear(&decoder);
5,481✔
6892
  return code;
5,481✔
6893
}
6894

6895
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,868✔
6896
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,868✔
6897
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
2,868✔
6898

6899
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
2,868✔
6900
  if (NULL == pColInfo) {
2,868✔
6901
    return TSDB_CODE_OUT_OF_RANGE;
×
6902
  }
6903

6904
  if (pData->totalRows == 0) {
2,868✔
6905
    pData->minRows = 0;
1,583✔
6906
  }
6907

6908
  int32_t row = 0;
2,868✔
6909
  char    st[256] = {0};
2,868✔
6910
  double  averageSize = 0;
2,868✔
6911
  if (pData->numOfBlocks != 0) {
2,868✔
6912
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1,285✔
6913
  }
6914
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
2,868✔
6915
  double   compRatio = 0;
2,868✔
6916
  if (totalRawSize != 0) {
2,868✔
6917
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1,285✔
6918
  }
6919

6920
  int32_t len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,868✔
6921
                         "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6922
                         pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
2,868✔
6923

6924
  varDataSetLen(st, len);
2,868✔
6925
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
2,868✔
6926
  if (TSDB_CODE_SUCCESS != code) {
2,868✔
6927
    return code;
×
6928
  }
6929

6930
  int64_t avgRows = 0;
2,868✔
6931
  if (pData->numOfBlocks > 0) {
2,868✔
6932
    avgRows = pData->totalRows / pData->numOfBlocks;
1,285✔
6933
  }
6934

6935
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,868✔
6936
                 "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6937
                 pData->minRows, pData->maxRows, avgRows);
6938
  varDataSetLen(st, len);
2,868✔
6939
  code = colDataSetVal(pColInfo, row++, st, false);
2,868✔
6940
  if (TSDB_CODE_SUCCESS != code) {
2,868✔
6941
    return code;
×
6942
  }
6943

6944
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
2,868✔
6945
                 pData->numOfInmemRows, pData->numOfSttRows);
6946
  varDataSetLen(st, len);
2,868✔
6947
  code = colDataSetVal(pColInfo, row++, st, false);
2,868✔
6948
  if (TSDB_CODE_SUCCESS != code) {
2,868✔
6949
    return code;
×
6950
  }
6951

6952
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
5,736✔
6953
                 "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
2,868✔
6954
                 pData->numOfVgroups);
6955

6956
  varDataSetLen(st, len);
2,868✔
6957
  code = colDataSetVal(pColInfo, row++, st, false);
2,868✔
6958
  if (TSDB_CODE_SUCCESS != code) {
2,868✔
6959
    return code;
×
6960
  }
6961

6962
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,868✔
6963
                 "--------------------------------------------------------------------------------");
6964
  varDataSetLen(st, len);
2,868✔
6965
  code = colDataSetVal(pColInfo, row++, st, false);
2,868✔
6966
  if (TSDB_CODE_SUCCESS != code) {
2,868✔
6967
    return code;
×
6968
  }
6969

6970
  int32_t maxVal = 0;
2,868✔
6971
  int32_t minVal = INT32_MAX;
2,868✔
6972
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
60,228✔
6973
    if (maxVal < pData->blockRowsHisto[i]) {
57,360✔
6974
      maxVal = pData->blockRowsHisto[i];
1,843✔
6975
    }
6976

6977
    if (minVal > pData->blockRowsHisto[i]) {
57,360✔
6978
      minVal = pData->blockRowsHisto[i];
3,595✔
6979
    }
6980
  }
6981

6982
  // maximum number of step is 80
6983
  double factor = pData->numOfBlocks / 80.0;
2,868✔
6984

6985
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
2,868✔
6986
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
2,868✔
6987

6988
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
60,228✔
6989
    len =
6990
        snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
57,360✔
6991

6992
    int32_t num = 0;
57,360✔
6993
    if (pData->blockRowsHisto[i] > 0) {
57,360✔
6994
      num = (pData->blockRowsHisto[i]) / factor;
2,959✔
6995
    }
6996

6997
    for (int32_t j = 0; j < num; ++j) {
159,602✔
6998
      int32_t x = snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
102,242✔
6999
      len += x;
102,242✔
7000
    }
7001

7002
    if (pData->blockRowsHisto[i] > 0) {
57,360✔
7003
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
2,959✔
7004
      len += snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
2,959✔
7005
                      pData->blockRowsHisto[i], v, '%');
7006
    }
7007

7008
    varDataSetLen(st, len);
57,360✔
7009
    code = colDataSetVal(pColInfo, row++, st, false);
57,360✔
7010
    if (TSDB_CODE_SUCCESS != code) {
57,360✔
7011
      return code;
×
7012
    }
7013
  }
7014

7015
  return TSDB_CODE_SUCCESS;
2,868✔
7016
}
7017
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
361✔
7018
  if (pResultInfo->initialized) {
361✔
7019
    return TSDB_CODE_SUCCESS;
×
7020
  }
7021
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
361✔
7022
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7023
  }
7024

7025
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
361✔
7026
  return TSDB_CODE_SUCCESS;
361✔
7027
}
7028
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
722✔
7029
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
722✔
7030

7031
  SInputColumnInfoData* pInput = &pCtx->input;
722✔
7032
  SColumnInfoData*      pInputCol = pInput->pData[0];
722✔
7033
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
722✔
7034
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
722✔
7035

7036
  SDBBlockUsageInfo p1 = {0};
722✔
7037
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
722✔
7038
    qError("failed to deserialize block dist info");
×
7039
    return TSDB_CODE_FAILED;
×
7040
  }
7041

7042
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
722✔
7043
  pDistInfo->walInDiskSize += p1.walInDiskSize;
722✔
7044
  pDistInfo->rawDataSize += p1.rawDataSize;
722✔
7045
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
722✔
7046
  return TSDB_CODE_SUCCESS;
722✔
7047
}
7048

7049
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
1,444✔
7050
  SEncoder encoder = {0};
1,444✔
7051
  int32_t  code = 0;
1,444✔
7052
  int32_t  lino;
7053
  int32_t  tlen;
7054
  tEncoderInit(&encoder, buf, bufLen);
1,444✔
7055

7056
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
1,444✔
7057

7058
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
2,888✔
7059
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
2,888✔
7060
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
2,888✔
7061

7062
  tEndEncode(&encoder);
1,444✔
7063

7064
_exit:
1,444✔
7065
  if (code) {
1,444✔
7066
    tlen = code;
×
7067
  } else {
7068
    tlen = encoder.pos;
1,444✔
7069
  }
7070
  tEncoderClear(&encoder);
1,444✔
7071
  return tlen;
1,444✔
7072
}
7073
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
722✔
7074
  SDecoder decoder = {0};
722✔
7075
  int32_t  code = 0;
722✔
7076
  int32_t  lino;
7077
  tDecoderInit(&decoder, buf, bufLen);
722✔
7078

7079
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
722✔
7080
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
1,444✔
7081
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
1,444✔
7082
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
1,444✔
7083

7084
_exit:
722✔
7085
  tDecoderClear(&decoder);
722✔
7086
  return code;
722✔
7087
}
7088
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
361✔
7089
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
361✔
7090
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
361✔
7091

7092
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
361✔
7093
  if (NULL == pColInfo) {
361✔
7094
    return TSDB_CODE_OUT_OF_RANGE;
×
7095
  }
7096
  int32_t len = 0;
361✔
7097
  int32_t row = 0;
361✔
7098
  char    st[256] = {0};
361✔
7099

7100
  uint64_t totalDiskSize = pData->dataInDiskSize;
361✔
7101
  uint64_t rawDataSize = pData->rawDataSize;
361✔
7102
  double   compressRatio = 0;
361✔
7103
  if (rawDataSize != 0) {
361✔
7104
    compressRatio = totalDiskSize * 100 / (double)rawDataSize;
185✔
7105
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[%.2f%]", compressRatio);
185✔
7106
  } else {
7107
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[NULL]");
176✔
7108
  }
7109

7110
  varDataSetLen(st, len);
361✔
7111
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
361✔
7112
  if (TSDB_CODE_SUCCESS != code) {
361✔
7113
    return code;
×
7114
  }
7115

7116
  len =
7117
      snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
361✔
7118
  varDataSetLen(st, len);
361✔
7119
  code = colDataSetVal(pColInfo, row++, st, false);
361✔
7120
  if (TSDB_CODE_SUCCESS != code) {
361✔
7121
    return code;
×
7122
  }
7123
  return code;
361✔
7124
}
7125

7126
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
217,291✔
7127
  pEnv->calcMemSize = sizeof(SDerivInfo);
217,291✔
7128
  return true;
217,291✔
7129
}
7130

7131
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
490,741✔
7132
  if (pResInfo->initialized) {
490,741✔
7133
    return TSDB_CODE_SUCCESS;
240,563✔
7134
  }
7135
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
250,178✔
7136
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7137
  }
7138

7139
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
250,178✔
7140

7141
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
250,178✔
7142
  pDerivInfo->prevTs = -1;
250,178✔
7143
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
250,178✔
7144
  pDerivInfo->valueSet = false;
250,178✔
7145
  return TSDB_CODE_SUCCESS;
250,178✔
7146
}
7147

7148
int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
273,450✔
7149

7150
static int32_t DoDerivativeFunction(SqlFunctionCtx* pCtx) {
273,450✔
7151
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
273,450✔
7152
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
273,450✔
7153

7154
  SInputColumnInfoData* pInput = &pCtx->input;
273,450✔
7155
  SColumnInfoData*      pInputCol = pInput->pData[0];
273,450✔
7156

7157
  int32_t          numOfElems = 0;
273,450✔
7158
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
273,450✔
7159
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
273,450✔
7160
  int32_t          code = TSDB_CODE_SUCCESS;
273,450✔
7161

7162
  funcInputUpdate(pCtx);
273,450✔
7163

7164
  double v = 0;
273,450✔
7165
  if (pCtx->order == TSDB_ORDER_ASC) {
273,450✔
7166
    SFuncInputRow row = {0};
270,868✔
7167
    bool          result = false;
270,868✔
7168
    while (1) {
124,999,401✔
7169
      code = funcInputGetNextRow(pCtx, &row, &result);
125,270,269✔
7170
      if (TSDB_CODE_SUCCESS != code) {
125,270,269✔
7171
        return code;
×
7172
      }
7173
      if (!result) {
125,270,269✔
7174
        break;
270,868✔
7175
      }
7176
      if (row.isDataNull) {
124,999,401✔
7177
        continue;
3,863,862✔
7178
      }
7179

7180
      char* d = row.pData;
121,135,539✔
7181
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
121,135,539✔
7182

7183
      int32_t pos = pCtx->offset + numOfElems;
121,135,539✔
7184
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
121,135,539✔
7185
        pDerivInfo->valueSet = true;
207,220✔
7186
      } else {
7187
        if (row.ts == pDerivInfo->prevTs) {
120,928,319✔
7188
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7189
        }
7190
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
120,928,319✔
7191
        if (pDerivInfo->ignoreNegative && r < 0) {
120,928,319✔
7192
        } else {
7193
          if (isinf(r) || isnan(r)) {
110,322,523✔
7194
            colDataSetNULL(pOutput, pos);
×
7195
          } else {
7196
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
110,322,523✔
7197
            if (code != TSDB_CODE_SUCCESS) {
110,322,523✔
7198
              return code;
×
7199
            }
7200
          }
7201

7202
          if (pTsOutput != NULL) {
110,322,523✔
7203
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
7204
          }
7205

7206
          // handle selectivity
7207
          if (pCtx->subsidiaries.num > 0) {
110,322,523✔
7208
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,967,487✔
7209
            if (code != TSDB_CODE_SUCCESS) {
1,967,487✔
7210
              return code;
×
7211
            }
7212
          }
7213

7214
          numOfElems++;
110,322,523✔
7215
        }
7216
      }
7217

7218
      pDerivInfo->prevValue = v;
121,135,539✔
7219
      pDerivInfo->prevTs = row.ts;
121,135,539✔
7220
    }
7221
  } else {
7222
    SFuncInputRow row = {0};
2,582✔
7223
    bool          result = false;
2,582✔
7224
    while (1) {
24,208✔
7225
      code = funcInputGetNextRow(pCtx, &row, &result);
26,790✔
7226
      if (TSDB_CODE_SUCCESS != code) {
26,790✔
7227
        return code;
×
7228
      }
7229
      if (!result) {
26,790✔
7230
        break;
2,582✔
7231
      }
7232
      if (row.isDataNull) {
24,208✔
7233
        continue;
24,208✔
7234
      }
7235

7236
      char* d = row.pData;
×
7237
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
×
7238

7239
      int32_t pos = pCtx->offset + numOfElems;
×
7240
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
×
7241
        pDerivInfo->valueSet = true;
×
7242
      } else {
7243
        if (row.ts == pDerivInfo->prevTs) {
×
7244
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7245
        }
7246
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
×
7247
        if (pDerivInfo->ignoreNegative && r < 0) {
×
7248
        } else {
7249
          if (isinf(r) || isnan(r)) {
×
7250
            colDataSetNULL(pOutput, pos);
×
7251
          } else {
7252
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
×
7253
            if (code != TSDB_CODE_SUCCESS) {
×
7254
              return code;
×
7255
            }
7256
          }
7257

7258
          if (pTsOutput != NULL) {
×
7259
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
7260
          }
7261

7262
          // handle selectivity
7263
          if (pCtx->subsidiaries.num > 0) {
×
7264
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
×
7265
            if (code != TSDB_CODE_SUCCESS) {
×
7266
              return code;
×
7267
            }
7268
          }
7269
          numOfElems++;
×
7270
        }
7271
      }
7272

7273
      pDerivInfo->prevValue = v;
×
7274
      pDerivInfo->prevTs = row.ts;
×
7275
    }
7276
  }
7277

7278
  pResInfo->numOfRes = numOfElems;
273,450✔
7279

7280
  return TSDB_CODE_SUCCESS;
273,450✔
7281
}
7282

7283
int32_t derivativeFunctionByRow(SArray* pCtxArray) {
273,450✔
7284
  for (int32_t i = 0; i < taosArrayGetSize(pCtxArray); ++i) {
546,900✔
7285
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
273,450✔
7286
    int32_t         code = DoDerivativeFunction(pCtx);
273,450✔
7287
    if (code != TSDB_CODE_SUCCESS) {
273,450✔
7288
      return code;
×
7289
    }
7290
  }
7291
  return TSDB_CODE_SUCCESS;
273,450✔
7292
}
7293

7294
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
244,636✔
7295

7296
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
203,119✔
7297
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
203,119✔
7298
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
203,119✔
7299
  return true;
203,119✔
7300
}
7301

7302
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,946,335✔
7303
  if (pResInfo->initialized) {
1,946,335✔
7304
    return TSDB_CODE_SUCCESS;
×
7305
  }
7306
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
1,946,335✔
7307
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7308
  }
7309

7310
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,946,335✔
7311

7312
  pInfo->firstKey = INT64_MIN;
1,946,335✔
7313
  pInfo->lastKey = INT64_MIN;
1,946,335✔
7314
  pInfo->firstValue = (double)INT64_MIN;
1,946,335✔
7315
  pInfo->lastValue = (double)INT64_MIN;
1,946,335✔
7316

7317
  pInfo->hasResult = 0;
1,946,335✔
7318
  return TSDB_CODE_SUCCESS;
1,946,335✔
7319
}
7320

7321
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
296,270,345✔
7322
  if (isFirst) {
296,270,345✔
7323
    pRateInfo->firstValue = v;
147,673,226✔
7324
    pRateInfo->firstKey = ts;
147,673,226✔
7325
    if (pRateInfo->firstPk) {
147,673,226✔
7326
      int32_t pkBytes;
7327
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
24,185✔
7328
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
5,528✔
7329
      } else {
7330
        pkBytes = pRateInfo->pkBytes;
18,657✔
7331
      }
7332
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
24,185✔
7333
    }
7334
  } else {
7335
    pRateInfo->lastValue = v;
148,597,119✔
7336
    pRateInfo->lastKey = ts;
148,597,119✔
7337
    if (pRateInfo->lastPk) {
148,597,119✔
7338
      int32_t pkBytes;
7339
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
35,932✔
7340
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
8,292✔
7341
      } else {
7342
        pkBytes = pRateInfo->pkBytes;
27,640✔
7343
      }
7344
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
35,932✔
7345
    }
7346
  }
7347
}
296,270,345✔
7348

7349
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,150,470✔
7350
  if (pCtx->hasPrimaryKey) {
2,150,470✔
7351
    if (!isMerge) {
13,129✔
7352
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
11,747✔
7353
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
11,747✔
7354
      pRateInfo->firstPk = pRateInfo->pkData;
11,747✔
7355
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
11,747✔
7356
    } else {
7357
      pRateInfo->firstPk = pRateInfo->pkData;
1,382✔
7358
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,382✔
7359
    }
7360
  } else {
7361
    pRateInfo->firstPk = NULL;
2,137,341✔
7362
    pRateInfo->lastPk = NULL;
2,136,856✔
7363
  }
7364
}
2,150,470✔
7365

7366
int32_t irateFunction(SqlFunctionCtx* pCtx) {
2,088,931✔
7367
  int32_t              code = TSDB_CODE_SUCCESS;
2,088,931✔
7368
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,088,931✔
7369
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,088,931✔
7370

7371
  SInputColumnInfoData* pInput = &pCtx->input;
2,088,931✔
7372
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,088,931✔
7373

7374
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,088,931✔
7375

7376
  funcInputUpdate(pCtx);
2,088,931✔
7377

7378
  initializeRateInfo(pCtx, pRateInfo, false);
2,089,416✔
7379

7380
  int32_t       numOfElems = 0;
2,089,416✔
7381
  int32_t       type = pInputCol->info.type;
2,089,416✔
7382
  SFuncInputRow row = {0};
2,089,416✔
7383
  bool          result = false;
2,089,416✔
7384
  while (1) {
198,378,621✔
7385
    code = funcInputGetNextRow(pCtx, &row, &result);
200,468,037✔
7386
    if (TSDB_CODE_SUCCESS != code) {
200,468,037✔
7387
      return code;
×
7388
    }
7389
    if (!result) {
200,468,037✔
7390
      break;
2,089,416✔
7391
    }
7392
    if (row.isDataNull) {
198,378,621✔
7393
      continue;
8,864,281✔
7394
    }
7395

7396
    char*  data = row.pData;
189,514,340✔
7397
    double v = 0;
189,514,340✔
7398
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
189,514,340✔
7399

7400
    if (INT64_MIN == pRateInfo->lastKey) {
189,514,340✔
7401
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
927,723✔
7402
      pRateInfo->hasResult = 1;
927,723✔
7403
      continue;
927,723✔
7404
    }
7405

7406
    if (row.ts > pRateInfo->lastKey) {
188,586,617✔
7407
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
147,644,664✔
7408
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
147,644,664✔
7409
      }
7410
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
147,644,664✔
7411
      continue;
147,644,664✔
7412
    } else if (row.ts == pRateInfo->lastKey) {
40,941,953✔
7413
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7414
    }
7415

7416
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
40,941,953✔
7417
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
2,074✔
7418
    } else if (row.ts == pRateInfo->firstKey) {
40,939,879✔
7419
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7420
    }
7421
  }
7422

7423
  numOfElems++;
2,089,416✔
7424

7425
  SET_VAL(pResInfo, numOfElems, 1);
2,089,416✔
7426
  return TSDB_CODE_SUCCESS;
2,089,416✔
7427
}
7428

7429
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
1,915,808✔
7430
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
1,915,808✔
7431
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
174,477✔
7432
    return 0.0;
1,741,331✔
7433
  }
7434

7435
  double diff = 0;
174,477✔
7436
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
7437
  // value between two values.
7438
  diff = pRateInfo->lastValue;
174,477✔
7439
  if (diff >= pRateInfo->firstValue) {
174,477✔
7440
    diff -= pRateInfo->firstValue;
105,191✔
7441
  }
7442

7443
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
174,477✔
7444
  if (duration == 0) {
174,477✔
7445
    return 0;
×
7446
  }
7447

7448
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
174,477✔
7449
}
7450

7451
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
25,162✔
7452
  if (inputKey > pOutput->lastKey) {
25,162✔
7453
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
8,780✔
7454
    if (isFirstKey) {
8,780✔
7455
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
3,512✔
7456
    } else {
7457
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
5,268✔
7458
    }
7459
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
16,382✔
7460
    if (isFirstKey) {
1,756✔
7461
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
878✔
7462
    } else {
7463
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
878✔
7464
    }
7465
  } else {
7466
    // inputKey < pOutput->firstKey
7467
  }
7468
}
25,162✔
7469

7470
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
15,952✔
7471
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
15,952✔
7472
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
15,952✔
7473
}
15,952✔
7474

7475
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
28,533✔
7476
  if ((pInput->firstKey != INT64_MIN &&
28,533✔
7477
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
25,853✔
7478
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
28,533✔
7479
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7480
  }
7481

7482
  if (pOutput->hasResult == 0) {
28,533✔
7483
    irateCopyInfo(pInput, pOutput);
15,952✔
7484
    pOutput->hasResult = pInput->hasResult;
15,952✔
7485
    return TSDB_CODE_SUCCESS;
15,952✔
7486
  }
7487

7488
  if (pInput->firstKey != INT64_MIN) {
12,581✔
7489
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
12,581✔
7490
  }
7491

7492
  if (pInput->lastKey != INT64_MIN) {
12,581✔
7493
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
12,581✔
7494
  }
7495

7496
  pOutput->hasResult = pInput->hasResult;
12,581✔
7497
  return TSDB_CODE_SUCCESS;
12,581✔
7498
}
7499

7500
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
30,527✔
7501
  SInputColumnInfoData* pInput = &pCtx->input;
30,527✔
7502
  SColumnInfoData*      pCol = pInput->pData[0];
30,527✔
7503
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
30,527✔
7504
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7505
  }
7506

7507
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
30,527✔
7508
  initializeRateInfo(pCtx, pInfo, true);
30,527✔
7509

7510
  int32_t start = pInput->startRowIndex;
30,527✔
7511
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
61,054✔
7512
    char*      data = colDataGetData(pCol, i);
30,527✔
7513
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
30,527✔
7514
    initializeRateInfo(pCtx, pInfo, true);
30,527✔
7515
    if (pInputInfo->hasResult) {
30,527✔
7516
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
28,533✔
7517
      if (code != TSDB_CODE_SUCCESS) {
28,533✔
7518
        return code;
×
7519
      }
7520
    }
7521
  }
7522

7523
  if (pInfo->hasResult) {
30,527✔
7524
    GET_RES_INFO(pCtx)->numOfRes = 1;
28,533✔
7525
  }
7526

7527
  return TSDB_CODE_SUCCESS;
30,527✔
7528
}
7529

7530
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
30,527✔
7531
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
30,527✔
7532
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
30,527✔
7533
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
30,527✔
7534
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
30,527✔
7535

7536
  if (NULL == res) {
30,527✔
7537
    return terrno;
×
7538
  }
7539
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
30,527✔
7540
  varDataSetLen(res, resultBytes);
30,527✔
7541

7542
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
30,527✔
7543
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
30,527✔
7544
  if (NULL == pCol) {
30,527✔
7545
    taosMemoryFree(res);
×
7546
    return TSDB_CODE_OUT_OF_RANGE;
×
7547
  }
7548

7549
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
30,527✔
7550

7551
  taosMemoryFree(res);
30,527✔
7552
  return code;
30,527✔
7553
}
7554

7555
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,915,808✔
7556
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,915,808✔
7557
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,915,808✔
7558
  if (NULL == pCol) {
1,915,808✔
7559
    return TSDB_CODE_OUT_OF_RANGE;
×
7560
  }
7561

7562
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,915,808✔
7563
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
1,915,808✔
7564

7565
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,915,808✔
7566
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
1,915,808✔
7567
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
1,915,808✔
7568

7569
  return code;
1,915,808✔
7570
}
7571

7572
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
7573
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
7574
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
7575
  bool                 isWindow = pCtx->hasWindowOrGroup && pCtx->hasWindow;
2,147,483,647✔
7576

7577
  if (pInfo->hasResult && (!isWindow || !pInfo->isNull)) {
2,147,483,647✔
7578
    // If already has result for 'group by' or
7579
    // has non-null result for 'window', we can skip left data blocks.
7580
    goto _group_value_over;
2,147,483,647✔
7581
  }
7582

7583
  int32_t               valueRowIndex = -1;
2,147,483,647✔
7584
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
7585
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
7586

7587
  // try to find a non-null value
7588
  if (NULL != pInputCol->pData) {
2,147,483,647✔
7589
    if (isWindow) {
2,147,483,647✔
7590
      // for 'window', non-null value can appear at any row of any data block
7591
      int64_t startIndex = pInput->startRowIndex;
2,147,483,647✔
7592
      int64_t endIndex = pInput->startRowIndex + pInput->numOfRows - 1;
2,147,483,647✔
7593
      for (int64_t i = startIndex; i <= endIndex; ++i) {
2,147,483,647✔
7594
        if (!colDataIsNull_s(pInputCol, i)) {
2,147,483,647✔
7595
          valueRowIndex = i;
2,147,483,647✔
7596
          break;
2,147,483,647✔
7597
        }
7598
      }
7599
    } else {
7600
      // for 'group by', just take the first row
7601
      if (!colDataIsNull_s(pInputCol, pInput->startRowIndex)) {
410,971,744✔
7602
        valueRowIndex = pInput->startRowIndex;
203,300,770✔
7603
      }
7604
    }
7605
  }
7606

7607
  if (valueRowIndex != -1) {
2,147,483,647✔
7608
    // found a non-null value
7609
    char* data = colDataGetData(pInputCol, valueRowIndex);
2,147,483,647✔
7610
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
2,147,483,647✔
7611
      int32_t bytes = calcStrBytesByType(pInputCol->info.type, data);
2,147,483,647✔
7612
      (void)memcpy(pInfo->data, data, bytes);
2,147,483,647✔
7613
    } else {
7614
      (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
2,147,483,647✔
7615
    }
7616
    pInfo->isNull = false;
2,147,483,647✔
7617
  } else {
7618
    // all values are null or first value is null for group by
7619
    pInfo->isNull = true;
570,588,943✔
7620
  }
7621
  pInfo->hasResult = true;
2,147,483,647✔
7622

7623
_group_value_over:
2,147,483,647✔
7624
  SET_VAL(pResInfo, 1, 1);
2,147,483,647✔
7625
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
7626
}
7627

7628
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
2,147,483,647✔
7629

7630
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
7631
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
7632
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
7633
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
7634
  if (NULL == pCol) {
2,147,483,647✔
7635
    return TSDB_CODE_OUT_OF_RANGE;
×
7636
  }
7637

7638
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
7639

7640
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
7641

7642
  if (pInfo->hasResult) {
2,147,483,647✔
7643
    int32_t currentRow = pBlock->info.rows;
2,147,483,647✔
7644
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
2,147,483,647✔
7645
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
2,147,483,647✔
7646
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
7647
        return code;
×
7648
      }
7649
    }
7650
  } else {
7651
    pResInfo->numOfRes = 0;
×
7652
  }
7653

7654
  return code;
2,147,483,647✔
7655
}
7656

7657
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
2,147,483,647✔
7658

7659
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7660
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7661
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7662

7663
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7664
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7665

7666
  // escape rest of data blocks to avoid first entry to be overwritten.
7667
  if (pDBuf->hasResult) {
×
7668
    goto _group_key_over;
×
7669
  }
7670

7671
  if (pSBuf->isNull) {
×
7672
    pDBuf->isNull = true;
×
7673
    pDBuf->hasResult = true;
×
7674
    goto _group_key_over;
×
7675
  }
7676

7677
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7678
    int32_t bytes = calcStrBytesByType(pSourceCtx->resDataInfo.type, pSBuf->data);
×
7679
    (void)memcpy(pDBuf->data, pSBuf->data, bytes);
×
7680
  } else {
7681
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7682
  }
7683

7684
  pDBuf->hasResult = true;
×
7685

7686
_group_key_over:
×
7687

7688
  SET_VAL(pDResInfo, 1, 1);
×
7689
  return TSDB_CODE_SUCCESS;
×
7690
}
7691

7692
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
416,441✔
7693
  int32_t numOfElems = 0;
416,441✔
7694

7695
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
416,441✔
7696
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
416,441✔
7697

7698
  SInputColumnInfoData* pInput = &pCtx->input;
416,441✔
7699
  SColumnInfoData*      pInputCol = pInput->pData[0];
416,441✔
7700

7701
  int32_t bytes = pInputCol->info.bytes;
416,441✔
7702
  pInfo->bytes = bytes;
416,441✔
7703

7704
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
416,441✔
7705
  pInfo->pkType = -1;
416,441✔
7706
  __compar_fn_t pkCompareFn = NULL;
416,441✔
7707
  if (pCtx->hasPrimaryKey) {
416,441✔
7708
    pInfo->pkType = pkCol->info.type;
15,804✔
7709
    pInfo->pkBytes = pkCol->info.bytes;
15,804✔
7710
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
15,804✔
7711
  }
7712

7713
  // data is guaranteed to be in descending order
7714
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
892,151✔
7715
    numOfElems++;
475,710✔
7716

7717
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
475,710✔
7718
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
475,710✔
7719

7720
    TSKEY cts = getRowPTs(pInput->pPTS, i);
475,710✔
7721
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
475,710✔
7722
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
380,883✔
7723
      if (code != TSDB_CODE_SUCCESS) {
380,883✔
7724
        return code;
×
7725
      }
7726
      pResInfo->numOfRes = 1;
380,883✔
7727
    }
7728
  }
7729

7730
  SET_VAL(pResInfo, numOfElems, 1);
416,441✔
7731
  return TSDB_CODE_SUCCESS;
416,441✔
7732
}
7733

7734
bool getCorrFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
7735
  pEnv->calcMemSize = sizeof(SCorrRes);
×
7736
  return true;
×
7737
}
7738

7739
int32_t corrFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
7740
  if (pResultInfo->initialized) {
×
7741
    return TSDB_CODE_SUCCESS;
×
7742
  }
7743
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
×
7744
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7745
  }
7746

7747
  SCorrRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
×
7748
  (void)memset(pRes, 0, sizeof(SCorrRes));
×
7749
  return TSDB_CODE_SUCCESS;
×
7750
}
7751

7752
int32_t corrFunction(SqlFunctionCtx* pCtx) {
×
7753
  int32_t               numOfElem = 0;
×
7754
  SInputColumnInfoData* pInput = &pCtx->input;
×
7755
  int32_t               xType = pInput->pData[0]->info.type;
×
7756
  int32_t               yType = pInput->pData[1]->info.type;
×
7757
  SCorrRes*             pCorrRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7758

7759
  // computing based on the true data block
7760
  SColumnInfoData* pLeft = pInput->pData[0];   // left
×
7761
  SColumnInfoData* pRight = pInput->pData[1];  // right
×
7762

7763
  int32_t leftMod = typeGetTypeModFromColInfo(&pLeft->info);
×
7764
  int32_t rightMod = typeGetTypeModFromColInfo(&pRight->info);
×
7765
  int32_t start = pInput->startRowIndex;
×
7766
  int32_t numOfRows = pInput->numOfRows;
×
7767

7768
  if (IS_NULL_TYPE(xType) || IS_NULL_TYPE(yType)) {
×
7769
    numOfElem = 0;
×
7770
    goto _over;
×
7771
  }
7772

7773
  for (int32_t i = 0; i < numOfRows; ++i) {
×
7774
    double pInputX = 0, pInputY = 0;
×
7775

7776
    if (colDataIsNull_f(pLeft, i) || colDataIsNull_f(pRight, i)) {
×
7777
      continue;
×
7778
    }
7779

7780
    char* pXVal = colDataGetData(pLeft, i);
×
7781
    char* pYVal = colDataGetData(pRight, i);
×
7782

7783
    GET_TYPED_DATA(pInputX, double, xType, pXVal, leftMod);
×
7784
    GET_TYPED_DATA(pInputY, double, yType, pYVal, rightMod);
×
7785

7786
    pCorrRes->sumLeft += pInputX;
×
7787
    pCorrRes->sumRight += pInputY;
×
7788

7789
    pCorrRes->quadLeft += pInputX * pInputX;
×
7790
    pCorrRes->quadRight += pInputY * pInputY;
×
7791

7792
    pCorrRes->productVal += pInputX * pInputY;
×
7793

7794
    pCorrRes->count += 1;
×
7795
    numOfElem += 1;
×
7796
  }
7797

7798
_over:
×
7799
  // data in the check operation are all null, not output
7800
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
×
7801
  return TSDB_CODE_SUCCESS;
×
7802
}
7803

7804
int32_t corrFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
7805
  SInputColumnInfoData* pInput = &pCtx->input;
×
7806
  SCorrRes*             pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7807
  double                avg;
7808

7809
  if (pRes->count == 0) {
×
7810
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
7811
    return functionFinalize(pCtx, pBlock);
×
7812
  }
7813

7814
  /**
7815
    numerator = sum_xy - (sum_x * sum_y) / n
7816
    denominator_x = math.sqrt(sum_x2 - (sum_x**2) / n)
7817
    denominator_y = math.sqrt(sum_y2 - (sum_y**2) / n)
7818

7819
    if denominator_x == 0 or denominator_y == 0:
7820
        return 0.0
7821
    res = numerator / (denominator_x * denominator_y)
7822
  */
7823

7824
  if (pRes->count == 1) {
×
7825
    pRes->result = 0.0;
×
7826
  } else {
7827
    double numerator = pRes->productVal - (pRes->sumLeft * pRes->sumRight) / pRes->count;
×
7828
    double dnmX = sqrt(pRes->quadLeft - pRes->sumLeft * pRes->sumLeft / pRes->count);
×
7829
    double dnmY = sqrt(pRes->quadRight - pRes->sumRight * pRes->sumRight / pRes->count);
×
7830

7831
    if (DBL_EQUAL(dnmX, 0.0) || DBL_EQUAL(dnmY, 0.0)) {
×
7832
      pRes->result = 0.0;
×
7833
    } else {
7834
      pRes->result = numerator / (dnmX * dnmY);
×
7835

7836
      if (pRes->result > 1 || pRes->result < -1) {
×
7837
        qError("invalid corr results, %.4f, numerator:%.4f, dnmX:%.4f, dnmY:%.4f", pRes->result, numerator, dnmX, dnmY);
×
7838
        if (pRes->result > 1) {
×
7839
          pRes->result = 1;
×
7840
        } else if (pRes->result < -1) {
×
7841
          pRes->result = -1;
×
7842
        }
7843
      }
7844
    }
7845
  }
7846

7847
  return functionFinalize(pCtx, pBlock);
×
7848
}
7849

7850
int32_t getCorrInfoSize() { return sizeof(SCorrRes); }
×
7851

7852
int32_t corrPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
7853
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
7854
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7855
  int32_t              resultBytes = getCorrInfoSize();
×
7856
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
7857
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
×
7858
  int32_t              code = 0;
×
7859

7860
  if (NULL == res) {
×
7861
    return terrno;
×
7862
  }
7863

7864
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
7865
  varDataSetLen(res, resultBytes);
×
7866

7867
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
7868
  if (NULL == pCol) {
×
7869
    taosMemoryFree(res);
×
7870
    return TSDB_CODE_OUT_OF_RANGE;
×
7871
  }
7872

7873
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
7874

7875
  taosMemoryFree(res);
×
7876
  return code;
×
7877
}
7878

7879
int32_t corrFuncMerge(SqlFunctionCtx* pCtx) {
×
7880
  SInputColumnInfoData* pInput = &pCtx->input;
×
7881
  SColumnInfoData*      pCol = pInput->pData[0];
×
7882

7883
  if (IS_NULL_TYPE(pCol->info.type)) {
×
7884
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
7885
    return TSDB_CODE_SUCCESS;
×
7886
  }
7887

7888
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
7889
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7890
  }
7891

7892
  SCorrRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7893

7894
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
×
7895
    if (colDataIsNull_s(pCol, i)) {
×
7896
      continue;
×
7897
    }
7898

7899
    char*     data = colDataGetData(pCol, i);
×
7900
    SCorrRes* pInputInfo = (SCorrRes*)varDataVal(data);
×
7901

7902
    if (pInputInfo->count == 0) {
×
7903
      continue;
×
7904
    }
7905

7906
    // pOutput->type = pInput->type;
7907
    if (pInfo->count == 0) {
×
7908
      TAOS_MEMCPY(pInfo, pInputInfo, sizeof(SCorrRes));
×
7909
    } else if (pInfo->count > 0) {
×
7910
      pInfo->productVal += pInputInfo->productVal;
×
7911
      pInfo->quadLeft += pInputInfo->quadLeft;
×
7912
      pInfo->quadRight += pInputInfo->quadRight;
×
7913
      pInfo->sumLeft += pInputInfo->sumLeft;
×
7914
      pInfo->sumRight += pInputInfo->sumRight;
×
7915
      pInfo->count += pInputInfo->count;
×
7916
    }
7917
  }
7918

7919
  SET_VAL(GET_RES_INFO(pCtx), pInfo->count, 1);
×
7920
  return TSDB_CODE_SUCCESS;
×
7921
}
7922

7923
int32_t hasNullFunction(SqlFunctionCtx* pCtx) {
16,059,610✔
7924
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,059,610✔
7925
  bool* pRes = GET_ROWCELL_INTERBUF(pResInfo);
16,059,610✔
7926
  if (*pRes) {
16,059,610✔
7927
    return TSDB_CODE_SUCCESS;
×
7928
  }
7929

7930
  SInputColumnInfoData* pInput = &pCtx->input;
16,059,610✔
7931
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
16,059,610✔
7932
  SColumnInfoData* pCol = pInput->pData[0];
16,059,610✔
7933

7934
  if (pInput->numOfRows > 0) {
16,059,610✔
7935
    pResInfo->numOfRes = 1;
16,059,610✔
7936
  }
7937

7938
  if (IS_NULL_TYPE(pCol->info.type) && pInput->numOfRows > 0) {
16,059,610✔
7939
    *pRes = true;
×
7940
    return TSDB_CODE_SUCCESS;
×
7941
  }
7942

7943
  if (pInput->colDataSMAIsSet) {
16,059,610✔
7944
    if (pAgg->numOfNull > 0) {
×
7945
      *pRes = true;
×
7946
      return TSDB_CODE_SUCCESS;
×
7947
    }
7948

7949
    if (pInput->numOfRows <= INT16_MAX) {
×
7950
      return TSDB_CODE_SUCCESS;
×
7951
    }
7952
  }
7953

7954
  int32_t start = pInput->startRowIndex;
16,059,610✔
7955
  int32_t end = start + pInput->numOfRows;
16,059,610✔
7956

7957
  if (pCol->hasNull) {
16,059,610✔
7958
    for (int32_t i = start; i < end; ++i) {
38,236,615✔
7959
      if (colDataIsNull_s(pCol, i)) {
64,835,202✔
7960
        *pRes = true;
10,150,458✔
7961
        break;
10,150,458✔
7962
      }
7963
    }
7964
  }  
7965

7966
  return TSDB_CODE_SUCCESS;
16,059,610✔
7967
}
7968

7969

7970

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