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

taosdata / TDengine / #5011

03 Apr 2026 03:59PM UTC coverage: 72.3% (+0.008%) from 72.292%
#5011

push

travis-ci

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

4053 of 5985 new or added lines in 68 files covered. (67.72%)

732 existing lines in 143 files now uncovered.

257430 of 356056 relevant lines covered (72.3%)

131834103.52 hits per line

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

82.64
/source/libs/function/src/detail/tminmax.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 "tcompare.h"
19
#include "tdatablock.h"
20
#include "tfunctionInt.h"
21
#include "tglobal.h"
22
#include "decimal.h"
23

24
#define __COMPARE_ACQUIRED_MAX(i, end, bm, _data, ctx, val, pos) \
25
  int32_t code = TSDB_CODE_SUCCESS;                              \
26
  for (; i < (end); ++i) {                                       \
27
    if (BMIsNull(bm, i)) {                                \
28
      continue;                                                  \
29
    }                                                            \
30
                                                                 \
31
    if ((val) < (_data)[i]) {                                    \
32
      (val) = (_data)[i];                                        \
33
      if ((ctx)->subsidiaries.num > 0) {                         \
34
        code = updateTupleData((ctx), i, (ctx)->pSrcBlock, pos); \
35
        if (TSDB_CODE_SUCCESS != code) {                         \
36
          return code;                                           \
37
        }                                                        \
38
      }                                                          \
39
    }                                                            \
40
  }
41

42
#define __COMPARE_ACQUIRED_MIN(i, end, bm, _data, ctx, val, pos) \
43
  int32_t code = TSDB_CODE_SUCCESS;                              \
44
  for (; i < (end); ++i) {                                       \
45
    if (BMIsNull(bm, i)) {                                \
46
      continue;                                                  \
47
    }                                                            \
48
                                                                 \
49
    if ((val) > (_data)[i]) {                                    \
50
      (val) = (_data)[i];                                        \
51
      if ((ctx)->subsidiaries.num > 0) {                         \
52
        code = updateTupleData((ctx), i, (ctx)->pSrcBlock, pos); \
53
        if (TSDB_CODE_SUCCESS != code) {                         \
54
          return code;                                           \
55
        }                                                        \
56
      }                                                          \
57
    }                                                            \
58
  }
59

60
#define __COMPARE_EXTRACT_MIN(start, end, val, _data) \
61
  for (int32_t i = (start); i < (end); ++i) {         \
62
    if ((val) > (_data)[i]) {                         \
63
      (val) = (_data)[i];                             \
64
    }                                                 \
65
  }
66

67
#define __COMPARE_EXTRACT_MAX(start, end, val, _data) \
68
  for (int32_t i = (start); i < (end); ++i) {         \
69
    if ((val) < (_data)[i]) {                         \
70
      (val) = (_data)[i];                             \
71
    }                                                 \
72
  }
73

74
#define GET_INVOKE_INTRINSIC_THRESHOLD(_bits, _bytes) ((_bits) / ((_bytes) << 3u))
75

76
static int32_t findFirstValPosition(const SColumnInfoData* pCol, int32_t start, int32_t numOfRows, bool isStr) {
2,147,483,647✔
77
  int32_t i = start;
2,147,483,647✔
78

79
  while (i < (start + numOfRows) && (isStr ? colDataIsNull_s(pCol, i) : colDataIsNull_f(pCol, i) == true)) {
2,147,483,647✔
80
    i += 1;
2,147,483,647✔
81
  }
82

83
  return i;
2,147,483,647✔
84
}
85

86
static void handleInt8Col(const void* data, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf, bool isMinFunc,
13,829,578✔
87
                          bool signVal) {
88
  if (!pBuf->assign) {
13,829,578✔
89
    pBuf->v = ((const int8_t*)data)[start];
271,224✔
90
  }
91

92
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int8_t) >= M256_BYTES) {
13,829,578✔
93
    int32_t code = i8VectorCmpAVX2(((char*)data) + start * sizeof(int8_t), numOfRows, isMinFunc, signVal, &pBuf->v);
13,829,578✔
94
    if (code == TSDB_CODE_SUCCESS) {
13,829,578✔
95
      pBuf->assign = true;
13,829,578✔
96
      return;
13,829,578✔
97
    }
98
  }
99

100
  if (signVal) {
×
101
    const int8_t* p = (const int8_t*)data;
×
102
    int8_t*       v = (int8_t*)&pBuf->v;
×
103

104
    if (isMinFunc) {
×
105
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
106
    } else {
107
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
108
    }
109
  } else {
110
    const uint8_t* p = (const uint8_t*)data;
×
111
    uint8_t*       v = (uint8_t*)&pBuf->v;
×
112

113
    if (isMinFunc) {
×
114
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
115
    } else {
116
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
117
    }
118
  }
119

120
  pBuf->assign = true;
×
121
}
122

123
static void handleInt16Col(const void* data, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf, bool isMinFunc,
12,106,864✔
124
                           bool signVal) {
125
  if (!pBuf->assign) {
12,106,864✔
126
    pBuf->v = ((const int16_t*)data)[start];
348,139✔
127
  }
128

129
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int16_t) >= M256_BYTES) {
12,106,864✔
130
    int32_t code = i16VectorCmpAVX2(((char*)data) + start * sizeof(int16_t), numOfRows, isMinFunc, signVal, &pBuf->v);
12,107,539✔
131
    if (code == TSDB_CODE_SUCCESS) {
12,108,214✔
132
      pBuf->assign = true;
12,107,539✔
133
      return;
12,107,539✔
134
    }
135
  }
136

137
  if (signVal) {
×
138
    const int16_t* p = (const int16_t*)data;
×
139
    int16_t*       v = (int16_t*)&pBuf->v;
×
140

141
    if (isMinFunc) {
×
142
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
143
    } else {
144
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
145
    }
146
  } else {
147
    const uint16_t* p = (const uint16_t*)data;
×
148
    uint16_t*       v = (uint16_t*)&pBuf->v;
×
149

150
    if (isMinFunc) {
×
151
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
152
    } else {
153
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
154
    }
155
  }
156

157
  pBuf->assign = true;
×
158
}
159

160
static void handleInt32Col(const void* data, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf, bool isMinFunc,
33,398,004✔
161
                           bool signVal) {
162
  if (!pBuf->assign) {
33,398,004✔
163
    pBuf->v = ((const int32_t*)data)[start];
16,218,723✔
164
  }
165

166
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int32_t) >= M256_BYTES) {
33,401,968✔
167
    int32_t code = i32VectorCmpAVX2(((char*)data) + start * sizeof(int32_t), numOfRows, isMinFunc, signVal, &pBuf->v);
33,394,764✔
168
    if (code == TSDB_CODE_SUCCESS) {
33,382,154✔
169
      pBuf->assign = true;
33,389,358✔
170
      return;
33,389,358✔
171
    }
172
  }
173

174
  if (signVal) {
×
175
    const int32_t* p = (const int32_t*)data;
×
176
    int32_t*       v = (int32_t*)&pBuf->v;
×
177

178
    if (isMinFunc) {
×
179
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
180
    } else {
181
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
182
    }
183
  } else {
184
    const uint32_t* p = (const uint32_t*)data;
×
185
    uint32_t*       v = (uint32_t*)&pBuf->v;
×
186

187
    if (isMinFunc) {
×
188
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
×
189
    } else {
190
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
×
191
    }
192
  }
193

194
  pBuf->assign = true;
×
195
}
196

197
static void handleInt64Col(const void* data, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf, bool isMinFunc,
13,168,180✔
198
                           bool signVal) {
199
  if (!pBuf->assign) {
13,168,180✔
200
    pBuf->v = ((const int64_t*)data)[start];
475,234✔
201
  }
202

203
  if (signVal) {
13,168,180✔
204
    const int64_t* p = (const int64_t*)data;
8,027,438✔
205
    int64_t*       v = &pBuf->v;
8,027,438✔
206

207
    if (isMinFunc) {
8,027,438✔
208
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
915,321,038✔
209
    } else {
210
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
880,457,456✔
211
    }
212
  } else {
213
    const uint64_t* p = (const uint64_t*)data;
5,140,742✔
214
    uint64_t*       v = (uint64_t*)&pBuf->v;
5,140,742✔
215

216
    if (isMinFunc) {
5,140,742✔
217
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
506,017,114✔
218
    } else {
219
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
506,067,991✔
220
    }
221
  }
222

223
  pBuf->assign = true;
13,161,960✔
224
}
13,168,180✔
225

226
static void handleFloatCol(SColumnInfoData* pCol, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf,
8,233,445✔
227
                           bool isMinFunc) {
228
  float* pData = (float*)pCol->pData;
8,233,445✔
229
  float* val = (float*)&pBuf->v;
8,233,445✔
230
  if (!pBuf->assign) {
8,233,445✔
231
    *val = pData[start];
502,383✔
232
  }
233

234
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(float) >= M256_BYTES) {
8,233,445✔
235
    int32_t code = floatVectorCmpAVX2(pData + start, numOfRows, isMinFunc, val);
8,233,445✔
236
    if (code == TSDB_CODE_SUCCESS) {
8,233,445✔
237
      pBuf->assign = true;
8,233,445✔
238
      return;
8,233,445✔
239
    }
240
  }
241

242
  if (isMinFunc) {  // min
×
243
    __COMPARE_EXTRACT_MIN(start, start + numOfRows, *val, pData);
×
244
  } else {  // max
245
    __COMPARE_EXTRACT_MAX(start, start + numOfRows, *val, pData);
×
246
  }
247

248
  pBuf->assign = true;
×
249
}
250

251
static void handleDoubleCol(SColumnInfoData* pCol, int32_t start, int32_t numOfRows, SMinmaxResInfo* pBuf,
5,278,948✔
252
                            bool isMinFunc) {
253
  double* pData = (double*)pCol->pData;
5,278,948✔
254
  double* val = (double*)&pBuf->v;
5,278,948✔
255
  if (!pBuf->assign) {
5,278,948✔
256
    *val = pData[start];
255,642✔
257
  }
258

259
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(double) >= M256_BYTES) {
5,278,948✔
260
    int32_t code = doubleVectorCmpAVX2(pData + start, numOfRows, isMinFunc, val);
5,278,948✔
261
    if (code == TSDB_CODE_SUCCESS) {
5,278,317✔
262
      pBuf->assign = true;
5,278,317✔
263
      return;
5,278,948✔
264
    }
265
  }
266

267
  if (isMinFunc) {  // min
×
268
    __COMPARE_EXTRACT_MIN(start, start + numOfRows, *val, pData);
×
269
  } else {  // max
270
    __COMPARE_EXTRACT_MAX(start, start + numOfRows, *val, pData);
×
271
  }
272

273
  pBuf->assign = true;
×
274
}
275

276
static int32_t findRowIndex(int32_t start, int32_t num, SColumnInfoData* pCol, const char* tval) {
×
277
  // the data is loaded, not only the block SMA value
278
  for (int32_t i = start; i < num + start; ++i) {
×
279
    char* p = colDataGetData(pCol, i);
×
280
    if (memcmp((void*)tval, p, pCol->info.bytes) == 0) {
×
281
      return i;
×
282
    }
283
  }
284

285
  // if reach here means real data of block SMA is not set in pCtx->input.
286
  return -1;
×
287
}
288

289
static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFunctionCtx* pCtx, SMinmaxResInfo* pBuf,
2,102,933,887✔
290
                            bool isMinFunc) {
291
  if (isMinFunc) {
2,102,933,887✔
292
    switch (pCol->info.type) {
948,478,356✔
293
      case TSDB_DATA_TYPE_BOOL:
17,645,516✔
294
      case TSDB_DATA_TYPE_TINYINT: {
295
        const int8_t* pData = (const int8_t*)pCol->pData;
17,645,516✔
296
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int8_t*)&(pBuf->v), &pBuf->tuplePos)
94,964,482✔
297
        break;
17,645,516✔
298
      }
299

300
      case TSDB_DATA_TYPE_SMALLINT: {
1,925,090✔
301
        const int16_t* pData = (const int16_t*)pCol->pData;
1,925,090✔
302
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int16_t*)&(pBuf->v), &pBuf->tuplePos)
29,754,600✔
303
        break;
1,925,090✔
304
      }
305

306
      case TSDB_DATA_TYPE_INT: {
631,988,043✔
307
        const int32_t* pData = (const int32_t*)pCol->pData;
631,988,043✔
308
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int32_t*)&(pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
309
        break;
631,984,199✔
310
      }
311

312
      case TSDB_DATA_TYPE_BIGINT:
173,350,168✔
313
      case TSDB_DATA_TYPE_TIMESTAMP: {
314
        const int64_t* pData = (const int64_t*)pCol->pData;
173,350,168✔
315
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, (pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
316
        break;
171,708,548✔
317
      }
318

319
      case TSDB_DATA_TYPE_UTINYINT: {
14,323,528✔
320
        const uint8_t* pData = (const uint8_t*)pCol->pData;
14,323,528✔
321
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint8_t*)&(pBuf->v), &pBuf->tuplePos)
568,615,825✔
322
        break;
14,323,528✔
323
      }
324

325
      case TSDB_DATA_TYPE_USMALLINT: {
361,816✔
326
        const uint16_t* pData = (const uint16_t*)pCol->pData;
361,816✔
327
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint16_t*)&(pBuf->v), &pBuf->tuplePos)
19,400,435✔
328
        break;
361,816✔
329
      }
330

331
      case TSDB_DATA_TYPE_UINT: {
462,022✔
332
        const uint32_t* pData = (const uint32_t*)pCol->pData;
462,022✔
333
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint32_t*)&(pBuf->v), &pBuf->tuplePos)
20,367,088✔
334
        break;
462,022✔
335
      }
336

337
      case TSDB_DATA_TYPE_UBIGINT: {
485,488✔
338
        const uint64_t* pData = (const uint64_t*)pCol->pData;
485,488✔
339
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint64_t*)&(pBuf->v), &pBuf->tuplePos)
20,384,580✔
340
        break;
485,488✔
341
      }
342

343
      case TSDB_DATA_TYPE_FLOAT: {
23,270,153✔
344
        const float* pData = (const float*)pCol->pData;
23,270,153✔
345
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(float*)&(pBuf->v), &pBuf->tuplePos)
1,508,173,611✔
346
        break;
23,263,302✔
347
      }
348

349
      case TSDB_DATA_TYPE_DOUBLE: {
49,350,674✔
350
        const double* pData = (const double*)pCol->pData;
49,350,674✔
351
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos)
1,536,536,313✔
352
        break;
49,404,341✔
353
      }
354

355
      case TSDB_DATA_TYPE_VARCHAR:
21,518,073✔
356
      case TSDB_DATA_TYPE_VARBINARY: {
357
        int32_t code = TSDB_CODE_SUCCESS;
21,518,073✔
358
        for (; i < (end); ++i) {
2,147,483,647✔
359
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
360
            continue;
311,376✔
361
          }
362
          char* pLeft = (char*)colDataGetData(pCol, i);
2,147,483,647✔
363
          char* pRight = (char*)pBuf->str;
2,147,483,647✔
364

365
          int32_t ret = compareLenBinaryVal(pLeft, pRight);
2,147,483,647✔
366
          if (ret < 0) {
2,147,483,647✔
367
            memcpy(pBuf->str, pLeft, varDataTLen(pLeft));
474,288✔
368
            if (pCtx->subsidiaries.num > 0) {
474,288✔
369
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
2,324✔
370
              if (TSDB_CODE_SUCCESS != code) {
2,324✔
371
                return code;
×
372
              }
373
            }
374
          }
375
        }
376
        break;
22,836,289✔
377
      }
378
      case TSDB_DATA_TYPE_NCHAR: {
13,383,358✔
379
        int32_t code = TSDB_CODE_SUCCESS;
13,383,358✔
380
        for (; i < (end); ++i) {
2,147,483,647✔
381
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
382
            continue;
155,688✔
383
          }
384
          char* pLeft = (char*)colDataGetData(pCol, i);
2,147,483,647✔
385
          char* pRight = (char*)pBuf->str;
2,147,483,647✔
386

387
          int32_t ret = compareLenPrefixedWStr(pLeft, pRight);
2,147,483,647✔
388
          if (ret < 0) {
2,147,483,647✔
389
            memcpy(pBuf->str, pLeft, varDataTLen(pLeft));
369,141✔
390
            if (pCtx->subsidiaries.num > 0) {
369,141✔
UNCOV
391
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
UNCOV
392
              if (TSDB_CODE_SUCCESS != code) {
×
393
                return code;
×
394
              }
395
            }
396
          }
397
        }
398
        break;
14,598,548✔
399
      }
400
      case TSDB_DATA_TYPE_DECIMAL64: {
337,278✔
401
        const Decimal64*   pData = (const Decimal64*)pCol->pData;
337,278✔
402
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
337,278✔
403
        int32_t            code = 0;
337,278✔
404
        for (; i < end; ++i) {
7,128,540✔
405
          if (colDataIsNull_f(pCol, i)) {
6,791,262✔
406
            continue;
259,521✔
407
          }
408
          if (pOps->gt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
6,531,741✔
409
            pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
24,219✔
410
            if (pCtx->subsidiaries.num > 0) {
24,219✔
411
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
412
              if (TSDB_CODE_SUCCESS != code) return code;
×
413
            }
414
          }
415
        }
416
      } break;
337,278✔
417
      case TSDB_DATA_TYPE_DECIMAL: {
22,410✔
418
        int32_t            code = 0;
22,410✔
419
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
22,410✔
420
        const Decimal128*  pData = (const Decimal128*)pCol->pData;
22,410✔
421
        for (; i < end; ++i) {
17,954,892✔
422
          if (colDataIsNull_f(pCol, i)) {
17,932,482✔
423
            continue;
274,896✔
424
          }
425
          if (pOps->gt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
17,657,586✔
426
            memcpy(pBuf->dec, pData + i, pCol->info.bytes);
29,133✔
427
            if (pCtx->subsidiaries.num > 0) {
29,133✔
428
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
429
              if (TSDB_CODE_SUCCESS != code) return code;
×
430
            }
431
          }
432
        }
433
      } break;
22,410✔
434
    }
435
  } else {
436
    switch (pCol->info.type) {
1,154,455,531✔
437
      case TSDB_DATA_TYPE_BOOL:
9,665,618✔
438
      case TSDB_DATA_TYPE_TINYINT: {
439
        const int8_t* pData = (const int8_t*)pCol->pData;
9,665,618✔
440
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int8_t*)&(pBuf->v), &pBuf->tuplePos)
71,720,994✔
441
        break;
9,665,618✔
442
      }
443

444
      case TSDB_DATA_TYPE_SMALLINT: {
48,633,178✔
445
        const int16_t* pData = (const int16_t*)pCol->pData;
48,633,178✔
446
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int16_t*)&(pBuf->v), &pBuf->tuplePos)
120,452,630✔
447
        break;
48,652,369✔
448
      }
449

450
      case TSDB_DATA_TYPE_INT: {
264,911,987✔
451
        const int32_t* pData = (const int32_t*)pCol->pData;
264,911,987✔
452
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int32_t*)&(pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
453
        break;
264,859,435✔
454
      }
455

456
      case TSDB_DATA_TYPE_BIGINT: 
23,702,474✔
457
      case TSDB_DATA_TYPE_TIMESTAMP: {
458
        const int64_t* pData = (const int64_t*)pCol->pData;
23,702,474✔
459
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, (pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
460
        break;
22,463,159✔
461
      }
462

463
      case TSDB_DATA_TYPE_UTINYINT: {
405,860✔
464
        const uint8_t* pData = (const uint8_t*)pCol->pData;
405,860✔
465
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint8_t*)&(pBuf->v), &pBuf->tuplePos)
19,487,727✔
466
        break;
405,860✔
467
      }
468

469
      case TSDB_DATA_TYPE_USMALLINT: {
17,463,954✔
470
        const uint16_t* pData = (const uint16_t*)pCol->pData;
17,463,954✔
471
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint16_t*)&(pBuf->v), &pBuf->tuplePos)
692,183,555✔
472
        break;
17,463,954✔
473
      }
474

475
      case TSDB_DATA_TYPE_UINT: {
657,247,439✔
476
        const uint32_t* pData = (const uint32_t*)pCol->pData;
657,247,439✔
477
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint32_t*)&(pBuf->v), &pBuf->tuplePos)
2,098,883,362✔
478
        break;
657,247,439✔
479
      }
480

481
      case TSDB_DATA_TYPE_UBIGINT: {
486,712✔
482
        const uint64_t* pData = (const uint64_t*)pCol->pData;
486,712✔
483
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint64_t*)&(pBuf->v), &pBuf->tuplePos)
21,012,548✔
484
        break;
486,712✔
485
      }
486

487
      case TSDB_DATA_TYPE_FLOAT: {
71,415,024✔
488
        const float* pData = (const float*)pCol->pData;
71,415,024✔
489
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(float*)&(pBuf->v), &pBuf->tuplePos)
1,590,802,505✔
490
        break;
71,325,451✔
491
      }
492

493
      case TSDB_DATA_TYPE_DOUBLE: {
25,236,443✔
494
        const double* pData = (const double*)pCol->pData;
25,236,443✔
495
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos)
1,477,346,875✔
496
        break;
25,358,827✔
497
      }
498
      case TSDB_DATA_TYPE_DECIMAL64: {
320,071✔
499
        const Decimal64* pData = (const Decimal64*)pCol->pData;
320,071✔
500
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
320,071✔
501
        int32_t code = 0;
320,071✔
502
        for (; i < end; ++i) {
10,637,640✔
503
          if (colDataIsNull_f(pCol, i)) {
10,317,569✔
504
            continue;
259,521✔
505
          }
506
          if (pOps->lt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
10,058,328✔
507
            pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
319,651✔
508
            if (pCtx->subsidiaries.num > 0) {
319,651✔
509
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
510
              if (TSDB_CODE_SUCCESS != code) return code;
×
511
            }
512
          }
513
        }
514
      } break;
320,071✔
515
      case TSDB_DATA_TYPE_DECIMAL: {
36,691✔
516
        int32_t            code = 0;
36,691✔
517
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
36,691✔
518
        const Decimal128*  pData = (const Decimal128*)pCol->pData;
36,691✔
519
        for (; i < end; ++i) {
21,565,390✔
520
          if (colDataIsNull_f(pCol, i)) {
21,528,699✔
521
            continue;
274,896✔
522
          }
523
          if (pOps->lt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
21,253,803✔
524
            memcpy(pBuf->dec, pData + i, pCol->info.bytes);
26,091✔
525
            if (pCtx->subsidiaries.num > 0) {
26,091✔
526
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
527
              if (TSDB_CODE_SUCCESS != code) return code;
×
528
            }
529
          }
530
        }
531
      } break;
36,691✔
532

533
      case TSDB_DATA_TYPE_VARCHAR:
21,516,293✔
534
      case TSDB_DATA_TYPE_VARBINARY: {
535
        int32_t code = TSDB_CODE_SUCCESS;
21,516,293✔
536
        for (; i < (end); ++i) {
2,147,483,647✔
537
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
538
            continue;
311,376✔
539
          }
540
          char* pLeft = (char*)colDataGetData(pCol, i);
2,147,483,647✔
541
          char* pRight = (char*)pBuf->str;
2,147,483,647✔
542

543
          int32_t ret = compareLenBinaryVal(pLeft, pRight);
2,147,483,647✔
544
          if (ret > 0) {
2,147,483,647✔
545
            memcpy(pBuf->str, pLeft, varDataTLen(pLeft));
1,313,001✔
546
            if (pCtx->subsidiaries.num > 0) {
1,313,001✔
547
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
8,715✔
548
              if (TSDB_CODE_SUCCESS != code) {
8,715✔
549
                return code;
×
550
              }
551
            }
552
          }
553
        }
554
        break;
21,295,602✔
555
      }
556

557
      case TSDB_DATA_TYPE_NCHAR: {
13,522,698✔
558
        int32_t code = TSDB_CODE_SUCCESS;
13,522,698✔
559
        for (; i < (end); ++i) {
2,147,483,647✔
560
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
561
            continue;
155,688✔
562
          }
563
          char* pLeft = (char*)colDataGetData(pCol, i);
2,147,483,647✔
564
          char* pRight = (char*)pBuf->str;
2,147,483,647✔
565

566
          int32_t ret = compareLenPrefixedWStr(pLeft, pRight);
2,147,483,647✔
567
          if (ret > 0) {
2,147,483,647✔
568
            memcpy(pBuf->str, pLeft, varDataTLen(pLeft));
823,164✔
569
            if (pCtx->subsidiaries.num > 0) {
823,164✔
570
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
4,067✔
571
              if (TSDB_CODE_SUCCESS != code) {
4,067✔
572
                return code;
×
573
              }
574
            }
575
          }
576
        }
577
        break;
13,472,799✔
578
      }
579
    }
580
  }
581
  return TSDB_CODE_SUCCESS;
2,102,927,399✔
582
}
583

584
static int32_t saveRelatedTupleTag(SqlFunctionCtx* pCtx, SInputColumnInfoData* pInput, void* tval) {
1,347,740✔
585
  SColumnInfoData* pCol = pInput->pData[0];
1,347,740✔
586

587
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
1,347,740✔
588
  SMinmaxResInfo*      pBuf = GET_ROWCELL_INTERBUF(pResInfo);
1,347,740✔
589

590
  int32_t code = TSDB_CODE_SUCCESS;
1,347,740✔
591
  if (pCtx->subsidiaries.num > 0) {
1,347,740✔
592
    code = saveTupleData(pCtx, 0, pCtx->pSrcBlock, &pBuf->tuplePos);
×
593
  }
594
  return code;
1,347,740✔
595
}
596

597
int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems) {
2,147,483,647✔
598
  int32_t numOfElems = 0;
2,147,483,647✔
599
  int32_t code = TSDB_CODE_SUCCESS;
2,147,483,647✔
600

601
  SInputColumnInfoData* pInput = &pCtx->input;
2,147,483,647✔
602
  SColumnDataAgg*       pAgg = pInput->pColumnDataAgg[0];
2,147,483,647✔
603

604
  SColumnInfoData* pCol = pInput->pData[0];
2,147,483,647✔
605
  int32_t          type = pCol->info.type;
2,147,483,647✔
606

607
  SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
2,147,483,647✔
608
  SMinmaxResInfo*      pBuf = GET_ROWCELL_INTERBUF(pResInfo);
2,147,483,647✔
609
  pBuf->type = type;
2,147,483,647✔
610

611
  if (IS_NULL_TYPE(type)) {
2,147,483,647✔
612
    goto _over;
359,144✔
613
  }
614

615
  // data in current data block are qualified to the query
616
  if (pInput->colDataSMAIsSet && !IS_STR_DATA_TYPE(type)) {
2,147,483,647✔
617
    numOfElems = pInput->numOfRows - pAgg->numOfNull;
5,738,433✔
618
    if (numOfElems == 0) {
5,738,433✔
619
      goto _over;
1,592✔
620
    }
621

622
    int16_t index = 0;
5,736,841✔
623
    void*   tval = NULL;
5,736,841✔
624
    if (IS_DECIMAL_TYPE(type)) {
5,736,841✔
625
      tval = isMinFunc ? pInput->pColumnDataAgg[0]->decimal128Min : pInput->pColumnDataAgg[0]->decimal128Max;
17,928✔
626
    } else {
627
      tval = (isMinFunc) ? &pInput->pColumnDataAgg[0]->min : &pInput->pColumnDataAgg[0]->max;
5,718,913✔
628
    }
629

630
    if (!pBuf->assign) {
5,736,841✔
631
      if (type == TSDB_DATA_TYPE_FLOAT) {
99,110✔
632
        GET_FLOAT_VAL(&pBuf->v) = GET_DOUBLE_VAL(tval);
796✔
633
      } else if (type == TSDB_DATA_TYPE_DECIMAL) {
98,314✔
634
        memcpy(pBuf->dec, tval, pCol->info.bytes);
8,964✔
635
      } else {
636
        pBuf->v = GET_INT64_VAL(tval);
89,350✔
637
      }
638

639
      code = saveRelatedTupleTag(pCtx, pInput, tval);
99,110✔
640
    } else {
641
      if (IS_SIGNED_NUMERIC_TYPE(type) || TSDB_DATA_TYPE_BOOL == type || TSDB_DATA_TYPE_TIMESTAMP == type) {
8,507,709✔
642
        int64_t prev = 0;
2,869,978✔
643
        GET_TYPED_DATA(prev, int64_t, type, &pBuf->v, 0);
2,869,978✔
644

645
        int64_t val = GET_INT64_VAL(tval);
2,869,978✔
646
        if ((prev < val) ^ isMinFunc) {
2,869,978✔
647
          GET_INT64_VAL(&pBuf->v) = val;
526,796✔
648
          code = saveRelatedTupleTag(pCtx, pInput, tval);
526,796✔
649
        }
650
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
5,529,530✔
651
        uint64_t prev = 0;
2,761,777✔
652
        GET_TYPED_DATA(prev, uint64_t, type, &pBuf->v, 0);
2,761,777✔
653

654
        uint64_t val = GET_UINT64_VAL(tval);
2,761,777✔
655
        if ((prev < val) ^ isMinFunc) {
2,761,777✔
656
          GET_UINT64_VAL(&pBuf->v) = val;
718,099✔
657
          code = saveRelatedTupleTag(pCtx, pInput, tval);
718,099✔
658
        }
659
      } else if (type == TSDB_DATA_TYPE_DOUBLE) {
5,976✔
660
        double prev = 0;
×
661
        GET_TYPED_DATA(prev, double, type, &pBuf->v, 0);
×
662

663
        double val = GET_DOUBLE_VAL(tval);
×
664
        if ((prev < val) ^ isMinFunc) {
×
665
          GET_DOUBLE_VAL(&pBuf->v) = val;
×
666
          code = saveRelatedTupleTag(pCtx, pInput, tval);
×
667
        }
668
      } else if (type == TSDB_DATA_TYPE_FLOAT) {
5,976✔
669
        float prev = 0;
×
670
        GET_TYPED_DATA(prev, float, type, &pBuf->v, 0);
×
671

672
        float val = GET_DOUBLE_VAL(tval);
×
673
        if ((prev < val) ^ isMinFunc) {
×
674
          GET_FLOAT_VAL(&pBuf->v) = val;
×
675
          code = saveRelatedTupleTag(pCtx, pInput, tval);
×
676
        }
677
      } else if (type == TSDB_DATA_TYPE_DECIMAL64) {
5,976✔
678
        const SDecimalOps* pOps = getDecimalOps(type);
1,494✔
679
        if (pOps->lt(&pBuf->v, tval, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) {
1,494✔
680
          DECIMAL64_SET_VALUE((Decimal64*)&pBuf->v, *(int64_t*)tval);
1,494✔
681
          code =saveRelatedTupleTag(pCtx, pInput, tval);
1,494✔
682
        }
683
      } else if (type == TSDB_DATA_TYPE_DECIMAL) {
4,482✔
684
        const SDecimalOps* pOps = getDecimalOps(type);
4,482✔
685
        if (pOps->lt(pBuf->dec, tval, DECIMAL_WORD_NUM(Decimal128)) ^ isMinFunc) {
4,482✔
686
          DECIMAL128_CLONE((Decimal128*)pBuf->dec, (Decimal128*)tval);
2,241✔
687
          code =saveRelatedTupleTag(pCtx, pInput, tval);
2,241✔
688
        }
689
      }
690
    }
691

692
    numOfElems = 1;
5,736,841✔
693
    pBuf->assign = true;
5,736,841✔
694
    goto _over;
5,736,841✔
695
  }
696

697
  int32_t start = pInput->startRowIndex;
2,147,483,647✔
698
  int32_t numOfRows = pInput->numOfRows;
2,147,483,647✔
699
  int32_t end = start + numOfRows;
2,147,483,647✔
700

701
  // clang-format off
702
  int32_t threshold[] = {
2,147,483,647✔
703
      //NULL,    BOOL,      TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE, VARCHAR,   TIMESTAMP, NCHAR,
704
      INT32_MAX, 32,        32,      16,       8,   4,      8,     4,      INT32_MAX, 4,         INT32_MAX,
705
      // UTINYINT,USMALLINT, UINT, UBIGINT,   JSON,      VARBINARY, DECIMAL,   BLOB,      MEDIUMBLOB, BINARY,   Decimal64
706
      32,         16,        8,    4,         INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX, INT32_MAX,  INT32_MAX, INT32_MAX,
707
  };
708
  // clang-format on
709

710
  if (pCol->hasNull || numOfRows < threshold[pCol->info.type] || pCtx->subsidiaries.num > 0) {
2,147,483,647✔
711
    int32_t i = findFirstValPosition(pCol, start, numOfRows, IS_STR_DATA_TYPE(type));
2,147,483,647✔
712

713
    if ((i < end) && (!pBuf->assign)) {
2,147,483,647✔
714
      char* p = pCol->pData + pCol->info.bytes * i;
1,756,943,071✔
715

716
      switch (type) {
1,756,941,514✔
717
        case TSDB_DATA_TYPE_DOUBLE:
181,631,405✔
718
        case TSDB_DATA_TYPE_UBIGINT:
719
        case TSDB_DATA_TYPE_BIGINT:
720
        case TSDB_DATA_TYPE_TIMESTAMP:
721
          pBuf->v = *(int64_t*)p;
181,631,405✔
722
          break;
181,631,391✔
723
        case TSDB_DATA_TYPE_UINT:
1,491,844,842✔
724
        case TSDB_DATA_TYPE_INT:
725
          pBuf->v = *(int32_t*)p;
1,491,844,842✔
726
          break;
1,491,847,688✔
727
        case TSDB_DATA_TYPE_USMALLINT:
19,263,495✔
728
        case TSDB_DATA_TYPE_SMALLINT:
729
          pBuf->v = *(int16_t*)p;
19,263,495✔
730
          break;
19,264,170✔
731
        case TSDB_DATA_TYPE_BOOL:
36,264,520✔
732
        case TSDB_DATA_TYPE_UTINYINT:
733
        case TSDB_DATA_TYPE_TINYINT:
734
          pBuf->v = *(int8_t*)p;
36,264,520✔
735
          break;
36,264,520✔
736
        case TSDB_DATA_TYPE_FLOAT: {
22,567,982✔
737
          *(float*)&pBuf->v = *(float*)p;
22,567,982✔
738
          break;
22,567,982✔
739
        }
740
        case TSDB_DATA_TYPE_VARCHAR:
4,702,728✔
741
        case TSDB_DATA_TYPE_VARBINARY:
742
        case TSDB_DATA_TYPE_NCHAR: {
743
          pBuf->str = taosMemoryMalloc(pCol->info.bytes);
4,702,728✔
744
          if (pBuf->str == NULL) {
4,703,169✔
745
            return terrno;
×
746
          }
747
          (void)memcpy(pBuf->str, colDataGetData(pCol, i), varDataTLen(colDataGetData(pCol, i)));
4,702,147✔
748
          break;
4,703,610✔
749
        }
750
        case TSDB_DATA_TYPE_DECIMAL64:
644,347✔
751
          *(int64_t*)&pBuf->v = *(int64_t*)p;
644,347✔
752
          break;
644,347✔
753
        case TSDB_DATA_TYPE_DECIMAL:
22,195✔
754
          (void)memcpy(pBuf->dec, p, pCol->info.bytes);
22,195✔
755
          break;
22,195✔
756
        default:
×
757
          (void)memcpy(&pBuf->v, p, pCol->info.bytes);
×
758
          break;
×
759
      }
760

761
      if (pCtx->subsidiaries.num > 0) {
1,756,945,903✔
762
        code = saveTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
1,927,672✔
763
        if (code != TSDB_CODE_SUCCESS) {
1,926,850✔
764
          return code;
×
765
        }
766
      }
767
      pBuf->assign = true;
1,756,944,780✔
768
      numOfElems = 1;
1,756,935,687✔
769
    }
770

771
    if (i >= end) {
2,147,483,647✔
772
      goto _over;
2,147,483,647✔
773
    }
774

775
    code = doExtractVal(pCol, i, end, pCtx, pBuf, isMinFunc);
2,102,876,147✔
776
  } else {
777
    numOfElems = numOfRows;
86,005,923✔
778

779
    switch (type) {
86,005,923✔
780
      case TSDB_DATA_TYPE_BOOL:
6,310,666✔
781
      case TSDB_DATA_TYPE_TINYINT: {
782
        handleInt8Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
6,310,666✔
783
        break;
6,310,666✔
784
      }
785
      case TSDB_DATA_TYPE_SMALLINT: {
6,856,652✔
786
        handleInt16Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
6,856,652✔
787
        break;
6,856,652✔
788
      }
789
      case TSDB_DATA_TYPE_INT: {
26,777,143✔
790
        handleInt32Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
26,777,143✔
791
        break;
26,763,855✔
792
      }
793
      case TSDB_DATA_TYPE_BIGINT:
8,027,438✔
794
      case TSDB_DATA_TYPE_TIMESTAMP: {
795
        handleInt64Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
8,027,438✔
796
        break;
8,027,438✔
797
      }
798
      case TSDB_DATA_TYPE_UTINYINT: {
7,518,912✔
799
        handleInt8Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
7,518,912✔
800
        break;
7,518,912✔
801
      }
802
      case TSDB_DATA_TYPE_USMALLINT: {
5,250,212✔
803
        handleInt16Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
5,250,212✔
804
        break;
5,250,212✔
805
      }
806
      case TSDB_DATA_TYPE_UINT: {
6,621,527✔
807
        handleInt32Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
6,621,527✔
808
        break;
6,620,962✔
809
      }
810
      case TSDB_DATA_TYPE_UBIGINT: {
5,140,742✔
811
        handleInt64Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
5,140,742✔
812
        break;
5,140,742✔
813
      }
814
      case TSDB_DATA_TYPE_FLOAT: {
8,233,445✔
815
        handleFloatCol(pCol, start, numOfRows, pBuf, isMinFunc);
8,233,445✔
816
        break;
8,233,445✔
817
      }
818
      case TSDB_DATA_TYPE_DOUBLE: {
5,278,948✔
819
        handleDoubleCol(pCol, start, numOfRows, pBuf, isMinFunc);
5,278,948✔
820
        break;
5,278,948✔
821
      }
822
    }
823

824
    pBuf->assign = true;
85,992,070✔
825
  }
826

827
_over:
2,147,483,647✔
828
  if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pBuf->nullTupleSaved) {
2,147,483,647✔
829
    code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pBuf->nullTuplePos);
1,343,089✔
830
    if (code != TSDB_CODE_SUCCESS) {
1,342,678✔
831
      return code;
×
832
    }
833

834
    pBuf->nullTupleSaved = true;
1,342,678✔
835
  }
836

837
  *nElems = numOfElems;
2,147,483,647✔
838
  return code;
2,147,483,647✔
839
}
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