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

taosdata / TDengine / #5010

29 Mar 2026 04:32AM UTC coverage: 72.292% (+0.03%) from 72.26%
#5010

push

travis-ci

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

253774 of 351039 relevant lines covered (72.29%)

133420324.04 hits per line

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

77.76
/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; }
46,070,590✔
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,137,554✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
56,137,554✔
199

200
  if (!pCtx->bInputFinished) {
56,139,007✔
201
    pIter->pInput = &pCtx->input;
56,139,494✔
202
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
56,139,494✔
203
    pIter->pDataCol = pIter->pInput->pData[0];
56,139,494✔
204
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
56,138,982✔
205
    pIter->rowIndex = pIter->pInput->startRowIndex;
56,138,982✔
206
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
56,138,982✔
207
    pIter->pSrcBlock = pCtx->pSrcBlock;
56,138,982✔
208
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
56,138,495✔
209
      pIter->hasGroupId = true;
6,847,280✔
210
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
6,846,848✔
211
      pIter->hasPrev = false;
6,847,280✔
212
    }
213
  } else {
214
    pIter->finalRow = true;
×
215
  }
216
}
56,137,914✔
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) {
3,441,116✔
333
  int32_t idx = rowIndex + 1;
3,441,116✔
334
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
37,875,410✔
335
    ++idx;
34,434,294✔
336
  }
337
  pIter->rowIndex = idx;
3,441,116✔
338
}
3,441,116✔
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) {
5,272,124✔
351
  if (pIter->hasPrev) {
5,272,124✔
352
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
692,172✔
353
      pIter->hasPrev = true;
×
354
      return false;
×
355
    } else {
356
      int32_t idx = pIter->rowIndex;
692,172✔
357
      while (pIter->tsList[idx] == pIter->prevBlockTsEnd) {
692,172✔
358
        ++idx;
×
359
      }
360

361
      pIter->hasPrev = false;
692,172✔
362
      setInputRowInfo(pRow, pIter, idx, true);
692,172✔
363
      forwardToNextDiffTsRow(pIter, idx);
692,172✔
364
      return true;
692,172✔
365
    }
366
  } else {
367
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,579,952✔
368
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
3,664,884✔
369

370
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,664,884✔
371
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
3,664,884✔
372
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
2,748,944✔
373
      } else {
374
        pIter->rowIndex = pIter->inputEndIndex + 1;
915,940✔
375
      }
376
      return true;
3,664,884✔
377
    } else {
378
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
915,068✔
379
      pIter->hasPrev = true;
915,068✔
380
      pIter->prevBlockTsEnd = tsEnd;
915,068✔
381
      return false;
915,068✔
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,022,328✔
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) {
5,272,124✔
400
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
401
      return TSDB_CODE_SUCCESS;
402
    } else {
403
      *res = funcInputGetNextRowAscPk(pIter, pRow);
5,272,124✔
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;
5,272,124✔
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,178✔
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,963,283✔
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,416✔
502
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
83,416✔
503
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
83,416✔
504
  if (NULL == pCol) {
83,416✔
505
    return TSDB_CODE_OUT_OF_RANGE;
×
506
  }
507
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
83,416✔
508
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
83,416✔
509

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

513
  return code;
83,416✔
514
}
515

516
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
15,742,377✔
517
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
15,742,377✔
518
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
15,744,003✔
519
    return FUNC_DATA_REQUIRED_NOT_LOAD;
11,678,501✔
520
  }
521
  return FUNC_DATA_REQUIRED_SMA_LOAD;
4,065,508✔
522
}
523

524
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
48,960,446✔
525
  pEnv->calcMemSize = sizeof(int64_t);
48,960,446✔
526
  return true;
48,998,777✔
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,610,963✔
541
  }
542
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
2,147,483,647✔
543
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
840,233✔
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,625,929,695✔
578
    val += 0;
1,625,929,695✔
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);
7,406,886✔
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,137,598,389✔
620
    goto _sum_over;
1,137,598,389✔
621
  }
622

623
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
624
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
34,865,539✔
625

626
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
34,865,539✔
627
      SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
17,713,504✔
628
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
17,152,035✔
629
      SUM_RES_INC_USUM(pSumRes, pAgg->sum);
17,154,124✔
630
    } else if (IS_FLOAT_TYPE(type)) {
1,643✔
631
      SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
4✔
632
    } else if (IS_DECIMAL_TYPE(type)) {
8,481✔
633
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
8,481✔
634
      const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
8,481✔
635
      if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
15,420✔
636
                                                       &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
6,939✔
637
        return TSDB_CODE_DECIMAL_OVERFLOW;
1,542✔
638
      }
639
      pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
6,939✔
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);
2,147,483,647✔
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);
2,147,483,647✔
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,242,172,929✔
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);
2,147,483,647✔
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) {
5,519,164✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
2,147,483,647✔
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
3,130,744✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
2,147,483,647✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
222,266,295✔
668
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
516,848,825✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
154,584,058✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
423,977,071✔
671
    } else if (IS_DECIMAL_TYPE(type)) {
21,909✔
672
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
21,909✔
673
      int32_t overflow = false;
23,130✔
674
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
23,130✔
675
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
6,174,168✔
676
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
16,962✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
12,357,588✔
678
      }
679
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
23,130✔
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)) {
70,874,321✔
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) {
25,752,649✔
725
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
25,752,649✔
726
  return true;
25,765,728✔
727
}
728

729
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
24,852,915✔
730
  SNode* pParam;
731
  switch (pFunc->funcType) {
24,852,915✔
732
    case FUNCTION_TYPE_MAX:
24,853,930✔
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);
24,853,930✔
744
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
24,857,810✔
745
        return true;
1,125,456✔
746
      }
747
      break;
23,731,185✔
748
    default:
1✔
749
      break;
1✔
750
  }
751
  return false;
23,730,170✔
752
}
753

754
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
24,850,962✔
755
  if (funcNotSupportStringSma(pFunc)) {
24,850,962✔
756
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,125,456✔
757
  }
758
  return FUNC_DATA_REQUIRED_SMA_LOAD;
23,731,786✔
759
}
760

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

769
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
2,062,515,959✔
770
  buf->assign = false;
2,062,499,721✔
771
  buf->tuplePos.pageId = -1;
2,062,508,378✔
772

773
  buf->nullTupleSaved = false;
2,062,505,424✔
774
  buf->nullTuplePos.pageId = -1;
2,062,521,967✔
775
  buf->str = NULL;
2,062,511,707✔
776
  return TSDB_CODE_SUCCESS;
2,062,528,687✔
777
}
778

779
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
45,872,064✔
780
  COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
781
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
45,872,064✔
782
  return true;
45,876,756✔
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,028,783,050✔
810
  int32_t code = TSDB_CODE_SUCCESS;
2,028,783,050✔
811

812
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2,028,783,050✔
813
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2,028,785,997✔
814

815
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
2,028,786,224✔
816
  int32_t currentRow = pBlock->info.rows;
2,028,782,992✔
817

818
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,028,781,471✔
819
  if (NULL == pCol) {
2,028,782,054✔
820
    return TSDB_CODE_OUT_OF_RANGE;
×
821
  }
822
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
2,028,782,054✔
823

824
  // NOTE: do nothing change it, for performance issue
825
  if (!pEntryInfo->isNullRes) {
2,028,782,908✔
826
    switch (pCol->info.type) {
1,587,338,249✔
827
      case TSDB_DATA_TYPE_UBIGINT:
142,125,064✔
828
      case TSDB_DATA_TYPE_BIGINT:
829
      case TSDB_DATA_TYPE_TIMESTAMP:
830
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
142,125,064✔
831
        break;
142,123,863✔
832
      case TSDB_DATA_TYPE_UINT:
1,333,884,292✔
833
      case TSDB_DATA_TYPE_INT:
834
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
1,333,884,292✔
835
        break;
1,333,884,055✔
836
      case TSDB_DATA_TYPE_USMALLINT:
15,562,172✔
837
      case TSDB_DATA_TYPE_SMALLINT:
838
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
15,562,172✔
839
        break;
15,562,172✔
840
      case TSDB_DATA_TYPE_BOOL:
42,407,382✔
841
      case TSDB_DATA_TYPE_UTINYINT:
842
      case TSDB_DATA_TYPE_TINYINT:
843
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
42,407,382✔
844
        break;
42,407,382✔
845
      case TSDB_DATA_TYPE_DOUBLE:
20,302,856✔
846
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
20,302,856✔
847
        break;
20,302,856✔
848
      case TSDB_DATA_TYPE_FLOAT: {
22,778,330✔
849
        float v = GET_FLOAT_VAL(&pRes->v);
22,778,330✔
850
        colDataSetFloat(pCol, currentRow, &v);
22,778,330✔
851
        break;
22,778,330✔
852
      }
853
      case TSDB_DATA_TYPE_VARBINARY:
9,565,003✔
854
      case TSDB_DATA_TYPE_VARCHAR:
855
      case TSDB_DATA_TYPE_NCHAR: {
856
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
9,565,003✔
857
        if (TSDB_CODE_SUCCESS != code) {
9,565,438✔
858
          return code;
×
859
        }
860
        break;
9,565,438✔
861
      }
862
      case TSDB_DATA_TYPE_DECIMAL64:
679,418✔
863
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
679,418✔
864
        break;
679,418✔
865
      case TSDB_DATA_TYPE_DECIMAL:
31,781✔
866
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
31,781✔
867
        break;
31,781✔
868
    }
869
  } else {
870
    colDataSetNULL(pCol, currentRow);
441,444,411✔
871
  }
872

873
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
2,028,775,359✔
874
  if (pCtx->subsidiaries.num > 0) {
2,028,779,767✔
875
    if (pEntryInfo->numOfRes > 0) {
2,149,230✔
876
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
1,927,878✔
877
    } else {
878
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
221,352✔
879
    }
880
  }
881

882
  return code;
2,028,779,474✔
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) {
831,143✔
891
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
534,949✔
892
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
534,949✔
893

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

901
  return TSDB_CODE_SUCCESS;
296,194✔
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) ||
73,025,333✔
910
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
911
    int32_t numOfCols = pCtx->subsidiaries.num;
73,020,987✔
912
    char*   p = NULL;
73,024,719✔
913
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
73,026,016✔
914
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
73,022,736✔
915
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
916
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
917
      return TSDB_CODE_NOT_FOUND;
×
918
    }
919

920
    bool* nullList = (bool*)p;
73,023,848✔
921
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
73,023,848✔
922

923
    // todo set the offset value to optimize the performance.
924
    for (int32_t j = 0; j < numOfCols; ++j) {
241,387,405✔
925
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
168,363,612✔
926
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
168,359,078✔
927

928
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
168,361,438✔
929
      if (NULL == pDstCol) {
168,353,518✔
930
        return terrno;
×
931
      }
932
      if (nullList[j]) {
168,353,518✔
933
        colDataSetNULL(pDstCol, rowIndex);
54,956,913✔
934
      } else {
935
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
113,398,817✔
936
        if (TSDB_CODE_SUCCESS != code) {
113,406,695✔
937
          return code;
×
938
        }
939
      }
940
      pStart += pDstCol->info.bytes;
168,363,608✔
941
    }
942
  }
943

944
  return TSDB_CODE_SUCCESS;
73,024,036✔
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,010,078✔
950
  if (pCtx->subsidiaries.num <= 0) {
1,010,078✔
951
    return TSDB_CODE_SUCCESS;
×
952
  }
953

954
  int32_t code = TSDB_CODE_SUCCESS;
1,010,078✔
955
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,284,102✔
956
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
1,274,024✔
957

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

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

967
    char* pData = colDataGetData(pSrcCol, rowIndex);
1,274,024✔
968

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

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

977
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,548,048✔
978
      colDataSetNULL(pDstCol, pos);
52,344✔
979
    } else {
980
      code = colDataSetVal(pDstCol, pos, pData, false);
1,221,680✔
981
      if (TSDB_CODE_SUCCESS != code) {
1,221,680✔
982
        return code;
×
983
      }
984
    }
985
  }
986
  return code;
1,010,078✔
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); }
19,096,479✔
1083

1084
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
5,153,331✔
1085
  pEnv->calcMemSize = sizeof(SStdRes);
5,153,331✔
1086
  return true;
5,154,337✔
1087
}
1088

1089
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
579,523,994✔
1090
  if (pResultInfo->initialized) {
579,523,994✔
1091
    return TSDB_CODE_SUCCESS;
×
1092
  }
1093
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
579,526,682✔
1094
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1095
  }
1096

1097
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
579,514,173✔
1098
  (void)memset(pRes, 0, sizeof(SStdRes));
579,517,799✔
1099
  return TSDB_CODE_SUCCESS;
579,517,799✔
1100
}
1101

1102
int32_t stdFunction(SqlFunctionCtx* pCtx) {
1,111,625,668✔
1103
  int32_t numOfElem = 0;
1,111,625,668✔
1104

1105
  // Only the pre-computing information loaded and actual data does not loaded
1106
  SInputColumnInfoData* pInput = &pCtx->input;
1,111,625,668✔
1107
  int32_t               type = pInput->pData[0]->info.type;
1,111,634,854✔
1108

1109
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,111,655,152✔
1110
  pStdRes->type = type;
1,111,660,200✔
1111

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

1115
  int32_t start = pInput->startRowIndex;
1,111,642,373✔
1116
  int32_t numOfRows = pInput->numOfRows;
1,111,664,971✔
1117

1118
  if (IS_NULL_TYPE(type)) {
1,111,681,031✔
1119
    numOfElem = 0;
170,757,964✔
1120
    goto _stddev_over;
170,757,964✔
1121
  }
1122

1123
  switch (type) {
940,923,067✔
1124
    case TSDB_DATA_TYPE_TINYINT: {
46,944,227✔
1125
      int8_t* plist = (int8_t*)pCol->pData;
46,944,227✔
1126
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1127
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1128
          continue;
2,147,483,647✔
1129
        }
1130

1131
        numOfElem += 1;
2,065,169,320✔
1132
        pStdRes->count += 1;
2,065,169,320✔
1133
        double nr = (double)plist[i];
2,089,567,086✔
1134
        if (pStdRes->count == 1) {
2,089,587,798✔
1135
          pStdRes->dsum = nr;
24,473,917✔
1136
        } else {
1137
          double          s_kminusone = pStdRes->dsum;
2,065,217,064✔
1138
          volatile double diff = nr - s_kminusone;
2,064,891,466✔
1139
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,064,891,466✔
1140
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,065,254,906✔
1141
        }
1142
      }
1143

1144
      break;
46,280,603✔
1145
    }
1146

1147
    case TSDB_DATA_TYPE_SMALLINT: {
802,232,343✔
1148
      int16_t* plist = (int16_t*)pCol->pData;
802,232,343✔
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;
2,147,483,647✔
1155
        pStdRes->count += 1;
2,147,483,647✔
1156
        double nr = (double)plist[i];
2,147,483,647✔
1157
        if (pStdRes->count == 1) {
2,147,483,647✔
1158
          pStdRes->dsum = nr;
364,806,499✔
1159
        } else {
1160
          double          s_kminusone = pStdRes->dsum;
2,147,483,647✔
1161
          volatile double diff = nr - s_kminusone;
2,147,483,647✔
1162
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,147,483,647✔
1163
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,147,483,647✔
1164
        }
1165
      }
1166
      break;
802,231,095✔
1167
    }
1168

1169
    case TSDB_DATA_TYPE_INT: {
20,415,424✔
1170
      int32_t* plist = (int32_t*)pCol->pData;
20,415,424✔
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;
2,147,483,647✔
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;
9,697,904✔
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;
20,415,318✔
1190
    }
1191

1192
    case TSDB_DATA_TYPE_BIGINT: {
15,995,743✔
1193
      int64_t* plist = (int64_t*)pCol->pData;
15,995,743✔
1194
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1195
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1196
          continue;
2,147,483,647✔
1197
        }
1198

1199
        numOfElem += 1;
2,147,483,647✔
1200
        pStdRes->count += 1;
2,147,483,647✔
1201
        double nr = (double)plist[i];
2,147,483,647✔
1202
        if (pStdRes->count == 1) {
2,147,483,647✔
1203
          pStdRes->dsum = nr;
3,618,487✔
1204
        } else {
1205
          double          s_kminusone = pStdRes->dsum;
2,147,483,647✔
1206
          volatile double diff = nr - s_kminusone;
2,147,483,647✔
1207
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,147,483,647✔
1208
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,147,483,647✔
1209
        }
1210
      }
1211
      break;
15,999,007✔
1212
    }
1213

1214
    case TSDB_DATA_TYPE_UTINYINT: {
14,679,360✔
1215
      uint8_t* plist = (uint8_t*)pCol->pData;
14,679,360✔
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;
2,147,483,647✔
1219
        }
1220

1221
        numOfElem += 1;
2,147,483,647✔
1222
        pStdRes->count += 1;
2,147,483,647✔
1223
        double nr = (double)plist[i];
2,147,483,647✔
1224
        if (pStdRes->count == 1) {
2,147,483,647✔
1225
          pStdRes->dsum = nr;
275,089✔
1226
        } else {
1227
          double          s_kminusone = pStdRes->dsum;
2,147,483,647✔
1228
          volatile double diff = nr - s_kminusone;
2,147,483,647✔
1229
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,147,483,647✔
1230
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,147,483,647✔
1231
        }
1232
      }
1233

1234
      break;
26,395,349✔
1235
    }
1236

1237
    case TSDB_DATA_TYPE_USMALLINT: {
11,754,989✔
1238
      uint16_t* plist = (uint16_t*)pCol->pData;
11,754,989✔
1239
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1240
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1241
          continue;
2,147,483,647✔
1242
        }
1243

1244
        numOfElem += 1;
1,767,097,115✔
1245
        pStdRes->count += 1;
1,767,097,115✔
1246
        double nr = (double)plist[i];
1,792,246,343✔
1247
        if (pStdRes->count == 1) {
1,792,510,071✔
1248
          pStdRes->dsum = nr;
115,865✔
1249
        } else {
1250
          double          s_kminusone = pStdRes->dsum;
1,792,282,246✔
1251
          volatile double diff = nr - s_kminusone;
1,792,361,240✔
1252
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,792,361,240✔
1253
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,792,350,666✔
1254
        }
1255
      }
1256
      break;
11,754,367✔
1257
    }
1258

1259
    case TSDB_DATA_TYPE_UINT: {
6,410,203✔
1260
      uint32_t* plist = (uint32_t*)pCol->pData;
6,410,203✔
1261
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1262
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1263
          continue;
2,147,483,647✔
1264
        }
1265

1266
        numOfElem += 1;
1,071,825,416✔
1267
        pStdRes->count += 1;
1,071,825,416✔
1268
        double nr = (double)plist[i];
1,086,723,572✔
1269
        if (pStdRes->count == 1) {
1,086,722,328✔
1270
          pStdRes->dsum = nr;
77,835✔
1271
        } else {
1272
          double          s_kminusone = pStdRes->dsum;
1,086,646,359✔
1273
          volatile double diff = nr - s_kminusone;
1,086,573,585✔
1274
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,086,573,585✔
1275
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,086,628,321✔
1276
        }
1277
      }
1278

1279
      break;
6,410,203✔
1280
    }
1281

1282
    case TSDB_DATA_TYPE_UBIGINT: {
6,409,819✔
1283
      uint64_t* plist = (uint64_t*)pCol->pData;
6,409,819✔
1284
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1285
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1286
          continue;
2,147,483,647✔
1287
        }
1288

1289
        numOfElem += 1;
840,180,675✔
1290
        pStdRes->count += 1;
840,180,675✔
1291
        double nr = (double)plist[i];
850,509,146✔
1292
        if (pStdRes->count == 1) {
850,520,756✔
1293
          pStdRes->dsum = nr;
67,377✔
1294
        } else {
1295
          double          s_kminusone = pStdRes->dsum;
850,516,401✔
1296
          volatile double diff = nr - s_kminusone;
850,478,507✔
1297
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
850,478,507✔
1298
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
850,151,947✔
1299
        }
1300
      }
1301
      break;
6,407,953✔
1302
    }
1303

1304
    case TSDB_DATA_TYPE_FLOAT: {
10,506,049✔
1305
      float* plist = (float*)pCol->pData;
10,506,049✔
1306
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,787,599,521✔
1307
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,777,095,962✔
1308
          continue;
2,125,782✔
1309
        }
1310

1311
        numOfElem += 1;
1,774,962,318✔
1312
        pStdRes->count += 1;
1,774,962,318✔
1313
        double nr = (double)plist[i];
1,774,970,514✔
1314
        if (pStdRes->count == 1) {
1,774,969,900✔
1315
          pStdRes->dsum = nr;
9,500,907✔
1316
        } else {
1317
          double          s_kminusone = pStdRes->dsum;
1,765,463,867✔
1318
          volatile double diff = nr - s_kminusone;
1,765,464,861✔
1319
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,765,464,861✔
1320
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,765,468,323✔
1321
        }
1322
      }
1323
      break;
10,506,965✔
1324
    }
1325

1326
    case TSDB_DATA_TYPE_DOUBLE: {
5,574,910✔
1327
      double* plist = (double*)pCol->pData;
5,574,910✔
1328
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
260,392,953✔
1329
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
254,834,907✔
1330
          continue;
75,473,977✔
1331
        }
1332

1333
        numOfElem += 1;
179,326,114✔
1334
        pStdRes->count += 1;
179,326,114✔
1335
        double nr = (double)plist[i];
179,316,866✔
1336
        if (pStdRes->count == 1) {
179,317,410✔
1337
          pStdRes->dsum = nr;
4,722,855✔
1338
        } else {
1339
          double          s_kminusone = pStdRes->dsum;
174,602,715✔
1340
          volatile double diff = nr - s_kminusone;
174,572,795✔
1341
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
174,572,795✔
1342
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
174,593,467✔
1343
        }
1344
      }
1345
      break;
5,584,158✔
1346
    }
1347

1348
    default:
×
1349
      break;
×
1350
  }
1351

1352
_stddev_over:
1,122,742,982✔
1353
  // data in the check operation are all null, not output
1354
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1,122,742,982✔
1355
  return TSDB_CODE_SUCCESS;
1,111,613,802✔
1356
}
1357

1358
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
18,555,254✔
1359
  if (IS_NULL_TYPE(pInput->type)) {
18,555,254✔
1360
    return;
23,510✔
1361
  }
1362
  pOutput->type = pInput->type;
18,531,744✔
1363
  if (pOutput->count == 0) {
18,531,744✔
1364
    pOutput->quadraticDSum += pInput->quadraticDSum;
17,703,609✔
1365
    pOutput->dsum += pInput->dsum;
17,703,609✔
1366
    pOutput->count = pInput->count;
17,703,609✔
1367
  } else if (pInput->count > 0) {
828,135✔
1368
    double totalCount = pOutput->count + pInput->count;
327,267✔
1369
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
327,267✔
1370
    double mean = totalSum / totalCount;
327,267✔
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;
327,267✔
1378
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pOutput->count * (diff * diff) / totalCount;
327,267✔
1379
    pOutput->dsum = mean;
327,267✔
1380
    pOutput->count += pInput->count;
327,267✔
1381
  }
1382
}
1383

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

1388
  if (IS_NULL_TYPE(pCol->info.type)) {
18,543,194✔
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) {
18,543,194✔
1394
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1395
  }
1396

1397
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
18,543,194✔
1398

1399
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
37,098,448✔
1400
    if (colDataIsNull_s(pCol, i)) continue;
37,110,508✔
1401
    char*    data = colDataGetData(pCol, i);
18,555,254✔
1402
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
18,555,254✔
1403
    stdTransferInfo(pInputInfo, pInfo);
18,555,254✔
1404
  }
1405

1406
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
18,543,194✔
1407
  return TSDB_CODE_SUCCESS;
18,543,194✔
1408
}
1409

1410
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
537,555,325✔
1411
  SInputColumnInfoData* pInput = &pCtx->input;
537,555,325✔
1412
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
537,556,349✔
1413
  int32_t               type = pStddevRes->type;
537,557,917✔
1414
  double                avg;
1415

1416
  if (pStddevRes->count == 0) {
537,556,893✔
1417
    GET_RES_INFO(pCtx)->numOfRes = 0;
143,144,569✔
1418

1419
    return functionFinalize(pCtx, pBlock);
143,143,033✔
1420
  }
1421

1422
  if (pStddevRes->count == 1) {
394,411,748✔
1423
    pStddevRes->result = 0.0;
276,725,401✔
1424
  } else {
1425
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
117,686,347✔
1426
  }
1427

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

1433
  return functionFinalize(pCtx, pBlock);
394,411,748✔
1434
}
1435

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

1442
  if (pStdvarRes->count == 0) {
6,796,188✔
1443
    GET_RES_INFO(pCtx)->numOfRes = 0;
31,110✔
1444
    return functionFinalize(pCtx, pBlock);
31,110✔
1445
  }
1446

1447
  if (pStdvarRes->count == 1) {
6,765,078✔
1448
    pStdvarRes->result = 0.0;
924✔
1449
  } else {
1450
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
6,764,154✔
1451
  }
1452

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

1458
  return functionFinalize(pCtx, pBlock);
6,765,078✔
1459
}
1460

1461
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
18,559,274✔
1462
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
18,559,274✔
1463
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
18,559,274✔
1464
  int32_t              resultBytes = getStdInfoSize();
18,558,729✔
1465
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
18,558,107✔
1466

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

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

1480
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
18,558,652✔
1481

1482
  taosMemoryFree(res);
18,559,274✔
1483
  return code;
18,558,652✔
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,922✔
1502
  SInputColumnInfoData* pInput = &pCtx->input;
3,222,922✔
1503
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,222,922✔
1504
  double                avg;
1505

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

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

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

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

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

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

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

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

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

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

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

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

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

1567
  int32_t sepParamIdx = pCtx->numOfParams - 1;
1,428✔
1568
  pRes->separator = pCtx->param[sepParamIdx].param.pz;
1,428✔
1569
  pRes->type = pCtx->param[sepParamIdx].param.nType;
1,428✔
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,428✔
1579
}
1580

1581
static int32_t gconcatHelper(const char* input, char* output, bool hasNchar, int32_t type, VarDataLenT* dataLen,
18,050✔
1582
                             void* charsetCxt) {
1583
  if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) {
18,050✔
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,050✔
1600
    *dataLen += varDataLen(input);
18,050✔
1601
  }
1602

1603
  return TSDB_CODE_SUCCESS;
18,050✔
1604
}
1605

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

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

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

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

1630
      if (TSDB_DATA_TYPE_NCHAR == type) {
950✔
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;
950✔
1648
  SColumnInfoData* pCol = pInput->pData[numOfCols - 1];
950✔
1649

1650
  sep = colDataGetData(pCol, 0);
950✔
1651
  pRes->type = pCol->info.type;
950✔
1652
  for (int r = rowStart; r < rowStart + numOfRows; ++r) {
10,450✔
1653
    if (prefixSep) {
9,500✔
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,550✔
1658
      if (code) {
8,550✔
1659
        goto _over;
×
1660
      }
1661
    }
1662

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

1667
      if (IS_NULL_TYPE(type) || (pCol->hasNull && colDataIsNull_f(pCol, r))) {
9,500✔
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,500✔
1673
      if (code) {
9,500✔
1674
        goto _over;
×
1675
      }
1676
    }
1677

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

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

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

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

1697
  if (NULL == pCol) {
950✔
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);
950✔
1703

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

1706
  return code;
950✔
1707
}
1708

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

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

1722
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,513,747✔
1723

1724
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
4,512,115✔
1725
                 typeGetTypeModFromCol(pCtx->param[1].pCol));
1726
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
4,511,657✔
1727
                 typeGetTypeModFromCol(pCtx->param[2].pCol));
1728
  return TSDB_CODE_SUCCESS;
4,512,172✔
1729
}
1730

1731
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
5,377,536✔
1732
  int32_t numOfElem = 0;
5,377,536✔
1733

1734
  SInputColumnInfoData* pInput = &pCtx->input;
5,377,536✔
1735
  int32_t               type = pInput->pData[0]->info.type;
5,379,111✔
1736

1737
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,379,111✔
1738

1739
  SColumnInfoData* pCol = pInput->pData[0];
5,377,021✔
1740

1741
  double(*param)[3] = pInfo->matrix;
5,378,567✔
1742
  double x = pInfo->startVal;
5,379,111✔
1743

1744
  int32_t start = pInput->startRowIndex;
5,378,023✔
1745
  int32_t numOfRows = pInput->numOfRows;
5,378,023✔
1746

1747
  switch (type) {
5,374,301✔
1748
    case TSDB_DATA_TYPE_TINYINT: {
229,520✔
1749
      int8_t* plist = (int8_t*)pCol->pData;
229,520✔
1750
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,697,888✔
1751
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,468,368✔
1752
          continue;
111,344✔
1753
        }
1754
        numOfElem++;
18,357,024✔
1755
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,357,024✔
1756
      }
1757
      break;
229,520✔
1758
    }
1759
    case TSDB_DATA_TYPE_SMALLINT: {
230,630✔
1760
      int16_t* plist = (int16_t*)pCol->pData;
230,630✔
1761
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,798,038✔
1762
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,567,408✔
1763
          continue;
321,244✔
1764
        }
1765

1766
        numOfElem++;
18,246,164✔
1767
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,246,164✔
1768
      }
1769
      break;
230,630✔
1770
    }
1771

1772
    case TSDB_DATA_TYPE_INT: {
1,025,034✔
1773
      int32_t* plist = (int32_t*)pCol->pData;
1,025,034✔
1774
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
165,825,818✔
1775
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
164,799,839✔
1776
          continue;
74,514,938✔
1777
        }
1778

1779
        numOfElem++;
90,272,389✔
1780
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
90,272,389✔
1781
      }
1782
      break;
1,026,580✔
1783
    }
1784

1785
    case TSDB_DATA_TYPE_BIGINT: {
2,690,028✔
1786
      int64_t* plist = (int64_t*)pCol->pData;
2,690,028✔
1787
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
101,422,328✔
1788
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
98,730,668✔
1789
          continue;
58,444✔
1790
        }
1791

1792
        numOfElem++;
98,668,416✔
1793
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
98,668,416✔
1794
      }
1795
      break;
2,694,380✔
1796
    }
1797

1798
    case TSDB_DATA_TYPE_UTINYINT: {
17,460✔
1799
      uint8_t* plist = (uint8_t*)pCol->pData;
17,460✔
1800
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,216,268✔
1801
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,198,808✔
1802
          continue;
10,164✔
1803
        }
1804
        numOfElem++;
18,188,644✔
1805
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,188,644✔
1806
      }
1807
      break;
17,460✔
1808
    }
1809
    case TSDB_DATA_TYPE_USMALLINT: {
17,460✔
1810
      uint16_t* plist = (uint16_t*)pCol->pData;
17,460✔
1811
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,216,268✔
1812
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,198,808✔
1813
          continue;
9,240✔
1814
        }
1815

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

1822
    case TSDB_DATA_TYPE_UINT: {
17,460✔
1823
      uint32_t* plist = (uint32_t*)pCol->pData;
17,460✔
1824
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,216,268✔
1825
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,198,808✔
1826
          continue;
9,240✔
1827
        }
1828

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

1835
    case TSDB_DATA_TYPE_UBIGINT: {
17,460✔
1836
      uint64_t* plist = (uint64_t*)pCol->pData;
17,460✔
1837
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,216,268✔
1838
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,198,808✔
1839
          continue;
9,240✔
1840
        }
1841

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

1848
    case TSDB_DATA_TYPE_FLOAT: {
749,972✔
1849
      float* plist = (float*)pCol->pData;
749,972✔
1850
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,731,980✔
1851
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,982,008✔
1852
          continue;
160,844✔
1853
        }
1854

1855
        numOfElem++;
18,821,164✔
1856
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,821,164✔
1857
      }
1858
      break;
749,972✔
1859
    }
1860

1861
    case TSDB_DATA_TYPE_DOUBLE: {
379,277✔
1862
      double* plist = (double*)pCol->pData;
379,277✔
1863
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,391,441✔
1864
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,012,164✔
1865
          continue;
164,244✔
1866
        }
1867

1868
        numOfElem++;
18,847,920✔
1869
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,847,920✔
1870
      }
1871
      break;
379,277✔
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;
5,380,199✔
1884
  pInfo->num += numOfElem;
5,379,111✔
1885

1886
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
5,378,710✔
1887

1888
  return TSDB_CODE_SUCCESS;
5,379,798✔
1889
}
1890

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

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

1902
  if (0 == pInfo->num) {
4,513,371✔
1903
    colDataSetNULL(pCol, currentRow);
1,382,900✔
1904
    return TSDB_CODE_SUCCESS;
1,382,900✔
1905
  }
1906

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

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

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

1915
  if (0 == param00) {
3,131,015✔
1916
    colDataSetNULL(pCol, currentRow);
2,472,114✔
1917
    return TSDB_CODE_SUCCESS;
2,471,570✔
1918
  }
1919

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

1925
  param12 /= param[1][1];
658,901✔
1926

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

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

1944
  return code;
658,901✔
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) {
90,145✔
1970
  pEnv->calcMemSize = sizeof(SPercentileInfo);
90,145✔
1971
  return true;
90,145✔
1972
}
1973

1974
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
462,121✔
1975
  if (pResultInfo->initialized) {
462,121✔
1976
    return TSDB_CODE_SUCCESS;
×
1977
  }
1978
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
462,121✔
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);
462,121✔
1984
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
462,121✔
1985
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
462,121✔
1986
  pInfo->numOfElems = 0;
462,121✔
1987

1988
  return TSDB_CODE_SUCCESS;
462,121✔
1989
}
1990

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

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

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

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

2013
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,965,642✔
2014
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
1,965,642✔
2015
    pInfo->stage += 1;
462,121✔
2016

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

2030
  // the first stage, only acquire the min/max value
2031
  if (pInfo->stage == 0) {
1,705,713✔
2032
    if (pCtx->input.colDataSMAIsSet) {
982,821✔
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;
982,821✔
2057
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,938,732✔
2058
        if (colDataIsNull_f(pCol, i)) {
17,955,911✔
2059
          continue;
342,660✔
2060
        }
2061

2062
        char* data = colDataGetData(pCol, i);
17,613,251✔
2063

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

2070
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
17,613,251✔
2071
          SET_DOUBLE_VAL(&pInfo->maxval, v);
14,060,708✔
2072
        }
2073

2074
        pInfo->numOfElems += 1;
17,613,251✔
2075
      }
2076
    }
2077
  } else {
2078
    // the second stage, calculate the true percentile value
2079
    int32_t start = pInput->startRowIndex;
722,892✔
2080
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,308,543✔
2081
      if (colDataIsNull_f(pCol, i)) {
17,586,111✔
2082
        continue;
×
2083
      }
2084

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

2094
    SET_VAL(pResInfo, numOfElems, 1);
722,432✔
2095
  }
2096

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

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

2105
  int32_t code = 0;
461,201✔
2106
  double  v = 0;
461,201✔
2107

2108
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
461,201✔
2109
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
461,201✔
2110
    if (pCtx->numOfParams > 2) {
201,272✔
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;
198,512✔
2151

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

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

2159
      tMemBucketDestroy(pMemBucket);
198,512✔
2160
      return functionFinalize(pCtx, pBlock);
198,512✔
2161
    }
2162
  } else {
2163
    return functionFinalize(pCtx, pBlock);
259,929✔
2164
  }
2165

2166
_fin_error:
×
2167

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

2172
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
3,505,099✔
2173
  int32_t bytesHist =
3,505,099✔
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,505,099✔
2176
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
3,505,099✔
2177
  return true;
3,508,438✔
2178
}
2179

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

2187
static int8_t getApercentileAlgo(char* algoStr) {
3,054,176✔
2188
  int8_t algoType;
2189
  if (strcasecmp(algoStr, "default") == 0) {
3,054,176✔
2190
    algoType = APERCT_ALGO_DEFAULT;
1,526,244✔
2191
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,527,932✔
2192
    algoType = APERCT_ALGO_TDIGEST;
1,529,020✔
2193
  } else {
2194
    algoType = APERCT_ALGO_UNKNOWN;
×
2195
  }
2196

2197
  return algoType;
3,054,176✔
2198
}
2199

2200
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
91,352,110✔
2201
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
91,352,110✔
2202
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
91,355,268✔
2203
}
91,355,816✔
2204

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

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

2217
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
28,673,418✔
2218

2219
  SVariant* pVal = &pCtx->param[1].param;
28,673,962✔
2220
  pInfo->percent = 0;
28,674,506✔
2221
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
28,674,964✔
2222

2223
  if (pCtx->numOfParams == 2) {
28,673,962✔
2224
    pInfo->algo = APERCT_ALGO_DEFAULT;
25,618,612✔
2225
  } else if (pCtx->numOfParams == 3) {
3,055,808✔
2226
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
3,055,264✔
2227
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
3,055,264✔
2228
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2229
    }
2230
  }
2231

2232
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
28,672,330✔
2233
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
28,672,874✔
2234
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,529,564✔
2235
  } else {
2236
    buildHistogramInfo(pInfo);
27,142,766✔
2237
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
27,144,398✔
2238
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
27,144,774✔
2239
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2240
  }
2241

2242
  return TSDB_CODE_SUCCESS;
28,674,338✔
2243
}
2244

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

2250
  SColumnInfoData* pCol = pInput->pData[0];
39,345,801✔
2251
  int32_t          type = pCol->info.type;
39,346,803✔
2252

2253
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
39,345,801✔
2254

2255
  int32_t start = pInput->startRowIndex;
39,346,803✔
2256
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
39,344,553✔
2257
    buildTDigestInfo(pInfo);
1,528,550✔
2258
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,528,006✔
2259
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
79,610,828✔
2260
      if (colDataIsNull_f(pCol, i)) {
78,084,998✔
2261
        continue;
37,211,222✔
2262
      }
2263
      numOfElems += 1;
40,871,600✔
2264
      char* data = colDataGetData(pCol, i);
40,871,600✔
2265

2266
      double  v = 0;  // value
40,873,776✔
2267
      int64_t w = 1;  // weigth
40,873,776✔
2268
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
40,873,776✔
2269
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
40,874,320✔
2270
      if (code != TSDB_CODE_SUCCESS) {
40,871,600✔
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);
37,815,471✔
2278
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
37,814,059✔
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;
2,147,483,647✔
2284
      }
2285
      numOfElems += 1;
2,147,483,647✔
2286
      char* data = colDataGetData(pCol, i);
2,147,483,647✔
2287

2288
      double v = 0;
2,147,483,647✔
2289
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
2,147,483,647✔
2290
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
2,147,483,647✔
2291
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2292
        return code;
×
2293
      }
2294
    }
2295

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

2301
  SET_VAL(pResInfo, numOfElems, 1);
39,346,017✔
2302
  return TSDB_CODE_SUCCESS;
39,346,017✔
2303
}
2304

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

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

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

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

2324
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
14,100✔
2325
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
14,100✔
2326
      tdigestAutoFill(pTDigest, COMPRESSION);
14,100✔
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);
624,678✔
2335
    if (pInput->pHisto->numOfElems <= 0) {
624,678✔
2336
      return TSDB_CODE_SUCCESS;
356,229✔
2337
    }
2338

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

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

2346
    if (pHisto->numOfElems <= 0) {
268,449✔
2347
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
253,082✔
2348
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
253,082✔
2349

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

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

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

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

2377
  SInputColumnInfoData* pInput = &pCtx->input;
637,136✔
2378

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

2384
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
637,136✔
2385

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

2388
  bool    hasRes = false;
637,136✔
2389
  int32_t start = pInput->startRowIndex;
637,136✔
2390
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,276,384✔
2391
    char* data = colDataGetData(pCol, i);
639,248✔
2392

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

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

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

2410
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
26,395,132✔
2411
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
26,395,132✔
2412
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
26,395,132✔
2413

2414
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
26,395,132✔
2415
    buildTDigestInfo(pInfo);
1,514,534✔
2416
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,514,534✔
2417
    if (pInfo->pTDigest->size > 0) {
1,514,534✔
2418
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,514,534✔
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);
24,880,054✔
2425
    if (pInfo->pHisto->numOfElems > 0) {
24,880,054✔
2426
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
11,882,982✔
2427
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2428

2429
      double  ratio[] = {pInfo->percent};
11,882,982✔
2430
      double* res = NULL;
11,883,526✔
2431
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
11,883,526✔
2432
      if (TSDB_CODE_SUCCESS != code) {
11,883,526✔
2433
        taosMemoryFree(res);
×
2434
        return code;
×
2435
      }
2436
      pInfo->result = *res;
11,883,526✔
2437
      // memcpy(pCtx->pOutput, res, sizeof(double));
2438
      taosMemoryFree(res);
11,883,526✔
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__,
12,997,072✔
2443
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2444
    }
2445
  }
2446

2447
  return functionFinalize(pCtx, pBlock);
26,395,132✔
2448
}
2449

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

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

2460
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
639,248✔
2461
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
14,570✔
2462
    varDataSetLen(res, resultBytes);
14,570✔
2463
  } else {
2464
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
624,678✔
2465
    varDataSetLen(res, resultBytes);
624,678✔
2466
  }
2467

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

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

2477
  taosMemoryFree(res);
639,248✔
2478
  return code;
639,248✔
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) {
914,605✔
2501
  char numVal[8] = {0};
914,605✔
2502
  switch (pkType) {
915,283✔
2503
    case TSDB_DATA_TYPE_INT:
178,301✔
2504
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
178,301✔
2505
      break;
178,979✔
2506
    case TSDB_DATA_TYPE_UINT:
168,794✔
2507
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
168,794✔
2508
      break;
169,472✔
2509
    case TSDB_DATA_TYPE_BIGINT:
169,472✔
2510
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
169,472✔
2511
      break;
169,472✔
2512
    case TSDB_DATA_TYPE_UBIGINT:
170,828✔
2513
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
170,828✔
2514
      break;
169,472✔
2515
    default:
227,888✔
2516
      break;
227,888✔
2517
  }
2518
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
915,283✔
2519
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
915,283✔
2520
  return fn(pkData, blockData);
917,317✔
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;
495,282✔
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;
11,909,881✔
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) {
397,980✔
2545
        return FUNC_DATA_REQUIRED_NOT_LOAD;
85,464✔
2546
      }
2547
    }
2548
    return FUNC_DATA_REQUIRED_DATA_LOAD;
724,253✔
2549
  } else {
2550
    return FUNC_DATA_REQUIRED_DATA_LOAD;
10,395,776✔
2551
  }
2552
}
2553

2554
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
63,557,266✔
2555
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
63,557,266✔
2556

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

2562
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
63,557,266✔
2563
  if (pResult->hasResult) {
63,630,401✔
2564
    if (pResult->pkBytes > 0) {
53,516,836✔
2565
      pResult->pkData = pResult->buf + pResult->bytes;
760,219✔
2566
    } else {
2567
      pResult->pkData = NULL;
52,753,333✔
2568
    }
2569
    if (pResult->ts > pBlockInfo->window.ekey) {
53,513,798✔
2570
      return FUNC_DATA_REQUIRED_NOT_LOAD;
33,333,420✔
2571
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
20,178,699✔
2572
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
519,337✔
2573
        return FUNC_DATA_REQUIRED_NOT_LOAD;
117,823✔
2574
      }
2575
    }
2576
    return FUNC_DATA_REQUIRED_DATA_LOAD;
20,060,750✔
2577
  } else {
2578
    return FUNC_DATA_REQUIRED_DATA_LOAD;
10,132,251✔
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,865,041,599✔
2584

2585
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
70,769,154✔
2586
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
70,769,154✔
2587
  // TODO: change SFunctionNode to add pk info
2588
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
70,764,652✔
2589
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
70,750,548✔
2590
  return true;
70,745,582✔
2591
}
2592

2593
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
14,567,138✔
2594
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
14,567,138✔
2595
  pEnv->calcMemSize = pNode->node.resType.bytes;
14,571,615✔
2596
  return true;
14,564,181✔
2597
}
2598

2599

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

2605
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
37,063,646✔
2606
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
37,063,646✔
2607
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
37,082,808✔
2608
  return true;
37,067,000✔
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) {
113,017,714✔
2634
  if (pCtx->subsidiaries.rowLen == 0) {
113,017,714✔
2635
    int32_t rowLen = 0;
4,660,276✔
2636
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
10,917,386✔
2637
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
6,249,282✔
2638
      rowLen += pc->pExpr->base.resSchema.bytes;
6,240,487✔
2639
    }
2640

2641
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
4,655,295✔
2642
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
4,660,852✔
2643
    if (NULL == pCtx->subsidiaries.buf) {
4,658,999✔
2644
      return terrno;
×
2645
    }
2646
  }
2647
  return TSDB_CODE_SUCCESS;
113,042,715✔
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) {
71,545,977✔
2659
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
58,341,287✔
2660
  } else if (!noElements) {
13,215,593✔
2661
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
13,205,246✔
2662
  } else {
2663
  }  // dothing
2664

2665
  return code;
71,557,702✔
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)) {
186,110,227✔
2685
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
61,999,010✔
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);
186,106,180✔
2693
    pInfo->pkData = pInfo->buf + pInfo->bytes;
186,108,871✔
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;
171,449,654✔
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;
50,751,265✔
2728
    pInfo->pkBytes = pkCol->info.bytes;
50,755,990✔
2729
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
50,754,655✔
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);
192,046,321✔
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;
171,433,162✔
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;
50,810,412✔
2863
    pInfo->pkBytes = pkCol->info.bytes;
50,813,103✔
2864
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
50,809,077✔
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];
2,147,483,647✔
2947
      int32_t chosen = i;
2,147,483,647✔
2948

2949
      if (cts < pts[i + 1]) {
2,147,483,647✔
2950
        cts = pts[i + 1];
137,812,853✔
2951
        chosen = i + 1;
137,812,853✔
2952
      }
2953

2954
      if (cts < pts[i + 2]) {
2,147,483,647✔
2955
        cts = pts[i + 2];
137,813,137✔
2956
        chosen = i + 2;
137,813,137✔
2957
      }
2958

2959
      if (cts < pts[i + 3]) {
2,147,483,647✔
2960
        cts = pts[i + 3];
137,811,523✔
2961
        chosen = i + 3;
137,811,523✔
2962
      }
2963

2964
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2,147,483,647✔
2965
        char*   data = colDataGetData(pInputCol, chosen);
170,222,542✔
2966
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
170,171,485✔
2967
        if (code != TSDB_CODE_SUCCESS) {
170,179,624✔
2968
          return code;
×
2969
        }
2970
        pResInfo->numOfRes = 1;
170,179,624✔
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);
916,048,668✔
2977
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
915,347,158✔
2978
        if (code != TSDB_CODE_SUCCESS) {
915,805,037✔
2979
          return code;
×
2980
        }
2981
        pResInfo->numOfRes = 1;
915,805,037✔
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);
184,156,007✔
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,428,352,287✔
3028
  if (!pInput->hasResult) {
1,428,352,287✔
3029
    return false;
×
3030
  }
3031
  __compar_fn_t pkCompareFn = NULL;
1,428,352,253✔
3032
  if (pInput->pkData) {
1,428,352,253✔
3033
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
2,143,650✔
3034
  }
3035
  if (pOutput->hasResult) {
1,428,352,727✔
3036
    if (isFirst) {
780,951,306✔
3037
      if (pInput->ts > pOutput->ts ||
672,701,841✔
3038
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
669,586,684✔
3039
        return false;
3,115,157✔
3040
      }
3041
    } else {
3042
      if (pInput->ts < pOutput->ts ||
108,249,465✔
3043
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
102,329,024✔
3044
        return false;
5,920,441✔
3045
      }
3046
    }
3047
  }
3048

3049
  pOutput->isNull = pInput->isNull;
1,419,317,400✔
3050
  pOutput->ts = pInput->ts;
1,419,317,163✔
3051
  pOutput->bytes = pInput->bytes;
1,419,317,840✔
3052
  pOutput->pkType = pInput->pkType;
1,419,317,603✔
3053

3054
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,419,317,061✔
3055
  if (pInput->pkData) {
1,419,317,298✔
3056
    pOutput->pkBytes = pInput->pkBytes;
2,028,238✔
3057
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
2,028,238✔
3058
    pOutput->pkData = pOutput->buf + pOutput->bytes;
2,028,238✔
3059
  }
3060
  return true;
1,419,318,314✔
3061
}
3062

3063
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,428,350,357✔
3064
                                     int32_t rowIndex) {
3065
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,428,350,357✔
3066
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,419,317,535✔
3067
    if (TSDB_CODE_SUCCESS != code) {
1,419,318,551✔
3068
      return code;
×
3069
    }
3070
    pOutput->hasResult = true;
1,419,318,551✔
3071
  }
3072
  return TSDB_CODE_SUCCESS;
1,428,354,183✔
3073
}
3074

3075
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
686,569,758✔
3076
  SInputColumnInfoData* pInput = &pCtx->input;
686,569,758✔
3077
  SColumnInfoData*      pCol = pInput->pData[0];
686,569,758✔
3078

3079
  if (IS_NULL_TYPE(pCol->info.type)) {
686,569,995✔
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) {
686,569,995✔
3085
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3086
  }
3087

3088
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
686,570,469✔
3089

3090
  int32_t start = pInput->startRowIndex;
686,570,469✔
3091
  int32_t numOfElems = 0;
686,570,435✔
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;
250,671,694✔
3096
    }
3097
    char*          data = colDataGetData(pCol, i);
1,428,351,542✔
3098
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,428,352,253✔
3099
    if (pCtx->hasPrimaryKey) {
1,428,352,253✔
3100
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
2,143,650✔
3101
    } else {
3102
      pInputInfo->pkData = NULL;
1,426,208,840✔
3103
    }
3104

3105
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,428,350,391✔
3106
    if (code != TSDB_CODE_SUCCESS) {
1,428,353,709✔
3107
      return code;
×
3108
    }
3109
    if (!numOfElems) {
1,428,353,709✔
3110
      numOfElems = pInputInfo->hasResult ? 1 : 0;
671,966,328✔
3111
    }
3112
  }
3113

3114
  if (numOfElems == 0) {
686,566,237✔
3115
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
14,602,279✔
3116
    if (code != TSDB_CODE_SUCCESS) {
14,602,279✔
3117
      return code;
×
3118
    }
3119
    pInfo->nullTupleSaved = true;
14,602,279✔
3120
  }
3121

3122
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
686,566,948✔
3123
  return TSDB_CODE_SUCCESS;
686,567,185✔
3124
}
3125

3126
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
390,579,288✔
3127

3128
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
295,990,944✔
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,020,378,695✔
3145
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,020,377,545✔
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,780,998,357✔
3162
  int32_t code = TSDB_CODE_SUCCESS;
1,780,998,357✔
3163

3164
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,780,998,357✔
3165
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,781,097,008✔
3166

3167
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,781,098,289✔
3168

3169
  // todo check for failure
3170
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,780,405,249✔
3171
  if (NULL == res) {
1,776,914,522✔
3172
    return terrno;
×
3173
  }
3174
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,776,914,522✔
3175

3176
  varDataSetLen(res, resultBytes);
1,776,978,659✔
3177

3178
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,780,892,571✔
3179
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,781,400,223✔
3180
  if (NULL == pCol) {
1,781,263,171✔
3181
    taosMemoryFree(res);
×
3182
    return TSDB_CODE_OUT_OF_RANGE;
×
3183
  }
3184

3185
  if (pEntryInfo->numOfRes == 0) {
1,781,263,171✔
3186
    colDataSetNULL(pCol, pBlock->info.rows);
260,755,746✔
3187
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
260,700,693✔
3188
  } else {
3189
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,520,716,639✔
3190
    if (TSDB_CODE_SUCCESS != code) {
1,520,481,393✔
3191
      taosMemoryFree(res);
×
3192
      return code;
×
3193
    }
3194
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,520,481,393✔
3195
  }
3196
  taosMemoryFree(res);
1,780,403,937✔
3197
  return code;
1,779,905,493✔
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) {
38,933,228✔
3215
  SInputColumnInfoData* pInput = &pCtx->input;
38,933,228✔
3216
  SColumnInfoData*      pInputCol = pInput->pData[0];
38,953,646✔
3217
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
38,950,991✔
3218

3219
  if (colDataIsNull_s(pInputCol, rowIndex)) {
77,910,764✔
3220
    pInfo->isNull = true;
11,214,032✔
3221
  } else {
3222
    pInfo->isNull = false;
27,737,371✔
3223

3224
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
27,731,443✔
3225
      pInfo->bytes = calcStrBytesByType(pInputCol->info.type, pData);
5,930,163✔
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);
27,724,685✔
3234
  }
3235

3236
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
48,096,354✔
3237
    char* pkData = colDataGetData(pkCol, rowIndex);
9,165,654✔
3238
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
9,163,620✔
3239
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
3,028,603✔
3240
    }
3241
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
9,163,613✔
3242
    pInfo->pkData = pInfo->buf + pInfo->bytes;
9,165,619✔
3243
  }
3244
  pInfo->ts = cts;
38,921,155✔
3245
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
38,921,062✔
3246
  if (code != TSDB_CODE_SUCCESS) {
38,918,027✔
3247
    return code;
×
3248
  }
3249

3250
  pInfo->hasResult = true;
38,918,027✔
3251

3252
  return TSDB_CODE_SUCCESS;
38,928,520✔
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,654✔
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;
50,690,828✔
3276
    pInfo->pkBytes = pkCol->info.bytes;
50,690,821✔
3277
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
50,690,814✔
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) {
23,824,359✔
3284
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
11,915,721✔
3285
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
11,912,564✔
3286
      TSKEY cts = getRowPTs(pInput->pPTS, i);
11,926,469✔
3287
      numOfElems++;
11,926,450✔
3288

3289
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
11,926,450✔
3290
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
4,022,279✔
3291
        if (code != TSDB_CODE_SUCCESS) return code;
4,008,227✔
3292
      }
3293

3294
      break;
11,907,418✔
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);
17,957,954✔
3307
        if (code != TSDB_CODE_SUCCESS) return code;
23,740,418✔
3308
      }
3309
      break;
2,147,483,647✔
3310
    }
3311
  } else {
3312
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
50,057,515✔
3313
    int      from = -1;
51,237,669✔
3314
    int32_t  i = -1;
51,238,136✔
3315
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
246,544,780✔
3316
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
195,289,858✔
3317
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
195,309,181✔
3318
      TSKEY cts = pts[i];
195,314,960✔
3319

3320
      numOfElems++;
195,314,999✔
3321
      char* pkData = NULL;
195,314,999✔
3322
      if (pCtx->hasPrimaryKey) {
195,314,999✔
3323
        pkData = colDataGetData(pkCol, i);
191,573,467✔
3324
      }
3325
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
195,319,246✔
3326
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
184,503,769✔
3327
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
10,824,102✔
3328
        if (code != TSDB_CODE_SUCCESS) {
10,818,951✔
3329
          return code;
×
3330
        }
3331
        pResInfo->numOfRes = 1;
10,818,951✔
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) {
542,399✔
3341
  pEnv->calcMemSize = sizeof(SDiffInfo);
542,399✔
3342
  return true;
542,399✔
3343
}
3344

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

3365
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
5,664,641✔
3366
  switch (type) {
5,664,641✔
3367
    case TSDB_DATA_TYPE_BOOL:
3,923✔
3368
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
3,923✔
3369
      break;
3,923✔
3370
    case TSDB_DATA_TYPE_UTINYINT:
27,033✔
3371
    case TSDB_DATA_TYPE_TINYINT:
3372
      pDiffInfo->prev.i64 = *(int8_t*)pv;
27,033✔
3373
      break;
27,033✔
3374
    case TSDB_DATA_TYPE_UINT:
5,396,403✔
3375
    case TSDB_DATA_TYPE_INT:
3376
      pDiffInfo->prev.i64 = *(int32_t*)pv;
5,396,403✔
3377
      break;
5,396,403✔
3378
    case TSDB_DATA_TYPE_USMALLINT:
33,381✔
3379
    case TSDB_DATA_TYPE_SMALLINT:
3380
      pDiffInfo->prev.i64 = *(int16_t*)pv;
33,381✔
3381
      break;
33,381✔
3382
    case TSDB_DATA_TYPE_TIMESTAMP:
113,307✔
3383
    case TSDB_DATA_TYPE_UBIGINT:
3384
    case TSDB_DATA_TYPE_BIGINT:
3385
      pDiffInfo->prev.i64 = *(int64_t*)pv;
113,307✔
3386
      break;
113,307✔
3387
    case TSDB_DATA_TYPE_FLOAT:
23,607✔
3388
      pDiffInfo->prev.d64 = *(float*)pv;
23,607✔
3389
      break;
23,607✔
3390
    case TSDB_DATA_TYPE_DOUBLE:
66,987✔
3391
      pDiffInfo->prev.d64 = *(double*)pv;
66,987✔
3392
      break;
66,987✔
3393
    default:
×
3394
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3395
  }
3396
  pDiffInfo->prevTs = ts;
5,664,641✔
3397
  pDiffInfo->hasPrev = true;
5,664,641✔
3398
  return TSDB_CODE_SUCCESS;
5,664,641✔
3399
}
3400

3401
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
1,486,216✔
3402
  switch (type) {
1,486,216✔
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: {
163,836✔
3408
      int64_t v = *(int32_t*)pv;
163,836✔
3409
      return v < pDiffInfo->prev.i64;
163,836✔
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: {
37,496✔
3420
      int64_t v = *(int8_t*)pv;
37,496✔
3421
      return v < pDiffInfo->prev.i64;
37,496✔
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: {
277,386✔
3428
      int64_t v = *(int16_t*)pv;
277,386✔
3429
      return v < pDiffInfo->prev.i64;
277,386✔
3430
    }
3431
    case TSDB_DATA_TYPE_UBIGINT: {
3,488✔
3432
      uint64_t v = *(uint64_t*)pv;
3,488✔
3433
      return v < (uint64_t)pDiffInfo->prev.i64;
3,488✔
3434
    }
3435
    case TSDB_DATA_TYPE_TIMESTAMP:
263,660✔
3436
    case TSDB_DATA_TYPE_BIGINT: {
3437
      int64_t v = *(int64_t*)pv;
263,660✔
3438
      return v < pDiffInfo->prev.i64;
263,660✔
3439
    }
3440
    case TSDB_DATA_TYPE_FLOAT: {
110,532✔
3441
      float v = *(float*)pv;
110,532✔
3442
      return v < pDiffInfo->prev.d64;
110,532✔
3443
    }
3444
    case TSDB_DATA_TYPE_DOUBLE: {
629,818✔
3445
      double v = *(double*)pv;
629,818✔
3446
      return v < pDiffInfo->prev.d64;
629,818✔
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;
464,380✔
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);
350,552✔
3463
    pOutput->hasNull = true;
350,552✔
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) {
29,676,524✔
3471
  double delta = v - pDiffInfo->prev.d64;
29,676,524✔
3472
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
29,676,524✔
3473
    colDataSetNull_f_s(pOutput, pos);
373,988✔
3474
  } else {
3475
    colDataSetDouble(pOutput, pos, &delta);
29,302,536✔
3476
  }
3477
  pDiffInfo->prev.d64 = v;
29,676,524✔
3478
}
29,676,524✔
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);
64,938✔
3484
    return doSetPrevVal(pDiffInfo, type, pv, ts);
64,938✔
3485
  }
3486
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3487
  switch (type) {
2,147,483,647✔
3488
    case TSDB_DATA_TYPE_UINT: {
458,276✔
3489
      int64_t v = *(uint32_t*)pv;
458,276✔
3490
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
458,276✔
3491
      break;
458,276✔
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,441,077✔
3499
      int64_t v = *(bool*)pv;
4,441,077✔
3500
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,441,077✔
3501
      break;
4,441,077✔
3502
    }
3503
    case TSDB_DATA_TYPE_UTINYINT: {
58,860✔
3504
      int64_t v = *(uint8_t*)pv;
58,860✔
3505
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
58,860✔
3506
      break;
58,860✔
3507
    }
3508
    case TSDB_DATA_TYPE_TINYINT: {
8,971,403✔
3509
      int64_t v = *(int8_t*)pv;
8,971,403✔
3510
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
8,971,403✔
3511
      break;
8,971,403✔
3512
    }
3513
    case TSDB_DATA_TYPE_USMALLINT: {
58,860✔
3514
      int64_t v = *(uint16_t*)pv;
58,860✔
3515
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
58,860✔
3516
      break;
58,860✔
3517
    }
3518
    case TSDB_DATA_TYPE_SMALLINT: {
9,904,759✔
3519
      int64_t v = *(int16_t*)pv;
9,904,759✔
3520
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
9,904,759✔
3521
      break;
9,904,759✔
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: {
14,129,509✔
3531
      double v = *(float*)pv;
14,129,509✔
3532
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
14,129,509✔
3533
      break;
14,129,509✔
3534
    }
3535
    case TSDB_DATA_TYPE_DOUBLE: {
15,547,015✔
3536
      double v = *(double*)pv;
15,547,015✔
3537
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
15,547,015✔
3538
      break;
15,547,015✔
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,424,768✔
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) {
720,725,624✔
3565
      from = pInput->startRowIndex;
152,265,974✔
3566
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
568,459,650✔
3567
      return false;
152,278,379✔
3568
    }
3569
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
568,440,465✔
3570
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
568,462,369✔
3571
    int8_t           pkType = pkCol->info.type;
568,466,374✔
3572
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
568,458,350✔
3573
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
568,458,350✔
3574
    int32_t          select = from;
568,411,673✔
3575
    char*            val = colDataGetData(pkCol, select);
568,411,673✔
3576
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,415,075,097✔
3577
      char* val1 = colDataGetData(pkCol, from + 1);
846,600,664✔
3578
      if (compareFunc(val1, val) < 0) {
846,676,586✔
3579
        select = from + 1;
262,358,598✔
3580
        val = val1;
262,358,598✔
3581
      }
3582
      from = from + 1;
846,599,930✔
3583
    }
3584
    *pRowIndex = select;
568,258,564✔
3585
    *nextFrom = from + 1;
568,463,592✔
3586
    return true;
568,476,411✔
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;
14,706,563✔
3601
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3602
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
1,486,216✔
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,791,850✔
3614
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,791,850✔
3615
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,791,850✔
3616
  pDiffInfo->isFirstRow = false;
5,791,850✔
3617
  if (pRow->isDataNull) {
5,791,850✔
3618
    return TSDB_CODE_SUCCESS;
192,147✔
3619
  }
3620

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

3625
  char* pv = pRow->pData;
5,599,703✔
3626
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
5,599,703✔
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);
8,857,187✔
3640
    pOutput->hasNull = true;
8,857,187✔
3641

