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

taosdata / TDengine / #3629

04 Mar 2025 01:45PM UTC coverage: 63.692% (-0.1%) from 63.79%
#3629

push

travis-ci

web-flow
Merge pull request #30007 from taosdata/revert-29951-docs/update-exception-handling-strategy

Revert "docs: update exception handling strategy"

149369 of 300378 branches covered (49.73%)

Branch coverage included in aggregate %.

233614 of 300930 relevant lines covered (77.63%)

18792670.99 hits per line

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

73.1
/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,936,351,655✔
32
bool ignoreNull(int8_t ignoreOption) { return (ignoreOption & 0x2) == 0x2; }
2,253,184✔
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,579,446✔
194
  SFuncInputRowIter* pIter = &pCtx->rowIter;
17,579,446✔
195

196
  if (!pCtx->bInputFinished) {
17,579,446!
197
    pIter->pInput = &pCtx->input;
17,579,520✔
198
    pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData;
17,579,520✔
199
    pIter->pDataCol = pIter->pInput->pData[0];
17,579,520✔
200
    pIter->pPkCol = pIter->pInput->pPrimaryKey;
17,579,520✔
201
    pIter->rowIndex = pIter->pInput->startRowIndex;
17,579,520✔
202
    pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1;
17,579,520✔
203
    pIter->pSrcBlock = pCtx->pSrcBlock;
17,579,520✔
204
    if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) {
17,579,520✔
205
      pIter->hasGroupId = true;
216,644✔
206
      pIter->groupId = pIter->pSrcBlock->info.id.groupId;
216,644✔
207
      pIter->hasPrev = false;
216,644✔
208
    }
209
  } else {
210
    pIter->finalRow = true;
×
211
  }
212
}
17,579,446✔
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) {
29,406✔
329
  int32_t idx = rowIndex + 1;
29,406✔
330
  while (idx <= pIter->inputEndIndex && pIter->tsList[idx] == pIter->tsList[rowIndex]) {
407,347!
331
    ++idx;
377,941✔
332
  }
333
  pIter->rowIndex = idx;
29,406✔
334
}
29,406✔
335

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

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

357
      pIter->hasPrev = false;
1,116✔
358
      setInputRowInfo(pRow, pIter, idx, true);
1,116✔
359
      forwardToNextDiffTsRow(pIter, idx);
1,116✔
360
      return true;
1,116✔
361
    }
362
  } else {
363
    if (pIter->rowIndex <= pIter->inputEndIndex) {
33,332✔
364
      setInputRowInfo(pRow, pIter, pIter->rowIndex, true);
30,814✔
365

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

382
bool funcInputGetNextRowNoPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) {
1,983,217,357✔
383
  if (pIter->rowIndex <= pIter->inputEndIndex) {
1,983,217,357✔
384
    setInputRowInfo(pRow, pIter, pIter->rowIndex, false);
1,965,725,129✔
385
    ++pIter->rowIndex;
1,965,639,011✔
386
    return true;
1,965,639,011✔
387
  } else {
388
    return false;
17,492,228✔
389
  }
390
}
391

392
int32_t funcInputGetNextRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, bool* res) {
1,983,271,169✔
393
  SFuncInputRowIter* pIter = &pCtx->rowIter;
1,983,271,169✔
394
  if (pCtx->hasPrimaryKey) {
1,983,271,169✔
395
    if (pCtx->order == TSDB_ORDER_ASC) {
34,448!
396
      *res = funcInputGetNextRowAscPk(pIter, pRow);
34,448✔
397
      return TSDB_CODE_SUCCESS;
34,448✔
398
    } else {
399
      return funcInputGetNextRowDescPk(pIter, pRow, res);
×
400
    }
401
  } else {
402
    *res = funcInputGetNextRowNoPk(pIter, pRow);
1,983,236,721✔
403
    return TSDB_CODE_SUCCESS;
1,983,101,399✔
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,048,632✔
411
  if (pCtx->subsidiaries.num <= 0) {
36,048,632!
412
    return TSDB_CODE_SUCCESS;
×
413
  }
414

415
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
72,104,603✔
416
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
36,055,964✔
417

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

422
    SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
36,055,964✔
423
    if (NULL == pSrcCol) {
36,055,951!
424
      return TSDB_CODE_OUT_OF_RANGE;
×
425
    }
426

427
    char* pData = colDataGetData(pSrcCol, rowIndex);
36,055,951!
428

429
    // append to dest col
430
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
36,055,951✔
431

432
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
36,055,951✔
433
    if (NULL == pDstCol) {
36,055,924!
434
      return TSDB_CODE_OUT_OF_RANGE;
×
435
    }
436
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
72,111,848✔
437
      colDataSetNULL(pDstCol, pos);
20!
438
    } else {
439
      int32_t code = colDataSetVal(pDstCol, pos, pData, false);
36,055,904✔
440
      if (TSDB_CODE_SUCCESS != code) {
36,055,951!
441
        return code;
×
442
      }
443
    }
444
  }
445
  return TSDB_CODE_SUCCESS;
36,048,639✔
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) {
735,021,150✔
454
  if (pResultInfo->initialized) {
735,021,150✔
455
    return TSDB_CODE_SUCCESS;  // already initialized
160,819✔
456
  }
457

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

462
  initResultRowEntry(pResultInfo, pCtx->resDataInfo.interBufSize);
734,860,331✔
463
  return TSDB_CODE_SUCCESS;
734,860,331✔
464
}
465

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

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

479
  return code;
180,203,676✔
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) {
220,836✔
513
  SNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
220,836✔
514
  if (QUERY_NODE_COLUMN == nodeType(pParam) && PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pParam)->colId) {
220,899!
515
    return FUNC_DATA_REQUIRED_NOT_LOAD;
163,851✔
516
  }
517
  return FUNC_DATA_REQUIRED_SMA_LOAD;
57,048✔
518
}
519

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

525
static int64_t getNumOfElems(SqlFunctionCtx* pCtx) {
114,521,290✔
526
  int64_t numOfElem = 0;
114,521,290✔
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;
114,521,290✔
534
  SColumnInfoData*      pInputCol = pInput->pData[0];
114,521,290✔
535
  if (1 == pInput->numOfRows && pInput->blankFill) {
114,521,290✔
536
    return 0;
456,218✔
537
  }
538
  if (pInput->colDataSMAIsSet && pInput->totalRows == pInput->numOfRows) {
114,065,072✔
539
    numOfElem = pInput->numOfRows - pInput->pColumnDataAgg[0]->numOfNull;
4,004✔
540
  } else {
541
    if (pInputCol->hasNull) {
114,061,068✔
542
      for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
345,916,573✔
543
        if (colDataIsNull(pInputCol, pInput->totalRows, i, NULL)) {
634,994,974!
544
          continue;
4,225,456✔
545
        }
546
        numOfElem += 1;
313,272,031✔
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;
85,641,982✔
552
    }
553
  }
554
  return numOfElem;
114,065,072✔
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) {
114,693,312✔
562
  int64_t numOfElem = 0;
114,693,312✔
563

564
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
114,693,312✔
565
  SInputColumnInfoData* pInput = &pCtx->input;
114,693,312✔
566

567
  int32_t type = pInput->pData[0]->info.type;
114,693,312✔
568

569
  char* buf = GET_ROWCELL_INTERBUF(pResInfo);
114,693,312✔
570
  if (IS_NULL_TYPE(type)) {
114,693,312✔
571
    // select count(NULL) returns 0
572
    numOfElem = 1;
138,884✔
573
    *((int64_t*)buf) += 0;
138,884✔
574
  } else {
575
    numOfElem = getNumOfElems(pCtx);
114,554,428✔
576
    *((int64_t*)buf) += numOfElem;
114,280,454✔
577
  }
578

579
  if (tsCountAlwaysReturnValue) {
114,419,338!
580
    pResInfo->numOfRes = 1;
114,442,866✔
581
  } else {
582
    SET_VAL(pResInfo, *((int64_t*)buf), 1);
×
583
  }
584

585
  return TSDB_CODE_SUCCESS;
114,419,338✔
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) {
89,039,400✔
614
  int32_t numOfElem = 0;
89,039,400✔
615

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

621
  SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
89,039,400✔
622
  pSumRes->type = type;
89,039,400✔
623

624
  if (IS_NULL_TYPE(type)) {
89,039,400✔
625
    numOfElem = 0;
237✔
626
    goto _sum_over;
237✔
627
  }
628

629
  if (pInput->colDataSMAIsSet) {
89,039,163✔
630
    numOfElem = pInput->numOfRows - pAgg->numOfNull;
2,565✔
631

632
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
2,565!
633
      pSumRes->isum += pAgg->sum;
2,566✔
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];
89,036,598✔
641

642
    int32_t start = pInput->startRowIndex;
89,036,598✔
643
    int32_t numOfRows = pInput->numOfRows;
89,036,598✔
644

645
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
89,036,598!
646
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
85,163,740!
647
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int8_t, numOfElem);
1,421,798✔
648
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
84,817,454✔
649
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int16_t, numOfElem);
670,404✔
650
      } else if (type == TSDB_DATA_TYPE_INT) {
84,766,371✔
651
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int32_t, numOfElem);
405,118,578✔
652
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
18,840,345!
653
        LIST_ADD_N(pSumRes->isum, pCol, start, numOfRows, int64_t, numOfElem);
73,342,437✔
654
      }
655
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
3,872,858!
656
      if (type == TSDB_DATA_TYPE_UTINYINT) {
486✔
657
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint8_t, numOfElem);
130,039!
658
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
447✔
659
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint16_t, numOfElem);
130,047✔
660
      } else if (type == TSDB_DATA_TYPE_UINT) {
407✔
661
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint32_t, numOfElem);
133,317!
662
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
270!
663
        LIST_ADD_N(pSumRes->usum, pCol, start, numOfRows, uint64_t, numOfElem);
134,175✔
664
      }
665
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
3,872,372✔
666
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem);
4,195,710✔
667
    } else if (type == TSDB_DATA_TYPE_FLOAT) {
2,774,309✔
668
      LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem);
7,949,623✔
669
    }
670
  }
671

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

677
_sum_over:
89,434,873✔
678
  if (numOfElem == 0) {
89,039,400✔
679
    if (tsCountAlwaysReturnValue && pCtx->pExpr->pExpr->_function.pFunctNode->hasOriginalFunc &&
101,314✔
680
        fmIsCountLikeFunc(pCtx->pExpr->pExpr->_function.pFunctNode->originalFuncId)) {
11,557✔
681
      numOfElem = 1;
37✔
682
    }
683
  }
684
  // data in the check operation are all null, not output
685
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
89,039,400✔
686
  return TSDB_CODE_SUCCESS;
89,039,400✔
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) {
34✔
750
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
34✔
751
  SSumRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
34✔
752

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

757
  if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
34!
758
    pDBuf->isum += pSBuf->isum;
34✔
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);
34✔
765
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
34✔
766
  return TSDB_CODE_SUCCESS;
34✔
767
}
768

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

774
static bool funcNotSupportStringSma(SFunctionNode* pFunc) {
180,346✔
775
  SNode* pParam;
776
  switch (pFunc->funcType) {
180,346!
777
    case FUNCTION_TYPE_MAX:
180,346✔
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);
180,346✔
789
      if (pParam && nodesIsExprNode(pParam) && (IS_VAR_DATA_TYPE(((SExprNode*)pParam)->resType.type))) {
180,346!
790
        return true;
132✔
791
      }
792
      break;
180,214✔
793
    default:
×
794
      break;
×
795
  }
796
  return false;
180,214✔
797
}
798

799
EFuncDataRequired statisDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
180,346✔
800
  if(funcNotSupportStringSma(pFunc)) {
180,346✔
801
    return FUNC_DATA_REQUIRED_DATA_LOAD;
132✔
802
  }
803
  return FUNC_DATA_REQUIRED_SMA_LOAD;
180,214✔
804
}
805

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

814
  SMinmaxResInfo* buf = GET_ROWCELL_INTERBUF(pResultInfo);
46,211,237✔
815
  buf->assign = false;
46,211,237✔
816
  buf->tuplePos.pageId = -1;
46,211,237✔
817

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

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

829
int32_t minFunction(SqlFunctionCtx* pCtx) {
26,688,922✔
830
  int32_t numOfElems = 0;
26,688,922✔
831
  int32_t code = doMinMaxHelper(pCtx, 1, &numOfElems);
26,688,922✔
832
  if (code != TSDB_CODE_SUCCESS) {
26,740,901!
833
    return code;
×
834
  }
835
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
26,740,901✔
836
  return TSDB_CODE_SUCCESS;
26,740,901✔
837
}
838

839
int32_t maxFunction(SqlFunctionCtx* pCtx) {
24,401,257✔
840
  int32_t numOfElems = 0;
24,401,257✔
841
  int32_t code = doMinMaxHelper(pCtx, 0, &numOfElems);
24,401,257✔
842
  if (code != TSDB_CODE_SUCCESS) {
24,432,574!
843
    return code;
×
844
  }
845
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
24,432,574✔
846
  return TSDB_CODE_SUCCESS;
24,432,574✔
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) {
44,784,568✔
854
  int32_t code = TSDB_CODE_SUCCESS;
44,784,568✔
855

856
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
44,784,568✔
857
  SMinmaxResInfo*      pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
44,784,568✔
858

859
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
44,784,568✔
860
  int32_t currentRow = pBlock->info.rows;
44,784,568✔
861

862
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
44,784,568✔
863
  if (NULL == pCol) {
44,788,702!
864
    return TSDB_CODE_OUT_OF_RANGE;
×
865
  }
866
  pEntryInfo->isNullRes = (pEntryInfo->numOfRes == 0) ? 1 : 0;
44,788,702✔
867

868
  // NOTE: do nothing change it, for performance issue
869
  if (!pEntryInfo->isNullRes) {
44,788,702✔
870
    switch (pCol->info.type) {
38,342,783!
871
      case TSDB_DATA_TYPE_UBIGINT:
16,812,662✔
872
      case TSDB_DATA_TYPE_BIGINT:
873
        ((int64_t*)pCol->pData)[currentRow] = pRes->v;
16,812,662✔
874
        break;
16,812,662✔
875
      case TSDB_DATA_TYPE_UINT:
15,629,259✔
876
      case TSDB_DATA_TYPE_INT:
877
        colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v);
15,629,259✔
878
        break;
15,629,259✔
879
      case TSDB_DATA_TYPE_USMALLINT:
2,803,691✔
880
      case TSDB_DATA_TYPE_SMALLINT:
881
        colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v);
2,803,691✔
882
        break;
2,803,691✔
883
      case TSDB_DATA_TYPE_BOOL:
206,807✔
884
      case TSDB_DATA_TYPE_UTINYINT:
885
      case TSDB_DATA_TYPE_TINYINT:
886
        colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v);
206,807✔
887
        break;
206,807✔
888
      case TSDB_DATA_TYPE_DOUBLE:
7,025✔
889
        colDataSetDouble(pCol, currentRow, (double*)&pRes->v);
7,025✔
890
        break;
7,025✔
891
      case TSDB_DATA_TYPE_FLOAT: {
2,713✔
892
        float v = GET_FLOAT_VAL(&pRes->v);
2,713✔
893
        colDataSetFloat(pCol, currentRow, &v);
2,713✔
894
        break;
2,713✔
895
      }
896
      case TSDB_DATA_TYPE_VARBINARY:
2,886,067✔
897
      case TSDB_DATA_TYPE_VARCHAR:
898
      case TSDB_DATA_TYPE_NCHAR: {
899
        code = colDataSetVal(pCol, currentRow, pRes->str, false);
2,886,067✔
900
        if (TSDB_CODE_SUCCESS != code) {
2,886,067!
901
          return code;
×
902
        }
903
        break;
2,886,067✔
904
      }
905
    }
906
  } else {
907
    colDataSetNULL(pCol, currentRow);
6,445,919!
908
  }
909

910
  taosMemoryFreeClear(pRes->str);
44,788,702!
911
  if (pCtx->subsidiaries.num > 0) {
44,788,702✔
912
    if (pEntryInfo->numOfRes > 0) {
10,350,645✔
913
      code = setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow);
10,348,121✔
914
    } else {
915
      code = setNullSelectivityValue(pCtx, pBlock, currentRow);
2,524✔
916
    }
917
  }
918

919
  return code;
44,788,528✔
920
}
921

922
int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex) {
2,445,360✔
923
  if (pCtx->subsidiaries.num <= 0) {
2,445,360✔
924
    return TSDB_CODE_SUCCESS;
2,442,953✔
925
  }
926

927
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
6,888✔
928
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
4,481✔
929
    int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
4,481✔
930

931
    SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
4,481✔
932
    if (NULL == pDstCol) {
4,481!
933
      return terrno;
×
934
    }
935
    colDataSetNULL(pDstCol, rowIndex);
4,481✔
936
  }
937

938
  return TSDB_CODE_SUCCESS;
2,407✔
939
}
940

941
int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, int32_t rowIndex) {
270,894,909✔
942
  if (pCtx->subsidiaries.num <= 0) {
270,894,909✔
943
    return TSDB_CODE_SUCCESS;
121,170,076✔
944
  }
945

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

957
    bool* nullList = (bool*)p;
149,964,906✔
958
    char* pStart = (char*)(nullList + numOfCols * sizeof(bool));
149,964,906✔
959

960
    // todo set the offset value to optimize the performance.
961
    for (int32_t j = 0; j < numOfCols; ++j) {
299,918,073✔
962
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
149,984,350✔
963
      int32_t         dstSlotId = pc->pExpr->base.resSchema.slotId;
149,984,350✔
964

965
      SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
149,984,350✔
966
      if (NULL == pDstCol) {
149,955,432!
967
        return terrno;
×
968
      }
969
      if (nullList[j]) {
149,960,538✔
970
        colDataSetNULL(pDstCol, rowIndex);
168!
971
      } else {
972
        code = colDataSetValOrCover(pDstCol, rowIndex, pStart, false);
149,960,370✔
973
        if (TSDB_CODE_SUCCESS != code) {
149,952,999!
974
          return code;
×
975
        }
976
      }
977
      pStart += pDstCol->info.bytes;
149,953,167✔
978
    }
979
  }
980

981
  return TSDB_CODE_SUCCESS;
149,941,611✔
982
}
983

984
// This function append the selectivity to subsidiaries function context directly, without fetching data
985
// from intermediate disk based buf page
986
int32_t appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) {
57,384,448✔
987
  if (pCtx->subsidiaries.num <= 0) {
57,384,448!
988
    return TSDB_CODE_SUCCESS;
×
989
  }
990

991
  int32_t code = TSDB_CODE_SUCCESS;
57,384,448✔
992
  for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
114,772,319✔
993
    SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
57,389,532✔
994

995
    // get data from source col
996
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
57,389,532✔
997
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
57,389,532✔
998

999
    SColumnInfoData* pSrcCol = taosArrayGet(pCtx->pSrcBlock->pDataBlock, srcSlotId);
57,389,532✔
1000
    if (NULL == pSrcCol) {
57,376,288!
1001
      return TSDB_CODE_OUT_OF_RANGE;
×
1002
    }
1003

1004
    char* pData = colDataGetData(pSrcCol, rowIndex);
57,376,288!
1005

1006
    // append to dest col
1007
    int32_t dstSlotId = pc->pExpr->base.resSchema.slotId;
57,376,288✔
1008

1009
    SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId);
57,376,288✔
1010
    if (NULL == pDstCol) {
57,375,981!
1011
      return TSDB_CODE_OUT_OF_RANGE;
×
1012
    }
1013

1014
    if (colDataIsNull_s(pSrcCol, rowIndex) == true) {
114,751,962✔
1015
      colDataSetNULL(pDstCol, pos);
560✔
1016
    } else {
1017
      code = colDataSetVal(pDstCol, pos, pData, false);
57,375,421✔
1018
      if (TSDB_CODE_SUCCESS != code) {
57,387,311!
1019
        return code;
×
1020
      }
1021
    }
1022
  }
1023
  return code;
57,382,787✔
1024
}
1025

1026
void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; }
26✔
1027

1028
#define COMPARE_MINMAX_DATA(type) (((*(type*)&pDBuf->v) < (*(type*)&pSBuf->v)) ^ isMinFunc)
1029
int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) {
50✔
1030
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
50✔
1031
  SMinmaxResInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
50✔
1032

1033
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
50✔
1034
  SMinmaxResInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
50✔
1035
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
50✔
1036

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

1093
int32_t minCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
11✔
1094
  return minMaxCombine(pDestCtx, pSourceCtx, 1);
11✔
1095
}
1096
int32_t maxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
39✔
1097
  return minMaxCombine(pDestCtx, pSourceCtx, 0);
39✔
1098
}
1099

1100
int32_t getStdInfoSize() { return (int32_t)sizeof(SStdRes); }
791,643✔
1101

1102
bool getStdFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
152,324✔
1103
  pEnv->calcMemSize = sizeof(SStdRes);
152,324✔
1104
  return true;
152,324✔
1105
}
1106

1107
int32_t stdFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,388,369✔
1108
  if (pResultInfo->initialized) {
5,388,369!
1109
    return TSDB_CODE_SUCCESS;
×
1110
  }
1111
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,388,369!
1112
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1113
  }
1114

1115
  SStdRes* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
5,388,385✔
1116
  (void)memset(pRes, 0, sizeof(SStdRes));
5,388,385✔
1117
  return TSDB_CODE_SUCCESS;
5,388,385✔
1118
}
1119

1120
int32_t stdFunction(SqlFunctionCtx* pCtx) {
4,614,811✔
1121
  int32_t numOfElem = 0;
4,614,811✔
1122

1123
  // Only the pre-computing information loaded and actual data does not loaded
1124
  SInputColumnInfoData* pInput = &pCtx->input;
4,614,811✔
1125
  int32_t               type = pInput->pData[0]->info.type;
4,614,811✔
1126

1127
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,614,811✔
1128
  pStdRes->type = type;
4,614,811✔
1129

1130
  // computing based on the true data block
1131
  SColumnInfoData* pCol = pInput->pData[0];
4,614,811✔
1132

1133
  int32_t start = pInput->startRowIndex;
4,614,811✔
1134
  int32_t numOfRows = pInput->numOfRows;
4,614,811✔
1135

1136
  if (IS_NULL_TYPE(type)) {
4,614,811✔
1137
    numOfElem = 0;
141✔
1138
    goto _stddev_over;
141✔
1139
  }
1140

1141
  switch (type) {
4,614,670!
1142
    case TSDB_DATA_TYPE_TINYINT: {
11,908✔
1143
      int8_t* plist = (int8_t*)pCol->pData;
11,908✔
1144
      for (int32_t i = start; i < numOfRows + start; ++i) {
157,035✔
1145
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
145,127✔
1146
          continue;
29,987✔
1147
        }
1148

1149
        numOfElem += 1;
115,140✔
1150
        pStdRes->count += 1;
115,140✔
1151
        pStdRes->isum += plist[i];
115,140✔
1152
        pStdRes->quadraticISum += plist[i] * plist[i];
115,140✔
1153
      }
1154

1155
      break;
11,908✔
1156
    }
1157

1158
    case TSDB_DATA_TYPE_SMALLINT: {
248,224✔
1159
      int16_t* plist = (int16_t*)pCol->pData;
248,224✔
1160
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
915,033✔
1161
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
666,809✔
1162
          continue;
53,390✔
1163
        }
1164

1165
        numOfElem += 1;
613,419✔
1166
        pStdRes->count += 1;
613,419✔
1167
        pStdRes->isum += plist[i];
613,419✔
1168
        pStdRes->quadraticISum += plist[i] * plist[i];
613,419✔
1169
      }
1170
      break;
248,224✔
1171
    }
1172

1173
    case TSDB_DATA_TYPE_INT: {
2,011,145✔
1174
      int32_t* plist = (int32_t*)pCol->pData;
2,011,145✔
1175
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
6,897,365✔
1176
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
4,886,220✔
1177
          continue;
117,072✔
1178
        }
1179

1180
        numOfElem += 1;
4,769,148✔
1181
        pStdRes->count += 1;
4,769,148✔
1182
        pStdRes->isum += plist[i];
4,769,148✔
1183
        pStdRes->quadraticISum += plist[i] * plist[i];
4,769,148✔
1184
      }
1185

1186
      break;
2,011,145✔
1187
    }
1188

1189
    case TSDB_DATA_TYPE_BIGINT: {
25,503✔
1190
      int64_t* plist = (int64_t*)pCol->pData;
25,503✔
1191
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
749,551✔
1192
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
724,048✔
1193
          continue;
28,974✔
1194
        }
1195

1196
        numOfElem += 1;
695,074✔
1197
        pStdRes->count += 1;
695,074✔
1198
        pStdRes->isum += plist[i];
695,074✔
1199
        pStdRes->quadraticISum += plist[i] * plist[i];
695,074✔
1200
      }
1201
      break;
25,503✔
1202
    }
1203

1204
    case TSDB_DATA_TYPE_UTINYINT: {
25✔
1205
      uint8_t* plist = (uint8_t*)pCol->pData;
25✔
1206
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,032✔
1207
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,007!
1208
          continue;
4✔
1209
        }
1210

1211
        numOfElem += 1;
80,003✔
1212
        pStdRes->count += 1;
80,003✔
1213
        pStdRes->usum += plist[i];
80,003✔
1214
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,003✔
1215
      }
1216

1217
      break;
25✔
1218
    }
1219

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

1227
        numOfElem += 1;
80,000✔
1228
        pStdRes->count += 1;
80,000✔
1229
        pStdRes->usum += plist[i];
80,000✔
1230
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1231
      }
1232
      break;
24✔
1233
    }
1234

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

1242
        numOfElem += 1;
80,005✔
1243
        pStdRes->count += 1;
80,005✔
1244
        pStdRes->usum += plist[i];
80,005✔
1245
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,005✔
1246
      }
1247

1248
      break;
25✔
1249
    }
1250

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

1258
        numOfElem += 1;
80,000✔
1259
        pStdRes->count += 1;
80,000✔
1260
        pStdRes->usum += plist[i];
80,000✔
1261
        pStdRes->quadraticUSum += plist[i] * plist[i];
80,000✔
1262
      }
1263
      break;
24✔
1264
    }
1265

1266
    case TSDB_DATA_TYPE_FLOAT: {
22,226✔
1267
      float* plist = (float*)pCol->pData;
22,226✔
1268
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
2,637,302✔
1269
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
2,615,076✔
1270
          continue;
183,281✔
1271
        }
1272

1273
        numOfElem += 1;
2,431,795✔
1274
        pStdRes->count += 1;
2,431,795✔
1275
        pStdRes->dsum += plist[i];
2,431,795✔
1276
        pStdRes->quadraticDSum += plist[i] * plist[i];
2,431,795✔
1277
      }
1278
      break;
22,226✔
1279
    }
1280

1281
    case TSDB_DATA_TYPE_DOUBLE: {
2,295,577✔
1282
      double* plist = (double*)pCol->pData;
2,295,577✔
1283
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
8,894,677✔
1284
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
6,599,100✔
1285
          continue;
456,479✔
1286
        }
1287

1288
        numOfElem += 1;
6,142,621✔
1289
        pStdRes->count += 1;
6,142,621✔
1290
        pStdRes->dsum += plist[i];
6,142,621✔
1291
        pStdRes->quadraticDSum += plist[i] * plist[i];
6,142,621✔
1292
      }
1293
      break;
2,295,577✔
1294
    }
1295

1296
    default:
×
1297
      break;
×
1298
  }
1299

1300
_stddev_over:
4,614,811✔
1301
  // data in the check operation are all null, not output
1302
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
4,614,811✔
1303
  return TSDB_CODE_SUCCESS;
4,614,811✔
1304
}
1305

1306
static void stdTransferInfo(SStdRes* pInput, SStdRes* pOutput) {
790,119✔
1307
  if (IS_NULL_TYPE(pInput->type)) {
790,119✔
1308
    return;
80✔
1309
  }
1310
  pOutput->type = pInput->type;
790,039✔
1311
  if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) {
790,039!
1312
    pOutput->quadraticISum += pInput->quadraticISum;
789,834✔
1313
    pOutput->isum += pInput->isum;
789,834✔
1314
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) {
205!
1315
    pOutput->quadraticUSum += pInput->quadraticUSum;
1✔
1316
    pOutput->usum += pInput->usum;
1✔
1317
  } else {
1318
    pOutput->quadraticDSum += pInput->quadraticDSum;
204✔
1319
    pOutput->dsum += pInput->dsum;
204✔
1320
  }
1321

1322
  pOutput->count += pInput->count;
790,039✔
1323
}
1324

1325
int32_t stdFunctionMerge(SqlFunctionCtx* pCtx) {
790,036✔
1326
  SInputColumnInfoData* pInput = &pCtx->input;
790,036✔
1327
  SColumnInfoData*      pCol = pInput->pData[0];
790,036✔
1328

1329
  if (IS_NULL_TYPE(pCol->info.type)) {
790,036!
1330
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
1331
    return TSDB_CODE_SUCCESS;
×
1332
  }
1333

1334
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
790,036!
1335
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1336
  }
1337

1338
  SStdRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
790,036✔
1339

1340
  for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
1,580,152✔
1341
    if (colDataIsNull_s(pCol, i)) continue;
1,580,232!
1342
    char*    data = colDataGetData(pCol, i);
790,116!
1343
    SStdRes* pInputInfo = (SStdRes*)varDataVal(data);
790,116✔
1344
    stdTransferInfo(pInputInfo, pInfo);
790,116✔
1345
  }
1346

1347
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
790,036✔
1348
  return TSDB_CODE_SUCCESS;
790,036✔
1349
}
1350

1351
#ifdef BUILD_NO_CALL
1352
int32_t stdInvertFunction(SqlFunctionCtx* pCtx) {
1353
  int32_t numOfElem = 0;
1354

1355
  // Only the pre-computing information loaded and actual data does not loaded
1356
  SInputColumnInfoData* pInput = &pCtx->input;
1357
  int32_t               type = pInput->pData[0]->info.type;
1358

1359
  SStdRes* pStdRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1360

1361
  // computing based on the true data block
1362
  SColumnInfoData* pCol = pInput->pData[0];
1363

1364
  int32_t start = pInput->startRowIndex;
1365
  int32_t numOfRows = pInput->numOfRows;
1366

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

1412
  // data in the check operation are all null, not output
1413
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
1414
  return TSDB_CODE_SUCCESS;
1415
}
1416
#endif
1417

1418
int32_t stddevFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,559,566✔
1419
  SInputColumnInfoData* pInput = &pCtx->input;
4,559,566✔
1420
  SStdRes*              pStddevRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
4,559,566✔
1421
  int32_t               type = pStddevRes->type;
4,559,566✔
1422
  double                avg;
1423

1424
  if (pStddevRes->count == 0) {
4,559,566✔
1425
    GET_RES_INFO(pCtx)->numOfRes = 0;
55,988✔
1426
    return functionFinalize(pCtx, pBlock);
55,988✔
1427
  }
1428

1429
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,503,578!
1430
    avg = pStddevRes->isum / ((double)pStddevRes->count);
2,218,000✔
1431
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticISum / ((double)pStddevRes->count) - avg * avg));
2,218,000✔
1432
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,285,578!
1433
    avg = pStddevRes->usum / ((double)pStddevRes->count);
10✔
1434
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticUSum / ((double)pStddevRes->count) - avg * avg));
10✔
1435
  } else {
1436
    avg = pStddevRes->dsum / ((double)pStddevRes->count);
2,285,568✔
1437
    pStddevRes->result = sqrt(fabs(pStddevRes->quadraticDSum / ((double)pStddevRes->count) - avg * avg));
2,285,568✔
1438
  }
1439

1440
  // check for overflow
1441
  if (isinf(pStddevRes->result) || isnan(pStddevRes->result)) {
4,503,578!
1442
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1443
  }
1444

1445
  return functionFinalize(pCtx, pBlock);
4,503,578✔
1446
}
1447

1448
int32_t stdvarFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
1449
  SInputColumnInfoData* pInput = &pCtx->input;
×
1450
  SStdRes*              pStdvarRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1451
  int32_t               type = pStdvarRes->type;
×
1452
  double                avg;
1453

1454
  if (pStdvarRes->count == 0) {
×
1455
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1456
    return functionFinalize(pCtx, pBlock);
×
1457
  }
1458

1459
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
1460
    avg = pStdvarRes->isum / ((double)pStdvarRes->count);
×
1461
    pStdvarRes->result = fabs(pStdvarRes->quadraticISum / ((double)pStdvarRes->count) - avg * avg);
×
1462
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1463
    avg = pStdvarRes->usum / ((double)pStdvarRes->count);
×
1464
    pStdvarRes->result = fabs(pStdvarRes->quadraticUSum / ((double)pStdvarRes->count) - avg * avg);
×
1465
  } else {
1466
    avg = pStdvarRes->dsum / ((double)pStdvarRes->count);
×
1467
    pStdvarRes->result = fabs(pStdvarRes->quadraticDSum / ((double)pStdvarRes->count) - avg * avg);
×
1468
  }
1469

1470
  // check for overflow
1471
  if (isinf(pStdvarRes->result) || isnan(pStdvarRes->result)) {
×
1472
    GET_RES_INFO(pCtx)->numOfRes = 0;
×
1473
  }
1474

1475
  return functionFinalize(pCtx, pBlock);
×
1476
}
1477

1478
int32_t stdPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
790,029✔
1479
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
790,029✔
1480
  SStdRes*             pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
790,029✔
1481
  int32_t              resultBytes = getStdInfoSize();
790,029✔
1482
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
790,029!
1483

1484
  if (NULL == res) {
790,030!
1485
    return terrno;
×
1486
  }
1487
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
790,030✔
1488
  varDataSetLen(res, resultBytes);
790,030✔
1489

1490
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
790,030✔
1491
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
790,030✔
1492
  if (NULL == pCol) {
790,030!
1493
    taosMemoryFree(res);
×
1494
    return TSDB_CODE_OUT_OF_RANGE;
×
1495
  }
1496

1497
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
790,030✔
1498

1499
  taosMemoryFree(res);
790,030!
1500
  return code;
790,030✔
1501
}
1502

1503
int32_t stdCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
1504
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
1505
  SStdRes*             pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
1506

1507
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
1508
  SStdRes*             pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
1509
  int16_t              type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type;
3!
1510

1511
  stdTransferInfo(pSBuf, pDBuf);
3✔
1512

1513
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
1514
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
1515
  return TSDB_CODE_SUCCESS;
3✔
1516
}
1517

1518
bool getLeastSQRFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
43,152✔
1519
  pEnv->calcMemSize = sizeof(SLeastSQRInfo);
43,152✔
1520
  return true;
43,152✔
1521
}
1522

1523
int32_t leastSQRFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
5,422,397✔
1524
  if (pResultInfo->initialized) {
5,422,397!
1525
    return TSDB_CODE_SUCCESS;
×
1526
  }
1527
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
5,422,397!
1528
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1529
  }
1530

1531
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5,422,398✔
1532

1533
  GET_TYPED_DATA(pInfo->startVal, double, pCtx->param[1].param.nType, &pCtx->param[1].param.i);
5,422,398!
1534
  GET_TYPED_DATA(pInfo->stepVal, double, pCtx->param[2].param.nType, &pCtx->param[2].param.i);
5,422,398!
1535
  return TSDB_CODE_SUCCESS;
5,422,398✔
1536
}
1537

1538
int32_t leastSQRFunction(SqlFunctionCtx* pCtx) {
6,329,676✔
1539
  int32_t numOfElem = 0;
6,329,676✔
1540

1541
  SInputColumnInfoData* pInput = &pCtx->input;
6,329,676✔
1542
  int32_t               type = pInput->pData[0]->info.type;
6,329,676✔
1543

1544
  SLeastSQRInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
6,329,676✔
1545

1546
  SColumnInfoData* pCol = pInput->pData[0];
6,329,676✔
1547

1548
  double(*param)[3] = pInfo->matrix;
6,329,676✔
1549
  double x = pInfo->startVal;
6,329,676✔
1550

1551
  int32_t start = pInput->startRowIndex;
6,329,676✔
1552
  int32_t numOfRows = pInput->numOfRows;
6,329,676✔
1553

1554
  switch (type) {
6,329,676!
1555
    case TSDB_DATA_TYPE_TINYINT: {
1,863,150✔
1556
      int8_t* plist = (int8_t*)pCol->pData;
1,863,150✔
1557
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
5,817,243✔
1558
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
3,954,093✔
1559
          continue;
2,260✔
1560
        }
1561
        numOfElem++;
3,951,833✔
1562
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
3,951,833✔
1563
      }
1564
      break;
1,863,150✔
1565
    }
1566
    case TSDB_DATA_TYPE_SMALLINT: {
8,579✔
1567
      int16_t* plist = (int16_t*)pCol->pData;
8,579✔
1568
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
990,100✔
1569
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
981,521✔
1570
          continue;
4,060✔
1571
        }
1572

1573
        numOfElem++;
977,461✔
1574
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
977,461✔
1575
      }
1576
      break;
8,579✔
1577
    }
1578

1579
    case TSDB_DATA_TYPE_INT: {
15,327✔
1580
      int32_t* plist = (int32_t*)pCol->pData;
15,327✔
1581
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
687,243✔
1582
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
671,916✔
1583
          continue;
149,474✔
1584
        }
1585

1586
        numOfElem++;
522,442✔
1587
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
522,442✔
1588
      }
1589
      break;
15,327✔
1590
    }
1591

1592
    case TSDB_DATA_TYPE_BIGINT: {
4,813✔
1593
      int64_t* plist = (int64_t*)pCol->pData;
4,813✔
1594
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
470,199✔
1595
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
465,386✔
1596
          continue;
1,860✔
1597
        }
1598

1599
        numOfElem++;
463,526✔
1600
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
463,526✔
1601
      }
1602
      break;
4,813✔
1603
    }
1604

1605
    case TSDB_DATA_TYPE_UTINYINT: {
154✔
1606
      uint8_t* plist = (uint8_t*)pCol->pData;
154✔
1607
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1608
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1609
          continue;
110✔
1610
        }
1611
        numOfElem++;
80,310✔
1612
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,310✔
1613
      }
1614
      break;
154✔
1615
    }
1616
    case TSDB_DATA_TYPE_USMALLINT: {
154✔
1617
      uint16_t* plist = (uint16_t*)pCol->pData;
154✔
1618
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1619
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1620
          continue;
100✔
1621
        }
1622

1623
        numOfElem++;
80,320✔
1624
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1625
      }
1626
      break;
154✔
1627
    }
1628

1629
    case TSDB_DATA_TYPE_UINT: {
154✔
1630
      uint32_t* plist = (uint32_t*)pCol->pData;
154✔
1631
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1632
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1633
          continue;
100✔
1634
        }
1635

1636
        numOfElem++;
80,320✔
1637
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1638
      }
1639
      break;
154✔
1640
    }
1641

1642
    case TSDB_DATA_TYPE_UBIGINT: {
154✔
1643
      uint64_t* plist = (uint64_t*)pCol->pData;
154✔
1644
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
80,574✔
1645
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
80,420!
1646
          continue;
100✔
1647
        }
1648

1649
        numOfElem++;
80,320✔
1650
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
80,320✔
1651
      }
1652
      break;
154✔
1653
    }
1654

1655
    case TSDB_DATA_TYPE_FLOAT: {
10,168✔
1656
      float* plist = (float*)pCol->pData;
10,168✔
1657
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
613,240✔
1658
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
603,072✔
1659
          continue;
285,892✔
1660
        }
1661

1662
        numOfElem++;
317,180✔
1663
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
317,180✔
1664
      }
1665
      break;
10,168✔
1666
    }
1667

1668
    case TSDB_DATA_TYPE_DOUBLE: {
4,427,025✔
1669
      double* plist = (double*)pCol->pData;
4,427,025✔
1670
      for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) {
15,398,643✔
1671
        if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
10,971,618✔
1672
          continue;
2,060✔
1673
        }
1674

1675
        numOfElem++;
10,969,558✔
1676
        LEASTSQR_CAL(param, x, plist, i, pInfo->stepVal);
10,969,558✔
1677
      }
1678
      break;
4,427,025✔
1679
    }
1680
    case TSDB_DATA_TYPE_NULL: {
×
1681
      GET_RES_INFO(pCtx)->isNullRes = 1;
×
1682
      numOfElem = 1;
×
1683
      break;
×
1684
    }
1685

1686
    default:
×
1687
      break;
×
1688
  }
1689

1690
  pInfo->startVal = x;
6,329,676✔
1691
  pInfo->num += numOfElem;
6,329,676✔
1692

1693
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
6,329,676✔
1694

1695
  return TSDB_CODE_SUCCESS;
6,329,676✔
1696
}
1697

1698
int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
5,420,380✔
1699
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5,420,380✔
1700
  SLeastSQRInfo*       pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
5,420,380✔
1701
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
5,420,380✔
1702
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5,420,380✔
1703

1704
  if (NULL == pCol) {
5,420,379!
1705
    return TSDB_CODE_OUT_OF_RANGE;
×
1706
  }
1707
  int32_t currentRow = pBlock->info.rows;
5,420,379✔
1708

1709
  if (0 == pInfo->num) {
5,420,379✔
1710
    colDataSetNULL(pCol, currentRow);
21,253!
1711
    return TSDB_CODE_SUCCESS;
21,253✔
1712
  }
1713

1714
  double(*param)[3] = pInfo->matrix;
5,399,126✔
1715

1716
  param[1][1] = (double)pInfo->num;
5,399,126✔
1717
  param[1][0] = param[0][1];
5,399,126✔
1718

1719
  double param00 = param[0][0] - param[1][0] * (param[0][1] / param[1][1]);
5,399,126✔
1720
  double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]);
5,399,126✔
1721

1722
  if (0 == param00) {
5,399,126✔
1723
    colDataSetNULL(pCol, currentRow);
3,854,891!
1724
    return TSDB_CODE_SUCCESS;
3,854,891✔
1725
  }
1726

1727
  // param[0][1] = 0;
1728
  double param12 = param[1][2] - param02 * (param[1][0] / param00);
1,544,235✔
1729
  // param[1][0] = 0;
1730
  param02 /= param00;
1,544,235✔
1731

1732
  param12 /= param[1][1];
1,544,235✔
1733

1734
  char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
1,544,235✔
1735
  char slopBuf[64] = {0};
1,544,235✔
1736
  char interceptBuf[64] = {0};
1,544,235✔
1737
  int  n = tsnprintf(slopBuf, 64, "%.6lf", param02);
1,544,235✔
1738
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,544,236✔
1739
    (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param02);
78✔
1740
  }
1741
  n = tsnprintf(interceptBuf, 64, "%.6lf", param12);
1,544,236✔
1742
  if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
1,544,238✔
1743
    (void)snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, param12);
518✔
1744
  }
1745
  size_t len =
1,544,238✔
1746
      snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
1,544,238✔
1747
  varDataSetLen(buf, len);
1,544,238✔
1748

1749
  int32_t code = colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes);
1,544,238✔
1750

1751
  return code;
1,544,237✔
1752
}
1753

1754
int32_t leastSQRCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
1755
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
1756
  SLeastSQRInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
1757
  int32_t              type = pDestCtx->input.pData[0]->info.type;
×
1758
  double(*pDparam)[3] = pDBuf->matrix;
×
1759

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

1776
bool getPercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
929✔
1777
  pEnv->calcMemSize = sizeof(SPercentileInfo);
929✔
1778
  return true;
929✔
1779
}
1780

1781
int32_t percentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
4,727✔
1782
  if (pResultInfo->initialized) {
4,727!
1783
    return TSDB_CODE_SUCCESS;
×
1784
  }
1785
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
4,727!
1786
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
1787
  }
1788

1789
  // in the first round, get the min-max value of all involved data
1790
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
4,727✔
1791
  SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
4,727✔
1792
  SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
4,727✔
1793
  pInfo->numOfElems = 0;
4,727✔
1794

1795
  return TSDB_CODE_SUCCESS;
4,727✔
1796
}
1797

1798
void percentileFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
1799
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
1800
    return;
×
1801
  }
1802
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
1803
  if (pInfo->pMemBucket != NULL) {
×
1804
    tMemBucketDestroy(&(pInfo->pMemBucket));
×
1805
    pInfo->pMemBucket = NULL;
×
1806
  }
1807
}
1808

1809
int32_t percentileFunction(SqlFunctionCtx* pCtx) {
3,243,734✔
1810
  int32_t              code = TSDB_CODE_SUCCESS;
3,243,734✔
1811
  int32_t              numOfElems = 0;
3,243,734✔
1812
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
3,243,734✔
1813

1814
  SInputColumnInfoData* pInput = &pCtx->input;
3,243,734✔
1815
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
3,243,734✔
1816

1817
  SColumnInfoData* pCol = pInput->pData[0];
3,243,734✔
1818
  int32_t          type = pCol->info.type;
3,243,734✔
1819

1820
  SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,243,734✔
1821
  if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) {
3,243,734✔
1822
    pInfo->stage += 1;
4,727✔
1823

1824
    // all data are null, set it completed
1825
    if (pInfo->numOfElems == 0) {
4,727✔
1826
      pResInfo->complete = true;
1,004✔
1827
      return TSDB_CODE_SUCCESS;
1,004✔
1828
    } else {
1829
      code = tMemBucketCreate(pCol->info.bytes, type, pInfo->minval, pInfo->maxval, pCtx->hasWindowOrGroup,
3,723✔
1830
                              &pInfo->pMemBucket, pInfo->numOfElems);
3,723✔
1831
      if (TSDB_CODE_SUCCESS != code) {
3,723!
1832
        return code;
×
1833
      }
1834
    }
1835
  }
1836

1837
  // the first stage, only acquire the min/max value
1838
  if (pInfo->stage == 0) {
3,242,730✔
1839
    if (pCtx->input.colDataSMAIsSet) {
1,621,867✔
1840
      double tmin = 0.0, tmax = 0.0;
1,615,950✔
1841
      if (IS_SIGNED_NUMERIC_TYPE(type)) {
1,615,950!
1842
        tmin = (double)GET_INT64_VAL(&pAgg->min);
×
1843
        tmax = (double)GET_INT64_VAL(&pAgg->max);
×
1844
      } else if (IS_FLOAT_TYPE(type)) {
1,615,950!
1845
        tmin = GET_DOUBLE_VAL(&pAgg->min);
1,615,950✔
1846
        tmax = GET_DOUBLE_VAL(&pAgg->max);
1,615,950✔
1847
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
1848
        tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
1849
        tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
1850
      }
1851

1852
      if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
1,615,950✔
1853
        SET_DOUBLE_VAL(&pInfo->minval, tmin);
14✔
1854
      }
1855

1856
      if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
1,615,950✔
1857
        SET_DOUBLE_VAL(&pInfo->maxval, tmax);
14✔
1858
      }
1859

1860
      pInfo->numOfElems += (pInput->numOfRows - pAgg->numOfNull);
1,615,950✔
1861
    } else {
1862
      // check the valid data one by one
1863
      int32_t start = pInput->startRowIndex;
5,917✔
1864
      for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,079,740✔
1865
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,073,823✔
1866
          continue;
1,400✔
1867
        }
1868

1869
        char* data = colDataGetData(pCol, i);
1,072,423!
1870

1871
        double v = 0;
1,072,423✔
1872
        GET_TYPED_DATA(v, double, type, data);
1,072,423!
1873
        if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
1,072,423✔
1874
          SET_DOUBLE_VAL(&pInfo->minval, v);
3,961✔
1875
        }
1876

1877
        if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
1,072,423✔
1878
          SET_DOUBLE_VAL(&pInfo->maxval, v);
410,979✔
1879
        }
1880

1881
        pInfo->numOfElems += 1;
1,072,423✔
1882
      }
1883
    }
1884
  } else {
1885
    // the second stage, calculate the true percentile value
1886
    int32_t start = pInput->startRowIndex;
1,620,863✔
1887
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
2,147,483,647✔
1888
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
2,147,483,647!
1889
        continue;
×
1890
      }
1891

1892
      char* data = colDataGetData(pCol, i);
2,147,483,647!
1893
      numOfElems += 1;
2,147,483,647✔
1894
      code = tMemBucketPut(pInfo->pMemBucket, data, 1);
2,147,483,647✔
1895
      if (code != TSDB_CODE_SUCCESS) {
2,147,483,647!
1896
        tMemBucketDestroy(&(pInfo->pMemBucket));
×
1897
        return code;
×
1898
      }
1899
    }
1900

1901
    SET_VAL(pResInfo, numOfElems, 1);
1,620,863!
1902
  }
1903

1904
  pCtx->needCleanup = true;
3,242,730✔
1905
  return TSDB_CODE_SUCCESS;
3,242,730✔
1906
}
1907

1908
int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
4,727✔
1909
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
4,727✔
1910
  SPercentileInfo*     ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
4,727✔
1911

1912
  int32_t code = 0;
4,727✔
1913
  double  v = 0;
4,727✔
1914

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

1923
      varDataVal(buf)[0] = '[';
34✔
1924
      for (int32_t i = 1; i < pCtx->numOfParams; ++i) {
342✔
1925
        SVariant* pVal = &pCtx->param[i].param;
308✔
1926

1927
        GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
308!
1928

1929
        code = getPercentile((*pMemBucket), v, &ppInfo->result);
308✔
1930
        if (code != TSDB_CODE_SUCCESS) {
308!
1931
          goto _fin_error;
×
1932
        }
1933

1934
        if (i == pCtx->numOfParams - 1) {
308✔
1935
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result);
34✔
1936
        } else {
1937
          len += tsnprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result);
274✔
1938
        }
1939
      }
1940

1941
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
34✔
1942
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
34✔
1943
      if (NULL == pCol) {
34!
1944
        code = terrno;
×
1945
        goto _fin_error;
×
1946
      }
1947

1948
      varDataSetLen(buf, len);
34✔
1949
      code = colDataSetVal(pCol, pBlock->info.rows, buf, false);
34✔
1950
      if (code != TSDB_CODE_SUCCESS) {
34!
1951
        goto _fin_error;
×
1952
      }
1953

1954
      tMemBucketDestroy(pMemBucket);
34✔
1955
      return TSDB_CODE_SUCCESS;
34✔
1956
    } else {
1957
      SVariant* pVal = &pCtx->param[1].param;
3,689✔
1958

1959
      GET_TYPED_DATA(v, double, pVal->nType, &pVal->i);
3,689!
1960

1961
      code = getPercentile((*pMemBucket), v, &ppInfo->result);
3,689✔
1962
      if (code != TSDB_CODE_SUCCESS) {
3,689!
1963
        goto _fin_error;
×
1964
      }
1965

1966
      tMemBucketDestroy(pMemBucket);
3,689✔
1967
      return functionFinalize(pCtx, pBlock);
3,689✔
1968
    }
1969
  } else {
1970
    return functionFinalize(pCtx, pBlock);
1,004✔
1971
  }
1972

1973
_fin_error:
×
1974

1975
  tMemBucketDestroy(pMemBucket);
×
1976
  return code;
×
1977
}
1978

1979
bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
75,173✔
1980
  int32_t bytesHist =
75,173✔
1981
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1982
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
75,173✔
1983
  pEnv->calcMemSize = TMAX(bytesHist, bytesDigest);
75,173✔
1984
  return true;
75,173✔
1985
}
1986

1987
int32_t getApercentileMaxSize() {
10,116✔
1988
  int32_t bytesHist =
10,116✔
1989
      (int32_t)(sizeof(SAPercentileInfo) + sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
1990
  int32_t bytesDigest = (int32_t)(sizeof(SAPercentileInfo) + TDIGEST_SIZE(COMPRESSION));
10,116✔
1991
  return TMAX(bytesHist, bytesDigest);
10,116✔
1992
}
1993

1994
static int8_t getApercentileAlgo(char* algoStr) {
24,905✔
1995
  int8_t algoType;
1996
  if (strcasecmp(algoStr, "default") == 0) {
24,905✔
1997
    algoType = APERCT_ALGO_DEFAULT;
11,145✔
1998
  } else if (strcasecmp(algoStr, "t-digest") == 0) {
13,760✔
1999
    algoType = APERCT_ALGO_TDIGEST;
13,756✔
2000
  } else {
2001
    algoType = APERCT_ALGO_UNKNOWN;
4✔
2002
  }
2003

2004
  return algoType;
24,905✔
2005
}
2006

2007
static void buildHistogramInfo(SAPercentileInfo* pInfo) {
899,708✔
2008
  pInfo->pHisto = (SHistogramInfo*)((char*)pInfo + sizeof(SAPercentileInfo));
899,708✔
2009
  pInfo->pHisto->elems = (SHistBin*)((char*)pInfo->pHisto + sizeof(SHistogramInfo));
899,708✔
2010
}
899,708✔
2011

2012
static void buildTDigestInfo(SAPercentileInfo* pInfo) {
28,421✔
2013
  pInfo->pTDigest = (TDigest*)((char*)pInfo + sizeof(SAPercentileInfo));
28,421✔
2014
}
28,421✔
2015

2016
int32_t apercentileFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
316,296✔
2017
  if (pResultInfo->initialized) {
316,296!
2018
    return TSDB_CODE_SUCCESS;
×
2019
  }
2020
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
316,296!
2021
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2022
  }
2023

2024
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
316,315✔
2025

2026
  SVariant* pVal = &pCtx->param[1].param;
316,315✔
2027
  pInfo->percent = 0;
316,315✔
2028
  GET_TYPED_DATA(pInfo->percent, double, pVal->nType, &pVal->i);
316,315!
2029

2030
  if (pCtx->numOfParams == 2) {
316,315✔
2031
    pInfo->algo = APERCT_ALGO_DEFAULT;
291,414✔
2032
  } else if (pCtx->numOfParams == 3) {
24,901!
2033
    pInfo->algo = getApercentileAlgo(varDataVal(pCtx->param[2].param.pz));
24,906✔
2034
    if (pInfo->algo == APERCT_ALGO_UNKNOWN) {
24,898!
2035
      return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
2036
    }
2037
  }
2038

2039
  char* tmp = (char*)pInfo + sizeof(SAPercentileInfo);
316,307✔
2040
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
316,307✔
2041
    pInfo->pTDigest = tdigestNewFrom(tmp, COMPRESSION);
13,755✔
2042
  } else {
2043
    buildHistogramInfo(pInfo);
302,552✔
2044
    pInfo->pHisto = tHistogramCreateFrom(tmp, MAX_HISTOGRAM_BIN);
302,557✔
2045
    qDebug("%s set up histogram, numOfElems:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
302,574✔
2046
           pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2047
  }
2048

2049
  return TSDB_CODE_SUCCESS;
316,329✔
2050
}
2051

2052
int32_t apercentileFunction(SqlFunctionCtx* pCtx) {
321,751✔
2053
  int32_t               numOfElems = 0;
321,751✔
2054
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
321,751✔
2055
  SInputColumnInfoData* pInput = &pCtx->input;
321,751✔
2056

2057
  SColumnInfoData* pCol = pInput->pData[0];
321,751✔
2058
  int32_t          type = pCol->info.type;
321,751✔
2059

2060
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
321,751✔
2061

2062
  int32_t start = pInput->startRowIndex;
321,751✔
2063
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
321,751✔
2064
    buildTDigestInfo(pInfo);
13,754✔
2065
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
13,753✔
2066
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
1,960,262✔
2067
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,946,448✔
2068
        continue;
215,557✔
2069
      }
2070
      numOfElems += 1;
1,730,891✔
2071
      char* data = colDataGetData(pCol, i);
1,730,891!
2072

2073
      double  v = 0;  // value
1,730,891✔
2074
      int64_t w = 1;  // weigth
1,730,891✔
2075
      GET_TYPED_DATA(v, double, type, data);
1,730,891✔
2076
      int32_t code = tdigestAdd(pInfo->pTDigest, v, w);
1,730,891✔
2077
      if (code != TSDB_CODE_SUCCESS) {
1,730,954!
2078
        return code;
×
2079
      }
2080
    }
2081
  } else {
2082
    // might be a race condition here that pHisto can be overwritten or setup function
2083
    // has not been called, need to relink the buffer pHisto points to.
2084
    buildHistogramInfo(pInfo);
307,997✔
2085
    qDebug("%s before add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
307,988✔
2086
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2087
           pInfo->pHisto->elems);
2088
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
3,806,502✔
2089
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
3,498,539✔
2090
        continue;
691,668✔
2091
      }
2092
      numOfElems += 1;
2,806,871✔
2093
      char* data = colDataGetData(pCol, i);
2,806,871!
2094

2095
      double v = 0;
2,806,871✔
2096
      GET_TYPED_DATA(v, double, type, data);
2,806,871✔
2097
      int32_t code = tHistogramAdd(&pInfo->pHisto, v);
2,806,871✔
2098
      if (code != TSDB_CODE_SUCCESS) {
2,806,844!
2099
        return code;
×
2100
      }
2101
    }
2102

2103
    qDebug("%s after add %d elements into histogram, total:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems: %p",
307,963✔
2104
           __FUNCTION__, numOfElems, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto,
2105
           pInfo->pHisto->elems);
2106
  }
2107

2108
  SET_VAL(pResInfo, numOfElems, 1);
321,735✔
2109
  return TSDB_CODE_SUCCESS;
321,735✔
2110
}
2111

2112
static int32_t apercentileTransferInfo(SAPercentileInfo* pInput, SAPercentileInfo* pOutput, bool* hasRes) {
8,720✔
2113
  pOutput->percent = pInput->percent;
8,720✔
2114
  pOutput->algo = pInput->algo;
8,720✔
2115
  if (pOutput->algo == APERCT_ALGO_TDIGEST) {
8,720✔
2116
    buildTDigestInfo(pInput);
913✔
2117
    tdigestAutoFill(pInput->pTDigest, COMPRESSION);
913✔
2118

2119
    if (pInput->pTDigest->num_centroids == 0 && pInput->pTDigest->num_buffered_pts == 0) {
913✔
2120
      return TSDB_CODE_SUCCESS;
1✔
2121
    }
2122

2123
    if (hasRes) {
912✔
2124
      *hasRes = true;
910✔
2125
    }
2126

2127
    buildTDigestInfo(pOutput);
912✔
2128
    TDigest* pTDigest = pOutput->pTDigest;
912✔
2129
    tdigestAutoFill(pTDigest, COMPRESSION);
912✔
2130

2131
    if (pTDigest->num_centroids <= 0 && pTDigest->num_buffered_pts == 0) {
912!
2132
      (void)memcpy(pTDigest, pInput->pTDigest, (size_t)TDIGEST_SIZE(COMPRESSION));
910✔
2133
      tdigestAutoFill(pTDigest, COMPRESSION);
910✔
2134
    } else {
2135
      int32_t code = tdigestMerge(pTDigest, pInput->pTDigest);
2✔
2136
      if (TSDB_CODE_SUCCESS != code) {
2!
2137
        return code;
×
2138
      }
2139
    }
2140
  } else {
2141
    buildHistogramInfo(pInput);
7,807✔
2142
    if (pInput->pHisto->numOfElems <= 0) {
7,807✔
2143
      return TSDB_CODE_SUCCESS;
205✔
2144
    }
2145

2146
    if (hasRes) {
7,602✔
2147
      *hasRes = true;
7,600✔
2148
    }
2149

2150
    buildHistogramInfo(pOutput);
7,602✔
2151
    SHistogramInfo* pHisto = pOutput->pHisto;
7,602✔
2152

2153
    if (pHisto->numOfElems <= 0) {
7,602✔
2154
      (void)memcpy(pHisto, pInput->pHisto, sizeof(SHistogramInfo) + sizeof(SHistBin) * (MAX_HISTOGRAM_BIN + 1));
7,255✔
2155
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
7,255✔
2156

2157
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
7,255✔
2158
             pHisto);
2159
    } else {
2160
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
347✔
2161
      qDebug("%s input histogram, elem:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems,
347✔
2162
             pHisto->numOfEntries, pInput->pHisto);
2163

2164
      SHistogramInfo* pRes = NULL;
347✔
2165
      int32_t         code = tHistogramMerge(pHisto, pInput->pHisto, MAX_HISTOGRAM_BIN, &pRes);
347✔
2166
      if (TSDB_CODE_SUCCESS != code) {
347!
2167
        tHistogramDestroy(&pRes);
×
2168
        return code;
×
2169
      }
2170
      (void)memcpy(pHisto, pRes, sizeof(SHistogramInfo) + sizeof(SHistBin) * MAX_HISTOGRAM_BIN);
347✔
2171
      pHisto->elems = (SHistBin*)((char*)pHisto + sizeof(SHistogramInfo));
347✔
2172

2173
      qDebug("%s merge histo, total:%" PRId64 ", entry:%d, %p", __FUNCTION__, pHisto->numOfElems, pHisto->numOfEntries,
347✔
2174
             pHisto);
2175
      tHistogramDestroy(&pRes);
347✔
2176
    }
2177
  }
2178
  return TSDB_CODE_SUCCESS;
8,514✔
2179
}
2180

2181
int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) {
8,636✔
2182
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,636✔
2183

2184
  SInputColumnInfoData* pInput = &pCtx->input;
8,636✔
2185

2186
  SColumnInfoData* pCol = pInput->pData[0];
8,636✔
2187
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
8,636!
2188
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2189
  }
2190

2191
  SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,636✔
2192

2193
  qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto);
8,636✔
2194

2195
  bool    hasRes = false;
8,636✔
2196
  int32_t start = pInput->startRowIndex;
8,636✔
2197
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
17,352✔
2198
    char* data = colDataGetData(pCol, i);
8,716!
2199

2200
    SAPercentileInfo* pInputInfo = (SAPercentileInfo*)varDataVal(data);
8,716✔
2201
    int32_t           code = apercentileTransferInfo(pInputInfo, pInfo, &hasRes);
8,716✔
2202
    if (TSDB_CODE_SUCCESS != code) {
8,716!
2203
      return code;
×
2204
    }
2205
  }
2206

2207
  if (pInfo->algo != APERCT_ALGO_TDIGEST) {
8,636✔
2208
    buildHistogramInfo(pInfo);
7,725✔
2209
    qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems,
7,725✔
2210
           pInfo->pHisto->numOfEntries, pInfo->pHisto);
2211
  }
2212

2213
  SET_VAL(pResInfo, hasRes ? 1 : 0, 1);
8,636✔
2214
  return TSDB_CODE_SUCCESS;
8,636✔
2215
}
2216

2217
int32_t apercentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
278,920✔
2218
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
278,920✔
2219
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
278,920✔
2220

2221
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
278,920✔
2222
    buildTDigestInfo(pInfo);
12,843✔
2223
    tdigestAutoFill(pInfo->pTDigest, COMPRESSION);
12,842✔
2224
    if (pInfo->pTDigest->size > 0) {
12,840!
2225
      pInfo->result = tdigestQuantile(pInfo->pTDigest, pInfo->percent / 100);
12,840✔
2226
    } else {  // no need to free
2227
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2228
      return TSDB_CODE_SUCCESS;
×
2229
    }
2230
  } else {
2231
    buildHistogramInfo(pInfo);
266,077✔
2232
    if (pInfo->pHisto->numOfElems > 0) {
266,073✔
2233
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d, pHisto:%p, elems:%p", __FUNCTION__,
218,093✔
2234
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto, pInfo->pHisto->elems);
2235

2236
      double  ratio[] = {pInfo->percent};
218,096✔
2237
      double* res = NULL;
218,096✔
2238
      int32_t code = tHistogramUniform(pInfo->pHisto, ratio, 1, &res);
218,096✔
2239
      if (TSDB_CODE_SUCCESS != code) {
218,095!
2240
        taosMemoryFree(res);
×
2241
        return code;
×
2242
      }
2243
      pInfo->result = *res;
218,095✔
2244
      // memcpy(pCtx->pOutput, res, sizeof(double));
2245
      taosMemoryFree(res);
218,095!
2246
    } else {  // no need to free
2247
      // setNull(pCtx->pOutput, pCtx->outputType, pCtx->outputBytes);
2248
      // return TSDB_CODE_SUCCESS;
2249
      qDebug("%s get the final res, elements:%" PRId64 ", numOfEntry:%d. result is null", __FUNCTION__,
47,980✔
2250
             pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries);
2251
    }
2252
  }
2253

2254
  return functionFinalize(pCtx, pBlock);
278,923✔
2255
}
2256

2257
int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,390✔
2258
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,390✔
2259
  SAPercentileInfo*    pInfo = (SAPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo);
8,390✔
2260

2261
  int32_t resultBytes = getApercentileMaxSize();
8,390✔
2262
  char*   res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
8,390!
2263
  if (NULL == res) {
8,390!
2264
    return terrno;
×
2265
  }
2266

2267
  if (pInfo->algo == APERCT_ALGO_TDIGEST) {
8,390✔
2268
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
911✔
2269
    varDataSetLen(res, resultBytes);
911✔
2270
  } else {
2271
    (void)memcpy(varDataVal(res), pInfo, resultBytes);
7,479✔
2272
    varDataSetLen(res, resultBytes);
7,479✔
2273
  }
2274

2275
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
8,390✔
2276
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,390✔
2277
  if (NULL == pCol) {
8,390!
2278
    taosMemoryFree(res);
×
2279
    return TSDB_CODE_OUT_OF_RANGE;
×
2280
  }
2281

2282
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
8,390✔
2283

2284
  taosMemoryFree(res);
8,390!
2285
  return code;
8,390✔
2286
}
2287

2288
int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
4✔
2289
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
4✔
2290
  SAPercentileInfo*    pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
4✔
2291

2292
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
4✔
2293
  SAPercentileInfo*    pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
4✔
2294

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

2297
  int32_t code = apercentileTransferInfo(pSBuf, pDBuf, NULL);
4✔
2298
  if (TSDB_CODE_SUCCESS != code) {
4!
2299
    return code;
×
2300
  }
2301
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
4✔
2302
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
4✔
2303
  return TSDB_CODE_SUCCESS;
4✔
2304
}
2305

2306
// TODO: change this function when block data info pks changed
2307
static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) {
3,456✔
2308
  char numVal[8] = {0};
3,456✔
2309
  switch (pkType) {
3,456✔
2310
    case TSDB_DATA_TYPE_INT:
544✔
2311
      *(int32_t*)numVal = (int32_t)pVal->val;
544✔
2312
      break;
544✔
2313
    case TSDB_DATA_TYPE_UINT:
471✔
2314
      *(uint32_t*)numVal = (uint32_t)pVal->val;
471✔
2315
      break;
471✔
2316
    case TSDB_DATA_TYPE_BIGINT:
710✔
2317
      *(int64_t*)numVal = (int64_t)pVal->val;
710✔
2318
      break;
710✔
2319
    case TSDB_DATA_TYPE_UBIGINT:
673✔
2320
      *(uint64_t*)numVal = (uint64_t)pVal->val;
673✔
2321
      break;
673✔
2322
    default:
1,058✔
2323
      break;
1,058✔
2324
  }
2325
  char*         blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*)numVal : (char*)pVal->pData;
3,456!
2326
  __compar_fn_t fn = getKeyComparFunc(pkType, order);
3,456✔
2327
  return fn(pkData, blockData);
3,457✔
2328
}
2329

2330
EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
8,390✔
2331
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
8,390✔
2332

2333
  // not initialized yet, data is required
2334
  if (pEntry == NULL) {
8,390!
2335
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2336
  }
2337

2338
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
8,390✔
2339
  if (pResult->hasResult) {
8,390✔
2340
    if (pResult->pkBytes > 0) {
8,336✔
2341
      pResult->pkData = pResult->buf + pResult->bytes;
2,045✔
2342
    } else {
2343
      pResult->pkData = NULL;
6,291✔
2344
    }
2345
    if (pResult->ts < pBlockInfo->window.skey) {
8,336✔
2346
      return FUNC_DATA_REQUIRED_NOT_LOAD;
5,909✔
2347
    } else if (pResult->ts == pBlockInfo->window.skey) {
2,427✔
2348
      if (NULL == pResult->pkData) {
1,440✔
2349
        return FUNC_DATA_REQUIRED_NOT_LOAD;
242✔
2350
      }
2351
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) {
1,198✔
2352
        return FUNC_DATA_REQUIRED_NOT_LOAD;
96✔
2353
      }
2354
    }
2355
    return FUNC_DATA_REQUIRED_DATA_LOAD;
2,087✔
2356
  } else {
2357
    return FUNC_DATA_REQUIRED_DATA_LOAD;
54✔
2358
  }
2359
}
2360

2361
EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) {
11,017✔
2362
  SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes;
11,017✔
2363

2364
  // not initialized yet, data is required
2365
  if (pEntry == NULL) {
11,017!
2366
    return FUNC_DATA_REQUIRED_DATA_LOAD;
×
2367
  }
2368

2369
  SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry);
11,017✔
2370
  if (pResult->hasResult) {
11,017✔
2371
    if (pResult->pkBytes > 0) {
10,947✔
2372
      pResult->pkData = pResult->buf + pResult->bytes;
3,356✔
2373
    } else {
2374
      pResult->pkData = NULL;
7,591✔
2375
    }
2376
    if (pResult->ts > pBlockInfo->window.ekey) {
10,947✔
2377
      return FUNC_DATA_REQUIRED_NOT_LOAD;
5,765✔
2378
    } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) {
5,182✔
2379
      if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) {
2,261✔
2380
        return FUNC_DATA_REQUIRED_NOT_LOAD;
700✔
2381
      }
2382
    }
2383
    return FUNC_DATA_REQUIRED_DATA_LOAD;
4,482✔
2384
  } else {
2385
    return FUNC_DATA_REQUIRED_DATA_LOAD;
70✔
2386
  }
2387
}
2388

2389
// TODO modify it to include primary key bytes
2390
int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes) { return sizeof(SFirstLastRes) + resBytes + pkBytes; }
83,027,225✔
2391

2392
bool getFirstLastFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,995,765✔
2393
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,995,765✔
2394
  // TODO: change SFunctionNode to add pk info
2395
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
1,997,334✔
2396
  pEnv->calcMemSize = getFirstLastInfoSize(pNode->node.resType.bytes, pkBytes);
1,997,334✔
2397
  return true;
1,996,823✔
2398
}
2399

2400
bool getSelectivityFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
1,230,843✔
2401
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
1,230,843✔
2402
  pEnv->calcMemSize = pNode->node.resType.bytes;
1,231,793✔
2403
  return true;
1,231,793✔
2404
}
2405

2406
bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
475,883✔
2407
  SColumnNode* pNode = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
475,883✔
2408
  pEnv->calcMemSize = sizeof(SGroupKeyInfo) + pNode->node.resType.bytes;
476,069✔
2409
  return true;
476,069✔
2410
}
2411

2412
static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowIndex) {
2413
  if (pTsColInfo == NULL || pTsColInfo->pData == NULL) {
447,072,912!
2414
    return 0;
×
2415
  }
2416

2417
  return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
447,177,126!
2418
}
2419

2420
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
24,345,937✔
2421
  if (pResInfo->initialized) {
24,345,937!
2422
    return TSDB_CODE_SUCCESS;
×
2423
  }
2424
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
24,345,937!
2425
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
2426
  }
2427

2428
  SFirstLastRes*        pRes = GET_ROWCELL_INTERBUF(pResInfo);
24,346,577✔
2429
  pRes->nullTupleSaved = false;
24,346,577✔
2430
  pRes->nullTuplePos.pageId = -1;
24,346,577✔
2431
  return TSDB_CODE_SUCCESS;
24,346,577✔
2432
}
2433

2434
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
255,568,181✔
2435
  if (pCtx->subsidiaries.rowLen == 0) {
255,568,181✔
2436
    int32_t rowLen = 0;
703,546✔
2437
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
1,417,073✔
2438
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
713,527✔
2439
      rowLen += pc->pExpr->base.resSchema.bytes;
713,527✔
2440
    }
2441

2442
    pCtx->subsidiaries.rowLen = rowLen + pCtx->subsidiaries.num * sizeof(bool);
703,546✔
2443
    pCtx->subsidiaries.buf = taosMemoryMalloc(pCtx->subsidiaries.rowLen);
703,546!
2444
    if (NULL == pCtx->subsidiaries.buf) {
704,141!
2445
      return terrno;
×
2446
    }
2447
  }
2448
  return TSDB_CODE_SUCCESS;
255,568,776✔
2449
}
2450

2451
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
251,119,022✔
2452
                                      SFirstLastRes* pInfo, bool noElements) {
2453
  int32_t code = TSDB_CODE_SUCCESS;
251,119,022✔
2454

2455
  if (pCtx->subsidiaries.num <= 0) {
251,119,022✔
2456
    return TSDB_CODE_SUCCESS;
121,508,931✔
2457
  }
2458

2459
  if (!pInfo->hasResult) {
129,610,091✔
2460
    code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
103,887,889✔
2461
  } else if (!noElements) {
25,722,202!
2462
    code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
25,811,995✔
2463
  } else { } // dothing
2464

2465
  return code;
129,523,559✔
2466
}
2467

2468
static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t currentTs, char* pkData, int32_t type,
97,511,521✔
2469
                                char* pData) {
2470
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
97,511,521✔
2471
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
97,511,521✔
2472

2473
  if (IS_VAR_DATA_TYPE(type)) {
97,511,521!
2474
    if (type == TSDB_DATA_TYPE_JSON) {
7,560,976!
2475
      pInfo->bytes = getJsonValueLen(pData);
×
2476
    } else {
2477
      pInfo->bytes = varDataTLen(pData);
7,560,976✔
2478
    }
2479
  }
2480

2481
  (void)memcpy(pInfo->buf, pData, pInfo->bytes);
97,511,521✔
2482
  if (pkData != NULL) {
97,511,521✔
2483
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
1,437,527!
2484
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
468,001!
2485
        pInfo->pkBytes = getJsonValueLen(pkData);
×
2486
      } else {
2487
        pInfo->pkBytes = varDataTLen(pkData);
468,001✔
2488
      }
2489
    }
2490
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
1,437,527✔
2491
    pInfo->pkData = pInfo->buf + pInfo->bytes;
1,437,527✔
2492
  }
2493

2494
  pInfo->ts = currentTs;
97,511,521✔
2495
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
97,511,521✔
2496
  if (code != TSDB_CODE_SUCCESS) {
97,494,061!
2497
    return code;
×
2498
  }
2499

2500
  pInfo->hasResult = true;
97,494,061✔
2501
  return TSDB_CODE_SUCCESS;
97,494,061✔
2502
}
2503

2504
// This ordinary first function does not care if current scan is ascending order or descending order scan
2505
// the OPTIMIZED version of first function will only handle the ascending order scan
2506
int32_t firstFunction(SqlFunctionCtx* pCtx) {
52,499,873✔
2507
  int32_t numOfElems = 0;
52,499,873✔
2508

2509
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
52,499,873✔
2510
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
52,499,873✔
2511

2512
  SInputColumnInfoData* pInput = &pCtx->input;
52,499,873✔
2513
  SColumnInfoData*      pInputCol = pInput->pData[0];
52,499,873✔
2514

2515
  pInfo->bytes = pInputCol->info.bytes;
52,499,873✔
2516

2517
  if (IS_NULL_TYPE(pInputCol->info.type)) {
52,499,873✔
2518
    return TSDB_CODE_SUCCESS;
4,994✔
2519
  }
2520

2521
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
52,494,879✔
2522
  pInfo->pkType = -1;
52,494,879✔
2523
  __compar_fn_t pkCompareFn = NULL;
52,494,879✔
2524
  if (pCtx->hasPrimaryKey) {
52,494,879✔
2525
    pInfo->pkType = pkCol->info.type;
191,648✔
2526
    pInfo->pkBytes = pkCol->info.bytes;
191,648✔
2527
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_ASC);
191,648✔
2528
  }
2529

2530
  // All null data column, return directly.
2531
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
52,498,876!
2532
      pInputCol->hasNull == true) {
×
2533
    // save selectivity value for column consisted of all null values
2534
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2535
    if (code != TSDB_CODE_SUCCESS) {
×
2536
      return code;
×
2537
    }
2538
    pInfo->nullTupleSaved = true;
×
2539
    return TSDB_CODE_SUCCESS;
×
2540
  }
2541

2542
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
52,498,876!
2543

2544
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
52,498,876!
2545
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
52,498,876!
2546

2547
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
52,498,876✔
2548

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

2560
    for (int32_t i = pInput->startRowIndex; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
2561
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2562
        continue;
2563
      }
2564

2565
      numOfElems++;
2566

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

2583
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2584
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2585
        continue;
2586
      }
2587

2588
      numOfElems++;
2589

2590
      char* data = colDataGetData(pInputCol, i);
2591
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2592

2593
      if (pResInfo->numOfRes == 0 || pInfo->ts > cts) {
2594
        doSaveCurrentVal(pCtx, i, cts, pInputCol->info.type, data);
2595
        break;
2596
      }
2597
    }
2598
  }
2599
#else
2600
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
52,498,876✔
2601

2602
  int     from = -1;
52,498,876✔
2603
  int32_t i = -1;
52,498,876✔
2604
  while (funcInputGetNextRowIndex(pInput, from, true, &i, &from)) {
167,362,000✔
2605
    if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
154,309,820!
2606
      continue;
2,437,413✔
2607
    }
2608

2609
    numOfElems++;
112,452,508✔
2610
    char* data = colDataGetData(pInputCol, i);
112,452,508!
2611
    char* pkData = NULL;
112,452,508✔
2612
    if (pCtx->hasPrimaryKey) {
112,452,508✔
2613
      pkData = colDataGetData(pkCol, i);
1,413,194!
2614
    }
2615
    TSKEY cts = pts[i];
112,452,508✔
2616
    if (pResInfo->numOfRes == 0 || pInfo->ts > cts ||
112,452,508✔
2617
        (pInfo->ts == cts && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
66,819,625!
2618
      int32_t code = doSaveCurrentVal(pCtx, i, cts, pkData, pInputCol->info.type, data);
45,632,883✔
2619
      if (code != TSDB_CODE_SUCCESS) {
45,606,088!
2620
        return code;
×
2621
      }
2622
      pResInfo->numOfRes = 1;
45,606,088✔
2623
    }
2624
  }
2625
#endif
2626

2627
  if (numOfElems == 0) {
52,038,918✔
2628
    // save selectivity value for column consisted of all null values
2629
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
32,330✔
2630
    if (code != TSDB_CODE_SUCCESS) {
32,331!
2631
      return code;
×
2632
    }
2633
    pInfo->nullTupleSaved = true;
32,331✔
2634
  }
2635
  SET_VAL(pResInfo, numOfElems, 1);
52,038,919✔
2636
  return TSDB_CODE_SUCCESS;
52,038,919✔
2637
}
2638

2639
int32_t lastFunction(SqlFunctionCtx* pCtx) {
42,936,699✔
2640
  int32_t numOfElems = 0;
42,936,699✔
2641

2642
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
42,936,699✔
2643
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
42,936,699✔
2644

2645
  SInputColumnInfoData* pInput = &pCtx->input;
42,936,699✔
2646
  SColumnInfoData*      pInputCol = pInput->pData[0];
42,936,699✔
2647

2648
  int32_t type = pInputCol->info.type;
42,936,699✔
2649
  int32_t bytes = pInputCol->info.bytes;
42,936,699✔
2650

2651
  if (IS_NULL_TYPE(type)) {
42,936,699✔
2652
    return TSDB_CODE_SUCCESS;
4,994✔
2653
  }
2654
  pInfo->bytes = bytes;
42,931,705✔
2655

2656
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
42,931,705✔
2657
  pInfo->pkType = -1;
42,931,705✔
2658
  __compar_fn_t pkCompareFn = NULL;
42,931,705✔
2659
  if (pCtx->hasPrimaryKey) {
42,931,705✔
2660
    pInfo->pkType = pkCol->info.type;
247,760✔
2661
    pInfo->pkBytes = pkCol->info.bytes;
247,760✔
2662
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
247,760✔
2663
  }
2664

2665
  // All null data column, return directly.
2666
  if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
43,057,479!
2667
      pInputCol->hasNull == true) {
×
2668
    // save selectivity value for column consisted of all null values
2669
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
×
2670
    if (code != TSDB_CODE_SUCCESS) {
×
2671
      return code;
×
2672
    }
2673
    pInfo->nullTupleSaved = true;
×
2674
    return TSDB_CODE_SUCCESS;
×
2675
  }
2676

2677
  SColumnDataAgg* pColAgg = (pInput->colDataSMAIsSet) ? pInput->pColumnDataAgg[0] : NULL;
43,057,479!
2678

2679
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
43,057,479!
2680
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
43,057,479!
2681

2682
  int32_t blockDataOrder = (startKey <= endKey) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
43,057,479✔
2683

2684
  //  please ref. to the comment in lastRowFunction for the reason why disabling the opt version of last/first function.
2685
#if 0
2686
  if (blockDataOrder == TSDB_ORDER_ASC) {
2687
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
2688
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2689
        continue;
2690
      }
2691

2692
      numOfElems++;
2693

2694
      char* data = colDataGetData(pInputCol, i);
2695
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2696
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2697
        doSaveCurrentVal(pCtx, i, cts, type, data);
2698
      }
2699

2700
      break;
2701
    }
2702
  } else {  // descending order
2703
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2704
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2705
        continue;
2706
      }
2707

2708
      numOfElems++;
2709

2710
      char* data = colDataGetData(pInputCol, i);
2711
      TSKEY cts = getRowPTs(pInput->pPTS, i);
2712
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
2713
        doSaveCurrentVal(pCtx, i, cts, type, data);
2714
      }
2715
      break;
2716
    }
2717
  }
2718
#else
2719
  int64_t* pts = (int64_t*)pInput->pPTS->pData;
43,057,479✔
2720

2721
#if 0
2722
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2723
      if (pInputCol->hasNull && colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
2724
        continue;
2725
      }
2726

2727
      numOfElems++;
2728
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
2729
        char* data = colDataGetData(pInputCol, i);
2730
        doSaveCurrentVal(pCtx, i, pts[i], type, data);
2731
        pResInfo->numOfRes = 1;
2732
      }
2733
    }
2734
#else
2735

2736
  // todo refactor
2737
  if (!pInputCol->hasNull && !pCtx->hasPrimaryKey) {
69,937,688✔
2738
    numOfElems = 1;
26,943,977✔
2739

2740
    int32_t round = pInput->numOfRows >> 2;
26,943,977✔
2741
    int32_t reminder = pInput->numOfRows & 0x03;
26,943,977✔
2742

2743
    for (int32_t i = pInput->startRowIndex, tick = 0; tick < round; i += 4, tick += 1) {
42,479,070✔
2744
      int64_t cts = pts[i];
15,533,230✔
2745
      int32_t chosen = i;
15,533,230✔
2746

2747
      if (cts < pts[i + 1]) {
15,533,230✔
2748
        cts = pts[i + 1];
4,909,170✔
2749
        chosen = i + 1;
4,909,170✔
2750
      }
2751

2752
      if (cts < pts[i + 2]) {
15,533,230✔
2753
        cts = pts[i + 2];
4,906,713✔
2754
        chosen = i + 2;
4,906,713✔
2755
      }
2756

2757
      if (cts < pts[i + 3]) {
15,533,230✔
2758
        cts = pts[i + 3];
4,906,825✔
2759
        chosen = i + 3;
4,906,825✔
2760
      }
2761

2762
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
15,533,230✔
2763
        char*   data = colDataGetData(pInputCol, chosen);
4,547,331!
2764
        int32_t code = doSaveCurrentVal(pCtx, chosen, cts, NULL, type, data);
4,547,331✔
2765
        if (code != TSDB_CODE_SUCCESS) {
4,549,194!
2766
          return code;
×
2767
        }
2768
        pResInfo->numOfRes = 1;
4,549,194✔
2769
      }
2770
    }
2771

2772
    for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) {
59,528,003✔
2773
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) {
32,647,794✔
2774
        char*   data = colDataGetData(pInputCol, i);
18,944,489!
2775
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], NULL, type, data);
18,944,489✔
2776
        if (code != TSDB_CODE_SUCCESS) {
18,878,858!
2777
          return code;
×
2778
        }
2779
        pResInfo->numOfRes = 1;
18,878,858✔
2780
      }
2781
    }
2782
  } else {
2783
    int     from = -1;
16,113,502✔
2784
    int32_t i = -1;
16,113,502✔
2785
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
160,833,541✔
2786
      if (colDataIsNull(pInputCol, pInput->totalRows, i, pColAgg)) {
289,443,908✔
2787
        continue;
5,609,235✔
2788
      }
2789

2790
      numOfElems++;
139,112,719✔
2791
      char* pkData = NULL;
139,112,719✔
2792
      if (pCtx->hasPrimaryKey) {
139,112,719✔
2793
        pkData = colDataGetData(pkCol, i);
101,504,778!
2794
      }
2795
      if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i] ||
139,112,719✔
2796
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
110,754,605!
2797
        char*   data = colDataGetData(pInputCol, i);
28,412,062!
2798
        int32_t code = doSaveCurrentVal(pCtx, i, pts[i], pkData, type, data);
28,412,062✔
2799
        if (code != TSDB_CODE_SUCCESS) {
28,410,147!
2800
          return code;
×
2801
        }
2802
        pResInfo->numOfRes = 1;
28,410,147✔
2803
      }
2804
    }
2805
  }
2806
#endif
2807

2808
#endif
2809

2810
  // save selectivity value for column consisted of all null values
2811
  if (numOfElems == 0) {
43,240,945✔
2812
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
4,104,668✔
2813
    if (code != TSDB_CODE_SUCCESS) {
4,100,916!
2814
      return code;
×
2815
    }
2816
    pInfo->nullTupleSaved = true;
4,100,916✔
2817
  }
2818

2819
  return TSDB_CODE_SUCCESS;
43,237,193✔
2820
}
2821

2822
static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst) {
76,651,595✔
2823
  if (!pInput->hasResult) {
76,651,595✔
2824
    return false;
2✔
2825
  }
2826
  __compar_fn_t pkCompareFn = NULL;
76,651,593✔
2827
  if (pInput->pkData) {
76,651,593✔
2828
    pkCompareFn = getKeyComparFunc(pInput->pkType, (isFirst) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
47,252✔
2829
  }
2830
  if (pOutput->hasResult) {
76,655,998✔
2831
    if (isFirst) {
31,336,896✔
2832
      if (pInput->ts > pOutput->ts ||
8,596,609✔
2833
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
8,596,172✔
2834
        return false;
1,053✔
2835
      }
2836
    } else {
2837
      if (pInput->ts < pOutput->ts ||
22,740,287✔
2838
          (pInput->ts == pOutput->ts && pkCompareFn && pkCompareFn(pInput->pkData, pOutput->pkData) > 0)) {
12,311,928✔
2839
        return false;
10,431,840✔
2840
      }
2841
    }
2842
  }
2843

2844
  pOutput->isNull = pInput->isNull;
66,223,105✔
2845
  pOutput->ts = pInput->ts;
66,223,105✔
2846
  pOutput->bytes = pInput->bytes;
66,223,105✔
2847
  pOutput->pkType = pInput->pkType;
66,223,105✔
2848

2849
  (void)memcpy(pOutput->buf, pInput->buf, pOutput->bytes);
66,223,105✔
2850
  if (pInput->pkData) {
66,223,105✔
2851
    pOutput->pkBytes = pInput->pkBytes;
43,972✔
2852
    (void)memcpy(pOutput->buf + pOutput->bytes, pInput->pkData, pOutput->pkBytes);
43,972✔
2853
    pOutput->pkData = pOutput->buf + pOutput->bytes;
43,972✔
2854
  }
2855
  return true;
66,223,105✔
2856
}
2857

2858
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
76,651,081✔
2859
                                     int32_t rowIndex) {
2860
  if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
76,651,081✔
2861
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, false);
66,223,192✔
2862
    if (TSDB_CODE_SUCCESS != code) {
66,216,169!
2863
      return code;
×
2864
    }
2865
    pOutput->hasResult = true;
66,216,169✔
2866
  }
2867
  return TSDB_CODE_SUCCESS;
76,645,147✔
2868
}
2869

2870
static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuery) {
45,370,036✔
2871
  SInputColumnInfoData* pInput = &pCtx->input;
45,370,036✔
2872
  SColumnInfoData*      pCol = pInput->pData[0];
45,370,036✔
2873

2874
  if (IS_NULL_TYPE(pCol->info.type)) {
45,370,036!
2875
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
2876
    return TSDB_CODE_SUCCESS;
×
2877
  }
2878

2879
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
45,370,036!
2880
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2881
  }
2882

2883
  SFirstLastRes* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
45,370,036✔
2884

2885
  int32_t start = pInput->startRowIndex;
45,370,036✔
2886
  int32_t numOfElems = 0;
45,370,036✔
2887

2888
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
124,306,103✔
2889
    if (colDataIsNull_s(pCol, i)) {
157,892,176✔
2890
      continue;
2,291,491✔
2891
    }
2892
    char*          data = colDataGetData(pCol, i);
76,654,597!
2893
    SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data);
76,654,597✔
2894
    if (pCtx->hasPrimaryKey) {
76,654,597✔
2895
      pInputInfo->pkData = pInputInfo->buf + pInputInfo->bytes;
47,252✔
2896
    } else {
2897
      pInputInfo->pkData = NULL;
76,607,345✔
2898
    }
2899

2900
    int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i);
76,654,597✔
2901
    if (code != TSDB_CODE_SUCCESS) {
76,644,576!
2902
      return code;
×
2903
    }
2904
    if (!numOfElems) {
76,644,576✔
2905
      numOfElems = pInputInfo->hasResult ? 1 : 0;
45,351,468✔
2906
    }
2907
  }
2908

2909
  if (numOfElems == 0) {
45,360,015✔
2910
    int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, true);
14,299✔
2911
    if (code != TSDB_CODE_SUCCESS) {
14,299!
2912
      return code;
×
2913
    }
2914
    pInfo->nullTupleSaved = true;
14,299✔
2915
  }
2916

2917
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
45,360,015✔
2918
  return TSDB_CODE_SUCCESS;
45,360,015✔
2919
}
2920

2921
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, true); }
13,431,771✔
2922

2923
int32_t lastFunctionMerge(SqlFunctionCtx* pCtx) { return firstLastFunctionMergeImpl(pCtx, false); }
31,939,409✔
2924

2925
int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
110,789,813✔
2926
  int32_t          code = TSDB_CODE_SUCCESS;
110,789,813✔
2927
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
110,789,813✔
2928
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
110,789,813✔
2929
  if (NULL == pCol) {
110,787,595!
2930
    return TSDB_CODE_OUT_OF_RANGE;
×
2931
  }
2932

2933
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
110,787,595✔
2934
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
110,787,595✔
2935

2936
  SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
110,787,595✔
2937

2938
  if (pResInfo->isNullRes) {
110,787,595✔
2939
    colDataSetNULL(pCol, pBlock->info.rows);
48,715✔
2940
    return setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
48,715✔
2941
  }
2942
  code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
110,738,880!
2943
  if (TSDB_CODE_SUCCESS != code) {
110,734,170!
2944
    return code;
×
2945
  }
2946

2947
  // handle selectivity
2948
  code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
110,734,170✔
2949

2950
  return code;
110,727,465✔
2951
}
2952

2953
int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
81,009,367✔
2954
  int32_t code = TSDB_CODE_SUCCESS;
81,009,367✔
2955

2956
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
81,009,367✔
2957
  SFirstLastRes*       pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
81,009,367✔
2958

2959
  int32_t resultBytes = getFirstLastInfoSize(pRes->bytes, pRes->pkBytes);
81,009,367✔
2960

2961
  // todo check for failure
2962
  char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
80,955,154!
2963
  if (NULL == res) {
81,218,986!
2964
    return terrno;
×
2965
  }
2966
  (void)memcpy(varDataVal(res), pRes, resultBytes);
81,218,986✔
2967

2968
  varDataSetLen(res, resultBytes);
81,218,986✔
2969

2970
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
81,218,986✔
2971
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
81,218,986✔
2972
  if (NULL == pCol) {
81,167,640!
2973
    taosMemoryFree(res);
×
2974
    return TSDB_CODE_OUT_OF_RANGE;
×
2975
  }
2976

2977
  if (pEntryInfo->numOfRes == 0) {
81,181,878✔
2978
    colDataSetNULL(pCol, pBlock->info.rows);
2,395,295!
2979
    code = setNullSelectivityValue(pCtx, pBlock, pBlock->info.rows);
2,395,295✔
2980
  } else {
2981
    code = colDataSetVal(pCol, pBlock->info.rows, res, false);
78,786,583✔
2982
    if (TSDB_CODE_SUCCESS != code) {
78,403,658!
2983
      taosMemoryFree(res);
×
2984
      return code;
×
2985
    }
2986
    code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
78,403,658✔
2987
  }
2988
  taosMemoryFree(res);
80,854,536!
2989
  return code;
81,242,883✔
2990
}
2991

2992
int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
3✔
2993
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
3✔
2994
  SFirstLastRes*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
3✔
2995
  int32_t              bytes = pDBuf->bytes;
3✔
2996

2997
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
3✔
2998
  SFirstLastRes*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
3✔
2999

3000
  pDBuf->hasResult = firstLastTransferInfoImpl(pSBuf, pDBuf, false);
3✔
3001
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
3✔
3002
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
3✔
3003
  return TSDB_CODE_SUCCESS;
3✔
3004
}
3005

3006
static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex, int64_t cts, SFirstLastRes* pInfo) {
83,464,153✔
3007
  SInputColumnInfoData* pInput = &pCtx->input;
83,464,153✔
3008
  SColumnInfoData*      pInputCol = pInput->pData[0];
83,464,153✔
3009
  SColumnInfoData*      pkCol = pInput->pPrimaryKey;
83,464,153✔
3010

3011
  if (colDataIsNull_s(pInputCol, rowIndex)) {
166,928,306✔
3012
    pInfo->isNull = true;
2,184✔
3013
  } else {
3014
    pInfo->isNull = false;
83,461,969✔
3015

3016
    if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
83,461,969!
3017
      if (pInputCol->info.type == TSDB_DATA_TYPE_JSON) {
122,402!
3018
        pInfo->bytes = getJsonValueLen(pData);
×
3019
      } else {
3020
        pInfo->bytes = varDataTLen(pData);
122,402✔
3021
      }
3022
    }
3023

3024
    (void)memcpy(pInfo->buf, pData, pInfo->bytes);
83,461,969✔
3025
  }
3026

3027
  if (pCtx->hasPrimaryKey && !colDataIsNull_s(pkCol, rowIndex)) {
83,536,785✔
3028
    char* pkData = colDataGetData(pkCol, rowIndex);
72,609!
3029
    if (IS_VAR_DATA_TYPE(pInfo->pkType)) {
72,609!
3030
      if (pInfo->pkType == TSDB_DATA_TYPE_JSON) {
23,870!
3031
        pInfo->pkBytes = getJsonValueLen(pkData);
×
3032
      } else {
3033
        pInfo->pkBytes = varDataTLen(pkData);
23,870✔
3034
      }
3035
    }
3036
    (void)memcpy(pInfo->buf + pInfo->bytes, pkData, pInfo->pkBytes);
72,609✔
3037
    pInfo->pkData = pInfo->buf + pInfo->bytes;
72,609✔
3038
  }
3039
  pInfo->ts = cts;
83,464,153✔
3040
  int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
83,464,153✔
3041
  if (code != TSDB_CODE_SUCCESS) {
83,377,671!
3042
    return code;
×
3043
  }
3044

3045
  pInfo->hasResult = true;
83,377,671✔
3046

3047
  return TSDB_CODE_SUCCESS;
83,377,671✔
3048
}
3049

3050
int32_t lastRowFunction(SqlFunctionCtx* pCtx) {
85,110,973✔
3051
  int32_t numOfElems = 0;
85,110,973✔
3052

3053
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
85,110,973✔
3054
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
85,110,973✔
3055

3056
  SInputColumnInfoData* pInput = &pCtx->input;
85,110,973✔
3057
  SColumnInfoData*      pInputCol = pInput->pData[0];
85,110,973✔
3058

3059
  int32_t type = pInputCol->info.type;
85,110,973✔
3060
  int32_t bytes = pInputCol->info.bytes;
85,110,973✔
3061
  pInfo->bytes = bytes;
85,110,973✔
3062

3063
  if (IS_NULL_TYPE(type)) {
85,110,973✔
3064
    return TSDB_CODE_SUCCESS;
56✔
3065
  }
3066
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
85,110,917✔
3067
  pInfo->pkType = -1;
85,110,917✔
3068
  __compar_fn_t pkCompareFn = NULL;
85,110,917✔
3069
  if (pCtx->hasPrimaryKey) {
85,110,917✔
3070
    pInfo->pkType = pkCol->info.type;
201,671✔
3071
    pInfo->pkBytes = pkCol->info.bytes;
201,671✔
3072
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
201,671✔
3073
  }
3074
  TSKEY startKey = getRowPTs(pInput->pPTS, 0);
85,151,618✔
3075
  TSKEY endKey = getRowPTs(pInput->pPTS, pInput->totalRows - 1);
85,151,618!
3076

3077
  if (pCtx->order == TSDB_ORDER_ASC && !pCtx->hasPrimaryKey) {
85,151,618!
3078
    for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
95,342,936!
3079
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
47,674,782✔
3080
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
47,674,782!
3081
      TSKEY cts = getRowPTs(pInput->pPTS, i);
47,674,782!
3082
      numOfElems++;
47,674,782✔
3083

3084
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
47,674,782✔
3085
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
46,004,654✔
3086
        if (code != TSDB_CODE_SUCCESS) return code;
45,998,251!
3087
      }
3088

3089
      break;
47,668,379✔
3090
    }
3091
  } else if (!pCtx->hasPrimaryKey && pCtx->order == TSDB_ORDER_DESC) {
37,477,061!
3092
    // the optimized version only valid if all tuples in one block are monotonious increasing or descreasing.
3093
    // this assumption is NOT always works if project operator exists in downstream.
3094
    for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
74,537,086!
3095
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
37,309,841✔
3096
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
37,309,841!
3097
      TSKEY cts = getRowPTs(pInput->pPTS, i);
37,309,841✔
3098
      numOfElems++;
37,309,841✔
3099

3100
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
37,309,841✔
3101
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
37,111,104✔
3102
        if (code != TSDB_CODE_SUCCESS) return code;
37,030,514!
3103
      }
3104
      break;
37,229,251✔
3105
    }
3106
  } else {
3107
    int64_t* pts = (int64_t*)pInput->pPTS->pData;
169,226✔
3108
    int      from = -1;
169,226✔
3109
    int32_t  i = -1;
169,226✔
3110
    while (funcInputGetNextRowIndex(pInput, from, false, &i, &from)) {
2,341,187✔
3111
      bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
2,171,459✔
3112
      char* data = isNull ? NULL : colDataGetData(pInputCol, i);
2,171,459!
3113
      TSKEY cts = pts[i];
2,171,459✔
3114

3115
      numOfElems++;
2,171,459✔
3116
      char* pkData = NULL;
2,171,459✔
3117
      if (pCtx->hasPrimaryKey) {
2,171,459✔
3118
        pkData = colDataGetData(pkCol, i);
1,397,167!
3119
      }
3120
      if (pResInfo->numOfRes == 0 || pInfo->ts < cts ||
2,171,459✔
3121
          (pInfo->ts == pts[i] && pkCompareFn && pkCompareFn(pkData, pInfo->pkData) < 0)) {
1,812,360✔
3122
        int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
359,105✔
3123
        if (code != TSDB_CODE_SUCCESS) {
359,604!
3124
          return code;
×
3125
        }
3126
        pResInfo->numOfRes = 1;
359,604✔
3127
      }
3128
    }
3129
  }
3130

3131
  SET_VAL(pResInfo, numOfElems, 1);
85,097,753!
3132
  return TSDB_CODE_SUCCESS;
85,097,753✔
3133
}
3134

3135
bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
29,526✔
3136
  pEnv->calcMemSize = sizeof(SDiffInfo);
29,526✔
3137
  return true;
29,526✔
3138
}
3139

3140
int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
2,282,710✔
3141
  if (pResInfo->initialized) {
2,282,710✔
3142
    return TSDB_CODE_SUCCESS;
2,201,032✔
3143
  }
3144
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
81,678!
3145
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3146
  }
3147
  SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
81,678✔
3148
  pDiffInfo->hasPrev = false;
81,678✔
3149
  pDiffInfo->isFirstRow = true;
81,678✔
3150
  pDiffInfo->prev.i64 = 0;
81,678✔
3151
  pDiffInfo->prevTs = -1;
81,678✔
3152
  if (pCtx->numOfParams > 1) {
81,678!
3153
    pDiffInfo->ignoreOption = pCtx->param[1].param.i;  // TODO set correct param
81,678✔
3154
  } else {
3155
    pDiffInfo->ignoreOption = 0;
×
3156
  }
3157
  return TSDB_CODE_SUCCESS;
81,678✔
3158
}
3159

3160
static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, int64_t ts) {
1,598,726✔
3161
  switch (type) {
1,598,726!
3162
    case TSDB_DATA_TYPE_BOOL:
28✔
3163
      pDiffInfo->prev.i64 = *(bool*)pv ? 1 : 0;
28✔
3164
      break;
28✔
3165
    case TSDB_DATA_TYPE_UTINYINT:
1,207,764✔
3166
    case TSDB_DATA_TYPE_TINYINT:
3167
      pDiffInfo->prev.i64 = *(int8_t*)pv;
1,207,764✔
3168
      break;
1,207,764✔
3169
    case TSDB_DATA_TYPE_UINT:
190,624✔
3170
    case TSDB_DATA_TYPE_INT:
3171
      pDiffInfo->prev.i64 = *(int32_t*)pv;
190,624✔
3172
      break;
190,624✔
3173
    case TSDB_DATA_TYPE_USMALLINT:
198,901✔
3174
    case TSDB_DATA_TYPE_SMALLINT:
3175
      pDiffInfo->prev.i64 = *(int16_t*)pv;
198,901✔
3176
      break;
198,901✔
3177
    case TSDB_DATA_TYPE_TIMESTAMP:
589✔
3178
    case TSDB_DATA_TYPE_UBIGINT:
3179
    case TSDB_DATA_TYPE_BIGINT:
3180
      pDiffInfo->prev.i64 = *(int64_t*)pv;
589✔
3181
      break;
589✔
3182
    case TSDB_DATA_TYPE_FLOAT:
235✔
3183
      pDiffInfo->prev.d64 = *(float*)pv;
235✔
3184
      break;
235✔
3185
    case TSDB_DATA_TYPE_DOUBLE:
585✔
3186
      pDiffInfo->prev.d64 = *(double*)pv;
585✔
3187
      break;
585✔
3188
    default:
×
3189
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3190
  }
3191
  pDiffInfo->prevTs = ts;
1,598,726✔
3192
  pDiffInfo->hasPrev = true;
1,598,726✔
3193
  return TSDB_CODE_SUCCESS;
1,598,726✔
3194
}
3195

3196
static bool diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
6,245,616✔
3197
  switch (type) {
6,245,616!
3198
    case TSDB_DATA_TYPE_UINT: {
×
3199
      int64_t v = *(uint32_t*)pv;
×
3200
      return v < pDiffInfo->prev.i64;
×
3201
    }
3202
    case TSDB_DATA_TYPE_INT: {
413,169✔
3203
      int64_t v = *(int32_t*)pv;
413,169✔
3204
      return v < pDiffInfo->prev.i64;
413,169✔
3205
    }
3206
    case TSDB_DATA_TYPE_BOOL: {
×
3207
      int64_t v = *(bool*)pv;
×
3208
      return v < pDiffInfo->prev.i64;
×
3209
    }
3210
    case TSDB_DATA_TYPE_UTINYINT: {
×
3211
      int64_t v = *(uint8_t*)pv;
×
3212
      return v < pDiffInfo->prev.i64;
×
3213
    }
3214
    case TSDB_DATA_TYPE_TINYINT: {
4,983,383✔
3215
      int64_t v = *(int8_t*)pv;
4,983,383✔
3216
      return v < pDiffInfo->prev.i64;
4,983,383✔
3217
    }
3218
    case TSDB_DATA_TYPE_USMALLINT: {
×
3219
      int64_t v = *(uint16_t*)pv;
×
3220
      return v < pDiffInfo->prev.i64;
×
3221
    }
3222
    case TSDB_DATA_TYPE_SMALLINT: {
831,904✔
3223
      int64_t v = *(int16_t*)pv;
831,904✔
3224
      return v < pDiffInfo->prev.i64;
831,904✔
3225
    }
3226
    case TSDB_DATA_TYPE_UBIGINT: {
24✔
3227
      uint64_t v = *(uint64_t*)pv;
24✔
3228
      return v < (uint64_t)pDiffInfo->prev.i64;
24✔
3229
    }
3230
    case TSDB_DATA_TYPE_TIMESTAMP:
5,326✔
3231
    case TSDB_DATA_TYPE_BIGINT: {
3232
      int64_t v = *(int64_t*)pv;
5,326✔
3233
      return v < pDiffInfo->prev.i64;
5,326✔
3234
    }
3235
    case TSDB_DATA_TYPE_FLOAT: {
4,847✔
3236
      float v = *(float*)pv;
4,847✔
3237
      return v < pDiffInfo->prev.d64;
4,847✔
3238
    }
3239
    case TSDB_DATA_TYPE_DOUBLE: {
6,963✔
3240
      double v = *(double*)pv;
6,963✔
3241
      return v < pDiffInfo->prev.d64;
6,963✔
3242
    }
3243
    default:
×
3244
      return false;
×
3245
  }
3246

3247
  return false;
3248
}
3249

3250
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
1,926,746,034✔
3251
  bool isNegative = v < pDiffInfo->prev.i64;
1,926,746,034✔
3252
  if (type == TSDB_DATA_TYPE_UBIGINT) {
1,926,746,034✔
3253
    isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
3,443✔
3254
  }
3255
  int64_t delta = v - pDiffInfo->prev.i64;
1,926,746,034✔
3256
  if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
1,926,746,034✔
3257
    colDataSetNull_f_s(pOutput, pos);
1,591,157✔
3258
    pOutput->hasNull = true;
1,591,157✔
3259
  } else {
3260
    colDataSetInt64(pOutput, pos, &delta);
1,925,154,877✔
3261
  }
3262
  pDiffInfo->prev.i64 = v;
1,926,746,034✔
3263
}
1,926,746,034✔
3264

3265
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
95,325✔
3266
  double delta = v - pDiffInfo->prev.d64;
95,325✔
3267
  if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
95,325✔
3268
    colDataSetNull_f_s(pOutput, pos);
5,859✔
3269
  } else {
3270
    colDataSetDouble(pOutput, pos, &delta);
89,466✔
3271
  }
3272
  pDiffInfo->prev.d64 = v;
95,325✔
3273
}
95,325✔
3274

3275
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
1,926,840,244✔
3276
                            int64_t ts) {
3277
  if (!pDiffInfo->hasPrev) {
1,926,840,244✔
3278
    colDataSetNull_f_s(pOutput, pos);
569✔
3279
    return doSetPrevVal(pDiffInfo, type, pv, ts);
569✔
3280
  }
3281
  pDiffInfo->prevTs = ts;
1,926,839,675✔
3282
  switch (type) {
1,926,839,675!
3283
    case TSDB_DATA_TYPE_UINT: {
3,401✔
3284
      int64_t v = *(uint32_t*)pv;
3,401✔
3285
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,401✔
3286
      break;
3,401✔
3287
    }
3288
    case TSDB_DATA_TYPE_INT: {
26,526,286✔
3289
      int64_t v = *(int32_t*)pv;
26,526,286✔
3290
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
26,526,286✔
3291
      break;
26,526,286✔
3292
    }
3293
    case TSDB_DATA_TYPE_BOOL: {
10,617✔
3294
      int64_t v = *(bool*)pv;
10,617✔
3295
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
10,617✔
3296
      break;
10,617✔
3297
    }
3298
    case TSDB_DATA_TYPE_UTINYINT: {
405✔
3299
      int64_t v = *(uint8_t*)pv;
405✔
3300
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3301
      break;
405✔
3302
    }
3303
    case TSDB_DATA_TYPE_TINYINT: {
3,821,928✔
3304
      int64_t v = *(int8_t*)pv;
3,821,928✔
3305
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
3,821,928✔
3306
      break;
3,821,928✔
3307
    }
3308
    case TSDB_DATA_TYPE_USMALLINT: {
405✔
3309
      int64_t v = *(uint16_t*)pv;
405✔
3310
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
405✔
3311
      break;
405✔
3312
    }
3313
    case TSDB_DATA_TYPE_SMALLINT: {
1,084,226✔
3314
      int64_t v = *(int16_t*)pv;
1,084,226✔
3315
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,084,226✔
3316
      break;
1,084,226✔
3317
    }
3318
    case TSDB_DATA_TYPE_TIMESTAMP:
1,895,305,011✔
3319
    case TSDB_DATA_TYPE_UBIGINT:
3320
    case TSDB_DATA_TYPE_BIGINT: {
3321
      int64_t v = *(int64_t*)pv;
1,895,305,011✔
3322
      tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
1,895,305,011✔
3323
      break;
1,895,305,011✔
3324
    }
3325
    case TSDB_DATA_TYPE_FLOAT: {
45,050✔
3326
      double v = *(float*)pv;
45,050✔
3327
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
45,050✔
3328
      break;
45,050✔
3329
    }
3330
    case TSDB_DATA_TYPE_DOUBLE: {
50,275✔
3331
      double v = *(double*)pv;
50,275✔
3332
      tryToSetDouble(pDiffInfo, pOutput, v, pos);
50,275✔
3333
      break;
50,275✔
3334
    }
3335
    default:
×
3336
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3337
  }
3338
  pDiffInfo->hasPrev = true;
1,926,847,604✔
3339
  return TSDB_CODE_SUCCESS;
1,926,847,604✔
3340
}
3341

3342
// TODO: the primary key compare can be skipped for ordered pk if knonwn before
3343
// TODO: for desc ordered, pk shall select the smallest one for one ts. if across block boundaries.
3344
bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool firstOccur, int32_t* pRowIndex,
329,912,502✔
3345
                              int32_t* nextFrom) {
3346
  if (pInput->pPrimaryKey == NULL) {
329,912,502✔
3347
    if (from == -1) {
225,058,867✔
3348
      from = pInput->startRowIndex;
69,136,809✔
3349
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
155,922,058✔
3350
      return false;
68,897,832✔
3351
    }
3352
    *pRowIndex = from;
156,161,035✔
3353
    *nextFrom = from + 1;
156,161,035✔
3354
    return true;
156,161,035✔
3355
  } else {
3356
    if (from == -1) {
104,853,635✔
3357
      from = pInput->startRowIndex;
640,893✔
3358
    } else if (from >= pInput->numOfRows + pInput->startRowIndex) {
104,212,742✔
3359
      return false;
641,162✔
3360
    }
3361
    TSKEY*           tsList = (int64_t*)pInput->pPTS->pData;
104,212,473✔
3362
    SColumnInfoData* pkCol = pInput->pPrimaryKey;
104,212,473✔
3363
    int8_t           pkType = pkCol->info.type;
104,212,473✔
3364
    int32_t          order = (firstOccur) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
104,212,473✔
3365
    __compar_fn_t    compareFunc = getKeyComparFunc(pkType, order);
104,212,473✔
3366
    int32_t          select = from;
104,305,977✔
3367
    char*            val = colDataGetData(pkCol, select);
104,305,977!
3368
    while (from < pInput->numOfRows + pInput->startRowIndex - 1 && tsList[from + 1] == tsList[from]) {
110,764,295✔
3369
      char* val1 = colDataGetData(pkCol, from + 1);
6,459,493!
3370
      if (compareFunc(val1, val) < 0) {
6,459,493✔
3371
        select = from + 1;
1,972,365✔
3372
        val = val1;
1,972,365✔
3373
      }
3374
      from = from + 1;
6,458,318✔
3375
    }
3376
    *pRowIndex = select;
104,304,802✔
3377
    *nextFrom = from + 1;
104,304,802✔
3378
    return true;
104,304,802✔
3379
  }
3380
}
3381

3382
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
26✔
3383
  pEnv->calcMemSize = sizeof(float);
26✔
3384
  return true;
26✔
3385
}
3386

3387
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,928,537,164✔
3388
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,928,537,164✔
3389
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,928,537,164✔
3390

3391
  if (pRow->isDataNull || !pDiffInfo->hasPrev) {
1,928,537,164✔
3392
    return true;
178,813✔
3393
  } else if (ignoreNegative(pDiffInfo->ignoreOption)) {
1,928,358,351✔
3394
    return diffIsNegtive(pDiffInfo, pCtx->input.pData[0]->info.type, pRow->pData);
6,240,556✔
3395
  }
3396
  return false;
1,922,117,156✔
3397
}
3398

3399
bool isFirstRow(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,926,996,629✔
3400
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,926,996,629✔
3401
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,926,996,629✔
3402
  return pDiffInfo->isFirstRow;
1,926,996,629✔
3403
}
3404

3405
int32_t trySetPreVal(SqlFunctionCtx* pCtx, SFuncInputRow* pRow) {
1,600,008✔
3406
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,600,008✔
3407
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,600,008✔
3408
  pDiffInfo->isFirstRow = false;
1,600,008✔
3409
  if (pRow->isDataNull) {
1,600,008✔
3410
    return TSDB_CODE_SUCCESS;
1,851✔
3411
  }
3412

3413
  SInputColumnInfoData* pInput = &pCtx->input;
1,598,157✔
3414
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,598,157✔
3415
  int8_t                inputType = pInputCol->info.type;
1,598,157✔
3416

3417
  char* pv = pRow->pData;
1,598,157✔
3418
  return doSetPrevVal(pDiffInfo, inputType, pv, pRow->ts);
1,598,157✔
3419
}
3420

3421
int32_t setDoDiffResult(SqlFunctionCtx* pCtx, SFuncInputRow* pRow, int32_t pos) {
1,926,930,332✔
3422
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,926,930,332✔
3423
  SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
1,926,930,332✔
3424

3425
  SInputColumnInfoData* pInput = &pCtx->input;
1,926,930,332✔
3426
  SColumnInfoData*      pInputCol = pInput->pData[0];
1,926,930,332✔
3427
  int8_t                inputType = pInputCol->info.type;
1,926,930,332✔
3428
  SColumnInfoData*      pOutput = (SColumnInfoData*)pCtx->pOutput;
1,926,930,332✔
3429
  int32_t               code = TSDB_CODE_SUCCESS;
1,926,930,332✔
3430
  if (pRow->isDataNull) {
1,926,930,332✔
3431
    colDataSetNull_f_s(pOutput, pos);
96,702✔
3432
    pOutput->hasNull = true;
96,702✔
3433

3434
    // handle selectivity
3435
    if (pCtx->subsidiaries.num > 0) {
96,702✔
3436
      code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
149✔
3437
      if (code != TSDB_CODE_SUCCESS) {
149!
3438
        return code;
×
3439
      }
3440
    }
3441
    return TSDB_CODE_SUCCESS;
96,702✔
3442
  }
3443

3444
  char* pv = pRow->pData;
1,926,833,630✔
3445

3446
  if (pRow->ts == pDiffInfo->prevTs) {
1,926,833,630✔
3447
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
21✔
3448
  }
3449
  code = doHandleDiff(pDiffInfo, inputType, pv, pOutput, pos, pRow->ts);
1,926,833,609✔
3450
  if (code != TSDB_CODE_SUCCESS) {
1,926,838,378!
3451
    return code;
×
3452
  }
3453
  // handle selectivity
3454
  if (pCtx->subsidiaries.num > 0) {
1,926,838,378✔
3455
    code = appendSelectivityCols(pCtx, pRow->block, pRow->rowIndex, pos);
34,197,266✔
3456
    if (code != TSDB_CODE_SUCCESS) {
34,197,266!
3457
      return code;
×
3458
    }
3459
  }
3460

3461
  return TSDB_CODE_SUCCESS;
1,926,838,378✔
3462
}
3463

3464
int32_t diffFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; }
2,253,184✔
3465

3466
int32_t diffFunctionByRow(SArray* pCtxArray) {
2,253,028✔
3467
  int32_t code = TSDB_CODE_SUCCESS;
2,253,028✔
3468
  int     diffColNum = pCtxArray->size;
2,253,028✔
3469
  if (diffColNum == 0) {
2,253,028!
3470
    return TSDB_CODE_SUCCESS;
×
3471
  }
3472
  int32_t numOfElems = 0;
2,253,028✔
3473

3474
  SArray* pRows = taosArrayInit_s(sizeof(SFuncInputRow), diffColNum);
2,253,028✔
3475
  if (NULL == pRows) {
2,253,028!
3476
    return terrno;
×
3477
  }
3478

3479
  bool keepNull = false;
2,253,028✔
3480
  for (int i = 0; i < diffColNum; ++i) {
4,506,212✔
3481
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,253,184✔
3482
    if (NULL == pCtx) {
2,253,184!
3483
      code = terrno;
×
3484
      goto _exit;
×
3485
    }
3486
    funcInputUpdate(pCtx);
2,253,184✔
3487
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,253,184✔
3488
    SDiffInfo*           pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,253,184✔
3489
    if (!ignoreNull(pDiffInfo->ignoreOption)) {
2,253,184✔
3490
      keepNull = true;
2,237,094✔
3491
    }
3492
  }
3493

3494
  SqlFunctionCtx* pCtx0 = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, 0);
2,253,028✔
3495
  SFuncInputRow*  pRow0 = (SFuncInputRow*)taosArrayGet(pRows, 0);
2,253,028✔
3496
  if (NULL == pCtx0 || NULL == pRow0) {
2,253,028!
3497
    code = terrno;
×
3498
    goto _exit;
×
3499
  }
3500
  int32_t startOffset = pCtx0->offset;
2,253,028✔
3501
  bool    result = false;
2,253,028✔
3502
  while (1) {
1,928,521,872✔
3503
    code = funcInputGetNextRow(pCtx0, pRow0, &result);
1,930,774,900✔
3504
    if (TSDB_CODE_SUCCESS != code) {
1,930,775,443!
3505
      goto _exit;
×
3506
    }
3507
    if (!result) {
1,930,775,443✔
3508
      break;
2,253,007✔
3509
    }
3510
    bool hasNotNullValue = !diffResultIsNull(pCtx0, pRow0);
1,928,522,436✔
3511
    for (int i = 1; i < diffColNum; ++i) {
1,928,531,293✔
3512
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
14,494✔
3513
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
14,494✔
3514
      if (NULL == pCtx || NULL == pRow) {
14,494!
3515
        code = terrno;
×
3516
        goto _exit;
×
3517
      }
3518
      code = funcInputGetNextRow(pCtx, pRow, &result);
14,494✔
3519
      if (TSDB_CODE_SUCCESS != code) {
14,494!
3520
        goto _exit;
×
3521
      }
3522
      if (!result) {
14,494!
3523
        // rows are not equal
3524
        code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3525
        goto _exit;
×
3526
      }
3527
      if (!diffResultIsNull(pCtx, pRow)) {
14,494✔
3528
        hasNotNullValue = true;
14,052✔
3529
      }
3530
    }
3531
    int32_t pos = startOffset + numOfElems;
1,928,516,799✔
3532

3533
    bool newRow = false;
1,928,516,799✔
3534
    for (int i = 0; i < diffColNum; ++i) {
2,147,483,647✔
3535
      SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
1,928,530,938✔
3536
      SFuncInputRow*  pRow = (SFuncInputRow*)taosArrayGet(pRows, i);
1,928,529,364✔
3537
      if (NULL == pCtx || NULL == pRow) {
1,928,523,258!
3538
        code = terrno;
×
3539
        goto _exit;
×
3540
      }
3541
      if ((keepNull || hasNotNullValue) && !isFirstRow(pCtx, pRow)) {
1,928,523,750✔
3542
        code = setDoDiffResult(pCtx, pRow, pos);
1,926,928,240✔
3543
        if (code != TSDB_CODE_SUCCESS) {
1,926,936,024✔
3544
          goto _exit;
21✔
3545
        }
3546
        newRow = true;
1,926,936,003✔
3547
      } else {
3548
        code = trySetPreVal(pCtx, pRow);
1,598,868✔
3549
        if (code != TSDB_CODE_SUCCESS) {
1,600,008!
3550
          goto _exit;
×
3551
        }
3552
      }
3553
    }
3554
    if (newRow) ++numOfElems;
1,928,521,872✔
3555
  }
3556

3557
  for (int i = 0; i < diffColNum; ++i) {
4,506,167✔
3558
    SqlFunctionCtx* pCtx = *(SqlFunctionCtx**)taosArrayGet(pCtxArray, i);
2,253,160✔
3559
    if (NULL == pCtx) {
2,253,160!
3560
      code = terrno;
×
3561
      goto _exit;
×
3562
    }
3563
    SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,253,160✔
3564
    pResInfo->numOfRes = numOfElems;
2,253,160✔
3565
  }
3566

3567
_exit:
2,253,007✔
3568
  if (pRows) {
2,253,028!
3569
    taosArrayDestroy(pRows);
2,253,028✔
3570
    pRows = NULL;
2,253,028✔
3571
  }
3572
  return code;
2,253,028✔
3573
}
3574

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

3577
bool getTopBotFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
88,421✔
3578
  SValueNode* pkNode = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
88,421✔
3579
  pEnv->calcMemSize = sizeof(STopBotRes) + pkNode->datum.i * sizeof(STopBotResItem);
88,472✔
3580
  return true;
88,472✔
3581
}
3582

3583
int32_t topBotFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
37,072,056✔
3584
  if (pResInfo->initialized) {
37,072,056!
3585
    return TSDB_CODE_SUCCESS;
×
3586
  }
3587
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
37,072,056!
3588
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
3589
  }
3590

3591
  STopBotRes*           pRes = GET_ROWCELL_INTERBUF(pResInfo);
37,075,292✔
3592
  SInputColumnInfoData* pInput = &pCtx->input;
37,075,292✔
3593

3594
  pRes->maxSize = pCtx->param[1].param.i;
37,075,292✔
3595

3596
  pRes->nullTupleSaved = false;
37,075,292✔
3597
  pRes->nullTuplePos.pageId = -1;
37,075,292✔
3598
  return TSDB_CODE_SUCCESS;
37,075,292✔
3599
}
3600

3601
static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) {
169,947,581✔
3602
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
169,947,581✔
3603
  STopBotRes*          pRes = GET_ROWCELL_INTERBUF(pResInfo);
169,947,581✔
3604
  pRes->pItems = (STopBotResItem*)((char*)pRes + sizeof(STopBotRes));
169,947,581✔
3605

3606
  return pRes;
169,947,581✔
3607
}
3608

3609
static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock,
3610
                               uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery);
3611

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

3614
int32_t topFunction(SqlFunctionCtx* pCtx) {
20,790,660✔
3615
  int32_t              numOfElems = 0;
20,790,660✔
3616
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
20,790,660✔
3617

3618
  SInputColumnInfoData* pInput = &pCtx->input;
20,790,660✔
3619
  SColumnInfoData*      pCol = pInput->pData[0];
20,790,660✔
3620

3621
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
20,790,660✔
3622
  pRes->type = pInput->pData[0]->info.type;
20,790,707✔
3623

3624
  int32_t start = pInput->startRowIndex;
20,790,707✔
3625
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
66,807,806✔
3626
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
46,014,830✔
3627
      continue;
23,069✔
3628
    }
3629

3630
    numOfElems++;
45,991,761✔
3631
    char*   data = colDataGetData(pCol, i);
45,991,761!
3632
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true);
45,991,761✔
3633
    if (code != TSDB_CODE_SUCCESS) {
45,994,030!
3634
      return code;
×
3635
    }
3636
  }
3637

3638
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
20,792,976✔
3639
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
118✔
3640
    if (code != TSDB_CODE_SUCCESS) {
118!
3641
      return code;
×
3642
    }
3643
    pRes->nullTupleSaved = true;
118✔
3644
  }
3645
  return TSDB_CODE_SUCCESS;
20,792,976✔
3646
}
3647

3648
int32_t bottomFunction(SqlFunctionCtx* pCtx) {
16,744,831✔
3649
  int32_t              numOfElems = 0;
16,744,831✔
3650
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
16,744,831✔
3651

3652
  SInputColumnInfoData* pInput = &pCtx->input;
16,744,831✔
3653
  SColumnInfoData*      pCol = pInput->pData[0];
16,744,831✔
3654

3655
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
16,744,831✔
3656
  pRes->type = pInput->pData[0]->info.type;
16,748,625✔
3657

3658
  int32_t start = pInput->startRowIndex;
16,748,625✔
3659
  for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
66,293,132✔
3660
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
49,529,581✔
3661
      continue;
22,432✔
3662
    }
3663

3664
    numOfElems++;
49,507,149✔
3665
    char*   data = colDataGetData(pCol, i);
49,507,149!
3666
    int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false);
49,507,149✔
3667
    if (code != TSDB_CODE_SUCCESS) {
49,522,075!
3668
      return code;
×
3669
    }
3670
  }
3671

3672
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) {
16,763,551✔
3673
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pRes->nullTuplePos);
784✔
3674
    if (code != TSDB_CODE_SUCCESS) {
784!
3675
      return code;
×
3676
    }
3677
    pRes->nullTupleSaved = true;
784✔
3678
  }
3679

3680
  return TSDB_CODE_SUCCESS;
16,763,551✔
3681
}
3682

3683
static int32_t topBotResComparFn(const void* p1, const void* p2, const void* param) {
365,384,196✔
3684
  uint16_t type = *(uint16_t*)param;
365,384,196✔
3685

3686
  STopBotResItem* val1 = (STopBotResItem*)p1;
365,384,196✔
3687
  STopBotResItem* val2 = (STopBotResItem*)p2;
365,384,196✔
3688

3689
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
365,384,196!
3690
    if (val1->v.i == val2->v.i) {
143,214,682✔
3691
      return 0;
234,503✔
3692
    }
3693

3694
    return (val1->v.i > val2->v.i) ? 1 : -1;
142,980,179✔
3695
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
222,169,514✔
3696
    if (val1->v.u == val2->v.u) {
730,353✔
3697
      return 0;
154,955✔
3698
    }
3699

3700
    return (val1->v.u > val2->v.u) ? 1 : -1;
575,398✔
3701
  } else if (TSDB_DATA_TYPE_FLOAT == type) {
221,439,161✔
3702
    if (val1->v.f == val2->v.f) {
81,275,893✔
3703
      return 0;
63✔
3704
    }
3705

3706
    return (val1->v.f > val2->v.f) ? 1 : -1;
81,275,830✔
3707
  }
3708

3709
  if (val1->v.d == val2->v.d) {
140,163,268✔
3710
    return 0;
11✔
3711
  }
3712

3713
  return (val1->v.d > val2->v.d) ? 1 : -1;
140,163,257✔
3714
}
3715

3716
int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type,
95,454,822✔
3717
                        uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) {
3718
  STopBotRes* pRes = getTopBotOutputInfo(pCtx);
95,454,822✔
3719
  int32_t     code = TSDB_CODE_SUCCESS;
95,480,706✔
3720

3721
  SVariant val = {0};
95,480,706✔
3722
  TAOS_CHECK_RETURN(taosVariantCreateFromBinary(&val, pData, tDataTypes[type].bytes, type));
95,480,706!
3723

3724
  STopBotResItem* pItems = pRes->pItems;
95,514,576✔
3725

3726
  // not full yet
3727
  if (pEntryInfo->numOfRes < pRes->maxSize) {
95,514,576✔
3728
    STopBotResItem* pItem = &pItems[pEntryInfo->numOfRes];
58,388,239✔
3729
    pItem->v = val;
58,388,239✔
3730
    pItem->uid = uid;
58,388,239✔
3731

3732
    // save the data of this tuple
3733
    if (pCtx->subsidiaries.num > 0) {
58,388,239✔
3734
      code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
34,627,789✔
3735
      if (code != TSDB_CODE_SUCCESS) {
34,618,541!
3736
        return code;
×
3737
      }
3738
    }
3739
#ifdef BUF_PAGE_DEBUG
3740
    qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId,
3741
           pItem->tuplePos.offset);
3742
#endif
3743
    // allocate the buffer and keep the data of this row into the new allocated buffer
3744
    pEntryInfo->numOfRes++;
58,378,991✔
3745
    code = taosheapsort((void*)pItems, sizeof(STopBotResItem), pEntryInfo->numOfRes, (const void*)&type,
58,378,991✔
3746
                        topBotResComparFn, !isTopQuery);
58,378,991✔
3747
    if (code != TSDB_CODE_SUCCESS) {
58,389,577!
3748
      return code;
×
3749
    }
3750
  } else {  // replace the minimum value in the result
3751
    if ((isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i > pItems[0].v.i) ||
37,126,337!
3752
                        (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u > pItems[0].v.u) ||
11,724,602!
3753
                        (TSDB_DATA_TYPE_FLOAT == type && val.f > pItems[0].v.f) ||
11,628,766✔
3754
                        (TSDB_DATA_TYPE_DOUBLE == type && val.d > pItems[0].v.d))) ||
11,627,300✔
3755
        (!isTopQuery && ((IS_SIGNED_NUMERIC_TYPE(type) && val.i < pItems[0].v.i) ||
33,166,371!
3756
                         (IS_UNSIGNED_NUMERIC_TYPE(type) && val.u < pItems[0].v.u) ||
22,332,606!
3757
                         (TSDB_DATA_TYPE_FLOAT == type && val.f < pItems[0].v.f) ||
22,328,396✔
3758
                         (TSDB_DATA_TYPE_DOUBLE == type && val.d < pItems[0].v.d)))) {
20,557,434✔
3759
      // replace the old data and the coresponding tuple data
3760
      STopBotResItem* pItem = &pItems[0];
7,674,025✔
3761
      pItem->v = val;
7,674,025✔
3762
      pItem->uid = uid;
7,674,025✔
3763

3764
      // save the data of this tuple by over writing the old data
3765
      if (pCtx->subsidiaries.num > 0) {
7,674,025✔
3766
        code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pItem->tuplePos);
5,325,622✔
3767
        if (code != TSDB_CODE_SUCCESS) {
5,324,671!
3768
          return code;
×
3769
        }
3770
      }
3771
#ifdef BUF_PAGE_DEBUG
3772
      qDebug("page_copyTuple pageId:%d, offset:%d", pItem->tuplePos.pageId, pItem->tuplePos.offset);
3773
#endif
3774
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
7,673,074✔
3775
                            topBotResComparFn, NULL, !isTopQuery);
7,673,074✔
3776
      if (code != TSDB_CODE_SUCCESS) {
7,658,460!
3777
        return code;
×
3778
      }
3779
    }
3780
  }
3781

3782
  return TSDB_CODE_SUCCESS;
95,500,349✔
3783
}
3784

3785
/*
3786
 * +------------------------------------+--------------+--------------+
3787
 * |            null bitmap             |              |              |
3788
 * |(n columns, one bit for each column)| src column #1| src column #2|
3789
 * +------------------------------------+--------------+--------------+
3790
 */
3791
int32_t serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsidiaryResInfo* pSubsidiaryies,
255,552,276✔
3792
                           char* buf, char** res) {
3793
  char* nullList = buf;
255,552,276✔
3794
  char* pStart = (char*)(nullList + sizeof(bool) * pSubsidiaryies->num);
255,552,276✔
3795

3796
  int32_t offset = 0;
255,552,276✔
3797
  for (int32_t i = 0; i < pSubsidiaryies->num; ++i) {
511,160,331✔
3798
    SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i];
255,640,043✔
3799

3800
    // group_key function has its own process function
3801
    // do not process there
3802
    if (fmIsGroupKeyFunc(pc->functionId)) {
255,640,043!
3803
      continue;
×
3804
    }
3805

3806
    SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0];
255,657,324✔
3807
    int32_t      srcSlotId = pFuncParam->pCol->slotId;
255,657,324✔
3808

3809
    SColumnInfoData* pCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
255,657,324✔
3810
    if (NULL == pCol) {
255,608,055!
3811
      return TSDB_CODE_OUT_OF_RANGE;
×
3812
    }
3813
    if ((nullList[i] = colDataIsNull_s(pCol, rowIndex)) == true) {
511,216,110✔
3814
      offset += pCol->info.bytes;
809✔
3815
      continue;
809✔
3816
    }
3817

3818
    char* p = colDataGetData(pCol, rowIndex);
255,607,246!
3819
    if (IS_VAR_DATA_TYPE(pCol->info.type)) {
255,607,246!
3820
      (void)memcpy(pStart + offset, p, (pCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(p) : varDataTLen(p));
38,395!
3821
    } else {
3822
      (void)memcpy(pStart + offset, p, pCol->info.bytes);
255,568,851✔
3823
    }
3824

3825
    offset += pCol->info.bytes;
255,607,246✔
3826
  }
3827

3828
  *res = buf;
255,520,288✔
3829
  return TSDB_CODE_SUCCESS;
255,520,288✔
3830
}
3831

3832
static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, SWinKey* key,
305,450,387✔
3833
                               STuplePos* pPos, SFunctionStateStore* pStore) {
3834
  STuplePos p = {0};
305,450,387✔
3835
  if (pHandle->pBuf != NULL) {
305,450,387✔
3836
    SFilePage* pPage = NULL;
305,415,295✔
3837

3838
    if (pHandle->currentPage == -1) {
305,415,295✔
3839
      pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
712,772✔
3840
      if (pPage == NULL) {
712,832!
3841
        return terrno;
×
3842
      }
3843
      pPage->num = sizeof(SFilePage);
712,832✔
3844
    } else {
3845
      pPage = getBufPage(pHandle->pBuf, pHandle->currentPage);
304,702,523✔
3846
      if (pPage == NULL) {
304,644,426!
3847
        return terrno;
×
3848
      }
3849
      if (pPage->num + length > getBufPageSize(pHandle->pBuf)) {
304,644,426✔
3850
        // current page is all used, let's prepare a new buffer page
3851
        releaseBufPage(pHandle->pBuf, pPage);
3,965,123✔
3852
        pPage = getNewBufPage(pHandle->pBuf, &pHandle->currentPage);
3,965,124✔
3853
        if (pPage == NULL) {
3,965,123!
3854
          return terrno;
×
3855
        }
3856
        pPage->num = sizeof(SFilePage);
3,965,123✔
3857
      }
3858
    }
3859

3860
    p = (STuplePos){.pageId = pHandle->currentPage, .offset = pPage->num};
305,354,702✔
3861
    (void)memcpy(pPage->data + pPage->num, pBuf, length);
305,354,702✔
3862

3863
    pPage->num += length;
305,354,702✔
3864
    setBufPageDirty(pPage, true);
305,354,702✔
3865
    releaseBufPage(pHandle->pBuf, pPage);
305,296,839✔
3866
  } else {  // other tuple save policy
3867
    if (pStore->streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) {
35,092!
3868
      p.streamTupleKey = *key;
52,967✔
3869
    }
3870
  }
3871

3872
  *pPos = p;
305,300,595✔
3873
  return TSDB_CODE_SUCCESS;
305,300,595✔
3874
}
3875

3876
int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
204,430,770✔
3877
  int32_t code = prepareBuf(pCtx);
204,430,770✔
3878
  if (TSDB_CODE_SUCCESS != code) {
204,428,289!
3879
    return code;
×
3880
  }
3881

3882
  SWinKey key = {0};
204,428,289✔
3883
  if (pCtx->saveHandle.pBuf == NULL) {
204,428,289✔
3884
    SColumnInfoData* pColInfo = taosArrayGet(pSrcBlock->pDataBlock, pCtx->saveHandle.pState->tsIndex);
52,971✔
3885
    if (NULL == pColInfo) {
52,971!
3886
      return TSDB_CODE_OUT_OF_RANGE;
×
3887
    }
3888
    if (pColInfo->info.type != TSDB_DATA_TYPE_TIMESTAMP) {
52,971!
3889
      return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
3890
    }
3891
    key.groupId = pSrcBlock->info.id.groupId;
52,971✔
3892
    key.ts = *(int64_t*)colDataGetData(pColInfo, rowIndex);
52,971!
3893
  }
3894

3895
  char* buf = NULL;
204,428,289✔
3896
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
204,428,289✔
3897
  if (TSDB_CODE_SUCCESS != code) {
204,378,805!
3898
    return code;
×
3899
  }
3900
  return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos, pCtx->pStore);
204,378,805✔
3901
}
3902

3903
static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos,
51,172,633✔
3904
                                 SFunctionStateStore* pStore) {
3905
  if (pHandle->pBuf != NULL) {
51,172,633✔
3906
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
51,078,126✔
3907
    if (pPage == NULL) {
51,076,877!
3908
      return terrno;
×
3909
    }
3910
    (void)memcpy(pPage->data + pPos->offset, pBuf, length);
51,076,877✔
3911
    setBufPageDirty(pPage, true);
51,076,877✔
3912
    releaseBufPage(pHandle->pBuf, pPage);
51,074,370✔
3913
  } else {
3914
    int32_t code = pStore->streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length);
94,507✔
3915
    if (TSDB_CODE_SUCCESS != code) {
94,740!
3916
      return code;
×
3917
    }
3918
  }
3919

3920
  return TSDB_CODE_SUCCESS;
51,168,476✔
3921
}
3922

3923
int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos) {
51,171,487✔
3924
  int32_t code = prepareBuf(pCtx);
51,171,487✔
3925
  if (TSDB_CODE_SUCCESS != code) {
51,171,867!
3926
    return code;
×
3927
  }
3928

3929
  char* buf = NULL;
51,171,867✔
3930
  code = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf, &buf);
51,171,867✔
3931
  if (TSDB_CODE_SUCCESS != code) {
51,172,058!
3932
    return code;
×
3933
  }
3934
  return doUpdateTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pPos, pCtx->pStore);
51,172,058✔
3935
}
3936

3937
static int32_t doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPos, SFunctionStateStore* pStore,
150,023,318✔
3938
                               char** value) {
3939
  if (pHandle->pBuf != NULL) {
150,023,318✔
3940
    SFilePage* pPage = getBufPage(pHandle->pBuf, pPos->pageId);
149,982,182✔
3941
    if (pPage == NULL) {
149,943,923!
3942
      *value = NULL;
×
3943
      return terrno;
×
3944
    }
3945
    *value = pPage->data + pPos->offset;
149,943,923✔
3946
    releaseBufPage(pHandle->pBuf, pPage);
149,943,923✔
3947
    return TSDB_CODE_SUCCESS;
149,928,136✔
3948
  } else {
3949
    *value = NULL;
41,136✔
3950
    int32_t vLen;
3951
    int32_t code = pStore->streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, (void**)(value), &vLen);
41,136✔
3952
    if (TSDB_CODE_SUCCESS != code) {
52,950!
3953
      return code;
×
3954
    }
3955
    return TSDB_CODE_SUCCESS;
52,950✔
3956
  }
3957
}
3958

3959
int32_t loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos, char** value) {
149,907,589✔
3960
  return doLoadTupleData(&pCtx->saveHandle, pPos, pCtx->pStore, value);
149,907,589✔
3961
}
3962

3963
int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
37,043,579✔
3964
  int32_t code = TSDB_CODE_SUCCESS;
37,043,579✔
3965

3966
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
37,043,579✔
3967
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
37,043,579✔
3968

3969
  int16_t type = pCtx->pExpr->base.resSchema.type;
37,040,538✔
3970
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
37,040,538✔
3971

3972
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
37,040,538✔
3973
  if (NULL == pCol) {
37,038,493!
3974
    return TSDB_CODE_OUT_OF_RANGE;
×
3975
  }
3976

3977
  // todo assign the tag value and the corresponding row data
3978
  int32_t currentRow = pBlock->info.rows;
37,038,493✔
3979
  if (pEntryInfo->numOfRes <= 0) {
37,038,493✔
3980
    colDataSetNULL(pCol, currentRow);
479!
3981
    code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow);
479✔
3982
    return code;
479✔
3983
  }
3984
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
95,346,328✔
3985
    STopBotResItem* pItem = &pRes->pItems[i];
58,298,399✔
3986
    code = colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false);
58,298,399✔
3987
    if (TSDB_CODE_SUCCESS != code) {
58,311,025!
3988
      return code;
×
3989
    }
3990
#ifdef BUF_PAGE_DEBUG
3991
    qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId,
3992
           pItem->tuplePos.offset);
3993
#endif
3994
    code = setSelectivityValue(pCtx, pBlock, &pRes->pItems[i].tuplePos, currentRow);
58,311,025✔
3995
    if (TSDB_CODE_SUCCESS != code) {
58,308,314!
3996
      return code;
×
3997
    }
3998
    currentRow += 1;
58,308,314✔
3999
  }
4000

4001
  return code;
37,047,929✔
4002
}
4003

4004
int32_t addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery) {
×
4005
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
×
4006
  STopBotRes*          pRes = getTopBotOutputInfo(pCtx);
×
4007
  STopBotResItem*      pItems = pRes->pItems;
×
4008
  int32_t              code = TSDB_CODE_SUCCESS;
×
4009

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

4037
      // save the data of this tuple by over writing the old data
4038
      replaceTupleData(&pItem->tuplePos, &pSourceItem->tuplePos);
×
4039
      code = taosheapadjust((void*)pItems, sizeof(STopBotResItem), 0, pEntryInfo->numOfRes - 1, (const void*)&type,
×
4040
                            topBotResComparFn, NULL, !isTopQuery);
×
4041
      if (TSDB_CODE_SUCCESS != code) {
×
4042
        return code;
×
4043
      }
4044
    }
4045
  }
4046
  return code;
×
4047
}
4048

4049
int32_t topCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4050
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4051
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4052
  int16_t              type = pSBuf->type;
×
4053
  int32_t              code = TSDB_CODE_SUCCESS;
×
4054
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4055
    code = addResult(pDestCtx, pSBuf->pItems + i, type, true);
×
4056
    if (TSDB_CODE_SUCCESS != code) {
×
4057
      return code;
×
4058
    }
4059
  }
4060
  return TSDB_CODE_SUCCESS;
×
4061
}
4062

4063
int32_t bottomCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4064
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4065
  STopBotRes*          pSBuf = getTopBotOutputInfo(pSourceCtx);
×
4066
  int16_t              type = pSBuf->type;
×
4067
  int32_t              code = TSDB_CODE_SUCCESS;
×
4068
  for (int32_t i = 0; i < pSResInfo->numOfRes; i++) {
×
4069
    code = addResult(pDestCtx, pSBuf->pItems + i, type, false);
×
4070
    if (TSDB_CODE_SUCCESS != code) {
×
4071
      return code;
×
4072
    }
4073
  }
4074
  return TSDB_CODE_SUCCESS;
×
4075
}
4076

4077
int32_t getSpreadInfoSize() { return (int32_t)sizeof(SSpreadInfo); }
1,203,860✔
4078

4079
bool getSpreadFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
104,879✔
4080
  pEnv->calcMemSize = sizeof(SSpreadInfo);
104,879✔
4081
  return true;
104,879✔
4082
}
4083

4084
int32_t spreadFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
3,932,152✔
4085
  if (pResultInfo->initialized) {
3,932,152!
4086
    return TSDB_CODE_SUCCESS;
×
4087
  }
4088
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
3,932,152!
4089
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4090
  }
4091

4092
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
3,932,165✔
4093
  SET_DOUBLE_VAL(&pInfo->min, DBL_MAX);
3,932,165✔
4094
  SET_DOUBLE_VAL(&pInfo->max, -DBL_MAX);
3,932,165✔
4095
  pInfo->hasResult = false;
3,932,165✔
4096
  return TSDB_CODE_SUCCESS;
3,932,165✔
4097
}
4098

4099
int32_t spreadFunction(SqlFunctionCtx* pCtx) {
2,782,014✔
4100
  int32_t numOfElems = 0;
2,782,014✔
4101

4102
  // Only the pre-computing information loaded and actual data does not loaded
4103
  SInputColumnInfoData* pInput = &pCtx->input;
2,782,014✔
4104
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,782,014✔
4105
  int32_t               type = pInput->pData[0]->info.type;
2,782,014✔
4106

4107
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,782,014✔
4108

4109
  if (pInput->colDataSMAIsSet) {
2,782,014!
4110
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
×
4111
    if (numOfElems == 0) {
×
4112
      goto _spread_over;
×
4113
    }
4114
    double tmin = 0.0, tmax = 0.0;
×
4115
    if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) {
×
4116
      tmin = (double)GET_INT64_VAL(&pAgg->min);
×
4117
      tmax = (double)GET_INT64_VAL(&pAgg->max);
×
4118
    } else if (IS_FLOAT_TYPE(type)) {
×
4119
      tmin = GET_DOUBLE_VAL(&pAgg->min);
×
4120
      tmax = GET_DOUBLE_VAL(&pAgg->max);
×
4121
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
4122
      tmin = (double)GET_UINT64_VAL(&pAgg->min);
×
4123
      tmax = (double)GET_UINT64_VAL(&pAgg->max);
×
4124
    }
4125

4126
    if (GET_DOUBLE_VAL(&pInfo->min) > tmin) {
×
4127
      SET_DOUBLE_VAL(&pInfo->min, tmin);
×
4128
    }
4129

4130
    if (GET_DOUBLE_VAL(&pInfo->max) < tmax) {
×
4131
      SET_DOUBLE_VAL(&pInfo->max, tmax);
×
4132
    }
4133

4134
  } else {  // computing based on the true data block
4135
    SColumnInfoData* pCol = pInput->pData[0];
2,782,014✔
4136

4137
    int32_t start = pInput->startRowIndex;
2,782,014✔
4138
    // check the valid data one by one
4139
    for (int32_t i = start; i < pInput->numOfRows + start; ++i) {
13,819,918✔
4140
      if (colDataIsNull_f(pCol->nullbitmap, i)) {
11,037,904✔
4141
        continue;
1,385,375✔
4142
      }
4143

4144
      char* data = colDataGetData(pCol, i);
9,652,529!
4145

4146
      double v = 0;
9,652,529✔
4147
      GET_TYPED_DATA(v, double, type, data);
9,652,529!
4148
      if (v < GET_DOUBLE_VAL(&pInfo->min)) {
9,652,529✔
4149
        SET_DOUBLE_VAL(&pInfo->min, v);
3,048,560✔
4150
      }
4151

4152
      if (v > GET_DOUBLE_VAL(&pInfo->max)) {
9,652,529✔
4153
        SET_DOUBLE_VAL(&pInfo->max, v);
3,578,904✔
4154
      }
4155

4156
      numOfElems += 1;
9,652,529✔
4157
    }
4158
  }
4159

4160
_spread_over:
2,782,014✔
4161
  // data in the check operation are all null, not output
4162
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
2,782,014✔
4163
  if (numOfElems > 0) {
2,782,014✔
4164
    pInfo->hasResult = true;
2,753,730✔
4165
  }
4166

4167
  return TSDB_CODE_SUCCESS;
2,782,014✔
4168
}
4169

4170
static void spreadTransferInfo(SSpreadInfo* pInput, SSpreadInfo* pOutput) {
1,202,282✔
4171
  pOutput->hasResult = pInput->hasResult;
1,202,282✔
4172
  if (pInput->max > pOutput->max) {
1,202,282✔
4173
    pOutput->max = pInput->max;
1,197,827✔
4174
  }
4175

4176
  if (pInput->min < pOutput->min) {
1,202,282✔
4177
    pOutput->min = pInput->min;
1,197,841✔
4178
  }
4179
}
1,202,282✔
4180

4181
int32_t spreadFunctionMerge(SqlFunctionCtx* pCtx) {
1,198,303✔
4182
  SInputColumnInfoData* pInput = &pCtx->input;
1,198,303✔
4183
  SColumnInfoData*      pCol = pInput->pData[0];
1,198,303✔
4184

4185
  if (IS_NULL_TYPE(pCol->info.type)) {
1,198,303!
4186
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4187
    return TSDB_CODE_SUCCESS;
×
4188
  }
4189

4190
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,198,303!
4191
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4192
  }
4193

4194
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,198,303✔
4195

4196
  int32_t start = pInput->startRowIndex;
1,198,303✔
4197
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
2,400,801✔
4198
    if (colDataIsNull_s(pCol, i)) continue;
2,404,996!
4199
    char*        data = colDataGetData(pCol, i);
1,202,498!
4200
    SSpreadInfo* pInputInfo = (SSpreadInfo*)varDataVal(data);
1,202,498✔
4201
    if (pInputInfo->hasResult) {
1,202,498✔
4202
      spreadTransferInfo(pInputInfo, pInfo);
1,202,281✔
4203
    }
4204
  }
4205

4206
  if (pInfo->hasResult) {
1,198,303✔
4207
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,198,152✔
4208
  }
4209

4210
  return TSDB_CODE_SUCCESS;
1,198,303✔
4211
}
4212

4213
int32_t spreadFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
2,712,106✔
4214
  SSpreadInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
2,712,106✔
4215
  if (pInfo->hasResult == true) {
2,712,106✔
4216
    SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min);
2,684,365✔
4217
  } else {
4218
    GET_RES_INFO(pCtx)->isNullRes = 1;
27,741✔
4219
  }
4220
  return functionFinalize(pCtx, pBlock);
2,712,106✔
4221
}
4222

4223
int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,202,286✔
4224
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,202,286✔
4225
  SSpreadInfo*         pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,202,286✔
4226
  int32_t              resultBytes = getSpreadInfoSize();
1,202,286✔
4227
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,202,286!
4228

4229
  if (NULL == res) {
1,202,286!
4230
    return terrno;
×
4231
  }
4232
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,202,286✔
4233
  varDataSetLen(res, resultBytes);
1,202,286✔
4234

4235
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,202,286✔
4236
  int32_t          code = TSDB_CODE_SUCCESS;
1,202,286✔
4237
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,202,286✔
4238
  if (NULL == pCol) {
1,202,286!
4239
    code = terrno;
×
4240
    goto _exit;
×
4241
  }
4242

4243
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,202,286✔
4244
  if (TSDB_CODE_SUCCESS != code) {
1,202,286!
4245
    goto _exit;
×
4246
  }
4247

4248
_exit:
1,202,286✔
4249
  taosMemoryFree(res);
1,202,286!
4250
  return code;
1,202,286✔
4251
}
4252

4253
int32_t spreadCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
4254
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
4255
  SSpreadInfo*         pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
4256

4257
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
4258
  SSpreadInfo*         pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
4259
  spreadTransferInfo(pSBuf, pDBuf);
1✔
4260
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
4261
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
4262
  return TSDB_CODE_SUCCESS;
1✔
4263
}
4264

4265
int32_t getElapsedInfoSize() { return (int32_t)sizeof(SElapsedInfo); }
×
4266

4267
bool getElapsedFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
104,413✔
4268
  pEnv->calcMemSize = sizeof(SElapsedInfo);
104,413✔
4269
  return true;
104,413✔
4270
}
4271

4272
int32_t elapsedFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
12,812,857✔
4273
  if (pResultInfo->initialized) {
12,812,857!
4274
    return TSDB_CODE_SUCCESS;
×
4275
  }
4276
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
12,812,857!
4277
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4278
  }
4279

4280
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
12,812,858✔
4281
  pInfo->result = 0;
12,812,858✔
4282
  pInfo->min = TSKEY_MAX;
12,812,858✔
4283
  pInfo->max = 0;
12,812,858✔
4284

4285
  if (pCtx->numOfParams > 1) {
12,812,858✔
4286
    pInfo->timeUnit = pCtx->param[1].param.i;
12,796,110✔
4287
  } else {
4288
    pInfo->timeUnit = 1;
16,748✔
4289
  }
4290

4291
  return TSDB_CODE_SUCCESS;
12,812,858✔
4292
}
4293

4294
int32_t elapsedFunction(SqlFunctionCtx* pCtx) {
12,834,758✔
4295
  int32_t numOfElems = 0;
12,834,758✔
4296

4297
  // Only the pre-computing information loaded and actual data does not loaded
4298
  SInputColumnInfoData* pInput = &pCtx->input;
12,834,758✔
4299
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
12,834,758✔
4300

4301
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
12,834,758✔
4302

4303
  numOfElems = pInput->numOfRows;  // since this is the primary timestamp, no need to exclude NULL values
12,834,758✔
4304
  if (numOfElems == 0) {
12,834,758✔
4305
    // for stream
4306
    if (pCtx->end.key != INT64_MIN) {
1,708✔
4307
      pInfo->max = pCtx->end.key + 1;
52✔
4308
    }
4309
    goto _elapsed_over;
1,708✔
4310
  }
4311

4312
  if (pInput->colDataSMAIsSet) {
12,833,050!
4313
    if (pInfo->min == TSKEY_MAX) {
×
4314
      pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4315
      pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4316
    } else {
4317
      if (pCtx->order == TSDB_ORDER_ASC) {
×
4318
        pInfo->max = GET_INT64_VAL(&pAgg->max);
×
4319
      } else {
4320
        pInfo->min = GET_INT64_VAL(&pAgg->min);
×
4321
      }
4322
    }
4323
  } else {  // computing based on the true data block
4324
    if (0 == pInput->numOfRows) {
12,833,050!
4325
      if (pCtx->order == TSDB_ORDER_DESC) {
×
4326
        if (pCtx->end.key != INT64_MIN) {
×
4327
          pInfo->min = pCtx->end.key;
×
4328
        }
4329
      } else {
4330
        if (pCtx->end.key != INT64_MIN) {
×
4331
          pInfo->max = pCtx->end.key + 1;
×
4332
        }
4333
      }
4334
      goto _elapsed_over;
×
4335
    }
4336

4337
    SColumnInfoData* pCol = pInput->pData[0];
12,833,050✔
4338

4339
    int32_t start = pInput->startRowIndex;
12,833,050✔
4340
    TSKEY*  ptsList = (int64_t*)colDataGetData(pCol, 0);
12,833,050!
4341
    if (pCtx->order == TSDB_ORDER_DESC) {
12,833,050✔
4342
      if (pCtx->start.key == INT64_MIN) {
670!
4343
        pInfo->max = (pInfo->max < ptsList[start]) ? ptsList[start] : pInfo->max;
670✔
4344
      } else {
4345
        pInfo->max = pCtx->start.key + 1;
×
4346
      }
4347

4348
      if (pCtx->end.key == INT64_MIN) {
670!
4349
        pInfo->min =
670✔
4350
            (pInfo->min > ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->min;
670✔
4351
      } else {
4352
        pInfo->min = pCtx->end.key;
×
4353
      }
4354
    } else {
4355
      if (pCtx->start.key == INT64_MIN) {
12,832,380✔
4356
        pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min;
7,607,256✔
4357
      } else {
4358
        pInfo->min = pCtx->start.key;
5,225,124✔
4359
      }
4360

4361
      if (pCtx->end.key == INT64_MIN) {
12,832,380✔
4362
        pInfo->max =
7,382,731✔
4363
            (pInfo->max < ptsList[start + pInput->numOfRows - 1]) ? ptsList[start + pInput->numOfRows - 1] : pInfo->max;
7,382,731✔
4364
      } else {
4365
        pInfo->max = pCtx->end.key + 1;
5,449,649✔
4366
      }
4367
    }
4368
  }
4369

4370
_elapsed_over:
12,834,758✔
4371
  // data in the check operation are all null, not output
4372
  SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
12,834,758✔
4373

4374
  return TSDB_CODE_SUCCESS;
12,834,758✔
4375
}
4376

4377
static void elapsedTransferInfo(SElapsedInfo* pInput, SElapsedInfo* pOutput) {
×
4378
  pOutput->timeUnit = pInput->timeUnit;
×
4379
  if (pOutput->min > pInput->min) {
×
4380
    pOutput->min = pInput->min;
×
4381
  }
4382

4383
  if (pOutput->max < pInput->max) {
×
4384
    pOutput->max = pInput->max;
×
4385
  }
4386
}
×
4387

4388
int32_t elapsedFunctionMerge(SqlFunctionCtx* pCtx) {
×
4389
  SInputColumnInfoData* pInput = &pCtx->input;
×
4390
  SColumnInfoData*      pCol = pInput->pData[0];
×
4391
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
×
4392
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4393
  }
4394

4395
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4396

4397
  int32_t start = pInput->startRowIndex;
×
4398

4399
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
×
4400
    char*         data = colDataGetData(pCol, i);
×
4401
    SElapsedInfo* pInputInfo = (SElapsedInfo*)varDataVal(data);
×
4402
    elapsedTransferInfo(pInputInfo, pInfo);
×
4403
  }
4404

4405
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
×
4406
  return TSDB_CODE_SUCCESS;
×
4407
}
4408

4409
int32_t elapsedFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
12,794,605✔
4410
  SElapsedInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
12,794,605✔
4411
  double        result = (double)pInfo->max - (double)pInfo->min;
12,794,605✔
4412
  result = (result >= 0) ? result : -result;
12,794,605✔
4413
  pInfo->result = result / pInfo->timeUnit;
12,794,605✔
4414
  return functionFinalize(pCtx, pBlock);
12,794,605✔
4415
}
4416

4417
int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
4418
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
×
4419
  SElapsedInfo*        pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
×
4420
  int32_t              resultBytes = getElapsedInfoSize();
×
4421
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
×
4422

4423
  if (NULL == res) {
×
4424
    return terrno;
×
4425
  }
4426
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
×
4427
  varDataSetLen(res, resultBytes);
×
4428

4429
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
×
4430
  int32_t          code = TSDB_CODE_SUCCESS;
×
4431
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
×
4432
  if (NULL == pCol) {
×
4433
    code = terrno;
×
4434
    goto _exit;
×
4435
  }
4436

4437
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
×
4438
  if (TSDB_CODE_SUCCESS != code) {
×
4439
    goto _exit;
×
4440
  }
4441
_exit:
×
4442
  taosMemoryFree(res);
×
4443
  return code;
×
4444
}
4445

4446
int32_t elapsedCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4447
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4448
  SElapsedInfo*        pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4449

4450
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4451
  SElapsedInfo*        pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4452

4453
  elapsedTransferInfo(pSBuf, pDBuf);
×
4454
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4455
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4456
  return TSDB_CODE_SUCCESS;
×
4457
}
4458

4459
int32_t getHistogramInfoSize() {
1,931,098✔
4460
  return (int32_t)sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
1,931,098✔
4461
}
4462

4463
bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
112,157✔
4464
  pEnv->calcMemSize = sizeof(SHistoFuncInfo) + HISTOGRAM_MAX_BINS_NUM * sizeof(SHistoFuncBin);
112,157✔
4465
  return true;
112,157✔
4466
}
4467

4468
static int8_t getHistogramBinType(char* binTypeStr) {
8,176,215✔
4469
  int8_t binType;
4470
  if (strcasecmp(binTypeStr, "user_input") == 0) {
8,176,215✔
4471
    binType = USER_INPUT_BIN;
1,177✔
4472
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
8,175,038✔
4473
    binType = LINEAR_BIN;
1,757✔
4474
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
8,173,281!
4475
    binType = LOG_BIN;
8,173,374✔
4476
  } else {
4477
    binType = UNKNOWN_BIN;
×
4478
  }
4479

4480
  return binType;
8,176,215✔
4481
}
4482

4483
static int32_t getHistogramBinDesc(SHistoFuncInfo* pInfo, char* binDescStr, int8_t binType, bool normalized) {
8,176,344✔
4484
  cJSON*  binDesc = cJSON_Parse(binDescStr);
8,176,344✔
4485
  int32_t numOfBins;
4486
  double* intervals;
4487
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
8,176,293✔
4488
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
8,175,173✔
4489
    int32_t startIndex;
4490
    if (numOfParams != 4) {
8,175,176!
4491
      cJSON_Delete(binDesc);
×
4492
      return TSDB_CODE_FAILED;
×
4493
    }
4494

4495
    cJSON* start = cJSON_GetObjectItem(binDesc, "start");
8,175,176✔
4496
    cJSON* factor = cJSON_GetObjectItem(binDesc, "factor");
8,175,200✔
4497
    cJSON* width = cJSON_GetObjectItem(binDesc, "width");
8,175,179✔
4498
    cJSON* count = cJSON_GetObjectItem(binDesc, "count");
8,174,924✔
4499
    cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity");
8,175,148✔
4500

4501
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
8,175,157!
4502
      cJSON_Delete(binDesc);
×
4503
      return TSDB_CODE_FAILED;
×
4504
    }
4505

4506
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
8,175,120!
4507
      cJSON_Delete(binDesc);
2✔
4508
      return TSDB_CODE_FAILED;
×
4509
    }
4510

4511
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
8,175,118!
4512
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
8,175,118!
4513
      cJSON_Delete(binDesc);
×
4514
      return TSDB_CODE_FAILED;
×
4515
    }
4516

4517
    int32_t counter = (int32_t)count->valueint;
8,175,118✔
4518
    if (infinity->valueint == false) {
8,175,118✔
4519
      startIndex = 0;
3,348,895✔
4520
      numOfBins = counter + 1;
3,348,895✔
4521
    } else {
4522
      startIndex = 1;
4,826,223✔
4523
      numOfBins = counter + 3;
4,826,223✔
4524
    }
4525

4526
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
8,175,118!
4527
    if (NULL == intervals) {
8,174,864!
4528
      cJSON_Delete(binDesc);
×
4529
      qError("histogram function out of memory");
×
4530
      return terrno;
×
4531
    }
4532
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
8,174,864!
4533
      // linear bin process
4534
      if (width->valuedouble == 0) {
1,758!
4535
        taosMemoryFree(intervals);
×
4536
        cJSON_Delete(binDesc);
×
4537
        return TSDB_CODE_FAILED;
×
4538
      }
4539
      for (int i = 0; i < counter + 1; ++i) {
10,000✔
4540
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
8,242✔
4541
        if (isinf(intervals[startIndex])) {
8,242!
4542
          taosMemoryFree(intervals);
×
4543
          cJSON_Delete(binDesc);
×
4544
          return TSDB_CODE_FAILED;
×
4545
        }
4546
        startIndex++;
8,242✔
4547
      }
4548
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
8,173,119!
4549
      // log bin process
4550
      if (start->valuedouble == 0) {
8,173,140!
4551
        taosMemoryFree(intervals);
×
4552
        cJSON_Delete(binDesc);
×
4553
        return TSDB_CODE_FAILED;
×
4554
      }
4555
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
8,173,140!
4556
        taosMemoryFree(intervals);
×
4557
        cJSON_Delete(binDesc);
×
4558
        return TSDB_CODE_FAILED;
×
4559
      }
4560
      for (int i = 0; i < counter + 1; ++i) {
57,207,753✔
4561
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
49,034,595✔
4562
        if (isinf(intervals[startIndex])) {
49,034,595!
4563
          taosMemoryFree(intervals);
×
4564
          cJSON_Delete(binDesc);
×
4565
          return TSDB_CODE_FAILED;
×
4566
        }
4567
        startIndex++;
49,034,595✔
4568
      }
4569
    } else {
4570
      taosMemoryFree(intervals);
×
4571
      cJSON_Delete(binDesc);
×
4572
      return TSDB_CODE_FAILED;
×
4573
    }
4574

4575
    if (infinity->valueint == true) {
8,174,916✔
4576
      intervals[0] = -INFINITY;
4,826,379✔
4577
      intervals[numOfBins - 1] = INFINITY;
4,826,379✔
4578
      // in case of desc bin orders, -inf/inf should be swapped
4579
      if (numOfBins < 4) {
4,826,379!
4580
        return TSDB_CODE_FAILED;
×
4581
      }
4582
      if (intervals[1] > intervals[numOfBins - 2]) {
4,826,379✔
4583
        TSWAP(intervals[0], intervals[numOfBins - 1]);
4,825,197✔
4584
      }
4585
    }
4586
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
1,177!
4587
    if (binType != USER_INPUT_BIN) {
1,177!
4588
      cJSON_Delete(binDesc);
×
4589
      return TSDB_CODE_FAILED;
×
4590
    }
4591
    numOfBins = cJSON_GetArraySize(binDesc);
1,177✔
4592
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
1,177!
4593
    if (NULL == intervals) {
1,177!
4594
      cJSON_Delete(binDesc);
×
4595
      qError("histogram function out of memory");
×
4596
      return terrno;
×
4597
    }
4598
    cJSON* bin = binDesc->child;
1,177✔
4599
    if (bin == NULL) {
1,177!
4600
      taosMemoryFree(intervals);
×
4601
      cJSON_Delete(binDesc);
×
4602
      return TSDB_CODE_FAILED;
×
4603
    }
4604
    int i = 0;
1,177✔
4605
    while (bin) {
3,580✔
4606
      intervals[i] = bin->valuedouble;
2,403✔
4607
      if (!cJSON_IsNumber(bin)) {
2,403!
4608
        taosMemoryFree(intervals);
×
4609
        cJSON_Delete(binDesc);
×
4610
        return TSDB_CODE_FAILED;
×
4611
      }
4612
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
2,403!
4613
        taosMemoryFree(intervals);
×
4614
        cJSON_Delete(binDesc);
×
4615
        return TSDB_CODE_FAILED;
×
4616
      }
4617
      bin = bin->next;
2,403✔
4618
      i++;
2,403✔
4619
    }
4620
  } else {
4621
    cJSON_Delete(binDesc);
×
4622
    return TSDB_CODE_FAILED;
×
4623
  }
4624

4625
  pInfo->numOfBins = numOfBins - 1;
8,176,093✔
4626
  pInfo->normalized = normalized;
8,176,093✔
4627
  for (int32_t i = 0; i < pInfo->numOfBins; ++i) {
58,699,018✔
4628
    pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
50,522,925✔
4629
    pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
50,522,925✔
4630
    pInfo->bins[i].count = 0;
50,522,925✔
4631
  }
4632

4633
  taosMemoryFree(intervals);
8,176,093!
4634
  cJSON_Delete(binDesc);
8,176,263✔
4635

4636
  return TSDB_CODE_SUCCESS;
8,176,353✔
4637
}
4638

4639
int32_t histogramFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,176,223✔
4640
  if (pResultInfo->initialized) {
8,176,223!
4641
    return TSDB_CODE_SUCCESS;
×
4642
  }
4643
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,176,223!
4644
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
4645
  }
4646

4647
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
8,176,176✔
4648
  pInfo->numOfBins = 0;
8,176,176✔
4649
  pInfo->totalCount = 0;
8,176,176✔
4650
  pInfo->normalized = 0;
8,176,176✔
4651

4652
  char* binTypeStr = taosStrndup(varDataVal(pCtx->param[1].param.pz), varDataLen(pCtx->param[1].param.pz));
8,176,176!
4653
  if (binTypeStr == NULL) {
8,176,243!
4654
    return terrno;
×
4655
  }
4656
  int8_t binType = getHistogramBinType(binTypeStr);
8,176,243✔
4657
  taosMemoryFree(binTypeStr);
8,176,271!
4658

4659
  if (binType == UNKNOWN_BIN) {
8,176,186!
4660
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4661
  }
4662
  char* binDesc = taosStrndup(varDataVal(pCtx->param[2].param.pz), varDataLen(pCtx->param[2].param.pz));
8,176,186!
4663
  if (binDesc == NULL) {
8,176,339!
4664
    return terrno;
×
4665
  }
4666
  int64_t normalized = pCtx->param[3].param.i;
8,176,339✔
4667
  if (normalized != 0 && normalized != 1) {
8,176,339!
4668
    taosMemoryFree(binDesc);
×
4669
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
4670
  }
4671
  int32_t code = getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized);
8,176,339✔
4672
  if (TSDB_CODE_SUCCESS != code) {
8,176,336!
4673
    taosMemoryFree(binDesc);
×
4674
    return code;
×
4675
  }
4676
  taosMemoryFree(binDesc);
8,176,336!
4677

4678
  return TSDB_CODE_SUCCESS;
8,176,357✔
4679
}
4680

4681
static int32_t histogramFunctionImpl(SqlFunctionCtx* pCtx, bool isPartial) {
8,206,418✔
4682
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,206,418✔
4683

4684
  SInputColumnInfoData* pInput = &pCtx->input;
8,206,418✔
4685
  SColumnInfoData*      pCol = pInput->pData[0];
8,206,418✔
4686

4687
  int32_t type = pInput->pData[0]->info.type;
8,206,418✔
4688

4689
  int32_t start = pInput->startRowIndex;
8,206,418✔
4690
  int32_t numOfRows = pInput->numOfRows;
8,206,418✔
4691

4692
  int32_t numOfElems = 0;
8,206,418✔
4693
  for (int32_t i = start; i < numOfRows + start; ++i) {
27,166,795✔
4694
    if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) {
18,960,377✔
4695
      continue;
603,814✔
4696
    }
4697

4698
    numOfElems++;
18,356,563✔
4699

4700
    char*  data = colDataGetData(pCol, i);
18,356,563!
4701
    double v;
4702
    GET_TYPED_DATA(v, double, type, data);
18,356,563!
4703

4704
    for (int32_t k = 0; k < pInfo->numOfBins; ++k) {
53,889,973✔
4705
      if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) {
47,864,986✔
4706
        pInfo->bins[k].count++;
12,331,576✔
4707
        pInfo->totalCount++;
12,331,576✔
4708
        break;
12,331,576✔
4709
      }
4710
    }
4711
  }
4712

4713
  if (!isPartial) {
8,206,418✔
4714
    GET_RES_INFO(pCtx)->numOfRes = pInfo->numOfBins;
6,280,634✔
4715
  } else {
4716
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,925,784✔
4717
  }
4718
  return TSDB_CODE_SUCCESS;
8,206,418✔
4719
}
4720

4721
int32_t histogramFunction(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, false); }
6,280,638✔
4722

4723
int32_t histogramFunctionPartial(SqlFunctionCtx* pCtx) { return histogramFunctionImpl(pCtx, true); }
1,925,840✔
4724

4725
static void histogramTransferInfo(SHistoFuncInfo* pInput, SHistoFuncInfo* pOutput) {
1,904,625✔
4726
  pOutput->normalized = pInput->normalized;
1,904,625✔
4727
  pOutput->numOfBins = pInput->numOfBins;
1,904,625✔
4728
  pOutput->totalCount += pInput->totalCount;
1,904,625✔
4729
  for (int32_t k = 0; k < pOutput->numOfBins; ++k) {
15,233,053✔
4730
    pOutput->bins[k].lower = pInput->bins[k].lower;
13,328,428✔
4731
    pOutput->bins[k].upper = pInput->bins[k].upper;
13,328,428✔
4732
    pOutput->bins[k].count += pInput->bins[k].count;
13,328,428✔
4733
  }
4734
}
1,904,625✔
4735

4736
int32_t histogramFunctionMerge(SqlFunctionCtx* pCtx) {
1,904,625✔
4737
  SInputColumnInfoData* pInput = &pCtx->input;
1,904,625✔
4738
  SColumnInfoData*      pCol = pInput->pData[0];
1,904,625✔
4739
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,904,625!
4740
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
4741
  }
4742

4743
  SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,904,625✔
4744

4745
  int32_t start = pInput->startRowIndex;
1,904,625✔
4746

4747
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,809,250✔
4748
    char*           data = colDataGetData(pCol, i);
1,904,625!
4749
    SHistoFuncInfo* pInputInfo = (SHistoFuncInfo*)varDataVal(data);
1,904,625✔
4750
    histogramTransferInfo(pInputInfo, pInfo);
1,904,625✔
4751
  }
4752

4753
  SET_VAL(GET_RES_INFO(pCtx), pInfo->numOfBins, pInfo->numOfBins);
1,904,625!
4754
  return TSDB_CODE_SUCCESS;
1,904,625✔
4755
}
4756

4757
int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,119,375✔
4758
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,119,375✔
4759
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,119,375✔
4760
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
8,119,375✔
4761
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
8,119,375✔
4762
  int32_t              code = TSDB_CODE_SUCCESS;
8,119,333✔
4763

4764
  int32_t currentRow = pBlock->info.rows;
8,119,333✔
4765
  if (NULL == pCol) {
8,119,333!
4766
    return TSDB_CODE_OUT_OF_RANGE;
×
4767
  }
4768

4769
  if (pInfo->normalized) {
8,119,333✔
4770
    for (int32_t k = 0; k < pResInfo->numOfRes; ++k) {
20,003,390✔
4771
      if (pInfo->totalCount != 0) {
16,669,724✔
4772
        pInfo->bins[k].percentage = pInfo->bins[k].count / (double)pInfo->totalCount;
4,848,777✔
4773
      } else {
4774
        pInfo->bins[k].percentage = 0;
11,820,947✔
4775
      }
4776
    }
4777
  }
4778

4779
  for (int32_t i = 0; i < pResInfo->numOfRes; ++i) {
58,262,216✔
4780
    int32_t len;
4781
    char    buf[512] = {0};
50,162,402✔
4782
    if (!pInfo->normalized) {
50,162,402✔
4783
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
33,492,679✔
4784
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}", pInfo->bins[i].lower,
4785
                      pInfo->bins[i].upper, pInfo->bins[i].count);
4786
    } else {
4787
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE,
16,669,723✔
4788
                      "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", pInfo->bins[i].lower, pInfo->bins[i].upper,
4789
                      pInfo->bins[i].percentage);
4790
    }
4791
    varDataSetLen(buf, len);
50,162,401✔
4792
    code = colDataSetVal(pCol, currentRow, buf, false);
50,162,401✔
4793
    if (TSDB_CODE_SUCCESS != code) {
50,142,883!
4794
      return code;
×
4795
    }
4796
    currentRow++;
50,142,883✔
4797
  }
4798

4799
  return code;
8,099,814✔
4800
}
4801

4802
int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,924,899✔
4803
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,924,899✔
4804
  SHistoFuncInfo*      pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,924,899✔
4805
  int32_t              resultBytes = getHistogramInfoSize();
1,924,899✔
4806
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,924,899!
4807

4808
  if (NULL == res) {
1,924,900!
4809
    return terrno;
×
4810
  }
4811
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,924,900✔
4812
  varDataSetLen(res, resultBytes);
1,924,900✔
4813

4814
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,924,900✔
4815
  int32_t          code = TSDB_CODE_SUCCESS;
1,924,900✔
4816
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,924,900✔
4817
  if (NULL == pCol) {
1,924,900!
4818
    code = terrno;
×
4819
    goto _exit;
×
4820
  }
4821
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,924,900✔
4822

4823
_exit:
1,924,900✔
4824
  taosMemoryFree(res);
1,924,900!
4825
  return code;
1,924,900✔
4826
}
4827

4828
int32_t histogramCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
4829
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
4830
  SHistoFuncInfo*      pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
4831

4832
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
4833
  SHistoFuncInfo*      pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
4834

4835
  histogramTransferInfo(pSBuf, pDBuf);
×
4836
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
×
4837
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
×
4838
  return TSDB_CODE_SUCCESS;
×
4839
}
4840

4841
int32_t getHLLInfoSize() { return (int32_t)sizeof(SHLLInfo); }
10,517✔
4842

4843
bool getHLLFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
68,900✔
4844
  pEnv->calcMemSize = sizeof(SHLLInfo);
68,900✔
4845
  return true;
68,900✔
4846
}
4847

4848
static uint8_t hllCountNum(void* data, int32_t bytes, int32_t* buk) {
3,731,449✔
4849
  uint64_t hash = MurmurHash3_64(data, bytes);
3,731,449✔
4850
  int32_t  index = hash & HLL_BUCKET_MASK;
3,731,509✔
4851
  hash >>= HLL_BUCKET_BITS;
3,731,509✔
4852
  hash |= ((uint64_t)1 << HLL_DATA_BITS);
3,731,509✔
4853
  uint64_t bit = 1;
3,731,509✔
4854
  uint8_t  count = 1;
3,731,509✔
4855
  while ((hash & bit) == 0) {
7,182,351✔
4856
    count++;
3,450,842✔
4857
    bit <<= 1;
3,450,842✔
4858
  }
4859
  *buk = index;
3,731,509✔
4860
  return count;
3,731,509✔
4861
}
4862

4863
static void hllBucketHisto(uint8_t* buckets, int32_t* bucketHisto) {
249,190✔
4864
  uint64_t* word = (uint64_t*)buckets;
249,190✔
4865
  uint8_t*  bytes;
4866

4867
  for (int32_t j = 0; j < HLL_BUCKETS >> 3; j++) {
505,172,930✔
4868
    if (*word == 0) {
504,923,740✔
4869
      bucketHisto[0] += 8;
504,077,888✔
4870
    } else {
4871
      bytes = (uint8_t*)word;
845,852✔
4872
      bucketHisto[bytes[0]]++;
845,852✔
4873
      bucketHisto[bytes[1]]++;
845,852✔
4874
      bucketHisto[bytes[2]]++;
845,852✔
4875
      bucketHisto[bytes[3]]++;
845,852✔
4876
      bucketHisto[bytes[4]]++;
845,852✔
4877
      bucketHisto[bytes[5]]++;
845,852✔
4878
      bucketHisto[bytes[6]]++;
845,852✔
4879
      bucketHisto[bytes[7]]++;
845,852✔
4880
    }
4881
    word++;
504,923,740✔
4882
  }
4883
}
249,190✔
4884
static double hllTau(double x) {
249,186✔
4885
  if (x == 0. || x == 1.) return 0.;
249,186!
4886
  double zPrime;
4887
  double y = 1.0;
×
4888
  double z = 1 - x;
×
4889
  do {
4890
    x = sqrt(x);
×
4891
    zPrime = z;
×
4892
    y *= 0.5;
×
4893
    z -= pow(1 - x, 2) * y;
×
4894
  } while (zPrime != z);
×
4895
  return z / 3;
×
4896
}
4897

4898
static double hllSigma(double x) {
249,199✔
4899
  if (x == 1.0) return INFINITY;
249,199✔
4900
  double zPrime;
4901
  double y = 1;
224,297✔
4902
  double z = x;
224,297✔
4903
  do {
4904
    x *= x;
4,398,026✔
4905
    zPrime = z;
4,398,026✔
4906
    z += x * y;
4,398,026✔
4907
    y += y;
4,398,026✔
4908
  } while (zPrime != z);
4,398,026✔
4909
  return z;
224,297✔
4910
}
4911

4912
// estimate the cardinality, the algorithm refer this paper: "New cardinality estimation algorithms for HyperLogLog
4913
// sketches"
4914
static uint64_t hllCountCnt(uint8_t* buckets) {
249,175✔
4915
  double  m = HLL_BUCKETS;
249,175✔
4916
  int32_t buckethisto[64] = {0};
249,175✔
4917
  hllBucketHisto(buckets, buckethisto);
249,175✔
4918

4919
  double z = m * hllTau((m - buckethisto[HLL_DATA_BITS + 1]) / (double)m);
249,190✔
4920
  for (int j = HLL_DATA_BITS; j >= 1; --j) {
12,705,731✔
4921
    z += buckethisto[j];
12,456,533✔
4922
    z *= 0.5;
12,456,533✔
4923
  }
4924

4925
  z += m * hllSigma(buckethisto[0] / (double)m);
249,198✔
4926
  double E = (double)llroundl(HLL_ALPHA_INF * m * m / z);
249,201✔
4927

4928
  return (uint64_t)E;
249,201✔
4929
}
4930

4931
int32_t hllFunction(SqlFunctionCtx* pCtx) {
274,381✔
4932
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
274,381✔
4933

4934
  SInputColumnInfoData* pInput = &pCtx->input;
274,381✔
4935
  SColumnInfoData*      pCol = pInput->pData[0];
274,381✔
4936

4937
  int32_t type = pCol->info.type;
274,381✔
4938
  int32_t bytes = pCol->info.bytes;
274,381✔
4939

4940
  int32_t start = pInput->startRowIndex;
274,381✔
4941
  int32_t numOfRows = pInput->numOfRows;
274,381✔
4942

4943
  int32_t numOfElems = 0;
274,381✔
4944
  if (IS_NULL_TYPE(type)) {
274,381✔
4945
    goto _hll_over;
1,566✔
4946
  }
4947

4948
  for (int32_t i = start; i < numOfRows + start; ++i) {
4,895,065✔
4949
    if (pCol->hasNull && colDataIsNull_s(pCol, i)) {
6,319,424!
4950
      continue;
888,799✔
4951
    }
4952

4953
    numOfElems++;
3,734,851✔
4954

4955
    char* data = colDataGetData(pCol, i);
3,734,851!
4956
    if (IS_VAR_DATA_TYPE(type)) {
3,734,851!
4957
      bytes = varDataLen(data);
1,017,146✔
4958
      data = varDataVal(data);
1,017,146✔
4959
    }
4960

4961
    int32_t index = 0;
3,734,851✔
4962
    uint8_t count = hllCountNum(data, bytes, &index);
3,734,851✔
4963
    uint8_t oldcount = pInfo->buckets[index];
3,733,451✔
4964
    if (count > oldcount) {
3,733,451✔
4965
      pInfo->buckets[index] = count;
866,833✔
4966
    }
4967
  }
4968

4969
_hll_over:
271,415✔
4970
  pInfo->totalCount += numOfElems;
272,981✔
4971

4972
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
272,981✔
4973
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
1,394✔
4974
  } else {
4975
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
271,587✔
4976
  }
4977

4978
  return TSDB_CODE_SUCCESS;
272,981✔
4979
}
4980

4981
static void hllTransferInfo(SHLLInfo* pInput, SHLLInfo* pOutput) {
10,801✔
4982
  for (int32_t k = 0; k < HLL_BUCKETS; ++k) {
174,806,070✔
4983
    if (pOutput->buckets[k] < pInput->buckets[k]) {
174,795,269✔
4984
      pOutput->buckets[k] = pInput->buckets[k];
153,145✔
4985
    }
4986
  }
4987
  pOutput->totalCount += pInput->totalCount;
10,801✔
4988
}
10,801✔
4989

4990
int32_t hllFunctionMerge(SqlFunctionCtx* pCtx) {
10,728✔
4991
  SInputColumnInfoData* pInput = &pCtx->input;
10,728✔
4992
  SColumnInfoData*      pCol = pInput->pData[0];
10,728✔
4993

4994
  if (IS_NULL_TYPE(pCol->info.type)) {
10,728!
4995
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
×
4996
    return TSDB_CODE_SUCCESS;
×
4997
  }
4998

4999
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
10,728!
5000
    return TSDB_CODE_SUCCESS;
×
5001
  }
5002

5003
  SHLLInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,728✔
5004

5005
  int32_t start = pInput->startRowIndex;
10,728✔
5006

5007
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
21,528✔
5008
    if (colDataIsNull_s(pCol, i)) continue;
21,598!
5009
    char*     data = colDataGetData(pCol, i);
10,799!
5010
    SHLLInfo* pInputInfo = (SHLLInfo*)varDataVal(data);
10,799✔
5011
    hllTransferInfo(pInputInfo, pInfo);
10,799✔
5012
  }
5013

5014
  if (pInfo->totalCount == 0 && !tsCountAlwaysReturnValue) {
10,729✔
5015
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
3✔
5016
  } else {
5017
    SET_VAL(GET_RES_INFO(pCtx), 1, 1);
10,726✔
5018
  }
5019

5020
  return TSDB_CODE_SUCCESS;
10,729✔
5021
}
5022

5023
int32_t hllFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
249,176✔
5024
  SResultRowEntryInfo* pInfo = GET_RES_INFO(pCtx);
249,176✔
5025

5026
  SHLLInfo* pHllInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
249,176✔
5027
  pHllInfo->result = hllCountCnt(pHllInfo->buckets);
249,176✔
5028
  if (tsCountAlwaysReturnValue && pHllInfo->result == 0) {
249,200✔
5029
    pInfo->numOfRes = 1;
23,528✔
5030
  }
5031

5032
  return functionFinalize(pCtx, pBlock);
249,200✔
5033
}
5034

5035
int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
10,517✔
5036
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
10,517✔
5037
  SHLLInfo*            pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
10,517✔
5038
  int32_t              resultBytes = getHLLInfoSize();
10,517✔
5039
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
10,517!
5040

5041
  if (NULL == res) {
10,516!
5042
    return terrno;
×
5043
  }
5044
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
10,516✔
5045
  varDataSetLen(res, resultBytes);
10,516✔
5046

5047
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
10,516✔
5048
  int32_t          code = TSDB_CODE_SUCCESS;
10,516✔
5049
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
10,516✔
5050
  if (NULL == pCol) {
10,519!
5051
    code = terrno;
×
5052
    goto _exit;
×
5053
  }
5054

5055
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
10,519✔
5056

5057
_exit:
10,519✔
5058
  taosMemoryFree(res);
10,519!
5059
  return code;
10,519✔
5060
}
5061

5062
int32_t hllCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
1✔
5063
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
1✔
5064
  SHLLInfo*            pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
1✔
5065

5066
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
1✔
5067
  SHLLInfo*            pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
1✔
5068

5069
  hllTransferInfo(pSBuf, pDBuf);
1✔
5070
  pDResInfo->numOfRes = TMAX(pDResInfo->numOfRes, pSResInfo->numOfRes);
1✔
5071
  pDResInfo->isNullRes &= pSResInfo->isNullRes;
1✔
5072
  return TSDB_CODE_SUCCESS;
1✔
5073
}
5074

5075
bool getStateFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
22,332✔
5076
  pEnv->calcMemSize = sizeof(SStateInfo);
22,332✔
5077
  return true;
22,332✔
5078
}
5079

5080
static int8_t getStateOpType(char* opStr) {
143,353✔
5081
  int8_t opType;
5082
  if (strncasecmp(opStr, "LT", 2) == 0) {
143,353✔
5083
    opType = STATE_OPER_LT;
30,881✔
5084
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
112,472✔
5085
    opType = STATE_OPER_GT;
80,367✔
5086
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
32,105✔
5087
    opType = STATE_OPER_LE;
984✔
5088
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
31,121✔
5089
    opType = STATE_OPER_GE;
2,873✔
5090
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
28,248✔
5091
    opType = STATE_OPER_NE;
1,839✔
5092
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
26,409!
5093
    opType = STATE_OPER_EQ;
26,409✔
5094
  } else {
5095
    opType = STATE_OPER_INVALID;
×
5096
  }
5097

5098
  return opType;
143,353✔
5099
}
5100

5101
static bool checkStateOp(int8_t op, SColumnInfoData* pCol, int32_t index, SVariant param) {
35,118,159✔
5102
  char* data = colDataGetData(pCol, index);
35,118,159!
5103
  switch (pCol->info.type) {
35,118,159!
5104
    case TSDB_DATA_TYPE_TINYINT: {
7,030,380✔
5105
      int8_t v = *(int8_t*)data;
7,030,380✔
5106
      STATE_COMP(op, v, param);
7,030,380!
5107
      break;
×
5108
    }
5109
    case TSDB_DATA_TYPE_UTINYINT: {
5,760✔
5110
      uint8_t v = *(uint8_t*)data;
5,760✔
5111
      STATE_COMP(op, v, param);
5,760!
5112
      break;
×
5113
    }
5114
    case TSDB_DATA_TYPE_SMALLINT: {
22,530,130✔
5115
      int16_t v = *(int16_t*)data;
22,530,130✔
5116
      STATE_COMP(op, v, param);
22,530,130!
5117
      break;
×
5118
    }
5119
    case TSDB_DATA_TYPE_USMALLINT: {
5,760✔
5120
      uint16_t v = *(uint16_t*)data;
5,760✔
5121
      STATE_COMP(op, v, param);
5,760!
5122
      break;
×
5123
    }
5124
    case TSDB_DATA_TYPE_INT: {
32,570✔
5125
      int32_t v = *(int32_t*)data;
32,570✔
5126
      STATE_COMP(op, v, param);
32,570!
5127
      break;
×
5128
    }
5129
    case TSDB_DATA_TYPE_UINT: {
5,760✔
5130
      uint32_t v = *(uint32_t*)data;
5,760✔
5131
      STATE_COMP(op, v, param);
5,760!
5132
      break;
×
5133
    }
5134
    case TSDB_DATA_TYPE_BIGINT: {
5,316,504✔
5135
      int64_t v = *(int64_t*)data;
5,316,504✔
5136
      STATE_COMP(op, v, param);
5,316,504!
5137
      break;
×
5138
    }
5139
    case TSDB_DATA_TYPE_UBIGINT: {
5,760✔
5140
      uint64_t v = *(uint64_t*)data;
5,760✔
5141
      STATE_COMP(op, v, param);
5,760!
5142
      break;
×
5143
    }
5144
    case TSDB_DATA_TYPE_FLOAT: {
14,524✔
5145
      float v = *(float*)data;
14,524✔
5146
      STATE_COMP(op, v, param);
14,524!
5147
      break;
×
5148
    }
5149
    case TSDB_DATA_TYPE_DOUBLE: {
172,466✔
5150
      double v = *(double*)data;
172,466✔
5151
      STATE_COMP(op, v, param);
172,466!
5152
      break;
×
5153
    }
5154
    default: {
×
5155
      return false;
×
5156
    }
5157
  }
5158
  return false;
×
5159
}
5160

5161
int32_t stateCountFunction(SqlFunctionCtx* pCtx) {
106,659✔
5162
  int32_t              code = TSDB_CODE_SUCCESS;
106,659✔
5163
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
106,659✔
5164
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
106,659✔
5165

5166
  SInputColumnInfoData* pInput = &pCtx->input;
106,659✔
5167
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
106,659✔
5168

5169
  SColumnInfoData* pInputCol = pInput->pData[0];
106,659✔
5170

5171
  int32_t          numOfElems = 0;
106,659✔
5172
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
106,659✔
5173

5174
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
106,659✔
5175
  if (STATE_OPER_INVALID == op) {
106,659!
5176
    return 0;
×
5177
  }
5178

5179
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
28,196,522✔
5180
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
28,089,841!
5181
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5182
    } else {
5183
      pInfo->prevTs = tsList[i];
28,089,841✔
5184
    }
5185

5186
    pInfo->isPrevTsSet = true;
28,089,841✔
5187
    numOfElems++;
28,089,841✔
5188

5189
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
28,089,841✔
5190
      colDataSetNULL(pOutput, i);
107,224!
5191
      // handle selectivity
5192
      if (pCtx->subsidiaries.num > 0) {
107,224✔
5193
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
36✔
5194
        if (TSDB_CODE_SUCCESS != code) {
36!
5195
          return code;
×
5196
        }
5197
      }
5198
      continue;
107,224✔
5199
    }
5200

5201
    bool ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
27,982,617✔
5202

5203
    int64_t output = -1;
27,982,521✔
5204
    if (ret) {
27,982,521✔
5205
      output = ++pInfo->count;
11,273,288✔
5206
    } else {
5207
      pInfo->count = 0;
16,709,233✔
5208
    }
5209
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
27,982,521✔
5210
    if (TSDB_CODE_SUCCESS != code) {
27,982,639!
5211
      return code;
×
5212
    }
5213

5214
    // handle selectivity
5215
    if (pCtx->subsidiaries.num > 0) {
27,982,639✔
5216
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
16,297,560✔
5217
      if (TSDB_CODE_SUCCESS != code) {
16,297,560!
5218
        return code;
×
5219
      }
5220
    }
5221
  }
5222

5223
  pResInfo->numOfRes = numOfElems;
106,681✔
5224
  return TSDB_CODE_SUCCESS;
106,681✔
5225
}
5226

5227
int32_t stateDurationFunction(SqlFunctionCtx* pCtx) {
36,695✔
5228
  int32_t              code = TSDB_CODE_SUCCESS;
36,695✔
5229
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
36,695✔
5230
  SStateInfo*          pInfo = GET_ROWCELL_INTERBUF(pResInfo);
36,695✔
5231

5232
  SInputColumnInfoData* pInput = &pCtx->input;
36,695✔
5233
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
36,695✔
5234

5235
  SColumnInfoData* pInputCol = pInput->pData[0];
36,695✔
5236

5237
  int32_t          numOfElems = 0;
36,695✔
5238
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
36,695✔
5239

5240
  // TODO: process timeUnit for different db precisions
5241
  int32_t timeUnit = 1;
36,695✔
5242
  if (pCtx->numOfParams == 5) {  // TODO: param number incorrect
36,695✔
5243
    timeUnit = pCtx->param[3].param.i;
34,735✔
5244
  }
5245

5246
  int8_t op = getStateOpType(varDataVal(pCtx->param[1].param.pz));
36,695✔
5247
  if (STATE_OPER_INVALID == op) {
36,695!
5248
    return TSDB_CODE_INVALID_PARA;
×
5249
  }
5250

5251
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
7,337,589✔
5252
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
7,300,894!
5253
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5254
    } else {
5255
      pInfo->prevTs = tsList[i];
7,300,894✔
5256
    }
5257

5258
    pInfo->isPrevTsSet = true;
7,300,894✔
5259
    numOfElems++;
7,300,894✔
5260

5261
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
7,300,894✔
5262
      colDataSetNULL(pOutput, i);
164,536!
5263
      // handle selectivity
5264
      if (pCtx->subsidiaries.num > 0) {
164,536✔
5265
        code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
44✔
5266
        if (TSDB_CODE_SUCCESS != code) {
44!
5267
          return code;
×
5268
        }
5269
      }
5270
      continue;
164,536✔
5271
    }
5272

5273
    bool    ret = checkStateOp(op, pInputCol, i, pCtx->param[2].param);
7,136,358✔
5274
    int64_t output = -1;
7,136,358✔
5275
    if (ret) {
7,136,358✔
5276
      if (pInfo->durationStart == 0) {
6,885,795✔
5277
        output = 0;
179,381✔
5278
        pInfo->durationStart = tsList[i];
179,381✔
5279
      } else {
5280
        output = (tsList[i] - pInfo->durationStart) / timeUnit;
6,706,414✔
5281
      }
5282
    } else {
5283
      pInfo->durationStart = 0;
250,563✔
5284
    }
5285
    code = colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false);
7,136,358✔
5286
    if (TSDB_CODE_SUCCESS != code) {
7,136,358!
5287
      return code;
×
5288
    }
5289

5290
    // handle selectivity
5291
    if (pCtx->subsidiaries.num > 0) {
7,136,358✔
5292
      code = appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1);
3,676,076✔
5293
      if (TSDB_CODE_SUCCESS != code) {
3,676,076!
5294
        return code;
×
5295
      }
5296
    }
5297
  }
5298

5299
  pResInfo->numOfRes = numOfElems;
36,695✔
5300
  return TSDB_CODE_SUCCESS;
36,695✔
5301
}
5302

5303
bool getCsumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
15,689✔
5304
  pEnv->calcMemSize = sizeof(SSumRes);
15,689✔
5305
  return true;
15,689✔
5306
}
5307

5308
int32_t csumFunction(SqlFunctionCtx* pCtx) {
18,618✔
5309
  int32_t              code = TSDB_CODE_SUCCESS;
18,618✔
5310
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
18,618✔
5311
  SSumRes*             pSumRes = GET_ROWCELL_INTERBUF(pResInfo);
18,618✔
5312

5313
  SInputColumnInfoData* pInput = &pCtx->input;
18,618✔
5314
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
18,618✔
5315

5316
  SColumnInfoData* pInputCol = pInput->pData[0];
18,618✔
5317
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
18,618✔
5318

5319
  int32_t numOfElems = 0;
18,618✔
5320
  int32_t type = pInputCol->info.type;
18,618✔
5321
  int32_t startOffset = pCtx->offset;
18,618✔
5322
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
4,007,449✔
5323
    if (pSumRes->isPrevTsSet == true && tsList[i] == pSumRes->prevTs) {
3,988,845✔
5324
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
18✔
5325
    } else {
5326
      pSumRes->prevTs = tsList[i];
3,988,827✔
5327
    }
5328
    pSumRes->isPrevTsSet = true;
3,988,827✔
5329

5330
    int32_t pos = startOffset + numOfElems;
3,988,827✔
5331
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
3,988,827✔
5332
      // colDataSetNULL(pOutput, i);
5333
      continue;
508,072✔
5334
    }
5335

5336
    char* data = colDataGetData(pInputCol, i);
3,480,755!
5337
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
4,399,281✔
5338
      int64_t v;
5339
      GET_TYPED_DATA(v, int64_t, type, data);
918,517!
5340
      pSumRes->isum += v;
918,517✔
5341
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false);
918,517✔
5342
      if (TSDB_CODE_SUCCESS != code) {
918,526!
5343
        return code;
×
5344
      }
5345
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
2,562,918!
5346
      uint64_t v;
5347
      GET_TYPED_DATA(v, uint64_t, type, data);
680!
5348
      pSumRes->usum += v;
680✔
5349
      code = colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false);
680✔
5350
      if (TSDB_CODE_SUCCESS != code) {
680!
5351
        return code;
×
5352
      }
5353
    } else if (IS_FLOAT_TYPE(type)) {
2,561,558✔
5354
      double v;
5355
      GET_TYPED_DATA(v, double, type, data);
2,561,542!
5356
      pSumRes->dsum += v;
2,561,542✔
5357
      // check for overflow
5358
      if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) {
2,561,542!
5359
        colDataSetNULL(pOutput, pos);
×
5360
      } else {
5361
        code = colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false);
2,561,555✔
5362
        if (TSDB_CODE_SUCCESS != code) {
2,561,550!
5363
          return code;
×
5364
        }
5365
      }
5366
    }
5367

5368
    // handle selectivity
5369
    if (pCtx->subsidiaries.num > 0) {
3,480,759✔
5370
      code = appendSelectivityValue(pCtx, i, pos);
2,010,072✔
5371
      if (TSDB_CODE_SUCCESS != code) {
2,010,072!
5372
        return code;
×
5373
      }
5374
    }
5375

5376
    numOfElems++;
3,480,759✔
5377
  }
5378

5379
  pResInfo->numOfRes = numOfElems;
18,604✔
5380
  return TSDB_CODE_SUCCESS;
18,604✔
5381
}
5382

5383
bool getMavgFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
13,728✔
5384
  pEnv->calcMemSize = sizeof(SMavgInfo) + MAVG_MAX_POINTS_NUM * sizeof(double);
13,728✔
5385
  return true;
13,728✔
5386
}
5387

5388
int32_t mavgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
67,625✔
5389
  if (pResultInfo->initialized) {
67,625✔
5390
    return TSDB_CODE_SUCCESS;
52,893✔
5391
  }
5392
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
14,732!
5393
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5394
  }
5395

5396
  SMavgInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
14,732✔
5397
  pInfo->pos = 0;
14,732✔
5398
  pInfo->sum = 0;
14,732✔
5399
  pInfo->prevTs = -1;
14,732✔
5400
  pInfo->isPrevTsSet = false;
14,732✔
5401
  pInfo->numOfPoints = pCtx->param[1].param.i;
14,732✔
5402
  if (pInfo->numOfPoints < 1 || pInfo->numOfPoints > MAVG_MAX_POINTS_NUM) {
14,732!
5403
    return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
×
5404
  }
5405
  pInfo->pointsMeet = false;
14,732✔
5406

5407
  return TSDB_CODE_SUCCESS;
14,732✔
5408
}
5409

5410
int32_t mavgFunction(SqlFunctionCtx* pCtx) {
53,896✔
5411
  int32_t              code = TSDB_CODE_SUCCESS;
53,896✔
5412
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
53,896✔
5413
  SMavgInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
53,896✔
5414

5415
  SInputColumnInfoData* pInput = &pCtx->input;
53,896✔
5416
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
53,896✔
5417

5418
  SColumnInfoData* pInputCol = pInput->pData[0];
53,896✔
5419
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
53,896✔
5420
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
53,896✔
5421

5422
  int32_t numOfElems = 0;
53,896✔
5423
  int32_t type = pInputCol->info.type;
53,896✔
5424
  int32_t startOffset = pCtx->offset;
53,896✔
5425
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
58,988,258✔
5426
    if (pInfo->isPrevTsSet == true && tsList[i] == pInfo->prevTs) {
58,934,364!
5427
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
5428
    } else {
5429
      pInfo->prevTs = tsList[i];
58,934,364✔
5430
    }
5431
    pInfo->isPrevTsSet = true;
58,934,364✔
5432

5433
    int32_t pos = startOffset + numOfElems;
58,934,364✔
5434
    if (colDataIsNull_f(pInputCol->nullbitmap, i)) {
58,934,364✔
5435
      // colDataSetNULL(pOutput, i);
5436
      continue;
306,325✔
5437
    }
5438

5439
    char*  data = colDataGetData(pInputCol, i);
58,628,039!
5440
    double v;
5441
    GET_TYPED_DATA(v, double, type, data);
58,628,039!
5442

5443
    if (!pInfo->pointsMeet && (pInfo->pos < pInfo->numOfPoints - 1)) {
58,628,039✔
5444
      pInfo->points[pInfo->pos] = v;
2,653,896✔
5445
      pInfo->sum += v;
2,653,896✔
5446
    } else {
5447
      if (!pInfo->pointsMeet && (pInfo->pos == pInfo->numOfPoints - 1)) {
55,974,143!
5448
        pInfo->sum += v;
11,059✔
5449
        pInfo->pointsMeet = true;
11,059✔
5450
      } else {
5451
        pInfo->sum = pInfo->sum + v - pInfo->points[pInfo->pos];
55,963,084✔
5452
      }
5453

5454
      pInfo->points[pInfo->pos] = v;
55,974,143✔
5455
      double result = pInfo->sum / pInfo->numOfPoints;
55,974,143✔
5456
      // check for overflow
5457
      if (isinf(result) || isnan(result)) {
55,974,143!
5458
        colDataSetNULL(pOutput, pos);
×
5459
      } else {
5460
        code = colDataSetVal(pOutput, pos, (char*)&result, false);
55,974,336✔
5461
        if (TSDB_CODE_SUCCESS != code) {
55,974,334!
5462
          return code;
×
5463
        }
5464
      }
5465

5466
      // handle selectivity
5467
      if (pCtx->subsidiaries.num > 0) {
55,974,141✔
5468
        code = appendSelectivityValue(pCtx, i, pos);
35,471,751✔
5469
        if (TSDB_CODE_SUCCESS != code) {
35,471,751!
5470
          return code;
×
5471
        }
5472
      }
5473

5474
      numOfElems++;
55,974,141✔
5475
    }
5476

5477
    pInfo->pos++;
58,628,037✔
5478
    if (pInfo->pos == pInfo->numOfPoints) {
58,628,037✔
5479
      pInfo->pos = 0;
1,106,148✔
5480
    }
5481
  }
5482

5483
  pResInfo->numOfRes = numOfElems;
53,894✔
5484
  return TSDB_CODE_SUCCESS;
53,894✔
5485
}
5486

5487
static SSampleInfo* getSampleOutputInfo(SqlFunctionCtx* pCtx) {
12,737,288✔
5488
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
12,737,288✔
5489
  SSampleInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
12,737,288✔
5490

5491
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
12,737,288✔
5492
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
12,737,288✔
5493

5494
  return pInfo;
12,737,288✔
5495
}
5496

5497
bool getSampleFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
30,789✔
5498
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
30,789✔
5499
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
30,795✔
5500
  int32_t      numOfSamples = pVal->datum.i;
30,804✔
5501
  pEnv->calcMemSize = sizeof(SSampleInfo) + numOfSamples * (pCol->node.resType.bytes + sizeof(STuplePos));
30,804✔
5502
  return true;
30,804✔
5503
}
5504

5505
int32_t sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
6,381,077✔
5506
  if (pResultInfo->initialized) {
6,381,077!
5507
    return TSDB_CODE_SUCCESS;
×
5508
  }
5509
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
6,381,077!
5510
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5511
  }
5512

5513
  taosSeedRand(taosSafeRand());
6,381,078✔
5514

5515
  SSampleInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
6,381,079✔
5516
  pInfo->samples = pCtx->param[1].param.i;
6,381,079✔
5517
  pInfo->totalPoints = 0;
6,381,079✔
5518
  pInfo->numSampled = 0;
6,381,079✔
5519
  pInfo->colType = pCtx->resDataInfo.type;
6,381,079✔
5520
  pInfo->colBytes = pCtx->resDataInfo.bytes;
6,381,079✔
5521
  pInfo->nullTuplePos.pageId = -1;
6,381,079✔
5522
  pInfo->nullTupleSaved = false;
6,381,079✔
5523
  pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
6,381,079✔
5524
  pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
6,381,079✔
5525

5526
  return TSDB_CODE_SUCCESS;
6,381,079✔
5527
}
5528

5529
static void sampleAssignResult(SSampleInfo* pInfo, char* data, int32_t index) {
14,866,805✔
5530
  assignVal(pInfo->data + index * pInfo->colBytes, data, pInfo->colBytes, pInfo->colType);
14,866,805✔
5531
}
14,866,821✔
5532

5533
static int32_t doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* data, int32_t index) {
16,533,384✔
5534
  pInfo->totalPoints++;
16,533,384✔
5535
  if (pInfo->numSampled < pInfo->samples) {
16,533,384✔
5536
    sampleAssignResult(pInfo, data, pInfo->numSampled);
13,459,211✔
5537
    if (pCtx->subsidiaries.num > 0) {
13,459,228✔
5538
      int32_t code = saveTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[pInfo->numSampled]);
1,177,421✔
5539
      if (code != TSDB_CODE_SUCCESS) {
1,177,238!
5540
        return code;
×
5541
      }
5542
    }
5543
    pInfo->numSampled++;
13,459,045✔
5544
  } else {
5545
    int32_t j = taosRand() % (pInfo->totalPoints);
3,074,173✔
5546
    if (j < pInfo->samples) {
3,076,992✔
5547
      sampleAssignResult(pInfo, data, j);
1,408,042✔
5548
      if (pCtx->subsidiaries.num > 0) {
1,408,025✔
5549
        int32_t code = updateTupleData(pCtx, index, pCtx->pSrcBlock, &pInfo->tuplePos[j]);
852,671✔
5550
        if (code != TSDB_CODE_SUCCESS) {
851,450!
5551
          return code;
×
5552
        }
5553
      }
5554
    }
5555
  }
5556

5557
  return TSDB_CODE_SUCCESS;
16,534,799✔
5558
}
5559

5560
int32_t sampleFunction(SqlFunctionCtx* pCtx) {
6,469,073✔
5561
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,469,073✔
5562
  SSampleInfo*         pInfo = getSampleOutputInfo(pCtx);
6,469,073✔
5563

5564
  SInputColumnInfoData* pInput = &pCtx->input;
6,469,073✔
5565

5566
  SColumnInfoData* pInputCol = pInput->pData[0];
6,469,073✔
5567
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; i += 1) {
23,326,659✔
5568
    if (colDataIsNull_s(pInputCol, i)) {
33,714,362✔
5569
      continue;
322,840✔
5570
    }
5571

5572
    char*   data = colDataGetData(pInputCol, i);
16,534,341!
5573
    int32_t code = doReservoirSample(pCtx, pInfo, data, i);
16,534,341✔
5574
    if (code != TSDB_CODE_SUCCESS) {
16,534,746!
5575
      return code;
×
5576
    }
5577
  }
5578

5579
  if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
6,469,478✔
5580
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
20✔
5581
    if (code != TSDB_CODE_SUCCESS) {
20!
5582
      return code;
×
5583
    }
5584
    pInfo->nullTupleSaved = true;
20✔
5585
  }
5586

5587
  SET_VAL(pResInfo, pInfo->numSampled, pInfo->numSampled);
6,469,478✔
5588
  return TSDB_CODE_SUCCESS;
6,469,478✔
5589
}
5590

5591
int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
6,268,215✔
5592
  int32_t              code = TSDB_CODE_SUCCESS;
6,268,215✔
5593
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
6,268,215✔
5594

5595
  SSampleInfo* pInfo = getSampleOutputInfo(pCtx);
6,268,215✔
5596
  pEntryInfo->complete = true;
6,268,215✔
5597

5598
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
6,268,215✔
5599
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
6,268,215✔
5600
  if (NULL == pCol) {
6,268,215!
5601
    return TSDB_CODE_OUT_OF_RANGE;
×
5602
  }
5603

5604
  int32_t currentRow = pBlock->info.rows;
6,268,215✔
5605
  if (pInfo->numSampled == 0) {
6,268,215✔
5606
    colDataSetNULL(pCol, currentRow);
1,945✔
5607
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
1,945✔
5608
    return code;
1,944✔
5609
  }
5610
  for (int32_t i = 0; i < pInfo->numSampled; ++i) {
19,500,256✔
5611
    code = colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false);
13,234,116✔
5612
    if (TSDB_CODE_SUCCESS != code) {
13,234,098!
5613
      return code;
×
5614
    }
5615
    code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i);
13,234,098✔
5616
    if (TSDB_CODE_SUCCESS != code) {
13,233,986!
5617
      return code;
×
5618
    }
5619
  }
5620

5621
  return code;
6,266,140✔
5622
}
5623

5624
bool getTailFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5625
#if 0
5626
  SColumnNode* pCol = (SColumnNode*)nodesListGetNode(pFunc->pParameterList, 0);
5627
  SValueNode*  pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
5628
  int32_t      numOfPoints = pVal->datum.i;
5629
  pEnv->calcMemSize = sizeof(STailInfo) + numOfPoints * (POINTER_BYTES + sizeof(STailItem) + pCol->node.resType.bytes);
5630
#endif
5631
  return true;
×
5632
}
5633

5634
int32_t tailFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
×
5635
#if 0
5636
  if (!functionSetup(pCtx, pResultInfo)) {
5637
    return false;
5638
  }
5639

5640
  STailInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo);
5641
  pInfo->numAdded = 0;
5642
  pInfo->numOfPoints = pCtx->param[1].param.i;
5643
  if (pCtx->numOfParams == 4) {
5644
    pInfo->offset = pCtx->param[2].param.i;
5645
  } else {
5646
    pInfo->offset = 0;
5647
  }
5648
  pInfo->colType = pCtx->resDataInfo.type;
5649
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5650
  if ((pInfo->numOfPoints < 1 || pInfo->numOfPoints > TAIL_MAX_POINTS_NUM) ||
5651
      (pInfo->numOfPoints < 0 || pInfo->numOfPoints > TAIL_MAX_OFFSET)) {
5652
    return false;
5653
  }
5654

5655
  pInfo->pItems = (STailItem**)((char*)pInfo + sizeof(STailInfo));
5656
  char* pItem = (char*)pInfo->pItems + pInfo->numOfPoints * POINTER_BYTES;
5657

5658
  size_t unitSize = sizeof(STailItem) + pInfo->colBytes;
5659
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5660
    pInfo->pItems[i] = (STailItem*)(pItem + i * unitSize);
5661
    pInfo->pItems[i]->isNull = false;
5662
  }
5663
#endif
5664

5665
  return TSDB_CODE_SUCCESS;
×
5666
}
5667

5668
static void tailAssignResult(STailItem* pItem, char* data, int32_t colBytes, TSKEY ts, bool isNull) {
×
5669
#if 0
5670
  pItem->timestamp = ts;
5671
  if (isNull) {
5672
    pItem->isNull = true;
5673
  } else {
5674
    pItem->isNull = false;
5675
    memcpy(pItem->data, data, colBytes);
5676
  }
5677
#endif
5678
}
×
5679

5680
#if 0
5681
static int32_t tailCompFn(const void* p1, const void* p2, const void* param) {
5682
  STailItem* d1 = *(STailItem**)p1;
5683
  STailItem* d2 = *(STailItem**)p2;
5684
  return compareInt64Val(&d1->timestamp, &d2->timestamp);
5685
}
5686

5687
static void doTailAdd(STailInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5688
  STailItem** pList = pInfo->pItems;
5689
  if (pInfo->numAdded < pInfo->numOfPoints) {
5690
    tailAssignResult(pList[pInfo->numAdded], data, pInfo->colBytes, ts, isNull);
5691
    taosheapsort((void*)pList, sizeof(STailItem**), pInfo->numAdded + 1, NULL, tailCompFn, 0);
5692
    pInfo->numAdded++;
5693
  } else if (pList[0]->timestamp < ts) {
5694
    tailAssignResult(pList[0], data, pInfo->colBytes, ts, isNull);
5695
    taosheapadjust((void*)pList, sizeof(STailItem**), 0, pInfo->numOfPoints - 1, NULL, tailCompFn, NULL, 0);
5696
  }
5697
}
5698
#endif
5699

5700
int32_t tailFunction(SqlFunctionCtx* pCtx) {
×
5701
#if 0
5702
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5703
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5704

5705
  SInputColumnInfoData* pInput = &pCtx->input;
5706
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5707

5708
  SColumnInfoData* pInputCol = pInput->pData[0];
5709
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5710

5711
  int32_t startOffset = pCtx->offset;
5712
  if (pInfo->offset >= pInput->numOfRows) {
5713
    return 0;
5714
  } else {
5715
    pInfo->numOfPoints = TMIN(pInfo->numOfPoints, pInput->numOfRows - pInfo->offset);
5716
  }
5717
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex - pInfo->offset; i += 1) {
5718
    char* data = colDataGetData(pInputCol, i);
5719
    doTailAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5720
  }
5721

5722
  taosqsort(pInfo->pItems, pInfo->numOfPoints, POINTER_BYTES, NULL, tailCompFn);
5723

5724
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5725
    int32_t    pos = startOffset + i;
5726
    STailItem* pItem = pInfo->pItems[i];
5727
    if (pItem->isNull) {
5728
      colDataSetNULL(pOutput, pos);
5729
    } else {
5730
      colDataSetVal(pOutput, pos, pItem->data, false);
5731
    }
5732
  }
5733

5734
  return pInfo->numOfPoints;
5735
#endif
5736
  return 0;
×
5737
}
5738

5739
int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
×
5740
#if 0
5741
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
5742
  STailInfo*           pInfo = GET_ROWCELL_INTERBUF(pEntryInfo);
5743
  pEntryInfo->complete = true;
5744

5745
  int32_t type = pCtx->input.pData[0]->info.type;
5746
  int32_t slotId = pCtx->pExpr->base.resSchema.slotId;
5747

5748
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
5749

5750
  // todo assign the tag value and the corresponding row data
5751
  int32_t currentRow = pBlock->info.rows;
5752
  for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) {
5753
    STailItem* pItem = pInfo->pItems[i];
5754
    colDataSetVal(pCol, currentRow, pItem->data, false);
5755
    currentRow += 1;
5756
  }
5757

5758
  return pEntryInfo->numOfRes;
5759
#endif
5760
  return 0;
×
5761
}
5762

5763
bool getUniqueFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
×
5764
#if 0
5765
  pEnv->calcMemSize = sizeof(SUniqueInfo) + UNIQUE_MAX_RESULT_SIZE;
5766
#endif
5767
  return true;
×
5768
}
5769

5770
int32_t uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
×
5771
#if 0
5772
  if (!functionSetup(pCtx, pResInfo)) {
5773
    return false;
5774
  }
5775

5776
  SUniqueInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5777
  pInfo->numOfPoints = 0;
5778
  pInfo->colType = pCtx->resDataInfo.type;
5779
  pInfo->colBytes = pCtx->resDataInfo.bytes;
5780
  if (pInfo->pHash != NULL) {
5781
    taosHashClear(pInfo->pHash);
5782
  } else {
5783
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
5784
  }
5785
#endif
5786
  return TSDB_CODE_SUCCESS;
×
5787
}
5788

5789
#if 0
5790
static void doUniqueAdd(SUniqueInfo* pInfo, char* data, TSKEY ts, bool isNull) {
5791
  // handle null elements
5792
  if (isNull == true) {
5793
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5794
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5795
    if (pInfo->hasNull == false && pItem->isNull == false) {
5796
      pItem->timestamp = ts;
5797
      pItem->isNull = true;
5798
      pInfo->numOfPoints++;
5799
      pInfo->hasNull = true;
5800
    } else if (pItem->timestamp > ts && pItem->isNull == true) {
5801
      pItem->timestamp = ts;
5802
    }
5803
    return;
5804
  }
5805

5806
  int32_t      hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes;
5807
  SUniqueItem* pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes);
5808
  if (pHashItem == NULL) {
5809
    int32_t      size = sizeof(SUniqueItem) + pInfo->colBytes;
5810
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + pInfo->numOfPoints * size);
5811
    pItem->timestamp = ts;
5812
    memcpy(pItem->data, data, pInfo->colBytes);
5813

5814
    taosHashPut(pInfo->pHash, data, hashKeyBytes, (char*)pItem, sizeof(SUniqueItem*));
5815
    pInfo->numOfPoints++;
5816
  } else if (pHashItem->timestamp > ts) {
5817
    pHashItem->timestamp = ts;
5818
  }
5819
}
5820
#endif
5821

5822
int32_t uniqueFunction(SqlFunctionCtx* pCtx) {
×
5823
#if 0
5824
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
5825
  SUniqueInfo*         pInfo = GET_ROWCELL_INTERBUF(pResInfo);
5826

5827
  SInputColumnInfoData* pInput = &pCtx->input;
5828
  TSKEY*                tsList = (int64_t*)pInput->pPTS->pData;
5829

5830
  SColumnInfoData* pInputCol = pInput->pData[0];
5831
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
5832
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
5833

5834
  int32_t startOffset = pCtx->offset;
5835
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
5836
    char* data = colDataGetData(pInputCol, i);
5837
    doUniqueAdd(pInfo, data, tsList[i], colDataIsNull_s(pInputCol, i));
5838

5839
    if (sizeof(SUniqueInfo) + pInfo->numOfPoints * (sizeof(SUniqueItem) + pInfo->colBytes) >= UNIQUE_MAX_RESULT_SIZE) {
5840
      taosHashCleanup(pInfo->pHash);
5841
      return 0;
5842
    }
5843
  }
5844

5845
  for (int32_t i = 0; i < pInfo->numOfPoints; ++i) {
5846
    SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes));
5847
    if (pItem->isNull == true) {
5848
      colDataSetNULL(pOutput, i);
5849
    } else {
5850
      colDataSetVal(pOutput, i, pItem->data, false);
5851
    }
5852
    if (pTsOutput != NULL) {
5853
      colDataSetInt64(pTsOutput, i, &pItem->timestamp);
5854
    }
5855
  }
5856

5857
  return pInfo->numOfPoints;
5858
#endif
5859
  return 0;
×
5860
}
5861

5862
bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
24,902✔
5863
  pEnv->calcMemSize = sizeof(SModeInfo);
24,902✔
5864
  return true;
24,902✔
5865
}
5866

5867
int32_t modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
25,725✔
5868
  if (pResInfo->initialized) {
25,725!
5869
    return TSDB_CODE_SUCCESS;
×
5870
  }
5871
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
25,725!
5872
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
5873
  }
5874

5875
  SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
25,724✔
5876
  pInfo->colType = pCtx->resDataInfo.type;
25,724✔
5877
  pInfo->colBytes = pCtx->resDataInfo.bytes;
25,724✔
5878
  if (pInfo->pHash != NULL) {
25,724!
5879
    taosHashClear(pInfo->pHash);
×
5880
  } else {
5881
    pInfo->pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
25,724✔
5882
    if (NULL == pInfo->pHash) {
25,725!
5883
      return terrno;
×
5884
    }
5885
  }
5886
  pInfo->nullTupleSaved = false;
25,725✔
5887
  pInfo->nullTuplePos.pageId = -1;
25,725✔
5888

5889
  pInfo->buf = taosMemoryMalloc(pInfo->colBytes);
25,725!
5890
  if (NULL == pInfo->buf) {
25,725!
5891
    taosHashCleanup(pInfo->pHash);
×
5892
    pInfo->pHash = NULL;
×
5893
    return terrno;
×
5894
  }
5895
  pCtx->needCleanup = true;
25,725✔
5896
  return TSDB_CODE_SUCCESS;
25,725✔
5897
}
5898

5899
static void modeFunctionCleanup(SModeInfo* pInfo) {
25,725✔
5900
  taosHashCleanup(pInfo->pHash);
25,725✔
5901
  pInfo->pHash = NULL;
25,725✔
5902
  taosMemoryFreeClear(pInfo->buf);
25,725!
5903
}
25,725✔
5904

5905
void modeFunctionCleanupExt(SqlFunctionCtx* pCtx) {
×
5906
  if (pCtx == NULL || GET_RES_INFO(pCtx) == NULL || GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)) == NULL) {
×
5907
    return;
×
5908
  }
5909
  modeFunctionCleanup(GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)));
×
5910
}
5911

5912
static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo* pInfo, STuplePos* pPos) {
101,034,055✔
5913
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
101,034,055!
5914
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
38,831,256!
5915
      (void)memcpy(pInfo->buf, data, getJsonValueLen(data));
×
5916
    } else {
5917
      (void)memcpy(pInfo->buf, data, varDataTLen(data));
38,831,256✔
5918
    }
5919
  } else {
5920
    (void)memcpy(pInfo->buf, data, pInfo->colBytes);
62,202,799✔
5921
  }
5922

5923
  return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos, pCtx->pStore);
101,034,055✔
5924
}
5925

5926
static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) {
123,462,569✔
5927
  int32_t code = TSDB_CODE_SUCCESS;
123,462,569✔
5928
  int32_t hashKeyBytes;
5929
  if (IS_VAR_DATA_TYPE(pInfo->colType)) {
123,462,569!
5930
    if (pInfo->colType == TSDB_DATA_TYPE_JSON) {
38,831,418!
5931
      hashKeyBytes = getJsonValueLen(data);
×
5932
    } else {
5933
      hashKeyBytes = varDataTLen(data);
38,831,418✔
5934
    }
5935
  } else {
5936
    hashKeyBytes = pInfo->colBytes;
84,631,151✔
5937
  }
5938

5939
  SModeItem* pHashItem = (SModeItem*)taosHashGet(pInfo->pHash, data, hashKeyBytes);
123,462,478✔
5940
  if (pHashItem == NULL) {
123,461,379✔
5941
    int32_t   size = sizeof(SModeItem);
101,034,090✔
5942
    SModeItem item = {0};
101,034,090✔
5943

5944
    item.count += 1;
101,034,090✔
5945
    code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos);
101,034,090✔
5946
    if (code != TSDB_CODE_SUCCESS) {
101,032,374!
5947
      return code;
×
5948
    }
5949

5950
    if (pCtx->subsidiaries.num > 0) {
101,032,374✔
5951
      code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos);
54,385,940✔
5952
      if (code != TSDB_CODE_SUCCESS) {
54,385,940!
5953
        return code;
×
5954
      }
5955
    }
5956

5957
    code = taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem));
101,032,374✔
5958
    if (code != TSDB_CODE_SUCCESS) {
101,035,707!
5959
      return code;
×
5960
    }
5961
  } else {
5962
    pHashItem->count += 1;
22,427,289✔
5963
    if (pCtx->subsidiaries.num > 0) {
22,427,289✔
5964
      code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos);
18,191,490✔
5965
      if (code != TSDB_CODE_SUCCESS) {
18,191,490!
5966
        return code;
×
5967
      }
5968
    }
5969
  }
5970

5971
  return code;
123,462,996✔
5972
}
5973

5974
int32_t modeFunction(SqlFunctionCtx* pCtx) {
2,499,404✔
5975
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,499,404✔
5976
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
2,499,404✔
5977

5978
  SInputColumnInfoData* pInput = &pCtx->input;
2,499,404✔
5979

5980
  SColumnInfoData* pInputCol = pInput->pData[0];
2,499,404✔
5981
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
2,499,404✔
5982

5983
  int32_t numOfElems = 0;
2,499,404✔
5984
  int32_t startOffset = pCtx->offset;
2,499,404✔
5985
  for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
126,431,210✔
5986
    if (colDataIsNull_s(pInputCol, i)) {
247,863,196✔
5987
      continue;
469,173✔
5988
    }
5989
    numOfElems++;
123,462,425✔
5990

5991
    char*   data = colDataGetData(pInputCol, i);
123,462,425!
5992
    int32_t code = doModeAdd(pInfo, i, pCtx, data);
123,462,425✔
5993
    if (code != TSDB_CODE_SUCCESS) {
123,462,981✔
5994
      modeFunctionCleanup(pInfo);
348✔
5995
      return code;
×
5996
    }
5997
  }
5998

5999
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) {
2,499,612!
6000
    int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos);
50✔
6001
    if (code != TSDB_CODE_SUCCESS) {
50!
6002
      modeFunctionCleanup(pInfo);
×
6003
      return code;
×
6004
    }
6005
    pInfo->nullTupleSaved = true;
50✔
6006
  }
6007

6008
  SET_VAL(pResInfo, numOfElems, 1);
2,499,612✔
6009

6010
  return TSDB_CODE_SUCCESS;
2,499,612✔
6011
}
6012

6013
int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
25,724✔
6014
  int32_t              code = TSDB_CODE_SUCCESS;
25,724✔
6015
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
25,724✔
6016
  SModeInfo*           pInfo = GET_ROWCELL_INTERBUF(pResInfo);
25,724✔
6017
  int32_t              slotId = pCtx->pExpr->base.resSchema.slotId;
25,724✔
6018
  SColumnInfoData*     pCol = taosArrayGet(pBlock->pDataBlock, slotId);
25,724✔
6019
  int32_t              currentRow = pBlock->info.rows;
25,725✔
6020
  if (NULL == pCol) {
25,725!
6021
    modeFunctionCleanup(pInfo);
×
6022
    return TSDB_CODE_OUT_OF_RANGE;
×
6023
  }
6024

6025
  STuplePos resDataPos, resTuplePos;
6026
  int32_t   maxCount = 0;
25,725✔
6027

6028
  void* pIter = taosHashIterate(pInfo->pHash, NULL);
25,725✔
6029
  while (pIter != NULL) {
101,061,712✔
6030
    SModeItem* pItem = (SModeItem*)pIter;
101,035,987✔
6031
    if (pItem->count >= maxCount) {
101,035,987✔
6032
      maxCount = pItem->count;
97,637,584✔
6033
      resDataPos = pItem->dataPos;
97,637,584✔
6034
      resTuplePos = pItem->tuplePos;
97,637,584✔
6035
    }
6036

6037
    pIter = taosHashIterate(pInfo->pHash, pIter);
101,035,987✔
6038
  }
6039

6040
  if (maxCount != 0) {
25,725✔
6041
    char* pData = NULL;
22,997✔
6042
    code = loadTupleData(pCtx, &resDataPos, &pData);
22,997✔
6043
    if (pData == NULL || TSDB_CODE_SUCCESS != code) {
22,997!
6044
      code = terrno = TSDB_CODE_NOT_FOUND;
×
6045
      qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
×
6046
             resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
6047
      modeFunctionCleanup(pInfo);
×
6048
      return code;
×
6049
    }
6050

6051
    code = colDataSetVal(pCol, currentRow, pData, false);
22,997✔
6052
    if (TSDB_CODE_SUCCESS != code) {
22,997!
6053
      modeFunctionCleanup(pInfo);
×
6054
      return code;
×
6055
    }
6056
    code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow);
22,997✔
6057
  } else {
6058
    colDataSetNULL(pCol, currentRow);
2,728✔
6059
    code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow);
2,728✔
6060
  }
6061

6062
  modeFunctionCleanup(pInfo);
25,725✔
6063

6064
  return code;
25,725✔
6065
}
6066

6067
bool getTwaFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
77,303✔
6068
  pEnv->calcMemSize = sizeof(STwaInfo);
77,303✔
6069
  return true;
77,303✔
6070
}
6071

6072
int32_t twaFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
8,101,661✔
6073
  if (pResultInfo->initialized) {
8,101,661!
6074
    return TSDB_CODE_SUCCESS;
×
6075
  }
6076
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
8,101,661!
6077
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6078
  }
6079

6080
  STwaInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,101,703✔
6081
  pInfo->numOfElems = 0;
8,101,703✔
6082
  pInfo->p.key = INT64_MIN;
8,101,703✔
6083
  pInfo->win = TSWINDOW_INITIALIZER;
8,101,703✔
6084
  return TSDB_CODE_SUCCESS;
8,101,703✔
6085
}
6086

6087
static double twa_get_area(SPoint1 s, SPoint1 e) {
18,618,927✔
6088
  if (e.key == INT64_MAX || s.key == INT64_MIN) {
18,618,927!
6089
    return 0;
×
6090
  }
6091

6092
  if ((s.val >= 0 && e.val >= 0) || (s.val <= 0 && e.val <= 0)) {
18,619,074✔
6093
    return (s.val + e.val) * (e.key - s.key) / 2;
13,785,051✔
6094
  }
6095

6096
  double x = (s.key * e.val - e.key * s.val) / (e.val - s.val);
4,834,023✔
6097
  double val = (s.val * (x - s.key) + e.val * (e.key - x)) / 2;
4,834,023✔
6098
  return val;
4,834,023✔
6099
}
6100

6101
int32_t twaFunction(SqlFunctionCtx* pCtx) {
8,102,151✔
6102
  int32_t               code = TSDB_CODE_SUCCESS;
8,102,151✔
6103
  SInputColumnInfoData* pInput = &pCtx->input;
8,102,151✔
6104
  SColumnInfoData*      pInputCol = pInput->pData[0];
8,102,151✔
6105

6106
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,102,151✔
6107
  STwaInfo*            pInfo = GET_ROWCELL_INTERBUF(pResInfo);
8,102,151✔
6108
  SPoint1*             last = &pInfo->p;
8,102,151✔
6109

6110
  if (IS_NULL_TYPE(pInputCol->info.type)) {
8,102,151!
6111
    pInfo->numOfElems = 0;
×
6112
    goto _twa_over;
×
6113
  }
6114

6115
  funcInputUpdate(pCtx);
8,102,151✔
6116
  SFuncInputRow row = {0};
8,102,217✔
6117
  bool          result = false;
8,102,217✔
6118
  if (pCtx->start.key != INT64_MIN && last->key == INT64_MIN) {
8,102,217!
6119
    while (1) {
6120
      code = funcInputGetNextRow(pCtx, &row, &result);
4,404,320✔
6121
      if (TSDB_CODE_SUCCESS != code) {
4,404,314!
6122
        return code;
×
6123
      }
6124
      if (!result) {
4,404,314✔
6125
        break;
2✔
6126
      }
6127
      if (row.isDataNull) {
4,404,312✔
6128
        continue;
2✔
6129
      }
6130

6131
      last->key = row.ts;
4,404,310✔
6132

6133
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
4,404,310!
6134

6135
      pInfo->dOutput += twa_get_area(pCtx->start, *last);
4,404,310✔
6136
      pInfo->win.skey = pCtx->start.key;
4,404,313✔
6137
      pInfo->numOfElems++;
4,404,313✔
6138
      break;
4,404,313✔
6139
    }
6140
  } else if (pInfo->p.key == INT64_MIN) {
3,697,899✔
6141
    while (1) {
6142
      code = funcInputGetNextRow(pCtx, &row, &result);
3,822,705✔
6143
      if (TSDB_CODE_SUCCESS != code) {
3,822,560!
6144
        return code;
×
6145
      }
6146
      if (!result) {
3,822,560✔
6147
        break;
15,433✔
6148
      }
6149
      if (row.isDataNull) {
3,807,127✔
6150
        continue;
125,008✔
6151
      }
6152

6153
      last->key = row.ts;
3,682,119✔
6154

6155
      GET_TYPED_DATA(last->val, double, pInputCol->info.type, row.pData);
3,682,119!
6156

6157
      pInfo->win.skey = last->key;
3,682,119✔
6158
      pInfo->numOfElems++;
3,682,119✔
6159
      break;
3,682,119✔
6160
    }
6161
  }
6162

6163
  SPoint1 st = {0};
8,102,069✔
6164

6165
  // calculate the value of
6166
  while (1) {
6167
    code = funcInputGetNextRow(pCtx, &row, &result);
17,670,059✔
6168
    if (TSDB_CODE_SUCCESS != code) {
17,669,440!
6169
      return code;
×
6170
    }
6171
    if (!result) {
17,669,440✔
6172
      break;
8,102,141✔
6173
    }
6174
    if (row.isDataNull) {
9,567,299✔
6175
      continue;
630✔
6176
    }
6177
    pInfo->numOfElems++;
9,566,669✔
6178
    switch (pInputCol->info.type) {
9,566,669!
6179
      case TSDB_DATA_TYPE_TINYINT: {
356,459✔
6180
        INIT_INTP_POINT(st, row.ts, *(int8_t*)row.pData);
356,459✔
6181
        break;
356,459✔
6182
      }
6183
      case TSDB_DATA_TYPE_SMALLINT: {
81,618✔
6184
        INIT_INTP_POINT(st, row.ts, *(int16_t*)row.pData);
81,618✔
6185
        break;
81,618✔
6186
      }
6187
      case TSDB_DATA_TYPE_INT: {
119,487✔
6188
        INIT_INTP_POINT(st, row.ts, *(int32_t*)row.pData);
119,487✔
6189
        break;
119,487✔
6190
      }
6191
      case TSDB_DATA_TYPE_BIGINT: {
8,304,993✔
6192
        INIT_INTP_POINT(st, row.ts, *(int64_t*)row.pData);
8,304,993✔
6193
        break;
8,304,993✔
6194
      }
6195
      case TSDB_DATA_TYPE_FLOAT: {
73,264✔
6196
        INIT_INTP_POINT(st, row.ts, *(float_t*)row.pData);
73,264✔
6197
        break;
73,264✔
6198
      }
6199
      case TSDB_DATA_TYPE_DOUBLE: {
363,134✔
6200
        INIT_INTP_POINT(st, row.ts, *(double*)row.pData);
363,134✔
6201
        break;
363,134✔
6202
      }
6203
      case TSDB_DATA_TYPE_UTINYINT: {
69,169✔
6204
        INIT_INTP_POINT(st, row.ts, *(uint8_t*)row.pData);
69,169✔
6205
        break;
69,169✔
6206
      }
6207
      case TSDB_DATA_TYPE_USMALLINT: {
69,079✔
6208
        INIT_INTP_POINT(st, row.ts, *(uint16_t*)row.pData);
69,079✔
6209
        break;
69,079✔
6210
      }
6211
      case TSDB_DATA_TYPE_UINT: {
71,128✔
6212
        INIT_INTP_POINT(st, row.ts, *(uint32_t*)row.pData);
71,128✔
6213
        break;
71,128✔
6214
      }
6215
      case TSDB_DATA_TYPE_UBIGINT: {
58,984✔
6216
        INIT_INTP_POINT(st, row.ts, *(uint64_t*)row.pData);
58,984✔
6217
        break;
58,984✔
6218
      }
6219
      default: {
×
6220
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
6221
      }
6222
    }
6223
    if (pInfo->p.key == st.key) {
9,567,315!
6224
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6225
    }
6226

6227
    pInfo->dOutput += twa_get_area(pInfo->p, st);
9,567,315✔
6228
    pInfo->p = st;
9,567,360✔
6229
  }
6230

6231
  // the last interpolated time window value
6232
  if (pCtx->end.key != INT64_MIN) {
8,102,141✔
6233
    pInfo->dOutput += twa_get_area(pInfo->p, pCtx->end);
4,647,986✔
6234
    pInfo->p = pCtx->end;
4,647,989✔
6235
    pInfo->numOfElems += 1;
4,647,989✔
6236
  }
6237

6238
  pInfo->win.ekey = pInfo->p.key;
8,102,144✔
6239

6240
_twa_over:
8,102,144✔
6241
  SET_VAL(pResInfo, 1, 1);
8,102,144✔
6242
  return TSDB_CODE_SUCCESS;
8,102,144✔
6243
}
6244

6245
/*
6246
 * To copy the input to interResBuf to avoid the input buffer space be over writen
6247
 * by next input data. The TWA function only applies to each table, so no merge procedure
6248
 * is required, we simply copy to the resut ot interResBuffer.
6249
 */
6250
// void twa_function_copy(SQLFunctionCtx *pCtx) {
6251
//   SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
6252
//
6253
//   memcpy(GET_ROWCELL_INTERBUF(pResInfo), pCtx->pInput, (size_t)pCtx->inputBytes);
6254
//   pResInfo->hasResult = ((STwaInfo *)pCtx->pInput)->hasResult;
6255
// }
6256

6257
int32_t twaFinalize(struct SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
8,088,945✔
6258
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
8,088,945✔
6259

6260
  STwaInfo* pInfo = (STwaInfo*)GET_ROWCELL_INTERBUF(pResInfo);
8,088,945✔
6261
  if (pInfo->numOfElems == 0) {
8,088,945✔
6262
    pResInfo->numOfRes = 0;
15,281✔
6263
  } else {
6264
    if (pInfo->win.ekey == pInfo->win.skey) {
8,073,664✔
6265
      pInfo->dTwaRes = pInfo->p.val;
3,047,323✔
6266
    } else if (pInfo->win.ekey == INT64_MAX || pInfo->win.skey == INT64_MIN) {  // no data in timewindow
5,026,341!
6267
      pInfo->dTwaRes = 0;
×
6268
    } else {
6269
      pInfo->dTwaRes = pInfo->dOutput / (pInfo->win.ekey - pInfo->win.skey);
5,026,436✔
6270
    }
6271

6272
    pResInfo->numOfRes = 1;
8,073,664✔
6273
  }
6274

6275
  return functionFinalize(pCtx, pBlock);
8,088,945✔
6276
}
6277

6278
int32_t blockDistSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1,628✔
6279
  if (pResultInfo->initialized) {
1,628!
6280
    return TSDB_CODE_SUCCESS;
×
6281
  }
6282
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1,628!
6283
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6284
  }
6285

6286
  STableBlockDistInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,628✔
6287
  pInfo->minRows = INT32_MAX;
1,628✔
6288
  return TSDB_CODE_SUCCESS;
1,628✔
6289
}
6290

6291
int32_t blockDistFunction(SqlFunctionCtx* pCtx) {
3,253✔
6292
  const int32_t BLOCK_DIST_RESULT_ROWS = 25;
3,253✔
6293

6294
  SInputColumnInfoData* pInput = &pCtx->input;
3,253✔
6295
  SColumnInfoData*      pInputCol = pInput->pData[0];
3,253✔
6296
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
3,253✔
6297
  STableBlockDistInfo*  pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
3,253✔
6298

6299
  STableBlockDistInfo p1 = {0};
3,253✔
6300
  if (tDeserializeBlockDistInfo(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
3,253!
6301
    qError("failed to deserialize block dist info");
×
6302
    return TSDB_CODE_FAILED;
×
6303
  }
6304

6305
  pDistInfo->numOfBlocks += p1.numOfBlocks;
3,253✔
6306
  pDistInfo->numOfTables += p1.numOfTables;
3,253✔
6307
  pDistInfo->numOfInmemRows += p1.numOfInmemRows;
3,253✔
6308
  pDistInfo->numOfSttRows += p1.numOfSttRows;
3,253✔
6309
  pDistInfo->totalSize += p1.totalSize;
3,253✔
6310
  pDistInfo->totalRows += p1.totalRows;
3,253✔
6311
  pDistInfo->numOfFiles += p1.numOfFiles;
3,253✔
6312

6313
  pDistInfo->defMinRows = p1.defMinRows;
3,253✔
6314
  pDistInfo->defMaxRows = p1.defMaxRows;
3,253✔
6315
  pDistInfo->rowSize = p1.rowSize;
3,253✔
6316

6317
  if (pDistInfo->minRows > p1.minRows) {
3,253✔
6318
    pDistInfo->minRows = p1.minRows;
2✔
6319
  }
6320
  if (pDistInfo->maxRows < p1.maxRows) {
3,253✔
6321
    pDistInfo->maxRows = p1.maxRows;
2✔
6322
  }
6323
  pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0);
3,253✔
6324
  for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) {
68,313✔
6325
    pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i];
65,060✔
6326
  }
6327

6328
  pResInfo->numOfRes = BLOCK_DIST_RESULT_ROWS;  // default output rows
3,253✔
6329
  return TSDB_CODE_SUCCESS;
3,253✔
6330
}
6331

6332
int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDistInfo* pInfo) {
6,499✔
6333
  SEncoder encoder = {0};
6,499✔
6334
  int32_t  code = 0;
6,499✔
6335
  int32_t  lino;
6336
  int32_t  tlen;
6337
  tEncoderInit(&encoder, buf, bufLen);
6,499✔
6338

6339
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
6,502!
6340
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->rowSize));
12,994!
6341

6342
  TAOS_CHECK_EXIT(tEncodeU16(&encoder, pInfo->numOfFiles));
12,994!
6343
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfBlocks));
12,994!
6344
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfTables));
12,994!
6345

6346
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalSize));
12,994!
6347
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->totalRows));
12,994!
6348
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->maxRows));
12,994!
6349
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->minRows));
12,994!
6350
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMaxRows));
12,994!
6351
  TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->defMinRows));
12,994!
6352
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfInmemRows));
12,994!
6353
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfSttRows));
12,994!
6354
  TAOS_CHECK_EXIT(tEncodeU32(&encoder, pInfo->numOfVgroups));
12,994!
6355

6356
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
136,259✔
6357
    TAOS_CHECK_EXIT(tEncodeI32(&encoder, pInfo->blockRowsHisto[i]));
259,524!
6358
  }
6359

6360
  tEndEncode(&encoder);
6,497✔
6361

6362
_exit:
6,500✔
6363
  if (code) {
6,500!
6364
    tlen = code;
×
6365
  } else {
6366
    tlen = encoder.pos;
6,500✔
6367
  }
6368
  tEncoderClear(&encoder);
6,500✔
6369
  return tlen;
6,500✔
6370
}
6371

6372
int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo* pInfo) {
3,253✔
6373
  SDecoder decoder = {0};
3,253✔
6374
  int32_t  code = 0;
3,253✔
6375
  int32_t  lino;
6376
  tDecoderInit(&decoder, buf, bufLen);
3,253✔
6377

6378
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
3,253!
6379
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->rowSize));
6,506!
6380

6381
  TAOS_CHECK_EXIT(tDecodeU16(&decoder, &pInfo->numOfFiles));
6,506!
6382
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfBlocks));
6,506!
6383
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfTables));
6,506!
6384

6385
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalSize));
6,506!
6386
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->totalRows));
6,506!
6387
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->maxRows));
6,506!
6388
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->minRows));
6,506!
6389
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMaxRows));
6,506!
6390
  TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->defMinRows));
6,506!
6391
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfInmemRows));
6,506!
6392
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfSttRows));
6,506!
6393
  TAOS_CHECK_EXIT(tDecodeU32(&decoder, &pInfo->numOfVgroups));
6,506!
6394

6395
  for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) {
68,313✔
6396
    TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]));
130,120!
6397
  }
6398

6399
_exit:
3,253✔
6400
  tDecoderClear(&decoder);
3,253✔
6401
  return code;
3,253✔
6402
}
6403

6404
int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,628✔
6405
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,628✔
6406
  STableBlockDistInfo* pData = GET_ROWCELL_INTERBUF(pResInfo);
1,628✔
6407

6408
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1,628✔
6409
  if (NULL == pColInfo) {
1,628!
6410
    return TSDB_CODE_OUT_OF_RANGE;
×
6411
  }
6412

6413
  if (pData->totalRows == 0) {
1,628✔
6414
    pData->minRows = 0;
1,626✔
6415
  }
6416

6417
  int32_t row = 0;
1,628✔
6418
  char    st[256] = {0};
1,628✔
6419
  double  averageSize = 0;
1,628✔
6420
  if (pData->numOfBlocks != 0) {
1,628✔
6421
    averageSize = ((double)pData->totalSize) / pData->numOfBlocks;
2✔
6422
  }
6423
  uint64_t totalRawSize = pData->totalRows * pData->rowSize;
1,628✔
6424
  double   compRatio = 0;
1,628✔
6425
  if (totalRawSize != 0) {
1,628✔
6426
    compRatio = pData->totalSize * 100 / (double)totalRawSize;
2✔
6427
  }
6428

6429
  int32_t len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6430
                          "Total_Blocks=[%d] Total_Size=[%.2f KiB] Average_size=[%.2f KiB] Compression_Ratio=[%.2f %c]",
6431
                          pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%');
1,628✔
6432

6433
  varDataSetLen(st, len);
1,628✔
6434
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6435
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6436
    return code;
×
6437
  }
6438

6439
  int64_t avgRows = 0;
1,628✔
6440
  if (pData->numOfBlocks > 0) {
1,628✔
6441
    avgRows = pData->totalRows / pData->numOfBlocks;
2✔
6442
  }
6443

6444
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6445
                  "Block_Rows=[%" PRId64 "] MinRows=[%d] MaxRows=[%d] AvgRows=[%" PRId64 "]", pData->totalRows,
6446
                  pData->minRows, pData->maxRows, avgRows);
6447
  varDataSetLen(st, len);
1,628✔
6448
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6449
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6450
    return code;
×
6451
  }
6452

6453
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Inmem_Rows=[%u] Stt_Rows=[%u] ",
1,628✔
6454
                  pData->numOfInmemRows, pData->numOfSttRows);
6455
  varDataSetLen(st, len);
1,628✔
6456
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6457
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6458
    return code;
×
6459
  }
6460

6461
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
3,256✔
6462
                  "Total_Tables=[%d] Total_Filesets=[%d] Total_Vgroups=[%d]", pData->numOfTables, pData->numOfFiles,
1,628✔
6463
                  pData->numOfVgroups);
6464

6465
  varDataSetLen(st, len);
1,628✔
6466
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6467
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6468
    return code;
×
6469
  }
6470

6471
  len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE,
1,628✔
6472
                  "--------------------------------------------------------------------------------");
6473
  varDataSetLen(st, len);
1,628✔
6474
  code = colDataSetVal(pColInfo, row++, st, false);
1,628✔
6475
  if (TSDB_CODE_SUCCESS != code) {
1,628!
6476
    return code;
×
6477
  }
6478

6479
  int32_t maxVal = 0;
1,628✔
6480
  int32_t minVal = INT32_MAX;
1,628✔
6481
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6482
    if (maxVal < pData->blockRowsHisto[i]) {
32,560✔
6483
      maxVal = pData->blockRowsHisto[i];
3✔
6484
    }
6485

6486
    if (minVal > pData->blockRowsHisto[i]) {
32,560✔
6487
      minVal = pData->blockRowsHisto[i];
1,629✔
6488
    }
6489
  }
6490

6491
  // maximum number of step is 80
6492
  double factor = pData->numOfBlocks / 80.0;
1,628✔
6493

6494
  int32_t numOfBuckets = sizeof(pData->blockRowsHisto) / sizeof(pData->blockRowsHisto[0]);
1,628✔
6495
  int32_t bucketRange = ceil(((double)(pData->defMaxRows - pData->defMinRows)) / numOfBuckets);
1,628✔
6496

6497
  for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) {
34,188✔
6498
    len =
32,560✔
6499
        tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1));
32,560✔
6500

6501
    int32_t num = 0;
32,560✔
6502
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6503
      num = (pData->blockRowsHisto[i]) / factor;
3✔
6504
    }
6505

6506
    for (int32_t j = 0; j < num; ++j) {
32,719✔
6507
      int32_t x = tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "%c", '|');
159✔
6508
      len += x;
159✔
6509
    }
6510

6511
    if (pData->blockRowsHisto[i] > 0) {
32,560✔
6512
      double v = pData->blockRowsHisto[i] * 100.0 / pData->numOfBlocks;
3✔
6513
      len += tsnprintf(varDataVal(st) + len, sizeof(st) - VARSTR_HEADER_SIZE - len, "  %d (%.2f%c)",
3✔
6514
                       pData->blockRowsHisto[i], v, '%');
6515
    }
6516

6517
    varDataSetLen(st, len);
32,560✔
6518
    code = colDataSetVal(pColInfo, row++, st, false);
32,560✔
6519
    if (TSDB_CODE_SUCCESS != code) {
32,560!
6520
      return code;
×
6521
    }
6522
  }
6523

6524
  return TSDB_CODE_SUCCESS;
1,628✔
6525
}
6526
int32_t blockDBUsageSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
1✔
6527
  if (pResultInfo->initialized) {
1!
6528
    return TSDB_CODE_SUCCESS;
×
6529
  }
6530
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
1!
6531
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6532
  }
6533

6534
  SDBBlockUsageInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1✔
6535
  return TSDB_CODE_SUCCESS;
1✔
6536
}
6537
int32_t blockDBUsageFunction(SqlFunctionCtx* pCtx) {
2✔
6538
  const int32_t BLOCK_DISK_USAGE_RESULT_ROWS = 2;
2✔
6539

6540
  SInputColumnInfoData* pInput = &pCtx->input;
2✔
6541
  SColumnInfoData*      pInputCol = pInput->pData[0];
2✔
6542
  SResultRowEntryInfo*  pResInfo = GET_RES_INFO(pCtx);
2✔
6543
  SDBBlockUsageInfo*    pDistInfo = GET_ROWCELL_INTERBUF(pResInfo);
2✔
6544

6545
  SDBBlockUsageInfo p1 = {0};
2✔
6546
  if (tDeserializeBlockDbUsage(varDataVal(pInputCol->pData), varDataLen(pInputCol->pData), &p1) < 0) {
2!
6547
    qError("failed to deserialize block dist info");
×
6548
    return TSDB_CODE_FAILED;
×
6549
  }
6550

6551
  pDistInfo->dataInDiskSize += p1.dataInDiskSize;
2✔
6552
  pDistInfo->walInDiskSize += p1.walInDiskSize;
2✔
6553
  pDistInfo->rawDataSize += p1.rawDataSize;
2✔
6554
  pResInfo->numOfRes = BLOCK_DISK_USAGE_RESULT_ROWS;  // default output rows
2✔
6555
  return TSDB_CODE_SUCCESS;
2✔
6556
}
6557

6558
int32_t tSerializeBlockDbUsage(void* buf, int32_t bufLen, const SDBBlockUsageInfo* pInfo) {
4✔
6559
  SEncoder encoder = {0};
4✔
6560
  int32_t  code = 0;
4✔
6561
  int32_t  lino;
6562
  int32_t  tlen;
6563
  tEncoderInit(&encoder, buf, bufLen);
4✔
6564

6565
  TAOS_CHECK_EXIT(tStartEncode(&encoder));
4!
6566

6567
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->dataInDiskSize));
8!
6568
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->walInDiskSize));
8!
6569
  TAOS_CHECK_EXIT(tEncodeU64(&encoder, pInfo->rawDataSize));
8!
6570

6571
  tEndEncode(&encoder);
4✔
6572

6573
_exit:
4✔
6574
  if (code) {
4!
6575
    tlen = code;
×
6576
  } else {
6577
    tlen = encoder.pos;
4✔
6578
  }
6579
  tEncoderClear(&encoder);
4✔
6580
  return tlen;
4✔
6581
}
6582
int32_t tDeserializeBlockDbUsage(void* buf, int32_t bufLen, SDBBlockUsageInfo* pInfo) {
2✔
6583
  SDecoder decoder = {0};
2✔
6584
  int32_t  code = 0;
2✔
6585
  int32_t  lino;
6586
  tDecoderInit(&decoder, buf, bufLen);
2✔
6587

6588
  TAOS_CHECK_EXIT(tStartDecode(&decoder));
2!
6589
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->dataInDiskSize));
4!
6590
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->walInDiskSize));
4!
6591
  TAOS_CHECK_EXIT(tDecodeU64(&decoder, &pInfo->rawDataSize));
4!
6592

6593
_exit:
2✔
6594
  tDecoderClear(&decoder);
2✔
6595
  return code;
2✔
6596
}
6597
int32_t blockDBUsageFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1✔
6598
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1✔
6599
  SDBBlockUsageInfo*   pData = GET_ROWCELL_INTERBUF(pResInfo);
1✔
6600

6601
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, 0);
1✔
6602
  if (NULL == pColInfo) {
1!
6603
    return TSDB_CODE_OUT_OF_RANGE;
×
6604
  }
6605
  int32_t len = 0;
1✔
6606
  int32_t row = 0;
1✔
6607
  char    st[256] = {0};
1✔
6608

6609
  uint64_t totalDiskSize = pData->dataInDiskSize;
1✔
6610
  uint64_t rawDataSize = pData->rawDataSize;
1✔
6611
  double   compressRadio = 0;
1✔
6612
  if (rawDataSize != 0) {
1!
6613
    compressRadio = totalDiskSize * 100 / (double)rawDataSize;
1✔
6614
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[%.2f]", compressRadio);
1✔
6615
  } else {
6616
    len = tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Compress_radio=[NULL]");
×
6617
  }
6618

6619
  varDataSetLen(st, len);
1✔
6620
  int32_t code = colDataSetVal(pColInfo, row++, st, false);
1✔
6621
  if (TSDB_CODE_SUCCESS != code) {
1!
6622
    return code;
×
6623
  }
6624

6625
  len =
1✔
6626
      tsnprintf(varDataVal(st), sizeof(st) - VARSTR_HEADER_SIZE, "Disk_occupied=[%" PRId64 "k]", pData->dataInDiskSize);
1✔
6627
  varDataSetLen(st, len);
1✔
6628
  code = colDataSetVal(pColInfo, row++, st, false);
1✔
6629
  if (TSDB_CODE_SUCCESS != code) {
1!
6630
    return code;
×
6631
  }
6632
  return code;
1✔
6633
}
6634

6635
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
31,323✔
6636
  pEnv->calcMemSize = sizeof(SDerivInfo);
31,323✔
6637
  return true;
31,323✔
6638
}
6639

6640
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
63,438✔
6641
  if (pResInfo->initialized) {
63,438✔
6642
    return TSDB_CODE_SUCCESS;
31,971✔
6643
  }
6644
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
31,467!
6645
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6646
  }
6647

6648
  SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
31,467✔
6649

6650
  pDerivInfo->ignoreNegative = pCtx->param[2].param.i;
31,467✔
6651
  pDerivInfo->prevTs = -1;
31,467✔
6652
  pDerivInfo->tsWindow = pCtx->param[1].param.i;
31,467✔
6653
  pDerivInfo->valueSet = false;
31,467✔
6654
  return TSDB_CODE_SUCCESS;
31,467✔
6655
}
6656

6657
int32_t derivativeFunction(SqlFunctionCtx* pCtx) {
32,115✔
6658
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
32,115✔
6659
  SDerivInfo*          pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo);
32,115✔
6660

6661
  SInputColumnInfoData* pInput = &pCtx->input;
32,115✔
6662
  SColumnInfoData*      pInputCol = pInput->pData[0];
32,115✔
6663

6664
  int32_t          numOfElems = 0;
32,115✔
6665
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
32,115✔
6666
  SColumnInfoData* pTsOutput = pCtx->pTsOutput;
32,115✔
6667
  int32_t          code = TSDB_CODE_SUCCESS;
32,115✔
6668

6669
  funcInputUpdate(pCtx);
32,115✔
6670

6671
  double v = 0;
32,115✔
6672
  if (pCtx->order == TSDB_ORDER_ASC) {
32,115✔
6673
    SFuncInputRow row = {0};
28,760✔
6674
    bool          result = false;
28,760✔
6675
    while (1) {
3,552,311✔
6676
      code = funcInputGetNextRow(pCtx, &row, &result);
3,581,071✔
6677
      if (TSDB_CODE_SUCCESS != code) {
3,581,071!
6678
        return code;
×
6679
      }
6680
      if (!result) {
3,581,071✔
6681
        break;
28,760✔
6682
      }
6683
      if (row.isDataNull) {
3,552,311✔
6684
        continue;
35,646✔
6685
      }
6686

6687
      char* d = row.pData;
3,516,665✔
6688
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
3,516,665!
6689

6690
      int32_t pos = pCtx->offset + numOfElems;
3,516,665✔
6691
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
3,516,665✔
6692
        pDerivInfo->valueSet = true;
27,765✔
6693
      } else {
6694
        if (row.ts == pDerivInfo->prevTs) {
3,488,900!
6695
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6696
        }
6697
        double r = ((v - pDerivInfo->prevValue) * pDerivInfo->tsWindow) / (row.ts - pDerivInfo->prevTs);
3,488,900✔
6698
        if (pDerivInfo->ignoreNegative && r < 0) {
3,488,900✔
6699
        } else {
6700
          if (isinf(r) || isnan(r)) {
2,271,608!
6701
            colDataSetNULL(pOutput, pos);
×
6702
          } else {
6703
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
2,271,608✔
6704
            if (code != TSDB_CODE_SUCCESS) {
2,271,608!
6705
              return code;
×
6706
            }
6707
          }
6708

6709
          if (pTsOutput != NULL) {
2,271,608!
6710
            colDataSetInt64(pTsOutput, pos, &row.ts);
×
6711
          }
6712

6713
          // handle selectivity
6714
          if (pCtx->subsidiaries.num > 0) {
2,271,608✔
6715
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
1,771,869✔
6716
            if (code != TSDB_CODE_SUCCESS) {
1,771,869!
6717
              return code;
×
6718
            }
6719
          }
6720

6721
          numOfElems++;
2,271,608✔
6722
        }
6723
      }
6724

6725
      pDerivInfo->prevValue = v;
3,516,665✔
6726
      pDerivInfo->prevTs = row.ts;
3,516,665✔
6727
    }
6728
  } else {
6729
    SFuncInputRow row = {0};
3,355✔
6730
    bool          result = false;
3,355✔
6731
    while (1) {
332,962✔
6732
      code = funcInputGetNextRow(pCtx, &row, &result);
336,317✔
6733
      if (TSDB_CODE_SUCCESS != code) {
336,317!
6734
        return code;
×
6735
      }
6736
      if (!result) {
336,317✔
6737
        break;
3,355✔
6738
      }
6739
      if (row.isDataNull) {
332,962✔
6740
        continue;
22✔
6741
      }
6742

6743
      char* d = row.pData;
332,940✔
6744
      GET_TYPED_DATA(v, double, pInputCol->info.type, d);
332,940!
6745

6746
      int32_t pos = pCtx->offset + numOfElems;
332,940✔
6747
      if (!pDerivInfo->valueSet) {  // initial value is not set yet
332,940✔
6748
        pDerivInfo->valueSet = true;
3,344✔
6749
      } else {
6750
        if (row.ts == pDerivInfo->prevTs) {
329,596!
6751
          return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6752
        }
6753
        double r = ((pDerivInfo->prevValue - v) * pDerivInfo->tsWindow) / (pDerivInfo->prevTs - row.ts);
329,596✔
6754
        if (pDerivInfo->ignoreNegative && r < 0) {
329,596✔
6755
        } else {
6756
          if (isinf(r) || isnan(r)) {
261,026!
6757
            colDataSetNULL(pOutput, pos);
×
6758
          } else {
6759
            code = colDataSetVal(pOutput, pos, (const char*)&r, false);
261,026✔
6760
            if (code != TSDB_CODE_SUCCESS) {
261,026!
6761
              return code;
×
6762
            }
6763
          }
6764

6765
          if (pTsOutput != NULL) {
261,026!
6766
            colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs);
×
6767
          }
6768

6769
          // handle selectivity
6770
          if (pCtx->subsidiaries.num > 0) {
261,026✔
6771
            code = appendSelectivityCols(pCtx, row.block, row.rowIndex, pos);
79,428✔
6772
            if (code != TSDB_CODE_SUCCESS) {
79,428!
6773
              return code;
×
6774
            }
6775
          }
6776
          numOfElems++;
261,026✔
6777
        }
6778
      }
6779

6780
      pDerivInfo->prevValue = v;
332,940✔
6781
      pDerivInfo->prevTs = row.ts;
332,940✔
6782
    }
6783
  }
6784

6785
  pResInfo->numOfRes = numOfElems;
32,115✔
6786

6787
  return TSDB_CODE_SUCCESS;
32,115✔
6788
}
6789

6790
int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; }
2,006,836✔
6791

6792
bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
122,100✔
6793
  int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0;
122,100✔
6794
  pEnv->calcMemSize = getIrateInfoSize(pkBytes);
122,100✔
6795
  return true;
122,287✔
6796
}
6797

6798
int32_t irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
9,075,275✔
6799
  if (pResInfo->initialized) {
9,075,275!
6800
    return TSDB_CODE_SUCCESS;
×
6801
  }
6802
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
9,075,275!
6803
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
6804
  }
6805

6806
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
9,075,311✔
6807

6808
  pInfo->firstKey = INT64_MIN;
9,075,311✔
6809
  pInfo->lastKey = INT64_MIN;
9,075,311✔
6810
  pInfo->firstValue = (double)INT64_MIN;
9,075,311✔
6811
  pInfo->lastValue = (double)INT64_MIN;
9,075,311✔
6812

6813
  pInfo->hasResult = 0;
9,075,311✔
6814
  return TSDB_CODE_SUCCESS;
9,075,311✔
6815
}
6816

6817
static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) {
27,759,850✔
6818
  if (isFirst) {
27,759,850✔
6819
    pRateInfo->firstValue = v;
10,291,453✔
6820
    pRateInfo->firstKey = ts;
10,291,453✔
6821
    if (pRateInfo->firstPk) {
10,291,453✔
6822
      int32_t pkBytes;
6823
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
35!
6824
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
8!
6825
          pkBytes = getJsonValueLen(pk);
×
6826
        } else {
6827
          pkBytes = varDataTLen(pk);
8✔
6828
        }
6829
      } else {
6830
        pkBytes = pRateInfo->pkBytes;
27✔
6831
      }
6832
      (void)memcpy(pRateInfo->firstPk, pk, pkBytes);
35✔
6833
    }
6834
  } else {
6835
    pRateInfo->lastValue = v;
17,468,397✔
6836
    pRateInfo->lastKey = ts;
17,468,397✔
6837
    if (pRateInfo->lastPk) {
17,468,397✔
6838
      int32_t pkBytes;
6839
      if (IS_VAR_DATA_TYPE(pRateInfo->pkType)) {
52!
6840
        if (pRateInfo->pkType == TSDB_DATA_TYPE_JSON) {
12!
6841
          pkBytes = getJsonValueLen(pk);
×
6842
        } else {
6843
          pkBytes = varDataTLen(pk);
12✔
6844
        }
6845
      } else {
6846
        pkBytes = pRateInfo->pkBytes;
40✔
6847
      }
6848
      (void)memcpy(pRateInfo->lastPk, pk, pkBytes);
52✔
6849
    }
6850
  }
6851
}
27,759,850✔
6852

6853
static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) {
10,960,739✔
6854
  if (pCtx->hasPrimaryKey) {
10,960,739✔
6855
    if (!isMerge) {
19✔
6856
      pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type;
17✔
6857
      pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes;
17✔
6858
      pRateInfo->firstPk = pRateInfo->pkData;
17✔
6859
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
17✔
6860
    } else {
6861
      pRateInfo->firstPk = pRateInfo->pkData;
2✔
6862
      pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes;
2✔
6863
    }
6864
  } else {
6865
    pRateInfo->firstPk = NULL;
10,960,720✔
6866
    pRateInfo->lastPk = NULL;
10,960,720✔
6867
  }
6868
}
10,960,739✔
6869

6870
int32_t irateFunction(SqlFunctionCtx* pCtx) {
7,192,589✔
6871
  int32_t              code = TSDB_CODE_SUCCESS;
7,192,589✔
6872
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,192,589✔
6873
  SRateInfo*           pRateInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,192,589✔
6874

6875
  SInputColumnInfoData* pInput = &pCtx->input;
7,192,589✔
6876
  SColumnInfoData*      pInputCol = pInput->pData[0];
7,192,589✔
6877

6878
  SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput;
7,192,589✔
6879

6880
  funcInputUpdate(pCtx);
7,192,589✔
6881

6882
  initializeRateInfo(pCtx, pRateInfo, false);
7,192,623✔
6883

6884
  int32_t       numOfElems = 0;
7,192,620✔
6885
  int32_t       type = pInputCol->info.type;
7,192,620✔
6886
  SFuncInputRow row = {0};
7,192,620✔
6887
  bool          result = false;
7,192,620✔
6888
  while (1) {
15,858,191✔
6889
    code = funcInputGetNextRow(pCtx, &row, &result);
23,050,811✔
6890
    if (TSDB_CODE_SUCCESS != code) {
23,050,147!
6891
      return code;
×
6892
    }
6893
    if (!result) {
23,050,147✔
6894
      break;
7,192,572✔
6895
    }
6896
    if (row.isDataNull) {
15,857,575✔
6897
      continue;
130,965✔
6898
    }
6899

6900
    char*  data = row.pData;
15,726,610✔
6901
    double v = 0;
15,726,610✔
6902
    GET_TYPED_DATA(v, double, type, data);
15,726,610!
6903

6904
    if (INT64_MIN == pRateInfo->lastKey) {
15,726,610✔
6905
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
7,177,850✔
6906
      pRateInfo->hasResult = 1;
7,177,846✔
6907
      continue;
7,177,846✔
6908
    }
6909

6910
    if (row.ts > pRateInfo->lastKey) {
8,548,760✔
6911
      if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) {
8,406,831!
6912
        doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue);
8,406,832✔
6913
      }
6914
      doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v);
8,406,830✔
6915
      continue;
8,406,829✔
6916
    } else if (row.ts == pRateInfo->lastKey) {
141,929!
6917
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6918
    }
6919

6920
    if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) {
141,929!
6921
      doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v);
×
6922
    } else if (row.ts == pRateInfo->firstKey) {
142,259!
6923
      return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6924
    }
6925
  }
6926

6927
  numOfElems++;
7,192,572✔
6928

6929
  SET_VAL(pResInfo, numOfElems, 1);
7,192,572!
6930
  return TSDB_CODE_SUCCESS;
7,192,572✔
6931
}
6932

6933
static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) {
7,187,149✔
6934
  if ((INT64_MIN == pRateInfo->lastKey) || (INT64_MIN == pRateInfo->firstKey) ||
7,187,149✔
6935
      (pRateInfo->firstKey >= pRateInfo->lastKey)) {
627,594!
6936
    return 0.0;
6,559,555✔
6937
  }
6938

6939
  double diff = 0;
627,594✔
6940
  // If the previous value of the last is greater than the last value, only keep the last point instead of the delta
6941
  // value between two values.
6942
  diff = pRateInfo->lastValue;
627,594✔
6943
  if (diff >= pRateInfo->firstValue) {
627,594✔
6944
    diff -= pRateInfo->firstValue;
290,081✔
6945
  }
6946

6947
  int64_t duration = pRateInfo->lastKey - pRateInfo->firstKey;
627,594✔
6948
  if (duration == 0) {
627,594!
6949
    return 0;
×
6950
  }
6951

6952
  return (duration > 0) ? ((double)diff) / (duration / tickPerSec) : 0.0;
627,594!
6953
}
6954

6955
static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) {
214✔
6956
  if (inputKey > pOutput->lastKey) {
214✔
6957
    doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue);
158✔
6958
    if (isFirstKey) {
158✔
6959
      doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue);
72✔
6960
    } else {
6961
      doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
86✔
6962
    }
6963
  } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) {
56!
6964
    if (isFirstKey) {
8✔
6965
      doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
4✔
6966
    } else {
6967
      doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue);
4✔
6968
    }
6969
  } else {
6970
    // inputKey < pOutput->firstKey
6971
  }
6972
}
214✔
6973

6974
static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,883,971✔
6975
  doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue);
1,883,971✔
6976
  doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue);
1,883,971✔
6977
}
1,883,971✔
6978

6979
static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) {
1,884,078✔
6980
  if ((pInput->firstKey != INT64_MIN &&
1,884,078✔
6981
       (pInput->firstKey == pOutput->firstKey || pInput->firstKey == pOutput->lastKey)) ||
138,569!
6982
      (pInput->lastKey != INT64_MIN && (pInput->lastKey == pOutput->firstKey || pInput->lastKey == pOutput->lastKey))) {
1,884,078!
6983
    return TSDB_CODE_FUNC_DUP_TIMESTAMP;
×
6984
  }
6985

6986
  if (pOutput->hasResult == 0) {
1,884,078✔
6987
    irateCopyInfo(pInput, pOutput);
1,883,971✔
6988
    pOutput->hasResult = pInput->hasResult;
1,883,971✔
6989
    return TSDB_CODE_SUCCESS;
1,883,971✔
6990
  }
6991

6992
  if (pInput->firstKey != INT64_MIN) {
107!
6993
    irateTransferInfoImpl(pInput->firstKey, pInput, pOutput, true);
107✔
6994
  }
6995

6996
  if (pInput->lastKey != INT64_MIN) {
107!
6997
    irateTransferInfoImpl(pInput->lastKey, pInput, pOutput, false);
107✔
6998
  }
6999

7000
  pOutput->hasResult = pInput->hasResult;
107✔
7001
  return TSDB_CODE_SUCCESS;
107✔
7002
}
7003

7004
int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) {
1,884,090✔
7005
  SInputColumnInfoData* pInput = &pCtx->input;
1,884,090✔
7006
  SColumnInfoData*      pCol = pInput->pData[0];
1,884,090✔
7007
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
1,884,090!
7008
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
7009
  }
7010

7011
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,884,090✔
7012
  initializeRateInfo(pCtx, pInfo, true);
1,884,090✔
7013

7014
  int32_t start = pInput->startRowIndex;
1,884,090✔
7015
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
3,768,180✔
7016
    char*      data = colDataGetData(pCol, i);
1,884,090!
7017
    SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data);
1,884,090✔
7018
    initializeRateInfo(pCtx, pInfo, true);
1,884,090✔
7019
    if (pInputInfo->hasResult) {
1,884,090✔
7020
      int32_t code = irateTransferInfo(pInputInfo, pInfo);
1,884,078✔
7021
      if (code != TSDB_CODE_SUCCESS) {
1,884,078!
7022
        return code;
×
7023
      }
7024
    }
7025
  }
7026

7027
  if (pInfo->hasResult) {
1,884,090✔
7028
    GET_RES_INFO(pCtx)->numOfRes = 1;
1,884,078✔
7029
  }
7030

7031
  return TSDB_CODE_SUCCESS;
1,884,090✔
7032
}
7033

7034
int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
1,884,453✔
7035
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,884,453✔
7036
  SRateInfo*           pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
1,884,453✔
7037
  int32_t              resultBytes = getIrateInfoSize(pInfo->pkBytes);
1,884,453✔
7038
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
1,884,453!
7039

7040
  if (NULL == res) {
1,884,454!
7041
    return terrno;
×
7042
  }
7043
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
1,884,454✔
7044
  varDataSetLen(res, resultBytes);
1,884,454✔
7045

7046
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,884,454✔
7047
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,884,454✔
7048
  if (NULL == pCol) {
1,884,454!
7049
    taosMemoryFree(res);
×
7050
    return TSDB_CODE_OUT_OF_RANGE;
×
7051
  }
7052

7053
  int32_t code = colDataSetVal(pCol, pBlock->info.rows, res, false);
1,884,454✔
7054

7055
  taosMemoryFree(res);
1,884,454!
7056
  return code;
1,884,453✔
7057
}
7058

7059
int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
7,187,154✔
7060
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
7,187,154✔
7061
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
7,187,154✔
7062
  if (NULL == pCol) {
7,187,148!
7063
    return TSDB_CODE_OUT_OF_RANGE;
×
7064
  }
7065

7066
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
7,187,148✔
7067
  pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
7,187,148✔
7068

7069
  SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
7,187,148✔
7070
  double     result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i));
7,187,148!
7071
  int32_t    code = colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes);
7,187,145✔
7072

7073
  return code;
7,187,098✔
7074
}
7075

7076
int32_t groupConstValueFunction(SqlFunctionCtx* pCtx) {
105,851,370✔
7077
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
105,851,370✔
7078
  SGroupKeyInfo*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
105,851,370✔
7079

7080
  SInputColumnInfoData* pInput = &pCtx->input;
105,851,370✔
7081
  SColumnInfoData*      pInputCol = pInput->pData[0];
105,851,370✔
7082

7083
  int32_t startIndex = pInput->startRowIndex;
105,851,370✔
7084

7085
  // escape rest of data blocks to avoid first entry to be overwritten.
7086
  if (pInfo->hasResult) {
105,851,370✔
7087
    goto _group_value_over;
11,374,525✔
7088
  }
7089

7090
  if (pInputCol->pData == NULL || colDataIsNull_s(pInputCol, startIndex)) {
188,478,917✔
7091
    pInfo->isNull = true;
2,696,588✔
7092
    pInfo->hasResult = true;
2,696,588✔
7093
    goto _group_value_over;
2,696,588✔
7094
  }
7095

7096
  char* data = colDataGetData(pInputCol, startIndex);
91,780,257!
7097
  if (IS_VAR_DATA_TYPE(pInputCol->info.type)) {
91,780,257!
7098
    (void)memcpy(pInfo->data, data,
72,426,588✔
7099
                 (pInputCol->info.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(data) : varDataTLen(data));
72,426,588✔
7100
  } else {
7101
    (void)memcpy(pInfo->data, data, pInputCol->info.bytes);
19,353,669✔
7102
  }
7103
  pInfo->hasResult = true;
91,780,257✔
7104

7105
_group_value_over:
105,851,370✔
7106

7107
  SET_VAL(pResInfo, 1, 1);
105,851,370✔
7108
  return TSDB_CODE_SUCCESS;
105,851,370✔
7109
}
7110

7111
int32_t groupKeyFunction(SqlFunctionCtx* pCtx) { return groupConstValueFunction(pCtx); }
105,078,583✔
7112

7113
int32_t groupConstValueFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
93,024,783✔
7114
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
93,024,783✔
7115
  int32_t          code = TSDB_CODE_SUCCESS;
93,024,783✔
7116
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
93,024,783✔
7117
  if (NULL == pCol) {
93,019,491!
7118
    return TSDB_CODE_OUT_OF_RANGE;
×
7119
  }
7120

7121
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
93,019,491✔
7122

7123
  SGroupKeyInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo);
93,019,491✔
7124

7125
  if (pInfo->hasResult) {
93,019,491!
7126
    int32_t currentRow = pBlock->info.rows;
93,046,862✔
7127
    for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) {
186,345,672✔
7128
      code = colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false);
93,084,823✔
7129
      if (TSDB_CODE_SUCCESS != code) {
93,298,810!
7130
        return code;
×
7131
      }
7132
    }
7133
  } else {
7134
    pResInfo->numOfRes = 0;
×
7135
  }
7136

7137
  return code;
93,233,478✔
7138
}
7139

7140
int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return groupConstValueFinalize(pCtx, pBlock); }
92,730,172✔
7141

7142
int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
×
7143
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
×
7144
  SGroupKeyInfo*       pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
×
7145

7146
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
×
7147
  SGroupKeyInfo*       pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
×
7148

7149
  // escape rest of data blocks to avoid first entry to be overwritten.
7150
  if (pDBuf->hasResult) {
×
7151
    goto _group_key_over;
×
7152
  }
7153

7154
  if (pSBuf->isNull) {
×
7155
    pDBuf->isNull = true;
×
7156
    pDBuf->hasResult = true;
×
7157
    goto _group_key_over;
×
7158
  }
7159

7160
  if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) {
×
7161
    (void)memcpy(pDBuf->data, pSBuf->data,
×
7162
                 (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data)
×
7163
                                                                       : varDataTLen(pSBuf->data));
×
7164
  } else {
7165
    (void)memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes);
×
7166
  }
7167

7168
  pDBuf->hasResult = true;
×
7169

7170
_group_key_over:
×
7171

7172
  SET_VAL(pDResInfo, 1, 1);
×
7173
  return TSDB_CODE_SUCCESS;
×
7174
}
7175

7176
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) {
6,755✔
7177
  int32_t numOfElems = 0;
6,755✔
7178

7179
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
6,755✔
7180
  SFirstLastRes*       pInfo = GET_ROWCELL_INTERBUF(pResInfo);
6,755✔
7181

7182
  SInputColumnInfoData* pInput = &pCtx->input;
6,755✔
7183
  SColumnInfoData*      pInputCol = pInput->pData[0];
6,755✔
7184

7185
  int32_t bytes = pInputCol->info.bytes;
6,755✔
7186
  pInfo->bytes = bytes;
6,755✔
7187

7188
  SColumnInfoData* pkCol = pInput->pPrimaryKey;
6,755✔
7189
  pInfo->pkType = -1;
6,755✔
7190
  __compar_fn_t pkCompareFn = NULL;
6,755✔
7191
  if (pCtx->hasPrimaryKey) {
6,755✔
7192
    pInfo->pkType = pkCol->info.type;
3,538✔
7193
    pInfo->pkBytes = pkCol->info.bytes;
3,538✔
7194
    pkCompareFn = getKeyComparFunc(pInfo->pkType, TSDB_ORDER_DESC);
3,538✔
7195
  }
7196

7197
  // TODO it traverse the different way.
7198
  // last_row function does not ignore the null value
7199
  for (int32_t i = pInput->numOfRows + pInput->startRowIndex - 1; i >= pInput->startRowIndex; --i) {
13,522✔
7200
    numOfElems++;
6,766✔
7201

7202
    bool  isNull = colDataIsNull(pInputCol, pInput->numOfRows, i, NULL);
6,766✔
7203
    char* data = isNull ? NULL : colDataGetData(pInputCol, i);
6,766!
7204

7205
    TSKEY cts = getRowPTs(pInput->pPTS, i);
6,766!
7206
    if (pResInfo->numOfRes == 0 || pInfo->ts < cts) {
6,766✔
7207
      int32_t code = doSaveLastrow(pCtx, data, i, cts, pInfo);
4,289✔
7208
      if (code != TSDB_CODE_SUCCESS) {
4,289!
7209
        return code;
×
7210
      }
7211
      pResInfo->numOfRes = 1;
4,289✔
7212
    }
7213
  }
7214

7215
  SET_VAL(pResInfo, numOfElems, 1);
6,756!
7216
  return TSDB_CODE_SUCCESS;
6,756✔
7217
}
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