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

taosdata / TDengine / #5051

13 May 2026 12:00PM UTC coverage: 73.358% (-0.04%) from 73.398%
#5051

push

travis-ci

web-flow
feat: taosdump support stream backup/restore (#35326)

139 of 170 new or added lines in 3 files covered. (81.76%)

714 existing lines in 146 files now uncovered.

281543 of 383795 relevant lines covered (73.36%)

135448694.71 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

199
void funcInputUpdate(SqlFunctionCtx* pCtx) {
73,265,536✔
200
  SFuncInputRowIter* pIter = &pCtx->rowIter;
73,265,536✔
201

202
  if (!pCtx->bInputFinished) {
73,265,536✔
203
    pIter->pInput = &pCtx->input;
73,265,536✔
204
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
73,264,975✔
205
    pIter->pDataCol = pIter->pInput->pData[0];
73,266,027✔
206
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
73,264,975✔
207
    pIter->rowIndex = pIter->pInput->startRowIndex;
73,266,027✔
208
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
73,266,027✔
209
    pIter->pSrcBlock = pCtx->pSrcBlock;
73,265,536✔
210
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
73,265,536✔
211
      pIter->hasGroupId = true;
7,730,546✔
212
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
7,731,107✔
213
      pIter->hasPrev = false;
7,730,055✔
214
    }
215
  } else {
216
    pIter->finalRow = true;
×
217
  }
218
}
73,265,466✔
219

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

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

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

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

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

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

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

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

334
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
3,933,674✔
335
  int32_t idx = rowIndex + 1;
3,933,674✔
336
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
55,405,974✔
337
    ++idx;
51,472,300✔
338
  }
339
  pIter->rowIndex = idx;
3,933,674✔
340
}
3,933,674✔
341

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

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

363
      pIter->hasPrev = false;
356,526✔
364
      setInputRowInfo(pRow, pIter, idx, true);
356,526✔
365
      forwardToNextDiffTsRow(pIter, idx);
356,526✔
366
      return true;
356,526✔
367
    }
368
  } else {
369
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,760,610✔
370
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
4,169,370✔
371

372
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
4,169,370✔
373
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
4,169,370✔
374
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
3,577,148✔
375
      } else {
376
        pIter->rowIndex = pIter->inputEndIndex + 1;
592,222✔
377
      }
378
      return true;
4,169,370✔
379
    } else {
380
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
591,240✔
381
      pIter->hasPrev = true;
591,240✔
382
      pIter->prevBlockTsEnd = tsEnd;
591,240✔
383
      return false;
591,240✔
384
    }
385
  }
386
}
387

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

515
  return code;
123,958✔
516
}
517

518
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
16,630,859✔
519
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
16,630,859✔
520
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
16,631,940✔
521
    return FUNC_DATA_REQUIRED_NOT_LOAD;
12,180,058✔
522
  }
523
  return FUNC_DATA_REQUIRED_SMA_LOAD;
4,451,724✔
524
}
525

526
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
62,519,035✔
527
  pEnv->calcMemSize = sizeof(int64_t);
62,519,035✔
528
  return true;
62,527,511✔
529
}
530

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

625
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
626
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
35,938,990✔
627

628
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
35,939,671✔
629
      SUM_RES_INC_ISUM(pSumRes, pAgg->sum);
18,343,025✔
630
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
17,596,646✔
631
      SUM_RES_INC_USUM(pSumRes, pAgg->sum);
17,565,866✔
632
    } else if (IS_FLOAT_TYPE(type)) {
33,488✔
633
      SUM_RES_INC_DSUM(pSumRes, GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
33,488✔
UNCOV
634
    } else if (IS_DECIMAL_TYPE(type)) {
×
UNCOV
635
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
×
UNCOV
636
      const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
×
UNCOV
637
      if (pAgg->overflow || decimal128AddCheckOverflow((Decimal*)&SUM_RES_GET_DECIMAL_SUM(pSumRes),
×
UNCOV
638
                                                       &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal))) {
×
UNCOV
639
        return TSDB_CODE_DECIMAL_OVERFLOW;
×
640
      }
UNCOV
641
      pOps->add(&SUM_RES_GET_DECIMAL_SUM(pSumRes), &pAgg->decimal128Sum, DECIMAL_WORD_NUM(Decimal));
×
642
    }
643
  } else {  // computing based on the true data block
644
    SColumnInfoData* pCol = pInput->pData[0];
2,147,483,647✔
645

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

649
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
650
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
651
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int8_t, numOfElem);
802,481,041✔
652
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
2,147,483,647✔
653
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
539,120,528✔
654
      } else if (type == TSDB_DATA_TYPE_INT) {
2,147,483,647✔
655
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int32_t, numOfElem);
2,147,483,647✔
656
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
1,383,084,094✔
657
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int64_t, numOfElem);
2,147,483,647✔
658
      }
659
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,147,483,647✔
660
      if (type == TSDB_DATA_TYPE_UTINYINT) {
2,147,483,647✔
661
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint8_t, numOfElem);
536,299,935✔
662
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
2,147,483,647✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint16_t, numOfElem);
2,147,483,647✔
664
      } else if (type == TSDB_DATA_TYPE_UINT) {
75,276,658✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
581,561,190✔
666
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
2,318,318✔
667
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
440,486,397✔
668
      }
669
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
219,632,782✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
632,797,650✔
671
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
145,370,349✔
672
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
448,741,122✔
673
    } else if (IS_DECIMAL_TYPE(type)) {
85,462✔
674
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
85,462✔
675
      int32_t overflow = false;
44,492✔
676
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
44,492✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
15,460,602✔
678
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
27,778✔
679
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
24,686,135✔
680
      }
681
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
43,464✔
682
    }
683
  }
684

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

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

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

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

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

726
bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,823,114✔
727
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
31,823,114✔
728
  return true;
31,822,860✔
729
}
730

731
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
27,381,996✔
732
  SNode* pParam;
733
  switch (pFunc->funcType) {
27,381,996✔
734
    case FUNCTION_TYPE_MAX:
27,385,581✔
735
    case FUNCTION_TYPE_MIN:
736
    case FUNCTION_TYPE_SUM:
737
    case FUNCTION_TYPE_AVG:
738
    case FUNCTION_TYPE_AVG_PARTIAL:
739
    case FUNCTION_TYPE_PERCENTILE:
740
    case FUNCTION_TYPE_SPREAD:
741
    case FUNCTION_TYPE_SPREAD_PARTIAL:
742
    case FUNCTION_TYPE_SPREAD_MERGE:
743
    case FUNCTION_TYPE_TWA:
744
    case FUNCTION_TYPE_ELAPSED:
745
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
27,385,581✔
746
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
27,386,275✔
747
        return true;
1,705,678✔
748
      }
749
      break;
25,679,195✔
750
    default:
×
751
      break;
×
752
  }
753
  return false;
25,675,610✔
754
}
755

756
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
27,381,749✔
757
  if (funcNotSupportStringSma(pFunc)) {
27,381,749✔
758
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,705,678✔
759
  }
760
  return FUNC_DATA_REQUIRED_SMA_LOAD;
25,679,523✔
761
}
762

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

771
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
2,106,063,914✔
772
  buf->assign = false;
2,106,066,486✔
773
  buf->tuplePos.pageId = -1;
2,106,074,125✔
774

775
  buf->nullTupleSaved = false;
2,106,069,575✔
776
  buf->nullTuplePos.pageId = -1;
2,106,067,645✔
777
  buf->str = NULL;
2,106,059,655✔
778
  return TSDB_CODE_SUCCESS;
2,106,077,944✔
779
}
780

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

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

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

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

811
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,068,400,387✔
812
  int32_t code = TSDB_CODE_SUCCESS;
2,068,400,387✔
813

814
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
2,068,400,387✔
815
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
2,068,401,652✔
816

817
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
2,068,399,783✔
818
  int32_t currentRow = pBlock->info.rows;
2,068,402,891✔
819

820
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,068,401,013✔
821
  if (NULL == pCol) {
2,068,400,675✔
822
    return TSDB_CODE_OUT_OF_RANGE;
×
823
  }
824
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
2,068,400,675✔
825

826
  // NOTE: do nothing change it, for performance issue
827
  if (!pEntryInfo->isNullRes) {
2,068,398,701✔
828
    switch (pCol->info.type) {
1,802,931,046✔
829
      case TSDB_DATA_TYPE_UBIGINT:
158,040,945✔
830
      case TSDB_DATA_TYPE_BIGINT:
831
      case TSDB_DATA_TYPE_TIMESTAMP:
832
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
158,040,945✔
833
        break;
158,039,693✔
834
      case TSDB_DATA_TYPE_UINT:
1,522,018,104✔
835
      case TSDB_DATA_TYPE_INT:
836
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
1,522,018,104✔
837
        break;
1,522,016,960✔
838
      case TSDB_DATA_TYPE_USMALLINT:
26,513,282✔
839
      case TSDB_DATA_TYPE_SMALLINT:
840
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
26,513,282✔
841
        break;
26,513,282✔
842
      case TSDB_DATA_TYPE_BOOL:
40,895,191✔
843
      case TSDB_DATA_TYPE_UTINYINT:
844
      case TSDB_DATA_TYPE_TINYINT:
845
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
40,895,191✔
846
        break;
40,895,191✔
847
      case TSDB_DATA_TYPE_DOUBLE:
28,392,577✔
848
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
28,392,577✔
849
        break;
28,392,577✔
850
      case TSDB_DATA_TYPE_FLOAT: {
21,087,511✔
851
        float v = GET_FLOAT_VAL(&pRes->v);
21,087,511✔
852
        colDataSetFloat(pCol, currentRow, &v);
21,087,511✔
853
        break;
21,087,511✔
854
      }
855
      case TSDB_DATA_TYPE_VARBINARY:
5,223,678✔
856
      case TSDB_DATA_TYPE_VARCHAR:
857
      case TSDB_DATA_TYPE_NCHAR: {
858
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
5,223,678✔
859
        if (TSDB_CODE_SUCCESS != code) {
5,223,678✔
860
          return code;
×
861
        }
862
        break;
5,223,678✔
863
      }
864
      case TSDB_DATA_TYPE_DECIMAL64:
723,856✔
865
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
723,856✔
866
        break;
723,856✔
867
      case TSDB_DATA_TYPE_DECIMAL:
38,298✔
868
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
38,298✔
869
        break;
38,298✔
870
    }
871
  } else {
872
    colDataSetNULL(pCol, currentRow);
265,467,580✔
873
  }
874

875
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
2,068,398,013✔
876
  if (pCtx->subsidiaries.num > 0) {
2,068,399,186✔
877
    if (pEntryInfo->numOfRes > 0) {
2,477,484✔
878
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
2,192,608✔
879
    } else {
880
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
284,876✔
881
    }
882
  }
883

884
  return code;
2,068,399,283✔
885
}
886

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

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

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

903
  return TSDB_CODE_SUCCESS;
369,341✔
904
}
905

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

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

922
    bool* nullList = (bool*)p;
84,546,006✔
923
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
84,546,006✔
924

925
    // todo set the offset value to optimize the performance.
926
    for (int32_t j = 0; j < numOfCols; ++j) {
273,232,476✔
927
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
188,685,008✔
928
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
188,685,739✔
929

930
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
188,685,562✔
931
      if (NULL == pDstCol) {
188,685,802✔
932
        return terrno;
×
933
      }
934
      if (nullList[j]) {
188,685,802✔
935
        colDataSetNULL(pDstCol, rowIndex);
59,742,351✔
936
      } else {
937
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
128,941,989✔
938
        if (TSDB_CODE_SUCCESS != code) {
128,944,850✔
939
          return code;
×
940
        }
941
      }
942
      pStart += pDstCol->info.bytes;
188,687,201✔
943
    }
944
  }
945

946
  return TSDB_CODE_SUCCESS;
84,547,468✔
947
}
948

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

956
  int32_t code = TSDB_CODE_SUCCESS;
1,133,694✔
957
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
2,565,270✔
958
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
1,431,576✔
959

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

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

969
    char* pData = colDataGetData(pSrcCol, rowIndex);
1,431,576✔
970

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

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

979
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
2,863,152✔
980
      colDataSetNULL(pDstCol, pos);
59,064✔
981
    } else {
982
      code = colDataSetVal(pDstCol, pos, pData, false);
1,372,512✔
983
      if (TSDB_CODE_SUCCESS != code) {
1,372,512✔
984
        return code;
×
985
      }
986
    }
987
  }
988
  return code;
1,133,694✔
989
}
990

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

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

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

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

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

1084
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
19,677,753✔
1085

1086
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
4,411,043✔
1087
  pEnv->calcMemSize = sizeof(SStdRes);
4,411,043✔
1088
  return true;
4,414,363✔
1089
}
1090

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

1099
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
513,475,604✔
1100
  (void)memset(pRes, 0, sizeof(SStdRes));
513,475,604✔
1101
  return TSDB_CODE_SUCCESS;
513,475,604✔
1102
}
1103

1104
int32_t stdFunction(SqlFunctionCtx* pCtx) {
1,087,684,719✔
1105
  int32_t numOfElem = 0;
1,087,684,719✔
1106

1107
  // Only the pre-computing information loaded and actual data does not loaded
1108
  SInputColumnInfoData* pInput = &pCtx->input;
1,087,684,719✔
1109
  int32_t               type = pInput->pData[0]->info.type;
1,087,687,284✔
1110

1111
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,087,689,519✔
1112
  pStdRes->type = type;
1,087,688,231✔
1113

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

1117
  int32_t start = pInput->startRowIndex;
1,087,683,442✔
1118
  int32_t numOfRows = pInput->numOfRows;
1,087,650,850✔
1119

1120
  if (IS_NULL_TYPE(type)) {
1,087,687,615✔
1121
    numOfElem = 0;
97,496✔
1122
    goto _stddev_over;
97,496✔
1123
  }
1124

1125
  switch (type) {
1,087,590,119✔
1126
    case TSDB_DATA_TYPE_TINYINT: {
13,911,119✔
1127
      int8_t* plist = (int8_t*)pCol->pData;
13,911,119✔
1128
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1129
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1130
          continue;
1,582,398,230✔
1131
        }
1132

1133
        numOfElem += 1;
706,869,330✔
1134
        pStdRes->count += 1;
706,869,330✔
1135
        double nr = (double)plist[i];
711,241,384✔
1136
        if (pStdRes->count == 1) {
711,244,141✔
1137
          pStdRes->dsum = nr;
1,324,329✔
1138
        } else {
1139
          double          s_kminusone = pStdRes->dsum;
709,920,493✔
1140
          volatile double diff = nr - s_kminusone;
709,921,866✔
1141
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
709,921,866✔
1142
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
709,908,872✔
1143
        }
1144
      }
1145

1146
      break;
13,794,578✔
1147
    }
1148

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

1156
        numOfElem += 1;
1,301,337,573✔
1157
        pStdRes->count += 1;
1,301,337,573✔
1158
        double nr = (double)plist[i];
1,305,554,226✔
1159
        if (pStdRes->count == 1) {
1,305,441,817✔
1160
          pStdRes->dsum = nr;
395,792,867✔
1161
        } else {
1162
          double          s_kminusone = pStdRes->dsum;
909,680,968✔
1163
          volatile double diff = nr - s_kminusone;
909,688,448✔
1164
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
909,688,448✔
1165
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
909,743,631✔
1166
        }
1167
      }
1168
      break;
974,741,244✔
1169
    }
1170

1171
    case TSDB_DATA_TYPE_INT: {
20,725,504✔
1172
      int32_t* plist = (int32_t*)pCol->pData;
20,725,504✔
1173
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1174
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1175
          continue;
827,650,330✔
1176
        }
1177

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

1191
      break;
20,725,504✔
1192
    }
1193

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

1201
        numOfElem += 1;
938,494,483✔
1202
        pStdRes->count += 1;
938,494,483✔
1203
        double nr = (double)plist[i];
942,334,926✔
1204
        if (pStdRes->count == 1) {
942,345,303✔
1205
          pStdRes->dsum = nr;
2,698,045✔
1206
        } else {
1207
          double          s_kminusone = pStdRes->dsum;
939,660,859✔
1208
          volatile double diff = nr - s_kminusone;
939,662,902✔
1209
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
939,662,902✔
1210
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
939,599,887✔
1211
        }
1212
      }
1213
      break;
15,308,752✔
1214
    }
1215

1216
    case TSDB_DATA_TYPE_UTINYINT: {
14,075,965✔
1217
      uint8_t* plist = (uint8_t*)pCol->pData;
14,075,965✔
1218
      for (int32_t i = start; i < numOfRows + start; ++i) {
2,147,483,647✔
1219
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1220
          continue;
1,712,261,063✔
1221
        }
1222

1223
        numOfElem += 1;
1,114,149,462✔
1224
        pStdRes->count += 1;
1,114,149,462✔
1225
        double nr = (double)plist[i];
1,118,292,316✔
1226
        if (pStdRes->count == 1) {
1,118,052,952✔
1227
          pStdRes->dsum = nr;
81,495✔
1228
        } else {
1229
          double          s_kminusone = pStdRes->dsum;
1,118,032,166✔
1230
          volatile double diff = nr - s_kminusone;
1,115,443,190✔
1231
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,115,443,190✔
1232
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,117,969,392✔
1233
        }
1234
      }
1235

1236
      break;
13,900,243✔
1237
    }
1238

1239
    case TSDB_DATA_TYPE_USMALLINT: {
11,333,231✔
1240
      uint16_t* plist = (uint16_t*)pCol->pData;
11,333,231✔
1241
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
1242
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,147,483,647✔
1243
          continue;
1,710,603,637✔
1244
        }
1245

1246
        numOfElem += 1;
563,878,907✔
1247
        pStdRes->count += 1;
563,878,907✔
1248
        double nr = (double)plist[i];
569,725,170✔
1249
        if (pStdRes->count == 1) {
569,725,170✔
1250
          pStdRes->dsum = nr;
35,322✔
1251
        } else {
1252
          double          s_kminusone = pStdRes->dsum;
569,689,848✔
1253
          volatile double diff = nr - s_kminusone;
569,689,848✔
1254
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
569,689,848✔
1255
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
569,689,848✔
1256
        }
1257
      }
1258
      break;
11,333,242✔
1259
    }
1260

1261
    case TSDB_DATA_TYPE_UINT: {
6,184,924✔
1262
      uint32_t* plist = (uint32_t*)pCol->pData;
6,184,924✔
1263
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,258,281,421✔
1264
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,252,200,702✔
1265
          continue;
890,421,296✔
1266
        }
1267

1268
        numOfElem += 1;
361,488,124✔
1269
        pStdRes->count += 1;
361,488,124✔
1270
        double nr = (double)plist[i];
363,660,758✔
1271
        if (pStdRes->count == 1) {
363,670,314✔
1272
          pStdRes->dsum = nr;
26,154✔
1273
        } else {
1274
          double          s_kminusone = pStdRes->dsum;
363,640,096✔
1275
          volatile double diff = nr - s_kminusone;
363,640,777✔
1276
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
363,640,777✔
1277
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
363,603,948✔
1278
        }
1279
      }
1280

1281
      break;
6,185,605✔
1282
    }
1283

1284
    case TSDB_DATA_TYPE_UBIGINT: {
6,185,173✔
1285
      uint64_t* plist = (uint64_t*)pCol->pData;
6,185,173✔
1286
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,258,191,420✔
1287
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,252,071,854✔
1288
          continue;
958,893,109✔
1289
        }
1290

1291
        numOfElem += 1;
293,063,952✔
1292
        pStdRes->count += 1;
293,063,952✔
1293
        double nr = (double)plist[i];
295,007,181✔
1294
        if (pStdRes->count == 1) {
294,913,642✔
1295
          pStdRes->dsum = nr;
22,987✔
1296
        } else {
1297
          double          s_kminusone = pStdRes->dsum;
294,907,746✔
1298
          volatile double diff = nr - s_kminusone;
294,913,205✔
1299
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
294,913,205✔
1300
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
294,930,933✔
1301
        }
1302
      }
1303
      break;
6,185,173✔
1304
    }
1305

1306
    case TSDB_DATA_TYPE_FLOAT: {
11,122,051✔
1307
      float* plist = (float*)pCol->pData;
11,122,051✔
1308
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,004,542,593✔
1309
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,993,426,807✔
1310
          continue;
4,768,859✔
1311
        }
1312

1313
        numOfElem += 1;
1,988,655,263✔
1314
        pStdRes->count += 1;
1,988,655,263✔
1315
        double nr = (double)plist[i];
1,988,658,485✔
1316
        if (pStdRes->count == 1) {
1,988,658,485✔
1317
          pStdRes->dsum = nr;
10,147,036✔
1318
        } else {
1319
          double          s_kminusone = pStdRes->dsum;
1,978,511,270✔
1320
          volatile double diff = nr - s_kminusone;
1,978,504,468✔
1321
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,978,504,468✔
1322
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,978,506,258✔
1323
        }
1324
      }
1325
      break;
11,122,230✔
1326
    }
1327

1328
    case TSDB_DATA_TYPE_DOUBLE: {
14,003,348✔
1329
      double* plist = (double*)pCol->pData;
14,003,348✔
1330
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
360,594,903✔
1331
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
346,588,575✔
1332
          continue;
24,472,470✔
1333
        }
1334

1335
        numOfElem += 1;
322,095,841✔
1336
        pStdRes->count += 1;
322,095,841✔
1337
        double nr = (double)plist[i];
322,098,225✔
1338
        if (pStdRes->count == 1) {
322,102,993✔
1339
          pStdRes->dsum = nr;
6,193,868✔
1340
        } else {
1341
          double          s_kminusone = pStdRes->dsum;
315,909,721✔
1342
          volatile double diff = nr - s_kminusone;
315,912,105✔
1343
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
315,912,105✔
1344
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
315,903,165✔
1345
        }
1346
      }
1347
      break;
14,006,924✔
1348
    }
1349

1350
    default:
×
1351
      break;
×
1352
  }
1353

1354
_stddev_over:
1,087,400,991✔
1355
  // data in the check operation are all null, not output
1356
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1,087,400,991✔
1357
  return TSDB_CODE_SUCCESS;
1,087,679,164✔
1358
}
1359

1360
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
18,932,190✔
1361
  if (IS_NULL_TYPE(pInput->type)) {
18,932,190✔
1362
    return;
29,035✔
1363
  }
1364
  pOutput->type = pInput->type;
18,903,155✔
1365
  if (pOutput->count == 0) {
18,903,155✔
1366
    pOutput->quadraticDSum += pInput->quadraticDSum;
18,573,580✔
1367
    pOutput->dsum += pInput->dsum;
18,573,580✔
1368
    pOutput->count = pInput->count;
18,573,580✔
1369
  } else if (pInput->count > 0) {
329,575✔
1370
    double totalCount = pOutput->count + pInput->count;
150,032✔
1371
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
150,032✔
1372
    double mean = totalSum / totalCount;
150,032✔
1373

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

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

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

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

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

1399
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
18,901,648✔
1400

1401
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
37,833,838✔
1402
    if (colDataIsNull_s(pCol, i)) continue;
37,864,380✔
1403
    char*    data = colDataGetData(pCol, i);
18,932,190✔
1404
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
18,932,190✔
1405
    stdTransferInfo(pInputInfo, pInfo);
18,932,190✔
1406
  }
1407

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

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

1418
  if (pStddevRes->count == 0) {
467,331,770✔
1419
    GET_RES_INFO(pCtx)->numOfRes = 0;
64,229,716✔
1420

1421
    return functionFinalize(pCtx, pBlock);
64,229,716✔
1422
  }
1423

1424
  if (pStddevRes->count == 1) {
403,102,054✔
1425
    pStddevRes->result = 0.0;
289,949,312✔
1426
  } else {
1427
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
113,152,742✔
1428
  }
1429

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

1435
  return functionFinalize(pCtx, pBlock);
403,102,054✔
1436
}
1437

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

1444
  if (pStdvarRes->count == 0) {
7,323,954✔
1445
    GET_RES_INFO(pCtx)->numOfRes = 0;
9,272✔
1446
    return functionFinalize(pCtx, pBlock);
9,272✔
1447
  }
1448

1449
  if (pStdvarRes->count == 1) {
7,314,682✔
1450
    pStdvarRes->result = 0.0;
1,034✔
1451
  } else {
1452
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
7,313,648✔
1453
  }
1454

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

1460
  return functionFinalize(pCtx, pBlock);
7,314,682✔
1461
}
1462

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

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

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

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

1484
  taosMemoryFree(res);
18,937,560✔
1485
  return code;
18,937,560✔
1486
}
1487

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

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

1496
  stdTransferInfo(pSBuf, pDBuf);
×
1497

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

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

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

1513
  if (pStddevRes->count == 1) {
3,607,890✔
1514
    pStddevRes->result = 0.0;
517✔
1515
  } else {
1516
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / (pStddevRes->count - 1));
3,607,373✔
1517
  }
1518

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

1524
  return functionFinalize(pCtx, pBlock);
3,607,890✔
1525
}
1526

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

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

1537
  if (pStddevRes->count == 1) {
3,606,856✔
1538
    pStddevRes->result = 0.0;
517✔
1539
  } else {
1540
    pStddevRes->result = pStddevRes->quadraticDSum / (pStddevRes->count - 1);
3,606,339✔
1541
  }
1542

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

1548
  return functionFinalize(pCtx, pBlock);
3,606,856✔
1549
}
1550

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

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

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

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

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

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

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

1580
  return TSDB_CODE_SUCCESS;
52,481✔
1581
}
1582

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

1608
  return TSDB_CODE_SUCCESS;
140,941✔
1609
}
1610

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

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

1630
    varDataSetLen(pRes->result, 0);
51,951✔
1631

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