3642
    // handle selectivity
3643
    if (pCtx->subsidiaries.num > 0) {
8,857,187✔
3644
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
20,926✔
3645
      if (code != TSDB_CODE_SUCCESS) {
20,926✔
3646
        return code;
×
3647
      }
3648
    }
3649
    return TSDB_CODE_SUCCESS;
8,857,187✔
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,990✔
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; }
46,070,590✔
3673

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

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

3687
  bool keepNull = false;
46,047,046✔
3688
  for (int i = 0; i < diffColNum; ++i) {
92,117,636✔
3689
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
46,070,590✔
3690
    if (NULL == pCtx) {
46,070,590✔
3691
      code = terrno;
×
3692
      goto _exit;
×
3693
    }
3694
    funcInputUpdate(pCtx);
46,070,590✔
3695
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
46,070,590✔
3696
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
46,070,590✔
3697
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
46,070,590✔
3698
      keepNull = true;
46,052,714✔
3699
    }
3700
  }
3701

3702
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
46,047,046✔
3703
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
46,047,046✔
3704
  if (NULL == pCtx0 || NULL == pRow0) {
46,047,046✔
3705
    code = terrno;
×
3706
    goto _exit;
×
3707
  }
3708
  int32_t startOffset = pCtx0->offset;
46,047,046✔
3709
  bool    result = false;
46,047,046✔
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;
46,039,056✔
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,013,128✔
3721
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
5,013,128✔
3722
      if (NULL == pCtx || NULL == pRow) {
5,013,128✔
3723
        code = terrno;
×
3724
        goto _exit;
×
3725
      }
3726
      code = funcInputGetNextRow(pCtx, pRow, &result);
5,013,128✔
3727
      if (TSDB_CODE_SUCCESS != code) {
5,013,128✔
3728
        goto _exit;
×
3729
      }
3730
      if (!result) {
5,013,128✔
3731
        // rows are not equal
3732
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3733
        goto _exit;
×
3734
      }
3735
      if (!diffResultIsNull(pCtx, pRow)) {
5,013,128✔
3736
        hasNotNullValue = true;
4,948,600✔
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,990✔
3753
        }
3754
        newRow = true;
2,147,483,647✔
3755
      } else {
3756
        code = trySetPreVal(pCtx, pRow);
5,791,850✔
3757
        if (code != TSDB_CODE_SUCCESS) {
5,791,850✔
3758
          goto _exit;
×
3759
        }
3760
      }
3761
    }
3762
    if (newRow) ++numOfElems;
2,147,483,647✔
3763
  }
3764

3765
  for (int i = 0; i < diffColNum; ++i) {
92,101,220✔
3766
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
46,062,164✔
3767
    if (NULL == pCtx) {
46,062,164✔
3768
      code = terrno;
×
3769
      goto _exit;
×
3770
    }
3771
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
46,062,164✔
3772
    pResInfo->numOfRes = numOfElems;
46,062,164✔
3773
  }
3774

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

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

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

3798
  return TSDB_CODE_SUCCESS;
38,849✔
3799
}
3800

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

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

3807
    return TSDB_CODE_SUCCESS;
14,256✔
3808
  }
3809

3810
  switch (type) {
111,764✔
3811
    case TSDB_DATA_TYPE_BOOL:
53,876✔
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,876✔
3822
      break;
53,876✔
3823
    case TSDB_DATA_TYPE_FLOAT:
20,736✔
3824
      colDataSetFloat(pOutput, pos, &pFillforwardInfo->fv);
20,736✔
3825
      break;
20,736✔
3826
    case TSDB_DATA_TYPE_DOUBLE:
23,328✔
3827
      colDataSetDouble(pOutput, pos, &pFillforwardInfo->dv);
23,328✔
3828
      break;
23,328✔
3829
    case TSDB_DATA_TYPE_DECIMAL64:
4,752✔
3830
      return colDataSetVal(pOutput, pos, (const char*)&pFillforwardInfo->v, false);
4,752✔
3831
    case TSDB_DATA_TYPE_DECIMAL:
×
3832
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->dec, false);
×
3833
    case TSDB_DATA_TYPE_VARCHAR:
9,072✔
3834
    case TSDB_DATA_TYPE_VARBINARY:
3835
    case TSDB_DATA_TYPE_NCHAR:
3836
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->str, false);
9,072✔
3837
    default:
×
3838
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3839
  }
3840

3841
  return TSDB_CODE_SUCCESS;
97,940✔
3842
}
3843

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

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

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

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

3867
  return TSDB_CODE_SUCCESS;
126,020✔
3868
}
3869

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

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

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

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

3909
    for (int i = 1; i < fillforwardColNum; ++i) {
126,452✔
3910
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
91,584✔
3911
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
91,584✔
3912
      if (NULL == pCtx || NULL == pRow) {
91,584✔
3913
        code = terrno;
×
3914
        goto _exit;
×
3915
      }
3916
      code = funcInputGetNextRow(pCtx, pRow, &result);
91,584✔
3917
      if (TSDB_CODE_SUCCESS != code) {
91,584✔
3918
        goto _exit;
×
3919
      }
3920
      if (!result) {
91,584✔
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,868✔
3928

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

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

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

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

3997
        if (!pFillforwardInfo->nonnull) {
77,204✔
3998
          pFillforwardInfo->nonnull = true;
37,985✔
3999
        }
4000
      }
4001

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

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

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

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

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

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

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

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

4041
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,351,536✔
4042
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2,351,536✔
4043
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2,353,981✔
4044
  return true;
2,349,514✔
4045
}
4046

4047
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
8,336,776✔
4048
  if (pResInfo->initialized) {
8,336,776✔
4049
    return TSDB_CODE_SUCCESS;
×
4050
  }
4051
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
8,335,911✔
4052
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4053
  }
4054

4055
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
8,338,052✔
4056
  SInputColumnInfoData* pInput = &pCtx->input;
8,338,931✔
4057

4058
  pRes->maxSize = pCtx->param[1].param.i;
8,338,681✔
4059

4060
  pRes->nullTupleSaved = false;
8,336,877✔
4061
  pRes->nullTuplePos.pageId = -1;
8,333,856✔
4062
  return TSDB_CODE_SUCCESS;
8,331,631✔
4063
}
4064

4065
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
2,147,483,647✔
4066
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
4067
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
4068
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
2,147,483,647✔
4069

4070
  return pRes;
2,147,483,647✔
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) {
9,329,163✔
4079
  int32_t              numOfElems = 0;
9,329,163✔
4080
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
9,329,163✔
4081

4082
  SInputColumnInfoData* pInput = &pCtx->input;
9,343,687✔
4083
  SColumnInfoData*      pCol = pInput->pData[0];
9,341,963✔
4084

4085
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
9,343,467✔
4086
  pRes->type = pInput->pData[0]->info.type;
9,333,909✔
4087

4088
  int32_t start = pInput->startRowIndex;
9,332,969✔
4089
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
4090
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
4091
      continue;
1,608,302✔
4092
    }
4093

4094
    numOfElems++;
2,147,483,647✔
4095
    char*   data = colDataGetData(pCol, i);
2,147,483,647✔
4096
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
2,147,483,647✔
4097
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
4098
      return code;
×
4099
    }
4100
  }
4101

4102
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
9,348,315✔
4103
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
6,280✔
4104
    if (code != TSDB_CODE_SUCCESS) {
6,280✔
4105
      return code;
×
4106
    }
4107
    pRes->nullTupleSaved = true;
6,280✔
4108
  }
4109
  return TSDB_CODE_SUCCESS;
9,340,560✔
4110
}
4111

4112
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
3,524,432✔
4113
  int32_t              numOfElems = 0;
3,524,432✔
4114
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,524,432✔
4115

4116
  SInputColumnInfoData* pInput = &pCtx->input;
3,529,128✔
4117
  SColumnInfoData*      pCol = pInput->pData[0];
3,528,683✔
4118

4119
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
3,527,793✔
4120
  pRes->type = pInput->pData[0]->info.type;
3,520,493✔
4121

4122
  int32_t start = pInput->startRowIndex;
3,528,966✔
4123
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
4124
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
4125
      continue;
3,172,692✔
4126
    }
4127

4128
    numOfElems++;
2,147,483,647✔
4129
    char*   data = colDataGetData(pCol, i);
2,147,483,647✔
4130
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
2,147,483,647✔
4131
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
4132
      return code;
×
4133
    }
4134
  }
4135

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

4144
  return TSDB_CODE_SUCCESS;
3,531,277✔
4145
}
4146

4147
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
509,957,847✔
4148
  uint16_t type = *(uint16_t*)param;
509,957,847✔
4149

4150
  STopBotResItem* val1 = (STopBotResItem*)p1;
510,003,831✔
4151
  STopBotResItem* val2 = (STopBotResItem*)p2;
510,003,831✔
4152

4153
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
510,003,831✔
4154
    if (val1->v.i == val2->v.i) {
321,503,304✔
4155
      return 0;
63,117,246✔
4156
    }
4157

4158
    return (val1->v.i > val2->v.i) ? 1 : -1;
259,028,922✔
4159
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
188,500,527✔
4160
    if (val1->v.u == val2->v.u) {
98,019,989✔
4161
      return 0;
21,177,618✔
4162
    }
4163

4164
    return (val1->v.u > val2->v.u) ? 1 : -1;
77,076,739✔
4165
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
90,480,849✔
4166
    if (val1->v.f == val2->v.f) {
3,960,544✔
4167
      return 0;
27,720✔
4168
    }
4169

4170
    return (val1->v.f > val2->v.f) ? 1 : -1;
3,932,824✔
4171
  }
4172

4173
  if (val1->v.d == val2->v.d) {
86,520,305✔
4174
    return 0;
4,840✔
4175
  }
4176

4177
  return (val1->v.d > val2->v.d) ? 1 : -1;
86,697,905✔
4178
}
4179

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

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

4188
  STopBotResItem* pItems = pRes->pItems;
2,147,483,647✔
4189

4190
  // not full yet
4191
  if (pEntryInfo->numOfRes < pRes->maxSize) {
2,147,483,647✔
4192
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
47,760,207✔
4193
    pItem->v = val;
47,755,991✔
4194
    pItem->uid = uid;
47,755,195✔
4195

4196
    // save the data of this tuple
4197
    if (pCtx->subsidiaries.num > 0) {
47,773,022✔
4198
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
11,757,678✔
4199
      if (code != TSDB_CODE_SUCCESS) {
11,755,141✔
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++;
47,764,532✔
4209
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
47,770,267✔
4210
                        topBotResComparFn, !isTopQuery);
47,776,619✔
4211
    if (code != TSDB_CODE_SUCCESS) {
47,816,508✔
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) ||
2,147,483,647✔
4216
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
2,147,483,647✔
4217
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
2,147,483,647✔
4218
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
2,147,483,647✔
4219
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
2,147,483,647✔
4220
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
2,147,483,647✔
4221
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
2,147,483,647✔
4222
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
2,147,483,647✔
4223
      // replace the old data and the coresponding tuple data
4224
      STopBotResItem* pItem = &pItems[0];
39,576,321✔
4225
      pItem->v = val;
39,576,321✔
4226
      pItem->uid = uid;
39,477,836✔
4227

4228
      // save the data of this tuple by over writing the old data
4229
      if (pCtx->subsidiaries.num > 0) {
39,486,060✔
4230
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
19,312,468✔
4231
        if (code != TSDB_CODE_SUCCESS) {
19,311,685✔
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,
39,480,712✔
4239
                            topBotResComparFn, NULL, !isTopQuery);
39,488,099✔
4240
      if (code != TSDB_CODE_SUCCESS) {
39,483,281✔
4241
        return code;
×
4242
      }
4243
    }
4244
  }
4245

4246
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
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,
113,040,700✔
4277
                           char* buf, char** res) {
4278
  char* nullList = buf;
113,040,700✔
4279
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
113,040,700✔
4280

4281
  int32_t offset = 0;
113,054,541✔
4282
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
360,204,471✔
4283
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
247,121,831✔
4284

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

4291
    if (fmIsSelectValueFunc(pc->functionId)) {
247,086,222✔
4292
      SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
247,097,964✔
4293
      int32_t      srcSlotId = pFuncParam->pCol->slotId;
247,090,781✔
4294

4295
      SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
247,115,233✔
4296
      if (NULL == pCol) {
247,103,591✔
4297
        return TSDB_CODE_OUT_OF_RANGE;
×
4298
      }
4299
      if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
494,191,179✔
4300
        offset += pCol->info.bytes;
66,951,953✔
4301
        continue;
66,951,953✔
4302
      }
4303

4304
      char* p = colDataGetData(pCol, rowIndex);
180,126,608✔
4305
      if (IS_VAR_DATA_TYPE(pCol->info.type)) {
180,165,730✔
4306
        int32_t bytes = calcStrBytesByType(pCol->info.type, p);
8,472,199✔
4307
        (void)memcpy(pStart + offset, p, bytes);
8,469,129✔
4308
      } else {
4309
        (void)memcpy(pStart + offset, p, pCol->info.bytes);
171,685,186✔
4310
      }
4311

4312
      offset += pCol->info.bytes;
180,187,150✔
4313
      continue;
180,212,224✔
4314
    }
4315
  }
4316

4317
  *res = buf;
113,037,095✔
4318
  return TSDB_CODE_SUCCESS;
113,101,459✔
4319
}
4320

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

4327
    if (pHandle->currentPage == -1) {
2,147,483,647✔
4328
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
5,660,539✔
4329
      if (pPage == NULL) {
5,692,849✔
4330
        return terrno;
×
4331
      }
4332
      pPage->num = sizeof(SFilePage);
5,692,849✔
4333
    } else {
4334
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
2,147,483,647✔
4335
      if (pPage == NULL) {
2,147,483,647✔
4336
        return terrno;
×
4337
      }
4338
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
2,147,483,647✔
4339
        // current page is all used, let's prepare a new buffer page
4340
        releaseBufPage(pHandle->pBuf, pPage);
8,274,949✔
4341
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
8,274,949✔
4342
        if (pPage == NULL) {
8,274,949✔
4343
          return terrno;
×
4344
        }
4345
        pPage->num = sizeof(SFilePage);
8,274,949✔
4346
      }
4347
    }
4348

4349
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
2,147,483,647✔
4350
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
2,147,483,647✔
4351

4352
    pPage->num += length;
2,147,483,647✔
4353
    setBufPageDirty(pPage, true);
2,147,483,647✔
4354
    releaseBufPage(pHandle->pBuf, pPage);
2,147,483,647✔
4355
  } else {  // other tuple save policy
4356
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
457✔
4357
      p.streamTupleKey = *key;
×
4358
    }
4359
  }
4360

4361
  *pPos = p;
2,147,483,647✔
4362
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
4363
}
4364

4365
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
74,527,154✔
4366
  int32_t code = prepareBuf(pCtx);
74,527,154✔
4367
  if (TSDB_CODE_SUCCESS != code) {
74,513,998✔
4368
    return code;
×
4369
  }
4370

4371
  SWinKey key = {0};
74,513,998✔
4372
  if (pCtx->saveHandle.pBuf == NULL) {
74,523,419✔
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;
74,528,036✔
4386
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
74,528,072✔
4387
  if (TSDB_CODE_SUCCESS != code) {
74,535,871✔
4388
    return code;
×
4389
  }
4390
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
74,535,871✔
4391
}
4392

4393
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
38,539,886✔
4394
                                 SFunctionStateStore* pStore) {
4395
  if (pHandle->pBuf != NULL) {
38,539,886✔
4396
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
38,545,466✔
4397
    if (pPage == NULL) {
38,544,935✔
4398
      return terrno;
×
4399
    }
4400
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
38,544,935✔
4401
    setBufPageDirty(pPage, true);
38,540,329✔
4402
    releaseBufPage(pHandle->pBuf, pPage);
38,541,265✔
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;
38,530,744✔
4411
}
4412

4413
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
38,529,440✔
4414
  int32_t code = prepareBuf(pCtx);
38,529,440✔
4415
  if (TSDB_CODE_SUCCESS != code) {
38,531,164✔
4416
    return code;
×
4417
  }
4418

4419
  char* buf = NULL;
38,531,164✔
4420
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
38,534,158✔
4421
  if (TSDB_CODE_SUCCESS != code) {
38,551,375✔
4422
    return code;
×
4423
  }
4424
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
38,551,375✔
4425
}
4426

4427
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
75,120,818✔
4428
                               char** value) {
4429
  if (pHandle->pBuf != NULL) {
75,120,818✔
4430
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
75,120,575✔
4431
    if (pPage == NULL) {
75,120,818✔
4432
      *value = NULL;
×
4433
      return terrno;
×
4434
    }
4435
    *value = pPage->data + pPos->offset;
75,120,818✔
4436
    releaseBufPage(pHandle->pBuf, pPage);
75,119,083✔
4437
    return TSDB_CODE_SUCCESS;
75,121,069✔
4438
  } else {
4439
    *value = NULL;
243✔
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) {
75,120,387✔
4450
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
75,120,387✔
4451
}
4452

4453
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,337,210✔
4454
  int32_t code = TSDB_CODE_SUCCESS;
8,337,210✔
4455

4456
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
8,337,210✔
4457
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
8,337,638✔
4458

4459
  int16_t type = pCtx->pExpr->base.resSchema.type;
8,337,122✔
4460
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
8,337,122✔
4461

4462
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,336,588✔
4463
  if (NULL == pCol) {
8,337,744✔
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;
8,337,744✔
4469
  if (pEntryInfo->numOfRes <= 0) {
8,337,316✔
4470
    colDataSetNULL(pCol, currentRow);
50,376✔
4471
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
50,376✔
4472
    return code;
50,376✔
4473
  }
4474
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
56,142,983✔
4475
    STopBotResItem* pItem = &pRes->pItems[i];
47,855,718✔
4476
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
47,855,721✔
4477
    if (TSDB_CODE_SUCCESS != code) {
47,857,633✔
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);
47,857,633✔
4485
    if (TSDB_CODE_SUCCESS != code) {
47,856,149✔
4486
      return code;
×
4487
    }
4488
    currentRow += 1;
47,856,149✔
4489
  }
4490

4491
  return code;
8,287,799✔
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); }
9,289,977✔
4568

4569
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
4,527,392✔
4570
  pEnv->calcMemSize = sizeof(SSpreadInfo);
4,527,392✔
4571
  return true;
4,533,896✔
4572
}
4573

4574
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
95,430,267✔
4575
  if (pResultInfo->initialized) {
95,430,267✔
4576
    return TSDB_CODE_SUCCESS;
×
4577
  }
4578
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
95,437,742✔
4579
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4580
  }
4581

4582
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
95,436,669✔
4583
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
95,437,053✔
4584
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
95,446,387✔
4585
  pInfo->hasResult = false;
95,447,979✔
4586
  return TSDB_CODE_SUCCESS;
95,450,672✔
4587
}
4588

4589
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
150,232,741✔
4590
  int32_t numOfElems = 0;
150,232,741✔
4591

4592
  // Only the pre-computing information loaded and actual data does not loaded
4593
  SInputColumnInfoData* pInput = &pCtx->input;
150,232,741✔
4594
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
150,239,911✔
4595
  int32_t               type = pInput->pData[0]->info.type;
150,316,214✔
4596

4597
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
150,321,402✔
4598

4599
  if (pInput->colDataSMAIsSet) {
150,313,864✔
4600
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
46,141,096✔
4601
    if (numOfElems == 0) {
46,153,572✔
4602
      goto _spread_over;
32,745,040✔
4603
    }
4604
    double tmin = 0.0, tmax = 0.0;
13,408,532✔
4605
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
13,408,532✔
4606
      tmin = (double)GET_INT64_VAL(&pAgg->min);
6,868,976✔
4607
      tmax = (double)GET_INT64_VAL(&pAgg->max);
6,863,378✔
4608
    } else if (IS_FLOAT_TYPE(type)) {
6,539,556✔
4609
      tmin = GET_DOUBLE_VAL(&pAgg->min);
2,488✔
4610
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4611
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
6,537,072✔
4612
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
6,540,796✔
4613
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
6,548,260✔
4614
    }
4615

4616
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
13,407,292✔
4617
      SET_DOUBLE_VAL(&pInfo->min, tmin);
609,466✔
4618
    }
4619

4620
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
13,407,288✔
4621
      SET_DOUBLE_VAL(&pInfo->max, tmax);
650,618✔
4622
    }
4623

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

4627
    int32_t start = pInput->startRowIndex;
104,162,946✔
4628
    // check the valid data one by one
4629
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
4630
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
4631
        continue;
2,147,483,647✔
4632
      }
4633

4634
      char* data = colDataGetData(pCol, i);
2,147,483,647✔
4635

4636
      double v = 0;
2,147,483,647✔
4637
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
2,147,483,647✔
4638
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
2,147,483,647✔
4639
        SET_DOUBLE_VAL(&pInfo->min, v);
103,878,019✔
4640
      }
4641

4642
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
2,147,483,647✔
4643
        SET_DOUBLE_VAL(&pInfo->max, v);
118,277,370✔
4644
      }
4645

