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

taosdata / TDengine / #3614

14 Feb 2025 09:14AM UTC coverage: 61.4% (-2.1%) from 63.499%
#3614

push

travis-ci

web-flow
Merge pull request #29781 from taosdata/doc/internal

docs: minor changes

142800 of 298998 branches covered (47.76%)

Branch coverage included in aggregate %.

224842 of 299767 relevant lines covered (75.01%)

17915812.99 hits per line

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

72.64
/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 "function.h"
19
#include "functionResInfoInt.h"
20
#include "query.h"
21
#include "querynodes.h"
22
#include "tanalytics.h"
23
#include "tcompare.h"
24
#include "tdatablock.h"
25
#include "tdigest.h"
26
#include "tfunctionInt.h"
27
#include "tglobal.h"
28
#include "thistogram.h"
29
#include "tpercentile.h"
30

31
bool ignoreNegative(int8_t ignoreOption) { return (ignoreOption & 0x1) == 0x1; }
1,813,094,545✔
32
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
2,133,710✔
33

34
typedef enum {
35
  APERCT_ALGO_UNKNOWN = 0,
36
  APERCT_ALGO_DEFAULT,
37
  APERCT_ALGO_TDIGEST,
38
} EAPerctAlgoType;
39

40
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
41

42
typedef enum {
43
  STATE_OPER_INVALID = 0,
44
  STATE_OPER_LT,
45
  STATE_OPER_GT,
46
  STATE_OPER_LE,
47
  STATE_OPER_GE,
48
  STATE_OPER_NE,
49
  STATE_OPER_EQ,
50
} EStateOperType;
51

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

60
#define GET_TS_LIST(x)    ((TSKEY*)((x)->ptsList))
61
#define GET_TS_DATA(x, y) (GET_TS_LIST(x)[(y)])
62

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

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

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

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

108
#define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem)             \
109
  do {                                                                   \
110
    _t* d = (_t*)(_col->pData);                                          \
111
    for (int32_t i = (_start); i < (_rows) + (_start); ++i) {            \
112
      if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \
113
        continue;                                                        \
114
      };                                                                 \
115
      (_res) -= (d)[i];                                                  \
116
      (numOfElem)++;                                                     \
117
    }                                                                    \
118
  } while (0)
119

120
//#define LIST_AVG_N(sumT, T)                                               \
121
//  do {                                                                    \
122
//    T* plist = (T*)pCol->pData;                                           \
123
//    for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
124
//      if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {        \
125
//        continue;                                                         \
126
//      }                                                                   \
127
//                                                                          \
128
//      numOfElem += 1;                                                     \
129
//      pAvgRes->count -= 1;                                                \
130
//      sumT -= plist[i];                                                   \
131
//    }                                                                     \
132
//  } while (0)
133

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

148
#define LEASTSQR_CAL(p, x, y, index, step) \
149
  do {                                     \
150
    (p)[0][0] += (double)(x) * (x);        \
151
    (p)[0][1] += (double)(x);              \
152
    (p)[0][2] += (double)(x) * (y)[index]; \
153
    (p)[1][2] += (y)[index];               \
154
    (x) += step;                           \
155
  } while (0)
156

157
#define STATE_COMP(_op, _lval, _param) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_param))
158

159
#define GET_STATE_VAL(param) ((param.nType == TSDB_DATA_TYPE_BIGINT) ? (param.i) : (param.d))
160

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

187
#define INIT_INTP_POINT(_p, _k, _v) \
188
  do {                              \
189
    (_p).key = (_k);                \
190
    (_p).val = (_v);                \
191
  } while (0)
192

193
void funcInputUpdate(SqlFunctionCtx* pCtx) {
17,834,081✔
194
  SFuncInputRowIter* pIter = &pCtx->rowIter;
17,834,081✔
195

196
  if (!pCtx->bInputFinished) {
17,834,081!
197
    pIter->pInput = &pCtx->input;
17,834,128✔
198
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
17,834,128✔
199
    pIter->pDataCol = pIter->pInput->pData[0];
17,834,128✔
200
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
17,834,128✔
201
    pIter->rowIndex = pIter->pInput->startRowIndex;
17,834,128✔
202
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
17,834,128✔
203
    pIter->pSrcBlock = pCtx->pSrcBlock;
17,834,128✔
204
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
17,834,128✔
205
      pIter->hasGroupId = true;
224,787✔
206
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
224,787✔
207
      pIter->hasPrev = false;
224,787✔
208
    }
209
  } else {
210
    pIter->finalRow = true;
×
211
  }
212
}
17,834,081✔
213

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

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

239
      pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex);
×
240

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

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

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

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

321
      int32_t code = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1, &pIter->pPrevRowBlock);
×
322
      *res = false;
×
323
      return code;
×
324
    }
325
  }
326
}
327

328
static void forwardToNextDiffTsRow(SFuncInputRowIter* pIter, int32_t rowIndex) {
160✔
329
  int32_t idx = rowIndex + 1;
160✔
330
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
362!
331
    ++idx;
202✔
332
  }
333
  pIter->rowIndex = idx;
160✔
334
}
160✔
335

336
static void setInputRowInfo(SFuncInputRow* pRow, SFuncInputRowIter* pIter, int32_t rowIndex, bool setPk) {
1,843,315,795✔
337
  pRow->ts = pIter->tsList[rowIndex];
1,843,315,795✔
338
  pRow->ts = pIter->tsList[rowIndex];
1,843,315,795✔
339
  pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, rowIndex);
1,843,315,795✔
340
  pRow->pData = colDataGetData(pIter->pDataCol, rowIndex);
1,843,315,795!
341
  pRow->pPk = setPk ? colDataGetData(pIter->pPkCol, rowIndex) : NULL;
1,843,315,795!
342
  pRow->block = pIter->pSrcBlock;
1,843,315,795✔
343
  pRow->rowIndex = rowIndex;
1,843,315,795✔
344
}
1,843,315,795✔
345

346
bool funcInputGetNextRowAscPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
330✔
347
  if (pIter->hasPrev) {
330!
348
    if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) {
×
349
      pIter->hasPrev = true;
×
350
      return false;
×
351
    } else {
352
      int32_t idx = pIter->rowIndex;
×
353
      while (pIter->tsList[idx] == pIter->prevBlockTsEnd) {
×
354
        ++idx;
×
355
      }
356

357
      pIter->hasPrev = false;
×
358
      setInputRowInfo(pRow, pIter, idx, true);
×
359
      forwardToNextDiffTsRow(pIter, idx);
×
360
      return true;
×
361
    }
362
  } else {
363
    if (pIter->rowIndex <= pIter->inputEndIndex) {
330✔
364
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
248✔
365

366
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
248✔
367
      if (pIter->tsList[pIter->rowIndex] != tsEnd) {
248✔
368
        forwardToNextDiffTsRow(pIter, pIter->rowIndex);
160✔
369
      } else {
370
        pIter->rowIndex = pIter->inputEndIndex + 1;
88✔
371
      }
372
      return true;
248✔
373
    } else {
374
      TSKEY tsEnd = pIter->tsList[pIter->inputEndIndex];
82✔
375
      pIter->hasPrev = true;
82✔
376
      pIter->prevBlockTsEnd = tsEnd;
82✔
377
      return false;
82✔
378
    }
379
  }
380
}
381

382
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
1,861,024,475✔
383
  if (pIter->rowIndex <= pIter->inputEndIndex) {
1,861,024,475✔
384
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
1,843,326,671✔
385
    ++pIter->rowIndex;
1,843,249,030✔
386
    return true;
1,843,249,030✔
387
  } else {
388
    return false;
17,697,804✔
389
  }
390
}
391

392
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
1,861,074,012✔
393
  SFuncInputRowIter* pIter = &pCtx->rowIter;
1,861,074,012✔
394
  if (pCtx->hasPrimaryKey) {
1,861,074,012✔
395
    if (pCtx->order == TSDB_ORDER_ASC) {
330!
396
      *res = funcInputGetNextRowAscPk(pIter, pRow);
330✔
397
      return TSDB_CODE_SUCCESS;
330✔
398
    } else {
399
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
400
    }
401
  } else {
402
    *res = funcInputGetNextRowNoPk(pIter, pRow);
1,861,073,682✔
403
    return TSDB_CODE_SUCCESS;
1,860,902,700✔
404
  }
405
  return TSDB_CODE_SUCCESS;
406
}
407

408
// This function append the selectivity to subsidiaries function context directly, without fetching data
409
// from intermediate disk based buf page
410
int32_t appendSelectivityCols(SqlFunctionCtx* pCtx, SSDataBlock* pSrcBlock, int32_t rowIndex, int32_t pos) {
36,175,116✔
411
  if (pCtx->subsidiaries.num <= 0) {
36,175,116!
412
    return TSDB_CODE_SUCCESS;
×
413
  }
414

415
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
98,048,514✔
416
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
61,873,650✔
417

418
    // get data from source col
419
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
61,873,650✔
420
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
61,873,650✔
421

422
    SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
61,873,650✔
423
    if (NULL == pSrcCol) {
61,873,546!
424
      return TSDB_CODE_OUT_OF_RANGE;
×
425
    }
426

427
    char* pData = colDataGetData(pSrcCol, rowIndex);
61,873,546!
428

429
    // append to dest col
430
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
61,873,546✔
431

432
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
61,873,546✔
433
    if (NULL == pDstCol) {
61,873,448!
434
      return TSDB_CODE_OUT_OF_RANGE;
×
435
    }
436
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
123,746,896✔
437
      colDataSetNULL(pDstCol, pos);
2,579,997✔
438
    } else {
439
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
59,293,451✔
440
      if (TSDB_CODE_SUCCESS != code) {
59,293,401!
441
        return code;
×
442
      }
443
    }
444
  }
445
  return TSDB_CODE_SUCCESS;
36,174,864✔
446
}
447

448
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
449
                              int32_t* nextFrom);
450

451
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst);
452

453
int32_t functionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
718,950,794✔
454
  if (pResultInfo->initialized) {
718,950,794✔
455
    return TSDB_CODE_SUCCESS;  // already initialized
165,119✔
456
  }
457

458
  if (pCtx->pOutput != NULL) {
718,785,675!
459
    (void)memset(pCtx->pOutput, 0, (size_t)pCtx->resDataInfo.bytes);
×
460
  }
461

462
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
718,785,675✔
463
  return TSDB_CODE_SUCCESS;
718,785,675✔
464
}
465

466
int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
206,483,686✔
467
  int32_t          code = TSDB_CODE_SUCCESS;
206,483,686✔
468
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
206,483,686✔
469
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
206,483,686✔
470
  if (NULL == pCol) {
206,043,489!
471
    return TSDB_CODE_OUT_OF_RANGE;
×
472
  }
473
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
206,043,489✔
474
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
206,043,489✔
475

476
  char* in = GET_ROWCELL_INTERBUF(pResInfo);
206,043,489✔
477
  code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
206,043,489✔
478

479
  return code;
207,314,766✔
480
}
481

482
int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
483
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
484
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
485
  int32_t              bytes = pDBuf->bytes;
3✔
486

487
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
488
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
489

490
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, true);
3✔
491

492
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
493
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
494
  return TSDB_CODE_SUCCESS;
3✔
495
}
496

497
int32_t functionFinalizeWithResultBuf(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, char* finalResult) {
39✔
498
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
39✔
499
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
39✔
500
  if (NULL == pCol) {
39!
501
    return TSDB_CODE_OUT_OF_RANGE;
×
502
  }
503
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
39✔
504
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
39✔
505

506
  char*   in = finalResult;
39✔
507
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes);
39✔
508

509
  return code;
39✔
510
}
511

512
EFuncDataRequired countDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
206,276✔
513
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
206,276✔
514
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
206,314!
515
    return FUNC_DATA_REQUIRED_NOT_LOAD;
147,416✔
516
  }
517
  return FUNC_DATA_REQUIRED_SMA_LOAD;
58,898✔
518
}
519

520
bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
1,744,557✔
521
  pEnv->calcMemSize = sizeof(int64_t);
1,744,557✔
522
  return true;
1,744,557✔
523
}
524

525
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
119,341,129✔
526
  int64_t numOfElem = 0;
119,341,129✔
527

528
  /*
529
   * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true;
530
   * 2. for general non-primary key columns, pInputCol->hasNull may be true or false, pInput->colDataSMAIsSet == true;
531
   * 3. for primary key column, pInputCol->hasNull always be false, pInput->colDataSMAIsSet == false;
532
   */
533
  SInputColumnInfoData* pInput = &pCtx->input;
119,341,129✔
534
  SColumnInfoData*      pInputCol = pInput->pData[0];
119,341,129✔
535
  if (1 == pInput->numOfRows && pInput->blankFill) {
119,341,129✔
536
    return 0;
447,965✔
537
  }
538
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
118,893,164!
539
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
4,088✔
540
  } else {
541
    if (pInputCol->hasNull) {
118,889,076✔
542
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
378,072,632✔
543
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
692,566,472!
544
          continue;
2,310,975✔
545
        }
546
        numOfElem += 1;
343,972,261✔
547
      }
548
    } else {
549
      // when counting on the primary time stamp column and no statistics data is presented, use the size value
550
      // directly.
551
      numOfElem = pInput->numOfRows;
87,099,680✔
552
    }
553
  }
554
  return numOfElem;
118,893,164✔
555
}
556

557
/*
558
 * count function does need the finalize, if data is missing, the default value, which is 0, is used
559
 * count function does not use the pCtx->interResBuf to keep the intermediate buffer
560
 */
561
int32_t countFunction(SqlFunctionCtx* pCtx) {
119,417,379✔
562
  int64_t numOfElem = 0;
119,417,379✔
563

564
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
119,417,379✔
565
  SInputColumnInfoData* pInput = &pCtx->input;
119,417,379✔
566

567
  int32_t type = pInput->pData[0]->info.type;
119,417,379✔
568

569
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
119,417,379✔
570
  if (IS_NULL_TYPE(type)) {
119,417,379✔
571
    // select count(NULL) returns 0
572
    numOfElem = 1;
136,104✔
573
    *((int64_t*)buf) += 0;
136,104✔
574
  } else {
575
    numOfElem = getNumOfElems(pCtx);
119,281,275✔
576
    *((int64_t*)buf) += numOfElem;
118,957,434✔
577
  }
578

579
  if (tsCountAlwaysReturnValue) {
119,093,538!
580
    pResInfo->numOfRes = 1;
119,154,710✔
581
  } else {
582
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
583
  }
584

585
  return TSDB_CODE_SUCCESS;
119,093,538✔
586
}
587

588
#ifdef BUILD_NO_CALL
589
int32_t countInvertFunction(SqlFunctionCtx* pCtx) {
590
  int64_t numOfElem = getNumOfElems(pCtx);
591

592
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
593
  char*                buf = GET_ROWCELL_INTERBUF(pResInfo);
594
  *((int64_t*)buf) -= numOfElem;
595

596
  SET_VAL(pResInfo, *((int64_t*)buf), 1);
597
  return TSDB_CODE_SUCCESS;
598
}
599
#endif
600

601
int32_t combineFunction(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
18✔
602
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
18✔
603
  char*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
18✔
604

605
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
18✔
606
  char*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
18✔
607
  *((int64_t*)pDBuf) += *((int64_t*)pSBuf);
18✔
608

609
  SET_VAL(pDResInfo, *((int64_t*)pDBuf), 1);
18!
610
  return TSDB_CODE_SUCCESS;
18✔
611
}
612

613
int32_t sumFunction(SqlFunctionCtx* pCtx) {
90,839,819✔
614
  int32_t numOfElem = 0;
90,839,819✔
615

616
  // Only the pre-computing information loaded and actual data does not loaded
617
  SInputColumnInfoData* pInput = &pCtx->input;
90,839,819✔
618
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
90,839,819✔
619
  int32_t               type = pInput->pData[0]->info.type;
90,839,819✔
620

621
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
90,839,819✔
622
  pSumRes->type = type;
90,839,819✔
623

624
  if (IS_NULL_TYPE(type)) {
90,839,819✔
625
    numOfElem = 0;
241✔
626
    goto _sum_over;
241✔
627
  }
628

629
  if (pInput->colDataSMAIsSet) {
90,839,578✔
630
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
2,878✔
631

632
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
2,878!
633
      pSumRes->isum += pAgg->sum;
2,878✔
634
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
635
      pSumRes->usum += pAgg->sum;
×
636
    } else if (IS_FLOAT_TYPE(type)) {
×
637
      pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum));
×
638
    }
639
  } else {  // computing based on the true data block
640
    SColumnInfoData* pCol = pInput->pData[0];
90,836,700✔
641

642
    int32_t start = pInput->startRowIndex;
90,836,700✔
643
    int32_t numOfRows = pInput->numOfRows;
90,836,700✔
644

645
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
90,836,700!
646
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
86,799,264!
647
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
1,868,000✔
648
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
86,411,044✔
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
534,336✔
650
      } else if (type == TSDB_DATA_TYPE_INT) {
86,367,306✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
396,045,986✔
652
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
20,533,235✔
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
77,366,588✔
654
      }
655
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
4,037,436!
656
      if (type == TSDB_DATA_TYPE_UTINYINT) {
202✔
657
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
658
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
163✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
660
      } else if (type == TSDB_DATA_TYPE_UINT) {
123✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
130,039!
662
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
84!
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
130,624✔
664
      }
665
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
4,037,234✔
666
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
10,700,065✔
667
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
770,578✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
1,883,037✔
669
    }
670
  }
671

672
  // check for overflow
673
  if (IS_FLOAT_TYPE(type) && (isinf(pSumRes->dsum) || isnan(pSumRes->dsum))) {
90,839,578!
674
    numOfElem = 0;
×
675
  }
676

677
_sum_over:
91,165,910✔
678
  if (numOfElem == 0) {
90,839,819✔
679
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
107,799✔
680
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,512✔
681
      numOfElem = 1;
31✔
682
    }
683
  }
684
  // data in the check operation are all null, not output
685
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
90,839,819✔
686
  return TSDB_CODE_SUCCESS;
90,839,819✔
687
}
688

689
#ifdef BUILD_NO_CALL
690
int32_t sumInvertFunction(SqlFunctionCtx* pCtx) {
691
  int32_t numOfElem = 0;
692

693
  // Only the pre-computing information loaded and actual data does not loaded
694
  SInputColumnInfoData* pInput = &pCtx->input;
695
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
696
  int32_t               type = pInput->pData[0]->info.type;
697

698
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
699

700
  if (pInput->colDataSMAIsSet) {
701
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
702

703
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
704
      pSumRes->isum -= pAgg->sum;
705
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
706
      pSumRes->usum -= pAgg->sum;
707
    } else if (IS_FLOAT_TYPE(type)) {
708
      pSumRes->dsum -= GET_DOUBLE_VAL((const char*)&(pAgg->sum));
709
    }
710
  } else {  // computing based on the true data block
711
    SColumnInfoData* pCol = pInput->pData[0];
712

713
    int32_t start = pInput->startRowIndex;
714
    int32_t numOfRows = pInput->numOfRows;
715

716
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
717
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
718
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
719
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
720
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
721
      } else if (type == TSDB_DATA_TYPE_INT) {
722
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
723
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
724
        LIST_SUB_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
725
      }
726
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
727
      if (type == TSDB_DATA_TYPE_UTINYINT) {
728
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
729
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
730
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
731
      } else if (type == TSDB_DATA_TYPE_UINT) {
732
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
733
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
734
        LIST_SUB_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
735
      }
736
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
737
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
738
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
739
      LIST_SUB_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
740
    }
741
  }
742

743
  // data in the check operation are all null, not output
744
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
745
  return TSDB_CODE_SUCCESS;
746
}
747
#endif
748

749
int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
46✔
750
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
46✔
751
  SSumRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
46✔
752

753
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
46✔
754
  SSumRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
46✔
755
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
46✔
756

757
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
46!
758
    pDBuf->isum += pSBuf->isum;
46✔
759
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
760
    pDBuf->usum += pSBuf->usum;
×
761
  } else if (type == TSDB_DATA_TYPE_DOUBLE || type == TSDB_DATA_TYPE_FLOAT) {
×
762
    pDBuf->dsum += pSBuf->dsum;
×
763
  }
764
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
46✔
765
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
46✔
766
  return TSDB_CODE_SUCCESS;
46✔
767
}
768

769
bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
236,540✔
770
  pEnv->calcMemSize = sizeof(SSumRes);
236,540✔
771
  return true;
236,540✔
772
}
773

774
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
187,625✔
775
  SNode* pParam;
776
  switch (pFunc->funcType) {
187,625!
777
    case FUNCTION_TYPE_MAX:
187,625✔
778
    case FUNCTION_TYPE_MIN:
779
    case FUNCTION_TYPE_SUM:
780
    case FUNCTION_TYPE_AVG:
781
    case FUNCTION_TYPE_AVG_PARTIAL:
782
    case FUNCTION_TYPE_PERCENTILE:
783
    case FUNCTION_TYPE_SPREAD:
784
    case FUNCTION_TYPE_SPREAD_PARTIAL:
785
    case FUNCTION_TYPE_SPREAD_MERGE:
786
    case FUNCTION_TYPE_TWA:
787
    case FUNCTION_TYPE_ELAPSED:
788
      pParam = nodesListGetNode(pFunc->pParameterList, 0);
187,625✔
789
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
187,625!
790
        return true;
126✔
791
      }
792
      break;
187,499✔
793
    default:
×
794
      break;
×
795
  }
796
  return false;
187,499✔
797
}
798

799
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
187,625✔
800
  if(funcNotSupportStringSma(pFunc)) {
187,625✔
801
    return FUNC_DATA_REQUIRED_DATA_LOAD;
126✔
802
  }
803
  return FUNC_DATA_REQUIRED_SMA_LOAD;
187,499✔
804
}
805

806
int32_t minmaxFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
56,597,256✔
807
  if (pResultInfo->initialized) {
56,597,256!
808
    return TSDB_CODE_SUCCESS;
×
809
  }
810
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
56,597,256!
811
    return TSDB_CODE_FUNC_SETUP_ERROR;  // not initialized since it has been initialized
×
812
  }
813

814
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
56,612,759✔
815
  buf->assign = false;
56,612,759✔
816
  buf->tuplePos.pageId = -1;
56,612,759✔
817

818
  buf->nullTupleSaved = false;
56,612,759✔
819
  buf->nullTuplePos.pageId = -1;
56,612,759✔
820
  buf->str = NULL;
56,612,759✔
821
  return TSDB_CODE_SUCCESS;
56,612,759✔
822
}
823

824
bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
423,039✔
825
  pEnv->calcMemSize = sizeof(SMinmaxResInfo);
423,039✔
826
  return true;
423,039✔
827
}
828

829
int32_t minFunction(SqlFunctionCtx* pCtx) {
32,056,110✔
830
  int32_t numOfElems = 0;
32,056,110✔
831
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
32,056,110✔
832
  if (code != TSDB_CODE_SUCCESS) {
32,149,974!
833
    return code;
×
834
  }
835
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
32,149,974✔
836
  return TSDB_CODE_SUCCESS;
32,149,974✔
837
}
838

839
int32_t maxFunction(SqlFunctionCtx* pCtx) {
29,406,619✔
840
  int32_t numOfElems = 0;
29,406,619✔
841
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
29,406,619✔
842
  if (code != TSDB_CODE_SUCCESS) {
29,524,657!
843
    return code;
×
844
  }
845
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
29,524,657✔
846
  return TSDB_CODE_SUCCESS;
29,524,657✔
847
}
848

849
static int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex);
850
static int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos,
851
                                   int32_t rowIndex);
852

853
int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
54,483,416✔
854
  int32_t code = TSDB_CODE_SUCCESS;
54,483,416✔
855

856
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
54,483,416✔
857
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
54,483,416✔
858

859
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
54,483,416✔
860
  int32_t currentRow = pBlock->info.rows;
54,483,416✔
861

862
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
54,483,416✔
863
  if (NULL == pCol) {
54,490,448!
864
    return TSDB_CODE_OUT_OF_RANGE;
×
865
  }
866
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
54,490,448✔
867

868
  // NOTE: do nothing change it, for performance issue
869
  if (!pEntryInfo->isNullRes) {
54,490,448✔
870
    switch (pCol->info.type) {
47,200,193!
871
      case TSDB_DATA_TYPE_UBIGINT:
15,058,066✔
872
      case TSDB_DATA_TYPE_BIGINT:
873
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
15,058,066✔
874
        break;
15,058,066✔
875
      case TSDB_DATA_TYPE_UINT:
19,849,630✔
876
      case TSDB_DATA_TYPE_INT:
877
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
19,849,630✔
878
        break;
19,849,630✔
879
      case TSDB_DATA_TYPE_USMALLINT:
8,660,050✔
880
      case TSDB_DATA_TYPE_SMALLINT:
881
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
8,660,050✔
882
        break;
8,660,050✔
883
      case TSDB_DATA_TYPE_BOOL:
203,267✔
884
      case TSDB_DATA_TYPE_UTINYINT:
885
      case TSDB_DATA_TYPE_TINYINT:
886
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
203,267✔
887
        break;
203,267✔
888
      case TSDB_DATA_TYPE_DOUBLE:
6,661✔
889
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
6,661✔
890
        break;
6,661✔
891
      case TSDB_DATA_TYPE_FLOAT: {
4,743✔
892
        float v = GET_FLOAT_VAL(&pRes->v);
4,743✔
893
        colDataSetFloat(pCol, currentRow, &v);
4,743✔
894
        break;
4,743✔
895
      }
896
      case TSDB_DATA_TYPE_VARBINARY:
3,449,158✔
897
      case TSDB_DATA_TYPE_VARCHAR:
898
      case TSDB_DATA_TYPE_NCHAR: {
899
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
3,449,158✔
900
        if (TSDB_CODE_SUCCESS != code) {
3,449,159!
901
          return code;
×
902
        }
903
        break;
3,449,159✔
904
      }
905
    }
906
  } else {
907
    colDataSetNULL(pCol, currentRow);
7,290,255!
908
  }
909

910
  taosMemoryFreeClear(pRes->str);
54,490,449!
911
  if (pCtx->subsidiaries.num > 0) {
54,490,451✔
912
    if (pEntryInfo->numOfRes > 0) {
11,012,537✔
913
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
11,010,158✔
914
    } else {
915
      code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
2,379✔
916
    }
917
  }
918

919
  return code;
54,498,720✔
920
}
921

922
#ifdef BUILD_NO_CALL
923
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
924
  if (pCtx->subsidiaries.num <= 0) {
925
    return TSDB_CODE_SUCCESS;
926
  }
927

928
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
929
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
930
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
931

932
    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
933
    colDataSetNULL(pDstCol, rowIndex);
934
  }
935

936
  return TSDB_CODE_SUCCESS;
937
}
938
#endif
939

940
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
261,512,175✔
941
  if (pCtx->subsidiaries.num <= 0) {
261,512,175✔
942
    return TSDB_CODE_SUCCESS;
137,828,804✔
943
  }
944

945
  if ((pCtx->saveHandle.pBuf != NULL && pTuplePos->pageId != -1) ||
123,683,371!
946
      (pCtx->saveHandle.pState && pTuplePos->streamTupleKey.ts > 0)) {
×
947
    int32_t numOfCols = pCtx->subsidiaries.num;
123,692,348✔
948
    char*   p = NULL;
123,692,348✔
949
    int32_t code = loadTupleData(pCtx, pTuplePos, &p);
123,692,348✔
950
    if (p == NULL || TSDB_CODE_SUCCESS != code) {
124,177,830!
951
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
952
             pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
953
      return TSDB_CODE_NOT_FOUND;
×
954
    }
955

956
    bool* nullList = (bool*)p;
124,179,676✔
957
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
124,179,676✔
958

959
    // todo set the offset value to optimize the performance.
960
    for (int32_t j = 0; j < numOfCols; ++j) {
248,223,323✔
961
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
124,216,983✔
962
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
124,216,983✔
963

964
      // group_key function has its own process function
965
      // do not process there
966
      if (fmIsGroupKeyFunc(pc->functionId)) {
124,216,983✔
967
        continue;
38,911✔
968
      }
969

970
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
124,180,012✔
971
      if (NULL == pDstCol) {
124,104,728!
972
        return TSDB_CODE_OUT_OF_RANGE;
×
973
      }
974
      if (nullList[j]) {
124,104,728✔
975
        colDataSetNULL(pDstCol, rowIndex);
200!
976
      } else {
977
        code = colDataSetVal(pDstCol, rowIndex, pStart, false);
124,104,528✔
978
        if (TSDB_CODE_SUCCESS != code) {
124,004,536!
979
          return code;
×
980
        }
981
      }
982
      pStart += pDstCol->info.bytes;
124,004,736✔
983
    }
984
  }
985

986
  return TSDB_CODE_SUCCESS;
123,997,363✔
987
}
988

989
// This function append the selectivity to subsidiaries function context directly, without fetching data
990
// from intermediate disk based buf page
991
int32_t appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) {
55,757,174✔
992
  if (pCtx->subsidiaries.num <= 0) {
55,757,174!
993
    return TSDB_CODE_SUCCESS;
×
994
  }
995

996
  int32_t code = TSDB_CODE_SUCCESS;
55,757,174✔
997
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
111,483,694✔
998
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
55,760,013✔
999

1000
    // get data from source col
1001
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
55,760,013✔
1002
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
55,760,013✔
1003

1004
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
55,760,013✔
1005
    if (NULL == pSrcCol) {
55,743,471!
1006
      return TSDB_CODE_OUT_OF_RANGE;
×
1007
    }
1008

1009
    char* pData = colDataGetData(pSrcCol, rowIndex);
55,743,471!
1010

1011
    // append to dest col
1012
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
55,743,471✔
1013

1014
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
55,743,471✔
1015
    if (NULL == pDstCol) {
55,718,867!
1016
      return TSDB_CODE_OUT_OF_RANGE;
×
1017
    }
1018

1019
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
111,437,734✔
1020
      colDataSetNULL(pDstCol, pos);
400✔
1021
    } else {
1022
      code = colDataSetVal(pDstCol, pos, pData, false);
55,718,467✔
1023
      if (TSDB_CODE_SUCCESS != code) {
55,726,120!
1024
        return code;
×
1025
      }
1026
    }
1027
  }
1028
  return code;
55,723,681✔
1029
}
1030

1031
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
32✔
1032

1033
#define COMPARE_MINMAX_DATA(type) (((*(type*)&pDBuf->v) < (*(type*)&pSBuf->v)) ^ isMinFunc)
1034
int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) {
57✔
1035
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
57✔
1036
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
57✔
1037

1038
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
57✔
1039
  SMinmaxResInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
57✔
1040
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
57✔
1041

1042
  switch (type) {
57!
1043
    case TSDB_DATA_TYPE_DOUBLE:
3✔
1044
    case TSDB_DATA_TYPE_UBIGINT:
1045
    case TSDB_DATA_TYPE_BIGINT:
1046
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int64_t) || !pDBuf->assign)) {
3!
1047
        pDBuf->v = pSBuf->v;
1✔
1048
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
1✔
1049
        pDBuf->assign = true;
1✔
1050
      }
1051
      break;
3✔
1052
    case TSDB_DATA_TYPE_UINT:
54✔
1053
    case TSDB_DATA_TYPE_INT:
1054
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int32_t) || !pDBuf->assign)) {
54!
1055
        pDBuf->v = pSBuf->v;
31✔
1056
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
31✔
1057
        pDBuf->assign = true;
31✔
1058
      }
1059
      break;
54✔
1060
    case TSDB_DATA_TYPE_USMALLINT:
×
1061
    case TSDB_DATA_TYPE_SMALLINT:
1062
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int16_t) || !pDBuf->assign)) {
×
1063
        pDBuf->v = pSBuf->v;
×
1064
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1065
        pDBuf->assign = true;
×
1066
      }
1067
      break;
×
1068
    case TSDB_DATA_TYPE_BOOL:
×
1069
    case TSDB_DATA_TYPE_UTINYINT:
1070
    case TSDB_DATA_TYPE_TINYINT:
1071
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(int8_t) || !pDBuf->assign)) {
×
1072
        pDBuf->v = pSBuf->v;
×
1073
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1074
        pDBuf->assign = true;
×
1075
      }
1076
      break;
×
1077
    case TSDB_DATA_TYPE_FLOAT: {
×
1078
      if (pSBuf->assign && (COMPARE_MINMAX_DATA(double) || !pDBuf->assign)) {
×
1079
        pDBuf->v = pSBuf->v;
×
1080
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1081
        pDBuf->assign = true;
×
1082
      }
1083
      break;
×
1084
    }
1085
    default:
×
1086
      if (pSBuf->assign && (strcmp((char*)&pDBuf->v, (char*)&pSBuf->v) || !pDBuf->assign)) {
×
1087
        pDBuf->v = pSBuf->v;
×
1088
        replaceTupleData(&pDBuf->tuplePos, &pSBuf->tuplePos);
×
1089
        pDBuf->assign = true;
×
1090
      }
1091
      break;
×
1092
  }
1093
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
57✔
1094
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
57✔
1095
  return TSDB_CODE_SUCCESS;
57✔
1096
}
1097

1098
int32_t minCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
11✔
1099
  return minMaxCombine(pDestCtx, pSourceCtx, 1);
11✔
1100
}
1101
int32_t maxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
46✔
1102
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
46✔
1103
}
1104

1105
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
1,075,173✔
1106

1107
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
151,694✔
1108
  pEnv->calcMemSize = sizeof(SStdRes);
151,694✔
1109
  return true;
151,694✔
1110
}
1111

1112
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,129,529✔
1113
  if (pResultInfo->initialized) {
8,129,529!
1114
    return TSDB_CODE_SUCCESS;
×
1115
  }
1116
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,129,529!
1117
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1118
  }
1119

1120
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
8,129,545✔
1121
  (void)memset(pRes, 0, sizeof(SStdRes));
8,129,545✔
1122
  return TSDB_CODE_SUCCESS;
8,129,545✔
1123
}
1124

1125
int32_t stdFunction(SqlFunctionCtx* pCtx) {
8,144,612✔
1126
  int32_t numOfElem = 0;
8,144,612✔
1127

1128
  // Only the pre-computing information loaded and actual data does not loaded
1129
  SInputColumnInfoData* pInput = &pCtx->input;
8,144,612✔
1130
  int32_t               type = pInput->pData[0]->info.type;
8,144,612✔
1131

1132
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,144,612✔
1133
  pStdRes->type = type;
8,144,612✔
1134

1135
  // computing based on the true data block
1136
  SColumnInfoData* pCol = pInput->pData[0];
8,144,612✔
1137

1138
  int32_t start = pInput->startRowIndex;
8,144,612✔
1139
  int32_t numOfRows = pInput->numOfRows;
8,144,612✔
1140

1141
  if (IS_NULL_TYPE(type)) {
8,144,612✔
1142
    numOfElem = 0;
124✔
1143
    goto _stddev_over;
124✔
1144
  }
1145

1146
  switch (type) {
8,144,488!
1147
    case TSDB_DATA_TYPE_TINYINT: {
2,425,426✔
1148
      int8_t* plist = (int8_t*)pCol->pData;
2,425,426✔
1149
      for (int32_t i = start; i < numOfRows + start; ++i) {
8,817,778✔
1150
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
6,392,352✔
1151
          continue;
104,523✔
1152
        }
1153

1154
        numOfElem += 1;
6,287,829✔
1155
        pStdRes->count += 1;
6,287,829✔
1156
        pStdRes->isum += plist[i];
6,287,829✔
1157
        pStdRes->quadraticISum += plist[i] * plist[i];
6,287,829✔
1158
      }
1159

1160
      break;
2,425,426✔
1161
    }
1162

1163
    case TSDB_DATA_TYPE_SMALLINT: {
220,634✔
1164
      int16_t* plist = (int16_t*)pCol->pData;
220,634✔
1165
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,222,044✔
1166
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,001,410✔
1167
          continue;
110,852✔
1168
        }
1169

1170
        numOfElem += 1;
890,558✔
1171
        pStdRes->count += 1;
890,558✔
1172
        pStdRes->isum += plist[i];
890,558✔
1173
        pStdRes->quadraticISum += plist[i] * plist[i];
890,558✔
1174
      }
1175
      break;
220,634✔
1176
    }
1177

1178
    case TSDB_DATA_TYPE_INT: {
19,982✔
1179
      int32_t* plist = (int32_t*)pCol->pData;
19,982✔
1180
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,158,743✔
1181
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,138,761✔
1182
          continue;
37,619✔
1183
        }
1184

1185
        numOfElem += 1;
1,101,142✔
1186
        pStdRes->count += 1;
1,101,142✔
1187
        pStdRes->isum += plist[i];
1,101,142✔
1188
        pStdRes->quadraticISum += plist[i] * plist[i];
1,101,142✔
1189
      }
1190

1191
      break;
19,982✔
1192
    }
1193

1194
    case TSDB_DATA_TYPE_BIGINT: {
5,414,512✔
1195
      int64_t* plist = (int64_t*)pCol->pData;
5,414,512✔
1196
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
20,263,633✔
1197
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
14,849,121✔
1198
          continue;
40,235✔
1199
        }
1200

1201
        numOfElem += 1;
14,808,886✔
1202
        pStdRes->count += 1;
14,808,886✔
1203
        pStdRes->isum += plist[i];
14,808,886✔
1204
        pStdRes->quadraticISum += plist[i] * plist[i];
14,808,886✔
1205
      }
1206
      break;
5,414,512✔
1207
    }
1208

1209
    case TSDB_DATA_TYPE_UTINYINT: {
25✔
1210
      uint8_t* plist = (uint8_t*)pCol->pData;
25✔
1211
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,032✔
1212
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,007!
1213
          continue;
4✔
1214
        }
1215

1216
        numOfElem += 1;
80,003✔
1217
        pStdRes->count += 1;
80,003✔
1218
        pStdRes->usum += plist[i];
80,003✔
1219
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,003✔
1220
      }
1221

1222
      break;
25✔
1223
    }
1224

1225
    case TSDB_DATA_TYPE_USMALLINT: {
24✔
1226
      uint16_t* plist = (uint16_t*)pCol->pData;
24✔
1227
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,024✔
1228
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,000!
1229
          continue;
×
1230
        }
1231

1232
        numOfElem += 1;
80,000✔
1233
        pStdRes->count += 1;
80,000✔
1234
        pStdRes->usum += plist[i];
80,000✔
1235
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1236
      }
1237
      break;
24✔
1238
    }
1239

1240
    case TSDB_DATA_TYPE_UINT: {
25✔
1241
      uint32_t* plist = (uint32_t*)pCol->pData;
25✔
1242
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,030✔
1243
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,005!
1244
          continue;
×
1245
        }
1246

1247
        numOfElem += 1;
80,005✔
1248
        pStdRes->count += 1;
80,005✔
1249
        pStdRes->usum += plist[i];
80,005✔
1250
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,005✔
1251
      }
1252

1253
      break;
25✔
1254
    }
1255

1256
    case TSDB_DATA_TYPE_UBIGINT: {
24✔
1257
      uint64_t* plist = (uint64_t*)pCol->pData;
24✔
1258
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,024✔
1259
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,000!
1260
          continue;
×
1261
        }
1262

1263
        numOfElem += 1;
80,000✔
1264
        pStdRes->count += 1;
80,000✔
1265
        pStdRes->usum += plist[i];
80,000✔
1266
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1267
      }
1268
      break;
24✔
1269
    }
1270

1271
    case TSDB_DATA_TYPE_FLOAT: {
17,177✔
1272
      float* plist = (float*)pCol->pData;
17,177✔
1273
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
1,345,349✔
1274
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,328,172✔
1275
          continue;
93,307✔
1276
        }
1277

1278
        numOfElem += 1;
1,234,865✔
1279
        pStdRes->count += 1;
1,234,865✔
1280
        pStdRes->dsum += plist[i];
1,234,865✔
1281
        pStdRes->quadraticDSum += plist[i] * plist[i];
1,234,865✔
1282
      }
1283
      break;
17,177✔
1284
    }
1285

1286
    case TSDB_DATA_TYPE_DOUBLE: {
47,025✔
1287
      double* plist = (double*)pCol->pData;
47,025✔
1288
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,034,480✔
1289
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
1,987,455✔
1290
          continue;
908,112✔
1291
        }
1292

1293
        numOfElem += 1;
1,079,343✔
1294
        pStdRes->count += 1;
1,079,343✔
1295
        pStdRes->dsum += plist[i];
1,079,343✔
1296
        pStdRes->quadraticDSum += plist[i] * plist[i];
1,079,343✔
1297
      }
1298
      break;
47,025✔
1299
    }
1300

1301
    default:
×
1302
      break;
×
1303
  }
1304

1305
_stddev_over:
8,144,612✔
1306
  // data in the check operation are all null, not output
1307
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
8,144,612✔
1308
  return TSDB_CODE_SUCCESS;
8,144,612✔
1309
}
1310

1311
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
1,073,602✔
1312
  if (IS_NULL_TYPE(pInput->type)) {
1,073,602✔
1313
    return;
80✔
1314
  }
1315
  pOutput->type = pInput->type;
1,073,522✔
1316
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
1,073,522!
1317
    pOutput->quadraticISum += pInput->quadraticISum;
1,073,325✔
1318
    pOutput->isum += pInput->isum;
1,073,325✔
1319
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
197!
1320
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1321
    pOutput->usum += pInput->usum;
1✔
1322
  } else {
1323
    pOutput->quadraticDSum += pInput->quadraticDSum;
196✔
1324
    pOutput->dsum += pInput->dsum;
196✔
1325
  }
1326

1327
  pOutput->count += pInput->count;
1,073,522✔
1328
}
1329

1330
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
1,073,537✔
1331
  SInputColumnInfoData* pInput = &pCtx->input;
1,073,537✔
1332
  SColumnInfoData*      pCol = pInput->pData[0];
1,073,537✔
1333

1334
  if (IS_NULL_TYPE(pCol->info.type)) {
1,073,537!
1335
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1336
    return TSDB_CODE_SUCCESS;
×
1337
  }
1338

1339
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,073,537!
1340
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1341
  }
1342

1343
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,073,537✔
1344

1345
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2,147,136✔
1346
    if (colDataIsNull_s(pCol, i)) continue;
2,147,198!
1347
    char*    data = colDataGetData(pCol, i);
1,073,599!
1348
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
1,073,599✔
1349
    stdTransferInfo(pInputInfo, pInfo);
1,073,599✔
1350
  }
1351

1352
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
1,073,537✔
1353
  return TSDB_CODE_SUCCESS;
1,073,537✔
1354
}
1355

1356
#ifdef BUILD_NO_CALL
1357
int32_t stdInvertFunction(SqlFunctionCtx* pCtx) {
1358
  int32_t numOfElem = 0;
1359

1360
  // Only the pre-computing information loaded and actual data does not loaded
1361
  SInputColumnInfoData* pInput = &pCtx->input;
1362
  int32_t               type = pInput->pData[0]->info.type;
1363

1364
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1365

1366
  // computing based on the true data block
1367
  SColumnInfoData* pCol = pInput->pData[0];
1368

1369
  int32_t start = pInput->startRowIndex;
1370
  int32_t numOfRows = pInput->numOfRows;
1371

1372
  switch (type) {
1373
    case TSDB_DATA_TYPE_TINYINT: {
1374
      LIST_STDDEV_SUB_N(pStdRes->isum, int8_t);
1375
      break;
1376
    }
1377
    case TSDB_DATA_TYPE_SMALLINT: {
1378
      LIST_STDDEV_SUB_N(pStdRes->isum, int16_t);
1379
      break;
1380
    }
1381
    case TSDB_DATA_TYPE_INT: {
1382
      LIST_STDDEV_SUB_N(pStdRes->isum, int32_t);
1383
      break;
1384
    }
1385
    case TSDB_DATA_TYPE_BIGINT: {
1386
      LIST_STDDEV_SUB_N(pStdRes->isum, int64_t);
1387
      break;
1388
    }
1389
    case TSDB_DATA_TYPE_UTINYINT: {
1390
      LIST_STDDEV_SUB_N(pStdRes->isum, uint8_t);
1391
      break;
1392
    }
1393
    case TSDB_DATA_TYPE_USMALLINT: {
1394
      LIST_STDDEV_SUB_N(pStdRes->isum, uint16_t);
1395
      break;
1396
    }
1397
    case TSDB_DATA_TYPE_UINT: {
1398
      LIST_STDDEV_SUB_N(pStdRes->isum, uint32_t);
1399
      break;
1400
    }
1401
    case TSDB_DATA_TYPE_UBIGINT: {
1402
      LIST_STDDEV_SUB_N(pStdRes->isum, uint64_t);
1403
      break;
1404
    }
1405
    case TSDB_DATA_TYPE_FLOAT: {
1406
      LIST_STDDEV_SUB_N(pStdRes->dsum, float);
1407
      break;
1408
    }
1409
    case TSDB_DATA_TYPE_DOUBLE: {
1410
      LIST_STDDEV_SUB_N(pStdRes->dsum, double);
1411
      break;
1412
    }
1413
    default:
1414
      break;
1415
  }
1416

1417
  // data in the check operation are all null, not output
1418
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1419
  return TSDB_CODE_SUCCESS;
1420
}
1421
#endif
1422

1423
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,026,869✔
1424
  SInputColumnInfoData* pInput = &pCtx->input;
7,026,869✔
1425
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
7,026,869✔
1426
  int32_t               type = pStddevRes->type;
7,026,869✔
1427
  double                avg;
1428

1429
  if (pStddevRes->count == 0) {
7,026,869✔
1430
    GET_RES_INFO(pCtx)->numOfRes = 0;
64,535✔
1431
    return functionFinalize(pCtx, pBlock);
64,535✔
1432
  }
1433

1434
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
6,962,334!
1435
    avg = pStddevRes->isum / ((double)pStddevRes->count);
6,934,945✔
1436
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
6,934,945✔
1437
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
27,389!
1438
    avg = pStddevRes->usum / ((double)pStddevRes->count);
10✔
1439
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
10✔
1440
  } else {
1441
    avg = pStddevRes->dsum / ((double)pStddevRes->count);
27,379✔
1442
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
27,379✔
1443
  }
1444

1445
  // check for overflow
1446
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
6,962,334!
1447
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1448
  }
1449

1450
  return functionFinalize(pCtx, pBlock);
6,962,334✔
1451
}
1452

1453
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
1454
  SInputColumnInfoData* pInput = &pCtx->input;
×
1455
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1456
  int32_t               type = pStdvarRes->type;
×
1457
  double                avg;
1458

1459
  if (pStdvarRes->count == 0) {
×
1460
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1461
    return functionFinalize(pCtx, pBlock);
×
1462
  }
1463

1464
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
1465
    avg = pStdvarRes->isum / ((double)pStdvarRes->count);
×
1466
    pStdvarRes->result = fabs(pStdvarRes->quadraticISum / ((double)pStdvarRes->count) - avg * avg);
×
1467
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1468
    avg = pStdvarRes->usum / ((double)pStdvarRes->count);
×
1469
    pStdvarRes->result = fabs(pStdvarRes->quadraticUSum / ((double)pStdvarRes->count) - avg * avg);
×
1470
  } else {
1471
    avg = pStdvarRes->dsum / ((double)pStdvarRes->count);
×
1472
    pStdvarRes->result = fabs(pStdvarRes->quadraticDSum / ((double)pStdvarRes->count) - avg * avg);
×
1473
  }
1474

1475
  // check for overflow
1476
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
×
1477
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1478
  }
1479

1480
  return functionFinalize(pCtx, pBlock);
×
1481
}
1482

1483
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,073,523✔
1484
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,073,523✔
1485
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,073,523✔
1486
  int32_t              resultBytes = getStdInfoSize();
1,073,523✔
1487
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,073,523!
1488

1489
  if (NULL == res) {
1,073,523!
1490
    return terrno;
×
1491
  }
1492
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,073,523✔
1493
  varDataSetLen(res, resultBytes);
1,073,523✔
1494

1495
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,073,523✔
1496
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,073,523✔
1497
  if (NULL == pCol) {
1,073,523!
1498
    taosMemoryFree(res);
×
1499
    return TSDB_CODE_OUT_OF_RANGE;
×
1500
  }
1501

1502
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,073,523✔
1503

1504
  taosMemoryFree(res);
1,073,522!
1505
  return code;
1,073,523✔
1506
}
1507

1508
int32_t stdCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
1509
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
1510
  SStdRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
1511

1512
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
1513
  SStdRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
1514
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
3!
1515

1516
  stdTransferInfo(pSBuf, pDBuf);
3✔
1517

1518
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
1519
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
1520
  return TSDB_CODE_SUCCESS;
3✔
1521
}
1522

1523
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
44,349✔
1524
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
44,349✔
1525
  return true;
44,349✔
1526
}
1527

1528
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3,634,638✔
1529
  if (pResultInfo->initialized) {
3,634,638!
1530
    return TSDB_CODE_SUCCESS;
×
1531
  }
1532
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
3,634,638!
1533
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1534
  }
1535

1536
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
3,634,643✔
1537

1538
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
3,634,643!
1539
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
3,634,643!
1540
  return TSDB_CODE_SUCCESS;
3,634,643✔
1541
}
1542

1543
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
4,349,463✔
1544
  int32_t numOfElem = 0;
4,349,463✔
1545

1546
  SInputColumnInfoData* pInput = &pCtx->input;
4,349,463✔
1547
  int32_t               type = pInput->pData[0]->info.type;
4,349,463✔
1548

1549
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,349,463✔
1550

1551
  SColumnInfoData* pCol = pInput->pData[0];
4,349,463✔
1552

1553
  double(*param)[3] = pInfo->matrix;
4,349,463✔
1554
  double x = pInfo->startVal;
4,349,463✔
1555

1556
  int32_t start = pInput->startRowIndex;
4,349,463✔
1557
  int32_t numOfRows = pInput->numOfRows;
4,349,463✔
1558

1559
  switch (type) {
4,349,463!
1560
    case TSDB_DATA_TYPE_TINYINT: {
10,994✔
1561
      int8_t* plist = (int8_t*)pCol->pData;
10,994✔
1562
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
643,311✔
1563
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
632,317✔
1564
          continue;
148,756✔
1565
        }
1566
        numOfElem++;
483,561✔
1567
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
483,561✔
1568
      }
1569
      break;
10,994✔
1570
    }
1571
    case TSDB_DATA_TYPE_SMALLINT: {
4,425✔
1572
      int16_t* plist = (int16_t*)pCol->pData;
4,425✔
1573
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
225,910✔
1574
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
221,485✔
1575
          continue;
139,069✔
1576
        }
1577

1578
        numOfElem++;
82,416✔
1579
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
82,416✔
1580
      }
1581
      break;
4,425✔
1582
    }
1583

1584
    case TSDB_DATA_TYPE_INT: {
4,996✔
1585
      int32_t* plist = (int32_t*)pCol->pData;
4,996✔
1586
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
354,981✔
1587
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
349,985✔
1588
          continue;
3,016✔
1589
        }
1590

1591
        numOfElem++;
346,969✔
1592
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
346,969✔
1593
      }
1594
      break;
4,996✔
1595
    }
1596

1597
    case TSDB_DATA_TYPE_BIGINT: {
4,303,207✔
1598
      int64_t* plist = (int64_t*)pCol->pData;
4,303,207✔
1599
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
14,364,183✔
1600
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
10,060,976✔
1601
          continue;
2,236✔
1602
        }
1603

1604
        numOfElem++;
10,058,740✔
1605
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
10,058,740✔
1606
      }
1607
      break;
4,303,207✔
1608
    }
1609

1610
    case TSDB_DATA_TYPE_UTINYINT: {
102✔
1611
      uint8_t* plist = (uint8_t*)pCol->pData;
102✔
1612
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,354✔
1613
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,252!
1614
          continue;
66✔
1615
        }
1616
        numOfElem++;
80,186✔
1617
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,186✔
1618
      }
1619
      break;
102✔
1620
    }
1621
    case TSDB_DATA_TYPE_USMALLINT: {
102✔
1622
      uint16_t* plist = (uint16_t*)pCol->pData;
102✔
1623
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,354✔
1624
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,252!
1625
          continue;
60✔
1626
        }
1627

1628
        numOfElem++;
80,192✔
1629
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,192✔
1630
      }
1631
      break;
102✔
1632
    }
1633

1634
    case TSDB_DATA_TYPE_UINT: {
102✔
1635
      uint32_t* plist = (uint32_t*)pCol->pData;
102✔
1636
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,354✔
1637
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,252!
1638
          continue;
60✔
1639
        }
1640

1641
        numOfElem++;
80,192✔
1642
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,192✔
1643
      }
1644
      break;
102✔
1645
    }
1646

1647
    case TSDB_DATA_TYPE_UBIGINT: {
102✔
1648
      uint64_t* plist = (uint64_t*)pCol->pData;
102✔
1649
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,354✔
1650
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,252!
1651
          continue;
60✔
1652
        }
1653

1654
        numOfElem++;
80,192✔
1655
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,192✔
1656
      }
1657
      break;
102✔
1658
    }
1659

1660
    case TSDB_DATA_TYPE_FLOAT: {
10,691✔
1661
      float* plist = (float*)pCol->pData;
10,691✔
1662
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
386,975✔
1663
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
376,284✔
1664
          continue;
149,584✔
1665
        }
1666

1667
        numOfElem++;
226,700✔
1668
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
226,700✔
1669
      }
1670
      break;
10,691✔
1671
    }
1672

1673
    case TSDB_DATA_TYPE_DOUBLE: {
14,741✔
1674
      double* plist = (double*)pCol->pData;
14,741✔
1675
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
398,970✔
1676
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
384,229✔
1677
          continue;
298,049✔
1678
        }
1679

1680
        numOfElem++;
86,180✔
1681
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
86,180✔
1682
      }
1683
      break;
14,741✔
1684
    }
1685
    case TSDB_DATA_TYPE_NULL: {
×
1686
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1687
      numOfElem = 1;
×
1688
      break;
×
1689
    }
1690

1691
    default:
1✔
1692
      break;
1✔
1693
  }
1694

1695
  pInfo->startVal = x;
4,349,463✔
1696
  pInfo->num += numOfElem;
4,349,463✔
1697

1698
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
4,349,463✔
1699

1700
  return TSDB_CODE_SUCCESS;
4,349,463✔
1701
}
1702

1703
int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
3,633,577✔
1704
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,633,577✔
1705
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
3,633,577✔
1706
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
3,633,577✔
1707
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
3,633,577✔
1708

1709
  if (NULL == pCol) {
3,633,576!
1710
    return TSDB_CODE_OUT_OF_RANGE;
×
1711
  }
1712
  int32_t currentRow = pBlock->info.rows;
3,633,576✔
1713

1714
  if (0 == pInfo->num) {
3,633,576✔
1715
    colDataSetNULL(pCol, currentRow);
28,828!
1716
    return TSDB_CODE_SUCCESS;
28,828✔
1717
  }
1718

1719
  double(*param)[3] = pInfo->matrix;
3,604,748✔
1720

1721
  param[1][1] = (double)pInfo->num;
3,604,748✔
1722
  param[1][0] = param[0][1];
3,604,748✔
1723

1724
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
3,604,748✔
1725
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
3,604,748✔
1726

1727
  if (0 == param00) {
3,604,748✔
1728
    colDataSetNULL(pCol, currentRow);
2,485,735!
1729
    return TSDB_CODE_SUCCESS;
2,485,735✔
1730
  }
1731

1732
  // param[0][1] = 0;
1733
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
1,119,013✔
1734
  // param[1][0] = 0;
1735
  param02 /= param00;
1,119,013✔
1736

1737
  param12 /= param[1][1];
1,119,013✔
1738

1739
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
1,119,013✔
1740
  char slopBuf[64] = {0};
1,119,013✔
1741
  char interceptBuf[64] = {0};
1,119,013✔
1742
  int  n = tsnprintf(slopBuf, 64, "%.6lf", param02);
1,119,013✔
1743
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,119,014✔
1744
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
140✔
1745
  }
1746
  n = tsnprintf(interceptBuf, 64, "%.6lf", param12);
1,119,014✔
1747
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,119,016✔
1748
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
1,051,474✔
1749
  }
1750
  size_t len =
1,119,016✔
1751
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
1,119,016✔
1752
  varDataSetLen(buf, len);
1,119,016✔
1753

1754
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,119,016✔
1755

1756
  return code;
1,119,016✔
1757
}
1758

1759
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1760
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1761
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1762
  int32_t              type = pDestCtx->input.pData[0]->info.type;
×
1763
  double(*pDparam)[3] = pDBuf->matrix;
×
1764

1765
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
1766
  SLeastSQRInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
1767
  double(*pSparam)[3] = pSBuf->matrix;
×
1768
  for (int32_t i = 0; i < pSBuf->num; i++) {
×
1769
    pDparam[0][0] += pDBuf->startVal * pDBuf->startVal;
×
1770
    pDparam[0][1] += pDBuf->startVal;
×
1771
    pDBuf->startVal += pDBuf->stepVal;
×
1772
  }
1773
  pDparam[0][2] += pSparam[0][2] + pDBuf->num * pDBuf->stepVal * pSparam[1][2];
×
1774
  pDparam[1][2] += pSparam[1][2];
×
1775
  pDBuf->num += pSBuf->num;
×
1776
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
1777
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
1778
  return TSDB_CODE_SUCCESS;
×
1779
}
1780

1781
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
933✔
1782
  pEnv->calcMemSize = sizeof(SPercentileInfo);
933✔
1783
  return true;
933✔
1784
}
1785

1786
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,589✔
1787
  if (pResultInfo->initialized) {
5,589!
1788
    return TSDB_CODE_SUCCESS;
×
1789
  }
1790
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,589!
1791
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1792
  }
1793

1794
  // in the first round, get the min-max value of all involved data
1795
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,589✔
1796
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
5,589✔
1797
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
5,589✔
1798
  pInfo->numOfElems = 0;
5,589✔
1799

1800
  return TSDB_CODE_SUCCESS;
5,589✔
1801
}
1802

1803
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
1804
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
1805
    return;
×
1806
  }
1807
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1808
  if (pInfo->pMemBucket != NULL) {
×
1809
    tMemBucketDestroy(&(pInfo->pMemBucket));
×
1810
    pInfo->pMemBucket = NULL;
×
1811
  }
1812
}
1813

1814
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
3,172,628✔
1815
  int32_t              code = TSDB_CODE_SUCCESS;
3,172,628✔
1816
  int32_t              numOfElems = 0;
3,172,628✔
1817
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,172,628✔
1818

1819
  SInputColumnInfoData* pInput = &pCtx->input;
3,172,628✔
1820
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
3,172,628✔
1821

1822
  SColumnInfoData* pCol = pInput->pData[0];
3,172,628✔
1823
  int32_t          type = pCol->info.type;
3,172,628✔
1824

1825
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,172,628✔
1826
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
3,172,628✔
1827
    pInfo->stage += 1;
5,589✔
1828

1829
    // all data are null, set it completed
1830
    if (pInfo->numOfElems == 0) {
5,589✔
1831
      pResInfo->complete = true;
2,004✔
1832
      return TSDB_CODE_SUCCESS;
2,004✔
1833
    } else {
1834
      code = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup,
3,585✔
1835
                              &pInfo->pMemBucket, pInfo->numOfElems);
3,585✔
1836
      if (TSDB_CODE_SUCCESS != code) {
3,585!
1837
        return code;
×
1838
      }
1839
    }
1840
  }
1841

1842
  // the first stage, only acquire the min/max value
1843
  if (pInfo->stage == 0) {
3,170,624✔
1844
    if (pCtx->input.colDataSMAIsSet) {
1,586,314✔
1845
      double tmin = 0.0, tmax = 0.0;
1,576,295✔
1846
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
1,576,295!
1847
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
1848
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
1849
      } else if (IS_FLOAT_TYPE(type)) {
1,576,295!
1850
        tmin = GET_DOUBLE_VAL(&pAgg->min);
1,576,295✔
1851
        tmax = GET_DOUBLE_VAL(&pAgg->max);
1,576,295✔
1852
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1853
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
1854
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
1855
      }
1856

1857
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
1,576,295✔
1858
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
14✔
1859
      }
1860

1861
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
1,576,295✔
1862
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
14✔
1863
      }
1864

1865
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
1,576,295✔
1866
    } else {
1867
      // check the valid data one by one
1868
      int32_t start = pInput->startRowIndex;
10,019✔
1869
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
14,594,442✔
1870
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
14,584,423✔
1871
          continue;
2,400✔
1872
        }
1873

1874
        char* data = colDataGetData(pCol, i);
14,582,023!
1875

1876
        double v = 0;
14,582,023✔
1877
        GET_TYPED_DATA(v, double, type, data);
14,582,023!
1878
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
14,582,023✔
1879
          SET_DOUBLE_VAL(&pInfo->minval, v);
3,797✔
1880
        }
1881

1882
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
14,582,023✔
1883
          SET_DOUBLE_VAL(&pInfo->maxval, v);
410,817✔
1884
        }
1885

1886
        pInfo->numOfElems += 1;
14,582,023✔
1887
      }
1888
    }
1889
  } else {
1890
    // the second stage, calculate the true percentile value
1891
    int32_t start = pInput->startRowIndex;
1,584,310✔
1892
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
1893
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
2,147,483,647!
1894
        continue;
×
1895
      }
1896

1897
      char* data = colDataGetData(pCol, i);
2,147,483,647!
1898
      numOfElems += 1;
2,147,483,647✔
1899
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
2,147,483,647✔
1900
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
1901
        tMemBucketDestroy(&(pInfo->pMemBucket));
×
1902
        return code;
×
1903
      }
1904
    }
1905

1906
    SET_VAL(pResInfo, numOfElems, 1);
1,584,310!
1907
  }
1908

1909
  pCtx->needCleanup = true;
3,170,624✔
1910
  return TSDB_CODE_SUCCESS;
3,170,624✔
1911
}
1912

1913
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,589✔
1914
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,589✔
1915
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
5,589✔
1916

1917
  int32_t code = 0;
5,589✔
1918
  double  v = 0;
5,589✔
1919

1920
  tMemBucket** pMemBucket = &ppInfo->pMemBucket;
5,589✔
1921
  if ((*pMemBucket) != NULL && (*pMemBucket)->total > 0) {  // check for null
5,589!
1922
    if (pCtx->numOfParams > 2) {
3,585✔
1923
      char buf[3200] = {0};
34✔
1924
      // max length of double num is 317, e.g. use %.6lf to print -1.0e+308, consider the comma and bracket, 3200 is
1925
      // enough.
1926
      size_t len = 1;
34✔
1927

1928
      varDataVal(buf)[0] = '[';
34✔
1929
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
342✔
1930
        SVariant* pVal = &pCtx->param[i].param;
308✔
1931

1932
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
308!
1933

1934
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
308✔
1935
        if (code != TSDB_CODE_SUCCESS) {
308!
1936
          goto _fin_error;
×
1937
        }
1938

1939
        if (i == pCtx->numOfParams - 1) {
308✔
1940
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
34✔
1941
        } else {
1942
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
274✔
1943
        }
1944
      }
1945

1946
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
34✔
1947
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
34✔
1948
      if (NULL == pCol) {
34!
1949
        code = terrno;
×
1950
        goto _fin_error;
×
1951
      }
1952

1953
      varDataSetLen(buf, len);
34✔
1954
      code = colDataSetVal(pCol, pBlock->info.rows, buf, false);
34✔
1955
      if (code != TSDB_CODE_SUCCESS) {
34!
1956
        goto _fin_error;
×
1957
      }
1958

1959
      tMemBucketDestroy(pMemBucket);
34✔
1960
      return TSDB_CODE_SUCCESS;
34✔
1961
    } else {
1962
      SVariant* pVal = &pCtx->param[1].param;
3,551✔
1963

1964
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
3,551!
1965

1966
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
3,551✔
1967
      if (code != TSDB_CODE_SUCCESS) {
3,551!
1968
        goto _fin_error;
×
1969
      }
1970

1971
      tMemBucketDestroy(pMemBucket);
3,551✔
1972
      return functionFinalize(pCtx, pBlock);
3,551✔
1973
    }
1974
  } else {
1975
    return functionFinalize(pCtx, pBlock);
2,004✔
1976
  }
1977

1978
_fin_error:
×
1979

1980
  tMemBucketDestroy(pMemBucket);
×
1981
  return code;
×
1982
}
1983

1984
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
144,347✔
1985
  int32_t bytesHist =
144,347✔
1986
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1987
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
144,347✔
1988
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
144,347✔
1989
  return true;
144,347✔
1990
}
1991

1992
int32_t getApercentileMaxSize() {
4,241,317✔
1993
  int32_t bytesHist =
4,241,317✔
1994
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1995
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
4,241,317✔
1996
  return TMAX(bytesHist, bytesDigest);
4,241,317✔
1997
}
1998

1999
static int8_t getApercentileAlgo(char* algoStr) {
26,245✔
2000
  int8_t algoType;
2001
  if (strcasecmp(algoStr, "default") == 0) {
26,245✔
2002
    algoType = APERCT_ALGO_DEFAULT;
11,145✔
2003
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
15,100✔
2004
    algoType = APERCT_ALGO_TDIGEST;
15,091✔
2005
  } else {
2006
    algoType = APERCT_ALGO_UNKNOWN;
9✔
2007
  }
2008

2009
  return algoType;
26,245✔
2010
}
2011

2012
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
82,693,258✔
2013
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
82,693,258✔
2014
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
82,693,258✔
2015
}
82,693,258✔
2016

2017
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
37,098✔
2018
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
37,098✔
2019
}
37,098✔
2020

2021
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
26,134,247✔
2022
  if (pResultInfo->initialized) {
26,134,247!
2023
    return TSDB_CODE_SUCCESS;
×
2024
  }
2025
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
26,134,247!
2026
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2027
  }
2028

2029
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
26,134,268✔
2030

2031
  SVariant* pVal = &pCtx->param[1].param;
26,134,268✔
2032
  pInfo->percent = 0;
26,134,268✔
2033
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i);
26,134,268!
2034

2035
  if (pCtx->numOfParams == 2) {
26,134,268✔
2036
    pInfo->algo = APERCT_ALGO_DEFAULT;
26,108,031✔
2037
  } else if (pCtx->numOfParams == 3) {
26,237!
2038
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
26,247✔
2039
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
26,235!
2040
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2041
    }
2042
  }
2043

2044
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
26,134,256✔
2045
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
26,134,256✔
2046
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
15,091✔
2047
  } else {
2048
    buildHistogramInfo(pInfo);
26,119,165✔
2049
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
26,119,173✔
2050
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
26,119,168✔
2051
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2052
  }
2053

2054
  return TSDB_CODE_SUCCESS;
26,134,263✔
2055
}
2056

2057
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
22,025,093✔
2058
  int32_t               numOfElems = 0;
22,025,093✔
2059
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
22,025,093✔
2060
  SInputColumnInfoData* pInput = &pCtx->input;
22,025,093✔
2061

2062
  SColumnInfoData* pCol = pInput->pData[0];
22,025,093✔
2063
  int32_t          type = pCol->info.type;
22,025,093✔
2064

2065
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
22,025,093✔
2066

2067
  int32_t start = pInput->startRowIndex;
22,025,093✔
2068
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
22,025,093✔
2069
    buildTDigestInfo(pInfo);
21,089✔
2070
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
21,087✔
2071
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,521,235✔
2072
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,500,148✔
2073
        continue;
362,502✔
2074
      }
2075
      numOfElems += 1;
1,137,646✔
2076
      char* data = colDataGetData(pCol, i);
1,137,646!
2077

2078
      double  v = 0;  // value
1,137,646✔
2079
      int64_t w = 1;  // weigth
1,137,646✔
2080
      GET_TYPED_DATA(v, double, type, data);
1,137,646!
2081
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
1,137,646✔
2082
      if (code != TSDB_CODE_SUCCESS) {
1,137,646!
2083
        return code;
×
2084
      }
2085
    }
2086
  } else {
2087
    // might be a race condition here that pHisto can be overwritten or setup function
2088
    // has not been called, need to relink the buffer pHisto points to.
2089
    buildHistogramInfo(pInfo);
22,004,004✔
2090
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
22,003,998✔
2091
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2092
           pInfo->pHisto->elems);
2093
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
59,946,100✔
2094
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
37,941,979✔
2095
        continue;
1,028,800✔
2096
      }
2097
      numOfElems += 1;
36,913,179✔
2098
      char* data = colDataGetData(pCol, i);
36,913,179!
2099

2100
      double v = 0;
36,913,179✔
2101
      GET_TYPED_DATA(v, double, type, data);
36,913,179!
2102
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
36,913,179✔
2103
      if (code != TSDB_CODE_SUCCESS) {
36,913,304!
2104
        return code;
×
2105
      }
2106
    }
2107

2108
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
22,004,121✔
2109
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2110
           pInfo->pHisto->elems);
2111
  }
2112

2113
  SET_VAL(pResInfo, numOfElems, 1);
22,025,105✔
2114
  return TSDB_CODE_SUCCESS;
22,025,105✔
2115
}
2116

2117
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
4,239,993✔
2118
  pOutput->percent = pInput->percent;
4,239,993✔
2119
  pOutput->algo = pInput->algo;
4,239,993✔
2120
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
4,239,993✔
2121
    buildTDigestInfo(pInput);
917✔
2122
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
917✔
2123

2124
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
917✔
2125
      return TSDB_CODE_SUCCESS;
1✔
2126
    }
2127

2128
    if (hasRes) {
916✔
2129
      *hasRes = true;
914✔
2130
    }
2131

2132
    buildTDigestInfo(pOutput);
916✔
2133
    TDigest* pTDigest = pOutput->pTDigest;
916✔
2134
    tdigestAutoFill(pTDigest, COMPRESSION);
916✔
2135

2136
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
916!
2137
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
914✔
2138
      tdigestAutoFill(pTDigest, COMPRESSION);
914✔
2139
    } else {
2140
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
2✔
2141
      if (TSDB_CODE_SUCCESS != code) {
2!
2142
        return code;
×
2143
      }
2144
    }
2145
  } else {
2146
    buildHistogramInfo(pInput);
4,239,076✔
2147
    if (pInput->pHisto->numOfElems <= 0) {
4,239,076✔
2148
      return TSDB_CODE_SUCCESS;
171✔
2149
    }
2150

2151
    if (hasRes) {
4,238,905✔
2152
      *hasRes = true;
4,238,903✔
2153
    }
2154

2155
    buildHistogramInfo(pOutput);
4,238,905✔
2156
    SHistogramInfo* pHisto = pOutput->pHisto;
4,238,905✔
2157

2158
    if (pHisto->numOfElems <= 0) {
4,238,905✔
2159
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
4,238,482✔
2160
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
4,238,482✔
2161

2162
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
4,238,482✔
2163
             pHisto);
2164
    } else {
2165
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
423✔
2166
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
423✔
2167
             pHisto->numOfEntries, pInput->pHisto);
2168

2169
      SHistogramInfo* pRes = NULL;
423✔
2170
      int32_t         code = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN, &pRes);
423✔
2171
      if (TSDB_CODE_SUCCESS != code) {
423!
2172
        tHistogramDestroy(&pRes);
×
2173
        return code;
×
2174
      }
2175
      (void)memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
423✔
2176
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
423✔
2177

2178
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
423✔
2179
             pHisto);
2180
      tHistogramDestroy(&pRes);
423✔
2181
    }
2182
  }
2183
  return TSDB_CODE_SUCCESS;
4,239,821✔
2184
}
2185

2186
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
4,239,927✔
2187
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,239,927✔
2188

2189
  SInputColumnInfoData* pInput = &pCtx->input;
4,239,927✔
2190

2191
  SColumnInfoData* pCol = pInput->pData[0];
4,239,927✔
2192
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
4,239,927!
2193
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2194
  }
2195

2196
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
4,239,927✔
2197

2198
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
4,239,927✔
2199

2200
  bool    hasRes = false;
4,239,927✔
2201
  int32_t start = pInput->startRowIndex;
4,239,927✔
2202
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
8,479,916✔
2203
    char* data = colDataGetData(pCol, i);
4,239,989!
2204

2205
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
4,239,989✔
2206
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
4,239,989✔
2207
    if (TSDB_CODE_SUCCESS != code) {
4,239,989!
2208
      return code;
×
2209
    }
2210
  }
2211

2212
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
4,239,927✔
2213
    buildHistogramInfo(pInfo);
4,239,012✔
2214
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
4,239,012✔
2215
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2216
  }
2217

2218
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
4,239,927✔
2219
  return TSDB_CODE_SUCCESS;
4,239,927✔
2220
}
2221

2222
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
21,867,329✔
2223
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
21,867,329✔
2224
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
21,867,329✔
2225

2226
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
21,867,329✔
2227
    buildTDigestInfo(pInfo);
14,180✔
2228
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
14,180✔
2229
    if (pInfo->pTDigest->size > 0) {
14,179!
2230
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
14,179✔
2231
    } else {  // no need to free
2232
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2233
      return TSDB_CODE_SUCCESS;
×
2234
    }
2235
  } else {
2236
    buildHistogramInfo(pInfo);
21,853,149✔
2237
    if (pInfo->pHisto->numOfElems > 0) {
21,853,150✔
2238
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
21,787,713✔
2239
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2240

2241
      double  ratio[] = {pInfo->percent};
21,787,713✔
2242
      double* res = NULL;
21,787,713✔
2243
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
21,787,713✔
2244
      if (TSDB_CODE_SUCCESS != code) {
21,787,716!
2245
        taosMemoryFree(res);
×
2246
        return code;
×
2247
      }
2248
      pInfo->result = *res;
21,787,716✔
2249
      // memcpy(pCtx->pOutput, res, sizeof(double));
2250
      taosMemoryFree(res);
21,787,716✔
2251
    } else {  // no need to free
2252
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2253
      // return TSDB_CODE_SUCCESS;
2254
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
65,437✔
2255
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2256
    }
2257
  }
2258

2259
  return functionFinalize(pCtx, pBlock);
21,867,328✔
2260
}
2261

2262
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,239,673✔
2263
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,239,673✔
2264
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
4,239,673✔
2265

2266
  int32_t resultBytes = getApercentileMaxSize();
4,239,673✔
2267
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
4,239,673!
2268
  if (NULL == res) {
4,239,673!
2269
    return terrno;
×
2270
  }
2271

2272
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
4,239,673✔
2273
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
915✔
2274
    varDataSetLen(res, resultBytes);
915✔
2275
  } else {
2276
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
4,238,758✔
2277
    varDataSetLen(res, resultBytes);
4,238,758✔
2278
  }
2279

2280
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
4,239,673✔
2281
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
4,239,673✔
2282
  if (NULL == pCol) {
4,239,673!
2283
    taosMemoryFree(res);
×
2284
    return TSDB_CODE_OUT_OF_RANGE;
×
2285
  }
2286

2287
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
4,239,673✔
2288

2289
  taosMemoryFree(res);
4,239,672!
2290
  return code;
4,239,673✔
2291
}
2292

2293
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
4✔
2294
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
4✔
2295
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
4✔
2296

2297
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
4✔
2298
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
4✔
2299

2300
  qDebug("%s start to combine apercentile, %p", __FUNCTION__, pDBuf->pHisto);
4!
2301

2302
  int32_t code = apercentileTransferInfo(pSBuf, pDBuf, NULL);
4✔
2303
  if (TSDB_CODE_SUCCESS != code) {
4!
2304
    return code;
×
2305
  }
2306
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
4✔
2307
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
4✔
2308
  return TSDB_CODE_SUCCESS;
4✔
2309
}
2310

2311
// TODO: change this function when block data info pks changed
2312
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
11✔
2313
  char numVal[8] = {0};
11✔
2314
  switch (pkType) {
11!
2315
    case TSDB_DATA_TYPE_INT:
11✔
2316
      *(int32_t*)numVal = (int32_t)pVal->val;
11✔
2317
      break;
11✔
2318
    case TSDB_DATA_TYPE_UINT:
×
2319
      *(uint32_t*)numVal = (uint32_t)pVal->val;
×
2320
      break;
×
2321
    case TSDB_DATA_TYPE_BIGINT:
×
2322
      *(int64_t*)numVal = (int64_t)pVal->val;
×
2323
      break;
×
2324
    case TSDB_DATA_TYPE_UBIGINT:
×
2325
      *(uint64_t*)numVal = (uint64_t)pVal->val;
×
2326
      break;
×
2327
    default:
×
2328
      break;
×
2329
  }
2330
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
11!
2331
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
11✔
2332
  return fn(pkData, blockData);
11✔
2333
}
2334

2335
EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
8,080✔
2336
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
8,080✔
2337

2338
  // not initialized yet, data is required
2339
  if (pEntry == NULL) {
8,080!
2340
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2341
  }
2342

2343
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
8,080✔
2344
  if (pResult->hasResult) {
8,080✔
2345
    if (pResult->pkBytes > 0) {
8,037✔
2346
      pResult->pkData = pResult->buf + pResult->bytes;
6✔
2347
    } else {
2348
      pResult->pkData = NULL;
8,031✔
2349
    }
2350
    if (pResult->ts < pBlockInfo->window.skey) {
8,037✔
2351
      return FUNC_DATA_REQUIRED_NOT_LOAD;
6,385✔
2352
    } else if (pResult->ts == pBlockInfo->window.skey) {
1,652✔
2353
      if (NULL == pResult->pkData) {
203✔
2354
        return FUNC_DATA_REQUIRED_NOT_LOAD;
197✔
2355
      }
2356
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
6!
2357
        return FUNC_DATA_REQUIRED_NOT_LOAD;
6✔
2358
      }
2359
    }
2360
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,449✔
2361
  } else {
2362
    return FUNC_DATA_REQUIRED_DATA_LOAD;
43✔
2363
  }
2364
}
2365

2366
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
4,425✔
2367
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
4,425✔
2368

2369
  // not initialized yet, data is required
2370
  if (pEntry == NULL) {
4,425!
2371
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2372
  }
2373

2374
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
4,425✔
2375
  if (pResult->hasResult) {
4,425✔
2376
    if (pResult->pkBytes > 0) {
4,363✔
2377
      pResult->pkData = pResult->buf + pResult->bytes;
5✔
2378
    } else {
2379
      pResult->pkData = NULL;
4,358✔
2380
    }
2381
    if (pResult->ts > pBlockInfo->window.ekey) {
4,363✔
2382
      return FUNC_DATA_REQUIRED_NOT_LOAD;
2,975✔
2383
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
1,388✔
2384
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
5!
2385
        return FUNC_DATA_REQUIRED_NOT_LOAD;
×
2386
      }
2387
    }
2388
    return FUNC_DATA_REQUIRED_DATA_LOAD;
1,388✔
2389
  } else {
2390
    return FUNC_DATA_REQUIRED_DATA_LOAD;
62✔
2391
  }
2392
}
2393

2394
// TODO modify it to include primary key bytes
2395
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
60,464,797✔
2396

2397
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,762,031✔
2398
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,762,031✔
2399
  // TODO: change SFunctionNode to add pk info
2400
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
1,763,579✔
2401
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
1,763,579✔
2402
  return true;
1,763,733✔
2403
}
2404

2405
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,211,534✔
2406
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,211,534✔
2407
  pEnv->calcMemSize = pNode->node.resType.bytes;
1,212,615✔
2408
  return true;
1,212,615✔
2409
}
2410

2411
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
255,990✔
2412
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
255,990✔
2413
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
256,372✔
2414
  return true;
256,372✔
2415
}
2416

2417
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2418
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
320,221,659!
2419
    return 0;
×
2420
  }
2421

2422
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
320,262,567!
2423
}
2424

2425
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
9,969,893✔
2426
  if (pResInfo->initialized) {
9,969,893!
2427
    return TSDB_CODE_SUCCESS;
×
2428
  }
2429
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
9,969,893!
2430
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2431
  }
2432

2433
  SFirstLastRes*        pRes = GET_ROWCELL_INTERBUF(pResInfo);
9,970,649✔
2434
  SInputColumnInfoData* pInput = &pCtx->input;
9,970,649✔
2435

2436
  pRes->nullTupleSaved = false;
9,970,649✔
2437
  pRes->nullTuplePos.pageId = -1;
9,970,649✔
2438
  return TSDB_CODE_SUCCESS;
9,970,649✔
2439
}
2440

2441
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
172,771,847✔
2442
  if (pCtx->subsidiaries.rowLen == 0) {
172,771,847✔
2443
    int32_t rowLen = 0;
616,742✔
2444
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,240,384✔
2445
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
623,642✔
2446
      rowLen += pc->pExpr->base.resSchema.bytes;
623,642✔
2447
    }
2448

2449
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
616,742✔
2450
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
616,742!
2451
    if (NULL == pCtx->subsidiaries.buf) {
616,132!
2452
      return terrno;
×
2453
    }
2454
  }
2455
  return TSDB_CODE_SUCCESS;
172,771,237✔
2456
}
2457

2458
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
181,567,457✔
2459
                                      SFirstLastRes* pInfo, bool noElements) {
2460
  int32_t code = TSDB_CODE_SUCCESS;
181,567,457✔
2461

2462
  if (pCtx->subsidiaries.num <= 0) {
181,567,457✔
2463
    return TSDB_CODE_SUCCESS;
101,764,245✔
2464
  }
2465

2466
  if (!pInfo->hasResult) {
79,803,212✔
2467
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
70,401,399✔
2468
  } else {
2469
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
9,401,813✔
2470
  }
2471

2472
  return code;
79,706,386✔
2473
}
2474

2475
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
77,219,110✔
2476
                                char* pData) {
2477
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
77,219,110✔
2478
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
77,219,110✔
2479

2480
  if (IS_VAR_DATA_TYPE(type)) {
77,219,110!
2481
    if (type == TSDB_DATA_TYPE_JSON) {
6,742,153!
2482
      pInfo->bytes = getJsonValueLen(pData);
×
2483
    } else {
2484
      pInfo->bytes = varDataTLen(pData);
6,742,153✔
2485
    }
2486
  }
2487

2488
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
77,219,110✔
2489
  if (pkData != NULL) {
77,219,110✔
2490
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
30,118!
2491
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
24!
2492
        pInfo->pkBytes = getJsonValueLen(pkData);
×
2493
      } else {
2494
        pInfo->pkBytes = varDataTLen(pkData);
24✔
2495
      }
2496
    }
2497
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
30,118✔
2498
    pInfo->pkData = pInfo->buf + pInfo->bytes;
30,118✔
2499
  }
2500

2501
  pInfo->ts = currentTs;
77,219,110✔
2502
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
77,219,110✔
2503
  if (code != TSDB_CODE_SUCCESS) {
77,308,632!
2504
    return code;
×
2505
  }
2506

2507
  pInfo->hasResult = true;
77,308,632✔
2508
  return TSDB_CODE_SUCCESS;
77,308,632✔
2509
}
2510

2511
// This ordinary first function does not care if current scan is ascending order or descending order scan
2512
// the OPTIMIZED version of first function will only handle the ascending order scan
2513
int32_t firstFunction(SqlFunctionCtx* pCtx) {
46,563,605✔
2514
  int32_t numOfElems = 0;
46,563,605✔
2515

2516
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
46,563,605✔
2517
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
46,563,605✔
2518

2519
  SInputColumnInfoData* pInput = &pCtx->input;
46,563,605✔
2520
  SColumnInfoData*      pInputCol = pInput->pData[0];
46,563,605✔
2521

2522
  pInfo->bytes = pInputCol->info.bytes;
46,563,605✔
2523

2524
  if (IS_NULL_TYPE(pInputCol->info.type)) {
46,563,605✔
2525
    return TSDB_CODE_SUCCESS;
5,028✔
2526
  }
2527

2528
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
46,558,577✔
2529
  pInfo->pkType = -1;
46,558,577✔
2530
  __compar_fn_t pkCompareFn = NULL;
46,558,577✔
2531
  if (pCtx->hasPrimaryKey) {
46,558,577✔
2532
    pInfo->pkType = pkCol->info.type;
51✔
2533
    pInfo->pkBytes = pkCol->info.bytes;
51✔
2534
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
51✔
2535
  }
2536

2537
  // All null data column, return directly.
2538
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
46,582,261!
2539
      pInputCol->hasNull == true) {
×
2540
    // save selectivity value for column consisted of all null values
2541
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2542
    if (code != TSDB_CODE_SUCCESS) {
×
2543
      return code;
×
2544
    }
2545
    pInfo->nullTupleSaved = true;
×
2546
    return TSDB_CODE_SUCCESS;
×
2547
  }
2548

2549
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
46,582,261!
2550

2551
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
46,582,261!
2552
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
46,582,261!
2553

2554
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
46,582,261✔
2555

2556
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first
2557
  //  function. we will use this opt implementation in an new version that is only available in scan subplan
2558
#if 0
2559
  if (blockDataOrder == TSDB_ORDER_ASC) {
2560
    // filter according to current result firstly
2561
    if (pResInfo->numOfRes > 0) {
2562
      if (pInfo->ts < startKey) {
2563
        return TSDB_CODE_SUCCESS;
2564
      }
2565
    }
2566

2567
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2568
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2569
        continue;
2570
      }
2571

2572
      numOfElems++;
2573

2574
      char* data = colDataGetData(pInputCol, i);
2575
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2576
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2577
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2578
        break;
2579
      }
2580
    }
2581
  } else {
2582
    // in case of descending order time stamp serial, which usually happens as the results of the nest query,
2583
    // all data needs to be check.
2584
    if (pResInfo->numOfRes > 0) {
2585
      if (pInfo->ts < endKey) {
2586
        return TSDB_CODE_SUCCESS;
2587
      }
2588
    }
2589

2590
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2591
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2592
        continue;
2593
      }
2594

2595
      numOfElems++;
2596

2597
      char* data = colDataGetData(pInputCol, i);
2598
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2599

2600
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2601
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2602
        break;
2603
      }
2604
    }
2605
  }
2606
#else
2607
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
46,582,261✔
2608

2609
  int     from = -1;
46,582,261✔
2610
  int32_t i = -1;
46,582,261✔
2611
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
157,199,884✔
2612
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
143,097,274!
2613
      continue;
72,060✔
2614
    }
2615

2616
    numOfElems++;
110,500,573✔
2617
    char* data = colDataGetData(pInputCol, i);
110,500,573!
2618
    char* pkData = NULL;
110,500,573✔
2619
    if (pCtx->hasPrimaryKey) {
110,500,573✔
2620
      pkData = colDataGetData(pkCol, i);
153!
2621
    }
2622
    TSKEY cts = pts[i];
110,500,573✔
2623
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
110,500,573✔
2624
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
72,911,564!
2625
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
37,589,009✔
2626
      if (code != TSDB_CODE_SUCCESS) {
37,633,999!
2627
        return code;
×
2628
      }
2629
      pResInfo->numOfRes = 1;
37,633,999✔
2630
    }
2631
  }
2632
#endif
2633

2634
  if (numOfElems == 0) {
45,921,814✔
2635
    // save selectivity value for column consisted of all null values
2636
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
24,298✔
2637
    if (code != TSDB_CODE_SUCCESS) {
24,294!
2638
      return code;
×
2639
    }
2640
    pInfo->nullTupleSaved = true;
24,294✔
2641
  }
2642
  SET_VAL(pResInfo, numOfElems, 1);
45,921,810✔
2643
  return TSDB_CODE_SUCCESS;
45,921,810✔
2644
}
2645

2646
int32_t lastFunction(SqlFunctionCtx* pCtx) {
39,064,696✔
2647
  int32_t numOfElems = 0;
39,064,696✔
2648

2649
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
39,064,696✔
2650
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
39,064,696✔
2651

2652
  SInputColumnInfoData* pInput = &pCtx->input;
39,064,696✔
2653
  SColumnInfoData*      pInputCol = pInput->pData[0];
39,064,696✔
2654

2655
  int32_t type = pInputCol->info.type;
39,064,696✔
2656
  int32_t bytes = pInputCol->info.bytes;
39,064,696✔
2657
  pInfo->bytes = bytes;
39,064,696✔
2658

2659
  if (IS_NULL_TYPE(type)) {
39,064,696✔
2660
    return TSDB_CODE_SUCCESS;
5,028✔
2661
  }
2662

2663
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
39,059,668✔
2664
  pInfo->pkType = -1;
39,059,668✔
2665
  __compar_fn_t pkCompareFn = NULL;
39,059,668✔
2666
  if (pCtx->hasPrimaryKey) {
39,059,668✔
2667
    pInfo->pkType = pkCol->info.type;
30,067✔
2668
    pInfo->pkBytes = pkCol->info.bytes;
30,067✔
2669
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
30,067✔
2670
  }
2671

2672
  // All null data column, return directly.
2673
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
39,144,122!
2674
      pInputCol->hasNull == true) {
×
2675
    // save selectivity value for column consisted of all null values
2676
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
×
2677
    if (code != TSDB_CODE_SUCCESS) {
×
2678
      return code;
×
2679
    }
2680
    pInfo->nullTupleSaved = true;
×
2681
    return TSDB_CODE_SUCCESS;
×
2682
  }
2683

2684
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
39,144,122!
2685

2686
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
39,144,122✔
2687
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
39,144,122!
2688

2689
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
39,144,122✔
2690

2691
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2692
#if 0
2693
  if (blockDataOrder == TSDB_ORDER_ASC) {
2694
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2695
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2696
        continue;
2697
      }
2698

2699
      numOfElems++;
2700

2701
      char* data = colDataGetData(pInputCol, i);
2702
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2703
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2704
        doSaveCurrentVal(pCtx, i, cts, type, data);
2705
      }
2706

2707
      break;
2708
    }
2709
  } else {  // descending order
2710
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2711
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2712
        continue;
2713
      }
2714

2715
      numOfElems++;
2716

2717
      char* data = colDataGetData(pInputCol, i);
2718
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2719
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2720
        doSaveCurrentVal(pCtx, i, cts, type, data);
2721
      }
2722
      break;
2723
    }
2724
  }
2725
#else
2726
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
39,144,122✔
2727

2728
#if 0
2729
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2730
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2731
        continue;
2732
      }
2733

2734
      numOfElems++;
2735
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2736
        char* data = colDataGetData(pInputCol, i);
2737
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2738
        pResInfo->numOfRes = 1;
2739
      }
2740
    }
2741
#else
2742

2743
  // todo refactor
2744
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
64,427,529✔
2745
    numOfElems = 1;
25,319,935✔
2746

2747
    int32_t round = pInput->numOfRows >> 2;
25,319,935✔
2748
    int32_t reminder = pInput->numOfRows & 0x03;
25,319,935✔
2749

2750
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
40,953,274✔
2751
      int64_t cts = pts[i];
15,632,698✔
2752
      int32_t chosen = i;
15,632,698✔
2753

2754
      if (cts < pts[i + 1]) {
15,632,698✔
2755
        cts = pts[i + 1];
4,876,001✔
2756
        chosen = i + 1;
4,876,001✔
2757
      }
2758

2759
      if (cts < pts[i + 2]) {
15,632,698✔
2760
        cts = pts[i + 2];
4,876,418✔
2761
        chosen = i + 2;
4,876,418✔
2762
      }
2763

2764
      if (cts < pts[i + 3]) {
15,632,698✔
2765
        cts = pts[i + 3];
4,876,622✔
2766
        chosen = i + 3;
4,876,622✔
2767
      }
2768

2769
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
15,632,698✔
2770
        char*   data = colDataGetData(pInputCol, chosen);
3,745,617!
2771
        int32_t code = doSaveCurrentVal(pCtx, i, cts, NULL, type, data);
3,745,617✔
2772
        if (code != TSDB_CODE_SUCCESS) {
3,746,258!
2773
          return code;
×
2774
        }
2775
        pResInfo->numOfRes = 1;
3,746,258✔
2776
      }
2777
    }
2778

2779
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
52,932,499✔
2780
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
27,649,092✔
2781
        char*   data = colDataGetData(pInputCol, i);
18,217,906!
2782
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
18,217,906✔
2783
        if (code != TSDB_CODE_SUCCESS) {
18,180,737!
2784
          return code;
×
2785
        }
2786
        pResInfo->numOfRes = 1;
18,180,737✔
2787
      }
2788
    }
2789
  } else {
2790
    int     from = -1;
13,824,187✔
2791
    int32_t i = -1;
13,824,187✔
2792
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
145,513,715✔
2793
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
263,390,030✔
2794
        continue;
5,607,542✔
2795
      }
2796

2797
      numOfElems++;
126,087,473✔
2798
      char* pkData = NULL;
126,087,473✔
2799
      if (pCtx->hasPrimaryKey) {
126,087,473✔
2800
        pkData = colDataGetData(pkCol, i);
100,000,193!
2801
      }
2802
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
126,087,473✔
2803
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
108,494,618!
2804
        char*   data = colDataGetData(pInputCol, i);
17,650,006!
2805
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
17,650,006✔
2806
        if (code != TSDB_CODE_SUCCESS) {
17,644,519!
2807
          return code;
×
2808
        }
2809
        pResInfo->numOfRes = 1;
17,644,519✔
2810
      }
2811
    }
2812
  }
2813
#endif
2814

2815
#endif
2816

2817
  // save selectivity value for column consisted of all null values
2818
  if (numOfElems == 0) {
39,239,979✔
2819
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
4,098,157✔
2820
    if (code != TSDB_CODE_SUCCESS) {
4,088,631!
2821
      return code;
×
2822
    }
2823
    pInfo->nullTupleSaved = true;
4,088,631✔
2824
  }
2825

2826
  return TSDB_CODE_SUCCESS;
39,230,453✔
2827
}
2828

2829
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
54,737,881✔
2830
  if (!pInput->hasResult) {
54,737,881✔
2831
    return false;
2✔
2832
  }
2833
  __compar_fn_t pkCompareFn = NULL;
54,737,879✔
2834
  if (pInput->pkData) {
54,737,879✔
2835
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
52✔
2836
  }
2837
  if (pOutput->hasResult) {
54,739,427✔
2838
    if (isFirst) {
18,330,927✔
2839
      if (pInput->ts > pOutput->ts ||
8,571,751✔
2840
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,571,163!
2841
        return false;
588✔
2842
      }
2843
    } else {
2844
      if (pInput->ts < pOutput->ts ||
9,759,176✔
2845
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
6,112,322!
2846
        return false;
3,646,854✔
2847
      }
2848
    }
2849
  }
2850

2851
  pOutput->isNull = pInput->isNull;
51,091,985✔
2852
  pOutput->ts = pInput->ts;
51,091,985✔
2853
  pOutput->bytes = pInput->bytes;
51,091,985✔
2854
  pOutput->pkType = pInput->pkType;
51,091,985✔
2855

2856
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
51,091,985✔
2857
  if (pInput->pkData) {
51,091,985✔
2858
    pOutput->pkBytes = pInput->pkBytes;
46✔
2859
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
46✔
2860
    pOutput->pkData = pOutput->buf + pOutput->bytes;
46✔
2861
  }
2862
  return true;
51,091,985✔
2863
}
2864

2865
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
54,737,893✔
2866
                                     int32_t rowIndex) {
2867
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
54,737,893✔
2868
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
51,091,771✔
2869
    if (TSDB_CODE_SUCCESS != code) {
51,085,890!
2870
      return code;
×
2871
    }
2872
    pOutput->hasResult = true;
51,085,890✔
2873
  }
2874
  return TSDB_CODE_SUCCESS;
54,731,674✔
2875
}
2876

2877
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
36,422,754✔
2878
  SInputColumnInfoData* pInput = &pCtx->input;
36,422,754✔
2879
  SColumnInfoData*      pCol = pInput->pData[0];
36,422,754✔
2880

2881
  if (IS_NULL_TYPE(pCol->info.type)) {
36,422,754!
2882
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
2883
    return TSDB_CODE_SUCCESS;
×
2884
  }
2885

2886
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
36,422,754!
2887
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2888
  }
2889

2890
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
36,422,754✔
2891

2892
  int32_t start = pInput->startRowIndex;
36,422,754✔
2893
  int32_t numOfElems = 0;
36,422,754✔
2894

2895
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
93,439,296✔
2896
    if (colDataIsNull_s(pCol, i)) {
114,052,790✔
2897
      continue;
2,285,193✔
2898
    }
2899
    char*          data = colDataGetData(pCol, i);
54,741,202!
2900
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
54,741,202✔
2901
    if (pCtx->hasPrimaryKey) {
54,741,202✔
2902
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
52✔
2903
    } else {
2904
      pInputInfo->pkData = NULL;
54,741,150✔
2905
    }
2906

2907
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
54,741,202✔
2908
    if (code != TSDB_CODE_SUCCESS) {
54,731,349!
2909
      return code;
×
2910
    }
2911
    if (!numOfElems) {
54,731,349✔
2912
      numOfElems = pInputInfo->hasResult ? 1 : 0;
36,411,915✔
2913
    }
2914
  }
2915

2916
  if (numOfElems == 0) {
36,412,901✔
2917
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
8,001✔
2918
    if (code != TSDB_CODE_SUCCESS) {
8,001!
2919
      return code;
×
2920
    }
2921
    pInfo->nullTupleSaved = true;
8,001✔
2922
  }
2923

2924
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
36,412,901✔
2925
  return TSDB_CODE_SUCCESS;
36,412,901✔
2926
}
2927

2928
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
9,168,257✔
2929

2930
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
27,257,694✔
2931

2932
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
80,523,442✔
2933
  int32_t          code = TSDB_CODE_SUCCESS;
80,523,442✔
2934
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
80,523,442✔
2935
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
80,523,442✔
2936
  if (NULL == pCol) {
80,497,566!
2937
    return TSDB_CODE_OUT_OF_RANGE;
×
2938
  }
2939

2940
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
80,497,566✔
2941
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
80,497,566✔
2942

2943
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
80,497,566✔
2944

2945
  if (pResInfo->isNullRes) {
80,497,566✔
2946
    colDataSetNULL(pCol, pBlock->info.rows);
41,834✔
2947
    return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
41,834✔
2948
  }
2949
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
80,455,732!
2950
  if (TSDB_CODE_SUCCESS != code) {
80,402,687!
2951
    return code;
×
2952
  }
2953

2954
  // handle selectivity
2955
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
80,402,687✔
2956

2957
  return code;
80,387,784✔
2958
}
2959

2960
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
58,692,617✔
2961
  int32_t code = TSDB_CODE_SUCCESS;
58,692,617✔
2962

2963
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
58,692,617✔
2964
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
58,692,617✔
2965

2966
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
58,692,617✔
2967

2968
  // todo check for failure
2969
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
58,655,971!
2970
  if (NULL == res) {
59,283,388!
2971
    return terrno;
×
2972
  }
2973
  (void)memcpy(varDataVal(res), pRes, resultBytes);
59,283,388✔
2974

2975
  varDataSetLen(res, resultBytes);
59,283,388✔
2976

2977
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
59,283,388✔
2978
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
59,283,388✔
2979
  if (NULL == pCol) {
58,984,745!
2980
    taosMemoryFree(res);
×
2981
    return TSDB_CODE_OUT_OF_RANGE;
×
2982
  }
2983

2984
  if (pEntryInfo->numOfRes == 0) {
59,026,422✔
2985
    colDataSetNULL(pCol, pBlock->info.rows);
2,378,790!
2986
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
2,378,790✔
2987
  } else {
2988
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
56,647,632✔
2989
    if (TSDB_CODE_SUCCESS != code) {
56,243,081!
2990
      taosMemoryFree(res);
×
2991
      return code;
×
2992
    }
2993
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
56,243,081✔
2994
  }
2995
  taosMemoryFree(res);
58,612,571!
2996
  return code;
59,081,262✔
2997
}
2998

2999
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
3000
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
3001
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
3002
  int32_t              bytes = pDBuf->bytes;
3✔
3003

3004
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
3005
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
3006

3007
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
3✔
3008
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
3009
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
3010
  return TSDB_CODE_SUCCESS;
3✔
3011
}
3012

3013
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
49,277,611✔
3014
  SInputColumnInfoData* pInput = &pCtx->input;
49,277,611✔
3015
  SColumnInfoData*      pInputCol = pInput->pData[0];
49,277,611✔
3016
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
49,277,611✔
3017

3018
  if (colDataIsNull_s(pInputCol, rowIndex)) {
98,555,222✔
3019
    pInfo->isNull = true;
13,063✔
3020
  } else {
3021
    pInfo->isNull = false;
49,264,548✔
3022

3023
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
49,264,548!
3024
      if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
188,671!
3025
        pInfo->bytes = getJsonValueLen(pData);
×
3026
      } else {
3027
        pInfo->bytes = varDataTLen(pData);
188,671✔
3028
      }
3029
    }
3030

3031
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
49,264,548✔
3032
  }
3033

3034
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
49,277,684!
3035
    char* pkData = colDataGetData(pkCol, rowIndex);
73!
3036
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
73!
3037
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
12!
3038
        pInfo->pkBytes = getJsonValueLen(pkData);
×
3039
      } else {
3040
        pInfo->pkBytes = varDataTLen(pkData);
12✔
3041
      }
3042
    }
3043
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
73✔
3044
    pInfo->pkData = pInfo->buf + pInfo->bytes;
73✔
3045
  }
3046
  pInfo->ts = cts;
49,277,611✔
3047
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
49,277,611✔
3048
  if (code != TSDB_CODE_SUCCESS) {
49,216,670!
3049
    return code;
×
3050
  }
3051

3052
  pInfo->hasResult = true;
49,216,670✔
3053

3054
  return TSDB_CODE_SUCCESS;
49,216,670✔
3055
}
3056

3057
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
49,461,992✔
3058
  int32_t numOfElems = 0;
49,461,992✔
3059

3060
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
49,461,992✔
3061
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
49,461,992✔
3062

3063
  SInputColumnInfoData* pInput = &pCtx->input;
49,461,992✔
3064
  SColumnInfoData*      pInputCol = pInput->pData[0];
49,461,992✔
3065

3066
  int32_t type = pInputCol->info.type;
49,461,992✔
3067
  int32_t bytes = pInputCol->info.bytes;
49,461,992✔
3068
  pInfo->bytes = bytes;
49,461,992✔
3069

3070
  if (IS_NULL_TYPE(type)) {
49,461,992✔
3071
    return TSDB_CODE_SUCCESS;
24✔
3072
  }
3073
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
49,461,968✔
3074
  pInfo->pkType = -1;
49,461,968✔
3075
  __compar_fn_t pkCompareFn = NULL;
49,461,968✔
3076
  if (pCtx->hasPrimaryKey) {
49,461,968✔
3077
    pInfo->pkType = pkCol->info.type;
57✔
3078
    pInfo->pkBytes = pkCol->info.bytes;
57✔
3079
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
57✔
3080
  }
3081
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
49,499,398!
3082
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
49,499,398!
3083

3084
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
49,499,398!
3085
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
57,399,571!
3086
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
28,701,802✔
3087
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
28,701,802!
3088
      TSKEY cts = getRowPTs(pInput->pPTS, i);
28,701,802!
3089
      numOfElems++;
28,701,802✔
3090

3091
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
28,701,802✔
3092
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
28,237,542✔
3093
        if (code != TSDB_CODE_SUCCESS) return code;
28,234,156!
3094
      }
3095

3096
      break;
28,698,416✔
3097
    }
3098
  } else if (!pCtx->hasPrimaryKey && pCtx->order == TSDB_ORDER_DESC) {
20,798,243!
3099
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3100
    // this assumption is NOT always works if project operator exists in downstream.
3101
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
41,636,860!
3102
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
20,849,226✔
3103
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
20,849,226!
3104
      TSKEY cts = getRowPTs(pInput->pPTS, i);
20,849,226!
3105
      numOfElems++;
20,849,226✔
3106

3107
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
20,849,226✔
3108
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
20,762,159✔
3109
        if (code != TSDB_CODE_SUCCESS) return code;
20,714,119!
3110
      }
3111
      break;
20,801,186✔
3112
    }
3113
  } else {
3114
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
×
3115
    int      from = -1;
×
3116
    int32_t  i = -1;
×
3117
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
300,024✔
3118
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
337,395✔
3119
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
337,395!
3120
      TSKEY cts = pts[i];
337,395✔
3121

3122
      numOfElems++;
337,395✔
3123
      char* pkData = NULL;
337,395✔
3124
      if (pCtx->hasPrimaryKey) {
337,395✔
3125
        pkData = colDataGetData(pkCol, i);
171!
3126
      }
3127
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
337,395✔
3128
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
73,940!
3129
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
263,461✔
3130
        if (code != TSDB_CODE_SUCCESS) {
263,521!
3131
          return code;
×
3132
        }
3133
        pResInfo->numOfRes = 1;
263,521✔
3134
      }
3135
    }
3136
  }
3137

3138
  SET_VAL(pResInfo, numOfElems, 1);
49,486,661!
3139
  return TSDB_CODE_SUCCESS;
49,486,661✔
3140
}
3141

3142
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
38,637✔
3143
  pEnv->calcMemSize = sizeof(SDiffInfo);
38,637✔
3144
  return true;
38,637✔
3145
}
3146

3147
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,172,347✔
3148
  if (pResInfo->initialized) {
2,172,347✔
3149
    return TSDB_CODE_SUCCESS;
2,081,570✔
3150
  }
3151
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
90,777!
3152
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3153
  }
3154
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
90,777✔
3155
  pDiffInfo->hasPrev = false;
90,777✔
3156
  pDiffInfo->isFirstRow = true;
90,777✔
3157
  pDiffInfo->prev.i64 = 0;
90,777✔
3158
  pDiffInfo->prevTs = -1;
90,777✔
3159
  if (pCtx->numOfParams > 1) {
90,777!
3160
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
90,777✔
3161
  } else {
3162
    pDiffInfo->ignoreOption = 0;
×
3163
  }
3164
  return TSDB_CODE_SUCCESS;
90,777✔
3165
}
3166

3167
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
2,814,710✔
3168
  switch (type) {
2,814,710!
3169
    case TSDB_DATA_TYPE_BOOL:
28✔
3170
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
28✔
3171
      break;
28✔
3172
    case TSDB_DATA_TYPE_UTINYINT:
316✔
3173
    case TSDB_DATA_TYPE_TINYINT:
3174
      pDiffInfo->prev.i64 = *(int8_t*)pv;
316✔
3175
      break;
316✔
3176
    case TSDB_DATA_TYPE_UINT:
343,877✔
3177
    case TSDB_DATA_TYPE_INT:
3178
      pDiffInfo->prev.i64 = *(int32_t*)pv;
343,877✔
3179
      break;
343,877✔
3180
    case TSDB_DATA_TYPE_USMALLINT:
331✔
3181
    case TSDB_DATA_TYPE_SMALLINT:
3182
      pDiffInfo->prev.i64 = *(int16_t*)pv;
331✔
3183
      break;
331✔
3184
    case TSDB_DATA_TYPE_TIMESTAMP:
286✔
3185
    case TSDB_DATA_TYPE_UBIGINT:
3186
    case TSDB_DATA_TYPE_BIGINT:
3187
      pDiffInfo->prev.i64 = *(int64_t*)pv;
286✔
3188
      break;
286✔
3189
    case TSDB_DATA_TYPE_FLOAT:
584,560✔
3190
      pDiffInfo->prev.d64 = *(float*)pv;
584,560✔
3191
      break;
584,560✔
3192
    case TSDB_DATA_TYPE_DOUBLE:
1,885,312✔
3193
      pDiffInfo->prev.d64 = *(double*)pv;
1,885,312✔
3194
      break;
1,885,312✔
3195
    default:
×
3196
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3197
  }
3198
  pDiffInfo->prevTs = ts;
2,814,710✔
3199
  pDiffInfo->hasPrev = true;
2,814,710✔
3200
  return TSDB_CODE_SUCCESS;
2,814,710✔
3201
}
3202

3203
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
8,742,730✔
3204
  switch (type) {
8,742,730!
3205
    case TSDB_DATA_TYPE_UINT: {
×
3206
      int64_t v = *(uint32_t*)pv;
×
3207
      return v < pDiffInfo->prev.i64;
×
3208
    }
3209
    case TSDB_DATA_TYPE_INT: {
1,660,583✔
3210
      int64_t v = *(int32_t*)pv;
1,660,583✔
3211
      return v < pDiffInfo->prev.i64;
1,660,583✔
3212
    }
3213
    case TSDB_DATA_TYPE_BOOL: {
×
3214
      int64_t v = *(bool*)pv;
×
3215
      return v < pDiffInfo->prev.i64;
×
3216
    }
3217
    case TSDB_DATA_TYPE_UTINYINT: {
×
3218
      int64_t v = *(uint8_t*)pv;
×
3219
      return v < pDiffInfo->prev.i64;
×
3220
    }
3221
    case TSDB_DATA_TYPE_TINYINT: {
7,946✔
3222
      int64_t v = *(int8_t*)pv;
7,946✔
3223
      return v < pDiffInfo->prev.i64;
7,946✔
3224
    }
3225
    case TSDB_DATA_TYPE_USMALLINT: {
×
3226
      int64_t v = *(uint16_t*)pv;
×
3227
      return v < pDiffInfo->prev.i64;
×
3228
    }
3229
    case TSDB_DATA_TYPE_SMALLINT: {
4,588✔
3230
      int64_t v = *(int16_t*)pv;
4,588✔
3231
      return v < pDiffInfo->prev.i64;
4,588✔
3232
    }
3233
    case TSDB_DATA_TYPE_UBIGINT: {
24✔
3234
      uint64_t v = *(uint64_t*)pv;
24✔
3235
      return v < (uint64_t)pDiffInfo->prev.i64;
24✔
3236
    }
3237
    case TSDB_DATA_TYPE_TIMESTAMP:
5,691✔
3238
    case TSDB_DATA_TYPE_BIGINT: {
3239
      int64_t v = *(int64_t*)pv;
5,691✔
3240
      return v < pDiffInfo->prev.i64;
5,691✔
3241
    }
3242
    case TSDB_DATA_TYPE_FLOAT: {
1,661,455✔
3243
      float v = *(float*)pv;
1,661,455✔
3244
      return v < pDiffInfo->prev.d64;
1,661,455✔
3245
    }
3246
    case TSDB_DATA_TYPE_DOUBLE: {
5,402,443✔
3247
      double v = *(double*)pv;
5,402,443✔
3248
      return v < pDiffInfo->prev.d64;
5,402,443✔
3249
    }
3250
    default:
×
3251
      return false;
×
3252
  }
3253

3254
  return false;
3255
}
3256

3257
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
1,797,694,956✔
3258
  bool isNegative = v < pDiffInfo->prev.i64;
1,797,694,956✔
3259
  if (type == TSDB_DATA_TYPE_UBIGINT) {
1,797,694,956✔
3260
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
453✔
3261
  }
3262
  int64_t delta = v - pDiffInfo->prev.i64;
1,797,694,956✔
3263
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
1,797,694,956✔
3264
    colDataSetNull_f_s(pOutput, pos);
569,607✔
3265
    pOutput->hasNull = true;
569,607✔
3266
  } else {
3267
    colDataSetInt64(pOutput, pos, &delta);
1,797,125,349✔
3268
  }
3269
  pDiffInfo->prev.i64 = v;
1,797,694,956✔
3270
}
1,797,694,956✔
3271

3272
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
4,705,630✔
3273
  double delta = v - pDiffInfo->prev.d64;
4,705,630✔
3274
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
4,705,630✔
3275
    colDataSetNull_f_s(pOutput, pos);
1,214,272✔
3276
  } else {
3277
    colDataSetDouble(pOutput, pos, &delta);
3,491,358✔
3278
  }
3279
  pDiffInfo->prev.d64 = v;
4,705,630✔
3280
}
4,705,630✔
3281

3282
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
1,802,401,155✔
3283
                            int64_t ts) {
3284
  if (!pDiffInfo->hasPrev) {
1,802,401,155✔
3285
    colDataSetNull_f_s(pOutput, pos);
569✔
3286
    return doSetPrevVal(pDiffInfo, type, pv, ts);
569✔
3287
  }
3288
  pDiffInfo->prevTs = ts;
1,802,400,586✔
3289
  switch (type) {
1,802,400,586!
3290
    case TSDB_DATA_TYPE_UINT: {
411✔
3291
      int64_t v = *(uint32_t*)pv;
411✔
3292
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
411✔
3293
      break;
411✔
3294
    }
3295
    case TSDB_DATA_TYPE_INT: {
27,625,724✔
3296
      int64_t v = *(int32_t*)pv;
27,625,724✔
3297
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
27,625,724✔
3298
      break;
27,625,724✔
3299
    }
3300
    case TSDB_DATA_TYPE_BOOL: {
10,617✔
3301
      int64_t v = *(bool*)pv;
10,617✔
3302
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,617✔
3303
      break;
10,617✔
3304
    }
3305
    case TSDB_DATA_TYPE_UTINYINT: {
405✔
3306
      int64_t v = *(uint8_t*)pv;
405✔
3307
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3308
      break;
405✔
3309
    }
3310
    case TSDB_DATA_TYPE_TINYINT: {
36,413✔
3311
      int64_t v = *(int8_t*)pv;
36,413✔
3312
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
36,413✔
3313
      break;
36,413✔
3314
    }
3315
    case TSDB_DATA_TYPE_USMALLINT: {
405✔
3316
      int64_t v = *(uint16_t*)pv;
405✔
3317
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3318
      break;
405✔
3319
    }
3320
    case TSDB_DATA_TYPE_SMALLINT: {
38,617✔
3321
      int64_t v = *(int16_t*)pv;
38,617✔
3322
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
38,617✔
3323
      break;
38,617✔
3324
    }
3325
    case TSDB_DATA_TYPE_TIMESTAMP:
1,769,982,364✔
3326
    case TSDB_DATA_TYPE_UBIGINT:
3327
    case TSDB_DATA_TYPE_BIGINT: {
3328
      int64_t v = *(int64_t*)pv;
1,769,982,364✔
3329
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,769,982,364✔
3330
      break;
1,769,982,364✔
3331
    }
3332
    case TSDB_DATA_TYPE_FLOAT: {
1,125,719✔
3333
      double v = *(float*)pv;
1,125,719✔
3334
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
1,125,719✔
3335
      break;
1,125,719✔
3336
    }
3337
    case TSDB_DATA_TYPE_DOUBLE: {
3,579,911✔
3338
      double v = *(double*)pv;
3,579,911✔
3339
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
3,579,911✔
3340
      break;
3,579,911✔
3341
    }
3342
    default:
×
3343
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3344
  }
3345
  pDiffInfo->hasPrev = true;
1,802,400,586✔
3346
  return TSDB_CODE_SUCCESS;
1,802,400,586✔
3347
}
3348

3349
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3350
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3351
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
302,137,749✔
3352
                              int32_t* nextFrom) {
3353
  if (pInput->pPrimaryKey == NULL) {
302,137,749✔
3354
    if (from == -1) {
202,175,340✔
3355
      from = pInput->startRowIndex;
61,095,945✔
3356
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
141,079,395✔
3357
      return false;
60,900,660✔
3358
    }
3359
    *pRowIndex = from;
141,274,680✔
3360
    *nextFrom = from + 1;
141,274,680✔
3361
    return true;
141,274,680✔
3362
  } else {
3363
    if (from == -1) {
99,962,409✔
3364
      from = pInput->startRowIndex;
30,175✔
3365
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
99,932,234✔
3366
      return false;
30,175✔
3367
    }
3368
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
99,932,234✔
3369
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
99,932,234✔
3370
    int8_t           pkType = pkCol->info.type;
99,932,234✔
3371
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
99,932,234✔
3372
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
99,932,234✔
3373
    int32_t          select = from;
100,000,517✔
3374
    char*            val = colDataGetData(pkCol, select);
100,000,517!
3375
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
100,001,072✔
3376
      char* val1 = colDataGetData(pkCol, from + 1);
555!
3377
      if (compareFunc(val1, val) < 0) {
555!
3378
        select = from + 1;
×
3379
        val = val1;
×
3380
      }
3381
      from = from + 1;
555✔
3382
    }
3383
    *pRowIndex = select;
100,000,517✔
3384
    *nextFrom = from + 1;
100,000,517✔
3385
    return true;
100,000,517✔
3386
  }
3387
}
3388

3389
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
26✔
3390
  pEnv->calcMemSize = sizeof(float);
26✔
3391
  return true;
26✔
3392
}
3393

3394
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,805,305,118✔
3395
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,805,305,118✔
3396
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,805,305,118✔
3397

3398
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
1,805,305,118✔
3399
    return true;
179,436✔
3400
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
1,805,125,682✔
3401
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
8,742,730✔
3402
  }
3403
  return false;
1,796,382,952✔
3404
}
3405

3406
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,802,559,391✔
3407
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,802,559,391✔
3408
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,802,559,391✔
3409
  return pDiffInfo->isFirstRow;
1,802,559,391✔
3410
}
3411

3412
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
2,815,902✔
3413
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,815,902✔
3414
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,815,902✔
3415
  pDiffInfo->isFirstRow = false;
2,815,902✔
3416
  if (pRow->isDataNull) {
2,815,902✔
3417
    return TSDB_CODE_SUCCESS;
1,761✔
3418
  }
3419

3420
  SInputColumnInfoData* pInput = &pCtx->input;
2,814,141✔
3421
  SColumnInfoData*      pInputCol = pInput->pData[0];
2,814,141✔
3422
  int8_t                inputType = pInputCol->info.type;
2,814,141✔
3423

3424
  char* pv = pRow->pData;
2,814,141✔
3425
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
2,814,141✔
3426
}
3427

3428
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
1,802,489,216✔
3429
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,802,489,216✔
3430
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,802,489,216✔
3431

3432
  SInputColumnInfoData* pInput = &pCtx->input;
1,802,489,216✔
3433
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,802,489,216✔
3434
  int8_t                inputType = pInputCol->info.type;
1,802,489,216✔
3435
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
1,802,489,216✔
3436
  int32_t               code = TSDB_CODE_SUCCESS;
1,802,489,216✔
3437
  if (pRow->isDataNull) {
1,802,489,216✔
3438
    colDataSetNull_f_s(pOutput, pos);
88,040✔
3439
    pOutput->hasNull = true;
88,040✔
3440

3441
    // handle selectivity
3442
    if (pCtx->subsidiaries.num > 0) {
88,040✔
3443
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
676✔
3444
      if (code != TSDB_CODE_SUCCESS) {
676!
3445
        return code;
×
3446
      }
3447
    }
3448
    return TSDB_CODE_SUCCESS;
88,040✔
3449
  }
3450

3451
  char* pv = pRow->pData;
1,802,401,176✔
3452

3453
  if (pRow->ts == pDiffInfo->prevTs) {
1,802,401,176✔
3454
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
21✔
3455
  }
3456
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
1,802,401,155✔
3457
  if (code != TSDB_CODE_SUCCESS) {
1,802,401,155!
3458
    return code;
×
3459
  }
3460
  // handle selectivity
3461
  if (pCtx->subsidiaries.num > 0) {
1,802,401,155✔
3462
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
34,628,751✔
3463
    if (code != TSDB_CODE_SUCCESS) {
34,628,751!
3464
      return code;
×
3465
    }
3466
  }
3467

3468
  return TSDB_CODE_SUCCESS;
1,802,401,155✔
3469
}
3470

3471
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
2,133,710✔
3472

3473
int32_t diffFunctionByRow(SArray* pCtxArray) {
2,133,554✔
3474
  int32_t code = TSDB_CODE_SUCCESS;
2,133,554✔
3475
  int     diffColNum = pCtxArray->size;
2,133,554✔
3476
  if (diffColNum == 0) {
2,133,554!
3477
    return TSDB_CODE_SUCCESS;
×
3478
  }
3479
  int32_t numOfElems = 0;
2,133,554✔
3480

3481
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
2,133,554✔
3482
  if (NULL == pRows) {
2,133,554!
3483
    return terrno;
×
3484
  }
3485

3486
  bool keepNull = false;
2,133,554✔
3487
  for (int i = 0; i < diffColNum; ++i) {
4,267,264✔
3488
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,133,710✔
3489
    if (NULL == pCtx) {
2,133,710!
3490
      code = terrno;
×
3491
      goto _exit;
×
3492
    }
3493
    funcInputUpdate(pCtx);
2,133,710✔
3494
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,133,710✔
3495
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,133,710✔
3496
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
2,133,710✔
3497
      keepNull = true;
2,113,169✔
3498
    }
3499
  }
3500

3501
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
2,133,554✔
3502
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
2,133,554✔
3503
  if (NULL == pCtx0 || NULL == pRow0) {
2,133,554!
3504
    code = terrno;
×
3505
    goto _exit;
×
3506
  }
3507
  int32_t startOffset = pCtx0->offset;
2,133,554✔
3508
  bool    result = false;
2,133,554✔
3509
  while (1) {
1,805,290,603✔
3510
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
1,807,424,157✔
3511
    if (TSDB_CODE_SUCCESS != code) {
1,807,424,157!
3512
      goto _exit;
×
3513
    }
3514
    if (!result) {
1,807,424,157✔
3515
      break;
2,133,533✔
3516
    }
3517
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
1,805,290,624✔
3518
    for (int i = 1; i < diffColNum; ++i) {
1,805,305,118✔
3519
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
14,494✔
3520
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
14,494✔
3521
      if (NULL == pCtx || NULL == pRow) {
14,494!
3522
        code = terrno;
×
3523
        goto _exit;
×
3524
      }
3525
      code = funcInputGetNextRow(pCtx, pRow, &result);
14,494✔
3526
      if (TSDB_CODE_SUCCESS != code) {
14,494!
3527
        goto _exit;
×
3528
      }
3529
      if (!result) {
14,494!
3530
        // rows are not equal
3531
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3532
        goto _exit;
×
3533
      }
3534
      if (!diffResultIsNull(pCtx, pRow)) {
14,494✔
3535
        hasNotNullValue = true;
14,052✔
3536
      }
3537
    }
3538
    int32_t pos = startOffset + numOfElems;
1,805,290,624✔
3539

3540
    bool newRow = false;
1,805,290,624✔
3541
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3542
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,805,305,118✔
3543
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
1,805,305,118✔
3544
      if (NULL == pCtx || NULL == pRow) {
1,805,305,118!
3545
        code = terrno;
×
3546
        goto _exit;
×
3547
      }
3548
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
1,805,305,118✔
3549
        code = setDoDiffResult(pCtx, pRow, pos);
1,802,489,216✔
3550
        if (code != TSDB_CODE_SUCCESS) {
1,802,489,216✔
3551
          goto _exit;
21✔
3552
        }
3553
        newRow = true;
1,802,489,195✔
3554
      } else {
3555
        code = trySetPreVal(pCtx, pRow);
2,815,902✔
3556
        if (code != TSDB_CODE_SUCCESS) {
2,815,902!
3557
          goto _exit;
×
3558
        }
3559
      }
3560
    }
3561
    if (newRow) ++numOfElems;
1,805,290,603✔
3562
  }
3563

3564
  for (int i = 0; i < diffColNum; ++i) {
4,267,219✔
3565
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,133,686✔
3566
    if (NULL == pCtx) {
2,133,686!
3567
      code = terrno;
×
3568
      goto _exit;
×
3569
    }
3570
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,133,686✔
3571
    pResInfo->numOfRes = numOfElems;
2,133,686✔
3572
  }
3573

3574
_exit:
2,133,533✔
3575
  if (pRows) {
2,133,554!
3576
    taosArrayDestroy(pRows);
2,133,554✔
3577
    pRows = NULL;
2,133,554✔
3578
  }
3579
  return code;
2,133,554✔
3580
}
3581

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

3584
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
87,465✔
3585
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
87,465✔
3586
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
87,511✔
3587
  return true;
87,511✔
3588
}
3589

3590
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
46,784,655✔
3591
  if (pResInfo->initialized) {
46,784,655!
3592
    return TSDB_CODE_SUCCESS;
×
3593
  }
3594
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
46,784,655!
3595
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3596
  }
3597

3598
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
46,809,159✔
3599
  SInputColumnInfoData* pInput = &pCtx->input;
46,809,159✔
3600

3601
  pRes->maxSize = pCtx->param[1].param.i;
46,809,159✔
3602

3603
  pRes->nullTupleSaved = false;
46,809,159✔
3604
  pRes->nullTuplePos.pageId = -1;
46,809,159✔
3605
  return TSDB_CODE_SUCCESS;
46,809,159✔
3606
}
3607

3608
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
214,332,477✔
3609
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
214,332,477✔
3610
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
214,332,477✔
3611
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
214,332,477✔
3612

3613
  return pRes;
214,332,477✔
3614
}
3615

3616
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
3617
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
3618

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

3621
int32_t topFunction(SqlFunctionCtx* pCtx) {
23,959,722✔
3622
  int32_t              numOfElems = 0;
23,959,722✔
3623
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
23,959,722✔
3624

3625
  SInputColumnInfoData* pInput = &pCtx->input;
23,959,722✔
3626
  SColumnInfoData*      pCol = pInput->pData[0];
23,959,722✔
3627

3628
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
23,959,722✔
3629
  pRes->type = pInput->pData[0]->info.type;
23,960,834✔
3630

3631
  int32_t start = pInput->startRowIndex;
23,960,834✔
3632
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
77,534,800✔
3633
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
53,533,669✔
3634
      continue;
28,473✔
3635
    }
3636

3637
    numOfElems++;
53,505,196✔
3638
    char*   data = colDataGetData(pCol, i);
53,505,196!
3639
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
53,505,196✔
3640
    if (code != TSDB_CODE_SUCCESS) {
53,545,493!
3641
      return code;
×
3642
    }
3643
  }
3644

3645
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
24,001,131✔
3646
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
131✔
3647
    if (code != TSDB_CODE_SUCCESS) {
131!
3648
      return code;
×
3649
    }
3650
    pRes->nullTupleSaved = true;
131✔
3651
  }
3652
  return TSDB_CODE_SUCCESS;
24,001,131✔
3653
}
3654

3655
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
23,927,008✔
3656
  int32_t              numOfElems = 0;
23,927,008✔
3657
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
23,927,008✔
3658

3659
  SInputColumnInfoData* pInput = &pCtx->input;
23,927,008✔
3660
  SColumnInfoData*      pCol = pInput->pData[0];
23,927,008✔
3661

3662
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
23,927,008✔
3663
  pRes->type = pInput->pData[0]->info.type;
23,928,413✔
3664

3665
  int32_t start = pInput->startRowIndex;
23,928,413✔
3666
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
90,514,658✔
3667
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
66,568,963✔
3668
      continue;
37,073✔
3669
    }
3670

3671
    numOfElems++;
66,531,890✔
3672
    char*   data = colDataGetData(pCol, i);
66,531,890!
3673
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
66,531,890✔
3674
    if (code != TSDB_CODE_SUCCESS) {
66,549,172!
3675
      return code;
×
3676
    }
3677
  }
3678

3679
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
23,945,695✔
3680
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
4,042✔
3681
    if (code != TSDB_CODE_SUCCESS) {
4,042!
3682
      return code;
×
3683
    }
3684
    pRes->nullTupleSaved = true;
4,042✔
3685
  }
3686

3687
  return TSDB_CODE_SUCCESS;
23,945,695✔
3688
}
3689

3690
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
389,543,161✔
3691
  uint16_t type = *(uint16_t*)param;
389,543,161✔
3692

3693
  STopBotResItem* val1 = (STopBotResItem*)p1;
389,543,161✔
3694
  STopBotResItem* val2 = (STopBotResItem*)p2;
389,543,161✔
3695

3696
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
389,543,161!
3697
    if (val1->v.i == val2->v.i) {
344,411,684✔
3698
      return 0;
205,120✔
3699
    }
3700

3701
    return (val1->v.i > val2->v.i) ? 1 : -1;
344,206,564✔
3702
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
45,131,477!
3703
    if (val1->v.u == val2->v.u) {
635,729✔
3704
      return 0;
133,891✔
3705
    }
3706

3707
    return (val1->v.u > val2->v.u) ? 1 : -1;
501,838✔
3708
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
44,495,748✔
3709
    if (val1->v.f == val2->v.f) {
3,550,821✔
3710
      return 0;
63✔
3711
    }
3712

3713
    return (val1->v.f > val2->v.f) ? 1 : -1;
3,550,758✔
3714
  }
3715

3716
  if (val1->v.d == val2->v.d) {
40,944,927✔
3717
    return 0;
11✔
3718
  }
3719

3720
  return (val1->v.d > val2->v.d) ? 1 : -1;
40,944,916✔
3721
}
3722

3723
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
120,024,370✔
3724
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3725
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
120,024,370✔
3726
  int32_t     code = TSDB_CODE_SUCCESS;
119,999,677✔
3727

3728
  SVariant val = {0};
119,999,677✔
3729
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
119,999,677!
3730

3731
  STopBotResItem* pItems = pRes->pItems;
120,046,798✔
3732

3733
  // not full yet
3734
  if (pEntryInfo->numOfRes < pRes->maxSize) {
120,046,798✔
3735
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
78,698,453✔
3736
    pItem->v = val;
78,698,453✔
3737
    pItem->uid = uid;
78,698,453✔
3738

3739
    // save the data of this tuple
3740
    if (pCtx->subsidiaries.num > 0) {
78,698,453✔
3741
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
41,763,618✔
3742
      if (code != TSDB_CODE_SUCCESS) {
41,709,238!
3743
        return code;
×
3744
      }
3745
    }
3746
#ifdef BUF_PAGE_DEBUG
3747
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3748
           pItem->tuplePos.offset);
3749
#endif
3750
    // allocate the buffer and keep the data of this row into the new allocated buffer
3751
    pEntryInfo->numOfRes++;
78,644,073✔
3752
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
78,644,073✔
3753
                        topBotResComparFn, !isTopQuery);
78,644,073✔
3754
    if (code != TSDB_CODE_SUCCESS) {
78,748,319!
3755
      return code;
×
3756
    }
3757
  } else {  // replace the minimum value in the result
3758
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
41,348,345✔
3759
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
15,203,274!
3760
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
15,112,307✔
3761
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
14,996,989✔
3762
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
38,144,128!
3763
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
19,725,892!
3764
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
19,724,877✔
3765
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
19,631,369✔
3766
      // replace the old data and the coresponding tuple data
3767
      STopBotResItem* pItem = &pItems[0];
8,539,662✔
3768
      pItem->v = val;
8,539,662✔
3769
      pItem->uid = uid;
8,539,662✔
3770

3771
      // save the data of this tuple by over writing the old data
3772
      if (pCtx->subsidiaries.num > 0) {
8,539,662✔
3773
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
5,688,475✔
3774
        if (code != TSDB_CODE_SUCCESS) {
5,684,564!
3775
          return code;
×
3776
        }
3777
      }
3778
#ifdef BUF_PAGE_DEBUG
3779
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3780
#endif
3781
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
8,535,751✔
3782
                            topBotResComparFn, NULL, !isTopQuery);
8,535,751✔
3783
      if (code != TSDB_CODE_SUCCESS) {
8,497,142!
3784
        return code;
×
3785
      }
3786
    }
3787
  }
3788

3789
  return TSDB_CODE_SUCCESS;
120,054,144✔
3790
}
3791

3792
/*
3793
 * +------------------------------------+--------------+--------------+
3794
 * |            null bitmap             |              |              |
3795
 * |(n columns, one bit for each column)| src column #1| src column #2|
3796
 * +------------------------------------+--------------+--------------+
3797
 */
3798
int32_t serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
172,755,739✔
3799
                           char* buf, char** res) {
3800
  char* nullList = buf;
172,755,739✔
3801
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
172,755,739✔
3802

3803
  int32_t offset = 0;
172,755,739✔
3804
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
345,445,418✔
3805
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
172,808,680✔
3806

3807
    // group_key function has its own process function
3808
    // do not process there
3809
    if (fmIsGroupKeyFunc(pc->functionId)) {
172,808,680✔
3810
      continue;
2,818,615✔
3811
    }
3812

3813
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
169,967,149✔
3814
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
169,967,149✔
3815

3816
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
169,967,149✔
3817
    if (NULL == pCol) {
169,871,064!
3818
      return TSDB_CODE_OUT_OF_RANGE;
×
3819
    }
3820
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
339,742,128✔
3821
      offset += pCol->info.bytes;
276✔
3822
      continue;
276✔
3823
    }
3824

3825
    char* p = colDataGetData(pCol, rowIndex);
169,870,788!
3826
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
169,870,788!
3827
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
41,169!
3828
    } else {
3829
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
169,829,619✔
3830
    }
3831

3832
    offset += pCol->info.bytes;
169,870,788✔
3833
  }
3834

3835
  *res = buf;
172,636,738✔
3836
  return TSDB_CODE_SUCCESS;
172,636,738✔
3837
}
3838

3839
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
195,320,623✔
3840
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3841
  STuplePos p = {0};
195,320,623✔
3842
  if (pHandle->pBuf != NULL) {
195,320,623✔
3843
    SFilePage* pPage = NULL;
195,264,214✔
3844

3845
    if (pHandle->currentPage == -1) {
195,264,214✔
3846
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
625,244✔
3847
      if (pPage == NULL) {
625,244!
3848
        return terrno;
×
3849
      }
3850
      pPage->num = sizeof(SFilePage);
625,244✔
3851
    } else {
3852
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
194,638,970✔
3853
      if (pPage == NULL) {
194,601,290!
3854
        return terrno;
×
3855
      }
3856
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
194,601,290✔
3857
        // current page is all used, let's prepare a new buffer page
3858
        releaseBufPage(pHandle->pBuf, pPage);
1,534,853✔
3859
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
1,534,846✔
3860
        if (pPage == NULL) {
1,534,862!
3861
          return terrno;
×
3862
        }
3863
        pPage->num = sizeof(SFilePage);
1,534,862✔
3864
      }
3865
    }
3866

3867
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
195,213,501✔
3868
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
195,213,501✔
3869

3870
    pPage->num += length;
195,213,501✔
3871
    setBufPageDirty(pPage, true);
195,213,501✔
3872
    releaseBufPage(pHandle->pBuf, pPage);
195,146,285✔
3873
  } else {  // other tuple save policy
3874
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
56,409!
3875
      p.streamTupleKey = *key;
65,672✔
3876
    }
3877
  }
3878

3879
  *pPos = p;
195,160,629✔
3880
  return TSDB_CODE_SUCCESS;
195,160,629✔
3881
}
3882

3883
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
153,009,752✔
3884
  int32_t code = prepareBuf(pCtx);
153,009,752✔
3885
  if (TSDB_CODE_SUCCESS != code) {
152,997,609!
3886
    return code;
×
3887
  }
3888

3889
  SWinKey key = {0};
152,997,609✔
3890
  if (pCtx->saveHandle.pBuf == NULL) {
152,997,609✔
3891
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
65,671✔
3892
    if (NULL == pColInfo) {
65,670!
3893
      return TSDB_CODE_OUT_OF_RANGE;
×
3894
    }
3895
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
65,670!
3896
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3897
    }
3898
    key.groupId = pSrcBlock->info.id.groupId;
65,670✔
3899
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
65,670!
3900
  }
3901

3902
  char* buf = NULL;
152,997,608✔
3903
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
152,997,608✔
3904
  if (TSDB_CODE_SUCCESS != code) {
152,923,669!
3905
    return code;
×
3906
  }
3907
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
152,923,669✔
3908
}
3909

3910
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
19,776,385✔
3911
                                 SFunctionStateStore* pStore) {
3912
  if (pHandle->pBuf != NULL) {
19,776,385✔
3913
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
19,651,583✔
3914
    if (pPage == NULL) {
19,650,640!
3915
      return terrno;
×
3916
    }
3917
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
19,650,640✔
3918
    setBufPageDirty(pPage, true);
19,650,640✔
3919
    releaseBufPage(pHandle->pBuf, pPage);
19,648,768✔
3920
  } else {
3921
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
124,802✔
3922
    if (TSDB_CODE_SUCCESS != code) {
124,969!
3923
      return code;
×
3924
    }
3925
  }
3926

3927
  return TSDB_CODE_SUCCESS;
19,771,970✔
3928
}
3929

3930
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
19,778,758✔
3931
  int32_t code = prepareBuf(pCtx);
19,778,758✔
3932
  if (TSDB_CODE_SUCCESS != code) {
19,778,372!
3933
    return code;
×
3934
  }
3935

3936
  char* buf = NULL;
19,778,372✔
3937
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
19,778,372✔
3938
  if (TSDB_CODE_SUCCESS != code) {
19,776,273!
3939
    return code;
×
3940
  }
3941
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
19,776,273✔
3942
}
3943

3944
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
124,190,597✔
3945
                               char** value) {
3946
  if (pHandle->pBuf != NULL) {
124,190,597✔
3947
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
124,127,293✔
3948
    if (pPage == NULL) {
124,177,965!
3949
      *value = NULL;
×
3950
      return terrno;
×
3951
    }
3952
    *value = pPage->data + pPos->offset;
124,177,965✔
3953
    releaseBufPage(pHandle->pBuf, pPage);
124,177,965✔
3954
    return TSDB_CODE_SUCCESS;
124,136,823✔
3955
  } else {
3956
    *value = NULL;
63,304✔
3957
    int32_t vLen;
3958
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
63,304✔
3959
    if (TSDB_CODE_SUCCESS != code) {
65,624!
3960
      return code;
×
3961
    }
3962
    return TSDB_CODE_SUCCESS;
65,624✔
3963
  }
3964
}
3965

3966
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
124,126,147✔
3967
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
124,126,147✔
3968
}
3969

3970
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
46,676,075✔
3971
  int32_t code = TSDB_CODE_SUCCESS;
46,676,075✔
3972

3973
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
46,676,075✔
3974
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
46,676,075✔
3975

3976
  int16_t type = pCtx->pExpr->base.resSchema.type;
46,670,175✔
3977
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
46,670,175✔
3978

3979
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
46,670,175✔
3980
  if (NULL == pCol) {
46,652,094!
3981
    return TSDB_CODE_OUT_OF_RANGE;
×
3982
  }
3983

3984
  // todo assign the tag value and the corresponding row data
3985
  int32_t currentRow = pBlock->info.rows;
46,652,094✔
3986
  if (pEntryInfo->numOfRes <= 0) {
46,652,094✔
3987
    colDataSetNULL(pCol, currentRow);
609!
3988
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
609✔
3989
    return code;
609✔
3990
  }
3991
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
124,977,806✔
3992
    STopBotResItem* pItem = &pRes->pItems[i];
78,368,874✔
3993
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
78,368,874✔
3994
    if (TSDB_CODE_SUCCESS != code) {
78,334,376!
3995
      return code;
×
3996
    }
3997
#ifdef BUF_PAGE_DEBUG
3998
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3999
           pItem->tuplePos.offset);
4000
#endif
4001
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
78,334,376✔
4002
    if (TSDB_CODE_SUCCESS != code) {
78,326,321!
4003
      return code;
×
4004
    }
4005
    currentRow += 1;
78,326,321✔
4006
  }
4007

4008
  return code;
46,608,932✔
4009
}
4010

4011
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
4012
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
4013
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
4014
  STopBotResItem*      pItems = pRes->pItems;
×
4015
  int32_t              code = TSDB_CODE_SUCCESS;
×
4016

4017
  // not full yet
4018
  if (pEntryInfo->numOfRes < pRes->maxSize) {
×
4019
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
×
4020
    pItem->v = pSourceItem->v;
×
4021
    pItem->uid = pSourceItem->uid;
×
4022
    pItem->tuplePos.pageId = -1;
×
4023
    replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4024
    pEntryInfo->numOfRes++;
×
4025
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
×
4026
                        topBotResComparFn, !isTopQuery);
×
4027
    if (TSDB_CODE_SUCCESS != code) {
×
4028
      return code;
×
4029
    }
4030
  } else {  // replace the minimum value in the result
4031
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i > pItems[0].v.i) ||
×
4032
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u > pItems[0].v.u) ||
×
4033
                        (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f > pItems[0].v.f) ||
×
4034
                        (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d > pItems[0].v.d))) ||
×
4035
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && pSourceItem->v.i < pItems[0].v.i) ||
×
4036
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && pSourceItem->v.u < pItems[0].v.u) ||
×
4037
                         (TSDB_DATA_TYPE_FLOAT == type && pSourceItem->v.f < pItems[0].v.f) ||
×
4038
                         (TSDB_DATA_TYPE_DOUBLE == type && pSourceItem->v.d < pItems[0].v.d)))) {
×
4039
      // replace the old data and the coresponding tuple data
4040
      STopBotResItem* pItem = &pItems[0];
×
4041
      pItem->v = pSourceItem->v;
×
4042
      pItem->uid = pSourceItem->uid;
×
4043

4044
      // save the data of this tuple by over writing the old data
4045
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4046
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4047
                            topBotResComparFn, NULL, !isTopQuery);
×
4048
      if (TSDB_CODE_SUCCESS != code) {
×
4049
        return code;
×
4050
      }
4051
    }
4052
  }
4053
  return code;
×
4054
}
4055

4056
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4057
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4058
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4059
  int16_t              type = pSBuf->type;
×
4060
  int32_t              code = TSDB_CODE_SUCCESS;
×
4061
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4062
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
4063
    if (TSDB_CODE_SUCCESS != code) {
×
4064
      return code;
×
4065
    }
4066
  }
4067
  return TSDB_CODE_SUCCESS;
×
4068
}
4069

4070
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4071
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4072
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4073
  int16_t              type = pSBuf->type;
×
4074
  int32_t              code = TSDB_CODE_SUCCESS;
×
4075
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4076
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4077
    if (TSDB_CODE_SUCCESS != code) {
×
4078
      return code;
×
4079
    }
4080
  }
4081
  return TSDB_CODE_SUCCESS;
×
4082
}
4083

4084
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
1,037,312✔
4085

4086
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
105,358✔
4087
  pEnv->calcMemSize = sizeof(SSpreadInfo);
105,358✔
4088
  return true;
105,358✔
4089
}
4090

4091
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3,485,665✔
4092
  if (pResultInfo->initialized) {
3,485,665!
4093
    return TSDB_CODE_SUCCESS;
×
4094
  }
4095
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
3,485,665!
4096
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4097
  }
4098

4099
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
3,485,678✔
4100
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
3,485,678✔
4101
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
3,485,678✔
4102
  pInfo->hasResult = false;
3,485,678✔
4103
  return TSDB_CODE_SUCCESS;
3,485,678✔
4104
}
4105

4106
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
2,502,905✔
4107
  int32_t numOfElems = 0;
2,502,905✔
4108

4109
  // Only the pre-computing information loaded and actual data does not loaded
4110
  SInputColumnInfoData* pInput = &pCtx->input;
2,502,905✔
4111
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,502,905✔
4112
  int32_t               type = pInput->pData[0]->info.type;
2,502,905✔
4113

4114
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,502,905✔
4115

4116
  if (pInput->colDataSMAIsSet) {
2,502,905!
4117
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
×
4118
    if (numOfElems == 0) {
×
4119
      goto _spread_over;
×
4120
    }
4121
    double tmin = 0.0, tmax = 0.0;
×
4122
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
×
4123
      tmin = (double)GET_INT64_VAL(&pAgg->min);
×
4124
      tmax = (double)GET_INT64_VAL(&pAgg->max);
×
4125
    } else if (IS_FLOAT_TYPE(type)) {
×
4126
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4127
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4128
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
4129
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
4130
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
4131
    }
4132

4133
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
×
4134
      SET_DOUBLE_VAL(&pInfo->min, tmin);
×
4135
    }
4136

4137
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
×
4138
      SET_DOUBLE_VAL(&pInfo->max, tmax);
×
4139
    }
4140

4141
  } else {  // computing based on the true data block
4142
    SColumnInfoData* pCol = pInput->pData[0];
2,502,905✔
4143

4144
    int32_t start = pInput->startRowIndex;
2,502,905✔
4145
    // check the valid data one by one
4146
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
12,663,112✔
4147
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
10,160,207✔
4148
        continue;
1,836,391✔
4149
      }
4150

4151
      char* data = colDataGetData(pCol, i);
8,323,816!
4152

4153
      double v = 0;
8,323,816✔
4154
      GET_TYPED_DATA(v, double, type, data);
8,323,816!
4155
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
8,323,816✔
4156
        SET_DOUBLE_VAL(&pInfo->min, v);
2,687,653✔
4157
      }
4158

4159
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
8,323,816✔
4160
        SET_DOUBLE_VAL(&pInfo->max, v);
3,233,659✔
4161
      }
4162

4163
      numOfElems += 1;
8,323,816✔
4164
    }
4165
  }
4166

4167
_spread_over:
2,502,905✔
4168
  // data in the check operation are all null, not output
4169
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,502,905✔
4170
  if (numOfElems > 0) {
2,502,905✔
4171
    pInfo->hasResult = true;
2,462,506✔
4172
  }
4173

4174
  return TSDB_CODE_SUCCESS;
2,502,905✔
4175
}
4176

4177
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
1,035,739✔
4178
  pOutput->hasResult = pInput->hasResult;
1,035,739✔
4179
  if (pInput->max > pOutput->max) {
1,035,739✔
4180
    pOutput->max = pInput->max;
1,031,218✔
4181
  }
4182

4183
  if (pInput->min < pOutput->min) {
1,035,739✔
4184
    pOutput->min = pInput->min;
1,031,216✔
4185
  }
4186
}
1,035,739✔
4187

4188
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
1,031,785✔
4189
  SInputColumnInfoData* pInput = &pCtx->input;
1,031,785✔
4190
  SColumnInfoData*      pCol = pInput->pData[0];
1,031,785✔
4191

4192
  if (IS_NULL_TYPE(pCol->info.type)) {
1,031,785!
4193
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4194
    return TSDB_CODE_SUCCESS;
×
4195
  }
4196

4197
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,031,785!
4198
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4199
  }
4200

4201
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,031,785✔
4202

4203
  int32_t start = pInput->startRowIndex;
1,031,785✔
4204
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,067,755✔
4205
    if (colDataIsNull_s(pCol, i)) continue;
2,071,940!
4206
    char*        data = colDataGetData(pCol, i);
1,035,970!
4207
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
1,035,970✔
4208
    if (pInputInfo->hasResult) {
1,035,970✔
4209
      spreadTransferInfo(pInputInfo, pInfo);
1,035,738✔
4210
    }
4211
  }
4212

4213
  if (pInfo->hasResult) {
1,031,785✔
4214
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,031,619✔
4215
  }
4216

4217
  return TSDB_CODE_SUCCESS;
1,031,785✔
4218
}
4219

4220
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,439,594✔
4221
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,439,594✔
4222
  if (pInfo->hasResult == true) {
2,439,594✔
4223
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
2,399,620✔
4224
  } else {
4225
    GET_RES_INFO(pCtx)->isNullRes = 1;
39,974✔
4226
  }
4227
  return functionFinalize(pCtx, pBlock);
2,439,594✔
4228
}
4229

4230
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,035,768✔
4231
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,035,768✔
4232
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,035,768✔
4233
  int32_t              resultBytes = getSpreadInfoSize();
1,035,768✔
4234
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,035,768!
4235

4236
  if (NULL == res) {
1,035,768!
4237
    return terrno;
×
4238
  }
4239
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,035,768✔
4240
  varDataSetLen(res, resultBytes);
1,035,768✔
4241

4242
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,035,768✔
4243
  int32_t          code = TSDB_CODE_SUCCESS;
1,035,768✔
4244
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,035,768✔
4245
  if (NULL == pCol) {
1,035,768!
4246
    code = terrno;
×
4247
    goto _exit;
×
4248
  }
4249

4250
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,035,768✔
4251
  if (TSDB_CODE_SUCCESS != code) {
1,035,768!
4252
    goto _exit;
×
4253
  }
4254

4255
_exit:
1,035,768✔
4256
  taosMemoryFree(res);
1,035,768!
4257
  return code;
1,035,768✔
4258
}
4259

4260
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
4261
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
4262
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
4263

4264
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
4265
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
4266
  spreadTransferInfo(pSBuf, pDBuf);
1✔
4267
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
4268
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
4269
  return TSDB_CODE_SUCCESS;
1✔
4270
}
4271

4272
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4273

4274
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
96,988✔
4275
  pEnv->calcMemSize = sizeof(SElapsedInfo);
96,988✔
4276
  return true;
96,988✔
4277
}
4278

4279
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,906,386✔
4280
  if (pResultInfo->initialized) {
8,906,386!
4281
    return TSDB_CODE_SUCCESS;
×
4282
  }
4283
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,906,386!
4284
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4285
  }
4286

4287
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
8,906,394✔
4288
  pInfo->result = 0;
8,906,394✔
4289
  pInfo->min = TSKEY_MAX;
8,906,394✔
4290
  pInfo->max = 0;
8,906,394✔
4291

4292
  if (pCtx->numOfParams > 1) {
8,906,394✔
4293
    pInfo->timeUnit = pCtx->param[1].param.i;
8,888,659✔
4294
  } else {
4295
    pInfo->timeUnit = 1;
17,735✔
4296
  }
4297

4298
  return TSDB_CODE_SUCCESS;
8,906,394✔
4299
}
4300

4301
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
8,928,213✔
4302
  int32_t numOfElems = 0;
8,928,213✔
4303

4304
  // Only the pre-computing information loaded and actual data does not loaded
4305
  SInputColumnInfoData* pInput = &pCtx->input;
8,928,213✔
4306
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
8,928,213✔
4307

4308
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,928,213✔
4309

4310
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
8,928,213✔
4311
  if (numOfElems == 0) {
8,928,213✔
4312
    // for stream
4313
    if (pCtx->end.key != INT64_MIN) {
1,532✔
4314
      pInfo->max = pCtx->end.key + 1;
52✔
4315
    }
4316
    goto _elapsed_over;
1,532✔
4317
  }
4318

4319
  if (pInput->colDataSMAIsSet) {
8,926,681!
4320
    if (pInfo->min == TSKEY_MAX) {
×
4321
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4322
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4323
    } else {
4324
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4325
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4326
      } else {
4327
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4328
      }
4329
    }
4330
  } else {  // computing based on the true data block
4331
    if (0 == pInput->numOfRows) {
8,926,681!
4332
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4333
        if (pCtx->end.key != INT64_MIN) {
×
4334
          pInfo->min = pCtx->end.key;
×
4335
        }
4336
      } else {
4337
        if (pCtx->end.key != INT64_MIN) {
×
4338
          pInfo->max = pCtx->end.key + 1;
×
4339
        }
4340
      }
4341
      goto _elapsed_over;
×
4342
    }
4343

4344
    SColumnInfoData* pCol = pInput->pData[0];
8,926,681✔
4345

4346
    int32_t start = pInput->startRowIndex;
8,926,681✔
4347
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
8,926,681!
4348
    if (pCtx->order == TSDB_ORDER_DESC) {
8,926,681✔
4349
      if (pCtx->start.key == INT64_MIN) {
684!
4350
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
684✔
4351
      } else {
4352
        pInfo->max = pCtx->start.key + 1;
×
4353
      }
4354

4355
      if (pCtx->end.key == INT64_MIN) {
684!
4356
        pInfo->min =
684✔
4357
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
684✔
4358
      } else {
4359
        pInfo->min = pCtx->end.key;
×
4360
      }
4361
    } else {
4362
      if (pCtx->start.key == INT64_MIN) {
8,925,997✔
4363
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
4,182,344✔
4364
      } else {
4365
        pInfo->min = pCtx->start.key;
4,743,653✔
4366
      }
4367

4368
      if (pCtx->end.key == INT64_MIN) {
8,925,997✔
4369
        pInfo->max =
3,897,250✔
4370
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
3,897,250✔
4371
      } else {
4372
        pInfo->max = pCtx->end.key + 1;
5,028,747✔
4373
      }
4374
    }
4375
  }
4376

4377
_elapsed_over:
8,928,213✔
4378
  // data in the check operation are all null, not output
4379
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
8,928,213✔
4380

4381
  return TSDB_CODE_SUCCESS;
8,928,213✔
4382
}
4383

4384
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4385
  pOutput->timeUnit = pInput->timeUnit;
×
4386
  if (pOutput->min > pInput->min) {
×
4387
    pOutput->min = pInput->min;
×
4388
  }
4389

4390
  if (pOutput->max < pInput->max) {
×
4391
    pOutput->max = pInput->max;
×
4392
  }
4393
}
×
4394

4395
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4396
  SInputColumnInfoData* pInput = &pCtx->input;
×
4397
  SColumnInfoData*      pCol = pInput->pData[0];
×
4398
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4399
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4400
  }
4401

4402
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4403

4404
  int32_t start = pInput->startRowIndex;
×
4405

4406
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4407
    char*         data = colDataGetData(pCol, i);
×
4408
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4409
    elapsedTransferInfo(pInputInfo, pInfo);
×
4410
  }
4411

4412
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4413
  return TSDB_CODE_SUCCESS;
×
4414
}
4415

4416
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,902,023✔
4417
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,902,023✔
4418
  double        result = (double)pInfo->max - (double)pInfo->min;
8,902,023✔
4419
  result = (result >= 0) ? result : -result;
8,902,023✔
4420
  pInfo->result = result / pInfo->timeUnit;
8,902,023✔
4421
  return functionFinalize(pCtx, pBlock);
8,902,023✔
4422
}
4423

4424
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4425
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4426
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4427
  int32_t              resultBytes = getElapsedInfoSize();
×
4428
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4429

4430
  if (NULL == res) {
×
4431
    return terrno;
×
4432
  }
4433
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4434
  varDataSetLen(res, resultBytes);
×
4435

4436
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4437
  int32_t          code = TSDB_CODE_SUCCESS;
×
4438
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4439
  if (NULL == pCol) {
×
4440
    code = terrno;
×
4441
    goto _exit;
×
4442
  }
4443

4444
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4445
  if (TSDB_CODE_SUCCESS != code) {
×
4446
    goto _exit;
×
4447
  }
4448
_exit:
×
4449
  taosMemoryFree(res);
×
4450
  return code;
×
4451
}
4452

4453
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4454
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4455
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4456

4457
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4458
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4459

4460
  elapsedTransferInfo(pSBuf, pDBuf);
×
4461
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4462
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4463
  return TSDB_CODE_SUCCESS;
×
4464
}
4465

4466
int32_t getHistogramInfoSize() {
2,261,019✔
4467
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
2,261,019✔
4468
}
4469

4470
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
110,080✔
4471
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
110,080✔
4472
  return true;
110,080✔
4473
}
4474

4475
static int8_t getHistogramBinType(char* binTypeStr) {
13,730,492✔
4476
  int8_t binType;
4477
  if (strcasecmp(binTypeStr, "user_input") == 0) {
13,730,492✔
4478
    binType = USER_INPUT_BIN;
2,249✔
4479
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
13,728,243✔
4480
    binType = LINEAR_BIN;
3,472✔
4481
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
13,724,771!
4482
    binType = LOG_BIN;
13,725,049✔
4483
  } else {
4484
    binType = UNKNOWN_BIN;
×
4485
  }
4486

4487
  return binType;
13,730,492✔
4488
}
4489

4490
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
13,730,633✔
4491
  cJSON*  binDesc = cJSON_Parse(binDescStr);
13,730,633✔
4492
  int32_t numOfBins;
4493
  double* intervals;
4494
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
13,730,660✔
4495
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
13,728,371✔
4496
    int32_t startIndex;
4497
    if (numOfParams != 4) {
13,728,284!
4498
      cJSON_Delete(binDesc);
×
4499
      return TSDB_CODE_FAILED;
×
4500
    }
4501

4502
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
13,728,284✔
4503
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
13,728,437✔
4504
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
13,728,448✔
4505
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
13,727,338✔
4506
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
13,728,259✔
4507

4508
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
13,728,472!
4509
      cJSON_Delete(binDesc);
×
4510
      return TSDB_CODE_FAILED;
×
4511
    }
4512

4513
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
13,728,322!
4514
      cJSON_Delete(binDesc);
×
4515
      return TSDB_CODE_FAILED;
×
4516
    }
4517

4518
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
13,728,330!
4519
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
13,728,330!
4520
      cJSON_Delete(binDesc);
×
4521
      return TSDB_CODE_FAILED;
×
4522
    }
4523

4524
    int32_t counter = (int32_t)count->valueint;
13,728,330✔
4525
    if (infinity->valueint == false) {
13,728,330✔
4526
      startIndex = 0;
10,065,023✔
4527
      numOfBins = counter + 1;
10,065,023✔
4528
    } else {
4529
      startIndex = 1;
3,663,307✔
4530
      numOfBins = counter + 3;
3,663,307✔
4531
    }
4532

4533
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
13,728,330!
4534
    if (NULL == intervals) {
13,728,650!
4535
      cJSON_Delete(binDesc);
×
4536
      qError("histogram function out of memory");
×
4537
      return terrno;
×
4538
    }
4539
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
13,728,650!
4540
      // linear bin process
4541
      if (width->valuedouble == 0) {
3,473!
4542
        taosMemoryFree(intervals);
×
4543
        cJSON_Delete(binDesc);
×
4544
        return TSDB_CODE_FAILED;
×
4545
      }
4546
      for (int i = 0; i < counter + 1; ++i) {
22,005✔
4547
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
18,532✔
4548
        if (isinf(intervals[startIndex])) {
18,532!
4549
          taosMemoryFree(intervals);
×
4550
          cJSON_Delete(binDesc);
×
4551
          return TSDB_CODE_FAILED;
×
4552
        }
4553
        startIndex++;
18,532✔
4554
      }
4555
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
13,725,155!
4556
      // log bin process
4557
      if (start->valuedouble == 0) {
13,725,146!
4558
        taosMemoryFree(intervals);
×
4559
        cJSON_Delete(binDesc);
×
4560
        return TSDB_CODE_FAILED;
×
4561
      }
4562
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
13,725,146!
4563
        taosMemoryFree(intervals);
×
4564
        cJSON_Delete(binDesc);
×
4565
        return TSDB_CODE_FAILED;
×
4566
      }
4567
      for (int i = 0; i < counter + 1; ++i) {
96,065,617✔
4568
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
82,340,457✔
4569
        if (isinf(intervals[startIndex])) {
82,340,457!
4570
          taosMemoryFree(intervals);
×
4571
          cJSON_Delete(binDesc);
×
4572
          return TSDB_CODE_FAILED;
×
4573
        }
4574
        startIndex++;
82,340,457✔
4575
      }
4576
    } else {
4577
      taosMemoryFree(intervals);
×
4578
      cJSON_Delete(binDesc);
×
4579
      return TSDB_CODE_FAILED;
×
4580
    }
4581

4582
    if (infinity->valueint == true) {
13,728,633✔
4583
      intervals[0] = -INFINITY;
3,663,942✔
4584
      intervals[numOfBins - 1] = INFINITY;
3,663,942✔
4585
      // in case of desc bin orders, -inf/inf should be swapped
4586
      if (numOfBins < 4) {
3,663,942!
4587
        return TSDB_CODE_FAILED;
×
4588
      }
4589
      if (intervals[1] > intervals[numOfBins - 2]) {
3,663,942✔
4590
        TSWAP(intervals[0], intervals[numOfBins - 1]);
3,662,975✔
4591
      }
4592
    }
4593
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
2,250!
4594
    if (binType != USER_INPUT_BIN) {
2,250!
4595
      cJSON_Delete(binDesc);
×
4596
      return TSDB_CODE_FAILED;
×
4597
    }
4598
    numOfBins = cJSON_GetArraySize(binDesc);
2,250✔
4599
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
2,250!
4600
    if (NULL == intervals) {
2,250!
4601
      cJSON_Delete(binDesc);
×
4602
      qError("histogram function out of memory");
×
4603
      return terrno;
×
4604
    }
4605
    cJSON* bin = binDesc->child;
2,250✔
4606
    if (bin == NULL) {
2,250!
4607
      taosMemoryFree(intervals);
×
4608
      cJSON_Delete(binDesc);
×
4609
      return TSDB_CODE_FAILED;
×
4610
    }
4611
    int i = 0;
2,250✔
4612
    while (bin) {
8,942✔
4613
      intervals[i] = bin->valuedouble;
6,692✔
4614
      if (!cJSON_IsNumber(bin)) {
6,692!
4615
        taosMemoryFree(intervals);
×
4616
        cJSON_Delete(binDesc);
×
4617
        return TSDB_CODE_FAILED;
×
4618
      }
4619
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
6,692!
4620
        taosMemoryFree(intervals);
×
4621
        cJSON_Delete(binDesc);
×
4622
        return TSDB_CODE_FAILED;
×
4623
      }
4624
      bin = bin->next;
6,692✔
4625
      i++;
6,692✔
4626
    }
4627
  } else {
4628
    cJSON_Delete(binDesc);
×
4629
    return TSDB_CODE_FAILED;
×
4630
  }
4631

4632
  pInfo->numOfBins = numOfBins - 1;
13,730,883✔
4633
  pInfo->normalized = normalized;
13,730,883✔
4634
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
89,698,364✔
4635
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
75,967,481✔
4636
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
75,967,481✔
4637
    pInfo->bins[i].count = 0;
75,967,481✔
4638
  }
4639

4640
  taosMemoryFree(intervals);
13,730,883✔
4641
  cJSON_Delete(binDesc);
13,730,788✔
4642

4643
  return TSDB_CODE_SUCCESS;
13,730,606✔
4644
}
4645

4646
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
13,730,609✔
4647
  if (pResultInfo->initialized) {
13,730,609!
4648
    return TSDB_CODE_SUCCESS;
×
4649
  }
4650
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
13,730,609!
4651
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4652
  }
4653

4654
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
13,730,568✔
4655
  pInfo->numOfBins = 0;
13,730,568✔
4656
  pInfo->totalCount = 0;
13,730,568✔
4657
  pInfo->normalized = 0;
13,730,568✔
4658

4659
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
13,730,568!
4660
  if (binTypeStr == NULL) {
13,730,545!
4661
    return terrno;
×
4662
  }
4663
  int8_t binType = getHistogramBinType(binTypeStr);
13,730,545✔
4664
  taosMemoryFree(binTypeStr);
13,730,676!
4665

4666
  if (binType == UNKNOWN_BIN) {
13,730,507!
4667
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4668
  }
4669
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
13,730,507!
4670
  if (binDesc == NULL) {
13,730,620!
4671
    return terrno;
×
4672
  }
4673
  int64_t normalized = pCtx->param[3].param.i;
13,730,620✔
4674
  if (normalized != 0 && normalized != 1) {
13,730,620!
4675
    taosMemoryFree(binDesc);
×
4676
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4677
  }
4678
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
13,730,620✔
4679
  if (TSDB_CODE_SUCCESS != code) {
13,730,596!
4680
    taosMemoryFree(binDesc);
×
4681
    return code;
×
4682
  }
4683
  taosMemoryFree(binDesc);
13,730,596!
4684

4685
  return TSDB_CODE_SUCCESS;
13,730,703✔
4686
}
4687

4688
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
15,984,458✔
4689
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
15,984,458✔
4690

4691
  SInputColumnInfoData* pInput = &pCtx->input;
15,984,458✔
4692
  SColumnInfoData*      pCol = pInput->pData[0];
15,984,458✔
4693

4694
  int32_t type = pInput->pData[0]->info.type;
15,984,458✔
4695

4696
  int32_t start = pInput->startRowIndex;
15,984,458✔
4697
  int32_t numOfRows = pInput->numOfRows;
15,984,458✔
4698

4699
  int32_t numOfElems = 0;
15,984,458✔
4700
  for (int32_t i = start; i < numOfRows + start; ++i) {
58,349,449✔
4701
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
42,364,991✔
4702
      continue;
717,632✔
4703
    }
4704

4705
    numOfElems++;
41,647,359✔
4706

4707
    char*  data = colDataGetData(pCol, i);
41,647,359!
4708
    double v;
4709
    GET_TYPED_DATA(v, double, type, data);
41,647,359!
4710

4711
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
201,101,177✔
4712
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
170,179,946✔
4713
        pInfo->bins[k].count++;
10,726,128✔
4714
        pInfo->totalCount++;
10,726,128✔
4715
        break;
10,726,128✔
4716
      }
4717
    }
4718
  }
4719

4720
  if (!isPartial) {
15,984,458✔
4721
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
11,517,159✔
4722
  } else {
4723
    GET_RES_INFO(pCtx)->numOfRes = 1;
4,467,299✔
4724
  }
4725
  return TSDB_CODE_SUCCESS;
15,984,458✔
4726
}
4727

4728
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
11,516,928✔
4729

4730
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
4,467,908✔
4731

4732
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
2,224,279✔
4733
  pOutput->normalized = pInput->normalized;
2,224,279✔
4734
  pOutput->numOfBins = pInput->numOfBins;
2,224,279✔
4735
  pOutput->totalCount += pInput->totalCount;
2,224,279✔
4736
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
13,348,163✔
4737
    pOutput->bins[k].lower = pInput->bins[k].lower;
11,123,884✔
4738
    pOutput->bins[k].upper = pInput->bins[k].upper;
11,123,884✔
4739
    pOutput->bins[k].count += pInput->bins[k].count;
11,123,884✔
4740
  }
4741
}
2,224,279✔
4742

4743
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
2,224,279✔
4744
  SInputColumnInfoData* pInput = &pCtx->input;
2,224,279✔
4745
  SColumnInfoData*      pCol = pInput->pData[0];
2,224,279✔
4746
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
2,224,279!
4747
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4748
  }
4749

4750
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,224,279✔
4751

4752
  int32_t start = pInput->startRowIndex;
2,224,279✔
4753

4754
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
4,448,558✔
4755
    char*           data = colDataGetData(pCol, i);
2,224,279!
4756
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
2,224,279✔
4757
    histogramTransferInfo(pInputInfo, pInfo);
2,224,279✔
4758
  }
4759

4760
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
2,224,279!
4761
  return TSDB_CODE_SUCCESS;
2,224,279✔
4762
}
4763

4764
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
13,640,954✔
4765
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
13,640,954✔
4766
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
13,640,954✔
4767
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
13,640,954✔
4768
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
13,640,954✔
4769
  int32_t              code = TSDB_CODE_SUCCESS;
13,640,556✔
4770

4771
  int32_t currentRow = pBlock->info.rows;
13,640,556✔
4772
  if (NULL == pCol) {
13,640,556!
4773
    return TSDB_CODE_OUT_OF_RANGE;
×
4774
  }
4775

4776
  if (pInfo->normalized) {
13,640,556✔
4777
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
32,365✔
4778
      if (pInfo->totalCount != 0) {
26,331✔
4779
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
12,794✔
4780
      } else {
4781
        pInfo->bins[k].percentage = 0;
13,537✔
4782
      }
4783
    }
4784
  }
4785

4786
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
89,028,271✔
4787
    int32_t len;
4788
    char    buf[512] = {0};
75,439,364✔
4789
    if (!pInfo->normalized) {
75,439,364✔
4790
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
75,413,034✔
4791
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
4792
                      pInfo->bins[i].upper, pInfo->bins[i].count);
4793
    } else {
4794
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
26,330✔
4795
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
4796
                      pInfo->bins[i].percentage);
4797
    }
4798
    varDataSetLen(buf, len);
75,440,463✔
4799
    code = colDataSetVal(pCol, currentRow, buf, false);
75,440,463✔
4800
    if (TSDB_CODE_SUCCESS != code) {
75,387,715!
4801
      return code;
×
4802
    }
4803
    currentRow++;
75,387,715✔
4804
  }
4805

4806
  return code;
13,588,907✔
4807
}
4808

4809
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,254,854✔
4810
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,254,854✔
4811
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,254,854✔
4812
  int32_t              resultBytes = getHistogramInfoSize();
2,254,854✔
4813
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
2,254,854!
4814

4815
  if (NULL == res) {
2,254,854!
4816
    return terrno;
×
4817
  }
4818
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
2,254,854✔
4819
  varDataSetLen(res, resultBytes);
2,254,854✔
4820

4821
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
2,254,854✔
4822
  int32_t          code = TSDB_CODE_SUCCESS;
2,254,854✔
4823
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
2,254,854✔
4824
  if (NULL == pCol) {
2,254,854!
4825
    code = terrno;
×
4826
    goto _exit;
×
4827
  }
4828
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
2,254,854✔
4829

4830
_exit:
2,254,854✔
4831
  taosMemoryFree(res);
2,254,854!
4832
  return code;
2,254,854✔
4833
}
4834

4835
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4836
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4837
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4838

4839
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4840
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4841

4842
  histogramTransferInfo(pSBuf, pDBuf);
×
4843
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4844
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4845
  return TSDB_CODE_SUCCESS;
×
4846
}
4847

4848
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,327✔
4849

4850
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
66,296✔
4851
  pEnv->calcMemSize = sizeof(SHLLInfo);
66,296✔
4852
  return true;
66,296✔
4853
}
4854

4855
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
3,514,738✔
4856
  uint64_t hash = MurmurHash3_64(data, bytes);
3,514,738✔
4857
  int32_t  index = hash & HLL_BUCKET_MASK;
3,514,189✔
4858
  hash >>= HLL_BUCKET_BITS;
3,514,189✔
4859
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
3,514,189✔
4860
  uint64_t bit = 1;
3,514,189✔
4861
  uint8_t  count = 1;
3,514,189✔
4862
  while ((hash & bit) == 0) {
7,144,403✔
4863
    count++;
3,630,214✔
4864
    bit <<= 1;
3,630,214✔
4865
  }
4866
  *buk = index;
3,514,189✔
4867
  return count;
3,514,189✔
4868
}
4869

4870
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
246,856✔
4871
  uint64_t* word = (uint64_t*)buckets;
246,856✔
4872
  uint8_t*  bytes;
4873

4874
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
498,173,695✔
4875
    if (*word == 0) {
497,926,839✔
4876
      bucketHisto[0] += 8;
496,983,742✔
4877
    } else {
4878
      bytes = (uint8_t*)word;
943,097✔
4879
      bucketHisto[bytes[0]]++;
943,097✔
4880
      bucketHisto[bytes[1]]++;
943,097✔
4881
      bucketHisto[bytes[2]]++;
943,097✔
4882
      bucketHisto[bytes[3]]++;
943,097✔
4883
      bucketHisto[bytes[4]]++;
943,097✔
4884
      bucketHisto[bytes[5]]++;
943,097✔
4885
      bucketHisto[bytes[6]]++;
943,097✔
4886
      bucketHisto[bytes[7]]++;
943,097✔
4887
    }
4888
    word++;
497,926,839✔
4889
  }
4890
}
246,856✔
4891
static double hllTau(double x) {
246,864✔
4892
  if (x == 0. || x == 1.) return 0.;
246,864!
4893
  double zPrime;
4894
  double y = 1.0;
×
4895
  double z = 1 - x;
×
4896
  do {
4897
    x = sqrt(x);
×
4898
    zPrime = z;
×
4899
    y *= 0.5;
×
4900
    z -= pow(1 - x, 2) * y;
×
4901
  } while (zPrime != z);
×
4902
  return z / 3;
×
4903
}
4904

4905
static double hllSigma(double x) {
246,865✔
4906
  if (x == 1.0) return INFINITY;
246,865✔
4907
  double zPrime;
4908
  double y = 1;
213,171✔
4909
  double z = x;
213,171✔
4910
  do {
4911
    x *= x;
4,174,585✔
4912
    zPrime = z;
4,174,585✔
4913
    z += x * y;
4,174,585✔
4914
    y += y;
4,174,585✔
4915
  } while (zPrime != z);
4,174,585✔
4916
  return z;
213,171✔
4917
}
4918

4919
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
4920
// sketches"
4921
static uint64_t hllCountCnt(uint8_t* buckets) {
246,816✔
4922
  double  m = HLL_BUCKETS;
246,816✔
4923
  int32_t buckethisto[64] = {0};
246,816✔
4924
  hllBucketHisto(buckets, buckethisto);
246,816✔
4925

4926
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
246,863✔
4927
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
12,586,302✔
4928
    z += buckethisto[j];
12,339,436✔
4929
    z *= 0.5;
12,339,436✔
4930
  }
4931

4932
  z += m * hllSigma(buckethisto[0] / (double)m);
246,866✔
4933
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
246,866✔
4934

4935
  return (uint64_t)E;
246,866✔
4936
}
4937

4938
int32_t hllFunction(SqlFunctionCtx* pCtx) {
272,123✔
4939
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
272,123✔
4940

4941
  SInputColumnInfoData* pInput = &pCtx->input;
272,123✔
4942
  SColumnInfoData*      pCol = pInput->pData[0];
272,123✔
4943

4944
  int32_t type = pCol->info.type;
272,123✔
4945
  int32_t bytes = pCol->info.bytes;
272,123✔
4946

4947
  int32_t start = pInput->startRowIndex;
272,123✔
4948
  int32_t numOfRows = pInput->numOfRows;
272,123✔
4949

4950
  int32_t numOfElems = 0;
272,123✔
4951
  if (IS_NULL_TYPE(type)) {
272,123✔
4952
    goto _hll_over;
1,572✔
4953
  }
4954

4955
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,850,152✔
4956
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
6,275,840!
4957
      continue;
1,063,761✔
4958
    }
4959

4960
    numOfElems++;
3,517,532✔
4961

4962
    char* data = colDataGetData(pCol, i);
3,517,532!
4963
    if (IS_VAR_DATA_TYPE(type)) {
3,517,532!
4964
      bytes = varDataLen(data);
1,209,724✔
4965
      data = varDataVal(data);
1,209,724✔
4966
    }
4967

4968
    int32_t index = 0;
3,517,532✔
4969
    uint8_t count = hllCountNum(data, bytes, &index);
3,517,532✔
4970
    uint8_t oldcount = pInfo->buckets[index];
3,515,840✔
4971
    if (count > oldcount) {
3,515,840✔
4972
      pInfo->buckets[index] = count;
969,775✔
4973
    }
4974
  }
4975

4976
_hll_over:
268,859✔
4977
  pInfo->totalCount += numOfElems;
270,431✔
4978

4979
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
270,431✔
4980
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
939✔
4981
  } else {
4982
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
269,492✔
4983
  }
4984

4985
  return TSDB_CODE_SUCCESS;
270,431✔
4986
}
4987

4988
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
10,601✔
4989
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
169,821,481✔
4990
    if (pOutput->buckets[k] < pInput->buckets[k]) {
169,810,880✔
4991
      pOutput->buckets[k] = pInput->buckets[k];
155,978✔
4992
    }
4993
  }
4994
  pOutput->totalCount += pInput->totalCount;
10,601✔
4995
}
10,601✔
4996

4997
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
10,546✔
4998
  SInputColumnInfoData* pInput = &pCtx->input;
10,546✔
4999
  SColumnInfoData*      pCol = pInput->pData[0];
10,546✔
5000

5001
  if (IS_NULL_TYPE(pCol->info.type)) {
10,546!
5002
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
5003
    return TSDB_CODE_SUCCESS;
×
5004
  }
5005

5006
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
10,546!
5007
    return TSDB_CODE_SUCCESS;
×
5008
  }
5009

5010
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,546✔
5011

5012
  int32_t start = pInput->startRowIndex;
10,546✔
5013

5014
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
21,146✔
5015
    if (colDataIsNull_s(pCol, i)) continue;
21,200!
5016
    char*     data = colDataGetData(pCol, i);
10,600!
5017
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
10,600✔
5018
    hllTransferInfo(pInputInfo, pInfo);
10,600✔
5019
  }
5020

5021
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,546✔
5022
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
3✔
5023
  } else {
5024
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,543✔
5025
  }
5026

5027
  return TSDB_CODE_SUCCESS;
10,546✔
5028
}
5029

5030
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
246,818✔
5031
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
246,818✔
5032

5033
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
246,818✔
5034
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
246,818✔
5035
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
246,873✔
5036
    pInfo->numOfRes = 1;
32,776✔
5037
  }
5038

5039
  return functionFinalize(pCtx, pBlock);
246,873✔
5040
}
5041

5042
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,328✔
5043
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,328✔
5044
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,328✔
5045
  int32_t              resultBytes = getHLLInfoSize();
10,328✔
5046
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
10,328!
5047

5048
  if (NULL == res) {
10,327!
5049
    return terrno;
×
5050
  }
5051
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
10,327✔
5052
  varDataSetLen(res, resultBytes);
10,327✔
5053

5054
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
10,327✔
5055
  int32_t          code = TSDB_CODE_SUCCESS;
10,327✔
5056
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
10,327✔
5057
  if (NULL == pCol) {
10,329!
5058
    code = terrno;
×
5059
    goto _exit;
×
5060
  }
5061

5062
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
10,329✔
5063

5064
_exit:
10,328✔
5065
  taosMemoryFree(res);
10,328!
5066
  return code;
10,329✔
5067
}
5068

5069
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
5070
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
5071
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
5072

5073
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
5074
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
5075

5076
  hllTransferInfo(pSBuf, pDBuf);
1✔
5077
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
5078
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
5079
  return TSDB_CODE_SUCCESS;
1✔
5080
}
5081

5082
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,336✔
5083
  pEnv->calcMemSize = sizeof(SStateInfo);
22,336✔
5084
  return true;
22,336✔
5085
}
5086

5087
static int8_t getStateOpType(char* opStr) {
142,514✔
5088
  int8_t opType;
5089
  if (strncasecmp(opStr, "LT", 2) == 0) {
142,514✔
5090
    opType = STATE_OPER_LT;
1,923✔
5091
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
140,591✔
5092
    opType = STATE_OPER_GT;
2,358✔
5093
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
138,233✔
5094
    opType = STATE_OPER_LE;
984✔
5095
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
137,249✔
5096
    opType = STATE_OPER_GE;
30,629✔
5097
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
106,620✔
5098
    opType = STATE_OPER_NE;
79,681✔
5099
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
26,939!
5100
    opType = STATE_OPER_EQ;
26,939✔
5101
  } else {
5102
    opType = STATE_OPER_INVALID;
×
5103
  }
5104

5105
  return opType;
142,514✔
5106
}
5107

5108
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
35,108,865✔
5109
  char* data = colDataGetData(pCol, index);
35,108,865!
5110
  switch (pCol->info.type) {
35,108,865!
5111
    case TSDB_DATA_TYPE_TINYINT: {
23,712✔
5112
      int8_t v = *(int8_t*)data;
23,712✔
5113
      STATE_COMP(op, v, param);
23,712!
5114
      break;
×
5115
    }
5116
    case TSDB_DATA_TYPE_UTINYINT: {
5,760✔
5117
      uint8_t v = *(uint8_t*)data;
5,760✔
5118
      STATE_COMP(op, v, param);
5,760!
5119
      break;
×
5120
    }
5121
    case TSDB_DATA_TYPE_SMALLINT: {
137,624✔
5122
      int16_t v = *(int16_t*)data;
137,624✔
5123
      STATE_COMP(op, v, param);
137,624!
5124
      break;
×
5125
    }
5126
    case TSDB_DATA_TYPE_USMALLINT: {
5,760✔
5127
      uint16_t v = *(uint16_t*)data;
5,760✔
5128
      STATE_COMP(op, v, param);
5,760!
5129
      break;
×
5130
    }
5131
    case TSDB_DATA_TYPE_INT: {
108,970✔
5132
      int32_t v = *(int32_t*)data;
108,970✔
5133
      STATE_COMP(op, v, param);
108,970!
5134
      break;
×
5135
    }
5136
    case TSDB_DATA_TYPE_UINT: {
5,760✔
5137
      uint32_t v = *(uint32_t*)data;
5,760✔
5138
      STATE_COMP(op, v, param);
5,760!
5139
      break;
×
5140
    }
5141
    case TSDB_DATA_TYPE_BIGINT: {
34,499,174✔
5142
      int64_t v = *(int64_t*)data;
34,499,174✔
5143
      STATE_COMP(op, v, param);
34,499,174!
5144
      break;
×
5145
    }
5146
    case TSDB_DATA_TYPE_UBIGINT: {
5,760✔
5147
      uint64_t v = *(uint64_t*)data;
5,760✔
5148
      STATE_COMP(op, v, param);
5,760!
5149
      break;
×
5150
    }
5151
    case TSDB_DATA_TYPE_FLOAT: {
96,124✔
5152
      float v = *(float*)data;
96,124✔
5153
      STATE_COMP(op, v, param);
96,124!
5154
      break;
×
5155
    }
5156
    case TSDB_DATA_TYPE_DOUBLE: {
223,926✔
5157
      double v = *(double*)data;
223,926✔
5158
      STATE_COMP(op, v, param);
223,926!
5159
      break;
37✔
5160
    }
5161
    default: {
×
5162
      return false;
×
5163
    }
5164
  }
5165
  return false;
37✔
5166
}
5167

5168
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
31,967✔
5169
  int32_t              code = TSDB_CODE_SUCCESS;
31,967✔
5170
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
31,967✔
5171
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,967✔
5172

5173
  SInputColumnInfoData* pInput = &pCtx->input;
31,967✔
5174
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
31,967✔
5175

5176
  SColumnInfoData* pInputCol = pInput->pData[0];
31,967✔
5177

5178
  int32_t          numOfElems = 0;
31,967✔
5179
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
31,967✔
5180

5181
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
31,967✔
5182
  if (STATE_OPER_INVALID == op) {
31,967!
5183
    return 0;
×
5184
  }
5185

5186
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
7,452,642✔
5187
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
7,420,672!
5188
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5189
    } else {
5190
      pInfo->prevTs = tsList[i];
7,420,672✔
5191
    }
5192

5193
    pInfo->isPrevTsSet = true;
7,420,672✔
5194
    numOfElems++;
7,420,672✔
5195

5196
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
7,420,672✔
5197
      colDataSetNULL(pOutput, i);
183,581!
5198
      // handle selectivity
5199
      if (pCtx->subsidiaries.num > 0) {
183,581✔
5200
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
44✔
5201
        if (TSDB_CODE_SUCCESS != code) {
44!
5202
          return code;
×
5203
        }
5204
      }
5205
      continue;
183,581✔
5206
    }
5207

5208
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
7,237,091✔
5209

5210
    int64_t output = -1;
7,236,961✔
5211
    if (ret) {
7,236,961✔
5212
      output = ++pInfo->count;
3,553,128✔
5213
    } else {
5214
      pInfo->count = 0;
3,683,833✔
5215
    }
5216
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
7,236,961✔
5217
    if (TSDB_CODE_SUCCESS != code) {
7,237,094!
5218
      return code;
×
5219
    }
5220

5221
    // handle selectivity
5222
    if (pCtx->subsidiaries.num > 0) {
7,237,094✔
5223
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,616,116✔
5224
      if (TSDB_CODE_SUCCESS != code) {
3,616,116!
5225
        return code;
×
5226
      }
5227
    }
5228
  }
5229

5230
  pResInfo->numOfRes = numOfElems;
31,970✔
5231
  return TSDB_CODE_SUCCESS;
31,970✔
5232
}
5233

5234
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
110,548✔
5235
  int32_t              code = TSDB_CODE_SUCCESS;
110,548✔
5236
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
110,548✔
5237
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
110,548✔
5238

5239
  SInputColumnInfoData* pInput = &pCtx->input;
110,548✔
5240
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
110,548✔
5241

5242
  SColumnInfoData* pInputCol = pInput->pData[0];
110,548✔
5243

5244
  int32_t          numOfElems = 0;
110,548✔
5245
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
110,548✔
5246

5247
  // TODO: process timeUnit for different db precisions
5248
  int32_t timeUnit = 1;
110,548✔
5249
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
110,548✔
5250
    timeUnit = pCtx->param[3].param.i;
108,588✔
5251
  }
5252

5253
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
110,548✔
5254
  if (STATE_OPER_INVALID == op) {
110,548!
5255
    return TSDB_CODE_INVALID_PARA;
×
5256
  }
5257

5258
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
28,083,058✔
5259
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
27,972,510!
5260
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5261
    } else {
5262
      pInfo->prevTs = tsList[i];
27,972,510✔
5263
    }
5264

5265
    pInfo->isPrevTsSet = true;
27,972,510✔
5266
    numOfElems++;
27,972,510✔
5267

5268
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
27,972,510✔
5269
      colDataSetNULL(pOutput, i);
99,440!
5270
      // handle selectivity
5271
      if (pCtx->subsidiaries.num > 0) {
99,440✔
5272
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
48✔
5273
        if (TSDB_CODE_SUCCESS != code) {
48!
5274
          return code;
×
5275
        }
5276
      }
5277
      continue;
99,440✔
5278
    }
5279

5280
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
27,873,070✔
5281
    int64_t output = -1;
27,873,070✔
5282
    if (ret) {
27,873,070✔
5283
      if (pInfo->durationStart == 0) {
22,580,749✔
5284
        output = 0;
37,549✔
5285
        pInfo->durationStart = tsList[i];
37,549✔
5286
      } else {
5287
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
22,543,200✔
5288
      }
5289
    } else {
5290
      pInfo->durationStart = 0;
5,292,321✔
5291
    }
5292
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
27,873,070✔
5293
    if (TSDB_CODE_SUCCESS != code) {
27,873,070!
5294
      return code;
×
5295
    }
5296

5297
    // handle selectivity
5298
    if (pCtx->subsidiaries.num > 0) {
27,873,070✔
5299
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
16,333,680✔
5300
      if (TSDB_CODE_SUCCESS != code) {
16,333,680!
5301
        return code;
×
5302
      }
5303
    }
5304
  }
5305

5306
  pResInfo->numOfRes = numOfElems;
110,548✔
5307
  return TSDB_CODE_SUCCESS;
110,548✔
5308
}
5309

5310
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
15,712✔
5311
  pEnv->calcMemSize = sizeof(SSumRes);
15,712✔
5312
  return true;
15,712✔
5313
}
5314

5315
int32_t csumFunction(SqlFunctionCtx* pCtx) {
23,734✔
5316
  int32_t              code = TSDB_CODE_SUCCESS;
23,734✔
5317
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
23,734✔
5318
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
23,734✔
5319

5320
  SInputColumnInfoData* pInput = &pCtx->input;
23,734✔
5321
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
23,734✔
5322

5323
  SColumnInfoData* pInputCol = pInput->pData[0];
23,734✔
5324
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
23,734✔
5325

5326
  int32_t numOfElems = 0;
23,734✔
5327
  int32_t type = pInputCol->info.type;
23,734✔
5328
  int32_t startOffset = pCtx->offset;
23,734✔
5329
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4,018,997✔
5330
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,994,781✔
5331
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5332
    } else {
5333
      pSumRes->prevTs = tsList[i];
3,994,763✔
5334
    }
5335
    pSumRes->isPrevTsSet = true;
3,994,763✔
5336

5337
    int32_t pos = startOffset + numOfElems;
3,994,763✔
5338
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,994,763✔
5339
      // colDataSetNULL(pOutput, i);
5340
      continue;
426,426✔
5341
    }
5342

5343
    char* data = colDataGetData(pInputCol, i);
3,568,337!
5344
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,264,901✔
5345
      int64_t v;
5346
      GET_TYPED_DATA(v, int64_t, type, data);
696,064!
5347
      pSumRes->isum += v;
696,064✔
5348
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
696,064✔
5349
      if (TSDB_CODE_SUCCESS != code) {
696,564!
5350
        return code;
×
5351
      }
5352
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,872,953!
5353
      uint64_t v;
5354
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5355
      pSumRes->usum += v;
680✔
5356
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5357
      if (TSDB_CODE_SUCCESS != code) {
680!
5358
        return code;
×
5359
      }
5360
    } else if (IS_FLOAT_TYPE(type)) {
2,871,593✔
5361
      double v;
5362
      GET_TYPED_DATA(v, double, type, data);
2,871,322!
5363
      pSumRes->dsum += v;
2,871,322✔
5364
      // check for overflow
5365
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
2,871,322!
5366
        colDataSetNULL(pOutput, pos);
8!
5367
      } else {
5368
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
2,871,314✔
5369
        if (TSDB_CODE_SUCCESS != code) {
2,871,314!
5370
          return code;
×
5371
        }
5372
      }
5373
    }
5374

5375
    // handle selectivity
5376
    if (pCtx->subsidiaries.num > 0) {
3,568,837✔
5377
      code = appendSelectivityValue(pCtx, i, pos);
2,015,388✔
5378
      if (TSDB_CODE_SUCCESS != code) {
2,015,388!
5379
        return code;
×
5380
      }
5381
    }
5382

5383
    numOfElems++;
3,568,837✔
5384
  }
5385

5386
  pResInfo->numOfRes = numOfElems;
24,216✔
5387
  return TSDB_CODE_SUCCESS;
24,216✔
5388
}
5389

5390
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
13,595✔
5391
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
13,595✔
5392
  return true;
13,595✔
5393
}
5394

5395
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
253,041✔
5396
  if (pResultInfo->initialized) {
253,041✔
5397
    return TSDB_CODE_SUCCESS;
238,753✔
5398
  }
5399
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,288!
5400
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5401
  }
5402

5403
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
14,287✔
5404
  pInfo->pos = 0;
14,287✔
5405
  pInfo->sum = 0;
14,287✔
5406
  pInfo->prevTs = -1;
14,287✔
5407
  pInfo->isPrevTsSet = false;
14,287✔
5408
  pInfo->numOfPoints = pCtx->param[1].param.i;
14,287✔
5409
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
14,287!
5410
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5411
  }
5412
  pInfo->pointsMeet = false;
14,288✔
5413

5414
  return TSDB_CODE_SUCCESS;
14,288✔
5415
}
5416

5417
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
239,440✔
5418
  int32_t              code = TSDB_CODE_SUCCESS;
239,440✔
5419
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
239,440✔
5420
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
239,440✔
5421

5422
  SInputColumnInfoData* pInput = &pCtx->input;
239,440✔
5423
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
239,440✔
5424

5425
  SColumnInfoData* pInputCol = pInput->pData[0];
239,440✔
5426
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
239,440✔
5427
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
239,440✔
5428

5429
  int32_t numOfElems = 0;
239,440✔
5430
  int32_t type = pInputCol->info.type;
239,440✔
5431
  int32_t startOffset = pCtx->offset;
239,440✔
5432
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
59,140,751✔
5433
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
58,901,311!
5434
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5435
    } else {
5436
      pInfo->prevTs = tsList[i];
58,901,311✔
5437
    }
5438
    pInfo->isPrevTsSet = true;
58,901,311✔
5439

5440
    int32_t pos = startOffset + numOfElems;
58,901,311✔
5441
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
58,901,311✔
5442
      // colDataSetNULL(pOutput, i);
5443
      continue;
383,018✔
5444
    }
5445

5446
    char*  data = colDataGetData(pInputCol, i);
58,518,293!
5447
    double v;
5448
    GET_TYPED_DATA(v, double, type, data);
58,518,293!
5449

5450
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
58,518,293✔
5451
      pInfo->points[pInfo->pos] = v;
3,682,419✔
5452
      pInfo->sum += v;
3,682,419✔
5453
    } else {
5454
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
54,835,874!
5455
        pInfo->sum += v;
11,402✔
5456
        pInfo->pointsMeet = true;
11,402✔
5457
      } else {
5458
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
54,824,472✔
5459
      }
5460

5461
      pInfo->points[pInfo->pos] = v;
54,835,874✔
5462
      double result = pInfo->sum / pInfo->numOfPoints;
54,835,874✔
5463
      // check for overflow
5464
      if (isinf(result) || isnan(result)) {
54,835,874!
5465
        colDataSetNULL(pOutput, pos);
1!
5466
      } else {
5467
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
54,835,873✔
5468
        if (TSDB_CODE_SUCCESS != code) {
54,835,873!
5469
          return code;
×
5470
        }
5471
      }
5472

5473
      // handle selectivity
5474
      if (pCtx->subsidiaries.num > 0) {
54,835,874✔
5475
        code = appendSelectivityValue(pCtx, i, pos);
33,883,914✔
5476
        if (TSDB_CODE_SUCCESS != code) {
33,883,914!
5477
          return code;
×
5478
        }
5479
      }
5480

5481
      numOfElems++;
54,835,874✔
5482
    }
5483

5484
    pInfo->pos++;
58,518,293✔
5485
    if (pInfo->pos == pInfo->numOfPoints) {
58,518,293✔
5486
      pInfo->pos = 0;
295,638✔
5487
    }
5488
  }
5489

5490
  pResInfo->numOfRes = numOfElems;
239,440✔
5491
  return TSDB_CODE_SUCCESS;
239,440✔
5492
}
5493

5494
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
28,836,472✔
5495
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
28,836,472✔
5496
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
28,836,472✔
5497

5498
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
28,836,472✔
5499
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
28,836,472✔
5500

5501
  return pInfo;
28,836,472✔
5502
}
5503

5504
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
30,652✔
5505
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
30,652✔
5506
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
30,656✔
5507
  int32_t      numOfSamples = pVal->datum.i;
30,660✔
5508
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
30,660✔
5509
  return true;
30,660✔
5510
}
5511

5512
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
12,756,642✔
5513
  if (pResultInfo->initialized) {
12,756,642!
5514
    return TSDB_CODE_SUCCESS;
×
5515
  }
5516
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
12,756,642!
5517
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5518
  }
5519

5520
  taosSeedRand(taosSafeRand());
12,756,642✔
5521

5522
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
12,756,645✔
5523
  pInfo->samples = pCtx->param[1].param.i;
12,756,645✔
5524
  pInfo->totalPoints = 0;
12,756,645✔
5525
  pInfo->numSampled = 0;
12,756,645✔
5526
  pInfo->colType = pCtx->resDataInfo.type;
12,756,645✔
5527
  pInfo->colBytes = pCtx->resDataInfo.bytes;
12,756,645✔
5528
  pInfo->nullTuplePos.pageId = -1;
12,756,645✔
5529
  pInfo->nullTupleSaved = false;
12,756,645✔
5530
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
12,756,645✔
5531
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
12,756,645✔
5532

5533
  return TSDB_CODE_SUCCESS;
12,756,645✔
5534
}
5535

5536
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
37,891,525✔
5537
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
37,891,525✔
5538
}
37,890,876✔
5539

5540
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
39,542,069✔
5541
  pInfo->totalPoints++;
39,542,069✔
5542
  if (pInfo->numSampled < pInfo->samples) {
39,542,069✔
5543
    sampleAssignResult(pInfo, data, pInfo->numSampled);
35,421,222✔
5544
    if (pCtx->subsidiaries.num > 0) {
35,420,886✔
5545
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,220,662✔
5546
      if (code != TSDB_CODE_SUCCESS) {
1,220,999!
5547
        return code;
×
5548
      }
5549
    }
5550
    pInfo->numSampled++;
35,421,223✔
5551
  } else {
5552
    int32_t j = taosRand() % (pInfo->totalPoints);
4,120,847✔
5553
    if (j < pInfo->samples) {
4,123,667✔
5554
      sampleAssignResult(pInfo, data, j);
2,471,426✔
5555
      if (pCtx->subsidiaries.num > 0) {
2,471,356✔
5556
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
654,479✔
5557
        if (code != TSDB_CODE_SUCCESS) {
652,139!
5558
          return code;
×
5559
        }
5560
      }
5561
    }
5562
  }
5563

5564
  return TSDB_CODE_SUCCESS;
39,542,480✔
5565
}
5566

5567
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
16,432,735✔
5568
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,432,735✔
5569
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
16,432,735✔
5570

5571
  SInputColumnInfoData* pInput = &pCtx->input;
16,432,729✔
5572

5573
  SColumnInfoData* pInputCol = pInput->pData[0];
16,432,729✔
5574
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
56,418,980✔
5575
    if (colDataIsNull_s(pInputCol, i)) {
79,971,202✔
5576
      continue;
444,057✔
5577
    }
5578

5579
    char*   data = colDataGetData(pInputCol, i);
39,541,544!
5580
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
39,541,544✔
5581
    if (code != TSDB_CODE_SUCCESS) {
39,542,194!
5582
      return code;
×
5583
    }
5584
  }
5585

5586
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
16,433,379✔
5587
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
33✔
5588
    if (code != TSDB_CODE_SUCCESS) {
33!
5589
      return code;
×
5590
    }
5591
    pInfo->nullTupleSaved = true;
33✔
5592
  }
5593

5594
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
16,433,379✔
5595
  return TSDB_CODE_SUCCESS;
16,433,379✔
5596
}
5597

5598
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
12,403,743✔
5599
  int32_t              code = TSDB_CODE_SUCCESS;
12,403,743✔
5600
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
12,403,743✔
5601

5602
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
12,403,743✔
5603
  pEntryInfo->complete = true;
12,403,744✔
5604

5605
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
12,403,744✔
5606
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
12,403,744✔
5607
  if (NULL == pCol) {
12,403,742!
5608
    return TSDB_CODE_OUT_OF_RANGE;
×
5609
  }
5610

5611
  int32_t currentRow = pBlock->info.rows;
12,403,742✔
5612
  if (pInfo->numSampled == 0) {
12,403,742✔
5613
    colDataSetNULL(pCol, currentRow);
2,772✔
5614
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,772✔
5615
    return code;
2,772✔
5616
  }
5617
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
45,922,600✔
5618
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
33,522,120✔
5619
    if (TSDB_CODE_SUCCESS != code) {
33,521,588!
5620
      return code;
×
5621
    }
5622
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
33,521,588✔
5623
    if (TSDB_CODE_SUCCESS != code) {
33,521,630!
5624
      return code;
×
5625
    }
5626
  }
5627

5628
  return code;
12,400,480✔
5629
}
5630

5631
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5632
#if 0
5633
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
5634
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
5635
  int32_t      numOfPoints = pVal->datum.i;
5636
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
5637
#endif
5638
  return true;
×
5639
}
5640

5641
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
5642
#if 0
5643
  if (!functionSetup(pCtx, pResultInfo)) {
5644
    return false;
5645
  }
5646

5647
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5648
  pInfo->numAdded = 0;
5649
  pInfo->numOfPoints = pCtx->param[1].param.i;
5650
  if (pCtx->numOfParams == 4) {
5651
    pInfo->offset = pCtx->param[2].param.i;
5652
  } else {
5653
    pInfo->offset = 0;
5654
  }
5655
  pInfo->colType = pCtx->resDataInfo.type;
5656
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5657
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
5658
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
5659
    return false;
5660
  }
5661

5662
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
5663
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
5664

5665
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
5666
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5667
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
5668
    pInfo->pItems[i]->isNull = false;
5669
  }
5670
#endif
5671

5672
  return TSDB_CODE_SUCCESS;
×
5673
}
5674

5675
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
5676
#if 0
5677
  pItem->timestamp = ts;
5678
  if (isNull) {
5679
    pItem->isNull = true;
5680
  } else {
5681
    pItem->isNull = false;
5682
    memcpy(pItem->data, data, colBytes);
5683
  }
5684
#endif
5685
}
×
5686

5687
#if 0
5688
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
5689
  STailItem* d1 = *(STailItem**)p1;
5690
  STailItem* d2 = *(STailItem**)p2;
5691
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
5692
}
5693

5694
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5695
  STailItem** pList = pInfo->pItems;
5696
  if (pInfo->numAdded < pInfo->numOfPoints) {
5697
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
5698
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
5699
    pInfo->numAdded++;
5700
  } else if (pList[0]->timestamp < ts) {
5701
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
5702
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
5703
  }
5704
}
5705
#endif
5706

5707
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
5708
#if 0
5709
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5710
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5711

5712
  SInputColumnInfoData* pInput = &pCtx->input;
5713
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5714

5715
  SColumnInfoData* pInputCol = pInput->pData[0];
5716
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5717

5718
  int32_t startOffset = pCtx->offset;
5719
  if (pInfo->offset >= pInput->numOfRows) {
5720
    return 0;
5721
  } else {
5722
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
5723
  }
5724
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
5725
    char* data = colDataGetData(pInputCol, i);
5726
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5727
  }
5728

5729
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
5730

5731
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5732
    int32_t    pos = startOffset + i;
5733
    STailItem* pItem = pInfo->pItems[i];
5734
    if (pItem->isNull) {
5735
      colDataSetNULL(pOutput, pos);
5736
    } else {
5737
      colDataSetVal(pOutput, pos, pItem->data, false);
5738
    }
5739
  }
5740

5741
  return pInfo->numOfPoints;
5742
#endif
5743
  return 0;
×
5744
}
5745

5746
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
5747
#if 0
5748
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
5749
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
5750
  pEntryInfo->complete = true;
5751

5752
  int32_t type = pCtx->input.pData[0]->info.type;
5753
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
5754

5755
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5756

5757
  // todo assign the tag value and the corresponding row data
5758
  int32_t currentRow = pBlock->info.rows;
5759
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
5760
    STailItem* pItem = pInfo->pItems[i];
5761
    colDataSetVal(pCol, currentRow, pItem->data, false);
5762
    currentRow += 1;
5763
  }
5764

5765
  return pEntryInfo->numOfRes;
5766
#endif
5767
  return 0;
×
5768
}
5769

5770
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5771
#if 0
5772
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
5773
#endif
5774
  return true;
×
5775
}
5776

5777
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
5778
#if 0
5779
  if (!functionSetup(pCtx, pResInfo)) {
5780
    return false;
5781
  }
5782

5783
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5784
  pInfo->numOfPoints = 0;
5785
  pInfo->colType = pCtx->resDataInfo.type;
5786
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5787
  if (pInfo->pHash != NULL) {
5788
    taosHashClear(pInfo->pHash);
5789
  } else {
5790
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
5791
  }
5792
#endif
5793
  return TSDB_CODE_SUCCESS;
×
5794
}
5795

5796
#if 0
5797
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5798
  // handle null elements
5799
  if (isNull == true) {
5800
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5801
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5802
    if (pInfo->hasNull == false && pItem->isNull == false) {
5803
      pItem->timestamp = ts;
5804
      pItem->isNull = true;
5805
      pInfo->numOfPoints++;
5806
      pInfo->hasNull = true;
5807
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
5808
      pItem->timestamp = ts;
5809
    }
5810
    return;
5811
  }
5812

5813
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
5814
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
5815
  if (pHashItem == NULL) {
5816
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5817
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5818
    pItem->timestamp = ts;
5819
    memcpy(pItem->data, data, pInfo->colBytes);
5820

5821
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
5822
    pInfo->numOfPoints++;
5823
  } else if (pHashItem->timestamp > ts) {
5824
    pHashItem->timestamp = ts;
5825
  }
5826
}
5827
#endif
5828

5829
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
5830
#if 0
5831
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5832
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5833

5834
  SInputColumnInfoData* pInput = &pCtx->input;
5835
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5836

5837
  SColumnInfoData* pInputCol = pInput->pData[0];
5838
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
5839
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5840

5841
  int32_t startOffset = pCtx->offset;
5842
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5843
    char* data = colDataGetData(pInputCol, i);
5844
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5845

5846
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
5847
      taosHashCleanup(pInfo->pHash);
5848
      return 0;
5849
    }
5850
  }
5851

5852
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5853
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
5854
    if (pItem->isNull == true) {
5855
      colDataSetNULL(pOutput, i);
5856
    } else {
5857
      colDataSetVal(pOutput, i, pItem->data, false);
5858
    }
5859
    if (pTsOutput != NULL) {
5860
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
5861
    }
5862
  }
5863

5864
  return pInfo->numOfPoints;
5865
#endif
5866
  return 0;
×
5867
}
5868

5869
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
24,703✔
5870
  pEnv->calcMemSize = sizeof(SModeInfo);
24,703✔
5871
  return true;
24,703✔
5872
}
5873

5874
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
21,614✔
5875
  if (pResInfo->initialized) {
21,614!
5876
    return TSDB_CODE_SUCCESS;
×
5877
  }
5878
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
21,614!
5879
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5880
  }
5881

5882
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
21,614✔
5883
  pInfo->colType = pCtx->resDataInfo.type;
21,614✔
5884
  pInfo->colBytes = pCtx->resDataInfo.bytes;
21,614✔
5885
  if (pInfo->pHash != NULL) {
21,614!
5886
    taosHashClear(pInfo->pHash);
×
5887
  } else {
5888
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
21,614✔
5889
    if (NULL == pInfo->pHash) {
21,614!
5890
      return terrno;
×
5891
    }
5892
  }
5893
  pInfo->nullTupleSaved = false;
21,614✔
5894
  pInfo->nullTuplePos.pageId = -1;
21,614✔
5895

5896
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
21,614!
5897
  if (NULL == pInfo->buf) {
21,614!
5898
    taosHashCleanup(pInfo->pHash);
×
5899
    pInfo->pHash = NULL;
×
5900
    return terrno;
×
5901
  }
5902
  pCtx->needCleanup = true;
21,614✔
5903
  return TSDB_CODE_SUCCESS;
21,614✔
5904
}
5905

5906
static void modeFunctionCleanup(SModeInfo* pInfo) {
21,614✔
5907
  taosHashCleanup(pInfo->pHash);
21,614✔
5908
  pInfo->pHash = NULL;
21,614✔
5909
  taosMemoryFreeClear(pInfo->buf);
21,614!
5910
}
21,614✔
5911

5912
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5913
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5914
    return;
×
5915
  }
5916
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5917
}
5918

5919
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
42,377,106✔
5920
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
42,377,106!
5921
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
12,655,546!
5922
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
×
5923
    } else {
5924
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
12,655,546✔
5925
    }
5926
  } else {
5927
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
29,721,560✔
5928
  }
5929

5930
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
42,377,106✔
5931
}
5932

5933
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
49,735,281✔
5934
  int32_t code = TSDB_CODE_SUCCESS;
49,735,281✔
5935
  int32_t hashKeyBytes;
5936
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
49,735,281✔
5937
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
12,655,979!
5938
      hashKeyBytes = getJsonValueLen(data);
×
5939
    } else {
5940
      hashKeyBytes = varDataTLen(data);
12,655,979✔
5941
    }
5942
  } else {
5943
    hashKeyBytes = pInfo->colBytes;
37,079,302✔
5944
  }
5945

5946
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
49,735,217✔
5947
  if (pHashItem == NULL) {
49,735,174✔
5948
    int32_t   size = sizeof(SModeItem);
42,377,267✔
5949
    SModeItem item = {0};
42,377,267✔
5950

5951
    item.count += 1;
42,377,267✔
5952
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
42,377,267✔
5953
    if (code != TSDB_CODE_SUCCESS) {
42,375,632!
5954
      return code;
×
5955
    }
5956

5957
    if (pCtx->subsidiaries.num > 0) {
42,375,632✔
5958
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
28,589,113✔
5959
      if (code != TSDB_CODE_SUCCESS) {
28,589,113!
5960
        return code;
×
5961
      }
5962
    }
5963

5964
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
42,375,632✔
5965
    if (code != TSDB_CODE_SUCCESS) {
42,377,733!
5966
      return code;
×
5967
    }
5968
  } else {
5969
    pHashItem->count += 1;
7,357,907✔
5970
    if (pCtx->subsidiaries.num > 0) {
7,357,907✔
5971
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
2,986,513✔
5972
      if (code != TSDB_CODE_SUCCESS) {
2,986,513!
5973
        return code;
×
5974
      }
5975
    }
5976
  }
5977

5978
  return code;
49,735,640✔
5979
}
5980

5981
int32_t modeFunction(SqlFunctionCtx* pCtx) {
23,366✔
5982
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
23,366✔
5983
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
23,366✔
5984

5985
  SInputColumnInfoData* pInput = &pCtx->input;
23,366✔
5986

5987
  SColumnInfoData* pInputCol = pInput->pData[0];
23,366✔
5988
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
23,366✔
5989

5990
  int32_t numOfElems = 0;
23,366✔
5991
  int32_t startOffset = pCtx->offset;
23,366✔
5992
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
50,108,832✔
5993
    if (colDataIsNull_s(pInputCol, i)) {
100,171,016✔
5994
      continue;
350,393✔
5995
    }
5996
    numOfElems++;
49,735,115✔
5997

5998
    char*   data = colDataGetData(pInputCol, i);
49,735,115!
5999
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
49,735,115✔
6000
    if (code != TSDB_CODE_SUCCESS) {
49,735,629✔
6001
      modeFunctionCleanup(pInfo);
556✔
6002
      return code;
×
6003
    }
6004
  }
6005

6006
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
23,324!
6007
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
6008
    if (code != TSDB_CODE_SUCCESS) {
50!
6009
      modeFunctionCleanup(pInfo);
×
6010
      return code;
×
6011
    }
6012
    pInfo->nullTupleSaved = true;
50✔
6013
  }
6014

6015
  SET_VAL(pResInfo, numOfElems, 1);
23,324✔
6016

6017
  return TSDB_CODE_SUCCESS;
23,324✔
6018
}
6019

6020
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
21,614✔
6021
  int32_t              code = TSDB_CODE_SUCCESS;
21,614✔
6022
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
21,614✔
6023
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
21,614✔
6024
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
21,614✔
6025
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
21,614✔
6026
  int32_t              currentRow = pBlock->info.rows;
21,614✔
6027
  if (NULL == pCol) {
21,614!
6028
    modeFunctionCleanup(pInfo);
×
6029
    return TSDB_CODE_OUT_OF_RANGE;
×
6030
  }
6031

6032
  STuplePos resDataPos, resTuplePos;
6033
  int32_t   maxCount = 0;
21,614✔
6034

6035
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
21,614✔
6036
  while (pIter != NULL) {
42,399,640✔
6037
    SModeItem* pItem = (SModeItem*)pIter;
42,378,026✔
6038
    if (pItem->count >= maxCount) {
42,378,026✔
6039
      maxCount = pItem->count;
27,384,495✔
6040
      resDataPos = pItem->dataPos;
27,384,495✔
6041
      resTuplePos = pItem->tuplePos;
27,384,495✔
6042
    }
6043

6044
    pIter = taosHashIterate(pInfo->pHash, pIter);
42,378,026✔
6045
  }
6046

6047
  if (maxCount != 0) {
21,614✔
6048
    char* pData = NULL;
19,381✔
6049
    code = loadTupleData(pCtx, &resDataPos, &pData);
19,381✔
6050
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
19,381!
6051
      code = terrno = TSDB_CODE_NOT_FOUND;
×
6052
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
6053
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
6054
      modeFunctionCleanup(pInfo);
×
6055
      return code;
×
6056
    }
6057

6058
    code = colDataSetVal(pCol, currentRow, pData, false);
19,381✔
6059
    if (TSDB_CODE_SUCCESS != code) {
19,381!
6060
      modeFunctionCleanup(pInfo);
×
6061
      return code;
×
6062
    }
6063
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
19,381✔
6064
  } else {
6065
    colDataSetNULL(pCol, currentRow);
2,233✔
6066
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,233✔
6067
  }
6068

6069
  modeFunctionCleanup(pInfo);
21,614✔
6070

6071
  return code;
21,614✔
6072
}
6073

6074
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
79,805✔
6075
  pEnv->calcMemSize = sizeof(STwaInfo);
79,805✔
6076
  return true;
79,805✔
6077
}
6078

6079
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,315,434✔
6080
  if (pResultInfo->initialized) {
8,315,434!
6081
    return TSDB_CODE_SUCCESS;
×
6082
  }
6083
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,315,434!
6084
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6085
  }
6086

6087
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,315,439✔
6088
  pInfo->numOfElems = 0;
8,315,439✔
6089
  pInfo->p.key = INT64_MIN;
8,315,439✔
6090
  pInfo->win = TSWINDOW_INITIALIZER;
8,315,439✔
6091
  return TSDB_CODE_SUCCESS;
8,315,439✔
6092
}
6093

6094
static double twa_get_area(SPoint1 s, SPoint1 e) {
19,118,580✔
6095
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
19,118,580!
6096
    return 0;
×
6097
  }
6098

6099
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
19,118,798✔
6100
    return (s.val + e.val) * (e.key - s.key) / 2;
13,730,823✔
6101
  }
6102

6103
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
5,387,975✔
6104
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
5,387,975✔
6105
  return val;
5,387,975✔
6106
}
6107

6108
int32_t twaFunction(SqlFunctionCtx* pCtx) {
8,320,081✔
6109
  int32_t               code = TSDB_CODE_SUCCESS;
8,320,081✔
6110
  SInputColumnInfoData* pInput = &pCtx->input;
8,320,081✔
6111
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,320,081✔
6112

6113
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,320,081✔
6114
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,320,081✔
6115
  SPoint1*             last = &pInfo->p;
8,320,081✔
6116

6117
  if (IS_NULL_TYPE(pInputCol->info.type)) {
8,320,081!
6118
    pInfo->numOfElems = 0;
×
6119
    goto _twa_over;
×
6120
  }
6121

6122
  funcInputUpdate(pCtx);
8,320,081✔
6123
  SFuncInputRow row = {0};
8,320,153✔
6124
  bool          result = false;
8,320,153✔
6125
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
8,320,153✔
6126
    while (1) {
6127
      code = funcInputGetNextRow(pCtx, &row, &result);
4,608,287✔
6128
      if (TSDB_CODE_SUCCESS != code) {
4,608,257!
6129
        return code;
×
6130
      }
6131
      if (!result) {
4,608,257✔
6132
        break;
2✔
6133
      }
6134
      if (row.isDataNull) {
4,608,255✔
6135
        continue;
2✔
6136
      }
6137

6138
      last->key = row.ts;
4,608,253✔
6139

6140
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
4,608,253!
6141

6142
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
4,608,253✔
6143
      pInfo->win.skey = pCtx->start.key;
4,608,206✔
6144
      pInfo->numOfElems++;
4,608,206✔
6145
      break;
4,608,206✔
6146
    }
6147
  } else if (pInfo->p.key == INT64_MIN) {
3,711,868✔
6148
    while (1) {
6149
      code = funcInputGetNextRow(pCtx, &row, &result);
3,821,003✔
6150
      if (TSDB_CODE_SUCCESS != code) {
3,820,917!
6151
        return code;
×
6152
      }
6153
      if (!result) {
3,820,917✔
6154
        break;
11,571✔
6155
      }
6156
      if (row.isDataNull) {
3,809,346✔
6157
        continue;
113,264✔
6158
      }
6159

6160
      last->key = row.ts;
3,696,082✔
6161

6162
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,696,082!
6163

6164
      pInfo->win.skey = last->key;
3,696,082✔
6165
      pInfo->numOfElems++;
3,696,082✔
6166
      break;
3,696,082✔
6167
    }
6168
  }
6169

6170
  SPoint1 st = {0};
8,319,990✔
6171

6172
  // calculate the value of
6173
  while (1) {
6174
    code = funcInputGetNextRow(pCtx, &row, &result);
17,955,735✔
6175
    if (TSDB_CODE_SUCCESS != code) {
17,955,583!
6176
      return code;
×
6177
    }
6178
    if (!result) {
17,955,583✔
6179
      break;
8,319,941✔
6180
    }
6181
    if (row.isDataNull) {
9,635,642✔
6182
      continue;
630✔
6183
    }
6184
    pInfo->numOfElems++;
9,635,012✔
6185
    switch (pInputCol->info.type) {
9,635,012!
6186
      case TSDB_DATA_TYPE_TINYINT: {
85,820✔
6187
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
85,820✔
6188
        break;
85,820✔
6189
      }
6190
      case TSDB_DATA_TYPE_SMALLINT: {
5,737,025✔
6191
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
5,737,025✔
6192
        break;
5,737,025✔
6193
      }
6194
      case TSDB_DATA_TYPE_INT: {
396,106✔
6195
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
396,106✔
6196
        break;
396,106✔
6197
      }
6198
      case TSDB_DATA_TYPE_BIGINT: {
92,418✔
6199
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
92,418✔
6200
        break;
92,418✔
6201
      }
6202
      case TSDB_DATA_TYPE_FLOAT: {
342,033✔
6203
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
342,033✔
6204
        break;
342,033✔
6205
      }
6206
      case TSDB_DATA_TYPE_DOUBLE: {
2,715,924✔
6207
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
2,715,924✔
6208
        break;
2,715,924✔
6209
      }
6210
      case TSDB_DATA_TYPE_UTINYINT: {
67,832✔
6211
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
67,832✔
6212
        break;
67,832✔
6213
      }
6214
      case TSDB_DATA_TYPE_USMALLINT: {
68,514✔
6215
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
68,514✔
6216
        break;
68,514✔
6217
      }
6218
      case TSDB_DATA_TYPE_UINT: {
71,024✔
6219
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
71,024✔
6220
        break;
71,024✔
6221
      }
6222
      case TSDB_DATA_TYPE_UBIGINT: {
58,550✔
6223
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
58,550✔
6224
        break;
58,550✔
6225
      }
6226
      default: {
×
6227
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6228
      }
6229
    }
6230
    if (pInfo->p.key == st.key) {
9,635,246!
6231
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6232
    }
6233

6234
    pInfo->dOutput += twa_get_area(pInfo->p, st);
9,635,246✔
6235
    pInfo->p = st;
9,635,115✔
6236
  }
6237

6238
  // the last interpolated time window value
6239
  if (pCtx->end.key != INT64_MIN) {
8,319,941✔
6240
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
4,876,784✔
6241
    pInfo->p = pCtx->end;
4,876,777✔
6242
    pInfo->numOfElems += 1;
4,876,777✔
6243
  }
6244

6245
  pInfo->win.ekey = pInfo->p.key;
8,319,934✔
6246

6247
_twa_over:
8,319,934✔
6248
  SET_VAL(pResInfo, 1, 1);
8,319,934✔
6249
  return TSDB_CODE_SUCCESS;
8,319,934✔
6250
}
6251

6252
/*
6253
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6254
 * by next input data. The TWA function only applies to each table, so no merge procedure
6255
 * is required, we simply copy to the resut ot interResBuffer.
6256
 */
6257
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6258
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6259
//
6260
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6261
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6262
// }
6263

6264
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,304,448✔
6265
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,304,448✔
6266

6267
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
8,304,448✔
6268
  if (pInfo->numOfElems == 0) {
8,304,448✔
6269
    pResInfo->numOfRes = 0;
11,095✔
6270
  } else {
6271
    if (pInfo->win.ekey == pInfo->win.skey) {
8,293,353✔
6272
      pInfo->dTwaRes = pInfo->p.val;
3,026,240✔
6273
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
5,267,113!
6274
      pInfo->dTwaRes = 0;
×
6275
    } else {
6276
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
5,267,392✔
6277
    }
6278

6279
    pResInfo->numOfRes = 1;
8,293,353✔
6280
  }
6281

6282
  return functionFinalize(pCtx, pBlock);
8,304,448✔
6283
}
6284

6285
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,628✔
6286
  if (pResultInfo->initialized) {
1,628!
6287
    return TSDB_CODE_SUCCESS;
×
6288
  }
6289
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,628!
6290
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6291
  }
6292

6293
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,628✔
6294
  pInfo->minRows = INT32_MAX;
1,628✔
6295
  return TSDB_CODE_SUCCESS;
1,628✔
6296
}
6297

6298
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,253✔
6299
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,253✔
6300

6301
  SInputColumnInfoData* pInput = &pCtx->input;
3,253✔
6302
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,253✔
6303
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,253✔
6304
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,253✔
6305

6306
  STableBlockDistInfo p1 = {0};
3,253✔
6307
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,253!
6308
    qError("failed to deserialize block dist info");
×
6309
    return TSDB_CODE_FAILED;
×
6310
  }
6311

6312
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,253✔
6313
  pDistInfo->numOfTables += p1.numOfTables;
3,253✔
6314
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,253✔
6315
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,253✔
6316
  pDistInfo->totalSize += p1.totalSize;
3,253✔
6317
  pDistInfo->totalRows += p1.totalRows;
3,253✔
6318
  pDistInfo->numOfFiles += p1.numOfFiles;
3,253✔
6319

6320
  pDistInfo->defMinRows = p1.defMinRows;
3,253✔
6321
  pDistInfo->defMaxRows = p1.defMaxRows;
3,253✔
6322
  pDistInfo->rowSize = p1.rowSize;
3,253✔
6323

6324
  if (pDistInfo->minRows > p1.minRows) {
3,253✔
6325
    pDistInfo->minRows = p1.minRows;
2✔
6326
  }
6327
  if (pDistInfo->maxRows < p1.maxRows) {
3,253✔
6328
    pDistInfo->maxRows = p1.maxRows;
2✔
6329
  }
6330
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,253✔
6331
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,313✔
6332
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,060✔
6333
  }
6334

6335
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,253✔
6336
  return TSDB_CODE_SUCCESS;
3,253✔
6337
}
6338

6339
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,490✔
6340
  SEncoder encoder = {0};
6,490✔
6341
  int32_t  code = 0;
6,490✔
6342
  int32_t  lino;
6343
  int32_t  tlen;
6344
  tEncoderInit(&encoder, buf, bufLen);
6,490✔
6345

6346
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,496!
6347
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
12,982!
6348

6349
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
12,982!
6350
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
12,982!
6351
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
12,982!
6352

6353
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
12,982!
6354
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
12,982!
6355
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
12,982!
6356
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
12,982!
6357
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
12,982!
6358
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
12,982!
6359
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
12,982!
6360
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
12,982!
6361
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
12,982!
6362

6363
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,013✔
6364
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,044!
6365
  }
6366

6367
  tEndEncode(&encoder);
6,491✔
6368

6369
_exit:
6,498✔
6370
  if (code) {
6,498!
6371
    tlen = code;
×
6372
  } else {
6373
    tlen = encoder.pos;
6,498✔
6374
  }
6375
  tEncoderClear(&encoder);
6,498✔
6376
  return tlen;
6,495✔
6377
}
6378

6379
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,253✔
6380
  SDecoder decoder = {0};
3,253✔
6381
  int32_t  code = 0;
3,253✔
6382
  int32_t  lino;
6383
  tDecoderInit(&decoder, buf, bufLen);
3,253✔
6384

6385
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,253!
6386
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,506!
6387

6388
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,506!
6389
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,506!
6390
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,506!
6391

6392
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,506!
6393
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,506!
6394
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,506!
6395
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,506!
6396
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,506!
6397
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,506!
6398
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,506!
6399
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,506!
6400
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,506!
6401

6402
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,313✔
6403
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,120!
6404
  }
6405

6406
_exit:
3,253✔
6407
  tDecoderClear(&decoder);
3,253✔
6408
  return code;
3,253✔
6409
}
6410

6411
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,628✔
6412
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,628✔
6413
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,628✔
6414

6415
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,628✔
6416
  if (NULL == pColInfo) {
1,628!
6417
    return TSDB_CODE_OUT_OF_RANGE;
×
6418
  }
6419

6420
  if (pData->totalRows == 0) {
1,628✔
6421
    pData->minRows = 0;
1,626✔
6422
  }
6423

6424
  int32_t row = 0;
1,628✔
6425
  char    st[256] = {0};
1,628✔
6426
  double  averageSize = 0;
1,628✔
6427
  if (pData->numOfBlocks != 0) {
1,628✔
6428
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
2✔
6429
  }
6430
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,628✔
6431
  double   compRatio = 0;
1,628✔
6432
  if (totalRawSize != 0) {
1,628✔
6433
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
2✔
6434
  }
6435

6436
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6437
                          "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6438
                          pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,628✔
6439

6440
  varDataSetLen(st, len);
1,628✔
6441
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6442
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6443
    return code;
×
6444
  }
6445

6446
  int64_t avgRows = 0;
1,628✔
6447
  if (pData->numOfBlocks > 0) {
1,628✔
6448
    avgRows = pData->totalRows / pData->numOfBlocks;
2✔
6449
  }
6450

6451
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6452
                  "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6453
                  pData->minRows, pData->maxRows, avgRows);
6454
  varDataSetLen(st, len);
1,628✔
6455
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6456
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6457
    return code;
×
6458
  }
6459

6460
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
1,628✔
6461
                  pData->numOfInmemRows, pData->numOfSttRows);
6462
  varDataSetLen(st, len);
1,628✔
6463
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6464
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6465
    return code;
×
6466
  }
6467

6468
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6469
                  "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
1,628✔
6470
                  pData->numOfVgroups);
6471

6472
  varDataSetLen(st, len);
1,628✔
6473
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6474
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6475
    return code;
×
6476
  }
6477

6478
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6479
                  "--------------------------------------------------------------------------------");
6480
  varDataSetLen(st, len);
1,628✔
6481
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6482
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6483
    return code;
×
6484
  }
6485

6486
  int32_t maxVal = 0;
1,628✔
6487
  int32_t minVal = INT32_MAX;
1,628✔
6488
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6489
    if (maxVal < pData->blockRowsHisto[i]) {
32,560✔
6490
      maxVal = pData->blockRowsHisto[i];
3✔
6491
    }
6492

6493
    if (minVal > pData->blockRowsHisto[i]) {
32,560✔
6494
      minVal = pData->blockRowsHisto[i];
1,629✔
6495
    }
6496
  }
6497

6498
  // maximum number of step is 80
6499
  double factor = pData->numOfBlocks / 80.0;
1,628✔
6500

6501
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,628✔
6502
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,628✔
6503

6504
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6505
    len =
32,560✔
6506
        tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,560✔
6507

6508
    int32_t num = 0;
32,560✔
6509
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6510
      num = (pData->blockRowsHisto[i]) / factor;
4✔
6511
    }
6512

6513
    for (int32_t j = 0; j < num; ++j) {
32,719✔
6514
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
159✔
6515
      len += x;
159✔
6516
    }
6517

6518
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6519
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
4✔
6520
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
4✔
6521
                       pData->blockRowsHisto[i], v, '%');
6522
    }
6523

6524
    varDataSetLen(st, len);
32,560✔
6525
    code = colDataSetVal(pColInfo, row++, st, false);
32,560✔
6526
    if (TSDB_CODE_SUCCESS != code) {
32,560!
6527
      return code;
×
6528
    }
6529
  }
6530

6531
  return TSDB_CODE_SUCCESS;
1,628✔
6532
}
6533
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1✔
6534
  if (pResultInfo->initialized) {
1!
6535
    return TSDB_CODE_SUCCESS;
×
6536
  }
6537
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1!
6538
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6539
  }
6540

6541
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1✔
6542
  return TSDB_CODE_SUCCESS;
1✔
6543
}
6544
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
2✔
6545
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
2✔
6546

6547
  SInputColumnInfoData* pInput = &pCtx->input;
2✔
6548
  SColumnInfoData*      pInputCol = pInput->pData[0];
2✔
6549
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
2✔
6550
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
2✔
6551

6552
  SDBBlockUsageInfo p1 = {0};
2✔
6553
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
2!
6554
    qError("failed to deserialize block dist info");
×
6555
    return TSDB_CODE_FAILED;
×
6556
  }
6557

6558
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
2✔
6559
  pDistInfo->walInDiskSize += p1.walInDiskSize;
2✔
6560
  pDistInfo->rawDataSize += p1.rawDataSize;
2✔
6561
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
2✔
6562
  return TSDB_CODE_SUCCESS;
2✔
6563
}
6564

6565
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
4✔
6566
  SEncoder encoder = {0};
4✔
6567
  int32_t  code = 0;
4✔
6568
  int32_t  lino;
6569
  int32_t  tlen;
6570
  tEncoderInit(&encoder, buf, bufLen);
4✔
6571

6572
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
4!
6573

6574
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
8!
6575
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
8!
6576
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
8!
6577

6578
  tEndEncode(&encoder);
4✔
6579

6580
_exit:
4✔
6581
  if (code) {
4!
6582
    tlen = code;
×
6583
  } else {
6584
    tlen = encoder.pos;
4✔
6585
  }
6586
  tEncoderClear(&encoder);
4✔
6587
  return tlen;
4✔
6588
}
6589
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
2✔
6590
  SDecoder decoder = {0};
2✔
6591
  int32_t  code = 0;
2✔
6592
  int32_t  lino;
6593
  tDecoderInit(&decoder, buf, bufLen);
2✔
6594

6595
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
2!
6596
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
4!
6597
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
4!
6598
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
4!
6599

6600
_exit:
2✔
6601
  tDecoderClear(&decoder);
2✔
6602
  return code;
2✔
6603
}
6604
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1✔
6605
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1✔
6606
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
1✔
6607

6608
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1✔
6609
  if (NULL == pColInfo) {
1!
6610
    return TSDB_CODE_OUT_OF_RANGE;
×
6611
  }
6612
  int32_t len = 0;
1✔
6613
  int32_t row = 0;
1✔
6614
  char    st[256] = {0};
1✔
6615

6616
  uint64_t totalDiskSize = pData->dataInDiskSize;
1✔
6617
  uint64_t rawDataSize = pData->rawDataSize;
1✔
6618
  double   compressRadio = 0;
1✔
6619
  if (rawDataSize != 0) {
1!
6620
    compressRadio = totalDiskSize * 100 / (double)rawDataSize;
1✔
6621
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[%.2f]", compressRadio);
1✔
6622
  } else {
6623
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[NULL]");
×
6624
  }
6625

6626
  varDataSetLen(st, len);
1✔
6627
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1✔
6628
  if (TSDB_CODE_SUCCESS != code) {
1!
6629
    return code;
×
6630
  }
6631

6632
  len =
1✔
6633
      tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
1✔
6634
  varDataSetLen(st, len);
1✔
6635
  code = colDataSetVal(pColInfo, row++, st, false);
1✔
6636
  if (TSDB_CODE_SUCCESS != code) {
1!
6637
    return code;
×
6638
  }
6639
  return code;
1✔
6640
}
6641

6642
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
30,658✔
6643
  pEnv->calcMemSize = sizeof(SDerivInfo);
30,658✔
6644
  return true;
30,658✔
6645
}
6646

6647
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
61,433✔
6648
  if (pResInfo->initialized) {
61,433✔
6649
    return TSDB_CODE_SUCCESS;
30,654✔
6650
  }
6651
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
30,779!
6652
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6653
  }
6654

6655
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
30,779✔
6656

6657
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
30,779✔
6658
  pDerivInfo->prevTs = -1;
30,779✔
6659
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
30,779✔
6660
  pDerivInfo->valueSet = false;
30,779✔
6661
  return TSDB_CODE_SUCCESS;
30,779✔
6662
}
6663

6664
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
30,775✔
6665
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
30,775✔
6666
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
30,775✔
6667

6668
  SInputColumnInfoData* pInput = &pCtx->input;
30,775✔
6669
  SColumnInfoData*      pInputCol = pInput->pData[0];
30,775✔
6670

6671
  int32_t          numOfElems = 0;
30,775✔
6672
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
30,775✔
6673
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
30,775✔
6674
  int32_t          code = TSDB_CODE_SUCCESS;
30,775✔
6675

6676
  funcInputUpdate(pCtx);
30,775✔
6677

6678
  double v = 0;
30,775✔
6679
  if (pCtx->order == TSDB_ORDER_ASC) {
30,775✔
6680
    SFuncInputRow row = {0};
27,366✔
6681
    bool          result = false;
27,366✔
6682
    while (1) {
3,531,832✔
6683
      code = funcInputGetNextRow(pCtx, &row, &result);
3,559,198✔
6684
      if (TSDB_CODE_SUCCESS != code) {
3,559,198!
6685
        return code;
×
6686
      }
6687
      if (!result) {
3,559,198✔
6688
        break;
27,366✔
6689
      }
6690
      if (row.isDataNull) {
3,531,832✔
6691
        continue;
40,847✔
6692
      }
6693

6694
      char* d = row.pData;
3,490,985✔
6695
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
3,490,985!
6696

6697
      int32_t pos = pCtx->offset + numOfElems;
3,490,985✔
6698
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
3,490,985✔
6699
        pDerivInfo->valueSet = true;
26,949✔
6700
      } else {
6701
        if (row.ts == pDerivInfo->prevTs) {
3,464,036!
6702
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6703
        }
6704
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
3,464,036✔
6705
        if (pDerivInfo->ignoreNegative && r < 0) {
3,464,036✔
6706
        } else {
6707
          if (isinf(r) || isnan(r)) {
1,982,534!
6708
            colDataSetNULL(pOutput, pos);
×
6709
          } else {
6710
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
1,982,534✔
6711
            if (code != TSDB_CODE_SUCCESS) {
1,982,534!
6712
              return code;
×
6713
            }
6714
          }
6715

6716
          if (pTsOutput != NULL) {
1,982,534!
6717
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6718
          }
6719

6720
          // handle selectivity
6721
          if (pCtx->subsidiaries.num > 0) {
1,982,534✔
6722
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,478,753✔
6723
            if (code != TSDB_CODE_SUCCESS) {
1,478,753!
6724
              return code;
×
6725
            }
6726
          }
6727

6728
          numOfElems++;
1,982,534✔
6729
        }
6730
      }
6731

6732
      pDerivInfo->prevValue = v;
3,490,985✔
6733
      pDerivInfo->prevTs = row.ts;
3,490,985✔
6734
    }
6735
  } else {
6736
    SFuncInputRow row = {0};
3,409✔
6737
    bool          result = false;
3,409✔
6738
    while (1) {
338,330✔
6739
      code = funcInputGetNextRow(pCtx, &row, &result);
341,739✔
6740
      if (TSDB_CODE_SUCCESS != code) {
341,739!
6741
        return code;
×
6742
      }
6743
      if (!result) {
341,739✔
6744
        break;
3,409✔
6745
      }
6746
      if (row.isDataNull) {
338,330✔
6747
        continue;
2,448✔
6748
      }
6749

6750
      char* d = row.pData;
335,882✔
6751
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
335,882!
6752

6753
      int32_t pos = pCtx->offset + numOfElems;
335,882✔
6754
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
335,882✔
6755
        pDerivInfo->valueSet = true;
3,373✔
6756
      } else {
6757
        if (row.ts == pDerivInfo->prevTs) {
332,509!
6758
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6759
        }
6760
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
332,509✔
6761
        if (pDerivInfo->ignoreNegative && r < 0) {
332,509✔
6762
        } else {
6763
          if (isinf(r) || isnan(r)) {
191,440!
6764
            colDataSetNULL(pOutput, pos);
×
6765
          } else {
6766
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
191,440✔
6767
            if (code != TSDB_CODE_SUCCESS) {
191,440!
6768
              return code;
×
6769
            }
6770
          }
6771

6772
          if (pTsOutput != NULL) {
191,440!
6773
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6774
          }
6775

6776
          // handle selectivity
6777
          if (pCtx->subsidiaries.num > 0) {
191,440✔
6778
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
67,146✔
6779
            if (code != TSDB_CODE_SUCCESS) {
67,146!
6780
              return code;
×
6781
            }
6782
          }
6783
          numOfElems++;
191,440✔
6784
        }
6785
      }
6786

6787
      pDerivInfo->prevValue = v;
335,882✔
6788
      pDerivInfo->prevTs = row.ts;
335,882✔
6789
    }
6790
  }
6791

6792
  pResInfo->numOfRes = numOfElems;
30,775✔
6793

6794
  return TSDB_CODE_SUCCESS;
30,775✔
6795
}
6796

6797
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
1,940,473✔
6798

6799
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
125,271✔
6800
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
125,271✔
6801
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
125,271✔
6802
  return true;
125,378✔
6803
}
6804

6805
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
9,145,821✔
6806
  if (pResInfo->initialized) {
9,145,821!
6807
    return TSDB_CODE_SUCCESS;
×
6808
  }
6809
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
9,145,821!
6810
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6811
  }
6812

6813
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
9,145,830✔
6814

6815
  pInfo->firstKey = INT64_MIN;
9,145,830✔
6816
  pInfo->lastKey = INT64_MIN;
9,145,830✔
6817
  pInfo->firstValue = (double)INT64_MIN;
9,145,830✔
6818
  pInfo->lastValue = (double)INT64_MIN;
9,145,830✔
6819

6820
  pInfo->hasResult = 0;
9,145,830✔
6821
  return TSDB_CODE_SUCCESS;
9,145,830✔
6822
}
6823

6824
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
28,607,083✔
6825
  if (isFirst) {
28,607,083✔
6826
    pRateInfo->firstValue = v;
10,644,096✔
6827
    pRateInfo->firstKey = ts;
10,644,096✔
6828
    if (pRateInfo->firstPk) {
10,644,096✔
6829
      int32_t pkBytes;
6830
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
35!
6831
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
8!
6832
          pkBytes = getJsonValueLen(pk);
×
6833
        } else {
6834
          pkBytes = varDataTLen(pk);
8✔
6835
        }
6836
      } else {
6837
        pkBytes = pRateInfo->pkBytes;
27✔
6838
      }
6839
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6840
    }
6841
  } else {
6842
    pRateInfo->lastValue = v;
17,962,987✔
6843
    pRateInfo->lastKey = ts;
17,962,987✔
6844
    if (pRateInfo->lastPk) {
17,962,987✔
6845
      int32_t pkBytes;
6846
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
52!
6847
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
12!
6848
          pkBytes = getJsonValueLen(pk);
×
6849
        } else {
6850
          pkBytes = varDataTLen(pk);
12✔
6851
        }
6852
      } else {
6853
        pkBytes = pRateInfo->pkBytes;
40✔
6854
      }
6855
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6856
    }
6857
  }
6858
}
28,607,083✔
6859

6860
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
10,980,781✔
6861
  if (pCtx->hasPrimaryKey) {
10,980,781✔
6862
    if (!isMerge) {
19✔
6863
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6864
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6865
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6866
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6867
    } else {
6868
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6869
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6870
    }
6871
  } else {
6872
    pRateInfo->firstPk = NULL;
10,980,762✔
6873
    pRateInfo->lastPk = NULL;
10,980,762✔
6874
  }
6875
}
10,980,781✔
6876

6877
int32_t irateFunction(SqlFunctionCtx* pCtx) {
7,350,732✔
6878
  int32_t              code = TSDB_CODE_SUCCESS;
7,350,732✔
6879
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,350,732✔
6880
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,350,732✔
6881

6882
  SInputColumnInfoData* pInput = &pCtx->input;
7,350,732✔
6883
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,350,732✔
6884

6885
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7,350,732✔
6886

6887
  funcInputUpdate(pCtx);
7,350,732✔
6888

6889
  initializeRateInfo(pCtx, pRateInfo, false);
7,350,741✔
6890

6891
  int32_t       numOfElems = 0;
7,350,741✔
6892
  int32_t       type = pInputCol->info.type;
7,350,741✔
6893
  SFuncInputRow row = {0};
7,350,741✔
6894
  bool          result = false;
7,350,741✔
6895
  while (1) {
16,403,544✔
6896
    code = funcInputGetNextRow(pCtx, &row, &result);
23,754,285✔
6897
    if (TSDB_CODE_SUCCESS != code) {
23,753,963!
6898
      return code;
×
6899
    }
6900
    if (!result) {
23,753,963✔
6901
      break;
7,350,712✔
6902
    }
6903
    if (row.isDataNull) {
16,403,251✔
6904
      continue;
115,774✔
6905
    }
6906

6907
    char*  data = row.pData;
16,287,477✔
6908
    double v = 0;
16,287,477✔
6909
    GET_TYPED_DATA(v, double, type, data);
16,287,477!
6910

6911
    if (INT64_MIN == pRateInfo->lastKey) {
16,287,477✔
6912
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
7,319,608✔
6913
      pRateInfo->hasResult = 1;
7,319,604✔
6914
      continue;
7,319,604✔
6915
    }
6916

6917
    if (row.ts > pRateInfo->lastKey) {
8,967,869✔
6918
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
8,828,560!
6919
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
8,828,560✔
6920
      }
6921
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
8,828,563✔
6922
      continue;
8,828,555✔
6923
    } else if (row.ts == pRateInfo->lastKey) {
139,309!
6924
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6925
    }
6926

6927
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
139,309!
6928
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
16✔
6929
    } else if (row.ts == pRateInfo->firstKey) {
139,293!
6930
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6931
    }
6932
  }
6933

6934
  numOfElems++;
7,350,712✔
6935

6936
  SET_VAL(pResInfo, numOfElems, 1);
7,350,712!
6937
  return TSDB_CODE_SUCCESS;
7,350,712✔
6938
}
6939

6940
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
7,318,759✔
6941
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
7,318,759✔
6942
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
632,374!
6943
    return 0.0;
6,686,385✔
6944
  }
6945

6946
  double diff = 0;
632,374✔
6947
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6948
  // value between two values.
6949
  diff = pRateInfo->lastValue;
632,374✔
6950
  if (diff >= pRateInfo->firstValue) {
632,374✔
6951
    diff -= pRateInfo->firstValue;
348,406✔
6952
  }
6953

6954
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
632,374✔
6955
  if (duration == 0) {
632,374!
6956
    return 0;
×
6957
  }
6958

6959
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
632,374!
6960
}
6961

6962
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
174✔
6963
  if (inputKey > pOutput->lastKey) {
174✔
6964
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
118✔
6965
    if (isFirstKey) {
118✔
6966
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
54✔
6967
    } else {
6968
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
64✔
6969
    }
6970
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
56!
6971
    if (isFirstKey) {
16✔
6972
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
8✔
6973
    } else {
6974
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
8✔
6975
    }
6976
  } else {
6977
    // inputKey < pOutput->firstKey
6978
  }
6979
}
174✔
6980

6981
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,814,931✔
6982
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,814,931✔
6983
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,814,931✔
6984
}
1,814,931✔
6985

6986
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,815,018✔
6987
  if ((pInput->firstKey != INT64_MIN &&
1,815,018✔
6988
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
138,671!
6989
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
1,815,018!
6990
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6991
  }
6992

6993
  if (pOutput->hasResult == 0) {
1,815,018✔
6994
    irateCopyInfo(pInput, pOutput);
1,814,931✔
6995
    pOutput->hasResult = pInput->hasResult;
1,814,931✔
6996
    return TSDB_CODE_SUCCESS;
1,814,931✔
6997
  }
6998

6999
  if (pInput->firstKey != INT64_MIN) {
87!
7000
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
87✔
7001
  }
7002

7003
  if (pInput->lastKey != INT64_MIN) {
87!
7004
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
87✔
7005
  }
7006

7007
  pOutput->hasResult = pInput->hasResult;
87✔
7008
  return TSDB_CODE_SUCCESS;
87✔
7009
}
7010

7011
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
1,815,026✔
7012
  SInputColumnInfoData* pInput = &pCtx->input;
1,815,026✔
7013
  SColumnInfoData*      pCol = pInput->pData[0];
1,815,026✔
7014
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,815,026!
7015
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7016
  }
7017

7018
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,815,026✔
7019
  initializeRateInfo(pCtx, pInfo, true);
1,815,026✔
7020

7021
  int32_t start = pInput->startRowIndex;
1,815,026✔
7022
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,630,052✔
7023
    char*      data = colDataGetData(pCol, i);
1,815,026!
7024
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
1,815,026✔
7025
    initializeRateInfo(pCtx, pInfo, true);
1,815,026✔
7026
    if (pInputInfo->hasResult) {
1,815,026✔
7027
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
1,815,018✔
7028
      if (code != TSDB_CODE_SUCCESS) {
1,815,018!
7029
        return code;
×
7030
      }
7031
    }
7032
  }
7033

7034
  if (pInfo->hasResult) {
1,815,026✔
7035
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,815,018✔
7036
  }
7037

7038
  return TSDB_CODE_SUCCESS;
1,815,026✔
7039
}
7040

7041
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,815,026✔
7042
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,815,026✔
7043
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,815,026✔
7044
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
1,815,026✔
7045
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,815,026!
7046

7047
  if (NULL == res) {
1,815,026!
7048
    return terrno;
×
7049
  }
7050
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,815,026✔
7051
  varDataSetLen(res, resultBytes);
1,815,026✔
7052

7053
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,815,026✔
7054
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,815,026✔
7055
  if (NULL == pCol) {
1,815,026!
7056
    taosMemoryFree(res);
×
7057
    return TSDB_CODE_OUT_OF_RANGE;
×
7058
  }
7059

7060
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,815,026✔
7061

7062
  taosMemoryFree(res);
1,815,026!
7063
  return code;
1,815,026✔
7064
}
7065

7066
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,318,774✔
7067
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,318,774✔
7068
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,318,774✔
7069
  if (NULL == pCol) {
7,318,756!
7070
    return TSDB_CODE_OUT_OF_RANGE;
×
7071
  }
7072

7073
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,318,756✔
7074
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
7,318,756✔
7075

7076
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,318,756✔
7077
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
7,318,756!
7078
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
7,318,762✔
7079

7080
  return code;
7,318,715✔
7081
}
7082

7083
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
108,952,125✔
7084
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
108,952,125✔
7085
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
108,952,125✔
7086

7087
  SInputColumnInfoData* pInput = &pCtx->input;
108,952,125✔
7088
  SColumnInfoData*      pInputCol = pInput->pData[0];
108,952,125✔
7089

7090
  int32_t startIndex = pInput->startRowIndex;
108,952,125✔
7091

7092
  // escape rest of data blocks to avoid first entry to be overwritten.
7093
  if (pInfo->hasResult) {
108,952,125✔
7094
    goto _group_value_over;
10,767,240✔
7095
  }
7096

7097
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
195,998,540✔
7098
    pInfo->isNull = true;
2,548,284✔
7099
    pInfo->hasResult = true;
2,548,284✔
7100
    goto _group_value_over;
2,548,284✔
7101
  }
7102

7103
  char* data = colDataGetData(pInputCol, startIndex);
95,636,601!
7104
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
95,636,601!
7105
    (void)memcpy(pInfo->data, data,
73,476,503✔
7106
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
73,476,503✔
7107
  } else {
7108
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
22,160,098✔
7109
  }
7110
  pInfo->hasResult = true;
95,636,601✔
7111

7112
_group_value_over:
108,952,125✔
7113

7114
  SET_VAL(pResInfo, 1, 1);
108,952,125✔
7115
  return TSDB_CODE_SUCCESS;
108,952,125✔
7116
}
7117

7118
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
108,934,875✔
7119

7120
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
96,639,684✔
7121
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
96,639,684✔
7122
  int32_t          code = TSDB_CODE_SUCCESS;
96,639,684✔
7123
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
96,639,684✔
7124
  if (NULL == pCol) {
96,558,103!
7125
    return TSDB_CODE_OUT_OF_RANGE;
×
7126
  }
7127

7128
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
96,558,103✔
7129

7130
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
96,558,103✔
7131

7132
  if (pInfo->hasResult) {
96,558,103!
7133
    int32_t currentRow = pBlock->info.rows;
96,585,864✔
7134
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
194,291,016✔
7135
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
96,607,378✔
7136
      if (TSDB_CODE_SUCCESS != code) {
97,705,152!
7137
        return code;
×
7138
      }
7139
    }
7140
  } else {
7141
    pResInfo->numOfRes = 0;
×
7142
  }
7143

7144
  return code;
97,655,877✔
7145
}
7146

7147
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
96,664,785✔
7148

7149
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7150
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7151
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7152

7153
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7154
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7155

7156
  // escape rest of data blocks to avoid first entry to be overwritten.
7157
  if (pDBuf->hasResult) {
×
7158
    goto _group_key_over;
×
7159
  }
7160

7161
  if (pSBuf->isNull) {
×
7162
    pDBuf->isNull = true;
×
7163
    pDBuf->hasResult = true;
×
7164
    goto _group_key_over;
×
7165
  }
7166

7167
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7168
    (void)memcpy(pDBuf->data, pSBuf->data,
×
7169
                 (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data)
×
7170
                                                                       : varDataTLen(pSBuf->data));
×
7171
  } else {
7172
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7173
  }
7174

7175
  pDBuf->hasResult = true;
×
7176

7177
_group_key_over:
×
7178

7179
  SET_VAL(pDResInfo, 1, 1);
×
7180
  return TSDB_CODE_SUCCESS;
×
7181
}
7182

7183
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
8,945✔
7184
  int32_t numOfElems = 0;
8,945✔
7185

7186
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,945✔
7187
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,945✔
7188

7189
  SInputColumnInfoData* pInput = &pCtx->input;
8,945✔
7190
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,945✔
7191

7192
  int32_t bytes = pInputCol->info.bytes;
8,945✔
7193
  pInfo->bytes = bytes;
8,945✔
7194

7195
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
8,945✔
7196
  pInfo->pkType = -1;
8,945✔
7197
  __compar_fn_t pkCompareFn = NULL;
8,945✔
7198
  if (pCtx->hasPrimaryKey) {
8,945✔
7199
    pInfo->pkType = pkCol->info.type;
20✔
7200
    pInfo->pkBytes = pkCol->info.bytes;
20✔
7201
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
20✔
7202
  }
7203

7204
  // TODO it traverse the different way.
7205
  // last_row function does not ignore the null value
7206
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
17,900✔
7207
    numOfElems++;
8,955✔
7208

7209
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
8,955✔
7210
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
8,955!
7211

7212
    TSKEY cts = getRowPTs(pInput->pPTS, i);
8,955!
7213
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
8,955✔
7214
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
8,649✔
7215
      if (code != TSDB_CODE_SUCCESS) {
8,649!
7216
        return code;
×
7217
      }
7218
      pResInfo->numOfRes = 1;
8,649✔
7219
    }
7220
  }
7221

7222
  SET_VAL(pResInfo, numOfElems, 1);
8,945!
7223
  return TSDB_CODE_SUCCESS;
8,945✔
7224
}
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