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

taosdata / TDengine / #5009

29 Mar 2026 04:32AM UTC coverage: 72.26% (+0.02%) from 72.241%
#5009

push

travis-ci

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

253662 of 351039 relevant lines covered (72.26%)

131649114.75 hits per line

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

77.66
/source/libs/function/src/builtinsimpl.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "builtinsimpl.h"
17
#include "cJSON.h"
18
#include "decimal.h"
19
#include "function.h"
20
#include "functionResInfoInt.h"
21
#include "query.h"
22
#include "querynodes.h"
23
#include "tanalytics.h"
24
#include "tarray.h"
25
#include "tcompare.h"
26
#include "tdatablock.h"
27
#include "tdigest.h"
28
#include "tfunctionInt.h"
29
#include "tglobal.h"
30
#include "thistogram.h"
31
#include "tpercentile.h"
32
#include "ttypes.h"
33

34
bool ignoreNegative(int8_t ignoreOption) { return (ignoreOption & 0x1) == 0x1; }
2,147,483,647✔
35
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
45,749,606✔
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,228,609✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
56,228,609✔
199

200
  if (!pCtx->bInputFinished) {
56,228,609✔
201
    pIter->pInput = &pCtx->input;
56,228,609✔
202
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
56,228,609✔
203
    pIter->pDataCol = pIter->pInput->pData[0];
56,228,609✔
204
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
56,228,609✔
205
    pIter->rowIndex = pIter->pInput->startRowIndex;
56,228,609✔
206
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
56,228,609✔
207
    pIter->pSrcBlock = pCtx->pSrcBlock;
56,228,609✔
208
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
56,228,609✔
209
      pIter->hasGroupId = true;
6,848,071✔
210
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
6,848,071✔
211
      pIter->hasPrev = false;
6,848,071✔
212
    }
213
  } else {
214
    pIter->finalRow = true;
×
215
  }
216
}
56,228,609✔
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,567,636✔
333
  int32_t idx = rowIndex + 1;
3,567,636✔
334
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
50,231,674✔
335
    ++idx;
46,664,038✔
336
  }
337
  pIter->rowIndex = idx;
3,567,636✔
338
}
3,567,636✔
339

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

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

361
      pIter->hasPrev = false;
322,596✔
362
      setInputRowInfo(pRow, pIter, idx, true);
322,596✔
363
      forwardToNextDiffTsRow(pIter, idx);
322,596✔
364
      return true;
322,596✔
365
    }
366
  } else {
367
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,317,774✔
368
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
3,781,848✔
369

370
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,781,848✔
371
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
3,781,848✔
372
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
3,245,040✔
373
      } else {
374
        pIter->rowIndex = pIter->inputEndIndex + 1;
536,808✔
375
      }
376
      return true;
3,781,848✔
377
    } else {
378
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
535,926✔
379
      pIter->hasPrev = true;
535,926✔
380
      pIter->prevBlockTsEnd = tsEnd;
535,926✔
381
      return false;
535,926✔
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,384,626✔
393
  }
394
}
395

396
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
2,147,483,647✔
397
  SFuncInputRowIter* pIter = &pCtx->rowIter;
2,147,483,647✔
398
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
399
    if (pCtx->order == TSDB_ORDER_DESC) {
4,640,370✔
400
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
401
      return TSDB_CODE_SUCCESS;
402
    } else {
403
      *res = funcInputGetNextRowAscPk(pIter, pRow);
4,640,370✔
404
    }
405
  } else {
406
    *res = funcInputGetNextRowNoPk(pIter, pRow);
2,147,483,647✔
407
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
408
  }
409
  return TSDB_CODE_SUCCESS;
4,640,370✔
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,201✔
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,973,471✔
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) {
84,188✔
502
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
84,188✔
503
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
84,188✔
504
  if (NULL == pCol) {
84,188✔
505
    return TSDB_CODE_OUT_OF_RANGE;
×
506
  }
507
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
84,188✔
508
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
84,188✔
509

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

513
  return code;
84,188✔
514
}
515

516
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
15,365,663✔
517
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
15,365,663✔
518
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
15,366,452✔
519
    return FUNC_DATA_REQUIRED_NOT_LOAD;
11,338,786✔
520
  }
521
  return FUNC_DATA_REQUIRED_SMA_LOAD;
4,027,666✔
522
}
523

524
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
55,977,669✔
525
  pEnv->calcMemSize = sizeof(int64_t);
55,977,669✔
526
  return true;
55,984,421✔
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,046,378✔
541
  }
542
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
2,147,483,647✔
543
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
831,557✔
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,825,032,732✔
578
    val += 0;
1,825,032,732✔
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);
9,067,081✔
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,288,744,457✔
620
    goto _sum_over;
1,288,744,457✔
621
  }
622

623
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
624
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
33,071,155✔
625

626
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
33,070,537✔
627
      SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
16,798,340✔
628
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
16,272,197✔
629
      SUM_RES_INC_USUM(pSumRes, pAgg->sum);
16,266,474✔
630
    } else if (IS_FLOAT_TYPE(type)) {
5,723✔
631
      SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
×
632
    } else if (IS_DECIMAL_TYPE(type)) {
8,195✔
633
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
8,195✔
634
      const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
8,195✔
635
      if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
14,900✔
636
                                                       &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
6,705✔
637
        return TSDB_CODE_DECIMAL_OVERFLOW;
1,490✔
638
      }
639
      pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
6,705✔
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);
727,569,366✔
650
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
2,147,483,647✔
651
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
510,134,541✔
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,227,478,609✔
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);
450,062,165✔
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) {
3,857,750✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
374,923,855✔
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
2,033,257✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
375,594,209✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
186,334,928✔
668
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
470,179,581✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
128,852,698✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
352,523,345✔
671
    } else if (IS_DECIMAL_TYPE(type)) {
46,783✔
672
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
46,783✔
673
      int32_t overflow = false;
22,350✔
674
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
22,350✔
675
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
5,965,960✔
676
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
16,390✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
11,940,860✔
678
      }
679
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
22,350✔
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)) {
84,111,631✔
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) {
29,942,603✔
725
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
29,942,603✔
726
  return true;
29,946,077✔
727
}
728

729
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
25,113,386✔
730
  SNode* pParam;
731
  switch (pFunc->funcType) {
25,113,386✔
732
    case FUNCTION_TYPE_MAX:
25,113,411✔
733
    case FUNCTION_TYPE_MIN:
734
    case FUNCTION_TYPE_SUM:
735
    case FUNCTION_TYPE_AVG:
736
    case FUNCTION_TYPE_AVG_PARTIAL:
737
    case FUNCTION_TYPE_PERCENTILE:
738
    case FUNCTION_TYPE_SPREAD:
739
    case FUNCTION_TYPE_SPREAD_PARTIAL:
740
    case FUNCTION_TYPE_SPREAD_MERGE:
741
    case FUNCTION_TYPE_TWA:
742
    case FUNCTION_TYPE_ELAPSED:
743
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
25,113,411✔
744
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
25,116,816✔
745
        return true;
1,476,022✔
746
      }
747
      break;
23,638,650✔
748
    default:
44✔
749
      break;
44✔
750
  }
751
  return false;
23,638,625✔
752
}
753

754
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
25,111,920✔
755
  if (funcNotSupportStringSma(pFunc)) {
25,111,920✔
756
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,476,022✔
757
  }
758
  return FUNC_DATA_REQUIRED_SMA_LOAD;
23,639,591✔
759
}
760

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

769
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
2,147,483,647✔
770
  buf->assign = false;
2,147,483,647✔
771
  buf->tuplePos.pageId = -1;
2,147,483,647✔
772

773
  buf->nullTupleSaved = false;
2,147,483,647✔
774
  buf->nullTuplePos.pageId = -1;
2,147,483,647✔
775
  buf->str = NULL;
2,147,483,647✔
776
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
777
}
778

779
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
46,006,330✔
780
  COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
781
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
46,006,330✔
782
  return true;
46,007,619✔
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,147,483,647✔
810
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
811

812
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
813
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2,147,483,647✔
814

815
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
816
  int32_t currentRow = pBlock->info.rows;
2,147,483,647✔
817

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

824
  // NOTE: do nothing change it, for performance issue
825
  if (!pEntryInfo->isNullRes) {
2,147,483,647✔
826
    switch (pCol->info.type) {
1,710,587,984✔
827
      case TSDB_DATA_TYPE_UBIGINT:
137,548,780✔
828
      case TSDB_DATA_TYPE_BIGINT:
829
      case TSDB_DATA_TYPE_TIMESTAMP:
830
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
137,548,780✔
831
        break;
137,547,630✔
832
      case TSDB_DATA_TYPE_UINT:
1,471,090,638✔
833
      case TSDB_DATA_TYPE_INT:
834
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
1,471,090,638✔
835
        break;
1,471,161,186✔
836
      case TSDB_DATA_TYPE_USMALLINT:
14,458,267✔
837
      case TSDB_DATA_TYPE_SMALLINT:
838
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
14,458,267✔
839
        break;
14,458,267✔
840
      case TSDB_DATA_TYPE_BOOL:
31,900,589✔
841
      case TSDB_DATA_TYPE_UTINYINT:
842
      case TSDB_DATA_TYPE_TINYINT:
843
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
31,900,589✔
844
        break;
31,900,589✔
845
      case TSDB_DATA_TYPE_DOUBLE:
28,527,472✔
846
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
28,527,472✔
847
        break;
28,527,472✔
848
      case TSDB_DATA_TYPE_FLOAT: {
21,617,420✔
849
        float v = GET_FLOAT_VAL(&pRes->v);
21,617,420✔
850
        colDataSetFloat(pCol, currentRow, &v);
21,617,420✔
851
        break;
21,617,420✔
852
      }
853
      case TSDB_DATA_TYPE_VARBINARY:
4,696,494✔
854
      case TSDB_DATA_TYPE_VARCHAR:
855
      case TSDB_DATA_TYPE_NCHAR: {
856
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
4,696,494✔
857
        if (TSDB_CODE_SUCCESS != code) {
4,696,055✔
858
          return code;
×
859
        }
860
        break;
4,696,055✔
861
      }
862
      case TSDB_DATA_TYPE_DECIMAL64:
645,956✔
863
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
645,956✔
864
        break;
645,956✔
865
      case TSDB_DATA_TYPE_DECIMAL:
31,031✔
866
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
31,031✔
867
        break;
31,031✔
868
    }
869
  } else {
870
    colDataSetNULL(pCol, currentRow);
448,008,853✔
871
  }
872

873
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
2,147,483,647✔
874
  if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
875
    if (pEntryInfo->numOfRes > 0) {
2,212,092✔
876
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
2,003,204✔
877
    } else {
878
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
208,888✔
879
    }
880
  }
881

882
  return code;
2,147,483,647✔
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) {
714,082✔
891
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
429,662✔
892
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
429,662✔
893

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

901
  return TSDB_CODE_SUCCESS;
284,420✔
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) ||
83,841,014✔
910
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
911
    int32_t numOfCols = pCtx->subsidiaries.num;
83,841,007✔
912
    char*   p = NULL;
83,841,632✔
913
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
83,841,446✔
914
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
83,841,632✔
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;
83,841,632✔
921
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
83,841,632✔
922

923
    // todo set the offset value to optimize the performance.
924
    for (int32_t j = 0; j < numOfCols; ++j) {
273,719,594✔
925
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
189,877,962✔
926
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
189,877,523✔
927

928
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
189,877,291✔
929
      if (NULL == pDstCol) {
189,877,962✔
930
        return terrno;
×
931
      }
932
      if (nullList[j]) {
189,877,962✔
933
        colDataSetNULL(pDstCol, rowIndex);
62,584,964✔
934
      } else {
935
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
127,292,998✔
936
        if (TSDB_CODE_SUCCESS != code) {
127,292,998✔
937
          return code;
×
938
        }
939
      }
940
      pStart += pDstCol->info.bytes;
189,877,962✔
941
    }
942
  }
943

944
  return TSDB_CODE_SUCCESS;
83,842,064✔
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,017,248✔
950
  if (pCtx->subsidiaries.num <= 0) {
1,017,248✔
951
    return TSDB_CODE_SUCCESS;
×
952
  }
953

954
  int32_t code = TSDB_CODE_SUCCESS;
1,017,248✔
955
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,302,684✔
956
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
1,285,436✔
957

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

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

967
    char* pData = colDataGetData(pSrcCol, rowIndex);
1,285,436✔
968

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

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

977
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,570,872✔
978
      colDataSetNULL(pDstCol, pos);
53,184✔
979
    } else {
980
      code = colDataSetVal(pDstCol, pos, pData, false);
1,232,252✔
981
      if (TSDB_CODE_SUCCESS != code) {
1,232,252✔
982
        return code;
×
983
      }
984
    }
985
  }
986
  return code;
1,017,248✔
987
}
988

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

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

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

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

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

1082
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
17,603,069✔
1083

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

1089
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
616,096,734✔
1090
  if (pResultInfo->initialized) {
616,096,734✔
1091
    return TSDB_CODE_SUCCESS;
×
1092
  }
1093
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
616,098,774✔
1094
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1095
  }
1096

1097
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
616,102,927✔
1098
  (void)memset(pRes, 0, sizeof(SStdRes));
616,100,996✔
1099
  return TSDB_CODE_SUCCESS;
616,100,996✔
1100
}
1101

1102
int32_t stdFunction(SqlFunctionCtx* pCtx) {
1,139,796,979✔
1103
  int32_t numOfElem = 0;
1,139,796,979✔
1104

1105
  // Only the pre-computing information loaded and actual data does not loaded
1106
  SInputColumnInfoData* pInput = &pCtx->input;
1,139,796,979✔
1107
  int32_t               type = pInput->pData[0]->info.type;
1,139,802,795✔
1108

1109
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,139,807,253✔
1110
  pStdRes->type = type;
1,139,810,561✔
1111

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

1115
  int32_t start = pInput->startRowIndex;
1,139,804,623✔
1116
  int32_t numOfRows = pInput->numOfRows;
1,139,768,196✔
1117

1118
  if (IS_NULL_TYPE(type)) {
1,139,804,523✔
1119
    numOfElem = 0;
170,197,400✔
1120
    goto _stddev_over;
170,197,400✔
1121
  }
1122

1123
  switch (type) {
969,607,123✔
1124
    case TSDB_DATA_TYPE_TINYINT: {
14,450,802✔
1125
      int8_t* plist = (int8_t*)pCol->pData;
14,450,802✔
1126
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,095,374,714✔
1127
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,081,129,131✔
1128
          continue;
1,432,143,596✔
1129
        }
1130

1131
        numOfElem += 1;
648,812,201✔
1132
        pStdRes->count += 1;
648,812,201✔
1133
        double nr = (double)plist[i];
654,802,543✔
1134
        if (pStdRes->count == 1) {
654,806,251✔
1135
          pStdRes->dsum = nr;
3,683,950✔
1136
        } else {
1137
          double          s_kminusone = pStdRes->dsum;
651,153,929✔
1138
          volatile double diff = nr - s_kminusone;
651,009,317✔
1139
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
651,009,317✔
1140
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
651,169,241✔
1141
        }
1142
      }
1143

1144
      break;
14,245,583✔
1145
    }
1146

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

1154
        numOfElem += 1;
1,244,508,004✔
1155
        pStdRes->count += 1;
1,244,508,004✔
1156
        double nr = (double)plist[i];
1,251,782,312✔
1157
        if (pStdRes->count == 1) {
1,251,792,200✔
1158
          pStdRes->dsum = nr;
404,819,855✔
1159
        } else {
1160
          double          s_kminusone = pStdRes->dsum;
847,000,155✔
1161
          volatile double diff = nr - s_kminusone;
846,959,985✔
1162
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
846,959,985✔
1163
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
846,953,187✔
1164
        }
1165
      }
1166
      break;
857,945,929✔
1167
    }
1168

1169
    case TSDB_DATA_TYPE_INT: {
19,890,666✔
1170
      int32_t* plist = (int32_t*)pCol->pData;
19,890,666✔
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;
796,890,752✔
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,658,217✔
1181
        } else {
1182
          double          s_kminusone = pStdRes->dsum;
2,147,483,647✔
1183
          volatile double diff = nr - s_kminusone;
2,147,483,647✔
1184
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,147,483,647✔
1185
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,147,483,647✔
1186
        }
1187
      }
1188

1189
      break;
19,891,668✔
1190
    }
1191

1192
    case TSDB_DATA_TYPE_BIGINT: {
16,794,231✔
1193
      int64_t* plist = (int64_t*)pCol->pData;
16,794,231✔
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;
1,326,266,179✔
1197
        }
1198

1199
        numOfElem += 1;
842,149,755✔
1200
        pStdRes->count += 1;
842,149,755✔
1201
        double nr = (double)plist[i];
855,210,305✔
1202
        if (pStdRes->count == 1) {
855,217,103✔
1203
          pStdRes->dsum = nr;
2,189,033✔
1204
        } else {
1205
          double          s_kminusone = pStdRes->dsum;
853,029,924✔
1206
          volatile double diff = nr - s_kminusone;
852,870,800✔
1207
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
852,870,800✔
1208
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
853,023,206✔
1209
        }
1210
      }
1211
      break;
16,794,151✔
1212
    }
1213

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

1221
        numOfElem += 1;
1,017,693,676✔
1222
        pStdRes->count += 1;
1,017,693,676✔
1223
        double nr = (double)plist[i];
1,015,308,237✔
1224
        if (pStdRes->count == 1) {
1,015,329,557✔
1225
          pStdRes->dsum = nr;
74,018✔
1226
        } else {
1227
          double          s_kminusone = pStdRes->dsum;
1,015,143,036✔
1228
          volatile double diff = nr - s_kminusone;
1,015,289,848✔
1229
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,015,289,848✔
1230
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,015,205,690✔
1231
        }
1232
      }
1233

1234
      break;
13,863,194✔
1235
    }
1236

1237
    case TSDB_DATA_TYPE_USMALLINT: {
10,294,203✔
1238
      uint16_t* plist = (uint16_t*)pCol->pData;
10,294,203✔
1239
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,072,346,020✔
1240
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,064,261,376✔
1241
          continue;
1,553,435,669✔
1242
        }
1243

1244
        numOfElem += 1;
510,722,789✔
1245
        pStdRes->count += 1;
510,722,789✔
1246
        double nr = (double)plist[i];
517,171,652✔
1247
        if (pStdRes->count == 1) {
517,175,978✔
1248
          pStdRes->dsum = nr;
32,535✔
1249
        } else {
1250
          double          s_kminusone = pStdRes->dsum;
517,139,117✔
1251
          volatile double diff = nr - s_kminusone;
517,139,117✔
1252
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
517,139,117✔
1253
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
517,116,251✔
1254
        }
1255
      }
1256
      break;
10,293,574✔
1257
    }
1258

1259
    case TSDB_DATA_TYPE_UINT: {
5,617,867✔
1260
      uint32_t* plist = (uint32_t*)pCol->pData;
5,617,867✔
1261
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,141,455,543✔
1262
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,135,921,944✔
1263
          continue;
808,666,461✔
1264
        }
1265

1266
        numOfElem += 1;
327,151,527✔
1267
        pStdRes->count += 1;
327,151,527✔
1268
        double nr = (double)plist[i];
330,116,385✔
1269
        if (pStdRes->count == 1) {
330,113,295✔
1270
          pStdRes->dsum = nr;
23,731✔
1271
        } else {
1272
          double          s_kminusone = pStdRes->dsum;
330,087,710✔
1273
          volatile double diff = nr - s_kminusone;
330,079,058✔
1274
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
330,079,058✔
1275
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
330,086,474✔
1276
        }
1277
      }
1278

1279
      break;
5,617,867✔
1280
    }
1281

1282
    case TSDB_DATA_TYPE_UBIGINT: {
5,617,484✔
1283
      uint64_t* plist = (uint64_t*)pCol->pData;
5,617,484✔
1284
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,142,152,859✔
1285
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,136,501,827✔
1286
          continue;
870,408,530✔
1287
        }
1288

1289
        numOfElem += 1;
266,071,590✔
1290
        pStdRes->count += 1;
266,071,590✔
1291
        double nr = (double)plist[i];
267,781,156✔
1292
        if (pStdRes->count == 1) {
267,785,482✔
1293
          pStdRes->dsum = nr;
20,865✔
1294
        } else {
1295
          double          s_kminusone = pStdRes->dsum;
267,771,415✔
1296
          volatile double diff = nr - s_kminusone;
267,756,583✔
1297
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
267,756,583✔
1298
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
267,750,403✔
1299
        }
1300
      }
1301
      break;
5,616,866✔
1302
    }
1303

1304
    case TSDB_DATA_TYPE_FLOAT: {
19,983,257✔
1305
      float* plist = (float*)pCol->pData;
19,983,257✔
1306
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,825,462,894✔
1307
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,805,479,127✔
1308
          continue;
24,364,977✔
1309
        }
1310

1311
        numOfElem += 1;
1,781,114,150✔
1312
        pStdRes->count += 1;
1,781,114,150✔
1313
        double nr = (double)plist[i];
1,781,092,220✔
1314
        if (pStdRes->count == 1) {
1,781,092,220✔
1315
          pStdRes->dsum = nr;
8,769,713✔
1316
        } else {
1317
          double          s_kminusone = pStdRes->dsum;
1,772,322,507✔
1318
          volatile double diff = nr - s_kminusone;
1,772,322,507✔
1319
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,772,322,507✔
1320
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,772,322,507✔
1321
        }
1322
      }
1323
      break;
19,981,727✔
1324
    }
1325

1326
    case TSDB_DATA_TYPE_DOUBLE: {
6,228,486✔
1327
      double* plist = (double*)pCol->pData;
6,228,486✔
1328
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
265,651,925✔
1329
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
259,425,053✔
1330
          continue;
156,789,667✔
1331
        }
1332

1333
        numOfElem += 1;
102,633,772✔
1334
        pStdRes->count += 1;
102,633,772✔
1335
        double nr = (double)plist[i];
102,633,234✔
1336
        if (pStdRes->count == 1) {
102,632,696✔
1337
          pStdRes->dsum = nr;
2,799,284✔
1338
        } else {
1339
          double          s_kminusone = pStdRes->dsum;
99,831,798✔
1340
          volatile double diff = nr - s_kminusone;
99,824,266✔
1341
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
99,824,266✔
1342
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
99,830,184✔
1343
        }
1344
      }
1345
      break;
6,230,638✔
1346
    }
1347

1348
    default:
×
1349
      break;
×
1350
  }
1351

1352
_stddev_over:
1,140,678,597✔
1353
  // data in the check operation are all null, not output
1354
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1,140,678,597✔
1355
  return TSDB_CODE_SUCCESS;
1,139,791,851✔
1356
}
1357

1358
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
16,966,267✔
1359
  if (IS_NULL_TYPE(pInput->type)) {
16,966,267✔
1360
    return;
23,120✔
1361
  }
1362
  pOutput->type = pInput->type;
16,943,147✔
1363
  if (pOutput->count == 0) {
16,943,147✔
1364
    pOutput->quadraticDSum += pInput->quadraticDSum;
16,643,818✔
1365
    pOutput->dsum += pInput->dsum;
16,643,818✔
1366
    pOutput->count = pInput->count;
16,643,818✔
1367
  } else if (pInput->count > 0) {
299,329✔
1368
    double totalCount = pOutput->count + pInput->count;
123,344✔
1369
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
123,344✔
1370
    double mean = totalSum / totalCount;
123,344✔
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;
123,344✔
1378
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pOutput->count * (diff * diff) / totalCount;
123,344✔
1379
    pOutput->dsum = mean;
123,344✔
1380
    pOutput->count += pInput->count;
123,344✔
1381
  }
1382
}
1383

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

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

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

1397
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
16,953,727✔
1398

1399
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
33,919,994✔
1400
    if (colDataIsNull_s(pCol, i)) continue;
33,932,534✔
1401
    char*    data = colDataGetData(pCol, i);
16,966,267✔
1402
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
16,966,267✔
1403
    stdTransferInfo(pInputInfo, pInfo);
16,966,267✔
1404
  }
1405

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

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

1416
  if (pStddevRes->count == 0) {
575,804,029✔
1417
    GET_RES_INFO(pCtx)->numOfRes = 0;
166,601,094✔
1418

1419
    return functionFinalize(pCtx, pBlock);
166,601,094✔
1420
  }
1421

1422
  if (pStddevRes->count == 1) {
409,201,887✔
1423
    pStddevRes->result = 0.0;
290,914,829✔
1424
  } else {
1425
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
118,287,058✔
1426
  }
1427

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

1433
  return functionFinalize(pCtx, pBlock);
409,201,887✔
1434
}
1435

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

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

1447
  if (pStdvarRes->count == 1) {
6,563,788✔
1448
    pStdvarRes->result = 0.0;
928✔
1449
  } else {
1450
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
6,562,860✔
1451
  }
1452

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

1458
  return functionFinalize(pCtx, pBlock);
6,563,788✔
1459
}
1460

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

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

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

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

1482
  taosMemoryFree(res);
16,970,107✔
1483
  return code;
16,970,107✔
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,236,878✔
1502
  SInputColumnInfoData* pInput = &pCtx->input;
3,236,878✔
1503
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,236,878✔
1504
  double                avg;
1505

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

1511
  if (pStddevRes->count == 1) {
3,236,414✔
1512
    pStddevRes->result = 0.0;
464✔
1513
  } else {
1514
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / (pStddevRes->count - 1));
3,235,950✔
1515
  }
1516

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

1522
  return functionFinalize(pCtx, pBlock);
3,236,414✔
1523
}
1524

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

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

1535
  if (pStddevRes->count == 1) {
3,235,486✔
1536
    pStddevRes->result = 0.0;
464✔
1537
  } else {
1538
    pStddevRes->result = pStddevRes->quadraticDSum / (pStddevRes->count - 1);
3,235,022✔
1539
  }
1540

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

1546
  return functionFinalize(pCtx, pBlock);
3,235,486✔
1547
}
1548

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

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

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

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

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

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

1603
  return TSDB_CODE_SUCCESS;
18,202✔
1604
}
1605

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1706
  return code;
958✔
1707
}
1708

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

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

1722
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,574,705✔
1723

1724
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
4,574,167✔
1725
                 typeGetTypeModFromCol(pCtx->param[1].pCol));
1726
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
4,575,243✔
1727
                 typeGetTypeModFromCol(pCtx->param[2].pCol));
1728
  return TSDB_CODE_SUCCESS;
4,575,781✔
1729
}
1730

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

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

1737
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,465,185✔
1738

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

1741
  double(*param)[3] = pInfo->matrix;
5,464,109✔
1742
  double x = pInfo->startVal;
5,464,109✔
1743

1744
  int32_t start = pInput->startRowIndex;
5,463,571✔
1745
  int32_t numOfRows = pInput->numOfRows;
5,463,571✔
1746

1747
  switch (type) {
5,463,033✔
1748
    case TSDB_DATA_TYPE_TINYINT: {
280,809✔
1749
      int8_t* plist = (int8_t*)pCol->pData;
280,809✔
1750
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,041,983✔
1751
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,761,174✔
1752
          continue;
111,440✔
1753
        }
1754
        numOfElem++;
18,649,734✔
1755
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,649,734✔
1756
      }
1757
      break;
280,809✔
1758
    }
1759
    case TSDB_DATA_TYPE_SMALLINT: {
2,721,394✔
1760
      int16_t* plist = (int16_t*)pCol->pData;
2,721,394✔
1761
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
100,813,510✔
1762
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
98,093,730✔
1763
          continue;
79,397,290✔
1764
        }
1765

1766
        numOfElem++;
18,696,978✔
1767
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,696,978✔
1768
      }
1769
      break;
2,721,932✔
1770
    }
1771

1772
    case TSDB_DATA_TYPE_INT: {
972,942✔
1773
      int32_t* plist = (int32_t*)pCol->pData;
972,942✔
1774
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
183,292,547✔
1775
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
182,323,371✔
1776
          continue;
73,874,489✔
1777
        }
1778

1779
        numOfElem++;
108,431,666✔
1780
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
108,431,666✔
1781
      }
1782
      break;
974,018✔
1783
    }
1784

1785
    case TSDB_DATA_TYPE_BIGINT: {
440,038✔
1786
      int64_t* plist = (int64_t*)pCol->pData;
440,038✔
1787
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,412,812✔
1788
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,972,774✔
1789
          continue;
58,540✔
1790
        }
1791

1792
        numOfElem++;
18,914,234✔
1793
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,914,234✔
1794
      }
1795
      break;
440,038✔
1796
    }
1797

1798
    case TSDB_DATA_TYPE_UTINYINT: {
17,740✔
1799
      uint8_t* plist = (uint8_t*)pCol->pData;
17,740✔
1800
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,457,220✔
1801
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,439,480✔
1802
          continue;
10,340✔
1803
        }
1804
        numOfElem++;
18,429,140✔
1805
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
18,429,140✔
1806
      }
1807
      break;
17,740✔
1808
    }
1809
    case TSDB_DATA_TYPE_USMALLINT: {
17,740✔
1810
      uint16_t* plist = (uint16_t*)pCol->pData;
17,740✔
1811
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,457,220✔
1812
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,439,480✔
1813
          continue;
9,400✔
1814
        }
1815

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

1822
    case TSDB_DATA_TYPE_UINT: {
17,740✔
1823
      uint32_t* plist = (uint32_t*)pCol->pData;
17,740✔
1824
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,457,220✔
1825
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,439,480✔
1826
          continue;
9,400✔
1827
        }
1828

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

1835
    case TSDB_DATA_TYPE_UBIGINT: {
17,740✔
1836
      uint64_t* plist = (uint64_t*)pCol->pData;
17,740✔
1837
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,457,220✔
1838
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
18,439,480✔
1839
          continue;
9,400✔
1840
        }
1841

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

1848
    case TSDB_DATA_TYPE_FLOAT: {
700,050✔
1849
      float* plist = (float*)pCol->pData;
700,050✔
1850
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,872,330✔
1851
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,172,280✔
1852
          continue;
56,640✔
1853
        }
1854

1855
        numOfElem++;
19,115,640✔
1856
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,115,640✔
1857
      }
1858
      break;
700,050✔
1859
    }
1860

1861
    case TSDB_DATA_TYPE_DOUBLE: {
276,840✔
1862
      double* plist = (double*)pCol->pData;
276,840✔
1863
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
19,482,480✔
1864
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
19,205,640✔
1865
          continue;
111,440✔
1866
        }
1867

1868
        numOfElem++;
19,094,200✔
1869
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
19,094,200✔
1870
      }
1871
      break;
276,840✔
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,464,647✔
1884
  pInfo->num += numOfElem;
5,464,647✔
1885

1886
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
5,465,185✔
1887

1888
  return TSDB_CODE_SUCCESS;
5,464,647✔
1889
}
1890

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

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

1902
  if (0 == pInfo->num) {
4,575,381✔
1903
    colDataSetNULL(pCol, currentRow);
3,456,471✔
1904
    return TSDB_CODE_SUCCESS;
3,456,471✔
1905
  }
1906

1907
  double(*param)[3] = pInfo->matrix;
1,118,910✔
1908

1909
  param[1][1] = (double)pInfo->num;
1,118,910✔
1910
  param[1][0] = param[0][1];
1,118,910✔
1911

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

1915
  if (0 == param00) {
1,118,910✔
1916
    colDataSetNULL(pCol, currentRow);
958,207✔
1917
    return TSDB_CODE_SUCCESS;
958,207✔
1918
  }
1919

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

1925
  param12 /= param[1][1];
160,703✔
1926

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

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

1944
  return code;
160,703✔
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) {
89,630✔
1970
  pEnv->calcMemSize = sizeof(SPercentileInfo);
89,630✔
1971
  return true;
89,630✔
1972
}
1973

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

1988
  return TSDB_CODE_SUCCESS;
362,056✔
1989
}
1990

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

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

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

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

2013
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,767,192✔
2014
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
1,767,192✔
2015
    pInfo->stage += 1;
362,056✔
2016

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

2030
  // the first stage, only acquire the min/max value
2031
  if (pInfo->stage == 0) {
1,661,392✔
2032
    if (pCtx->input.colDataSMAIsSet) {
883,596✔
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;
883,596✔
2057
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,352,396✔
2058
        if (colDataIsNull_f(pCol, i)) {
17,468,800✔
2059
          continue;
136,754✔
2060
        }
2061

2062
        char* data = colDataGetData(pCol, i);
17,332,046✔
2063

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

2070
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
17,332,046✔
2071
          SET_DOUBLE_VAL(&pInfo->maxval, v);
13,881,752✔
2072
        }
2073

2074
        pInfo->numOfElems += 1;
17,332,046✔
2075
      }
2076
    }
2077
  } else {
2078
    // the second stage, calculate the true percentile value
2079
    int32_t start = pInput->startRowIndex;
777,796✔
2080
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
18,081,702✔
2081
      if (colDataIsNull_f(pCol, i)) {
17,304,375✔
2082
        continue;
×
2083
      }
2084

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

2094
    SET_VAL(pResInfo, numOfElems, 1);
777,327✔
2095
  }
2096

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

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

2105
  int32_t code = 0;
361,118✔
2106
  double  v = 0;
361,118✔
2107

2108
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
361,118✔
2109
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
361,118✔
2110
    if (pCtx->numOfParams > 2) {
255,318✔
2111
      char buf[3200] = {0};
2,814✔
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,814✔
2115

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

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

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

2127
        if (i == pCtx->numOfParams - 1) {
28,140✔
2128
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
2,814✔
2129
        } else {
2130
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
25,326✔
2131
        }
2132
      }
2133

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

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

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

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

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

2159
      tMemBucketDestroy(pMemBucket);
252,504✔
2160
      return functionFinalize(pCtx, pBlock);
252,504✔
2161
    }
2162
  } else {
2163
    return functionFinalize(pCtx, pBlock);
105,800✔
2164
  }
2165

2166
_fin_error:
×
2167

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

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

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

2187
static int8_t getApercentileAlgo(char* algoStr) {
3,024,068✔
2188
  int8_t algoType;
2189
  if (strcasecmp(algoStr, "default") == 0) {
3,024,068✔
2190
    algoType = APERCT_ALGO_DEFAULT;
1,510,638✔
2191
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,513,430✔
2192
    algoType = APERCT_ALGO_TDIGEST;
1,513,968✔
2193
  } else {
2194
    algoType = APERCT_ALGO_UNKNOWN;
×
2195
  }
2196

2197
  return algoType;
3,024,068✔
2198
}
2199

2200
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
147,816,010✔
2201
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
147,816,010✔
2202
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
147,842,530✔
2203
}
147,843,131✔
2204

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

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

2217
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
47,796,685✔
2218

2219
  SVariant* pVal = &pCtx->param[1].param;
47,799,235✔
2220
  pInfo->percent = 0;
47,802,295✔
2221
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
47,802,805✔
2222

2223
  if (pCtx->numOfParams == 2) {
47,802,267✔
2224
    pInfo->algo = APERCT_ALGO_DEFAULT;
44,778,199✔
2225
  } else if (pCtx->numOfParams == 3) {
3,024,068✔
2226
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
3,024,606✔
2227
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
3,024,606✔
2228
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2229
    }
2230
  }
2231

2232
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
47,801,757✔
2233
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
47,794,645✔
2234
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,513,430✔
2235
  } else {
2236
    buildHistogramInfo(pInfo);
46,278,637✔
2237
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
46,287,307✔
2238
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
46,287,307✔
2239
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2240
  }
2241

2242
  return TSDB_CODE_SUCCESS;
47,802,267✔
2243
}
2244

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

2250
  SColumnInfoData* pCol = pInput->pData[0];
57,452,304✔
2251
  int32_t          type = pCol->info.type;
57,452,384✔
2252

2253
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
57,452,922✔
2254

2255
  int32_t start = pInput->startRowIndex;
57,452,922✔
2256
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
57,452,922✔
2257
    buildTDigestInfo(pInfo);
1,513,495✔
2258
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,512,957✔
2259
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
78,747,034✔
2260
      if (colDataIsNull_f(pCol, i)) {
77,236,229✔
2261
        continue;
76,467,562✔
2262
      }
2263
      numOfElems += 1;
769,743✔
2264
      char* data = colDataGetData(pCol, i);
769,743✔
2265

2266
      double  v = 0;  // value
769,743✔
2267
      int64_t w = 1;  // weigth
769,743✔
2268
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
769,743✔
2269
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
769,743✔
2270
      if (code != TSDB_CODE_SUCCESS) {
766,432✔
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);
55,938,798✔
2278
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
55,939,427✔
2279
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2280
           pInfo->pHisto->elems);
2281
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
2282
      if (colDataIsNull_f(pCol, i)) {
2,147,483,647✔
2283
        continue;
1,577,667,109✔
2284
      }
2285
      numOfElems += 1;
813,083,267✔
2286
      char* data = colDataGetData(pCol, i);
813,083,267✔
2287

2288
      double v = 0;
813,587,313✔
2289
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
813,587,313✔
2290
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
813,586,779✔
2291
      if (code != TSDB_CODE_SUCCESS) {
811,465,084✔
2292
        return code;
×
2293
      }
2294
    }
2295

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

2301
  SET_VAL(pResInfo, numOfElems, 1);
57,452,293✔
2302
  return TSDB_CODE_SUCCESS;
57,451,675✔
2303
}
2304

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

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

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

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

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

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

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

2346
    if (pHisto->numOfElems <= 0) {
125,551✔
2347
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
111,768✔
2348
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
111,768✔
2349

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

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

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

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

2377
  SInputColumnInfoData* pInput = &pCtx->input;
248,160✔
2378

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

2384
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
248,160✔
2385

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

2388
  bool    hasRes = false;
248,160✔
2389
  int32_t start = pInput->startRowIndex;
248,160✔
2390
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
498,962✔
2391
    char* data = colDataGetData(pCol, i);
250,802✔
2392

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

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

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

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

2414
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
46,526,194✔
2415
    buildTDigestInfo(pInfo);
1,498,836✔
2416
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,498,836✔
2417
    if (pInfo->pTDigest->size > 0) {
1,498,836✔
2418
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,498,836✔
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);
45,028,888✔
2425
    if (pInfo->pHisto->numOfElems > 0) {
45,027,868✔
2426
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
3,335,445✔
2427
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2428

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

2447
  return functionFinalize(pCtx, pBlock);
46,528,206✔
2448
}
2449

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

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

2460
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
250,802✔
2461
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
14,663✔
2462
    varDataSetLen(res, resultBytes);
14,663✔
2463
  } else {
2464
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
236,139✔
2465
    varDataSetLen(res, resultBytes);
236,139✔
2466
  }
2467

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

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

2477
  taosMemoryFree(res);
250,802✔
2478
  return code;
250,802✔
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) {
316,674✔
2501
  char numVal[8] = {0};
316,674✔
2502
  switch (pkType) {
316,674✔
2503
    case TSDB_DATA_TYPE_INT:
47,482✔
2504
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
47,482✔
2505
      break;
47,482✔
2506
    case TSDB_DATA_TYPE_UINT:
50,984✔
2507
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
50,984✔
2508
      break;
50,984✔
2509
    case TSDB_DATA_TYPE_BIGINT:
63,062✔
2510
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
63,062✔
2511
      break;
63,062✔
2512
    case TSDB_DATA_TYPE_UBIGINT:
63,062✔
2513
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
63,062✔
2514
      break;
63,062✔
2515
    default:
92,084✔
2516
      break;
92,084✔
2517
  }
2518
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
316,674✔
2519
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
316,674✔
2520
  return fn(pkData, blockData);
316,674✔
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;
306,371✔
2535
    } else {
2536
      pResult->pkData = NULL;
2,147,483,647✔
2537
    }
2538
    if (pResult->ts < pBlockInfo->window.skey) {
2,147,483,647✔
2539
      return FUNC_DATA_REQUIRED_NOT_LOAD;
2,825,562✔
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) {
210,179✔
2545
        return FUNC_DATA_REQUIRED_NOT_LOAD;
17,620✔
2546
      }
2547
    }
2548
    return FUNC_DATA_REQUIRED_DATA_LOAD;
382,302✔
2549
  } else {
2550
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,205,298✔
2551
  }
2552
}
2553

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

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

2562
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
28,574,718✔
2563
  if (pResult->hasResult) {
28,576,132✔
2564
    if (pResult->pkBytes > 0) {
26,441,363✔
2565
      pResult->pkData = pResult->buf + pResult->bytes;
346,975✔
2566
    } else {
2567
      pResult->pkData = NULL;
26,093,956✔
2568
    }
2569
    if (pResult->ts > pBlockInfo->window.ekey) {
26,441,363✔
2570
      return FUNC_DATA_REQUIRED_NOT_LOAD;
7,692,682✔
2571
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
18,748,033✔
2572
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
106,495✔
2573
        return FUNC_DATA_REQUIRED_NOT_LOAD;
37,068✔
2574
      }
2575
    }
2576
    return FUNC_DATA_REQUIRED_DATA_LOAD;
18,710,533✔
2577
  } else {
2578
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,138,501✔
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,829,223,638✔
2584

2585
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
65,023,244✔
2586
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
65,023,244✔
2587
  // TODO: change SFunctionNode to add pk info
2588
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
65,027,366✔
2589
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
65,023,051✔
2590
  return true;
65,023,810✔
2591
}
2592

2593
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
15,430,731✔
2594
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
15,430,731✔
2595
  pEnv->calcMemSize = pNode->node.resType.bytes;
15,432,709✔
2596
  return true;
15,430,931✔
2597
}
2598

2599

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

2605
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
67,954,024✔
2606
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
67,954,024✔
2607
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
67,956,655✔
2608
  return true;
67,954,462✔
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) {
125,488,176✔
2634
  if (pCtx->subsidiaries.rowLen == 0) {
125,488,176✔
2635
    int32_t rowLen = 0;
5,204,031✔
2636
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
12,155,794✔
2637
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
6,953,850✔
2638
      rowLen += pc->pExpr->base.resSchema.bytes;
6,949,071✔
2639
    }
2640

2641
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
5,205,043✔
2642
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
5,205,482✔
2643
    if (NULL == pCtx->subsidiaries.buf) {
5,201,912✔
2644
      return terrno;
×
2645
    }
2646
  }
2647
  return TSDB_CODE_SUCCESS;
125,487,606✔
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) {
82,074,389✔
2659
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
68,428,928✔
2660
  } else if (!noElements) {
13,646,132✔
2661
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
13,634,711✔
2662
  } else {
2663
  }  // dothing
2664

2665
  return code;
82,076,163✔
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)) {
175,095,765✔
2685
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
58,356,078✔
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);
175,097,110✔
2693
    pInfo->pkData = pInfo->buf + pInfo->bytes;
175,097,110✔
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,216,998✔
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;
47,575,742✔
2728
    pInfo->pkBytes = pkCol->info.bytes;
47,578,779✔
2729
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
47,581,972✔
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);
181,627,811✔
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,198,840✔
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;
47,706,990✔
2863
    pInfo->pkBytes = pkCol->info.bytes;
47,709,462✔
2864
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
47,710,030✔
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];
416,523,502✔
2947
      int32_t chosen = i;
416,526,193✔
2948

2949
      if (cts < pts[i + 1]) {
416,526,193✔
2950
        cts = pts[i + 1];
142,085,560✔
2951
        chosen = i + 1;
142,085,560✔
2952
      }
2953

2954
      if (cts < pts[i + 2]) {
416,532,100✔
2955
        cts = pts[i + 2];
142,085,819✔
2956
        chosen = i + 2;
142,085,819✔
2957
      }
2958

2959
      if (cts < pts[i + 3]) {
416,531,761✔
2960
        cts = pts[i + 3];
142,084,211✔
2961
        chosen = i + 3;
142,084,211✔
2962
      }
2963

2964
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
416,391,308✔
2965
        char*   data = colDataGetData(pInputCol, chosen);
170,343,898✔
2966
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
170,344,278✔
2967
        if (code != TSDB_CODE_SUCCESS) {
170,355,793✔
2968
          return code;
×
2969
        }
2970
        pResInfo->numOfRes = 1;
170,355,793✔
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);
925,787,919✔
2977
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
922,382,576✔
2978
        if (code != TSDB_CODE_SUCCESS) {
922,679,003✔
2979
          return code;
×
2980
        }
2981
        pResInfo->numOfRes = 1;
922,679,003✔
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);
173,437,493✔
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,405,609,195✔
3028
  if (!pInput->hasResult) {
1,405,609,195✔
3029
    return false;
×
3030
  }
3031
  __compar_fn_t pkCompareFn = NULL;
1,405,609,436✔
3032
  if (pInput->pkData) {
1,405,609,436✔
3033
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
3,973,062✔
3034
  }
3035
  if (pOutput->hasResult) {
1,405,611,364✔
3036
    if (isFirst) {
767,764,944✔
3037
      if (pInput->ts > pOutput->ts ||
670,778,067✔
3038
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
670,000,711✔
3039
        return false;
926,318✔
3040
      }
3041
    } else {
3042
      if (pInput->ts < pOutput->ts ||
96,986,877✔
3043
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
94,358,000✔
3044
        return false;
2,842,255✔
3045
      }
3046
    }
3047
  }
3048

3049
  pOutput->isNull = pInput->isNull;
1,401,842,550✔
3050
  pOutput->ts = pInput->ts;
1,401,842,791✔
3051
  pOutput->bytes = pInput->bytes;
1,401,843,996✔
3052
  pOutput->pkType = pInput->pkType;
1,401,843,514✔
3053

3054
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,401,843,514✔
3055
  if (pInput->pkData) {
1,401,843,514✔
3056
    pOutput->pkBytes = pInput->pkBytes;
3,496,494✔
3057
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
3,496,494✔
3058
    pOutput->pkData = pOutput->buf + pOutput->bytes;
3,496,494✔
3059
  }
3060
  return true;
1,401,842,068✔
3061
}
3062

3063
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,405,609,436✔
3064
                                     int32_t rowIndex) {
3065
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,405,609,436✔
3066
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,401,842,068✔
3067
    if (TSDB_CODE_SUCCESS != code) {
1,401,843,514✔
3068
      return code;
×
3069
    }
3070
    pOutput->hasResult = true;
1,401,843,514✔
3071
  }
3072
  return TSDB_CODE_SUCCESS;
1,405,612,087✔
3073
}
3074

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

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

3088
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
653,349,561✔
3089

3090
  int32_t start = pInput->startRowIndex;
653,349,561✔
3091
  int32_t numOfElems = 0;
653,349,802✔
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;
239,735,746✔
3096
    }
3097
    char*          data = colDataGetData(pCol, i);
1,405,611,364✔
3098
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,405,612,569✔
3099
    if (pCtx->hasPrimaryKey) {
1,405,612,328✔
3100
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
3,973,062✔
3101
    } else {
3102
      pInputInfo->pkData = NULL;
1,401,639,507✔
3103
    }
3104

3105
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,405,609,677✔
3106
    if (code != TSDB_CODE_SUCCESS) {
1,405,611,605✔
3107
      return code;
×
3108
    }
3109
    if (!numOfElems) {
1,405,611,605✔
3110
      numOfElems = pInputInfo->hasResult ? 1 : 0;
649,392,516✔
3111
    }
3112
  }
3113

3114
  if (numOfElems == 0) {
653,344,018✔
3115
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
3,954,635✔
3116
    if (code != TSDB_CODE_SUCCESS) {
3,954,635✔
3117
      return code;
×
3118
    }
3119
    pInfo->nullTupleSaved = true;
3,954,635✔
3120
  }
3121

3122
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
653,344,500✔
3123
  return TSDB_CODE_SUCCESS;
653,344,500✔
3124
}
3125

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

3128
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
272,030,735✔
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,144,875,957✔
3145
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,144,875,957✔
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,747,896,016✔
3162
  int32_t code = TSDB_CODE_SUCCESS;
1,747,896,016✔
3163

3164
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,747,896,016✔
3165
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,748,321,982✔
3166

3167
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,748,306,421✔
3168

3169
  // todo check for failure
3170
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,748,201,493✔
3171
  if (NULL == res) {
1,742,971,014✔
3172
    return terrno;
×
3173
  }
3174
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,742,971,014✔
3175

3176
  varDataSetLen(res, resultBytes);
1,743,013,764✔
3177

3178
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,747,571,048✔
3179
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,748,247,514✔
3180
  if (NULL == pCol) {
1,748,057,446✔
3181
    taosMemoryFree(res);
×
3182
    return TSDB_CODE_OUT_OF_RANGE;
×
3183
  }
3184

3185
  if (pEntryInfo->numOfRes == 0) {
1,748,057,446✔
3186
    colDataSetNULL(pCol, pBlock->info.rows);
249,925,972✔
3187
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
249,932,470✔
3188
  } else {
3189
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,498,021,354✔
3190
    if (TSDB_CODE_SUCCESS != code) {
1,498,192,621✔
3191
      taosMemoryFree(res);
×
3192
      return code;
×
3193
    }
3194
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,498,192,621✔
3195
  }
3196
  taosMemoryFree(res);
1,747,622,940✔
3197
  return code;
1,747,620,249✔
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) {
22,787,303✔
3215
  SInputColumnInfoData* pInput = &pCtx->input;
22,787,303✔
3216
  SColumnInfoData*      pInputCol = pInput->pData[0];
22,802,349✔
3217
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
22,819,469✔
3218

3219
  if (colDataIsNull_s(pInputCol, rowIndex)) {
45,645,125✔
3220
    pInfo->isNull = true;
2,773,049✔
3221
  } else {
3222
    pInfo->isNull = false;
20,048,385✔
3223

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

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

3236
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
31,981,983✔
3237
    char* pkData = colDataGetData(pkCol, rowIndex);
9,175,098✔
3238
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
9,171,390✔
3239
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
3,054,426✔
3240
    }
3241
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
9,172,626✔
3242
    pInfo->pkData = pInfo->buf + pInfo->bytes;
9,168,300✔
3243
  }
3244
  pInfo->ts = cts;
22,799,507✔
3245
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
22,805,787✔
3246
  if (code != TSDB_CODE_SUCCESS) {
22,795,481✔
3247
    return code;
×
3248
  }
3249

3250
  pInfo->hasResult = true;
22,795,481✔
3251

3252
  return TSDB_CODE_SUCCESS;
22,803,800✔
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,879✔
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;
46,987,434✔
3276
    pInfo->pkBytes = pkCol->info.bytes;
46,986,198✔
3277
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
46,988,052✔
3278
  }
3279
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
3280
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
3281

3282
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3283
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
21,581,602✔
3284
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
10,792,175✔
3285
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
10,792,175✔
3286
      TSKEY cts = getRowPTs(pInput->pPTS, i);
10,791,717✔
3287
      numOfElems++;
10,792,175✔
3288

3289
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
10,792,175✔
3290
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
3,103,949✔
3291
        if (code != TSDB_CODE_SUCCESS) return code;
3,103,033✔
3292
      }
3293

3294
      break;
10,789,885✔
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);
7,538,522✔
3307
        if (code != TSDB_CODE_SUCCESS) return code;
8,463,850✔
3308
      }
3309
      break;
2,147,483,647✔
3310
    }
3311
  } else {
3312
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
47,102,258✔
3313
    int      from = -1;
47,537,204✔
3314
    int32_t  i = -1;
47,534,732✔
3315
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
220,415,635✔
3316
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
172,849,630✔
3317
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
172,880,289✔
3318
      TSKEY cts = pts[i];
172,872,496✔
3319

3320
      numOfElems++;
172,871,878✔
3321
      char* pkData = NULL;
172,871,878✔
3322
      if (pCtx->hasPrimaryKey) {
172,871,878✔
3323
        pkData = colDataGetData(pkCol, i);
168,326,334✔
3324
      }
3325
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
172,871,878✔
3326
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
162,166,334✔
3327
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
10,705,791✔
3328
        if (code != TSDB_CODE_SUCCESS) {
10,713,825✔
3329
          return code;
×
3330
        }
3331
        pResInfo->numOfRes = 1;
10,713,825✔
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) {
536,806✔
3341
  pEnv->calcMemSize = sizeof(SDiffInfo);
536,806✔
3342
  return true;
536,806✔
3343
}
3344

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

3365
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
5,657,776✔
3366
  switch (type) {
5,657,776✔
3367
    case TSDB_DATA_TYPE_BOOL:
3,967✔
3368
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
3,967✔
3369
      break;
3,967✔
3370
    case TSDB_DATA_TYPE_UTINYINT:
33,628✔
3371
    case TSDB_DATA_TYPE_TINYINT:
3372
      pDiffInfo->prev.i64 = *(int8_t*)pv;
33,628✔
3373
      break;
33,628✔
3374
    case TSDB_DATA_TYPE_UINT:
5,379,974✔
3375
    case TSDB_DATA_TYPE_INT:
3376
      pDiffInfo->prev.i64 = *(int32_t*)pv;
5,379,974✔
3377
      break;
5,379,974✔
3378
    case TSDB_DATA_TYPE_USMALLINT:
37,312✔
3379
    case TSDB_DATA_TYPE_SMALLINT:
3380
      pDiffInfo->prev.i64 = *(int16_t*)pv;
37,312✔
3381
      break;
37,312✔
3382
    case TSDB_DATA_TYPE_TIMESTAMP:
115,620✔
3383
    case TSDB_DATA_TYPE_UBIGINT:
3384
    case TSDB_DATA_TYPE_BIGINT:
3385
      pDiffInfo->prev.i64 = *(int64_t*)pv;
115,620✔
3386
      break;
115,620✔
3387
    case TSDB_DATA_TYPE_FLOAT:
28,913✔
3388
      pDiffInfo->prev.d64 = *(float*)pv;
28,913✔
3389
      break;
28,913✔
3390
    case TSDB_DATA_TYPE_DOUBLE:
58,362✔
3391
      pDiffInfo->prev.d64 = *(double*)pv;
58,362✔
3392
      break;
58,362✔
3393
    default:
×
3394
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3395
  }
3396
  pDiffInfo->prevTs = ts;
5,657,776✔
3397
  pDiffInfo->hasPrev = true;
5,657,776✔
3398
  return TSDB_CODE_SUCCESS;
5,657,776✔
3399
}
3400

3401
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
3,240,702✔
3402
  switch (type) {
3,240,702✔
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: {
787,330✔
3408
      int64_t v = *(int32_t*)pv;
787,330✔
3409
      return v < pDiffInfo->prev.i64;
787,330✔
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: {
205,306✔
3420
      int64_t v = *(int8_t*)pv;
205,306✔
3421
      return v < pDiffInfo->prev.i64;
205,306✔
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: {
541,860✔
3428
      int64_t v = *(int16_t*)pv;
541,860✔
3429
      return v < pDiffInfo->prev.i64;
541,860✔
3430
    }
3431
    case TSDB_DATA_TYPE_UBIGINT: {
3,528✔
3432
      uint64_t v = *(uint64_t*)pv;
3,528✔
3433
      return v < (uint64_t)pDiffInfo->prev.i64;
3,528✔
3434
    }
3435
    case TSDB_DATA_TYPE_TIMESTAMP:
740,954✔
3436
    case TSDB_DATA_TYPE_BIGINT: {
3437
      int64_t v = *(int64_t*)pv;
740,954✔
3438
      return v < pDiffInfo->prev.i64;
740,954✔
3439
    }
3440
    case TSDB_DATA_TYPE_FLOAT: {
224,826✔
3441
      float v = *(float*)pv;
224,826✔
3442
      return v < pDiffInfo->prev.d64;
224,826✔
3443
    }
3444
    case TSDB_DATA_TYPE_DOUBLE: {
736,898✔
3445
      double v = *(double*)pv;
736,898✔
3446
      return v < pDiffInfo->prev.d64;
736,898✔
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;
443,469✔
3459
  }
3460
  int64_t delta = v - pDiffInfo->prev.i64;
2,147,483,647✔
3461
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3462
    colDataSetNull_f_s(pOutput, pos);
1,138,846✔
3463
    pOutput->hasNull = true;
1,138,846✔
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,795,131✔
3471
  double delta = v - pDiffInfo->prev.d64;
29,795,131✔
3472
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
29,795,131✔
3473
    colDataSetNull_f_s(pOutput, pos);
488,885✔
3474
  } else {
3475
    colDataSetDouble(pOutput, pos, &delta);
29,306,246✔
3476
  }
3477
  pDiffInfo->prev.d64 = v;
29,795,131✔
3478
}
29,795,131✔
3479

3480
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2,147,483,647✔
3481
                            int64_t ts) {
3482
  if (!pDiffInfo->hasPrev) {
2,147,483,647✔
3483
    colDataSetNull_f_s(pOutput, pos);
65,549✔
3484
    return doSetPrevVal(pDiffInfo, type, pv, ts);
65,549✔
3485
  }
3486
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3487
  switch (type) {
2,147,483,647✔
3488
    case TSDB_DATA_TYPE_UINT: {
437,295✔
3489
      int64_t v = *(uint32_t*)pv;
437,295✔
3490
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
437,295✔
3491
      break;
437,295✔
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,491,988✔
3499
      int64_t v = *(bool*)pv;
4,491,988✔
3500
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
4,491,988✔
3501
      break;
4,491,988✔
3502
    }
3503
    case TSDB_DATA_TYPE_UTINYINT: {
59,535✔
3504
      int64_t v = *(uint8_t*)pv;
59,535✔
3505
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
59,535✔
3506
      break;
59,535✔
3507
    }
3508
    case TSDB_DATA_TYPE_TINYINT: {
9,713,832✔
3509
      int64_t v = *(int8_t*)pv;
9,713,832✔
3510
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
9,713,832✔
3511
      break;
9,713,832✔
3512
    }
3513
    case TSDB_DATA_TYPE_USMALLINT: {
59,535✔
3514
      int64_t v = *(uint16_t*)pv;
59,535✔
3515
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
59,535✔
3516
      break;
59,535✔
3517
    }
3518
    case TSDB_DATA_TYPE_SMALLINT: {
10,562,162✔
3519
      int64_t v = *(int16_t*)pv;
10,562,162✔
3520
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,562,162✔
3521
      break;
10,562,162✔
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: {
15,165,547✔
3531
      double v = *(float*)pv;
15,165,547✔
3532
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
15,165,547✔
3533
      break;
15,165,547✔
3534
    }
3535
    case TSDB_DATA_TYPE_DOUBLE: {
14,629,584✔
3536
      double v = *(double*)pv;
14,629,584✔
3537
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
14,629,584✔
3538
      break;
14,629,584✔
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,327,976✔
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) {
666,323,999✔
3565
      from = pInput->startRowIndex;
142,247,250✔
3566
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
524,076,749✔
3567
      return false;
142,291,125✔
3568
    }
3569
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
524,071,134✔
3570
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
524,100,492✔
3571
    int8_t           pkType = pkCol->info.type;
524,090,551✔
3572
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
524,126,963✔
3573
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
524,126,963✔
3574
    int32_t          select = from;
524,063,150✔
3575
    char*            val = colDataGetData(pkCol, select);
524,063,150✔
3576
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,304,152,006✔
3577
      char* val1 = colDataGetData(pkCol, from + 1);
780,057,956✔
3578
      if (compareFunc(val1, val) < 0) {
780,097,052✔
3579
        select = from + 1;
244,534,238✔
3580
        val = val1;
244,534,238✔
3581
      }
3582
      from = from + 1;
780,053,012✔
3583
    }
3584
    *pRowIndex = select;
523,889,324✔
3585
    *nextFrom = from + 1;
524,081,643✔
3586
    return true;
524,100,286✔
3587
  }
3588
}
3589

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

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

3599
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
2,147,483,647✔
3600
    return true;
13,087,450✔
3601
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3602
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
3,240,702✔
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,771,007✔
3614
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,771,007✔
3615
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,771,007✔
3616
  pDiffInfo->isFirstRow = false;
5,771,007✔
3617
  if (pRow->isDataNull) {
5,771,007✔
3618
    return TSDB_CODE_SUCCESS;
178,780✔
3619
  }
3620

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

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

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

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

3642
    // handle selectivity
3643
    if (pCtx->subsidiaries.num > 0) {
7,258,391✔
3644
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
21,164✔
3645
      if (code != TSDB_CODE_SUCCESS) {
21,164✔
3646
        return code;
×
3647
      }
3648
    }
3649
    return TSDB_CODE_SUCCESS;
7,258,391✔
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,999✔
3656
  }
3657
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
2,147,483,647✔
3658
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3659
    return code;
×
3660
  }
3661
  // handle selectivity
3662
  if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
3663
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
2,147,483,647✔
3664
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3665
      return code;
×
3666
    }
3667
  }
3668

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

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

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

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

3687
  bool keepNull = false;
45,725,792✔
3688
  for (int i = 0; i < diffColNum; ++i) {
91,475,398✔
3689
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
45,749,606✔
3690
    if (NULL == pCtx) {
45,749,606✔
3691
      code = terrno;
×
3692
      goto _exit;
×
3693
    }
3694
    funcInputUpdate(pCtx);
45,749,606✔
3695
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
45,749,606✔
3696
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
45,749,606✔
3697
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
45,749,606✔
3698
      keepNull = true;
45,731,525✔
3699
    }
3700
  }
3701

3702
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
45,725,792✔
3703
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
45,725,792✔
3704
  if (NULL == pCtx0 || NULL == pRow0) {
45,725,792✔
3705
    code = terrno;
×
3706
    goto _exit;
×
3707
  }
3708
  int32_t startOffset = pCtx0->offset;
45,725,792✔
3709
  bool    result = false;
45,725,792✔
3710
  while (1) {
2,147,483,647✔
3711
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
2,147,483,647✔
3712
    if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3713
      goto _exit;
×
3714
    }
3715
    if (!result) {
2,147,483,647✔
3716
      break;
45,717,793✔
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,070,618✔
3721
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
5,070,618✔
3722
      if (NULL == pCtx || NULL == pRow) {
5,070,618✔
3723
        code = terrno;
×
3724
        goto _exit;
×
3725
      }
3726
      code = funcInputGetNextRow(pCtx, pRow, &result);
5,070,618✔
3727
      if (TSDB_CODE_SUCCESS != code) {
5,070,618✔
3728
        goto _exit;
×
3729
      }
3730
      if (!result) {
5,070,618✔
3731
        // rows are not equal
3732
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3733
        goto _exit;
×
3734
      }
3735
      if (!diffResultIsNull(pCtx, pRow)) {
5,070,618✔
3736
        hasNotNullValue = true;
5,005,350✔
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,999✔
3753
        }
3754
        newRow = true;
2,147,483,647✔
3755
      } else {
3756
        code = trySetPreVal(pCtx, pRow);
5,771,007✔
3757
        if (code != TSDB_CODE_SUCCESS) {
5,771,007✔
3758
          goto _exit;
×
3759
        }
3760
      }
3761
    }
3762
    if (newRow) ++numOfElems;
2,147,483,647✔
3763
  }
3764

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

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

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

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

3798
  return TSDB_CODE_SUCCESS;
39,297✔
3799
}
3800

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

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

3807
    return TSDB_CODE_SUCCESS;
14,421✔
3808
  }
3809

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

3841
  return TSDB_CODE_SUCCESS;
99,067✔
3842
}
3843

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

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

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

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

3867
  return TSDB_CODE_SUCCESS;
127,472✔
3868
}
3869

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

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

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

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

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

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

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

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

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

3997
        if (!pFillforwardInfo->nonnull) {
78,091✔
3998
          pFillforwardInfo->nonnull = true;
38,423✔
3999
        }
4000
      }
4001

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

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

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

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

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

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

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

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

4041
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,117,860✔
4042
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2,117,860✔
4043
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2,119,075✔
4044
  return true;
2,118,457✔
4045
}
4046

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

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

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

4060
  pRes->nullTupleSaved = false;
7,732,248✔
4061
  pRes->nullTuplePos.pageId = -1;
7,730,764✔
4062
  return TSDB_CODE_SUCCESS;
7,731,630✔
4063
}
4064

4065
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
2,085,273,687✔
4066
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,085,273,687✔
4067
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
2,085,683,342✔
4068
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
2,085,726,467✔
4069

4070
  return pRes;
2,083,021,084✔
4071
}
4072

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

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

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

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

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

4088
  int32_t start = pInput->startRowIndex;
8,623,215✔
4089
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,236,138,123✔
4090
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,228,859,033✔
4091
      continue;
2,677,182✔
4092
    }
4093

4094
    numOfElems++;
1,224,534,327✔
4095
    char*   data = colDataGetData(pCol, i);
1,224,534,327✔
4096
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
1,230,615,506✔
4097
    if (code != TSDB_CODE_SUCCESS) {
1,224,835,872✔
4098
      return code;
×
4099
    }
4100
  }
4101

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

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

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

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

4122
  int32_t start = pInput->startRowIndex;
2,808,109✔
4123
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
845,470,723✔
4124
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
842,662,084✔
4125
      continue;
2,656,196✔
4126
    }
4127

4128
    numOfElems++;
839,997,844✔
4129
    char*   data = colDataGetData(pCol, i);
839,997,844✔
4130
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
840,074,332✔
4131
    if (code != TSDB_CODE_SUCCESS) {
840,005,800✔
4132
      return code;
×
4133
    }
4134
  }
4135

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

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

4147
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
506,174,533✔
4148
  uint16_t type = *(uint16_t*)param;
506,174,533✔
4149

4150
  STopBotResItem* val1 = (STopBotResItem*)p1;
506,175,883✔
4151
  STopBotResItem* val2 = (STopBotResItem*)p2;
506,175,883✔
4152

4153
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
506,175,883✔
4154
    if (val1->v.i == val2->v.i) {
322,597,295✔
4155
      return 0;
55,901,281✔
4156
    }
4157

4158
    return (val1->v.i > val2->v.i) ? 1 : -1;
266,815,660✔
4159
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
183,578,588✔
4160
    if (val1->v.u == val2->v.u) {
89,978,045✔
4161
      return 0;
18,755,624✔
4162
    }
4163

4164
    return (val1->v.u > val2->v.u) ? 1 : -1;
71,224,054✔
4165
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
93,600,649✔
4166
    if (val1->v.f == val2->v.f) {
4,434,407✔
4167
      return 0;
28,287✔
4168
    }
4169

4170
    return (val1->v.f > val2->v.f) ? 1 : -1;
4,406,120✔
4171
  }
4172

4173
  if (val1->v.d == val2->v.d) {
89,166,242✔
4174
    return 0;
4,939✔
4175
  }
4176

4177
  return (val1->v.d > val2->v.d) ? 1 : -1;
89,168,551✔
4178
}
4179

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

4185
  SVariant val = {0};
2,061,308,048✔
4186
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
2,061,779,699✔
4187

4188
  STopBotResItem* pItems = pRes->pItems;
2,063,574,280✔
4189

4190
  // not full yet
4191
  if (pEntryInfo->numOfRes < pRes->maxSize) {
2,065,272,171✔
4192
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
44,764,502✔
4193
    pItem->v = val;
44,764,486✔
4194
    pItem->uid = uid;
44,763,868✔
4195

4196
    // save the data of this tuple
4197
    if (pCtx->subsidiaries.num > 0) {
44,763,967✔
4198
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
12,433,073✔
4199
      if (code != TSDB_CODE_SUCCESS) {
12,432,851✔
4200
        return code;
×
4201
      }
4202
    }
4203
#ifdef BUF_PAGE_DEBUG
4204
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
4205
           pItem->tuplePos.offset);
4206
#endif
4207
    // allocate the buffer and keep the data of this row into the new allocated buffer
4208
    pEntryInfo->numOfRes++;
44,763,732✔
4209
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
44,764,264✔
4210
                        topBotResComparFn, !isTopQuery);
44,764,264✔
4211
    if (code != TSDB_CODE_SUCCESS) {
44,766,283✔
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,017,694,673✔
4216
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
1,174,636,410✔
4217
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
1,165,576,839✔
4218
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
1,165,423,045✔
4219
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
1,986,937,513✔
4220
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
828,784,022✔
4221
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
827,721,212✔
4222
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
827,626,164✔
4223
      // replace the old data and the coresponding tuple data
4224
      STopBotResItem* pItem = &pItems[0];
36,861,213✔
4225
      pItem->v = val;
36,861,213✔
4226
      pItem->uid = uid;
37,798,159✔
4227

4228
      // save the data of this tuple by over writing the old data
4229
      if (pCtx->subsidiaries.num > 0) {
37,799,395✔
4230
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
20,308,299✔
4231
        if (code != TSDB_CODE_SUCCESS) {
20,307,096✔
4232
          return code;
×
4233
        }
4234
      }
4235
#ifdef BUF_PAGE_DEBUG
4236
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
4237
#endif
4238
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
37,798,106✔
4239
                            topBotResComparFn, NULL, !isTopQuery);
37,796,956✔
4240
      if (code != TSDB_CODE_SUCCESS) {
37,795,730✔
4241
        return code;
×
4242
      }
4243
    }
4244
  }
4245

4246
  return TSDB_CODE_SUCCESS;
2,065,756,076✔
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,
125,486,236✔
4277
                           char* buf, char** res) {
4278
  char* nullList = buf;
125,486,236✔
4279
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
125,486,236✔
4280

4281
  int32_t offset = 0;
125,488,853✔
4282
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
391,593,302✔
4283
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
266,104,503✔
4284

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

4291
    if (fmIsSelectValueFunc(pc->functionId)) {
266,098,631✔
4292
      SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
266,096,685✔
4293
      int32_t      srcSlotId = pFuncParam->pCol->slotId;
266,097,124✔
4294

4295
      SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
266,098,539✔
4296
      if (NULL == pCol) {
266,099,504✔
4297
        return TSDB_CODE_OUT_OF_RANGE;
×
4298
      }
4299
      if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
532,197,680✔
4300
        offset += pCol->info.bytes;
72,237,293✔
4301
        continue;
72,237,293✔
4302
      }
4303

4304
      char* p = colDataGetData(pCol, rowIndex);
193,862,970✔
4305
      if (IS_VAR_DATA_TYPE(pCol->info.type)) {
193,868,147✔
4306
        int32_t bytes = calcStrBytesByType(pCol->info.type, p);
9,081,625✔
4307
        (void)memcpy(pStart + offset, p, bytes);
9,086,394✔
4308
      } else {
4309
        (void)memcpy(pStart + offset, p, pCol->info.bytes);
184,778,760✔
4310
      }
4311

4312
      offset += pCol->info.bytes;
193,867,355✔
4313
      continue;
193,866,003✔
4314
    }
4315
  }
4316

4317
  *res = buf;
125,479,890✔
4318
  return TSDB_CODE_SUCCESS;
125,482,629✔
4319
}
4320

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

4327
    if (pHandle->currentPage == -1) {
229,674,239✔
4328
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
5,705,470✔
4329
      if (pPage == NULL) {
5,710,250✔
4330
        return terrno;
×
4331
      }
4332
      pPage->num = sizeof(SFilePage);
5,710,250✔
4333
    } else {
4334
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
223,966,636✔
4335
      if (pPage == NULL) {
223,943,441✔
4336
        return terrno;
×
4337
      }
4338
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
223,943,441✔
4339
        // current page is all used, let's prepare a new buffer page
4340
        releaseBufPage(pHandle->pBuf, pPage);
430,995✔
4341
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
430,995✔
4342
        if (pPage == NULL) {
430,995✔
4343
          return terrno;
×
4344
        }
4345
        pPage->num = sizeof(SFilePage);
430,995✔
4346
      }
4347
    }
4348

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

4352
    pPage->num += length;
229,649,121✔
4353
    setBufPageDirty(pPage, true);
229,656,900✔
4354
    releaseBufPage(pHandle->pBuf, pPage);
229,655,933✔
4355
  } else {  // other tuple save policy
4356
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
×
4357
      p.streamTupleKey = *key;
×
4358
    }
4359
  }
4360

4361
  *pPos = p;
229,650,955✔
4362
  return TSDB_CODE_SUCCESS;
229,650,417✔
4363
}
4364

4365
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
85,399,169✔
4366
  int32_t code = prepareBuf(pCtx);
85,399,169✔
4367
  if (TSDB_CODE_SUCCESS != code) {
85,401,206✔
4368
    return code;
×
4369
  }
4370

4371
  SWinKey key = {0};
85,401,206✔
4372
  if (pCtx->saveHandle.pBuf == NULL) {
85,401,645✔
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;
85,401,065✔
4386
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
85,399,086✔
4387
  if (TSDB_CODE_SUCCESS != code) {
85,401,431✔
4388
    return code;
×
4389
  }
4390
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
85,401,431✔
4391
}
4392

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

4410
  return TSDB_CODE_SUCCESS;
40,086,680✔
4411
}
4412

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

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

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

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

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

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

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

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

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

4491
  return code;
7,671,814✔
4492
}
4493

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

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

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

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

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

4567
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
8,398,137✔
4568

4569
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
3,782,913✔
4570
  pEnv->calcMemSize = sizeof(SSpreadInfo);
3,782,913✔
4571
  return true;
3,783,989✔
4572
}
4573

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

4582
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
116,472,652✔
4583
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
116,473,162✔
4584
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
116,472,690✔
4585
  pInfo->hasResult = false;
116,472,686✔
4586
  return TSDB_CODE_SUCCESS;
116,471,556✔
4587
}
4588

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

4592
  // Only the pre-computing information loaded and actual data does not loaded
4593
  SInputColumnInfoData* pInput = &pCtx->input;
167,680,155✔
4594
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
167,689,893✔
4595
  int32_t               type = pInput->pData[0]->info.type;
167,706,461✔
4596

4597
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
167,708,695✔
4598

4599
  if (pInput->colDataSMAIsSet) {
167,706,972✔
4600
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
46,132,180✔
4601
    if (numOfElems == 0) {
46,136,517✔
4602
      goto _spread_over;
32,731,885✔
4603
    }
4604
    double tmin = 0.0, tmax = 0.0;
13,404,632✔
4605
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
13,404,632✔
4606
      tmin = (double)GET_INT64_VAL(&pAgg->min);
6,859,118✔
4607
      tmax = (double)GET_INT64_VAL(&pAgg->max);
6,857,882✔
4608
    } else if (IS_FLOAT_TYPE(type)) {
6,545,514✔
4609
      tmin = GET_DOUBLE_VAL(&pAgg->min);
618✔
4610
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4611
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
6,544,896✔
4612
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
6,545,514✔
4613
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
6,544,896✔
4614
    }
4615

4616
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
13,403,396✔
4617
      SET_DOUBLE_VAL(&pInfo->min, tmin);
611,142✔
4618
    }
4619

4620
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
13,405,250✔
4621
      SET_DOUBLE_VAL(&pInfo->max, tmax);
646,511✔
4622
    }
4623

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

4627
    int32_t start = pInput->startRowIndex;
121,573,971✔
4628
    // check the valid data one by one
4629
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,068,347,406✔
4630
      if (colDataIsNull_f(pCol, i)) {
946,772,629✔
4631
        continue;
302,532,906✔
4632
      }
4633

4634
      char* data = colDataGetData(pCol, i);
644,239,909✔
4635

4636
      double v = 0;
644,245,773✔
4637
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
644,245,773✔
4638
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
644,241,343✔
4639
        SET_DOUBLE_VAL(&pInfo->min, v);
124,604,676✔
4640
      }
4641

4642
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
644,237,771✔
4643
        SET_DOUBLE_VAL(&pInfo->max, v);
118,071,426✔
4644
      }
4645

4646
      numOfElems += 1;
644,241,621✔
4647
    }
4648
  }
4649

4650
_spread_over:
121,554,894✔
4651
  // data in the check operation are all null, not output
4652
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
167,690,163✔
4653
  if (numOfElems > 0) {
167,689,205✔
4654
    pInfo->hasResult = true;
120,129,019✔
4655
  }
4656

4657
  return TSDB_CODE_SUCCESS;
167,674,344✔
4658
}
4659

4660
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
7,690,963✔
4661
  pOutput->hasResult = pInput->hasResult;
7,690,963✔
4662
  if (pInput->max > pOutput->max) {
7,690,963✔
4663
    pOutput->max = pInput->max;
5,382,143✔
4664
  }
4665

4666
  if (pInput->min < pOutput->min) {
7,690,963✔
4667
    pOutput->min = pInput->min;
5,374,765✔
4668
  }
4669
}
7,690,963✔
4670

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

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

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

4684
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,699,136✔
4685

4686
  int32_t start = pInput->startRowIndex;
5,699,136✔
4687
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
13,654,888✔
4688
    if (colDataIsNull_s(pCol, i)) continue;
15,911,504✔
4689
    char*        data = colDataGetData(pCol, i);
7,955,752✔
4690
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
7,955,752✔
4691
    if (pInputInfo->hasResult) {
7,955,752✔
4692
      spreadTransferInfo(pInputInfo, pInfo);
7,690,963✔
4693
    }
4694
  }
4695

4696
  if (pInfo->hasResult) {
5,699,136✔
4697
    GET_RES_INFO(pCtx)->numOfRes = 1;
5,558,684✔
4698
  }
4699

4700
  return TSDB_CODE_SUCCESS;
5,699,136✔
4701
}
4702

4703
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
100,677,093✔
4704
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
100,677,093✔
4705
  if (pInfo->hasResult == true) {
100,677,093✔
4706
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
85,924,217✔
4707
  } else {
4708
    GET_RES_INFO(pCtx)->isNullRes = 1;
14,752,366✔
4709
  }
4710
  return functionFinalize(pCtx, pBlock);
100,676,583✔
4711
}
4712

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

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

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

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

4738
_exit:
7,969,540✔
4739
  taosMemoryFree(res);
7,969,540✔
4740
  return code;
7,967,872✔
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,392,336✔
4758
  pEnv->calcMemSize = sizeof(SElapsedInfo);
2,392,336✔
4759
  return true;
2,393,338✔
4760
}
4761

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

4770
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,631,887✔
4771
  pInfo->result = 0;
4,631,887✔
4772
  pInfo->min = TSKEY_MAX;
4,631,887✔
4773
  pInfo->max = 0;
4,631,887✔
4774

4775
  if (pCtx->numOfParams > 1) {
4,631,887✔
4776
    pInfo->timeUnit = pCtx->param[1].param.i;
2,957,337✔
4777
  } else {
4778
    pInfo->timeUnit = 1;
1,674,550✔
4779
  }
4780

4781
  return TSDB_CODE_SUCCESS;
4,631,887✔
4782
}
4783

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

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

4791
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,697,432✔
4792

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

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

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

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

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

4851
      if (pCtx->end.key == INT64_MIN) {
4,662,298✔
4852
        pInfo->max =
4,601,972✔
4853
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
4,601,972✔
4854
      } else {
4855
        pInfo->max = pCtx->end.key + 1;
60,864✔
4856
      }
4857
    }
4858
  }
4859

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

4864
  return TSDB_CODE_SUCCESS;
4,696,430✔
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,631,887✔
4900
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,631,887✔
4901
  double        result = (double)(pInfo->max - pInfo->min);
4,631,887✔
4902
  pInfo->result = fabs(result) / pInfo->timeUnit;
4,631,887✔
4903
  return functionFinalize(pCtx, pBlock);
4,631,887✔
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() {
756,932✔
4949
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
756,932✔
4950
}
4951

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

4957
static int8_t getHistogramBinType(char* binTypeStr) {
937,652✔
4958
  int8_t binType;
4959
  if (strcasecmp(binTypeStr, "user_input") == 0) {
937,652✔
4960
    binType = USER_INPUT_BIN;
465,277✔
4961
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
472,375✔
4962
    binType = LINEAR_BIN;
294,642✔
4963
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
177,733✔
4964
    binType = LOG_BIN;
176,698✔
4965
  } else {
4966
    binType = UNKNOWN_BIN;
1,035✔
4967
  }
4968

4969
  return binType;
937,652✔
4970
}
4971

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

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

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

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

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

5006
    int32_t counter = (int32_t)count->valueint;
471,847✔
5007
    if (infinity->valueint == false) {
471,847✔
5008
      startIndex = 0;
415,570✔
5009
      numOfBins = counter + 1;
415,570✔
5010
    } else {
5011
      startIndex = 1;
56,277✔
5012
      numOfBins = counter + 3;
56,277✔
5013
    }
5014

5015
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
471,847✔
5016
    if (NULL == intervals) {
471,466✔
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) {
471,466✔
5022
      // linear bin process
5023
      if (width->valuedouble == 0) {
294,261✔
5024
        taosMemoryFree(intervals);
×
5025
        cJSON_Delete(binDesc);
×
5026
        return TSDB_CODE_FAILED;
×
5027
      }
5028
      for (int i = 0; i < counter + 1; ++i) {
1,750,701✔
5029
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
1,456,059✔
5030
        if (isinf(intervals[startIndex])) {
1,456,059✔
5031
          taosMemoryFree(intervals);
×
5032
          cJSON_Delete(binDesc);
×
5033
          return TSDB_CODE_FAILED;
×
5034
        }
5035
        startIndex++;
1,456,059✔
5036
      }
5037
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
177,205✔
5038
      // log bin process
5039
      if (start->valuedouble == 0) {
177,205✔
5040
        taosMemoryFree(intervals);
×
5041
        cJSON_Delete(binDesc);
×
5042
        return TSDB_CODE_FAILED;
×
5043
      }
5044
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
177,205✔
5045
        taosMemoryFree(intervals);
×
5046
        cJSON_Delete(binDesc);
×
5047
        return TSDB_CODE_FAILED;
×
5048
      }
5049
      for (int i = 0; i < counter + 1; ++i) {
930,040✔
5050
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
751,821✔
5051
        if (isinf(intervals[startIndex])) {
752,328✔
5052
          taosMemoryFree(intervals);
×
5053
          cJSON_Delete(binDesc);
×
5054
          return TSDB_CODE_FAILED;
×
5055
        }
5056
        startIndex++;
752,835✔
5057
      }
5058
    } else {
5059
      taosMemoryFree(intervals);
×
5060
      cJSON_Delete(binDesc);
×
5061
      return TSDB_CODE_FAILED;
×
5062
    }
5063

5064
    if (infinity->valueint == true) {
472,861✔
5065
      intervals[0] = -INFINITY;
56,277✔
5066
      intervals[numOfBins - 1] = INFINITY;
56,277✔
5067
      // in case of desc bin orders, -inf/inf should be swapped
5068
      if (numOfBins < 4) {
56,277✔
5069
        return TSDB_CODE_FAILED;
×
5070
      }
5071
      if (intervals[1] > intervals[numOfBins - 2]) {
56,277✔
5072
        TSWAP(intervals[0], intervals[numOfBins - 1]);
56,277✔
5073
      }
5074
    }
5075
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
465,277✔
5076
    if (binType != USER_INPUT_BIN) {
465,805✔
5077
      cJSON_Delete(binDesc);
×
5078
      return TSDB_CODE_FAILED;
×
5079
    }
5080
    numOfBins = cJSON_GetArraySize(binDesc);
465,805✔
5081
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
465,805✔
5082
    if (NULL == intervals) {
465,277✔
5083
      cJSON_Delete(binDesc);
×
5084
      qError("histogram function out of memory");
×
5085
      return terrno;
×
5086
    }
5087
    cJSON* bin = binDesc->child;
465,277✔
5088
    if (bin == NULL) {
465,805✔
5089
      taosMemoryFree(intervals);
×
5090
      cJSON_Delete(binDesc);
×
5091
      return TSDB_CODE_FAILED;
×
5092
    }
5093
    int i = 0;
465,805✔
5094
    while (bin) {
2,016,913✔
5095
      intervals[i] = bin->valuedouble;
1,552,702✔
5096
      if (!cJSON_IsNumber(bin)) {
1,553,240✔
5097
        taosMemoryFree(intervals);
×
5098
        cJSON_Delete(binDesc);
×
5099
        return TSDB_CODE_FAILED;
×
5100
      }
5101
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
1,552,174✔
5102
        taosMemoryFree(intervals);
×
5103
        cJSON_Delete(binDesc);
×
5104
        return TSDB_CODE_FAILED;
×
5105
      }
5106
      bin = bin->next;
1,552,174✔
5107
      i++;
1,551,108✔
5108
    }
5109
  } else {
5110
    cJSON_Delete(binDesc);
×
5111
    return TSDB_CODE_FAILED;
×
5112
  }
5113

5114
  pInfo->numOfBins = numOfBins - 1;
935,551✔
5115
  pInfo->normalized = normalized;
937,652✔
5116
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
3,872,577✔
5117
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
2,939,459✔
5118
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
2,938,372✔
5119
    pInfo->bins[i].count = 0;
2,936,428✔
5120
  }
5121

5122
  taosMemoryFree(intervals);
936,596✔
5123
  cJSON_Delete(binDesc);
937,652✔
5124

5125
  return TSDB_CODE_SUCCESS;
937,662✔
5126
}
5127

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

5136
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
938,190✔
5137
  pInfo->numOfBins = 0;
937,652✔
5138
  pInfo->totalCount = 0;
937,652✔
5139
  pInfo->normalized = 0;
938,190✔
5140

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

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

5167
  return TSDB_CODE_SUCCESS;
937,134✔
5168
}
5169

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

5173
  SInputColumnInfoData* pInput = &pCtx->input;
1,092,525✔
5174
  SColumnInfoData*      pCol = pInput->pData[0];
1,093,560✔
5175

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

5178
  int32_t start = pInput->startRowIndex;
1,093,560✔
5179
  int32_t numOfRows = pInput->numOfRows;
1,093,591✔
5180

5181
  int32_t numOfElems = 0;
1,096,495✔
5182
  for (int32_t i = start; i < numOfRows + start; ++i) {
158,047,826✔
5183
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
156,953,728✔
5184
      continue;
104,298,916✔
5185
    }
5186

5187
    numOfElems++;
52,643,333✔
5188

5189
    char*  data = colDataGetData(pCol, i);
52,643,333✔
5190
    double v;
5191
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
52,702,064✔
5192

5193
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
219,484,440✔
5194
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
192,197,391✔
5195
        pInfo->bins[k].count++;
25,365,366✔
5196
        pInfo->totalCount++;
25,365,366✔
5197
        break;
25,365,366✔
5198
      }
5199
    }
5200
  }
5201

5202
  if (!isPartial) {
1,094,098✔
5203
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
740,719✔
5204
  } else {
5205
    GET_RES_INFO(pCtx)->numOfRes = 1;
353,379✔
5206
  }
5207
  return TSDB_CODE_SUCCESS;
1,093,560✔
5208
}
5209

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

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

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

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

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

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

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

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

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

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

5258
  if (pInfo->normalized) {
915,827✔
5259
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
2,156,798✔
5260
      if (pInfo->totalCount != 0) {
1,653,831✔
5261
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
178,395✔
5262
      } else {
5263
        pInfo->bins[k].percentage = 0;
1,477,971✔
5264
      }
5265
    }
5266
  }
5267

5268
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
3,721,655✔
5269
    int32_t len;
5270
    char    buf[512] = {0};
2,805,828✔
5271
    if (!pInfo->normalized) {
2,805,321✔
5272
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
1,149,462✔
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,
1,656,366✔
5277
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
5278
                     pInfo->bins[i].percentage);
5279
    }
5280
    varDataSetLen(buf, len);
2,805,828✔
5281
    code = colDataSetVal(pCol, currentRow, buf, false);
2,805,828✔
5282
    if (TSDB_CODE_SUCCESS != code) {
2,805,828✔
5283
      return code;
×
5284
    }
5285
    currentRow++;
2,805,828✔
5286
  }
5287

5288
  return code;
915,827✔
5289
}
5290

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

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

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

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

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

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

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

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

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

5337
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
576,470,101✔
5338
  uint64_t hash = MurmurHash3_64(data, bytes);
576,470,101✔
5339
  int32_t  index = hash & HLL_BUCKET_MASK;
576,443,694✔
5340
  hash >>= HLL_BUCKET_BITS;
576,443,694✔
5341
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
576,443,694✔
5342
  uint64_t bit = 1;
576,443,694✔
5343
  uint8_t  count = 1;
576,443,694✔
5344
  while ((hash & bit) == 0) {
1,217,763,770✔
5345
    count++;
641,320,076✔
5346
    bit <<= 1;
641,320,076✔
5347
  }
5348
  *buk = index;
576,443,694✔
5349
  return count;
576,446,108✔
5350
}
5351

5352
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
9,181,811✔
5353
  uint64_t* word = (uint64_t*)buckets;
9,181,811✔
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;
122,428,866✔
5361
      bucketHisto[bytes[0]]++;
122,428,866✔
5362
      bucketHisto[bytes[1]]++;
119,114,836✔
5363
      bucketHisto[bytes[2]]++;
119,114,836✔
5364
      bucketHisto[bytes[3]]++;
119,114,310✔
5365
      bucketHisto[bytes[4]]++;
119,114,836✔
5366
      bucketHisto[bytes[5]]++;
119,114,836✔
5367
      bucketHisto[bytes[6]]++;
119,114,836✔
5368
      bucketHisto[bytes[7]]++;
118,959,892✔
5369
    }
5370
    word++;
2,147,483,647✔
5371
  }
5372
}
8,938,581✔
5373
static double hllTau(double x) {
9,181,811✔
5374
  if (x == 0. || x == 1.) return 0.;
9,181,811✔
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,181,811✔
5388
  if (x == 1.0) return INFINITY;
9,181,811✔
5389
  double zPrime;
5390
  double y = 1;
6,241,122✔
5391
  double z = x;
6,241,122✔
5392
  do {
5393
    x *= x;
119,508,825✔
5394
    zPrime = z;
119,508,825✔
5395
    z += x * y;
119,508,825✔
5396
    y += y;
119,508,825✔
5397
  } while (zPrime != z);
119,508,825✔
5398
  return z;
6,241,122✔
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,181,811✔
5404
  double  m = HLL_BUCKETS;
9,181,811✔
5405
  int32_t buckethisto[64] = {0};
9,181,811✔
5406
  hllBucketHisto(buckets, buckethisto);
9,181,811✔
5407

5408
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
9,181,811✔
5409
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
468,256,759✔
5410
    z += buckethisto[j];
459,074,948✔
5411
    z *= 0.5;
459,074,948✔
5412
  }
5413

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

5417
  return (uint64_t)E;
9,181,811✔
5418
}
5419

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

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

5426
  int32_t type = pCol->info.type;
9,440,358✔
5427
  int32_t bytes = pCol->info.bytes;
9,440,208✔
5428

5429
  int32_t start = pInput->startRowIndex;
9,438,744✔
5430
  int32_t numOfRows = pInput->numOfRows;
9,440,746✔
5431

5432
  int32_t numOfElems = 0;
9,438,206✔
5433
  if (IS_NULL_TYPE(type)) {
9,438,206✔
5434
    goto _hll_over;
144,582✔
5435
  }
5436

5437
  for (int32_t i = start; i < numOfRows + start; ++i) {
743,181,226✔
5438
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
902,403,608✔
5439
      continue;
157,449,188✔
5440
    }
5441

5442
    numOfElems++;
576,436,562✔
5443

5444
    char* data = colDataGetData(pCol, i);
576,436,562✔
5445
    if (IS_VAR_DATA_TYPE(type)) {
576,471,703✔
5446
      if (IS_STR_DATA_BLOB(type)) {
100,229,368✔
5447
        bytes = blobDataLen(data);
×
5448
        data = blobDataVal(data);
×
5449
      } else {
5450
        bytes = varDataLen(data);
100,237,438✔
5451
        data = varDataVal(data);
100,237,438✔
5452
      }
5453
    }
5454

5455
    int32_t index = 0;
576,480,179✔
5456
    uint8_t count = hllCountNum(data, bytes, &index);
576,468,428✔
5457
    uint8_t oldcount = pInfo->buckets[index];
576,436,101✔
5458
    if (count > oldcount) {
576,444,010✔
5459
      pInfo->buckets[index] = count;
167,854,212✔
5460
    }
5461
  }
5462

5463
_hll_over:
9,290,219✔
5464
  pInfo->totalCount += numOfElems;
9,434,801✔
5465

5466
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
9,440,746✔
5467
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
490,739✔
5468
  } else {
5469
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
8,951,083✔
5470
  }
5471

5472
  return TSDB_CODE_SUCCESS;
9,440,746✔
5473
}
5474

5475
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
264,655✔
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];
53,211,970✔
5479
    }
5480
  }
5481
  pOutput->totalCount += pInput->totalCount;
157,165✔
5482
}
264,655✔
5483

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

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

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

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

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

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

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

5514
  return TSDB_CODE_SUCCESS;
264,655✔
5515
}
5516

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

5520
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
9,181,811✔
5521
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
9,181,811✔
5522
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
9,181,811✔
5523
    pInfo->numOfRes = 1;
2,449,895✔
5524
  }
5525

5526
  return functionFinalize(pCtx, pBlock);
9,181,273✔
5527
}
5528

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

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

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

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

5551
_exit:
264,655✔
5552
  taosMemoryFree(res);
264,655✔
5553
  return code;
264,655✔
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,345,085✔
5570
  pEnv->calcMemSize = sizeof(SStateInfo);
1,345,085✔
5571
  return true;
1,345,613✔
5572
}
5573

5574
static int8_t getStateOpType(char* opStr) {
1,365,965✔
5575
  int8_t opType;
5576
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,365,965✔
5577
    opType = STATE_OPER_LT;
486,269✔
5578
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
879,696✔
5579
    opType = STATE_OPER_GT;
214,358✔
5580
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
665,338✔
5581
    opType = STATE_OPER_LE;
114,402✔
5582
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
550,936✔
5583
    opType = STATE_OPER_GE;
112,494✔
5584
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
438,442✔
5585
    opType = STATE_OPER_NE;
110,636✔
5586
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
327,806✔
5587
    opType = STATE_OPER_EQ;
327,806✔
5588
  } else {
5589
    opType = STATE_OPER_INVALID;
×
5590
  }
5591

5592
  return opType;
1,365,965✔
5593
}
5594

5595
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
148,944,443✔
5596
  char* data = colDataGetData(pCol, index);
148,944,443✔
5597
  switch (pCol->info.type) {
148,943,915✔
5598
    case TSDB_DATA_TYPE_TINYINT: {
36,139,638✔
5599
      int8_t v = *(int8_t*)data;
36,139,638✔
5600
      STATE_COMP(op, v, param);
36,139,638✔
5601
      break;
×
5602
    }
5603
    case TSDB_DATA_TYPE_UTINYINT: {
35,282,880✔
5604
      uint8_t v = *(uint8_t*)data;
35,282,880✔
5605
      STATE_COMP(op, v, param);
35,282,880✔
5606
      break;
×
5607
    }
5608
    case TSDB_DATA_TYPE_SMALLINT: {
32,540,196✔
5609
      int16_t v = *(int16_t*)data;
32,540,196✔
5610
      STATE_COMP(op, v, param);
32,540,196✔
5611
      break;
×
5612
    }
5613
    case TSDB_DATA_TYPE_USMALLINT: {
630,720✔
5614
      uint16_t v = *(uint16_t*)data;
630,720✔
5615
      STATE_COMP(op, v, param);
630,720✔
5616
      break;
×
5617
    }
5618
    case TSDB_DATA_TYPE_INT: {
35,913,321✔
5619
      int32_t v = *(int32_t*)data;
35,913,321✔
5620
      STATE_COMP(op, v, param);
35,913,321✔
5621
      break;
×
5622
    }
5623
    case TSDB_DATA_TYPE_UINT: {
630,720✔
5624
      uint32_t v = *(uint32_t*)data;
630,720✔
5625
      STATE_COMP(op, v, param);
630,720✔
5626
      break;
×
5627
    }
5628
    case TSDB_DATA_TYPE_BIGINT: {
701,049✔
5629
      int64_t v = *(int64_t*)data;
701,049✔
5630
      STATE_COMP(op, v, param);
701,049✔
5631
      break;
×
5632
    }
5633
    case TSDB_DATA_TYPE_UBIGINT: {
630,720✔
5634
      uint64_t v = *(uint64_t*)data;
630,720✔
5635
      STATE_COMP(op, v, param);
630,720✔
5636
      break;
×
5637
    }
5638
    case TSDB_DATA_TYPE_FLOAT: {
691,396✔
5639
      float v = *(float*)data;
691,396✔
5640
      STATE_COMP(op, v, param);
691,396✔
5641
      break;
×
5642
    }
5643
    case TSDB_DATA_TYPE_DOUBLE: {
5,783,803✔
5644
      double v = *(double*)data;
5,783,803✔
5645
      STATE_COMP(op, v, param);
5,783,803✔
5646
      break;
×
5647
    }
5648
    default: {
×
5649
      return false;
×
5650
    }
5651
  }
5652
  return false;
×
5653
}
5654

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

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

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

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

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

5673
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
85,394,184✔
5674
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
85,061,765✔
5675
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
860✔
5676
    } else {
5677
      pInfo->prevTs = tsList[i];
85,060,905✔
5678
    }
5679

5680
    pInfo->isPrevTsSet = true;
85,060,905✔
5681
    numOfElems++;
85,060,905✔
5682

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

5695
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
80,419,953✔
5696

5697
    int64_t output = -1;
80,419,953✔
5698
    if (ret) {
80,419,953✔
5699
      output = ++pInfo->count;
32,898,916✔
5700
    } else {
5701
      pInfo->count = 0;
47,521,037✔
5702
    }
5703
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
80,419,953✔
5704
    if (TSDB_CODE_SUCCESS != code) {
80,419,953✔
5705
      return code;
×
5706
    }
5707

5708
    // handle selectivity
5709
    if (pCtx->subsidiaries.num > 0) {
80,419,953✔
5710
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
853,348✔
5711
      if (TSDB_CODE_SUCCESS != code) {
853,348✔
5712
        return code;
×
5713
      }
5714
    }
5715
  }
5716

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

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

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

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

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

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

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

5745
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
93,340,748✔
5746
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
92,308,922✔
5747
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
860✔
5748
    } else {
5749
      pInfo->prevTs = tsList[i];
92,308,062✔
5750
    }
5751

5752
    pInfo->isPrevTsSet = true;
92,308,062✔
5753
    numOfElems++;
92,308,062✔
5754

5755
    if (colDataIsNull_f(pInputCol, i)) {
92,308,062✔
5756
      colDataSetNULL(pOutput, i);
23,783,572✔
5757
      // handle selectivity
5758
      if (pCtx->subsidiaries.num > 0) {
23,783,572✔
5759
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
7,726✔
5760
        if (TSDB_CODE_SUCCESS != code) {
7,726✔
5761
          return code;
×
5762
        }
5763
      }
5764
      continue;
23,783,572✔
5765
    }
5766

5767
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
68,524,490✔
5768
    int64_t output = -1;
68,524,490✔
5769
    if (ret) {
68,524,490✔
5770
      if (pInfo->durationStart == 0) {
25,689,999✔
5771
        output = 0;
5,739,113✔
5772
        pInfo->durationStart = tsList[i];
5,739,113✔
5773
      } else {
5774
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
19,950,886✔
5775
      }
5776
    } else {
5777
      pInfo->durationStart = 0;
42,834,491✔
5778
    }
5779
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
68,524,490✔
5780
    if (TSDB_CODE_SUCCESS != code) {
68,524,490✔
5781
      return code;
×
5782
    }
5783

5784
    // handle selectivity
5785
    if (pCtx->subsidiaries.num > 0) {
68,524,490✔
5786
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
95,944✔
5787
      if (TSDB_CODE_SUCCESS != code) {
95,944✔
5788
        return code;
×
5789
      }
5790
    }
5791
  }
5792

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

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

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

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

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

5813
  int32_t numOfElems = 0;
758,429✔
5814
  int32_t type = pInputCol->info.type;
758,429✔
5815
  int32_t startOffset = pCtx->offset;
758,810✔
5816
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
131,534,152✔
5817
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
130,782,578✔
5818
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
7,236✔
5819
    } else {
5820
      pSumRes->prevTs = tsList[i];
130,775,342✔
5821
    }
5822
    pSumRes->isPrevTsSet = true;
130,775,723✔
5823

5824
    int32_t pos = startOffset + numOfElems;
130,775,723✔
5825
    if (colDataIsNull_f(pInputCol, i)) {
130,775,723✔
5826
      // colDataSetNULL(pOutput, i);
5827
      continue;
62,652,949✔
5828
    }
5829

5830
    char* data = colDataGetData(pInputCol, i);
68,122,393✔
5831
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
100,654,655✔
5832
      int64_t v;
5833
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
32,531,881✔
5834
      pSumRes->isum += v;
32,531,881✔
5835
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
32,531,881✔
5836
      if (TSDB_CODE_SUCCESS != code) {
32,531,881✔
5837
        return code;
×
5838
      }
5839
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
47,975,295✔
5840
      uint64_t v;
5841
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
12,384,402✔
5842
      pSumRes->usum += v;
12,384,402✔
5843
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
12,384,402✔
5844
      if (TSDB_CODE_SUCCESS != code) {
12,384,402✔
5845
        return code;
×
5846
      }
5847
    } else if (IS_FLOAT_TYPE(type)) {
23,206,491✔
5848
      double v;
5849
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
23,206,872✔
5850
      pSumRes->dsum += v;
23,206,872✔
5851
      // check for overflow
5852
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
23,206,872✔
5853
        colDataSetNULL(pOutput, pos);
898✔
5854
      } else {
5855
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
23,205,974✔
5856
        if (TSDB_CODE_SUCCESS != code) {
23,205,974✔
5857
          return code;
×
5858
        }
5859
      }
5860
    }
5861

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

5870
    numOfElems++;
68,122,774✔
5871
  }
5872

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

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

5882
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
870,885✔
5883
  if (pResultInfo->initialized) {
870,885✔
5884
    return TSDB_CODE_SUCCESS;
386,609✔
5885
  }
5886
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
484,276✔
5887
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5888
  }
5889

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

5901
  return TSDB_CODE_SUCCESS;
483,243✔
5902
}
5903

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

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

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

5916
  int32_t numOfElems = 0;
478,972✔
5917
  int32_t type = pInputCol->info.type;
478,972✔
5918
  int32_t startOffset = pCtx->offset;
478,972✔
5919
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
127,659,622✔
5920
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
127,185,059✔
5921
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
860✔
5922
    } else {
5923
      pInfo->prevTs = tsList[i];
127,183,692✔
5924
    }
5925
    pInfo->isPrevTsSet = true;
127,184,706✔
5926

5927
    int32_t pos = startOffset + numOfElems;
127,185,720✔
5928
    if (colDataIsNull_f(pInputCol, i)) {
127,185,720✔
5929
      // colDataSetNULL(pOutput, i);
5930
      continue;
31,860,380✔
5931
    }
5932

5933
    char*  data = colDataGetData(pInputCol, i);
95,333,959✔
5934
    double v;
5935
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
95,333,959✔
5936

5937
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
95,333,959✔
5938
      pInfo->points[pInfo->pos] = v;
39,068,412✔
5939
      pInfo->sum += v;
39,068,412✔
5940
    } else {
5941
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
56,265,547✔
5942
        pInfo->sum += v;
89,245✔
5943
        pInfo->pointsMeet = true;
89,245✔
5944
      } else {
5945
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
56,176,302✔
5946
      }
5947

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

5960
      // handle selectivity
5961
      if (pCtx->subsidiaries.num > 0) {
56,265,547✔
5962
        code = appendSelectivityValue(pCtx, i, pos);
33,364✔
5963
        if (TSDB_CODE_SUCCESS != code) {
33,364✔
5964
          return code;
×
5965
        }
5966
      }
5967

5968
      numOfElems++;
56,265,547✔
5969
    }
5970

5971
    pInfo->pos++;
95,333,959✔
5972
    if (pInfo->pos == pInfo->numOfPoints) {
95,333,959✔
5973
      pInfo->pos = 0;
759,869✔
5974
    }
5975
  }
5976

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

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

5985
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
3,837,455✔
5986
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
3,837,455✔
5987

5988
  return pInfo;
3,837,016✔
5989
}
5990

5991
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
802,991✔
5992
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
802,991✔
5993
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
803,372✔
5994
  int32_t      numOfSamples = pVal->datum.i;
801,877✔
5995
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
801,877✔
5996
  return true;
801,496✔
5997
}
5998

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

6007
  taosSeedRand(taosSafeRand());
1,750,479✔
6008

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

6020
  return TSDB_CODE_SUCCESS;
1,751,446✔
6021
}
6022

6023
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
54,427,429✔
6024
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
54,427,429✔
6025
}
54,439,845✔
6026

6027
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
96,065,684✔
6028
  pInfo->totalPoints++;
96,065,684✔
6029
  if (pInfo->numSampled < pInfo->samples) {
96,065,684✔
6030
    sampleAssignResult(pInfo, data, pInfo->numSampled);
46,799,620✔
6031
    if (pCtx->subsidiaries.num > 0) {
46,798,507✔
6032
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,019,256✔
6033
      if (code != TSDB_CODE_SUCCESS) {
1,019,256✔
6034
        return code;
×
6035
      }
6036
    }
6037
    pInfo->numSampled++;
46,798,119✔
6038
  } else {
6039
    int32_t j = (int32_t)(taosRand() % (uint64_t)pInfo->totalPoints);
49,266,013✔
6040
    if (j < pInfo->samples) {
49,266,452✔
6041
      sampleAssignResult(pInfo, data, j);
7,639,010✔
6042
      if (pCtx->subsidiaries.num > 0) {
7,639,010✔
6043
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
350,265✔
6044
        if (code != TSDB_CODE_SUCCESS) {
349,877✔
6045
          return code;
×
6046
        }
6047
      }
6048
    }
6049
  }
6050

6051
  return TSDB_CODE_SUCCESS;
96,063,795✔
6052
}
6053

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

6058
  SInputColumnInfoData* pInput = &pCtx->input;
2,088,589✔
6059

6060
  SColumnInfoData* pInputCol = pInput->pData[0];
2,088,589✔
6061
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
152,035,873✔
6062
    if (colDataIsNull_s(pInputCol, i)) {
299,843,371✔
6063
      continue;
53,883,489✔
6064
    }
6065

6066
    char*   data = colDataGetData(pInputCol, i);
96,062,580✔
6067
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
96,066,409✔
6068
    if (code != TSDB_CODE_SUCCESS) {
96,063,795✔
6069
      return code;
×
6070
    }
6071
  }
6072

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

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

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

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

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

6098
  int32_t currentRow = pBlock->info.rows;
1,748,866✔
6099
  if (pInfo->numSampled == 0) {
1,748,866✔
6100
    colDataSetNULL(pCol, currentRow);
295,828✔
6101
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
295,828✔
6102
    return code;
295,828✔
6103
  }
6104
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
48,254,986✔
6105
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
46,802,387✔
6106
    if (TSDB_CODE_SUCCESS != code) {
46,801,999✔
6107
      return code;
×
6108
    }
6109
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
46,801,999✔
6110
    if (TSDB_CODE_SUCCESS != code) {
46,801,948✔
6111
      return code;
×
6112
    }
6113
  }
6114

6115
  return code;
1,453,038✔
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) {
779,736✔
6356
  pEnv->calcMemSize = sizeof(SModeInfo);
779,736✔
6357
  return true;
780,264✔
6358
}
6359

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

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

6382
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
954,754✔
6383
  if (NULL == pInfo->buf) {
954,754✔
6384
    taosHashCleanup(pInfo->pHash);
×
6385
    pInfo->pHash = NULL;
×
6386
    return terrno;
×
6387
  }
6388
  pCtx->needCleanup = true;
954,754✔
6389
  return TSDB_CODE_SUCCESS;
953,992✔
6390
}
6391

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

6398
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
780,390✔
6399
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
780,390✔
6400
    return;
67,389✔
6401
  }
6402
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
713,382✔
6403
}
6404

6405
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
144,266,190✔
6406
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
144,266,190✔
6407
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
16,283,192✔
6408
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
277,398✔
6409
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
16,010,464✔
6410
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
×
6411
    } else {
6412
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
16,010,464✔
6413
    }
6414
  } else {
6415
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
127,983,733✔
6416
  }
6417

6418
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
144,272,738✔
6419
}
6420

6421
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
313,619,395✔
6422
  int32_t code = TSDB_CODE_SUCCESS;
313,619,395✔
6423
  int32_t hashKeyBytes;
6424
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
313,619,395✔
6425
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
16,437,396✔
6426
  } else {
6427
    hashKeyBytes = pInfo->colBytes;
297,186,629✔
6428
  }
6429

6430
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
313,629,666✔
6431
  if (pHashItem == NULL) {
313,621,964✔
6432
    int32_t   size = sizeof(SModeItem);
144,266,092✔
6433
    SModeItem item = {0};
144,266,092✔
6434

6435
    item.count += 1;
144,266,522✔
6436
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
144,266,522✔
6437
    if (code != TSDB_CODE_SUCCESS) {
144,251,417✔
6438
      return code;
×
6439
    }
6440

6441
    if (pCtx->subsidiaries.num > 0) {
144,251,417✔
6442
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
266,186✔
6443
      if (code != TSDB_CODE_SUCCESS) {
266,186✔
6444
        return code;
×
6445
      }
6446
    }
6447

6448
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
144,251,798✔
6449
    if (code != TSDB_CODE_SUCCESS) {
144,271,840✔
6450
      return code;
×
6451
    }
6452
  } else {
6453
    pHashItem->count += 1;
169,355,872✔
6454
    if (pCtx->subsidiaries.num > 0) {
169,355,872✔
6455
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,453,166✔
6456
      if (code != TSDB_CODE_SUCCESS) {
3,453,166✔
6457
        return code;
×
6458
      }
6459
    }
6460
  }
6461

6462
  return code;
313,618,709✔
6463
}
6464

6465
int32_t modeFunction(SqlFunctionCtx* pCtx) {
1,573,290✔
6466
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,573,290✔
6467
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,573,290✔
6468

6469
  SInputColumnInfoData* pInput = &pCtx->input;
1,573,290✔
6470

6471
  SColumnInfoData* pInputCol = pInput->pData[0];
1,573,671✔
6472
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,573,290✔
6473

6474
  int32_t numOfElems = 0;
1,573,671✔
6475
  int32_t startOffset = pCtx->offset;
1,573,671✔
6476
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
335,769,768✔
6477
    if (colDataIsNull_s(pInputCol, i)) {
668,395,798✔
6478
      continue;
20,581,384✔
6479
    }
6480
    numOfElems++;
313,621,474✔
6481

6482
    char*   data = colDataGetData(pInputCol, i);
313,621,474✔
6483
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
313,624,876✔
6484
    if (code != TSDB_CODE_SUCCESS) {
313,618,562✔
6485
      modeFunctionCleanup(pInfo);
3,849✔
6486
      return code;
×
6487
    }
6488
  }
6489

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

6499
  SET_VAL(pResInfo, numOfElems, 1);
1,573,671✔
6500

6501
  return TSDB_CODE_SUCCESS;
1,573,671✔
6502
}
6503

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

6516
  STuplePos resDataPos, resTuplePos;
953,464✔
6517
  int32_t   maxCount = 0;
953,464✔
6518

6519
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
953,464✔
6520
  while (pIter != NULL) {
145,224,999✔
6521
    SModeItem* pItem = (SModeItem*)pIter;
144,271,535✔
6522
    if (pItem->count >= maxCount) {
144,271,535✔
6523
      maxCount = pItem->count;
140,929,642✔
6524
      resDataPos = pItem->dataPos;
140,929,642✔
6525
      resTuplePos = pItem->tuplePos;
140,929,642✔
6526
    }
6527

6528
    pIter = taosHashIterate(pInfo->pHash, pIter);
144,271,535✔
6529
  }
6530

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

6553
  modeFunctionCleanup(pInfo);
953,464✔
6554

6555
  return code;
953,464✔
6556
}
6557

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

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

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

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

6583
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
207,179,479✔
6584
    return (s.val + e.val) * (e.key - s.key) / 2;
186,905,376✔
6585
  }
6586

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

6592
int32_t twaFunction(SqlFunctionCtx* pCtx) {
8,022,624✔
6593
  int32_t               code = TSDB_CODE_SUCCESS;
8,022,624✔
6594
  SInputColumnInfoData* pInput = &pCtx->input;
8,022,624✔
6595
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,022,624✔
6596

6597
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,022,624✔
6598
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,022,624✔
6599
  SPoint1*             last = &pInfo->p;
8,022,624✔
6600

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

6606
  funcInputUpdate(pCtx);
8,022,624✔
6607
  SFuncInputRow row = {0};
8,022,624✔
6608
  bool          result = false;
8,022,624✔
6609
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
8,022,624✔
6610
    while (1) {
6611
      code = funcInputGetNextRow(pCtx, &row, &result);
5,344,220✔
6612
      if (TSDB_CODE_SUCCESS != code) {
5,344,220✔
6613
        return code;
×
6614
      }
6615
      if (!result) {
5,344,220✔
6616
        break;
766✔
6617
      }
6618
      if (row.isDataNull) {
5,343,454✔
6619
        continue;
766✔
6620
      }
6621

6622
      last->key = row.ts;
5,342,688✔
6623

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

6626
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
5,342,688✔
6627
      pInfo->win.skey = pCtx->start.key;
5,342,688✔
6628
      pInfo->numOfElems++;
5,342,688✔
6629
      break;
5,342,688✔
6630
    }
6631
  } else if (pInfo->p.key == INT64_MIN) {
2,679,170✔
6632
    while (1) {
6633
      code = funcInputGetNextRow(pCtx, &row, &result);
11,216,244✔
6634
      if (TSDB_CODE_SUCCESS != code) {
11,216,244✔
6635
        return code;
×
6636
      }
6637
      if (!result) {
11,216,244✔
6638
        break;
751,395✔
6639
      }
6640
      if (row.isDataNull) {
10,464,849✔
6641
        continue;
8,616,425✔
6642
      }
6643

6644
      last->key = row.ts;
1,848,424✔
6645

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

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

6654
  SPoint1 st = {0};
8,022,624✔
6655

6656
  // calculate the value of
6657
  while (1) {
6658
    code = funcInputGetNextRow(pCtx, &row, &result);
204,559,580✔
6659
    if (TSDB_CODE_SUCCESS != code) {
204,581,680✔
6660
      return code;
×
6661
    }
6662
    if (!result) {
204,581,680✔
6663
      break;
8,022,624✔
6664
    }
6665
    if (row.isDataNull) {
196,559,056✔
6666
      continue;
55,692✔
6667
    }
6668
    pInfo->numOfElems++;
196,503,364✔
6669
    switch (pInputCol->info.type) {
196,503,364✔
6670
      case TSDB_DATA_TYPE_TINYINT: {
14,417,575✔
6671
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
14,417,575✔
6672
        break;
14,417,133✔
6673
      }
6674
      case TSDB_DATA_TYPE_SMALLINT: {
14,631,124✔
6675
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
14,631,124✔
6676
        break;
14,631,124✔
6677
      }
6678
      case TSDB_DATA_TYPE_INT: {
93,022,188✔
6679
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
93,022,188✔
6680
        break;
93,021,304✔
6681
      }
6682
      case TSDB_DATA_TYPE_BIGINT: {
13,840,347✔
6683
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
13,840,347✔
6684
        break;
13,839,905✔
6685
      }
6686
      case TSDB_DATA_TYPE_FLOAT: {
11,886,278✔
6687
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
11,886,278✔
6688
        break;
11,886,278✔
6689
      }
6690
      case TSDB_DATA_TYPE_DOUBLE: {
13,574,162✔
6691
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
13,574,162✔
6692
        break;
13,574,162✔
6693
      }
6694
      case TSDB_DATA_TYPE_UTINYINT: {
8,974,456✔
6695
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
8,974,456✔
6696
        break;
8,974,898✔
6697
      }
6698
      case TSDB_DATA_TYPE_USMALLINT: {
8,975,340✔
6699
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
8,975,340✔
6700
        break;
8,975,340✔
6701
      }
6702
      case TSDB_DATA_TYPE_UINT: {
9,049,964✔
6703
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
9,049,964✔
6704
        break;
9,049,964✔
6705
      }
6706
      case TSDB_DATA_TYPE_UBIGINT: {
8,131,046✔
6707
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
8,131,046✔
6708
        break;
8,131,046✔
6709
      }
6710
      default: {
×
6711
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6712
      }
6713
    }
6714
    if (pInfo->p.key == st.key) {
196,501,154✔
6715
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6716
    }
6717

6718
    pInfo->dOutput += twa_get_area(pInfo->p, st);
196,501,596✔
6719
    pInfo->p = st;
196,479,054✔
6720
  }
6721

6722
  // the last interpolated time window value
6723
  if (pCtx->end.key != INT64_MIN) {
8,022,624✔
6724
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5,345,685✔
6725
    pInfo->p = pCtx->end;
5,345,685✔
6726
    pInfo->numOfElems += 1;
5,345,685✔
6727
  }
6728

6729
  pInfo->win.ekey = pInfo->p.key;
8,022,624✔
6730

6731
_twa_over:
8,022,624✔
6732
  SET_VAL(pResInfo, 1, 1);
8,022,624✔
6733
  return TSDB_CODE_SUCCESS;
8,022,624✔
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,931,106✔
6749
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,931,106✔
6750

6751
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,931,106✔
6752
  if (pInfo->numOfElems == 0) {
7,931,106✔
6753
    pResInfo->numOfRes = 0;
739,228✔
6754
  } else {
6755
    if (pInfo->win.ekey == pInfo->win.skey) {
7,191,878✔
6756
      pInfo->dTwaRes = pInfo->p.val;
953,464✔
6757
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
6,238,414✔
6758
      pInfo->dTwaRes = 0;
766✔
6759
    } else {
6760
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
6,237,648✔
6761
    }
6762

6763
    pResInfo->numOfRes = 1;
7,191,878✔
6764
  }
6765

6766
  return functionFinalize(pCtx, pBlock);
7,931,106✔
6767
}
6768

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

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

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

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

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

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

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

6808
  if (pDistInfo->minRows > p1.minRows) {
5,575✔
6809
    pDistInfo->minRows = p1.minRows;
1,296✔
6810
  }
6811
  if (pDistInfo->maxRows < p1.maxRows) {
5,575✔
6812
    pDistInfo->maxRows = p1.maxRows;
1,296✔
6813
  }
6814
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
5,575✔
6815
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
117,075✔
6816
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
111,500✔
6817
  }
6818

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

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

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

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

6837
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
22,300✔
6838
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
22,300✔
6839
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
22,300✔
6840
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
22,300✔
6841
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
22,300✔
6842
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
22,300✔
6843
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
22,300✔
6844
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
22,300✔
6845
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
22,300✔
6846

6847
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
234,150✔
6848
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
446,000✔
6849
  }
6850

6851
  tEndEncode(&encoder);
11,150✔
6852

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

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

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

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

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

6886
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
117,075✔
6887
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
223,000✔
6888
  }
6889

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

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

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

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

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

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

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

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

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

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

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

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

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

6970
  int32_t maxVal = 0;
2,919✔
6971
  int32_t minVal = INT32_MAX;
2,919✔
6972
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
61,299✔
6973
    if (maxVal < pData->blockRowsHisto[i]) {
58,380✔
6974
      maxVal = pData->blockRowsHisto[i];
1,856✔
6975
    }
6976

6977
    if (minVal > pData->blockRowsHisto[i]) {
58,380✔
6978
      minVal = pData->blockRowsHisto[i];
3,655✔
6979
    }
6980
  }
6981

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

7131
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
669,566✔
7132
  if (pResInfo->initialized) {
669,566✔
7133
    return TSDB_CODE_SUCCESS;
430,762✔
7134
  }
7135
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
238,804✔
7136
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7137
  }
7138

7139
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
238,804✔
7140

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

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

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

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

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

7162
  funcInputUpdate(pCtx);
462,972✔
7163

7164
  double v = 0;
462,972✔
7165
  if (pCtx->order == TSDB_ORDER_ASC) {
462,972✔
7166
    SFuncInputRow row = {0};
459,836✔
7167
    bool          result = false;
459,836✔
7168
    while (1) {
131,235,591✔
7169
      code = funcInputGetNextRow(pCtx, &row, &result);
131,695,427✔
7170
      if (TSDB_CODE_SUCCESS != code) {
131,695,427✔
7171
        return code;
×
7172
      }
7173
      if (!result) {
131,695,427✔
7174
        break;
459,836✔
7175
      }
7176
      if (row.isDataNull) {
131,235,591✔
7177
        continue;
3,001,836✔
7178
      }
7179

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

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

7202
          if (pTsOutput != NULL) {
115,178,032✔
7203
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
7204
          }
7205

7206
          // handle selectivity
7207
          if (pCtx->subsidiaries.num > 0) {
115,178,032✔
7208
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,904,171✔
7209
            if (code != TSDB_CODE_SUCCESS) {
1,904,171✔
7210
              return code;
×
7211
            }
7212
          }
7213

7214
          numOfElems++;
115,178,032✔
7215
        }
7216
      }
7217

7218
      pDerivInfo->prevValue = v;
128,233,755✔
7219
      pDerivInfo->prevTs = row.ts;
128,233,755✔
7220
    }
7221
  } else {
7222
    SFuncInputRow row = {0};
3,136✔
7223
    bool          result = false;
3,136✔
7224
    while (1) {
6,272✔
7225
      code = funcInputGetNextRow(pCtx, &row, &result);
9,408✔
7226
      if (TSDB_CODE_SUCCESS != code) {
9,408✔
7227
        return code;
×
7228
      }
7229
      if (!result) {
9,408✔
7230
        break;
3,136✔
7231
      }
7232
      if (row.isDataNull) {
6,272✔
7233
        continue;
5,252✔
7234
      }
7235

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

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

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

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

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

7278
  pResInfo->numOfRes = numOfElems;
462,972✔
7279

7280
  return TSDB_CODE_SUCCESS;
462,972✔
7281
}
7282

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

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

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

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

7310
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,845,745✔
7311

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

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

7321
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
333,116,292✔
7322
  if (isFirst) {
333,116,292✔
7323
    pRateInfo->firstValue = v;
165,995,716✔
7324
    pRateInfo->firstKey = ts;
165,995,716✔
7325
    if (pRateInfo->firstPk) {
165,995,716✔
7326
      int32_t pkBytes;
7327
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
24,500✔
7328
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
5,600✔
7329
      } else {
7330
        pkBytes = pRateInfo->pkBytes;
18,900✔
7331
      }
7332
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
24,500✔
7333
    }
7334
  } else {
7335
    pRateInfo->lastValue = v;
167,120,576✔
7336
    pRateInfo->lastKey = ts;
167,120,576✔
7337
    if (pRateInfo->lastPk) {
167,120,576✔
7338
      int32_t pkBytes;
7339
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
36,400✔
7340
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
8,400✔
7341
      } else {
7342
        pkBytes = pRateInfo->pkBytes;
28,000✔
7343
      }
7344
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
36,400✔
7345
    }
7346
  }
7347
}
333,116,292✔
7348

7349
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,016,372✔
7350
  if (pCtx->hasPrimaryKey) {
2,016,372✔
7351
    if (!isMerge) {
13,300✔
7352
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
11,900✔
7353
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
11,900✔
7354
      pRateInfo->firstPk = pRateInfo->pkData;
11,900✔
7355
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
11,900✔
7356
    } else {
7357
      pRateInfo->firstPk = pRateInfo->pkData;
1,400✔
7358
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,400✔
7359
    }
7360
  } else {
7361
    pRateInfo->firstPk = NULL;
2,003,072✔
7362
    pRateInfo->lastPk = NULL;
2,003,072✔
7363
  }
7364
}
2,016,372✔
7365

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

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

7374
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,954,110✔
7375

7376
  funcInputUpdate(pCtx);
1,954,110✔
7377

7378
  initializeRateInfo(pCtx, pRateInfo, false);
1,954,110✔
7379

7380
  int32_t       numOfElems = 0;
1,954,110✔
7381
  int32_t       type = pInputCol->info.type;
1,954,110✔
7382
  SFuncInputRow row = {0};
1,954,110✔
7383
  bool          result = false;
1,954,110✔
7384
  while (1) {
216,234,969✔
7385
    code = funcInputGetNextRow(pCtx, &row, &result);
218,189,079✔
7386
    if (TSDB_CODE_SUCCESS != code) {
218,189,079✔
7387
      return code;
×
7388
    }
7389
    if (!result) {
218,189,079✔
7390
      break;
1,954,110✔
7391
    }
7392
    if (row.isDataNull) {
216,234,969✔
7393
      continue;
8,307,149✔
7394
    }
7395

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

7400
    if (INT64_MIN == pRateInfo->lastKey) {
207,927,820✔
7401
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
1,127,554✔
7402
      pRateInfo->hasResult = 1;
1,127,554✔
7403
      continue;
1,127,554✔
7404
    }
7405

7406
    if (row.ts > pRateInfo->lastKey) {
206,800,266✔
7407
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
165,967,341✔
7408
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
165,967,341✔
7409
      }
7410
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
165,967,341✔
7411
      continue;
165,967,341✔
7412
    } else if (row.ts == pRateInfo->lastKey) {
40,832,925✔
7413
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7414
    }
7415

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

7423
  numOfElems++;
1,954,110✔
7424

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

7429
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
1,814,614✔
7430
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
1,814,614✔
7431
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
144,796✔
7432
    return 0.0;
1,669,818✔
7433
  }
7434

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

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

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

7451
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
25,722✔
7452
  if (inputKey > pOutput->lastKey) {
25,722✔
7453
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
9,429✔
7454
    if (isFirstKey) {
9,429✔
7455
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
4,041✔
7456
    } else {
7457
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
5,388✔
7458
    }
7459
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
16,293✔
7460
    if (isFirstKey) {
2,694✔
7461
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,347✔
7462
    } else {
7463
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,347✔
7464
    }
7465
  } else {
7466
    // inputKey < pOutput->firstKey
7467
  }
7468
}
25,722✔
7469

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

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

7482
  if (pOutput->hasResult == 0) {
29,113✔
7483
    irateCopyInfo(pInput, pOutput);
16,252✔
7484
    pOutput->hasResult = pInput->hasResult;
16,252✔
7485
    return TSDB_CODE_SUCCESS;
16,252✔
7486
  }
7487

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

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

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

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

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

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

7523
  if (pInfo->hasResult) {
31,131✔
7524
    GET_RES_INFO(pCtx)->numOfRes = 1;
29,113✔
7525
  }
7526

7527
  return TSDB_CODE_SUCCESS;
31,131✔
7528
}
7529

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

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

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

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

7551
  taosMemoryFree(res);
31,131✔
7552
  return code;
31,131✔
7553
}
7554

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

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

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

7569
  return code;
1,814,614✔
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)) {
417,880,133✔
7602
        valueRowIndex = pInput->startRowIndex;
206,464,970✔
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;
536,571,835✔
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) {
792,880✔
7693
  int32_t numOfElems = 0;
792,880✔
7694

7695
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
792,880✔
7696
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
793,312✔
7697

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

7701
  int32_t bytes = pInputCol->info.bytes;
793,312✔
7702
  pInfo->bytes = bytes;
793,312✔
7703

7704
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
793,312✔
7705
  pInfo->pkType = -1;
793,312✔
7706
  __compar_fn_t pkCompareFn = NULL;
793,312✔
7707
  if (pCtx->hasPrimaryKey) {
793,312✔
7708
    pInfo->pkType = pkCol->info.type;
389,719✔
7709
    pInfo->pkBytes = pkCol->info.bytes;
389,719✔
7710
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
389,719✔
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) {
1,645,913✔
7715
    numOfElems++;
853,033✔
7716

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

7720
    TSKEY cts = getRowPTs(pInput->pPTS, i);
853,033✔
7721
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
853,033✔
7722
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
519,203✔
7723
      if (code != TSDB_CODE_SUCCESS) {
518,771✔
7724
        return code;
×
7725
      }
7726
      pResInfo->numOfRes = 1;
518,771✔
7727
    }
7728
  }
7729

7730
  SET_VAL(pResInfo, numOfElems, 1);
792,880✔
7731
  return TSDB_CODE_SUCCESS;
793,312✔
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) {
15,703,024✔
7924
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
15,703,024✔
7925
  bool* pRes = GET_ROWCELL_INTERBUF(pResInfo);
15,703,024✔
7926
  if (*pRes) {
15,703,024✔
7927
    return TSDB_CODE_SUCCESS;
×
7928
  }
7929

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

7934
  if (pInput->numOfRows > 0) {
15,703,024✔
7935
    pResInfo->numOfRes = 1;
15,703,024✔
7936
  }
7937

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

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

7957
  if (pCol->hasNull) {
15,703,024✔
7958
    for (int32_t i = start; i < end; ++i) {
37,380,640✔
7959
      if (colDataIsNull_s(pCol, i)) {
63,378,952✔
7960
        *pRes = true;
9,921,390✔
7961
        break;
9,921,390✔
7962
      }
7963
    }
7964
  }  
7965

7966
  return TSDB_CODE_SUCCESS;
15,703,024✔
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