4646
      numOfElems += 1;
2,147,483,647✔
4647
    }
4648
  }
4649

4650
_spread_over:
104,169,400✔
4651
  // data in the check operation are all null, not output
4652
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
150,314,256✔
4653
  if (numOfElems > 0) {
150,327,008✔
4654
    pInfo->hasResult = true;
110,861,798✔
4655
  }
4656

4657
  return TSDB_CODE_SUCCESS;
150,295,150✔
4658
}
4659

4660
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
8,070,209✔
4661
  pOutput->hasResult = pInput->hasResult;
8,070,209✔
4662
  if (pInput->max > pOutput->max) {
8,070,209✔
4663
    pOutput->max = pInput->max;
5,692,494✔
4664
  }
4665

4666
  if (pInput->min < pOutput->min) {
8,070,209✔
4667
    pOutput->min = pInput->min;
5,686,585✔
4668
  }
4669
}
8,070,209✔
4670

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

4675
  if (IS_NULL_TYPE(pCol->info.type)) {
6,673,915✔
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) {
6,673,915✔
4681
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4682
  }
4683

4684
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,673,915✔
4685

4686
  int32_t start = pInput->startRowIndex;
6,673,915✔
4687
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
15,578,790✔
4688
    if (colDataIsNull_s(pCol, i)) continue;
17,809,750✔
4689
    char*        data = colDataGetData(pCol, i);
8,904,875✔
4690
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
8,904,875✔
4691
    if (pInputInfo->hasResult) {
8,904,875✔
4692
      spreadTransferInfo(pInputInfo, pInfo);
8,070,209✔
4693
    }
4694
  }
4695

4696
  if (pInfo->hasResult) {
6,673,915✔
4697
    GET_RES_INFO(pCtx)->numOfRes = 1;
6,185,991✔
4698
  }
4699

4700
  return TSDB_CODE_SUCCESS;
6,673,915✔
4701
}
4702

4703
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
78,784,640✔
4704
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
78,784,640✔
4705
  if (pInfo->hasResult == true) {
78,789,312✔
4706
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
76,765,065✔
4707
  } else {
4708
    GET_RES_INFO(pCtx)->isNullRes = 1;
2,023,671✔
4709
  }
4710
  return functionFinalize(pCtx, pBlock);
78,789,184✔
4711
}
4712

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

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

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

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

4738
_exit:
8,918,279✔
4739
  taosMemoryFree(res);
8,918,279✔
4740
  return code;
8,918,279✔
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,493,014✔
4758
  pEnv->calcMemSize = sizeof(SElapsedInfo);
2,493,014✔
4759
  return true;
2,495,670✔
4760
}
4761

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

4770
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,768,326✔
4771
  pInfo->result = 0;
4,767,868✔
4772
  pInfo->min = TSKEY_MAX;
4,767,324✔
4773
  pInfo->max = 0;
4,765,034✔
4774

4775
  if (pCtx->numOfParams > 1) {
4,763,746✔
4776
    pInfo->timeUnit = pCtx->param[1].param.i;
2,862,153✔
4777
  } else {
4778
    pInfo->timeUnit = 1;
1,899,646✔
4779
  }
4780

4781
  return TSDB_CODE_SUCCESS;
4,765,120✔
4782
}
4783

4784
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
5,605,074✔
4785
  int32_t numOfElems = 0;
5,605,074✔
4786

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

4791
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,603,614✔
4792

4793
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
5,595,484✔
4794
  if (numOfElems == 0) {
5,597,746✔
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) {
5,597,746✔
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) {
5,603,700✔
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];
5,599,835✔
4828

4829
    int32_t start = pInput->startRowIndex;
5,601,467✔
4830
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
5,600,980✔
4831
    if (pCtx->order == TSDB_ORDER_DESC) {
5,601,238✔
4832
      if (pCtx->start.key == INT64_MIN) {
34,472✔
4833
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
33,985✔
4834
      } else {
4835
        pInfo->max = pCtx->start.key + 1;
×
4836
      }
4837

4838
      if (pCtx->end.key == INT64_MIN) {
33,985✔
4839
        pInfo->min =
33,985✔
4840
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
33,985✔
4841
      } else {
4842
        pInfo->min = pCtx->end.key;
×
4843
      }
4844
    } else {
4845
      if (pCtx->start.key == INT64_MIN) {
5,558,865✔
4846
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
5,569,657✔
4847
      } else {
4848
        pInfo->min = pCtx->start.key;
×
4849
      }
4850

4851
      if (pCtx->end.key == INT64_MIN) {
5,571,604✔
4852
        pInfo->max =
5,506,717✔
4853
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
5,505,772✔
4854
      } else {
4855
        pInfo->max = pCtx->end.key + 1;
60,135✔
4856
      }
4857
    }
4858
  }
4859

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

4864
  return TSDB_CODE_SUCCESS;
5,592,020✔
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,770,088✔
4900
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,770,088✔
4901
  double        result = (double)(pInfo->max - pInfo->min);
4,770,088✔
4902
  pInfo->result = fabs(result) / pInfo->timeUnit;
4,770,088✔
4903
  return functionFinalize(pCtx, pBlock);
4,770,088✔
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() {
762,060✔
4949
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
762,060✔
4950
}
4951

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

4957
static int8_t getHistogramBinType(char* binTypeStr) {
945,725✔
4958
  int8_t binType;
4959
  if (strcasecmp(binTypeStr, "user_input") == 0) {
945,725✔
4960
    binType = USER_INPUT_BIN;
526,839✔
4961
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
418,886✔
4962
    binType = LINEAR_BIN;
340,550✔
4963
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
78,336✔
4964
    binType = LOG_BIN;
78,336✔
4965
  } else {
4966
    binType = UNKNOWN_BIN;
×
4967
  }
4968

4969
  return binType;
945,725✔
4970
}
4971

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

4984
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
418,342✔
4985
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
418,503✔
4986
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
417,959✔
4987
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
418,503✔
4988
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
417,959✔
4989

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

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

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

5006
    int32_t counter = (int32_t)count->valueint;
418,503✔
5007
    if (infinity->valueint == false) {
418,503✔
5008
      startIndex = 0;
156,672✔
5009
      numOfBins = counter + 1;
156,672✔
5010
    } else {
5011
      startIndex = 1;
262,214✔
5012
      numOfBins = counter + 3;
262,214✔
5013
    }
5014

5015
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
418,886✔
5016
    if (NULL == intervals) {
418,503✔
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) {
418,503✔
5022
      // linear bin process
5023
      if (width->valuedouble == 0) {
340,167✔
5024
        taosMemoryFree(intervals);
×
5025
        cJSON_Delete(binDesc);
×
5026
        return TSDB_CODE_FAILED;
×
5027
      }
5028
      for (int i = 0; i < counter + 1; ++i) {
2,068,208✔
5029
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
1,727,658✔
5030
        if (isinf(intervals[startIndex])) {
1,728,041✔
5031
          taosMemoryFree(intervals);
×
5032
          cJSON_Delete(binDesc);
×
5033
          return TSDB_CODE_FAILED;
×
5034
        }
5035
        startIndex++;
1,728,041✔
5036
      }
5037
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
78,336✔
5038
      // log bin process
5039
      if (start->valuedouble == 0) {
78,336✔
5040
        taosMemoryFree(intervals);
×
5041
        cJSON_Delete(binDesc);
×
5042
        return TSDB_CODE_FAILED;
×
5043
      }
5044
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
78,336✔
5045
        taosMemoryFree(intervals);
×
5046
        cJSON_Delete(binDesc);
×
5047
        return TSDB_CODE_FAILED;
×
5048
      }
5049
      for (int i = 0; i < counter + 1; ++i) {
234,464✔
5050
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
156,672✔
5051
        if (isinf(intervals[startIndex])) {
156,672✔
5052
          taosMemoryFree(intervals);
×
5053
          cJSON_Delete(binDesc);
×
5054
          return TSDB_CODE_FAILED;
×
5055
        }
5056
        startIndex++;
156,128✔
5057
      }
5058
    } else {
5059
      taosMemoryFree(intervals);
×
5060
      cJSON_Delete(binDesc);
×
5061
      return TSDB_CODE_FAILED;
×
5062
    }
5063

5064
    if (infinity->valueint == true) {
418,342✔
5065
      intervals[0] = -INFINITY;
261,831✔
5066
      intervals[numOfBins - 1] = INFINITY;
261,831✔
5067
      // in case of desc bin orders, -inf/inf should be swapped
5068
      if (numOfBins < 4) {
261,831✔
5069
        return TSDB_CODE_FAILED;
×
5070
      }
5071
      if (intervals[1] > intervals[numOfBins - 2]) {
261,831✔
5072
        TSWAP(intervals[0], intervals[numOfBins - 1]);
×
5073
      }
5074
    }
5075
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
526,839✔
5076
    if (binType != USER_INPUT_BIN) {
526,839✔
5077
      cJSON_Delete(binDesc);
×
5078
      return TSDB_CODE_FAILED;
×
5079
    }
5080
    numOfBins = cJSON_GetArraySize(binDesc);
526,839✔
5081
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
527,383✔
5082
    if (NULL == intervals) {
526,839✔
5083
      cJSON_Delete(binDesc);
×
5084
      qError("histogram function out of memory");
×
5085
      return terrno;
×
5086
    }
5087
    cJSON* bin = binDesc->child;
526,839✔
5088
    if (bin == NULL) {
526,839✔
5089
      taosMemoryFree(intervals);
×
5090
      cJSON_Delete(binDesc);
×
5091
      return TSDB_CODE_FAILED;
×
5092
    }
5093
    int i = 0;
526,839✔
5094
    while (bin) {
2,320,189✔
5095
      intervals[i] = bin->valuedouble;
1,793,894✔
5096
      if (!cJSON_IsNumber(bin)) {
1,794,438✔
5097
        taosMemoryFree(intervals);
×
5098
        cJSON_Delete(binDesc);
×
5099
        return TSDB_CODE_FAILED;
×
5100
      }
5101
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
1,794,423✔
5102
        taosMemoryFree(intervals);
×
5103
        cJSON_Delete(binDesc);
×
5104
        return TSDB_CODE_FAILED;
×
5105
      }
5106
      bin = bin->next;
1,793,350✔
5107
      i++;
1,793,350✔
5108
    }
5109
  } else {
5110
    cJSON_Delete(binDesc);
×
5111
    return TSDB_CODE_FAILED;
×
5112
  }
5113

5114
  pInfo->numOfBins = numOfBins - 1;
944,798✔
5115
  pInfo->normalized = normalized;
944,652✔
5116
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
4,201,710✔
5117
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
3,257,058✔
5118
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
3,255,602✔
5119
    pInfo->bins[i].count = 0;
3,255,985✔
5120
  }
5121

5122
  taosMemoryFree(intervals);
944,269✔
5123
  cJSON_Delete(binDesc);
946,269✔
5124

5125
  return TSDB_CODE_SUCCESS;
945,886✔
5126
}
5127

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

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

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

5148
  if (binType == UNKNOWN_BIN) {
946,269✔
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));
946,269✔
5152
  if (binDesc == NULL) {
945,725✔
5153
    return terrno;
×
5154
  }
5155
  int64_t normalized = pCtx->param[3].param.i;
945,725✔
5156
  if (normalized != 0 && normalized != 1) {
945,725✔
5157
    taosMemoryFree(binDesc);
×
5158
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5159
  }
5160
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
945,725✔
5161
  if (TSDB_CODE_SUCCESS != code) {
944,798✔
5162
    taosMemoryFree(binDesc);
×
5163
    return code;
×
5164
  }
5165
  taosMemoryFree(binDesc);
944,798✔
5166

5167
  return TSDB_CODE_SUCCESS;
945,725✔
5168
}
5169

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

5173
  SInputColumnInfoData* pInput = &pCtx->input;
1,101,590✔
5174
  SColumnInfoData*      pCol = pInput->pData[0];
1,101,590✔
5175

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

5178
  int32_t start = pInput->startRowIndex;
1,101,590✔
5179
  int32_t numOfRows = pInput->numOfRows;
1,101,973✔
5180

5181
  int32_t numOfElems = 0;
1,106,925✔
5182
  for (int32_t i = start; i < numOfRows + start; ++i) {
159,291,447✔
5183
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
158,188,930✔
5184
      continue;
83,524,268✔
5185
    }
5186

5187
    numOfElems++;
74,659,422✔
5188

5189
    char*  data = colDataGetData(pCol, i);
74,659,422✔
5190
    double v;
5191
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
74,754,611✔
5192

5193
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
250,438,236✔
5194
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
206,999,142✔
5195
        pInfo->bins[k].count++;
31,235,304✔
5196
        pInfo->totalCount++;
31,235,304✔
5197
        break;
31,235,304✔
5198
      }
5199
    }
5200
  }
5201

5202
  if (!isPartial) {
1,102,517✔
5203
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
746,325✔
5204
  } else {
5205
    GET_RES_INFO(pCtx)->numOfRes = 1;
356,192✔
5206
  }
5207
  return TSDB_CODE_SUCCESS;
1,101,973✔
5208
}
5209

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

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

5214
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
227,889✔
5215
  pOutput->normalized = pInput->normalized;
227,889✔
5216
  pOutput->numOfBins = pInput->numOfBins;
228,272✔
5217
  pOutput->totalCount += pInput->totalCount;
228,272✔
5218
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
1,281,087✔
5219
    pOutput->bins[k].lower = pInput->bins[k].lower;
1,053,964✔
5220
    pOutput->bins[k].upper = pInput->bins[k].upper;
1,053,581✔
5221
    pOutput->bins[k].count += pInput->bins[k].count;
1,053,964✔
5222
  }
5223
}
227,506✔
5224

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

5232
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
228,272✔
5233

5234
  int32_t start = pInput->startRowIndex;
227,889✔
5235

5236
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
456,544✔
5237
    char*           data = colDataGetData(pCol, i);
228,272✔
5238
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
228,272✔
5239
    histogramTransferInfo(pInputInfo, pInfo);
227,889✔
5240
  }
5241

5242
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
228,272✔
5243
  return TSDB_CODE_SUCCESS;
227,889✔
5244
}
5245

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

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

5258
  if (pInfo->normalized) {
922,792✔
5259
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
508,912✔
5260
      if (pInfo->totalCount != 0) {
264,180✔
5261
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
29,172✔
5262
      } else {
5263
        pInfo->bins[k].percentage = 0;
235,008✔
5264
      }
5265
    }
5266
  }
5267

5268
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
4,073,817✔
5269
    int32_t len;
5270
    char    buf[512] = {0};
3,151,025✔
5271
    if (!pInfo->normalized) {
3,151,025✔
5272
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
2,887,374✔
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,
264,180✔
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);
3,149,730✔
5281
    code = colDataSetVal(pCol, currentRow, buf, false);
3,149,730✔
5282
    if (TSDB_CODE_SUCCESS != code) {
3,151,937✔
5283
      return code;
×
5284
    }
5285
    currentRow++;
3,151,937✔
5286
  }
5287

5288
  return code;
923,175✔
5289
}
5290

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

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

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

5312
_exit:
228,272✔
5313
  taosMemoryFree(res);
228,272✔
5314
  return code;
228,272✔
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); }
266,014✔
5331

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

5337
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
614,057,517✔
5338
  uint64_t hash = MurmurHash3_64(data, bytes);
614,057,517✔
5339
  int32_t  index = hash & HLL_BUCKET_MASK;
613,920,723✔
5340
  hash >>= HLL_BUCKET_BITS;
613,920,723✔
5341
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
613,920,723✔
5342
  uint64_t bit = 1;
613,920,723✔
5343
  uint8_t  count = 1;
613,920,723✔
5344
  while ((hash & bit) == 0) {
1,080,598,942✔
5345
    count++;
466,678,219✔
5346
    bit <<= 1;
466,678,219✔
5347
  }
5348
  *buk = index;
613,920,723✔
5349
  return count;
614,033,477✔
5350
}
5351

5352
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
9,278,570✔
5353
  uint64_t* word = (uint64_t*)buckets;
9,278,570✔
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;
67,363,907✔
5361
      bucketHisto[bytes[0]]++;
67,363,907✔
5362
      bucketHisto[bytes[1]]++;
87,757,027✔
5363
      bucketHisto[bytes[2]]++;
87,759,203✔
5364
      bucketHisto[bytes[3]]++;
87,761,379✔
5365
      bucketHisto[bytes[4]]++;
87,764,643✔
5366
      bucketHisto[bytes[5]]++;
87,764,643✔
5367
      bucketHisto[bytes[6]]++;
87,763,555✔
5368
      bucketHisto[bytes[7]]++;
87,763,555✔
5369
    }
5370
    word++;
2,147,483,647✔
5371
  }
5372
}
738✔
5373
static double hllTau(double x) {
9,279,098✔
5374
  if (x == 0. || x == 1.) return 0.;
9,279,098✔
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,279,642✔
5388
  if (x == 1.0) return INFINITY;
9,279,642✔
5389
  double zPrime;
5390
  double y = 1;
7,640,817✔
5391
  double z = x;
7,640,817✔
5392
  do {
5393
    x *= x;
148,523,713✔
5394
    zPrime = z;
148,523,713✔
5395
    z += x * y;
148,523,713✔
5396
    y += y;
148,523,713✔
5397
  } while (zPrime != z);
148,523,713✔
5398
  return z;
7,640,817✔
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,278,042✔
5404
  double  m = HLL_BUCKETS;
9,278,042✔
5405
  int32_t buckethisto[64] = {0};
9,278,042✔
5406
  hllBucketHisto(buckets, buckethisto);
9,278,042✔
5407

5408
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
9,279,642✔
5409
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
473,213,326✔
5410
    z += buckethisto[j];
463,933,684✔
5411
    z *= 0.5;
463,933,684✔
5412
  }
5413

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

5417
  return (uint64_t)E;
9,279,642✔
5418
}
5419

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

5423
  SInputColumnInfoData* pInput = &pCtx->input;
9,533,717✔
5424
  SColumnInfoData*      pCol = pInput->pData[0];
9,533,717✔
5425

5426
  int32_t type = pCol->info.type;
9,531,541✔
5427
  int32_t bytes = pCol->info.bytes;
9,527,749✔
5428

5429
  int32_t start = pInput->startRowIndex;
9,530,453✔
5430
  int32_t numOfRows = pInput->numOfRows;
9,531,030✔
5431

5432
  int32_t numOfElems = 0;
9,527,205✔
5433
  if (IS_NULL_TYPE(type)) {
9,527,205✔
5434
    goto _hll_over;
144,872✔
5435
  }
5436

5437
  for (int32_t i = start; i < numOfRows + start; ++i) {
731,189,915✔
5438
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
842,617,147✔
5439
      continue;
107,783,805✔
5440
    }
5441

5442
    numOfElems++;
614,005,164✔
5443

5444
    char* data = colDataGetData(pCol, i);
614,005,164✔
5445
    if (IS_VAR_DATA_TYPE(type)) {
614,204,345✔
5446
      if (IS_STR_DATA_BLOB(type)) {
80,573,290✔
5447
        bytes = blobDataLen(data);
52,658✔
5448
        data = blobDataVal(data);
×
5449
      } else {
5450
        bytes = varDataLen(data);
80,520,632✔
5451
        data = varDataVal(data);
80,518,368✔
5452
      }
5453
    }
5454

5455
    int32_t index = 0;
614,149,967✔
5456
    uint8_t count = hllCountNum(data, bytes, &index);
613,894,607✔
5457
    uint8_t oldcount = pInfo->buckets[index];
614,022,135✔
5458
    if (count > oldcount) {
614,060,045✔
5459
      pInfo->buckets[index] = count;
131,410,788✔
5460
    }
5461
  }
5462

5463
_hll_over:
9,373,008✔
5464
  pInfo->totalCount += numOfElems;
9,517,880✔
5465

5466
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
9,534,805✔
5467
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
496,124✔
5468
  } else {
5469
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
9,038,697✔
5470
  }
5471

5472
  return TSDB_CODE_SUCCESS;
9,533,189✔
5473
}
5474

5475
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
266,014✔
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];
35,472,540✔
5479
    }
5480
  }
5481
  pOutput->totalCount += pInput->totalCount;
7,742✔
5482
}
266,014✔
5483

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

5488
  if (IS_NULL_TYPE(pCol->info.type)) {
266,014✔
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) {
266,014✔
5494
    return TSDB_CODE_SUCCESS;
×
5495
  }
5496

5497
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
266,014✔
5498

5499
  int32_t start = pInput->startRowIndex;
266,014✔
5500

5501
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
532,028✔
5502
    if (colDataIsNull_s(pCol, i)) continue;
532,028✔
5503
    char*     data = colDataGetData(pCol, i);
266,014✔
5504
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
266,014✔
5505
    hllTransferInfo(pInputInfo, pInfo);
266,014✔
5506
  }
5507

5508
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
266,014✔
5509
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
60✔
5510
  } else {
5511
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
265,954✔
5512
  }
5513

5514
  return TSDB_CODE_SUCCESS;
266,014✔
5515
}
5516

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

