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

taosdata / TDengine / #5034

24 Apr 2026 11:25AM UTC coverage: 73.058%. Remained the same
#5034

push

travis-ci

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

merge: from main to 3.0 branch[manual-only]

1336 of 1975 new or added lines in 48 files covered. (67.65%)

14149 existing lines in 164 files now uncovered.

275896 of 377640 relevant lines covered (73.06%)

132944440.29 hits per line

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

80.96
/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,
14,304,113✔
87
                          bool signVal) {
88
  if (!pBuf->assign) {
14,304,113✔
89
    pBuf->v = ((const int8_t*)data)[start];
280,477✔
90
  }
91

92
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int8_t) >= M256_BYTES) {
14,304,113✔
93
    int32_t code = i8VectorCmpAVX2(((char*)data) + start * sizeof(int8_t), numOfRows, isMinFunc, signVal, &pBuf->v);
14,304,113✔
94
    if (code == TSDB_CODE_SUCCESS) {
14,303,469✔
95
      pBuf->assign = true;
14,303,469✔
96
      return;
14,303,469✔
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,520,469✔
124
                           bool signVal) {
125
  if (!pBuf->assign) {
12,520,469✔
126
    pBuf->v = ((const int16_t*)data)[start];
358,437✔
127
  }
128

129
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int16_t) >= M256_BYTES) {
12,520,469✔
130
    int32_t code = i16VectorCmpAVX2(((char*)data) + start * sizeof(int16_t), numOfRows, isMinFunc, signVal, &pBuf->v);
12,520,469✔
131
    if (code == TSDB_CODE_SUCCESS) {
12,520,469✔
132
      pBuf->assign = true;
12,520,469✔
133
      return;
12,520,469✔
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,
34,347,731✔
161
                           bool signVal) {
162
  if (!pBuf->assign) {
34,347,731✔
163
    pBuf->v = ((const int32_t*)data)[start];
16,640,256✔
164
  }
165

166
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(int32_t) >= M256_BYTES) {
34,352,506✔
167
    int32_t code = i32VectorCmpAVX2(((char*)data) + start * sizeof(int32_t), numOfRows, isMinFunc, signVal, &pBuf->v);
34,345,678✔
168
    if (code == TSDB_CODE_SUCCESS) {
34,326,050✔
169
      pBuf->assign = true;
34,332,878✔
170
      return;
34,334,244✔
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,865,206✔
198
                           bool signVal) {
199
  if (!pBuf->assign) {
13,865,206✔
200
    pBuf->v = ((const int64_t*)data)[start];
521,165✔
201
  }
202

203
  if (signVal) {
13,865,850✔
204
    const int64_t* p = (const int64_t*)data;
8,548,104✔
205
    int64_t*       v = &pBuf->v;
8,548,104✔
206

207
    if (isMinFunc) {
8,548,104✔
208
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
1,405,601,991✔
209
    } else {
210
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
1,377,319,407✔
211
    }
212
  } else {
213
    const uint64_t* p = (const uint64_t*)data;
5,317,746✔
214
    uint64_t*       v = (uint64_t*)&pBuf->v;
5,317,746✔
215

216
    if (isMinFunc) {
5,317,746✔
217
      __COMPARE_EXTRACT_MIN(start, start + numOfRows, *v, p);
523,524,088✔
218
    } else {
219
      __COMPARE_EXTRACT_MAX(start, start + numOfRows, *v, p);
523,524,022✔
220
    }
221
  }
222

223
  pBuf->assign = true;
13,865,850✔
224
}
13,865,206✔
225

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

234
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(float) >= M256_BYTES) {
8,523,445✔
235
    int32_t code = floatVectorCmpAVX2(pData + start, numOfRows, isMinFunc, val);
8,523,445✔
236
    if (code == TSDB_CODE_SUCCESS) {
8,523,445✔
237
      pBuf->assign = true;
8,523,445✔
238
      return;
8,523,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,461,318✔
252
                            bool isMinFunc) {
253
  double* pData = (double*)pCol->pData;
5,461,318✔
254
  double* val = (double*)&pBuf->v;
5,461,318✔
255
  if (!pBuf->assign) {
5,461,318✔
256
    *val = pData[start];
264,942✔
257
  }
258

259
  if (tsAVX2Supported && tsSIMDEnable && numOfRows * sizeof(double) >= M256_BYTES) {
5,461,318✔
260
    int32_t code = doubleVectorCmpAVX2(pData + start, numOfRows, isMinFunc, val);
5,461,318✔
261
    if (code == TSDB_CODE_SUCCESS) {
5,461,318✔
262
      pBuf->assign = true;
5,461,318✔
263
      return;
5,461,318✔
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,033,362,798✔
290
                            bool isMinFunc) {
291
  if (isMinFunc) {
2,033,362,798✔
292
    switch (pCol->info.type) {
913,591,170✔
293
      case TSDB_DATA_TYPE_BOOL:
19,423,476✔
294
      case TSDB_DATA_TYPE_TINYINT: {
295
        const int8_t* pData = (const int8_t*)pCol->pData;
19,423,476✔
296
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int8_t*)&(pBuf->v), &pBuf->tuplePos)
108,063,327✔
297
        break;
19,423,476✔
298
      }
299

300
      case TSDB_DATA_TYPE_SMALLINT: {
1,842,414✔
301
        const int16_t* pData = (const int16_t*)pCol->pData;
1,842,414✔
302
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int16_t*)&(pBuf->v), &pBuf->tuplePos)
40,436,185✔
303
        break;
1,843,108✔
304
      }
305

306
      case TSDB_DATA_TYPE_INT: {
584,144,435✔
307
        const int32_t* pData = (const int32_t*)pCol->pData;
584,144,435✔
308
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(int32_t*)&(pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
309
        break;
584,134,362✔
310
      }
311

312
      case TSDB_DATA_TYPE_BIGINT:
172,480,212✔
313
      case TSDB_DATA_TYPE_TIMESTAMP: {
314
        const int64_t* pData = (const int64_t*)pCol->pData;
172,480,212✔
315
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, (pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
316
        break;
185,705,892✔
317
      }
318

319
      case TSDB_DATA_TYPE_UTINYINT: {
10,517,332✔
320
        const uint8_t* pData = (const uint8_t*)pCol->pData;
10,517,332✔
321
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint8_t*)&(pBuf->v), &pBuf->tuplePos)
418,373,295✔
322
        break;
10,517,332✔
323
      }
324

325
      case TSDB_DATA_TYPE_USMALLINT: {
384,530✔
326
        const uint16_t* pData = (const uint16_t*)pCol->pData;
384,530✔
327
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint16_t*)&(pBuf->v), &pBuf->tuplePos)
20,277,676✔
328
        break;
384,530✔
329
      }
330

331
      case TSDB_DATA_TYPE_UINT: {
489,158✔
332
        const uint32_t* pData = (const uint32_t*)pCol->pData;
489,158✔
333
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint32_t*)&(pBuf->v), &pBuf->tuplePos)
21,287,885✔
334
        break;
489,158✔
335
      }
336

337
      case TSDB_DATA_TYPE_UBIGINT: {
511,687✔
338
        const uint64_t* pData = (const uint64_t*)pCol->pData;
511,687✔
339
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(uint64_t*)&(pBuf->v), &pBuf->tuplePos)
21,303,507✔
340
        break;
511,687✔
341
      }
342

343
      case TSDB_DATA_TYPE_FLOAT: {
27,514,193✔
344
        const float* pData = (const float*)pCol->pData;
27,514,193✔
345
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(float*)&(pBuf->v), &pBuf->tuplePos)
1,531,155,911✔
346
        break;
27,500,025✔
347
      }
348

349
      case TSDB_DATA_TYPE_DOUBLE: {
59,751,900✔
350
        const double* pData = (const double*)pCol->pData;
59,751,900✔
351
        __COMPARE_ACQUIRED_MIN(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos)
1,617,558,252✔
352
        break;
59,742,600✔
353
      }
354

355
      case TSDB_DATA_TYPE_VARCHAR:
22,278,800✔
356
      case TSDB_DATA_TYPE_VARBINARY: {
357
        int32_t code = TSDB_CODE_SUCCESS;
22,278,800✔
358
        for (; i < (end); ++i) {
2,147,483,647✔
359
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
360
            continue;
332,280✔
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));
492,632✔
368
            if (pCtx->subsidiaries.num > 0) {
492,632✔
369
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
599✔
370
              if (TSDB_CODE_SUCCESS != code) {
599✔
371
                return code;
×
372
              }
373
            }
374
          }
375
        }
376
        break;
22,789,612✔
377
      }
378
      case TSDB_DATA_TYPE_NCHAR: {
13,852,988✔
379
        int32_t code = TSDB_CODE_SUCCESS;
13,852,988✔
380
        for (; i < (end); ++i) {
2,147,483,647✔
381
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
382
            continue;
166,140✔
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));
377,267✔
390
            if (pCtx->subsidiaries.num > 0) {
377,267✔
391
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
599✔
392
              if (TSDB_CODE_SUCCESS != code) {
599✔
393
                return code;
×
394
              }
395
            }
396
          }
397
        }
398
        break;
13,998,448✔
399
      }
400
      case TSDB_DATA_TYPE_DECIMAL64: {
361,903✔
401
        const Decimal64*   pData = (const Decimal64*)pCol->pData;
361,903✔
402
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
361,903✔
403
        int32_t            code = 0;
361,903✔
404
        for (; i < end; ++i) {
9,724,394✔
405
          if (colDataIsNull_f(pCol, i)) {
9,362,491✔
406
            continue;
299,696✔
407
          }
408
          if (pOps->gt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
9,062,795✔
409
            pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
27,275✔
410
            if (pCtx->subsidiaries.num > 0) {
27,275✔
411
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
412
              if (TSDB_CODE_SUCCESS != code) return code;
×
413
            }
414
          }
415
        }
416
      } break;
361,903✔
417
      case TSDB_DATA_TYPE_DECIMAL: {
31,410✔
418
        int32_t            code = 0;
31,410✔
419
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
31,410✔
420
        const Decimal128*  pData = (const Decimal128*)pCol->pData;
31,410✔
421
        for (; i < end; ++i) {
25,515,948✔
422
          if (colDataIsNull_f(pCol, i)) {
25,484,538✔
423
            continue;
421,512✔
424
          }
425
          if (pOps->gt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
25,063,026✔
426
            memcpy(pBuf->dec, pData + i, pCol->info.bytes);
57,779✔
427
            if (pCtx->subsidiaries.num > 0) {
57,779✔
428
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
429
              if (TSDB_CODE_SUCCESS != code) return code;
×
430
            }
431
          }
432
        }
433
      } break;
31,410✔
434
    }
435
  } else {
436
    switch (pCol->info.type) {
1,119,771,628✔
437
      case TSDB_DATA_TYPE_BOOL:
24,354,005✔
438
      case TSDB_DATA_TYPE_TINYINT: {
439
        const int8_t* pData = (const int8_t*)pCol->pData;
24,354,005✔
440
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int8_t*)&(pBuf->v), &pBuf->tuplePos)
111,740,379✔
441
        break;
24,354,005✔
442
      }
443

444
      case TSDB_DATA_TYPE_SMALLINT: {
51,949,077✔
445
        const int16_t* pData = (const int16_t*)pCol->pData;
51,949,077✔
446
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int16_t*)&(pBuf->v), &pBuf->tuplePos)
128,163,503✔
447
        break;
51,900,501✔
448
      }
449

450
      case TSDB_DATA_TYPE_INT: {
281,526,146✔
451
        const int32_t* pData = (const int32_t*)pCol->pData;
281,526,146✔
452
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(int32_t*)&(pBuf->v), &pBuf->tuplePos)
2,147,483,647✔
453
        break;
281,570,625✔
454
      }
455

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

463
      case TSDB_DATA_TYPE_UTINYINT: {
430,075✔
464
        const uint8_t* pData = (const uint8_t*)pCol->pData;
430,075✔
465
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint8_t*)&(pBuf->v), &pBuf->tuplePos)
20,367,897✔
466
        break;
430,075✔
467
      }
468

469
      case TSDB_DATA_TYPE_USMALLINT: {
12,779,866✔
470
        const uint16_t* pData = (const uint16_t*)pCol->pData;
12,779,866✔
471
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint16_t*)&(pBuf->v), &pBuf->tuplePos)
507,907,512✔
472
        break;
12,779,866✔
473
      }
474

475
      case TSDB_DATA_TYPE_UINT: {
585,545,613✔
476
        const uint32_t* pData = (const uint32_t*)pCol->pData;
585,545,613✔
477
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(uint32_t*)&(pBuf->v), &pBuf->tuplePos)
1,801,327,240✔
478
        break;
585,545,613✔
479
      }
480

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

487
      case TSDB_DATA_TYPE_FLOAT: {
80,832,417✔
488
        const float* pData = (const float*)pCol->pData;
80,832,417✔
489
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(float*)&(pBuf->v), &pBuf->tuplePos)
1,651,018,562✔
490
        break;
80,533,657✔
491
      }
492

493
      case TSDB_DATA_TYPE_DOUBLE: {
23,828,980✔
494
        const double* pData = (const double*)pCol->pData;
23,828,980✔
495
        __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos)
1,511,362,229✔
496
        break;
23,818,676✔
497
      }
498
      case TSDB_DATA_TYPE_DECIMAL64: {
344,192✔
499
        const Decimal64* pData = (const Decimal64*)pCol->pData;
344,192✔
500
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
344,192✔
501
        int32_t code = 0;
344,612✔
502
        for (; i < end; ++i) {
13,218,094✔
503
          if (colDataIsNull_f(pCol, i)) {
12,873,902✔
504
            continue;
299,696✔
505
          }
506
          if (pOps->lt(&pBuf->v, &pData[i], DECIMAL_WORD_NUM(Decimal64))) {
12,575,536✔
507
            pBuf->v = DECIMAL64_GET_VALUE(&pData[i]);
359,688✔
508
            if (pCtx->subsidiaries.num > 0) {
359,688✔
509
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
510
              if (TSDB_CODE_SUCCESS != code) return code;
×
511
            }
512
          }
513
        }
514
      } break;
344,192✔
515
      case TSDB_DATA_TYPE_DECIMAL: {
47,349✔
516
        int32_t            code = 0;
47,349✔
517
        const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
47,349✔
518
        const Decimal128*  pData = (const Decimal128*)pCol->pData;
47,349✔
519
        for (; i < end; ++i) {
29,132,721✔
520
          if (colDataIsNull_f(pCol, i)) {
29,085,372✔
521
            continue;
421,512✔
522
          }
523
          if (pOps->lt(pBuf->dec, &pData[i], DECIMAL_WORD_NUM(Decimal128))) {
28,663,860✔
524
            memcpy(pBuf->dec, pData + i, pCol->info.bytes);
67,222✔
525
            if (pCtx->subsidiaries.num > 0) {
67,222✔
526
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
×
527
              if (TSDB_CODE_SUCCESS != code) return code;
×
528
            }
529
          }
530
        }
531
      } break;
47,349✔
532

533
      case TSDB_DATA_TYPE_VARCHAR:
22,276,284✔
534
      case TSDB_DATA_TYPE_VARBINARY: {
535
        int32_t code = TSDB_CODE_SUCCESS;
22,276,284✔
536
        for (; i < (end); ++i) {
2,147,483,647✔
537
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
538
            continue;
332,280✔
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,379,411✔
546
            if (pCtx->subsidiaries.num > 0) {
1,379,411✔
547
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
8,985✔
548
              if (TSDB_CODE_SUCCESS != code) {
8,985✔
549
                return code;
×
550
              }
551
            }
552
          }
553
        }
554
        break;
22,220,508✔
555
      }
556

557
      case TSDB_DATA_TYPE_NCHAR: {
13,997,360✔
558
        int32_t code = TSDB_CODE_SUCCESS;
13,997,360✔
559
        for (; i < (end); ++i) {
2,147,483,647✔
560
          if (colDataIsNull_var(pCol, i)) {
2,147,483,647✔
561
            continue;
166,140✔
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));
860,034✔
569
            if (pCtx->subsidiaries.num > 0) {
860,034✔
570
              code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
4,792✔
571
              if (TSDB_CODE_SUCCESS != code) {
4,792✔
572
                return code;
×
573
              }
574
            }
575
          }
576
        }
577
        break;
13,947,187✔
578
      }
579
    }
580
  }
581
  return TSDB_CODE_SUCCESS;
2,034,628,482✔
582
}
583

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

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

590
  int32_t code = TSDB_CODE_SUCCESS;
1,375,895✔
591
  if (pCtx->subsidiaries.num > 0) {
1,375,895✔
592
    code = saveTupleData(pCtx, 0, pCtx->pSrcBlock, &pBuf->tuplePos);
×
593
  }
594
  return code;
1,376,547✔
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;
370,766✔
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,960,095✔
618
    if (numOfElems == 0) {
5,959,443✔
619
      goto _over;
1,630✔
620
    }
621

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

630
    if (!pBuf->assign) {
5,959,769✔
631
      if (type == TSDB_DATA_TYPE_FLOAT) {
80,956✔
632
        GET_FLOAT_VAL(&pBuf->v) = GET_DOUBLE_VAL(tval);
815✔
633
      } else if (type == TSDB_DATA_TYPE_DECIMAL) {
80,141✔
UNCOV
634
        memcpy(pBuf->dec, tval, pCol->info.bytes);
×
635
      } else {
636
        pBuf->v = GET_INT64_VAL(tval);
80,141✔
637
      }
638

639
      code = saveRelatedTupleTag(pCtx, pInput, tval);
80,956✔
640
    } else {
641
      if (IS_SIGNED_NUMERIC_TYPE(type) || TSDB_DATA_TYPE_BOOL == type || TSDB_DATA_TYPE_TIMESTAMP == type) {
8,840,569✔
642
        int64_t prev = 0;
2,963,712✔
643
        GET_TYPED_DATA(prev, int64_t, type, &pBuf->v, 0);
2,963,712✔
644

645
        int64_t val = GET_INT64_VAL(tval);
2,961,756✔
646
        if ((prev < val) ^ isMinFunc) {
2,961,756✔
647
          GET_INT64_VAL(&pBuf->v) = val;
547,653✔
648
          code = saveRelatedTupleTag(pCtx, pInput, tval);
547,653✔
649
        }
650
      } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
5,831,522✔
651
        uint64_t prev = 0;
2,912,501✔
652
        GET_TYPED_DATA(prev, uint64_t, type, &pBuf->v, 0);
2,912,501✔
653

654
        uint64_t val = GET_UINT64_VAL(tval);
2,913,805✔
655
        if ((prev < val) ^ isMinFunc) {
2,912,501✔
656
          GET_UINT64_VAL(&pBuf->v) = val;
747,938✔
657
          code = saveRelatedTupleTag(pCtx, pInput, tval);
747,938✔
658
        }
659
      } else if (type == TSDB_DATA_TYPE_DOUBLE) {
2,600✔
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) {
2,600✔
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) {
2,600✔
UNCOV
678
        const SDecimalOps* pOps = getDecimalOps(type);
×
UNCOV
679
        if (pOps->lt(&pBuf->v, tval, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) {
×
680
          DECIMAL64_SET_VALUE((Decimal64*)&pBuf->v, *(int64_t*)tval);
×
681
          code =saveRelatedTupleTag(pCtx, pInput, tval);
×
682
        }
683
      } else if (type == TSDB_DATA_TYPE_DECIMAL) {
2,600✔
UNCOV
684
        const SDecimalOps* pOps = getDecimalOps(type);
×
UNCOV
685
        if (pOps->lt(pBuf->dec, tval, DECIMAL_WORD_NUM(Decimal128)) ^ isMinFunc) {
×
UNCOV
686
          DECIMAL128_CLONE((Decimal128*)pBuf->dec, (Decimal128*)tval);
×
UNCOV
687
          code =saveRelatedTupleTag(pCtx, pInput, tval);
×
688
        }
689
      }
690
    }
691

692
    numOfElems = 1;
5,961,733✔
693
    pBuf->assign = true;
5,961,733✔
694
    goto _over;
5,958,473✔
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,666,149,801✔
715

716
      switch (type) {
1,666,140,482✔
717
        case TSDB_DATA_TYPE_DOUBLE:
185,534,183✔
718
        case TSDB_DATA_TYPE_UBIGINT:
719
        case TSDB_DATA_TYPE_BIGINT:
720
        case TSDB_DATA_TYPE_TIMESTAMP:
721
          pBuf->v = *(int64_t*)p;
185,534,183✔
722
          break;
185,534,183✔
723
        case TSDB_DATA_TYPE_UINT:
1,383,908,883✔
724
        case TSDB_DATA_TYPE_INT:
725
          pBuf->v = *(int32_t*)p;
1,383,908,883✔
726
          break;
1,383,912,866✔
727
        case TSDB_DATA_TYPE_USMALLINT:
14,676,432✔
728
        case TSDB_DATA_TYPE_SMALLINT:
729
          pBuf->v = *(int16_t*)p;
14,676,432✔
730
          break;
14,676,432✔
731
        case TSDB_DATA_TYPE_BOOL:
43,544,660✔
732
        case TSDB_DATA_TYPE_UTINYINT:
733
        case TSDB_DATA_TYPE_TINYINT:
734
          pBuf->v = *(int8_t*)p;
43,544,660✔
735
          break;
43,544,660✔
736
        case TSDB_DATA_TYPE_FLOAT: {
32,821,583✔
737
          *(float*)&pBuf->v = *(float*)p;
32,821,583✔
738
          break;
32,821,583✔
739
        }
740
        case TSDB_DATA_TYPE_VARCHAR:
4,927,571✔
741
        case TSDB_DATA_TYPE_VARBINARY:
742
        case TSDB_DATA_TYPE_NCHAR: {
743
          pBuf->str = taosMemoryMalloc(pCol->info.bytes);
4,927,571✔
744
          if (pBuf->str == NULL) {
4,928,481✔
745
            return terrno;
×
746
          }
747
          (void)memcpy(pBuf->str, colDataGetData(pCol, i), varDataTLen(colDataGetData(pCol, i)));
4,928,026✔
748
          break;
4,928,936✔
749
        }
750
        case TSDB_DATA_TYPE_DECIMAL64:
691,149✔
751
          *(int64_t*)&pBuf->v = *(int64_t*)p;
691,149✔
752
          break;
691,149✔
753
        case TSDB_DATA_TYPE_DECIMAL:
36,021✔
754
          (void)memcpy(pBuf->dec, p, pCol->info.bytes);
36,021✔
755
          break;
36,021✔
756
        default:
×
757
          (void)memcpy(&pBuf->v, p, pCol->info.bytes);
×
758
          break;
×
759
      }
760

761
      if (pCtx->subsidiaries.num > 0) {
1,666,145,830✔
762
        code = saveTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos);
2,068,992✔
763
        if (code != TSDB_CODE_SUCCESS) {
2,068,992✔
764
          return code;
×
765
        }
766
      }
767
      pBuf->assign = true;
1,666,142,583✔
768
      numOfElems = 1;
1,666,133,114✔
769
    }
770

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

775
    code = doExtractVal(pCol, i, end, pCtx, pBuf, isMinFunc);
2,034,464,255✔
776
  } else {
777
    numOfElems = numOfRows;
89,012,907✔
778

779
    switch (type) {
89,012,907✔
780
      case TSDB_DATA_TYPE_BOOL:
6,527,117✔
781
      case TSDB_DATA_TYPE_TINYINT: {
782
        handleInt8Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
6,527,117✔
783
        break;
6,527,117✔
784
      }
785
      case TSDB_DATA_TYPE_SMALLINT: {
7,089,773✔
786
        handleInt16Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
7,089,773✔
787
        break;
7,089,773✔
788
      }
789
      case TSDB_DATA_TYPE_INT: {
27,562,093✔
790
        handleInt32Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
27,562,093✔
791
        break;
27,545,890✔
792
      }
793
      case TSDB_DATA_TYPE_BIGINT:
8,547,460✔
794
      case TSDB_DATA_TYPE_TIMESTAMP: {
795
        handleInt64Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, true);
8,547,460✔
796
        break;
8,548,104✔
797
      }
798
      case TSDB_DATA_TYPE_UTINYINT: {
7,776,996✔
799
        handleInt8Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
7,776,996✔
800
        break;
7,776,352✔
801
      }
802
      case TSDB_DATA_TYPE_USMALLINT: {
5,430,696✔
803
        handleInt16Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
5,430,696✔
804
        break;
5,430,696✔
805
      }
806
      case TSDB_DATA_TYPE_UINT: {
6,788,370✔
807
        handleInt32Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
6,788,370✔
808
        break;
6,788,370✔
809
      }
810
      case TSDB_DATA_TYPE_UBIGINT: {
5,317,746✔
811
        handleInt64Col(pCol->pData, start, numOfRows, pBuf, isMinFunc, false);
5,317,746✔
812
        break;
5,317,746✔
813
      }
814
      case TSDB_DATA_TYPE_FLOAT: {
8,523,445✔
815
        handleFloatCol(pCol, start, numOfRows, pBuf, isMinFunc);
8,523,445✔
816
        break;
8,523,445✔
817
      }
818
      case TSDB_DATA_TYPE_DOUBLE: {
5,461,318✔
819
        handleDoubleCol(pCol, start, numOfRows, pBuf, isMinFunc);
5,461,318✔
820
        break;
5,461,318✔
821
      }
822
    }
823

824
    pBuf->assign = true;
88,996,704✔
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,305,294✔
830
    if (code != TSDB_CODE_SUCCESS) {
1,305,718✔
831
      return code;
×
832
    }
833

834
    pBuf->nullTupleSaved = true;
1,305,718✔
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 TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc