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

taosdata / TDengine / #4103

17 May 2025 02:18AM UTC coverage: 63.264% (+0.4%) from 62.905%
#4103

push

travis-ci

web-flow
Merge pull request #31110 from taosdata/3.0

merge 3.0

158149 of 318142 branches covered (49.71%)

Branch coverage included in aggregate %.

3 of 5 new or added lines in 1 file covered. (60.0%)

1725 existing lines in 138 files now uncovered.

243642 of 316962 relevant lines covered (76.87%)

16346281.8 hits per line

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

82.13
/source/libs/function/src/detail/tavgfunction.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 "function.h"
18
#include "tdatablock.h"
19
#include "tfunctionInt.h"
20
#include "tglobal.h"
21

22
#define SET_VAL(_info, numOfElem, res) \
23
  do {                                 \
24
    if ((numOfElem) <= 0) {            \
25
      break;                           \
26
    }                                  \
27
    (_info)->numOfRes = (res);         \
28
  } while (0)
29

30
#define LIST_AVG_N(sumT, T)                                               \
31
  do {                                                                    \
32
    T* plist = (T*)pCol->pData;                                           \
33
    for (int32_t i = start; i < numOfRows + pInput->startRowIndex; ++i) { \
34
      if (colDataIsNull_f(pCol->nullbitmap, i)) {                         \
35
        continue;                                                         \
36
      }                                                                   \
37
                                                                          \
38
      numOfElem += 1;                                                     \
39
      pAvgRes->count -= 1;                                                \
40
      sumT -= plist[i];                                                   \
41
    }                                                                     \
42
  } while (0)
43

44
// define signed number sum with check overflow
45
#define CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, val)                                    \
46
  do {                                                                             \
47
    SAvgRes* out = pAvgRes;                                                        \
48
    if (out->sum.overflow) {                                                       \
49
      out->sum.dsum += val;                                                        \
50
    } else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \
51
               out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val) { \
52
      double dsum = (double)out->sum.isum;                                         \
53
      out->sum.overflow = true;                                                    \
54
      out->sum.dsum = dsum + val;                                                  \
55
    } else {                                                                       \
56
      out->sum.isum += val;                                                        \
57
    }                                                                              \
58
  } while (0)
59

60
// val is big than INT64_MAX, val come from merge
61
#define CHECK_OVERFLOW_SUM_SIGNED_BIG(pAvgRes, val, big)                                  \
62
  do {                                                                                    \
63
    SAvgRes* out = pAvgRes;                                                               \
64
    if (out->sum.overflow) {                                                              \
65
      out->sum.dsum += val;                                                               \
66
    } else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val ||        \
67
               out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val || big) { \
68
      double dsum = (double)out->sum.isum;                                                \
69
      out->sum.overflow = true;                                                           \
70
      out->sum.dsum = dsum + val;                                                         \
71
    } else {                                                                              \
72
      SUM_RES_INC_ISUM(&AVG_RES_GET_SUM(out), val);                                       \
73
    }                                                                                     \
74
  } while (0)
75

76
// define unsigned number sum with check overflow
77
#define CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, val)   \
78
  do {                                              \
79
    SAvgRes* out = pAvgRes;                         \
80
    if (out->sum.overflow) {                        \
81
      out->sum.dsum += val;                         \
82
    } else if (UINT64_MAX - out->sum.usum <= val) { \
83
      double dsum = (double)out->sum.usum;          \
84
      out->sum.overflow = true;                     \
85
      out->sum.dsum = dsum + val;                   \
86
    } else {                                        \
87
      out->sum.usum += val;                         \
88
    }                                               \
89
  } while (0)
90

91
// val is big than UINT64_MAX, val come from merge
92
#define CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pAvgRes, val, big) \
93
  do {                                                     \
94
    SAvgRes* out = pAvgRes;                                \
95
    if (out->sum.overflow) {                               \
96
      out->sum.dsum += val;                                \
97
    } else if (UINT64_MAX - out->sum.usum <= val || big) { \
98
      double dsum = (double)out->sum.usum;                 \
99
      out->sum.overflow = true;                            \
100
      out->sum.dsum = dsum + val;                          \
101
    } else {                                               \
102
      out->sum.usum += val;                                \
103
    }                                                      \
104
  } while (0)
105

106
int32_t getAvgInfoSize(SFunctionNode* pFunc) {
179,788✔
107
  if (pFunc->pSrcFuncRef) return AVG_RES_GET_SIZE(pFunc->pSrcFuncRef->srcFuncInputType.type);
179,788✔
108
  return AVG_RES_GET_SIZE(pFunc->srcFuncInputType.type);
164,695✔
109
}
110

111
bool getAvgFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) {
164,262✔
112
  pEnv->calcMemSize =getAvgInfoSize(pFunc);
164,262✔
113
  return true;
164,422✔
114
}
115

116
int32_t avgFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo) {
34,172,539✔
117
  if (pResultInfo->initialized) {
34,172,539!
118
    return TSDB_CODE_SUCCESS;
×
119
  }
120
  if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResultInfo)) {
34,172,539!
121
    return TSDB_CODE_FUNC_SETUP_ERROR;
×
122
  }
123

124
  void* pRes = GET_ROWCELL_INTERBUF(pResultInfo);
34,325,926✔
125
  (void)memset(pRes, 0, pCtx->resDataInfo.interBufSize);
34,325,926✔
126
  return TSDB_CODE_SUCCESS;
34,325,926✔
127
}
128

129
static int32_t calculateAvgBySMAInfo(void* pRes, int32_t numOfRows, int32_t type, const SColumnDataAgg* pAgg, int32_t* pNumOfElem) {
243✔
130
  int32_t numOfElem = numOfRows - pAgg->numOfNull;
243✔
131

132
  AVG_RES_INC_COUNT(pRes, type, numOfElem);
243✔
133
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
243!
134
    CHECK_OVERFLOW_SUM_SIGNED(pRes, pAgg->sum);
188!
135
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
55!
136
    CHECK_OVERFLOW_SUM_UNSIGNED(pRes, pAgg->sum);
×
137
  } else if (IS_FLOAT_TYPE(type)) {
55!
138
    SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), GET_DOUBLE_VAL((const char*)&(pAgg->sum)));
×
139
  } else if (IS_DECIMAL_TYPE(type)) {
55!
140
    bool overflow = pAgg->overflow;
55✔
141
    if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
55✔
142
    SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes), &pAgg->decimal128Sum, TSDB_DATA_TYPE_DECIMAL);
45!
143
    if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
45!
144
  }
145

146
  *pNumOfElem = numOfElem;
233✔
147
  return 0;
233✔
148
}
149

150
static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputColumnInfoData *pInput, void* pRes, int32_t* pNumOfElem) {
23,788,307✔
151
  int32_t start = pInput->startRowIndex;
23,788,307✔
152
  int32_t numOfRows = pInput->numOfRows;
23,788,307✔
153
  int32_t numOfElems = 0;
23,788,307✔
154

155
  switch (type) {
23,788,307!
156
    case TSDB_DATA_TYPE_TINYINT: {
456,248✔
157
      int8_t* plist = (int8_t*)pCol->pData;
456,248✔
158
      for (int32_t i = start; i < numOfRows + start; ++i) {
1,804,263✔
159
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,348,015✔
160
          continue;
1,020,555✔
161
        }
162

163
        numOfElems += 1;
327,460✔
164
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_TINYINT, 1);
327,460✔
165
        CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
327,460!
166
      }
167

168
      break;
456,248✔
169
    }
170

171
    case TSDB_DATA_TYPE_SMALLINT: {
7,783✔
172
      int16_t* plist = (int16_t*)pCol->pData;
7,783✔
173
      for (int32_t i = start; i < numOfRows + start; ++i) {
560,281✔
174
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
552,498✔
175
          continue;
165,543✔
176
        }
177

178
        numOfElems += 1;
386,955✔
179
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_SMALLINT, 1);
386,955✔
180
        CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
386,955!
181
      }
182
      break;
7,783✔
183
    }
184

185
    case TSDB_DATA_TYPE_INT: {
825,729✔
186
      int32_t* plist = (int32_t*)pCol->pData;
825,729✔
187
      for (int32_t i = start; i < numOfRows + start; ++i) {
4,298,517✔
188
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
3,472,788✔
189
          continue;
1,218,286✔
190
        }
191

192
        numOfElems += 1;
2,254,502✔
193
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_INT, 1);
2,254,502✔
194
        CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
2,254,502!
195
      }
196

197
      break;
825,729✔
198
    }
199

200
    case TSDB_DATA_TYPE_BIGINT: {
18,272,730✔
201
      int64_t* plist = (int64_t*)pCol->pData;
18,272,730✔
202
      for (int32_t i = start; i < numOfRows + start; ++i) {
47,445,801✔
203
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
29,173,071✔
204
          continue;
23,834,536✔
205
        }
206

207
        numOfElems += 1;
5,338,535✔
208
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_BIGINT, 1);
5,338,535✔
209
        CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]);
5,338,535✔
210
      }
211
      break;
18,272,730✔
212
    }
213

214
    case TSDB_DATA_TYPE_UTINYINT: {
25✔
215
      uint8_t* plist = (uint8_t*)pCol->pData;
25✔
216
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,035✔
217
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
80,010!
218
          continue;
×
219
        }
220

221
        numOfElems += 1;
80,010✔
222
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UTINYINT, 1);
80,010✔
223
        CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
80,010!
224
      }
225

226
      break;
25✔
227
    }
228

229
    case TSDB_DATA_TYPE_USMALLINT: {
25✔
230
      uint16_t* plist = (uint16_t*)pCol->pData;
25✔
231
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,035✔
232
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
80,010!
233
          continue;
×
234
        }
235

236
        numOfElems += 1;
80,010✔
237
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_USMALLINT, 1);
80,010✔
238
        CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
80,010!
239
      }
240
      break;
25✔
241
    }
242

243
    case TSDB_DATA_TYPE_UINT: {
140,521✔
244
      uint32_t* plist = (uint32_t*)pCol->pData;
140,521✔
245
      for (int32_t i = start; i < numOfRows + start; ++i) {
406,901✔
246
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
266,380✔
247
          continue;
33,691✔
248
        }
249

250
        numOfElems += 1;
232,689✔
251
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UINT, 1);
232,689✔
252
        CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
232,689!
253
      }
254

255
      break;
140,521✔
256
    }
257

258
    case TSDB_DATA_TYPE_UBIGINT: {
121✔
259
      uint64_t* plist = (uint64_t*)pCol->pData;
121✔
260
      for (int32_t i = start; i < numOfRows + start; ++i) {
80,840✔
261
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
80,719✔
262
          continue;
4✔
263
        }
264

265
        numOfElems += 1;
80,715✔
266
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_UBIGINT, 1);
80,715✔
267
        CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]);
80,715✔
268
        
269
      }
270
      break;
121✔
271
    }
272

273
    case TSDB_DATA_TYPE_FLOAT: {
411,694✔
274
      float* plist = (float*)pCol->pData;
411,694✔
275
      for (int32_t i = start; i < numOfRows + start; ++i) {
1,826,023✔
276
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
1,414,329✔
277
          continue;
960,714✔
278
        }
279

280
        numOfElems += 1;
453,615✔
281
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_FLOAT, 1);
453,615✔
282
        SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), plist[i]);
453,615✔
283
      }
284
      break;
411,694✔
285
    }
286

287
    case TSDB_DATA_TYPE_DOUBLE: {
3,699,300✔
288
      double* plist = (double*)pCol->pData;
3,699,300✔
289
      for (int32_t i = start; i < numOfRows + start; ++i) {
16,521,218✔
290
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
12,821,918✔
291
          continue;
1,854,663✔
292
        }
293

294
        numOfElems += 1;
10,967,255✔
295
        AVG_RES_INC_COUNT(pRes, TSDB_DATA_TYPE_DOUBLE, 1);
10,967,255✔
296
        SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pRes), plist[i]);
10,967,255✔
297
      }
298
      break;
3,699,300✔
299
    }
300
    case TSDB_DATA_TYPE_DECIMAL64:
3,200✔
301
    case TSDB_DATA_TYPE_DECIMAL: {
302
      const char* pDec = pCol->pData;
3,200✔
303
      for (int32_t i = start; i < numOfRows + start; ++i) {
223,330✔
304
        if (colDataIsNull_f(pCol->nullbitmap, i)) {
220,130✔
305
          continue;
3,386✔
306
        }
307

308
        numOfElems += 1;
216,744✔
309
        AVG_RES_INC_COUNT(pRes, type, 1);
216,744!
310
        bool overflow = false;
216,744✔
311
        SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes), (const void*)(pDec + i * tDataTypes[type].bytes), type);
216,744!
312
        if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
216,744!
313
      }
314
    } break;
3,200✔
315
    default:
×
316
      break;
×
317
  }
318

319
  *pNumOfElem = numOfElems;
23,788,307✔
320
  return 0;
23,788,307✔
321
}
322

323
int32_t avgFunction(SqlFunctionCtx* pCtx) {
47,481,181✔
324
  int32_t       numOfElem = 0;
47,481,181✔
325
  const int32_t THRESHOLD_SIZE = 8;
47,481,181✔
326

327
  SInputColumnInfoData* pInput = &pCtx->input;
47,481,181✔
328
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
47,481,181✔
329
  int32_t               type = pInput->pData[0]->info.type;
47,481,181✔
330
  pCtx->inputType = type;
47,481,181✔
331

332
  void* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
47,481,181✔
333

334
  // computing based on the true data block
335
  SColumnInfoData* pCol = pInput->pData[0];
47,481,181✔
336

337
  int32_t start = pInput->startRowIndex;
47,481,181✔
338
  int32_t numOfRows = pInput->numOfRows;
47,481,181✔
339

340
  if (IS_NULL_TYPE(type)) {
47,481,181✔
341
    goto _over;
228✔
342
  }
343

344
  AVG_RES_SET_TYPE(pAvgRes, pCtx->inputType, type);
47,480,953!
345
  if (IS_DECIMAL_TYPE(type)) AVG_RES_SET_INPUT_SCALE(pAvgRes, pInput->pData[0]->info.scale);
47,480,953!
346

347
  if (pInput->colDataSMAIsSet) {  // try to use SMA if available
47,480,953✔
348
    int32_t code = calculateAvgBySMAInfo(pAvgRes, numOfRows, type, pAgg, &numOfElem);
243✔
349
    if (code != 0) return code;
243✔
350
  } else if (!pCol->hasNull) {  // try to employ the simd instructions to speed up the loop
47,480,710✔
351
    numOfElem = pInput->numOfRows;
24,600,953✔
352
    AVG_RES_INC_COUNT(pAvgRes, pCtx->inputType, pInput->numOfRows);
24,600,953!
353

354
    switch(type) {
24,600,953!
355
      case TSDB_DATA_TYPE_UTINYINT:
5,537✔
356
      case TSDB_DATA_TYPE_TINYINT: {
357
        const int8_t* plist = (const int8_t*) pCol->pData;
5,537✔
358

359
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
224,926✔
360
          if (type == TSDB_DATA_TYPE_TINYINT) {
219,389✔
361
            CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
169,349!
362
          } else {
363
            CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint8_t)plist[i]);
50,040!
364
          }
365
        }
366
        break;
5,537✔
367
      }
368

369
      case TSDB_DATA_TYPE_USMALLINT:
7,475✔
370
      case TSDB_DATA_TYPE_SMALLINT: {
371
        const int16_t* plist = (const int16_t*)pCol->pData;
7,475✔
372

373
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
610,117✔
374
          if (type == TSDB_DATA_TYPE_SMALLINT) {
602,642✔
375
            CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
552,602!
376
          } else {
377
            CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint16_t)plist[i]);
50,040!
378
          }
379
        }
380
        break;
7,475✔
381
      }
382

383
      case TSDB_DATA_TYPE_UINT:
5,597,300✔
384
      case TSDB_DATA_TYPE_INT: {
385
        const int32_t* plist = (const int32_t*) pCol->pData;
5,597,300✔
386

387
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
20,459,556✔
388
          if (type == TSDB_DATA_TYPE_INT) {
14,862,256✔
389
            CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
14,514,823!
390
          } else {
391
            CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint32_t)plist[i]);
347,433!
392
          }
393
        }
394
        break;
5,597,300✔
395
      }
396

397
      case TSDB_DATA_TYPE_UBIGINT:
15,882,283✔
398
      case TSDB_DATA_TYPE_BIGINT: {
399
        const int64_t* plist = (const int64_t*) pCol->pData;
15,882,283✔
400

401
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
50,151,701✔
402
          if (type == TSDB_DATA_TYPE_BIGINT) {
34,269,418✔
403
            CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]);
34,216,155!
404
          } else {
405
            CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint64_t)plist[i]);
53,263✔
406
          }
407
        }
408
        break;
15,882,283✔
409
      }
410

411
      case TSDB_DATA_TYPE_FLOAT: {
617,275✔
412
        const float* plist = (const float*) pCol->pData;
617,275✔
413

414
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
2,033,277✔
415
          SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pAvgRes), plist[i]);
1,416,002✔
416
        }
417
        break;
617,275✔
418
      }
419
      case TSDB_DATA_TYPE_DOUBLE: {
2,515,141✔
420
        const double* plist = (const double*)pCol->pData;
2,515,141✔
421

422
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
20,482,557✔
423
          SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pAvgRes), plist[i]);
17,967,416✔
424
        }
425
        break;
2,515,141✔
426
      }
427
      case TSDB_DATA_TYPE_DECIMAL:
998✔
428
      case TSDB_DATA_TYPE_DECIMAL64: {
429
        const char* pDec = pCol->pData;
998✔
430
        for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) {
1,997✔
431
          bool overflow = false;
998✔
432
          if (type == TSDB_DATA_TYPE_DECIMAL64) {
998✔
433
            SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pAvgRes), (const void*)(pDec + i * tDataTypes[type].bytes),
988!
434
                                    TSDB_DATA_TYPE_DECIMAL64);
435
          } else {
436
            SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pAvgRes), (const void*)(pDec + i * tDataTypes[type].bytes),
10!
437
                                    TSDB_DATA_TYPE_DECIMAL);
438
          }
439
          if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
999!
440
        }
441
      } break;
999✔
442
      default:
×
443
        return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
444
    }
445
  } else {
446
    int32_t code = doAddNumericVector(pCol, type, pInput, pAvgRes, &numOfElem);
22,879,757✔
447
    if (code) return code;
23,819,608!
448
  }
449

450
_over:
23,819,608✔
451
  // data in the check operation are all null, not output
452
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
48,446,079✔
453
  return TSDB_CODE_SUCCESS;
48,446,079✔
454
}
455

456
static int32_t avgTransferInfo(SqlFunctionCtx* pCtx, void* pInput, void* pOutput) {
20,699,509✔
457
  int32_t inputDT = pCtx->pExpr->pExpr->_function.pFunctNode->srcFuncInputType.type;
20,699,509✔
458
  int32_t type = AVG_RES_GET_TYPE(pInput, inputDT);
20,699,509!
459
  pCtx->inputType = type;
20,699,509✔
460
  if (IS_NULL_TYPE(type)) {
20,699,509✔
461
    return 0;
194✔
462
  }
463

464

465
  AVG_RES_SET_TYPE(pOutput, inputDT, type);
20,699,315!
466
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
39,444,557!
467
    bool overflow = AVG_RES_GET_SUM_OVERFLOW(pInput, false, 0);
18,745,242✔
468
    CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, (overflow ? SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)) : SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pInput))), overflow);
18,745,242!
469
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
1,963,066✔
470
    bool overflow = AVG_RES_GET_SUM_OVERFLOW(pInput, false, 0);
8,993✔
471
    CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, (overflow ? SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)) : SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pInput))), overflow);
8,993!
472
  } else if (IS_DECIMAL_TYPE(type)) {
1,945,610!
UNCOV
473
    AVG_RES_SET_INPUT_SCALE(pOutput, AVG_RES_GET_INPUT_SCALE(pInput));
×
UNCOV
474
    bool overflow = false;
×
UNCOV
475
    SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pOutput), &AVG_RES_GET_DECIMAL_SUM(pInput), TSDB_DATA_TYPE_DECIMAL);
×
476
    if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW;
530!
477
  } else {
478
    SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pOutput), SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pInput)));
1,946,097✔
479
  }
480

481
  AVG_RES_INC_COUNT(pOutput, type, AVG_RES_GET_COUNT(pInput, true, type));
20,700,862!
482
  return 0;
20,700,862✔
483
}
484

485
int32_t avgFunctionMerge(SqlFunctionCtx* pCtx) {
8,627,658✔
486
  SInputColumnInfoData* pInput = &pCtx->input;
8,627,658✔
487
  SColumnInfoData*      pCol = pInput->pData[0];
8,627,658✔
488

489
  if (IS_NULL_TYPE(pCol->info.type)) {
8,627,658✔
490
    SET_VAL(GET_RES_INFO(pCtx), 0, 1);
7✔
491
    return TSDB_CODE_SUCCESS;
7✔
492
  }
493

494
  if (pCol->info.type != TSDB_DATA_TYPE_BINARY) {
8,627,651!
495
    return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
496
  }
497

498
  void* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
8,627,651✔
499

500
  int32_t start = pInput->startRowIndex;
8,627,651✔
501

502
  for (int32_t i = start; i < start + pInput->numOfRows; ++i) {
29,328,041✔
503
    if(colDataIsNull_s(pCol, i)) continue;
41,398,140!
504
    char*    data = colDataGetData(pCol, i);
20,699,070!
505
    void* pInputInfo = varDataVal(data);
20,699,070✔
506
    int32_t code = avgTransferInfo(pCtx, pInputInfo, pInfo);
20,699,070✔
507
    if (code != 0) return code;
20,700,390!
508
  }
509

510
  SET_VAL(GET_RES_INFO(pCtx), 1, 1);
8,628,971✔
511

512
  return TSDB_CODE_SUCCESS;
8,628,971✔
513
}
514

515
#ifdef BUILD_NO_CALL
516
int32_t avgInvertFunction(SqlFunctionCtx* pCtx) {
517
  int32_t numOfElem = 0;
518

519
  // Only the pre-computing information loaded and actual data does not loaded
520
  SInputColumnInfoData* pInput = &pCtx->input;
521
  SAvgRes* pAvgRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
522

523
  // computing based on the true data block
524
  SColumnInfoData* pCol = pInput->pData[0];
525

526
  int32_t start = pInput->startRowIndex;
527
  int32_t numOfRows = pInput->numOfRows;
528

529
  switch (pCol->info.type) {
530
    case TSDB_DATA_TYPE_TINYINT: {
531
      LIST_AVG_N(pAvgRes->sum.isum, int8_t);
532
      break;
533
    }
534
    case TSDB_DATA_TYPE_SMALLINT: {
535
      LIST_AVG_N(pAvgRes->sum.isum, int16_t);
536
      break;
537
    }
538
    case TSDB_DATA_TYPE_INT: {
539
      LIST_AVG_N(pAvgRes->sum.isum, int32_t);
540
      break;
541
    }
542
    case TSDB_DATA_TYPE_BIGINT: {
543
      LIST_AVG_N(pAvgRes->sum.isum, int64_t);
544
      break;
545
    }
546
    case TSDB_DATA_TYPE_UTINYINT: {
547
      LIST_AVG_N(pAvgRes->sum.usum, uint8_t);
548
      break;
549
    }
550
    case TSDB_DATA_TYPE_USMALLINT: {
551
      LIST_AVG_N(pAvgRes->sum.usum, uint16_t);
552
      break;
553
    }
554
    case TSDB_DATA_TYPE_UINT: {
555
      LIST_AVG_N(pAvgRes->sum.usum, uint32_t);
556
      break;
557
    }
558
    case TSDB_DATA_TYPE_UBIGINT: {
559
      LIST_AVG_N(pAvgRes->sum.usum, uint64_t);
560
      break;
561
    }
562
    case TSDB_DATA_TYPE_FLOAT: {
563
      LIST_AVG_N(pAvgRes->sum.dsum, float);
564
      break;
565
    }
566
    case TSDB_DATA_TYPE_DOUBLE: {
567
      LIST_AVG_N(pAvgRes->sum.dsum, double);
568
      break;
569
    }
570
    default:
571
      break;
572
  }
573

574
  // data in the check operation are all null, not output
575
  SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1);
576
  return TSDB_CODE_SUCCESS;
577
}
578
#endif
579

580
int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) {
10✔
581
  SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx);
10✔
582
  void*                pDBuf = GET_ROWCELL_INTERBUF(pDResInfo);
10✔
583
  int32_t              type = AVG_RES_GET_TYPE(pDBuf, pDestCtx->inputType);
10!
584

585
  SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx);
10✔
586
  void*                pSBuf = GET_ROWCELL_INTERBUF(pSResInfo);
10✔
587
  type = (type == TSDB_DATA_TYPE_NULL) ? AVG_RES_GET_TYPE(pSBuf, pDestCtx->inputType) : type;
10!
588

589
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
10!
590
    CHECK_OVERFLOW_SUM_SIGNED(pDBuf, SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pSBuf)));
×
591
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
10!
592
    CHECK_OVERFLOW_SUM_UNSIGNED(pDBuf, SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pSBuf)));
×
593
  } else if (IS_DECIMAL_TYPE(type)) {
20!
594
    bool overflow = false;
10✔
595
    SUM_RES_INC_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pDBuf), &SUM_RES_GET_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pSBuf)), type);
10!
596
    if (overflow) {
597

598
    }
599
  } else {
600
    SUM_RES_INC_DSUM(&AVG_RES_GET_SUM(pDBuf), SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pSBuf)));
×
601
  }
602
  AVG_RES_INC_COUNT(pDBuf, pDestCtx->inputType, AVG_RES_GET_COUNT(pSBuf, true, pDestCtx->inputType));
10!
603

604
  return TSDB_CODE_SUCCESS;
10✔
605
}
606

607
int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
12,311,621✔
608
  SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx);
12,311,621✔
609

610
  void*   pRes = GET_ROWCELL_INTERBUF(pEntryInfo);
12,311,621✔
611
  int32_t type = AVG_RES_GET_TYPE(pRes, pCtx->inputType);
12,311,621✔
612
  int64_t count = AVG_RES_GET_COUNT(pRes, true, type);
12,311,621✔
613

614
  if (AVG_RES_GET_COUNT(pRes, true, pCtx->inputType) > 0) {
12,311,621✔
615
    
616
    if(AVG_RES_GET_SUM_OVERFLOW(pRes, true, pCtx->inputType)) {
11,430,179✔
617
      AVG_RES_GET_AVG(pRes) = SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
9,847✔
618
    }else if (IS_SIGNED_NUMERIC_TYPE(type)) {
11,420,332!
619
      AVG_RES_GET_AVG(pRes) = SUM_RES_GET_ISUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
6,619,077✔
620
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
4,801,255✔
621
      AVG_RES_GET_AVG(pRes) = SUM_RES_GET_USUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
193,333✔
622
    } else if (IS_DECIMAL_TYPE(type)) {
4,609,570✔
623
      int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
1,534✔
624
      SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
1,534✔
625
      SDataType        sumDt = {.type = TSDB_DATA_TYPE_DECIMAL,
1,648✔
626
                                .bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
1,648✔
627
                                .precision = pCol->info.precision,
1,648✔
628
                                .scale = AVG_RES_GET_INPUT_SCALE(pRes)};
1,648✔
629
      SDataType        countDt = {
1,648✔
630
                 .type = TSDB_DATA_TYPE_BIGINT, .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .precision = 0, .scale = 0};
1,648✔
631
      SDataType avgDt = {.type = TSDB_DATA_TYPE_DECIMAL,
1,648✔
632
                         .bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
1,648✔
633
                         .precision = pCol->info.precision,
1,648✔
634
                         .scale = pCol->info.scale};
1,648✔
635
      int64_t   count = AVG_RES_GET_COUNT(pRes, true, type);
1,648!
636
      int32_t   code =
637
          decimalOp(OP_TYPE_DIV, &sumDt, &countDt, &avgDt, &SUM_RES_GET_DECIMAL_SUM(&AVG_RES_GET_DECIMAL_SUM(pRes)),
1,648✔
638
                    &count, &AVG_RES_GET_DECIMAL_AVG(pRes));
1,648✔
639
      if (code != TSDB_CODE_SUCCESS) {
1,648!
640
        return code;
×
641
      }
642
    } else {
643
      AVG_RES_GET_AVG(pRes) = SUM_RES_GET_DSUM(&AVG_RES_GET_SUM(pRes)) / ((double)AVG_RES_GET_COUNT(pRes, false, 0));
4,606,388✔
644
    }
645
  }
646
  if (AVG_RES_GET_COUNT(pRes, true, pCtx->inputType) == 0) {
12,311,735✔
647
    pEntryInfo->numOfRes = 0;
881,808✔
648
  } else if (!IS_DECIMAL_TYPE(pCtx->inputType)) {
11,429,927✔
649
    if (isinf(AVG_RES_GET_AVG(pRes)) || isnan(AVG_RES_GET_AVG(pRes))) pEntryInfo->numOfRes = 0;
11,428,724!
650
  } else {
651
    pEntryInfo->numOfRes = 1;
1,203✔
652
  }
653

654
  return functionFinalize(pCtx, pBlock);
12,311,735✔
655
}
656

657
int32_t avgPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
22,057,277✔
658
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
22,057,277✔
659
  void*                pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx));
22,057,277✔
660
  int32_t              resultBytes = AVG_RES_GET_SIZE(pCtx->inputType);
22,057,277!
661
  char*                res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char));
22,057,277!
662
  int32_t              code = TSDB_CODE_SUCCESS;
22,470,880✔
663
  if (NULL == res) {
22,470,880!
664
    return terrno;
×
665
  }
666
  (void)memcpy(varDataVal(res), pInfo, resultBytes);
22,470,880✔
667
  varDataSetLen(res, resultBytes);
22,470,880✔
668

669
  int32_t          slotId = pCtx->pExpr->base.resSchema.slotId;
22,470,880✔
670
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
22,470,880✔
671
  if(NULL == pCol) {
22,409,625!
672
    code = TSDB_CODE_OUT_OF_RANGE;
×
673
    goto _exit;
×
674
  }
675

676
  code = colDataSetVal(pCol, pBlock->info.rows, res, false);
22,409,625✔
677

678
_exit:
22,188,695✔
679
  taosMemoryFree(res);
22,188,695!
680
  return code;
22,614,127✔
681
}
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