5520
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,279,642✔
5521
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
9,279,642✔
5522
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
9,279,642✔
5523
    pInfo->numOfRes = 1;
1,142,577✔
5524
  }
5525

5526
  return functionFinalize(pCtx, pBlock);
9,279,642✔
5527
}
5528

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

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

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

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

5551
_exit:
266,014✔
5552
  taosMemoryFree(res);
266,014✔
5553
  return code;
266,014✔
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,757✔
5570
  pEnv->calcMemSize = sizeof(SStateInfo);
1,332,757✔
5571
  return true;
1,333,140✔
5572
}
5573

5574
static int8_t getStateOpType(char* opStr) {
1,356,242✔
5575
  int8_t opType;
5576
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,356,242✔
5577
    opType = STATE_OPER_LT;
142,808✔
5578
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
1,213,434✔
5579
    opType = STATE_OPER_GT;
426,942✔
5580
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
786,492✔
5581
    opType = STATE_OPER_LE;
112,840✔
5582
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
673,652✔
5583
    opType = STATE_OPER_GE;
110,920✔
5584
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
562,732✔
5585
    opType = STATE_OPER_NE;
410,097✔
5586
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
152,635✔
5587
    opType = STATE_OPER_EQ;
152,531✔
5588
  } else {
5589
    opType = STATE_OPER_INVALID;
104✔
5590
  }
5591

5592
  return opType;
1,356,242✔
5593
}
5594

5595
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
81,944,718✔
5596
  char* data = colDataGetData(pCol, index);
81,944,718✔
5597
  switch (pCol->info.type) {
81,944,718✔
5598
    case TSDB_DATA_TYPE_TINYINT: {
21,360,948✔
5599
      int8_t v = *(int8_t*)data;
21,360,948✔
5600
      STATE_COMP(op, v, param);
21,360,948✔
5601
      break;
×
5602
    }
5603
    case TSDB_DATA_TYPE_UTINYINT: {
31,030,784✔
5604
      uint8_t v = *(uint8_t*)data;
31,030,784✔
5605
      STATE_COMP(op, v, param);
31,030,784✔
5606
      break;
×
5607
    }
5608
    case TSDB_DATA_TYPE_SMALLINT: {
681,656✔
5609
      int16_t v = *(int16_t*)data;
681,656✔
5610
      STATE_COMP(op, v, param);
681,656✔
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: {
22,246,625✔
5619
      int32_t v = *(int32_t*)data;
22,246,625✔
5620
      STATE_COMP(op, v, param);
22,246,625✔
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,134✔
5629
      int64_t v = *(int64_t*)data;
691,134✔
5630
      STATE_COMP(op, v, param);
691,134✔
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: {
3,112,056✔
5639
      float v = *(float*)data;
3,112,056✔
5640
      STATE_COMP(op, v, param);
3,112,056✔
5641
      break;
×
5642
    }
5643
    case TSDB_DATA_TYPE_DOUBLE: {
955,275✔
5644
      double v = *(double*)data;
955,275✔
5645
      STATE_COMP(op, v, param);
955,275✔
5646
      break;
×
5647
    }
5648
    default: {
×
5649
      return false;
×
5650
    }
5651
  }
5652
  return false;
×
5653
}
5654

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

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

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

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

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

5673
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
49,112,455✔
5674
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
48,899,568✔
5675
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
856✔
5676
    } else {
5677
      pInfo->prevTs = tsList[i];
48,898,712✔
5678
    }
5679

5680
    pInfo->isPrevTsSet = true;
48,898,712✔
5681
    numOfElems++;
48,898,712✔
5682

5683
    if (colDataIsNull_f(pInputCol, i)) {
48,898,712✔
5684
      colDataSetNULL(pOutput, i);
22,441,460✔
5685
      // handle selectivity
5686
      if (pCtx->subsidiaries.num > 0) {
22,441,460✔
5687
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,915✔
5688
        if (TSDB_CODE_SUCCESS != code) {
3,915✔
5689
          return code;
×
5690
        }
5691
      }
5692
      continue;
22,441,460✔
5693
    }
5694

5695
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
26,457,252✔
5696

5697
    int64_t output = -1;
26,457,252✔
5698
    if (ret) {
26,457,252✔
5699
      output = ++pInfo->count;
14,690,657✔
5700
    } else {
5701
      pInfo->count = 0;
11,766,595✔
5702
    }
5703
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
26,457,252✔
5704
    if (TSDB_CODE_SUCCESS != code) {
26,457,252✔
5705
      return code;
×
5706
    }
5707

5708
    // handle selectivity
5709
    if (pCtx->subsidiaries.num > 0) {
26,457,252✔
5710
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
848,836✔
5711
      if (TSDB_CODE_SUCCESS != code) {
848,836✔
5712
        return code;
×
5713
      }
5714
    }
5715
  }
5716

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

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

5726
  SInputColumnInfoData* pInput = &pCtx->input;
1,142,541✔
5727
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,142,541✔
5728

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

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

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

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

5745
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
121,468,808✔
5746
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
120,328,788✔
5747
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
856✔
5748
    } else {
5749
      pInfo->prevTs = tsList[i];
120,327,591✔
5750
    }
5751

5752
    pInfo->isPrevTsSet = true;
120,328,023✔
5753
    numOfElems++;
120,328,880✔
5754

5755
    if (colDataIsNull_f(pInputCol, i)) {
120,328,880✔
5756
      colDataSetNULL(pOutput, i);
64,854,267✔
5757
      // handle selectivity
5758
      if (pCtx->subsidiaries.num > 0) {
64,879,399✔
5759
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
7,591✔
5760
        if (TSDB_CODE_SUCCESS != code) {
7,104✔
5761
          return code;
×
5762
        }
5763
      }
5764
      continue;
64,879,399✔
5765
    }
5766

5767
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
55,486,979✔
5768
    int64_t output = -1;
55,487,466✔
5769
    if (ret) {
55,487,466✔
5770
      if (pInfo->durationStart == 0) {
39,794,756✔
5771
        output = 0;
2,641,809✔
5772
        pInfo->durationStart = tsList[i];
2,641,809✔
5773
      } else {
5774
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
37,152,947✔
5775
      }
5776
    } else {
5777
      pInfo->durationStart = 0;
15,692,710✔
5778
    }
5779
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
55,486,979✔
5780
    if (TSDB_CODE_SUCCESS != code) {
55,486,979✔
5781
      return code;
×
5782
    }
5783

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

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

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

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

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

5810
  SColumnInfoData* pInputCol = pInput->pData[0];
756,016✔
5811
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
755,624✔
5812

5813
  int32_t numOfElems = 0;
755,624✔
5814
  int32_t type = pInputCol->info.type;
755,624✔
5815
  int32_t startOffset = pCtx->offset;
755,624✔
5816
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
127,072,443✔
5817
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
126,244,063✔
5818
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
7,263✔
5819
    } else {
5820
      pSumRes->prevTs = tsList[i];
126,236,572✔
5821
    }
5822
    pSumRes->isPrevTsSet = true;
126,237,840✔
5823

5824
    int32_t pos = startOffset + numOfElems;
126,240,448✔
5825
    if (colDataIsNull_f(pInputCol, i)) {
126,240,448✔
5826
      // colDataSetNULL(pOutput, i);
5827
      continue;
62,255,019✔
5828
    }
5829

5830
    char* data = colDataGetData(pInputCol, i);
64,060,386✔
5831
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
102,192,524✔
5832
      int64_t v;
5833
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
38,130,605✔
5834
      pSumRes->isum += v;
38,130,605✔
5835
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
38,130,605✔
5836
      if (TSDB_CODE_SUCCESS != code) {
38,131,116✔
5837
        return code;
×
5838
      }
5839
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
36,171,875✔
5840
      uint64_t v;
5841
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
10,241,072✔
5842
      pSumRes->usum += v;
10,241,072✔
5843
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
10,241,072✔
5844
      if (TSDB_CODE_SUCCESS != code) {
10,241,072✔
5845
        return code;
×
5846
      }
5847
    } else if (IS_FLOAT_TYPE(type)) {
15,689,731✔
5848
      double v;
5849
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
15,689,220✔
5850
      pSumRes->dsum += v;
15,689,220✔
5851
      // check for overflow
5852
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
15,689,220✔
5853
        colDataSetNULL(pOutput, pos);
888✔
5854
      } else {
5855
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
15,688,332✔
5856
        if (TSDB_CODE_SUCCESS != code) {
15,688,332✔
5857
          return code;
×
5858
        }
5859
      }
5860
    }
5861

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

5870
    numOfElems++;
64,061,408✔
5871
  }
5872

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

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

5882
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
866,826✔
5883
  if (pResultInfo->initialized) {
866,826✔
5884
    return TSDB_CODE_SUCCESS;
386,111✔
5885
  }
5886
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
480,715✔
5887
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5888
  }
5889

5890
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
480,187✔
5891
  pInfo->pos = 0;
480,715✔
5892
  pInfo->sum = 0;
480,715✔
5893
  pInfo->prevTs = -1;
480,715✔
5894
  pInfo->isPrevTsSet = false;
480,187✔
5895
  pInfo->numOfPoints = pCtx->param[1].param.i;
479,659✔
5896
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
480,187✔
5897
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5898
  }
5899
  pInfo->pointsMeet = false;
480,715✔
5900

5901
  return TSDB_CODE_SUCCESS;
479,659✔
5902
}
5903

5904
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
476,000✔
5905
  int32_t              code = TSDB_CODE_SUCCESS;
476,000✔
5906
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
476,000✔
5907
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
476,000✔
5908

5909
  SInputColumnInfoData* pInput = &pCtx->input;
476,000✔
5910
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
476,000✔
5911

5912
  SColumnInfoData* pInputCol = pInput->pData[0];
476,000✔
5913
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
476,000✔
5914
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
476,000✔
5915

5916
  int32_t numOfElems = 0;
476,000✔
5917
  int32_t type = pInputCol->info.type;
476,000✔
5918
  int32_t startOffset = pCtx->offset;
476,000✔
5919
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
123,421,822✔
5920
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
122,957,630✔
5921
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
856✔
5922
    } else {
5923
      pInfo->prevTs = tsList[i];
122,954,406✔
5924
    }
5925
    pInfo->isPrevTsSet = true;
122,958,749✔
5926

5927
    int32_t pos = startOffset + numOfElems;
122,960,061✔
5928
    if (colDataIsNull_f(pInputCol, i)) {
122,960,061✔
5929
      // colDataSetNULL(pOutput, i);
5930
      continue;
25,195,825✔
5931
    }
5932

5933
    char*  data = colDataGetData(pInputCol, i);
97,845,549✔
5934
    double v;
5935
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
97,851,429✔
5936

5937
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
97,851,429✔
5938
      pInfo->points[pInfo->pos] = v;
17,003,832✔
5939
      pInfo->sum += v;
17,004,224✔
5940
    } else {
5941
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
80,838,973✔
5942
        pInfo->sum += v;
291,868✔
5943
        pInfo->pointsMeet = true;
291,868✔
5944
      } else {
5945
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
80,546,713✔
5946
      }
5947

5948
      pInfo->points[pInfo->pos] = v;
80,838,581✔
5949
      double result = pInfo->sum / pInfo->numOfPoints;
80,838,581✔
5950
      // check for overflow
5951
      if (isinf(result) || isnan(result)) {
80,838,581✔
5952
        colDataSetNULL(pOutput, pos);
×
5953
      } else {
5954
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
80,838,581✔
5955
        if (TSDB_CODE_SUCCESS != code) {
80,838,581✔
5956
          return code;
×
5957
        }
5958
      }
5959

5960
      // handle selectivity
5961
      if (pCtx->subsidiaries.num > 0) {
80,838,581✔
5962
        code = appendSelectivityValue(pCtx, i, pos);
32,856✔
5963
        if (TSDB_CODE_SUCCESS != code) {
32,856✔
5964
          return code;
×
5965
        }
5966
      }
5967

5968
      numOfElems++;
80,838,581✔
5969
    }
5970

5971
    pInfo->pos++;
97,842,805✔
5972
    if (pInfo->pos == pInfo->numOfPoints) {
97,842,413✔
5973
      pInfo->pos = 0;
1,761,646✔
5974
    }
5975
  }
5976

5977
  pResInfo->numOfRes = numOfElems;
475,144✔
5978
  return TSDB_CODE_SUCCESS;
475,144✔
5979
}
5980

5981
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
3,821,636✔
5982
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,821,636✔
5983
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,821,636✔
5984

5985
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
3,822,165✔
5986
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
3,821,737✔
5987

5988
  return pInfo;
3,821,315✔
5989
}
5990

5991
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
803,260✔
5992
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
803,260✔
5993
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
801,663✔
5994
  int32_t      numOfSamples = pVal->datum.i;
800,717✔
5995
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
799,422✔
5996
  return true;
797,647✔
5997
}
5998

5999
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,742,278✔
6000
  if (pResultInfo->initialized) {
1,742,278✔
6001
    return TSDB_CODE_SUCCESS;
×
6002
  }
6003
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,742,807✔
6004
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6005
  }
6006

6007
  taosSeedRand(taosSafeRand());
1,742,365✔
6008

6009
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,743,235✔
6010
  pInfo->samples = pCtx->param[1].param.i;
1,743,235✔
6011
  pInfo->totalPoints = 0;
1,743,235✔
6012
  pInfo->numSampled = 0;
1,743,235✔
6013
  pInfo->colType = pCtx->resDataInfo.type;
1,743,235✔
6014
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,743,235✔
6015
  pInfo->nullTuplePos.pageId = -1;
1,743,235✔
6016
  pInfo->nullTupleSaved = false;
1,743,235✔
6017
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
1,743,235✔
6018
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
1,743,235✔
6019

6020
  return TSDB_CODE_SUCCESS;
1,743,235✔
6021
}
6022

6023
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
7,255,411✔
6024
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
7,255,411✔
6025
}
7,254,989✔
6026

6027
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
43,311,407✔
6028
  pInfo->totalPoints++;
43,311,407✔
6029
  if (pInfo->numSampled < pInfo->samples) {
43,311,841✔
6030
    sampleAssignResult(pInfo, data, pInfo->numSampled);
5,707,004✔
6031
    if (pCtx->subsidiaries.num > 0) {
5,706,148✔
6032
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,011,939✔
6033
      if (code != TSDB_CODE_SUCCESS) {
1,011,939✔
6034
        return code;
×
6035
      }
6036
    }
6037
    pInfo->numSampled++;
5,706,998✔
6038
  } else {
6039
    int32_t j = (int32_t)(taosRand() % (uint64_t)pInfo->totalPoints);
37,605,693✔
6040
    if (j < pInfo->samples) {
37,597,568✔
6041
      sampleAssignResult(pInfo, data, j);
1,548,841✔
6042
      if (pCtx->subsidiaries.num > 0) {
1,548,841✔
6043
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
332,876✔
6044
        if (code != TSDB_CODE_SUCCESS) {
331,169✔
6045
          return code;
×
6046
        }
6047
      }
6048
    }
6049
  }
6050

6051
  return TSDB_CODE_SUCCESS;
43,299,435✔
6052
}
6053

6054
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
2,081,498✔
6055
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,081,498✔
6056
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
2,081,498✔
6057

6058
  SInputColumnInfoData* pInput = &pCtx->input;
2,080,648✔
6059

6060
  SColumnInfoData* pInputCol = pInput->pData[0];
2,080,648✔
6061
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
152,250,676✔
6062
    if (colDataIsNull_s(pInputCol, i)) {
300,288,079✔
6063
      continue;
106,869,309✔
6064
    }
6065

6066
    char*   data = colDataGetData(pInputCol, i);
43,295,703✔
6067
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
43,305,849✔
6068
    if (code != TSDB_CODE_SUCCESS) {
43,300,291✔
6069
      return code;
×
6070
    }
6071
  }
6072

6073
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,081,498✔
6074
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
1,740✔
6075
    if (code != TSDB_CODE_SUCCESS) {
1,740✔
6076
      return code;
×
6077
    }
6078
    pInfo->nullTupleSaved = true;
1,740✔
6079
  }
6080

6081
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
2,081,498✔
6082
  return TSDB_CODE_SUCCESS;
2,081,498✔
6083
}
6084

6085
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,740,667✔
6086
  int32_t              code = TSDB_CODE_SUCCESS;
1,740,667✔
6087
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,740,667✔
6088

6089
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
1,740,667✔
6090
  pEntryInfo->complete = true;
1,740,667✔
6091

6092
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,740,667✔
6093
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,740,156✔
6094
  if (NULL == pCol) {
1,739,199✔
6095
    return TSDB_CODE_OUT_OF_RANGE;
×
6096
  }
6097

6098
  int32_t currentRow = pBlock->info.rows;
1,739,199✔
6099
  if (pInfo->numSampled == 0) {
1,739,728✔
6100
    colDataSetNULL(pCol, currentRow);
602,722✔
6101
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
602,722✔
6102
    return code;
602,339✔
6103
  }
6104
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
6,844,508✔
6105
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
5,706,991✔
6106
    if (TSDB_CODE_SUCCESS != code) {
5,707,854✔
6107
      return code;
×
6108
    }
6109
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
5,707,854✔
6110
    if (TSDB_CODE_SUCCESS != code) {
5,707,426✔
6111
      return code;
×
6112
    }
6113
  }
6114

6115
  return code;
1,137,945✔
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) {
1,474,807✔
6356
  pEnv->calcMemSize = sizeof(SModeInfo);
1,474,807✔
6357
  return true;
1,475,336✔
6358
}
6359

6360
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,597,972✔
6361
  if (pResInfo->initialized) {
2,597,972✔
6362
    return TSDB_CODE_SUCCESS;
×
6363
  }
6364
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,597,972✔
6365
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6366
  }
6367

6368
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,597,972✔
6369
  pInfo->colType = pCtx->resDataInfo.type;
2,597,972✔
6370
  pInfo->colBytes = pCtx->resDataInfo.bytes;
2,597,972✔
6371
  if (pInfo->pHash != NULL) {
2,597,972✔
6372
    taosHashClear(pInfo->pHash);
×
6373
  } else {
6374
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
2,597,972✔
6375
    if (NULL == pInfo->pHash) {
2,597,972✔
6376
      return terrno;
×
6377
    }
6378
  }
6379
  pInfo->nullTupleSaved = false;
2,597,972✔
6380
  pInfo->nullTuplePos.pageId = -1;
2,597,972✔
6381

6382
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
2,597,972✔
6383
  if (NULL == pInfo->buf) {
2,597,589✔
6384
    taosHashCleanup(pInfo->pHash);
×
6385
    pInfo->pHash = NULL;
×
6386
    return terrno;
×
6387
  }
6388
  pCtx->needCleanup = true;
2,597,544✔
6389
  return TSDB_CODE_SUCCESS;
2,597,544✔
6390
}
6391

6392
static void modeFunctionCleanup(SModeInfo* pInfo) {
4,002,040✔
6393
  taosHashCleanup(pInfo->pHash);
4,002,040✔
6394
  pInfo->pHash = NULL;
4,002,040✔
6395
  taosMemoryFreeClear(pInfo->buf);
4,002,040✔
6396
}
4,002,040✔
6397

6398
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
1,476,248✔
6399
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
1,476,248✔
6400
    return;
70,896✔
6401
  }
6402
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
1,405,352✔
6403
}
6404

6405
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
2,147,483,647✔
6406
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
2,147,483,647✔
6407
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
41,839,756✔
6408
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
271,458✔
6409
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
41,573,828✔
6410
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
383✔
6411
    } else {
6412
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
41,572,916✔
6413
    }
6414
  } else {
6415
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
2,147,483,647✔
6416
  }
6417

6418
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
2,147,483,647✔
6419
}
6420

6421
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
2,147,483,647✔
6422
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
6423
  int32_t hashKeyBytes;
6424
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
2,147,483,647✔
6425
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
2,147,483,647✔
6426
  } else {
6427
    hashKeyBytes = pInfo->colBytes;
2,147,483,647✔
6428
  }
6429

6430
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
2,147,483,647✔
6431
  if (pHashItem == NULL) {
2,147,483,647✔
6432
    int32_t   size = sizeof(SModeItem);
2,147,483,647✔
6433
    SModeItem item = {0};
2,147,483,647✔
6434

6435
    item.count += 1;
2,147,483,647✔
6436
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
2,147,483,647✔
6437
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
6438
      return code;
×
6439
    }
6440

6441
    if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
6442
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
265,844✔
6443
      if (code != TSDB_CODE_SUCCESS) {
265,844✔
6444
        return code;
×
6445
      }
6446
    }
6447

6448
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
2,147,483,647✔
6449
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
6450
      return code;
×
6451
    }
6452
  } else {
6453
    pHashItem->count += 1;
2,147,483,647✔
6454
    if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
6455
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,488,780✔
6456
      if (code != TSDB_CODE_SUCCESS) {
3,488,780✔
6457
        return code;
×
6458
      }
6459
    }
6460
  }
6461

6462
  return code;
2,147,483,647✔
6463
}
6464

6465
int32_t modeFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
6466
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
6467
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
6468

6469
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
6470

6471
  SColumnInfoData* pInputCol = pInput->pData[0];
2,147,483,647✔
6472
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,147,483,647✔
6473

6474
  int32_t numOfElems = 0;
2,147,483,647✔
6475
  int32_t startOffset = pCtx->offset;
2,147,483,647✔
6476
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
6477
    if (colDataIsNull_s(pInputCol, i)) {
2,147,483,647✔
6478
      continue;
2,147,483,647✔
6479
    }
6480
    numOfElems++;
2,147,483,647✔
6481

6482
    char*   data = colDataGetData(pInputCol, i);
2,147,483,647✔
6483
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
2,147,483,647✔
6484
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
6485
      modeFunctionCleanup(pInfo);
35,756✔
6486
      return code;
×
6487
    }
6488
  }
6489

6490
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,147,483,647✔
6491
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
4,480✔
6492
    if (code != TSDB_CODE_SUCCESS) {
4,480✔
6493
      modeFunctionCleanup(pInfo);
×
6494
      return code;
×
6495
    }
6496
    pInfo->nullTupleSaved = true;
4,480✔
6497
  }
6498

6499
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
6500

6501
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
6502
}
6503

6504
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,596,688✔
6505
  int32_t              code = TSDB_CODE_SUCCESS;
2,596,688✔
6506
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,596,688✔
6507
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,596,688✔
6508
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
2,596,688✔
6509
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,596,688✔
6510
  int32_t              currentRow = pBlock->info.rows;
2,596,688✔
6511
  if (NULL == pCol) {
2,596,177✔
6512
    modeFunctionCleanup(pInfo);
×
6513
    return TSDB_CODE_OUT_OF_RANGE;
×
6514
  }
6515

6516
  STuplePos resDataPos, resTuplePos;
2,596,177✔
6517
  int32_t   maxCount = 0;
2,596,688✔
6518

6519
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
2,596,688✔
6520
  while (pIter != NULL) {
2,147,483,647✔
6521
    SModeItem* pItem = (SModeItem*)pIter;
2,147,483,647✔
6522
    if (pItem->count >= maxCount) {
2,147,483,647✔
6523
      maxCount = pItem->count;
2,147,483,647✔
6524
      resDataPos = pItem->dataPos;
2,147,483,647✔
6525
      resTuplePos = pItem->tuplePos;
2,147,483,647✔
6526
    }
6527

6528
    pIter = taosHashIterate(pInfo->pHash, pIter);
2,147,483,647✔
6529
  }
6530

6531
  if (maxCount != 0) {
2,596,688✔
6532
    char* pData = NULL;
2,095,677✔
6533
    code = loadTupleData(pCtx, &resDataPos, &pData);
2,095,677✔
6534
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
2,095,677✔
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);
2,095,677✔
6543
    if (TSDB_CODE_SUCCESS != code) {
2,095,677✔
6544
      modeFunctionCleanup(pInfo);
×
6545
      return code;
×
6546
    }
6547
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
2,095,677✔
6548
  } else {
6549
    colDataSetNULL(pCol, currentRow);
501,011✔
6550
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
501,011✔
6551
  }
6552

6553
  modeFunctionCleanup(pInfo);
2,596,688✔
6554

6555
  return code;
2,596,688✔
6556
}
6557

6558
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
307,069✔
6559
  pEnv->calcMemSize = sizeof(STwaInfo);
307,069✔
6560
  return true;
307,501✔
6561
}
6562

6563
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,475,469✔
6564
  if (pResultInfo->initialized) {
7,475,469✔
6565
    return TSDB_CODE_SUCCESS;
×
6566
  }
6567
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,475,469✔
6568
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6569
  }
6570

6571
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,475,571✔
6572
  pInfo->numOfElems = 0;
7,475,571✔
6573
  pInfo->p.key = INT64_MIN;
7,476,003✔
6574
  pInfo->win = TSWINDOW_INITIALIZER;
7,475,084✔
6575
  return TSDB_CODE_SUCCESS;
7,476,003✔
6576
}
6577

6578
static double twa_get_area(SPoint1 s, SPoint1 e) {
186,218,757✔
6579
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
186,218,757✔
6580
    return 0;
×
6581
  }
6582

6583
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
186,261,621✔
6584
    return (s.val + e.val) * (e.key - s.key) / 2;
169,083,242✔
6585
  }
6586

6587
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
17,178,379✔
6588
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
17,178,379✔
6589
  return val;
17,178,379✔
6590
}
6591

6592
int32_t twaFunction(SqlFunctionCtx* pCtx) {
7,496,304✔
6593
  int32_t               code = TSDB_CODE_SUCCESS;
7,496,304✔
6594
  SInputColumnInfoData* pInput = &pCtx->input;
7,496,304✔
6595
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,497,325✔
6596

6597
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,496,893✔
6598
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,497,325✔
6599
  SPoint1*             last = &pInfo->p;
7,496,893✔
6600

6601
  if (IS_NULL_TYPE(pInputCol->info.type)) {
7,496,893✔
6602
    pInfo->numOfElems = 0;
×
6603
    goto _twa_over;
×
6604
  }
6605

6606
  funcInputUpdate(pCtx);
7,496,791✔
6607
  SFuncInputRow row = {0};
7,495,927✔
6608
  bool          result = false;
7,495,927✔
6609
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
7,495,927✔
6610
    while (1) {
6611
      code = funcInputGetNextRow(pCtx, &row, &result);
5,211,595✔
6612
      if (TSDB_CODE_SUCCESS != code) {
5,211,595✔
6613
        return code;
×
6614
      }
6615
      if (!result) {
5,211,595✔
6616
        break;
768✔
6617
      }
6618
      if (row.isDataNull) {
5,210,827✔
6619
        continue;
768✔
6620
      }
6621

6622
      last->key = row.ts;
5,210,059✔
6623

6624
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
5,210,059✔
6625

6626
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
5,210,059✔
6627
      pInfo->win.skey = pCtx->start.key;
5,210,059✔
6628
      pInfo->numOfElems++;
5,210,059✔
6629
      break;
5,210,059✔
6630
    }
6631
  } else if (pInfo->p.key == INT64_MIN) {
2,285,964✔
6632
    while (1) {
6633
      code = funcInputGetNextRow(pCtx, &row, &result);
11,157,991✔
6634
      if (TSDB_CODE_SUCCESS != code) {
11,158,525✔
6635
        return code;
×
6636
      }
6637
      if (!result) {
11,158,525✔
6638
        break;
857,282✔
6639
      }
6640
      if (row.isDataNull) {
10,301,243✔
6641
        continue;
8,893,247✔
6642
      }
6643

6644
      last->key = row.ts;
1,407,996✔
6645

6646
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
1,407,030✔
6647

6648
      pInfo->win.skey = last->key;
1,407,030✔
6649
      pInfo->numOfElems++;
1,407,462✔
6650
      break;
1,407,030✔
6651
    }
6652
  }
6653

6654
  SPoint1 st = {0};
7,495,495✔
6655

6656
  // calculate the value of
6657
  while (1) {
6658
    code = funcInputGetNextRow(pCtx, &row, &result);
183,372,825✔
6659
    if (TSDB_CODE_SUCCESS != code) {
183,382,431✔
6660
      return code;
×
6661
    }
6662
    if (!result) {
183,382,431✔
6663
      break;
7,497,325✔
6664
    }
6665
    if (row.isDataNull) {
175,885,106✔
6666
      continue;
54,432✔
6667
    }
6668
    pInfo->numOfElems++;
175,830,674✔
6669
    switch (pInputCol->info.type) {
175,839,314✔
6670
      case TSDB_DATA_TYPE_TINYINT: {
13,473,430✔
6671
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
13,473,430✔
6672
        break;
13,473,430✔
6673
      }
6674
      case TSDB_DATA_TYPE_SMALLINT: {
13,428,672✔
6675
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
13,428,672✔
6676
        break;
13,428,240✔
6677
      }
6678
      case TSDB_DATA_TYPE_INT: {
74,839,144✔
6679
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
74,839,144✔
6680
        break;
74,838,712✔
6681
      }
6682
      case TSDB_DATA_TYPE_BIGINT: {
14,596,709✔
6683
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
14,596,709✔
6684
        break;
14,595,413✔
6685
      }
6686
      case TSDB_DATA_TYPE_FLOAT: {
11,837,948✔
6687
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
11,837,948✔
6688
        break;
11,837,516✔
6689
      }
6690
      case TSDB_DATA_TYPE_DOUBLE: {
13,199,219✔
6691
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
13,199,219✔
6692
        break;
13,174,595✔
6693
      }
6694
      case TSDB_DATA_TYPE_UTINYINT: {
8,814,618✔
6695
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
8,814,618✔
6696
        break;
8,813,322✔
6697
      }
6698
      case TSDB_DATA_TYPE_USMALLINT: {
8,809,434✔
6699
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
8,809,434✔
6700
        break;
8,809,002✔
6701
      }
6702
      case TSDB_DATA_TYPE_UINT: {
8,873,886✔
6703
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
8,873,886✔
6704
        break;
8,872,590✔
6705
      }
6706
      case TSDB_DATA_TYPE_UBIGINT: {
7,964,094✔
6707
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
7,964,094✔
6708
        break;
7,961,070✔
6709
      }
6710
      default: {
×
6711
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6712
      }
6713
    }
6714
    if (pInfo->p.key == st.key) {
175,803,890✔
6715
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6716
    }
6717

6718
    pInfo->dOutput += twa_get_area(pInfo->p, st);
175,829,378✔
6719
    pInfo->p = st;
175,806,914✔
6720
  }
6721

6722
  // the last interpolated time window value
6723
  if (pCtx->end.key != INT64_MIN) {
7,497,325✔
6724
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5,213,016✔
6725
    pInfo->p = pCtx->end;
5,213,016✔
6726
    pInfo->numOfElems += 1;
5,213,016✔
6727
  }
6728

6729
  pInfo->win.ekey = pInfo->p.key;
7,497,325✔
6730

6731
_twa_over:
7,496,791✔
6732
  SET_VAL(pResInfo, 1, 1);
7,497,325✔
6733
  return TSDB_CODE_SUCCESS;
7,497,325✔
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,475,571✔
6749
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,475,571✔
6750

6751
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,476,003✔
6752
  if (pInfo->numOfElems == 0) {
7,476,003✔
6753
    pResInfo->numOfRes = 0;
857,282✔
6754
  } else {
6755
    if (pInfo->win.ekey == pInfo->win.skey) {
6,618,289✔
6756
      pInfo->dTwaRes = pInfo->p.val;
584,770✔
6757
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
6,033,519✔
6758
      pInfo->dTwaRes = 0;
768✔
6759
    } else {
6760
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
6,032,751✔
6761
    }
6762

6763
    pResInfo->numOfRes = 1;
6,618,289✔
6764
  }
6765

6766
  return functionFinalize(pCtx, pBlock);
7,476,003✔
6767
}
6768

6769
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,882✔
6770
  if (pResultInfo->initialized) {
2,882✔
6771
    return TSDB_CODE_SUCCESS;
×
6772
  }
6773
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,882✔
6774
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6775
  }
6776

6777
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,882✔
6778
  pInfo->minRows = INT32_MAX;
2,882✔
6779
  return TSDB_CODE_SUCCESS;
2,882✔
6780
}
6781

6782
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
5,518✔
6783
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
5,518✔
6784

6785
  SInputColumnInfoData* pInput = &pCtx->input;
5,518✔
6786
  SColumnInfoData*      pInputCol = pInput->pData[0];
5,518✔
6787
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
5,518✔
6788
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,518✔
6789

6790
  STableBlockDistInfo p1 = {0};
5,518✔
6791
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
5,518✔
6792
    qError("failed to deserialize block dist info");
×
6793
    return TSDB_CODE_FAILED;
×
6794
  }
6795

6796
  pDistInfo->numOfBlocks += p1.numOfBlocks;
5,518✔
6797
  pDistInfo->numOfTables += p1.numOfTables;
5,518✔
6798
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
5,518✔
6799
  pDistInfo->numOfSttRows += p1.numOfSttRows;
5,518✔
6800
  pDistInfo->totalSize += p1.totalSize;
5,518✔
6801
  pDistInfo->totalRows += p1.totalRows;
5,518✔
6802
  pDistInfo->numOfFiles += p1.numOfFiles;
5,518✔
6803

6804
  pDistInfo->defMinRows = p1.defMinRows;
5,518✔
6805
  pDistInfo->defMaxRows = p1.defMaxRows;
5,518✔
6806
  pDistInfo->rowSize = p1.rowSize;
5,518✔
6807

6808
  if (pDistInfo->minRows > p1.minRows) {
5,518✔
6809
    pDistInfo->minRows = p1.minRows;
1,285✔
6810
  }
6811
  if (pDistInfo->maxRows < p1.maxRows) {
5,518✔
6812
    pDistInfo->maxRows = p1.maxRows;
1,285✔
6813
  }
6814
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
5,518✔
6815
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
115,878✔
6816
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
110,360✔
6817
  }
6818

6819
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
5,518✔
6820
  return TSDB_CODE_SUCCESS;
5,518✔
6821
}
6822

6823
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
11,014✔
6824
  SEncoder encoder = {0};
11,014✔
6825
  int32_t  code = 0;
11,036✔
6826
  int32_t  lino;
6827
  int32_t  tlen;
6828
  tEncoderInit(&encoder, buf, bufLen);
11,036✔
6829

6830
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
11,036✔
6831
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
22,050✔
6832

6833
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
22,050✔
6834
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
22,072✔
6835
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
21,865✔
6836

6837
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
21,821✔
6838
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
21,799✔
6839
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
21,658✔
6840
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
21,887✔
6841
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
22,050✔
6842
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
21,843✔
6843
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
21,865✔
6844
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
21,865✔
6845
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
21,658✔
6846

6847
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
225,189✔
6848
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
428,720✔
6849
  }
6850

6851
  tEndEncode(&encoder);
10,829✔
6852

6853
_exit:
10,851✔
6854
  if (code) {
10,851✔
6855
    tlen = code;
×
6856
  } else {
6857
    tlen = encoder.pos;
10,851✔
6858
  }
6859
  tEncoderClear(&encoder);
10,851✔
6860
  return tlen;
11,036✔
6861
}
6862

6863
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
5,518✔
6864
  SDecoder decoder = {0};
5,518✔
6865
  int32_t  code = 0;
5,518✔
6866
  int32_t  lino;
6867
  tDecoderInit(&decoder, buf, bufLen);
5,518✔
6868

6869
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
5,518✔
6870
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
11,036✔
6871

6872
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
11,036✔
6873
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
11,036✔
6874
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
11,036✔
6875

6876
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
11,036✔
6877
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
11,036✔
6878
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
11,036✔
6879
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
11,036✔
6880
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
11,036✔
6881
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
11,036✔
6882
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
11,036✔
6883
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
11,036✔
6884
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
11,036✔
6885

6886
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
115,878✔
6887
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
220,720✔
6888
  }
6889

6890
_exit:
5,518✔
6891
  tDecoderClear(&decoder);
5,518✔
6892
  return code;
5,518✔
6893
}
6894

6895
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,882✔
6896
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,882✔
6897
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
2,882✔
6898

6899
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
2,882✔
6900
  if (NULL == pColInfo) {
2,882✔
6901
    return TSDB_CODE_OUT_OF_RANGE;
×
6902
  }
6903

6904
  if (pData->totalRows == 0) {
2,882✔
6905
    pData->minRows = 0;
1,597✔
6906
  }
6907

6908
  int32_t row = 0;
2,882✔
6909
  char    st[256] = {0};
2,882✔
6910
  double  averageSize = 0;
2,882✔
6911
  if (pData->numOfBlocks != 0) {
2,882✔
6912
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1,285✔
6913
  }
6914
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
2,882✔
6915
  double   compRatio = 0;
2,882✔
6916
  if (totalRawSize != 0) {
2,882✔
6917
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1,285✔
6918
  }
6919

6920
  int32_t len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,882✔
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,882✔
6923

6924
  varDataSetLen(st, len);
2,882✔
6925
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
2,882✔
6926
  if (TSDB_CODE_SUCCESS != code) {
2,882✔
6927
    return code;
×
6928
  }
6929

6930
  int64_t avgRows = 0;
2,882✔
6931
  if (pData->numOfBlocks > 0) {
2,882✔
6932
    avgRows = pData->totalRows / pData->numOfBlocks;
1,285✔
6933
  }
6934

6935
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,882✔
6936
                 "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6937
                 pData->minRows, pData->maxRows, avgRows);
6938
  varDataSetLen(st, len);
2,882✔
6939
  code = colDataSetVal(pColInfo, row++, st, false);
2,882✔
6940
  if (TSDB_CODE_SUCCESS != code) {
2,882✔
6941
    return code;
×
6942
  }
6943

6944
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
2,882✔
6945
                 pData->numOfInmemRows, pData->numOfSttRows);
6946
  varDataSetLen(st, len);
2,882✔
6947
  code = colDataSetVal(pColInfo, row++, st, false);
2,882✔
6948
  if (TSDB_CODE_SUCCESS != code) {
2,882✔
6949
    return code;
×
6950
  }
6951

6952
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
5,764✔
6953
                 "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
2,882✔
6954
                 pData->numOfVgroups);
6955

6956
  varDataSetLen(st, len);
2,882✔
6957
  code = colDataSetVal(pColInfo, row++, st, false);
2,882✔
6958
  if (TSDB_CODE_SUCCESS != code) {
2,882✔
6959
    return code;
×
6960
  }
6961

6962
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,882✔
6963
                 "--------------------------------------------------------------------------------");
6964
  varDataSetLen(st, len);
2,882✔
6965
  code = colDataSetVal(pColInfo, row++, st, false);
2,882✔
6966
  if (TSDB_CODE_SUCCESS != code) {
2,882✔
6967
    return code;
×
6968
  }
6969

6970
  int32_t maxVal = 0;
2,882✔
6971
  int32_t minVal = INT32_MAX;
2,882✔
6972
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
60,522✔
6973
    if (maxVal < pData->blockRowsHisto[i]) {
57,640✔
6974
      maxVal = pData->blockRowsHisto[i];
1,851✔
6975
    }
6976

6977
    if (minVal > pData->blockRowsHisto[i]) {
57,640✔
6978
      minVal = pData->blockRowsHisto[i];
3,601✔
6979
    }
6980
  }
6981

6982
  // maximum number of step is 80
6983
  double factor = pData->numOfBlocks / 80.0;
2,882✔
6984

6985
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
2,882✔
6986
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
2,882✔
6987

6988
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
60,522✔
6989
    len =
6990
        snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
57,640✔
6991

6992
    int32_t num = 0;
57,640✔
6993
    if (pData->blockRowsHisto[i] > 0) {
57,640✔
6994
      num = (pData->blockRowsHisto[i]) / factor;
2,983✔
6995
    }
6996

6997
    for (int32_t j = 0; j < num; ++j) {
159,874✔
6998
      int32_t x = snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
102,234✔
6999
      len += x;
102,234✔
7000
    }
7001

7002
    if (pData->blockRowsHisto[i] > 0) {
57,640✔
7003
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
2,983✔
7004
      len += snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
2,983✔
7005
                      pData->blockRowsHisto[i], v, '%');
7006
    }
7007

7008
    varDataSetLen(st, len);
57,640✔
7009
    code = colDataSetVal(pColInfo, row++, st, false);
57,640✔
7010
    if (TSDB_CODE_SUCCESS != code) {
57,640✔
7011
      return code;
×
7012
    }
7013
  }
7014

7015
  return TSDB_CODE_SUCCESS;
2,882✔
7016
}
7017
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
359✔
7018
  if (pResultInfo->initialized) {
359✔
7019
    return TSDB_CODE_SUCCESS;
×
7020
  }
7021
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
359✔
7022
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7023
  }
7024

7025
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
359✔
7026
  return TSDB_CODE_SUCCESS;
359✔
7027
}
7028
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
718✔
7029
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
718✔
7030

7031
  SInputColumnInfoData* pInput = &pCtx->input;
718✔
7032
  SColumnInfoData*      pInputCol = pInput->pData[0];
718✔
7033
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
718✔
7034
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
718✔
7035

7036
  SDBBlockUsageInfo p1 = {0};
718✔
7037
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
718✔
7038
    qError("failed to deserialize block dist info");
×
7039
    return TSDB_CODE_FAILED;
×
7040
  }
7041

7042
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
718✔
7043
  pDistInfo->walInDiskSize += p1.walInDiskSize;
718✔
7044
  pDistInfo->rawDataSize += p1.rawDataSize;
718✔
7045
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
718✔
7046
  return TSDB_CODE_SUCCESS;
718✔
7047
}
7048

7049
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
1,436✔
7050
  SEncoder encoder = {0};
1,436✔
7051
  int32_t  code = 0;
1,436✔
7052
  int32_t  lino;
7053
  int32_t  tlen;
7054
  tEncoderInit(&encoder, buf, bufLen);
1,436✔
7055

7056
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
1,436✔
7057

7058
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
2,872✔
7059
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
2,872✔
7060
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
2,872✔
7061

7062
  tEndEncode(&encoder);
1,436✔
7063

7064
_exit:
1,436✔
7065
  if (code) {
1,436✔
7066
    tlen = code;
×
7067
  } else {
7068
    tlen = encoder.pos;
1,436✔
7069
  }
7070
  tEncoderClear(&encoder);
1,436✔
7071
  return tlen;
1,436✔
7072
}
7073
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
718✔
7074
  SDecoder decoder = {0};
718✔
7075
  int32_t  code = 0;
718✔
7076
  int32_t  lino;
7077
  tDecoderInit(&decoder, buf, bufLen);
718✔
7078

7079
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
718✔
7080
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
1,436✔
7081
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
1,436✔
7082
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
1,436✔
7083

7084
_exit:
718✔
7085
  tDecoderClear(&decoder);
718✔
7086
  return code;
718✔
7087
}
7088
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
359✔
7089
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
359✔
7090
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
359✔
7091

7092
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
359✔
7093
  if (NULL == pColInfo) {
359✔
7094
    return TSDB_CODE_OUT_OF_RANGE;
×
7095
  }
7096
  int32_t len = 0;
359✔
7097
  int32_t row = 0;
359✔
7098
  char    st[256] = {0};
359✔
7099

7100
  uint64_t totalDiskSize = pData->dataInDiskSize;
359✔
7101
  uint64_t rawDataSize = pData->rawDataSize;
359✔
7102
  double   compressRatio = 0;
359✔
7103
  if (rawDataSize != 0) {
359✔
7104
    compressRatio = totalDiskSize * 100 / (double)rawDataSize;
186✔
7105
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[%.2f%]", compressRatio);
186✔
7106
  } else {
7107
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[NULL]");
173✔
7108
  }
7109

7110
  varDataSetLen(st, len);
359✔
7111
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
359✔
7112
  if (TSDB_CODE_SUCCESS != code) {
359✔
7113
    return code;
×
7114
  }
7115

7116
  len =
7117
      snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
359✔
7118
  varDataSetLen(st, len);
359✔
7119
  code = colDataSetVal(pColInfo, row++, st, false);
359✔
7120
  if (TSDB_CODE_SUCCESS != code) {
359✔
7121
    return code;
×
7122
  }
7123
  return code;
359✔
7124
}
7125

7126
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
205,927✔
7127
  pEnv->calcMemSize = sizeof(SDerivInfo);
205,927✔
7128
  return true;
205,927✔
7129
}
7130

7131
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
897,236✔
7132
  if (pResInfo->initialized) {
897,236✔
7133
    return TSDB_CODE_SUCCESS;
659,529✔
7134
  }
7135
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
237,707✔
7136
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7137
  }
7138

7139
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
237,707✔
7140

7141
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
237,707✔
7142
  pDerivInfo->prevTs = -1;
237,707✔
7143
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
237,707✔
7144
  pDerivInfo->valueSet = false;
237,707✔
7145
  return TSDB_CODE_SUCCESS;
237,707✔
7146
}
7147

7148
int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
691,309✔
7149

7150
static int32_t DoDerivativeFunction(SqlFunctionCtx* pCtx) {
691,309✔
7151
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
691,309✔
7152
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
691,309✔
7153

7154
  SInputColumnInfoData* pInput = &pCtx->input;
691,309✔
7155
  SColumnInfoData*      pInputCol = pInput->pData[0];
691,309✔
7156

7157
  int32_t          numOfElems = 0;
691,309✔
7158
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
691,309✔
7159
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
691,309✔
7160
  int32_t          code = TSDB_CODE_SUCCESS;
691,309✔
7161

7162
  funcInputUpdate(pCtx);
691,309✔
7163

7164
  double v = 0;
691,309✔
7165
  if (pCtx->order == TSDB_ORDER_ASC) {
691,309✔
7166
    SFuncInputRow row = {0};
689,739✔
7167
    bool          result = false;
689,739✔
7168
    while (1) {
125,091,346✔
7169
      code = funcInputGetNextRow(pCtx, &row, &result);
125,781,085✔
7170
      if (TSDB_CODE_SUCCESS != code) {
125,781,085✔
7171
        return code;
×
7172
      }
7173
      if (!result) {
125,781,085✔
7174
        break;
689,739✔
7175
      }
7176
      if (row.isDataNull) {
125,091,346✔
7177
        continue;
3,670,732✔
7178
      }
7179

7180
      char* d = row.pData;
121,420,614✔
7181
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
121,420,614✔
7182

7183
      int32_t pos = pCtx->offset + numOfElems;
121,420,614✔
7184
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
121,420,614✔
7185
        pDerivInfo->valueSet = true;
200,937✔
7186
      } else {
7187
        if (row.ts == pDerivInfo->prevTs) {
121,219,677✔
7188
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7189
        }
7190
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
121,219,677✔
7191
        if (pDerivInfo->ignoreNegative && r < 0) {
121,219,677✔
7192
        } else {
7193
          if (isinf(r) || isnan(r)) {
110,885,913✔
7194
            colDataSetNULL(pOutput, pos);
×
7195
          } else {
7196
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
110,885,913✔
7197
            if (code != TSDB_CODE_SUCCESS) {
110,885,913✔
7198
              return code;
×
7199
            }
7200
          }
7201

7202
          if (pTsOutput != NULL) {
110,885,913✔
7203
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
7204
          }
7205

7206
          // handle selectivity
7207
          if (pCtx->subsidiaries.num > 0) {
110,885,913✔
7208
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
2,034,456✔
7209
            if (code != TSDB_CODE_SUCCESS) {
2,034,456✔
7210
              return code;
×
7211
            }
7212
          }
7213

7214
          numOfElems++;
110,885,913✔
7215
        }
7216
      }
7217

7218
      pDerivInfo->prevValue = v;
121,420,614✔
7219
      pDerivInfo->prevTs = row.ts;
121,420,614✔
7220
    }
7221
  } else {
7222
    SFuncInputRow row = {0};
1,570✔
7223
    bool          result = false;
1,570✔
7224
    while (1) {
12,356✔
7225
      code = funcInputGetNextRow(pCtx, &row, &result);
13,926✔
7226
      if (TSDB_CODE_SUCCESS != code) {
13,926✔
7227
        return code;
×
7228
      }
7229
      if (!result) {
13,926✔
7230
        break;
1,570✔
7231
      }
7232
      if (row.isDataNull) {
12,356✔
7233
        continue;
10,240✔
7234
      }
7235

7236
      char* d = row.pData;
2,116✔
7237
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
2,116✔
7238

7239
      int32_t pos = pCtx->offset + numOfElems;
2,116✔
7240
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
2,116✔
7241
        pDerivInfo->valueSet = true;
1,058✔
7242
      } else {
7243
        if (row.ts == pDerivInfo->prevTs) {
1,058✔
7244
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7245
        }
7246
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
1,058✔
7247
        if (pDerivInfo->ignoreNegative && r < 0) {
1,058✔
7248
        } else {
7249
          if (isinf(r) || isnan(r)) {
1,058✔
7250
            colDataSetNULL(pOutput, pos);
×
7251
          } else {
7252
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
1,058✔
7253
            if (code != TSDB_CODE_SUCCESS) {
1,058✔
7254
              return code;
×
7255
            }
7256
          }
7257

7258
          if (pTsOutput != NULL) {
1,058✔
7259
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
7260
          }
7261

7262
          // handle selectivity
7263
          if (pCtx->subsidiaries.num > 0) {
1,058✔
7264
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
×
7265
            if (code != TSDB_CODE_SUCCESS) {
×
7266
              return code;
×
7267
            }
7268
          }
7269
          numOfElems++;
1,058✔
7270
        }
7271
      }
7272

7273
      pDerivInfo->prevValue = v;
2,116✔
7274
      pDerivInfo->prevTs = row.ts;
2,116✔
7275
    }
7276
  }
7277

7278
  pResInfo->numOfRes = numOfElems;
691,309✔
7279

7280
  return TSDB_CODE_SUCCESS;
691,309✔
7281
}
7282

7283
int32_t derivativeFunctionByRow(SArray* pCtxArray) {
691,309✔
7284
  for (int32_t i = 0; i < taosArrayGetSize(pCtxArray); ++i) {
1,382,618✔
7285
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
691,309✔
7286
    int32_t         code = DoDerivativeFunction(pCtx);
691,309✔
7287
    if (code != TSDB_CODE_SUCCESS) {
691,309✔
7288
      return code;
×
7289
    }
7290
  }
7291
  return TSDB_CODE_SUCCESS;
691,309✔
7292
}
7293

7294
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
242,763✔
7295

7296
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
199,938✔
7297
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
199,938✔
7298
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
201,429✔
7299
  return true;
200,992✔
7300
}
7301

7302
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,699,891✔
7303
  if (pResInfo->initialized) {
1,699,891✔
7304
    return TSDB_CODE_SUCCESS;
×
7305
  }
7306
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
1,699,891✔
7307
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7308
  }
7309

7310
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,699,891✔
7311

7312
  pInfo->firstKey = INT64_MIN;
1,699,891✔
7313
  pInfo->lastKey = INT64_MIN;
1,699,891✔
7314
  pInfo->firstValue = (double)INT64_MIN;
1,699,891✔
7315
  pInfo->lastValue = (double)INT64_MIN;
1,699,891✔
7316

7317
  pInfo->hasResult = 0;
1,699,891✔
7318
  return TSDB_CODE_SUCCESS;
1,699,891✔
7319
}
7320

7321
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
298,458,186✔
7322
  if (isFirst) {
298,458,186✔
7323
    pRateInfo->firstValue = v;
148,883,806✔
7324
    pRateInfo->firstKey = ts;
148,884,318✔
7325
    if (pRateInfo->firstPk) {
148,883,806✔
7326
      int32_t pkBytes;
7327
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
23,940✔
7328
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
5,472✔
7329
      } else {
7330
        pkBytes = pRateInfo->pkBytes;
18,468✔
7331
      }
7332
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
23,940✔
7333
    }
7334
  } else {
7335
    pRateInfo->lastValue = v;
149,574,380✔
7336
    pRateInfo->lastKey = ts;
149,583,084✔
7337
    if (pRateInfo->lastPk) {
149,583,084✔
7338
      int32_t pkBytes;
7339
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
35,568✔
7340
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
8,208✔
7341
      } else {
7342
        pkBytes = pRateInfo->pkBytes;
27,360✔
7343
      }
7344
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
35,568✔
7345
    }
7346
  }
7347
}
298,465,866✔
7348

7349
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
1,901,239✔
7350
  if (pCtx->hasPrimaryKey) {
1,901,239✔
7351
    if (!isMerge) {
12,996✔
7352
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
11,628✔
7353
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
11,628✔
7354
      pRateInfo->firstPk = pRateInfo->pkData;
11,628✔
7355
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
11,628✔
7356
    } else {
7357
      pRateInfo->firstPk = pRateInfo->pkData;
1,368✔
7358
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,368✔
7359
    }
7360
  } else {
7361
    pRateInfo->firstPk = NULL;
1,888,243✔
7362
    pRateInfo->lastPk = NULL;
1,888,243✔
7363
  }
7364
}
1,901,239✔
7365

7366
int32_t irateFunction(SqlFunctionCtx* pCtx) {
1,841,421✔
7367
  int32_t              code = TSDB_CODE_SUCCESS;
1,841,421✔
7368
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,841,421✔
7369
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,841,421✔
7370

7371
  SInputColumnInfoData* pInput = &pCtx->input;
1,841,421✔
7372
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,841,421✔
7373

7374
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,841,421✔
7375

7376
  funcInputUpdate(pCtx);
1,841,421✔
7377

7378
  initializeRateInfo(pCtx, pRateInfo, false);
1,840,909✔
7379

7380
  int32_t       numOfElems = 0;
1,840,487✔
7381
  int32_t       type = pInputCol->info.type;
1,840,487✔
7382
  SFuncInputRow row = {0};
1,840,487✔
7383
  bool          result = false;
1,840,487✔
7384
  while (1) {
199,796,526✔
7385
    code = funcInputGetNextRow(pCtx, &row, &result);
201,637,013✔
7386
    if (TSDB_CODE_SUCCESS != code) {
201,645,627✔
7387
      return code;
×
7388
    }
7389
    if (!result) {
201,645,627✔
7390
      break;
1,841,421✔
7391
    }
7392
    if (row.isDataNull) {
199,804,206✔
7393
      continue;
9,247,853✔
7394
    }
7395

7396
    char*  data = row.pData;
190,556,353✔
7397
    double v = 0;
190,556,353✔
7398
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
190,556,353✔
7399

7400
    if (INT64_MIN == pRateInfo->lastKey) {
190,556,353✔
7401
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
704,098✔
7402
      pRateInfo->hasResult = 1;
704,098✔
7403
      continue;
704,098✔
7404
    }
7405

7406
    if (row.ts > pRateInfo->lastKey) {
189,851,743✔
7407
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
148,852,665✔
7408
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
148,852,665✔
7409
      }
7410
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
148,849,081✔
7411
      continue;
148,846,521✔
7412
    } else if (row.ts == pRateInfo->lastKey) {
40,999,590✔
7413
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7414
    }
7415

7416
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
40,999,590✔
7417
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
×
7418
    } else if (row.ts == pRateInfo->firstKey) {
40,999,590✔
7419
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7420
    }
7421
  }
7422

7423
  numOfElems++;
1,841,421✔
7424

7425
  SET_VAL(pResInfo, numOfElems, 1);
1,841,421✔
7426
  return TSDB_CODE_SUCCESS;
1,841,421✔
7427
}
7428

7429
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
1,669,515✔
7430
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
1,669,515✔
7431
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
145,580✔
7432
    return 0.0;
1,523,935✔
7433
  }
7434

7435
  double diff = 0;
145,580✔
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;
145,580✔
7439
  if (diff >= pRateInfo->firstValue) {
145,580✔
7440
    diff -= pRateInfo->firstValue;
87,731✔
7441
  }
7442

7443
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
145,580✔
7444
  if (duration == 0) {
145,580✔
7445
    return 0;
×
7446
  }
7447

7448
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
145,580✔
7449
}
7450

7451
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
25,046✔
7452
  if (inputKey > pOutput->lastKey) {
25,046✔
7453
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
14,558✔
7454
    if (isFirstKey) {
14,558✔
7455
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
6,405✔
7456
    } else {
7457
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
8,153✔
7458
    }
7459
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
10,488✔
7460
    if (isFirstKey) {
1,748✔
7461
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
874✔
7462
    } else {
7463
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
874✔
7464
    }
7465
  } else {
7466
    // inputKey < pOutput->firstKey
7467
  }
7468
}
25,046✔
7469

7470
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
15,859✔
7471
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
15,859✔
7472
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
15,859✔
7473
}
15,859✔
7474

7475
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
28,382✔
7476
  if ((pInput->firstKey != INT64_MIN &&
28,382✔
7477
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
25,730✔
7478
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
28,382✔
7479
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7480
  }
7481

7482
  if (pOutput->hasResult == 0) {
28,382✔
7483
    irateCopyInfo(pInput, pOutput);
15,859✔
7484
    pOutput->hasResult = pInput->hasResult;
15,859✔
7485
    return TSDB_CODE_SUCCESS;
15,859✔
7486
  }
7487

7488
  if (pInput->firstKey != INT64_MIN) {
12,523✔
7489
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
12,523✔
7490
  }
7491

7492
  if (pInput->lastKey != INT64_MIN) {
12,523✔
7493
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
12,523✔
7494
  }
7495

7496
  pOutput->hasResult = pInput->hasResult;
12,523✔
7497
  return TSDB_CODE_SUCCESS;
12,523✔
7498
}
7499

7500
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
30,376✔
7501
  SInputColumnInfoData* pInput = &pCtx->input;
30,376✔
7502
  SColumnInfoData*      pCol = pInput->pData[0];
30,376✔
7503
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
30,376✔
7504
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7505
  }
7506

7507
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
30,376✔
7508
  initializeRateInfo(pCtx, pInfo, true);
30,376✔
7509

7510
  int32_t start = pInput->startRowIndex;
30,376✔
7511
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
60,752✔
7512
    char*      data = colDataGetData(pCol, i);
30,376✔
7513
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
30,376✔
7514
    initializeRateInfo(pCtx, pInfo, true);
30,376✔
7515
    if (pInputInfo->hasResult) {
30,376✔
7516
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
28,382✔
7517
      if (code != TSDB_CODE_SUCCESS) {
28,382✔
7518
        return code;
×
7519
      }
7520
    }
7521
  }
7522

7523
  if (pInfo->hasResult) {
30,376✔
7524
    GET_RES_INFO(pCtx)->numOfRes = 1;
28,382✔
7525
  }
7526

7527
  return TSDB_CODE_SUCCESS;
30,376✔
7528
}
7529

7530
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
30,376✔
7531
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
30,376✔
7532
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
30,376✔
7533
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
30,376✔
7534
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
30,376✔
7535

7536
  if (NULL == res) {
30,376✔
7537
    return terrno;
×
7538
  }
7539
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
30,376✔
7540
  varDataSetLen(res, resultBytes);
30,376✔
7541

7542
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
30,376✔
7543
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
30,376✔
7544
  if (NULL == pCol) {
30,376✔
7545
    taosMemoryFree(res);
×
7546
    return TSDB_CODE_OUT_OF_RANGE;
×
7547
  }
7548

7549
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
30,376✔
7550

7551
  taosMemoryFree(res);
30,376✔
7552
  return code;
30,376✔
7553
}
7554

7555
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,669,515✔
7556
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,669,515✔
7557
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,669,515✔
7558
  if (NULL == pCol) {
1,669,515✔
7559
    return TSDB_CODE_OUT_OF_RANGE;
×
7560
  }
7561

7562
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,669,515✔
7563
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
1,669,515✔
7564

7565
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,669,515✔
7566
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
1,669,515✔
7567
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
1,669,515✔
7568

7569
  return code;
1,669,515✔
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)) {
416,782,107✔
7602
        valueRowIndex = pInput->startRowIndex;
206,119,361✔
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;
512,936,329✔
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) {
419,224✔
7693
  int32_t numOfElems = 0;
419,224✔
7694

7695
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
419,224✔
7696
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
419,224✔
7697

7698
  SInputColumnInfoData* pInput = &pCtx->input;
419,224✔
7699
  SColumnInfoData*      pInputCol = pInput->pData[0];
419,224✔
7700

7701
  int32_t bytes = pInputCol->info.bytes;
419,224✔
7702
  pInfo->bytes = bytes;
419,224✔
7703

7704
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
419,224✔
7705
  pInfo->pkType = -1;
419,224✔
7706
  __compar_fn_t pkCompareFn = NULL;
419,224✔
7707
  if (pCtx->hasPrimaryKey) {
419,224✔
7708
    pInfo->pkType = pkCol->info.type;
15,876✔
7709
    pInfo->pkBytes = pkCol->info.bytes;
15,876✔
7710
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
15,876✔
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) {
898,596✔
7715
    numOfElems++;
479,372✔
7716

7717
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
479,372✔
7718
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
479,372✔
7719

7720
    TSKEY cts = getRowPTs(pInput->pPTS, i);
479,372✔
7721
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
478,940✔
7722
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
370,713✔
7723
      if (code != TSDB_CODE_SUCCESS) {
370,713✔
7724
        return code;
×
7725
      }
7726
      pResInfo->numOfRes = 1;
370,713✔
7727
    }
7728
  }
7729

7730
  SET_VAL(pResInfo, numOfElems, 1);
419,224✔
7731
  return TSDB_CODE_SUCCESS;
419,656✔
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,524,972✔
7924
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,524,972✔
7925
  bool* pRes = GET_ROWCELL_INTERBUF(pResInfo);
16,524,972✔
7926
  if (*pRes) {
16,524,972✔
7927
    return TSDB_CODE_SUCCESS;
×
7928
  }
7929

7930
  SInputColumnInfoData* pInput = &pCtx->input;
16,524,972✔
7931
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
16,524,972✔
7932
  SColumnInfoData* pCol = pInput->pData[0];
16,524,972✔
7933

7934
  if (pInput->numOfRows > 0) {
16,524,972✔
7935
    pResInfo->numOfRes = 1;
16,524,972✔
7936
  }
7937

7938
  if (IS_NULL_TYPE(pCol->info.type) && pInput->numOfRows > 0) {
16,524,972✔
7939
    *pRes = true;
×
7940
    return TSDB_CODE_SUCCESS;
×
7941
  }
7942

7943
  if (pInput->colDataSMAIsSet) {
16,524,972✔
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,524,972✔
7955
  int32_t end = start + pInput->numOfRows;
16,524,972✔
7956

7957
  if (pCol->hasNull) {
16,524,972✔
7958
    for (int32_t i = start; i < end; ++i) {
39,353,400✔
7959
      if (colDataIsNull_s(pCol, i)) {
66,734,960✔
7960
        *pRes = true;
10,449,246✔
7961
        break;
10,449,246✔
7962
      }
7963
    }
7964
  }  
7965

7966
  return TSDB_CODE_SUCCESS;
16,524,972✔
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