1636
      if (TSDB_DATA_TYPE_NCHAR == type) {
53,541✔
1637
        pRes->nchar = true;
33,736✔
1638
      }
1639
    }
1640
  } else {
1641
    dataLen = varDataLen(pRes->result);
×
1642
  }
1643

1644
  hasNchar = pRes->nchar;
51,951✔
1645

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

1650
  sep = colDataGetData(pCol, 0);
51,951✔
1651
  pRes->type = pCol->info.type;
51,951✔
1652
  for (int r = rowStart; r < rowStart + numOfRows; ++r) {
150,731✔
1653
    bool rowHasValue = false;
98,780✔
1654

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

1659
      if (IS_NULL_TYPE(type) || colDataIsNull_s(pCol, r)) {
206,040✔
1660
        continue;
3,180✔
1661
      }
1662

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

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

1677
      rowHasValue = true;
99,840✔
1678
    }
1679

1680
    hasResultValue |= rowHasValue;
98,780✔
1681
  }
1682

1683
  varDataSetLen(buf, dataLen);
51,951✔
1684
  if (hasResultValue) {
51,951✔
1685
    numOfElem += 1;
50,891✔
1686
  }
1687

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

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

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

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

1710
  taosMemoryFree(pRes->result);
51,951✔
1711

1712
  return code;
51,951✔
1713
}
1714

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

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

1728
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,236,681✔
1729

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

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

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

1743
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,213,406✔
1744

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

1747
  double(*param)[3] = pInfo->matrix;
6,211,618✔
1748
  double x = pInfo->startVal;
6,213,406✔
1749

1750
  int32_t start = pInput->startRowIndex;
6,213,406✔
1751
  int32_t numOfRows = pInput->numOfRows;
6,212,214✔
1752

1753
  switch (type) {
6,211,618✔
1754
    case TSDB_DATA_TYPE_TINYINT: {
305,280✔
1755
      int8_t* plist = (int8_t*)pCol->pData;
305,280✔
1756
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
21,210,896✔
1757
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,905,616✔
1758
          continue;
62,388✔
1759
        }
1760
        numOfElem++;
20,843,228✔
1761
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,843,228✔
1762
      }
1763
      break;
305,280✔
1764
    }
1765
    case TSDB_DATA_TYPE_SMALLINT: {
426,102✔
1766
      int16_t* plist = (int16_t*)pCol->pData;
426,102✔
1767
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
21,507,518✔
1768
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
21,081,416✔
1769
          continue;
296,788✔
1770
        }
1771

1772
        numOfElem++;
20,784,628✔
1773
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,784,628✔
1774
      }
1775
      break;
426,102✔
1776
    }
1777

1778
    case TSDB_DATA_TYPE_INT: {
2,893,093✔
1779
      int32_t* plist = (int32_t*)pCol->pData;
2,893,093✔
1780
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
190,194,291✔
1781
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
187,298,814✔
1782
          continue;
90,926✔
1783
        }
1784

1785
        numOfElem++;
187,201,332✔
1786
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
187,201,332✔
1787
      }
1788
      break;
2,893,093✔
1789
    }
1790

1791
    case TSDB_DATA_TYPE_BIGINT: {
595,780✔
1792
      int64_t* plist = (int64_t*)pCol->pData;
595,780✔
1793
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
21,735,796✔
1794
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
21,140,016✔
1795
          continue;
296,788✔
1796
        }
1797

1798
        numOfElem++;
20,843,228✔
1799
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,843,228✔
1800
      }
1801
      break;
595,780✔
1802
    }
1803

1804
    case TSDB_DATA_TYPE_UTINYINT: {
19,780✔
1805
      uint8_t* plist = (uint8_t*)pCol->pData;
19,780✔
1806
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,583,796✔
1807
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,564,016✔
1808
          continue;
11,528✔
1809
        }
1810
        numOfElem++;
20,552,488✔
1811
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,552,488✔
1812
      }
1813
      break;
19,780✔
1814
    }
1815
    case TSDB_DATA_TYPE_USMALLINT: {
19,780✔
1816
      uint16_t* plist = (uint16_t*)pCol->pData;
19,780✔
1817
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,583,796✔
1818
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,564,016✔
1819
          continue;
10,480✔
1820
        }
1821

1822
        numOfElem++;
20,553,536✔
1823
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,553,536✔
1824
      }
1825
      break;
19,780✔
1826
    }
1827

1828
    case TSDB_DATA_TYPE_UINT: {
19,780✔
1829
      uint32_t* plist = (uint32_t*)pCol->pData;
19,780✔
1830
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,583,796✔
1831
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,564,016✔
1832
          continue;
10,480✔
1833
        }
1834

1835
        numOfElem++;
20,553,536✔
1836
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,553,536✔
1837
      }
1838
      break;
19,780✔
1839
    }
1840

1841
    case TSDB_DATA_TYPE_UBIGINT: {
19,780✔
1842
      uint64_t* plist = (uint64_t*)pCol->pData;
19,780✔
1843
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,583,796✔
1844
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
20,564,016✔
1845
          continue;
10,480✔
1846
        }
1847

1848
        numOfElem++;
20,553,536✔
1849
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
20,553,536✔
1850
      }
1851
      break;
19,780✔
1852
    }
1853

1854
    case TSDB_DATA_TYPE_FLOAT: {
889,241✔
1855
      float* plist = (float*)pCol->pData;
889,241✔
1856
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
22,378,257✔
1857
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
21,489,016✔
1858
          continue;
6,288✔
1859
        }
1860

1861
        numOfElem++;
21,482,728✔
1862
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
21,482,728✔
1863
      }
1864
      break;
889,241✔
1865
    }
1866

1867
    case TSDB_DATA_TYPE_DOUBLE: {
1,023,002✔
1868
      double* plist = (double*)pCol->pData;
1,023,002✔
1869
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
104,049,710✔
1870
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
103,027,900✔
1871
          continue;
179,588✔
1872
        }
1873

1874
        numOfElem++;
102,833,412✔
1875
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
102,833,412✔
1876
      }
1877
      break;
1,024,194✔
1878
    }
1879
    case TSDB_DATA_TYPE_NULL: {
×
1880
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1881
      numOfElem = 1;
×
1882
      break;
×
1883
    }
1884

1885
    default:
×
1886
      break;
×
1887
  }
1888

1889
  pInfo->startVal = x;
6,212,810✔
1890
  pInfo->num += numOfElem;
6,213,406✔
1891

1892
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,213,406✔
1893

1894
  return TSDB_CODE_SUCCESS;
6,213,406✔
1895
}
1896

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

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

1908
  if (0 == pInfo->num) {
5,237,873✔
1909
    colDataSetNULL(pCol, currentRow);
649,318✔
1910
    return TSDB_CODE_SUCCESS;
649,318✔
1911
  }
1912

1913
  double(*param)[3] = pInfo->matrix;
4,587,959✔
1914

1915
  param[1][1] = (double)pInfo->num;
4,587,959✔
1916
  param[1][0] = param[0][1];
4,588,555✔
1917

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

1921
  if (0 == param00) {
4,587,959✔
1922
    colDataSetNULL(pCol, currentRow);
3,286,766✔
1923
    return TSDB_CODE_SUCCESS;
3,287,362✔
1924
  }
1925

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

1931
  param12 /= param[1][1];
1,301,193✔
1932

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

1948
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,301,193✔
1949

1950
  return code;
1,301,193✔
1951
}
1952

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

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

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

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

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

1994
  return TSDB_CODE_SUCCESS;
631,906✔
1995
}
1996

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

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

2013
  SInputColumnInfoData* pInput = &pCtx->input;
2,418,092✔
2014
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,418,092✔
2015

2016
  SColumnInfoData* pCol = pInput->pData[0];
2,418,092✔
2017
  int32_t          type = pCol->info.type;
2,418,092✔
2018

2019
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,418,092✔
2020
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
2,418,092✔
2021
    pInfo->stage += 1;
631,906✔
2022

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

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

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

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

2059
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
×
2060
    } else {
2061
      // check the valid data one by one
2062
      int32_t start = pInput->startRowIndex;
1,209,046✔
2063
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
22,530,870✔
2064
        if (colDataIsNull_f(pCol, i)) {
21,321,824✔
2065
          continue;
290,500✔
2066
        }
2067

2068
        char* data = colDataGetData(pCol, i);
21,031,324✔
2069

2070
        double v = 0;
21,031,324✔
2071
        GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
21,031,324✔
2072
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
21,031,324✔
2073
          SET_DOUBLE_VAL(&pInfo->minval, v);
427,500✔
2074
        }
2075

2076
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
21,031,324✔
2077
          SET_DOUBLE_VAL(&pInfo->maxval, v);
16,949,400✔
2078
        }
2079

2080
        pInfo->numOfElems += 1;
21,031,324✔
2081
      }
2082
    }
2083
  } else {
2084
    // the second stage, calculate the true percentile value
2085
    int32_t start = pInput->startRowIndex;
976,560✔
2086
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
22,007,884✔
2087
      if (colDataIsNull_f(pCol, i)) {
21,031,324✔
2088
        continue;
×
2089
      }
2090

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

2100
    SET_VAL(pResInfo, numOfElems, 1);
976,560✔
2101
  }
2102

2103
  pCtx->needCleanup = true;
2,185,606✔
2104
  return TSDB_CODE_SUCCESS;
2,185,606✔
2105
}
2106

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

2111
  int32_t code = 0;
631,906✔
2112
  double  v = 0;
631,906✔
2113

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

2122
      varDataVal(buf)[0] = '[';
3,138✔
2123
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
34,518✔
2124
        SVariant* pVal = &pCtx->param[i].param;
31,380✔
2125

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

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

2133
        if (i == pCtx->numOfParams - 1) {
31,380✔
2134
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
3,138✔
2135
        } else {
2136
          len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
28,242✔
2137
        }
2138
      }
2139

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

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

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

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

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

2165
      tMemBucketDestroy(pMemBucket);
396,282✔
2166
      return functionFinalize(pCtx, pBlock);
396,282✔
2167
    }
2168
  } else {
2169
    return functionFinalize(pCtx, pBlock);
232,486✔
2170
  }
2171

2172
_fin_error:
×
2173

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

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

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

2193
static int8_t getApercentileAlgo(char* algoStr) {
3,349,310✔
2194
  int8_t algoType;
2195
  if (strcasecmp(algoStr, "default") == 0) {
3,349,310✔
2196
    algoType = APERCT_ALGO_DEFAULT;
1,673,646✔
2197
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,675,664✔
2198
    algoType = APERCT_ALGO_TDIGEST;
1,676,260✔
2199
  } else {
2200
    algoType = APERCT_ALGO_UNKNOWN;
×
2201
  }
2202

2203
  return algoType;
3,349,310✔
2204
}
2205

2206
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
78,544,084✔
2207
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
78,544,084✔
2208
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
78,544,049✔
2209
}
78,545,837✔
2210

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

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

2223
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
24,963,336✔
2224

2225
  SVariant* pVal = &pCtx->param[1].param;
24,963,336✔
2226
  pInfo->percent = 0;
24,964,493✔
2227
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
24,964,493✔
2228

2229
  if (pCtx->numOfParams == 2) {
24,963,336✔
2230
    pInfo->algo = APERCT_ALGO_DEFAULT;
21,614,026✔
2231
  } else if (pCtx->numOfParams == 3) {
3,349,906✔
2232
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
3,350,502✔
2233
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
3,349,906✔
2234
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2235
    }
2236
  }
2237

2238
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
24,963,897✔
2239
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
24,962,740✔
2240
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,675,068✔
2241
  } else {
2242
    buildHistogramInfo(pInfo);
23,286,480✔
2243
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
23,287,672✔
2244
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
23,288,233✔
2245
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2246
  }
2247

2248
  return TSDB_CODE_SUCCESS;
24,963,301✔
2249
}
2250

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

2256
  SColumnInfoData* pCol = pInput->pData[0];
35,320,771✔
2257
  int32_t          type = pCol->info.type;
35,320,090✔
2258

2259
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
35,319,494✔
2260

2261
  int32_t start = pInput->startRowIndex;
35,320,771✔
2262
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
35,320,771✔
2263
    buildTDigestInfo(pInfo);
1,674,543✔
2264
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,675,735✔
2265
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
87,159,740✔
2266
      if (colDataIsNull_f(pCol, i)) {
85,487,581✔
2267
        continue;
1,821✔
2268
      }
2269
      numOfElems += 1;
85,485,164✔
2270
      char* data = colDataGetData(pCol, i);
85,485,164✔
2271

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

2294
      double v = 0;
1,075,350,332✔
2295
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
1,075,350,332✔
2296
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
1,075,355,405✔
2297
      if (code != TSDB_CODE_SUCCESS) {
1,071,624,795✔
2298
        return code;
×
2299
      }
2300
    }
2301

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

2307
  SET_VAL(pResInfo, numOfElems, 1);
35,321,367✔
2308
  return TSDB_CODE_SUCCESS;
35,321,367✔
2309
}
2310

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

2318
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
16,275✔
2319
      return TSDB_CODE_SUCCESS;
525✔
2320
    }
2321

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

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

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

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

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

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

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

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

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

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

2383
  SInputColumnInfoData* pInput = &pCtx->input;
271,159✔
2384

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

2390
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
271,159✔
2391

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

2394
  bool    hasRes = false;
271,159✔
2395
  int32_t start = pInput->startRowIndex;
271,159✔
2396
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
547,035✔
2397
    char* data = colDataGetData(pCol, i);
275,876✔
2398

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

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

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

2416
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
22,621,033✔
2417
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
22,621,033✔
2418
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
22,621,033✔
2419

2420
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
22,621,033✔
2421
    buildTDigestInfo(pInfo);
1,660,581✔
2422
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,660,581✔
2423
    if (pInfo->pTDigest->size > 0) {
1,660,581✔
2424
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,660,581✔
2425
    } else {  // no need to free
2426
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2427
      return TSDB_CODE_SUCCESS;
×
2428
    }
2429
  } else {
2430
    buildHistogramInfo(pInfo);
20,960,452✔
2431
    if (pInfo->pHisto->numOfElems > 0) {
20,960,452✔
2432
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
18,394,747✔
2433
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2434

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

2453
  return functionFinalize(pCtx, pBlock);
22,621,033✔
2454
}
2455

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

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

2466
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
275,876✔
2467
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
16,275✔
2468
    varDataSetLen(res, resultBytes);
16,275✔
2469
  } else {
2470
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
259,601✔
2471
    varDataSetLen(res, resultBytes);
259,601✔
2472
  }
2473

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

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

2483
  taosMemoryFree(res);
275,876✔
2484
  return code;
275,876✔
2485
}
2486

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

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

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

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

2505
// TODO: change this function when block data info pks changed
2506
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
431,505✔
2507
  char numVal[8] = {0};
431,505✔
2508
  switch (pkType) {
431,505✔
2509
    case TSDB_DATA_TYPE_INT:
57,631✔
2510
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
57,631✔
2511
      break;
57,631✔
2512
    case TSDB_DATA_TYPE_UINT:
25,597✔
2513
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
25,597✔
2514
      break;
25,597✔
2515
    case TSDB_DATA_TYPE_BIGINT:
116,241✔
2516
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
116,241✔
2517
      break;
116,241✔
2518
    case TSDB_DATA_TYPE_UBIGINT:
87,732✔
2519
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
87,732✔
2520
      break;
87,732✔
2521
    default:
144,304✔
2522
      break;
144,304✔
2523
  }
2524
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
431,505✔
2525
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
431,505✔
2526
  return fn(pkData, blockData);
431,505✔
2527
}
2528

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

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

2537
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
2,147,483,647✔
2538
  if (pResult->hasResult) {
2,147,483,647✔
2539
    if (pResult->pkBytes > 0) {
2,147,483,647✔
2540
      pResult->pkData = pResult->buf + pResult->bytes;
294,504✔
2541
    } else {
2542
      pResult->pkData = NULL;
2,147,483,647✔
2543
    }
2544
    if (pResult->ts < pBlockInfo->window.skey) {
2,147,483,647✔
2545
      return FUNC_DATA_REQUIRED_NOT_LOAD;
3,135,639✔
2546
    } else if (pResult->ts == pBlockInfo->window.skey) {
2,147,483,647✔
2547
      if (NULL == pResult->pkData) {
2,147,483,647✔
2548
        return FUNC_DATA_REQUIRED_NOT_LOAD;
2,147,483,647✔
2549
      }
2550
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
188,808✔
2551
        return FUNC_DATA_REQUIRED_NOT_LOAD;
11,888✔
2552
      }
2553
    }
2554
    return FUNC_DATA_REQUIRED_DATA_LOAD;
475,239✔
2555
  } else {
2556
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,424,165✔
2557
  }
2558
}
2559

2560
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
31,911,301✔
2561
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
31,911,301✔
2562

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

2568
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
31,911,301✔
2569
  if (pResult->hasResult) {
31,914,887✔
2570
    if (pResult->pkBytes > 0) {
29,549,902✔
2571
      pResult->pkData = pResult->buf + pResult->bytes;
506,937✔
2572
    } else {
2573
      pResult->pkData = NULL;
29,043,463✔
2574
    }
2575
    if (pResult->ts > pBlockInfo->window.ekey) {
29,549,477✔
2576
      return FUNC_DATA_REQUIRED_NOT_LOAD;
8,554,912✔
2577
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
20,995,046✔
2578
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
242,697✔
2579
        return FUNC_DATA_REQUIRED_NOT_LOAD;
77,046✔
2580
      }
2581
    }
2582
    return FUNC_DATA_REQUIRED_DATA_LOAD;
20,917,737✔
2583
  } else {
2584
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,364,431✔
2585
  }
2586
}
2587

2588
// TODO modify it to include primary key bytes
2589
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
2,061,691,835✔
2590

2591
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
70,736,169✔
2592
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
70,736,169✔
2593
  // TODO: change SFunctionNode to add pk info
2594
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
70,744,769✔
2595
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
70,731,351✔
2596
  return true;
70,734,831✔
2597
}
2598

2599
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
17,816,526✔
2600
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
17,816,526✔
2601
  pEnv->calcMemSize = pNode->node.resType.bytes;
17,816,329✔
2602
  return true;
17,817,551✔
2603
}
2604

2605

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

2611
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
71,817,576✔
2612
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
71,817,576✔
2613
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
71,835,014✔
2614
  return true;
71,825,671✔
2615
}
2616

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

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

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

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

2639
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
130,363,095✔
2640
  if (pCtx->subsidiaries.rowLen == 0) {
130,363,095✔
2641
    int32_t rowLen = 0;
6,101,429✔
2642
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
14,205,043✔
2643
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
8,104,615✔
2644
      rowLen += pc->pExpr->base.resSchema.bytes;
8,104,283✔
2645
    }
2646

2647
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
6,100,982✔
2648
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
6,098,893✔
2649
    if (NULL == pCtx->subsidiaries.buf) {
6,100,438✔
2650
      return terrno;
×
2651
    }
2652
  }
2653
  return TSDB_CODE_SUCCESS;
130,367,641✔
2654
}
2655

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

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

2664
  if (!pInfo->hasResult) {
82,218,970✔
2665
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
67,351,203✔
2666
  } else if (!noElements) {
14,866,918✔
2667
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
14,852,180✔
2668
  } else {
2669
  }  // dothing
2670

2671
  return code;
82,219,538✔
2672
}
2673

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

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

2688
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
2,147,483,647✔
2689
  if (pkData != NULL) {
2,147,483,647✔
2690
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
193,668,594✔
2691
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
64,378,827✔
2692
      // if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
2693
      //   pInfo->pkBytes = getJsonValueLen(pkData);
2694
      // } else {
2695
      //   pInfo->pkBytes = varDataTLen(pkData);
2696
      // }
2697
    }
2698
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
193,665,270✔
2699
    pInfo->pkData = pInfo->buf + pInfo->bytes;
193,663,904✔
2700
  }
2701

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

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

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

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

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

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

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

2729
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2730
  pInfo->pkType = -1;
2,147,483,647✔
2731
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2732
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2733
    pInfo->pkType = pkCol->info.type;
52,533,201✔
2734
    pInfo->pkBytes = pkCol->info.bytes;
52,543,446✔
2735
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
52,544,812✔
2736
  }
2737

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

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

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

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

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

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

2773
      numOfElems++;
2774

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

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

2796
      numOfElems++;
2797

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

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

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

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

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

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

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

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

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

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

2864
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2865
  pInfo->pkType = -1;
2,147,483,647✔
2866
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2867
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2868
    pInfo->pkType = pkCol->info.type;
52,698,904✔
2869
    pInfo->pkBytes = pkCol->info.bytes;
52,699,638✔
2870
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
52,687,976✔
2871
  }
2872

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

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

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

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

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

2900
      numOfElems++;
2901

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

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

2916
      numOfElems++;
2917

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

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

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

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

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

2951
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
2,147,483,647✔
2952
      int64_t cts = pts[i];
535,026,643✔
2953
      int32_t chosen = i;
535,032,492✔
2954

2955
      if (cts < pts[i + 1]) {
535,032,492✔
2956
        cts = pts[i + 1];
152,799,598✔
2957
        chosen = i + 1;
152,799,598✔
2958
      }
2959

2960
      if (cts < pts[i + 2]) {
535,033,758✔
2961
        cts = pts[i + 2];
152,799,910✔
2962
        chosen = i + 2;
152,799,910✔
2963
      }
2964

2965
      if (cts < pts[i + 3]) {
535,038,213✔
2966
        cts = pts[i + 3];
152,798,116✔
2967
        chosen = i + 3;
152,798,116✔
2968
      }
2969

2970
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
535,028,746✔
2971
        char*   data = colDataGetData(pInputCol, chosen);
184,746,478✔
2972
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
184,748,583✔
2973
        if (code != TSDB_CODE_SUCCESS) {
184,753,724✔
2974
          return code;
×
2975
        }
2976
        pResInfo->numOfRes = 1;
184,753,724✔
2977
      }
2978
    }
2979

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

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

3019
#endif
3020

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

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

3033
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
1,584,463,862✔
3034
  if (!pInput->hasResult) {
1,584,463,862✔
3035
    return false;
×
3036
  }
3037
  __compar_fn_t pkCompareFn = NULL;
1,584,463,862✔
3038
  if (pInput->pkData) {
1,584,463,862✔
3039
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
5,006,183✔
3040
  }
3041
  if (pOutput->hasResult) {
1,584,466,909✔
3042
    if (isFirst) {
866,098,946✔
3043
      if (pInput->ts > pOutput->ts ||
756,470,098✔
3044
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
755,549,592✔
3045
        return false;
989,220✔
3046
      }
3047
    } else {
3048
      if (pInput->ts < pOutput->ts ||
109,628,848✔
3049
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
106,008,059✔
3050
        return false;
3,712,895✔
3051
      }
3052
    }
3053
  }
3054

3055
  pOutput->isNull = pInput->isNull;
1,579,765,348✔
3056
  pOutput->ts = pInput->ts;
1,579,765,071✔
3057
  pOutput->bytes = pInput->bytes;
1,579,759,808✔
3058
  pOutput->pkType = pInput->pkType;
1,579,764,794✔
3059

3060
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,579,764,517✔
3061
  if (pInput->pkData) {
1,579,764,794✔
3062
    pOutput->pkBytes = pInput->pkBytes;
4,722,785✔
3063
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
4,722,785✔
3064
    pOutput->pkData = pOutput->buf + pOutput->bytes;
4,722,785✔
3065
  }
3066
  return true;
1,579,765,348✔
3067
}
3068

3069
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,584,463,308✔
3070
                                     int32_t rowIndex) {
3071
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,584,463,308✔
3072
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,579,765,348✔
3073
    if (TSDB_CODE_SUCCESS != code) {
1,579,764,794✔
3074
      return code;
×
3075
    }
3076
    pOutput->hasResult = true;
1,579,764,794✔
3077
  }
3078
  return TSDB_CODE_SUCCESS;
1,584,466,909✔
3079
}
3080

3081
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
735,878,227✔
3082
  SInputColumnInfoData* pInput = &pCtx->input;
735,878,227✔
3083
  SColumnInfoData*      pCol = pInput->pData[0];
735,879,058✔
3084

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

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

3094
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
735,879,058✔
3095

3096
  int32_t start = pInput->startRowIndex;
735,879,058✔
3097
  int32_t numOfElems = 0;
735,879,058✔
3098

3099
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,147,483,647✔
3100
    if (colDataIsNull_s(pCol, i)) {
2,147,483,647✔
3101
      continue;
270,714,143✔
3102
    }
3103
    char*          data = colDataGetData(pCol, i);
1,584,466,632✔
3104
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,584,468,294✔
3105
    if (pCtx->hasPrimaryKey) {
1,584,468,294✔
3106
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
5,006,183✔
3107
    } else {
3108
      pInputInfo->pkData = NULL;
1,579,462,111✔
3109
    }
3110

3111
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,584,463,308✔
3112
    if (code != TSDB_CODE_SUCCESS) {
1,584,466,909✔
3113
      return code;
×
3114
    }
3115
    if (!numOfElems) {
1,584,466,909✔
3116
      numOfElems = pInputInfo->hasResult ? 1 : 0;
731,504,883✔
3117
    }
3118
  }
3119

3120
  if (numOfElems == 0) {
735,878,227✔
3121
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
4,373,621✔
3122
    if (code != TSDB_CODE_SUCCESS) {
4,373,621✔
3123
      return code;
×
3124
    }
3125
    pInfo->nullTupleSaved = true;
4,373,621✔
3126
  }
3127

3128
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
735,878,227✔
3129
  return TSDB_CODE_SUCCESS;
735,878,504✔
3130
}
3131

3132
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
429,274,428✔
3133

3134
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
306,604,076✔
3135

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

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

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

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

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

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

3167
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,970,711,910✔
3168
  int32_t code = TSDB_CODE_SUCCESS;
1,970,711,910✔
3169

3170
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,970,711,910✔
3171
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,971,225,990✔
3172

3173
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,971,278,709✔
3174

3175
  // todo check for failure
3176
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,970,935,188✔
3177
  if (NULL == res) {
1,968,454,602✔
3178
    return terrno;
×
3179
  }
3180
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,968,454,602✔
3181

3182
  varDataSetLen(res, resultBytes);
1,968,487,866✔
3183

3184
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,971,019,539✔
3185
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,971,381,273✔
3186
  if (NULL == pCol) {
1,971,021,375✔
3187
    taosMemoryFree(res);
×
3188
    return TSDB_CODE_OUT_OF_RANGE;
×
3189
  }
3190

3191
  if (pEntryInfo->numOfRes == 0) {
1,971,021,375✔
3192
    colDataSetNULL(pCol, pBlock->info.rows);
282,168,359✔
3193
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
282,160,151✔
3194
  } else {
3195
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,688,224,068✔
3196
    if (TSDB_CODE_SUCCESS != code) {
1,688,331,535✔
3197
      taosMemoryFree(res);
×
3198
      return code;
×
3199
    }
3200
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,688,331,535✔
3201
  }
3202
  taosMemoryFree(res);
1,970,220,992✔
3203
  return code;
1,970,403,856✔
3204
}
3205

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

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

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

3220
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
26,220,694✔
3221
  SInputColumnInfoData* pInput = &pCtx->input;
26,220,694✔
3222
  SColumnInfoData*      pInputCol = pInput->pData[0];
26,222,791✔
3223
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
26,222,865✔
3224

3225
  if (colDataIsNull_s(pInputCol, rowIndex)) {
52,445,281✔
3226
    pInfo->isNull = true;
3,099,527✔
3227
  } else {
3228
    pInfo->isNull = false;
23,115,505✔
3229

3230
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
23,120,551✔
3231
      pInfo->bytes = calcStrBytesByType(pInputCol->info.type, pData);
4,126,087✔
3232
      // if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
3233
      //   pInfo->bytes = getJsonValueLen(pData);
3234
      // } else {
3235
      //   pInfo->bytes = varDataTLen(pData);
3236
      // }
3237
    }
3238

3239
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
23,124,228✔
3240
  }
3241

3242
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
36,727,733✔
3243
    char* pkData = colDataGetData(pkCol, rowIndex);
10,498,488✔
3244
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
10,502,589✔
3245
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
3,397,460✔
3246
    }
3247
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
10,498,632✔
3248
    pInfo->pkData = pInfo->buf + pInfo->bytes;
10,500,001✔
3249
  }
3250
  pInfo->ts = cts;
26,224,413✔
3251
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
26,221,621✔
3252
  if (code != TSDB_CODE_SUCCESS) {
26,218,488✔
3253
    return code;
×
3254
  }
3255

3256
  pInfo->hasResult = true;
26,218,488✔
3257

3258
  return TSDB_CODE_SUCCESS;
26,218,600✔
3259
}
3260

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

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

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

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

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

3288
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3289
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
23,744,299✔
3290
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
11,873,436✔
3291
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
11,871,484✔
3292
      TSKEY cts = getRowPTs(pInput->pPTS, i);
11,872,927✔
3293
      numOfElems++;
11,869,476✔
3294

3295
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
11,869,476✔
3296
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
3,320,854✔
3297
        if (code != TSDB_CODE_SUCCESS) return code;
3,320,826✔
3298
      }
3299

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

3311
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2,147,483,647✔
3312
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
8,480,080✔
3313
        if (code != TSDB_CODE_SUCCESS) return code;
10,014,667✔
3314
      }
3315
      break;
2,147,483,647✔
3316
    }
3317
  } else {
3318
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
49,549,737✔
3319
    int      from = -1;
53,088,396✔
3320
    int32_t  i = -1;
53,090,675✔
3321
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
257,312,841✔
3322
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
204,219,098✔
3323
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
204,236,269✔
3324
      TSKEY cts = pts[i];
204,225,660✔
3325

3326
      numOfElems++;
204,226,349✔
3327
      char* pkData = NULL;
204,226,349✔
3328
      if (pCtx->hasPrimaryKey) {
204,226,349✔
3329
        pkData = colDataGetData(pkCol, i);
199,449,340✔
3330
      }
3331
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
204,220,420✔
3332
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
191,791,008✔
3333
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
12,444,666✔
3334
        if (code != TSDB_CODE_SUCCESS) {
12,443,887✔
3335
          return code;
×
3336
        }
3337
        pResInfo->numOfRes = 1;
12,443,887✔
3338
      }
3339
    }
3340
  }
3341

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

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

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

3371
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
16,709,837✔
3372
  switch (type) {
16,709,837✔
3373
    case TSDB_DATA_TYPE_BOOL:
4,419✔
3374
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
4,419✔
3375
      break;
4,419✔
3376
    case TSDB_DATA_TYPE_UTINYINT:
43,983✔
3377
    case TSDB_DATA_TYPE_TINYINT:
3378
      pDiffInfo->prev.i64 = *(int8_t*)pv;
43,983✔
3379
      break;
43,983✔
3380
    case TSDB_DATA_TYPE_UINT:
16,400,320✔
3381
    case TSDB_DATA_TYPE_INT:
3382
      pDiffInfo->prev.i64 = *(int32_t*)pv;
16,400,320✔
3383
      break;
16,400,320✔
3384
    case TSDB_DATA_TYPE_USMALLINT:
41,639✔
3385
    case TSDB_DATA_TYPE_SMALLINT:
3386
      pDiffInfo->prev.i64 = *(int16_t*)pv;
41,639✔
3387
      break;
41,639✔
3388
    case TSDB_DATA_TYPE_TIMESTAMP:
125,771✔
3389
    case TSDB_DATA_TYPE_UBIGINT:
3390
    case TSDB_DATA_TYPE_BIGINT:
3391
      pDiffInfo->prev.i64 = *(int64_t*)pv;
125,771✔
3392
      break;
125,771✔
3393
    case TSDB_DATA_TYPE_FLOAT:
26,609✔
3394
      pDiffInfo->prev.d64 = *(float*)pv;
26,609✔
3395
      break;
26,609✔
3396
    case TSDB_DATA_TYPE_DOUBLE:
67,096✔
3397
      pDiffInfo->prev.d64 = *(double*)pv;
67,096✔
3398
      break;
67,096✔
3399
    default:
×
3400
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3401
  }
3402
  pDiffInfo->prevTs = ts;
16,709,837✔
3403
  pDiffInfo->hasPrev = true;
16,709,837✔
3404
  return TSDB_CODE_SUCCESS;
16,709,837✔
3405
}
3406

3407
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
2,820,700✔
3408
  switch (type) {
2,820,700✔
3409
    case TSDB_DATA_TYPE_UINT: {
×
3410
      int64_t v = *(uint32_t*)pv;
×
3411
      return v < pDiffInfo->prev.i64;
×
3412
    }
3413
    case TSDB_DATA_TYPE_INT: {
410,687✔
3414
      int64_t v = *(int32_t*)pv;
410,687✔
3415
      return v < pDiffInfo->prev.i64;
410,687✔
3416
    }
3417
    case TSDB_DATA_TYPE_BOOL: {
×
3418
      int64_t v = *(bool*)pv;
×
3419
      return v < pDiffInfo->prev.i64;
×
3420
    }
3421
    case TSDB_DATA_TYPE_UTINYINT: {
×
3422
      int64_t v = *(uint8_t*)pv;
×
3423
      return v < pDiffInfo->prev.i64;
×
3424
    }
3425
    case TSDB_DATA_TYPE_TINYINT: {
530,950✔
3426
      int64_t v = *(int8_t*)pv;
530,950✔
3427
      return v < pDiffInfo->prev.i64;
530,950✔
3428
    }
3429
    case TSDB_DATA_TYPE_USMALLINT: {
×
3430
      int64_t v = *(uint16_t*)pv;
×
3431
      return v < pDiffInfo->prev.i64;
×
3432
    }
3433
    case TSDB_DATA_TYPE_SMALLINT: {
1,004,575✔
3434
      int64_t v = *(int16_t*)pv;
1,004,575✔
3435
      return v < pDiffInfo->prev.i64;
1,004,575✔
3436
    }
3437
    case TSDB_DATA_TYPE_UBIGINT: {
3,928✔
3438
      uint64_t v = *(uint64_t*)pv;
3,928✔
3439
      return v < (uint64_t)pDiffInfo->prev.i64;
3,928✔
3440
    }
3441
    case TSDB_DATA_TYPE_TIMESTAMP:
347,062✔
3442
    case TSDB_DATA_TYPE_BIGINT: {
3443
      int64_t v = *(int64_t*)pv;
347,062✔
3444
      return v < pDiffInfo->prev.i64;
347,062✔
3445
    }
3446
    case TSDB_DATA_TYPE_FLOAT: {
348,424✔
3447
      float v = *(float*)pv;
348,424✔
3448
      return v < pDiffInfo->prev.d64;
348,424✔
3449
    }
3450
    case TSDB_DATA_TYPE_DOUBLE: {
175,074✔
3451
      double v = *(double*)pv;
175,074✔
3452
      return v < pDiffInfo->prev.d64;
175,074✔
3453
    }
3454
    default:
×
3455
      return false;
×
3456
  }
3457

3458
  return false;
3459
}
3460

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

3476
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
32,519,350✔
3477
  double delta = v - pDiffInfo->prev.d64;
32,519,350✔
3478
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
32,519,350✔
3479
    colDataSetNull_f_s(pOutput, pos);
250,174✔
3480
  } else {
3481
    colDataSetDouble(pOutput, pos, &delta);
32,269,176✔
3482
  }
3483
  pDiffInfo->prev.d64 = v;
32,519,350✔
3484
}
32,519,350✔
3485

3486
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2,147,483,647✔
3487
                            int64_t ts) {
3488
  if (!pDiffInfo->hasPrev) {
2,147,483,647✔
3489
    colDataSetNull_f_s(pOutput, pos);
73,206✔
3490
    return doSetPrevVal(pDiffInfo, type, pv, ts);
73,206✔
3491
  }
3492
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3493
  switch (type) {
2,147,483,647✔
3494
    case TSDB_DATA_TYPE_UINT: {
483,297✔
3495
      int64_t v = *(uint32_t*)pv;
483,297✔
3496
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
483,297✔
3497
      break;
483,297✔
3498
    }
3499
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
3500
      int64_t v = *(int32_t*)pv;
2,147,483,647✔
3501
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3502
      break;
2,147,483,647✔
3503
    }
3504
    case TSDB_DATA_TYPE_BOOL: {
5,001,326✔
3505
      int64_t v = *(bool*)pv;
5,001,326✔
3506
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
5,001,326✔
3507
      break;
5,001,326✔
3508
    }
3509
    case TSDB_DATA_TYPE_UTINYINT: {
67,257✔
3510
      int64_t v = *(uint8_t*)pv;
67,257✔
3511
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
67,257✔
3512
      break;
67,257✔
3513
    }
3514
    case TSDB_DATA_TYPE_TINYINT: {
10,956,857✔
3515
      int64_t v = *(int8_t*)pv;
10,956,857✔
3516
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,956,857✔
3517
      break;
10,956,857✔
3518
    }
3519
    case TSDB_DATA_TYPE_USMALLINT: {
67,257✔
3520
      int64_t v = *(uint16_t*)pv;
67,257✔
3521
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
67,257✔
3522
      break;
67,257✔
3523
    }
3524
    case TSDB_DATA_TYPE_SMALLINT: {
11,812,063✔
3525
      int64_t v = *(int16_t*)pv;
11,812,063✔
3526
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
11,812,063✔
3527
      break;
11,812,063✔
3528
    }
3529
    case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
3530
    case TSDB_DATA_TYPE_UBIGINT:
3531
    case TSDB_DATA_TYPE_BIGINT: {
3532
      int64_t v = *(int64_t*)pv;
2,147,483,647✔
3533
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3534
      break;
2,147,483,647✔
3535
    }
3536
    case TSDB_DATA_TYPE_FLOAT: {
16,268,795✔
3537
      double v = *(float*)pv;
16,268,795✔
3538
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
16,268,795✔
3539
      break;
16,268,795✔
3540
    }
3541
    case TSDB_DATA_TYPE_DOUBLE: {
16,250,555✔
3542
      double v = *(double*)pv;
16,250,555✔
3543
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
16,250,555✔
3544
      break;
16,250,555✔
3545
    }
3546
    default:
×
3547
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3548
  }
3549
  pDiffInfo->hasPrev = true;
2,147,483,647✔
3550
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3551
}
3552

3553
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3554
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3555
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
2,147,483,647✔
3556
                              int32_t* nextFrom) {
3557
  if (pInput->pPrimaryKey == NULL) {
2,147,483,647✔
3558
    if (pInput->numOfRows == 0) {
2,147,483,647✔
3559
      return false;
×
3560
    }
3561
    if (from == -1) {
2,147,483,647✔
3562
      from = pInput->startRowIndex;
2,147,483,647✔
3563
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
2,147,483,647✔
3564
      return false;
2,147,483,647✔
3565
    }
3566
    *pRowIndex = from;
2,147,483,647✔
3567
    *nextFrom = from + 1;
2,147,483,647✔
3568
    return true;
2,147,483,647✔
3569
  } else {
3570
    if (from == -1) {
748,558,735✔
3571
      from = pInput->startRowIndex;
157,663,570✔
3572
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
590,895,165✔
3573
      return false;
157,716,354✔
3574
    }
3575
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
590,844,274✔
3576
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
590,907,877✔
3577
    int8_t           pkType = pkCol->info.type;
590,902,563✔
3578
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
590,957,104✔
3579
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
590,957,104✔
3580
    int32_t          select = from;
590,789,469✔
3581
    char*            val = colDataGetData(pkCol, select);
590,789,469✔
3582
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,472,033,423✔
3583
      char* val1 = colDataGetData(pkCol, from + 1);
881,191,631✔
3584
      if (compareFunc(val1, val) < 0) {
881,313,023✔
3585
        select = from + 1;
270,160,936✔
3586
        val = val1;
270,160,936✔
3587
      }
3588
      from = from + 1;
881,122,997✔
3589
    }
3590
    *pRowIndex = select;
590,495,788✔
3591
    *nextFrom = from + 1;
590,875,704✔
3592
    return true;
590,898,926✔
3593
  }
3594
}
3595

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

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

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

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

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

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

3631
  char* pv = pRow->pData;
16,636,631✔
3632
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
16,636,631✔
3633
}
3634

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

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

3648
    // handle selectivity
3649
    if (pCtx->subsidiaries.num > 0) {
8,642,529✔
3650
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
23,568✔
3651
      if (code != TSDB_CODE_SUCCESS) {
23,568✔
3652
        return code;
×
3653
      }
3654
    }
3655
    return TSDB_CODE_SUCCESS;
8,642,529✔
3656
  }
3657

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

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

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

3678
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
61,324,552✔
3679

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

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

3693
  bool keepNull = false;
61,289,290✔
3694
  for (int i = 0; i < diffColNum; ++i) {
122,613,842✔
3695
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
61,324,552✔
3696
    if (NULL == pCtx) {
61,324,552✔
3697
      code = terrno;
×
3698
      goto _exit;
×
3699
    }
3700
    funcInputUpdate(pCtx);
61,324,552✔
3701
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
61,324,552✔
3702
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
61,324,552✔
3703
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
61,324,552✔
3704
      keepNull = true;
61,304,421✔
3705
    }
3706
  }
3707

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

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

3771
  for (int i = 0; i < diffColNum; ++i) {
122,595,561✔
3772
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
61,315,166✔
3773
    if (NULL == pCtx) {
61,315,166✔
3774
      code = terrno;
×
3775
      goto _exit;
×
3776
    }
3777
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
61,315,166✔
3778
    pResInfo->numOfRes = numOfElems;
61,315,166✔
3779
  }
3780

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

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

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

3799
int32_t lagFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
60,820✔
3800
  if (pResInfo->initialized) {
60,820✔
3801
    return TSDB_CODE_SUCCESS;
31,416✔
3802
  }
3803
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
29,404✔
3804
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3805
  }
3806

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

3813
  return TSDB_CODE_SUCCESS;
29,404✔
3814
}
3815

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

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

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

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

3836
  int32_t size = taosArrayGetSize(pValues);
105,384✔
3837
  for (int32_t i = 0; i < size; ++i) {
52,934,411✔
3838
    SLagLeadRowValue* pValue = (SLagLeadRowValue*)taosArrayGet(pValues, i);
52,829,027✔
3839
    if (pValue != NULL && pValue->pData != NULL) {
52,829,027✔
3840
      taosMemoryFree(pValue->pData);
52,823,997✔
3841
      pValue->pData = NULL;
52,823,997✔
3842
    }
3843
  }
3844

3845
  taosArrayDestroy(pValues);
105,384✔
3846
}
3847

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

3853
  int32_t size = taosArrayGetSize(pValueArrays);
69,701✔
3854
  for (int32_t i = 0; i < size; ++i) {
142,663✔
3855
    SArray** ppValues = (SArray**)taosArrayGet(pValueArrays, i);
72,962✔
3856
    if (ppValues != NULL && *ppValues != NULL) {
72,962✔
3857
      cleanupLagLeadRowValueArray(*ppValues);
72,962✔
3858
    }
3859
  }
3860

3861
  taosArrayDestroy(pValueArrays);
69,701✔
3862
}
3863

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

3871
  if (pRow->isDataNull) {
40,431,408✔
3872
    return TSDB_CODE_SUCCESS;
4,024✔
3873
  }
3874

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

3886
  (void)memcpy(pValue->pData, pRow->pData, dataLen);
40,427,384✔
3887
  return TSDB_CODE_SUCCESS;
40,427,384✔
3888
}
3889

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

3896
  SVariant* pDefault = &pCtx->param[2].param;
14,256,955✔
3897

3898
  if (IS_NULL_TYPE(pDefault->nType)) {
14,256,955✔
3899
    colDataSetNULL((SColumnInfoData*)pCtx->pOutput, pos);
25,793✔
3900
    return TSDB_CODE_SUCCESS;
25,793✔
3901
  }
3902

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4181
  return retCode;
14,231,162✔
4182
}
4183

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

4191
  if (pSrc->isDataNull || pSrc->pData == NULL) {
12,397,619✔
4192
    return TSDB_CODE_SUCCESS;
1,006✔
4193
  }
4194

4195
  int32_t dataLen = pSrc->dataLen;
12,396,613✔
4196

4197
  if (dataLen <= 0) {
12,396,613✔
4198
    return TSDB_CODE_SUCCESS;
×
4199
  }
4200

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

4206
  (void)memcpy(pDst->pData, pSrc->pData, dataLen);
12,396,613✔
4207
  return TSDB_CODE_SUCCESS;
12,396,613✔
4208
}
4209

4210
static int32_t setLagLeadOutputFromValue(SqlFunctionCtx* pCtx, int32_t pos, SLagLeadRowValue* pValue) {
32,115,386✔
4211
  if (pValue->isDataNull) {
32,115,386✔
4212
    colDataSetNULL((SColumnInfoData*)pCtx->pOutput, pos);
3,018✔
4213
    return TSDB_CODE_SUCCESS;
3,018✔
4214
  }
4215

4216
  return colDataSetVal((SColumnInfoData*)pCtx->pOutput, pos, pValue->pData, false);
32,112,368✔
4217
}
4218

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

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

4232
  for (int32_t i = 0; i < pendingSize; ++i) {
8,247,691✔
4233
    SLeadPendingItem* pItem = taosArrayGet(pState->pLeadPending, i);
8,243,667✔
4234
    if (pItem == NULL) {
8,243,667✔
4235
      code = terrno;
×
4236
      goto cleanup;
×
4237
    }
4238

4239
    if (pItem->needIdx < currSize) {
8,243,667✔
4240
      SLagLeadRowValue* pTarget = taosArrayGet(pCurrValues, pItem->needIdx);
5,940,933✔
4241
      if (pTarget == NULL) {
5,940,933✔
4242
        code = terrno;
×
4243
        goto cleanup;
×
4244
      }
4245

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

4259
  taosArrayDestroy(pState->pLeadPending);
4,024✔
4260
  pState->pLeadPending = pRemain;
4,024✔
4261

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

4267
  return code;
4,024✔
4268
}
4269

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

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

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

4284
  int32_t start = oldSize + currSize - keep;
32,422✔
4285
  for (int32_t idx = start; idx < oldSize + currSize; ++idx) {
12,430,041✔
4286
    SLagLeadRowValue* pSrc = NULL;
12,397,619✔
4287
    if (idx < oldSize) {
12,397,619✔
4288
      pSrc = taosArrayGet(pState->pLagTail, idx);
2,302,734✔
4289
    } else {
4290
      pSrc = taosArrayGet(pCurrValues, idx - oldSize);
10,094,885✔
4291
    }
4292

4293
    if (pSrc == NULL) {
12,397,619✔
4294
      cleanupLagLeadRowValueArray(pNewTail);
×
4295
      return terrno;
×
4296
    }
4297

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

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

4314
  if (pState->pLagTail != NULL) {
32,422✔
4315
    cleanupLagLeadRowValueArray(pState->pLagTail);
4,024✔
4316
  }
4317
  pState->pLagTail = pNewTail;
32,422✔
4318
  return TSDB_CODE_SUCCESS;
32,422✔
4319
}
4320

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

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

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

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

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

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

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

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

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

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

4398
    for (int32_t i = 1; i < colNum; ++i) {
40,431,408✔
4399
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
14,293✔
4400
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
14,293✔
4401
      if (NULL == pCtx || NULL == pRow) {
14,293✔
4402
        code = terrno;
×
4403
        goto _exit;
×
4404
      }
4405

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

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

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

4431
    ++numOfElems;
40,417,115✔
4432
  }
4433

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

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

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

4455
    if (isLead) {
72,962✔
4456
      if (pState->pLeadPending == NULL) {
40,540✔
4457
        pState->pLeadPending = taosArrayInit(8, sizeof(SLeadPendingItem));
36,516✔
4458
        if (pState->pLeadPending == NULL) {
36,516✔
4459
          code = terrno;
×
4460
          goto _exit;
×
4461
        }
4462
      }
4463

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

4470
    for (int32_t rowIdx = 0; rowIdx < numOfElems; ++rowIdx) {
40,504,370✔
4471
      int32_t pos = startOffset + rowIdx;
40,431,408✔
4472
      SLagLeadRowValue* pCurRowValue = taosArrayGet(pValues, rowIdx);
40,431,408✔
4473
      if (pCurRowValue == NULL) {
40,431,408✔
4474
        code = terrno;
×
4475
        goto _exit;
×
4476
      }
4477

4478
      if (isLead) {
40,431,408✔
4479
        int64_t targetIdx = (int64_t)rowIdx + offset;
20,232,391✔
4480
        if (targetIdx < numOfElems) {
20,232,391✔
4481
          SLagLeadRowValue* pTargetRowValue = taosArrayGet(pValues, targetIdx);
10,129,388✔
4482
          if (pTargetRowValue == NULL) {
10,129,388✔
4483
            code = terrno;
×
4484
            goto _exit;
×
4485
          }
4486
          code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
10,129,388✔
4487
        } else {
4488
          code = setLagLeadDefaultValue(pCtx, pos);
10,103,003✔
4489
          if (code == TSDB_CODE_SUCCESS) {
10,103,003✔
4490
            SLeadPendingItem pending = {.outputPos = pos, .needIdx = targetIdx - numOfElems};
10,103,003✔
4491
            if (NULL == taosArrayPush(pState->pLeadPending, &pending)) {
20,206,006✔
4492
              code = terrno;
×
4493
            }
4494
          }
4495
        }
4496
      } else {
4497
        int64_t targetIdx = (int64_t)rowIdx - offset;
20,199,017✔
4498
        if (targetIdx >= 0) {
20,199,017✔
4499
          SLagLeadRowValue* pTargetRowValue = taosArrayGet(pValues, targetIdx);
10,104,132✔
4500
          if (pTargetRowValue == NULL) {
10,104,132✔
4501
            code = terrno;
×
4502
            goto _exit;
×
4503
          }
4504
          code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
10,104,132✔
4505
        } else {
4506
          int32_t tailSize = (pState->pLagTail == NULL) ? 0 : taosArrayGetSize(pState->pLagTail);
10,094,885✔
4507
          int64_t tailIdx = tailSize + targetIdx;
10,094,885✔
4508
          if (tailIdx >= 0 && tailIdx < tailSize) {
16,035,818✔
4509
            SLagLeadRowValue* pTargetRowValue = taosArrayGet(pState->pLagTail, tailIdx);
5,940,933✔
4510
            if (pTargetRowValue == NULL) {
5,940,933✔
4511
              code = terrno;
×
4512
              goto _exit;
×
4513
            }
4514
            code = setLagLeadOutputFromValue(pCtx, pos, pTargetRowValue);
5,940,933✔
4515
          } else {
4516
            code = setLagLeadDefaultValue(pCtx, pos);
4,153,952✔
4517
          }
4518
        }
4519
      }
4520

4521
      if (code != TSDB_CODE_SUCCESS) {
40,431,408✔
4522
        goto _exit;
×
4523
      }
4524

4525
      if (pCtx->subsidiaries.num > 0) {
40,431,408✔
4526
        code = appendSelectivityCols(pCtx, pCurRowValue->block, pCurRowValue->rowIndex, pos);
20,230,682✔
4527
        if (code != TSDB_CODE_SUCCESS) {
20,230,682✔
4528
          goto _exit;
×
4529
        }
4530
      }
4531
    }
4532

4533
    if (!isLead) {
72,962✔
4534
      code = refreshLagTailValues(pState, pValues, offset);
32,422✔
4535
      if (code != TSDB_CODE_SUCCESS) {
32,422✔
4536
        goto _exit;
×
4537
      }
4538
    }
4539
  }
4540

4541
_exit:
69,701✔
4542
  for (int32_t i = 0; i < colNum; ++i) {
142,663✔
4543
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
72,962✔
4544
    if (!pCtx) {
72,962✔
4545
      break;
×
4546
    }
4547

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

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

4559
  cleanupLagLeadValueArrays(pValueArrays);
69,701✔
4560

4561
  return code;
69,701✔
4562
}
4563

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

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

4573
int32_t leadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
76,605✔
4574
  if (pResInfo->initialized) {
76,605✔
4575
    return TSDB_CODE_SUCCESS;
39,083✔
4576
  }
4577
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
37,522✔
4578
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4579
  }
4580

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

4587
  return TSDB_CODE_SUCCESS;
37,522✔
4588
}
4589

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

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

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

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

4606
  if (pState->pLagTail != NULL) {
66,926✔
4607
    cleanupLagLeadRowValueArray(pState->pLagTail);
28,398✔
4608
    pState->pLagTail = NULL;
28,398✔
4609
  }
4610

4611
  if (pState->pLeadPending != NULL) {
66,926✔
4612
    taosArrayDestroy(pState->pLeadPending);
36,516✔
4613
    pState->pLeadPending = NULL;
36,516✔
4614
  }
4615
}
4616

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

4622
int32_t fillforwardFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
84,426✔
4623
  if (pResInfo->initialized) {
84,426✔
4624
    return TSDB_CODE_SUCCESS;
40,755✔
4625
  }
4626
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
43,671✔
4627
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4628
  }
4629
  SFillforwardInfo* pFillforwardInfo = GET_ROWCELL_INTERBUF(pResInfo);
43,671✔
4630
  pFillforwardInfo->nonnull = false;
43,671✔
4631

4632
  return TSDB_CODE_SUCCESS;
43,671✔
4633
}
4634

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

4637
static int32_t doHandleFillforward(SFillforwardInfo* pFillforwardInfo, int32_t type, SColumnInfoData* pOutput, int32_t pos) {
141,636✔
4638
  if (!pFillforwardInfo->nonnull) {
141,636✔
4639
    colDataSetNULL(pOutput, pos);
16,038✔
4640

4641
    return TSDB_CODE_SUCCESS;
16,038✔
4642
  }
4643

4644
  switch (type) {
125,598✔
4645
    case TSDB_DATA_TYPE_BOOL:
60,474✔
4646
    case TSDB_DATA_TYPE_UTINYINT:
4647
    case TSDB_DATA_TYPE_TINYINT:
4648
    case TSDB_DATA_TYPE_USMALLINT:
4649
    case TSDB_DATA_TYPE_SMALLINT:
4650
    case TSDB_DATA_TYPE_UINT:
4651
    case TSDB_DATA_TYPE_INT:
4652
    case TSDB_DATA_TYPE_UBIGINT:
4653
    case TSDB_DATA_TYPE_BIGINT:
4654
    case TSDB_DATA_TYPE_TIMESTAMP:
4655
      colDataSetInt64(pOutput, pos, &pFillforwardInfo->v);
60,474✔
4656
      break;
60,474✔
4657
    case TSDB_DATA_TYPE_FLOAT:
23,328✔
4658
      colDataSetFloat(pOutput, pos, &pFillforwardInfo->fv);
23,328✔
4659
      break;
23,328✔
4660
    case TSDB_DATA_TYPE_DOUBLE:
26,244✔
4661
      colDataSetDouble(pOutput, pos, &pFillforwardInfo->dv);
26,244✔
4662
      break;
26,244✔
4663
    case TSDB_DATA_TYPE_DECIMAL64:
5,346✔
4664
      return colDataSetVal(pOutput, pos, (const char*)&pFillforwardInfo->v, false);
5,346✔
4665
    case TSDB_DATA_TYPE_DECIMAL:
×
4666
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->dec, false);
×
4667
    case TSDB_DATA_TYPE_VARCHAR:
10,206✔
4668
    case TSDB_DATA_TYPE_VARBINARY:
4669
    case TSDB_DATA_TYPE_NCHAR:
4670
      return colDataSetVal(pOutput, pos, (void*)pFillforwardInfo->str, false);
10,206✔
4671
    default:
×
4672
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4673
  }
4674

4675
  return TSDB_CODE_SUCCESS;
110,046✔
4676
}
4677

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

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

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

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

4701
  return TSDB_CODE_SUCCESS;
141,636✔
4702
}
4703

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

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

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

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

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

4761
    int32_t pos = startOffset + numOfElems;
39,090✔
4762

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

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

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

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

4831
        if (!pFillforwardInfo->nonnull) {
86,718✔
4832
          pFillforwardInfo->nonnull = true;
42,699✔
4833
        }
4834
      }
4835

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

4842
    ++numOfElems;
38,604✔
4843
  }
4844

4845
_exit:
12,567✔
4846
  for (int i = 0; i < fillforwardColNum; ++i) {
56,238✔
4847
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
43,671✔
4848
    if (!pCtx) {
43,671✔
4849
      break;
×
4850
    }
4851

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

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

4861
    if (!code) {
43,671✔
4862
      pResInfo->numOfRes = numOfElems;
43,185✔
4863
    }
4864
  }
4865

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

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

4875
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,384,200✔
4876
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
2,384,200✔
4877
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
2,388,202✔
4878
  return true;
2,388,202✔
4879
}
4880

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

4889
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
8,580,283✔
4890
  SInputColumnInfoData* pInput = &pCtx->input;
8,580,324✔
4891

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

4894
  pRes->nullTupleSaved = false;
8,581,394✔
4895
  pRes->nullTuplePos.pageId = -1;
8,582,358✔
4896
  return TSDB_CODE_SUCCESS;
8,580,780✔
4897
}
4898

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

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

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

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

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

4916
  SInputColumnInfoData* pInput = &pCtx->input;
9,561,010✔
4917
  SColumnInfoData*      pCol = pInput->pData[0];
9,561,010✔
4918

4919
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
9,560,407✔
4920
  pRes->type = pInput->pData[0]->info.type;
9,557,026✔
4921

4922
  int32_t start = pInput->startRowIndex;
9,560,122✔
4923
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,380,063,282✔
4924
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,373,930,460✔
4925
      continue;
1,023,177✔
4926
    }
4927

4928
    numOfElems++;
1,373,250,068✔
4929
    char*   data = colDataGetData(pCol, i);
1,373,250,068✔
4930
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
1,374,938,603✔
4931
    if (code != TSDB_CODE_SUCCESS) {
1,369,481,574✔
4932
      return code;
×
4933
    }
4934
  }
4935

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

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

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

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

4956
  int32_t start = pInput->startRowIndex;
3,110,771✔
4957
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
942,101,257✔
4958
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
938,985,302✔
4959
      continue;
1,933,199✔
4960
    }
4961

4962
    numOfElems++;
937,022,034✔
4963
    char*   data = colDataGetData(pCol, i);
937,022,034✔
4964
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
937,520,972✔
4965
    if (code != TSDB_CODE_SUCCESS) {
937,057,287✔
4966
      return code;
×
4967
    }
4968
  }
4969

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

4978
  return TSDB_CODE_SUCCESS;
3,110,771✔
4979
}
4980

4981
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
555,116,073✔
4982
  uint16_t type = *(uint16_t*)param;
555,116,073✔
4983

4984
  STopBotResItem* val1 = (STopBotResItem*)p1;
555,150,895✔
4985
  STopBotResItem* val2 = (STopBotResItem*)p2;
555,150,895✔
4986

4987
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
555,150,895✔
4988
    if (val1->v.i == val2->v.i) {
356,101,802✔
4989
      return 0;
62,750,456✔
4990
    }
4991

4992
    return (val1->v.i > val2->v.i) ? 1 : -1;
293,571,772✔
4993
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
199,049,093✔
4994
    if (val1->v.u == val2->v.u) {
97,890,969✔
4995
      return 0;
21,256,783✔
4996
    }
4997

4998
    return (val1->v.u > val2->v.u) ? 1 : -1;
76,656,358✔
4999
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
101,158,217✔
5000
    if (val1->v.f == val2->v.f) {
3,030,788✔
5001
      return 0;
31,122✔
5002
    }
5003

5004
    return (val1->v.f > val2->v.f) ? 1 : -1;
2,999,666✔
5005
  }
5006

5007
  if (val1->v.d == val2->v.d) {
98,127,429✔
5008
    return 0;
5,434✔
5009
  }
5010

5011
  return (val1->v.d > val2->v.d) ? 1 : -1;
98,171,315✔
5012
}
5013

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

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

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

5024
  // not full yet
5025
  if (pEntryInfo->numOfRes < pRes->maxSize) {
2,147,483,647✔
5026
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
49,944,613✔
5027
    pItem->v = val;
49,944,025✔
5028
    pItem->uid = uid;
49,939,427✔
5029

5030
    // save the data of this tuple
5031
    if (pCtx->subsidiaries.num > 0) {
49,945,618✔
5032
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
13,919,867✔
5033
      if (code != TSDB_CODE_SUCCESS) {
13,917,874✔
5034
        return code;
×
5035
      }
5036
    }
5037
#ifdef BUF_PAGE_DEBUG
5038
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
5039
           pItem->tuplePos.offset);
5040
#endif
5041
    // allocate the buffer and keep the data of this row into the new allocated buffer
5042
    pEntryInfo->numOfRes++;
49,944,531✔
5043
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
49,939,786✔
5044
                        topBotResComparFn, !isTopQuery);
49,937,328✔
5045
    if (code != TSDB_CODE_SUCCESS) {
49,941,020✔
5046
      return code;
×
5047
    }
5048
  } else {  // replace the minimum value in the result
5049
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
2,147,483,647✔
5050
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
1,316,219,002✔
5051
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
1,305,648,917✔
5052
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
1,305,678,729✔
5053
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
2,147,483,647✔
5054
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
924,776,165✔
5055
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
923,523,456✔
5056
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
923,404,856✔
5057
      // replace the old data and the coresponding tuple data
5058
      STopBotResItem* pItem = &pItems[0];
43,170,223✔
5059
      pItem->v = val;
43,170,223✔
5060
      pItem->uid = uid;
42,172,159✔
5061

5062
      // save the data of this tuple by over writing the old data
5063
      if (pCtx->subsidiaries.num > 0) {
42,173,123✔
5064
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
22,642,711✔
5065
        if (code != TSDB_CODE_SUCCESS) {
22,639,337✔
5066
          return code;
×
5067
        }
5068
      }
5069
#ifdef BUF_PAGE_DEBUG
5070
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
5071
#endif
5072
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
42,172,159✔
5073
                            topBotResComparFn, NULL, !isTopQuery);
42,170,231✔
5074
      if (code != TSDB_CODE_SUCCESS) {
42,172,053✔
5075
        return code;
×
5076
      }
5077
    }
5078
  }
5079

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

5083

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

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

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

5100
  return false;
×
5101
}
5102

5103

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

5115
  int32_t offset = 0;
130,366,803✔
5116
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
402,051,104✔
5117
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
271,684,225✔
5118

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

5125
    if (fmIsSelectValueFunc(pc->functionId)) {
271,676,243✔
5126
      SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
271,675,836✔
5127
      int32_t      srcSlotId = pFuncParam->pCol->slotId;
271,681,277✔
5128

5129
      SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
271,679,955✔
5130
      if (NULL == pCol) {
271,682,201✔
5131
        return TSDB_CODE_OUT_OF_RANGE;
×
5132
      }
5133
      if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
543,364,902✔
5134
        offset += pCol->info.bytes;
70,371,834✔
5135
        continue;
70,371,834✔
5136
      }
5137

5138
      char* p = colDataGetData(pCol, rowIndex);
201,308,550✔
5139
      if (IS_VAR_DATA_TYPE(pCol->info.type)) {
201,311,609✔
5140
        int32_t bytes = calcStrBytesByType(pCol->info.type, p);
9,966,688✔
5141
        (void)memcpy(pStart + offset, p, bytes);
9,977,466✔
5142
      } else {
5143
        (void)memcpy(pStart + offset, p, pCol->info.bytes);
191,338,464✔
5144
      }
5145

5146
      offset += pCol->info.bytes;
201,310,913✔
5147
      continue;
201,313,689✔
5148
    }
5149
  }
5150

5151
  *res = buf;
130,346,123✔
5152
  return TSDB_CODE_SUCCESS;
130,373,761✔
5153
}
5154

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

5161
    if (pHandle->currentPage == -1) {
194,456,699✔
5162
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
6,294,026✔
5163
      if (pPage == NULL) {
6,300,621✔
5164
        return terrno;
×
5165
      }
5166
      pPage->num = sizeof(SFilePage);
6,300,621✔
5167
    } else {
5168
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
188,157,911✔
5169
      if (pPage == NULL) {
188,153,837✔
5170
        return terrno;
×
5171
      }
5172
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
188,153,837✔
5173
        // current page is all used, let's prepare a new buffer page
5174
        releaseBufPage(pHandle->pBuf, pPage);
78,530✔
5175
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
78,530✔
5176
        if (pPage == NULL) {
78,530✔
5177
          return terrno;
×
5178
        }
5179
        pPage->num = sizeof(SFilePage);
78,530✔
5180
      }
5181
    }
5182

5183
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
194,454,948✔
5184
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
194,453,547✔
5185

5186
    pPage->num += length;
194,453,756✔
5187
    setBufPageDirty(pPage, true);
194,455,917✔
5188
    releaseBufPage(pHandle->pBuf, pPage);
194,457,842✔
5189
  } else {  // other tuple save policy
5190
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
3✔
5191
      p.streamTupleKey = *key;
×
5192
    }
5193
  }
5194

5195
  *pPos = p;
194,452,656✔
5196
  return TSDB_CODE_SUCCESS;
194,450,888✔
5197
}
5198

5199
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
86,310,961✔
5200
  int32_t code = prepareBuf(pCtx);
86,310,961✔
5201
  if (TSDB_CODE_SUCCESS != code) {
86,313,593✔
5202
    return code;
×
5203
  }
5204

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

5219
  char* buf = NULL;
86,312,961✔
5220
  code = serializeTupleData(pCtx, pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
86,311,330✔
5221
  if (TSDB_CODE_SUCCESS != code) {
86,312,848✔
5222
    return code;
×
5223
  }
5224
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
86,312,848✔
5225
}
5226

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

5244
  return TSDB_CODE_SUCCESS;
44,054,446✔
5245
}
5246

5247
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
44,055,622✔
5248
  int32_t code = prepareBuf(pCtx);
44,055,622✔
5249
  if (TSDB_CODE_SUCCESS != code) {
44,055,991✔
5250
    return code;
×
5251
  }
5252

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

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

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

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

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

5293
  int16_t type = pCtx->pExpr->base.resSchema.type;
8,569,707✔
5294
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
8,570,388✔
5295

5296
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,570,388✔
5297
  if (NULL == pCol) {
8,569,707✔
5298
    return TSDB_CODE_OUT_OF_RANGE;
×
5299
  }
5300

5301
  // todo assign the tag value and the corresponding row data
5302
  int32_t currentRow = pBlock->info.rows;
8,569,707✔
5303
  if (pEntryInfo->numOfRes <= 0) {
8,569,707✔
5304
    colDataSetNULL(pCol, currentRow);
31,394✔
5305
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
31,394✔
5306
    return code;
31,394✔
5307
  }
5308
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
58,489,633✔
5309
    STopBotResItem* pItem = &pRes->pItems[i];
49,950,639✔
5310
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
49,950,639✔
5311
    if (TSDB_CODE_SUCCESS != code) {
49,951,320✔
5312
      return code;
×
5313
    }
5314
#ifdef BUF_PAGE_DEBUG
5315
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
5316
           pItem->tuplePos.offset);
5317
#endif
5318
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
49,951,320✔
5319
    if (TSDB_CODE_SUCCESS != code) {
49,950,639✔
5320
      return code;
×
5321
    }
5322
    currentRow += 1;
49,950,639✔
5323
  }
5324

5325
  return code;
8,538,994✔
5326
}
5327

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

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

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

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

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

5401
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
9,290,432✔
5402

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

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

5416
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
106,972,670✔
5417
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
106,973,862✔
5418
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
106,973,862✔
5419
  pInfo->hasResult = false;
106,972,670✔
5420
  return TSDB_CODE_SUCCESS;
106,972,670✔
5421
}
5422

5423
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
162,065,213✔
5424
  int32_t numOfElems = 0;
162,065,213✔
5425

5426
  // Only the pre-computing information loaded and actual data does not loaded
5427
  SInputColumnInfoData* pInput = &pCtx->input;
162,065,213✔
5428
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
162,068,544✔
5429
  int32_t               type = pInput->pData[0]->info.type;
162,091,607✔
5430

5431
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
162,091,821✔
5432

5433
  if (pInput->colDataSMAIsSet) {
162,079,052✔
5434
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
50,779,109✔
5435
    if (numOfElems == 0) {
50,778,428✔
5436
      goto _spread_over;
36,022,116✔
5437
    }
5438
    double tmin = 0.0, tmax = 0.0;
14,756,312✔
5439
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
14,756,312✔
5440
      tmin = (double)GET_INT64_VAL(&pAgg->min);
7,550,830✔
5441
      tmax = (double)GET_INT64_VAL(&pAgg->max);
7,550,819✔
5442
    } else if (IS_FLOAT_TYPE(type)) {
7,205,482✔
UNCOV
5443
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
5444
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
5445
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
7,205,482✔
5446
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
7,204,098✔
5447
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
7,206,866✔
5448
    }
5449

5450
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
14,759,069✔
5451
      SET_DOUBLE_VAL(&pInfo->min, tmin);
674,329✔
5452
    }
5453

5454
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
14,756,312✔
5455
      SET_DOUBLE_VAL(&pInfo->max, tmax);
711,905✔
5456
    }
5457

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

5461
    int32_t start = pInput->startRowIndex;
111,310,584✔
5462
    // check the valid data one by one
5463
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,101,915,914✔
5464
      if (colDataIsNull_f(pCol, i)) {
990,611,059✔
5465
        continue;
103,258,499✔
5466
      }
5467

5468
      char* data = colDataGetData(pCol, i);
887,336,549✔
5469

5470
      double v = 0;
887,352,851✔
5471
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
887,352,851✔
5472
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
887,350,377✔
5473
        SET_DOUBLE_VAL(&pInfo->min, v);
92,628,883✔
5474
      }
5475

5476
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
887,344,417✔
5477
        SET_DOUBLE_VAL(&pInfo->max, v);
112,317,644✔
5478
      }
5479

5480
      numOfElems += 1;
887,346,205✔
5481
    }
5482
  }
5483

5484
_spread_over:
111,009,955✔
5485
  // data in the check operation are all null, not output
5486
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
161,768,160✔
5487
  if (numOfElems > 0) {
161,768,981✔
5488
    pInfo->hasResult = true;
110,217,422✔
5489
  }
5490

5491
  return TSDB_CODE_SUCCESS;
162,068,696✔
5492
}
5493

5494
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
8,483,677✔
5495
  pOutput->hasResult = pInput->hasResult;
8,483,677✔
5496
  if (pInput->max > pOutput->max) {
8,483,677✔
5497
    pOutput->max = pInput->max;
5,937,124✔
5498
  }
5499

5500
  if (pInput->min < pOutput->min) {
8,483,677✔
5501
    pOutput->min = pInput->min;
5,934,420✔
5502
  }
5503
}
8,483,677✔
5504

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

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

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

5518
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,289,286✔
5519

5520
  int32_t start = pInput->startRowIndex;
6,289,286✔
5521
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
15,070,856✔
5522
    if (colDataIsNull_s(pCol, i)) continue;
17,563,140✔
5523
    char*        data = colDataGetData(pCol, i);
8,781,570✔
5524
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
8,781,570✔
5525
    if (pInputInfo->hasResult) {
8,781,570✔
5526
      spreadTransferInfo(pInputInfo, pInfo);
8,483,677✔
5527
    }
5528
  }
5529

5530
  if (pInfo->hasResult) {
6,289,286✔
5531
    GET_RES_INFO(pCtx)->numOfRes = 1;
6,127,617✔
5532
  }
5533

5534
  return TSDB_CODE_SUCCESS;
6,289,286✔
5535
}
5536

5537
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
89,553,646✔
5538
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
89,553,646✔
5539
  if (pInfo->hasResult == true) {
89,553,646✔
5540
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
73,866,003✔
5541
  } else {
5542
    GET_RES_INFO(pCtx)->isNullRes = 1;
15,687,643✔
5543
  }
5544
  return functionFinalize(pCtx, pBlock);
89,553,646✔
5545
}
5546

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

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

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

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

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

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

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

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

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

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

5604
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,111,670✔
5605
  pInfo->result = 0;
5,111,670✔
5606
  pInfo->min = TSKEY_MAX;
5,111,670✔
5607
  pInfo->max = 0;
5,111,088✔
5608

5609
  if (pCtx->numOfParams > 1) {
5,111,088✔
5610
    pInfo->timeUnit = pCtx->param[1].param.i;
2,996,852✔
5611
  } else {
5612
    pInfo->timeUnit = 1;
2,114,236✔
5613
  }
5614

5615
  return TSDB_CODE_SUCCESS;
5,111,150✔
5616
}
5617

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

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

5625
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,176,584✔
5626

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

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

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

5663
    int32_t start = pInput->startRowIndex;
5,176,584✔
5664
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
5,175,468✔
5665
    if (pCtx->order == TSDB_ORDER_DESC) {
5,174,366✔
5666
      if (pCtx->start.key == INT64_MIN) {
38,760✔
5667
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
38,760✔
5668
      } else {
5669
        pInfo->max = pCtx->start.key + 1;
×
5670
      }
5671

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

5685
      if (pCtx->end.key == INT64_MIN) {
5,137,380✔
5686
        pInfo->max =
5,068,651✔
5687
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
5,069,705✔
5688
      } else {
5689
        pInfo->max = pCtx->end.key + 1;
68,133✔
5690
      }
5691
    }
5692
  }
5693

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

5698
  return TSDB_CODE_SUCCESS;
5,176,078✔
5699
}
5700

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

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

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

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

5721
  int32_t start = pInput->startRowIndex;
×
5722

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

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

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

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

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

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

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

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

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

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

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

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

5791
static int8_t getHistogramBinType(char* binTypeStr) {
1,035,526✔
5792
  int8_t binType;
5793
  if (strcasecmp(binTypeStr, "user_input") == 0) {
1,035,526✔
5794
    binType = USER_INPUT_BIN;
183,352✔
5795
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
852,174✔
5796
    binType = LINEAR_BIN;
131,184✔
5797
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
720,990✔
5798
    binType = LOG_BIN;
720,405✔
5799
  } else {
5800
    binType = UNKNOWN_BIN;
585✔
5801
  }
5802

5803
  return binType;
1,035,526✔
5804
}
5805

5806
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
1,034,941✔
5807
  cJSON*  binDesc = cJSON_Parse(binDescStr);
1,034,941✔
5808
  int32_t numOfBins;
5809
  double* intervals;
5810
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
1,035,526✔
5811
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
851,589✔
5812
    int32_t startIndex;
5813
    if (numOfParams != 4) {
852,174✔
5814
      cJSON_Delete(binDesc);
×
5815
      return TSDB_CODE_FAILED;
×
5816
    }
5817

5818
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
852,174✔
5819
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
851,004✔
5820
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
851,589✔
5821
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
852,174✔
5822
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
852,174✔
5823

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

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

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

5840
    int32_t counter = (int32_t)count->valueint;
852,174✔
5841
    if (infinity->valueint == false) {
850,579✔
5842
      startIndex = 0;
609,339✔
5843
      numOfBins = counter + 1;
609,339✔
5844
    } else {
5845
      startIndex = 1;
241,400✔
5846
      numOfBins = counter + 3;
241,400✔
5847
    }
5848

5849
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
850,739✔
5850
    if (NULL == intervals) {
850,579✔
5851
      cJSON_Delete(binDesc);
×
5852
      qError("histogram function out of memory");
×
5853
      return terrno;
×
5854
    }
5855
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
850,579✔
5856
      // linear bin process
5857
      if (width->valuedouble == 0) {
131,184✔
5858
        taosMemoryFree(intervals);
×
5859
        cJSON_Delete(binDesc);
×
5860
        return TSDB_CODE_FAILED;
×
5861
      }
5862
      for (int i = 0; i < counter + 1; ++i) {
574,992✔
5863
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
443,808✔
5864
        if (isinf(intervals[startIndex])) {
443,808✔
5865
          taosMemoryFree(intervals);
×
5866
          cJSON_Delete(binDesc);
×
5867
          return TSDB_CODE_FAILED;
×
5868
        }
5869
        startIndex++;
443,808✔
5870
      }
5871
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
720,405✔
5872
      // log bin process
5873
      if (start->valuedouble == 0) {
719,980✔
5874
        taosMemoryFree(intervals);
×
5875
        cJSON_Delete(binDesc);
×
5876
        return TSDB_CODE_FAILED;
×
5877
      }
5878
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
718,810✔
5879
        taosMemoryFree(intervals);
1,435✔
5880
        cJSON_Delete(binDesc);
×
5881
        return TSDB_CODE_FAILED;
×
5882
      }
5883
      for (int i = 0; i < counter + 1; ++i) {
4,698,737✔
5884
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
3,979,318✔
5885
        if (isinf(intervals[startIndex])) {
3,978,757✔
5886
          taosMemoryFree(intervals);
×
5887
          cJSON_Delete(binDesc);
×
5888
          return TSDB_CODE_FAILED;
×
5889
        }
5890
        startIndex++;
3,979,342✔
5891
      }
5892
    } else {
5893
      taosMemoryFree(intervals);
×
5894
      cJSON_Delete(binDesc);
×
5895
      return TSDB_CODE_FAILED;
×
5896
    }
5897

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

5948
  pInfo->numOfBins = numOfBins - 1;
1,034,091✔
5949
  pInfo->normalized = normalized;
1,032,945✔
5950
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
5,291,098✔
5951
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
4,256,269✔
5952
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
4,256,718✔
5953
    pInfo->bins[i].count = 0;
4,258,473✔
5954
  }
5955

5956
  taosMemoryFree(intervals);
1,033,979✔
5957
  cJSON_Delete(binDesc);
1,034,941✔
5958

5959
  return TSDB_CODE_SUCCESS;
1,034,516✔
5960
}
5961

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

5970
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,034,941✔
5971
  pInfo->numOfBins = 0;
1,034,941✔
5972
  pInfo->totalCount = 0;
1,034,941✔
5973
  pInfo->normalized = 0;
1,035,526✔
5974

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

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

6001
  return TSDB_CODE_SUCCESS;
1,034,380✔
6002
}
6003

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

6007
  SInputColumnInfoData* pInput = &pCtx->input;
1,208,225✔
6008
  SColumnInfoData*      pCol = pInput->pData[0];
1,207,664✔
6009

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

6012
  int32_t start = pInput->startRowIndex;
1,207,800✔
6013
  int32_t numOfRows = pInput->numOfRows;
1,207,239✔
6014

6015
  int32_t numOfElems = 0;
1,212,955✔
6016
  for (int32_t i = start; i < numOfRows + start; ++i) {
174,599,430✔
6017
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
173,390,620✔
6018
      continue;
89,927,944✔
6019
    }
6020

6021
    numOfElems++;
83,461,747✔
6022

6023
    char*  data = colDataGetData(pCol, i);
83,461,747✔
6024
    double v;
6025
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
83,502,161✔
6026

6027
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
248,019,235✔
6028
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
196,973,537✔
6029
        pInfo->bins[k].count++;
32,479,031✔
6030
        pInfo->totalCount++;
32,479,031✔
6031
        break;
32,479,031✔
6032
      }
6033
    }
6034
  }
6035

6036
  if (!isPartial) {
1,208,810✔
6037
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
820,356✔
6038
  } else {
6039
    GET_RES_INFO(pCtx)->numOfRes = 1;
388,454✔
6040
  }
6041
  return TSDB_CODE_SUCCESS;
1,208,810✔
6042
}
6043

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

6046
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
388,454✔
6047

6048
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
246,574✔
6049
  pOutput->normalized = pInput->normalized;
246,574✔
6050
  pOutput->numOfBins = pInput->numOfBins;
246,574✔
6051
  pOutput->totalCount += pInput->totalCount;
246,574✔
6052
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
1,609,328✔
6053
    pOutput->bins[k].lower = pInput->bins[k].lower;
1,362,754✔
6054
    pOutput->bins[k].upper = pInput->bins[k].upper;
1,362,754✔
6055
    pOutput->bins[k].count += pInput->bins[k].count;
1,362,754✔
6056
  }
6057
}
245,989✔
6058

6059
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
246,574✔
6060
  SInputColumnInfoData* pInput = &pCtx->input;
246,574✔
6061
  SColumnInfoData*      pCol = pInput->pData[0];
246,574✔
6062
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
246,574✔
6063
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6064
  }
6065

6066
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
246,574✔
6067

6068
  int32_t start = pInput->startRowIndex;
246,574✔
6069

6070
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
493,148✔
6071
    char*           data = colDataGetData(pCol, i);
246,574✔
6072
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
246,574✔
6073
    histogramTransferInfo(pInputInfo, pInfo);
246,574✔
6074
  }
6075

6076
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
246,574✔
6077
  return TSDB_CODE_SUCCESS;
246,574✔
6078
}
6079

6080
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,013,071✔
6081
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,013,071✔
6082
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,012,486✔
6083
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
1,012,646✔
6084
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,012,486✔
6085
  int32_t              code = TSDB_CODE_SUCCESS;
1,012,061✔
6086

6087
  int32_t currentRow = pBlock->info.rows;
1,012,061✔
6088
  if (NULL == pCol) {
1,011,636✔
6089
    return TSDB_CODE_OUT_OF_RANGE;
×
6090
  }
6091

6092
  if (pInfo->normalized) {
1,011,636✔
6093
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
4,991,532✔
6094
      if (pInfo->totalCount != 0) {
4,065,498✔
6095
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
505,965✔
6096
      } else {
6097
        pInfo->bins[k].percentage = 0;
3,558,258✔
6098
      }
6099
    }
6100
  }
6101

6102
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
5,166,924✔
6103
    int32_t len;
6104
    char    buf[512] = {0};
4,153,853✔
6105
    if (!pInfo->normalized) {
4,154,278✔
6106
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
86,230✔
6107
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
6108
                     pInfo->bins[i].upper, pInfo->bins[i].count);
6109
    } else {
6110
      len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
4,067,463✔
6111
                     "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
6112
                     pInfo->bins[i].percentage);
6113
    }
6114
    varDataSetLen(buf, len);
4,153,853✔
6115
    code = colDataSetVal(pCol, currentRow, buf, false);
4,153,853✔
6116
    if (TSDB_CODE_SUCCESS != code) {
4,154,278✔
6117
      return code;
×
6118
    }
6119
    currentRow++;
4,154,278✔
6120
  }
6121

6122
  return code;
1,013,071✔
6123
}
6124

6125
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
245,989✔
6126
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
245,989✔
6127
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
246,574✔
6128
  int32_t              resultBytes = getHistogramInfoSize();
246,574✔
6129
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
245,989✔
6130

6131
  if (NULL == res) {
246,574✔
6132
    return terrno;
×
6133
  }
6134
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
246,574✔
6135
  varDataSetLen(res, resultBytes);
246,574✔
6136

6137
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
246,574✔
6138
  int32_t          code = TSDB_CODE_SUCCESS;
246,574✔
6139
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
246,574✔
6140
  if (NULL == pCol) {
246,574✔
6141
    code = terrno;
×
6142
    goto _exit;
×
6143
  }
6144
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
246,574✔
6145

6146
_exit:
246,574✔
6147
  taosMemoryFree(res);
246,574✔
6148
  return code;
246,574✔
6149
}
6150

6151
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6152
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6153
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6154

6155
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6156
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6157

6158
  histogramTransferInfo(pSBuf, pDBuf);
×
6159
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
6160
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
6161
  return TSDB_CODE_SUCCESS;
×
6162
}
6163

6164
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
296,726✔
6165

6166
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
4,272,309✔
6167
  pEnv->calcMemSize = sizeof(SHLLInfo);
4,272,309✔
6168
  return true;
4,273,501✔
6169
}
6170

6171
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
758,036,356✔
6172
  uint64_t hash = MurmurHash3_64(data, bytes);
758,036,356✔
6173
  int32_t  index = hash & HLL_BUCKET_MASK;
758,000,936✔
6174
  hash >>= HLL_BUCKET_BITS;
758,000,936✔
6175
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
758,000,936✔
6176
  uint64_t bit = 1;
758,000,936✔
6177
  uint8_t  count = 1;
758,000,936✔
6178
  while ((hash & bit) == 0) {
1,647,030,072✔
6179
    count++;
889,029,136✔
6180
    bit <<= 1;
889,029,136✔
6181
  }
6182
  *buk = index;
758,000,936✔
6183
  return count;
758,030,864✔
6184
}
6185

6186
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
10,174,849✔
6187
  uint64_t* word = (uint64_t*)buckets;
10,174,849✔
6188
  uint8_t*  bytes;
6189

6190
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
2,147,483,647✔
6191
    if (*word == 0) {
2,147,483,647✔
6192
      bucketHisto[0] += 8;
2,147,483,647✔
6193
    } else {
6194
      bytes = (uint8_t*)word;
68,244,129✔
6195
      bucketHisto[bytes[0]]++;
68,244,129✔
6196
      bucketHisto[bytes[1]]++;
77,979,193✔
6197
      bucketHisto[bytes[2]]++;
77,979,193✔
6198
      bucketHisto[bytes[3]]++;
77,979,193✔
6199
      bucketHisto[bytes[4]]++;
77,979,193✔
6200
      bucketHisto[bytes[5]]++;
77,979,193✔
6201
      bucketHisto[bytes[6]]++;
77,979,193✔
6202
      bucketHisto[bytes[7]]++;
77,979,193✔
6203
    }
6204
    word++;
2,147,483,647✔
6205
  }
6206
}
10,196,305✔
6207
static double hllTau(double x) {
10,174,849✔
6208
  if (x == 0. || x == 1.) return 0.;
10,174,849✔
6209
  double zPrime;
6210
  double y = 1.0;
×
6211
  double z = 1 - x;
×
6212
  do {
6213
    x = sqrt(x);
×
6214
    zPrime = z;
×
6215
    y *= 0.5;
×
6216
    z -= pow(1 - x, 2) * y;
×
6217
  } while (zPrime != z);
×
6218
  return z / 3;
×
6219
}
6220

6221
static double hllSigma(double x) {
10,174,849✔
6222
  if (x == 1.0) return INFINITY;
10,174,849✔
6223
  double zPrime;
6224
  double y = 1;
9,983,092✔
6225
  double z = x;
9,983,092✔
6226
  do {
6227
    x *= x;
195,967,804✔
6228
    zPrime = z;
195,967,804✔
6229
    z += x * y;
195,967,804✔
6230
    y += y;
195,967,804✔
6231
  } while (zPrime != z);
195,967,804✔
6232
  return z;
9,983,092✔
6233
}
6234

6235
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
6236
// sketches"
6237
static uint64_t hllCountCnt(uint8_t* buckets) {
10,174,849✔
6238
  double  m = HLL_BUCKETS;
10,174,849✔
6239
  int32_t buckethisto[64] = {0};
10,174,849✔
6240
  hllBucketHisto(buckets, buckethisto);
10,174,849✔
6241

6242
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
10,174,849✔
6243
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
518,908,359✔
6244
    z += buckethisto[j];
508,733,510✔
6245
    z *= 0.5;
508,733,510✔
6246
  }
6247

6248
  z += m * hllSigma(buckethisto[0] / (double)m);
10,174,849✔
6249
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
10,174,849✔
6250

6251
  return (uint64_t)E;
10,174,849✔
6252
}
6253

6254
int32_t hllFunction(SqlFunctionCtx* pCtx) {
10,455,071✔
6255
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,455,071✔
6256

6257
  SInputColumnInfoData* pInput = &pCtx->input;
10,458,448✔
6258
  SColumnInfoData*      pCol = pInput->pData[0];
10,458,448✔
6259

6260
  int32_t type = pCol->info.type;
10,456,824✔
6261
  int32_t bytes = pCol->info.bytes;
10,455,667✔
6262

6263
  int32_t start = pInput->startRowIndex;
10,455,503✔
6264
  int32_t numOfRows = pInput->numOfRows;
10,455,503✔
6265

6266
  int32_t numOfElems = 0;
10,454,346✔
6267
  if (IS_NULL_TYPE(type)) {
10,454,346✔
6268
    goto _hll_over;
159,386✔
6269
  }
6270

6271
  for (int32_t i = start; i < numOfRows + start; ++i) {
800,567,990✔
6272
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
829,877,884✔
6273
      continue;
32,245,452✔
6274
    }
6275

6276
    numOfElems++;
758,028,649✔
6277

6278
    char* data = colDataGetData(pCol, i);
758,028,649✔
6279
    if (IS_VAR_DATA_TYPE(type)) {
758,061,912✔
6280
      if (IS_STR_DATA_BLOB(type)) {
88,185,882✔
UNCOV
6281
        bytes = blobDataLen(data);
×
6282
        data = blobDataVal(data);
×
6283
      } else {
6284
        bytes = varDataLen(data);
88,190,054✔
6285
        data = varDataVal(data);
88,190,054✔
6286
      }
6287
    }
6288

6289
    int32_t index = 0;
758,066,216✔
6290
    uint8_t count = hllCountNum(data, bytes, &index);
758,047,148✔
6291
    uint8_t oldcount = pInfo->buckets[index];
758,014,710✔
6292
    if (count > oldcount) {
758,019,742✔
6293
      pInfo->buckets[index] = count;
124,784,033✔
6294
    }
6295
  }
6296

6297
_hll_over:
10,282,307✔
6298
  pInfo->totalCount += numOfElems;
10,441,693✔
6299

6300
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,458,448✔
6301
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
828✔
6302
  } else {
6303
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,457,620✔
6304
  }
6305

6306
  return TSDB_CODE_SUCCESS;
10,457,256✔
6307
}
6308

6309
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
297,848✔
6310
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
2,147,483,647✔
6311
    if (pOutput->buckets[k] < pInput->buckets[k]) {
2,147,483,647✔
6312
      pOutput->buckets[k] = pInput->buckets[k];
24,353,992✔
6313
    }
6314
  }
6315
  pOutput->totalCount += pInput->totalCount;
129,005✔
6316
}
297,848✔
6317

6318
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
296,044✔
6319
  SInputColumnInfoData* pInput = &pCtx->input;
296,044✔
6320
  SColumnInfoData*      pCol = pInput->pData[0];
296,044✔
6321

6322
  if (IS_NULL_TYPE(pCol->info.type)) {
296,044✔
6323
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
6324
    return TSDB_CODE_SUCCESS;
×
6325
  }
6326

6327
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
296,044✔
6328
    return TSDB_CODE_SUCCESS;
×
6329
  }
6330

6331
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
296,044✔
6332

6333
  int32_t start = pInput->startRowIndex;
296,044✔
6334

6335
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
593,892✔
6336
    if (colDataIsNull_s(pCol, i)) continue;
595,696✔
6337
    char*     data = colDataGetData(pCol, i);
297,848✔
6338
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
297,848✔
6339
    hllTransferInfo(pInputInfo, pInfo);
297,848✔
6340
  }
6341

6342
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
296,044✔
6343
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
92✔
6344
  } else {
6345
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
295,952✔
6346
  }
6347

6348
  return TSDB_CODE_SUCCESS;
296,044✔
6349
}
6350

6351
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,174,849✔
6352
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
10,174,849✔
6353

6354
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,174,849✔
6355
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
10,174,849✔
6356
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
10,174,849✔
6357
    pInfo->numOfRes = 1;
191,573✔
6358
  }
6359

6360
  return functionFinalize(pCtx, pBlock);
10,174,849✔
6361
}
6362

6363
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
297,287✔
6364
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
297,287✔
6365
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
297,287✔
6366
  int32_t              resultBytes = getHLLInfoSize();
297,287✔
6367
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
296,726✔
6368

6369
  if (NULL == res) {
297,213✔
6370
    return terrno;
×
6371
  }
6372
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
297,213✔
6373
  varDataSetLen(res, resultBytes);
297,213✔
6374

6375
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
297,416✔
6376
  int32_t          code = TSDB_CODE_SUCCESS;
296,855✔
6377
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
296,855✔
6378
  if (NULL == pCol) {
297,287✔
6379
    code = terrno;
×
6380
    goto _exit;
×
6381
  }
6382

6383
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
297,287✔
6384

6385
_exit:
297,848✔
6386
  taosMemoryFree(res);
297,848✔
6387
  return code;
297,848✔
6388
}
6389

6390
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
6391
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
6392
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
6393

6394
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
6395
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
6396

6397
  hllTransferInfo(pSBuf, pDBuf);
×
6398
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
6399
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
6400
  return TSDB_CODE_SUCCESS;
×
6401
}
6402

6403
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,528,325✔
6404
  pEnv->calcMemSize = sizeof(SStateInfo);
1,528,325✔
6405
  return true;
1,528,325✔
6406
}
6407

6408
static int8_t getStateOpType(char* opStr) {
1,825,823✔
6409
  int8_t opType;
6410
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,825,823✔
6411
    opType = STATE_OPER_LT;
172,230✔
6412
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
1,653,593✔
6413
    opType = STATE_OPER_GT;
279,773✔
6414
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
1,373,820✔
6415
    opType = STATE_OPER_LE;
202,920✔
6416
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
1,170,900✔
6417
    opType = STATE_OPER_GE;
310,728✔
6418
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
860,172✔
6419
    opType = STATE_OPER_NE;
456,462✔
6420
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
403,710✔
6421
    opType = STATE_OPER_EQ;
403,710✔
6422
  } else {
UNCOV
6423
    opType = STATE_OPER_INVALID;
×
6424
  }
6425

6426
  return opType;
1,825,823✔
6427
}
6428

6429
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
174,587,296✔
6430
  char* data = colDataGetData(pCol, index);
174,587,296✔
6431
  switch (pCol->info.type) {
174,587,296✔
6432
    case TSDB_DATA_TYPE_TINYINT: {
765,666✔
6433
      int8_t v = *(int8_t*)data;
765,666✔
6434
      STATE_COMP(op, v, param);
765,666✔
6435
      break;
×
6436
    }
6437
    case TSDB_DATA_TYPE_UTINYINT: {
33,772,384✔
6438
      uint8_t v = *(uint8_t*)data;
33,772,384✔
6439
      STATE_COMP(op, v, param);
33,772,384✔
6440
      break;
×
6441
    }
6442
    case TSDB_DATA_TYPE_SMALLINT: {
768,732✔
6443
      int16_t v = *(int16_t*)data;
768,732✔
6444
      STATE_COMP(op, v, param);
768,732✔
6445
      break;
×
6446
    }
6447
    case TSDB_DATA_TYPE_USMALLINT: {
701,280✔
6448
      uint16_t v = *(uint16_t*)data;
701,280✔
6449
      STATE_COMP(op, v, param);
701,280✔
6450
      break;
×
6451
    }
6452
    case TSDB_DATA_TYPE_INT: {
105,983,775✔
6453
      int32_t v = *(int32_t*)data;
105,983,775✔
6454
      STATE_COMP(op, v, param);
105,983,775✔
UNCOV
6455
      break;
×
6456
    }
6457
    case TSDB_DATA_TYPE_UINT: {
701,280✔
6458
      uint32_t v = *(uint32_t*)data;
701,280✔
6459
      STATE_COMP(op, v, param);
701,280✔
6460
      break;
×
6461
    }
6462
    case TSDB_DATA_TYPE_BIGINT: {
782,403✔
6463
      int64_t v = *(int64_t*)data;
782,403✔
6464
      STATE_COMP(op, v, param);
782,403✔
6465
      break;
×
6466
    }
6467
    case TSDB_DATA_TYPE_UBIGINT: {
701,280✔
6468
      uint64_t v = *(uint64_t*)data;
701,280✔
6469
      STATE_COMP(op, v, param);
701,280✔
6470
      break;
×
6471
    }
6472
    case TSDB_DATA_TYPE_FLOAT: {
5,868,732✔
6473
      float v = *(float*)data;
5,868,732✔
6474
      STATE_COMP(op, v, param);
5,868,732✔
6475
      break;
×
6476
    }
6477
    case TSDB_DATA_TYPE_DOUBLE: {
24,541,284✔
6478
      double v = *(double*)data;
24,541,284✔
6479
      STATE_COMP(op, v, param);
24,541,284✔
6480
      break;
×
6481
    }
6482
    default: {
×
6483
      return false;
×
6484
    }
6485
  }
UNCOV
6486
  return false;
×
6487
}
6488

6489
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
447,437✔
6490
  int32_t              code = TSDB_CODE_SUCCESS;
447,437✔
6491
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
447,437✔
6492
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
447,437✔
6493

6494
  SInputColumnInfoData* pInput = &pCtx->input;
447,437✔
6495
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
447,437✔
6496

6497
  SColumnInfoData* pInputCol = pInput->pData[0];
447,437✔
6498

6499
  int32_t          numOfElems = 0;
447,437✔
6500
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
447,437✔
6501

6502
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
447,437✔
6503
  if (STATE_OPER_INVALID == op) {
447,437✔
6504
    return 0;
×
6505
  }
6506

6507
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
119,570,027✔
6508
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
119,124,510✔
6509
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,920✔
6510
    } else {
6511
      pInfo->prevTs = tsList[i];
119,122,590✔
6512
    }
6513

6514
    pInfo->isPrevTsSet = true;
119,122,590✔
6515
    numOfElems++;
119,122,590✔
6516

6517
    if (colDataIsNull_f(pInputCol, i)) {
119,122,590✔
6518
      colDataSetNULL(pOutput, i);
24,043,376✔
6519
      // handle selectivity
6520
      if (pCtx->subsidiaries.num > 0) {
24,043,376✔
6521
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
4,419✔
6522
        if (TSDB_CODE_SUCCESS != code) {
4,419✔
6523
          return code;
×
6524
        }
6525
      }
6526
      continue;
24,043,376✔
6527
    }
6528

6529
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
95,079,214✔
6530

6531
    int64_t output = -1;
95,078,243✔
6532
    if (ret) {
95,078,734✔
6533
      output = ++pInfo->count;
57,901,917✔
6534
    } else {
6535
      pInfo->count = 0;
37,176,817✔
6536
    }
6537
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
95,078,734✔
6538
    if (TSDB_CODE_SUCCESS != code) {
95,079,214✔
6539
      return code;
×
6540
    }
6541

6542
    // handle selectivity
6543
    if (pCtx->subsidiaries.num > 0) {
95,079,214✔
6544
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
952,044✔
6545
      if (TSDB_CODE_SUCCESS != code) {
952,044✔
6546
        return code;
×
6547
      }
6548
    }
6549
  }
6550

6551
  pResInfo->numOfRes = numOfElems;
445,517✔
6552
  return TSDB_CODE_SUCCESS;
445,517✔
6553
}
6554

6555
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
1,378,386✔
6556
  int32_t              code = TSDB_CODE_SUCCESS;
1,378,386✔
6557
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,378,386✔
6558
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,378,386✔
6559

6560
  SInputColumnInfoData* pInput = &pCtx->input;
1,378,386✔
6561
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,378,386✔
6562

6563
  SColumnInfoData* pInputCol = pInput->pData[0];
1,378,386✔
6564

6565
  int32_t          numOfElems = 0;
1,378,386✔
6566
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,378,386✔
6567

6568
  // TODO: process timeUnit for different db precisions
6569
  int32_t timeUnit = 1;
1,378,386✔
6570
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
1,378,386✔
6571
    timeUnit = pCtx->param[3].param.i;
1,099,941✔
6572
  }
6573

6574
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
1,378,386✔
6575
  if (STATE_OPER_INVALID == op) {
1,378,386✔
6576
    return TSDB_CODE_INVALID_PARA;
×
6577
  }
6578

6579
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
147,014,267✔
6580
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
145,637,801✔
6581
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,920✔
6582
    } else {
6583
      pInfo->prevTs = tsList[i];
145,635,401✔
6584
    }
6585

6586
    pInfo->isPrevTsSet = true;
145,635,401✔
6587
    numOfElems++;
145,635,401✔
6588

6589
    if (colDataIsNull_f(pInputCol, i)) {
145,635,401✔
6590
      colDataSetNULL(pOutput, i);
66,127,308✔
6591
      // handle selectivity
6592
      if (pCtx->subsidiaries.num > 0) {
66,127,788✔
6593
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
8,587✔
6594
        if (TSDB_CODE_SUCCESS != code) {
8,587✔
6595
          return code;
×
6596
        }
6597
      }
6598
      continue;
66,127,788✔
6599
    }
6600

6601
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
79,508,093✔
6602
    int64_t output = -1;
79,508,573✔
6603
    if (ret) {
79,508,573✔
6604
      if (pInfo->durationStart == 0) {
38,398,082✔
6605
        output = 0;
2,253,525✔
6606
        pInfo->durationStart = tsList[i];
2,253,525✔
6607
      } else {
6608
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
36,144,557✔
6609
      }
6610
    } else {
6611
      pInfo->durationStart = 0;
41,110,491✔
6612
    }
6613
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
79,508,573✔
6614
    if (TSDB_CODE_SUCCESS != code) {
79,508,573✔
6615
      return code;
×
6616
    }
6617

6618
    // handle selectivity
6619
    if (pCtx->subsidiaries.num > 0) {
79,508,573✔
6620
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
106,380✔
6621
      if (TSDB_CODE_SUCCESS != code) {
106,380✔
6622
        return code;
×
6623
      }
6624
    }
6625
  }
6626

6627
  pResInfo->numOfRes = numOfElems;
1,376,466✔
6628
  return TSDB_CODE_SUCCESS;
1,376,466✔
6629
}
6630

6631
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
794,254✔
6632
  pEnv->calcMemSize = sizeof(SSumRes);
794,254✔
6633
  return true;
794,254✔
6634
}
6635

6636
int32_t csumFunction(SqlFunctionCtx* pCtx) {
1,195,466✔
6637
  int32_t              code = TSDB_CODE_SUCCESS;
1,195,466✔
6638
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,195,466✔
6639
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
1,194,881✔
6640

6641
  SInputColumnInfoData* pInput = &pCtx->input;
1,194,881✔
6642
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,194,296✔
6643

6644
  SColumnInfoData* pInputCol = pInput->pData[0];
1,194,881✔
6645
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,194,881✔
6646

6647
  int32_t numOfElems = 0;
1,195,466✔
6648
  int32_t type = pInputCol->info.type;
1,195,466✔
6649
  int32_t startOffset = pCtx->offset;
1,194,881✔
6650
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
219,117,117✔
6651
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
217,886,424✔
6652
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
8,563✔
6653
    } else {
6654
      pSumRes->prevTs = tsList[i];
217,858,186✔
6655
    }
6656
    pSumRes->isPrevTsSet = true;
217,865,366✔
6657

6658
    int32_t pos = startOffset + numOfElems;
217,831,121✔
6659
    if (colDataIsNull_f(pInputCol, i)) {
217,831,121✔
6660
      // colDataSetNULL(pOutput, i);
6661
      continue;
93,660,724✔
6662
    }
6663

6664
    char* data = colDataGetData(pInputCol, i);
124,262,522✔
6665
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
235,795,884✔
6666
      int64_t v;
6667
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
111,533,362✔
6668
      pSumRes->isum += v;
111,533,362✔
6669
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
111,533,362✔
6670
      if (TSDB_CODE_SUCCESS != code) {
111,533,362✔
6671
        return code;
×
6672
      }
6673
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
23,909,060✔
6674
      uint64_t v;
6675
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
11,179,900✔
6676
      pSumRes->usum += v;
11,179,900✔
6677
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
11,179,900✔
6678
      if (TSDB_CODE_SUCCESS != code) {
11,179,900✔
6679
        return code;
×
6680
      }
6681
    } else if (IS_FLOAT_TYPE(type)) {
1,549,260✔
6682
      double v;
6683
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
1,549,260✔
6684
      pSumRes->dsum += v;
1,549,260✔
6685
      // check for overflow
6686
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
1,549,260✔
6687
        colDataSetNULL(pOutput, pos);
996✔
6688
      } else {
6689
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
1,548,264✔
6690
        if (TSDB_CODE_SUCCESS != code) {
1,548,264✔
6691
          return code;
×
6692
        }
6693
      }
6694
    }
6695

6696
    // handle selectivity
6697
    if (pCtx->subsidiaries.num > 0) {
124,262,522✔
6698
      code = appendSelectivityValue(pCtx, i, pos);
25,392✔
6699
      if (TSDB_CODE_SUCCESS != code) {
25,392✔
6700
        return code;
×
6701
      }
6702
    }
6703

6704
    numOfElems++;
124,262,522✔
6705
  }
6706

6707
  pResInfo->numOfRes = numOfElems;
1,186,903✔
6708
  return TSDB_CODE_SUCCESS;
1,186,903✔
6709
}
6710

6711
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
451,098✔
6712
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
451,098✔
6713
  return true;
451,098✔
6714
}
6715

6716
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,234,016✔
6717
  if (pResultInfo->initialized) {
1,234,016✔
6718
    return TSDB_CODE_SUCCESS;
579,672✔
6719
  }
6720
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
654,344✔
6721
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6722
  }
6723

6724
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
653,783✔
6725
  pInfo->pos = 0;
653,783✔
6726
  pInfo->sum = 0;
653,783✔
6727
  pInfo->prevTs = -1;
653,783✔
6728
  pInfo->isPrevTsSet = false;
654,344✔
6729
  pInfo->numOfPoints = pCtx->param[1].param.i;
654,344✔
6730
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
654,344✔
6731
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
6732
  }
6733
  pInfo->pointsMeet = false;
654,344✔
6734

6735
  return TSDB_CODE_SUCCESS;
654,344✔
6736
}
6737

6738
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
681,180✔
6739
  int32_t              code = TSDB_CODE_SUCCESS;
681,180✔
6740
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
681,180✔
6741
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
681,180✔
6742

6743
  SInputColumnInfoData* pInput = &pCtx->input;
681,180✔
6744
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
681,180✔
6745

6746
  SColumnInfoData* pInputCol = pInput->pData[0];
681,180✔
6747
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
681,180✔
6748
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
681,180✔
6749

6750
  int32_t numOfElems = 0;
681,180✔
6751
  int32_t type = pInputCol->info.type;
681,180✔
6752
  int32_t startOffset = pCtx->offset;
681,180✔
6753
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
174,533,692✔
6754
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
173,854,432✔
6755
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
1,920✔
6756
    } else {
6757
      pInfo->prevTs = tsList[i];
173,852,512✔
6758
    }
6759
    pInfo->isPrevTsSet = true;
173,852,512✔
6760

6761
    int32_t pos = startOffset + numOfElems;
173,852,512✔
6762
    if (colDataIsNull_f(pInputCol, i)) {
173,852,512✔
6763
      // colDataSetNULL(pOutput, i);
6764
      continue;
8,270,395✔
6765
    }
6766

6767
    char*  data = colDataGetData(pInputCol, i);
165,582,597✔
6768
    double v;
6769
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
165,582,597✔
6770

6771
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
165,582,117✔
6772
      pInfo->points[pInfo->pos] = v;
46,701,582✔
6773
      pInfo->sum += v;
46,701,582✔
6774
    } else {
6775
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
118,880,535✔
6776
        pInfo->sum += v;
365,526✔
6777
        pInfo->pointsMeet = true;
365,526✔
6778
      } else {
6779
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
118,515,489✔
6780
      }
6781

6782
      pInfo->points[pInfo->pos] = v;
118,881,015✔
6783
      double result = pInfo->sum / pInfo->numOfPoints;
118,881,015✔
6784
      // check for overflow
6785
      if (isinf(result) || isnan(result)) {
118,881,015✔
6786
        colDataSetNULL(pOutput, pos);
×
6787
      } else {
6788
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
118,881,015✔
6789
        if (TSDB_CODE_SUCCESS != code) {
118,881,015✔
6790
          return code;
×
6791
        }
6792
      }
6793

6794
      // handle selectivity
6795
      if (pCtx->subsidiaries.num > 0) {
118,881,015✔
6796
        code = appendSelectivityValue(pCtx, i, pos);
36,872✔
6797
        if (TSDB_CODE_SUCCESS != code) {
36,872✔
6798
          return code;
×
6799
        }
6800
      }
6801

6802
      numOfElems++;
118,881,015✔
6803
    }
6804

6805
    pInfo->pos++;
165,582,597✔
6806
    if (pInfo->pos == pInfo->numOfPoints) {
165,582,117✔
6807
      pInfo->pos = 0;
18,997,308✔
6808
    }
6809
  }
6810

6811
  pResInfo->numOfRes = numOfElems;
679,260✔
6812
  return TSDB_CODE_SUCCESS;
679,260✔
6813
}
6814

6815
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
4,304,789✔
6816
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,304,789✔
6817
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
4,304,789✔
6818

6819
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
4,304,789✔
6820
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
4,304,789✔
6821

6822
  return pInfo;
4,304,789✔
6823
}
6824

6825
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
895,082✔
6826
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
895,082✔
6827
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
896,918✔
6828
  int32_t      numOfSamples = pVal->datum.i;
895,807✔
6829
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
895,807✔
6830
  return true;
894,065✔
6831
}
6832

6833
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,968,361✔
6834
  if (pResultInfo->initialized) {
1,968,361✔
6835
    return TSDB_CODE_SUCCESS;
×
6836
  }
6837
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,968,361✔
6838
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6839
  }
6840

6841
  taosSeedRand(taosSafeRand());
1,968,361✔
6842

6843
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,968,361✔
6844
  pInfo->samples = pCtx->param[1].param.i;
1,968,361✔
6845
  pInfo->totalPoints = 0;
1,968,361✔
6846
  pInfo->numSampled = 0;
1,968,361✔
6847
  pInfo->colType = pCtx->resDataInfo.type;
1,968,361✔
6848
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,968,361✔
6849
  pInfo->nullTuplePos.pageId = -1;
1,968,361✔
6850
  pInfo->nullTupleSaved = false;
1,968,361✔
6851
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
1,968,361✔
6852
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
1,968,361✔
6853

6854
  return TSDB_CODE_SUCCESS;
1,968,361✔
6855
}
6856

6857
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
86,719,278✔
6858
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
86,719,278✔
6859
}
86,719,278✔
6860

6861
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
144,793,439✔
6862
  pInfo->totalPoints++;
144,793,439✔
6863
  if (pInfo->numSampled < pInfo->samples) {
144,793,439✔
6864
    sampleAssignResult(pInfo, data, pInfo->numSampled);
65,395,211✔
6865
    if (pCtx->subsidiaries.num > 0) {
65,395,691✔
6866
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,136,023✔
6867
      if (code != TSDB_CODE_SUCCESS) {
1,136,023✔
6868
        return code;
×
6869
      }
6870
    }
6871
    pInfo->numSampled++;
65,395,691✔
6872
  } else {
6873
    int32_t j = (int32_t)(taosRand() % (uint64_t)pInfo->totalPoints);
79,398,228✔
6874
    if (j < pInfo->samples) {
79,393,908✔
6875
      sampleAssignResult(pInfo, data, j);
21,323,587✔
6876
      if (pCtx->subsidiaries.num > 0) {
21,323,587✔
6877
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
390,340✔
6878
        if (code != TSDB_CODE_SUCCESS) {
387,460✔
6879
          return code;
×
6880
        }
6881
      }
6882
    }
6883
  }
6884

6885
  return TSDB_CODE_SUCCESS;
144,786,719✔
6886
}
6887

6888
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
2,340,766✔
6889
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,340,766✔
6890
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
2,340,766✔
6891

6892
  SInputColumnInfoData* pInput = &pCtx->input;
2,340,766✔
6893

6894
  SColumnInfoData* pInputCol = pInput->pData[0];
2,340,766✔
6895
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
171,709,226✔
6896
    if (colDataIsNull_s(pInputCol, i)) {
338,732,450✔
6897
      continue;
24,581,741✔
6898
    }
6899

6900
    char*   data = colDataGetData(pInputCol, i);
144,785,279✔
6901
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
144,792,959✔
6902
    if (code != TSDB_CODE_SUCCESS) {
144,786,719✔
6903
      return code;
×
6904
    }
6905
  }
6906

6907
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,340,766✔
6908
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
1,964✔
6909
    if (code != TSDB_CODE_SUCCESS) {
1,964✔
6910
      return code;
×
6911
    }
6912
    pInfo->nullTupleSaved = true;
1,964✔
6913
  }
6914

6915
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
2,340,766✔
6916
  return TSDB_CODE_SUCCESS;
2,340,766✔
6917
}
6918

6919
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,964,023✔
6920
  int32_t              code = TSDB_CODE_SUCCESS;
1,964,023✔
6921
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,964,023✔
6922

6923
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
1,964,023✔
6924
  pEntryInfo->complete = true;
1,964,023✔
6925

6926
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,964,023✔
6927
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,964,023✔
6928
  if (NULL == pCol) {
1,964,023✔
6929
    return TSDB_CODE_OUT_OF_RANGE;
×
6930
  }
6931

6932
  int32_t currentRow = pBlock->info.rows;
1,964,023✔
6933
  if (pInfo->numSampled == 0) {
1,964,023✔
6934
    colDataSetNULL(pCol, currentRow);
145,552✔
6935
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
145,552✔
6936
    return code;
145,552✔
6937
  }
6938
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
67,214,162✔
6939
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
65,395,691✔
6940
    if (TSDB_CODE_SUCCESS != code) {
65,395,691✔
6941
      return code;
×
6942
    }
6943
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
65,395,691✔
6944
    if (TSDB_CODE_SUCCESS != code) {
65,395,691✔
6945
      return code;
×
6946
    }
6947
  }
6948

6949
  return code;
1,818,471✔
6950
}
6951

6952
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6953
#if 0
6954
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
6955
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
6956
  int32_t      numOfPoints = pVal->datum.i;
6957
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
6958
#endif
6959
  return true;
×
6960
}
6961

6962
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
6963
#if 0
6964
  if (!functionSetup(pCtx, pResultInfo)) {
6965
    return false;
6966
  }
6967

6968
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6969
  pInfo->numAdded = 0;
6970
  pInfo->numOfPoints = pCtx->param[1].param.i;
6971
  if (pCtx->numOfParams == 4) {
6972
    pInfo->offset = pCtx->param[2].param.i;
6973
  } else {
6974
    pInfo->offset = 0;
6975
  }
6976
  pInfo->colType = pCtx->resDataInfo.type;
6977
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6978
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
6979
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
6980
    return false;
6981
  }
6982

6983
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
6984
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
6985

6986
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
6987
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6988
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
6989
    pInfo->pItems[i]->isNull = false;
6990
  }
6991
#endif
6992
  return TSDB_CODE_SUCCESS;
×
6993
}
6994

6995
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
6996
#if 0
6997
  pItem->timestamp = ts;
6998
  if (isNull) {
6999
    pItem->isNull = true;
7000
  } else {
7001
    pItem->isNull = false;
7002
    memcpy(pItem->data, data, colBytes);
7003
  }
7004
#endif
7005
}
×
7006

7007
#if 0
7008
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
7009
  STailItem* d1 = *(STailItem**)p1;
7010
  STailItem* d2 = *(STailItem**)p2;
7011
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
7012
}
7013

7014
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
7015
  STailItem** pList = pInfo->pItems;
7016
  if (pInfo->numAdded < pInfo->numOfPoints) {
7017
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
7018
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
7019
    pInfo->numAdded++;
7020
  } else if (pList[0]->timestamp < ts) {
7021
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
7022
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
7023
  }
7024
}
7025
#endif
7026

7027
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
7028
#if 0
7029
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7030
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7031

7032
  SInputColumnInfoData* pInput = &pCtx->input;
7033
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
7034

7035
  SColumnInfoData* pInputCol = pInput->pData[0];
7036
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7037

7038
  int32_t startOffset = pCtx->offset;
7039
  if (pInfo->offset >= pInput->numOfRows) {
7040
    return 0;
7041
  } else {
7042
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
7043
  }
7044
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
7045
    char* data = colDataGetData(pInputCol, i);
7046
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
7047
  }
7048

7049
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
7050

7051
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
7052
    int32_t    pos = startOffset + i;
7053
    STailItem* pItem = pInfo->pItems[i];
7054
    if (pItem->isNull) {
7055
      colDataSetNULL(pOutput, pos);
7056
    } else {
7057
      colDataSetVal(pOutput, pos, pItem->data, false);
7058
    }
7059
  }
7060

7061
  return pInfo->numOfPoints;
7062
#endif
7063
  return 0;
×
7064
}
7065

7066
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
7067
#if 0
7068
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
7069
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
7070
  pEntryInfo->complete = true;
7071

7072
  int32_t type = pCtx->input.pData[0]->info.type;
7073
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
7074

7075
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7076

7077
  // todo assign the tag value and the corresponding row data
7078
  int32_t currentRow = pBlock->info.rows;
7079
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
7080
    STailItem* pItem = pInfo->pItems[i];
7081
    colDataSetVal(pCol, currentRow, pItem->data, false);
7082
    currentRow += 1;
7083
  }
7084

7085
  return pEntryInfo->numOfRes;
7086
#endif
7087
  return 0;
×
7088
}
7089

7090
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
7091
#if 0
7092
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
7093
#endif
7094
  return true;
×
7095
}
7096

7097
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
7098
#if 0
7099
  if (!functionSetup(pCtx, pResInfo)) {
7100
    return false;
7101
  }
7102

7103
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7104
  pInfo->numOfPoints = 0;
7105
  pInfo->colType = pCtx->resDataInfo.type;
7106
  pInfo->colBytes = pCtx->resDataInfo.bytes;
7107
  if (pInfo->pHash != NULL) {
7108
    taosHashClear(pInfo->pHash);
7109
  } else {
7110
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
7111
  }
7112
#endif
7113
  return TSDB_CODE_SUCCESS;
×
7114
}
7115

7116
#if 0
7117
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
7118
  // handle null elements
7119
  if (isNull == true) {
7120
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
7121
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
7122
    if (pInfo->hasNull == false && pItem->isNull == false) {
7123
      pItem->timestamp = ts;
7124
      pItem->isNull = true;
7125
      pInfo->numOfPoints++;
7126
      pInfo->hasNull = true;
7127
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
7128
      pItem->timestamp = ts;
7129
    }
7130
    return;
7131
  }
7132

7133
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
7134
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
7135
  if (pHashItem == NULL) {
7136
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
7137
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
7138
    pItem->timestamp = ts;
7139
    memcpy(pItem->data, data, pInfo->colBytes);
7140

7141
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
7142
    pInfo->numOfPoints++;
7143
  } else if (pHashItem->timestamp > ts) {
7144
    pHashItem->timestamp = ts;
7145
  }
7146
}
7147
#endif
7148

7149
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
7150
#if 0
7151
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7152
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7153

7154
  SInputColumnInfoData* pInput = &pCtx->input;
7155
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
7156

7157
  SColumnInfoData* pInputCol = pInput->pData[0];
7158
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
7159
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7160

7161
  int32_t startOffset = pCtx->offset;
7162
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
7163
    char* data = colDataGetData(pInputCol, i);
7164
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
7165

7166
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
7167
      taosHashCleanup(pInfo->pHash);
7168
      return 0;
7169
    }
7170
  }
7171

7172
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
7173
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
7174
    if (pItem->isNull == true) {
7175
      colDataSetNULL(pOutput, i);
7176
    } else {
7177
      colDataSetVal(pOutput, i, pItem->data, false);
7178
    }
7179
    if (pTsOutput != NULL) {
7180
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
7181
    }
7182
  }
7183

7184
  return pInfo->numOfPoints;
7185
#endif
7186
  return 0;
×
7187
}
7188

7189
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
838,769✔
7190
  pEnv->calcMemSize = sizeof(SModeInfo);
838,769✔
7191
  return true;
838,769✔
7192
}
7193

7194
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
1,030,370✔
7195
  if (pResInfo->initialized) {
1,030,370✔
7196
    return TSDB_CODE_SUCCESS;
×
7197
  }
7198
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
1,030,370✔
7199
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7200
  }
7201

7202
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,030,370✔
7203
  pInfo->colType = pCtx->resDataInfo.type;
1,030,370✔
7204
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,030,370✔
7205
  if (pInfo->pHash != NULL) {
1,030,370✔
7206
    taosHashClear(pInfo->pHash);
×
7207
  } else {
7208
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
1,030,370✔
7209
    if (NULL == pInfo->pHash) {
1,030,370✔
7210
      return terrno;
×
7211
    }
7212
  }
7213
  pInfo->nullTupleSaved = false;
1,030,370✔
7214
  pInfo->nullTuplePos.pageId = -1;
1,030,370✔
7215

7216
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
1,030,370✔
7217
  if (NULL == pInfo->buf) {
1,030,370✔
7218
    taosHashCleanup(pInfo->pHash);
×
7219
    pInfo->pHash = NULL;
×
7220
    return terrno;
×
7221
  }
7222
  pCtx->needCleanup = true;
1,030,370✔
7223
  return TSDB_CODE_SUCCESS;
1,030,370✔
7224
}
7225

7226
static void modeFunctionCleanup(SModeInfo* pInfo) {
1,791,266✔
7227
  taosHashCleanup(pInfo->pHash);
1,791,266✔
7228
  pInfo->pHash = NULL;
1,791,266✔
7229
  taosMemoryFreeClear(pInfo->buf);
1,791,266✔
7230
}
1,791,266✔
7231

7232
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
838,769✔
7233
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
838,769✔
7234
    return;
76,433✔
7235
  }
7236
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
762,336✔
7237
}
7238

7239
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
108,141,105✔
7240
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
108,141,105✔
7241
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
318,755✔
7242
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
307,098✔
7243
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
11,657✔
7244
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
×
7245
    } else {
7246
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
11,657✔
7247
    }
7248
  } else {
7249
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
107,822,350✔
7250
  }
7251

7252
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
108,141,105✔
7253
}
7254

7255
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
249,426,105✔
7256
  int32_t code = TSDB_CODE_SUCCESS;
249,426,105✔
7257
  int32_t hashKeyBytes;
7258
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
249,426,105✔
7259
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
489,872✔
7260
  } else {
7261
    hashKeyBytes = pInfo->colBytes;
248,936,233✔
7262
  }
7263

7264
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
249,426,105✔
7265
  if (pHashItem == NULL) {
249,426,105✔
7266
    int32_t   size = sizeof(SModeItem);
108,141,105✔
7267
    SModeItem item = {0};
108,141,105✔
7268

7269
    item.count += 1;
108,141,105✔
7270
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
108,141,105✔
7271
    if (code != TSDB_CODE_SUCCESS) {
108,139,665✔
7272
      return code;
×
7273
    }
7274

7275
    if (pCtx->subsidiaries.num > 0) {
108,139,665✔
7276
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
285,045✔
7277
      if (code != TSDB_CODE_SUCCESS) {
285,045✔
7278
        return code;
×
7279
      }
7280
    }
7281

7282
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
108,139,665✔
7283
    if (code != TSDB_CODE_SUCCESS) {
108,141,105✔
7284
      return code;
×
7285
    }
7286
  } else {
7287
    pHashItem->count += 1;
141,285,000✔
7288
    if (pCtx->subsidiaries.num > 0) {
141,285,000✔
7289
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,762,289✔
7290
      if (code != TSDB_CODE_SUCCESS) {
3,762,289✔
7291
        return code;
×
7292
      }
7293
    }
7294
  }
7295

7296
  return code;
249,426,105✔
7297
}
7298

7299
int32_t modeFunction(SqlFunctionCtx* pCtx) {
1,706,532✔
7300
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,706,532✔
7301
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,706,532✔
7302

7303
  SInputColumnInfoData* pInput = &pCtx->input;
1,706,532✔
7304

7305
  SColumnInfoData* pInputCol = pInput->pData[0];
1,706,532✔
7306
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,705,947✔
7307

7308
  int32_t numOfElems = 0;
1,706,532✔
7309
  int32_t startOffset = pCtx->offset;
1,706,532✔
7310
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
344,786,374✔
7311
    if (colDataIsNull_s(pInputCol, i)) {
686,163,194✔
7312
      continue;
93,657,832✔
7313
    }
7314
    numOfElems++;
249,426,105✔
7315

7316
    char*   data = colDataGetData(pInputCol, i);
249,426,105✔
7317
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
249,426,105✔
7318
    if (code != TSDB_CODE_SUCCESS) {
249,426,105✔
7319
      modeFunctionCleanup(pInfo);
4,095✔
7320
      return code;
×
7321
    }
7322
  }
7323

7324
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
1,706,532✔
7325
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
5,030✔
7326
    if (code != TSDB_CODE_SUCCESS) {
5,030✔
7327
      modeFunctionCleanup(pInfo);
×
7328
      return code;
×
7329
    }
7330
    pInfo->nullTupleSaved = true;
5,030✔
7331
  }
7332

7333
  SET_VAL(pResInfo, numOfElems, 1);
1,706,532✔
7334

7335
  return TSDB_CODE_SUCCESS;
1,706,532✔
7336
}
7337

7338
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,028,930✔
7339
  int32_t              code = TSDB_CODE_SUCCESS;
1,028,930✔
7340
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,028,930✔
7341
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,028,930✔
7342
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
1,028,930✔
7343
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,028,930✔
7344
  int32_t              currentRow = pBlock->info.rows;
1,028,930✔
7345
  if (NULL == pCol) {
1,028,930✔
7346
    modeFunctionCleanup(pInfo);
×
7347
    return TSDB_CODE_OUT_OF_RANGE;
×
7348
  }
7349

7350
  STuplePos resDataPos, resTuplePos;
1,028,930✔
7351
  int32_t   maxCount = 0;
1,028,930✔
7352

7353
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
1,028,930✔
7354
  while (pIter != NULL) {
109,170,035✔
7355
    SModeItem* pItem = (SModeItem*)pIter;
108,141,105✔
7356
    if (pItem->count >= maxCount) {
108,141,105✔
7357
      maxCount = pItem->count;
108,120,155✔
7358
      resDataPos = pItem->dataPos;
108,120,155✔
7359
      resTuplePos = pItem->tuplePos;
108,120,155✔
7360
    }
7361

7362
    pIter = taosHashIterate(pInfo->pHash, pIter);
108,141,105✔
7363
  }
7364

7365
  if (maxCount != 0) {
1,028,930✔
7366
    char* pData = NULL;
486,905✔
7367
    code = loadTupleData(pCtx, &resDataPos, &pData);
486,905✔
7368
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
486,905✔
7369
      code = terrno = TSDB_CODE_NOT_FOUND;
×
7370
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
7371
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
7372
      modeFunctionCleanup(pInfo);
×
7373
      return code;
×
7374
    }
7375

7376
    code = colDataSetVal(pCol, currentRow, pData, false);
486,905✔
7377
    if (TSDB_CODE_SUCCESS != code) {
486,905✔
7378
      modeFunctionCleanup(pInfo);
×
7379
      return code;
×
7380
    }
7381
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
486,905✔
7382
  } else {
7383
    colDataSetNULL(pCol, currentRow);
542,025✔
7384
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
542,025✔
7385
  }
7386

7387
  modeFunctionCleanup(pInfo);
1,028,930✔
7388

7389
  return code;
1,028,930✔
7390
}
7391

7392
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
374,866✔
7393
  pEnv->calcMemSize = sizeof(STwaInfo);
374,866✔
7394
  return true;
374,866✔
7395
}
7396

7397
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,997,917✔
7398
  if (pResultInfo->initialized) {
8,997,917✔
7399
    return TSDB_CODE_SUCCESS;
×
7400
  }
7401
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,997,917✔
7402
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7403
  }
7404

7405
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,997,426✔
7406
  pInfo->numOfElems = 0;
8,997,426✔
7407
  pInfo->p.key = INT64_MIN;
8,997,426✔
7408
  pInfo->win = TSWINDOW_INITIALIZER;
8,997,917✔
7409
  return TSDB_CODE_SUCCESS;
8,996,865✔
7410
}
7411

7412
static double twa_get_area(SPoint1 s, SPoint1 e) {
213,362,861✔
7413
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
213,362,861✔
7414
    return 0;
×
7415
  }
7416

7417
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
213,394,964✔
7418
    return (s.val + e.val) * (e.key - s.key) / 2;
192,783,854✔
7419
  }
7420

7421
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
20,611,110✔
7422
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
20,611,110✔
7423
  return val;
20,611,110✔
7424
}
7425

7426
int32_t twaFunction(SqlFunctionCtx* pCtx) {
9,058,687✔
7427
  int32_t               code = TSDB_CODE_SUCCESS;
9,058,687✔
7428
  SInputColumnInfoData* pInput = &pCtx->input;
9,058,687✔
7429
  SColumnInfoData*      pInputCol = pInput->pData[0];
9,059,178✔
7430

7431
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
9,059,178✔
7432
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
9,059,178✔
7433
  SPoint1*             last = &pInfo->p;
9,058,126✔
7434

7435
  if (IS_NULL_TYPE(pInputCol->info.type)) {
9,058,687✔
7436
    pInfo->numOfElems = 0;
×
7437
    goto _twa_over;
×
7438
  }
7439

7440
  funcInputUpdate(pCtx);
9,058,196✔
7441
  SFuncInputRow row = {0};
9,058,687✔
7442
  bool          result = false;
9,058,687✔
7443
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
9,058,687✔
7444
    while (1) {
7445
      code = funcInputGetNextRow(pCtx, &row, &result);
5,829,213✔
7446
      if (TSDB_CODE_SUCCESS != code) {
5,829,213✔
7447
        return code;
×
7448
      }
7449
      if (!result) {
5,829,213✔
7450
        break;
864✔
7451
      }
7452
      if (row.isDataNull) {
5,828,349✔
7453
        continue;
864✔
7454
      }
7455

7456
      last->key = row.ts;
5,827,485✔
7457

7458
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
5,827,485✔
7459

7460
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
5,827,485✔
7461
      pInfo->win.skey = pCtx->start.key;
5,827,485✔
7462
      pInfo->numOfElems++;
5,827,485✔
7463
      break;
5,827,485✔
7464
    }
7465
  } else if (pInfo->p.key == INT64_MIN) {
3,229,777✔
7466
    while (1) {
7467
      code = funcInputGetNextRow(pCtx, &row, &result);
11,938,588✔
7468
      if (TSDB_CODE_SUCCESS != code) {
11,938,518✔
7469
        return code;
×
7470
      }
7471
      if (!result) {
11,938,518✔
7472
        break;
1,064,445✔
7473
      }
7474
      if (row.isDataNull) {
10,874,073✔
7475
        continue;
8,746,948✔
7476
      }
7477

7478
      last->key = row.ts;
2,127,125✔
7479

7480
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
2,128,177✔
7481

7482
      pInfo->win.skey = last->key;
2,127,686✔
7483
      pInfo->numOfElems++;
2,128,177✔
7484
      break;
2,127,686✔
7485
    }
7486
  }
7487

7488
  SPoint1 st = {0};
9,059,178✔
7489

7490
  // calculate the value of
7491
  while (1) {
7492
    code = funcInputGetNextRow(pCtx, &row, &result);
210,833,560✔
7493
    if (TSDB_CODE_SUCCESS != code) {
210,832,578✔
7494
      return code;
×
7495
    }
7496
    if (!result) {
210,832,578✔
7497
      break;
9,059,178✔
7498
    }
7499
    if (row.isDataNull) {
201,773,400✔
7500
      continue;
61,866✔
7501
    }
7502
    pInfo->numOfElems++;
201,711,534✔
7503
    switch (pInputCol->info.type) {
201,707,606✔
7504
      case TSDB_DATA_TYPE_TINYINT: {
15,490,959✔
7505
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
15,490,959✔
7506
        break;
15,489,977✔
7507
      }
7508
      case TSDB_DATA_TYPE_SMALLINT: {
14,881,890✔
7509
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
14,881,890✔
7510
        break;
14,881,399✔
7511
      }
7512
      case TSDB_DATA_TYPE_INT: {
85,576,011✔
7513
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
85,576,011✔
7514
        break;
85,576,011✔
7515
      }
7516
      case TSDB_DATA_TYPE_BIGINT: {
17,132,096✔
7517
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
17,132,096✔
7518
        break;
17,132,096✔
7519
      }
7520
      case TSDB_DATA_TYPE_FLOAT: {
13,393,506✔
7521
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
13,393,506✔
7522
        break;
13,393,506✔
7523
      }
7524
      case TSDB_DATA_TYPE_DOUBLE: {
16,136,192✔
7525
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
16,136,192✔
7526
        break;
16,136,192✔
7527
      }
7528
      case TSDB_DATA_TYPE_UTINYINT: {
9,985,477✔
7529
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
9,985,477✔
7530
        break;
9,985,477✔
7531
      }
7532
      case TSDB_DATA_TYPE_USMALLINT: {
9,987,932✔
7533
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
9,987,932✔
7534
        break;
9,986,950✔
7535
      }
7536
      case TSDB_DATA_TYPE_UINT: {
10,072,131✔
7537
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
10,072,131✔
7538
        break;
10,072,131✔
7539
      }
7540
      case TSDB_DATA_TYPE_UBIGINT: {
9,050,851✔
7541
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
9,050,851✔
7542
        break;
9,050,851✔
7543
      }
7544
      default: {
×
7545
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7546
      }
7547
    }
7548
    if (pInfo->p.key == st.key) {
201,704,590✔
7549
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7550
    }
7551

7552
    pInfo->dOutput += twa_get_area(pInfo->p, st);
201,705,081✔
7553
    pInfo->p = st;
201,712,516✔
7554
  }
7555

7556
  // the last interpolated time window value
7557
  if (pCtx->end.key != INT64_MIN) {
9,059,178✔
7558
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
5,841,097✔
7559
    pInfo->p = pCtx->end;
5,841,097✔
7560
    pInfo->numOfElems += 1;
5,841,097✔
7561
  }
7562

7563
  pInfo->win.ekey = pInfo->p.key;
9,059,178✔
7564

7565
_twa_over:
9,059,178✔
7566
  SET_VAL(pResInfo, 1, 1);
9,059,178✔
7567
  return TSDB_CODE_SUCCESS;
9,059,178✔
7568
}
7569

7570
/*
7571
 * To copy the input to interResBuf to avoid the input buffer space be over writen
7572
 * by next input data. The TWA function only applies to each table, so no merge procedure
7573
 * is required, we simply copy to the resut ot interResBuffer.
7574
 */
7575
// void twa_function_copy(SQLFunctionCtx *pCtx) {
7576
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
7577
//
7578
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
7579
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
7580
// }
7581

7582
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,996,945✔
7583
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,996,945✔
7584

7585
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
8,996,945✔
7586
  if (pInfo->numOfElems == 0) {
8,996,945✔
7587
    pResInfo->numOfRes = 0;
1,040,419✔
7588
  } else {
7589
    if (pInfo->win.ekey == pInfo->win.skey) {
7,956,526✔
7590
      pInfo->dTwaRes = pInfo->p.val;
1,145,872✔
7591
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
6,810,654✔
7592
      pInfo->dTwaRes = 0;
864✔
7593
    } else {
7594
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
6,809,790✔
7595
    }
7596

7597
    pResInfo->numOfRes = 1;
7,956,526✔
7598
  }
7599

7600
  return functionFinalize(pCtx, pBlock);
8,996,945✔
7601
}
7602

7603
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3,314✔
7604
  if (pResultInfo->initialized) {
3,314✔
7605
    return TSDB_CODE_SUCCESS;
×
7606
  }
7607
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
3,314✔
7608
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7609
  }
7610

7611
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,314✔
7612
  pInfo->minRows = INT32_MAX;
3,314✔
7613
  return TSDB_CODE_SUCCESS;
3,314✔
7614
}
7615

7616
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
6,310✔
7617
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
6,310✔
7618

7619
  SInputColumnInfoData* pInput = &pCtx->input;
6,310✔
7620
  SColumnInfoData*      pInputCol = pInput->pData[0];
6,310✔
7621
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
6,310✔
7622
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,310✔
7623

7624
  STableBlockDistInfo p1 = {0};
6,310✔
7625
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
6,310✔
7626
    qError("failed to deserialize block dist info");
×
7627
    return TSDB_CODE_FAILED;
×
7628
  }
7629

7630
  pDistInfo->numOfBlocks += p1.numOfBlocks;
6,310✔
7631
  pDistInfo->numOfTables += p1.numOfTables;
6,310✔
7632
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
6,310✔
7633
  pDistInfo->numOfSttRows += p1.numOfSttRows;
6,310✔
7634
  pDistInfo->totalSize += p1.totalSize;
6,310✔
7635
  pDistInfo->totalRows += p1.totalRows;
6,310✔
7636
  pDistInfo->numOfFiles += p1.numOfFiles;
6,310✔
7637

7638
  pDistInfo->defMinRows = p1.defMinRows;
6,310✔
7639
  pDistInfo->defMaxRows = p1.defMaxRows;
6,310✔
7640
  pDistInfo->rowSize = p1.rowSize;
6,310✔
7641

7642
  if (pDistInfo->minRows > p1.minRows) {
6,310✔
7643
    pDistInfo->minRows = p1.minRows;
1,415✔
7644
  }
7645
  if (pDistInfo->maxRows < p1.maxRows) {
6,310✔
7646
    pDistInfo->maxRows = p1.maxRows;
1,415✔
7647
  }
7648
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
6,310✔
7649
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
132,510✔
7650
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
126,200✔
7651
  }
7652
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHistoFixed); ++i) {
56,790✔
7653
    pDistInfo->blockRowsHistoFixed[i] += p1.blockRowsHistoFixed[i];
50,480✔
7654
  }
7655

7656
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
6,310✔
7657
  return TSDB_CODE_SUCCESS;
6,310✔
7658
}
7659

7660
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
12,612✔
7661
  SEncoder encoder = {0};
12,612✔
7662
  int32_t  code = 0;
12,612✔
7663
  int32_t  lino;
7664
  int32_t  tlen;
7665
  tEncoderInit(&encoder, buf, bufLen);
12,612✔
7666

7667
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
12,612✔
7668
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
25,224✔
7669

7670
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
25,224✔
7671
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
25,224✔
7672
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
25,224✔
7673

7674
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
25,224✔
7675
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
25,224✔
7676
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
25,224✔
7677
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
25,224✔
7678
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
25,224✔
7679
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
25,224✔
7680
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
25,224✔
7681
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
25,224✔
7682
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
25,224✔
7683

7684
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
264,852✔
7685
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
504,480✔
7686
  }
7687

7688
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHistoFixed); ++i) {
113,508✔
7689
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHistoFixed[i]));
201,792✔
7690
  }
7691

7692
  tEndEncode(&encoder);
12,612✔
7693

7694
_exit:
12,612✔
7695
  if (code) {
12,612✔
7696
    tlen = code;
×
7697
  } else {
7698
    tlen = encoder.pos;
12,612✔
7699
  }
7700
  tEncoderClear(&encoder);
12,612✔
7701
  return tlen;
12,612✔
7702
}
7703

7704
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
6,310✔
7705
  SDecoder decoder = {0};
6,310✔
7706
  int32_t  code = 0;
6,310✔
7707
  int32_t  lino;
7708
  tDecoderInit(&decoder, buf, bufLen);
6,310✔
7709

7710
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
6,310✔
7711
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
12,620✔
7712

7713
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
12,620✔
7714
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
12,620✔
7715
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
12,620✔
7716

7717
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
12,620✔
7718
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
12,620✔
7719
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
12,620✔
7720
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
12,620✔
7721
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
12,620✔
7722
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
12,620✔
7723
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
12,620✔
7724
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
12,620✔
7725
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
12,620✔
7726

7727
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
132,510✔
7728
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
252,400✔
7729
  }
7730

7731
  if (!tDecodeIsEnd(&decoder)) {
6,310✔
7732
    for (int32_t i = 0; i < tListLen(pInfo->blockRowsHistoFixed); ++i) {
56,790✔
7733
      TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHistoFixed[i]));
100,960✔
7734
    }
7735
  }
7736

7737
_exit:
6,310✔
7738
  tDecoderClear(&decoder);
6,310✔
7739
  return code;
6,310✔
7740
}
7741

7742
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,314✔
7743
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,314✔
7744
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
3,314✔
7745

7746
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
3,314✔
7747
  if (NULL == pColInfo) {
3,314✔
7748
    return TSDB_CODE_OUT_OF_RANGE;
×
7749
  }
7750

7751
  if (pData->totalRows == 0) {
3,314✔
7752
    pData->minRows = 0;
1,899✔
7753
  }
7754

7755
  int32_t row = 0;
3,314✔
7756
  char    st[256] = {0};
3,314✔
7757
  double  averageSize = 0;
3,314✔
7758
  if (pData->numOfBlocks != 0) {
3,314✔
7759
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1,415✔
7760
  }
7761
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
3,314✔
7762
  double   compRatio = 0;
3,314✔
7763
  if (totalRawSize != 0) {
3,314✔
7764
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1,415✔
7765
  }
7766

7767
  int32_t len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,314✔
7768
                         "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
7769
                         pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
3,314✔
7770

7771
  varDataSetLen(st, len);
3,314✔
7772
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
3,314✔
7773
  if (TSDB_CODE_SUCCESS != code) {
3,314✔
7774
    return code;
×
7775
  }
7776

7777
  int64_t avgRows = 0;
3,314✔
7778
  if (pData->numOfBlocks > 0) {
3,314✔
7779
    avgRows = pData->totalRows / pData->numOfBlocks;
1,415✔
7780
  }
7781

7782
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,314✔
7783
                 "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
7784
                 pData->minRows, pData->maxRows, avgRows);
7785
  varDataSetLen(st, len);
3,314✔
7786
  code = colDataSetVal(pColInfo, row++, st, false);
3,314✔
7787
  if (TSDB_CODE_SUCCESS != code) {
3,314✔
7788
    return code;
×
7789
  }
7790

7791
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
3,314✔
7792
                 pData->numOfInmemRows, pData->numOfSttRows);
7793
  varDataSetLen(st, len);
3,314✔
7794
  code = colDataSetVal(pColInfo, row++, st, false);
3,314✔
7795
  if (TSDB_CODE_SUCCESS != code) {
3,314✔
7796
    return code;
×
7797
  }
7798

7799
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
6,628✔
7800
                 "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
3,314✔
7801
                 pData->numOfVgroups);
7802

7803
  varDataSetLen(st, len);
3,314✔
7804
  code = colDataSetVal(pColInfo, row++, st, false);
3,314✔
7805
  if (TSDB_CODE_SUCCESS != code) {
3,314✔
7806
    return code;
×
7807
  }
7808

7809
  len = snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,314✔
7810
                 "--------------------------------------------------------------------------------");
7811
  varDataSetLen(st, len);
3,314✔
7812
  code = colDataSetVal(pColInfo, row++, st, false);
3,314✔
7813
  if (TSDB_CODE_SUCCESS != code) {
3,314✔
7814
    return code;
×
7815
  }
7816

7817
  int32_t maxVal = 0;
3,314✔
7818
  int32_t minVal = INT32_MAX;
3,314✔
7819
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
69,594✔
7820
    if (maxVal < pData->blockRowsHisto[i]) {
66,280✔
7821
      maxVal = pData->blockRowsHisto[i];
2,033✔
7822
    }
7823

7824
    if (minVal > pData->blockRowsHisto[i]) {
66,280✔
7825
      minVal = pData->blockRowsHisto[i];
4,111✔
7826
    }
7827
  }
7828

7829
  // maximum number of step is 80
7830
  double factor = pData->numOfBlocks / 80.0;
3,314✔
7831

7832
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
3,314✔
7833
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
3,314✔
7834

7835
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
69,594✔
7836
    len =
7837
        snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
66,280✔
7838

7839
    int32_t num = 0;
66,280✔
7840
    if (pData->blockRowsHisto[i] > 0) {
66,280✔
7841
      num = (pData->blockRowsHisto[i]) / factor;
3,269✔
7842
    }
7843

7844
    for (int32_t j = 0; j < num; ++j) {
178,862✔
7845
      int32_t x = snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
112,582✔
7846
      len += x;
112,582✔
7847
    }
7848

7849
    if (pData->blockRowsHisto[i] > 0) {
66,280✔
7850
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
3,269✔
7851
      len += snprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
3,269✔
7852
                      pData->blockRowsHisto[i], v, '%');
3,269✔
7853
    }
7854

7855
    varDataSetLen(st, len);
66,280✔
7856
    code = colDataSetVal(pColInfo, row++, st, false);
66,280✔
7857
    if (TSDB_CODE_SUCCESS != code) {
66,280✔
7858
      return code;
×
7859
    }
7860
  }
7861

7862
  return TSDB_CODE_SUCCESS;
3,314✔
7863
}
7864
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
440✔
7865
  if (pResultInfo->initialized) {
440✔
7866
    return TSDB_CODE_SUCCESS;
×
7867
  }
7868
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
440✔
7869
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7870
  }
7871

7872
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
440✔
7873
  return TSDB_CODE_SUCCESS;
440✔
7874
}
7875
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
880✔
7876
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
880✔
7877

7878
  SInputColumnInfoData* pInput = &pCtx->input;
880✔
7879
  SColumnInfoData*      pInputCol = pInput->pData[0];
880✔
7880
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
880✔
7881
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
880✔
7882

7883
  SDBBlockUsageInfo p1 = {0};
880✔
7884
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
880✔
7885
    qError("failed to deserialize block dist info");
×
7886
    return TSDB_CODE_FAILED;
×
7887
  }
7888

7889
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
880✔
7890
  pDistInfo->walInDiskSize += p1.walInDiskSize;
880✔
7891
  pDistInfo->rawDataSize += p1.rawDataSize;
880✔
7892
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
880✔
7893
  return TSDB_CODE_SUCCESS;
880✔
7894
}
7895

7896
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
1,760✔
7897
  SEncoder encoder = {0};
1,760✔
7898
  int32_t  code = 0;
1,760✔
7899
  int32_t  lino;
7900
  int32_t  tlen;
7901
  tEncoderInit(&encoder, buf, bufLen);
1,760✔
7902

7903
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
1,760✔
7904

7905
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
3,520✔
7906
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
3,520✔
7907
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
3,520✔
7908

7909
  tEndEncode(&encoder);
1,760✔
7910

7911
_exit:
1,760✔
7912
  if (code) {
1,760✔
7913
    tlen = code;
×
7914
  } else {
7915
    tlen = encoder.pos;
1,760✔
7916
  }
7917
  tEncoderClear(&encoder);
1,760✔
7918
  return tlen;
1,760✔
7919
}
7920
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
880✔
7921
  SDecoder decoder = {0};
880✔
7922
  int32_t  code = 0;
880✔
7923
  int32_t  lino;
7924
  tDecoderInit(&decoder, buf, bufLen);
880✔
7925

7926
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
880✔
7927
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
1,760✔
7928
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
1,760✔
7929
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
1,760✔
7930

7931
_exit:
880✔
7932
  tDecoderClear(&decoder);
880✔
7933
  return code;
880✔
7934
}
7935
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
440✔
7936
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
440✔
7937
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
440✔
7938

7939
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
440✔
7940
  if (NULL == pColInfo) {
440✔
7941
    return TSDB_CODE_OUT_OF_RANGE;
×
7942
  }
7943
  int32_t len = 0;
440✔
7944
  int32_t row = 0;
440✔
7945
  char    st[256] = {0};
440✔
7946

7947
  uint64_t totalDiskSize = pData->dataInDiskSize;
440✔
7948
  uint64_t rawDataSize = pData->rawDataSize;
440✔
7949
  double   compressRatio = 0;
440✔
7950
  if (rawDataSize != 0) {
440✔
7951
    compressRatio = totalDiskSize * 100 / (double)rawDataSize;
224✔
7952
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[%.2f%]", compressRatio);
224✔
7953
  } else {
7954
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[NULL]");
216✔
7955
  }
7956

7957
  varDataSetLen(st, len);
440✔
7958
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
440✔
7959
  if (TSDB_CODE_SUCCESS != code) {
440✔
7960
    return code;
×
7961
  }
7962

7963
  len =
7964
      snprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
440✔
7965
  varDataSetLen(st, len);
440✔
7966
  code = colDataSetVal(pColInfo, row++, st, false);
440✔
7967
  if (TSDB_CODE_SUCCESS != code) {
440✔
7968
    return code;
×
7969
  }
7970
  return code;
440✔
7971
}
7972

7973
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
249,580✔
7974
  pEnv->calcMemSize = sizeof(SDerivInfo);
249,580✔
7975
  return true;
249,580✔
7976
}
7977

7978
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
966,019✔
7979
  if (pResInfo->initialized) {
966,019✔
7980
    return TSDB_CODE_SUCCESS;
604,885✔
7981
  }
7982
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
361,134✔
7983
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7984
  }
7985

7986
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
361,134✔
7987

7988
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
361,134✔
7989
  pDerivInfo->prevTs = -1;
361,134✔
7990
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
361,134✔
7991
  pDerivInfo->valueSet = false;
361,134✔
7992
  return TSDB_CODE_SUCCESS;
361,134✔
7993
}
7994

7995
int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
643,027✔
7996

7997
static int32_t DoDerivativeFunction(SqlFunctionCtx* pCtx) {
643,027✔
7998
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
643,027✔
7999
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
643,027✔
8000

8001
  SInputColumnInfoData* pInput = &pCtx->input;
643,027✔
8002
  SColumnInfoData*      pInputCol = pInput->pData[0];
643,027✔
8003

8004
  int32_t          numOfElems = 0;
643,027✔
8005
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
643,027✔
8006
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
643,027✔
8007
  int32_t          code = TSDB_CODE_SUCCESS;
643,027✔
8008

8009
  funcInputUpdate(pCtx);
643,027✔
8010

8011
  double v = 0;
643,027✔
8012
  if (pCtx->order == TSDB_ORDER_ASC) {
643,027✔
8013
    SFuncInputRow row = {0};
555,758✔
8014
    bool          result = false;
555,758✔
8015
    while (1) {
140,920,451✔
8016
      code = funcInputGetNextRow(pCtx, &row, &result);
141,476,209✔
8017
      if (TSDB_CODE_SUCCESS != code) {
141,476,209✔
8018
        return code;
×
8019
      }
8020
      if (!result) {
141,476,209✔
8021
        break;
555,758✔
8022
      }
8023
      if (row.isDataNull) {
140,920,451✔
8024
        continue;
4,647,814✔
8025
      }
8026

8027
      char* d = row.pData;
136,272,637✔
8028
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
136,272,637✔
8029

8030
      int32_t pos = pCtx->offset + numOfElems;
136,272,637✔
8031
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
136,272,637✔
8032
        pDerivInfo->valueSet = true;
256,481✔
8033
      } else {
8034
        if (row.ts == pDerivInfo->prevTs) {
136,016,156✔
8035
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8036
        }
8037
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
136,016,156✔
8038
        if (pDerivInfo->ignoreNegative && r < 0) {
136,016,156✔
8039
        } else {
8040
          if (isinf(r) || isnan(r)) {
124,507,122✔
8041
            colDataSetNULL(pOutput, pos);
×
8042
          } else {
8043
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
124,507,122✔
8044
            if (code != TSDB_CODE_SUCCESS) {
124,507,122✔
8045
              return code;
×
8046
            }
8047
          }
8048

8049
          if (pTsOutput != NULL) {
124,507,122✔
8050
            colDataSetInt64(pTsOutput, pos, &row.ts);
3,443,264✔
8051
          }
8052

8053
          // handle selectivity
8054
          if (pCtx->subsidiaries.num > 0) {
124,507,122✔
8055
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
2,105,129✔
8056
            if (code != TSDB_CODE_SUCCESS) {
2,105,129✔
8057
              return code;
×
8058
            }
8059
          }
8060

8061
          numOfElems++;
124,507,122✔
8062
        }
8063
      }
8064

8065
      pDerivInfo->prevValue = v;
136,272,637✔
8066
      pDerivInfo->prevTs = row.ts;
136,272,637✔
8067
    }
8068
  } else {
8069
    SFuncInputRow row = {0};
87,269✔
8070
    bool          result = false;
87,269✔
8071
    while (1) {
31,859,308✔
8072
      code = funcInputGetNextRow(pCtx, &row, &result);
31,946,577✔
8073
      if (TSDB_CODE_SUCCESS != code) {
31,946,577✔
8074
        return code;
×
8075
      }
8076
      if (!result) {
31,946,577✔
8077
        break;
87,269✔
8078
      }
8079
      if (row.isDataNull) {
31,859,308✔
UNCOV
8080
        continue;
×
8081
      }
8082

8083
      char* d = row.pData;
31,859,308✔
8084
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
31,859,308✔
8085

8086
      int32_t pos = pCtx->offset + numOfElems;
31,859,308✔
8087
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
31,859,308✔
8088
        pDerivInfo->valueSet = true;
58,109✔
8089
      } else {
8090
        if (row.ts == pDerivInfo->prevTs) {
31,801,199✔
8091
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8092
        }
8093
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
31,801,199✔
8094
        if (pDerivInfo->ignoreNegative && r < 0) {
31,801,199✔
8095
        } else {
8096
          if (isinf(r) || isnan(r)) {
31,801,199✔
8097
            colDataSetNULL(pOutput, pos);
×
8098
          } else {
8099
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
31,801,199✔
8100
            if (code != TSDB_CODE_SUCCESS) {
31,801,199✔
8101
              return code;
×
8102
            }
8103
          }
8104

8105
          if (pTsOutput != NULL) {
31,801,199✔
8106
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
31,796,064✔
8107
          }
8108

8109
          // handle selectivity
8110
          if (pCtx->subsidiaries.num > 0) {
31,801,199✔
8111
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
×
8112
            if (code != TSDB_CODE_SUCCESS) {
×
8113
              return code;
×
8114
            }
8115
          }
8116
          numOfElems++;
31,801,199✔
8117
        }
8118
      }
8119

8120
      pDerivInfo->prevValue = v;
31,859,308✔
8121
      pDerivInfo->prevTs = row.ts;
31,859,308✔
8122
    }
8123
  }
8124

8125
  pResInfo->numOfRes = numOfElems;
643,027✔
8126

8127
  return TSDB_CODE_SUCCESS;
643,027✔
8128
}
8129

8130
int32_t derivativeFunctionByRow(SArray* pCtxArray) {
643,027✔
8131
  for (int32_t i = 0; i < taosArrayGetSize(pCtxArray); ++i) {
1,286,054✔
8132
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
643,027✔
8133
    int32_t         code = DoDerivativeFunction(pCtx);
643,027✔
8134
    if (code != TSDB_CODE_SUCCESS) {
643,027✔
8135
      return code;
×
8136
    }
8137
  }
8138
  return TSDB_CODE_SUCCESS;
643,027✔
8139
}
8140

8141
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
267,513✔
8142

8143
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
220,942✔
8144
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
220,942✔
8145
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
220,942✔
8146
  return true;
220,942✔
8147
}
8148

8149
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,000,820✔
8150
  if (pResInfo->initialized) {
2,000,820✔
8151
    return TSDB_CODE_SUCCESS;
×
8152
  }
8153
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,000,820✔
8154
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
8155
  }
8156

8157
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,000,820✔
8158

8159
  pInfo->firstKey = INT64_MIN;
2,000,820✔
8160
  pInfo->lastKey = INT64_MIN;
2,000,820✔
8161
  pInfo->firstValue = (double)INT64_MIN;
2,000,820✔
8162
  pInfo->lastValue = (double)INT64_MIN;
2,000,820✔
8163

8164
  pInfo->hasResult = 0;
2,000,820✔
8165
  return TSDB_CODE_SUCCESS;
2,000,820✔
8166
}
8167

8168
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
328,566,433✔
8169
  if (isFirst) {
328,566,433✔
8170
    pRateInfo->firstValue = v;
163,727,904✔
8171
    pRateInfo->firstKey = ts;
163,727,904✔
8172
    if (pRateInfo->firstPk) {
163,727,904✔
8173
      int32_t pkBytes;
8174
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
26,705✔
8175
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
6,104✔
8176
      } else {
8177
        pkBytes = pRateInfo->pkBytes;
20,601✔
8178
      }
8179
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
26,705✔
8180
    }
8181
  } else {
8182
    pRateInfo->lastValue = v;
164,838,529✔
8183
    pRateInfo->lastKey = ts;
164,838,529✔
8184
    if (pRateInfo->lastPk) {
164,838,529✔
8185
      int32_t pkBytes;
8186
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
39,676✔
8187
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
9,156✔
8188
      } else {
8189
        pkBytes = pRateInfo->pkBytes;
30,520✔
8190
      }
8191
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
39,676✔
8192
    }
8193
  }
8194
}
328,566,433✔
8195

8196
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,191,115✔
8197
  if (pCtx->hasPrimaryKey) {
2,191,115✔
8198
    if (!isMerge) {
14,497✔
8199
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
12,971✔
8200
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
12,971✔
8201
      pRateInfo->firstPk = pRateInfo->pkData;
12,971✔
8202
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
12,971✔
8203
    } else {
8204
      pRateInfo->firstPk = pRateInfo->pkData;
1,526✔
8205
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,526✔
8206
    }
8207
  } else {
8208
    pRateInfo->firstPk = NULL;
2,176,618✔
8209
    pRateInfo->lastPk = NULL;
2,176,618✔
8210
  }
8211
}
2,191,115✔
8212

8213
int32_t irateFunction(SqlFunctionCtx* pCtx) {
2,122,637✔
8214
  int32_t              code = TSDB_CODE_SUCCESS;
2,122,637✔
8215
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,122,637✔
8216
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,122,637✔
8217

8218
  SInputColumnInfoData* pInput = &pCtx->input;
2,122,637✔
8219
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,122,637✔
8220

8221
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,122,637✔
8222

8223
  funcInputUpdate(pCtx);
2,122,637✔
8224

8225
  initializeRateInfo(pCtx, pRateInfo, false);
2,122,637✔
8226

8227
  int32_t       numOfElems = 0;
2,122,637✔
8228
  int32_t       type = pInputCol->info.type;
2,122,637✔
8229
  SFuncInputRow row = {0};
2,122,637✔
8230
  bool          result = false;
2,122,637✔
8231
  while (1) {
217,290,548✔
8232
    code = funcInputGetNextRow(pCtx, &row, &result);
219,413,185✔
8233
    if (TSDB_CODE_SUCCESS != code) {
219,413,185✔
8234
      return code;
×
8235
    }
8236
    if (!result) {
219,413,185✔
8237
      break;
2,122,637✔
8238
    }
8239
    if (row.isDataNull) {
217,290,548✔
8240
      continue;
7,804,662✔
8241
    }
8242

8243
    char*  data = row.pData;
209,485,886✔
8244
    double v = 0;
209,485,886✔
8245
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
209,485,886✔
8246

8247
    if (INT64_MIN == pRateInfo->lastKey) {
209,485,886✔
8248
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
1,115,933✔
8249
      pRateInfo->hasResult = 1;
1,115,933✔
8250
      continue;
1,115,933✔
8251
    }
8252

8253
    if (row.ts > pRateInfo->lastKey) {
208,369,953✔
8254
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
163,687,807✔
8255
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
163,687,807✔
8256
      }
8257
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
163,687,807✔
8258
      continue;
163,687,807✔
8259
    } else if (row.ts == pRateInfo->lastKey) {
44,682,146✔
8260
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8261
    }
8262

8263
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
44,682,146✔
8264
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
2,344✔
8265
    } else if (row.ts == pRateInfo->firstKey) {
44,679,802✔
8266
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8267
    }
8268
  }
8269

8270
  numOfElems++;
2,122,637✔
8271

8272
  SET_VAL(pResInfo, numOfElems, 1);
2,122,637✔
8273
  return TSDB_CODE_SUCCESS;
2,122,637✔
8274
}
8275

8276
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
1,965,609✔
8277
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
1,965,609✔
8278
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
184,279✔
8279
    return 0.0;
1,781,330✔
8280
  }
8281

8282
  double diff = 0;
184,279✔
8283
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
8284
  // value between two values.
8285
  diff = pRateInfo->lastValue;
184,279✔
8286
  if (diff >= pRateInfo->firstValue) {
184,279✔
8287
    diff -= pRateInfo->firstValue;
127,907✔
8288
  }
8289

8290
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
184,279✔
8291
  if (duration == 0) {
184,279✔
8292
    return 0;
×
8293
  }
8294

8295
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
184,279✔
8296
}
8297

8298
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
28,272✔
8299
  if (inputKey > pOutput->lastKey) {
28,272✔
8300
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
16,910✔
8301
    if (isFirstKey) {
16,910✔
8302
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
7,714✔
8303
    } else {
8304
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
9,196✔
8305
    }
8306
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
11,362✔
8307
    if (isFirstKey) {
2,964✔
8308
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,482✔
8309
    } else {
8310
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,482✔
8311
    }
8312
  } else {
8313
    // inputKey < pOutput->firstKey
8314
  }
8315
}
28,272✔
8316

8317
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
17,879✔
8318
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
17,879✔
8319
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
17,879✔
8320
}
17,879✔
8321

8322
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
32,015✔
8323
  if ((pInput->firstKey != INT64_MIN &&
32,015✔
8324
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
29,035✔
8325
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
32,015✔
8326
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
8327
  }
8328

8329
  if (pOutput->hasResult == 0) {
32,015✔
8330
    irateCopyInfo(pInput, pOutput);
17,879✔
8331
    pOutput->hasResult = pInput->hasResult;
17,879✔
8332
    return TSDB_CODE_SUCCESS;
17,879✔
8333
  }
8334

8335
  if (pInput->firstKey != INT64_MIN) {
14,136✔
8336
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
14,136✔
8337
  }
8338

8339
  if (pInput->lastKey != INT64_MIN) {
14,136✔
8340
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
14,136✔
8341
  }
8342

8343
  pOutput->hasResult = pInput->hasResult;
14,136✔
8344
  return TSDB_CODE_SUCCESS;
14,136✔
8345
}
8346

8347
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
34,239✔
8348
  SInputColumnInfoData* pInput = &pCtx->input;
34,239✔
8349
  SColumnInfoData*      pCol = pInput->pData[0];
34,239✔
8350
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
34,239✔
8351
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
8352
  }
8353

8354
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
34,239✔
8355
  initializeRateInfo(pCtx, pInfo, true);
34,239✔
8356

8357
  int32_t start = pInput->startRowIndex;
34,239✔
8358
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
68,478✔
8359
    char*      data = colDataGetData(pCol, i);
34,239✔
8360
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
34,239✔
8361
    initializeRateInfo(pCtx, pInfo, true);
34,239✔
8362
    if (pInputInfo->hasResult) {
34,239✔
8363
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
32,015✔
8364
      if (code != TSDB_CODE_SUCCESS) {
32,015✔
8365
        return code;
×
8366
      }
8367
    }
8368
  }
8369

8370
  if (pInfo->hasResult) {
34,239✔
8371
    GET_RES_INFO(pCtx)->numOfRes = 1;
32,015✔
8372
  }
8373

8374
  return TSDB_CODE_SUCCESS;
34,239✔
8375
}
8376

8377
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
34,239✔
8378
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
34,239✔
8379
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
34,239✔
8380
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
34,239✔
8381
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
34,239✔
8382

8383
  if (NULL == res) {
34,239✔
8384
    return terrno;
×
8385
  }
8386
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
34,239✔
8387
  varDataSetLen(res, resultBytes);
34,239✔
8388

8389
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
34,239✔
8390
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
34,239✔
8391
  if (NULL == pCol) {
34,239✔
8392
    taosMemoryFree(res);
×
8393
    return TSDB_CODE_OUT_OF_RANGE;
×
8394
  }
8395

8396
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
34,239✔
8397

8398
  taosMemoryFree(res);
34,239✔
8399
  return code;
34,239✔
8400
}
8401

8402
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,965,609✔
8403
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,965,609✔
8404
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,965,609✔
8405
  if (NULL == pCol) {
1,965,609✔
8406
    return TSDB_CODE_OUT_OF_RANGE;
×
8407
  }
8408

8409
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,965,609✔
8410
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
1,965,609✔
8411

8412
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,965,609✔
8413
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
1,965,609✔
8414
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
1,965,609✔
8415

8416
  return code;
1,965,609✔
8417
}
8418

8419
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
8420
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
8421
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
8422
  bool                 isWindow = pCtx->hasWindowOrGroup && pCtx->hasWindow;
2,147,483,647✔
8423

8424
  if (pInfo->hasResult && (!isWindow || !pInfo->isNull)) {
2,147,483,647✔
8425
    // If already has result for 'group by' or
8426
    // has non-null result for 'window', we can skip left data blocks.
8427
    goto _group_value_over;
2,147,483,647✔
8428
  }
8429

8430
  int32_t               valueRowIndex = -1;
2,147,483,647✔
8431
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
8432
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
8433

8434
  // try to find a non-null value
8435
  if (NULL != pInputCol->pData) {
2,147,483,647✔
8436
    if (isWindow) {
2,147,483,647✔
8437
      // for 'window', non-null value can appear at any row of any data block
8438
      int64_t startIndex = pInput->startRowIndex;
2,147,483,647✔
8439
      int64_t endIndex = pInput->startRowIndex + pInput->numOfRows - 1;
2,147,483,647✔
8440
      for (int64_t i = startIndex; i <= endIndex; ++i) {
2,147,483,647✔
8441
        if (!colDataIsNull_s(pInputCol, i)) {
2,147,483,647✔
8442
          valueRowIndex = i;
2,147,483,647✔
8443
          break;
2,147,483,647✔
8444
        }
8445
      }
8446
    } else {
8447
      // for 'group by', just take the first row
8448
      if (!colDataIsNull_s(pInputCol, pInput->startRowIndex)) {
452,340,024✔
8449
        valueRowIndex = pInput->startRowIndex;
223,764,793✔
8450
      }
8451
    }
8452
  }
8453

8454
  if (valueRowIndex != -1) {
2,147,483,647✔
8455
    // found a non-null value
8456
    char* data = colDataGetData(pInputCol, valueRowIndex);
2,147,483,647✔
8457
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
2,147,483,647✔
8458
      int32_t bytes = calcStrBytesByType(pInputCol->info.type, data);
2,147,483,647✔
8459
      (void)memcpy(pInfo->data, data, bytes);
2,147,483,647✔
8460
    } else {
8461
      (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
2,147,483,647✔
8462
    }
8463
    pInfo->isNull = false;
2,147,483,647✔
8464
  } else {
8465
    // all values are null or first value is null for group by
8466
    pInfo->isNull = true;
1,470,938,750✔
8467
  }
8468
  pInfo->hasResult = true;
2,147,483,647✔
8469

8470
_group_value_over:
2,147,483,647✔
8471
  SET_VAL(pResInfo, 1, 1);
2,147,483,647✔
8472
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
8473
}
8474

8475
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
2,147,483,647✔
8476

8477
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
8478
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
8479
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
8480
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
8481
  if (NULL == pCol) {
2,147,483,647✔
8482
    return TSDB_CODE_OUT_OF_RANGE;
×
8483
  }
8484

8485
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
8486

8487
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
8488

8489
  if (pInfo->hasResult) {
2,147,483,647✔
8490
    int32_t currentRow = pBlock->info.rows;
2,147,483,647✔
8491
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
2,147,483,647✔
8492
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
2,147,483,647✔
8493
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
8494
        return code;
×
8495
      }
8496
    }
8497
  } else {
8498
    pResInfo->numOfRes = 0;
×
8499
  }
8500

8501
  return code;
2,147,483,647✔
8502
}
8503

8504
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
2,147,483,647✔
8505

8506
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
8507
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
8508
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
8509

8510
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
8511
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
8512

8513
  // escape rest of data blocks to avoid first entry to be overwritten.
8514
  if (pDBuf->hasResult) {
×
8515
    goto _group_key_over;
×
8516
  }
8517

8518
  if (pSBuf->isNull) {
×
8519
    pDBuf->isNull = true;
×
8520
    pDBuf->hasResult = true;
×
8521
    goto _group_key_over;
×
8522
  }
8523

8524
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
8525
    int32_t bytes = calcStrBytesByType(pSourceCtx->resDataInfo.type, pSBuf->data);
×
8526
    (void)memcpy(pDBuf->data, pSBuf->data, bytes);
×
8527
  } else {
8528
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
8529
  }
8530

8531
  pDBuf->hasResult = true;
×
8532

8533
_group_key_over:
×
8534

8535
  SET_VAL(pDResInfo, 1, 1);
×
8536
  return TSDB_CODE_SUCCESS;
×
8537
}
8538

8539
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
465,178✔
8540
  int32_t numOfElems = 0;
465,178✔
8541

8542
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
465,178✔
8543
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
465,178✔
8544

8545
  SInputColumnInfoData* pInput = &pCtx->input;
465,178✔
8546
  SColumnInfoData*      pInputCol = pInput->pData[0];
465,178✔
8547

8548
  int32_t bytes = pInputCol->info.bytes;
464,697✔
8549
  pInfo->bytes = bytes;
464,697✔
8550

8551
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
465,178✔
8552
  pInfo->pkType = -1;
464,697✔
8553
  __compar_fn_t pkCompareFn = NULL;
465,178✔
8554
  if (pCtx->hasPrimaryKey) {
465,178✔
8555
    pInfo->pkType = pkCol->info.type;
17,856✔
8556
    pInfo->pkBytes = pkCol->info.bytes;
17,856✔
8557
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
17,856✔
8558
  }
8559

8560
  // data is guaranteed to be in descending order
8561
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
996,058✔
8562
    numOfElems++;
531,361✔
8563

8564
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
531,361✔
8565
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
531,361✔
8566

8567
    TSKEY cts = getRowPTs(pInput->pPTS, i);
531,361✔
8568
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
531,361✔
8569
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
440,392✔
8570
      if (code != TSDB_CODE_SUCCESS) {
440,392✔
8571
        return code;
×
8572
      }
8573
      pResInfo->numOfRes = 1;
440,392✔
8574
    }
8575
  }
8576

8577
  SET_VAL(pResInfo, numOfElems, 1);
465,178✔
8578
  return TSDB_CODE_SUCCESS;
465,178✔
8579
}
8580

8581
bool getCorrFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
8582
  pEnv->calcMemSize = sizeof(SCorrRes);
×
8583
  return true;
×
8584
}
8585

8586
int32_t corrFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
8587
  if (pResultInfo->initialized) {
×
8588
    return TSDB_CODE_SUCCESS;
×
8589
  }
8590
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
×
8591
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
8592
  }
8593

8594
  SCorrRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
×
8595
  (void)memset(pRes, 0, sizeof(SCorrRes));
×
8596
  return TSDB_CODE_SUCCESS;
×
8597
}
8598

8599
int32_t corrFunction(SqlFunctionCtx* pCtx) {
×
8600
  int32_t               numOfElem = 0;
×
8601
  SInputColumnInfoData* pInput = &pCtx->input;
×
8602
  int32_t               xType = pInput->pData[0]->info.type;
×
8603
  int32_t               yType = pInput->pData[1]->info.type;
×
8604
  SCorrRes*             pCorrRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8605

8606
  // computing based on the true data block
8607
  SColumnInfoData* pLeft = pInput->pData[0];   // left
×
8608
  SColumnInfoData* pRight = pInput->pData[1];  // right
×
8609

8610
  int32_t leftMod = typeGetTypeModFromColInfo(&pLeft->info);
×
8611
  int32_t rightMod = typeGetTypeModFromColInfo(&pRight->info);
×
8612
  int32_t start = pInput->startRowIndex;
×
8613
  int32_t numOfRows = pInput->numOfRows;
×
8614

8615
  if (IS_NULL_TYPE(xType) || IS_NULL_TYPE(yType)) {
×
8616
    numOfElem = 0;
×
8617
    goto _over;
×
8618
  }
8619

8620
  for (int32_t i = 0; i < numOfRows; ++i) {
×
8621
    double pInputX = 0, pInputY = 0;
×
8622

8623
    if (colDataIsNull_f(pLeft, i) || colDataIsNull_f(pRight, i)) {
×
8624
      continue;
×
8625
    }
8626

8627
    char* pXVal = colDataGetData(pLeft, i);
×
8628
    char* pYVal = colDataGetData(pRight, i);
×
8629

8630
    GET_TYPED_DATA(pInputX, double, xType, pXVal, leftMod);
×
8631
    GET_TYPED_DATA(pInputY, double, yType, pYVal, rightMod);
×
8632

8633
    pCorrRes->sumLeft += pInputX;
×
8634
    pCorrRes->sumRight += pInputY;
×
8635

8636
    pCorrRes->quadLeft += pInputX * pInputX;
×
8637
    pCorrRes->quadRight += pInputY * pInputY;
×
8638

8639
    pCorrRes->productVal += pInputX * pInputY;
×
8640

8641
    pCorrRes->count += 1;
×
8642
    numOfElem += 1;
×
8643
  }
8644

8645
_over:
×
8646
  // data in the check operation are all null, not output
8647
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
×
8648
  return TSDB_CODE_SUCCESS;
×
8649
}
8650

8651
int32_t corrFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
8652
  SInputColumnInfoData* pInput = &pCtx->input;
×
8653
  SCorrRes*             pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8654
  double                avg;
8655

8656
  if (pRes->count == 0) {
×
8657
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
8658
    return functionFinalize(pCtx, pBlock);
×
8659
  }
8660

8661
  /**
8662
    numerator = sum_xy - (sum_x * sum_y) / n
8663
    denominator_x = math.sqrt(sum_x2 - (sum_x**2) / n)
8664
    denominator_y = math.sqrt(sum_y2 - (sum_y**2) / n)
8665

8666
    if denominator_x == 0 or denominator_y == 0:
8667
        return 0.0
8668
    res = numerator / (denominator_x * denominator_y)
8669
  */
8670

8671
  if (pRes->count == 1) {
×
8672
    pRes->result = 0.0;
×
8673
  } else {
8674
    double numerator = pRes->productVal - (pRes->sumLeft * pRes->sumRight) / pRes->count;
×
8675
    double dnmX = sqrt(pRes->quadLeft - pRes->sumLeft * pRes->sumLeft / pRes->count);
×
8676
    double dnmY = sqrt(pRes->quadRight - pRes->sumRight * pRes->sumRight / pRes->count);
×
8677

8678
    if (DBL_EQUAL(dnmX, 0.0) || DBL_EQUAL(dnmY, 0.0)) {
×
8679
      pRes->result = 0.0;
×
8680
    } else {
8681
      pRes->result = numerator / (dnmX * dnmY);
×
8682

8683
      if (pRes->result > 1 || pRes->result < -1) {
×
8684
        qError("invalid corr results, %.4f, numerator:%.4f, dnmX:%.4f, dnmY:%.4f", pRes->result, numerator, dnmX, dnmY);
×
8685
        if (pRes->result > 1) {
×
8686
          pRes->result = 1;
×
8687
        } else if (pRes->result < -1) {
×
8688
          pRes->result = -1;
×
8689
        }
8690
      }
8691
    }
8692
  }
8693

8694
  return functionFinalize(pCtx, pBlock);
×
8695
}
8696

8697
int32_t getCorrInfoSize() { return sizeof(SCorrRes); }
×
8698

8699
int32_t corrPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
8700
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
8701
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8702
  int32_t              resultBytes = getCorrInfoSize();
×
8703
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
8704
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
×
8705
  int32_t              code = 0;
×
8706

8707
  if (NULL == res) {
×
8708
    return terrno;
×
8709
  }
8710

8711
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
8712
  varDataSetLen(res, resultBytes);
×
8713

8714
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
8715
  if (NULL == pCol) {
×
8716
    taosMemoryFree(res);
×
8717
    return TSDB_CODE_OUT_OF_RANGE;
×
8718
  }
8719

8720
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
8721

8722
  taosMemoryFree(res);
×
8723
  return code;
×
8724
}
8725

8726
int32_t corrFuncMerge(SqlFunctionCtx* pCtx) {
×
8727
  SInputColumnInfoData* pInput = &pCtx->input;
×
8728
  SColumnInfoData*      pCol = pInput->pData[0];
×
8729

8730
  if (IS_NULL_TYPE(pCol->info.type)) {
×
8731
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
8732
    return TSDB_CODE_SUCCESS;
×
8733
  }
8734

8735
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
8736
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
8737
  }
8738

8739
  SCorrRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
8740

8741
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
×
8742
    if (colDataIsNull_s(pCol, i)) {
×
8743
      continue;
×
8744
    }
8745

8746
    char*     data = colDataGetData(pCol, i);
×
8747
    SCorrRes* pInputInfo = (SCorrRes*)varDataVal(data);
×
8748

8749
    if (pInputInfo->count == 0) {
×
8750
      continue;
×
8751
    }
8752

8753
    // pOutput->type = pInput->type;
8754
    if (pInfo->count == 0) {
×
8755
      TAOS_MEMCPY(pInfo, pInputInfo, sizeof(SCorrRes));
×
8756
    } else if (pInfo->count > 0) {
×
8757
      pInfo->productVal += pInputInfo->productVal;
×
8758
      pInfo->quadLeft += pInputInfo->quadLeft;
×
8759
      pInfo->quadRight += pInputInfo->quadRight;
×
8760
      pInfo->sumLeft += pInputInfo->sumLeft;
×
8761
      pInfo->sumRight += pInputInfo->sumRight;
×
8762
      pInfo->count += pInputInfo->count;
×
8763
    }
8764
  }
8765

8766
  SET_VAL(GET_RES_INFO(pCtx), pInfo->count, 1);
×
8767
  return TSDB_CODE_SUCCESS;
×
8768
}
8769

8770
int32_t hasNullFunction(SqlFunctionCtx* pCtx) {
17,575,850✔
8771
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
17,575,850✔
8772
  bool* pRes = GET_ROWCELL_INTERBUF(pResInfo);
17,575,850✔
8773
  if (*pRes) {
17,575,850✔
8774
    return TSDB_CODE_SUCCESS;
×
8775
  }
8776

8777
  SInputColumnInfoData* pInput = &pCtx->input;
17,575,850✔
8778
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
17,575,850✔
8779
  SColumnInfoData* pCol = pInput->pData[0];
17,575,850✔
8780

8781
  if (pInput->numOfRows > 0) {
17,575,850✔
8782
    pResInfo->numOfRes = 1;
17,575,850✔
8783
  }
8784

8785
  if (IS_NULL_TYPE(pCol->info.type) && pInput->numOfRows > 0) {
17,575,850✔
8786
    *pRes = true;
×
8787
    return TSDB_CODE_SUCCESS;
×
8788
  }
8789

8790
  if (pInput->colDataSMAIsSet) {
17,575,850✔
8791
    if (pAgg->numOfNull > 0) {
×
8792
      *pRes = true;
×
8793
      return TSDB_CODE_SUCCESS;
×
8794
    }
8795

8796
    if (pInput->numOfRows <= INT16_MAX) {
×
8797
      return TSDB_CODE_SUCCESS;
×
8798
    }
8799
  }
8800

8801
  int32_t start = pInput->startRowIndex;
17,575,850✔
8802
  int32_t end = start + pInput->numOfRows;
17,575,850✔
8803

8804
  if (pCol->hasNull) {
17,575,850✔
8805
    for (int32_t i = start; i < end; ++i) {
41,842,828✔
8806
      if (colDataIsNull_s(pCol, i)) {
70,947,312✔
8807
        *pRes = true;
11,106,746✔
8808
        break;
11,106,746✔
8809
      }
8810
    }
8811
  }  
8812

8813
  return TSDB_CODE_SUCCESS;
17,575,850✔
8814
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc