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

taosdata / TDengine / #4908

30 Dec 2025 10:52AM UTC coverage: 65.386% (-0.2%) from 65.541%
#4908

push

travis-ci

web-flow
enh: drop multi-stream (#33962)

60 of 106 new or added lines in 4 files covered. (56.6%)

1330 existing lines in 113 files now uncovered.

193461 of 295877 relevant lines covered (65.39%)

115765274.47 hits per line

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

64.68
/source/util/src/tcompare.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
#define _BSD_SOURCE
16
#define _GNU_SOURCE
17
#define _XOPEN_SOURCE
18
#define _DEFAULT_SOURCE
19
#include "tcompare.h"
20
#include "decimal.h"
21
#include "osString.h"
22
#include "regex.h"
23
#include "tdef.h"
24
#include "thash.h"
25
#include "tlog.h"
26
#include "ttimer.h"
27
#include "tutil.h"
28
#include "types.h"
29

30
int32_t setChkInBytes1(const void *pLeft, const void *pRight) {
678,265✔
31
  return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0;
678,265✔
32
}
33

34
int32_t setChkInBytes2(const void *pLeft, const void *pRight) {
1,566✔
35
  return NULL != taosHashGet((SHashObj *)pRight, pLeft, 2) ? 1 : 0;
1,566✔
36
}
37

38
int32_t setChkInBytes4(const void *pLeft, const void *pRight) {
1,269,650✔
39
  return NULL != taosHashGet((SHashObj *)pRight, pLeft, 4) ? 1 : 0;
1,269,650✔
40
}
41

42
int32_t setChkInBytes8(const void *pLeft, const void *pRight) {
460,726,650✔
43
  return NULL != taosHashGet((SHashObj *)pRight, pLeft, 8) ? 1 : 0;
460,726,650✔
44
}
45

46
int32_t setChkNotInBytes1(const void *pLeft, const void *pRight) {
31,812✔
47
  return NULL == taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0;
31,812✔
48
}
49

50
int32_t setChkNotInBytes2(const void *pLeft, const void *pRight) {
1,566✔
51
  return NULL == taosHashGet((SHashObj *)pRight, pLeft, 2) ? 1 : 0;
1,566✔
52
}
53

54
int32_t setChkNotInBytes4(const void *pLeft, const void *pRight) {
1,208,842✔
55
  return NULL == taosHashGet((SHashObj *)pRight, pLeft, 4) ? 1 : 0;
1,208,842✔
56
}
57

58
int32_t setChkNotInBytes8(const void *pLeft, const void *pRight) {
218,131,264✔
59
  return NULL == taosHashGet((SHashObj *)pRight, pLeft, 8) ? 1 : 0;
218,131,264✔
60
}
61

62
int32_t setChkInDecimalHash(const void *pLeft, const void *pRight) {
92,898,468✔
63
  const SDecimalCompareCtx *pCtxL = pLeft, *pCtxR = pRight;
92,898,468✔
64
  return NULL != taosHashGet((SHashObj *)(pCtxR->pData), pCtxL->pData, tDataTypes[pCtxL->type].bytes) ? 1 : 0;
92,898,468✔
65
}
66

67
int32_t setChkNotInDecimalHash(const void *pLeft, const void *pRight) {
92,977,092✔
68
  const SDecimalCompareCtx *pCtxL = pLeft, *pCtxR = pRight;
92,977,092✔
69
  return NULL == taosHashGet((SHashObj *)(pCtxR->pData), pCtxL->pData, tDataTypes[pCtxL->type].bytes) ? 1 : 0;
92,977,092✔
70
}
71

72
int32_t compareChkInString(const void *pLeft, const void *pRight) {
53,312,809✔
73
  return NULL != taosHashGet((SHashObj *)pRight, pLeft, varDataTLen(pLeft)) ? 1 : 0;
53,312,809✔
74
}
75

76
int32_t compareChkNotInString(const void *pLeft, const void *pRight) {
12,917,856✔
77
  return NULL == taosHashGet((SHashObj *)pRight, pLeft, varDataTLen(pLeft)) ? 1 : 0;
12,917,856✔
78
}
79

80
int32_t compareInt8Val(const void *pLeft, const void *pRight) {
2,147,483,647✔
81
  int8_t left = GET_INT8_VAL(pLeft), right = GET_INT8_VAL(pRight);
2,147,483,647✔
82
  if (left > right) return 1;
2,147,483,647✔
83
  if (left < right) return -1;
2,147,483,647✔
84
  return 0;
2,147,483,647✔
85
}
86

87
int32_t compareInt8ValDesc(const void *pLeft, const void *pRight) { return compareInt8Val(pRight, pLeft); }
403,536✔
88

89
int32_t compareInt16Val(const void *pLeft, const void *pRight) {
347,311,987✔
90
  int16_t left = GET_INT16_VAL(pLeft), right = GET_INT16_VAL(pRight);
347,311,987✔
91
  if (left > right) return 1;
347,338,999✔
92
  if (left < right) return -1;
180,786,300✔
93
  return 0;
24,590,899✔
94
}
95

96
int32_t compareInt16ValDesc(const void *pLeft, const void *pRight) { return compareInt16Val(pRight, pLeft); }
401,064✔
97

98
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
2,147,483,647✔
99
  int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight);
2,147,483,647✔
100
  if (left > right) return 1;
2,147,483,647✔
101
  if (left < right) return -1;
2,147,483,647✔
102
  return 0;
2,147,483,647✔
103
}
104

105
int32_t compareInt32ValDesc(const void *pLeft, const void *pRight) { return compareInt32Val(pRight, pLeft); }
619,399,624✔
106

107
int32_t compareInt64Val(const void *pLeft, const void *pRight) {
2,147,483,647✔
108
  int64_t left = GET_INT64_VAL(pLeft);
2,147,483,647✔
109
  int64_t right = GET_INT64_VAL(pRight);
2,147,483,647✔
110
  return (left > right) - (left < right);
2,147,483,647✔
111
}
112

113
int32_t compareInt64ValDesc(const void *pLeft, const void *pRight) { return compareInt64Val(pRight, pLeft); }
2,147,483,647✔
114

115
int32_t compareUint32Val(const void *pLeft, const void *pRight) {
255,042,474✔
116
  uint32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight);
255,042,474✔
117
  if (left > right) return 1;
255,045,522✔
118
  if (left < right) return -1;
141,538,500✔
119
  return 0;
67,706,640✔
120
}
121

122
int32_t compareUint32ValDesc(const void *pLeft, const void *pRight) { return compareUint32Val(pRight, pLeft); }
131,122,613✔
123

124
int32_t compareUint64Val(const void *pLeft, const void *pRight) {
267,832,868✔
125
  uint64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight);
267,832,868✔
126
  if (left > right) return 1;
267,834,698✔
127
  if (left < right) return -1;
150,009,336✔
128
  return 0;
73,768,032✔
129
}
130

131
int32_t compareUint64ValDesc(const void *pLeft, const void *pRight) { return compareUint64Val(pRight, pLeft); }
144,995,776✔
132

133
int32_t compareUint16Val(const void *pLeft, const void *pRight) {
7,448,011✔
134
  uint16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight);
7,448,011✔
135
  if (left > right) return 1;
7,449,360✔
136
  if (left < right) return -1;
6,961,913✔
137
  return 0;
286,723✔
138
}
139

140
int32_t compareUint16ValDesc(const void *pLeft, const void *pRight) { return compareUint16Val(pRight, pLeft); }
×
141

142
int32_t compareUint8Val(const void *pLeft, const void *pRight) {
3,056,584✔
143
  uint8_t left = GET_UINT8_VAL(pLeft), right = GET_UINT8_VAL(pRight);
3,056,584✔
144
  if (left > right) return 1;
3,056,584✔
145
  if (left < right) return -1;
1,797,570✔
146
  return 0;
269,878✔
147
}
148

149
int32_t compareUint8ValDesc(const void *pLeft, const void *pRight) { return compareUint8Val(pRight, pLeft); }
×
150

151
int32_t compareFloatVal(const void *pLeft, const void *pRight) {
2,147,483,647✔
152
  float p1 = GET_FLOAT_VAL(pLeft);
2,147,483,647✔
153
  float p2 = GET_FLOAT_VAL(pRight);
2,147,483,647✔
154

155
  if (isnan(p1) && isnan(p2)) {
2,147,483,647✔
156
    return 0;
×
157
  }
158

159
  if (isnan(p1)) {
2,147,483,647✔
160
    return -1;
×
161
  }
162

163
  if (isnan(p2)) {
2,147,483,647✔
164
    return 1;
×
165
  }
166
  if (FLT_EQUAL(p1, p2)) {
2,147,483,647✔
167
    return 0;
2,147,483,647✔
168
  }
169
  return FLT_GREATER(p1, p2) ? 1 : -1;
2,147,483,647✔
170
}
171

172
int32_t compareFloatValDesc(const void *pLeft, const void *pRight) { return compareFloatVal(pRight, pLeft); }
527,140✔
173

174
int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
2,147,483,647✔
175
  double p1 = GET_DOUBLE_VAL(pLeft);
2,147,483,647✔
176
  double p2 = GET_DOUBLE_VAL(pRight);
2,147,483,647✔
177

178
  if (isnan(p1) && isnan(p2)) {
2,147,483,647✔
179
    return 0;
×
180
  }
181

182
  if (isnan(p1)) {
2,147,483,647✔
183
    return -1;
×
184
  }
185

186
  if (isnan(p2)) {
2,147,483,647✔
187
    return 1;
107,406✔
188
  }
189

190
  if (DBL_EQUAL(p1, p2)) {
2,147,483,647✔
191
    return 0;
743,924,615✔
192
  }
193
  return DBL_GREATER(p1, p2) ? 1 : -1;
2,147,483,647✔
194
}
195

196
int32_t compareDoubleValDesc(const void *pLeft, const void *pRight) { return compareDoubleVal(pRight, pLeft); }
1,326,307✔
197

198
int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) {
2,147,483,647✔
199
  int32_t len1 = varDataLen(pLeft);
2,147,483,647✔
200
  int32_t len2 = varDataLen(pRight);
2,147,483,647✔
201

202
  int32_t minLen = TMIN(len1, len2);
2,147,483,647✔
203
  int32_t ret = strncmp(varDataVal(pLeft), varDataVal(pRight), minLen);
2,147,483,647✔
204
  if (ret == 0) {
2,147,483,647✔
205
    if (len1 == len2) {
2,147,483,647✔
206
      return 0;
2,147,483,647✔
207
    } else {
208
      return len1 > len2 ? 1 : -1;
30,733,634✔
209
    }
210
  } else {
211
    return ret > 0 ? 1 : -1;
2,147,483,647✔
212
  }
213
}
214

215
int32_t compareLenPrefixedStrDesc(const void *pLeft, const void *pRight) {
328,967,991✔
216
  return compareLenPrefixedStr(pRight, pLeft);
328,967,991✔
217
}
218

219
int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) {
2,147,483,647✔
220
  int32_t len1 = varDataLen(pLeft);
2,147,483,647✔
221
  int32_t len2 = varDataLen(pRight);
2,147,483,647✔
222
  int32_t ret = taosUcs4Compare((TdUcs4 *)varDataVal(pLeft), (TdUcs4 *)varDataVal(pRight), len1 > len2 ? len2 : len1);
2,147,483,647✔
223

224
/*  
225
  int32_t bufSize = 256;
226
  char *buf1 = NULL;
227
  char *buf2 = NULL;
228
  do {
229
    buf1 = taosMemoryCalloc(1, bufSize);
230
    if (buf1 == NULL) {
231
      break;
232
    }
233
    buf2 = taosMemoryCalloc(1, bufSize);
234
    if (buf2 == NULL) {
235
      break;
236
    }
237
    int32_t code = taosHexEncode(varDataVal(pLeft), buf1, varDataLen(pLeft), bufSize);
238
    if (code) {
239
      break;
240
    }
241
    code = taosHexEncode(varDataVal(pRight), buf2, varDataLen(pRight), bufSize);
242
    if (code) {
243
      break;
244
    }
245
    
246
    uInfo("ucs4compare res:%d, left:%d,%p,[%s], right:%d,%p,[%s]", ret, len1, pLeft, buf1, len2, pRight, buf2);
247
  } while (0);
248
  taosMemoryFree(buf1);
249
  taosMemoryFree(buf2);
250
*/
251

252
  if (ret == 0) {
2,147,483,647✔
253
    if (len1 > len2)
2,147,483,647✔
254
      return 1;
460,073✔
255
    else if (len1 < len2)
2,147,483,647✔
256
      return -1;
931,994✔
257
    else
258
      return 0;
2,147,483,647✔
259
  }
260
  return (ret < 0) ? -1 : 1;
2,147,483,647✔
261
}
262

263
int32_t compareLenPrefixedWStrDesc(const void *pLeft, const void *pRight) {
12,302,981✔
264
  return compareLenPrefixedWStr(pRight, pLeft);
12,302,981✔
265
}
266

267
int32_t compareLenBinaryVal(const void *pLeft, const void *pRight) {
1,076,851,309✔
268
  int32_t len1 = varDataLen(pLeft);
1,076,851,309✔
269
  int32_t len2 = varDataLen(pRight);
1,076,851,309✔
270

271
  int32_t minLen = TMIN(len1, len2);
1,076,851,309✔
272
  int32_t ret = memcmp(varDataVal(pLeft), varDataVal(pRight), minLen);
1,076,851,309✔
273
  if (ret == 0) {
1,076,851,309✔
274
    if (len1 == len2) {
162,154,926✔
275
      return 0;
162,088,695✔
276
    } else {
277
      return len1 > len2 ? 1 : -1;
66,231✔
278
    }
279
  } else {
280
    return ret > 0 ? 1 : -1;
914,696,383✔
281
  }
282
}
283
int32_t compareBlobVal(const void *pLeft, const void *pRight) {
×
284
  int32_t len1 = blobDataLen(pLeft);
×
285
  int32_t len2 = blobDataLen(pRight);
×
286

287
  int32_t minLen = TMIN(len1, len2);
×
288
  int32_t ret = memcmp(blobDataVal(pLeft), blobDataVal(pRight), minLen);
×
289
  if (ret == 0) {
×
290
    if (len1 == len2) {
×
291
      return 0;
×
292
    } else {
293
      return len1 > len2 ? 1 : -1;
×
294
    }
295
  } else {
296
    return ret > 0 ? 1 : -1;
×
297
  }
298
}
299

300
int32_t compareLenBinaryValDesc(const void *pLeft, const void *pRight) { return compareLenBinaryVal(pRight, pLeft); }
×
301
int32_t compareBlobValDesc(const void *pLeft, const void *pRight) { return compareBlobVal(pRight, pLeft); }
×
302

303
// string > number > bool > null
304
// ref: https://dev.mysql.com/doc/refman/8.0/en/json.html#json-comparison
305
int32_t compareJsonVal(const void *pLeft, const void *pRight) {
118,008✔
306
  char leftType = *(char *)pLeft;
118,008✔
307
  char rightType = *(char *)pRight;
118,008✔
308
  if (leftType != rightType) {
118,008✔
309
    return leftType > rightType ? 1 : -1;
76,437✔
310
  }
311

312
  char *realDataLeft = POINTER_SHIFT(pLeft, CHAR_BYTES);
41,571✔
313
  char *realDataRight = POINTER_SHIFT(pRight, CHAR_BYTES);
41,571✔
314
  if (leftType == TSDB_DATA_TYPE_BOOL) {
41,571✔
315
    DEFAULT_COMP(GET_INT8_VAL(realDataLeft), GET_INT8_VAL(realDataRight));
×
316
  } else if (leftType == TSDB_DATA_TYPE_DOUBLE) {
41,571✔
317
    DEFAULT_DOUBLE_COMP(GET_DOUBLE_VAL(realDataLeft), GET_DOUBLE_VAL(realDataRight));
19,668✔
318
  } else if (leftType == TSDB_DATA_TYPE_NCHAR) {
21,903✔
319
    return compareLenPrefixedWStr(realDataLeft, realDataRight);
15,645✔
320
  } else if (leftType == TSDB_DATA_TYPE_NULL) {
6,258✔
321
    return 0;
6,258✔
322
  } else {
323
    uError("data type unexpected leftType:%d rightType:%d", leftType, rightType);
×
324
    return 0;
×
325
  }
326
}
327

328
int32_t compareInt8Int16(const void *pLeft, const void *pRight) {
6,554,482✔
329
  int8_t  left = GET_INT8_VAL(pLeft);
6,554,482✔
330
  int16_t right = GET_INT16_VAL(pRight);
6,554,482✔
331
  if (left > right) return 1;
6,554,482✔
332
  if (left < right) return -1;
6,554,482✔
333
  return 0;
×
334
}
335

336
int32_t compareInt8Int32(const void *pLeft, const void *pRight) {
318,720✔
337
  int8_t  left = GET_INT8_VAL(pLeft);
318,720✔
338
  int32_t right = GET_INT32_VAL(pRight);
318,720✔
339
  if (left > right) return 1;
318,720✔
340
  if (left < right) return -1;
318,720✔
341
  return 0;
×
342
}
343

344
int32_t compareInt8Int64(const void *pLeft, const void *pRight) {
2,163,087✔
345
  int8_t  left = GET_INT8_VAL(pLeft);
2,163,087✔
346
  int64_t right = GET_INT64_VAL(pRight);
2,163,291✔
347
  if (left > right) return 1;
2,163,291✔
348
  if (left < right) return -1;
2,155,791✔
349
  return 0;
1,110,638✔
350
}
351

352
int32_t compareInt8Float(const void *pLeft, const void *pRight) {
37,524✔
353
  int8_t left = GET_INT8_VAL(pLeft);
37,524✔
354
  float  right = GET_FLOAT_VAL(pRight);
37,524✔
355
  if (left > right) return 1;
37,524✔
356
  if (left < right) return -1;
5,637✔
357
  return 0;
2,043✔
358
}
359

360
int32_t compareInt8Double(const void *pLeft, const void *pRight) {
10,824✔
361
  int8_t left = GET_INT8_VAL(pLeft);
10,824✔
362
  double right = GET_DOUBLE_VAL(pRight);
10,824✔
363
  if (left > right) return 1;
10,824✔
364
  if (left < right) return -1;
4,428✔
365
  return 0;
×
366
}
367

368
int32_t compareInt8Uint8(const void *pLeft, const void *pRight) {
×
369
  int8_t  left = GET_INT8_VAL(pLeft);
×
370
  uint8_t right = GET_UINT8_VAL(pRight);
×
371
  if (left > right) return 1;
×
372
  if (left < right) return -1;
×
373
  return 0;
×
374
}
375

376
int32_t compareInt8Uint16(const void *pLeft, const void *pRight) {
×
377
  int8_t   left = GET_INT8_VAL(pLeft);
×
378
  uint16_t right = GET_UINT16_VAL(pRight);
×
379
  if (left > right) return 1;
×
380
  if (left < right) return -1;
×
381
  return 0;
×
382
}
383

384
int32_t compareInt8Uint32(const void *pLeft, const void *pRight) {
×
385
  int8_t left = GET_INT8_VAL(pLeft);
×
386
  if (left < 0) return -1;
×
387
  uint32_t right = GET_UINT32_VAL(pRight);
×
388
  if ((uint32_t)left > right) return 1;
×
389
  if ((uint32_t)left < right) return -1;
×
390
  return 0;
×
391
}
392

393
int32_t compareInt8Uint64(const void *pLeft, const void *pRight) {
×
394
  int8_t left = GET_INT8_VAL(pLeft);
×
395
  if (left < 0) return -1;
×
396
  uint64_t right = GET_UINT64_VAL(pRight);
×
397
  if ((uint64_t)left > right) return 1;
×
398
  if ((uint64_t)left < right) return -1;
×
399
  return 0;
×
400
}
401

402
int32_t compareInt16Int8(const void *pLeft, const void *pRight) {
40,754,412✔
403
  int16_t left = GET_INT16_VAL(pLeft);
40,754,412✔
404
  int8_t  right = GET_INT8_VAL(pRight);
40,754,412✔
405
  if (left > right) return 1;
40,756,254✔
406
  if (left < right) return -1;
22,171,195✔
407
  return 0;
7,144,584✔
408
}
409

410
int32_t compareInt16Int32(const void *pLeft, const void *pRight) {
324,132✔
411
  int16_t left = GET_INT16_VAL(pLeft);
324,132✔
412
  int32_t right = GET_INT32_VAL(pRight);
324,132✔
413
  if (left > right) return 1;
324,132✔
414
  if (left < right) return -1;
324,132✔
415
  return 0;
×
416
}
417

418
int32_t compareInt16Int64(const void *pLeft, const void *pRight) {
200,412✔
419
  int16_t left = GET_INT16_VAL(pLeft);
200,412✔
420
  int64_t right = GET_INT64_VAL(pRight);
200,616✔
421
  if (left > right) return 1;
200,616✔
422
  if (left < right) return -1;
18,768✔
423
  return 0;
×
424
}
425

426
int32_t compareInt16Float(const void *pLeft, const void *pRight) {
41,460✔
427
  int16_t left = GET_INT16_VAL(pLeft);
41,460✔
428
  float   right = GET_FLOAT_VAL(pRight);
41,460✔
429
  if (left > right) return 1;
41,460✔
430
  if (left < right) return -1;
8,097✔
431
  return 0;
3,027✔
432
}
433

434
int32_t compareInt16Double(const void *pLeft, const void *pRight) {
12,390✔
435
  int16_t left = GET_INT16_VAL(pLeft);
12,390✔
436
  double  right = GET_DOUBLE_VAL(pRight);
12,390✔
437
  if (left > right) return 1;
12,390✔
438
  if (left < right) return -1;
5,994✔
439
  return 0;
×
440
}
441

442
int32_t compareInt16Uint8(const void *pLeft, const void *pRight) {
×
443
  int16_t left = GET_INT16_VAL(pLeft);
×
444
  uint8_t right = GET_UINT8_VAL(pRight);
×
445
  if (left > right) return 1;
×
446
  if (left < right) return -1;
×
447
  return 0;
×
448
}
449

450
int32_t compareInt16Uint16(const void *pLeft, const void *pRight) {
×
451
  int16_t  left = GET_INT16_VAL(pLeft);
×
452
  uint16_t right = GET_UINT16_VAL(pRight);
×
453
  if (left > right) return 1;
×
454
  if (left < right) return -1;
×
455
  return 0;
×
456
}
457

458
int32_t compareInt16Uint32(const void *pLeft, const void *pRight) {
×
459
  int16_t left = GET_INT16_VAL(pLeft);
×
460
  if (left < 0) return -1;
×
461
  uint32_t right = GET_UINT32_VAL(pRight);
×
462
  if ((uint32_t)left > right) return 1;
×
463
  if ((uint32_t)left < right) return -1;
×
464
  return 0;
×
465
}
466

467
int32_t compareInt16Uint64(const void *pLeft, const void *pRight) {
×
468
  int16_t left = GET_INT16_VAL(pLeft);
×
469
  if (left < 0) return -1;
×
470
  uint64_t right = GET_UINT64_VAL(pRight);
×
471
  if ((uint64_t)left > right) return 1;
×
472
  if ((uint64_t)left < right) return -1;
×
473
  return 0;
×
474
}
475

476
int32_t compareInt32Int8(const void *pLeft, const void *pRight) {
135,291,054✔
477
  int32_t left = GET_INT32_VAL(pLeft);
135,291,054✔
478
  int8_t  right = GET_INT8_VAL(pRight);
135,297,047✔
479
  if (left > right) return 1;
135,295,883✔
480
  if (left < right) return -1;
34,904,411✔
481
  return 0;
11,248,958✔
482
}
483

484
int32_t compareInt32Int16(const void *pLeft, const void *pRight) {
27,598,967✔
485
  int32_t left = GET_INT32_VAL(pLeft);
27,598,967✔
486
  int16_t right = GET_INT16_VAL(pRight);
27,598,967✔
487
  if (left > right) return 1;
27,598,967✔
488
  if (left < right) return -1;
5,617,553✔
489
  return 0;
360,135✔
490
}
491

