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

taosdata / TDengine / #4911

04 Jan 2026 09:05AM UTC coverage: 65.028% (-0.8%) from 65.864%
#4911

push

travis-ci

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

1206 of 4524 new or added lines in 22 files covered. (26.66%)

1517 existing lines in 134 files now uncovered.

195276 of 300296 relevant lines covered (65.03%)

116931714.52 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

197
void funcInputUpdate(SqlFunctionCtx* pCtx) {
51,776,593✔
198
  SFuncInputRowIter* pIter = &pCtx->rowIter;
51,776,593✔
199

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

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

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

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

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

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

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

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

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

332
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
3,285,380✔
333
  int32_t idx = rowIndex + 1;
3,285,380✔
334
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
46,725,698✔
335
    ++idx;
43,440,318✔
336
  }
337
  pIter->rowIndex = idx;
3,285,380✔
338
}
3,285,380✔
339

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

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

361
      pIter->hasPrev = false;
346,572✔
362
      setInputRowInfo(pRow, pIter, idx, true);
346,572✔
363
      forwardToNextDiffTsRow(pIter, idx);
346,572✔
364
      return true;
346,572✔
365
    }
366
  } else {
367
    if (pIter->rowIndex <= pIter->inputEndIndex) {
4,028,450✔
368
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
3,484,020✔
369

370
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
3,484,020✔
371
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
3,484,020✔
372
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
2,938,808✔
373
      } else {
374
        pIter->rowIndex = pIter->inputEndIndex + 1;
545,212✔
375
      }
376
      return true;
3,484,020✔
377
    } else {
378
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
544,430✔
379
      pIter->hasPrev = true;
544,430✔
380
      pIter->prevBlockTsEnd = tsEnd;
544,430✔
381
      return false;
544,430✔
382
    }
383
  }
384
}
385

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

513
  return code;
74,294✔
514
}
515

516
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
12,755,283✔
517
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
12,755,283✔
518
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
12,755,318✔
519
    return FUNC_DATA_REQUIRED_NOT_LOAD;
9,265,559✔
520
  }
521
  return FUNC_DATA_REQUIRED_SMA_LOAD;
3,489,638✔
522
}
523

524
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
48,028,162✔
525
  pEnv->calcMemSize = sizeof(int64_t);
48,028,162✔
526
  return true;
48,040,969✔
527
}
528

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

623
  if (pInput->colDataSMAIsSet) {
2,147,483,647✔
624
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
1,258,965✔
625

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

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

647
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
648
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
2,147,483,647✔
649
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int8_t, numOfElem);
377,031,809✔
650
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
2,147,483,647✔
651
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int16_t, numOfElem);
96,960,970✔
652
      } else if (type == TSDB_DATA_TYPE_INT) {
2,147,483,647✔
653
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int32_t, numOfElem);
2,147,483,647✔
654
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
1,101,760,870✔
655
        LIST_ADD_N(SUM_RES_GET_ISUM(pSumRes), pCol, start, numOfRows, int64_t, numOfElem);
2,147,483,647✔
656
      }
657
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
185,739,859✔
658
      if (type == TSDB_DATA_TYPE_UTINYINT) {
187,055✔
659
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint8_t, numOfElem);
17,965,427✔
660
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
181,628✔
661
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint16_t, numOfElem);
35,287,019✔
662
      } else if (type == TSDB_DATA_TYPE_UINT) {
170,052✔
663
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint32_t, numOfElem);
18,559,613✔
664
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
85,899✔
665
        LIST_ADD_N(SUM_RES_GET_USUM(pSumRes), pCol, start, numOfRows, uint64_t, numOfElem);
18,775,613✔
666
      }
667
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
185,552,804✔
668
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, double, numOfElem);
494,662,717✔
669
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
116,031,738✔
670
      LIST_ADD_N(SUM_RES_GET_DSUM(pSumRes), pCol, start, numOfRows, float, numOfElem);
315,611,285✔
671
    } else if (IS_DECIMAL_TYPE(type)) {
31,076✔
672
      SUM_RES_SET_TYPE(pSumRes, pCtx->inputType, TSDB_DATA_TYPE_DECIMAL);
31,076✔
673
      int32_t overflow = false;
29,358✔
674
      if (TSDB_DATA_TYPE_DECIMAL64 == type) {
29,358✔
675
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal64, numOfElem);
7,696,689✔
676
      } else if (TSDB_DATA_TYPE_DECIMAL == type) {
21,669✔
677
        LIST_ADD_DECIMAL_N(&SUM_RES_GET_DECIMAL_SUM(pSumRes), pCol, start, numOfRows, Decimal128, numOfElem);
15,533,178✔
678
      }
679
      if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
29,358✔
680
    }
681
  }
682

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

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

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

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

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

724
bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
33,308,866✔
725
  pEnv->calcMemSize = SUM_RES_GET_SIZE(pFunc->node.resType.type);
33,308,866✔
726
  return true;
33,312,374✔
727
}
728

729
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
15,702,392✔
730
  SNode* pParam;
731
  switch (pFunc->funcType) {
15,702,392✔
732
    case FUNCTION_TYPE_MAX:
15,702,392✔
733
    case FUNCTION_TYPE_MIN:
734
    case FUNCTION_TYPE_SUM:
735
    case FUNCTION_TYPE_AVG:
736
    case FUNCTION_TYPE_AVG_PARTIAL:
737
    case FUNCTION_TYPE_PERCENTILE:
738
    case FUNCTION_TYPE_SPREAD:
739
    case FUNCTION_TYPE_SPREAD_PARTIAL:
740
    case FUNCTION_TYPE_SPREAD_MERGE:
741
    case FUNCTION_TYPE_TWA:
742
    case FUNCTION_TYPE_ELAPSED:
743
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
15,702,392✔
744
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
15,702,392✔
745
        return true;
365,556✔
746
      }
747
      break;
15,336,836✔
748
    default:
×
749
      break;
×
750
  }
751
  return false;
15,336,836✔
752
}
753

754
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
15,702,392✔
755
  if (funcNotSupportStringSma(pFunc)) {
15,702,392✔
756
    return FUNC_DATA_REQUIRED_DATA_LOAD;
365,556✔
757
  }
758
  return FUNC_DATA_REQUIRED_SMA_LOAD;
15,336,836✔
759
}
760

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

769
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
488,417,135✔
770
  buf->assign = false;
488,400,085✔
771
  buf->tuplePos.pageId = -1;
488,421,652✔
772

773
  buf->nullTupleSaved = false;
488,423,226✔
774
  buf->nullTuplePos.pageId = -1;
488,421,020✔
775
  buf->str = NULL;
488,415,198✔
776
  return TSDB_CODE_SUCCESS;
488,429,000✔
777
}
778

779
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
15,785,597✔
780
  COMPILE_TIME_ASSERT(sizeof(SMinmaxResInfo) == sizeof(SOldMinMaxResInfo));
781
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
15,785,597✔
782
  return true;
15,787,356✔
783
}
784

785
int32_t minFunction(SqlFunctionCtx* pCtx) {
413,959,442✔
786
  int32_t numOfElems = 0;
413,959,442✔
787
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
414,239,481✔
788
  if (code != TSDB_CODE_SUCCESS) {
413,954,924✔
789
    return code;
×
790
  }
791
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
413,954,924✔
792
  return TSDB_CODE_SUCCESS;
413,864,706✔
793
}
794

795
int32_t maxFunction(SqlFunctionCtx* pCtx) {
471,475,135✔
796
  int32_t numOfElems = 0;
471,475,135✔
797
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
471,525,128✔
798
  if (code != TSDB_CODE_SUCCESS) {
471,416,802✔
799
    return code;
×
800
  }
801
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
471,416,802✔
802
  return TSDB_CODE_SUCCESS;
470,944,410✔
803
}
804

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

809
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
459,300,916✔
810
  int32_t code = TSDB_CODE_SUCCESS;
459,300,916✔
811

812
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
459,300,916✔
813
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
459,300,916✔
814

815
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
459,300,916✔
816
  int32_t currentRow = pBlock->info.rows;
459,300,204✔
817

818
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
459,301,654✔
819
  if (NULL == pCol) {
459,298,223✔
820
    return TSDB_CODE_OUT_OF_RANGE;
×
821
  }
822
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
459,298,223✔
823

824
  // NOTE: do nothing change it, for performance issue
825
  if (!pEntryInfo->isNullRes) {
459,300,097✔
826
    switch (pCol->info.type) {
386,151,458✔
827
      case TSDB_DATA_TYPE_UBIGINT:
116,137,467✔
828
      case TSDB_DATA_TYPE_BIGINT:
829
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
116,137,467✔
830
        break;
116,137,467✔
831
      case TSDB_DATA_TYPE_UINT:
210,488,188✔
832
      case TSDB_DATA_TYPE_INT:
833
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
210,488,188✔
834
        break;
210,488,176✔
835
      case TSDB_DATA_TYPE_USMALLINT:
1,577,085✔
836
      case TSDB_DATA_TYPE_SMALLINT:
837
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
1,577,085✔
838
        break;
1,577,085✔
839
      case TSDB_DATA_TYPE_BOOL:
16,203,852✔
840
      case TSDB_DATA_TYPE_UTINYINT:
841
      case TSDB_DATA_TYPE_TINYINT:
842
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
16,203,852✔
843
        break;
16,203,852✔
844
      case TSDB_DATA_TYPE_DOUBLE:
19,402,108✔
845
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
19,402,108✔
846
        break;
19,402,108✔
847
      case TSDB_DATA_TYPE_FLOAT: {
21,137,665✔
848
        float v = GET_FLOAT_VAL(&pRes->v);
21,137,665✔
849
        colDataSetFloat(pCol, currentRow, &v);
21,137,665✔
850
        break;
21,137,665✔
851
      }
852
      case TSDB_DATA_TYPE_VARBINARY:
1,152,408✔
853
      case TSDB_DATA_TYPE_VARCHAR:
854
      case TSDB_DATA_TYPE_NCHAR: {
855
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
1,152,408✔
856
        if (TSDB_CODE_SUCCESS != code) {
1,152,408✔
857
          return code;
×
858
        }
859
        break;
1,152,408✔
860
      }
861
      case TSDB_DATA_TYPE_DECIMAL64:
23,268✔
862
        code = colDataSetVal(pCol, currentRow, (const char*)&pRes->v, false);
23,268✔
863
        break;
23,268✔
864
      case TSDB_DATA_TYPE_DECIMAL:
29,349✔
865
        code = colDataSetVal(pCol, currentRow, (void*)pRes->dec, false);
29,349✔
866
        break;
29,349✔
867
    }
868
  } else {
869
    colDataSetNULL(pCol, currentRow);
73,146,167✔
870
  }
871

872
  if (IS_VAR_DATA_TYPE(pCol->info.type)) taosMemoryFreeClear(pRes->str);
459,296,007✔
873
  if (pCtx->subsidiaries.num > 0) {
459,298,183✔
874
    if (pEntryInfo->numOfRes > 0) {
981,318✔
875
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
736,244✔
876
    } else {
877
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
244,693✔
878
    }
879
  }
880

881
  return code;
459,297,801✔
882
}
883

884
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
206,434,448✔
885
  if (pCtx->subsidiaries.num <= 0) {
206,434,448✔
886
    return TSDB_CODE_SUCCESS;
206,272,522✔
887
  }
888

889
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
781,235✔
890
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
473,789✔
891
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
473,789✔
892

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

900
  return TSDB_CODE_SUCCESS;
307,446✔
901
}
902

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

908
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
17,096,060✔
909
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
362✔
910
    int32_t numOfCols = pCtx->subsidiaries.num;
17,096,654✔
911
    char*   p = NULL;
17,096,422✔
912
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
17,097,016✔
913
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
17,096,269✔
914
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
915
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
916
      return TSDB_CODE_NOT_FOUND;
×
917
    }
918

919
    bool* nullList = (bool*)p;
17,096,654✔
920
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
17,096,654✔
921

922
    // todo set the offset value to optimize the performance.
923
    for (int32_t j = 0; j < numOfCols; ++j) {
38,128,796✔
924
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
21,032,374✔
925
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
21,031,780✔
926

927
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
21,032,142✔
928
      if (NULL == pDstCol) {
21,032,736✔
929
        return terrno;
×
930
      }
931
      if (nullList[j]) {
21,032,736✔
932
        colDataSetNULL(pDstCol, rowIndex);
36,609✔
933
      } else {
934
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
20,995,171✔
935
        if (TSDB_CODE_SUCCESS != code) {
20,994,939✔
936
          return code;
×
937
        }
938
      }
939
      pStart += pDstCol->info.bytes;
21,031,548✔
940
    }
941
  }
942

943
  return TSDB_CODE_SUCCESS;
17,096,422✔
944
}
945

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

953
  int32_t code = TSDB_CODE_SUCCESS;
180,944✔
954
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
596,914✔
955
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
415,970✔
956

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

961
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
415,970✔
962
    if (NULL == pSrcCol) {
415,970✔
963
      return TSDB_CODE_OUT_OF_RANGE;
×
964
    }
965

966
    char* pData = colDataGetData(pSrcCol, rowIndex);
415,970✔
967

968
    // append to dest col
969
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
415,970✔
970

971
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
415,970✔
972
    if (NULL == pDstCol) {
415,970✔
973
      return TSDB_CODE_OUT_OF_RANGE;
×
974
    }
975

976
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
831,940✔
977
      colDataSetNULL(pDstCol, pos);
46,656✔
978
    } else {
979
      code = colDataSetVal(pDstCol, pos, pData, false);
369,314✔
980
      if (TSDB_CODE_SUCCESS != code) {
369,314✔
981
        return code;
×
982
      }
983
    }
984
  }
985
  return code;
180,944✔
986
}
987

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

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

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

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

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

1080
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
14,700,944✔
1081

1082
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,959,837✔
1083
  pEnv->calcMemSize = sizeof(SStdRes);
2,959,837✔
1084
  return true;
2,960,320✔
1085
}
1086

1087
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
103,794,402✔
1088
  if (pResultInfo->initialized) {
103,794,402✔
1089
    return TSDB_CODE_SUCCESS;
×
1090
  }
1091
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
103,795,847✔
1092
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1093
  }
1094

1095
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
103,794,953✔
1096
  (void)memset(pRes, 0, sizeof(SStdRes));
103,795,434✔
1097
  return TSDB_CODE_SUCCESS;
103,795,434✔
1098
}
1099

1100
int32_t stdFunction(SqlFunctionCtx* pCtx) {
91,181,815✔
1101
  int32_t numOfElem = 0;
91,181,815✔
1102

1103
  // Only the pre-computing information loaded and actual data does not loaded
1104
  SInputColumnInfoData* pInput = &pCtx->input;
91,181,815✔
1105
  int32_t               type = pInput->pData[0]->info.type;
91,182,777✔
1106

1107
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
91,183,260✔
1108
  pStdRes->type = type;
91,181,883✔
1109

1110
  // computing based on the true data block
1111
  SColumnInfoData* pCol = pInput->pData[0];
91,180,440✔
1112

1113
  int32_t start = pInput->startRowIndex;
91,183,741✔
1114
  int32_t numOfRows = pInput->numOfRows;
91,183,260✔
1115

1116
  if (IS_NULL_TYPE(type)) {
91,179,410✔
1117
    numOfElem = 0;
61,386✔
1118
    goto _stddev_over;
61,386✔
1119
  }
1120

1121
  switch (type) {
91,118,024✔
1122
    case TSDB_DATA_TYPE_TINYINT: {
1,085,996✔
1123
      int8_t* plist = (int8_t*)pCol->pData;
1,085,996✔
1124
      for (int32_t i = start; i < numOfRows + start; ++i) {
28,941,234✔
1125
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
27,855,238✔
1126
          continue;
2,026,584✔
1127
        }
1128

1129
        numOfElem += 1;
25,828,654✔
1130
        pStdRes->count += 1;
25,828,654✔
1131
        double nr = (double)plist[i];
25,828,654✔
1132
        if (pStdRes->count == 1) {
25,828,654✔
1133
          pStdRes->dsum = nr;
475,832✔
1134
        } else {
1135
          double          s_kminusone = pStdRes->dsum;
25,352,822✔
1136
          volatile double diff = nr - s_kminusone;
25,352,822✔
1137
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
25,352,822✔
1138
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
25,352,822✔
1139
        }
1140
      }
1141

1142
      break;
1,085,996✔
1143
    }
1144

1145
    case TSDB_DATA_TYPE_SMALLINT: {
48,633,562✔
1146
      int16_t* plist = (int16_t*)pCol->pData;
48,633,562✔
1147
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
118,338,720✔
1148
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
69,705,158✔
1149
          continue;
1,844,718✔
1150
        }
1151

1152
        numOfElem += 1;
67,860,440✔
1153
        pStdRes->count += 1;
67,860,440✔
1154
        double nr = (double)plist[i];
67,860,440✔
1155
        if (pStdRes->count == 1) {
67,860,440✔
1156
          pStdRes->dsum = nr;
47,469,622✔
1157
        } else {
1158
          double          s_kminusone = pStdRes->dsum;
20,390,818✔
1159
          volatile double diff = nr - s_kminusone;
20,390,818✔
1160
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
20,390,818✔
1161
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
20,390,818✔
1162
        }
1163
      }
1164
      break;
48,633,562✔
1165
    }
1166

1167
    case TSDB_DATA_TYPE_INT: {
12,086,168✔
1168
      int32_t* plist = (int32_t*)pCol->pData;
12,086,168✔
1169
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,033,355,585✔
1170
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
2,021,268,455✔
1171
          continue;
5,263,977✔
1172
        }
1173

1174
        numOfElem += 1;
2,016,003,997✔
1175
        pStdRes->count += 1;
2,016,003,997✔
1176
        double nr = (double)plist[i];
2,016,004,478✔
1177
        if (pStdRes->count == 1) {
2,016,004,959✔
1178
          pStdRes->dsum = nr;
10,444,866✔
1179
        } else {
1180
          double          s_kminusone = pStdRes->dsum;
2,005,563,460✔
1181
          volatile double diff = nr - s_kminusone;
2,005,563,460✔
1182
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
2,005,563,460✔
1183
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
2,005,563,460✔
1184
        }
1185
      }
1186

1187
      break;
12,087,130✔
1188
    }
1189

1190
    case TSDB_DATA_TYPE_BIGINT: {
9,395,095✔
1191
      int64_t* plist = (int64_t*)pCol->pData;
9,395,095✔
1192
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
126,195,149✔
1193
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
116,806,818✔
1194
          continue;
2,552,090✔
1195
        }
1196

1197
        numOfElem += 1;
114,250,868✔
1198
        pStdRes->count += 1;
114,250,868✔
1199
        double nr = (double)plist[i];
114,247,485✔
1200
        if (pStdRes->count == 1) {
114,247,485✔
1201
          pStdRes->dsum = nr;
8,437,568✔
1202
        } else {
1203
          double          s_kminusone = pStdRes->dsum;
105,809,432✔
1204
          volatile double diff = nr - s_kminusone;
105,809,432✔
1205
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
105,809,432✔
1206
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
105,809,915✔
1207
        }
1208
      }
1209
      break;
9,395,576✔
1210
    }
1211

1212
    case TSDB_DATA_TYPE_UTINYINT: {
6,035✔
1213
      uint8_t* plist = (uint8_t*)pCol->pData;
6,035✔
1214
      for (int32_t i = start; i < numOfRows + start; ++i) {
16,335,238✔
1215
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,329,203✔
1216
          continue;
2,916✔
1217
        }
1218

1219
        numOfElem += 1;
16,326,287✔
1220
        pStdRes->count += 1;
16,326,287✔
1221
        double nr = (double)plist[i];
16,326,287✔
1222
        if (pStdRes->count == 1) {
16,326,287✔
1223
          pStdRes->dsum = nr;
1,547✔
1224
        } else {
1225
          double          s_kminusone = pStdRes->dsum;
16,324,740✔
1226
          volatile double diff = nr - s_kminusone;
16,324,740✔
1227
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
16,324,740✔
1228
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
16,324,740✔
1229
        }
1230
      }
1231

1232
      break;
6,035✔
1233
    }
1234

1235
    case TSDB_DATA_TYPE_USMALLINT: {
5,720✔
1236
      uint16_t* plist = (uint16_t*)pCol->pData;
5,720✔
1237
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,381,984✔
1238
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,376,264✔
UNCOV
1239
          continue;
×
1240
        }
1241

1242
        numOfElem += 1;
16,376,264✔
1243
        pStdRes->count += 1;
16,376,264✔
1244
        double nr = (double)plist[i];
16,376,264✔
1245
        if (pStdRes->count == 1) {
16,376,264✔
1246
          pStdRes->dsum = nr;
1,232✔
1247
        } else {
1248
          double          s_kminusone = pStdRes->dsum;
16,375,032✔
1249
          volatile double diff = nr - s_kminusone;
16,375,032✔
1250
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
16,375,032✔
1251
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
16,375,032✔
1252
        }
1253
      }
1254
      break;
5,720✔
1255
    }
1256

1257
    case TSDB_DATA_TYPE_UINT: {
5,646✔
1258
      uint32_t* plist = (uint32_t*)pCol->pData;
5,646✔
1259
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,331,446✔
1260
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,325,800✔
UNCOV
1261
          continue;
×
1262
        }
1263

1264
        numOfElem += 1;
16,325,800✔
1265
        pStdRes->count += 1;
16,325,800✔
1266
        double nr = (double)plist[i];
16,325,800✔
1267
        if (pStdRes->count == 1) {
16,325,800✔
1268
          pStdRes->dsum = nr;
1,158✔
1269
        } else {
1270
          double          s_kminusone = pStdRes->dsum;
16,324,642✔
1271
          volatile double diff = nr - s_kminusone;
16,324,642✔
1272
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
16,324,642✔
1273
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
16,324,642✔
1274
        }
1275
      }
1276

1277
      break;
5,646✔
1278
    }
1279

1280
    case TSDB_DATA_TYPE_UBIGINT: {
5,306✔
1281
      uint64_t* plist = (uint64_t*)pCol->pData;
5,306✔
1282
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,329,406✔
1283
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,324,100✔
UNCOV
1284
          continue;
×
1285
        }
1286

1287
        numOfElem += 1;
16,324,100✔
1288
        pStdRes->count += 1;
16,324,100✔
1289
        double nr = (double)plist[i];
16,324,100✔
1290
        if (pStdRes->count == 1) {
16,324,100✔
1291
          pStdRes->dsum = nr;
818✔
1292
        } else {
1293
          double          s_kminusone = pStdRes->dsum;
16,323,282✔
1294
          volatile double diff = nr - s_kminusone;
16,323,282✔
1295
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
16,323,282✔
1296
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
16,323,282✔
1297
        }
1298
      }
1299
      break;
5,306✔
1300
    }
1301

1302
    case TSDB_DATA_TYPE_FLOAT: {
8,744,260✔
1303
      float* plist = (float*)pCol->pData;
8,744,260✔
1304
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,593,543,901✔
1305
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
1,584,799,228✔
1306
          continue;
2,183,246✔
1307
        }
1308

1309
        numOfElem += 1;
1,582,615,156✔
1310
        pStdRes->count += 1;
1,582,615,156✔
1311
        double nr = (double)plist[i];
1,582,615,569✔
1312
        if (pStdRes->count == 1) {
1,582,615,569✔
1313
          pStdRes->dsum = nr;
8,101,192✔
1314
        } else {
1315
          double          s_kminusone = pStdRes->dsum;
1,574,514,377✔
1316
          volatile double diff = nr - s_kminusone;
1,574,514,377✔
1317
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
1,574,514,377✔
1318
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
1,574,514,377✔
1319
        }
1320
      }
1321
      break;
8,744,260✔
1322
    }
1323

1324
    case TSDB_DATA_TYPE_DOUBLE: {
11,150,236✔
1325
      double* plist = (double*)pCol->pData;
11,150,236✔
1326
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
290,202,548✔
1327
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
279,061,475✔
1328
          continue;
4,093,002✔
1329
        }
1330

1331
        numOfElem += 1;
274,958,346✔
1332
        pStdRes->count += 1;
274,958,346✔
1333
        double nr = (double)plist[i];
274,958,342✔
1334
        if (pStdRes->count == 1) {
274,960,270✔
1335
          pStdRes->dsum = nr;
10,202,197✔
1336
        } else {
1337
          double          s_kminusone = pStdRes->dsum;
264,750,345✔
1338
          volatile double diff = nr - s_kminusone;
264,751,792✔
1339
          pStdRes->dsum = s_kminusone + diff / (double)pStdRes->count;
264,751,792✔
1340
          pStdRes->quadraticDSum += diff * (nr - pStdRes->dsum);
264,745,044✔
1341
        }
1342
      }
1343
      break;
11,153,124✔
1344
    }
1345

1346
    default:
×
1347
      break;
×
1348
  }
1349

1350
_stddev_over:
91,183,741✔
1351
  // data in the check operation are all null, not output
1352
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
91,183,741✔
1353
  return TSDB_CODE_SUCCESS;
91,183,260✔
1354
}
1355

1356
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
14,509,132✔
1357
  if (IS_NULL_TYPE(pInput->type)) {
14,509,132✔
1358
    return;
10,270✔
1359
  }
1360
  pOutput->type = pInput->type;
14,498,862✔
1361
  if (pOutput->count == 0) {
14,498,862✔
1362
    pOutput->quadraticDSum += pInput->quadraticDSum;
14,479,309✔
1363
    pOutput->dsum += pInput->dsum;
14,479,309✔
1364
    pOutput->count = pInput->count;
14,479,309✔
1365
  } else if (pInput->count > 0) {
19,553✔
1366
    double totalCount = pOutput->count + pInput->count;
19,553✔
1367
    double totalSum = pInput->count * pInput->dsum + pOutput->count * pOutput->dsum;
19,553✔
1368
    double mean = totalSum / totalCount;
19,553✔
1369

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

1375
    double diff = pInput->dsum - pOutput->dsum;
19,553✔
1376
    pOutput->quadraticDSum += pInput->quadraticDSum + pInput->count * pOutput->count * (diff * diff) / totalCount;
19,553✔
1377
    pOutput->dsum = mean;
19,553✔
1378
    pOutput->count += pInput->count;
19,553✔
1379
  }
1380
}
1381

1382
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
14,508,664✔
1383
  SInputColumnInfoData* pInput = &pCtx->input;
14,508,664✔
1384
  SColumnInfoData*      pCol = pInput->pData[0];
14,508,664✔
1385

1386
  if (IS_NULL_TYPE(pCol->info.type)) {
14,508,664✔
1387
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1388
    return TSDB_CODE_SUCCESS;
×
1389
  }
1390

1391
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
14,508,664✔
1392
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1393
  }
1394

1395
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
14,508,664✔
1396

1397
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
29,017,796✔
1398
    if (colDataIsNull_s(pCol, i)) continue;
29,018,264✔
1399
    char*    data = colDataGetData(pCol, i);
14,509,132✔
1400
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
14,509,132✔
1401
    stdTransferInfo(pInputInfo, pInfo);
14,509,132✔
1402
  }
1403

1404
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
14,508,664✔
1405
  return TSDB_CODE_SUCCESS;
14,508,664✔
1406
}
1407

1408
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
68,801,363✔
1409
  SInputColumnInfoData* pInput = &pCtx->input;
68,801,363✔
1410
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
68,801,844✔
1411
  int32_t               type = pStddevRes->type;
68,801,363✔
1412
  double                avg;
1413

1414
  if (pStddevRes->count == 0) {
68,801,844✔
1415
    GET_RES_INFO(pCtx)->numOfRes = 0;
3,165,245✔
1416

1417
    return functionFinalize(pCtx, pBlock);
3,165,245✔
1418
  }
1419

1420
  if (pStddevRes->count == 1) {
65,635,635✔
1421
    pStddevRes->result = 0.0;
46,600,549✔
1422
  } else {
1423
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / pStddevRes->count);
19,036,050✔
1424
  }
1425

1426
  // check for overflow
1427
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
65,635,635✔
1428
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1429
  }
1430

1431
  return functionFinalize(pCtx, pBlock);
65,635,154✔
1432
}
1433

1434
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,774,063✔
1435
  SInputColumnInfoData* pInput = &pCtx->input;
5,774,063✔
1436
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,774,063✔
1437
  int32_t               type = pStdvarRes->type;
5,774,063✔
1438
  double                avg;
1439

1440
  if (pStdvarRes->count == 0) {
5,774,063✔
1441
    GET_RES_INFO(pCtx)->numOfRes = 0;
828✔
1442
    return functionFinalize(pCtx, pBlock);
828✔
1443
  }
1444

1445
  if (pStdvarRes->count == 1) {
5,773,235✔
1446
    pStdvarRes->result = 0.0;
828✔
1447
  } else {
1448
    pStdvarRes->result = pStdvarRes->quadraticDSum / pStdvarRes->count;
5,772,407✔
1449
  }
1450

1451
  // check for overflow
1452
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
5,773,235✔
1453
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1454
  }
1455

1456
  return functionFinalize(pCtx, pBlock);
5,773,235✔
1457
}
1458

1459
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
14,509,132✔
1460
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
14,509,132✔
1461
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
14,509,132✔
1462
  int32_t              resultBytes = getStdInfoSize();
14,509,132✔
1463
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
14,509,132✔
1464

1465
  if (NULL == res) {
14,509,132✔
1466
    return terrno;
×
1467
  }
1468
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
14,509,132✔
1469
  varDataSetLen(res, resultBytes);
14,509,132✔
1470

1471
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
14,509,132✔
1472
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
14,509,132✔
1473
  if (NULL == pCol) {
14,509,132✔
1474
    taosMemoryFree(res);
×
1475
    return TSDB_CODE_OUT_OF_RANGE;
×
1476
  }
1477

1478
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
14,509,132✔
1479

1480
  taosMemoryFree(res);
14,509,132✔
1481
  return code;
14,509,132✔
1482
}
1483

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

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

1492
  stdTransferInfo(pSBuf, pDBuf);
×
1493

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

1499
int32_t stddevsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,888,069✔
1500
  SInputColumnInfoData* pInput = &pCtx->input;
2,888,069✔
1501
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,888,069✔
1502
  double                avg;
1503

1504
  if (pStddevRes->count == 0) {
2,888,069✔
1505
    GET_RES_INFO(pCtx)->numOfRes = 0;
414✔
1506
    return functionFinalize(pCtx, pBlock);
414✔
1507
  }
1508

1509
  if (pStddevRes->count == 1) {
2,887,655✔
1510
    pStddevRes->result = 0.0;
414✔
1511
  } else {
1512
    pStddevRes->result = sqrt(pStddevRes->quadraticDSum / (pStddevRes->count - 1));
2,887,241✔
1513
  }
1514

1515
  // check for overflow
1516
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
2,887,655✔
1517
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1518
  }
1519

1520
  return functionFinalize(pCtx, pBlock);
2,887,655✔
1521
}
1522

1523
int32_t stdvarsampFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,887,241✔
1524
  SInputColumnInfoData* pInput = &pCtx->input;
2,887,241✔
1525
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,887,241✔
1526
  double                avg;
1527

1528
  if (pStddevRes->count == 0) {
2,887,241✔
1529
    GET_RES_INFO(pCtx)->numOfRes = 0;
414✔
1530
    return functionFinalize(pCtx, pBlock);
414✔
1531
  }
1532

1533
  if (pStddevRes->count == 1) {
2,886,827✔
1534
    pStddevRes->result = 0.0;
414✔
1535
  } else {
1536
    pStddevRes->result = pStddevRes->quadraticDSum / (pStddevRes->count - 1);
2,886,413✔
1537
  }
1538

1539
  // check for overflow
1540
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
2,886,827✔
1541
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1542
  }
1543

1544
  return functionFinalize(pCtx, pBlock);
2,886,827✔
1545
}
1546

1547
bool gconcatGetFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
845✔
1548
  pEnv->calcMemSize = sizeof(SGconcatRes);
845✔
1549
  return true;
845✔
1550
}
1551

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

1560
  SGconcatRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
845✔
1561
  (void)memset(pRes, 0, sizeof(SStdRes));
845✔
1562

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

1565
  int32_t sepParamIdx = pCtx->numOfParams - 1;
845✔
1566
  pRes->separator = pCtx->param[sepParamIdx].param.pz;
845✔
1567
  pRes->type = pCtx->param[sepParamIdx].param.nType;
845✔
1568

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

1573
  pRes->nchar = (type == TSDB_DATA_TYPE_NCHAR);
1574
  */
1575

1576
  return TSDB_CODE_SUCCESS;
845✔
1577
}
1578

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

1601
  return TSDB_CODE_SUCCESS;
16,055✔
1602
}
1603

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

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

1622
    varDataSetLen(pRes->result, 0);
845✔
1623

1624
    for (int c = 0; c < numOfCols - 1; ++c) {
1,690✔
1625
      SColumnInfoData* pCol = pInput->pData[c];
845✔
1626
      int32_t          type = pCol->info.type;
845✔
1627

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

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

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

1648
  sep = colDataGetData(pCol, 0);
845✔
1649
  pRes->type = pCol->info.type;
845✔
1650
  for (int r = rowStart; r < rowStart + numOfRows; ++r) {
9,295✔
1651
    if (prefixSep) {
8,450✔
1652
      // concat the separator
1653
      // setup sepatator's charset instead of the default: pRes->charsetCxt
1654

1655
      code = gconcatHelper(sep, buf, hasNchar, pRes->type, &dataLen, NULL);
7,605✔
1656
      if (code) {
7,605✔
1657
        goto _over;
×
1658
      }
1659
    }
1660

1661
    for (int c = 0; c < numOfCols - 1; ++c) {
16,900✔
1662
      SColumnInfoData* pCol = pInput->pData[c];
8,450✔
1663
      int32_t          type = pCol->info.type;
8,450✔
1664

1665
      if (IS_NULL_TYPE(type) || (pCol->hasNull && colDataIsNull_f(pCol, r))) {
8,450✔
1666
        continue;
×
1667
      }
1668

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

1676
    prefixSep = true;
8,450✔
1677
  }
1678

1679
  varDataSetLen(buf, dataLen);
845✔
1680
  numOfElem += 1;
845✔
1681

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

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

1695
  if (NULL == pCol) {
845✔
1696
    taosMemoryFree(pRes->result);
×
1697
    return TSDB_CODE_OUT_OF_RANGE;
×
1698
  }
1699

1700
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->result, NULL == pRes->result);
845✔
1701

1702
  taosMemoryFree(pRes->result);
845✔
1703

1704
  return code;
845✔
1705
}
1706

1707
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
984,664✔
1708
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
984,664✔
1709
  return true;
984,664✔
1710
}
1711

1712
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,459,918✔
1713
  if (pResultInfo->initialized) {
4,459,918✔
1714
    return TSDB_CODE_SUCCESS;
×
1715
  }
1716
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,460,363✔
1717
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1718
  }
1719

1720
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,460,808✔
1721

1722
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i,
4,460,363✔
1723
                 typeGetTypeModFromCol(pCtx->param[1].pCol));
1724
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i,
4,460,808✔
1725
                 typeGetTypeModFromCol(pCtx->param[2].pCol));
1726
  return TSDB_CODE_SUCCESS;
4,460,363✔
1727
}
1728

1729
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
5,239,504✔
1730
  int32_t numOfElem = 0;
5,239,504✔
1731

1732
  SInputColumnInfoData* pInput = &pCtx->input;
5,239,504✔
1733
  int32_t               type = pInput->pData[0]->info.type;
5,240,394✔
1734

1735
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,239,949✔
1736

1737
  SColumnInfoData* pCol = pInput->pData[0];
5,240,394✔
1738

1739
  double(*param)[3] = pInfo->matrix;
5,239,466✔
1740
  double x = pInfo->startVal;
5,239,949✔
1741

1742
  int32_t start = pInput->startRowIndex;
5,239,466✔
1743
  int32_t numOfRows = pInput->numOfRows;
5,240,394✔
1744

1745
  switch (type) {
5,239,949✔
1746
    case TSDB_DATA_TYPE_TINYINT: {
449,158✔
1747
      int8_t* plist = (int8_t*)pCol->pData;
449,158✔
1748
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
17,290,266✔
1749
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,841,108✔
1750
          continue;
196,992✔
1751
        }
1752
        numOfElem++;
16,644,116✔
1753
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,644,116✔
1754
      }
1755
      break;
449,158✔
1756
    }
1757
    case TSDB_DATA_TYPE_SMALLINT: {
303,380✔
1758
      int16_t* plist = (int16_t*)pCol->pData;
303,380✔
1759
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,992,324✔
1760
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,688,944✔
1761
          continue;
148,592✔
1762
        }
1763

1764
        numOfElem++;
16,540,352✔
1765
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,540,352✔
1766
      }
1767
      break;
303,380✔
1768
    }
1769

1770
    case TSDB_DATA_TYPE_INT: {
2,457,649✔
1771
      int32_t* plist = (int32_t*)pCol->pData;
2,457,649✔
1772
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
95,620,599✔
1773
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
93,162,469✔
1774
          continue;
264,526✔
1775
        }
1776

1777
        numOfElem++;
92,897,943✔
1778
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
92,897,943✔
1779
      }
1780
      break;
2,457,649✔
1781
    }
1782

1783
    case TSDB_DATA_TYPE_BIGINT: {
256,994✔
1784
      int64_t* plist = (int64_t*)pCol->pData;
256,994✔
1785
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,951,302✔
1786
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,694,308✔
1787
          continue;
148,592✔
1788
        }
1789

1790
        numOfElem++;
16,545,716✔
1791
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,545,716✔
1792
      }
1793
      break;
256,994✔
1794
    }
1795

1796
    case TSDB_DATA_TYPE_UTINYINT: {
15,712✔
1797
      uint8_t* plist = (uint8_t*)pCol->pData;
15,712✔
1798
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,370,656✔
1799
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,354,944✔
1800
          continue;
9,152✔
1801
        }
1802
        numOfElem++;
16,345,792✔
1803
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,345,792✔
1804
      }
1805
      break;
15,712✔
1806
    }
1807
    case TSDB_DATA_TYPE_USMALLINT: {
15,712✔
1808
      uint16_t* plist = (uint16_t*)pCol->pData;
15,712✔
1809
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,370,656✔
1810
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,354,944✔
1811
          continue;
8,320✔
1812
        }
1813

1814
        numOfElem++;
16,346,624✔
1815
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,346,624✔
1816
      }
1817
      break;
15,712✔
1818
    }
1819

1820
    case TSDB_DATA_TYPE_UINT: {
15,712✔
1821
      uint32_t* plist = (uint32_t*)pCol->pData;
15,712✔
1822
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,370,656✔
1823
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,354,944✔
1824
          continue;
8,320✔
1825
        }
1826

1827
        numOfElem++;
16,346,624✔
1828
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,346,624✔
1829
      }
1830
      break;
15,712✔
1831
    }
1832

1833
    case TSDB_DATA_TYPE_UBIGINT: {
15,712✔
1834
      uint64_t* plist = (uint64_t*)pCol->pData;
15,712✔
1835
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
16,370,656✔
1836
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
16,354,944✔
1837
          continue;
8,320✔
1838
        }
1839

1840
        numOfElem++;
16,346,624✔
1841
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
16,346,624✔
1842
      }
1843
      break;
15,712✔
1844
    }
1845

1846
    case TSDB_DATA_TYPE_FLOAT: {
973,728✔
1847
      float* plist = (float*)pCol->pData;
973,728✔
1848
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
18,334,472✔
1849
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
17,360,744✔
1850
          continue;
340,592✔
1851
        }
1852

1853
        numOfElem++;
17,020,152✔
1854
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
17,020,152✔
1855
      }
1856
      break;
973,728✔
1857
    }
1858

1859
    case TSDB_DATA_TYPE_DOUBLE: {
736,192✔
1860
      double* plist = (double*)pCol->pData;
736,192✔
1861
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
83,801,563✔
1862
        if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
83,064,405✔
1863
          continue;
53,392✔
1864
        }
1865

1866
        numOfElem++;
83,009,564✔
1867
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
83,009,564✔
1868
      }
1869
      break;
736,192✔
1870
    }
1871
    case TSDB_DATA_TYPE_NULL: {
×
1872
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1873
      numOfElem = 1;
×
1874
      break;
×
1875
    }
1876

1877
    default:
×
1878
      break;
×
1879
  }
1880

1881
  pInfo->startVal = x;
5,239,949✔
1882
  pInfo->num += numOfElem;
5,239,504✔
1883

1884
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
5,239,504✔
1885

1886
  return TSDB_CODE_SUCCESS;
5,239,949✔
1887
}
1888

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

1895
  if (NULL == pCol) {
4,459,499✔
1896
    return TSDB_CODE_OUT_OF_RANGE;
×
1897
  }
1898
  int32_t currentRow = pBlock->info.rows;
4,459,499✔
1899

1900
  if (0 == pInfo->num) {
4,459,499✔
1901
    colDataSetNULL(pCol, currentRow);
992,311✔
1902
    return TSDB_CODE_SUCCESS;
992,311✔
1903
  }
1904

1905
  double(*param)[3] = pInfo->matrix;
3,467,188✔
1906

1907
  param[1][1] = (double)pInfo->num;
3,467,669✔
1908
  param[1][0] = param[0][1];
3,467,669✔
1909

1910
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
3,467,188✔
1911
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
3,467,669✔
1912

1913
  if (0 == param00) {
3,467,669✔
1914
    colDataSetNULL(pCol, currentRow);
2,442,992✔
1915
    return TSDB_CODE_SUCCESS;
2,442,992✔
1916
  }
1917

1918
  // param[0][1] = 0;
1919
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
1,024,677✔
1920
  // param[1][0] = 0;
1921
  param02 /= param00;
1,024,677✔
1922

1923
  param12 /= param[1][1];
1,024,677✔
1924

1925
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
1,024,677✔
1926
  char slopBuf[64] = {0};
1,024,677✔
1927
  char interceptBuf[64] = {0};
1,024,677✔
1928
  int  n = tsnprintf(slopBuf, 64, "%.6lf", param02);
1,024,677✔
1929
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,024,677✔
1930
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
832✔
1931
  }
1932
  n = tsnprintf(interceptBuf, 64, "%.6lf", param12);
1,024,677✔
1933
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,024,196✔
1934
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
2,132✔
1935
  }
1936
  size_t len =
1,024,196✔
1937
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
1,024,196✔
1938
  varDataSetLen(buf, len);
1,024,196✔
1939

1940
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,024,677✔
1941

1942
  return code;
1,024,677✔
1943
}
1944

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

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

1967
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
79,717✔
1968
  pEnv->calcMemSize = sizeof(SPercentileInfo);
79,717✔
1969
  return true;
79,717✔
1970
}
1971

1972
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
317,086✔
1973
  if (pResultInfo->initialized) {
317,086✔
1974
    return TSDB_CODE_SUCCESS;
×
1975
  }
1976
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
317,086✔
1977
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1978
  }
1979

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

1986
  return TSDB_CODE_SUCCESS;
317,086✔
1987
}
1988

1989
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
1,242✔
1990
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
1,242✔
1991
    return;
×
1992
  }
1993
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,242✔
1994
  if (pInfo->pMemBucket != NULL) {
1,242✔
1995
    tMemBucketDestroy(&(pInfo->pMemBucket));
414✔
1996
    pInfo->pMemBucket = NULL;
414✔
1997
  }
1998
}
1999

2000
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
1,603,532✔
2001
  int32_t              code = TSDB_CODE_SUCCESS;
1,603,532✔
2002
  int32_t              numOfElems = 0;
1,603,532✔
2003
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,603,532✔
2004

2005
  SInputColumnInfoData* pInput = &pCtx->input;
1,603,532✔
2006
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
1,603,532✔
2007

2008
  SColumnInfoData* pCol = pInput->pData[0];
1,603,532✔
2009
  int32_t          type = pCol->info.type;
1,603,532✔
2010

2011
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,603,532✔
2012
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
1,603,532✔
2013
    pInfo->stage += 1;
317,086✔
2014

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

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

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

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

2051
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
×
2052
    } else {
2053
      // check the valid data one by one
2054
      int32_t start = pInput->startRowIndex;
801,766✔
2055
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,934,516✔
2056
        if (colDataIsNull_f(pCol, i)) {
14,132,750✔
2057
          continue;
124,124✔
2058
        }
2059

2060
        char* data = colDataGetData(pCol, i);
14,008,626✔
2061

2062
        double v = 0;
14,008,626✔
2063
        GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
14,008,626✔
2064
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
14,008,626✔
2065
          SET_DOUBLE_VAL(&pInfo->minval, v);
291,746✔
2066
        }
2067

2068
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
14,008,626✔
2069
          SET_DOUBLE_VAL(&pInfo->maxval, v);
11,218,858✔
2070
        }
2071

2072
        pInfo->numOfElems += 1;
14,008,626✔
2073
      }
2074
    }
2075
  } else {
2076
    // the second stage, calculate the true percentile value
2077
    int32_t start = pInput->startRowIndex;
752,882✔
2078
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,736,668✔
2079
      if (colDataIsNull_f(pCol, i)) {
13,984,200✔
2080
        continue;
×
2081
      }
2082

2083
      char* data = colDataGetData(pCol, i);
13,984,200✔
2084
      numOfElems += 1;
13,984,200✔
2085
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
13,984,200✔
2086
      if (code != TSDB_CODE_SUCCESS) {
13,984,200✔
2087
        tMemBucketDestroy(&(pInfo->pMemBucket));
414✔
2088
        return code;
414✔
2089
      }
2090
    }
2091

2092
    SET_VAL(pResInfo, numOfElems, 1);
752,468✔
2093
  }
2094

2095
  pCtx->needCleanup = true;
1,554,234✔
2096
  return TSDB_CODE_SUCCESS;
1,554,234✔
2097
}
2098

2099
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
316,258✔
2100
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
316,258✔
2101
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
316,258✔
2102

2103
  int32_t code = 0;
316,258✔
2104
  double  v = 0;
316,258✔
2105

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

2114
      varDataVal(buf)[0] = '[';
2,484✔
2115
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
27,324✔
2116
        SVariant* pVal = &pCtx->param[i].param;
24,840✔
2117

2118
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[i].pCol));
24,840✔
2119

2120
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
24,840✔
2121
        if (code != TSDB_CODE_SUCCESS) {
24,840✔
2122
          goto _fin_error;
×
2123
        }
2124

2125
        if (i == pCtx->numOfParams - 1) {
24,840✔
2126
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
2,484✔
2127
        } else {
2128
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
22,356✔
2129
        }
2130
      }
2131

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

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

2145
      tMemBucketDestroy(pMemBucket);
2,484✔
2146
      return TSDB_CODE_SUCCESS;
2,484✔
2147
    } else {
2148
      SVariant* pVal = &pCtx->param[1].param;
264,890✔
2149

2150
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
264,890✔
2151

2152
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
264,890✔
2153
      if (code != TSDB_CODE_SUCCESS) {
264,890✔
2154
        goto _fin_error;
×
2155
      }
2156

2157
      tMemBucketDestroy(pMemBucket);
264,890✔
2158
      return functionFinalize(pCtx, pBlock);
264,890✔
2159
    }
2160
  } else {
2161
    return functionFinalize(pCtx, pBlock);
48,884✔
2162
  }
2163

2164
_fin_error:
×
2165

2166
  tMemBucketDestroy(pMemBucket);
×
2167
  return code;
×
2168
}
2169

2170
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
2,985,313✔
2171
  int32_t bytesHist =
2,985,313✔
2172
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2173
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
2,985,313✔
2174
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
2,985,313✔
2175
  return true;
2,988,209✔
2176
}
2177

2178
int32_t getApercentileMaxSize() {
149,485✔
2179
  int32_t bytesHist =
149,485✔
2180
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
2181
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
149,485✔
2182
  return TMAX(bytesHist, bytesDigest);
149,485✔
2183
}
2184

2185
static int8_t getApercentileAlgo(char* algoStr) {
2,704,005✔
2186
  int8_t algoType;
2187
  if (strcasecmp(algoStr, "default") == 0) {
2,704,005✔
2188
    algoType = APERCT_ALGO_DEFAULT;
1,350,287✔
2189
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
1,353,718✔
2190
    algoType = APERCT_ALGO_TDIGEST;
1,353,718✔
2191
  } else {
2192
    algoType = APERCT_ALGO_UNKNOWN;
×
2193
  }
2194

2195
  return algoType;
2,704,005✔
2196
}
2197

2198
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
113,423,155✔
2199
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
113,423,155✔
2200
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
113,424,572✔
2201
}
113,425,519✔
2202

2203
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
2,719,144✔
2204
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
2,719,144✔
2205
}
2,719,144✔
2206

2207
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
39,524,233✔
2208
  if (pResultInfo->initialized) {
39,524,233✔
2209
    return TSDB_CODE_SUCCESS;
×
2210
  }
2211
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
39,524,714✔
2212
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2213
  }
2214

2215
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
39,524,782✔
2216

2217
  SVariant* pVal = &pCtx->param[1].param;
39,524,782✔
2218
  pInfo->percent = 0;
39,525,663✔
2219
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i, typeGetTypeModFromCol(pCtx->param[1].pCol));
39,525,663✔
2220

2221
  if (pCtx->numOfParams == 2) {
39,525,182✔
2222
    pInfo->algo = APERCT_ALGO_DEFAULT;
36,820,283✔
2223
  } else if (pCtx->numOfParams == 3) {
2,703,522✔
2224
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
2,704,005✔
2225
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
2,704,005✔
2226
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2227
    }
2228
  }
2229

2230
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
39,524,288✔
2231
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
39,523,765✔
2232
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
1,353,718✔
2233
  } else {
2234
    buildHistogramInfo(pInfo);
38,170,047✔
2235
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
38,171,532✔
2236
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
38,171,532✔
2237
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2238
  }
2239

2240
  return TSDB_CODE_SUCCESS;
39,525,663✔
2241
}
2242

2243
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
39,845,974✔
2244
  int32_t               numOfElems = 0;
39,845,974✔
2245
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
39,845,974✔
2246
  SInputColumnInfoData* pInput = &pCtx->input;
39,845,974✔
2247

2248
  SColumnInfoData* pCol = pInput->pData[0];
39,845,974✔
2249
  int32_t          type = pCol->info.type;
39,845,974✔
2250

2251
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
39,845,974✔
2252

2253
  int32_t start = pInput->startRowIndex;
39,845,974✔
2254
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
39,845,012✔
2255
    buildTDigestInfo(pInfo);
1,353,300✔
2256
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,353,300✔
2257
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
70,537,214✔
2258
      if (colDataIsNull_f(pCol, i)) {
69,186,319✔
2259
        continue;
1,438✔
2260
      }
2261
      numOfElems += 1;
69,184,881✔
2262
      char* data = colDataGetData(pCol, i);
69,184,881✔
2263

2264
      double  v = 0;  // value
69,181,031✔
2265
      int64_t w = 1;  // weigth
69,181,031✔
2266
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
69,181,031✔
2267
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
69,181,993✔
2268
      if (code != TSDB_CODE_SUCCESS) {
69,183,438✔
2269
        return code;
×
2270
      }
2271
    }
2272
  } else {
2273
    // might be a race condition here that pHisto can be overwritten or setup function
2274
    // has not been called, need to relink the buffer pHisto points to.
2275
    buildHistogramInfo(pInfo);
38,492,674✔
2276
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
38,492,674✔
2277
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2278
           pInfo->pHisto->elems);
2279
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
321,742,480✔
2280
      if (colDataIsNull_f(pCol, i)) {
283,250,757✔
2281
        continue;
48,431,615✔
2282
      }
2283
      numOfElems += 1;
234,829,794✔
2284
      char* data = colDataGetData(pCol, i);
234,829,794✔
2285

2286
      double v = 0;
234,838,511✔
2287
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
234,838,511✔
2288
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
234,835,621✔
2289
      if (code != TSDB_CODE_SUCCESS) {
234,818,191✔
2290
        return code;
×
2291
      }
2292
    }
2293

2294
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
38,492,674✔
2295
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2296
           pInfo->pHisto->elems);
2297
  }
2298

2299
  SET_VAL(pResInfo, numOfElems, 1);
39,845,974✔
2300
  return TSDB_CODE_SUCCESS;
39,845,974✔
2301
}
2302

2303
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
81,048✔
2304
  pOutput->percent = pInput->percent;
81,048✔
2305
  pOutput->algo = pInput->algo;
81,048✔
2306
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
81,048✔
2307
    buildTDigestInfo(pInput);
12,958✔
2308
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
12,958✔
2309

2310
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
12,958✔
2311
      return TSDB_CODE_SUCCESS;
418✔
2312
    }
2313

2314
    if (hasRes) {
12,540✔
2315
      *hasRes = true;
12,540✔
2316
    }
2317

2318
    buildTDigestInfo(pOutput);
12,540✔
2319
    TDigest* pTDigest = pOutput->pTDigest;
12,540✔
2320
    tdigestAutoFill(pTDigest, COMPRESSION);
12,540✔
2321

2322
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
12,540✔
2323
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
12,540✔
2324
      tdigestAutoFill(pTDigest, COMPRESSION);
12,540✔
2325
    } else {
2326
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
×
2327
      if (TSDB_CODE_SUCCESS != code) {
×
2328
        return code;
×
2329
      }
2330
    }
2331
  } else {
2332
    buildHistogramInfo(pInput);
68,090✔
2333
    if (pInput->pHisto->numOfElems <= 0) {
68,090✔
2334
      return TSDB_CODE_SUCCESS;
4,158✔
2335
    }
2336

2337
    if (hasRes) {
63,932✔
2338
      *hasRes = true;
63,932✔
2339
    }
2340

2341
    buildHistogramInfo(pOutput);
63,932✔
2342
    SHistogramInfo* pHisto = pOutput->pHisto;
63,932✔
2343

2344
    if (pHisto->numOfElems <= 0) {
63,932✔
2345
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
52,697✔
2346
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
52,697✔
2347

2348
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
52,697✔
2349
             pHisto);
2350
    } else {
2351
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
11,235✔
2352
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
11,235✔
2353
             pHisto->numOfEntries, pInput->pHisto);
2354

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

2364
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
11,235✔
2365
             pHisto);
2366
      tHistogramDestroy(&pRes);
11,235✔
2367
    }
2368
  }
2369
  return TSDB_CODE_SUCCESS;
76,472✔
2370
}
2371

2372
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
79,104✔
2373
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
79,104✔
2374

2375
  SInputColumnInfoData* pInput = &pCtx->input;
79,104✔
2376

2377
  SColumnInfoData* pCol = pInput->pData[0];
79,104✔
2378
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
79,104✔
2379
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2380
  }
2381

2382
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
79,104✔
2383

2384
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
79,104✔
2385

2386
  bool    hasRes = false;
79,104✔
2387
  int32_t start = pInput->startRowIndex;
79,104✔
2388
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
160,152✔
2389
    char* data = colDataGetData(pCol, i);
81,048✔
2390

2391
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
81,048✔
2392
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
81,048✔
2393
    if (TSDB_CODE_SUCCESS != code) {
81,048✔
2394
      return code;
×
2395
    }
2396
  }
2397

2398
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
79,104✔
2399
    buildHistogramInfo(pInfo);
66,146✔
2400
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
66,146✔
2401
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2402
  }
2403

2404
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
79,104✔
2405
  return TSDB_CODE_SUCCESS;
79,104✔
2406
}
2407

2408
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
37,904,029✔
2409
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
37,904,029✔
2410
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
37,904,029✔
2411

2412
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
37,904,029✔
2413
    buildTDigestInfo(pInfo);
1,340,346✔
2414
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
1,340,346✔
2415
    if (pInfo->pTDigest->size > 0) {
1,340,346✔
2416
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
1,340,346✔
2417
    } else {  // no need to free
2418
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2419
      return TSDB_CODE_SUCCESS;
×
2420
    }
2421
  } else {
2422
    buildHistogramInfo(pInfo);
36,563,683✔
2423
    if (pInfo->pHisto->numOfElems > 0) {
36,563,683✔
2424
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
27,793,842✔
2425
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2426

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

2445
  return functionFinalize(pCtx, pBlock);
37,904,029✔
2446
}
2447

2448
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
81,048✔
2449
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
81,048✔
2450
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
81,048✔
2451

2452
  int32_t resultBytes = getApercentileMaxSize();
81,048✔
2453
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
81,048✔
2454
  if (NULL == res) {
81,048✔
2455
    return terrno;
×
2456
  }
2457

2458
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
81,048✔
2459
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
12,958✔
2460
    varDataSetLen(res, resultBytes);
12,958✔
2461
  } else {
2462
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
68,090✔
2463
    varDataSetLen(res, resultBytes);
68,090✔
2464
  }
2465

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

2473
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
81,048✔
2474

2475
  taosMemoryFree(res);
81,048✔
2476
  return code;
81,048✔
2477
}
2478

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

2483
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
2484
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
2485

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

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

2497
// TODO: change this function when block data info pks changed
2498
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
257,403✔
2499
  char numVal[8] = {0};
257,403✔
2500
  switch (pkType) {
257,403✔
2501
    case TSDB_DATA_TYPE_INT:
42,261✔
2502
      *(int32_t*)numVal = (int32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
42,261✔
2503
      break;
42,261✔
2504
    case TSDB_DATA_TYPE_UINT:
44,626✔
2505
      *(uint32_t*)numVal = (uint32_t)VALUE_GET_TRIVIAL_DATUM(pVal);
44,626✔
2506
      break;
45,220✔
2507
    case TSDB_DATA_TYPE_BIGINT:
55,912✔
2508
      *(int64_t*)numVal = (int64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
55,912✔
2509
      break;
55,912✔
2510
    case TSDB_DATA_TYPE_UBIGINT:
56,506✔
2511
      *(uint64_t*)numVal = (uint64_t)VALUE_GET_TRIVIAL_DATUM(pVal);
56,506✔
2512
      break;
55,912✔
2513
    default:
58,098✔
2514
      break;
58,098✔
2515
  }
2516
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
257,403✔
2517
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
257,403✔
2518
  return fn(pkData, blockData);
256,809✔
2519
}
2520

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

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

2529
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
2,147,483,647✔
2530
  if (pResult->hasResult) {
2,147,483,647✔
2531
    if (pResult->pkBytes > 0) {
2,147,483,647✔
2532
      pResult->pkData = pResult->buf + pResult->bytes;
772,314✔
2533
    } else {
2534
      pResult->pkData = NULL;
2,147,483,647✔
2535
    }
2536
    if (pResult->ts < pBlockInfo->window.skey) {
2,147,483,647✔
2537
      return FUNC_DATA_REQUIRED_NOT_LOAD;
761,872✔
2538
    } else if (pResult->ts == pBlockInfo->window.skey) {
2,147,483,647✔
2539
      if (NULL == pResult->pkData) {
2,147,483,647✔
2540
        return FUNC_DATA_REQUIRED_NOT_LOAD;
2,147,483,647✔
2541
      }
2542
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
186,270✔
2543
        return FUNC_DATA_REQUIRED_NOT_LOAD;
15,678✔
2544
      }
2545
    }
2546
    return FUNC_DATA_REQUIRED_DATA_LOAD;
288,822✔
2547
  } else {
2548
    return FUNC_DATA_REQUIRED_DATA_LOAD;
12,616✔
2549
  }
2550
}
2551

2552
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
16,825,891✔
2553
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
16,825,891✔
2554

2555
  // not initialized yet, data is required
2556
  if (pEntry == NULL) {
16,825,891✔
2557
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2558
  }
2559

2560
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
16,825,891✔
2561
  if (pResult->hasResult) {
16,913,167✔
2562
    if (pResult->pkBytes > 0) {
16,931,208✔
2563
      pResult->pkData = pResult->buf + pResult->bytes;
420,711✔
2564
    } else {
2565
      pResult->pkData = NULL;
16,510,507✔
2566
    }
2567
    if (pResult->ts > pBlockInfo->window.ekey) {
16,931,220✔
2568
      return FUNC_DATA_REQUIRED_NOT_LOAD;
752,783✔
2569
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
16,178,819✔
2570
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
71,133✔
2571
        return FUNC_DATA_REQUIRED_NOT_LOAD;
9,352✔
2572
      }
2573
    }
2574
    return FUNC_DATA_REQUIRED_DATA_LOAD;
16,093,281✔
2575
  } else {
2576
    return FUNC_DATA_REQUIRED_DATA_LOAD;
5,167✔
2577
  }
2578
}
2579

2580
// TODO modify it to include primary key bytes
2581
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
1,563,952,178✔
2582

2583
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
39,096,429✔
2584
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
39,096,429✔
2585
  // TODO: change SFunctionNode to add pk info
2586
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
39,097,947✔
2587
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
39,095,025✔
2588
  return true;
39,095,275✔
2589
}
2590

2591
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
10,819,437✔
2592
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
10,819,437✔
2593
  pEnv->calcMemSize = pNode->node.resType.bytes;
10,819,415✔
2594
  return true;
10,819,075✔
2595
}
2596

2597
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
42,617,157✔
2598
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
42,617,157✔
2599
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
42,632,772✔
2600
  return true;
42,619,683✔
2601
}
2602

2603
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2604
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
2,147,483,647✔
2605
    return 0;
×
2606
  }
2607

2608
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
2,147,483,647✔
2609
}
2610

2611
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
284,089,685✔
2612
  if (pResInfo->initialized) {
284,089,685✔
2613
    return TSDB_CODE_SUCCESS;
×
2614
  }
2615
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
284,090,598✔
2616
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2617
  }
2618

2619
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
284,089,985✔
2620
  pRes->nullTupleSaved = false;
284,087,908✔
2621
  pRes->nullTuplePos.pageId = -1;
284,090,016✔
2622
  return TSDB_CODE_SUCCESS;
284,086,369✔
2623
}
2624

2625
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
43,764,109✔
2626
  if (pCtx->subsidiaries.rowLen == 0) {
43,764,109✔
2627
    int32_t rowLen = 0;
4,099,988✔
2628
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
9,375,517✔
2629
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
5,277,288✔
2630
      rowLen += pc->pExpr->base.resSchema.bytes;
5,277,482✔
2631
    }
2632

2633
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
4,096,425✔
2634
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
4,096,494✔
2635
    if (NULL == pCtx->subsidiaries.buf) {
4,099,162✔
2636
      return terrno;
×
2637
    }
2638
  }
2639
  return TSDB_CODE_SUCCESS;
43,759,876✔
2640
}
2641

2642
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
2,147,483,647✔
2643
                                      SFirstLastRes* pInfo, bool noElements) {
2644
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
2645

2646
  if (pCtx->subsidiaries.num <= 0) {
2,147,483,647✔
2647
    return TSDB_CODE_SUCCESS;
2,147,483,647✔
2648
  }
2649

2650
  if (!pInfo->hasResult) {
11,449,087✔
2651
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
8,182,126✔
2652
  } else if (!noElements) {
3,266,984✔
2653
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
3,254,333✔
2654
  } else {
2655
  }  // dothing
2656

2657
  return code;
11,448,897✔
2658
}
2659

2660
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
2,147,483,647✔
2661
                                char* pData) {
2662
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2663
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2664

2665
  if (IS_VAR_DATA_TYPE(type)) {
2,147,483,647✔
2666
    pInfo->bytes = calcStrBytesByType(type, pData);
300,740,031✔
2667
    // if (type == TSDB_DATA_TYPE_JSON) {
2668
    //   pInfo->bytes = getJsonValueLen(pData);
2669
    // } else {
2670
    //   pInfo->bytes = varDataTLen(pData);
2671
    // }
2672
  }
2673

2674
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
2,147,483,647✔
2675
  if (pkData != NULL) {
2,147,483,647✔
2676
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
164,625,901✔
2677
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
54,841,702✔
2678
      // if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
2679
      //   pInfo->pkBytes = getJsonValueLen(pkData);
2680
      // } else {
2681
      //   pInfo->pkBytes = varDataTLen(pkData);
2682
      // }
2683
    }
2684
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
164,649,157✔
2685
    pInfo->pkData = pInfo->buf + pInfo->bytes;
164,656,932✔
2686
  }
2687

2688
  pInfo->ts = currentTs;
2,147,483,647✔
2689
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
2,147,483,647✔
2690
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
2691
    return code;
×
2692
  }
2693

2694
  pInfo->hasResult = true;
2,147,483,647✔
2695
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2696
}
2697

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

2703
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2704
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2705

2706
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2707
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2708

2709
  pInfo->bytes = pInputCol->info.bytes;
2,147,483,647✔
2710

2711
  if (IS_NULL_TYPE(pInputCol->info.type)) {
2,147,483,647✔
2712
    return TSDB_CODE_SUCCESS;
585,808✔
2713
  }
2714

2715
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2716
  pInfo->pkType = -1;
2,147,483,647✔
2717
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2718
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2719
    pInfo->pkType = pkCol->info.type;
44,657,954✔
2720
    pInfo->pkBytes = pkCol->info.bytes;
44,658,548✔
2721
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
44,647,435✔
2722
  }
2723

2724
  // All null data column, return directly.
2725
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
2,147,483,647✔
2726
      pInputCol->hasNull == true) {
×
2727
    // save selectivity value for column consisted of all null values
2728
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2729
    if (code != TSDB_CODE_SUCCESS) {
×
2730
      return code;
×
2731
    }
2732
    pInfo->nullTupleSaved = true;
×
2733
    return TSDB_CODE_SUCCESS;
×
2734
  }
2735

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

2738
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2739
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2740

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

2743
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
2744
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2745
#if 0
2746
  if (blockDataOrder == TSDB_ORDER_ASC) {
2747
    // filter according to current result firstly
2748
    if (pResInfo->numOfRes > 0) {
2749
      if (pInfo->ts < startKey) {
2750
        return TSDB_CODE_SUCCESS;
2751
      }
2752
    }
2753

2754
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2755
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2756
        continue;
2757
      }
2758

2759
      numOfElems++;
2760

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

2777
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2778
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2779
        continue;
2780
      }
2781

2782
      numOfElems++;
2783

2784
      char* data = colDataGetData(pInputCol, i);
2785
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2786

2787
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2788
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2789
        break;
2790
      }
2791
    }
2792
  }
2793
#else
2794
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2795

2796
  int     from = -1;
2,147,483,647✔
2797
  int32_t i = -1;
2,147,483,647✔
2798
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
2,147,483,647✔
2799
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2,147,483,647✔
2800
      continue;
26,556,082✔
2801
    }
2802

2803
    numOfElems++;
2,147,483,647✔
2804
    char* data = colDataGetData(pInputCol, i);
2,147,483,647✔
2805
    char* pkData = NULL;
2,147,483,647✔
2806
    if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2807
      pkData = colDataGetData(pkCol, i);
159,145,042✔
2808
    }
2809
    TSKEY cts = pts[i];
2,147,483,647✔
2810
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
2,147,483,647✔
2811
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
1,721,421,247✔
2812
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
1,697,819,382✔
2813
      if (code != TSDB_CODE_SUCCESS) {
1,694,871,249✔
2814
        return code;
×
2815
      }
2816
      pResInfo->numOfRes = 1;
1,694,871,249✔
2817
    }
2818
  }
2819
#endif
2820

2821
  if (numOfElems == 0) {
2,147,483,647✔
2822
    // save selectivity value for column consisted of all null values
2823
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
5,629,125✔
2824
    if (code != TSDB_CODE_SUCCESS) {
5,623,293✔
2825
      return code;
×
2826
    }
2827
    pInfo->nullTupleSaved = true;
5,623,293✔
2828
  }
2829
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
2830
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
2831
}
2832

2833
int32_t lastFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
2834
  int32_t numOfElems = 0;
2,147,483,647✔
2835

2836
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
2837
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
2838

2839
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
2840
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
2841

2842
  int32_t type = pInputCol->info.type;
2,147,483,647✔
2843
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
2844

2845
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
2846
    return TSDB_CODE_SUCCESS;
557,010✔
2847
  }
2848
  pInfo->bytes = bytes;
2,147,483,647✔
2849

2850
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
2851
  pInfo->pkType = -1;
2,147,483,647✔
2852
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
2853
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
2854
    pInfo->pkType = pkCol->info.type;
44,768,370✔
2855
    pInfo->pkBytes = pkCol->info.bytes;
44,775,385✔
2856
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
44,775,354✔
2857
  }
2858

2859
  // All null data column, return directly.
2860
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
2,147,483,647✔
2861
      pInputCol->hasNull == true) {
×
2862
    // save selectivity value for column consisted of all null values
2863
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2864
    if (code != TSDB_CODE_SUCCESS) {
×
2865
      return code;
×
2866
    }
2867
    pInfo->nullTupleSaved = true;
×
2868
    return TSDB_CODE_SUCCESS;
×
2869
  }
2870

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

2873
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
2874
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
2875

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

2878
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2879
#if 0
2880
  if (blockDataOrder == TSDB_ORDER_ASC) {
2881
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2882
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2883
        continue;
2884
      }
2885

2886
      numOfElems++;
2887

2888
      char* data = colDataGetData(pInputCol, i);
2889
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2890
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2891
        doSaveCurrentVal(pCtx, i, cts, type, data);
2892
      }
2893

2894
      break;
2895
    }
2896
  } else {  // descending order
2897
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2898
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2899
        continue;
2900
      }
2901

2902
      numOfElems++;
2903

2904
      char* data = colDataGetData(pInputCol, i);
2905
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2906
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2907
        doSaveCurrentVal(pCtx, i, cts, type, data);
2908
      }
2909
      break;
2910
    }
2911
  }
2912
#else
2913
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
2,147,483,647✔
2914

2915
#if 0
2916
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2917
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2918
        continue;
2919
      }
2920

2921
      numOfElems++;
2922
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2923
        char* data = colDataGetData(pInputCol, i);
2924
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2925
        pResInfo->numOfRes = 1;
2926
      }
2927
    }
2928
#else
2929

2930
  // todo refactor
2931
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
2,147,483,647✔
2932
    numOfElems = 1;
2,147,483,647✔
2933

2934
    int32_t round = pInput->numOfRows >> 2;
2,147,483,647✔
2935
    int32_t reminder = pInput->numOfRows & 0x03;
2,147,483,647✔
2936

2937
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
2,147,483,647✔
2938
      int64_t cts = pts[i];
191,330,106✔
2939
      int32_t chosen = i;
191,331,274✔
2940

2941
      if (cts < pts[i + 1]) {
191,331,274✔
2942
        cts = pts[i + 1];
26,852,027✔
2943
        chosen = i + 1;
26,850,794✔
2944
      }
2945

2946
      if (cts < pts[i + 2]) {
191,328,756✔
2947
        cts = pts[i + 2];
26,851,827✔
2948
        chosen = i + 2;
26,851,827✔
2949
      }
2950

2951
      if (cts < pts[i + 3]) {
191,331,387✔
2952
        cts = pts[i + 3];
26,850,441✔
2953
        chosen = i + 3;
26,849,619✔
2954
      }
2955

2956
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
191,328,579✔
2957
        char*   data = colDataGetData(pInputCol, chosen);
50,038,538✔
2958
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
50,038,342✔
2959
        if (code != TSDB_CODE_SUCCESS) {
50,035,735✔
2960
          return code;
×
2961
        }
2962
        pResInfo->numOfRes = 1;
50,035,735✔
2963
      }
2964
    }
2965

2966
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,147,483,647✔
2967
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2,147,483,647✔
2968
        char*   data = colDataGetData(pInputCol, i);
333,867,412✔
2969
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
331,095,762✔
2970
        if (code != TSDB_CODE_SUCCESS) {
330,523,190✔
2971
          return code;
×
2972
        }
2973
        pResInfo->numOfRes = 1;
330,523,190✔
2974
      }
2975
    }
2976
  } else {
2977
    int     from = -1;
540,958,529✔
2978
    int32_t i = -1;
538,682,150✔
2979
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
1,506,590,535✔
2980
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
1,933,257,057✔
2981
        continue;
512,567,324✔
2982
      }
2983

2984
      numOfElems++;
454,870,319✔
2985
      char* pkData = NULL;
454,870,319✔
2986
      if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, i)) {
614,238,499✔
2987
        // pkCol[i] might be null when using cachemodel
2988
        // however, if using cachemodel, we don't need pk to determine the order
2989
        // because ts is enough
2990
        pkData = colDataGetData(pkCol, i);
159,353,285✔
2991
      }
2992
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
454,864,948✔
2993
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
321,941,411✔
2994
        char*   data = colDataGetData(pInputCol, i);
132,952,726✔
2995
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
132,935,451✔
2996
        if (code != TSDB_CODE_SUCCESS) {
132,942,667✔
2997
          return code;
×
2998
        }
2999
        pResInfo->numOfRes = 1;
132,942,667✔
3000
      }
3001
    }
3002
  }
3003
#endif
3004

3005
#endif
3006

3007
  // save selectivity value for column consisted of all null values
3008
  if (numOfElems == 0) {
2,147,483,647✔
3009
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
351,709,334✔
3010
    if (code != TSDB_CODE_SUCCESS) {
351,188,114✔
3011
      return code;
×
3012
    }
3013
    pInfo->nullTupleSaved = true;
351,188,114✔
3014
  }
3015

3016
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3017
}
3018

3019
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
1,231,578,572✔
3020
  if (!pInput->hasResult) {
1,231,578,572✔
3021
    return false;
×
3022
  }
3023
  __compar_fn_t pkCompareFn = NULL;
1,231,578,572✔
3024
  if (pInput->pkData) {
1,231,578,572✔
3025
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
3,514,999✔
3026
  }
3027
  if (pOutput->hasResult) {
1,231,578,572✔
3028
    if (isFirst) {
675,562,903✔
3029
      if (pInput->ts > pOutput->ts ||
593,237,170✔
3030
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
593,149,841✔
3031
        return false;
229,889✔
3032
      }
3033
    } else {
3034
      if (pInput->ts < pOutput->ts ||
82,325,733✔
3035
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
80,923,621✔
3036
        return false;
1,580,312✔
3037
      }
3038
    }
3039
  }
3040

3041
  pOutput->isNull = pInput->isNull;
1,229,768,371✔
3042
  pOutput->ts = pInput->ts;
1,229,768,371✔
3043
  pOutput->bytes = pInput->bytes;
1,229,768,369✔
3044
  pOutput->pkType = pInput->pkType;
1,229,768,371✔
3045

3046
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
1,229,768,369✔
3047
  if (pInput->pkData) {
1,229,768,371✔
3048
    pOutput->pkBytes = pInput->pkBytes;
3,097,385✔
3049
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
3,097,385✔
3050
    pOutput->pkData = pOutput->buf + pOutput->bytes;
3,097,385✔
3051
  }
3052
  return true;
1,229,768,371✔
3053
}
3054

3055
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
1,231,578,572✔
3056
                                     int32_t rowIndex) {
3057
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
1,231,578,572✔
3058
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
1,229,768,371✔
3059
    if (TSDB_CODE_SUCCESS != code) {
1,229,768,369✔
3060
      return code;
×
3061
    }
3062
    pOutput->hasResult = true;
1,229,768,369✔
3063
  }
3064
  return TSDB_CODE_SUCCESS;
1,231,578,570✔
3065
}
3066

3067
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
561,915,838✔
3068
  SInputColumnInfoData* pInput = &pCtx->input;
561,915,838✔
3069
  SColumnInfoData*      pCol = pInput->pData[0];
561,915,838✔
3070

3071
  if (IS_NULL_TYPE(pCol->info.type)) {
561,915,838✔
3072
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
3073
    return TSDB_CODE_SUCCESS;
×
3074
  }
3075

3076
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
561,915,838✔
3077
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3078
  }
3079

3080
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
561,915,838✔
3081

3082
  int32_t start = pInput->startRowIndex;
561,915,838✔
3083
  int32_t numOfElems = 0;
561,915,838✔
3084

3085
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
1,988,421,757✔
3086
    if (colDataIsNull_s(pCol, i)) {
2,147,483,647✔
3087
      continue;
194,927,349✔
3088
    }
3089
    char*          data = colDataGetData(pCol, i);
1,231,578,572✔
3090
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
1,231,578,572✔
3091
    if (pCtx->hasPrimaryKey) {
1,231,578,572✔
3092
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
3,514,999✔
3093
    } else {
3094
      pInputInfo->pkData = NULL;
1,228,063,573✔
3095
    }
3096

3097
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
1,231,578,570✔
3098
    if (code != TSDB_CODE_SUCCESS) {
1,231,578,570✔
3099
      return code;
×
3100
    }
3101
    if (!numOfElems) {
1,231,578,570✔
3102
      numOfElems = pInputInfo->hasResult ? 1 : 0;
560,893,207✔
3103
    }
3104
  }
3105

3106
  if (numOfElems == 0) {
561,915,836✔
3107
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
1,022,629✔
3108
    if (code != TSDB_CODE_SUCCESS) {
1,022,629✔
3109
      return code;
×
3110
    }
3111
    pInfo->nullTupleSaved = true;
1,022,629✔
3112
  }
3113

3114
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
561,915,838✔
3115
  return TSDB_CODE_SUCCESS;
561,915,838✔
3116
}
3117

3118
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
334,413,569✔
3119

3120
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
227,502,269✔
3121

3122
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
825,368,566✔
3123
  int32_t          code = TSDB_CODE_SUCCESS;
825,368,566✔
3124
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
825,368,566✔
3125
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
825,368,562✔
3126
  if (NULL == pCol) {
825,361,914✔
3127
    return TSDB_CODE_OUT_OF_RANGE;
×
3128
  }
3129

3130
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
825,361,914✔
3131
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
825,361,930✔
3132

3133
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
825,362,836✔
3134

3135
  if (pResInfo->isNullRes) {
825,362,106✔
3136
    colDataSetNULL(pCol, pBlock->info.rows);
2,376,805✔
3137
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,376,805✔
3138
  }
3139
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
822,984,551✔
3140
  if (TSDB_CODE_SUCCESS != code) {
822,990,701✔
3141
    return code;
×
3142
  }
3143

3144
  // handle selectivity
3145
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
822,990,701✔
3146
  if (TSDB_CODE_SUCCESS != code) {
822,988,493✔
3147
    qError("%s failed at %d, msg:%s", __func__, __LINE__, tstrerror(code));
×
3148
  }
3149

3150
  return code;
822,987,179✔
3151
}
3152

3153
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,515,816,383✔
3154
  int32_t code = TSDB_CODE_SUCCESS;
1,515,816,383✔
3155

3156
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,515,816,383✔
3157
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
1,518,085,588✔
3158

3159
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
1,518,108,667✔
3160

3161
  // todo check for failure
3162
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,517,806,428✔
3163
  if (NULL == res) {
1,514,080,784✔
3164
    return terrno;
×
3165
  }
3166
  (void)memcpy(varDataVal(res), pRes, resultBytes);
1,514,080,784✔
3167

3168
  varDataSetLen(res, resultBytes);
1,514,037,556✔
3169

3170
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,517,652,145✔
3171
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,517,556,907✔
3172
  if (NULL == pCol) {
1,517,330,309✔
3173
    taosMemoryFree(res);
×
3174
    return TSDB_CODE_OUT_OF_RANGE;
×
3175
  }
3176

3177
  if (pEntryInfo->numOfRes == 0) {
1,517,330,309✔
3178
    colDataSetNULL(pCol, pBlock->info.rows);
203,923,069✔
3179
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
203,937,009✔
3180
  } else {
3181
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,313,661,808✔
3182
    if (TSDB_CODE_SUCCESS != code) {
1,314,023,701✔
3183
      taosMemoryFree(res);
×
3184
      return code;
×
3185
    }
3186
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
1,314,023,701✔
3187
  }
3188
  taosMemoryFree(res);
1,517,684,266✔
3189
  return code;
1,517,777,416✔
3190
}
3191

3192
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
3193
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
3194
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
3195
  int32_t              bytes = pDBuf->bytes;
×
3196

3197
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
3198
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
3199

3200
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
×
3201
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
3202
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
3203
  return TSDB_CODE_SUCCESS;
×
3204
}
3205

3206
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
16,933,130✔
3207
  SInputColumnInfoData* pInput = &pCtx->input;
16,933,130✔
3208
  SColumnInfoData*      pInputCol = pInput->pData[0];
16,936,350✔
3209
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
16,940,261✔
3210

3211
  if (colDataIsNull_s(pInputCol, rowIndex)) {
33,878,833✔
3212
    pInfo->isNull = true;
505,370✔
3213
  } else {
3214
    pInfo->isNull = false;
16,433,747✔
3215

3216
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
16,436,759✔
3217
      pInfo->bytes = calcStrBytesByType(pInputCol->info.type, pData);
2,770,770✔
3218
      // if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
3219
      //   pInfo->bytes = getJsonValueLen(pData);
3220
      // } else {
3221
      //   pInfo->bytes = varDataTLen(pData);
3222
      // }
3223
    }
3224

3225
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
16,431,936✔
3226
  }
3227

3228
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
25,470,265✔
3229
    char* pkData = colDataGetData(pkCol, rowIndex);
8,537,816✔
3230
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
8,538,961✔
3231
      pInfo->pkBytes = calcStrBytesByType(pInfo->pkType, pkData);
2,847,067✔
3232
    }
3233
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
8,541,308✔
3234
    pInfo->pkData = pInfo->buf + pInfo->bytes;
8,536,597✔
3235
  }
3236
  pInfo->ts = cts;
16,932,899✔
3237
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
16,934,926✔
3238
  if (code != TSDB_CODE_SUCCESS) {
16,935,850✔
3239
    return code;
×
3240
  }
3241

3242
  pInfo->hasResult = true;
16,935,850✔
3243

3244
  return TSDB_CODE_SUCCESS;
16,936,638✔
3245
}
3246

3247
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
3248
  int32_t numOfElems = 0;
2,147,483,647✔
3249

3250
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3251
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3252

3253
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3254
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3255

3256
  int32_t type = pInputCol->info.type;
2,147,483,647✔
3257
  int32_t bytes = pInputCol->info.bytes;
2,147,483,647✔
3258
  pInfo->bytes = bytes;
2,147,483,647✔
3259

3260
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
3261
    return TSDB_CODE_SUCCESS;
20,074✔
3262
  }
3263
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
2,147,483,647✔
3264
  pInfo->pkType = -1;
2,147,483,647✔
3265
  __compar_fn_t pkCompareFn = NULL;
2,147,483,647✔
3266
  if (pCtx->hasPrimaryKey) {
2,147,483,647✔
3267
    pInfo->pkType = pkCol->info.type;
44,118,021✔
3268
    pInfo->pkBytes = pkCol->info.bytes;
44,115,037✔
3269
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
44,130,837✔
3270
  }
3271
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
2,147,483,647✔
3272
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
2,147,483,647✔
3273

3274
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3275
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
18,206,254✔
3276
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
9,106,409✔
3277
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
9,100,979✔
3278
      TSKEY cts = getRowPTs(pInput->pPTS, i);
9,099,881✔
3279
      numOfElems++;
9,101,381✔
3280

3281
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
9,101,381✔
3282
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
2,309,939✔
3283
        if (code != TSDB_CODE_SUCCESS) return code;
2,309,993✔
3284
      }
3285

3286
      break;
9,100,229✔
3287
    }
3288
  } else if (pCtx->order == TSDB_ORDER_DESC && !pCtx->hasPrimaryKey) {
2,147,483,647✔
3289
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3290
    // this assumption is NOT always works if project operator exists in downstream.
3291
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2,147,483,647✔
3292
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
2,147,483,647✔
3293
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
2,147,483,647✔
3294
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2,147,483,647✔
3295
      numOfElems++;
2,147,483,647✔
3296

3297
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2,147,483,647✔
3298
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
5,798,442✔
3299
        if (code != TSDB_CODE_SUCCESS) return code;
4,234,212✔
3300
      }
3301
      break;
2,147,483,647✔
3302
    }
3303
  } else {
3304
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
45,211,641✔
3305
    int      from = -1;
44,604,860✔
3306
    int32_t  i = -1;
44,613,590✔
3307
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
206,610,048✔
3308
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
161,998,767✔
3309
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
162,003,528✔
3310
      TSKEY cts = pts[i];
161,994,786✔
3311

3312
      numOfElems++;
162,005,200✔
3313
      char* pkData = NULL;
162,005,200✔
3314
      if (pCtx->hasPrimaryKey) {
162,005,200✔
3315
        pkData = colDataGetData(pkCol, i);
158,302,348✔
3316
      }
3317
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
162,019,175✔
3318
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
152,079,119✔
3319
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
9,931,086✔
3320
        if (code != TSDB_CODE_SUCCESS) {
9,932,207✔
3321
          return code;
×
3322
        }
3323
        pResInfo->numOfRes = 1;
9,932,207✔
3324
      }
3325
    }
3326
  }
3327

3328
  SET_VAL(pResInfo, numOfElems, 1);
2,147,483,647✔
3329
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3330
}
3331

3332
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
481,609✔
3333
  pEnv->calcMemSize = sizeof(SDiffInfo);
481,609✔
3334
  return true;
481,609✔
3335
}
3336

3337
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
42,616,165✔
3338
  if (pResInfo->initialized) {
42,616,165✔
3339
    return TSDB_CODE_SUCCESS;
37,336,807✔
3340
  }
3341
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
5,279,358✔
3342
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3343
  }
3344
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,279,358✔
3345
  pDiffInfo->hasPrev = false;
5,279,358✔
3346
  pDiffInfo->isFirstRow = true;
5,279,358✔
3347
  pDiffInfo->prev.i64 = 0;
5,279,358✔
3348
  pDiffInfo->prevTs = -1;
5,279,358✔
3349
  if (pCtx->numOfParams > 1) {
5,279,358✔
3350
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
5,279,358✔
3351
  } else {
3352
    pDiffInfo->ignoreOption = 0;
×
3353
  }
3354
  return TSDB_CODE_SUCCESS;
5,279,358✔
3355
}
3356

3357
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
5,181,923✔
3358
  switch (type) {
5,181,923✔
3359
    case TSDB_DATA_TYPE_BOOL:
3,519✔
3360
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
3,519✔
3361
      break;
3,519✔
3362
    case TSDB_DATA_TYPE_UTINYINT:
26,384✔
3363
    case TSDB_DATA_TYPE_TINYINT:
3364
      pDiffInfo->prev.i64 = *(int8_t*)pv;
26,384✔
3365
      break;
26,384✔
3366
    case TSDB_DATA_TYPE_UINT:
4,936,109✔
3367
    case TSDB_DATA_TYPE_INT:
3368
      pDiffInfo->prev.i64 = *(int32_t*)pv;
4,936,109✔
3369
      break;
4,936,109✔
3370
    case TSDB_DATA_TYPE_USMALLINT:
38,968✔
3371
    case TSDB_DATA_TYPE_SMALLINT:
3372
      pDiffInfo->prev.i64 = *(int16_t*)pv;
38,968✔
3373
      break;
38,968✔
3374
    case TSDB_DATA_TYPE_TIMESTAMP:
92,904✔
3375
    case TSDB_DATA_TYPE_UBIGINT:
3376
    case TSDB_DATA_TYPE_BIGINT:
3377
      pDiffInfo->prev.i64 = *(int64_t*)pv;
92,904✔
3378
      break;
92,904✔
3379
    case TSDB_DATA_TYPE_FLOAT:
21,885✔
3380
      pDiffInfo->prev.d64 = *(float*)pv;
21,885✔
3381
      break;
21,885✔
3382
    case TSDB_DATA_TYPE_DOUBLE:
62,154✔
3383
      pDiffInfo->prev.d64 = *(double*)pv;
62,154✔
3384
      break;
62,154✔
3385
    default:
×
3386
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3387
  }
3388
  pDiffInfo->prevTs = ts;
5,181,923✔
3389
  pDiffInfo->hasPrev = true;
5,181,923✔
3390
  return TSDB_CODE_SUCCESS;
5,181,923✔
3391
}
3392

3393
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
2,923,186✔
3394
  switch (type) {
2,923,186✔
3395
    case TSDB_DATA_TYPE_UINT: {
×
3396
      int64_t v = *(uint32_t*)pv;
×
3397
      return v < pDiffInfo->prev.i64;
×
3398
    }
3399
    case TSDB_DATA_TYPE_INT: {
101,492✔
3400
      int64_t v = *(int32_t*)pv;
101,492✔
3401
      return v < pDiffInfo->prev.i64;
101,492✔
3402
    }
3403
    case TSDB_DATA_TYPE_BOOL: {
×
3404
      int64_t v = *(bool*)pv;
×
3405
      return v < pDiffInfo->prev.i64;
×
3406
    }
3407
    case TSDB_DATA_TYPE_UTINYINT: {
×
3408
      int64_t v = *(uint8_t*)pv;
×
3409
      return v < pDiffInfo->prev.i64;
×
3410
    }
3411
    case TSDB_DATA_TYPE_TINYINT: {
33,626✔
3412
      int64_t v = *(int8_t*)pv;
33,626✔
3413
      return v < pDiffInfo->prev.i64;
33,626✔
3414
    }
3415
    case TSDB_DATA_TYPE_USMALLINT: {
×
3416
      int64_t v = *(uint16_t*)pv;
×
3417
      return v < pDiffInfo->prev.i64;
×
3418
    }
3419
    case TSDB_DATA_TYPE_SMALLINT: {
1,310,692✔
3420
      int64_t v = *(int16_t*)pv;
1,310,692✔
3421
      return v < pDiffInfo->prev.i64;
1,310,692✔
3422
    }
3423
    case TSDB_DATA_TYPE_UBIGINT: {
3,128✔
3424
      uint64_t v = *(uint64_t*)pv;
3,128✔
3425
      return v < (uint64_t)pDiffInfo->prev.i64;
3,128✔
3426
    }
3427
    case TSDB_DATA_TYPE_TIMESTAMP:
600,352✔
3428
    case TSDB_DATA_TYPE_BIGINT: {
3429
      int64_t v = *(int64_t*)pv;
600,352✔
3430
      return v < pDiffInfo->prev.i64;
600,352✔
3431
    }
3432
    case TSDB_DATA_TYPE_FLOAT: {
671,438✔
3433
      float v = *(float*)pv;
671,438✔
3434
      return v < pDiffInfo->prev.d64;
671,438✔
3435
    }
3436
    case TSDB_DATA_TYPE_DOUBLE: {
202,458✔
3437
      double v = *(double*)pv;
202,458✔
3438
      return v < pDiffInfo->prev.d64;
202,458✔
3439
    }
3440
    default:
×
3441
      return false;
×
3442
  }
3443

3444
  return false;
3445
}
3446

3447
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
2,147,483,647✔
3448
  bool isNegative = v < pDiffInfo->prev.i64;
2,147,483,647✔
3449
  if (type == TSDB_DATA_TYPE_UBIGINT) {
2,147,483,647✔
3450
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
408,733✔
3451
  }
3452
  int64_t delta = v - pDiffInfo->prev.i64;
2,147,483,647✔
3453
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3454
    colDataSetNull_f_s(pOutput, pos);
995,328✔
3455
    pOutput->hasNull = true;
995,328✔
3456
  } else {
3457
    colDataSetInt64(pOutput, pos, &delta);
2,147,483,647✔
3458
  }
3459
  pDiffInfo->prev.i64 = v;
2,147,483,647✔
3460
}
2,147,483,647✔
3461

3462
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
26,443,879✔
3463
  double delta = v - pDiffInfo->prev.d64;
26,443,879✔
3464
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
26,443,879✔
3465
    colDataSetNull_f_s(pOutput, pos);
425,983✔
3466
  } else {
3467
    colDataSetDouble(pOutput, pos, &delta);
26,017,896✔
3468
  }
3469
  pDiffInfo->prev.d64 = v;
26,443,879✔
3470
}
26,443,879✔
3471

3472
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
2,147,483,647✔
3473
                            int64_t ts) {
3474
  if (!pDiffInfo->hasPrev) {
2,147,483,647✔
3475
    colDataSetNull_f_s(pOutput, pos);
57,388✔
3476
    return doSetPrevVal(pDiffInfo, type, pv, ts);
57,388✔
3477
  }
3478
  pDiffInfo->prevTs = ts;
2,147,483,647✔
3479
  switch (type) {
2,147,483,647✔
3480
    case TSDB_DATA_TYPE_UINT: {
403,259✔
3481
      int64_t v = *(uint32_t*)pv;
403,259✔
3482
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
403,259✔
3483
      break;
403,259✔
3484
    }
3485
    case TSDB_DATA_TYPE_INT: {
2,147,483,647✔
3486
      int64_t v = *(int32_t*)pv;
2,147,483,647✔
3487
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3488
      break;
2,147,483,647✔
3489
    }
3490
    case TSDB_DATA_TYPE_BOOL: {
3,982,726✔
3491
      int64_t v = *(bool*)pv;
3,982,726✔
3492
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,982,726✔
3493
      break;
3,982,726✔
3494
    }
3495
    case TSDB_DATA_TYPE_UTINYINT: {
52,785✔
3496
      int64_t v = *(uint8_t*)pv;
52,785✔
3497
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
52,785✔
3498
      break;
52,785✔
3499
    }
3500
    case TSDB_DATA_TYPE_TINYINT: {
8,583,368✔
3501
      int64_t v = *(int8_t*)pv;
8,583,368✔
3502
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
8,583,368✔
3503
      break;
8,583,368✔
3504
    }
3505
    case TSDB_DATA_TYPE_USMALLINT: {
52,785✔
3506
      int64_t v = *(uint16_t*)pv;
52,785✔
3507
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
52,785✔
3508
      break;
52,785✔
3509
    }
3510
    case TSDB_DATA_TYPE_SMALLINT: {
10,280,024✔
3511
      int64_t v = *(int16_t*)pv;
10,280,024✔
3512
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,280,024✔
3513
      break;
10,280,024✔
3514
    }
3515
    case TSDB_DATA_TYPE_TIMESTAMP:
2,147,483,647✔
3516
    case TSDB_DATA_TYPE_UBIGINT:
3517
    case TSDB_DATA_TYPE_BIGINT: {
3518
      int64_t v = *(int64_t*)pv;
2,147,483,647✔
3519
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
2,147,483,647✔
3520
      break;
2,147,483,647✔
3521
    }
3522
    case TSDB_DATA_TYPE_FLOAT: {
12,868,911✔
3523
      double v = *(float*)pv;
12,868,911✔
3524
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
12,868,911✔
3525
      break;
12,868,911✔
3526
    }
3527
    case TSDB_DATA_TYPE_DOUBLE: {
13,574,968✔
3528
      double v = *(double*)pv;
13,574,968✔
3529
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
13,574,968✔
3530
      break;
13,574,968✔
3531
    }
3532
    default:
×
3533
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3534
  }
3535
  pDiffInfo->hasPrev = true;
2,147,483,647✔
3536
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3537
}
3538

3539
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3540
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3541
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
2,147,483,647✔
3542
                              int32_t* nextFrom) {
3543
  if (pInput->pPrimaryKey == NULL) {
2,147,483,647✔
3544
    if (from == -1) {
2,147,483,647✔
3545
      from = pInput->startRowIndex;
2,147,483,647✔
3546
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
2,147,483,647✔
3547
      return false;
2,147,483,647✔
3548
    }
3549
    *pRowIndex = from;
2,147,483,647✔
3550
    *nextFrom = from + 1;
2,147,483,647✔
3551
    return true;
2,147,483,647✔
3552
  } else {
3553
    if (from == -1) {
610,910,598✔
3554
      from = pInput->startRowIndex;
133,520,545✔
3555
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
477,390,053✔
3556
      return false;
133,572,379✔
3557
    }
3558
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
477,387,670✔
3559
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
477,400,688✔
3560
    int8_t           pkType = pkCol->info.type;
477,415,661✔
3561
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
477,430,860✔
3562
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
477,430,860✔
3563
    int32_t          select = from;
477,405,413✔
3564
    char*            val = colDataGetData(pkCol, select);
477,405,413✔
3565
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
1,195,027,631✔
3566
      char* val1 = colDataGetData(pkCol, from + 1);
717,571,551✔
3567
      if (compareFunc(val1, val) < 0) {
717,617,014✔
3568
        select = from + 1;
230,281,398✔
3569
        val = val1;
230,281,398✔
3570
      }
3571
      from = from + 1;
717,578,463✔
3572
    }
3573
    *pRowIndex = select;
477,128,389✔
3574
    *nextFrom = from + 1;
477,469,229✔
3575
    return true;
477,489,017✔
3576
  }
3577
}
3578

3579
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
×
3580
  pEnv->calcMemSize = sizeof(double);
×
3581
  return true;
×
3582
}
3583

3584
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3585
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3586
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3587

3588
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
2,147,483,647✔
3589
    return true;
11,982,984✔
3590
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
2,147,483,647✔
3591
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
2,923,186✔
3592
  }
3593
  return false;
2,147,483,647✔
3594
}
3595

3596
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,147,483,647✔
3597
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3598
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3599
  return pDiffInfo->isFirstRow;
2,147,483,647✔
3600
}
3601

3602
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
5,285,989✔
3603
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,285,989✔
3604
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
5,285,989✔
3605
  pDiffInfo->isFirstRow = false;
5,285,989✔
3606
  if (pRow->isDataNull) {
5,285,989✔
3607
    return TSDB_CODE_SUCCESS;
161,454✔
3608
  }
3609

3610
  SInputColumnInfoData* pInput = &pCtx->input;
5,124,535✔
3611
  SColumnInfoData*      pInputCol = pInput->pData[0];
5,124,535✔
3612
  int8_t                inputType = pInputCol->info.type;
5,124,535✔
3613

3614
  char* pv = pRow->pData;
5,124,535✔
3615
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
5,124,535✔
3616
}
3617

3618
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
2,147,483,647✔
3619
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
3620
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
3621

3622
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
3623
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
3624
  int8_t                inputType = pInputCol->info.type;
2,147,483,647✔
3625
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
2,147,483,647✔
3626
  int32_t               code = TSDB_CODE_SUCCESS;
2,147,483,647✔
3627
  if (pRow->isDataNull) {
2,147,483,647✔
3628
    colDataSetNull_f_s(pOutput, pos);
6,646,254✔
3629
    pOutput->hasNull = true;
6,646,254✔
3630

3631
    // handle selectivity
3632
    if (pCtx->subsidiaries.num > 0) {
6,646,254✔
3633
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
18,768✔
3634
      if (code != TSDB_CODE_SUCCESS) {
18,768✔
3635
        return code;
×
3636
      }
3637
    }
3638
    return TSDB_CODE_SUCCESS;
6,646,254✔
3639
  }
3640

3641
  char* pv = pRow->pData;
2,147,483,647✔
3642

3643
  if (pRow->ts == pDiffInfo->prevTs) {
2,147,483,647✔
3644
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
6,953✔
3645
  }
3646
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
2,147,483,647✔
3647
  if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3648
    return code;
×
3649
  }
3650
  // handle selectivity
3651
  if (pCtx->subsidiaries.num > 0) {
2,147,483,647✔
3652
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
2,147,483,647✔
3653
    if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3654
      return code;
×
3655
    }
3656
  }
3657

3658
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
3659
}
3660

3661
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
42,134,556✔
3662

3663
int32_t diffFunctionByRow(SArray* pCtxArray) {
42,113,442✔
3664
  int32_t code = TSDB_CODE_SUCCESS;
42,113,442✔
3665
  int     diffColNum = pCtxArray->size;
42,113,442✔
3666
  if (diffColNum == 0) {
42,113,442✔
3667
    return TSDB_CODE_SUCCESS;
×
3668
  }
3669
  int32_t numOfElems = 0;
42,113,442✔
3670

3671
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
42,113,442✔
3672
  if (NULL == pRows) {
42,113,442✔
3673
    return terrno;
×
3674
  }
3675

3676
  bool keepNull = false;
42,113,442✔
3677
  for (int i = 0; i < diffColNum; ++i) {
84,247,998✔
3678
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
42,134,556✔
3679
    if (NULL == pCtx) {
42,134,556✔
3680
      code = terrno;
×
3681
      goto _exit;
×
3682
    }
3683
    funcInputUpdate(pCtx);
42,134,556✔
3684
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
42,134,556✔
3685
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
42,134,556✔
3686
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
42,134,556✔
3687
      keepNull = true;
42,118,525✔
3688
    }
3689
  }
3690

3691
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
42,113,442✔
3692
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
42,113,442✔
3693
  if (NULL == pCtx0 || NULL == pRow0) {
42,113,442✔
3694
    code = terrno;
×
3695
    goto _exit;
×
3696
  }
3697
  int32_t startOffset = pCtx0->offset;
42,113,442✔
3698
  bool    result = false;
42,113,442✔
3699
  while (1) {
2,147,483,647✔
3700
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
2,147,483,647✔
3701
    if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
3702
      goto _exit;
×
3703
    }
3704
    if (!result) {
2,147,483,647✔
3705
      break;
42,106,489✔
3706
    }
3707
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
2,147,483,647✔
3708
    for (int i = 1; i < diffColNum; ++i) {
2,147,483,647✔
3709
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
4,495,718✔
3710
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
4,495,718✔
3711
      if (NULL == pCtx || NULL == pRow) {
4,495,718✔
3712
        code = terrno;
×
3713
        goto _exit;
×
3714
      }
3715
      code = funcInputGetNextRow(pCtx, pRow, &result);
4,495,718✔
3716
      if (TSDB_CODE_SUCCESS != code) {
4,495,718✔
3717
        goto _exit;
×
3718
      }
3719
      if (!result) {
4,495,718✔
3720
        // rows are not equal
3721
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3722
        goto _exit;
×
3723
      }
3724
      if (!diffResultIsNull(pCtx, pRow)) {
4,495,718✔
3725
        hasNotNullValue = true;
4,437,850✔
3726
      }
3727
    }
3728
    int32_t pos = startOffset + numOfElems;
2,147,483,647✔
3729

3730
    bool newRow = false;
2,147,483,647✔
3731
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3732
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,147,483,647✔
3733
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
2,147,483,647✔
3734
      if (NULL == pCtx || NULL == pRow) {
2,147,483,647✔
3735
        code = terrno;
×
3736
        goto _exit;
×
3737
      }
3738
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
2,147,483,647✔
3739
        code = setDoDiffResult(pCtx, pRow, pos);
2,147,483,647✔
3740
        if (code != TSDB_CODE_SUCCESS) {
2,147,483,647✔
3741
          goto _exit;
6,953✔
3742
        }
3743
        newRow = true;
2,147,483,647✔
3744
      } else {
3745
        code = trySetPreVal(pCtx, pRow);
5,285,989✔
3746
        if (code != TSDB_CODE_SUCCESS) {
5,285,989✔
3747
          goto _exit;
×
3748
        }
3749
      }
3750
    }
3751
    if (newRow) ++numOfElems;
2,147,483,647✔
3752
  }
3753

3754
  for (int i = 0; i < diffColNum; ++i) {
84,233,701✔
3755
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
42,127,212✔
3756
    if (NULL == pCtx) {
42,127,212✔
3757
      code = terrno;
×
3758
      goto _exit;
×
3759
    }
3760
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
42,127,212✔
3761
    pResInfo->numOfRes = numOfElems;
42,127,212✔
3762
  }
3763

3764
_exit:
42,113,442✔
3765
  if (pRows) {
42,113,442✔
3766
    taosArrayDestroy(pRows);
42,113,442✔
3767
    pRows = NULL;
42,113,442✔
3768
  }
3769
  return code;
42,113,442✔
3770
}
3771

3772
bool getLagFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
31,872✔
3773
  pEnv->calcMemSize = sizeof(SLagInfo);
31,872✔
3774
  return true;
31,872✔
3775
}
3776

3777
int32_t lagFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
66,048✔
3778
  if (pResInfo->initialized) {
66,048✔
3779
    return TSDB_CODE_SUCCESS;
31,872✔
3780
  }
3781
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
34,176✔
3782
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3783
  }
3784
  SLagInfo* pLagInfo = GET_ROWCELL_INTERBUF(pResInfo);
34,176✔
3785
  pLagInfo->nonnull = false;
34,176✔
3786

3787
  return TSDB_CODE_SUCCESS;
34,176✔
3788
}
3789

3790
int32_t lagFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
34,176✔
3791

3792
static int32_t doHandleLag(SLagInfo* pLagInfo, int32_t type, SColumnInfoData* pOutput, int32_t pos) {
110,592✔
3793
  if (!pLagInfo->nonnull) {
110,592✔
3794
    colDataSetNULL(pOutput, pos);
12,672✔
3795

3796
    return TSDB_CODE_SUCCESS;
12,672✔
3797
  }
3798

3799
  switch (type) {
97,920✔
3800
    case TSDB_DATA_TYPE_BOOL:
46,464✔
3801
    case TSDB_DATA_TYPE_UTINYINT:
3802
    case TSDB_DATA_TYPE_TINYINT:
3803
    case TSDB_DATA_TYPE_USMALLINT:
3804
    case TSDB_DATA_TYPE_SMALLINT:
3805
    case TSDB_DATA_TYPE_UINT:
3806
    case TSDB_DATA_TYPE_INT:
3807
    case TSDB_DATA_TYPE_UBIGINT:
3808
    case TSDB_DATA_TYPE_BIGINT:
3809
    case TSDB_DATA_TYPE_TIMESTAMP:
3810
      colDataSetInt64(pOutput, pos, &pLagInfo->v);
46,464✔
3811
      break;
46,464✔
3812
    case TSDB_DATA_TYPE_FLOAT:
18,432✔
3813
      colDataSetFloat(pOutput, pos, &pLagInfo->fv);
18,432✔
3814
      break;
18,432✔
3815
    case TSDB_DATA_TYPE_DOUBLE:
20,736✔
3816
      colDataSetDouble(pOutput, pos, &pLagInfo->dv);
20,736✔
3817
      break;
20,736✔
3818
    case TSDB_DATA_TYPE_DECIMAL64:
4,224✔
3819
      return colDataSetVal(pOutput, pos, (const char*)&pLagInfo->v, false);
4,224✔
3820
    case TSDB_DATA_TYPE_DECIMAL:
×
3821
      return colDataSetVal(pOutput, pos, (void*)pLagInfo->dec, false);
×
3822
    case TSDB_DATA_TYPE_VARCHAR:
8,064✔
3823
    case TSDB_DATA_TYPE_VARBINARY:
3824
    case TSDB_DATA_TYPE_NCHAR:
3825
      return colDataSetVal(pOutput, pos, (void*)pLagInfo->str, false);
8,064✔
3826
    default:
×
3827
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3828
  }
3829

3830
  return TSDB_CODE_SUCCESS;
85,632✔
3831
}
3832

3833
static int32_t setLagResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
110,592✔
3834
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
110,592✔
3835
  SLagInfo*            pLagInfo = GET_ROWCELL_INTERBUF(pResInfo);
110,592✔
3836

3837
  SInputColumnInfoData* pInput = &pCtx->input;
110,592✔
3838
  SColumnInfoData*      pInputCol = pInput->pData[0];
110,592✔
3839
  int8_t                inputType = pInputCol->info.type;
110,592✔
3840
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
110,592✔
3841
  int32_t               code = TSDB_CODE_SUCCESS;
110,592✔
3842

3843
  code = doHandleLag(pLagInfo, inputType, pOutput, pos);
110,592✔
3844
  if (code != TSDB_CODE_SUCCESS) {
110,592✔
3845
    return code;
×
3846
  }
3847

3848
  // handle selectivity
3849
  if (pCtx->subsidiaries.num > 0) {
110,592✔
3850
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
29,184✔
3851
    if (code != TSDB_CODE_SUCCESS) {
29,184✔
3852
      return code;
×
3853
    }
3854
  }
3855

3856
  return TSDB_CODE_SUCCESS;
110,592✔
3857
}
3858

3859
int32_t lagFunctionByRow(SArray* pCtxArray) {
9,600✔
3860
  int32_t code = TSDB_CODE_SUCCESS;
9,600✔
3861
  int     lagColNum = pCtxArray->size;
9,600✔
3862
  if (lagColNum == 0) {
9,600✔
3863
    return TSDB_CODE_SUCCESS;
×
3864
  }
3865
  int32_t numOfElems = 0;
9,600✔
3866

3867
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), lagColNum);
9,600✔
3868
  if (NULL == pRows) {
9,600✔
3869
    return terrno;
×
3870
  }
3871

3872
  for (int i = 0; i < lagColNum; ++i) {
43,776✔
3873
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
34,176✔
3874
    if (NULL == pCtx) {
34,176✔
3875
      code = terrno;
×
3876
      goto _exit;
×
3877
    }
3878
    funcInputUpdate(pCtx);
34,176✔
3879
  }
3880

3881
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
9,600✔
3882
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
9,600✔
3883
  if (NULL == pCtx0 || NULL == pRow0) {
9,600✔
3884
    code = terrno;
×
3885
    goto _exit;
×
3886
  }
3887
  int32_t startOffset = pCtx0->offset;
9,600✔
3888
  bool    result = false;
9,600✔
3889
  while (1) {
29,184✔
3890
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
38,784✔
3891
    if (TSDB_CODE_SUCCESS != code) {
38,784✔
3892
      goto _exit;
×
3893
    }
3894
    if (!result) {
38,784✔
3895
      break;
9,216✔
3896
    }
3897

3898
    for (int i = 1; i < lagColNum; ++i) {
110,976✔
3899
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
81,408✔
3900
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
81,408✔
3901
      if (NULL == pCtx || NULL == pRow) {
81,408✔
3902
        code = terrno;
×
3903
        goto _exit;
×
3904
      }
3905
      code = funcInputGetNextRow(pCtx, pRow, &result);
81,408✔
3906
      if (TSDB_CODE_SUCCESS != code) {
81,408✔
3907
        goto _exit;
×
3908
      }
3909
      if (!result) {
81,408✔
3910
        // rows are not equal
3911
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3912
        goto _exit;
×
3913
      }
3914
    }
3915

3916
    int32_t pos = startOffset + numOfElems;
29,568✔
3917

3918
    for (int i = 0; i < lagColNum; ++i) {
140,160✔
3919
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
110,976✔
3920
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
110,976✔
3921
      if (NULL == pCtx || NULL == pRow) {
110,976✔
3922
        code = terrno;
×
3923
        goto _exit;
×
3924
      }
3925

3926
      if (!colDataIsNull_s(pCtx->input.pData[0], pCtx->rowIter.rowIndex - 1)) {
221,952✔
3927
        SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
67,584✔
3928
        SLagInfo*             pLagInfo = GET_ROWCELL_INTERBUF(pResInfo);
67,584✔
3929
        SInputColumnInfoData* pInput = &pCtx->input;
67,584✔
3930
        SColumnInfoData*      pInputCol = pInput->pData[0];
67,584✔
3931
        int8_t                inputType = pInputCol->info.type;
67,584✔
3932

3933
        char* pv = pRow->pData;
67,584✔
3934
        switch (inputType) {
67,584✔
3935
          case TSDB_DATA_TYPE_BOOL:
13,440✔
3936
            pLagInfo->v = *(bool*)pv ? 1 : 0;
13,440✔
3937
            break;
13,440✔
3938
          case TSDB_DATA_TYPE_UTINYINT:
384✔
3939
          case TSDB_DATA_TYPE_TINYINT:
3940
            pLagInfo->v = *(int8_t*)pv;
384✔
3941
            break;
384✔
3942
          case TSDB_DATA_TYPE_UINT:
18,432✔
3943
          case TSDB_DATA_TYPE_INT:
3944
            pLagInfo->v = *(int32_t*)pv;
18,432✔
3945
            break;
18,432✔
3946
          case TSDB_DATA_TYPE_USMALLINT:
384✔
3947
          case TSDB_DATA_TYPE_SMALLINT:
3948
            pLagInfo->v = *(int16_t*)pv;
384✔
3949
            break;
384✔
3950
          case TSDB_DATA_TYPE_TIMESTAMP:
384✔
3951
          case TSDB_DATA_TYPE_UBIGINT:
3952
          case TSDB_DATA_TYPE_BIGINT:
3953
            pLagInfo->v = *(int64_t*)pv;
384✔
3954
            break;
384✔
3955
          case TSDB_DATA_TYPE_FLOAT:
13,440✔
3956
            pLagInfo->fv = *(float*)pv;
13,440✔
3957
            break;
13,440✔
3958
          case TSDB_DATA_TYPE_DOUBLE:
14,976✔
3959
            pLagInfo->dv = *(double*)pv;
14,976✔
3960
            break;
14,976✔
3961
          case TSDB_DATA_TYPE_DECIMAL64:
2,304✔
3962
            DECIMAL64_SET_VALUE((Decimal64*)&pLagInfo->v, *(int64_t*)pv);
2,304✔
3963
            break;
2,304✔
3964
          case TSDB_DATA_TYPE_DECIMAL:
×
3965
            DECIMAL128_CLONE((Decimal128*)pLagInfo->dec, (Decimal128*)pv);
×
3966
            break;
×
3967
          case TSDB_DATA_TYPE_VARCHAR:
3,456✔
3968
          case TSDB_DATA_TYPE_VARBINARY:
3969
          case TSDB_DATA_TYPE_NCHAR: {
3970
            if (!pLagInfo->nonnull) {
3,456✔
3971
              pLagInfo->str = taosMemoryMalloc(pInputCol->info.bytes);
2,304✔
3972
              if (!pLagInfo->str) {
2,304✔
3973
                code = terrno;
×
3974
                goto _exit;
×
3975
              }
3976
            }
3977

3978
            (void)memcpy(pLagInfo->str, pv, varDataTLen(pv));
3,456✔
3979
          } break;
3,456✔
3980
          default: {
384✔
3981
            code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
384✔
3982
            goto _exit;
384✔
3983
          }
3984
        }
3985

3986
        if (!pLagInfo->nonnull) {
67,200✔
3987
          pLagInfo->nonnull = true;
33,408✔
3988
        }
3989
      }
3990

3991
      code = setLagResult(pCtx, pRow, pos);
110,592✔
3992
      if (code) {
110,592✔
3993
        goto _exit;
×
3994
      }
3995
    }
3996

3997
    ++numOfElems;
29,184✔
3998
  }
3999

4000
_exit:
9,600✔
4001
  for (int i = 0; i < lagColNum; ++i) {
43,776✔
4002
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
34,176✔
4003
    if (!pCtx) {
34,176✔
4004
      break;
×
4005
    }
4006

4007
    SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
34,176✔
4008
    SLagInfo*             pRes = GET_ROWCELL_INTERBUF(pResInfo);
34,176✔
4009
    SInputColumnInfoData* pInput = &pCtx->input;
34,176✔
4010
    SColumnInfoData*      pInputCol = pInput->pData[0];
34,176✔
4011

4012
    if (IS_VAR_DATA_TYPE(pInputCol->info.type) && pRes->nonnull) {
34,176✔
4013
      taosMemoryFree(pRes->str);
2,304✔
4014
    }
4015

4016
    if (!code) {
34,176✔
4017
      pResInfo->numOfRes = numOfElems;
33,792✔
4018
    }
4019
  }
4020

4021
  if (pRows) {
9,600✔
4022
    taosArrayDestroy(pRows);
9,600✔
4023
    pRows = NULL;
9,600✔
4024
  }
4025
  return code;
9,600✔
4026
}
4027

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

4030
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,593,047✔
4031
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
1,593,047✔
4032
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
1,593,047✔
4033
  return true;
1,593,047✔
4034
}
4035

4036
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
6,163,806✔
4037
  if (pResInfo->initialized) {
6,163,806✔
4038
    return TSDB_CODE_SUCCESS;
×
4039
  }
4040
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
6,163,806✔
4041
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4042
  }
4043

4044
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
6,163,806✔
4045
  SInputColumnInfoData* pInput = &pCtx->input;
6,163,806✔
4046

4047
  pRes->maxSize = pCtx->param[1].param.i;
6,163,806✔
4048

4049
  pRes->nullTupleSaved = false;
6,163,806✔
4050
  pRes->nullTuplePos.pageId = -1;
6,163,806✔
4051
  return TSDB_CODE_SUCCESS;
6,164,296✔
4052
}
4053

4054
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
1,075,944,797✔
4055
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,075,944,797✔
4056
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
1,075,947,737✔
4057
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
1,075,946,863✔
4058

4059
  return pRes;
1,075,943,146✔
4060
}
4061

4062
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
4063
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
4064

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

4067
int32_t topFunction(SqlFunctionCtx* pCtx) {
6,662,738✔
4068
  int32_t              numOfElems = 0;
6,662,738✔
4069
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,662,738✔
4070

4071
  SInputColumnInfoData* pInput = &pCtx->input;
6,662,738✔
4072
  SColumnInfoData*      pCol = pInput->pData[0];
6,661,760✔
4073

4074
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
6,662,354✔
4075
  pRes->type = pInput->pData[0]->info.type;
6,662,354✔
4076

4077
  int32_t start = pInput->startRowIndex;
6,662,738✔
4078
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
725,433,236✔
4079
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
718,803,441✔
4080
      continue;
1,860,777✔
4081
    }
4082

4083
    numOfElems++;
716,941,196✔
4084
    char*   data = colDataGetData(pCol, i);
716,941,196✔
4085
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
716,961,339✔
4086
    if (code != TSDB_CODE_SUCCESS) {
716,910,315✔
4087
      return code;
×
4088
    }
4089
  }
4090

4091
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
6,662,738✔
4092
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
5,308✔
4093
    if (code != TSDB_CODE_SUCCESS) {
5,308✔
4094
      return code;
×
4095
    }
4096
    pRes->nullTupleSaved = true;
5,308✔
4097
  }
4098
  return TSDB_CODE_SUCCESS;
6,662,738✔
4099
}
4100

4101
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
1,070,012✔
4102
  int32_t              numOfElems = 0;
1,070,012✔
4103
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,070,012✔
4104

4105
  SInputColumnInfoData* pInput = &pCtx->input;
1,070,012✔
4106
  SColumnInfoData*      pCol = pInput->pData[0];
1,070,012✔
4107

4108
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
1,070,012✔
4109
  pRes->type = pInput->pData[0]->info.type;
1,070,012✔
4110

4111
  int32_t start = pInput->startRowIndex;
1,070,012✔
4112
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
347,430,744✔
4113
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
346,360,639✔
4114
      continue;
1,264,923✔
4115
    }
4116

4117
    numOfElems++;
345,095,716✔
4118
    char*   data = colDataGetData(pCol, i);
345,095,716✔
4119
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
345,096,599✔
4120
    if (code != TSDB_CODE_SUCCESS) {
345,096,204✔
4121
      return code;
×
4122
    }
4123
  }
4124

4125
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
1,070,012✔
4126
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
6,276✔
4127
    if (code != TSDB_CODE_SUCCESS) {
6,276✔
4128
      return code;
×
4129
    }
4130
    pRes->nullTupleSaved = true;
6,276✔
4131
  }
4132

4133
  return TSDB_CODE_SUCCESS;
1,070,012✔
4134
}
4135

4136
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
348,172,611✔
4137
  uint16_t type = *(uint16_t*)param;
348,172,611✔
4138

4139
  STopBotResItem* val1 = (STopBotResItem*)p1;
348,177,805✔
4140
  STopBotResItem* val2 = (STopBotResItem*)p2;
348,177,805✔
4141

4142
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
348,177,805✔
4143
    if (val1->v.i == val2->v.i) {
192,663,250✔
4144
      return 0;
37,517,889✔
4145
    }
4146

4147
    return (val1->v.i > val2->v.i) ? 1 : -1;
155,661,101✔
4148
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
155,514,555✔
4149
    if (val1->v.u == val2->v.u) {
72,454,776✔
4150
      return 0;
14,889,107✔
4151
    }
4152

4153
    return (val1->v.u > val2->v.u) ? 1 : -1;
57,642,679✔
4154
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
83,059,865✔
4155
    if (val1->v.f == val2->v.f) {
1,663,907✔
4156
      return 0;
24,759✔
4157
    }
4158

4159
    return (val1->v.f > val2->v.f) ? 1 : -1;
1,639,148✔
4160
  }
4161

4162
  if (val1->v.d == val2->v.d) {
81,395,958✔
4163
    return 0;
4,323✔
4164
  }
4165

4166
  return (val1->v.d > val2->v.d) ? 1 : -1;
81,407,933✔
4167
}
4168

4169
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
1,062,058,926✔
4170
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
4171
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
1,062,058,926✔
4172
  int32_t     code = TSDB_CODE_SUCCESS;
1,062,059,210✔
4173

4174
  SVariant val = {0};
1,062,059,210✔
4175
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
1,062,059,700✔
4176

4177
  STopBotResItem* pItems = pRes->pItems;
1,062,066,313✔
4178

4179
  // not full yet
4180
  if (pEntryInfo->numOfRes < pRes->maxSize) {
1,062,065,333✔
4181
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
34,713,442✔
4182
    pItem->v = val;
34,715,316✔
4183
    pItem->uid = uid;
34,714,221✔
4184

4185
    // save the data of this tuple
4186
    if (pCtx->subsidiaries.num > 0) {
34,714,338✔
4187
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
7,340,569✔
4188
      if (code != TSDB_CODE_SUCCESS) {
7,339,406✔
4189
        return code;
×
4190
      }
4191
    }
4192
#ifdef BUF_PAGE_DEBUG
4193
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
4194
           pItem->tuplePos.offset);
4195
#endif
4196
    // allocate the buffer and keep the data of this row into the new allocated buffer
4197
    pEntryInfo->numOfRes++;
34,711,107✔
4198
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
34,714,826✔
4199
                        topBotResComparFn, !isTopQuery);
34,715,210✔
4200
    if (code != TSDB_CODE_SUCCESS) {
34,713,731✔
4201
      return code;
×
4202
    }
4203
  } else {  // replace the minimum value in the result
4204
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
1,027,351,162✔
4205
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
674,650,188✔
4206
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
667,065,656✔
4207
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
667,042,561✔
4208
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
1,000,133,237✔
4209
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
340,610,690✔
4210
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
340,059,277✔
4211
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
339,955,205✔
4212
      // replace the old data and the coresponding tuple data
4213
      STopBotResItem* pItem = &pItems[0];
29,307,587✔
4214
      pItem->v = val;
29,307,587✔
4215
      pItem->uid = uid;
29,290,046✔
4216

4217
      // save the data of this tuple by over writing the old data
4218
      if (pCtx->subsidiaries.num > 0) {
29,290,258✔
4219
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
17,727,357✔
4220
        if (code != TSDB_CODE_SUCCESS) {
17,727,357✔
4221
          return code;
×
4222
        }
4223
      }
4224
#ifdef BUF_PAGE_DEBUG
4225
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
4226
#endif
4227
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
29,285,742✔
4228
                            topBotResComparFn, NULL, !isTopQuery);
29,289,768✔
4229
      if (code != TSDB_CODE_SUCCESS) {
29,285,358✔
4230
        return code;
×
4231
      }
4232
    }
4233
  }
4234

4235
  return TSDB_CODE_SUCCESS;
1,062,042,770✔
4236
}
4237

4238
/*
4239
 * +------------------------------------+--------------+--------------+
4240
 * |            null bitmap             |              |              |
4241
 * |(n columns, one bit for each column)| src column #1| src column #2|
4242
 * +------------------------------------+--------------+--------------+
4243
 */
4244
int32_t serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
43,763,611✔
4245
                           char* buf, char** res) {
4246
  char* nullList = buf;
43,763,611✔
4247
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
43,763,611✔
4248

4249
  int32_t offset = 0;
43,763,917✔
4250
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
101,834,944✔
4251
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
58,074,781✔
4252

4253
    // group_key function has its own process function
4254
    // do not process there
4255
    if (fmIsGroupKeyFunc(pc->functionId)) {
58,071,375✔
4256
      continue;
×
4257
    }
4258

4259
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
58,066,201✔
4260
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
58,070,060✔
4261

4262
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
58,065,689✔
4263
    if (NULL == pCol) {
58,071,176✔
4264
      return TSDB_CODE_OUT_OF_RANGE;
×
4265
    }
4266
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
116,140,036✔
4267
      offset += pCol->info.bytes;
149,339✔
4268
      continue;
149,339✔
4269
    }
4270

4271
    char* p = colDataGetData(pCol, rowIndex);
57,915,494✔
4272
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
57,919,561✔
4273
      int32_t bytes = calcStrBytesByType(pCol->info.type, p);
7,791,455✔
4274
      (void)memcpy(pStart + offset, p, bytes);
7,794,947✔
4275
    } else {
4276
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
50,127,663✔
4277
    }
4278

4279
    offset += pCol->info.bytes;
57,920,381✔
4280
  }
4281

4282
  *res = buf;
43,755,412✔
4283
  return TSDB_CODE_SUCCESS;
43,761,121✔
4284
}
4285

4286
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
73,666,256✔
4287
                               STuplePos* pPos, SFunctionStateStore* pStore) {
4288
  STuplePos p = {0};
73,666,256✔
4289
  if (pHandle->pBuf != NULL) {
73,666,256✔
4290
    SFilePage* pPage = NULL;
73,664,638✔
4291

4292
    if (pHandle->currentPage == -1) {
73,664,638✔
4293
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
4,443,891✔
4294
      if (pPage == NULL) {
4,445,073✔
4295
        return terrno;
×
4296
      }
4297
      pPage->num = sizeof(SFilePage);
4,445,073✔
4298
    } else {
4299
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
69,219,977✔
4300
      if (pPage == NULL) {
69,216,876✔
4301
        return terrno;
×
4302
      }
4303
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
69,216,876✔
4304
        // current page is all used, let's prepare a new buffer page
4305
        releaseBufPage(pHandle->pBuf, pPage);
504,800✔
4306
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
504,800✔
4307
        if (pPage == NULL) {
504,800✔
4308
          return terrno;
×
4309
        }
4310
        pPage->num = sizeof(SFilePage);
504,800✔
4311
      }
4312
    }
4313

4314
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
73,662,186✔
4315
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
73,664,064✔
4316

4317
    pPage->num += length;
73,664,658✔
4318
    setBufPageDirty(pPage, true);
73,662,291✔
4319
    releaseBufPage(pHandle->pBuf, pPage);
73,660,626✔
4320
  } else {  // other tuple save policy
4321
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
1,020✔
4322
      p.streamTupleKey = *key;
×
4323
    }
4324
  }
4325

4326
  *pPos = p;
73,661,568✔
4327
  return TSDB_CODE_SUCCESS;
73,661,148✔
4328
}
4329

4330
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
17,821,409✔
4331
  int32_t code = prepareBuf(pCtx);
17,821,409✔
4332
  if (TSDB_CODE_SUCCESS != code) {
17,817,089✔
4333
    return code;
×
4334
  }
4335

4336
  SWinKey key = {0};
17,817,089✔
4337
  if (pCtx->saveHandle.pBuf == NULL) {
17,816,993✔
4338
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
×
4339
    if (NULL == pColInfo) {
×
4340
      return TSDB_CODE_OUT_OF_RANGE;
×
4341
    }
4342
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
×
4343
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4344
    }
4345
    key.groupId = pSrcBlock->info.id.groupId;
×
4346
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
×
4347
    key.numInGroup = pCtx->pExpr->pExpr->_function.bindExprID;
×
4348
  }
4349

4350
  char* buf = NULL;
17,820,932✔
4351
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
17,822,003✔
4352
  if (TSDB_CODE_SUCCESS != code) {
17,818,115✔
4353
    return code;
×
4354
  }
4355
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
17,818,115✔
4356
}
4357

4358
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
25,942,376✔
4359
                                 SFunctionStateStore* pStore) {
4360
  if (pHandle->pBuf != NULL) {
25,942,376✔
4361
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
25,942,874✔
4362
    if (pPage == NULL) {
25,941,396✔
4363
      return terrno;
×
4364
    }
4365
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
25,941,396✔
4366
    setBufPageDirty(pPage, true);
25,941,012✔
4367
    releaseBufPage(pHandle->pBuf, pPage);
25,942,874✔
4368
  } else {
4369
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
×
4370
    if (TSDB_CODE_SUCCESS != code) {
×
4371
      return code;
×
4372
    }
4373
  }
4374

4375
  return TSDB_CODE_SUCCESS;
25,941,992✔
4376
}
4377

4378
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
25,942,760✔
4379
  int32_t code = prepareBuf(pCtx);
25,942,760✔
4380
  if (TSDB_CODE_SUCCESS != code) {
25,941,992✔
4381
    return code;
×
4382
  }
4383

4384
  char* buf = NULL;
25,941,992✔
4385
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
25,941,992✔
4386
  if (TSDB_CODE_SUCCESS != code) {
25,942,874✔
4387
    return code;
×
4388
  }
4389
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
25,942,874✔
4390
}
4391

4392
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
17,616,207✔
4393
                               char** value) {
4394
  if (pHandle->pBuf != NULL) {
17,616,207✔
4395
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
17,615,845✔
4396
    if (pPage == NULL) {
17,616,801✔
4397
      *value = NULL;
×
4398
      return terrno;
×
4399
    }
4400
    *value = pPage->data + pPos->offset;
17,616,801✔
4401
    releaseBufPage(pHandle->pBuf, pPage);
17,616,801✔
4402
    return TSDB_CODE_SUCCESS;
17,616,416✔
4403
  } else {
4404
    *value = NULL;
362✔
4405
    int32_t vLen;
×
4406
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
×
4407
    if (TSDB_CODE_SUCCESS != code) {
×
4408
      return code;
×
4409
    }
4410
    return TSDB_CODE_SUCCESS;
×
4411
  }
4412
}
4413

4414
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
17,616,207✔
4415
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
17,616,207✔
4416
}
4417

4418
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,163,806✔
4419
  int32_t code = TSDB_CODE_SUCCESS;
6,163,806✔
4420

4421
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6,163,806✔
4422
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
6,163,806✔
4423

4424
  int16_t type = pCtx->pExpr->base.resSchema.type;
6,162,336✔
4425
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
6,162,336✔
4426

4427
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,162,336✔
4428
  if (NULL == pCol) {
6,163,806✔
4429
    return TSDB_CODE_OUT_OF_RANGE;
×
4430
  }
4431

4432
  // todo assign the tag value and the corresponding row data
4433
  int32_t currentRow = pBlock->info.rows;
6,163,806✔
4434
  if (pEntryInfo->numOfRes <= 0) {
6,163,806✔
4435
    colDataSetNULL(pCol, currentRow);
33,252✔
4436
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
33,252✔
4437
    return code;
33,252✔
4438
  }
4439
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
40,844,784✔
4440
    STopBotResItem* pItem = &pRes->pItems[i];
34,708,840✔
4441
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
34,713,740✔
4442
    if (TSDB_CODE_SUCCESS != code) {
34,712,270✔
4443
      return code;
×
4444
    }
4445
#ifdef BUF_PAGE_DEBUG
4446
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
4447
           pItem->tuplePos.offset);
4448
#endif
4449
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
34,712,270✔
4450
    if (TSDB_CODE_SUCCESS != code) {
34,714,230✔
4451
      return code;
×
4452
    }
4453
    currentRow += 1;
34,714,230✔
4454
  }
4455

4456
  return code;
6,131,044✔
4457
}
4458

4459
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
4460
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
4461
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
4462
  STopBotResItem*      pItems = pRes->pItems;
×
4463
  int32_t              code = TSDB_CODE_SUCCESS;
×
4464

4465
  // not full yet
4466
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
4467
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
4468
    pItem->v = pSourceItem->v;
×
4469
    pItem->uid = pSourceItem->uid;
×
4470
    pItem->tuplePos.pageId = -1;
×
4471
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4472
    pEntryInfo->numOfRes++;
×
4473
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
4474
                        topBotResComparFn, !isTopQuery);
×
4475
    if (TSDB_CODE_SUCCESS != code) {
×
4476
      return code;
×
4477
    }
4478
  } else {  // replace the minimum value in the result
4479
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
4480
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
4481
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
4482
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
4483
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
4484
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
4485
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
4486
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
4487
      // replace the old data and the coresponding tuple data
4488
      STopBotResItem* pItem = &pItems[0];
×
4489
      pItem->v = pSourceItem->v;
×
4490
      pItem->uid = pSourceItem->uid;
×
4491

4492
      // save the data of this tuple by over writing the old data
4493
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4494
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4495
                            topBotResComparFn, NULL, !isTopQuery);
×
4496
      if (TSDB_CODE_SUCCESS != code) {
×
4497
        return code;
×
4498
      }
4499
    }
4500
  }
4501
  return code;
×
4502
}
4503

4504
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4505
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4506
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4507
  int16_t              type = pSBuf->type;
×
4508
  int32_t              code = TSDB_CODE_SUCCESS;
×
4509
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4510
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
4511
    if (TSDB_CODE_SUCCESS != code) {
×
4512
      return code;
×
4513
    }
4514
  }
4515
  return TSDB_CODE_SUCCESS;
×
4516
}
4517

4518
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4519
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4520
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4521
  int16_t              type = pSBuf->type;
×
4522
  int32_t              code = TSDB_CODE_SUCCESS;
×
4523
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4524
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4525
    if (TSDB_CODE_SUCCESS != code) {
×
4526
      return code;
×
4527
    }
4528
  }
4529
  return TSDB_CODE_SUCCESS;
×
4530
}
4531

4532
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
6,702,573✔
4533

4534
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
3,117,577✔
4535
  pEnv->calcMemSize = sizeof(SSpreadInfo);
3,117,577✔
4536
  return true;
3,118,543✔
4537
}
4538

4539
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
65,496,497✔
4540
  if (pResultInfo->initialized) {
65,496,497✔
4541
    return TSDB_CODE_SUCCESS;
×
4542
  }
4543
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
65,497,479✔
4544
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4545
  }
4546

4547
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
65,498,922✔
4548
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
65,498,922✔
4549
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
65,498,441✔
4550
  pInfo->hasResult = false;
65,498,922✔
4551
  return TSDB_CODE_SUCCESS;
65,498,421✔
4552
}
4553

4554
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
68,975,604✔
4555
  int32_t numOfElems = 0;
68,975,604✔
4556

4557
  // Only the pre-computing information loaded and actual data does not loaded
4558
  SInputColumnInfoData* pInput = &pCtx->input;
68,975,604✔
4559
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
68,977,087✔
4560
  int32_t               type = pInput->pData[0]->info.type;
68,981,558✔
4561

4562
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
68,975,083✔
4563

4564
  if (pInput->colDataSMAIsSet) {
68,978,592✔
4565
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
×
4566
    if (numOfElems == 0) {
×
4567
      goto _spread_over;
×
4568
    }
4569
    double tmin = 0.0, tmax = 0.0;
×
4570
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
×
4571
      tmin = (double)GET_INT64_VAL(&pAgg->min);
×
4572
      tmax = (double)GET_INT64_VAL(&pAgg->max);
×
4573
    } else if (IS_FLOAT_TYPE(type)) {
×
4574
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4575
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4576
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
4577
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
4578
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
4579
    }
4580

4581
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
×
4582
      SET_DOUBLE_VAL(&pInfo->min, tmin);
×
4583
    }
4584

4585
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
×
4586
      SET_DOUBLE_VAL(&pInfo->max, tmax);
×
4587
    }
4588

4589
  } else {  // computing based on the true data block
4590
    SColumnInfoData* pCol = pInput->pData[0];
68,962,117✔
4591

4592
    int32_t start = pInput->startRowIndex;
68,959,613✔
4593
    // check the valid data one by one
4594
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
628,354,081✔
4595
      if (colDataIsNull_f(pCol, i)) {
559,372,557✔
4596
        continue;
29,153,188✔
4597
      }
4598

4599
      char* data = colDataGetData(pCol, i);
530,230,105✔
4600

4601
      double v = 0;
530,210,853✔
4602
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
530,210,853✔
4603
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
530,211,779✔
4604
        SET_DOUBLE_VAL(&pInfo->min, v);
63,538,212✔
4605
      }
4606

4607
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
530,237,360✔
4608
        SET_DOUBLE_VAL(&pInfo->max, v);
77,382,575✔
4609
      }
4610

4611
      numOfElems += 1;
530,241,803✔
4612
    }
4613
  }
4614

4615
_spread_over:
68,978,592✔
4616
  // data in the check operation are all null, not output
4617
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
68,978,592✔
4618
  if (numOfElems > 0) {
68,975,626✔
4619
    pInfo->hasResult = true;
68,226,639✔
4620
  }
4621

4622
  return TSDB_CODE_SUCCESS;
68,979,554✔
4623
}
4624

4625
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
6,512,131✔
4626
  pOutput->hasResult = pInput->hasResult;
6,512,131✔
4627
  if (pInput->max > pOutput->max) {
6,512,131✔
4628
    pOutput->max = pInput->max;
4,547,960✔
4629
  }
4630

4631
  if (pInput->min < pOutput->min) {
6,512,131✔
4632
    pOutput->min = pInput->min;
4,546,153✔
4633
  }
4634
}
6,512,131✔
4635

4636
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
4,584,371✔
4637
  SInputColumnInfoData* pInput = &pCtx->input;
4,584,371✔
4638
  SColumnInfoData*      pCol = pInput->pData[0];
4,584,371✔
4639

4640
  if (IS_NULL_TYPE(pCol->info.type)) {
4,584,371✔
4641
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4642
    return TSDB_CODE_SUCCESS;
×
4643
  }
4644

4645
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
4,584,371✔
4646
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4647
  }
4648

4649
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,584,371✔
4650

4651
  int32_t start = pInput->startRowIndex;
4,584,371✔
4652
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
11,115,408✔
4653
    if (colDataIsNull_s(pCol, i)) continue;
13,062,074✔
4654
    char*        data = colDataGetData(pCol, i);
6,531,037✔
4655
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
6,531,037✔
4656
    if (pInputInfo->hasResult) {
6,531,037✔
4657
      spreadTransferInfo(pInputInfo, pInfo);
6,512,131✔
4658
    }
4659
  }
4660

4661
  if (pInfo->hasResult) {
4,584,371✔
4662
    GET_RES_INFO(pCtx)->numOfRes = 1;
4,565,465✔
4663
  }
4664

4665
  return TSDB_CODE_SUCCESS;
4,584,371✔
4666
}
4667

4668
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
52,258,429✔
4669
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
52,258,429✔
4670
  if (pInfo->hasResult == true) {
52,258,910✔
4671
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
51,536,425✔
4672
  } else {
4673
    GET_RES_INFO(pCtx)->isNullRes = 1;
722,004✔
4674
  }
4675
  return functionFinalize(pCtx, pBlock);
52,258,429✔
4676
}
4677

4678
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,543,481✔
4679
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,543,481✔
4680
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,543,481✔
4681
  int32_t              resultBytes = getSpreadInfoSize();
6,543,481✔
4682
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
6,543,481✔
4683

4684
  if (NULL == res) {
6,543,481✔
4685
    return terrno;
×
4686
  }
4687
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
6,543,481✔
4688
  varDataSetLen(res, resultBytes);
6,543,481✔
4689

4690
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
6,543,481✔
4691
  int32_t          code = TSDB_CODE_SUCCESS;
6,543,481✔
4692
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,543,481✔
4693
  if (NULL == pCol) {
6,543,481✔
4694
    code = terrno;
×
4695
    goto _exit;
×
4696
  }
4697

4698
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
6,543,481✔
4699
  if (TSDB_CODE_SUCCESS != code) {
6,543,481✔
4700
    goto _exit;
×
4701
  }
4702

4703
_exit:
6,543,481✔
4704
  taosMemoryFree(res);
6,543,481✔
4705
  return code;
6,543,481✔
4706
}
4707

4708
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4709
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4710
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4711

4712
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4713
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4714
  spreadTransferInfo(pSBuf, pDBuf);
×
4715
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4716
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4717
  return TSDB_CODE_SUCCESS;
×
4718
}
4719

4720
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4721

4722
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
2,015,166✔
4723
  pEnv->calcMemSize = sizeof(SElapsedInfo);
2,015,166✔
4724
  return true;
2,015,166✔
4725
}
4726

4727
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,017,068✔
4728
  if (pResultInfo->initialized) {
4,017,068✔
4729
    return TSDB_CODE_SUCCESS;
×
4730
  }
4731
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,017,962✔
4732
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4733
  }
4734

4735
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,017,581✔
4736
  pInfo->result = 0;
4,017,136✔
4737
  pInfo->min = TSKEY_MAX;
4,017,994✔
4738
  pInfo->max = 0;
4,017,549✔
4739

4740
  if (pCtx->numOfParams > 1) {
4,016,653✔
4741
    pInfo->timeUnit = pCtx->param[1].param.i;
2,321,916✔
4742
  } else {
4743
    pInfo->timeUnit = 1;
1,695,152✔
4744
  }
4745

4746
  return TSDB_CODE_SUCCESS;
4,017,994✔
4747
}
4748

4749
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
4,016,210✔
4750
  int32_t numOfElems = 0;
4,016,210✔
4751

4752
  // Only the pre-computing information loaded and actual data does not loaded
4753
  SInputColumnInfoData* pInput = &pCtx->input;
4,016,210✔
4754
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
4,017,104✔
4755

4756
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,016,723✔
4757

4758
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
4,016,208✔
4759
  if (numOfElems == 0) {
4,015,414✔
4760
    // for stream
4761
    if (pCtx->end.key != INT64_MIN) {
×
4762
      pInfo->max = pCtx->end.key + 1;
×
4763
    }
4764
    goto _elapsed_over;
×
4765
  }
4766

4767
  if (pInput->colDataSMAIsSet) {
4,015,414✔
4768
    if (pInfo->min == TSKEY_MAX) {
×
4769
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4770
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4771
    } else {
4772
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4773
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4774
      } else {
4775
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4776
      }
4777
    }
4778
  } else {  // computing based on the true data block
4779
    if (0 == pInput->numOfRows) {
4,016,691✔
4780
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4781
        if (pCtx->end.key != INT64_MIN) {
×
4782
          pInfo->min = pCtx->end.key;
×
4783
        }
4784
      } else {
4785
        if (pCtx->end.key != INT64_MIN) {
×
4786
          pInfo->max = pCtx->end.key + 1;
×
4787
        }
4788
      }
4789
      goto _elapsed_over;
×
4790
    }
4791

4792
    SColumnInfoData* pCol = pInput->pData[0];
4,014,571✔
4793

4794
    int32_t start = pInput->startRowIndex;
4,017,517✔
4795
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
4,015,795✔
4796
    if (pCtx->order == TSDB_ORDER_DESC) {
4,017,481✔
4797
      if (pCtx->start.key == INT64_MIN) {
31,202✔
4798
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
31,202✔
4799
      } else {
4800
        pInfo->max = pCtx->start.key + 1;
×
4801
      }
4802

4803
      if (pCtx->end.key == INT64_MIN) {
31,202✔
4804
        pInfo->min =
31,202✔
4805
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
31,202✔
4806
      } else {
4807
        pInfo->min = pCtx->end.key;
×
4808
      }
4809
    } else {
4810
      if (pCtx->start.key == INT64_MIN) {
3,985,453✔
4811
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
3,982,630✔
4812
      } else {
4813
        pInfo->min = pCtx->start.key;
3,304✔
4814
      }
4815

4816
      if (pCtx->end.key == INT64_MIN) {
3,986,760✔
4817
        pInfo->max =
3,931,168✔
4818
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
3,932,437✔
4819
      } else {
4820
        pInfo->max = pCtx->end.key + 1;
54,285✔
4821
      }
4822
    }
4823
  }
4824

4825
_elapsed_over:
4,017,549✔
4826
  // data in the check operation are all null, not output
4827
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
4,017,549✔
4828

4829
  return TSDB_CODE_SUCCESS;
4,014,931✔
4830
}
4831

4832
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4833
  pOutput->timeUnit = pInput->timeUnit;
×
4834
  if (pOutput->min > pInput->min) {
×
4835
    pOutput->min = pInput->min;
×
4836
  }
4837

4838
  if (pOutput->max < pInput->max) {
×
4839
    pOutput->max = pInput->max;
×
4840
  }
4841
}
×
4842

4843
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4844
  SInputColumnInfoData* pInput = &pCtx->input;
×
4845
  SColumnInfoData*      pCol = pInput->pData[0];
×
4846
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4847
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4848
  }
4849

4850
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4851

4852
  int32_t start = pInput->startRowIndex;
×
4853

4854
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4855
    char*         data = colDataGetData(pCol, i);
×
4856
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4857
    elapsedTransferInfo(pInputInfo, pInfo);
×
4858
  }
4859

4860
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4861
  return TSDB_CODE_SUCCESS;
×
4862
}
4863

4864
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,018,407✔
4865
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,018,407✔
4866
  double        result = (double)(pInfo->max - pInfo->min);
4,018,407✔
4867
  pInfo->result = fabs(result) / pInfo->timeUnit;
4,018,407✔
4868
  return functionFinalize(pCtx, pBlock);
4,018,407✔
4869
}
4870

4871
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4872
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4873
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4874
  int32_t              resultBytes = getElapsedInfoSize();
×
4875
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4876

4877
  if (NULL == res) {
×
4878
    return terrno;
×
4879
  }
4880
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4881
  varDataSetLen(res, resultBytes);
×
4882

4883
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4884
  int32_t          code = TSDB_CODE_SUCCESS;
×
4885
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4886
  if (NULL == pCol) {
×
4887
    code = terrno;
×
4888
    goto _exit;
×
4889
  }
4890

4891
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4892
  if (TSDB_CODE_SUCCESS != code) {
×
4893
    goto _exit;
×
4894
  }
4895
_exit:
×
4896
  taosMemoryFree(res);
×
4897
  return code;
×
4898
}
4899

4900
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4901
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4902
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4903

4904
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4905
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4906

4907
  elapsedTransferInfo(pSBuf, pDBuf);
×
4908
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4909
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4910
  return TSDB_CODE_SUCCESS;
×
4911
}
4912

4913
int32_t getHistogramInfoSize() {
676,866✔
4914
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
676,866✔
4915
}
4916

4917
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,222,481✔
4918
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
1,222,481✔
4919
  return true;
1,223,445✔
4920
}
4921

4922
static int8_t getHistogramBinType(char* binTypeStr) {
837,904✔
4923
  int8_t binType;
4924
  if (strcasecmp(binTypeStr, "user_input") == 0) {
837,904✔
4925
    binType = USER_INPUT_BIN;
148,106✔
4926
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
689,798✔
4927
    binType = LINEAR_BIN;
117,872✔
4928
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
571,926✔
4929
    binType = LOG_BIN;
571,926✔
4930
  } else {
4931
    binType = UNKNOWN_BIN;
×
4932
  }
4933

4934
  return binType;
837,904✔
4935
}
4936

4937
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
837,904✔
4938
  cJSON*  binDesc = cJSON_Parse(binDescStr);
837,904✔
4939
  int32_t numOfBins;
4940
  double* intervals;
4941
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
837,904✔
4942
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
689,798✔
4943
    int32_t startIndex;
4944
    if (numOfParams != 4) {
689,464✔
4945
      cJSON_Delete(binDesc);
×
4946
      return TSDB_CODE_FAILED;
×
4947
    }
4948

4949
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
689,464✔
4950
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
688,978✔
4951
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
688,644✔
4952
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
689,317✔
4953
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
689,459✔
4954

4955
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
688,983✔
4956
      cJSON_Delete(binDesc);
×
4957
      return TSDB_CODE_FAILED;
×
4958
    }
4959

4960
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
689,798✔
4961
      cJSON_Delete(binDesc);
×
4962
      return TSDB_CODE_FAILED;
×
4963
    }
4964

4965
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
689,317✔
4966
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
689,125✔
4967
      cJSON_Delete(binDesc);
×
4968
      return TSDB_CODE_FAILED;
×
4969
    }
4970

4971
    int32_t counter = (int32_t)count->valueint;
689,464✔
4972
    if (infinity->valueint == false) {
689,464✔
4973
      startIndex = 0;
176,784✔
4974
      numOfBins = counter + 1;
176,784✔
4975
    } else {
4976
      startIndex = 1;
513,014✔
4977
      numOfBins = counter + 3;
513,014✔
4978
    }
4979

4980
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
689,798✔
4981
    if (NULL == intervals) {
689,464✔
4982
      cJSON_Delete(binDesc);
×
4983
      qError("histogram function out of memory");
×
4984
      return terrno;
×
4985
    }
4986
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
689,464✔
4987
      // linear bin process
4988
      if (width->valuedouble == 0) {
117,872✔
4989
        taosMemoryFree(intervals);
×
4990
        cJSON_Delete(binDesc);
×
4991
        return TSDB_CODE_FAILED;
×
4992
      }
4993
      for (int i = 0; i < counter + 1; ++i) {
547,472✔
4994
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
429,600✔
4995
        if (isinf(intervals[startIndex])) {
429,600✔
4996
          taosMemoryFree(intervals);
×
4997
          cJSON_Delete(binDesc);
×
4998
          return TSDB_CODE_FAILED;
×
4999
        }
5000
        startIndex++;
429,600✔
5001
      }
5002
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
571,926✔
5003
      // log bin process
5004
      if (start->valuedouble == 0) {
571,592✔
5005
        taosMemoryFree(intervals);
×
5006
        cJSON_Delete(binDesc);
×
5007
        return TSDB_CODE_FAILED;
×
5008
      }
5009
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
571,253✔
UNCOV
5010
        taosMemoryFree(intervals);
×
5011
        cJSON_Delete(binDesc);
×
5012
        return TSDB_CODE_FAILED;
×
5013
      }
5014
      for (int i = 0; i < counter + 1; ++i) {
3,723,061✔
5015
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
3,150,801✔
5016
        if (isinf(intervals[startIndex])) {
3,151,621✔
5017
          taosMemoryFree(intervals);
×
5018
          cJSON_Delete(binDesc);
×
5019
          return TSDB_CODE_FAILED;
×
5020
        }
5021
        startIndex++;
3,151,469✔
5022
      }
5023
    } else {
5024
      taosMemoryFree(intervals);
×
5025
      cJSON_Delete(binDesc);
×
5026
      return TSDB_CODE_FAILED;
×
5027
    }
5028

5029
    if (infinity->valueint == true) {
690,132✔
5030
      intervals[0] = -INFINITY;
513,014✔
5031
      intervals[numOfBins - 1] = INFINITY;
512,533✔
5032
      // in case of desc bin orders, -inf/inf should be swapped
5033
      if (numOfBins < 4) {
513,014✔
5034
        return TSDB_CODE_FAILED;
×
5035
      }
5036
      if (intervals[1] > intervals[numOfBins - 2]) {
513,014✔
5037
        TSWAP(intervals[0], intervals[numOfBins - 1]);
463,882✔
5038
      }
5039
    }
5040
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
148,106✔
5041
    if (binType != USER_INPUT_BIN) {
148,106✔
5042
      cJSON_Delete(binDesc);
×
5043
      return TSDB_CODE_FAILED;
×
5044
    }
5045
    numOfBins = cJSON_GetArraySize(binDesc);
148,106✔
5046
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
148,106✔
5047
    if (NULL == intervals) {
148,106✔
5048
      cJSON_Delete(binDesc);
×
5049
      qError("histogram function out of memory");
×
5050
      return terrno;
×
5051
    }
5052
    cJSON* bin = binDesc->child;
148,106✔
5053
    if (bin == NULL) {
148,106✔
5054
      taosMemoryFree(intervals);
×
5055
      cJSON_Delete(binDesc);
×
5056
      return TSDB_CODE_FAILED;
×
5057
    }
5058
    int i = 0;
148,106✔
5059
    while (bin) {
462,326✔
5060
      intervals[i] = bin->valuedouble;
314,220✔
5061
      if (!cJSON_IsNumber(bin)) {
314,220✔
5062
        taosMemoryFree(intervals);
×
5063
        cJSON_Delete(binDesc);
×
5064
        return TSDB_CODE_FAILED;
×
5065
      }
5066
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
314,220✔
5067
        taosMemoryFree(intervals);
×
5068
        cJSON_Delete(binDesc);
×
5069
        return TSDB_CODE_FAILED;
×
5070
      }
5071
      bin = bin->next;
314,220✔
5072
      i++;
314,220✔
5073
    }
5074
  } else {
5075
    cJSON_Delete(binDesc);
×
5076
    return TSDB_CODE_FAILED;
×
5077
  }
5078

5079
  pInfo->numOfBins = numOfBins - 1;
836,608✔
5080
  pInfo->normalized = normalized;
837,570✔
5081
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
4,921,424✔
5082
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
4,084,527✔
5083
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
4,083,039✔
5084
    pInfo->bins[i].count = 0;
4,083,373✔
5085
  }
5086

5087
  taosMemoryFree(intervals);
837,231✔
5088
  cJSON_Delete(binDesc);
837,904✔
5089

5090
  return TSDB_CODE_SUCCESS;
837,570✔
5091
}
5092

5093
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
837,904✔
5094
  if (pResultInfo->initialized) {
837,904✔
5095
    return TSDB_CODE_SUCCESS;
×
5096
  }
5097
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
837,904✔
5098
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5099
  }
5100

5101
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
837,904✔
5102
  pInfo->numOfBins = 0;
837,904✔
5103
  pInfo->totalCount = 0;
837,904✔
5104
  pInfo->normalized = 0;
837,904✔
5105

5106
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
837,904✔
5107
  if (binTypeStr == NULL) {
837,904✔
5108
    return terrno;
×
5109
  }
5110
  int8_t binType = getHistogramBinType(binTypeStr);
837,904✔
5111
  taosMemoryFree(binTypeStr);
837,904✔
5112

5113
  if (binType == UNKNOWN_BIN) {
837,904✔
5114
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5115
  }
5116
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
837,904✔
5117
  if (binDesc == NULL) {
837,904✔
5118
    return terrno;
×
5119
  }
5120
  int64_t normalized = pCtx->param[3].param.i;
837,904✔
5121
  if (normalized != 0 && normalized != 1) {
837,904✔
5122
    taosMemoryFree(binDesc);
×
5123
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5124
  }
5125
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
837,904✔
5126
  if (TSDB_CODE_SUCCESS != code) {
837,570✔
5127
    taosMemoryFree(binDesc);
×
5128
    return code;
×
5129
  }
5130
  taosMemoryFree(binDesc);
837,570✔
5131

5132
  return TSDB_CODE_SUCCESS;
837,089✔
5133
}
5134

5135
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
952,806✔
5136
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
952,806✔
5137

5138
  SInputColumnInfoData* pInput = &pCtx->input;
952,801✔
5139
  SColumnInfoData*      pCol = pInput->pData[0];
952,806✔
5140

5141
  int32_t type = pInput->pData[0]->info.type;
953,140✔
5142

5143
  int32_t start = pInput->startRowIndex;
952,806✔
5144
  int32_t numOfRows = pInput->numOfRows;
952,806✔
5145

5146
  int32_t numOfElems = 0;
956,218✔
5147
  for (int32_t i = start; i < numOfRows + start; ++i) {
141,222,182✔
5148
    if (pCol->hasNull && colDataIsNull_f(pCol, i)) {
140,269,042✔
5149
      continue;
40,122,348✔
5150
    }
5151

5152
    numOfElems++;
100,137,525✔
5153

5154
    char*  data = colDataGetData(pCol, i);
100,137,525✔
5155
    double v;
5156
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pCol->info));
100,179,005✔
5157

5158
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
204,506,963✔
5159
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
176,032,488✔
5160
        pInfo->bins[k].count++;
71,700,329✔
5161
        pInfo->totalCount++;
71,699,846✔
5162
        break;
71,700,329✔
5163
      }
5164
    }
5165
  }
5166

5167
  if (!isPartial) {
953,140✔
5168
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
639,673✔
5169
  } else {
5170
    GET_RES_INFO(pCtx)->numOfRes = 1;
313,467✔
5171
  }
5172
  return TSDB_CODE_SUCCESS;
953,140✔
5173
}
5174

5175
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
639,339✔
5176

5177
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
313,467✔
5178

5179
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
199,107✔
5180
  pOutput->normalized = pInput->normalized;
199,107✔
5181
  pOutput->numOfBins = pInput->numOfBins;
199,107✔
5182
  pOutput->totalCount += pInput->totalCount;
199,107✔
5183
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
1,518,230✔
5184
    pOutput->bins[k].lower = pInput->bins[k].lower;
1,319,123✔
5185
    pOutput->bins[k].upper = pInput->bins[k].upper;
1,319,123✔
5186
    pOutput->bins[k].count += pInput->bins[k].count;
1,319,123✔
5187
  }
5188
}
199,107✔
5189

5190
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
199,107✔
5191
  SInputColumnInfoData* pInput = &pCtx->input;
199,107✔
5192
  SColumnInfoData*      pCol = pInput->pData[0];
199,107✔
5193
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
199,107✔
5194
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
5195
  }
5196

5197
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
199,107✔
5198

5199
  int32_t start = pInput->startRowIndex;
199,107✔
5200

5201
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
398,214✔
5202
    char*           data = colDataGetData(pCol, i);
199,107✔
5203
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
199,107✔
5204
    histogramTransferInfo(pInputInfo, pInfo);
199,107✔
5205
  }
5206

5207
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
199,107✔
5208
  return TSDB_CODE_SUCCESS;
199,107✔
5209
}
5210

5211
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
819,553✔
5212
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
819,553✔
5213
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
819,553✔
5214
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
819,553✔
5215
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
819,553✔
5216
  int32_t              code = TSDB_CODE_SUCCESS;
819,219✔
5217

5218
  int32_t currentRow = pBlock->info.rows;
819,219✔
5219
  if (NULL == pCol) {
819,219✔
5220
    return TSDB_CODE_OUT_OF_RANGE;
×
5221
  }
5222

5223
  if (pInfo->normalized) {
819,219✔
5224
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
2,283,784✔
5225
      if (pInfo->totalCount != 0) {
1,837,784✔
5226
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
1,221,596✔
5227
      } else {
5228
        pInfo->bins[k].percentage = 0;
616,188✔
5229
      }
5230
    }
5231
  }
5232

5233
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
4,795,047✔
5234
    int32_t len;
5235
    char    buf[512] = {0};
3,975,828✔
5236
    if (!pInfo->normalized) {
3,975,828✔
5237
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
2,137,563✔
5238
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
5239
                      pInfo->bins[i].upper, pInfo->bins[i].count);
5240
    } else {
5241
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
1,837,450✔
5242
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
5243
                      pInfo->bins[i].percentage);
5244
    }
5245
    varDataSetLen(buf, len);
3,975,828✔
5246
    code = colDataSetVal(pCol, currentRow, buf, false);
3,975,828✔
5247
    if (TSDB_CODE_SUCCESS != code) {
3,975,828✔
5248
      return code;
×
5249
    }
5250
    currentRow++;
3,975,828✔
5251
  }
5252

5253
  return code;
819,553✔
5254
}
5255

5256
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
199,107✔
5257
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
199,107✔
5258
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
199,107✔
5259
  int32_t              resultBytes = getHistogramInfoSize();
199,107✔
5260
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
199,107✔
5261

5262
  if (NULL == res) {
199,107✔
5263
    return terrno;
×
5264
  }
5265
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
199,107✔
5266
  varDataSetLen(res, resultBytes);
199,107✔
5267

5268
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
199,107✔
5269
  int32_t          code = TSDB_CODE_SUCCESS;
199,107✔
5270
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
199,107✔
5271
  if (NULL == pCol) {
199,107✔
5272
    code = terrno;
×
5273
    goto _exit;
×
5274
  }
5275
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
199,107✔
5276

5277
_exit:
199,107✔
5278
  taosMemoryFree(res);
199,107✔
5279
  return code;
199,107✔
5280
}
5281

5282
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5283
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5284
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5285

5286
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5287
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5288

5289
  histogramTransferInfo(pSBuf, pDBuf);
×
5290
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5291
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5292
  return TSDB_CODE_SUCCESS;
×
5293
}
5294

5295
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
237,095✔
5296

5297
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
3,443,128✔
5298
  pEnv->calcMemSize = sizeof(SHLLInfo);
3,443,128✔
5299
  return true;
3,444,573✔
5300
}
5301

5302
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
425,836,630✔
5303
  uint64_t hash = MurmurHash3_64(data, bytes);
425,836,630✔
5304
  int32_t  index = hash & HLL_BUCKET_MASK;
425,854,427✔
5305
  hash >>= HLL_BUCKET_BITS;
425,854,427✔
5306
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
425,854,427✔
5307
  uint64_t bit = 1;
425,854,427✔
5308
  uint8_t  count = 1;
425,854,427✔
5309
  while ((hash & bit) == 0) {
960,225,830✔
5310
    count++;
534,371,403✔
5311
    bit <<= 1;
534,371,403✔
5312
  }
5313
  *buk = index;
425,854,427✔
5314
  return count;
425,855,880✔
5315
}
5316

5317
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
8,212,451✔
5318
  uint64_t* word = (uint64_t*)buckets;
8,212,451✔
5319
  uint8_t*  bytes;
5320

5321
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
2,147,483,647✔
5322
    if (*word == 0) {
2,147,483,647✔
5323
      bucketHisto[0] += 8;
2,147,483,647✔
5324
    } else {
5325
      bytes = (uint8_t*)word;
56,564,384✔
5326
      bucketHisto[bytes[0]]++;
56,564,384✔
5327
      bucketHisto[bytes[1]]++;
83,566,006✔
5328
      bucketHisto[bytes[2]]++;
83,565,525✔
5329
      bucketHisto[bytes[3]]++;
83,565,525✔
5330
      bucketHisto[bytes[4]]++;
83,566,006✔
5331
      bucketHisto[bytes[5]]++;
83,566,006✔
5332
      bucketHisto[bytes[6]]++;
83,565,525✔
5333
      bucketHisto[bytes[7]]++;
83,565,525✔
5334
    }
5335
    word++;
2,147,483,647✔
5336
  }
5337
}
3,630,203✔
5338
static double hllTau(double x) {
8,212,932✔
5339
  if (x == 0. || x == 1.) return 0.;
8,212,932✔
5340
  double zPrime;
5341
  double y = 1.0;
×
5342
  double z = 1 - x;
×
5343
  do {
5344
    x = sqrt(x);
×
5345
    zPrime = z;
×
5346
    y *= 0.5;
×
5347
    z -= pow(1 - x, 2) * y;
×
5348
  } while (zPrime != z);
×
5349
  return z / 3;
×
5350
}
5351

5352
static double hllSigma(double x) {
8,213,413✔
5353
  if (x == 1.0) return INFINITY;
8,213,413✔
5354
  double zPrime;
5355
  double y = 1;
7,006,270✔
5356
  double z = x;
7,006,270✔
5357
  do {
5358
    x *= x;
136,029,578✔
5359
    zPrime = z;
136,029,578✔
5360
    z += x * y;
136,029,578✔
5361
    y += y;
136,029,578✔
5362
  } while (zPrime != z);
136,029,578✔
5363
  return z;
7,006,270✔
5364
}
5365

5366
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
5367
// sketches"
5368
static uint64_t hllCountCnt(uint8_t* buckets) {
8,212,451✔
5369
  double  m = HLL_BUCKETS;
8,212,451✔
5370
  int32_t buckethisto[64] = {0};
8,212,451✔
5371
  hllBucketHisto(buckets, buckethisto);
8,212,932✔
5372

5373
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
8,212,932✔
5374
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
418,852,317✔
5375
    z += buckethisto[j];
410,638,904✔
5376
    z *= 0.5;
410,639,385✔
5377
  }
5378

5379
  z += m * hllSigma(buckethisto[0] / (double)m);
8,213,413✔
5380
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
8,213,413✔
5381

5382
  return (uint64_t)E;
8,213,413✔
5383
}
5384

5385
int32_t hllFunction(SqlFunctionCtx* pCtx) {
8,391,319✔
5386
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,391,319✔
5387

5388
  SInputColumnInfoData* pInput = &pCtx->input;
8,390,836✔
5389
  SColumnInfoData*      pCol = pInput->pData[0];
8,390,357✔
5390

5391
  int32_t type = pCol->info.type;
8,390,357✔
5392
  int32_t bytes = pCol->info.bytes;
8,389,393✔
5393

5394
  int32_t start = pInput->startRowIndex;
8,388,914✔
5395
  int32_t numOfRows = pInput->numOfRows;
8,392,762✔
5396

5397
  int32_t numOfElems = 0;
8,386,992✔
5398
  if (IS_NULL_TYPE(type)) {
8,386,992✔
5399
    goto _hll_over;
127,733✔
5400
  }
5401

5402
  for (int32_t i = start; i < numOfRows + start; ++i) {
493,479,294✔
5403
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
550,569,097✔
5404
      continue;
59,398,290✔
5405
    }
5406

5407
    numOfElems++;
425,811,634✔
5408

5409
    char* data = colDataGetData(pCol, i);
425,811,634✔
5410
    if (IS_VAR_DATA_TYPE(type)) {
425,844,811✔
5411
      if (IS_STR_DATA_BLOB(type)) {
68,523,670✔
5412
        bytes = blobDataLen(data);
964✔
5413
        data = blobDataVal(data);
×
5414
      } else {
5415
        bytes = varDataLen(data);
68,522,706✔
5416
        data = varDataVal(data);
68,522,225✔
5417
      }
5418
    }
5419

5420
    int32_t index = 0;
425,843,847✔
5421
    uint8_t count = hllCountNum(data, bytes, &index);
425,539,352✔
5422
    uint8_t oldcount = pInfo->buckets[index];
425,828,928✔
5423
    if (count > oldcount) {
425,836,145✔
5424
      pInfo->buckets[index] = count;
87,686,964✔
5425
    }
5426
  }
5427

5428
_hll_over:
8,259,261✔
5429
  pInfo->totalCount += numOfElems;
8,386,994✔
5430

5431
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
8,392,764✔
5432
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
220,851✔
5433
  } else {
5434
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
8,172,394✔
5435
  }
5436

5437
  return TSDB_CODE_SUCCESS;
8,390,840✔
5438
}
5439

5440
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
237,459✔
5441
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
2,147,483,647✔
5442
    if (pOutput->buckets[k] < pInput->buckets[k]) {
2,147,483,647✔
5443
      pOutput->buckets[k] = pInput->buckets[k];
21,265,649✔
5444
    }
5445
  }
5446
  pOutput->totalCount += pInput->totalCount;
305,197✔
5447
}
237,459✔
5448

5449
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
237,459✔
5450
  SInputColumnInfoData* pInput = &pCtx->input;
237,459✔
5451
  SColumnInfoData*      pCol = pInput->pData[0];
237,459✔
5452

5453
  if (IS_NULL_TYPE(pCol->info.type)) {
237,459✔
5454
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
5455
    return TSDB_CODE_SUCCESS;
×
5456
  }
5457

5458
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
237,459✔
5459
    return TSDB_CODE_SUCCESS;
×
5460
  }
5461

5462
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
237,459✔
5463

5464
  int32_t start = pInput->startRowIndex;
237,459✔
5465

5466
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
474,918✔
5467
    if (colDataIsNull_s(pCol, i)) continue;
474,918✔
5468
    char*     data = colDataGetData(pCol, i);
237,459✔
5469
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
237,459✔
5470
    hllTransferInfo(pInputInfo, pInfo);
237,459✔
5471
  }
5472

5473
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
237,459✔
5474
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
67✔
5475
  } else {
5476
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
237,392✔
5477
  }
5478

5479
  return TSDB_CODE_SUCCESS;
237,459✔
5480
}
5481

5482
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,213,413✔
5483
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
8,213,413✔
5484

5485
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,213,413✔
5486
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
8,212,932✔
5487
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
8,212,932✔
5488
    pInfo->numOfRes = 1;
986,761✔
5489
  }
5490

5491
  return functionFinalize(pCtx, pBlock);
8,212,932✔
5492
}
5493

5494
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
237,459✔
5495
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
237,459✔
5496
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
237,459✔
5497
  int32_t              resultBytes = getHLLInfoSize();
237,095✔
5498
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
237,095✔
5499

5500
  if (NULL == res) {
237,459✔
5501
    return terrno;
×
5502
  }
5503
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
237,459✔
5504
  varDataSetLen(res, resultBytes);
237,459✔
5505

5506
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
237,459✔
5507
  int32_t          code = TSDB_CODE_SUCCESS;
237,459✔
5508
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
237,459✔
5509
  if (NULL == pCol) {
237,459✔
5510
    code = terrno;
×
5511
    goto _exit;
×
5512
  }
5513

5514
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
237,459✔
5515

5516
_exit:
237,459✔
5517
  taosMemoryFree(res);
237,459✔
5518
  return code;
237,459✔
5519
}
5520

5521
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
5522
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
5523
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
5524

5525
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
5526
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
5527

5528
  hllTransferInfo(pSBuf, pDBuf);
×
5529
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
5530
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
5531
  return TSDB_CODE_SUCCESS;
×
5532
}
5533

5534
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,175,412✔
5535
  pEnv->calcMemSize = sizeof(SStateInfo);
1,175,412✔
5536
  return true;
1,175,412✔
5537
}
5538

5539
static int8_t getStateOpType(char* opStr) {
1,197,082✔
5540
  int8_t opType;
5541
  if (strncasecmp(opStr, "LT", 2) == 0) {
1,197,082✔
5542
    opType = STATE_OPER_LT;
316,889✔
5543
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
880,193✔
5544
    opType = STATE_OPER_GT;
176,075✔
5545
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
704,118✔
5546
    opType = STATE_OPER_LE;
97,016✔
5547
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
607,102✔
5548
    opType = STATE_OPER_GE;
97,892✔
5549
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
509,210✔
5550
    opType = STATE_OPER_NE;
412,194✔
5551
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
97,016✔
5552
    opType = STATE_OPER_EQ;
97,016✔
5553
  } else {
5554
    opType = STATE_OPER_INVALID;
×
5555
  }
5556

5557
  return opType;
1,197,082✔
5558
}
5559

5560
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
62,922,910✔
5561
  char* data = colDataGetData(pCol, index);
62,922,910✔
5562
  switch (pCol->info.type) {
62,922,910✔
5563
    case TSDB_DATA_TYPE_TINYINT: {
603,948✔
5564
      int8_t v = *(int8_t*)data;
603,948✔
5565
      STATE_COMP(op, v, param);
603,948✔
5566
      break;
×
5567
    }
5568
    case TSDB_DATA_TYPE_UTINYINT: {
552,960✔
5569
      uint8_t v = *(uint8_t*)data;
552,960✔
5570
      STATE_COMP(op, v, param);
552,960✔
5571
      break;
×
5572
    }
5573
    case TSDB_DATA_TYPE_SMALLINT: {
5,880,776✔
5574
      int16_t v = *(int16_t*)data;
5,880,776✔
5575
      STATE_COMP(op, v, param);
5,880,776✔
5576
      break;
×
5577
    }
5578
    case TSDB_DATA_TYPE_USMALLINT: {
552,960✔
5579
      uint16_t v = *(uint16_t*)data;
552,960✔
5580
      STATE_COMP(op, v, param);
552,960✔
5581
      break;
×
5582
    }
5583
    case TSDB_DATA_TYPE_INT: {
26,178,313✔
5584
      int32_t v = *(int32_t*)data;
26,178,313✔
5585
      STATE_COMP(op, v, param);
26,178,313✔
5586
      break;
×
5587
    }
5588
    case TSDB_DATA_TYPE_UINT: {
552,960✔
5589
      uint32_t v = *(uint32_t*)data;
552,960✔
5590
      STATE_COMP(op, v, param);
552,960✔
5591
      break;
×
5592
    }
5593
    case TSDB_DATA_TYPE_BIGINT: {
616,434✔
5594
      int64_t v = *(int64_t*)data;
616,434✔
5595
      STATE_COMP(op, v, param);
616,434✔
5596
      break;
×
5597
    }
5598
    case TSDB_DATA_TYPE_UBIGINT: {
552,960✔
5599
      uint64_t v = *(uint64_t*)data;
552,960✔
5600
      STATE_COMP(op, v, param);
552,960✔
5601
      break;
×
5602
    }
5603
    case TSDB_DATA_TYPE_FLOAT: {
606,376✔
5604
      float v = *(float*)data;
606,376✔
5605
      STATE_COMP(op, v, param);
606,376✔
5606
      break;
×
5607
    }
5608
    case TSDB_DATA_TYPE_DOUBLE: {
26,825,223✔
5609
      double v = *(double*)data;
26,825,223✔
5610
      STATE_COMP(op, v, param);
26,825,223✔
5611
      break;
×
5612
    }
5613
    default: {
×
5614
      return false;
×
5615
    }
5616
  }
5617
  return false;
×
5618
}
5619

5620
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
110,725✔
5621
  int32_t              code = TSDB_CODE_SUCCESS;
110,725✔
5622
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
110,725✔
5623
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
110,725✔
5624

5625
  SInputColumnInfoData* pInput = &pCtx->input;
110,725✔
5626
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
110,725✔
5627

5628
  SColumnInfoData* pInputCol = pInput->pData[0];
110,725✔
5629

5630
  int32_t          numOfElems = 0;
110,725✔
5631
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
110,725✔
5632

5633
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
110,725✔
5634
  if (STATE_OPER_INVALID == op) {
110,725✔
5635
    return 0;
×
5636
  }
5637

5638
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
12,569,976✔
5639
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
12,458,912✔
5640
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5641
    } else {
5642
      pInfo->prevTs = tsList[i];
12,457,895✔
5643
    }
5644

5645
    pInfo->isPrevTsSet = true;
12,458,573✔
5646
    numOfElems++;
12,454,844✔
5647

5648
    if (colDataIsNull_f(pInputCol, i)) {
12,454,844✔
5649
      colDataSetNULL(pOutput, i);
5,108,421✔
5650
      // handle selectivity
5651
      if (pCtx->subsidiaries.num > 0) {
5,110,794✔
5652
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,483✔
5653
        if (TSDB_CODE_SUCCESS != code) {
3,483✔
5654
          return code;
×
5655
        }
5656
      }
5657
      continue;
5,109,777✔
5658
    }
5659

5660
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
7,349,474✔
5661

5662
    int64_t output = -1;
7,349,474✔
5663
    if (ret) {
7,349,474✔
5664
      output = ++pInfo->count;
3,235,709✔
5665
    } else {
5666
      pInfo->count = 0;
4,113,765✔
5667
    }
5668
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
7,349,474✔
5669
    if (TSDB_CODE_SUCCESS != code) {
7,349,474✔
5670
      return code;
×
5671
    }
5672

5673
    // handle selectivity
5674
    if (pCtx->subsidiaries.num > 0) {
7,349,474✔
5675
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
41,796✔
5676
      if (TSDB_CODE_SUCCESS != code) {
41,796✔
5677
        return code;
×
5678
      }
5679
    }
5680
  }
5681

5682
  pResInfo->numOfRes = numOfElems;
110,725✔
5683
  return TSDB_CODE_SUCCESS;
110,725✔
5684
}
5685

5686
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
1,086,357✔
5687
  int32_t              code = TSDB_CODE_SUCCESS;
1,086,357✔
5688
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,086,357✔
5689
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,086,357✔
5690

5691
  SInputColumnInfoData* pInput = &pCtx->input;
1,085,876✔
5692
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
1,086,357✔
5693

5694
  SColumnInfoData* pInputCol = pInput->pData[0];
1,086,357✔
5695

5696
  int32_t          numOfElems = 0;
1,085,395✔
5697
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,085,395✔
5698

5699
  // TODO: process timeUnit for different db precisions
5700
  int32_t timeUnit = 1;
1,086,357✔
5701
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
1,086,357✔
5702
    timeUnit = pCtx->param[3].param.i;
898,116✔
5703
  }
5704

5705
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
1,085,876✔
5706
  if (STATE_OPER_INVALID == op) {
1,085,876✔
5707
    return TSDB_CODE_INVALID_PARA;
×
5708
  }
5709

5710
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
94,332,907✔
5711
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
93,247,031✔
5712
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5713
    } else {
5714
      pInfo->prevTs = tsList[i];
93,246,069✔
5715
    }
5716

5717
    pInfo->isPrevTsSet = true;
93,247,031✔
5718
    numOfElems++;
93,247,365✔
5719

5720
    if (colDataIsNull_f(pInputCol, i)) {
93,247,365✔
5721
      colDataSetNULL(pOutput, i);
37,681,090✔
5722
      // handle selectivity
5723
      if (pCtx->subsidiaries.num > 0) {
37,708,532✔
5724
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
6,791✔
5725
        if (TSDB_CODE_SUCCESS != code) {
6,791✔
5726
          return code;
×
5727
        }
5728
      }
5729
      continue;
37,708,532✔
5730
    }
5731

5732
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
55,573,436✔
5733
    int64_t output = -1;
55,573,436✔
5734
    if (ret) {
55,573,436✔
5735
      if (pInfo->durationStart == 0) {
42,834,828✔
5736
        output = 0;
8,140,687✔
5737
        pInfo->durationStart = tsList[i];
8,140,687✔
5738
      } else {
5739
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
34,694,141✔
5740
      }
5741
    } else {
5742
      pInfo->durationStart = 0;
12,738,608✔
5743
    }
5744
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
55,573,436✔
5745
    if (TSDB_CODE_SUCCESS != code) {
55,573,436✔
5746
      return code;
×
5747
    }
5748

5749
    // handle selectivity
5750
    if (pCtx->subsidiaries.num > 0) {
55,573,436✔
5751
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
81,492✔
5752
      if (TSDB_CODE_SUCCESS != code) {
81,492✔
5753
        return code;
×
5754
      }
5755
    }
5756
  }
5757

5758
  pResInfo->numOfRes = numOfElems;
1,086,357✔
5759
  return TSDB_CODE_SUCCESS;
1,086,357✔
5760
}
5761

5762
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
599,840✔
5763
  pEnv->calcMemSize = sizeof(SSumRes);
599,840✔
5764
  return true;
599,840✔
5765
}
5766

5767
int32_t csumFunction(SqlFunctionCtx* pCtx) {
671,613✔
5768
  int32_t              code = TSDB_CODE_SUCCESS;
671,613✔
5769
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
671,613✔
5770
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
671,613✔
5771

5772
  SInputColumnInfoData* pInput = &pCtx->input;
671,613✔
5773
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
671,613✔
5774

5775
  SColumnInfoData* pInputCol = pInput->pData[0];
671,613✔
5776
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
671,613✔
5777

5778
  int32_t numOfElems = 0;
671,613✔
5779
  int32_t type = pInputCol->info.type;
671,613✔
5780
  int32_t startOffset = pCtx->offset;
671,613✔
5781
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
100,069,796✔
5782
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
99,390,571✔
5783
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
6,237✔
5784
    } else {
5785
      pSumRes->prevTs = tsList[i];
99,385,301✔
5786
    }
5787
    pSumRes->isPrevTsSet = true;
99,382,988✔
5788

5789
    int32_t pos = startOffset + numOfElems;
99,382,841✔
5790
    if (colDataIsNull_f(pInputCol, i)) {
99,382,841✔
5791
      // colDataSetNULL(pOutput, i);
5792
      continue;
70,183,687✔
5793
    }
5794

5795
    char* data = colDataGetData(pInputCol, i);
29,214,496✔
5796
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
31,703,724✔
5797
      int64_t v;
5798
      GET_TYPED_DATA(v, int64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
2,489,228✔
5799
      pSumRes->isum += v;
2,489,228✔
5800
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
2,489,228✔
5801
      if (TSDB_CODE_SUCCESS != code) {
2,489,228✔
5802
        return code;
×
5803
      }
5804
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
26,792,112✔
5805
      uint64_t v;
5806
      GET_TYPED_DATA(v, uint64_t, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
66,844✔
5807
      pSumRes->usum += v;
66,844✔
5808
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
66,844✔
5809
      if (TSDB_CODE_SUCCESS != code) {
66,844✔
5810
        return code;
×
5811
      }
5812
    } else if (IS_FLOAT_TYPE(type)) {
26,658,424✔
5813
      double v;
5814
      GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
26,658,424✔
5815
      pSumRes->dsum += v;
26,658,424✔
5816
      // check for overflow
5817
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
26,658,424✔
5818
        colDataSetNULL(pOutput, pos);
788✔
5819
      } else {
5820
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
26,657,636✔
5821
        if (TSDB_CODE_SUCCESS != code) {
26,657,636✔
5822
          return code;
×
5823
        }
5824
      }
5825
    }
5826

5827
    // handle selectivity
5828
    if (pCtx->subsidiaries.num > 0) {
29,214,496✔
5829
      code = appendSelectivityValue(pCtx, i, pos);
20,292✔
5830
      if (TSDB_CODE_SUCCESS != code) {
20,292✔
5831
        return code;
×
5832
      }
5833
    }
5834

5835
    numOfElems++;
29,214,496✔
5836
  }
5837

5838
  pResInfo->numOfRes = numOfElems;
665,376✔
5839
  return TSDB_CODE_SUCCESS;
665,376✔
5840
}
5841

5842
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
348,531✔
5843
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
348,531✔
5844
  return true;
348,531✔
5845
}
5846

5847
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
762,747✔
5848
  if (pResultInfo->initialized) {
762,747✔
5849
    return TSDB_CODE_SUCCESS;
334,261✔
5850
  }
5851
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
428,486✔
5852
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5853
  }
5854

5855
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
428,486✔
5856
  pInfo->pos = 0;
428,486✔
5857
  pInfo->sum = 0;
428,486✔
5858
  pInfo->prevTs = -1;
428,486✔
5859
  pInfo->isPrevTsSet = false;
428,486✔
5860
  pInfo->numOfPoints = pCtx->param[1].param.i;
428,486✔
5861
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
428,486✔
5862
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5863
  }
5864
  pInfo->pointsMeet = false;
428,486✔
5865

5866
  return TSDB_CODE_SUCCESS;
428,486✔
5867
}
5868

5869
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
414,216✔
5870
  int32_t              code = TSDB_CODE_SUCCESS;
414,216✔
5871
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
414,216✔
5872
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
413,750✔
5873

5874
  SInputColumnInfoData* pInput = &pCtx->input;
414,216✔
5875
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
414,216✔
5876

5877
  SColumnInfoData* pInputCol = pInput->pData[0];
413,750✔
5878
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
414,216✔
5879
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
414,216✔
5880

5881
  int32_t numOfElems = 0;
413,750✔
5882
  int32_t type = pInputCol->info.type;
413,750✔
5883
  int32_t startOffset = pCtx->offset;
414,216✔
5884
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
64,389,412✔
5885
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
63,975,196✔
5886
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5887
    } else {
5888
      pInfo->prevTs = tsList[i];
63,974,730✔
5889
    }
5890
    pInfo->isPrevTsSet = true;
63,975,662✔
5891

5892
    int32_t pos = startOffset + numOfElems;
63,975,662✔
5893
    if (colDataIsNull_f(pInputCol, i)) {
63,975,662✔
5894
      // colDataSetNULL(pOutput, i);
5895
      continue;
54,595,155✔
5896
    }
5897

5898
    char*  data = colDataGetData(pInputCol, i);
9,387,031✔
5899
    double v;
5900
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
9,387,031✔
5901

5902
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
9,387,031✔
5903
      pInfo->points[pInfo->pos] = v;
8,903,936✔
5904
      pInfo->sum += v;
8,903,936✔
5905
    } else {
5906
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
483,095✔
5907
        pInfo->sum += v;
77,354✔
5908
        pInfo->pointsMeet = true;
77,354✔
5909
      } else {
5910
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
405,741✔
5911
      }
5912

5913
      pInfo->points[pInfo->pos] = v;
483,095✔
5914
      double result = pInfo->sum / pInfo->numOfPoints;
483,095✔
5915
      // check for overflow
5916
      if (isinf(result) || isnan(result)) {
483,095✔
5917
        colDataSetNULL(pOutput, pos);
×
5918
      } else {
5919
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
483,095✔
5920
        if (TSDB_CODE_SUCCESS != code) {
483,095✔
5921
          return code;
×
5922
        }
5923
      }
5924

5925
      // handle selectivity
5926
      if (pCtx->subsidiaries.num > 0) {
483,095✔
5927
        code = appendSelectivityValue(pCtx, i, pos);
27,090✔
5928
        if (TSDB_CODE_SUCCESS != code) {
27,090✔
5929
          return code;
×
5930
        }
5931
      }
5932

5933
      numOfElems++;
483,095✔
5934
    }
5935

5936
    pInfo->pos++;
9,387,031✔
5937
    if (pInfo->pos == pInfo->numOfPoints) {
9,387,031✔
5938
      pInfo->pos = 0;
124,602✔
5939
    }
5940
  }
5941

5942
  pResInfo->numOfRes = numOfElems;
414,216✔
5943
  return TSDB_CODE_SUCCESS;
414,216✔
5944
}
5945

5946
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
3,505,404✔
5947
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,505,404✔
5948
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,505,404✔
5949

5950
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
3,505,404✔
5951
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
3,505,404✔
5952

5953
  return pInfo;
3,505,404✔
5954
}
5955

5956
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
703,301✔
5957
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
703,301✔
5958
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
703,929✔
5959
  int32_t      numOfSamples = pVal->datum.i;
702,820✔
5960
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
702,820✔
5961
  return true;
702,005✔
5962
}
5963

5964
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,455,787✔
5965
  if (pResultInfo->initialized) {
1,455,787✔
5966
    return TSDB_CODE_SUCCESS;
×
5967
  }
5968
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,455,787✔
5969
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5970
  }
5971

5972
  taosSeedRand(taosSafeRand());
1,455,787✔
5973

5974
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
1,455,787✔
5975
  pInfo->samples = pCtx->param[1].param.i;
1,455,787✔
5976
  pInfo->totalPoints = 0;
1,455,787✔
5977
  pInfo->numSampled = 0;
1,455,787✔
5978
  pInfo->colType = pCtx->resDataInfo.type;
1,455,787✔
5979
  pInfo->colBytes = pCtx->resDataInfo.bytes;
1,455,787✔
5980
  pInfo->nullTuplePos.pageId = -1;
1,455,787✔
5981
  pInfo->nullTupleSaved = false;
1,455,787✔
5982
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
1,455,787✔
5983
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
1,455,787✔
5984

5985
  return TSDB_CODE_SUCCESS;
1,455,787✔
5986
}
5987

5988
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
67,535,708✔
5989
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
67,535,708✔
5990
}
67,537,151✔
5991

5992
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
79,620,716✔
5993
  pInfo->totalPoints++;
79,620,716✔
5994
  if (pInfo->numSampled < pInfo->samples) {
79,620,716✔
5995
    sampleAssignResult(pInfo, data, pInfo->numSampled);
55,825,572✔
5996
    if (pCtx->subsidiaries.num > 0) {
55,825,091✔
5997
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
892,154✔
5998
      if (code != TSDB_CODE_SUCCESS) {
892,154✔
5999
        return code;
×
6000
      }
6001
    }
6002
    pInfo->numSampled++;
55,825,572✔
6003
  } else {
6004
    int32_t j = taosRand() % (pInfo->totalPoints);
23,796,106✔
6005
    if (j < pInfo->samples) {
23,796,106✔
6006
      sampleAssignResult(pInfo, data, j);
11,713,022✔
6007
      if (pCtx->subsidiaries.num > 0) {
11,713,022✔
6008
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
293,135✔
6009
        if (code != TSDB_CODE_SUCCESS) {
290,249✔
6010
          return code;
×
6011
        }
6012
      }
6013
    }
6014
  }
6015

6016
  return TSDB_CODE_SUCCESS;
79,618,792✔
6017
}
6018

6019
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
2,050,098✔
6020
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,050,098✔
6021
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
2,050,098✔
6022

6023
  SInputColumnInfoData* pInput = &pCtx->input;
2,050,098✔
6024

6025
  SColumnInfoData* pInputCol = pInput->pData[0];
2,050,098✔
6026
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
109,010,998✔
6027
    if (colDataIsNull_s(pInputCol, i)) {
213,926,129✔
6028
      continue;
27,343,551✔
6029
    }
6030

6031
    char*   data = colDataGetData(pInputCol, i);
79,620,716✔
6032
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
79,620,235✔
6033
    if (code != TSDB_CODE_SUCCESS) {
79,617,349✔
6034
      return code;
×
6035
    }
6036
  }
6037

6038
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,050,098✔
6039
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
1,551✔
6040
    if (code != TSDB_CODE_SUCCESS) {
1,551✔
6041
      return code;
×
6042
    }
6043
    pInfo->nullTupleSaved = true;
1,551✔
6044
  }
6045

6046
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
2,050,098✔
6047
  return TSDB_CODE_SUCCESS;
2,050,098✔
6048
}
6049

6050
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,455,787✔
6051
  int32_t              code = TSDB_CODE_SUCCESS;
1,455,787✔
6052
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
1,455,787✔
6053

6054
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
1,455,787✔
6055
  pEntryInfo->complete = true;
1,455,306✔
6056

6057
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,455,306✔
6058
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,455,787✔
6059
  if (NULL == pCol) {
1,455,787✔
6060
    return TSDB_CODE_OUT_OF_RANGE;
×
6061
  }
6062

6063
  int32_t currentRow = pBlock->info.rows;
1,455,787✔
6064
  if (pInfo->numSampled == 0) {
1,455,787✔
6065
    colDataSetNULL(pCol, currentRow);
193,696✔
6066
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
193,696✔
6067
    return code;
193,696✔
6068
  }
6069
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
57,087,663✔
6070
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
55,826,534✔
6071
    if (TSDB_CODE_SUCCESS != code) {
55,827,977✔
6072
      return code;
×
6073
    }
6074
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
55,827,977✔
6075
    if (TSDB_CODE_SUCCESS != code) {
55,825,572✔
6076
      return code;
×
6077
    }
6078
  }
6079

6080
  return code;
1,262,091✔
6081
}
6082

6083
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6084
#if 0
6085
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
6086
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
6087
  int32_t      numOfPoints = pVal->datum.i;
6088
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
6089
#endif
6090
  return true;
×
6091
}
6092

6093
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
6094
#if 0
6095
  if (!functionSetup(pCtx, pResultInfo)) {
6096
    return false;
6097
  }
6098

6099
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6100
  pInfo->numAdded = 0;
6101
  pInfo->numOfPoints = pCtx->param[1].param.i;
6102
  if (pCtx->numOfParams == 4) {
6103
    pInfo->offset = pCtx->param[2].param.i;
6104
  } else {
6105
    pInfo->offset = 0;
6106
  }
6107
  pInfo->colType = pCtx->resDataInfo.type;
6108
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6109
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
6110
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
6111
    return false;
6112
  }
6113

6114
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
6115
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
6116

6117
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
6118
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6119
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
6120
    pInfo->pItems[i]->isNull = false;
6121
  }
6122
#endif
6123
  return TSDB_CODE_SUCCESS;
×
6124
}
6125

6126
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
6127
#if 0
6128
  pItem->timestamp = ts;
6129
  if (isNull) {
6130
    pItem->isNull = true;
6131
  } else {
6132
    pItem->isNull = false;
6133
    memcpy(pItem->data, data, colBytes);
6134
  }
6135
#endif
6136
}
×
6137

6138
#if 0
6139
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
6140
  STailItem* d1 = *(STailItem**)p1;
6141
  STailItem* d2 = *(STailItem**)p2;
6142
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
6143
}
6144

6145
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
6146
  STailItem** pList = pInfo->pItems;
6147
  if (pInfo->numAdded < pInfo->numOfPoints) {
6148
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
6149
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
6150
    pInfo->numAdded++;
6151
  } else if (pList[0]->timestamp < ts) {
6152
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
6153
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
6154
  }
6155
}
6156
#endif
6157

6158
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
6159
#if 0
6160
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6161
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6162

6163
  SInputColumnInfoData* pInput = &pCtx->input;
6164
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
6165

6166
  SColumnInfoData* pInputCol = pInput->pData[0];
6167
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6168

6169
  int32_t startOffset = pCtx->offset;
6170
  if (pInfo->offset >= pInput->numOfRows) {
6171
    return 0;
6172
  } else {
6173
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
6174
  }
6175
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
6176
    char* data = colDataGetData(pInputCol, i);
6177
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
6178
  }
6179

6180
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
6181

6182
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6183
    int32_t    pos = startOffset + i;
6184
    STailItem* pItem = pInfo->pItems[i];
6185
    if (pItem->isNull) {
6186
      colDataSetNULL(pOutput, pos);
6187
    } else {
6188
      colDataSetVal(pOutput, pos, pItem->data, false);
6189
    }
6190
  }
6191

6192
  return pInfo->numOfPoints;
6193
#endif
6194
  return 0;
×
6195
}
6196

6197
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
6198
#if 0
6199
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6200
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
6201
  pEntryInfo->complete = true;
6202

6203
  int32_t type = pCtx->input.pData[0]->info.type;
6204
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
6205

6206
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6207

6208
  // todo assign the tag value and the corresponding row data
6209
  int32_t currentRow = pBlock->info.rows;
6210
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
6211
    STailItem* pItem = pInfo->pItems[i];
6212
    colDataSetVal(pCol, currentRow, pItem->data, false);
6213
    currentRow += 1;
6214
  }
6215

6216
  return pEntryInfo->numOfRes;
6217
#endif
6218
  return 0;
×
6219
}
6220

6221
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
6222
#if 0
6223
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
6224
#endif
6225
  return true;
×
6226
}
6227

6228
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
6229
#if 0
6230
  if (!functionSetup(pCtx, pResInfo)) {
6231
    return false;
6232
  }
6233

6234
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6235
  pInfo->numOfPoints = 0;
6236
  pInfo->colType = pCtx->resDataInfo.type;
6237
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6238
  if (pInfo->pHash != NULL) {
6239
    taosHashClear(pInfo->pHash);
6240
  } else {
6241
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
6242
  }
6243
#endif
6244
  return TSDB_CODE_SUCCESS;
×
6245
}
6246

6247
#if 0
6248
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
6249
  // handle null elements
6250
  if (isNull == true) {
6251
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
6252
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
6253
    if (pInfo->hasNull == false && pItem->isNull == false) {
6254
      pItem->timestamp = ts;
6255
      pItem->isNull = true;
6256
      pInfo->numOfPoints++;
6257
      pInfo->hasNull = true;
6258
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
6259
      pItem->timestamp = ts;
6260
    }
6261
    return;
6262
  }
6263

6264
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
6265
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
6266
  if (pHashItem == NULL) {
6267
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
6268
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
6269
    pItem->timestamp = ts;
6270
    memcpy(pItem->data, data, pInfo->colBytes);
6271

6272
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
6273
    pInfo->numOfPoints++;
6274
  } else if (pHashItem->timestamp > ts) {
6275
    pHashItem->timestamp = ts;
6276
  }
6277
}
6278
#endif
6279

6280
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
6281
#if 0
6282
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6283
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6284

6285
  SInputColumnInfoData* pInput = &pCtx->input;
6286
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
6287

6288
  SColumnInfoData* pInputCol = pInput->pData[0];
6289
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
6290
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
6291

6292
  int32_t startOffset = pCtx->offset;
6293
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
6294
    char* data = colDataGetData(pInputCol, i);
6295
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
6296

6297
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
6298
      taosHashCleanup(pInfo->pHash);
6299
      return 0;
6300
    }
6301
  }
6302

6303
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
6304
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
6305
    if (pItem->isNull == true) {
6306
      colDataSetNULL(pOutput, i);
6307
    } else {
6308
      colDataSetVal(pOutput, i, pItem->data, false);
6309
    }
6310
    if (pTsOutput != NULL) {
6311
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
6312
    }
6313
  }
6314

6315
  return pInfo->numOfPoints;
6316
#endif
6317
  return 0;
×
6318
}
6319

6320
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
663,163✔
6321
  pEnv->calcMemSize = sizeof(SModeInfo);
663,163✔
6322
  return true;
663,163✔
6323
}
6324

6325
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
765,745✔
6326
  if (pResInfo->initialized) {
765,745✔
6327
    return TSDB_CODE_SUCCESS;
×
6328
  }
6329
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
765,745✔
6330
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6331
  }
6332

6333
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
765,745✔
6334
  pInfo->colType = pCtx->resDataInfo.type;
765,745✔
6335
  pInfo->colBytes = pCtx->resDataInfo.bytes;
765,745✔
6336
  if (pInfo->pHash != NULL) {
765,745✔
6337
    taosHashClear(pInfo->pHash);
×
6338
  } else {
6339
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
765,745✔
6340
    if (NULL == pInfo->pHash) {
765,745✔
6341
      return terrno;
×
6342
    }
6343
  }
6344
  pInfo->nullTupleSaved = false;
765,745✔
6345
  pInfo->nullTuplePos.pageId = -1;
765,745✔
6346

6347
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
765,745✔
6348
  if (NULL == pInfo->buf) {
765,745✔
6349
    taosHashCleanup(pInfo->pHash);
×
6350
    pInfo->pHash = NULL;
×
6351
    return terrno;
×
6352
  }
6353
  pCtx->needCleanup = true;
765,745✔
6354
  return TSDB_CODE_SUCCESS;
765,745✔
6355
}
6356

6357
static void modeFunctionCleanup(SModeInfo* pInfo) {
765,745✔
6358
  taosHashCleanup(pInfo->pHash);
765,745✔
6359
  pInfo->pHash = NULL;
765,745✔
6360
  taosMemoryFreeClear(pInfo->buf);
765,745✔
6361
}
765,745✔
6362

6363
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
6364
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
6365
    return;
×
6366
  }
6367
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
6368
}
6369

6370
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
55,841,733✔
6371
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
55,841,733✔
6372
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
5,459,484✔
6373
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
243,540✔
6374
    } else if (IS_STR_DATA_BLOB(pInfo->colType)) {
5,215,944✔
6375
      (void)memcpy(pInfo->buf, data, blobDataTLen(data));
×
6376
    } else {
6377
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
5,215,944✔
6378
    }
6379
  } else {
6380
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
50,384,128✔
6381
  }
6382

6383
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
55,843,278✔
6384
}
6385

6386
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
70,170,676✔
6387
  int32_t code = TSDB_CODE_SUCCESS;
70,170,676✔
6388
  int32_t hashKeyBytes;
6389
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
70,170,676✔
6390
    hashKeyBytes = calcStrBytesByType(pInfo->colType, data);
5,594,270✔
6391
  } else {
6392
    hashKeyBytes = pInfo->colBytes;
64,577,221✔
6393
  }
6394

6395
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
70,171,506✔
6396
  if (pHashItem == NULL) {
70,169,597✔
6397
    int32_t   size = sizeof(SModeItem);
55,841,399✔
6398
    SModeItem item = {0};
55,841,399✔
6399

6400
    item.count += 1;
55,841,399✔
6401
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
55,841,399✔
6402
    if (code != TSDB_CODE_SUCCESS) {
55,840,220✔
6403
      return code;
×
6404
    }
6405

6406
    if (pCtx->subsidiaries.num > 0) {
55,840,220✔
6407
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
142,238✔
6408
      if (code != TSDB_CODE_SUCCESS) {
142,238✔
6409
        return code;
×
6410
      }
6411
    }
6412

6413
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
55,840,220✔
6414
    if (code != TSDB_CODE_SUCCESS) {
55,842,959✔
6415
      return code;
×
6416
    }
6417
  } else {
6418
    pHashItem->count += 1;
14,328,198✔
6419
    if (pCtx->subsidiaries.num > 0) {
14,328,198✔
6420
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
3,056,798✔
6421
      if (code != TSDB_CODE_SUCCESS) {
3,056,798✔
6422
        return code;
×
6423
      }
6424
    }
6425
  }
6426

6427
  return code;
70,133,158✔
6428
}
6429

6430
int32_t modeFunction(SqlFunctionCtx* pCtx) {
1,570,392✔
6431
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,570,392✔
6432
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,570,392✔
6433

6434
  SInputColumnInfoData* pInput = &pCtx->input;
1,570,392✔
6435

6436
  SColumnInfoData* pInputCol = pInput->pData[0];
1,570,392✔
6437
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
1,570,392✔
6438

6439
  int32_t numOfElems = 0;
1,570,392✔
6440
  int32_t startOffset = pCtx->offset;
1,570,392✔
6441
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
113,949,255✔
6442
    if (colDataIsNull_s(pInputCol, i)) {
224,772,409✔
6443
      continue;
42,228,054✔
6444
    }
6445
    numOfElems++;
70,169,714✔
6446

6447
    char*   data = colDataGetData(pInputCol, i);
70,169,714✔
6448
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
70,170,195✔
6449
    if (code != TSDB_CODE_SUCCESS) {
70,169,714✔
6450
      modeFunctionCleanup(pInfo);
18,905✔
6451
      return code;
×
6452
    }
6453
  }
6454

6455
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
1,570,392✔
6456
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
4,020✔
6457
    if (code != TSDB_CODE_SUCCESS) {
4,020✔
6458
      modeFunctionCleanup(pInfo);
×
6459
      return code;
×
6460
    }
6461
    pInfo->nullTupleSaved = true;
4,020✔
6462
  }
6463

6464
  SET_VAL(pResInfo, numOfElems, 1);
1,570,392✔
6465

6466
  return TSDB_CODE_SUCCESS;
1,570,392✔
6467
}
6468

6469
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
765,745✔
6470
  int32_t              code = TSDB_CODE_SUCCESS;
765,745✔
6471
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
765,745✔
6472
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
765,745✔
6473
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
765,745✔
6474
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
765,745✔
6475
  int32_t              currentRow = pBlock->info.rows;
765,745✔
6476
  if (NULL == pCol) {
765,411✔
6477
    modeFunctionCleanup(pInfo);
×
6478
    return TSDB_CODE_OUT_OF_RANGE;
×
6479
  }
6480

6481
  STuplePos resDataPos, resTuplePos;
765,411✔
6482
  int32_t   maxCount = 0;
765,411✔
6483

6484
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
765,411✔
6485
  while (pIter != NULL) {
56,606,471✔
6486
    SModeItem* pItem = (SModeItem*)pIter;
55,840,726✔
6487
    if (pItem->count >= maxCount) {
55,840,726✔
6488
      maxCount = pItem->count;
38,165,442✔
6489
      resDataPos = pItem->dataPos;
38,165,442✔
6490
      resTuplePos = pItem->tuplePos;
38,165,442✔
6491
    }
6492

6493
    pIter = taosHashIterate(pInfo->pHash, pIter);
55,840,726✔
6494
  }
6495

6496
  if (maxCount != 0) {
765,745✔
6497
    char* pData = NULL;
520,147✔
6498
    code = loadTupleData(pCtx, &resDataPos, &pData);
520,147✔
6499
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
520,147✔
6500
      code = terrno = TSDB_CODE_NOT_FOUND;
×
6501
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
6502
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
6503
      modeFunctionCleanup(pInfo);
×
6504
      return code;
×
6505
    }
6506

6507
    code = colDataSetVal(pCol, currentRow, pData, false);
520,147✔
6508
    if (TSDB_CODE_SUCCESS != code) {
520,147✔
6509
      modeFunctionCleanup(pInfo);
×
6510
      return code;
×
6511
    }
6512
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
520,147✔
6513
  } else {
6514
    colDataSetNULL(pCol, currentRow);
245,598✔
6515
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
245,598✔
6516
  }
6517

6518
  modeFunctionCleanup(pInfo);
765,745✔
6519

6520
  return code;
765,745✔
6521
}
6522

6523
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
287,172✔
6524
  pEnv->calcMemSize = sizeof(STwaInfo);
287,172✔
6525
  return true;
287,172✔
6526
}
6527

6528
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
7,071,937✔
6529
  if (pResultInfo->initialized) {
7,071,937✔
6530
    return TSDB_CODE_SUCCESS;
×
6531
  }
6532
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
7,071,937✔
6533
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6534
  }
6535

6536
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,072,382✔
6537
  pInfo->numOfElems = 0;
7,071,937✔
6538
  pInfo->p.key = INT64_MIN;
7,071,937✔
6539
  pInfo->win = TSWINDOW_INITIALIZER;
7,071,937✔
6540
  return TSDB_CODE_SUCCESS;
7,071,937✔
6541
}
6542

6543
static double twa_get_area(SPoint1 s, SPoint1 e) {
120,254,106✔
6544
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
120,254,106✔
6545
    return 0;
×
6546
  }
6547

6548
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
120,254,581✔
6549
    return (s.val + e.val) * (e.key - s.key) / 2;
115,439,868✔
6550
  }
6551

6552
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
4,814,713✔
6553
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
4,814,713✔
6554
  return val;
4,814,713✔
6555
}
6556

6557
int32_t twaFunction(SqlFunctionCtx* pCtx) {
7,111,206✔
6558
  int32_t               code = TSDB_CODE_SUCCESS;
7,111,206✔
6559
  SInputColumnInfoData* pInput = &pCtx->input;
7,111,206✔
6560
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,111,651✔
6561

6562
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,111,651✔
6563
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,111,651✔
6564
  SPoint1*             last = &pInfo->p;
7,111,651✔
6565

6566
  if (IS_NULL_TYPE(pInputCol->info.type)) {
7,111,651✔
6567
    pInfo->numOfElems = 0;
×
6568
    goto _twa_over;
×
6569
  }
6570

6571
  funcInputUpdate(pCtx);
7,111,651✔
6572
  SFuncInputRow row = {0};
7,111,651✔
6573
  bool          result = false;
7,111,651✔
6574
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
7,111,651✔
6575
    while (1) {
6576
      code = funcInputGetNextRow(pCtx, &row, &result);
4,831,474✔
6577
      if (TSDB_CODE_SUCCESS != code) {
4,831,474✔
6578
        return code;
×
6579
      }
6580
      if (!result) {
4,831,474✔
6581
        break;
680✔
6582
      }
6583
      if (row.isDataNull) {
4,830,794✔
6584
        continue;
680✔
6585
      }
6586

6587
      last->key = row.ts;
4,830,114✔
6588

6589
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
4,830,114✔
6590

6591
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
4,830,114✔
6592
      pInfo->win.skey = pCtx->start.key;
4,830,114✔
6593
      pInfo->numOfElems++;
4,830,114✔
6594
      break;
4,830,114✔
6595
    }
6596
  } else if (pInfo->p.key == INT64_MIN) {
2,280,857✔
6597
    while (1) {
6598
      code = funcInputGetNextRow(pCtx, &row, &result);
10,411,303✔
6599
      if (TSDB_CODE_SUCCESS != code) {
10,410,413✔
6600
        return code;
×
6601
      }
6602
      if (!result) {
10,410,413✔
6603
        break;
880,127✔
6604
      }
6605
      if (row.isDataNull) {
9,530,286✔
6606
        continue;
8,150,316✔
6607
      }
6608

6609
      last->key = row.ts;
1,379,970✔
6610

6611
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData, typeGetTypeModFromColInfo(&pInputCol->info));
1,379,947✔
6612

6613
      pInfo->win.skey = last->key;
1,379,947✔
6614
      pInfo->numOfElems++;
1,380,860✔
6615
      break;
1,380,415✔
6616
    }
6617
  }
6618

6619
  SPoint1 st = {0};
7,111,206✔
6620

6621
  // calculate the value of
6622
  while (1) {
6623
    code = funcInputGetNextRow(pCtx, &row, &result);
117,755,855✔
6624
    if (TSDB_CODE_SUCCESS != code) {
117,763,758✔
6625
      return code;
×
6626
    }
6627
    if (!result) {
117,763,758✔
6628
      break;
7,111,651✔
6629
    }
6630
    if (row.isDataNull) {
110,652,107✔
6631
      continue;
48,510✔
6632
    }
6633
    pInfo->numOfElems++;
110,603,597✔
6634
    switch (pInputCol->info.type) {
110,602,767✔
6635
      case TSDB_DATA_TYPE_TINYINT: {
11,912,955✔
6636
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
11,912,955✔
6637
        break;
11,913,423✔
6638
      }
6639
      case TSDB_DATA_TYPE_SMALLINT: {
11,630,408✔
6640
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
11,630,408✔
6641
        break;
11,629,638✔
6642
      }
6643
      case TSDB_DATA_TYPE_INT: {
19,872,953✔
6644
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
19,872,953✔
6645
        break;
19,872,953✔
6646
      }
6647
      case TSDB_DATA_TYPE_BIGINT: {
12,082,877✔
6648
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
12,082,877✔
6649
        break;
12,082,492✔
6650
      }
6651
      case TSDB_DATA_TYPE_FLOAT: {
11,511,472✔
6652
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
11,511,472✔
6653
        break;
11,511,472✔
6654
      }
6655
      case TSDB_DATA_TYPE_DOUBLE: {
12,695,648✔
6656
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
12,695,648✔
6657
        break;
12,696,033✔
6658
      }
6659
      case TSDB_DATA_TYPE_UTINYINT: {
7,891,092✔
6660
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
7,891,092✔
6661
        break;
7,891,092✔
6662
      }
6663
      case TSDB_DATA_TYPE_USMALLINT: {
7,891,092✔
6664
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
7,891,092✔
6665
        break;
7,891,092✔
6666
      }
6667
      case TSDB_DATA_TYPE_UINT: {
7,956,531✔
6668
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
7,956,531✔
6669
        break;
7,956,531✔
6670
      }
6671
      case TSDB_DATA_TYPE_UBIGINT: {
7,156,116✔
6672
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
7,156,116✔
6673
        break;
7,156,116✔
6674
      }
6675
      default: {
×
6676
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6677
      }
6678
    }
6679
    if (pInfo->p.key == st.key) {
110,600,842✔
6680
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6681
    }
6682

6683
    pInfo->dOutput += twa_get_area(pInfo->p, st);
110,600,842✔
6684
    pInfo->p = st;
110,594,682✔
6685
  }
6686

6687
  // the last interpolated time window value
6688
  if (pCtx->end.key != INT64_MIN) {
7,111,651✔
6689
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
4,832,775✔
6690
    pInfo->p = pCtx->end;
4,832,775✔
6691
    pInfo->numOfElems += 1;
4,832,775✔
6692
  }
6693

6694
  pInfo->win.ekey = pInfo->p.key;
7,112,096✔
6695

6696
_twa_over:
7,111,206✔
6697
  SET_VAL(pResInfo, 1, 1);
7,111,206✔
6698
  return TSDB_CODE_SUCCESS;
7,111,651✔
6699
}
6700

6701
/*
6702
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6703
 * by next input data. The TWA function only applies to each table, so no merge procedure
6704
 * is required, we simply copy to the resut ot interResBuffer.
6705
 */
6706
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6707
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6708
//
6709
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6710
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6711
// }
6712

6713
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,072,382✔
6714
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,072,382✔
6715

6716
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
7,072,382✔
6717
  if (pInfo->numOfElems == 0) {
7,072,382✔
6718
    pResInfo->numOfRes = 0;
860,728✔
6719
  } else {
6720
    if (pInfo->win.ekey == pInfo->win.skey) {
6,211,654✔
6721
      pInfo->dTwaRes = pInfo->p.val;
628,450✔
6722
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
5,583,204✔
6723
      pInfo->dTwaRes = 0;
680✔
6724
    } else {
6725
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
5,582,524✔
6726
    }
6727

6728
    pResInfo->numOfRes = 1;
6,211,654✔
6729
  }
6730

6731
  return functionFinalize(pCtx, pBlock);
7,072,382✔
6732
}
6733

6734
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
2,613✔
6735
  if (pResultInfo->initialized) {
2,613✔
6736
    return TSDB_CODE_SUCCESS;
×
6737
  }
6738
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
2,613✔
6739
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6740
  }
6741

6742
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,613✔
6743
  pInfo->minRows = INT32_MAX;
2,613✔
6744
  return TSDB_CODE_SUCCESS;
2,613✔
6745
}
6746

6747
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
4,999✔
6748
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
4,999✔
6749

6750
  SInputColumnInfoData* pInput = &pCtx->input;
4,999✔
6751
  SColumnInfoData*      pInputCol = pInput->pData[0];
4,999✔
6752
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
4,999✔
6753
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
4,999✔
6754

6755
  STableBlockDistInfo p1 = {0};
4,999✔
6756
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
4,999✔
6757
    qError("failed to deserialize block dist info");
×
6758
    return TSDB_CODE_FAILED;
×
6759
  }
6760

6761
  pDistInfo->numOfBlocks += p1.numOfBlocks;
4,999✔
6762
  pDistInfo->numOfTables += p1.numOfTables;
4,999✔
6763
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
4,999✔
6764
  pDistInfo->numOfSttRows += p1.numOfSttRows;
4,999✔
6765
  pDistInfo->totalSize += p1.totalSize;
4,999✔
6766
  pDistInfo->totalRows += p1.totalRows;
4,999✔
6767
  pDistInfo->numOfFiles += p1.numOfFiles;
4,999✔
6768

6769
  pDistInfo->defMinRows = p1.defMinRows;
4,999✔
6770
  pDistInfo->defMaxRows = p1.defMaxRows;
4,999✔
6771
  pDistInfo->rowSize = p1.rowSize;
4,999✔
6772

6773
  if (pDistInfo->minRows > p1.minRows) {
4,999✔
6774
    pDistInfo->minRows = p1.minRows;
1,187✔
6775
  }
6776
  if (pDistInfo->maxRows < p1.maxRows) {
4,999✔
6777
    pDistInfo->maxRows = p1.maxRows;
1,187✔
6778
  }
6779
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
4,999✔
6780
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
104,979✔
6781
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
99,980✔
6782
  }
6783

6784
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
4,999✔
6785
  return TSDB_CODE_SUCCESS;
4,999✔
6786
}
6787

6788
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
9,998✔
6789
  SEncoder encoder = {0};
9,998✔
6790
  int32_t  code = 0;
9,998✔
6791
  int32_t  lino;
6792
  int32_t  tlen;
6793
  tEncoderInit(&encoder, buf, bufLen);
9,998✔
6794

6795
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
9,998✔
6796
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
19,996✔
6797

6798
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
19,996✔
6799
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
19,996✔
6800
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
19,996✔
6801

6802
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
19,996✔
6803
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
19,996✔
6804
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
19,996✔
6805
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
19,996✔
6806
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
19,996✔
6807
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
19,996✔
6808
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
19,996✔
6809
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
19,996✔
6810
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
19,996✔
6811

6812
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
209,958✔
6813
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
399,920✔
6814
  }
6815

6816
  tEndEncode(&encoder);
9,998✔
6817

6818
_exit:
9,998✔
6819
  if (code) {
9,998✔
6820
    tlen = code;
×
6821
  } else {
6822
    tlen = encoder.pos;
9,998✔
6823
  }
6824
  tEncoderClear(&encoder);
9,998✔
6825
  return tlen;
9,998✔
6826
}
6827

6828
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
4,999✔
6829
  SDecoder decoder = {0};
4,999✔
6830
  int32_t  code = 0;
4,999✔
6831
  int32_t  lino;
6832
  tDecoderInit(&decoder, buf, bufLen);
4,999✔
6833

6834
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
4,999✔
6835
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
9,998✔
6836

6837
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
9,998✔
6838
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
9,998✔
6839
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
9,998✔
6840

6841
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
9,998✔
6842
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
9,998✔
6843
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
9,998✔
6844
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
9,998✔
6845
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
9,998✔
6846
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
9,998✔
6847
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
9,998✔
6848
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
9,998✔
6849
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
9,998✔
6850

6851
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
104,979✔
6852
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
199,960✔
6853
  }
6854

6855
_exit:
4,999✔
6856
  tDecoderClear(&decoder);
4,999✔
6857
  return code;
4,999✔
6858
}
6859

6860
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,613✔
6861
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,613✔
6862
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
2,613✔
6863

6864
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
2,613✔
6865
  if (NULL == pColInfo) {
2,613✔
6866
    return TSDB_CODE_OUT_OF_RANGE;
×
6867
  }
6868

6869
  if (pData->totalRows == 0) {
2,613✔
6870
    pData->minRows = 0;
1,426✔
6871
  }
6872

6873
  int32_t row = 0;
2,613✔
6874
  char    st[256] = {0};
2,613✔
6875
  double  averageSize = 0;
2,613✔
6876
  if (pData->numOfBlocks != 0) {
2,613✔
6877
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
1,187✔
6878
  }
6879
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
2,613✔
6880
  double   compRatio = 0;
2,613✔
6881
  if (totalRawSize != 0) {
2,613✔
6882
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
1,187✔
6883
  }
6884

6885
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,613✔
6886
                          "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6887
                          pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
2,613✔
6888

6889
  varDataSetLen(st, len);
2,613✔
6890
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
2,613✔
6891
  if (TSDB_CODE_SUCCESS != code) {
2,613✔
6892
    return code;
×
6893
  }
6894

6895
  int64_t avgRows = 0;
2,613✔
6896
  if (pData->numOfBlocks > 0) {
2,613✔
6897
    avgRows = pData->totalRows / pData->numOfBlocks;
1,187✔
6898
  }
6899

6900
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,613✔
6901
                  "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6902
                  pData->minRows, pData->maxRows, avgRows);
6903
  varDataSetLen(st, len);
2,613✔
6904
  code = colDataSetVal(pColInfo, row++, st, false);
2,613✔
6905
  if (TSDB_CODE_SUCCESS != code) {
2,613✔
6906
    return code;
×
6907
  }
6908

6909
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
2,613✔
6910
                  pData->numOfInmemRows, pData->numOfSttRows);
6911
  varDataSetLen(st, len);
2,613✔
6912
  code = colDataSetVal(pColInfo, row++, st, false);
2,613✔
6913
  if (TSDB_CODE_SUCCESS != code) {
2,613✔
6914
    return code;
×
6915
  }
6916

6917
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
5,226✔
6918
                  "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
2,613✔
6919
                  pData->numOfVgroups);
6920

6921
  varDataSetLen(st, len);
2,613✔
6922
  code = colDataSetVal(pColInfo, row++, st, false);
2,613✔
6923
  if (TSDB_CODE_SUCCESS != code) {
2,613✔
6924
    return code;
×
6925
  }
6926

6927
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
2,613✔
6928
                  "--------------------------------------------------------------------------------");
6929
  varDataSetLen(st, len);
2,613✔
6930
  code = colDataSetVal(pColInfo, row++, st, false);
2,613✔
6931
  if (TSDB_CODE_SUCCESS != code) {
2,613✔
6932
    return code;
×
6933
  }
6934

6935
  int32_t maxVal = 0;
2,613✔
6936
  int32_t minVal = INT32_MAX;
2,613✔
6937
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
54,873✔
6938
    if (maxVal < pData->blockRowsHisto[i]) {
52,260✔
6939
      maxVal = pData->blockRowsHisto[i];
1,704✔
6940
    }
6941

6942
    if (minVal > pData->blockRowsHisto[i]) {
52,260✔
6943
      minVal = pData->blockRowsHisto[i];
3,283✔
6944
    }
6945
  }
6946

6947
  // maximum number of step is 80
6948
  double factor = pData->numOfBlocks / 80.0;
2,613✔
6949

6950
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
2,613✔
6951
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
2,613✔
6952

6953
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
54,873✔
6954
    len =
52,260✔
6955
        tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
52,260✔
6956

6957
    int32_t num = 0;
52,260✔
6958
    if (pData->blockRowsHisto[i] > 0) {
52,260✔
6959
      num = (pData->blockRowsHisto[i]) / factor;
2,738✔
6960
    }
6961

6962
    for (int32_t j = 0; j < num; ++j) {
146,703✔
6963
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
94,443✔
6964
      len += x;
94,443✔
6965
    }
6966

6967
    if (pData->blockRowsHisto[i] > 0) {
52,260✔
6968
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
2,738✔
6969
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
2,738✔
6970
                       pData->blockRowsHisto[i], v, '%');
6971
    }
6972

6973
    varDataSetLen(st, len);
52,260✔
6974
    code = colDataSetVal(pColInfo, row++, st, false);
52,260✔
6975
    if (TSDB_CODE_SUCCESS != code) {
52,260✔
6976
      return code;
×
6977
    }
6978
  }
6979

6980
  return TSDB_CODE_SUCCESS;
2,613✔
6981
}
6982
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
312✔
6983
  if (pResultInfo->initialized) {
312✔
6984
    return TSDB_CODE_SUCCESS;
×
6985
  }
6986
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
312✔
6987
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6988
  }
6989

6990
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
312✔
6991
  return TSDB_CODE_SUCCESS;
312✔
6992
}
6993
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
624✔
6994
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
624✔
6995

6996
  SInputColumnInfoData* pInput = &pCtx->input;
624✔
6997
  SColumnInfoData*      pInputCol = pInput->pData[0];
624✔
6998
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
624✔
6999
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
624✔
7000

7001
  SDBBlockUsageInfo p1 = {0};
624✔
7002
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
624✔
7003
    qError("failed to deserialize block dist info");
×
7004
    return TSDB_CODE_FAILED;
×
7005
  }
7006

7007
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
624✔
7008
  pDistInfo->walInDiskSize += p1.walInDiskSize;
624✔
7009
  pDistInfo->rawDataSize += p1.rawDataSize;
624✔
7010
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
624✔
7011
  return TSDB_CODE_SUCCESS;
624✔
7012
}
7013

7014
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
1,248✔
7015
  SEncoder encoder = {0};
1,248✔
7016
  int32_t  code = 0;
1,248✔
7017
  int32_t  lino;
7018
  int32_t  tlen;
7019
  tEncoderInit(&encoder, buf, bufLen);
1,248✔
7020

7021
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
1,248✔
7022

7023
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
2,496✔
7024
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
2,496✔
7025
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
2,496✔
7026

7027
  tEndEncode(&encoder);
1,248✔
7028

7029
_exit:
1,248✔
7030
  if (code) {
1,248✔
7031
    tlen = code;
×
7032
  } else {
7033
    tlen = encoder.pos;
1,248✔
7034
  }
7035
  tEncoderClear(&encoder);
1,248✔
7036
  return tlen;
1,248✔
7037
}
7038
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
624✔
7039
  SDecoder decoder = {0};
624✔
7040
  int32_t  code = 0;
624✔
7041
  int32_t  lino;
7042
  tDecoderInit(&decoder, buf, bufLen);
624✔
7043

7044
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
624✔
7045
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
1,248✔
7046
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
1,248✔
7047
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
1,248✔
7048

7049
_exit:
624✔
7050
  tDecoderClear(&decoder);
624✔
7051
  return code;
624✔
7052
}
7053
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
312✔
7054
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
312✔
7055
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
312✔
7056

7057
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
312✔
7058
  if (NULL == pColInfo) {
312✔
7059
    return TSDB_CODE_OUT_OF_RANGE;
×
7060
  }
7061
  int32_t len = 0;
312✔
7062
  int32_t row = 0;
312✔
7063
  char    st[256] = {0};
312✔
7064

7065
  uint64_t totalDiskSize = pData->dataInDiskSize;
312✔
7066
  uint64_t rawDataSize = pData->rawDataSize;
312✔
7067
  double   compressRatio = 0;
312✔
7068
  if (rawDataSize != 0) {
312✔
7069
    compressRatio = totalDiskSize * 100 / (double)rawDataSize;
160✔
7070
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[%.2f%]", compressRatio);
160✔
7071
  } else {
7072
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_ratio=[NULL]");
152✔
7073
  }
7074

7075
  varDataSetLen(st, len);
312✔
7076
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
312✔
7077
  if (TSDB_CODE_SUCCESS != code) {
312✔
7078
    return code;
×
7079
  }
7080

7081
  len =
312✔
7082
      tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
312✔
7083
  varDataSetLen(st, len);
312✔
7084
  code = colDataSetVal(pColInfo, row++, st, false);
312✔
7085
  if (TSDB_CODE_SUCCESS != code) {
312✔
7086
    return code;
×
7087
  }
7088
  return code;
312✔
7089
}
7090

7091
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
180,858✔
7092
  pEnv->calcMemSize = sizeof(SDerivInfo);
180,858✔
7093
  return true;
180,858✔
7094
}
7095

7096
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
577,985✔
7097
  if (pResInfo->initialized) {
577,985✔
7098
    return TSDB_CODE_SUCCESS;
370,444✔
7099
  }
7100
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
207,541✔
7101
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7102
  }
7103

7104
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
207,541✔
7105

7106
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
207,541✔
7107
  pDerivInfo->prevTs = -1;
207,541✔
7108
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
207,541✔
7109
  pDerivInfo->valueSet = false;
207,541✔
7110
  return TSDB_CODE_SUCCESS;
207,541✔
7111
}
7112

7113
int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
397,127✔
7114

7115
static int32_t DoDerivativeFunction(SqlFunctionCtx* pCtx) {
397,127✔
7116
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
397,127✔
7117
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
397,127✔
7118

7119
  SInputColumnInfoData* pInput = &pCtx->input;
397,127✔
7120
  SColumnInfoData*      pInputCol = pInput->pData[0];
397,127✔
7121

7122
  int32_t          numOfElems = 0;
397,127✔
7123
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
397,127✔
7124
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
397,127✔
7125
  int32_t          code = TSDB_CODE_SUCCESS;
397,127✔
7126

7127
  funcInputUpdate(pCtx);
397,127✔
7128

7129
  double v = 0;
397,127✔
7130
  if (pCtx->order == TSDB_ORDER_ASC) {
397,127✔
7131
    SFuncInputRow row = {0};
396,159✔
7132
    bool          result = false;
396,159✔
7133
    while (1) {
12,373,012✔
7134
      code = funcInputGetNextRow(pCtx, &row, &result);
12,769,171✔
7135
      if (TSDB_CODE_SUCCESS != code) {
12,769,171✔
7136
        return code;
×
7137
      }
7138
      if (!result) {
12,769,171✔
7139
        break;
396,159✔
7140
      }
7141
      if (row.isDataNull) {
12,373,012✔
7142
        continue;
2,822,394✔
7143
      }
7144

7145
      char* d = row.pData;
9,550,618✔
7146
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
9,550,618✔
7147

7148
      int32_t pos = pCtx->offset + numOfElems;
9,550,618✔
7149
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
9,550,618✔
7150
        pDerivInfo->valueSet = true;
178,716✔
7151
      } else {
7152
        if (row.ts == pDerivInfo->prevTs) {
9,371,902✔
7153
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7154
        }
7155
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
9,371,902✔
7156
        if (pDerivInfo->ignoreNegative && r < 0) {
9,371,902✔
7157
        } else {
7158
          if (isinf(r) || isnan(r)) {
8,828,944✔
7159
            colDataSetNULL(pOutput, pos);
×
7160
          } else {
7161
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
8,828,944✔
7162
            if (code != TSDB_CODE_SUCCESS) {
8,828,944✔
7163
              return code;
×
7164
            }
7165
          }
7166

7167
          if (pTsOutput != NULL) {
8,828,944✔
7168
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
7169
          }
7170

7171
          // handle selectivity
7172
          if (pCtx->subsidiaries.num > 0) {
8,828,944✔
7173
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,787,883✔
7174
            if (code != TSDB_CODE_SUCCESS) {
1,787,883✔
7175
              return code;
×
7176
            }
7177
          }
7178

7179
          numOfElems++;
8,828,944✔
7180
        }
7181
      }
7182

7183
      pDerivInfo->prevValue = v;
9,550,618✔
7184
      pDerivInfo->prevTs = row.ts;
9,550,618✔
7185
    }
7186
  } else {
7187
    SFuncInputRow row = {0};
968✔
7188
    bool          result = false;
968✔
7189
    while (1) {
193,600✔
7190
      code = funcInputGetNextRow(pCtx, &row, &result);
194,568✔
7191
      if (TSDB_CODE_SUCCESS != code) {
194,568✔
7192
        return code;
×
7193
      }
7194
      if (!result) {
194,568✔
7195
        break;
968✔
7196
      }
7197
      if (row.isDataNull) {
193,600✔
7198
        continue;
×
7199
      }
7200

7201
      char* d = row.pData;
193,600✔
7202
      GET_TYPED_DATA(v, double, pInputCol->info.type, d, typeGetTypeModFromColInfo(&pInputCol->info));
193,600✔
7203

7204
      int32_t pos = pCtx->offset + numOfElems;
193,600✔
7205
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
193,600✔
7206
        pDerivInfo->valueSet = true;
968✔
7207
      } else {
7208
        if (row.ts == pDerivInfo->prevTs) {
192,632✔
7209
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7210
        }
7211
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
192,632✔
7212
        if (pDerivInfo->ignoreNegative && r < 0) {
192,632✔
7213
        } else {
7214
          if (isinf(r) || isnan(r)) {
95,832✔
7215
            colDataSetNULL(pOutput, pos);
×
7216
          } else {
7217
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
95,832✔
7218
            if (code != TSDB_CODE_SUCCESS) {
95,832✔
7219
              return code;
×
7220
            }
7221
          }
7222

7223
          if (pTsOutput != NULL) {
95,832✔
7224
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
7225
          }
7226

7227
          // handle selectivity
7228
          if (pCtx->subsidiaries.num > 0) {
95,832✔
7229
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
×
7230
            if (code != TSDB_CODE_SUCCESS) {
×
7231
              return code;
×
7232
            }
7233
          }
7234
          numOfElems++;
95,832✔
7235
        }
7236
      }
7237

7238
      pDerivInfo->prevValue = v;
193,600✔
7239
      pDerivInfo->prevTs = row.ts;
193,600✔
7240
    }
7241
  }
7242

7243
  pResInfo->numOfRes = numOfElems;
397,127✔
7244

7245
  return TSDB_CODE_SUCCESS;
397,127✔
7246
}
7247

7248
int32_t derivativeFunctionByRow(SArray* pCtxArray) {
397,127✔
7249
  for (int32_t i = 0; i < taosArrayGetSize(pCtxArray); ++i) {
794,254✔
7250
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
397,127✔
7251
    int32_t         code = DoDerivativeFunction(pCtx);
397,127✔
7252
    if (code != TSDB_CODE_SUCCESS) {
397,127✔
7253
      return code;
×
7254
    }
7255
  }
7256
  return TSDB_CODE_SUCCESS;
397,127✔
7257
}
7258

7259
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
199,155✔
7260

7261
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
161,956✔
7262
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
161,956✔
7263
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
161,956✔
7264
  return true;
161,956✔
7265
}
7266

7267
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,039,585✔
7268
  if (pResInfo->initialized) {
2,039,585✔
7269
    return TSDB_CODE_SUCCESS;
×
7270
  }
7271
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
2,040,030✔
7272
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7273
  }
7274

7275
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,040,475✔
7276

7277
  pInfo->firstKey = INT64_MIN;
2,040,475✔
7278
  pInfo->lastKey = INT64_MIN;
2,040,475✔
7279
  pInfo->firstValue = (double)INT64_MIN;
2,040,030✔
7280
  pInfo->lastValue = (double)INT64_MIN;
2,040,030✔
7281

7282
  pInfo->hasResult = 0;
2,040,030✔
7283
  return TSDB_CODE_SUCCESS;
2,040,030✔
7284
}
7285

7286
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
23,341,387✔
7287
  if (isFirst) {
23,341,387✔
7288
    pRateInfo->firstValue = v;
11,131,362✔
7289
    pRateInfo->firstKey = ts;
11,130,917✔
7290
    if (pRateInfo->firstPk) {
11,130,472✔
7291
      int32_t pkBytes;
7292
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
22,155✔
7293
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
5,064✔
7294
      } else {
7295
        pkBytes = pRateInfo->pkBytes;
17,091✔
7296
      }
7297
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
22,155✔
7298
    }
7299
  } else {
7300
    pRateInfo->lastValue = v;
12,210,025✔
7301
    pRateInfo->lastKey = ts;
12,210,470✔
7302
    if (pRateInfo->lastPk) {
12,210,470✔
7303
      int32_t pkBytes;
7304
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
32,916✔
7305
        pkBytes = calcStrBytesByType(pRateInfo->pkType, pk);
7,596✔
7306
      } else {
7307
        pkBytes = pRateInfo->pkBytes;
25,320✔
7308
      }
7309
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
32,916✔
7310
    }
7311
  }
7312
}
23,341,387✔
7313

7314
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
2,154,699✔
7315
  if (pCtx->hasPrimaryKey) {
2,154,699✔
7316
    if (!isMerge) {
12,027✔
7317
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
10,761✔
7318
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
10,761✔
7319
      pRateInfo->firstPk = pRateInfo->pkData;
10,761✔
7320
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
10,761✔
7321
    } else {
7322
      pRateInfo->firstPk = pRateInfo->pkData;
1,266✔
7323
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
1,266✔
7324
    }
7325
  } else {
7326
    pRateInfo->firstPk = NULL;
2,142,672✔
7327
    pRateInfo->lastPk = NULL;
2,142,672✔
7328
  }
7329
}
2,154,699✔
7330

7331
int32_t irateFunction(SqlFunctionCtx* pCtx) {
2,099,973✔
7332
  int32_t              code = TSDB_CODE_SUCCESS;
2,099,973✔
7333
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,099,973✔
7334
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,099,973✔
7335

7336
  SInputColumnInfoData* pInput = &pCtx->input;
2,099,528✔
7337
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,099,528✔
7338

7339
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,099,528✔
7340

7341
  funcInputUpdate(pCtx);
2,099,528✔
7342

7343
  initializeRateInfo(pCtx, pRateInfo, false);
2,100,418✔
7344

7345
  int32_t       numOfElems = 0;
2,099,973✔
7346
  int32_t       type = pInputCol->info.type;
2,099,973✔
7347
  SFuncInputRow row = {0};
2,099,973✔
7348
  bool          result = false;
2,099,973✔
7349
  while (1) {
18,773,667✔
7350
    code = funcInputGetNextRow(pCtx, &row, &result);
20,873,640✔
7351
    if (TSDB_CODE_SUCCESS != code) {
20,874,085✔
7352
      return code;
×
7353
    }
7354
    if (!result) {
20,874,085✔
7355
      break;
2,099,973✔
7356
    }
7357
    if (row.isDataNull) {
18,774,112✔
7358
      continue;
6,441,151✔
7359
    }
7360

7361
    char*  data = row.pData;
12,332,961✔
7362
    double v = 0;
12,332,961✔
7363
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputCol->info));
12,332,961✔
7364

7365
    if (INT64_MIN == pRateInfo->lastKey) {
12,332,961✔
7366
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
1,080,858✔
7367
      pRateInfo->hasResult = 1;
1,080,858✔
7368
      continue;
1,081,303✔
7369
    }
7370

7371
    if (row.ts > pRateInfo->lastKey) {
11,252,103✔
7372
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
11,107,871✔
7373
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
11,107,426✔
7374
      }
7375
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
11,107,426✔
7376
      continue;
11,107,871✔
7377
    } else if (row.ts == pRateInfo->lastKey) {
144,232✔
7378
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7379
    }
7380

7381
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
144,232✔
7382
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
968✔
7383
    } else if (row.ts == pRateInfo->firstKey) {
143,264✔
7384
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7385
    }
7386
  }
7387

7388
  numOfElems++;
2,099,973✔
7389

7390
  SET_VAL(pResInfo, numOfElems, 1);
2,099,973✔
7391
  return TSDB_CODE_SUCCESS;
2,099,973✔
7392
}
7393

7394
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
2,013,112✔
7395
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
2,013,112✔
7396
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
109,427✔
7397
    return 0.0;
1,903,685✔
7398
  }
7399

7400
  double diff = 0;
109,427✔
7401
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
7402
  // value between two values.
7403
  diff = pRateInfo->lastValue;
109,427✔
7404
  if (diff >= pRateInfo->firstValue) {
109,427✔
7405
    diff -= pRateInfo->firstValue;
72,723✔
7406
  }
7407

7408
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
109,427✔
7409
  if (duration == 0) {
109,427✔
7410
    return 0;
×
7411
  }
7412

7413
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
109,427✔
7414
}
7415

7416
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
22,478✔
7417
  if (inputKey > pOutput->lastKey) {
22,478✔
7418
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
7,429✔
7419
    if (isFirstKey) {
7,429✔
7420
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
2,737✔
7421
    } else {
7422
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
4,692✔
7423
    }
7424
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
15,049✔
7425
    if (isFirstKey) {
782✔
7426
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
391✔
7427
    } else {
7428
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
391✔
7429
    }
7430
  } else {
7431
    // inputKey < pOutput->firstKey
7432
  }
7433
}
22,478✔
7434

7435
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
14,312✔
7436
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
14,312✔
7437
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
14,312✔
7438
}
14,312✔
7439

7440
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
25,551✔
7441
  if ((pInput->firstKey != INT64_MIN &&
25,551✔
7442
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
23,111✔
7443
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
25,551✔
7444
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
7445
  }
7446

7447
  if (pOutput->hasResult == 0) {
25,551✔
7448
    irateCopyInfo(pInput, pOutput);
14,312✔
7449
    pOutput->hasResult = pInput->hasResult;
14,312✔
7450
    return TSDB_CODE_SUCCESS;
14,312✔
7451
  }
7452

7453
  if (pInput->firstKey != INT64_MIN) {
11,239✔
7454
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
11,239✔
7455
  }
7456

7457
  if (pInput->lastKey != INT64_MIN) {
11,239✔
7458
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
11,239✔
7459
  }
7460

7461
  pOutput->hasResult = pInput->hasResult;
11,239✔
7462
  return TSDB_CODE_SUCCESS;
11,239✔
7463
}
7464

7465
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
27,363✔
7466
  SInputColumnInfoData* pInput = &pCtx->input;
27,363✔
7467
  SColumnInfoData*      pCol = pInput->pData[0];
27,363✔
7468
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
27,363✔
7469
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7470
  }
7471

7472
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
27,363✔
7473
  initializeRateInfo(pCtx, pInfo, true);
27,363✔
7474

7475
  int32_t start = pInput->startRowIndex;
27,363✔
7476
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
54,726✔
7477
    char*      data = colDataGetData(pCol, i);
27,363✔
7478
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
27,363✔
7479
    initializeRateInfo(pCtx, pInfo, true);
27,363✔
7480
    if (pInputInfo->hasResult) {
27,363✔
7481
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
25,551✔
7482
      if (code != TSDB_CODE_SUCCESS) {
25,551✔
7483
        return code;
×
7484
      }
7485
    }
7486
  }
7487

7488
  if (pInfo->hasResult) {
27,363✔
7489
    GET_RES_INFO(pCtx)->numOfRes = 1;
25,551✔
7490
  }
7491

7492
  return TSDB_CODE_SUCCESS;
27,363✔
7493
}
7494

7495
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
27,363✔
7496
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
27,363✔
7497
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
27,363✔
7498
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
27,363✔
7499
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
27,363✔
7500

7501
  if (NULL == res) {
27,363✔
7502
    return terrno;
×
7503
  }
7504
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
27,363✔
7505
  varDataSetLen(res, resultBytes);
27,363✔
7506

7507
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
27,363✔
7508
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
27,363✔
7509
  if (NULL == pCol) {
27,363✔
7510
    taosMemoryFree(res);
×
7511
    return TSDB_CODE_OUT_OF_RANGE;
×
7512
  }
7513

7514
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
27,363✔
7515

7516
  taosMemoryFree(res);
27,363✔
7517
  return code;
27,363✔
7518
}
7519

7520
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,013,112✔
7521
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,013,112✔
7522
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,013,112✔
7523
  if (NULL == pCol) {
2,013,112✔
7524
    return TSDB_CODE_OUT_OF_RANGE;
×
7525
  }
7526

7527
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,013,112✔
7528
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
2,013,112✔
7529

7530
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,013,112✔
7531
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
2,013,112✔
7532
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
2,013,112✔
7533

7534
  return code;
2,013,112✔
7535
}
7536

7537
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
2,147,483,647✔
7538
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
7539
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
7540
  bool                 isWindow = pCtx->hasWindowOrGroup && pCtx->hasWindow;
2,147,483,647✔
7541

7542
  if (pInfo->hasResult && (!isWindow || !pInfo->isNull)) {
2,147,483,647✔
7543
    // If already has result for 'group by' or
7544
    // has non-null result for 'window', we can skip left data blocks.
7545
    goto _group_value_over;
2,088,840,135✔
7546
  }
7547

7548
  int32_t               valueRowIndex = -1;
2,147,483,647✔
7549
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
7550
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,147,483,647✔
7551

7552
  // try to find a non-null value
7553
  if (NULL != pInputCol->pData) {
2,147,483,647✔
7554
    if (isWindow) {
2,147,483,647✔
7555
      // for 'window', non-null value can appear at any row of any data block
7556
      int64_t startIndex = pInput->startRowIndex;
2,147,483,647✔
7557
      int64_t endIndex = pInput->startRowIndex + pInput->numOfRows - 1;
2,147,483,647✔
7558
      for (int64_t i = startIndex; i <= endIndex; ++i) {
2,147,483,647✔
7559
        if (!colDataIsNull_s(pInputCol, i)) {
2,147,483,647✔
7560
          valueRowIndex = i;
2,147,483,647✔
7561
          break;
2,147,483,647✔
7562
        }
7563
      }
7564
    } else {
7565
      // for 'group by', just take the first row
7566
      if (!colDataIsNull_s(pInputCol, pInput->startRowIndex)) {
304,967,139✔
7567
        valueRowIndex = pInput->startRowIndex;
152,196,160✔
7568
      }
7569
    }
7570
  }
7571

7572
  if (valueRowIndex != -1) {
2,147,483,647✔
7573
    // found a non-null value
7574
    char* data = colDataGetData(pInputCol, valueRowIndex);
2,147,483,647✔
7575
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
2,147,483,647✔
7576
      int32_t bytes = calcStrBytesByType(pInputCol->info.type, data);
2,147,483,647✔
7577
      (void)memcpy(pInfo->data, data, bytes);
2,147,483,647✔
7578
    } else {
7579
      (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
2,047,716,192✔
7580
    }
7581
    pInfo->isNull = false;
2,147,483,647✔
7582
  } else {
7583
    // all values are null or first value is null for group by
7584
    pInfo->isNull = true;
263,061,956✔
7585
  }
7586
  pInfo->hasResult = true;
2,147,483,647✔
7587

7588
_group_value_over:
2,147,483,647✔
7589
  SET_VAL(pResInfo, 1, 1);
2,147,483,647✔
7590
  return TSDB_CODE_SUCCESS;
2,147,483,647✔
7591
}
7592

7593
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
2,147,483,647✔
7594

7595
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,147,483,647✔
7596
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,147,483,647✔
7597
  int32_t          code = TSDB_CODE_SUCCESS;
2,147,483,647✔
7598
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,147,483,647✔
7599
  if (NULL == pCol) {
2,147,483,647✔
7600
    return TSDB_CODE_OUT_OF_RANGE;
×
7601
  }
7602

7603
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
7604

7605
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
7606

7607
  if (pInfo->hasResult) {
2,147,483,647✔
7608
    int32_t currentRow = pBlock->info.rows;
2,147,483,647✔
7609
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
2,147,483,647✔
7610
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
2,147,483,647✔
7611
      if (TSDB_CODE_SUCCESS != code) {
2,147,483,647✔
7612
        return code;
×
7613
      }
7614
    }
7615
  } else {
7616
    pResInfo->numOfRes = 0;
×
7617
  }
7618

7619
  return code;
2,147,483,647✔
7620
}
7621

7622
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
2,147,483,647✔
7623

7624
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7625
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7626
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7627

7628
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7629
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7630

7631
  // escape rest of data blocks to avoid first entry to be overwritten.
7632
  if (pDBuf->hasResult) {
×
7633
    goto _group_key_over;
×
7634
  }
7635

7636
  if (pSBuf->isNull) {
×
7637
    pDBuf->isNull = true;
×
7638
    pDBuf->hasResult = true;
×
7639
    goto _group_key_over;
×
7640
  }
7641

7642
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7643
    int32_t bytes = calcStrBytesByType(pSourceCtx->resDataInfo.type, pSBuf->data);
×
7644
    (void)memcpy(pDBuf->data, pSBuf->data, bytes);
×
7645
  } else {
7646
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7647
  }
7648

7649
  pDBuf->hasResult = true;
×
7650

7651
_group_key_over:
×
7652

7653
  SET_VAL(pDResInfo, 1, 1);
×
7654
  return TSDB_CODE_SUCCESS;
×
7655
}
7656

7657
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
701,422✔
7658
  int32_t numOfElems = 0;
701,422✔
7659

7660
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
701,422✔
7661
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
701,422✔
7662

7663
  SInputColumnInfoData* pInput = &pCtx->input;
701,422✔
7664
  SColumnInfoData*      pInputCol = pInput->pData[0];
701,422✔
7665

7666
  int32_t bytes = pInputCol->info.bytes;
701,422✔
7667
  pInfo->bytes = bytes;
701,422✔
7668

7669
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
701,422✔
7670
  pInfo->pkType = -1;
701,422✔
7671
  __compar_fn_t pkCompareFn = NULL;
701,422✔
7672
  if (pCtx->hasPrimaryKey) {
701,422✔
7673
    pInfo->pkType = pkCol->info.type;
344,916✔
7674
    pInfo->pkBytes = pkCol->info.bytes;
344,916✔
7675
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
344,916✔
7676
  }
7677

7678
  // data is guaranteed to be in descending order
7679
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
1,455,462✔
7680
    numOfElems++;
754,040✔
7681

7682
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
754,040✔
7683
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
754,040✔
7684

7685
    TSKEY cts = getRowPTs(pInput->pPTS, i);
754,040✔
7686
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
754,040✔
7687
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
460,183✔
7688
      if (code != TSDB_CODE_SUCCESS) {
460,183✔
7689
        return code;
×
7690
      }
7691
      pResInfo->numOfRes = 1;
460,183✔
7692
    }
7693
  }
7694

7695
  SET_VAL(pResInfo, numOfElems, 1);
701,422✔
7696
  return TSDB_CODE_SUCCESS;
701,422✔
7697
}
7698

7699
bool getCorrFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
520✔
7700
  pEnv->calcMemSize = sizeof(SCorrRes);
520✔
7701
  return true;
520✔
7702
}
7703

7704
int32_t corrFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
520✔
7705
  if (pResultInfo->initialized) {
520✔
7706
    return TSDB_CODE_SUCCESS;
×
7707
  }
7708
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
520✔
7709
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
7710
  }
7711

7712
  SCorrRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
520✔
7713
  (void)memset(pRes, 0, sizeof(SCorrRes));
520✔
7714
  return TSDB_CODE_SUCCESS;
520✔
7715
}
7716

7717
int32_t corrFunction(SqlFunctionCtx* pCtx) {
520✔
7718
  int32_t               numOfElem = 0;
520✔
7719
  SInputColumnInfoData* pInput = &pCtx->input;
520✔
7720
  int32_t               xType = pInput->pData[0]->info.type;
520✔
7721
  int32_t               yType = pInput->pData[1]->info.type;
520✔
7722
  SCorrRes*             pCorrRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
520✔
7723

7724
  // computing based on the true data block
7725
  SColumnInfoData* pLeft = pInput->pData[0];   // left
520✔
7726
  SColumnInfoData* pRight = pInput->pData[1];  // right
520✔
7727

7728
  int32_t leftMod = typeGetTypeModFromColInfo(&pLeft->info);
520✔
7729
  int32_t rightMod = typeGetTypeModFromColInfo(&pRight->info);
520✔
7730
  int32_t start = pInput->startRowIndex;
520✔
7731
  int32_t numOfRows = pInput->numOfRows;
520✔
7732

7733
  if (IS_NULL_TYPE(xType) || IS_NULL_TYPE(yType)) {
520✔
7734
    numOfElem = 0;
×
7735
    goto _over;
×
7736
  }
7737

7738
  for (int32_t i = 0; i < numOfRows; ++i) {
2,080✔
7739
    double pInputX = 0, pInputY = 0;
1,560✔
7740

7741
    if (colDataIsNull_f(pLeft, i) || colDataIsNull_f(pRight, i)) {
1,560✔
7742
      continue;
×
7743
    }
7744

7745
    char* pXVal = colDataGetData(pLeft, i);
1,560✔
7746
    char* pYVal = colDataGetData(pRight, i);
1,560✔
7747

7748
    GET_TYPED_DATA(pInputX, double, xType, pXVal, leftMod);
1,560✔
7749
    GET_TYPED_DATA(pInputY, double, yType, pYVal, rightMod);
1,560✔
7750

7751
    pCorrRes->sumLeft += pInputX;
1,560✔
7752
    pCorrRes->sumRight += pInputY;
1,560✔
7753

7754
    pCorrRes->quadLeft += pInputX * pInputX;
1,560✔
7755
    pCorrRes->quadRight += pInputY * pInputY;
1,560✔
7756

7757
    pCorrRes->productVal += pInputX * pInputY;
1,560✔
7758

7759
    pCorrRes->count += 1;
1,560✔
7760
    numOfElem += 1;
1,560✔
7761
  }
7762

7763
_over:
520✔
7764
  // data in the check operation are all null, not output
7765
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
520✔
7766
  return TSDB_CODE_SUCCESS;
520✔
7767
}
7768

7769
int32_t corrFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
520✔
7770
  SInputColumnInfoData* pInput = &pCtx->input;
520✔
7771
  SCorrRes*             pRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
520✔
7772
  double                avg;
7773

7774
  if (pRes->count == 0) {
520✔
7775
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
7776
    return functionFinalize(pCtx, pBlock);
×
7777
  }
7778

7779
  /**
7780
    numerator = sum_xy - (sum_x * sum_y) / n
7781
    denominator_x = math.sqrt(sum_x2 - (sum_x**2) / n)
7782
    denominator_y = math.sqrt(sum_y2 - (sum_y**2) / n)
7783

7784
    if denominator_x == 0 or denominator_y == 0:
7785
        return 0.0
7786
    res = numerator / (denominator_x * denominator_y)
7787
  */
7788

7789
  if (pRes->count == 1) {
520✔
7790
    pRes->result = 0.0;
×
7791
  } else {
7792
    double numerator = pRes->productVal - (pRes->sumLeft * pRes->sumRight) / pRes->count;
520✔
7793
    double dnmX = sqrt(pRes->quadLeft - pRes->sumLeft * pRes->sumLeft / pRes->count);
520✔
7794
    double dnmY = sqrt(pRes->quadRight - pRes->sumRight * pRes->sumRight / pRes->count);
520✔
7795

7796
    if (DBL_EQUAL(dnmX, 0.0) || DBL_EQUAL(dnmY, 0.0)) {
520✔
7797
      pRes->result = 0.0;
520✔
7798
    } else {
7799
      pRes->result = numerator / (dnmX * dnmY);
×
7800

7801
      if (pRes->result > 1 || pRes->result < -1) {
×
7802
        qError("invalid corr results, %.4f, numerator:%.4f, dnmX:%.4f, dnmY:%.4f", pRes->result, numerator, dnmX, dnmY);
×
7803
        if (pRes->result > 1) {
×
7804
          pRes->result = 1;
×
7805
        } else if (pRes->result < -1) {
×
7806
          pRes->result = -1;
×
7807
        }
7808
      }
7809
    }
7810
  }
7811

7812
  return functionFinalize(pCtx, pBlock);
520✔
7813
}
7814

7815
int32_t getCorrInfoSize() { return sizeof(SCorrRes); }
×
7816

7817
int32_t corrPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
7818
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
7819
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7820
  int32_t              resultBytes = getCorrInfoSize();
×
7821
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
7822
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
×
7823
  int32_t              code = 0;
×
7824

7825
  if (NULL == res) {
×
7826
    return terrno;
×
7827
  }
7828

7829
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
7830
  varDataSetLen(res, resultBytes);
×
7831

7832
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
7833
  if (NULL == pCol) {
×
7834
    taosMemoryFree(res);
×
7835
    return TSDB_CODE_OUT_OF_RANGE;
×
7836
  }
7837

7838
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
7839

7840
  taosMemoryFree(res);
×
7841
  return code;
×
7842
}
7843

7844
int32_t corrFuncMerge(SqlFunctionCtx* pCtx) {
×
7845
  SInputColumnInfoData* pInput = &pCtx->input;
×
7846
  SColumnInfoData*      pCol = pInput->pData[0];
×
7847

7848
  if (IS_NULL_TYPE(pCol->info.type)) {
×
7849
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
7850
    return TSDB_CODE_SUCCESS;
×
7851
  }
7852

7853
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
7854
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7855
  }
7856

7857
  SCorrRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
7858

7859
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
×
7860
    if (colDataIsNull_s(pCol, i)) {
×
7861
      continue;
×
7862
    }
7863

7864
    char*     data = colDataGetData(pCol, i);
×
7865
    SCorrRes* pInputInfo = (SCorrRes*)varDataVal(data);
×
7866

7867
    if (pInputInfo->count == 0) {
×
7868
      continue;
×
7869
    }
7870

7871
    // pOutput->type = pInput->type;
7872
    if (pInfo->count == 0) {
×
7873
      TAOS_MEMCPY(pInfo, pInputInfo, sizeof(SCorrRes));
×
7874
    } else if (pInfo->count > 0) {
×
7875
      pInfo->productVal += pInputInfo->productVal;
×
7876
      pInfo->quadLeft += pInputInfo->quadLeft;
×
7877
      pInfo->quadRight += pInputInfo->quadRight;
×
7878
      pInfo->sumLeft += pInputInfo->sumLeft;
×
7879
      pInfo->sumRight += pInputInfo->sumRight;
×
7880
      pInfo->count += pInputInfo->count;
×
7881
    }
7882
  }
7883

7884
  SET_VAL(GET_RES_INFO(pCtx), pInfo->count, 1);
×
7885
  return TSDB_CODE_SUCCESS;
×
7886
}
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