492
int32_t compareInt32Int64(const void *pLeft, const void *pRight) {
47,817,825✔
493
  int32_t left = GET_INT32_VAL(pLeft);
47,817,825✔
494
  int64_t right = GET_INT64_VAL(pRight);
47,819,395✔
495
  if (left > right) return 1;
47,836,258✔
496
  if (left < right) return -1;
32,120,472✔
497
  return 0;
922,531✔
498
}
499

500
int32_t compareInt32Float(const void *pLeft, const void *pRight) {
18,050✔
501
  int32_t left = GET_INT32_VAL(pLeft);
18,050✔
502
  float   right = GET_FLOAT_VAL(pRight);
18,050✔
503
  if (left > right) return 1;
18,050✔
504
  if (left < right) return -1;
18,050✔
505
  return 0;
×
506
}
507

508
int32_t compareInt32Double(const void *pLeft, const void *pRight) {
1,032,554✔
509
  int32_t left = GET_INT32_VAL(pLeft);
1,032,554✔
510
  double  right = GET_DOUBLE_VAL(pRight);
1,032,554✔
511
  if (left > right) return 1;
1,033,081✔
512
  if (left < right) return -1;
767,865✔
513
  return 0;
214,363✔
514
}
515

516
int32_t compareInt32Uint8(const void *pLeft, const void *pRight) {
×
517
  int32_t left = GET_INT32_VAL(pLeft);
×
518
  uint8_t right = GET_UINT8_VAL(pRight);
×
519
  if (left > right) return 1;
×
520
  if (left < right) return -1;
×
521
  return 0;
×
522
}
523

524
int32_t compareInt32Uint16(const void *pLeft, const void *pRight) {
×
525
  int32_t  left = GET_INT32_VAL(pLeft);
×
526
  uint16_t right = GET_UINT16_VAL(pRight);
×
527
  if (left > right) return 1;
×
528
  if (left < right) return -1;
×
529
  return 0;
×
530
}
531

532
int32_t compareInt32Uint32(const void *pLeft, const void *pRight) {
16,944✔
533
  int32_t left = GET_INT32_VAL(pLeft);
16,944✔
534
  if (left < 0) return -1;
16,944✔
535
  uint32_t right = GET_UINT32_VAL(pRight);
16,944✔
536
  if ((uint32_t)left > right) return 1;
16,944✔
537
  if ((uint32_t)left < right) return -1;
9,531✔
538
  return 0;
9,531✔
539
}
540

541
int32_t compareInt32Uint64(const void *pLeft, const void *pRight) {
×
542
  int32_t left = GET_INT32_VAL(pLeft);
×
543
  if (left < 0) return -1;
×
544
  uint64_t right = GET_UINT64_VAL(pRight);
×
545
  if ((uint64_t)left > right) return 1;
×
546
  if ((uint64_t)left < right) return -1;
×
547
  return 0;
×
548
}
549

550
int32_t compareInt64Int8(const void *pLeft, const void *pRight) {
2,147,483,647✔
551
  int64_t left = GET_INT64_VAL(pLeft);
2,147,483,647✔
552
  int8_t  right = GET_INT8_VAL(pRight);
2,147,483,647✔
553
  if (left > right) return 1;
2,147,483,647✔
554
  if (left < right) return -1;
2,127,493,958✔
555
  return 0;
1,924,324,858✔
556
}
557

558
int32_t compareInt64Int16(const void *pLeft, const void *pRight) {
2,147,483,647✔
559
  int64_t left = GET_INT64_VAL(pLeft);
2,147,483,647✔
560
  int16_t right = GET_INT16_VAL(pRight);
2,147,483,647✔
561
  if (left > right) return 1;
2,147,483,647✔
562
  if (left < right) return -1;
2,147,483,647✔
563
  return 0;
2,147,483,647✔
564
}
565

566
int32_t compareInt64Int32(const void *pLeft, const void *pRight) {
2,147,483,647✔
567
  int64_t left = GET_INT64_VAL(pLeft);
2,147,483,647✔
568
  int32_t right = GET_INT32_VAL(pRight);
2,147,483,647✔
569
  if (left > right) return 1;
2,147,483,647✔
570
  if (left < right) return -1;
1,614,130,139✔
571
  return 0;
136,733,944✔
572
}
573

574
int32_t compareInt64Float(const void *pLeft, const void *pRight) {
41,460✔
575
  int64_t left = GET_INT64_VAL(pLeft);
41,460✔
576
  float   right = GET_FLOAT_VAL(pRight);
41,460✔
577
  if (left > right) return 1;
41,460✔
578
  if (left < right) return -1;
8,097✔
579
  return 0;
3,027✔
580
}
581

582
int32_t compareInt64Double(const void *pLeft, const void *pRight) {
8,540✔
583
  int64_t left = GET_INT64_VAL(pLeft);
8,540✔
584
  double  right = GET_DOUBLE_VAL(pRight);
8,540✔
585
  if (left > right) return 1;
8,540✔
586
  if (left < right) return -1;
8,540✔
587
  return 0;
×
588
}
589

590
int32_t compareInt64Uint8(const void *pLeft, const void *pRight) {
×
591
  int64_t left = GET_INT64_VAL(pLeft);
×
592
  uint8_t right = GET_UINT8_VAL(pRight);
×
593
  if (left > right) return 1;
×
594
  if (left < right) return -1;
×
595
  return 0;
×
596
}
597

598
int32_t compareInt64Uint16(const void *pLeft, const void *pRight) {
×
599
  int64_t  left = GET_INT64_VAL(pLeft);
×
600
  uint16_t right = GET_UINT16_VAL(pRight);
×
601
  if (left > right) return 1;
×
602
  if (left < right) return -1;
×
603
  return 0;
×
604
}
605

606
int32_t compareInt64Uint32(const void *pLeft, const void *pRight) {
×
607
  int64_t  left = GET_INT64_VAL(pLeft);
×
608
  uint32_t right = GET_UINT32_VAL(pRight);
×
609
  if (left > right) return 1;
×
610
  if (left < right) return -1;
×
611
  return 0;
×
612
}
613

614
int32_t compareInt64Uint64(const void *pLeft, const void *pRight) {
5,904✔
615
  int64_t left = GET_INT64_VAL(pLeft);
5,904✔
616
  if (left < 0) return -1;
5,904✔
617
  uint64_t right = GET_UINT64_VAL(pRight);
5,412✔
618
  if ((uint64_t)left > right) return 1;
5,412✔
619
  if ((uint64_t)left < right) return -1;
5,412✔
620
  return 0;
×
621
}
622

623
int32_t compareFloatInt8(const void *pLeft, const void *pRight) {
103,857,416✔
624
  float  left = GET_FLOAT_VAL(pLeft);
103,857,416✔
625
  int8_t right = GET_INT8_VAL(pRight);
103,858,637✔
626
  if (left > right) return 1;
103,858,636✔
627
  if (left < right) return -1;
98,806,644✔
628
  return 0;
96,075,576✔
629
}
630

631
int32_t compareFloatInt16(const void *pLeft, const void *pRight) {
12,708,000✔
632
  float   left = GET_FLOAT_VAL(pLeft);
12,708,000✔
633
  int16_t right = GET_INT16_VAL(pRight);
12,708,000✔
634
  if (left > right) return 1;
12,708,000✔
635
  if (left < right) return -1;
693,645✔
636
  return 0;
2,118✔
637
}
638

639
int32_t compareFloatInt32(const void *pLeft, const void *pRight) {
328,360✔
640
  float   left = GET_FLOAT_VAL(pLeft);
328,360✔
641
  int32_t right = GET_INT32_VAL(pRight);
328,360✔
642
  if (left > right) return 1;
328,360✔
643
  if (left < right) return -1;
278,880✔
644
  return 0;
×
645
}
646

647
int32_t compareFloatInt64(const void *pLeft, const void *pRight) {
1,891,840✔
648
  float   left = GET_FLOAT_VAL(pLeft);
1,891,840✔
649
  int64_t right = GET_INT64_VAL(pRight);
1,891,840✔
650
  if (left > right) return 1;
1,891,840✔
651
  if (left < right) return -1;
429,586✔
652
  return 0;
8,724✔
653
}
654

655
int32_t compareFloatDouble(const void *pLeft, const void *pRight) {
587,988,994✔
656
  float  left = GET_FLOAT_VAL(pLeft);
587,988,994✔
657
  double right = GET_DOUBLE_VAL(pRight);
587,991,847✔
658

659
  if (isnan(left) && isnan(right)) {
587,990,399✔
660
    return 0;
×
661
  }
662

663
  if (isnan(left)) {
587,990,399✔
664
    return -1;
×
665
  }
666

667
  if (isnan(right)) {
587,990,399✔
668
    return 1;
×
669
  }
670

671
  if (FLT_EQUAL(left, right)) {
587,990,399✔
672
    return 0;
562,185✔
673
  }
674
  return FLT_GREATER(left, right) ? 1 : -1;
587,428,214✔
675
}
676

677
int32_t compareFloatUint8(const void *pLeft, const void *pRight) {
×
678
  float   left = GET_FLOAT_VAL(pLeft);
×
679
  uint8_t right = GET_UINT8_VAL(pRight);
×
680
  if (left > right) return 1;
×
681
  if (left < right) return -1;
×
682
  return 0;
×
683
}
684

685
int32_t compareFloatUint16(const void *pLeft, const void *pRight) {
×
686
  float    left = GET_FLOAT_VAL(pLeft);
×
687
  uint16_t right = GET_UINT16_VAL(pRight);
×
688
  if (left > right) return 1;
×
689
  if (left < right) return -1;
×
690
  return 0;
×
691
}
692

693
int32_t compareFloatUint32(const void *pLeft, const void *pRight) {
×
694
  float    left = GET_FLOAT_VAL(pLeft);
×
695
  uint32_t right = GET_UINT32_VAL(pRight);
×
696
  if (left > right) return 1;
×
697
  if (left < right) return -1;
×
698
  return 0;
×
699
}
700

701
int32_t compareFloatUint64(const void *pLeft, const void *pRight) {
×
702
  float    left = GET_FLOAT_VAL(pLeft);
×
703
  uint64_t right = GET_UINT64_VAL(pRight);
×
704
  if (left > right) return 1;
×
705
  if (left < right) return -1;
×
706
  return 0;
×
707
}
708

709
int32_t compareDoubleInt8(const void *pLeft, const void *pRight) {
2,091,997,285✔
710
  double left = GET_DOUBLE_VAL(pLeft);
2,091,997,285✔
711
  int8_t right = GET_INT8_VAL(pRight);
2,092,056,003✔
712
  if (left > right) return 1;
2,093,198,503✔
713
  if (left < right) return -1;
1,272,000,871✔
714
  return 0;
266,032,819✔
715
}
716

717
int32_t compareDoubleInt16(const void *pLeft, const void *pRight) {
93,000,000✔
718
  double  left = GET_DOUBLE_VAL(pLeft);
93,000,000✔
719
  int16_t right = GET_INT16_VAL(pRight);
93,000,000✔
720
  if (left > right) return 1;
93,000,000✔
721
  if (left < right) return -1;
93,000,000✔
722
  return 0;
93,000,000✔
723
}
724

725
int32_t compareDoubleInt32(const void *pLeft, const void *pRight) {
9,184,528✔
726
  double  left = GET_DOUBLE_VAL(pLeft);
9,184,528✔
727
  int32_t right = GET_INT32_VAL(pRight);
9,184,528✔
728
  if (left > right) return 1;
9,184,528✔
729
  if (left < right) return -1;
8,060,426✔
730
  return 0;
42,138✔
731
}
732

733
int32_t compareDoubleInt64(const void *pLeft, const void *pRight) {
2,147,483,647✔
734
  double  left = GET_DOUBLE_VAL(pLeft);
2,147,483,647✔
735
  int64_t right = GET_INT64_VAL(pRight);
2,147,483,647✔
736
  if (left > right) return 1;
2,147,483,647✔
737
  if (left < right) return -1;
1,401,216,744✔
738
  return 0;
322,818,284✔
739
}
740

741
int32_t compareDoubleFloat(const void *pLeft, const void *pRight) {
38,622✔
742
  double left = GET_DOUBLE_VAL(pLeft);
38,622✔
743
  float  right = GET_FLOAT_VAL(pRight);
38,622✔
744

745
  if (isnan(left) && isnan(right)) {
38,622✔
746
    return 0;
×
747
  }
748

749
  if (isnan(left)) {
38,622✔
750
    return -1;
×
751
  }
752

753
  if (isnan(right)) {
38,622✔
754
    return 1;
×
755
  }
756

757
  if (FLT_EQUAL(left, right)) {
38,622✔
758
    return 0;
2,134✔
759
  }
760
  return FLT_GREATER(left, right) ? 1 : -1;
36,488✔
761
}
762

763
int32_t compareDoubleUint8(const void *pLeft, const void *pRight) {
×
764
  double  left = GET_DOUBLE_VAL(pLeft);
×
765
  uint8_t right = GET_UINT8_VAL(pRight);
×
766
  if (left > right) return 1;
×
767
  if (left < right) return -1;
×
768
  return 0;
×
769
}
770

771
int32_t compareDoubleUint16(const void *pLeft, const void *pRight) {
×
772
  double   left = GET_DOUBLE_VAL(pLeft);
×
773
  uint16_t right = GET_UINT16_VAL(pRight);
×
774
  if (left > right) return 1;
×
775
  if (left < right) return -1;
×
776
  return 0;
×
777
}
778

779
int32_t compareDoubleUint32(const void *pLeft, const void *pRight) {
×
780
  double   left = GET_DOUBLE_VAL(pLeft);
×
781
  uint32_t right = GET_UINT32_VAL(pRight);
×
782
  if (left > right) return 1;
×
783
  if (left < right) return -1;
×
784
  return 0;
×
785
}
786

787
int32_t compareDoubleUint64(const void *pLeft, const void *pRight) {
×
788
  double   left = GET_DOUBLE_VAL(pLeft);
×
789
  uint64_t right = GET_UINT64_VAL(pRight);
×
790
  if (left > right) return 1;
×
791
  if (left < right) return -1;
×
792
  return 0;
×
793
}
794

795
int32_t compareUint8Int8(const void *pLeft, const void *pRight) {
1,956,570✔
796
  uint8_t left = GET_UINT8_VAL(pLeft);
1,956,570✔
797
  int8_t  right = GET_INT8_VAL(pRight);
1,956,570✔
798
  if (left > right) return 1;
1,956,570✔
799
  if (left < right) return -1;
644,496✔
800
  return 0;
419,020✔
801
}
802

803
int32_t compareUint8Int16(const void *pLeft, const void *pRight) {
116✔
804
  uint8_t left = GET_UINT8_VAL(pLeft);
116✔
805
  int16_t right = GET_INT16_VAL(pRight);
116✔
806
  if (left > right) return 1;
116✔
807
  if (left < right) return -1;
116✔
808
  return 0;
58✔
809
}
810

811
int32_t compareUint8Int32(const void *pLeft, const void *pRight) {
×
812
  uint8_t left = GET_UINT8_VAL(pLeft);
×
813
  int32_t right = GET_INT32_VAL(pRight);
×
814
  if (left > right) return 1;
×
815
  if (left < right) return -1;
×
816
  return 0;
×
817
}
818

819
int32_t compareUint8Int64(const void *pLeft, const void *pRight) {
×
820
  uint8_t left = GET_UINT8_VAL(pLeft);
×
821
  int64_t right = GET_INT64_VAL(pRight);
×
822
  if (left > right) return 1;
×
823
  if (left < right) return -1;
×
824
  return 0;
×
825
}
826

827
int32_t compareUint8Float(const void *pLeft, const void *pRight) {
×
828
  uint8_t left = GET_UINT8_VAL(pLeft);
×
829
  float   right = GET_FLOAT_VAL(pRight);
×
830
  if (left > right) return 1;
×
831
  if (left < right) return -1;
×
832
  return 0;
×
833
}
834

835
int32_t compareUint8Double(const void *pLeft, const void *pRight) {
×
836
  uint8_t left = GET_UINT8_VAL(pLeft);
×
837
  double  right = GET_DOUBLE_VAL(pRight);
×
838
  if (left > right) return 1;
×
839
  if (left < right) return -1;
×
840
  return 0;
×
841
}
842

843
int32_t compareUint8Uint16(const void *pLeft, const void *pRight) {
×
844
  uint8_t  left = GET_UINT8_VAL(pLeft);
×
845
  uint16_t right = GET_UINT16_VAL(pRight);
×
846
  if (left > right) return 1;
×
847
  if (left < right) return -1;
×
848
  return 0;
×
849
}
850

851
int32_t compareUint8Uint32(const void *pLeft, const void *pRight) {
×
852
  uint8_t  left = GET_UINT8_VAL(pLeft);
×
853
  uint32_t right = GET_UINT32_VAL(pRight);
×
854
  if (left > right) return 1;
×
855
  if (left < right) return -1;
×
856
  return 0;
×
857
}
858

859
int32_t compareUint8Uint64(const void *pLeft, const void *pRight) {
×
860
  uint8_t  left = GET_UINT8_VAL(pLeft);
×
861
  uint64_t right = GET_UINT64_VAL(pRight);
×
862
  if (left > right) return 1;
×
863
  if (left < right) return -1;
×
864
  return 0;
×
865
}
866

867
int32_t compareUint16Int8(const void *pLeft, const void *pRight) {
1,731,018✔
868
  uint16_t left = GET_UINT16_VAL(pLeft);
1,731,018✔
869
  int8_t   right = GET_INT8_VAL(pRight);
1,731,018✔
870
  if (left > right) return 1;
1,731,018✔
871
  if (left < right) return -1;
513,406✔
872
  return 0;
375,100✔
873
}
874

UNCOV
875
int32_t compareUint16Int16(const void *pLeft, const void *pRight) {
×
UNCOV
876
  uint16_t left = GET_UINT16_VAL(pLeft);
×
UNCOV
877
  int16_t  right = GET_INT16_VAL(pRight);
×
UNCOV
878
  if (left > right) return 1;
×
UNCOV
879
  if (left < right) return -1;
×
UNCOV
880
  return 0;
×
881
}
882

883
int32_t compareUint16Int32(const void *pLeft, const void *pRight) {
116✔
884
  uint16_t left = GET_UINT16_VAL(pLeft);
116✔
885
  int32_t  right = GET_INT32_VAL(pRight);
116✔
886
  if (left > right) return 1;
116✔
887
  if (left < right) return -1;
116✔
888
  return 0;
58✔
889
}
890

891
int32_t compareUint16Int64(const void *pLeft, const void *pRight) {
×
892
  uint16_t left = GET_UINT16_VAL(pLeft);
×
893
  int64_t  right = GET_INT64_VAL(pRight);
×
894
  if (left > right) return 1;
×
895
  if (left < right) return -1;
×
896
  return 0;
×
897
}
898

899
int32_t compareUint16Float(const void *pLeft, const void *pRight) {
×
900
  uint16_t left = GET_UINT16_VAL(pLeft);
×
901
  float    right = GET_FLOAT_VAL(pRight);
×
902
  if (left > right) return 1;
×
903
  if (left < right) return -1;
×
904
  return 0;
×
905
}
906

907
int32_t compareUint16Double(const void *pLeft, const void *pRight) {
×
908
  uint16_t left = GET_UINT16_VAL(pLeft);
×
909
  double   right = GET_DOUBLE_VAL(pRight);
×
910
  if (left > right) return 1;
×
911
  if (left < right) return -1;
×
912
  return 0;
×
913
}
914

915
int32_t compareUint16Uint8(const void *pLeft, const void *pRight) {
×
916
  uint16_t left = GET_UINT16_VAL(pLeft);
×
917
  uint8_t  right = GET_UINT8_VAL(pRight);
×
918
  if (left > right) return 1;
×
919
  if (left < right) return -1;
×
920
  return 0;
×
921
}
922

923
int32_t compareUint16Uint32(const void *pLeft, const void *pRight) {
×
924
  uint16_t left = GET_UINT16_VAL(pLeft);
×
925
  uint32_t right = GET_UINT32_VAL(pRight);
×
926
  if (left > right) return 1;
×
927
  if (left < right) return -1;
×
928
  return 0;
×
929
}
930

931
int32_t compareUint16Uint64(const void *pLeft, const void *pRight) {
×
932
  uint16_t left = GET_UINT16_VAL(pLeft);
×
933
  uint64_t right = GET_UINT64_VAL(pRight);
×
934
  if (left > right) return 1;
×
935
  if (left < right) return -1;
×
936
  return 0;
×
937
}
938

939
int32_t compareUint32Int8(const void *pLeft, const void *pRight) {
1,980,943✔
940
  uint32_t left = GET_UINT32_VAL(pLeft);
1,980,943✔
941
  int8_t   right = GET_INT8_VAL(pRight);
1,980,943✔
942
  if (right < 0) return 1;
1,980,943✔
943
  if (left > (uint32_t)right) return 1;
1,980,943✔
944
  if (left < (uint32_t)right) return -1;
627,505✔
945
  return 0;
408,171✔
946
}
947

948
int32_t compareUint32Int16(const void *pLeft, const void *pRight) {
3,388✔
949
  uint32_t left = GET_UINT32_VAL(pLeft);
3,388✔
950
  int16_t  right = GET_INT16_VAL(pRight);
3,388✔
951
  if (right < 0) return 1;
3,388✔
952
  if (left > (uint32_t)right) return 1;
3,388✔
953
  if (left < (uint32_t)right) return -1;
3,265✔
954
  return 0;
3,142✔
955
}
956

957
int32_t compareUint32Int32(const void *pLeft, const void *pRight) {
52,105,210✔
958
  uint32_t left = GET_UINT32_VAL(pLeft);
52,105,210✔
959
  int32_t  right = GET_INT32_VAL(pRight);
52,105,210✔
960
  if (right < 0) return 1;
52,105,210✔
961
  if (left > (uint32_t)right) return 1;
52,105,210✔
962
  if (left < (uint32_t)right) return -1;
52,105,210✔
963
  return 0;
2,084✔
964
}
965

966
int32_t compareUint32Int64(const void *pLeft, const void *pRight) {
93,494✔
967
  uint32_t left = GET_UINT32_VAL(pLeft);
93,494✔
968
  int64_t  right = GET_INT64_VAL(pRight);
93,494✔
969
  if (left > right) return 1;
93,968✔
970
  if (left < right) return -1;
45,620✔
971
  return 0;
58✔
972
}
973

974
int32_t compareUint32Float(const void *pLeft, const void *pRight) {
×
975
  uint32_t left = GET_UINT32_VAL(pLeft);
×
976
  float    right = GET_FLOAT_VAL(pRight);
×
977
  if (left > right) return 1;
×
978
  if (left < right) return -1;
×
979
  return 0;
×
980
}
981

982
int32_t compareUint32Double(const void *pLeft, const void *pRight) {
1,566✔
983
  uint32_t left = GET_UINT32_VAL(pLeft);
1,566✔
984
  double   right = GET_DOUBLE_VAL(pRight);
1,566✔
985
  if (left > right) return 1;
1,566✔
986
  if (left < right) return -1;
1,566✔
987
  return 0;
×
988
}
989

990
int32_t compareUint32Uint8(const void *pLeft, const void *pRight) {
×
991
  uint32_t left = GET_UINT32_VAL(pLeft);
×
992
  uint8_t  right = GET_UINT8_VAL(pRight);
×
993
  if (left > right) return 1;
×
994
  if (left < right) return -1;
×
995
  return 0;
×
996
}
997

998
int32_t compareUint32Uint16(const void *pLeft, const void *pRight) {
×
999
  uint32_t left = GET_UINT32_VAL(pLeft);
×
1000
  uint16_t right = GET_UINT16_VAL(pRight);
×
1001
  if (left > right) return 1;
×
1002
  if (left < right) return -1;
×
1003
  return 0;
×
1004
}
1005

1006
int32_t compareUint32Uint64(const void *pLeft, const void *pRight) {
×
1007
  uint32_t left = GET_UINT32_VAL(pLeft);
×
1008
  uint64_t right = GET_UINT64_VAL(pRight);
×
1009
  if (left > right) return 1;
×
1010
  if (left < right) return -1;
×
1011
  return 0;
×
1012
}
1013

1014
int32_t compareUint64Int8(const void *pLeft, const void *pRight) {
3,215,007✔
1015
  uint64_t left = GET_UINT64_VAL(pLeft);
3,215,007✔
1016
  int8_t   right = GET_INT8_VAL(pRight);
3,215,007✔
1017
  if (right < 0) return 1;
3,215,007✔
1018
  if (left > (uint64_t)right) return 1;
3,215,007✔
1019
  if (left < (uint64_t)right) return -1;
1,559,523✔
1020
  return 0;
944,733✔
1021
}
1022

1023
int32_t compareUint64Int16(const void *pLeft, const void *pRight) {
3,060✔
1024
  uint64_t left = GET_UINT64_VAL(pLeft);
3,060✔
1025
  int16_t  right = GET_INT16_VAL(pRight);
3,060✔
1026
  if (right < 0) return 1;
3,060✔
1027
  if (left > (uint64_t)right) return 1;
3,060✔
1028
  if (left < (uint64_t)right) return -1;
3,060✔
1029
  return 0;
3,060✔
1030
}
1031

1032
int32_t compareUint64Int32(const void *pLeft, const void *pRight) {
293,188✔
1033
  uint64_t left = GET_UINT64_VAL(pLeft);
293,188✔
1034
  int32_t  right = GET_INT32_VAL(pRight);
293,188✔
1035
  if (right < 0) return 1;
293,188✔
1036
  if (left > (uint64_t)right) return 1;
293,188✔
1037
  if (left < (uint64_t)right) return -1;
293,188✔
1038
  return 0;
145,462✔
1039
}
1040

1041
int32_t compareUint64Int64(const void *pLeft, const void *pRight) {
1,706,082✔
1042
  uint64_t left = GET_UINT64_VAL(pLeft);
1,706,082✔
1043
  int64_t  right = GET_INT64_VAL(pRight);
1,706,082✔
1044
  if (right < 0) return 1;
1,706,082✔
1045
  if (left > (uint64_t)right) return 1;
1,706,082✔
1046
  if (left < (uint64_t)right) return -1;
1,706,082✔
1047
  return 0;
1,596,672✔
1048
}
1049

1050
int32_t compareUint64Float(const void *pLeft, const void *pRight) {
×
1051
  uint64_t left = GET_UINT64_VAL(pLeft);
×
1052
  float    right = GET_FLOAT_VAL(pRight);
×
1053
  if (left > right) return 1;
×
1054
  if (left < right) return -1;
×
1055
  return 0;
×
1056
}
1057

1058
int32_t compareUint64Double(const void *pLeft, const void *pRight) {
×
1059
  uint64_t left = GET_UINT64_VAL(pLeft);
×
1060
  double   right = GET_DOUBLE_VAL(pRight);
×
1061
  if (left > right) return 1;
×
1062
  if (left < right) return -1;
×
1063
  return 0;
×
1064
}
1065

1066
int32_t compareUint64Uint8(const void *pLeft, const void *pRight) {
×
1067
  uint64_t left = GET_UINT64_VAL(pLeft);
×
1068
  uint8_t  right = GET_UINT8_VAL(pRight);
×
1069
  if (left > right) return 1;
×
1070
  if (left < right) return -1;
×
1071
  return 0;
×
1072
}
1073

1074
int32_t compareUint64Uint16(const void *pLeft, const void *pRight) {
×
1075
  uint64_t left = GET_UINT64_VAL(pLeft);
×
1076
  uint16_t right = GET_UINT16_VAL(pRight);
×
1077
  if (left > right) return 1;
×
1078
  if (left < right) return -1;
×
1079
  return 0;
×
1080
}
1081

1082
int32_t compareUint64Uint32(const void *pLeft, const void *pRight) {
×
1083
  uint64_t left = GET_UINT64_VAL(pLeft);
×
1084
  uint32_t right = GET_UINT32_VAL(pRight);
×
1085
  if (left > right) return 1;
×
1086
  if (left < right) return -1;
×
1087
  return 0;
×
1088
}
1089

1090
int32_t compareDecimal64(const void *pleft, const void *pright) {
12,785,880✔
1091
  if (decimal64Compare(OP_TYPE_GREATER_THAN, pleft, pright)) return 1;
12,785,880✔
1092
  if (decimal64Compare(OP_TYPE_LOWER_THAN, pleft, pright)) return -1;
12,785,880✔
1093
  return 0;
12,785,880✔
1094
}
1095

1096
int32_t compareDecimal128(const void *pleft, const void *pright) {
578,729,775✔
1097
  if (decimalCompare(OP_TYPE_GREATER_THAN, pleft, pright)) return 1;
578,729,775✔
1098
  if (decimalCompare(OP_TYPE_LOWER_THAN, pleft, pright)) return -1;
309,504,194✔
1099
  return 0;
41,483,327✔
1100
}
1101

1102
int32_t compareDecimal64SameScale(const void *pleft, const void *pright) {
109,801,300✔
1103
  const SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
109,801,300✔
1104
  if (pOps->gt(pleft, pright, DECIMAL_WORD_NUM(Decimal64))) return 1;
109,801,300✔
1105
  if (pOps->lt(pleft, pright, DECIMAL_WORD_NUM(Decimal64))) return -1;
63,608,300✔
1106
  return 0;
6,911,800✔
1107
}
1108

1109
int32_t compareDecimal64SameScaleDesc(const void *pLeft, const void *pRight) {
×
1110
  const SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64);
×
1111
  if (pOps->lt(pLeft, pRight, DECIMAL_WORD_NUM(Decimal64))) return 1;
×
1112
  if (pOps->gt(pLeft, pRight, DECIMAL_WORD_NUM(Decimal64))) return -1;
×
1113
  return 0;
×
1114
}
1115

1116
int32_t compareDecimal128SameScale(const void *pleft, const void *pright) {
335,799,800✔
1117
  const SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
335,799,800✔
1118
  if (pOps->gt(pleft, pright, DECIMAL_WORD_NUM(Decimal))) return 1;
335,799,800✔
1119
  if (pOps->lt(pleft, pright, DECIMAL_WORD_NUM(Decimal))) return -1;
194,971,700✔
1120
  return 0;
17,669,400✔
1121
}
1122

1123
int32_t compareDecimal128SameScaleDesc(const void *pLeft, const void *pRight) {
×
1124
  const SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
×
1125
  if (pOps->lt(pLeft, pRight, DECIMAL_WORD_NUM(Decimal))) return 1;
×
1126
  if (pOps->gt(pLeft, pRight, DECIMAL_WORD_NUM(Decimal))) return -1;
×
1127
  return 0;
×
1128
}
1129

1130
int32_t compareJsonValDesc(const void *pLeft, const void *pRight) { return compareJsonVal(pRight, pLeft); }
22,797✔
1131

1132
/*
1133
 * Compare two strings
1134
 *    TSDB_MATCH:            Match
1135
 *    TSDB_NOMATCH:          No match
1136
 *    TSDB_NOWILDCARDMATCH:  No match in spite of having * or % wildcards.
1137
 * Like matching rules:
1138
 *      '%': Matches zero or more characters
1139
 *      '_': Matches one character
1140
 *
1141
 */
1142
int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t ssize,
2,147,483,647✔
1143
                     const SPatternCompareInfo *pInfo) {
1144
  char c, c1;
1145
  int32_t i = 0;
2,147,483,647✔
1146
  int32_t j = 0;
2,147,483,647✔
1147
  int32_t nMatchChar = 0;
2,147,483,647✔
1148

1149
  while ((i < psize) && ((c = pattern[i++]) != 0)) {
2,147,483,647✔
1150
    bool escaped = false;
1,345,517,402✔
1151

1152
    // handle escaped characters
1153
    if (c == '\\' && i < psize && 
1,345,517,402✔
1154
        (pattern[i] == pInfo->matchOne || pattern[i] == pInfo->matchAll || pattern[i] == '\\')) {
44,568✔
1155
      c = pattern[i++];
714,230✔
1156
      escaped = true;
43,208✔
1157
    }
1158

1159
    // handle matchAll wildcard '%' or '*'
1160
    if (!escaped && c == pInfo->matchAll) {
1,344,847,710✔
1161
      // skip continues matchAll and matchOne
1162
      while ((i < psize) && ((c = pattern[i++]) == pInfo->matchAll || c == pInfo->matchOne)) {
202,159,125✔
1163
        if (c == pInfo->matchOne) {
3,208,718✔
1164
          if (j >= ssize || str[j++] == 0) {
1,629,368✔
1165
            return TSDB_PATTERN_NOWILDCARDMATCH;
×
1166
          }
1167
          ++nMatchChar;
1,629,368✔
1168
        }
1169
      }
1170

1171
      // handle wildcard at the end of the pattern
1172
      if (i >= psize && (c == pInfo->matchOne || c == pInfo->matchAll)) {
198,951,069✔
1173
        return TSDB_PATTERN_MATCH;
179,325,290✔
1174
      }
1175

1176
      // now c is the next character after matchAll
1177
      // handle escaped characters (if after wildcard)
1178
      if (c == '\\' && i < psize && 
19,626,464✔
1179
          (pattern[i] == pInfo->matchOne || pattern[i] == pInfo->matchAll || pattern[i] == '\\')) {
290,181✔
1180
        c = pattern[i++];
290,181✔
1181
      }
1182

1183
      char rejectList[2] = {toupper(c), tolower(c)};
19,626,464✔
1184
      const char *remainStr = str + nMatchChar;
19,624,300✔
1185
      int32_t remainSize = ssize - nMatchChar;
19,626,940✔
1186

1187
      // greedily match the rest of the pattern
1188
      while (1) {
2,147,483,647✔
1189
        // find the first occurrence of the reject character in the remaining string
1190
        // this segments the string for potential recursive matching
1191
        size_t n = tstrncspn(remainStr, remainSize, rejectList, 2);
2,147,483,647✔
1192
        remainStr += n;
2,147,483,647✔
1193
        remainSize -= n;
2,147,483,647✔
1194

1195
        if (remainSize <= 0 || remainStr[0] == 0) {
2,147,483,647✔
1196
          break;
1197
        }
1198

1199
        int32_t ret = patternMatch(&pattern[i], psize - i, ++remainStr, --remainSize, pInfo);
2,147,483,647✔
1200
        if (ret != TSDB_PATTERN_NOMATCH) {
2,147,483,647✔
1201
          return ret;
8,862,698✔
1202
        }
1203
      }
1204

1205
      return TSDB_PATTERN_NOWILDCARDMATCH;
10,814,160✔
1206
    }
1207

1208
    // handle normal character or matchOne wildcard '_'
1209
    if (j < ssize) {
1,146,741,714✔
1210
      c1 = str[j++];
1,146,099,458✔
1211
      ++nMatchChar;
1,146,123,453✔
1212

1213
      if ((c == c1 || tolower(c) == tolower(c1)) || 
1,146,123,453✔
1214
          (!escaped && c == pInfo->matchOne && c1 != 0)) {
12,921,039✔
1215
        continue;
1,134,087,120✔
1216
      }
1217
    }
1218

1219
    return TSDB_PATTERN_NOMATCH;
12,678,891✔
1220
  }
1221

1222
  return (j >= ssize || str[j] == 0) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH;
2,147,483,647✔
1223
}
1224

1225
int32_t rawStrPatternMatch(const char *str, const char *pattern) {
467,622✔
1226
  SPatternCompareInfo pInfo = PATTERN_COMPARE_INFO_INITIALIZER;
467,622✔
1227

1228
  size_t pLen = strlen(pattern);
467,622✔
1229
  size_t sz = strlen(str);
467,622✔
1230
  if (pLen > TSDB_MAX_FIELD_LEN) {
467,622✔
1231
    return 1;
×
1232
  }
1233

1234
  int32_t ret = patternMatch(pattern, pLen, str, sz, &pInfo);
467,622✔
1235
  return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
467,622✔
1236
}
1237

1238
// same logic with patternMatch, but for UCS4 strings
1239
int32_t wcsPatternMatch(const TdUcs4 *pattern, size_t psize, const TdUcs4 *str, size_t ssize,
208,452,010✔
1240
                        const SPatternCompareInfo *pInfo) {
1241
  TdUcs4 c, c1;
1242
  int32_t i = 0;
208,452,010✔
1243
  int32_t j = 0;
208,452,010✔
1244
  int32_t nMatchChar = 0;
208,452,010✔
1245

1246
  while ((i < psize) && ((c = pattern[i++]) != 0)) {
1,234,769,198✔
1247
    bool escaped = false;
1,234,600,635✔
1248

1249
    if (c == '\\' && i < psize && 
1,234,600,635✔
1250
        (pattern[i] == pInfo->umatchOne || pattern[i] == pInfo->umatchAll || pattern[i] == '\\')) {
×
1251
      c = pattern[i++];
×
1252
      escaped = true;
×
1253
    }
1254

1255
    if (!escaped && c == pInfo->umatchAll) {
1,234,674,623✔
1256
      while ((i < psize) && ((c = pattern[i++]) == pInfo->umatchAll || c == pInfo->umatchOne)) {
207,179,389✔
UNCOV
1257
        if (c == pInfo->umatchOne) {
×
1258
          if (j >= ssize || str[j++] == 0) {
×
1259
            return TSDB_PATTERN_NOWILDCARDMATCH;
×
1260
          }
1261
          ++nMatchChar;
×
1262
        }
1263
      }
1264

1265
      if (i >= psize && (c == pInfo->matchOne || c == pInfo->matchAll)) {
207,189,763✔
1266
        return TSDB_PATTERN_MATCH;
206,073,270✔
1267
      }
1268

1269
      if (c == '\\' && i < psize && 
1,117,159✔
1270
          (pattern[i] == pInfo->umatchOne || pattern[i] == pInfo->umatchAll || pattern[i] == '\\')) {
×
1271
        c = pattern[i++];
×
1272
      }
1273

1274
      TdUcs4 rejectList[2] = {toupper(c), tolower(c)};
1,117,159✔
1275
      const TdUcs4 *remainStr = str + nMatchChar;
1,118,029✔
1276
      int32_t remainSize = ssize - nMatchChar;
1,118,029✔
1277

1278
      while (1) {
1,060,668✔
1279
        size_t n = twcsncspn(remainStr, remainSize, rejectList, 2);
2,178,697✔
1280
        remainStr += n;
2,176,585✔
1281
        remainSize -= n;
2,176,585✔
1282

1283
        if (remainSize <= 0 || remainStr[0] == 0) {
2,176,585✔
1284
          break;
1285
        }
1286

1287
        int32_t ret = wcsPatternMatch(&pattern[i], psize - i, ++remainStr, --remainSize, pInfo);
2,127,696✔
1288
        if (ret != TSDB_PATTERN_NOMATCH) {
2,130,336✔
1289
          return ret;
1,069,668✔
1290
        }
1291
      }
1292

1293
      return TSDB_PATTERN_NOWILDCARDMATCH;
48,889✔
1294
    }
1295

1296
    if (j < ssize) {
1,027,494,220✔
1297
      c1 = str[j++];
1,027,496,865✔
1298
      ++nMatchChar;
1,027,498,628✔
1299

1300
      if ((c == c1 || tolower(c) == tolower(c1)) || 
1,027,498,628✔
1301
          (!escaped && c == pInfo->umatchOne && c1 != 0)) {
1,333,110✔
1302
        continue;
1,026,317,188✔
1303
      }
1304
    }
1305

1306
    return TSDB_PATTERN_NOMATCH;
1,178,795✔
1307
  }
1308

1309
  return (j >= ssize || str[j] == 0) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH;
162,190✔
1310
}
1311

1312
int32_t comparestrRegexNMatch(const void *pLeft, const void *pRight) {
61,255,339✔
1313
  return comparestrRegexMatch(pLeft, pRight) ? 0 : 1;
61,255,339✔
1314
}
1315

1316
typedef struct UsingRegex {
1317
  regex_t pRegex;
1318
  int32_t lastUsedTime;
1319
} UsingRegex;
1320
typedef UsingRegex *HashRegexPtr;
1321

1322
typedef struct RegexCache {
1323
  SHashObj *regexHash;
1324
  void     *regexCacheTmr;
1325
  void     *timer;
1326
  SRWLatch  mutex;
1327
  bool      exit;
1328
  int8_t    inited;
1329
} RegexCache;
1330
static RegexCache sRegexCache;
1331
#define MAX_REGEX_CACHE_SIZE   20
1332
#define REGEX_CACHE_CLEAR_TIME 30
1333

1334
static void checkRegexCache(void *param, void *tmrId) {
1,909,355✔
1335
  int32_t code = 0;
1,909,355✔
1336
  taosRLockLatch(&sRegexCache.mutex);
1,909,355✔
1337
  if (sRegexCache.exit) {
1,909,355✔
1338
    goto _exit;
2,172✔
1339
  }
1340
  bool stopped = taosTmrReset(checkRegexCache, REGEX_CACHE_CLEAR_TIME * 1000, param, sRegexCache.regexCacheTmr, &tmrId);
1,907,183✔
1341
  if (stopped) {
1,907,183✔
1342
    uError("failed to reset regex cache timer");
×
1343
    goto _exit;
×
1344
  }
1345
  if (taosHashGetSize(sRegexCache.regexHash) < MAX_REGEX_CACHE_SIZE) {
1,907,183✔
1346
    goto _exit;
1,906,219✔
1347
  }
1348

1349
  if (taosHashGetSize(sRegexCache.regexHash) >= MAX_REGEX_CACHE_SIZE) {
964✔
1350
    UsingRegex **ppUsingRegex = taosHashIterate(sRegexCache.regexHash, NULL);
964✔
1351
    while ((ppUsingRegex != NULL)) {
101,220✔
1352
      if (taosGetTimestampSec() - (*ppUsingRegex)->lastUsedTime > REGEX_CACHE_CLEAR_TIME) {
100,256✔
1353
        size_t len = 0;
25,064✔
1354
        char  *key = (char *)taosHashGetKey(ppUsingRegex, &len);
25,064✔
1355
        if (TSDB_CODE_SUCCESS != taosHashRemove(sRegexCache.regexHash, key, len)) {
25,064✔
1356
          uError("failed to remove regex pattern %s from cache", key);
×
1357
          goto _exit;
×
1358
        }
1359
      }
1360
      ppUsingRegex = taosHashIterate(sRegexCache.regexHash, ppUsingRegex);
100,256✔
1361
    }
1362
  }
1363
_exit:
964✔
1364
  taosRUnLockLatch(&sRegexCache.mutex);
1,909,355✔
1365
}
1,909,355✔
1366

1367
void regexCacheFree(void *ppUsingRegex) {
93,332✔
1368
  regfree(&(*(UsingRegex **)ppUsingRegex)->pRegex);
93,332✔
1369
  taosMemoryFree(*(UsingRegex **)ppUsingRegex);
93,332✔
1370
}
93,332✔
1371

1372
int32_t InitRegexCache() {
1,724,262✔
1373
#ifdef WINDOWS
1374
  return 0;
1375
#endif
1376
  if (atomic_val_compare_exchange_8(&sRegexCache.inited, 0, 1) != 0) return TSDB_CODE_SUCCESS;
1,724,262✔
1377
  sRegexCache.regexHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
1,724,262✔
1378
  if (sRegexCache.regexHash == NULL) {
1,724,262✔
1379
    uError("failed to create RegexCache");
×
1380
    return terrno;
×
1381
  }
1382
  taosHashSetFreeFp(sRegexCache.regexHash, regexCacheFree);
1,724,262✔
1383
  sRegexCache.regexCacheTmr = taosTmrInit(0, 0, 0, "REGEXCACHE");
1,724,262✔
1384
  if (sRegexCache.regexCacheTmr == NULL) {
1,724,262✔
1385
    uError("failed to create regex cache check timer");
×
1386
    return terrno;
×
1387
  }
1388

1389
  sRegexCache.exit = false;
1,724,262✔
1390
  taosInitRWLatch(&sRegexCache.mutex);
1,724,262✔
1391
  sRegexCache.timer = taosTmrStart(checkRegexCache, REGEX_CACHE_CLEAR_TIME * 1000, NULL, sRegexCache.regexCacheTmr);
1,724,262✔
1392
  if (sRegexCache.timer == NULL) {
1,724,262✔
1393
    uError("failed to start regex cache timer");
×
1394
    return terrno;
×
1395
  }
1396

1397
  return TSDB_CODE_SUCCESS;
1,724,262✔
1398
}
1399

1400
void DestroyRegexCache() {
1,724,277✔
1401
#ifdef WINDOWS
1402
  return;
1403
#endif
1404
  int32_t code = 0;
1,724,277✔
1405
  uInfo("[regex cache] destroy regex cache");
1,724,277✔
1406
  bool ret = taosTmrStopA(&sRegexCache.timer);
1,724,277✔
1407
  if (!ret) {
1,724,277✔
1408
    uInfo("stop regex cache timer may be failed");
437,532✔
1409
  }
1410
  taosWLockLatch(&sRegexCache.mutex);
1,724,277✔
1411
  sRegexCache.exit = true;
1,724,277✔
1412
  taosWUnLockLatch(&sRegexCache.mutex);
1,724,277✔
1413
  taosHashCleanup(sRegexCache.regexHash);
1,724,277✔
1414
  sRegexCache.regexHash = NULL;
1,724,277✔
1415
  taosTmrCleanUp(sRegexCache.regexCacheTmr);
1,724,277✔
1416
  sRegexCache.regexCacheTmr = NULL;
1,724,277✔
1417
}
1,724,277✔
1418

1419
int32_t checkRegexPattern(const char *pPattern) {
5,736,197✔
1420
  if (pPattern == NULL) {
5,736,197✔
1421
    return TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
×
1422
  }
1423

1424
  regex_t regex;
5,731,817✔
1425
  int32_t cflags = REG_EXTENDED;
5,736,197✔
1426
  int32_t ret = regcomp(&regex, pPattern, cflags);
5,736,197✔
1427
  if (ret != 0) {
5,735,233✔
1428
    char msgbuf[256] = {0};
483,928✔
1429
    (void)regerror(ret, &regex, msgbuf, tListLen(msgbuf));
483,928✔
1430
    uError("Failed to compile regex pattern %s. reason %s", pPattern, msgbuf);
483,928✔
1431
    return TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
483,928✔
1432
  }
1433
  regfree(&regex);
5,251,305✔
1434
  return TSDB_CODE_SUCCESS;
5,252,269✔
1435
}
1436

1437
int32_t getRegComp(const char *pPattern, HashRegexPtr **regexRet) {
5,869,943✔
1438
  HashRegexPtr *ppUsingRegex = (HashRegexPtr *)taosHashAcquire(sRegexCache.regexHash, pPattern, strlen(pPattern));
5,869,943✔
1439
  if (ppUsingRegex != NULL) {
5,868,570✔
1440
    (*ppUsingRegex)->lastUsedTime = taosGetTimestampSec();
5,775,238✔
1441
    *regexRet = ppUsingRegex;
5,776,129✔
1442
    return TSDB_CODE_SUCCESS;
5,772,450✔
1443
  }
1444
  UsingRegex *pUsingRegex = taosMemoryMalloc(sizeof(UsingRegex));
93,332✔
1445
  if (pUsingRegex == NULL) {
93,332✔
1446
    uError("Failed to Malloc when compile regex pattern %s.", pPattern);
×
1447
    return terrno;
×
1448
  }
1449
  int32_t cflags = REG_EXTENDED;
93,332✔
1450
  int32_t ret = regcomp(&pUsingRegex->pRegex, pPattern, cflags);
93,332✔
1451
  if (ret != 0) {
93,332✔
1452
    char msgbuf[256] = {0};
×
1453
    (void)regerror(ret, &pUsingRegex->pRegex, msgbuf, tListLen(msgbuf));
×
1454
    uError("Failed to compile regex pattern %s. reason %s", pPattern, msgbuf);
×
1455
    taosMemoryFree(pUsingRegex);
×
1456
    return TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
×
1457
  }
1458

1459
  while (true) {
×
1460
    int code = taosHashPut(sRegexCache.regexHash, pPattern, strlen(pPattern), &pUsingRegex, sizeof(UsingRegex *));
93,332✔
1461
    if (code != 0 && code != TSDB_CODE_DUP_KEY) {
93,332✔
1462
      regexCacheFree(&pUsingRegex);
×
1463
      uError("Failed to put regex pattern %s into cache, exception internal error.", pPattern);
×
1464
      return code;
×
1465
    } else if (code == TSDB_CODE_DUP_KEY) {
93,332✔
1466
      terrno = 0;
951✔
1467
    }
1468
    ppUsingRegex = (UsingRegex **)taosHashAcquire(sRegexCache.regexHash, pPattern, strlen(pPattern));
93,332✔
1469
    if (ppUsingRegex) {
93,332✔
1470
      if (*ppUsingRegex != pUsingRegex) {
93,332✔
1471
        regexCacheFree(&pUsingRegex);
951✔
1472
      }
1473
      pUsingRegex = (*ppUsingRegex);
93,332✔
1474
      break;
93,332✔
1475
    } else {
1476
      continue;
×
1477
    }
1478
  }
1479
  pUsingRegex->lastUsedTime = taosGetTimestampSec();
93,332✔
1480
  *regexRet = ppUsingRegex;
93,332✔
1481
  return TSDB_CODE_SUCCESS;
93,332✔
1482
}
1483

1484
void releaseRegComp(UsingRegex **regex) { taosHashRelease(sRegexCache.regexHash, regex); }
5,869,943✔
1485

1486
static threadlocal UsingRegex **ppUsingRegex;
1487
static threadlocal regex_t     *pRegex;
1488
static threadlocal char        *pOldPattern = NULL;
1489

1490
#ifdef WINDOWS
1491
static threadlocal regex_t gRegex;
1492

1493
void DestoryThreadLocalRegComp() {
1494
  if (NULL != pOldPattern) {
1495
    regfree(&gRegex);
1496
    taosMemoryFree(pOldPattern);
1497
    pOldPattern = NULL;
1498
  }
1499
}
1500

1501
int32_t threadGetRegComp(regex_t **regex, const char *pPattern) {
1502
  if (NULL != pOldPattern) {
1503
    if (strcmp(pOldPattern, pPattern) == 0) {
1504
      *regex = &gRegex;
1505
      return 0;
1506
    } else {
1507
      DestoryThreadLocalRegComp();
1508
    }
1509
  }
1510
  pOldPattern = taosStrdup(pPattern);
1511
  if (NULL == pOldPattern) {
1512
    uError("Failed to Malloc when compile regex pattern %s.", pPattern);
1513
    return terrno;
1514
  }
1515
  int32_t cflags = REG_EXTENDED;
1516
  int32_t ret = regcomp(&gRegex, pPattern, cflags);
1517
  if (ret != 0) {
1518
    char msgbuf[256] = {0};
1519
    (void)regerror(ret, &gRegex, msgbuf, tListLen(msgbuf));
1520
    uError("Failed to compile regex pattern %s. reason %s", pPattern, msgbuf);
1521
    taosMemoryFree(pOldPattern);
1522
    pOldPattern = NULL;
1523
    return TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
1524
  }
1525
  *regex = &gRegex;
1526
  return 0;
1527
}
1528
#else
1529
void DestoryThreadLocalRegComp() {
192,295,306✔
1530
  if (NULL != pOldPattern) {
192,295,306✔
1531
    releaseRegComp(ppUsingRegex);
5,869,119✔
1532
    taosMemoryFree(pOldPattern);
5,869,943✔
1533
    ppUsingRegex = NULL;
5,868,637✔
1534
    pRegex = NULL;
5,868,637✔
1535
    pOldPattern = NULL;
5,868,637✔
1536
  }
1537
}
192,294,824✔
1538

1539
int32_t threadGetRegComp(regex_t **regex, const char *pPattern) {
658,362,366✔
1540
  if (NULL != pOldPattern) {
658,362,366✔
1541
    if (strcmp(pOldPattern, pPattern) == 0) {
657,882,913✔
1542
      *regex = pRegex;
652,511,483✔
1543
      return 0;
652,515,668✔
1544
    } else {
1545
      DestoryThreadLocalRegComp();
5,371,430✔
1546
    }
1547
  }
1548

1549
  HashRegexPtr *ppRegex = NULL;
5,855,902✔
1550
  int32_t       code = getRegComp(pPattern, &ppRegex);
5,868,215✔
1551
  if (code != TSDB_CODE_SUCCESS) {
5,865,782✔
1552
    return code;
×
1553
  }
1554
  pOldPattern = taosStrdup(pPattern);
5,865,782✔
1555
  if (NULL == pOldPattern) {
5,866,465✔
1556
    uError("Failed to Malloc when compile regex pattern %s.", pPattern);
×
1557
    return terrno;
×
1558
  }
1559
  ppUsingRegex = ppRegex;
5,866,465✔
1560
  pRegex = &((*ppUsingRegex)->pRegex);
5,866,465✔
1561
  *regex = &(*ppRegex)->pRegex;
5,866,418✔
1562
  return 0;
5,868,321✔
1563
}
1564
#endif
1565

1566
static int32_t doExecRegexMatch(const char *pString, const char *pPattern) {
658,308,286✔
1567
  int32_t ret = 0;
658,308,286✔
1568
  char    msgbuf[256] = {0};
658,308,286✔
1569

1570
  regex_t *regex = NULL;
658,310,546✔
1571
  ret = threadGetRegComp(&regex, pPattern);
658,319,148✔
1572
  if (ret != 0) {
658,310,401✔
1573
    return ret;
×
1574
  }
1575

1576
  regmatch_t pmatch[1];
658,310,401✔
1577
  ret = regexec(regex, pString, 1, pmatch, 0);
658,310,274✔
1578
  if (ret != 0 && ret != REG_NOMATCH) {
658,291,129✔
1579
    terrno = TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR;
×
1580
    (void)regerror(ret, regex, msgbuf, sizeof(msgbuf));
×
1581
    uDebug("Failed to match %s with pattern %s, reason %s", pString, pPattern, msgbuf)
×
1582
  }
1583

1584
  return (ret == 0) ? 0 : 1;
658,300,180✔
1585
}
1586

1587
int32_t comparestrRegexMatch(const void *pLeft, const void *pRight) {
553,570,481✔
1588
  size_t sz = varDataLen(pRight);
553,570,481✔
1589
  char  *pattern = taosMemoryMalloc(sz + 1);
553,570,481✔
1590
  if (NULL == pattern) {
553,561,741✔
1591
    return 1;  // terrno has been set
×
1592
  }
1593

1594
  (void)memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
553,561,741✔
1595
  pattern[sz] = 0;
553,562,692✔
1596

1597
  sz = varDataLen(pLeft);
553,561,930✔
1598
  char *str = taosMemoryMalloc(sz + 1);
553,444,146✔
1599
  if (NULL == str) {
553,541,341✔
1600
    taosMemoryFree(pattern);
×
1601
    return 1;  // terrno has been set
×
1602
  }
1603

1604
  (void)memcpy(str, varDataVal(pLeft), sz);
553,541,341✔
1605
  str[sz] = 0;
553,440,201✔
1606

1607
  int32_t ret = doExecRegexMatch(str, pattern);
553,553,135✔
1608

1609
  taosMemoryFree(str);
553,560,193✔
1610
  taosMemoryFree(pattern);
553,566,879✔
1611

1612
  return (ret == 0) ? 0 : 1;
553,565,026✔
1613
}
1614

1615
int32_t comparewcsRegexMatch(const void *pString, const void *pPattern) {
104,733,654✔
1616
  size_t len = varDataLen(pPattern);
104,733,654✔
1617
  char  *pattern = taosMemoryMalloc(len + 1);
104,733,654✔
1618
  if (NULL == pattern) {
104,735,763✔
1619
    return 1;  // terrno has been set
×
1620
  }
1621

1622
  int convertLen = taosUcs4ToMbs((TdUcs4 *)varDataVal(pPattern), len, pattern, NULL);
104,735,763✔
1623
  if (convertLen < 0) {
104,737,506✔
1624
    taosMemoryFree(pattern);
×
1625
    return 1;  // terrno has been set
×
1626
  }
1627

1628
  pattern[convertLen] = 0;
104,737,506✔
1629

1630
  len = varDataLen(pString);
104,737,975✔
1631
  char *str = taosMemoryMalloc(len + 1);
104,737,975✔
1632
  if (NULL == str) {
104,729,178✔
1633
    taosMemoryFree(pattern);
×
1634
    return 1;  // terrno has been set
×
1635
  }
1636

1637
  convertLen = taosUcs4ToMbs((TdUcs4 *)varDataVal(pString), len, str, NULL);
104,729,178✔
1638
  if (convertLen < 0) {
104,736,473✔
1639
    taosMemoryFree(str);
×
1640
    taosMemoryFree(pattern);
×
1641
    return 1;  // terrno has been set
×
1642
  }
1643

1644
  str[convertLen] = 0;
104,736,473✔
1645

1646
  int32_t ret = doExecRegexMatch(str, pattern);
104,736,473✔
1647

1648
  taosMemoryFree(str);
104,740,326✔
1649
  taosMemoryFree(pattern);
104,738,919✔
1650

1651
  return (ret == 0) ? 0 : 1;
104,739,039✔
1652
}
1653

1654
int32_t comparewcsRegexNMatch(const void *pLeft, const void *pRight) {
54,928,023✔
1655
  return comparewcsRegexMatch(pLeft, pRight) ? 0 : 1;
54,928,023✔
1656
}
1657

1658
int32_t taosArrayCompareString(const void *a, const void *b) {
13,961✔
1659
  const char *x = *(const char **)a;
13,961✔
1660
  const char *y = *(const char **)b;
13,961✔
1661

1662
  return strcmp(x, y);
13,961✔
1663
}
1664

1665
int32_t comparestrPatternMatch(const void *pLeft, const void *pRight) {
212,921,013✔
1666
  SPatternCompareInfo pInfo = PATTERN_COMPARE_INFO_INITIALIZER;
212,921,013✔
1667

1668
  if (varDataTLen(pRight) > TSDB_MAX_FIELD_LEN) {
212,934,035✔
1669
    return 1;
×
1670
  }
1671
  size_t pLen = varDataLen(pRight);
212,940,844✔
1672
  size_t sz = varDataLen(pLeft);
212,952,404✔
1673

1674
  int32_t ret = patternMatch(varDataVal(pRight), pLen, varDataVal(pLeft), sz, &pInfo);
212,976,962✔
1675
  return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
212,942,679✔
1676
}
1677

1678
int32_t comparestrPatternNMatch(const void *pLeft, const void *pRight) {
180,556✔
1679
  return comparestrPatternMatch(pLeft, pRight) ? 0 : 1;
180,556✔
1680
}
1681

1682
int32_t comparewcsPatternMatch(const void *pLeft, const void *pRight) {
206,299,449✔
1683
  SPatternCompareInfo pInfo = PATTERN_COMPARE_INFO_INITIALIZER;
206,299,449✔
1684

1685
  size_t psize = varDataLen(pRight);
206,303,265✔
1686

1687
  int32_t ret = wcsPatternMatch((TdUcs4 *)varDataVal(pRight), psize / TSDB_NCHAR_SIZE, (TdUcs4 *)varDataVal(pLeft),
206,305,776✔
1688
                                varDataLen(pLeft) / TSDB_NCHAR_SIZE, &pInfo);
206,304,273✔
1689
  return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
206,295,356✔
1690
}
1691

1692
int32_t comparewcsPatternNMatch(const void *pLeft, const void *pRight) {
×
1693
  return comparewcsPatternMatch(pLeft, pRight) ? 0 : 1;
×
1694
}
1695

1696
__compar_fn_t getComparFunc(int32_t type, int32_t optr) {
893,093,457✔
1697
  __compar_fn_t comparFn = NULL;
893,093,457✔
1698

1699
  if (optr == OP_TYPE_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_VARBINARY &&
893,093,457✔
1700
                             type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
×
1701
    switch (type) {
×
1702
      case TSDB_DATA_TYPE_BOOL:
×
1703
      case TSDB_DATA_TYPE_TINYINT:
1704
      case TSDB_DATA_TYPE_UTINYINT:
1705
        return setChkInBytes1;
×
1706
      case TSDB_DATA_TYPE_SMALLINT:
×
1707
      case TSDB_DATA_TYPE_USMALLINT:
1708
        return setChkInBytes2;
×
1709
      case TSDB_DATA_TYPE_INT:
×
1710
      case TSDB_DATA_TYPE_UINT:
1711
      case TSDB_DATA_TYPE_FLOAT:
1712
        return setChkInBytes4;
×
1713
      case TSDB_DATA_TYPE_BIGINT:
×
1714
      case TSDB_DATA_TYPE_UBIGINT:
1715
      case TSDB_DATA_TYPE_DOUBLE:
1716
      case TSDB_DATA_TYPE_TIMESTAMP:
1717
        return setChkInBytes8;
×
1718
      default:
×
1719
        uError("getComparFunc data type unexpected type:%d, optr:%d", type, optr);
×
1720
        terrno = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1721
        return NULL;
×
1722
    }
1723
  }
1724

1725
  if (optr == OP_TYPE_NOT_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_VARBINARY &&
893,093,457✔
1726
                                 type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
×
1727
    switch (type) {
×
1728
      case TSDB_DATA_TYPE_BOOL:
×
1729
      case TSDB_DATA_TYPE_TINYINT:
1730
      case TSDB_DATA_TYPE_UTINYINT:
1731
        return setChkNotInBytes1;
×
1732
      case TSDB_DATA_TYPE_SMALLINT:
×
1733
      case TSDB_DATA_TYPE_USMALLINT:
1734
        return setChkNotInBytes2;
×
1735
      case TSDB_DATA_TYPE_INT:
×
1736
      case TSDB_DATA_TYPE_UINT:
1737
      case TSDB_DATA_TYPE_FLOAT:
1738
        return setChkNotInBytes4;
×
1739
      case TSDB_DATA_TYPE_BIGINT:
×
1740
      case TSDB_DATA_TYPE_UBIGINT:
1741
      case TSDB_DATA_TYPE_DOUBLE:
1742
      case TSDB_DATA_TYPE_TIMESTAMP:
1743
        return setChkNotInBytes8;
×
1744
      default:
×
1745
        uError("getComparFunc data type unexpected type:%d, optr:%d", type, optr);
×
1746
        terrno = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1747
        return NULL;
×
1748
    }
1749
  }
1750

1751
  switch (type) {
893,093,457✔
1752
    case TSDB_DATA_TYPE_BOOL:
21,169,625✔
1753
    case TSDB_DATA_TYPE_TINYINT:
1754
      comparFn = compareInt8Val;
21,169,625✔
1755
      break;
21,169,625✔
1756
    case TSDB_DATA_TYPE_SMALLINT:
5,001,643✔
1757
      comparFn = compareInt16Val;
5,001,643✔
1758
      break;
5,001,643✔
1759
    case TSDB_DATA_TYPE_INT:
554,097,814✔
1760
      comparFn = compareInt32Val;
554,097,814✔
1761
      break;
554,097,814✔
1762
    case TSDB_DATA_TYPE_BIGINT:
69,219,875✔
1763
    case TSDB_DATA_TYPE_TIMESTAMP:
1764
      comparFn = compareInt64Val;
69,219,875✔
1765
      break;
69,219,875✔
1766
    case TSDB_DATA_TYPE_FLOAT:
1,760,319✔
1767
      comparFn = compareFloatVal;
1,760,319✔
1768
      break;
1,760,319✔
1769
    case TSDB_DATA_TYPE_DOUBLE:
174,851,635✔
1770
      comparFn = compareDoubleVal;
174,851,635✔
1771
      break;
174,851,635✔
1772
    case TSDB_DATA_TYPE_VARBINARY:
56,894✔
1773
      if (optr == OP_TYPE_IN) {
56,894✔
1774
        comparFn = compareChkInString;
×
1775
      } else if (optr == OP_TYPE_NOT_IN) {
56,894✔
1776
        comparFn = compareChkNotInString;
×
1777
      } else { /* normal relational comparFn */
1778
        comparFn = compareLenBinaryVal;
56,894✔
1779
      }
1780
      break;
56,894✔
1781
    case TSDB_DATA_TYPE_BINARY:
57,938,686✔
1782
    case TSDB_DATA_TYPE_GEOMETRY: {
1783
      if (optr == OP_TYPE_MATCH) {
57,938,686✔
1784
        comparFn = comparestrRegexMatch;
×
1785
      } else if (optr == OP_TYPE_NMATCH) {
57,938,686✔
1786
        comparFn = comparestrRegexNMatch;
×
1787
      } else if (optr == OP_TYPE_LIKE) { /* wildcard query using like operator */
57,938,686✔
1788
        comparFn = comparestrPatternMatch;
×
1789
      } else if (optr == OP_TYPE_NOT_LIKE) { /* wildcard query using like operator */
57,938,686✔
1790
        comparFn = comparestrPatternNMatch;
×
1791
      } else if (optr == OP_TYPE_IN) {
57,938,686✔
1792
        comparFn = compareChkInString;
×
1793
      } else if (optr == OP_TYPE_NOT_IN) {
57,938,686✔
1794
        comparFn = compareChkNotInString;
×
1795
      } else { /* normal relational comparFn */
1796
        comparFn = compareLenPrefixedStr;
57,938,686✔
1797
      }
1798

1799
      break;
57,938,686✔
1800
    }
1801

1802
    case TSDB_DATA_TYPE_NCHAR: {
5,804,261✔
1803
      if (optr == OP_TYPE_MATCH) {
5,804,261✔
1804
        comparFn = comparewcsRegexMatch;
×
1805
      } else if (optr == OP_TYPE_NMATCH) {
5,804,261✔
1806
        comparFn = comparewcsRegexNMatch;
×
1807
      } else if (optr == OP_TYPE_LIKE) {
5,804,261✔
1808
        comparFn = comparewcsPatternMatch;
×
1809
      } else if (optr == OP_TYPE_NOT_LIKE) {
5,804,261✔
1810
        comparFn = comparewcsPatternNMatch;
×
1811
      } else if (optr == OP_TYPE_IN) {
5,804,261✔
1812
        comparFn = compareChkInString;
×
1813
      } else if (optr == OP_TYPE_NOT_IN) {
5,804,261✔
1814
        comparFn = compareChkNotInString;
×
1815
      } else {
1816
        comparFn = compareLenPrefixedWStr;
5,804,261✔
1817
      }
1818
      break;
5,804,261✔
1819
    }
1820

1821
    case TSDB_DATA_TYPE_UTINYINT:
24,340✔
1822
      comparFn = compareUint8Val;
24,340✔
1823
      break;
24,340✔
1824
    case TSDB_DATA_TYPE_USMALLINT:
2,718,008✔
1825
      comparFn = compareUint16Val;
2,718,008✔
1826
      break;
2,718,008✔
1827
    case TSDB_DATA_TYPE_UINT:
413,026✔
1828
      comparFn = compareUint32Val;
413,026✔
1829
      break;
413,026✔
1830
    case TSDB_DATA_TYPE_UBIGINT:
38,068✔
1831
      comparFn = compareUint64Val;
38,068✔
1832
      break;
38,068✔
1833

1834
    default:
2,329✔
1835
      comparFn = compareInt32Val;
2,329✔
1836
      break;
2,329✔
1837
  }
1838

1839
  return comparFn;
893,093,457✔
1840
}
1841

1842
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) {
2,147,483,647✔
1843
  switch (keyType) {
2,147,483,647✔
1844
    case TSDB_DATA_TYPE_TINYINT:
5,794,767✔
1845
    case TSDB_DATA_TYPE_BOOL:
1846
      return (order == TSDB_ORDER_ASC) ? compareInt8Val : compareInt8ValDesc;
5,794,767✔
1847
    case TSDB_DATA_TYPE_SMALLINT:
67,387,864✔
1848
      return (order == TSDB_ORDER_ASC) ? compareInt16Val : compareInt16ValDesc;
67,387,864✔
1849
    case TSDB_DATA_TYPE_INT:
814,396,431✔
1850
      return (order == TSDB_ORDER_ASC) ? compareInt32Val : compareInt32ValDesc;
814,396,431✔
1851
    case TSDB_DATA_TYPE_BIGINT:
2,147,483,647✔
1852
    case TSDB_DATA_TYPE_TIMESTAMP:
1853
      return (order == TSDB_ORDER_ASC) ? compareInt64Val : compareInt64ValDesc;
2,147,483,647✔
1854
    case TSDB_DATA_TYPE_FLOAT:
71,587,045✔
1855
      return (order == TSDB_ORDER_ASC) ? compareFloatVal : compareFloatValDesc;
71,587,045✔
1856
    case TSDB_DATA_TYPE_DOUBLE:
1,114,875,799✔
1857
      return (order == TSDB_ORDER_ASC) ? compareDoubleVal : compareDoubleValDesc;
1,114,875,799✔
1858
    case TSDB_DATA_TYPE_UTINYINT:
23,255✔
1859
      return (order == TSDB_ORDER_ASC) ? compareUint8Val : compareUint8ValDesc;
23,255✔
1860
    case TSDB_DATA_TYPE_USMALLINT:
22,213✔
1861
      return (order == TSDB_ORDER_ASC) ? compareUint16Val : compareUint16ValDesc;
22,213✔
1862
    case TSDB_DATA_TYPE_UINT:
103,081,005✔
1863
      return (order == TSDB_ORDER_ASC) ? compareUint32Val : compareUint32ValDesc;
103,081,005✔
1864
    case TSDB_DATA_TYPE_UBIGINT:
109,718,739✔
1865
      return (order == TSDB_ORDER_ASC) ? compareUint64Val : compareUint64ValDesc;
109,718,739✔
1866
    case TSDB_DATA_TYPE_VARBINARY:
×
1867
      return (order == TSDB_ORDER_ASC) ? compareLenBinaryVal : compareLenBinaryValDesc;
×
1868
    case TSDB_DATA_TYPE_BINARY:
817,924,728✔
1869
    case TSDB_DATA_TYPE_GEOMETRY:
1870
      return (order == TSDB_ORDER_ASC) ? compareLenPrefixedStr : compareLenPrefixedStrDesc;
817,924,728✔
1871
    case TSDB_DATA_TYPE_NCHAR:
2,362,953✔
1872
      return (order == TSDB_ORDER_ASC) ? compareLenPrefixedWStr : compareLenPrefixedWStrDesc;
2,362,953✔
1873
    case TSDB_DATA_TYPE_JSON:
5,811✔
1874
      return (order == TSDB_ORDER_ASC) ? compareJsonVal : compareJsonValDesc;
5,811✔
1875
    case TSDB_DATA_TYPE_DECIMAL64:
2,800✔
1876
      return (order == TSDB_ORDER_ASC) ? compareDecimal64SameScale : compareDecimal64SameScaleDesc;
2,800✔
1877
    case TSDB_DATA_TYPE_DECIMAL:
8,400✔
1878
      return (order == TSDB_ORDER_ASC) ? compareDecimal128SameScale : compareDecimal128SameScaleDesc;
8,400✔
1879
    case TSDB_DATA_TYPE_BLOB:
×
1880
    case TSDB_DATA_TYPE_MEDIUMBLOB:
1881
      return (order == TSDB_ORDER_ASC) ? compareBlobVal : compareBlobValDesc;
×
UNCOV
1882
    default:
×
UNCOV
1883
      return (order == TSDB_ORDER_ASC) ? compareInt32Val : compareInt32ValDesc;
×
1884
  }
1885
}
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