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

taosdata / TDengine / #3531

19 Nov 2024 10:42AM UTC coverage: 60.213% (-0.006%) from 60.219%
#3531

push

travis-ci

web-flow
Merge pull request #28777 from taosdata/fix/3.0/TD-32366

fix:TD-32366/stmt add geometry datatype check

118529 of 252344 branches covered (46.97%)

Branch coverage included in aggregate %.

7 of 48 new or added lines in 3 files covered. (14.58%)

2282 existing lines in 115 files now uncovered.

199096 of 275161 relevant lines covered (72.36%)

6067577.83 hits per line

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

46.41
/source/libs/scalar/src/sclfunc.c
1
#include "cJSON.h"
2
#include "function.h"
3
#include "scalar.h"
4
#include "sclInt.h"
5
#include "sclvector.h"
6
#include "tdatablock.h"
7
#include "tjson.h"
8
#include "ttime.h"
9

10
typedef float (*_float_fn)(float);
11
typedef float (*_float_fn_2)(float, float);
12
typedef double (*_double_fn)(double);
13
typedef double (*_double_fn_2)(double, double);
14
typedef int (*_conv_fn)(int);
15
typedef void (*_trim_space_fn)(char *, char *, int32_t, int32_t);
16
typedef int32_t (*_trim_fn)(char *, char *, char *, int32_t, int32_t);
17
typedef int32_t (*_len_fn)(char *, int32_t, VarDataLenT *);
18

19
/** Math functions **/
20
static double tlog(double v) { return log(v); }
1,710,323✔
21

22
static double tlog2(double v, double base) {
741,449✔
23
  double a = log(v);
741,449✔
24
  double b = log(base);
741,449✔
25
  if (isnan(a) || isinf(a)) {
741,449✔
26
    return a;
184,513✔
27
  } else if (isnan(b) || isinf(b)) {
556,936✔
28
    return b;
258✔
29
  } else if (b == 0) {
556,678✔
30
    return INFINITY;
13,505✔
31
  } else {
32
    return a / b;
543,173✔
33
  }
34
}
35

36
static double degrees(double v) {
45✔
37
  return v * M_1_PI * 180.0;
45✔
38
}
39

40
static double radians(double v) {
45✔
41
  return v / 180.0 * M_PI ;
45✔
42
}
43

44
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
70,728✔
45
  SColumnInfoData *pInputData = pInput->columnData;
70,728✔
46
  SColumnInfoData *pOutputData = pOutput->columnData;
70,728✔
47

48
  int32_t type = GET_PARAM_TYPE(pInput);
70,728!
49

50
  switch (type) {
70,728✔
51
    case TSDB_DATA_TYPE_FLOAT: {
5,151✔
52
      float *in = (float *)pInputData->pData;
5,151✔
53
      float *out = (float *)pOutputData->pData;
5,151✔
54
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
227,506✔
55
        if (colDataIsNull_s(pInputData, i)) {
444,710✔
56
          colDataSetNULL(pOutputData, i);
4,510!
57
          continue;
4,510✔
58
        }
59
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
217,845✔
60
      }
61
      break;
5,151✔
62
    }
63

64
    case TSDB_DATA_TYPE_DOUBLE: {
26,649✔
65
      double *in = (double *)pInputData->pData;
26,649✔
66
      double *out = (double *)pOutputData->pData;
26,649✔
67
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
511,311✔
68
        if (colDataIsNull_s(pInputData, i)) {
969,324✔
69
          colDataSetNULL(pOutputData, i);
157,507!
70
          continue;
157,507✔
71
        }
72
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
327,155✔
73
      }
74
      break;
26,649✔
75
    }
76

77
    case TSDB_DATA_TYPE_TINYINT: {
4,537✔
78
      int8_t *in = (int8_t *)pInputData->pData;
4,537✔
79
      int8_t *out = (int8_t *)pOutputData->pData;
4,537✔
80
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
265,361✔
81
        if (colDataIsNull_s(pInputData, i)) {
521,648✔
82
          colDataSetNULL(pOutputData, i);
3,453!
83
          continue;
3,453✔
84
        }
85
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
257,371✔
86
      }
87
      break;
4,537✔
88
    }
89

90
    case TSDB_DATA_TYPE_SMALLINT: {
4,924✔
91
      int16_t *in = (int16_t *)pInputData->pData;
4,924✔
92
      int16_t *out = (int16_t *)pOutputData->pData;
4,924✔
93
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
235,467✔
94
        if (colDataIsNull_s(pInputData, i)) {
461,086✔
95
          colDataSetNULL(pOutputData, i);
3,587!
96
          continue;
3,587✔
97
        }
98
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
226,956✔
99
      }
100
      break;
4,924✔
101
    }
102

103
    case TSDB_DATA_TYPE_INT: {
13,265✔
104
      int32_t *in = (int32_t *)pInputData->pData;
13,265✔
105
      int32_t *out = (int32_t *)pOutputData->pData;
13,265✔
106
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
331,484✔
107
        if (colDataIsNull_s(pInputData, i)) {
636,438✔
108
          colDataSetNULL(pOutputData, i);
10,942!
109
          continue;
10,942✔
110
        }
111
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
307,277✔
112
      }
113
      break;
13,265✔
114
    }
115

116
    case TSDB_DATA_TYPE_BIGINT: {
15,736✔
117
      int64_t *in = (int64_t *)pInputData->pData;
15,736✔
118
      int64_t *out = (int64_t *)pOutputData->pData;
15,736✔
119
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
396,956✔
120
        if (colDataIsNull_s(pInputData, i)) {
762,440✔
121
          colDataSetNULL(pOutputData, i);
24,884!
122
          continue;
24,884✔
123
        }
124
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
356,336✔
125
      }
126
      break;
15,736✔
127
    }
128

129
    case TSDB_DATA_TYPE_NULL: {
4✔
130
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
8✔
131
        colDataSetNULL(pOutputData, i);
4!
132
      }
133
      break;
4✔
134
    }
135

136
    default: {
462✔
137
      SCL_ERR_RET(colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL));
462!
138
    }
139
  }
140

141
  pOutput->numOfRows = pInput->numOfRows;
70,751✔
142
  return TSDB_CODE_SUCCESS;
70,751✔
143
}
144

145
int32_t signFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
44✔
146
  SColumnInfoData *pInputData = pInput->columnData;
44✔
147
  SColumnInfoData *pOutputData = pOutput->columnData;
44✔
148

149
  int32_t type = GET_PARAM_TYPE(pInput);
44!
150

151
  switch (type) {
44!
152
    case TSDB_DATA_TYPE_FLOAT: {
×
153
      float *in = (float *)pInputData->pData;
×
154
      float *out = (float *)pOutputData->pData;
×
155
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
156
        if (colDataIsNull_s(pInputData, i)) {
×
157
          colDataSetNULL(pOutputData, i);
×
158
          continue;
×
159
        }
160
        out[i] = (float)(in[i] < 0.0 ? -1 : (in[i] > 0.0 ? 1 : 0));
×
161
      }
162
      break;
×
163
    }
164

165
    case TSDB_DATA_TYPE_DOUBLE: {
4✔
166
      double *in = (double *)pInputData->pData;
4✔
167
      double *out = (double *)pOutputData->pData;
4✔
168
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
8✔
169
        if (colDataIsNull_s(pInputData, i)) {
8!
170
          colDataSetNULL(pOutputData, i);
×
171
          continue;
×
172
        }
173
        out[i] = (double)(in[i] < 0.0 ? -1 : (in[i] > 0.0 ? 1 : 0));
4!
174
      }
175
      break;
4✔
176
    }
177

178
    case TSDB_DATA_TYPE_TINYINT: {
×
179
      int8_t *in = (int8_t *)pInputData->pData;
×
180
      int8_t *out = (int8_t *)pOutputData->pData;
×
181
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
182
        if (colDataIsNull_s(pInputData, i)) {
×
183
          colDataSetNULL(pOutputData, i);
×
184
          continue;
×
185
        }
186
        out[i] = (int8_t)(in[i] < 0 ? -1 : (in[i] > 0 ? 1 : 0));
×
187
      }
188
      break;
×
189
    }
190

191
    case TSDB_DATA_TYPE_SMALLINT: {
×
192
      int16_t *in = (int16_t *)pInputData->pData;
×
193
      int16_t *out = (int16_t *)pOutputData->pData;
×
194
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
195
        if (colDataIsNull_s(pInputData, i)) {
×
196
          colDataSetNULL(pOutputData, i);
×
197
          continue;
×
198
        }
199
        out[i] = (int16_t)(in[i] < 0 ? -1 : (in[i] > 0 ? 1 : 0));
×
200
      }
201
      break;
×
202
    }
203

204
    case TSDB_DATA_TYPE_INT: {
×
205
      int32_t *in = (int32_t *)pInputData->pData;
×
206
      int32_t *out = (int32_t *)pOutputData->pData;
×
207
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
208
        if (colDataIsNull_s(pInputData, i)) {
×
209
          colDataSetNULL(pOutputData, i);
×
210
          continue;
×
211
        }
212
        out[i] = (int32_t)(in[i] < 0 ? -1 : (in[i] > 0 ? 1 : 0));
×
213
      }
214
      break;
×
215
    }
216

217
    case TSDB_DATA_TYPE_BIGINT: {
39✔
218
      int64_t *in = (int64_t *)pInputData->pData;
39✔
219
      int64_t *out = (int64_t *)pOutputData->pData;
39✔
220
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
78✔
221
        if (colDataIsNull_s(pInputData, i)) {
78!
222
          colDataSetNULL(pOutputData, i);
×
223
          continue;
×
224
        }
225
        out[i] = (int64_t)(in[i] < 0 ? -1 : (in[i] > 0 ? 1 : 0));
39✔
226
      }
227
      break;
39✔
228
    }
229

230
    case TSDB_DATA_TYPE_UTINYINT: {
×
231
      uint8_t *in = (uint8_t *)pInputData->pData;
×
232
      uint8_t *out = (uint8_t *)pOutputData->pData;
×
233
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
234
        if (colDataIsNull_s(pInputData, i)) {
×
235
          colDataSetNULL(pOutputData, i);
×
236
          continue;
×
237
        }
238
        out[i] = (uint8_t)(in[i] > 0 ? 1 : 0);
×
239
      }
240
      break;
×
241
    }
242
    case TSDB_DATA_TYPE_USMALLINT: {
×
243
      uint16_t *in = (uint16_t *)pInputData->pData;
×
244
      uint16_t *out = (uint16_t *)pOutputData->pData;
×
245
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
246
        if (colDataIsNull_s(pInputData, i)) {
×
247
          colDataSetNULL(pOutputData, i);
×
248
          continue;
×
249
        }
250
        out[i] = (uint16_t)(in[i] > 0 ? 1 : 0);
×
251
      }
252
      break;
×
253
    }
254
    case TSDB_DATA_TYPE_UINT: {
×
255
      uint32_t *in = (uint32_t *)pInputData->pData;
×
256
      uint32_t *out = (uint32_t *)pOutputData->pData;
×
257
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
258
        if (colDataIsNull_s(pInputData, i)) {
×
259
          colDataSetNULL(pOutputData, i);
×
260
          continue;
×
261
        }
262
        out[i] = (uint32_t)(in[i] > 0 ? 1 : 0);
×
263
      }
264
      break;
×
265
    }
266
    case TSDB_DATA_TYPE_UBIGINT: {
×
267
      uint64_t *in = (uint64_t *)pInputData->pData;
×
268
      uint64_t *out = (uint64_t *)pOutputData->pData;
×
269
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
270
        if (colDataIsNull_s(pInputData, i)) {
×
271
          colDataSetNULL(pOutputData, i);
×
272
          continue;
×
273
        }
274
        out[i] = (uint64_t)(in[i] > 0 ? 1 : 0);
×
275
      }
276
      break;
×
277
    }
278
    case TSDB_DATA_TYPE_NULL: {
1✔
279
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
2✔
280
        colDataSetNULL(pOutputData, i);
1!
281
      }
282
      break;
1✔
283
    }
284

285
    default: {
×
286
      SCL_ERR_RET(TSDB_CODE_FUNC_FUNTION_PARA_TYPE);
×
287
    }
288
  }
289

290
  pOutput->numOfRows = pInput->numOfRows;
44✔
291
  return TSDB_CODE_SUCCESS;
44✔
292
}
293

294
static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _double_fn valFn) {
149,766✔
295
  int32_t type = GET_PARAM_TYPE(pInput);
149,766!
296

297
  SColumnInfoData *pInputData = pInput->columnData;
149,766✔
298
  SColumnInfoData *pOutputData = pOutput->columnData;
149,766✔
299

300
  _getDoubleValue_fn_t getValueFn;
301
  SCL_ERR_RET(getVectorDoubleValueFn(type, &getValueFn));
149,766!
302

303
  double *out = (double *)pOutputData->pData;
149,766✔
304

305
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
14,230,048✔
306
    if (colDataIsNull_s(pInputData, i) || IS_NULL_TYPE(type)) {
28,163,030!
307
      colDataSetNULL(pOutputData, i);
601,553!
308
      continue;
601,553✔
309
    }
310
    double tmp = 0;
13,479,962✔
311
    SCL_ERR_RET(getValueFn(pInputData->pData, i, &tmp));
13,479,962!
312
    double result = valFn(tmp);
13,479,296✔
313
    if (isinf(result) || isnan(result)) {
13,478,729!
314
      colDataSetNULL(pOutputData, i);
1,310,014!
315
    } else {
316
      out[i] = result;
12,168,715✔
317
    }
318
  }
319

320
  pOutput->numOfRows = pInput->numOfRows;
148,533✔
321
  return TSDB_CODE_SUCCESS;
148,533✔
322
}
323

324
static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput,
210,938✔
325
                                       _double_fn_2 valFn) {
326
  SColumnInfoData     *pInputData[2];
327
  SColumnInfoData     *pOutputData = pOutput->columnData;
210,938✔
328
  _getDoubleValue_fn_t getValueFn[2];
329

330
  for (int32_t i = 0; i < inputNum; ++i) {
632,814✔
331
    pInputData[i] = pInput[i].columnData;
421,876✔
332
    SCL_ERR_RET(getVectorDoubleValueFn(GET_PARAM_TYPE(&pInput[i]), &getValueFn[i]));
843,752!
333
  }
334

335
  double *out = (double *)pOutputData->pData;
210,938✔
336
  double  result;
337

338
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
210,938!
339

340
  int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
210,938✔
341
  if (pInput[0].numOfRows == pInput[1].numOfRows) {
210,938✔
342
    for (int32_t i = 0; i < numOfRows; ++i) {
786,504✔
343
      if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) {
1,878,098!
344
        colDataSetNULL(pOutputData, i);
99,074!
345
        continue;
99,074✔
346
      }
347
      double val1 = 0;
559,994✔
348
      double val2 = 0;
559,994✔
349
      SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, i, &val1));
559,994!
350
      SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, i, &val2));
559,918!
351
      result = valFn(val1, val2);
559,905✔
352
      if (isinf(result) || isnan(result)) {
559,968✔
353
        colDataSetNULL(pOutputData, i);
123,814!
354
      } else {
355
        out[i] = result;
436,154✔
356
      }
357
    }
358
  } else if (pInput[0].numOfRows == 1) {  // left operand is constant
83,476✔
359
    if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
80!
360
      colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows);
×
361
    } else {
362
      for (int32_t i = 0; i < numOfRows; ++i) {
680✔
363
        if (colDataIsNull_s(pInputData[1], i)) {
1,280✔
364
          colDataSetNULL(pOutputData, i);
30!
365
          continue;
235✔
366
        }
367
        double val1 = 0;
610✔
368
        double val2 = 0;
610✔
369
        SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, 0, &val1));
610!
370
        SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, i, &val2));
610!
371
        result = valFn(val1, val2);
610✔
372
        if (isinf(result) || isnan(result)) {
610✔
373
          colDataSetNULL(pOutputData, i);
205!
374
          continue;
205✔
375
        }
376

377
        out[i] = result;
405✔
378
      }
379
    }
380
  } else if (pInput[1].numOfRows == 1) {
83,436✔
381
    if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
166,720!
382
      colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows);
×
383
    } else {
384
      for (int32_t i = 0; i < numOfRows; ++i) {
2,947,009✔
385
        if (colDataIsNull_s(pInputData[0], i)) {
5,728,338✔
386
          colDataSetNULL(pOutputData, i);
596,593!
387
          continue;
683,968✔
388
        }
389
        double val1 = 0;
2,267,576✔
390
        double val2 = 0;
2,267,576✔
391
        SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, i, &val1));
2,267,576!
392
        SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, 0, &val2));
2,267,404!
393
        result = valFn(val1, val2);
2,267,281✔
394
        if (isinf(result) || isnan(result)) {
2,266,999✔
395
          colDataSetNULL(pOutputData, i);
87,375!
396
          continue;
87,375✔
397
        }
398

399
        out[i] = result;
2,179,624✔
400
      }
401
    }
402
  }
403

404
  pOutput->numOfRows = numOfRows;
210,335✔
405
  return TSDB_CODE_SUCCESS;
210,335✔
406
}
407

408
static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _float_fn f1,
164,534✔
409
                                _double_fn d1) {
410
  int32_t type = GET_PARAM_TYPE(pInput);
164,534!
411

412
  SColumnInfoData *pInputData = pInput->columnData;
164,534✔
413
  SColumnInfoData *pOutputData = pOutput->columnData;
164,534✔
414

415
  switch (type) {
164,534✔
416
    case TSDB_DATA_TYPE_FLOAT: {
3,620✔
417
      float *in = (float *)pInputData->pData;
3,620✔
418
      float *out = (float *)pOutputData->pData;
3,620✔
419

420
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
298,950✔
421
        if (colDataIsNull_s(pInputData, i)) {
590,666✔
422
          colDataSetNULL(pOutputData, i);
82,268!
423
          continue;
82,268✔
424
        }
425
        out[i] = f1(in[i]) + 0;
213,065✔
426
      }
427
      break;
3,617✔
428
    }
429

430
    case TSDB_DATA_TYPE_DOUBLE: {
148,216✔
431
      double *in = (double *)pInputData->pData;
148,216✔
432
      double *out = (double *)pOutputData->pData;
148,216✔
433

434
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
29,618,714✔
435
        if (colDataIsNull_s(pInputData, i)) {
58,940,458✔
436
          colDataSetNULL(pOutputData, i);
157,286✔
437
          continue;
157,286✔
438
        }
439
        out[i] = d1(in[i]) + 0;
29,312,943✔
440
      }
441
      break;
148,485✔
442
    }
443

444
    case TSDB_DATA_TYPE_NULL: {
12✔
445
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
24✔
446
        colDataSetNULL(pOutputData, i);
12!
447
      }
448
      break;
12✔
449
    }
450

451
    default: {
12,686✔
452
      SCL_ERR_RET(colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL));
12,686✔
453
    }
454
  }
455

456
  pOutput->numOfRows = pInput->numOfRows;
164,556✔
457
  return TSDB_CODE_SUCCESS;
164,556✔
458
}
459

460
/** String functions **/
461
static int32_t tlength(char *input, int32_t type, VarDataLenT *len) {
234,001✔
462
  *len = varDataLen(input);
234,001✔
463
  return TSDB_CODE_SUCCESS;
234,001✔
464
}
465

466
uint8_t getCharLen(const unsigned char *str) {
9,612,922✔
467
  if (strcasecmp(tsCharset, "UTF-8") != 0) {
9,612,922!
468
    return 1;
×
469
  }
470
  if ((str[0] & 0x80) == 0) {
9,612,922✔
471
    return 1;
9,604,642✔
472
  } else if ((str[0] & 0xE0) == 0xC0) {
8,280✔
473
    return 2;
1✔
474
  } else if ((str[0] & 0xF0) == 0xE0) {
8,279✔
475
    return 3;
49✔
476
  } else if ((str[0] & 0xF8) == 0xF0) {
8,230!
477
    return 4;
×
478
  } else {
479
    return 1;
8,230✔
480
  }
481
}
482

483
static int32_t tcharlength(char *input, int32_t type, VarDataLenT *len) {
722,527✔
484
  if (type == TSDB_DATA_TYPE_VARCHAR) {
722,527✔
485
    // calculate the number of characters in the string considering the multi-byte character
486
    char *str = varDataVal(input);
496,328✔
487
    VarDataLenT strLen = 0;
496,328✔
488
    VarDataLenT pos = 0;
496,328✔
489
    while(pos < varDataLen(input)) {
10,067,907✔
490
      strLen++;
9,612,034✔
491
      pos += getCharLen((unsigned char *)(str + pos));
9,612,034✔
492
    }
493
    *len = strLen;
455,873✔
494
    return TSDB_CODE_SUCCESS;
455,873✔
495
  } else if (type == TSDB_DATA_TYPE_GEOMETRY) {
226,199!
496
    *len = varDataLen(input);
×
497
  } else {  // NCHAR
498
    *len = varDataLen(input) / TSDB_NCHAR_SIZE;
226,199✔
499
  }
500
  return TSDB_CODE_SUCCESS;
226,199✔
501
}
502

503
static void tltrimspace(char *input, char *output, int32_t type, int32_t charLen) {
5,649,517✔
504
  int32_t numOfSpaces = 0;
5,649,517✔
505
  if (type == TSDB_DATA_TYPE_VARCHAR) {
5,649,517✔
506
    for (int32_t i = 0; i < charLen; ++i) {
4,316,268✔
507
      if (!isspace(*(varDataVal(input) + i))) {
4,016,581✔
508
        break;
4,016,079✔
509
      }
510
      numOfSpaces++;
502✔
511
    }
512
  } else {  // NCHAR
513
    for (int32_t i = 0; i < charLen; ++i) {
1,333,759!
514
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
1,336,075✔
515
        break;
1,336,067✔
516
      }
517
      numOfSpaces++;
8✔
518
    }
519
  }
520

521
  int32_t resLen;
522
  if (type == TSDB_DATA_TYPE_VARCHAR) {
5,649,517✔
523
    resLen = charLen - numOfSpaces;
4,322,419✔
524
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfSpaces, resLen);
4,322,419✔
525
  } else {
526
    resLen = (charLen - numOfSpaces) * TSDB_NCHAR_SIZE;
1,327,098✔
527
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfSpaces * TSDB_NCHAR_SIZE, resLen);
1,327,098✔
528
  }
529

530
  varDataSetLen(output, resLen);
5,649,517✔
531
}
5,649,517✔
532

533
static void tlrtrimspace(char *input, char *output, int32_t type, int32_t charLen) {
23✔
534
  int32_t numOfLeftSpaces = 0;
23✔
535
  int32_t numOfRightSpaces = 0;
23✔
536
  if (type == TSDB_DATA_TYPE_VARCHAR) {
23!
537
    for (int32_t i = 0; i < charLen; ++i) {
69✔
538
      if (!isspace(*(varDataVal(input) + i))) {
68✔
539
        break;
22✔
540
      }
541
      numOfLeftSpaces++;
46✔
542
    }
543
  } else {  // NCHAR
544
    for (int32_t i = 0; i < charLen; ++i) {
×
545
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
546
        break;
×
547
      }
548
      numOfLeftSpaces++;
×
549
    }
550
  }
551

552
  if (type == TSDB_DATA_TYPE_VARCHAR) {
23!
553
    for (int32_t i = charLen - 1; i >= 0; --i) {
76✔
554
      if (!isspace(*(varDataVal(input) + i))) {
75✔
555
        break;
22✔
556
      }
557
      numOfRightSpaces++;
53✔
558
    }
559
  } else {  // NCHAR
560
    for (int32_t i = charLen - 1; i >= 0; --i) {
×
561
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
562
        break;
×
563
      }
564
      numOfRightSpaces++;
×
565
    }
566
  }
567

568
  int32_t resLen;
569
  if (type == TSDB_DATA_TYPE_VARCHAR) {
23!
570
    resLen = charLen - (numOfLeftSpaces + numOfRightSpaces);
23✔
571
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfLeftSpaces, resLen);
23✔
572
  } else {
573
    resLen = (charLen - (numOfLeftSpaces + numOfRightSpaces)) * TSDB_NCHAR_SIZE;
×
574
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfLeftSpaces * TSDB_NCHAR_SIZE, resLen);
×
575
  }
576

577
  varDataSetLen(output, resLen);
23✔
578
}
23✔
579

580
static bool isCharStart(char c) {
26,941,294✔
581
  return strcasecmp(tsCharset, "UTF-8") == 0 ? ((c & 0xC0) != 0x80) : true;
26,941,294!
582
}
583

584
static int32_t trimHelper(char *orgStr, char* remStr, int32_t orgLen, int32_t remLen, bool trimLeft, bool isNchar) {
70✔
585
  if (trimLeft) {
70✔
586
    int32_t pos = 0;
35✔
587
    for (int32_t i = 0; i < orgLen; i += remLen) {
92!
588
      if (memcmp(orgStr + i, remStr, remLen) == 0) {
92✔
589
        if (isCharStart(orgStr[i + remLen]) || isNchar) {
57!
590
          pos = i + remLen;
57✔
591
          continue;
57✔
592
        } else {
593
          return pos;
×
594
        }
595
      } else {
596
        return pos;
35✔
597
      }
598
    }
599
    return pos;
×
600
  } else {
601
    int32_t pos = orgLen;
35✔
602
    for (int32_t i = orgLen - remLen; i >= 0; i -= remLen) {
106!
603
      if (memcmp(orgStr + i, remStr, remLen) == 0) {
106✔
604
        if (isCharStart(orgStr[i]) || isNchar) {
71!
605
          pos = i;
71✔
606
          continue;
71✔
607
        } else {
608
          return pos;
×
609
        }
610
      } else {
611
        return pos;
35✔
612
      }
613
    }
614
    return pos;
×
615
  }
616
}
617

618
static int32_t convVarcharToNchar(char *input, char **output, int32_t inputLen, int32_t *outputLen) {
×
619
  *output = taosMemoryCalloc(inputLen * TSDB_NCHAR_SIZE, 1);
×
620
  if (NULL == *output) {
×
621
    return terrno;
×
622
  }
623
  bool ret = taosMbsToUcs4(input, inputLen, (TdUcs4 *)*output, inputLen * TSDB_NCHAR_SIZE, outputLen);
×
624
  if (!ret) {
×
625
    taosMemoryFreeClear(*output);
×
626
    return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
627
  }
628
  return TSDB_CODE_SUCCESS;
×
629
}
630

631
static int32_t convNcharToVarchar(char *input, char **output, int32_t inputLen, int32_t *outputLen) {
×
632
  *output = taosMemoryCalloc(inputLen, 1);
×
633
  if (NULL == *output) {
×
634
    return terrno;
×
635
  }
636
  *outputLen = taosUcs4ToMbs((TdUcs4 *)input, inputLen, *output);
×
637
  if (*outputLen < 0) {
×
638
    taosMemoryFree(*output);
×
639
    return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
640
  }
641
  return TSDB_CODE_SUCCESS;
×
642
}
643

644
static int32_t convBetweenNcharAndVarchar(char *input, char **output, int32_t inputLen, int32_t *outputLen, int32_t wantType) {
×
645
  if (wantType == TSDB_DATA_TYPE_NCHAR) {
×
646
    return convVarcharToNchar(input, output, inputLen, outputLen);
×
647
  } else {
648
    return convNcharToVarchar(input, output, inputLen, outputLen);
×
649
  }
650
}
651
static int32_t tltrim(char *input, char *remInput, char *output, int32_t inputType, int32_t remType) {
13✔
652
  int32_t orgLen = varDataLen(input);
13✔
653
  char   *orgStr = varDataVal(input);
13✔
654
  int32_t remLen = varDataLen(remInput);
13✔
655
  char   *remStr = varDataVal(remInput);
13✔
656
  if (orgLen == 0) {
13!
657
    varDataSetLen(output, 0);
×
658
    return TSDB_CODE_SUCCESS;
×
659
  }
660
  int32_t pos = 0;
13✔
661

662
  bool    needFree = false;
13✔
663
  if (inputType != remType) {
13!
664
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType));
×
665
    needFree = true;
×
666
  }
667

668
  if (remLen == 0 || remLen > orgLen) {
13!
669
    (void)memcpy(varDataVal(output), orgStr, orgLen);
×
670
    varDataSetLen(output, orgLen);
×
671
    return TSDB_CODE_SUCCESS;
×
672
  }
673

674
  pos = trimHelper(orgStr, remStr, orgLen, remLen, true, inputType == TSDB_DATA_TYPE_NCHAR);
13✔
675

676
  if (needFree) {
13!
677
    taosMemoryFree(remStr);
×
678
  }
679

680
  int32_t resLen = orgLen - pos;
13✔
681
  (void)memcpy(varDataVal(output), orgStr + pos, resLen);
13✔
682
  varDataSetLen(output, resLen);
13✔
683
  return TSDB_CODE_SUCCESS;
13✔
684
}
685

686
static void trtrimspace(char *input, char *output, int32_t type, int32_t charLen) {
999,011✔
687
  int32_t numOfSpaces = 0;
999,011✔
688
  if (type == TSDB_DATA_TYPE_VARCHAR) {
999,011✔
689
    for (int32_t i = charLen - 1; i >= 0; --i) {
440,308✔
690
      if (!isspace(*(varDataVal(input) + i))) {
440,278✔
691
        break;
439,779✔
692
      }
693
      numOfSpaces++;
499✔
694
    }
695
  } else {  // NCHAR
696
    for (int32_t i = charLen - 1; i >= 0; --i) {
559,210!
697
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
559,244✔
698
        break;
559,236✔
699
      }
700
      numOfSpaces++;
8✔
701
    }
702
  }
703

704
  int32_t resLen;
705
  if (type == TSDB_DATA_TYPE_VARCHAR) {
999,011✔
706
    resLen = charLen - numOfSpaces;
439,817✔
707
  } else {
708
    resLen = (charLen - numOfSpaces) * TSDB_NCHAR_SIZE;
559,194✔
709
  }
710
  (void)memcpy(varDataVal(output), varDataVal(input), resLen);
999,011✔
711

712
  varDataSetLen(output, resLen);
999,011✔
713
}
999,011✔
714

715
static int32_t trtrim(char *input, char *remInput, char *output, int32_t inputType, int32_t remType) {
13✔
716
  int32_t orgLen = varDataLen(input);
13✔
717
  char   *orgStr = varDataVal(input);
13✔
718
  int32_t remLen = varDataLen(remInput);
13✔
719
  char   *remStr = varDataVal(remInput);
13✔
720
  if (orgLen == 0) {
13!
721
    varDataSetLen(output, 0);
×
722
    return TSDB_CODE_SUCCESS;
×
723
  }
724
  int32_t pos = 0;
13✔
725
  bool    needFree = false;
13✔
726

727
  if (inputType != remType) {
13!
728
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType));
×
729
    needFree = true;
×
730
  }
731

732
  if (remLen == 0 || remLen > orgLen) {
13!
733
    (void)memcpy(varDataVal(output), orgStr, orgLen);
×
734
    varDataSetLen(output, orgLen);
×
735
    return TSDB_CODE_SUCCESS;
×
736
  }
737

738
  pos = trimHelper(orgStr, remStr, orgLen, remLen, false, inputType == TSDB_DATA_TYPE_NCHAR);
13✔
739

740
  if (needFree) {
13!
741
    taosMemoryFree(remStr);
×
742
  }
743

744
  (void)memcpy(varDataVal(output), orgStr, pos);
13✔
745
  varDataSetLen(output, pos);
13✔
746
  return TSDB_CODE_SUCCESS;
13✔
747
}
748

749
static int32_t tlrtrim(char *input, char *remInput, char *output, int32_t inputType, int32_t remType) {
23✔
750
  int32_t orgLen = varDataLen(input);
23✔
751
  char   *orgStr = varDataVal(input);
23✔
752
  int32_t remLen = varDataLen(remInput);
23✔
753
  char   *remStr = varDataVal(remInput);
23✔
754
  if (orgLen == 0) {
23!
755
    varDataSetLen(output, 0);
×
756
    return TSDB_CODE_SUCCESS;
×
757
  }
758

759
  bool    needFree = false;
23✔
760

761
  if (inputType != remType) {
23!
762
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType));
×
763
    needFree = true;
×
764
  }
765

766
  if (remLen == 0 || remLen > orgLen) {
23!
767
    (void)memcpy(varDataVal(output), orgStr, orgLen);
1✔
768
    varDataSetLen(output, orgLen);
1✔
769
    if (needFree) {
1!
770
      taosMemoryFree(remStr);
×
771
    }
772
    return TSDB_CODE_SUCCESS;
1✔
773
  }
774

775
  int32_t leftPos = trimHelper(orgStr, remStr, orgLen, remLen, true, inputType == TSDB_DATA_TYPE_NCHAR);
22✔
776
  int32_t rightPos = trimHelper(orgStr, remStr, orgLen, remLen, false, inputType == TSDB_DATA_TYPE_NCHAR);
22✔
777

778
  if (needFree) {
22!
779
    taosMemoryFree(remStr);
×
780
  }
781

782
  if (leftPos >= rightPos) {
22!
783
    varDataSetLen(output, 0);
×
784
    return TSDB_CODE_SUCCESS;
×
785
  }
786
  (void)memcpy(varDataVal(output), orgStr + leftPos, rightPos - leftPos);
22✔
787
  varDataSetLen(output, rightPos - leftPos);
22✔
788
  return TSDB_CODE_SUCCESS;
22✔
789
}
790

791
static int32_t doLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _len_fn lenFn) {
36,085✔
792
  int32_t type = GET_PARAM_TYPE(pInput);
36,085!
793

794
  SColumnInfoData *pInputData = pInput->columnData;
36,085✔
795
  SColumnInfoData *pOutputData = pOutput->columnData;
36,085✔
796

797
  int64_t *out = (int64_t *)pOutputData->pData;
36,085✔
798

799
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
1,407,879✔
800
    if (colDataIsNull_s(pInputData, i)) {
2,745,358✔
801
      colDataSetNULL(pOutputData, i);
416,292!
802
      continue;
416,292✔
803
    }
804

805
    char *in = colDataGetData(pInputData, i);
956,387!
806
    SCL_ERR_RET(lenFn(in, type, (VarDataLenT *)&(out[i])));
956,387✔
807
  }
808

809
  pOutput->numOfRows = pInput->numOfRows;
35,200✔
810
  return TSDB_CODE_SUCCESS;
35,200✔
811
}
812

813
static int32_t concatCopyHelper(const char *input, char *output, bool hasNchar, int32_t type, VarDataLenT *dataLen) {
49,819,849✔
814
  if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) {
56,879,828✔
815
    TdUcs4 *newBuf = taosMemoryCalloc((varDataLen(input) + 1) * TSDB_NCHAR_SIZE, 1);
6,993,655✔
816
    if (NULL == newBuf) {
7,055,739!
817
      return terrno;
×
818
    }
819
    int32_t len = varDataLen(input);
7,055,739✔
820
    bool    ret = taosMbsToUcs4(varDataVal(input), len, newBuf, (varDataLen(input) + 1) * TSDB_NCHAR_SIZE, &len);
7,055,739✔
821
    if (!ret) {
7,054,248!
822
      taosMemoryFree(newBuf);
×
823
      return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
824
    }
825
    (void)memcpy(varDataVal(output) + *dataLen, newBuf, len);
7,054,248✔
826
    *dataLen += len;
7,054,248✔
827
    taosMemoryFree(newBuf);
7,054,248✔
828
  } else {
829
    (void)memcpy(varDataVal(output) + *dataLen, varDataVal(input), varDataLen(input));
42,826,194✔
830
    *dataLen += varDataLen(input);
42,826,194✔
831
  }
832
  return TSDB_CODE_SUCCESS;
49,886,173✔
833
}
834

835
static int32_t getNumOfNullEntries(SColumnInfoData *pColumnInfoData, int32_t numOfRows) {
×
836
  int32_t numOfNulls = 0;
×
837
  if (!pColumnInfoData->hasNull) {
×
838
    return numOfNulls;
×
839
  }
840
  for (int i = 0; i < numOfRows; ++i) {
×
841
    if (pColumnInfoData->varmeta.offset[i] == -1) {
×
842
      numOfNulls++;
×
843
    }
844
  }
845
  return numOfNulls;
×
846
}
847

848
int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
399,513✔
849
  int32_t           code = TSDB_CODE_SUCCESS;
399,513✔
850
  SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
399,513✔
851
  SColumnInfoData  *pOutputData = pOutput->columnData;
399,739✔
852
  char            **input = taosMemoryCalloc(inputNum, POINTER_BYTES);
399,739✔
853
  char             *outputBuf = NULL;
399,715✔
854

855
  if (NULL == pInputData) {
399,715!
856
    SCL_ERR_JRET(terrno);
×
857
  }
858
  if (NULL == input) {
399,715!
859
    SCL_ERR_JRET(terrno);
×
860
  }
861

862
  int32_t inputLen = 0;
399,545✔
863
  int32_t numOfRows = 0;
399,545✔
864
  bool    hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
399,545!
865
  for (int32_t i = 0; i < inputNum; ++i) {
1,806,271✔
866
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
1,406,726✔
867
  }
868
  int32_t outputLen = VARSTR_HEADER_SIZE;
399,545✔
869
  for (int32_t i = 0; i < inputNum; ++i) {
1,805,832✔
870
    if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
1,406,295!
871
      colDataSetNNULL(pOutputData, 0, numOfRows);
8!
872
      pOutput->numOfRows = numOfRows;
8✔
873
      goto _return;
8✔
874
    }
875
    pInputData[i] = pInput[i].columnData;
1,406,287✔
876
    int32_t factor = 1;
1,406,287✔
877
    if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
1,406,287!
878
      factor = TSDB_NCHAR_SIZE;
184,456✔
879
    }
880
    outputLen += pInputData[i]->info.bytes * factor;
1,406,287✔
881
  }
882

883
  outputBuf = taosMemoryCalloc(outputLen, 1);
399,537✔
884
  if (NULL == outputBuf) {
399,633!
885
    SCL_ERR_JRET(terrno);
×
886
  }
887

888
  for (int32_t k = 0; k < numOfRows; ++k) {
16,799,915✔
889
    bool hasNull = false;
16,384,858✔
890
    for (int32_t i = 0; i < inputNum; ++i) {
55,016,252✔
891
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
78,457,514!
892
        colDataSetNULL(pOutputData, k);
597,363✔
893
        hasNull = true;
597,363✔
894
        break;
597,363✔
895
      }
896
    }
897

898
    if (hasNull) {
16,384,858✔
899
      continue;
597,362✔
900
    }
901

902
    VarDataLenT dataLen = 0;
15,787,496✔
903
    char       *output = outputBuf;
15,787,496✔
904
    for (int32_t i = 0; i < inputNum; ++i) {
53,420,620✔
905
      int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
37,833,854✔
906
      input[i] = colDataGetData(pInputData[i], rowIdx);
37,833,854!
907

908
      SCL_ERR_JRET(concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen));
37,833,854✔
909
    }
910
    varDataSetLen(output, dataLen);
15,586,766✔
911
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, outputBuf, false));
15,586,766!
912
  }
913

914
  pOutput->numOfRows = numOfRows;
415,057✔
915

916
_return:
415,065✔
917
  taosMemoryFree(input);
415,065✔
918
  taosMemoryFree(outputBuf);
399,634✔
919
  taosMemoryFree(pInputData);
399,727✔
920

921
  SCL_RET(code);
399,643!
922
}
923

924
int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
277,487✔
925
  int32_t           code = TSDB_CODE_SUCCESS;
277,487✔
926
  SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
277,487✔
927
  SColumnInfoData  *pOutputData = pOutput->columnData;
277,595✔
928
  char             *outputBuf = NULL;
277,595✔
929

930
  if (NULL == pInputData) {
277,595!
931
    SCL_ERR_JRET(terrno);
×
932
  }
933

934
  int32_t inputLen = 0;
277,525✔
935
  int32_t numOfRows = 0;
277,525✔
936
  bool    hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
277,525!
937
  for (int32_t i = 0; i < inputNum; ++i) {
1,760,904✔
938
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
1,483,379✔
939
  }
940
  int32_t outputLen = VARSTR_HEADER_SIZE;
277,525✔
941
  for (int32_t i = 0; i < inputNum; ++i) {
1,760,297✔
942
    if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
1,482,780!
943
      colDataSetNNULL(pOutputData, 0, numOfRows);
8!
944
      pOutput->numOfRows = numOfRows;
8✔
945
      goto _return;
8✔
946
    }
947
    pInputData[i] = pInput[i].columnData;
1,482,772✔
948
    int32_t factor = 1;
1,482,772✔
949
    if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
1,482,772!
950
      factor = TSDB_NCHAR_SIZE;
201,643✔
951
    }
952

953
    if (i == 0) {
1,482,772✔
954
      // calculate required separator space
955
      outputLen += pInputData[i]->info.bytes * factor * (inputNum - 2);
277,369✔
956
    } else {
957
      outputLen += pInputData[i]->info.bytes * factor;
1,205,403✔
958
    }
959
  }
960

961
  outputBuf = taosMemoryCalloc(outputLen, 1);
277,517✔
962
  if (NULL == outputBuf) {
277,580!
963
    SCL_ERR_JRET(terrno);
×
964
  }
965

966
  for (int32_t k = 0; k < numOfRows; ++k) {
2,853,162✔
967
    if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) {
5,151,390!
968
      colDataSetNULL(pOutputData, k);
×
969
      continue;
×
970
    }
971

972
    VarDataLenT dataLen = 0;
2,575,695✔
973
    bool        hasNull = false;
2,575,695✔
974
    char       *output = outputBuf;
2,575,695✔
975
    for (int32_t i = 1; i < inputNum; ++i) {
9,807,793✔
976
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
15,402,880!
977
        hasNull = true;
467,362✔
978
        break;
467,362✔
979
      }
980

981
      int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
7,234,078✔
982

983
      SCL_ERR_JRET(concatCopyHelper(colDataGetData(pInputData[i], rowIdx), output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen));
7,234,078!
984

985
      if (i < inputNum - 1) {
7,230,375✔
986
        // insert the separator
987
        char *sep = (pInput[0].numOfRows == 1) ? colDataGetData(pInputData[0], 0) : colDataGetData(pInputData[0], k);
5,127,248!
988
        SCL_ERR_JRET(concatCopyHelper(sep, output, hasNchar, GET_PARAM_TYPE(&pInput[0]), &dataLen));
5,127,248✔
989
      }
990
    }
991

992
    if (hasNull) {
2,573,715✔
993
      colDataSetNULL(pOutputData, k);
467,361✔
994
      (void)memset(output, 0, dataLen);
467,361✔
995
    } else {
996
      varDataSetLen(output, dataLen);
2,106,354✔
997
      SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
2,106,354✔
998
    }
999
  }
1000

1001
  pOutput->numOfRows = numOfRows;
277,467✔
1002

1003
_return:
277,475✔
1004
  taosMemoryFree(outputBuf);
277,475✔
1005
  taosMemoryFree(pInputData);
277,565✔
1006

1007
  return code;
277,482✔
1008
}
1009

1010
static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _conv_fn convFn) {
77,943✔
1011
  int32_t type = GET_PARAM_TYPE(pInput);
77,943!
1012

1013
  SColumnInfoData *pInputData = pInput->columnData;
77,943✔
1014
  SColumnInfoData *pOutputData = pOutput->columnData;
77,943✔
1015

1016
  int32_t outputLen = pInputData->varmeta.length;
77,943✔
1017
  char   *outputBuf = taosMemoryCalloc(outputLen, 1);
77,943✔
1018
  if (outputBuf == NULL) {
78,002!
1019
    SCL_ERR_RET(terrno);
×
1020
  }
1021

1022
  char   *output = outputBuf;
77,998✔
1023

1024
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
12,811,014✔
1025
    if (colDataIsNull_s(pInputData, i)) {
25,457,196✔
1026
      colDataSetNULL(pOutputData, i);
1,293,458✔
1027
      continue;
1,293,458✔
1028
    }
1029

1030
    char   *input = colDataGetData(pInput[0].columnData, i);
11,435,140!
1031
    int32_t len = varDataLen(input);
11,435,140✔
1032
    if (type == TSDB_DATA_TYPE_VARCHAR) {
11,435,140✔
1033
      for (int32_t j = 0; j < len; ++j) {
49,388,902✔
1034
        *(varDataVal(output) + j) = convFn(*(varDataVal(input) + j));
41,278,341✔
1035
      }
1036
    } else {  // NCHAR
1037
      for (int32_t j = 0; j < len / TSDB_NCHAR_SIZE; ++j) {
79,130,776✔
1038
        *((uint32_t *)varDataVal(output) + j) = convFn(*((uint32_t *)varDataVal(input) + j));
75,787,714✔
1039
      }
1040
    }
1041
    varDataSetLen(output, len);
11,453,623✔
1042
    int32_t code = colDataSetVal(pOutputData, i, output, false);
11,453,623✔
1043
    if (TSDB_CODE_SUCCESS != code) {
11,428,474!
1044
      taosMemoryFree(outputBuf);
×
1045
      SCL_ERR_RET(code);
×
1046
    }
1047
    output += varDataTLen(output);
11,439,558✔
1048
  }
1049

1050
  pOutput->numOfRows = pInput->numOfRows;
82,416✔
1051
  taosMemoryFree(outputBuf);
82,416✔
1052

1053
  return TSDB_CODE_SUCCESS;
77,982✔
1054
}
1055

1056
static int32_t doTrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _trim_space_fn trimSpaceFn, _trim_fn trimFn) {
111,748✔
1057
  int32_t          code = TSDB_CODE_SUCCESS;
111,748✔
1058
  SColumnInfoData *pInputData[2];
1059
  SColumnInfoData *pOutputData = pOutput[0].columnData;
111,748✔
1060
  int32_t          outputLen;
1061
  int32_t          numOfRows;
1062
  pInputData[0] = pInput[0].columnData;
111,748✔
1063
  if (inputNum == 3) {
111,748✔
1064
    pInputData[1] = pInput[1].columnData;
49✔
1065
    outputLen = pInputData[1]->info.bytes;
49✔
1066
    numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
49✔
1067
  } else {
1068
    outputLen = pInputData[0]->info.bytes;
111,699✔
1069
    numOfRows = pInput[0].numOfRows;
111,699✔
1070
  }
1071
  char *outputBuf = taosMemoryCalloc(outputLen, 1);
111,748✔
1072
  if (outputBuf == NULL) {
111,861!
1073
    SCL_ERR_RET(terrno);
×
1074
  }
1075

1076
  char   *output = outputBuf;
111,799✔
1077

1078
  if (inputNum == 3) {
111,799✔
1079
    bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
49!
1080

1081
    if (hasNullType ||
49!
1082
        (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
98!
1083
        (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0))) {
98!
1084
      colDataSetNNULL(pOutputData, 0, numOfRows);
×
1085
    }
1086

1087
    for (int32_t i = 0; i < numOfRows; ++i) {
98✔
1088
      int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
49!
1089
      int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
49!
1090
      if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2)) {
147!
1091
        colDataSetNULL(pOutputData, i);
×
1092
        continue;
×
1093
      }
1094
      SCL_ERR_JRET(trimFn(colDataGetData(pInputData[1], colIdx2), colDataGetData(pInputData[0], colIdx1),
49!
1095
                          output, GET_PARAM_TYPE(&pInput[1]), GET_PARAM_TYPE(&pInput[0])));
1096
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
49!
1097
    }
1098
  } else {
1099
    for (int32_t i = 0; i < numOfRows; ++i) {
8,035,321✔
1100
      if (colDataIsNull_s(pInputData[0], i)) {
15,866,736✔
1101
        colDataSetNULL(pOutputData, i);
1,279,040✔
1102
        continue;
1,279,040✔
1103
      }
1104
      int32_t type = GET_PARAM_TYPE(pInput);
6,654,328✔
1105
      char   *input = colDataGetData(pInputData[0], i);
6,654,328!
1106
      int32_t len = varDataLen(input);
6,654,328✔
1107
      int32_t charLen = (type == TSDB_DATA_TYPE_VARCHAR) ? len : len / TSDB_NCHAR_SIZE;
6,654,328✔
1108
      trimSpaceFn(input, output, type, charLen);
6,654,328✔
1109
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
6,660,703!
1110
    }
1111
  }
1112
  pOutput->numOfRows = numOfRows;
102,002✔
1113
_return:
102,002✔
1114
  taosMemoryFree(outputBuf);
102,002✔
1115
  return code;
111,879✔
1116
}
1117

1118
static int32_t findPosBytes(char *orgStr, char *delimStr, int32_t orgLen, int32_t delimLen, int32_t charNums, bool isNchar) {
14,170,191✔
1119
  int32_t charCount = 0;
14,170,191✔
1120
  if (charNums > 0) {
14,170,191!
1121
    for (int32_t pos = 0; pos < orgLen; pos++) {
32,598,409✔
1122
      if (delimStr) {
26,948,911✔
1123
        if (pos + delimLen > orgLen)  {
341✔
1124
          return orgLen;
2✔
1125
        }
1126
        if ((isCharStart(orgStr[pos]) || isNchar) && memcmp(orgStr + pos, delimStr, delimLen) == 0) {
339!
1127
          charCount++;
70✔
1128
          if (charCount == charNums) {
70✔
1129
            return pos;
25✔
1130
          }
1131
          pos = pos + delimLen - 1;
45✔
1132
        }
1133
      } else {
1134
        if ((isCharStart(orgStr[pos]) || isNchar)) {
26,948,570!
1135
          charCount++;
26,929,260✔
1136
          if (charCount == charNums) {
26,929,260✔
1137
            return pos;
8,511,581✔
1138
          }
1139
        }
1140
      }
1141
    }
1142
    return orgLen;
5,649,498✔
1143
  } else {
1144
    if (delimStr) {
×
1145
      for (int32_t pos = orgLen - delimLen; pos >= 0; pos--) {
325✔
1146
        if ((isCharStart(orgStr[pos]) || isNchar) && memcmp(orgStr + pos, delimStr, delimLen) == 0) {
315!
1147
          charCount++;
75✔
1148
          if (charCount == -charNums) {
75✔
1149
            return pos + delimLen;
28✔
1150
          }
1151
          pos = pos - delimLen + 1;
47✔
1152
        }
1153
      }
1154
    } else {
1155
      for (int32_t pos = orgLen - 1; pos >= 0; pos--) {
×
1156
        if ((isCharStart(orgStr[pos]) || isNchar)) {
164!
1157
          charCount++;
164✔
1158
          if (charCount == -charNums) {
164✔
1159
            return pos;
28✔
1160
          }
1161
        }
1162
      }
1163
    }
1164
    return 0;
×
1165
  }
1166
}
1167

1168
int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
60,349✔
1169
  int32_t code = TSDB_CODE_SUCCESS;
60,349✔
1170
  SColumnInfoData *pInputData[3];
1171
  SColumnInfoData *pOutputData = pOutput->columnData;
60,349✔
1172

1173
  for (int32_t i = 0; i < inputNum; ++i) {
236,048✔
1174
    pInputData[i] = pInput[i].columnData;
175,699✔
1175
  }
1176

1177
  int32_t outputLen = pInputData[0]->info.bytes;
60,349✔
1178
  char *outputBuf = taosMemoryMalloc(outputLen);
60,349✔
1179
  if (outputBuf == NULL) {
60,374✔
1180
    qError("substr function memory allocation failure. size: %d", outputLen);
1!
1181
    return terrno;
1✔
1182
  }
1183

1184
  int32_t numOfRows = 0;
60,373✔
1185
  for (int32_t i = 0; i < inputNum; ++i) {
236,079✔
1186
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
175,706✔
1187
  }
1188

1189
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])) ||
115,350!
1190
                      (inputNum == 3 && IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[2]))));
54,977✔
1191

1192
  if (hasNullType ||
60,373✔
1193
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
84,648✔
1194
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0)) ||
114,008!
1195
      (inputNum == 3 && (pInput[2].numOfRows == 1 && colDataIsNull_s(pInputData[2], 0)))) {
103,885!
1196
    colDataSetNNULL(pOutputData, 0, numOfRows);
3,359✔
1197
    pOutput->numOfRows = numOfRows;
3,359✔
1198
    goto _return;
3,359✔
1199
  }
1200

1201
  int32_t colIdx[3];
1202
  for (int32_t i = 0; i < numOfRows; ++i) {
12,574,725✔
1203
    colIdx[0] = (pInput[0].numOfRows == 1) ? 0 : i;
12,507,851✔
1204
    colIdx[1] = (pInput[1].numOfRows == 1) ? 0 : i;
12,507,851!
1205
    if (inputNum == 3) {
12,507,851✔
1206
      colIdx[2] = (pInput[2].numOfRows == 1) ? 0 : i;
11,391,827!
1207
    }
1208

1209
    if (colDataIsNull_s(pInputData[0], colIdx[0]) || colDataIsNull_s(pInputData[1], colIdx[1]) ||
36,556,636!
1210
        (inputNum == 3 && colDataIsNull_s(pInputData[2], colIdx[2]))) {
21,789,490!
1211
      colDataSetNULL(pOutputData, i);
962,061✔
1212
      continue;
962,061✔
1213
    }
1214

1215
    int32_t subPos = 0;
11,545,790✔
1216
    int32_t subLen = INT16_MAX;
11,545,790✔
1217
    GET_TYPED_DATA(subPos, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], colIdx[1]));
11,545,790!
1218
    if (inputNum == 3) {
11,545,790✔
1219
      GET_TYPED_DATA(subLen, int32_t, GET_PARAM_TYPE(&pInput[2]), colDataGetData(pInputData[2], colIdx[2]));
10,905,975!
1220
    }
1221

1222
    if (subPos == 0 || subLen < 1) {
11,545,790!
1223
      varDataSetLen(outputBuf, 0);
1,689,766✔
1224
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
1,689,766!
1225
      continue;
1,797,448✔
1226
    }
1227

1228
    char   *input = colDataGetData(pInputData[0], colIdx[0]);
9,856,024!
1229
    int32_t len = varDataLen(input);
9,856,024✔
1230
    int32_t startPosBytes;
1231
    int32_t endPosBytes = len;
9,856,024✔
1232
    if (subPos > 0) {
9,856,024!
1233
      startPosBytes = (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR) ? findPosBytes(varDataVal(input), NULL, varDataLen(input), -1, subPos, false) : (subPos - 1) * TSDB_NCHAR_SIZE;
9,925,264!
1234
      startPosBytes = TMIN(startPosBytes, len);
9,775,984✔
1235
    } else {
1236
      startPosBytes =
×
1237
          (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR) ? findPosBytes(varDataVal(input), NULL, varDataLen(input), -1, subPos, false) : len + subPos * TSDB_NCHAR_SIZE;
×
1238
      startPosBytes = TMAX(startPosBytes, 0);
29✔
1239
    }
1240
    if (inputNum == 3) {
9,776,013✔
1241
      endPosBytes =
15,980,450✔
1242
          (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR)
9,125,396!
1243
              ? startPosBytes + findPosBytes(varDataVal(input) + startPosBytes, NULL, varDataLen(input) - startPosBytes, -1, subLen + 1, false)
6,926,288✔
1244
              : startPosBytes + subLen * TSDB_NCHAR_SIZE;
2,199,108✔
1245
      endPosBytes = TMIN(endPosBytes, len);
9,054,162✔
1246
    }
1247

1248
    char   *output = outputBuf;
9,704,779✔
1249
    int32_t resLen = endPosBytes - startPosBytes;
9,704,779✔
1250
    if (resLen > 0) {
9,704,779✔
1251
      (void)memcpy(varDataVal(output), varDataVal(input) + startPosBytes, resLen);
7,979,743✔
1252
      varDataSetLen(output, resLen);
7,979,743✔
1253
    } else {
1254
      varDataSetLen(output, 0);
1,725,036✔
1255
    }
1256

1257
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
9,704,779✔
1258
  }
1259

1260
  pOutput->numOfRows = numOfRows;
66,874✔
1261
_return:
70,233✔
1262
  taosMemoryFree(outputBuf);
70,233✔
1263

1264
  return code;
60,367✔
1265
}
1266

1267
int32_t md5Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
1,958✔
1268
  SColumnInfoData *pInputData = pInput->columnData;
1,958✔
1269
  SColumnInfoData *pOutputData = pOutput->columnData;
1,958✔
1270
  int32_t bufLen = TMAX(MD5_OUTPUT_LEN + VARSTR_HEADER_SIZE + 1, pInputData->info.bytes);
1,958✔
1271
  char* pOutputBuf = taosMemoryMalloc(bufLen);
1,958✔
1272
  if (!pOutputBuf) {
1,958!
1273
    qError("md5 function alloc memory failed");
×
1274
    return terrno;
×
1275
  }
1276
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
3,916✔
1277
    if (colDataIsNull_s(pInputData, i)) {
3,916!
1278
      colDataSetNULL(pOutputData, i);
×
1279
      continue;
×
1280
    }
1281
    char *input = colDataGetData(pInput[0].columnData, i);
1,958!
1282
    if (bufLen < varDataLen(input) + VARSTR_HEADER_SIZE) {
1,958!
1283
      bufLen = varDataLen(input) + VARSTR_HEADER_SIZE;
×
1284
      pOutputBuf = taosMemoryRealloc(pOutputBuf, bufLen);
×
1285
      if (!pOutputBuf) {
×
1286
        qError("md5 function alloc memory failed");
×
1287
        return terrno;
×
1288
      }
1289
    }
1290
    char *output = pOutputBuf;
1,958✔
1291
    (void)memcpy(varDataVal(output), varDataVal(input), varDataLen(input));
1,958✔
1292
    int32_t len = taosCreateMD5Hash(varDataVal(output), varDataLen(input));
1,958✔
1293
    varDataSetLen(output, len);
1,958✔
1294
    int32_t code = colDataSetVal(pOutputData, i, output, false);
1,958✔
1295
    if (TSDB_CODE_SUCCESS != code) {
1,958!
1296
      taosMemoryFree(pOutputBuf);
×
1297
      SCL_ERR_RET(code);
×
1298
    }
1299

1300
  }
1301
  pOutput->numOfRows = pInput->numOfRows;
1,958✔
1302
  taosMemoryFree(pOutputBuf);
1,958✔
1303
  return TSDB_CODE_SUCCESS;
1,958✔
1304
}
1305

1306
static void getAsciiChar(int32_t num, char **output) {
30✔
1307
  if (num & 0xFF000000L) {
30!
1308
    INT4TOCHAR(*output, num);
×
1309
  } else if (num & 0xFF0000L) {
30!
1310
    INT3TOCHAR(*output, num);
×
1311
  } else if (num & 0xFF00L) {
30✔
1312
    INT2TOCHAR(*output, num);
2✔
1313
  } else {
1314
    INT1TOCHAR(*output, num);
28✔
1315
  }
1316
}
30✔
1317
int32_t charFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
20✔
1318
  int32_t code = TSDB_CODE_SUCCESS;
20✔
1319
  int32_t outputLen = inputNum * 4 + 2;
20✔
1320
  char   *outputBuf = taosMemoryCalloc(outputLen, 1);
20✔
1321
  if (outputBuf == NULL) {
20!
1322
    SCL_ERR_RET(terrno);
×
1323
  }
1324
  int32_t numOfRows = 0;
20✔
1325
  for (int32_t i = 0; i < inputNum; ++i) {
52✔
1326
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
32✔
1327
  }
1328
  for (int32_t i = 0; i < numOfRows; ++i) {
40✔
1329
    char   *output = varDataVal(outputBuf);
20✔
1330
    for (int32_t j = 0; j < inputNum; ++j) {
52✔
1331
      int32_t colIdx = (pInput[j].numOfRows == 1) ? 0 : i;
32!
1332
      int32_t num;
1333
      if (colDataIsNull_s(pInput[j].columnData, i)) {
64✔
1334
        continue;
2✔
1335
      } else if (IS_NUMERIC_TYPE(GET_PARAM_TYPE(&pInput[j]))) {
30!
1336
        GET_TYPED_DATA(num, int32_t, GET_PARAM_TYPE(&pInput[j]), colDataGetData(pInput[j].columnData, colIdx));
27!
1337
        getAsciiChar(num, &output);
27✔
1338
      } else if (TSDB_DATA_TYPE_BINARY == GET_PARAM_TYPE(&pInput[j])) {
3!
1339
        num = taosStr2Int32(varDataVal(colDataGetData(pInput[j].columnData, colIdx)), NULL, 10);
3!
1340
        getAsciiChar(num, &output);
3✔
1341
      } else if (TSDB_DATA_TYPE_NCHAR == GET_PARAM_TYPE(&pInput[j])) {
×
1342
        char   *convBuf = taosMemoryMalloc(GET_PARAM_BYTES(&pInput[j]));
×
1343
        if (convBuf == NULL) {
×
1344
          SCL_ERR_RET(terrno);
×
1345
        }
1346
        int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(colDataGetData(pInput[j].columnData, colIdx)), varDataLen(colDataGetData(pInput[j].columnData, colIdx)), convBuf);
×
1347
        if (len < 0) {
×
1348
          taosMemoryFree(convBuf);
×
1349
          code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1350
          goto _return;
×
1351
        }
1352
        convBuf[len] = 0;
×
1353
        num = taosStr2Int32(convBuf, NULL, 10);
×
1354
        getAsciiChar(num, &output);
×
1355
        taosMemoryFree(convBuf);
×
1356
      } else {
1357
        code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
1358
        goto _return;
×
1359
      }
1360
    }
1361
    varDataSetLen(outputBuf, output - varDataVal(outputBuf));
20✔
1362
    SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, outputBuf, false));
20!
1363
  }
1364
  pOutput->numOfRows = pInput->numOfRows;
20✔
1365

1366
_return:
20✔
1367
  taosMemoryFree(outputBuf);
20✔
1368
  return code;
20✔
1369
}
1370

1371
int32_t asciiFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
28✔
1372
  int32_t type = GET_PARAM_TYPE(pInput);
28!
1373

1374
  SColumnInfoData *pInputData = pInput->columnData;
28✔
1375
  SColumnInfoData *pOutputData = pOutput->columnData;
28✔
1376

1377
  uint8_t *out = (uint8_t *)pOutputData->pData;
28✔
1378

1379
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
56✔
1380
    if (colDataIsNull_s(pInputData, i)) {
56✔
1381
      colDataSetNULL(pOutputData, i);
1!
1382
      continue;
1✔
1383
    }
1384
    if (type == TSDB_DATA_TYPE_NCHAR) {
27!
1385
      char   *in = varDataVal(colDataGetData(pInputData, i));
×
1386
      int32_t inLen = varDataLen(colDataGetData(pInputData, i));
×
1387
      SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData, i)), &in,
×
1388
                                             varDataLen(colDataGetData(pInputData, i)), &inLen,
1389
                                             TSDB_DATA_TYPE_VARBINARY));
1390
      out[i] = (uint8_t)(in)[0];
×
1391
      taosMemoryFree(in);
×
1392
    } else {
1393
      char *in = colDataGetData(pInputData, i);
27!
1394
      out[i] = (uint8_t)(varDataVal(in))[0];
27✔
1395
    }
1396
  }
1397

1398
  pOutput->numOfRows = pInput->numOfRows;
28✔
1399
  return TSDB_CODE_SUCCESS;
28✔
1400
}
1401

1402
static int32_t findPosChars(char *orgStr, char *delimStr, int32_t orgLen, int32_t delimLen, bool isNchar) {
28✔
1403
  int32_t charCount = 0;
28✔
1404
  for (int32_t pos = 0; pos < orgLen; pos += isNchar ? TSDB_NCHAR_SIZE : 1) {
121!
1405
    if (isNchar || isCharStart(orgStr[pos])) {
116!
1406
      if (pos + delimLen > orgLen) {
99✔
1407
        return 0;
3✔
1408
      }
1409
      if (memcmp(orgStr + pos, delimStr, delimLen) == 0) {
96✔
1410
        return charCount + 1;
20✔
1411
      } else {
1412
        charCount++;
76✔
1413
      }
1414
    }
1415
  }
1416
  return 0;
5✔
1417
}
1418

1419
int32_t positionFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
34✔
1420
  int32_t          code = TSDB_CODE_SUCCESS;
34✔
1421
  int32_t          numOfRows = 0;
34✔
1422
  SColumnInfoData *pInputData[2];
1423
  SColumnInfoData *pOutputData = pOutput[0].columnData;
34✔
1424

1425
  pInputData[0] = pInput[0].columnData;
34✔
1426
  pInputData[1] = pInput[1].columnData;
34✔
1427
  numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
34✔
1428

1429
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
34!
1430

1431
  if (hasNullType ||
34✔
1432
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
62!
1433
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0))) {
62!
1434
    colDataSetNNULL(pOutputData, 0, numOfRows);
3!
1435
  }
1436

1437
  for (int32_t i = 0; i < numOfRows; ++i) {
68✔
1438
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
34!
1439
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
34!
1440
    if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2)) {
101✔
1441
      colDataSetNULL(pOutputData, i);
3!
1442
      continue;
6✔
1443
    }
1444
    int64_t offset = 0;
31✔
1445
    if (varDataLen(colDataGetData(pInputData[0], colIdx1)) == 0) {
31!
1446
      offset = 1;
3✔
1447
      colDataSetInt64(pOutputData, i, &offset);
3✔
1448
      continue;
3✔
1449
    }
1450

1451
    char   *substr = varDataVal(colDataGetData(pInputData[0], colIdx1));
28!
1452
    char   *orgstr = varDataVal(colDataGetData(pInputData[1], colIdx2));
28!
1453
    int32_t subLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
28!
1454
    int32_t orgLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
28!
1455
    bool    needFreeSub = false;
28✔
1456
    if (GET_PARAM_TYPE(&pInput[1]) != GET_PARAM_TYPE(&pInput[0])) {
28!
1457
      SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[0], colIdx1)), &substr, varDataLen(colDataGetData(pInputData[0], colIdx1)), &subLen, GET_PARAM_TYPE(&pInput[1])));
×
1458
      needFreeSub = true;
×
1459
    }
1460

1461
    offset = findPosChars(orgstr, substr, orgLen, subLen, GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NCHAR);
28!
1462
    if (needFreeSub) {
28!
1463
      taosMemoryFree(substr);
×
1464
    }
1465
    colDataSetInt64(pOutput->columnData, i, &offset);
28✔
1466
  }
1467

1468
  pOutput->numOfRows = numOfRows;
34✔
1469
  return code;
34✔
1470
}
1471

1472
int32_t trimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
75✔
1473
  // trim space
1474
  uint8_t trimType = 0;
75✔
1475
  GET_TYPED_DATA(trimType, int32_t, GET_PARAM_TYPE(&pInput[inputNum - 1]), pInput[inputNum - 1].columnData->pData);
75!
1476
  switch (trimType) {
75!
1477
    case TRIM_TYPE_LEADING: {
14✔
1478
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, tltrimspace, tltrim));
14!
1479
      break;
14✔
1480
    }
1481
    case TRIM_TYPE_TRAILING: {
14✔
1482
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, trtrimspace, trtrim));
14!
1483
      break;
14✔
1484
    }
1485
    case TRIM_TYPE_BOTH: {
47✔
1486
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, tlrtrimspace, tlrtrim));
47!
1487
      break;
47✔
1488
    }
1489
  }
1490
  return TSDB_CODE_SUCCESS;
75✔
1491
}
1492

1493
int32_t replaceFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
37✔
1494
  int32_t          code = TSDB_CODE_SUCCESS;
37✔
1495
  SColumnInfoData *pInputData[3];
1496
  SColumnInfoData *pOutputData = pOutput[0].columnData;
37✔
1497
  int32_t          outputLen;
1498
  int32_t          numOfRows = 0;
37✔
1499

1500
  pInputData[0] = pInput[0].columnData;
37✔
1501
  pInputData[1] = pInput[1].columnData;
37✔
1502
  pInputData[2] = pInput[2].columnData;
37✔
1503

1504
  for (int i = 0; i < 3; i++) {
148✔
1505
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
111✔
1506
  }
1507

1508
  int8_t  orgType = pInputData[0]->info.type;
37✔
1509
  int8_t  toType = pInputData[2]->info.type;
37✔
1510
  int32_t orgLength = pInputData[0]->info.bytes - VARSTR_HEADER_SIZE;
37✔
1511
  int32_t toLength = pInputData[2]->info.bytes - VARSTR_HEADER_SIZE;
37✔
1512

1513
  if (orgType == TSDB_DATA_TYPE_NCHAR && toType != orgType) {
37!
1514
    toLength = toLength * TSDB_NCHAR_SIZE;
×
1515
  }
1516
  outputLen = toLength == 0 ? orgLength : TMIN(TSDB_MAX_FIELD_LEN, orgLength * toLength);
37✔
1517

1518
  if (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NULL ||
37!
1519
      GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NULL ||
35!
1520
      GET_PARAM_TYPE(&pInput[2]) == TSDB_DATA_TYPE_NULL ||
34!
1521
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
68!
1522
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0)) ||
68!
1523
      (pInput[2].numOfRows == 1 && colDataIsNull_s(pInputData[2], 0))) {
68!
1524
    colDataSetNNULL(pOutputData, 0, numOfRows);
3✔
1525
    pOutput->numOfRows = numOfRows;
3✔
1526
    return TSDB_CODE_SUCCESS;
3✔
1527
  }
1528

1529
  char *outputBuf = taosMemoryCalloc(outputLen + VARSTR_HEADER_SIZE, 1);
34✔
1530
  if (NULL == outputBuf) {
34!
1531
    SCL_ERR_RET(terrno);
×
1532
  }
1533

1534
  for (int32_t i = 0; i < numOfRows; ++i) {
68✔
1535
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
34!
1536
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
34!
1537
    int32_t colIdx3 = (pInput[2].numOfRows == 1) ? 0 : i;
34!
1538
    if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2) || colDataIsNull_s(pInputData[2], colIdx3)) {
136!
1539
      colDataSetNULL(pOutputData, i);
×
1540
      continue;
3✔
1541
    }
1542
    char   *output = outputBuf + VARSTR_HEADER_SIZE;
34✔
1543
    int32_t totalLen = 0;
34✔
1544

1545
    char   *orgStr = varDataVal(colDataGetData(pInputData[0], colIdx1));
34!
1546
    int32_t orgLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
34!
1547
    char   *fromStr = varDataVal(colDataGetData(pInputData[1], colIdx2));
34!
1548
    int32_t fromLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
34!
1549
    char   *toStr = varDataVal(colDataGetData(pInputData[2], colIdx3));
34!
1550
    int32_t toLen = varDataLen(colDataGetData(pInputData[2], colIdx3));
34!
1551
    bool    needFreeFrom = false;
34✔
1552
    bool    needFreeTo = false;
34✔
1553

1554
    if (fromLen == 0 || orgLen == 0) {
34✔
1555
      (void)memcpy(output, orgStr, orgLen);
3✔
1556
      totalLen = orgLen;
3✔
1557
      varDataSetLen(outputBuf, totalLen);
3✔
1558
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
3!
1559
      continue;
3✔
1560
    }
1561

1562
    if (GET_PARAM_TYPE(&pInput[1]) != GET_PARAM_TYPE(&pInput[0])) {
31!
1563
      SCL_ERR_JRET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[1], colIdx2)), &fromStr,
×
1564
                                             varDataLen(colDataGetData(pInputData[1], colIdx2)), &fromLen,
1565
                                             GET_PARAM_TYPE(&pInput[0])));
1566
      needFreeFrom = true;
×
1567
    }
1568
    if (GET_PARAM_TYPE(&pInput[2]) != GET_PARAM_TYPE(&pInput[0])) {
31!
1569
      code = convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[2], colIdx3)), &toStr,
×
1570
                                        varDataLen(colDataGetData(pInputData[2], colIdx3)), &toLen,
×
1571
                                        GET_PARAM_TYPE(&pInput[0]));
×
1572
      if (TSDB_CODE_SUCCESS != code) {
×
1573
        if (needFreeFrom) {
×
1574
          taosMemoryFree(fromStr);
×
1575
        }
1576
        goto _return;
×
1577
      }
1578
      needFreeTo = true;
×
1579
    }
1580

1581
    int32_t pos = 0;
31✔
1582
    while (pos < orgLen) {
179✔
1583
      if (orgLen - pos < fromLen) {
155✔
1584
        (void)memcpy(output, orgStr + pos, orgLen - pos);
7✔
1585
        output += orgLen - pos;
7✔
1586
        totalLen += orgLen - pos;
7✔
1587
        break;
7✔
1588
      }
1589
      if (memcmp(orgStr + pos, fromStr, fromLen) == 0 &&
148✔
1590
          (pos + fromLen == orgLen ||
78✔
1591
           isCharStart(orgStr[pos + fromLen]) ||
34✔
1592
           GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR)) {
1!
1593
        (void)memcpy(output, toStr, toLen);
43✔
1594
        output += toLen;
43✔
1595
        pos += fromLen;
43✔
1596
        totalLen += toLen;
43✔
1597
      } else {
1598
        int32_t charLen = GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR ? TSDB_NCHAR_SIZE : getCharLen(orgStr + pos);
105!
1599
        (void)memcpy(output, orgStr + pos, charLen);
105✔
1600
        output += charLen;
105✔
1601
        totalLen += charLen;
105✔
1602
        pos += charLen;
105✔
1603
      }
1604
    }
1605
    if (needFreeTo) {
31!
1606
      taosMemoryFree(toStr);
×
1607
    }
1608
    if (needFreeFrom) {
31!
1609
      taosMemoryFree(fromStr);
×
1610
    }
1611
    if (totalLen > TSDB_MAX_FIELD_LEN) {
31!
1612
      SCL_ERR_JRET(TSDB_CODE_FUNC_INVALID_RES_LENGTH);
×
1613
    }
1614
    varDataSetLen(outputBuf, totalLen);
31✔
1615
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
31!
1616
  }
1617
  pOutput->numOfRows = numOfRows;
34✔
1618
_return:
34✔
1619
  taosMemoryFree(outputBuf);
34✔
1620
  return code;
34✔
1621
}
1622

1623
int32_t substrIdxFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
79✔
1624
  int32_t          code = TSDB_CODE_SUCCESS;
79✔
1625
  SColumnInfoData *pInputData[3];
1626
  SColumnInfoData *pOutputData = pOutput[0].columnData;
79✔
1627
  int32_t          outputLen;
1628
  int32_t          numOfRows = 0;
79✔
1629

1630
  pInputData[0] = pInput[0].columnData;
79✔
1631
  pInputData[1] = pInput[1].columnData;
79✔
1632
  pInputData[2] = pInput[2].columnData;
79✔
1633

1634
  for (int32_t i = 0; i < inputNum; ++i) {
316✔
1635
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
237✔
1636
  }
1637

1638
  outputLen = pInputData[0]->info.bytes;
79✔
1639
  if (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NULL || GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NULL || GET_PARAM_TYPE(&pInput[2]) == TSDB_DATA_TYPE_NULL) {
79!
1640
    colDataSetNNULL(pOutputData, 0, numOfRows);
4✔
1641
    pOutput->numOfRows = numOfRows;
4✔
1642
    return TSDB_CODE_SUCCESS;
4✔
1643
  }
1644
  char *outputBuf = taosMemoryCalloc(outputLen + VARSTR_HEADER_SIZE, 1);
75✔
1645
  if (NULL == outputBuf) {
75!
1646
    SCL_ERR_RET(terrno);
×
1647
  }
1648

1649
  for (int32_t k = 0; k < numOfRows; ++k) {
150✔
1650
    bool hasNull = false;
75✔
1651
    for (int32_t i = 0; i < inputNum; ++i) {
300✔
1652
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
450!
1653
        colDataSetNULL(pOutputData, k);
×
1654
        hasNull = true;
×
1655
        break;
×
1656
      }
1657
    }
1658
    if (hasNull) {
75!
1659
      continue;
×
1660
    }
1661

1662
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : k;
75!
1663
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : k;
75!
1664
    int32_t count = 0;
75✔
1665
    char   *orgStr = varDataVal(colDataGetData(pInputData[0], colIdx1));
75!
1666
    int32_t orgLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
75!
1667
    char   *delimStr = varDataVal(colDataGetData(pInputData[1], colIdx2));
75!
1668
    int32_t delimLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
75!
1669
    bool    needFreeDelim = false;
75✔
1670
    GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[2]), colDataGetData(pInputData[2], (pInput[2].numOfRows == 1) ? 0 : k));
75!
1671

1672
    int32_t startPosBytes;
1673
    int32_t endPosBytes;
1674
    if (GET_PARAM_TYPE(&pInput[0]) != GET_PARAM_TYPE(&pInput[1])) {
75!
1675
      SCL_ERR_JRET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[1], colIdx2)), &delimStr,
×
1676
                                              varDataLen(colDataGetData(pInputData[1], colIdx2)), &delimLen,
1677
                                              GET_PARAM_TYPE(&pInput[0])));
1678
      needFreeDelim = true;
×
1679
    }
1680

1681
    if (count > 0) {
75✔
1682
      startPosBytes = 0;
36✔
1683
      endPosBytes = findPosBytes(orgStr, delimStr, orgLen, delimLen, count, GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR);
36!
1684
    } else if (count < 0) {
39✔
1685
      startPosBytes = findPosBytes(orgStr, delimStr, orgLen, delimLen, count, GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR);
38!
1686
      endPosBytes = orgLen;
38✔
1687
    } else {
1688
      startPosBytes = endPosBytes = 0;
1✔
1689
    }
1690

1691
    char   *output = outputBuf;
75✔
1692
    int32_t resLen = endPosBytes - startPosBytes;
75✔
1693
    if (resLen > 0) {
75✔
1694
      (void)memcpy(varDataVal(output), orgStr + startPosBytes, resLen);
73✔
1695
      varDataSetLen(output, resLen);
73✔
1696
    } else {
1697
      varDataSetLen(output, 0);
2✔
1698
    }
1699
    if (needFreeDelim) {
75!
1700
      taosMemoryFree(delimStr);
×
1701
    }
1702

1703
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
75!
1704
  }
1705
  pOutput->numOfRows = numOfRows;
75✔
1706
_return:
75✔
1707
  taosMemoryFree(outputBuf);
75✔
1708
  return code;
75✔
1709
}
1710

1711
static int32_t repeatStringHelper(char *input, int32_t inputLen, int32_t count, char *output) {
36✔
1712
  for (int32_t i = 0; i < count; ++i) {
17,371✔
1713
    (void)memcpy(output, input, inputLen);
17,335✔
1714
    output += inputLen;
17,335✔
1715
  }
1716
  return TSDB_CODE_SUCCESS;
36✔
1717
}
1718

1719
int32_t repeatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
41✔
1720
  int32_t          code = TSDB_CODE_SUCCESS;
41✔
1721
  SColumnInfoData *pInputData[2];
1722
  SColumnInfoData *pOutputData = pOutput[0].columnData;
41✔
1723
  int32_t          outputLen;
1724
  int32_t          numOfRows;
1725
  int32_t          maxCount = 0;
41✔
1726

1727
  for (int32_t i = 0; i < pInput[1].numOfRows; i++) {
82✔
1728
    int32_t tmpCount = 0;
41✔
1729
    if (colDataIsNull_s(pInput[1].columnData, i)) {
82✔
1730
      continue;
1✔
1731
    }
1732
    GET_TYPED_DATA(tmpCount, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i));
40!
1733
    maxCount = TMAX(maxCount, tmpCount);
40✔
1734
  }
1735
  pInputData[0] = pInput[0].columnData;
41✔
1736
  pInputData[1] = pInput[1].columnData;
41✔
1737
  outputLen = (int32_t)(pInputData[0]->info.bytes * maxCount + VARSTR_HEADER_SIZE);
41✔
1738
  if (outputLen > TSDB_MAX_FIELD_LEN) {
41✔
1739
    return TSDB_CODE_FUNC_INVALID_RES_LENGTH;
1✔
1740
  }
1741
  numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
40✔
1742
  char *outputBuf = taosMemoryCalloc(outputLen, 1);
40✔
1743
  if (outputBuf == NULL) {
40!
1744
    SCL_ERR_RET(terrno);
×
1745
  }
1746

1747
  char   *output = outputBuf;
40✔
1748

1749
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
40!
1750
  if (pInput[0].numOfRows == pInput[1].numOfRows) {
40!
1751
    for (int32_t i = 0; i < numOfRows; ++i) {
80✔
1752
      output = outputBuf;
40✔
1753
      if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) {
119!
1754
        colDataSetNULL(pOutputData, i);
2✔
1755
        continue;
2✔
1756
      }
1757
      int32_t count = 0;
38✔
1758
      GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i));
38!
1759
      if (count <= 0) {
38✔
1760
        varDataSetLen(output, 0);
2✔
1761
        SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
2!
1762
      } else {
1763
        char   *orgStr = colDataGetData(pInputData[0], i);
36!
1764
        varDataSetLen(output, varDataLen(orgStr) * count);
36✔
1765
        SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
36!
1766
        SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
36!
1767
      }
1768
    }
1769
  } else if (pInput[0].numOfRows == 1) {
×
1770
    if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
×
1771
      colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows);
×
1772
    } else {
1773
      for (int32_t i = 0; i < numOfRows; ++i) {
×
1774
        output = outputBuf;
×
1775
        if (colDataIsNull_s(pInputData[1], i)) {
×
1776
          colDataSetNULL(pOutputData, i);
×
1777
          continue;
×
1778
        }
1779
        int32_t count = 0;
×
1780
        GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i));
×
1781
        if (count <= 0) {
×
1782
          varDataSetLen(output, 0);
×
1783
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1784
        } else {
1785
          char   *orgStr = colDataGetData(pInputData[0], 0);
×
1786
          varDataSetLen(output, varDataLen(orgStr) * count);
×
1787
          SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
×
1788
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1789
        }
1790
      }
1791
    }
1792
  } else if (pInput[1].numOfRows == 1) {
×
1793
    if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
×
1794
      colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows);
×
1795
    } else {
1796
      for (int32_t i = 0; i < numOfRows; ++i) {
×
1797
        output = outputBuf;
×
1798
        if (colDataIsNull_s(pInputData[0], i)) {
×
1799
          colDataSetNULL(pOutputData, i);
×
1800
          continue;
×
1801
        }
1802
        int32_t count = 0;
×
1803
        GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, 0));
×
1804
        if (count <= 0) {
×
1805
          varDataSetLen(output, 0);
×
1806
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1807
        } else {
1808
          char   *orgStr = colDataGetData(pInputData[0], i);
×
1809
          varDataSetLen(output, varDataLen(orgStr) * count);
×
1810
          SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
×
1811
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1812
        }
1813
      }
1814
    }
1815
  }
1816

1817
  pOutput->numOfRows = numOfRows;
40✔
1818
_return:
40✔
1819
  taosMemoryFree(outputBuf);
40✔
1820
  return code;
40✔
1821
}
1822

1823
/** Conversion functions **/
1824
int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4,758,375✔
1825
  int16_t inputType = GET_PARAM_TYPE(&pInput[0]);
4,758,375!
1826
  int32_t inputLen = GET_PARAM_BYTES(&pInput[0]);
4,758,375✔
1827
  int16_t outputType = GET_PARAM_TYPE(&pOutput[0]);
4,758,375!
1828
  int64_t outputLen = GET_PARAM_BYTES(&pOutput[0]);
4,758,375✔
1829

1830
  int32_t code = TSDB_CODE_SUCCESS;
4,758,375✔
1831
  char   *convBuf = taosMemoryMalloc(inputLen);
4,758,375✔
1832
  char   *output = taosMemoryCalloc(1, outputLen + TSDB_NCHAR_SIZE);
4,757,377✔
1833
  int32_t bufSize = TSDB_MAX_FIELD_LEN + 1;
4,762,721✔
1834
  char   *buf = taosMemoryMalloc(bufSize);
4,762,721✔
1835

1836
  if (convBuf == NULL || output == NULL || buf == NULL) {
4,762,841!
1837
    code = terrno;
219✔
1838
    goto _end;
×
1839
  }
1840

1841
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
993,888,169!
1842
    if (colDataIsNull_s(pInput[0].columnData, i)) {
2,002,060,024✔
1843
      colDataSetNULL(pOutput->columnData, i);
2,428,978✔
1844
      continue;
2,428,978✔
1845
    }
1846

1847
    char *input = colDataGetData(pInput[0].columnData, i);
998,601,034!
1848

1849
    switch (outputType) {
998,601,034!
1850
      case TSDB_DATA_TYPE_TINYINT: {
76,188✔
1851
        if (inputType == TSDB_DATA_TYPE_BINARY) {
76,188✔
1852
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
10,983✔
1853
          buf[varDataLen(input)] = 0;
10,983✔
1854
          *(int8_t *)output = taosStr2Int8(buf, NULL, 10);
10,983✔
1855
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
65,205✔
1856
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
5,302✔
1857
          if (len < 0) {
5,302!
1858
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1859
            goto _end;
×
1860
          }
1861

1862
          convBuf[len] = 0;
5,302✔
1863
          *(int8_t *)output = taosStr2Int8(convBuf, NULL, 10);
5,302✔
1864
        } else {
1865
          GET_TYPED_DATA(*(int8_t *)output, int8_t, inputType, input);
59,903!
1866
        }
1867
        break;
76,188✔
1868
      }
1869
      case TSDB_DATA_TYPE_SMALLINT: {
65,066✔
1870
        if (inputType == TSDB_DATA_TYPE_BINARY) {
65,066✔
1871
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
9,623✔
1872
          buf[varDataLen(input)] = 0;
9,623✔
1873
          *(int16_t *)output = taosStr2Int16(buf, NULL, 10);
9,623✔
1874
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
55,443✔
1875
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
2,751✔
1876
          if (len < 0) {
2,751!
1877
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1878
            goto _end;
×
1879
          }
1880
          convBuf[len] = 0;
2,751✔
1881
          *(int16_t *)output = taosStr2Int16(convBuf, NULL, 10);
2,751✔
1882
        } else {
1883
          GET_TYPED_DATA(*(int16_t *)output, int16_t, inputType, input);
52,692!
1884
        }
1885
        break;
65,066✔
1886
      }
1887
      case TSDB_DATA_TYPE_INT: {
530,853,316✔
1888
        if (inputType == TSDB_DATA_TYPE_BINARY) {
530,853,316✔
1889
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
4,591,768✔
1890
          buf[varDataLen(input)] = 0;
4,591,768✔
1891
          *(int32_t *)output = taosStr2Int32(buf, NULL, 10);
4,591,768✔
1892
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
526,261,548✔
1893
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
3,202✔
1894
          if (len < 0) {
3,202!
1895
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1896
            goto _end;
×
1897
          }
1898

1899
          convBuf[len] = 0;
3,202✔
1900
          *(int32_t *)output = taosStr2Int32(convBuf, NULL, 10);
3,202✔
1901
        } else {
1902
          GET_TYPED_DATA(*(int32_t *)output, int32_t, inputType, input);
526,258,346!
1903
        }
1904
        break;
530,849,417✔
1905
      }
1906
      case TSDB_DATA_TYPE_BIGINT: {
451,200✔
1907
        if (inputType == TSDB_DATA_TYPE_BINARY) {
451,200✔
1908
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
57,214✔
1909
          buf[varDataLen(input)] = 0;
57,214✔
1910
          *(int64_t *)output = taosStr2Int64(buf, NULL, 10);
57,214✔
1911
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
393,986✔
1912
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
100,367✔
1913
          if (len < 0) {
100,557!
1914
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1915
            goto _end;
×
1916
          }
1917
          convBuf[len] = 0;
100,557✔
1918
          *(int64_t *)output = taosStr2Int64(convBuf, NULL, 10);
100,557✔
1919
        } else {
1920
          GET_TYPED_DATA(*(int64_t *)output, int64_t, inputType, input);
293,619!
1921
        }
1922
        break;
451,309✔
1923
      }
1924
      case TSDB_DATA_TYPE_UTINYINT: {
6,504✔
1925
        if (inputType == TSDB_DATA_TYPE_BINARY) {
6,504✔
1926
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
5,894✔
1927
          buf[varDataLen(input)] = 0;
5,894✔
1928
          *(uint8_t *)output = taosStr2UInt8(buf, NULL, 10);
5,894✔
1929
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
610!
1930
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
×
1931
          if (len < 0) {
×
1932
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1933
            goto _end;
×
1934
          }
1935
          convBuf[len] = 0;
×
1936
          *(uint8_t *)output = taosStr2UInt8(convBuf, NULL, 10);
×
1937
        } else {
1938
          GET_TYPED_DATA(*(uint8_t *)output, uint8_t, inputType, input);
610!
1939
        }
1940
        break;
6,504✔
1941
      }
1942
      case TSDB_DATA_TYPE_USMALLINT: {
5,901✔
1943
        if (inputType == TSDB_DATA_TYPE_BINARY) {
5,901✔
1944
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
5,221✔
1945
          buf[varDataLen(input)] = 0;
5,221✔
1946
          *(uint16_t *)output = taosStr2UInt16(buf, NULL, 10);
5,221✔
1947
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
680!
1948
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
×
1949
          if (len < 0) {
×
1950
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1951
            goto _end;
×
1952
          }
1953
          convBuf[len] = 0;
×
1954
          *(uint16_t *)output = taosStr2UInt16(convBuf, NULL, 10);
×
1955
        } else {
1956
          GET_TYPED_DATA(*(uint16_t *)output, uint16_t, inputType, input);
680!
1957
        }
1958
        break;
5,901✔
1959
      }
1960
      case TSDB_DATA_TYPE_UINT: {
6,129✔
1961
        if (inputType == TSDB_DATA_TYPE_BINARY) {
6,129✔
1962
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
5,221✔
1963
          buf[varDataLen(input)] = 0;
5,221✔
1964
          *(uint32_t *)output = taosStr2UInt32(buf, NULL, 10);
5,221✔
1965
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
908!
1966
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
×
1967
          if (len < 0) {
×
1968
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1969
            goto _end;
×
1970
          }
1971
          convBuf[len] = 0;
×
1972
          *(uint32_t *)output = taosStr2UInt32(convBuf, NULL, 10);
×
1973
        } else {
1974
          GET_TYPED_DATA(*(uint32_t *)output, uint32_t, inputType, input);
908!
1975
        }
1976
        break;
6,129✔
1977
      }
1978
      case TSDB_DATA_TYPE_UBIGINT: {
171,579✔
1979
        if (inputType == TSDB_DATA_TYPE_BINARY) {
171,579✔
1980
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
69,922✔
1981
          buf[varDataLen(input)] = 0;
69,922✔
1982
          *(uint64_t *)output = taosStr2UInt64(buf, NULL, 10);
69,922✔
1983
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
101,657✔
1984
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
48,701✔
1985
          if (len < 0) {
48,811!
1986
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1987
            goto _end;
×
1988
          }
1989

1990
          convBuf[len] = 0;
48,811✔
1991
          *(uint64_t *)output = taosStr2UInt64(convBuf, NULL, 10);
48,811✔
1992
        } else {
1993
          GET_TYPED_DATA(*(uint64_t *)output, uint64_t, inputType, input);
52,956!
1994
        }
1995
        break;
171,661✔
1996
      }
1997
      case TSDB_DATA_TYPE_FLOAT: {
87,184✔
1998
        if (inputType == TSDB_DATA_TYPE_BINARY) {
87,184✔
1999
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
11,125✔
2000
          buf[varDataLen(input)] = 0;
11,125✔
2001
          *(float *)output = taosStr2Float(buf, NULL);
11,125✔
2002
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
76,059✔
2003
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
5,402✔
2004
          if (len < 0) {
5,402!
2005
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2006
            goto _end;
×
2007
          }
2008
          convBuf[len] = 0;
5,402✔
2009
          *(float *)output = taosStr2Float(convBuf, NULL);
5,402✔
2010
        } else {
2011
          GET_TYPED_DATA(*(float *)output, float, inputType, input);
70,657!
2012
        }
2013
        break;
87,184✔
2014
      }
2015
      case TSDB_DATA_TYPE_DOUBLE: {
77,701✔
2016
        if (inputType == TSDB_DATA_TYPE_BINARY) {
77,701✔
2017
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
9,132✔
2018
          buf[varDataLen(input)] = 0;
9,132✔
2019
          *(double *)output = taosStr2Double(buf, NULL);
9,132✔
2020
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
68,569✔
2021
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
4,201✔
2022
          if (len < 0) {
4,201!
2023
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2024
            goto _end;
×
2025
          }
2026
          convBuf[len] = 0;
4,201✔
2027
          *(double *)output = taosStr2Double(convBuf, NULL);
4,201✔
2028
        } else {
2029
          GET_TYPED_DATA(*(double *)output, double, inputType, input);
64,368!
2030
        }
2031
        break;
77,701✔
2032
      }
2033
      case TSDB_DATA_TYPE_BOOL: {
520,415,686✔
2034
        if (inputType == TSDB_DATA_TYPE_BINARY) {
520,415,686✔
2035
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
18,130✔
2036
          buf[varDataLen(input)] = 0;
18,130✔
2037
          *(bool *)output = taosStr2Int8(buf, NULL, 10);
18,130✔
2038
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
520,397,556✔
2039
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
4,004✔
2040
          if (len < 0) {
4,004!
2041
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2042
            goto _end;
×
2043
          }
2044
          convBuf[len] = 0;
4,004✔
2045
          *(bool *)output = taosStr2Int8(convBuf, NULL, 10);
4,004✔
2046
        } else {
2047
          GET_TYPED_DATA(*(bool *)output, bool, inputType, input);
520,393,552!
2048
        }
2049
        break;
520,415,686✔
2050
      }
2051
      case TSDB_DATA_TYPE_TIMESTAMP: {
210,700✔
2052
        int64_t timeVal;
2053
        if (inputType == TSDB_DATA_TYPE_BINARY || inputType == TSDB_DATA_TYPE_NCHAR) {
274,211✔
2054
          int64_t timePrec;
2055
          GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
127,032✔
2056
          int32_t ret = convertStringToTimestamp(inputType, input, timePrec, &timeVal);
63,516✔
2057
          if (ret != TSDB_CODE_SUCCESS) {
63,511✔
2058
            *(int64_t *)output = 0;
60,901✔
2059
          } else {
2060
            *(int64_t *)output = timeVal;
2,610✔
2061
          }
2062
        } else {
2063
          GET_TYPED_DATA(*(int64_t *)output, int64_t, inputType, input);
147,184!
2064
        }
2065
        break;
210,695✔
2066
      }
2067
      case TSDB_DATA_TYPE_BINARY:
9,803,925✔
2068
      case TSDB_DATA_TYPE_GEOMETRY: {
2069
        if (inputType == TSDB_DATA_TYPE_BOOL) {
9,803,925✔
2070
          // NOTE: snprintf will append '\0' at the end of string
2071
          int32_t len = tsnprintf(varDataVal(output), outputLen + TSDB_NCHAR_SIZE - VARSTR_HEADER_SIZE, "%.*s",
71,524✔
2072
                                 (int32_t)(outputLen - VARSTR_HEADER_SIZE), *(int8_t *)input ? "true" : "false");
143,048✔
2073
          varDataSetLen(output, len);
71,548✔
2074
        } else if (inputType == TSDB_DATA_TYPE_BINARY) {
9,732,401✔
2075
          int32_t len = TMIN(varDataLen(input), outputLen - VARSTR_HEADER_SIZE);
22,017✔
2076
          (void)memcpy(varDataVal(output), varDataVal(input), len);
22,017✔
2077
          varDataSetLen(output, len);
22,017✔
2078
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
9,710,384✔
2079
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf);
31,639✔
2080
          if (len < 0) {
31,639!
2081
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2082
            goto _end;
×
2083
          }
2084
          len = TMIN(len, outputLen - VARSTR_HEADER_SIZE);
31,639✔
2085
          (void)memcpy(varDataVal(output), convBuf, len);
31,639✔
2086
          varDataSetLen(output, len);
31,639✔
2087
        } else {
2088
          int32_t outputSize = (outputLen - VARSTR_HEADER_SIZE) < bufSize ? (outputLen - VARSTR_HEADER_SIZE + 1): bufSize;
9,678,745✔
2089
          NUM_TO_STRING(inputType, input, outputSize, buf);
9,678,745!
2090
          int32_t len = (int32_t)strlen(buf);
9,678,745✔
2091
          len = (outputLen - VARSTR_HEADER_SIZE) > len ? len : (outputLen - VARSTR_HEADER_SIZE);
9,678,745✔
2092
          (void)memcpy(varDataVal(output), buf, len);
9,678,745✔
2093
          varDataSetLen(output, len);
9,678,745✔
2094
        }
2095
        break;
9,803,949✔
2096
      }
2097
      case TSDB_DATA_TYPE_VARBINARY:{
16✔
2098
        if (inputType == TSDB_DATA_TYPE_BINARY) {
16✔
2099
          int32_t len = TMIN(varDataLen(input), outputLen - VARSTR_HEADER_SIZE);
12✔
2100
          (void)memcpy(varDataVal(output), varDataVal(input), len);
12✔
2101
          varDataSetLen(output, len);
12✔
2102
        }else{
2103
          code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
4✔
2104
          goto _end;
4✔
2105
        }
2106
        break;
12✔
2107
      }
2108
      case TSDB_DATA_TYPE_NCHAR: {
439,860✔
2109
        int32_t outputCharLen = (outputLen - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
439,860✔
2110
        int32_t len;
2111
        if (inputType == TSDB_DATA_TYPE_BOOL) {
439,860✔
2112
          char tmp[8] = {0};
5,225✔
2113
          len = tsnprintf(tmp, sizeof(tmp), "%.*s", outputCharLen, *(int8_t *)input ? "true" : "false");
5,225✔
2114
          bool ret = taosMbsToUcs4(tmp, len, (TdUcs4 *)varDataVal(output), outputLen - VARSTR_HEADER_SIZE, &len);
5,225✔
2115
          if (!ret) {
5,225!
2116
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2117
            goto _end;
×
2118
          }
2119

2120
          varDataSetLen(output, len);
5,225✔
2121
        } else if (inputType == TSDB_DATA_TYPE_BINARY) {
434,635✔
2122
          len = outputCharLen > varDataLen(input) ? varDataLen(input) : outputCharLen;
192,799✔
2123
          bool ret = taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, (TdUcs4 *)varDataVal(output),
192,799✔
2124
                                   outputLen - VARSTR_HEADER_SIZE, &len);
192,799✔
2125
          if (!ret) {
193,052!
2126
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2127
            goto _end;
×
2128
          }
2129
          varDataSetLen(output, len);
193,052✔
2130
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
241,836✔
2131
          len = TMIN(outputLen - VARSTR_HEADER_SIZE, varDataLen(input));
187,699✔
2132
          (void)memcpy(output, input, len + VARSTR_HEADER_SIZE);
187,699✔
2133
          varDataSetLen(output, len);
187,699✔
2134
        } else {
2135
          NUM_TO_STRING(inputType, input, bufSize, buf);
54,137!
2136
          len = (int32_t)strlen(buf);
54,137✔
2137
          len = outputCharLen > len ? len : outputCharLen;
54,137✔
2138
          bool ret = taosMbsToUcs4(buf, len, (TdUcs4 *)varDataVal(output), outputLen - VARSTR_HEADER_SIZE, &len);
54,137✔
2139
          if (!ret) {
54,195!
2140
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2141
            goto _end;
×
2142
          }
2143
          varDataSetLen(output, len);
54,195✔
2144
        }
2145

2146
        // for constant conversion, need to set proper length of pOutput description
2147
        if (len < outputLen) {
440,171✔
2148
          pOutput->columnData->info.bytes = len + VARSTR_HEADER_SIZE;
440,147✔
2149
        }
2150

2151
        break;
440,171✔
2152
      }
2153
      default: {
×
2154
        code = TSDB_CODE_FAILED;
×
2155
        goto _end;
×
2156
      }
2157
    }
2158

2159
    code = colDataSetVal(pOutput->columnData, i, output, false);
1,062,667,573✔
2160
    if (TSDB_CODE_SUCCESS != code) {
986,696,569!
2161
      goto _end;
×
2162
    }
2163
  }
2164

2165
  pOutput->numOfRows = pInput->numOfRows;
×
2166

2167
_end:
×
2168
  taosMemoryFree(buf);
×
2169
  taosMemoryFree(output);
4,762,757✔
2170
  taosMemoryFree(convBuf);
4,760,937✔
2171
  return code;
4,759,727✔
2172
}
2173

2174
int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
15,459✔
2175
  int32_t type = GET_PARAM_TYPE(pInput);
15,459!
2176

2177
  bool    tzPresent = (inputNum == 2) ? true : false;
15,459✔
2178
  char    tz[20] = {0};
15,459✔
2179
  int32_t tzLen = 0;
15,459✔
2180
  if (tzPresent) {
15,459!
2181
    tzLen = varDataLen(pInput[1].columnData->pData);
15,459✔
2182
    (void)memcpy(tz, varDataVal(pInput[1].columnData->pData), tzLen);
15,459✔
2183
  }
2184

2185
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
350,086✔
2186
    if (colDataIsNull_s(pInput[0].columnData, i)) {
669,524!
2187
      colDataSetNULL(pOutput->columnData, i);
×
2188
      continue;
×
2189
    }
2190

2191
    char *input = colDataGetData(pInput[0].columnData, i);
334,762!
2192
    char  fraction[20] = {0};
334,762✔
2193
    bool  hasFraction = false;
334,762✔
2194
    NUM_TO_STRING(type, input, sizeof(fraction), fraction);
334,762!
2195
    int32_t fractionLen;
2196

2197
    char    buf[TD_TIME_STR_LEN] = {0};
334,762✔
2198
    int64_t timeVal;
2199
    char*   format = NULL;
334,762✔
2200
    int64_t  quot = 0;
334,762✔
2201
    long    mod = 0;
334,762✔
2202

2203
    GET_TYPED_DATA(timeVal, int64_t, type, input);
334,762!
2204

2205
    switch (pInput->columnData[0].info.precision) {
334,762!
2206
      case TSDB_TIME_PRECISION_MILLI: {
334,747✔
2207
        quot = timeVal / 1000;
334,747✔
2208
        fractionLen = 5;
334,747✔
2209
        format = ".%03" PRId64;
334,747✔
2210
        mod = timeVal % 1000;
334,747✔
2211
        break;
334,747✔
2212
      }
2213

2214
      case TSDB_TIME_PRECISION_MICRO: {
76✔
2215
        quot = timeVal / 1000000;
76✔
2216
        fractionLen = 8;
76✔
2217
        format = ".%06" PRId64;
76✔
2218
        mod = timeVal % 1000000;
76✔
2219
        break;
76✔
2220
      }
2221

2222
      case TSDB_TIME_PRECISION_NANO: {
76✔
2223
        quot = timeVal / 1000000000;
76✔
2224
        fractionLen = 11;
76✔
2225
        format = ".%09" PRId64;
76✔
2226
        mod = timeVal % 1000000000;
76✔
2227
        break;
76✔
2228
      }
2229

2230
      default: {
×
2231
        colDataSetNULL(pOutput->columnData, i);
×
2232
        continue;
×
2233
      }
2234
    }
2235

2236
    // trans current timezone's unix ts to dest timezone
2237
    // offset = delta from dest timezone to zero
2238
    // delta from zero to current timezone = 3600 * (cur)tsTimezone
2239
    int64_t offset = 0;
334,899✔
2240
    if (0 != offsetOfTimezone(tz, &offset)) {
334,899!
2241
      goto _end;
×
2242
    }
2243
    quot -= offset + 3600 * ((int64_t)tsTimezone);
334,649✔
2244

2245
    struct tm tmInfo;
2246
    int32_t len = 0;
334,649✔
2247

2248
    if (taosLocalTime((const time_t *)&quot, &tmInfo, buf, sizeof(buf)) == NULL) {
334,649!
2249
      len = (int32_t)strlen(buf);
×
2250
      goto _end;
×
2251
    }
2252

2253
    len = (int32_t)strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
334,924✔
2254

2255
    len += tsnprintf(buf + len, fractionLen, format, mod);
334,924✔
2256

2257
    // add timezone string
2258
    if (tzLen > 0) {
334,931✔
2259
      (void)snprintf(buf + len, tzLen + 1, "%s", tz);
334,897✔
2260
      len += tzLen;
334,897✔
2261
    }
2262

2263
_end:
34✔
2264
    memmove(buf + VARSTR_HEADER_SIZE, buf, len);
334,931✔
2265
    varDataSetLen(buf, len);
334,931✔
2266

2267
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, buf, false));
334,931!
2268
  }
2269

2270
  pOutput->numOfRows = pInput->numOfRows;
15,324✔
2271

2272
  return TSDB_CODE_SUCCESS;
15,324✔
2273
}
2274

2275
int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
12,673✔
2276
  int32_t type = GET_PARAM_TYPE(pInput);
12,673!
2277
  int64_t timePrec;
2278
  int32_t idx = (inputNum == 2) ? 1 : 2;
12,673✔
2279
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[idx]), pInput[idx].columnData->pData);
12,673!
2280

2281
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
802,217✔
2282
    if (colDataIsNull_s(pInput[0].columnData, i)) {
1,578,904✔
2283
      colDataSetNULL(pOutput->columnData, i);
201,938!
2284
      continue;
201,938✔
2285
    }
2286
    char *input = colDataGetData(pInput[0].columnData, i);
587,514!
2287

2288
    int64_t timeVal = 0;
587,514✔
2289
    int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
587,514✔
2290
    if (ret != TSDB_CODE_SUCCESS) {
588,369✔
2291
      colDataSetNULL(pOutput->columnData, i);
580,440!
2292
    } else {
2293
      SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false));
7,929✔
2294
    }
2295
  }
2296

2297
  pOutput->numOfRows = pInput->numOfRows;
12,765✔
2298

2299
  return TSDB_CODE_SUCCESS;
12,765✔
2300
}
2301

2302
int32_t toJsonFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
12✔
2303
  int32_t type = GET_PARAM_TYPE(pInput);
12!
2304

2305
  char tmp[TSDB_MAX_JSON_TAG_LEN] = {0};
12✔
2306
  int32_t code = TSDB_CODE_SUCCESS;
12✔
2307
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
24✔
2308
    SArray *pTagVals = taosArrayInit(8, sizeof(STagVal));
12✔
2309
    if (NULL == pTagVals) {
12!
2310
      return terrno;
×
2311
    }
2312
    STag   *pTag = NULL;
12✔
2313

2314
    if (colDataIsNull_s(pInput[0].columnData, i)) {
24!
2315
      code = tTagNew(pTagVals, 1, true, &pTag);
×
2316
      if (TSDB_CODE_SUCCESS != code) {
×
2317
        tTagFree(pTag);
×
2318
        taosArrayDestroy(pTagVals);
×
2319
        SCL_ERR_RET(code);
×
2320
      }
2321
    } else {
2322
      char *input = pInput[0].columnData->pData + pInput[0].columnData->varmeta.offset[i];
12✔
2323
      if (varDataLen(input) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
12!
2324
        taosArrayDestroy(pTagVals);
×
2325
        return TSDB_CODE_FAILED;
×
2326
      }
2327
      (void)memcpy(tmp, varDataVal(input), varDataLen(input));
12✔
2328
      tmp[varDataLen(input)] = 0;
12✔
2329
      if (parseJsontoTagData(tmp, pTagVals, &pTag, NULL)) {
12✔
2330
        code = tTagNew(pTagVals, 1, true, &pTag);
4✔
2331
        if (TSDB_CODE_SUCCESS != code) {
4!
2332
          tTagFree(pTag);
×
2333
          taosArrayDestroy(pTagVals);
×
2334
          SCL_ERR_RET(code);
×
2335
        }
2336
      }
2337
    }
2338

2339
    code = colDataSetVal(pOutput->columnData, i, (const char *)pTag, false);
12✔
2340
    tTagFree(pTag);
12✔
2341
    taosArrayDestroy(pTagVals);
12✔
2342
    if (TSDB_CODE_SUCCESS != code ) {
12!
2343
      SCL_ERR_RET(code);
×
2344
    }
2345
  }
2346

2347
  pOutput->numOfRows = pInput->numOfRows;
12✔
2348
  return TSDB_CODE_SUCCESS;
12✔
2349
}
2350

2351
#define TS_FORMAT_MAX_LEN 4096
2352
int32_t toTimestampFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
1,311✔
2353
  int64_t ts;
2354
  char *  tsStr = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
1,311✔
2355
  char *  format = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
1,312✔
2356
  int32_t len, code = TSDB_CODE_SUCCESS;
1,312✔
2357
  SArray *formats = NULL;
1,312✔
2358

2359
  if (tsStr == NULL || format == NULL) {
1,312!
2360
    SCL_ERR_JRET(terrno);
×
2361
  }
2362
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
1,195,270✔
2363
    if (colDataIsNull_s(pInput[1].columnData, i) || colDataIsNull_s(pInput[0].columnData, i)) {
3,422,135✔
2364
      colDataSetNULL(pOutput->columnData, i);
473,173!
2365
      continue;
473,173✔
2366
    }
2367

2368
    char *tsData = colDataGetData(pInput[0].columnData, i);
720,848!
2369
    char *formatData = colDataGetData(pInput[1].columnData, pInput[1].numOfRows > 1 ? i : 0);
720,848!
2370
    len = TMIN(TS_FORMAT_MAX_LEN - 1, varDataLen(tsData));
720,848✔
2371
    (void)strncpy(tsStr, varDataVal(tsData), len);  // No need to handle the return value.
720,848✔
2372
    tsStr[len] = '\0';
720,848✔
2373
    len = TMIN(TS_FORMAT_MAX_LEN - 1, varDataLen(formatData));
720,848✔
2374
    if (pInput[1].numOfRows > 1 || i == 0) {
720,848✔
2375
      (void)strncpy(format, varDataVal(formatData), len);  // No need to handle the return value.
121,126✔
2376
      format[len] = '\0';
121,126✔
2377
      if (formats) {
121,126✔
2378
        taosArrayDestroy(formats);
119,961✔
2379
        formats = NULL;
119,959✔
2380
      }
2381
    }
2382
    int32_t precision = pOutput->columnData->info.precision;
720,846✔
2383
    char    errMsg[128] = {0};
720,846✔
2384
    code = taosChar2Ts(format, &formats, tsStr, &ts, precision, errMsg, 128);
720,846✔
2385
    if (code) {
720,963✔
2386
      qError("func to_timestamp failed %s", errMsg);
44!
2387
      SCL_ERR_JRET(code);
44!
2388
    }
2389
    SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, (char *)&ts, false));
720,919!
2390
  }
2391

2392
_return:
1,249✔
2393
  if (formats) taosArrayDestroy(formats);
1,293✔
2394
  taosMemoryFree(tsStr);
1,293✔
2395
  taosMemoryFree(format);
1,312✔
2396
  return code;
1,312✔
2397
}
2398

2399
int32_t toCharFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
1,345✔
2400
  char *  format = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
1,345✔
2401
  char *  out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE);
1,351✔
2402
  int32_t len;
2403
  SArray *formats = NULL;
1,350✔
2404
  int32_t code = 0;
1,350✔
2405

2406
  if (format == NULL || out == NULL) {
1,350!
2407
    SCL_ERR_JRET(terrno);
×
2408
  }
2409
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
801,688✔
2410
    if (colDataIsNull_s(pInput[1].columnData, i) || colDataIsNull_s(pInput[0].columnData, i)) {
2,400,462!
2411
      colDataSetNULL(pOutput->columnData, i);
×
2412
      continue;
×
2413
    }
2414

2415
    char *ts = colDataGetData(pInput[0].columnData, i);
800,277!
2416
    char *formatData = colDataGetData(pInput[1].columnData, pInput[1].numOfRows > 1 ? i : 0);
800,277!
2417
    len = TMIN(TS_FORMAT_MAX_LEN - VARSTR_HEADER_SIZE, varDataLen(formatData));
800,277✔
2418
    if (pInput[1].numOfRows > 1 || i == 0) {
800,277!
2419
      (void)strncpy(format, varDataVal(formatData), len);
1,350✔
2420
      format[len] = '\0';
1,350✔
2421
      if (formats) {
1,350!
2422
        taosArrayDestroy(formats);
×
2423
        formats = NULL;
×
2424
      }
2425
    }
2426
    int32_t precision = pInput[0].columnData->info.precision;
800,277✔
2427
    SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)ts, precision, varDataVal(out), TS_FORMAT_MAX_LEN));
800,277!
2428
    varDataSetLen(out, strlen(varDataVal(out)));
802,343✔
2429
    SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, out, false));
802,343!
2430
  }
2431

2432
_return:
1,532✔
2433
  if (formats) taosArrayDestroy(formats);
1,532✔
2434
  taosMemoryFree(format);
1,532✔
2435
  taosMemoryFree(out);
1,351✔
2436
  return code;
1,351✔
2437
}
2438

2439
/** Time functions **/
2440
int64_t offsetFromTz(char *timezone, int64_t factor) {
119,157✔
2441
  char *minStr = &timezone[3];
119,157✔
2442
  int64_t minutes = taosStr2Int64(minStr, NULL, 10);
119,157✔
2443
  (void)memset(minStr, 0, strlen(minStr));
119,101✔
2444
  int64_t hours = taosStr2Int64(timezone, NULL, 10);
119,101✔
2445
  int64_t seconds = hours * 3600 + minutes * 60;
118,978✔
2446

2447
  return seconds * factor;
118,978✔
2448

2449
}
2450

2451
int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
11,715✔
2452
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
11,715!
2453

2454
  int64_t timeUnit, timePrec, timeVal = 0;
11,715✔
2455
  bool    ignoreTz = true;
11,715✔
2456
  char    timezone[20] = {0};
11,715✔
2457

2458
  GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
11,715!
2459

2460
  int32_t timePrecIdx = 2, timeZoneIdx = 3;
11,715✔
2461
  if (inputNum == 5) {
11,715✔
2462
    timePrecIdx += 1;
3,160✔
2463
    timeZoneIdx += 1;
3,160✔
2464
    GET_TYPED_DATA(ignoreTz, bool, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
3,160!
2465
  }
2466

2467
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[timePrecIdx]), pInput[timePrecIdx].columnData->pData);
11,715!
2468
  (void)memcpy(timezone, varDataVal(pInput[timeZoneIdx].columnData->pData), varDataLen(pInput[timeZoneIdx].columnData->pData));
11,715✔
2469

2470
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
491,434✔
2471
    if (colDataIsNull_s(pInput[0].columnData, i)) {
959,182✔
2472
      colDataSetNULL(pOutput->columnData, i);
34!
2473
      continue;
34✔
2474
    }
2475

2476
    char *input = colDataGetData(pInput[0].columnData, i);
479,557!
2477

2478
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
480,393!
2479
      int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
808✔
2480
      if (ret != TSDB_CODE_SUCCESS) {
836!
2481
        colDataSetNULL(pOutput->columnData, i);
×
2482
        continue;
×
2483
      }
2484
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
478,749✔
2485
      GET_TYPED_DATA(timeVal, int64_t, type, input);
7,135!
2486
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
471,614✔
2487
      GET_TYPED_DATA(timeVal, int64_t, type, input);
471,538!
2488
    }
2489

2490
    char buf[20] = {0};
479,585✔
2491
    NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal, sizeof(buf), buf);
479,585✔
2492

2493
    // truncate the timestamp to time_unit precision
2494
    int64_t seconds = timeUnit / TSDB_TICK_PER_SECOND(timePrec);
479,585✔
2495
    if (ignoreTz && (seconds == 604800 || seconds == 86400)) {
479,585✔
2496
      timeVal = timeVal - (timeVal + offsetFromTz(timezone, TSDB_TICK_PER_SECOND(timePrec))) % timeUnit;
119,057✔
2497
    } else {
2498
      timeVal = timeVal / timeUnit * timeUnit;
360,528✔
2499
    }
2500
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false));
479,409!
2501
  }
2502

2503
  pOutput->numOfRows = pInput->numOfRows;
11,843✔
2504

2505
  return TSDB_CODE_SUCCESS;
11,843✔
2506
}
2507

2508
int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
71,623✔
2509
  int64_t timeUnit = -1, timePrec, timeVal[2] = {0};
71,623✔
2510
  if (inputNum == 4) {
71,623✔
2511
    GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
16,398!
2512
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[3]), pInput[3].columnData->pData);
16,398!
2513
  } else {
2514
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
55,225!
2515
  }
2516

2517
  int64_t factor = TSDB_TICK_PER_SECOND(timePrec);
71,623✔
2518
  int32_t numOfRows = 0;
71,623✔
2519
  for (int32_t i = 0; i < inputNum; ++i) {
302,893✔
2520
    if (pInput[i].numOfRows > numOfRows) {
231,270✔
2521
      numOfRows = pInput[i].numOfRows;
76,879✔
2522
    }
2523
  }
2524

2525
  char *input[2];
2526
  for (int32_t i = 0; i < numOfRows; ++i) {
4,203,239✔
2527
    bool hasNull = false;
4,131,538✔
2528
    for (int32_t k = 0; k < 2; ++k) {
11,121,884✔
2529
      if (colDataIsNull_s(pInput[k].columnData, i)) {
15,066,276✔
2530
        hasNull = true;
351,512✔
2531
        break;
351,512✔
2532
      }
2533

2534
      int32_t rowIdx = (pInput[k].numOfRows == 1) ? 0 : i;
7,181,626✔
2535
      input[k] = colDataGetData(pInput[k].columnData, rowIdx);
7,181,626!
2536

2537
      int32_t type = GET_PARAM_TYPE(&pInput[k]);
7,181,626✔
2538
      if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
7,464,029!
2539
        int32_t ret = convertStringToTimestamp(type, input[k], TSDB_TIME_PRECISION_NANO, &timeVal[k]);
303,575✔
2540
        if (ret != TSDB_CODE_SUCCESS) {
303,231✔
2541
          hasNull = true;
20,828✔
2542
          break;
20,828✔
2543
        }
2544
      } else if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_TIMESTAMP) { /* unix timestamp or ts column*/
6,878,051✔
2545
        GET_TYPED_DATA(timeVal[k], int64_t, type, input[k]);
6,873,497!
2546
        if (type == TSDB_DATA_TYPE_TIMESTAMP) {
6,873,497✔
2547
          int64_t timeValSec = timeVal[k] / factor;
5,237,143✔
2548
          if (timeValSec < 1000000000) {
5,237,143✔
2549
            timeVal[k] = timeValSec;
2,110✔
2550
          }
2551
        }
2552

2553
        char buf[20] = {0};
6,873,497✔
2554
        NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal[k], sizeof(buf), buf);
6,873,497✔
2555
        int32_t tsDigits = (int32_t)strlen(buf);
6,873,497✔
2556
        if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
6,873,497✔
2557
          timeVal[k] = timeVal[k] * 1000000000;
667,762✔
2558
        } else if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
6,205,735✔
2559
          timeVal[k] = timeVal[k] * 1000000;
4,185,694✔
2560
        } else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
2,020,041✔
2561
          timeVal[k] = timeVal[k] * 1000;
941,925✔
2562
        } else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
1,078,116✔
2563
          timeVal[k] = timeVal[k] * 1;
908,008✔
2564
        } else {
2565
          hasNull = true;
170,108✔
2566
          break;
170,108✔
2567
        }
2568
      }
2569
    }
2570

2571
    if (hasNull) {
4,131,194✔
2572
      colDataSetNULL(pOutput->columnData, i);
641,064!
2573
      continue;
641,064✔
2574
    }
2575

2576
    int64_t result = timeVal[0] - timeVal[1];
3,490,130✔
2577

2578
    if (timeUnit < 0) {  // if no time unit given use db precision
3,490,130✔
2579
      switch (timePrec) {
2,900,728!
2580
        case TSDB_TIME_PRECISION_MILLI: {
2,153,108✔
2581
          result = result / 1000000;
2,153,108✔
2582
          break;
2,153,108✔
2583
        }
2584
        case TSDB_TIME_PRECISION_MICRO: {
349,300✔
2585
          result = result / 1000;
349,300✔
2586
          break;
349,300✔
2587
        }
2588
        case TSDB_TIME_PRECISION_NANO: {
398,461✔
2589
          result = result / 1;
398,461✔
2590
          break;
398,461✔
2591
        }
2592
      }
2593
    } else {
2594
      int64_t unit = timeUnit * 1000 / factor;
589,402✔
2595
      switch (unit) {
589,402!
2596
        case 0: { /* 1u or 1b */
197✔
2597
          if (timePrec == TSDB_TIME_PRECISION_NANO && timeUnit == 1) {
197✔
2598
            result = result / 1;
61✔
2599
          } else {
2600
            result = result / 1000;
136✔
2601
          }
2602
          break;
197✔
2603
        }
2604
        case 1: { /* 1a */
24,273✔
2605
          result = result / 1000000;
24,273✔
2606
          break;
24,273✔
2607
        }
2608
        case 1000: { /* 1s */
196,052✔
2609
          result = result / 1000000000;
196,052✔
2610
          break;
196,052✔
2611
        }
2612
        case 60000: { /* 1m */
231,786✔
2613
          result = result / 1000000000 / 60;
231,786✔
2614
          break;
231,786✔
2615
        }
2616
        case 3600000: { /* 1h */
19,743✔
2617
          result = result / 1000000000 / 3600;
19,743✔
2618
          break;
19,743✔
2619
        }
2620
        case 86400000: { /* 1d */
119,344✔
2621
          result = result / 1000000000 / 86400;
119,344✔
2622
          break;
119,344✔
2623
        }
2624
        case 604800000: { /* 1w */
220✔
2625
          result = result / 1000000000 / 604800;
220✔
2626
          break;
220✔
2627
        }
UNCOV
2628
        default: {
×
UNCOV
2629
          break;
×
2630
        }
2631
      }
2632
    }
2633

2634
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&result, false));
3,490,130!
2635
  }
2636

2637
  pOutput->numOfRows = numOfRows;
71,701✔
2638

2639
  return TSDB_CODE_SUCCESS;
71,701✔
2640
}
2641

2642
int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
113,843✔
2643
  int64_t timePrec;
2644
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData);
113,843!
2645

2646
  int64_t ts = taosGetTimestamp(timePrec);
113,843✔
2647
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
227,686✔
2648
    colDataSetInt64(pOutput->columnData, i, &ts);
113,843✔
2649
  }
2650
  pOutput->numOfRows = pInput->numOfRows;
113,843✔
2651
  return TSDB_CODE_SUCCESS;
113,843✔
2652
}
2653

2654
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
27,730✔
2655
  int64_t timePrec;
2656
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData);
27,730!
2657

2658
  int64_t ts = taosGetTimestampToday(timePrec);
27,730✔
2659
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
55,460✔
2660
    colDataSetInt64(pOutput->columnData, i, &ts);
27,730✔
2661
  }
2662
  pOutput->numOfRows = pInput->numOfRows;
27,730✔
2663
  return TSDB_CODE_SUCCESS;
27,730✔
2664
}
2665

2666
int32_t timeZoneStrLen() {
40,441✔
2667
  return sizeof(VarDataLenT) + strlen(tsTimezoneStr);
40,441✔
2668
}
2669

2670
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
38,563✔
2671
  char output[TD_TIMEZONE_LEN + VARSTR_HEADER_SIZE] = {0};
38,563✔
2672
  (void)memcpy(varDataVal(output), tsTimezoneStr, TD_TIMEZONE_LEN);
38,563✔
2673
  varDataSetLen(output, strlen(tsTimezoneStr));
38,563✔
2674
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
79,168✔
2675
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, output, false));
40,605!
2676
  }
2677
  pOutput->numOfRows = pInput->numOfRows;
38,563✔
2678
  return TSDB_CODE_SUCCESS;
38,563✔
2679
}
2680

2681
int32_t weekdayFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, bool startFromZero) {
57✔
2682
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
57!
2683

2684
  int64_t timePrec, timeVal = 0;
57✔
2685

2686
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
57!
2687

2688
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
114✔
2689
    if (colDataIsNull_s(pInput[0].columnData, i)) {
114✔
2690
      colDataSetNULL(pOutput->columnData, i);
2!
2691
      continue;
18✔
2692
    }
2693

2694
    char *input = colDataGetData(pInput[0].columnData, i);
55!
2695

2696
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
86!
2697
      int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
47✔
2698
      if (ret != TSDB_CODE_SUCCESS) {
47✔
2699
        colDataSetNULL(pOutput->columnData, i);
16!
2700
        continue;
16✔
2701
      }
2702
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
8!
2703
      GET_TYPED_DATA(timeVal, int64_t, type, input);
8!
2704
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
×
2705
      GET_TYPED_DATA(timeVal, int64_t, type, input);
×
2706
    }
2707
    struct STm tm;
2708
    TAOS_CHECK_RETURN(taosTs2Tm(timeVal, timePrec, &tm));
39!
2709
    int64_t ret = startFromZero ?  (tm.tm.tm_wday + 6) % 7 : tm.tm.tm_wday + 1;
39✔
2710
    colDataSetInt64(pOutput->columnData, i, &ret);
39✔
2711
  }
2712

2713
  pOutput->numOfRows = pInput->numOfRows;
57✔
2714

2715
  return TSDB_CODE_SUCCESS;
57✔
2716
}
2717

2718
int32_t weekdayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
29✔
2719
  return weekdayFunctionImpl(pInput, inputNum, pOutput, true);
29✔
2720
}
2721

2722
int32_t dayofweekFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
28✔
2723
  return weekdayFunctionImpl(pInput, inputNum, pOutput, false);
28✔
2724
}
2725

2726
// calculate day number from 0000-00-00
2727
static int32_t getDayNum(int32_t year, int32_t month, int32_t day) {
172✔
2728
  int32_t delsum;
2729
  int32_t temp;
2730
  int32_t y = year;
172✔
2731

2732
  if (y == 0 && month == 0) {
172!
2733
    return 0;
×
2734
  }
2735

2736
  delsum = 365 * y + 31 * (month - 1) + day;
172✔
2737
  if (month <= 2)
172✔
2738
    y--;
156✔
2739
  else
2740
    delsum -= (month * 4 + 23) / 10;
16✔
2741
  temp = ((y / 100 + 1) * 3) / 4;
172✔
2742
  return (delsum + y / 4 - temp);
172✔
2743
}
2744

2745
static int32_t getDaysInYear(int32_t year) {
49✔
2746
  return (((year % 100) == 0) ? ((year % 400) == 0) : ((year % 4) == 0)) ? 366 : 365;
49!
2747
}
2748

2749
static int32_t getWeekday(int32_t daynr, bool sundayFirstDay) {
86✔
2750
  return (daynr + 5 + (sundayFirstDay ? 1 : 0)) % 7;
86✔
2751
}
2752

2753
static int32_t calculateWeekNum(struct tm date, int32_t weekFlag) {
86✔
2754
  int32_t days;
2755
  int32_t year = date.tm_year + 1900;
86✔
2756
  int32_t month = date.tm_mon + 1;
86✔
2757
  int32_t day = date.tm_mday;
86✔
2758
  int32_t dayNum = getDayNum(year, month, day);
86✔
2759
  int32_t firstDayNum = getDayNum(year, 1, 1);
86✔
2760
  bool mondayFirst = (weekFlag & WEEK_FLAG_MONDAY_FIRST);
86✔
2761
  bool weekStartFromOne = (weekFlag & WEEK_FLAG_FROM_ONE);
86✔
2762
  bool firstWeekday = (weekFlag & WEEK_FLAG_INCLUDE_FIRST_DAY);
86✔
2763

2764
  int32_t weekday = getWeekday(firstDayNum, !mondayFirst);
86✔
2765
  if (month == 1 && day <= 7 - weekday) {
86✔
2766
    if (!weekStartFromOne && ((firstWeekday && weekday != 0) || (!firstWeekday && weekday >= 4))) {
45!
2767
      return 0;
17✔
2768
    }
2769
    weekStartFromOne = true;
28✔
2770
    days = getDaysInYear(--year);
28✔
2771
    firstDayNum -= days;
28✔
2772
    weekday = (weekday + 53 * 7 - days) % 7;
28✔
2773
  }
2774

2775
  if ((firstWeekday && weekday != 0) || (!firstWeekday && weekday >= 4))
69✔
2776
    days = dayNum - (firstDayNum + (7 - weekday));
40✔
2777
  else
2778
    days = dayNum - (firstDayNum - weekday);
29✔
2779

2780
  if (weekStartFromOne && days >= 52 * 7) {
69✔
2781
    weekday = (weekday + getDaysInYear(year)) % 7;
21✔
2782
    if ((!firstWeekday && weekday < 4) || (firstWeekday && weekday == 0)) {
21!
2783
      return 1;
13✔
2784
    }
2785
  }
2786
  return days / 7 + 1;
56✔
2787
}
2788

2789
static int32_t weekMode(int32_t mode) {
86✔
2790
  return mode & WEEK_FLAG_MONDAY_FIRST ? mode : mode ^ WEEK_FLAG_INCLUDE_FIRST_DAY;
86✔
2791
}
2792

2793
int32_t weekFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, int64_t prec, int32_t mode) {
104✔
2794
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
104!
2795

2796
  int64_t timeVal = 0;
104✔
2797

2798
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
208✔
2799
    if (colDataIsNull_s(pInput[0].columnData, i)) {
208✔
2800
      colDataSetNULL(pOutput->columnData, i);
2!
2801
      continue;
18✔
2802
    }
2803

2804
    char *input = colDataGetData(pInput[0].columnData, i);
102!
2805

2806
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
174!
2807
      int32_t ret = convertStringToTimestamp(type, input, prec, &timeVal);
88✔
2808
      if (ret != TSDB_CODE_SUCCESS) {
88✔
2809
        colDataSetNULL(pOutput->columnData, i);
16!
2810
        continue;
16✔
2811
      }
2812
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
14!
2813
      GET_TYPED_DATA(timeVal, int64_t, type, input);
14!
2814
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
×
2815
      GET_TYPED_DATA(timeVal, int64_t, type, input);
×
2816
    }
2817
    struct STm tm;
2818
    SCL_ERR_RET(taosTs2Tm(timeVal, prec, &tm));
86!
2819
    int64_t ret = calculateWeekNum(tm.tm, weekMode(mode));
86✔
2820
    colDataSetInt64(pOutput->columnData, i, &ret);
86✔
2821
  }
2822

2823
  pOutput->numOfRows = pInput->numOfRows;
104✔
2824

2825
  return TSDB_CODE_SUCCESS;
104✔
2826
}
2827

2828
int32_t weekFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
76✔
2829
  int64_t timePrec;
2830
  int32_t mode = 0;
76✔
2831
  if (inputNum == 2) {
76✔
2832
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
11!
2833
    return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, mode);
11✔
2834
  } else {
2835
    GET_TYPED_DATA(mode, int32_t , GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
65!
2836
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
65!
2837
    return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, mode);
65✔
2838
  }
2839
}
2840

2841
int32_t weekofyearFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
28✔
2842
  int64_t timePrec;
2843
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
28!
2844
  return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, 3);
28✔
2845
}
2846

2847
int32_t atanFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3,615✔
2848
  return doScalarFunctionUnique(pInput, inputNum, pOutput, atan);
3,615✔
2849
}
2850

2851
int32_t sinFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
49,929✔
2852
  return doScalarFunctionUnique(pInput, inputNum, pOutput, sin);
49,929✔
2853
}
2854

2855
int32_t cosFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4,497✔
2856
  return doScalarFunctionUnique(pInput, inputNum, pOutput, cos);
4,497✔
2857
}
2858

2859
int32_t tanFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3,070✔
2860
  return doScalarFunctionUnique(pInput, inputNum, pOutput, tan);
3,070✔
2861
}
2862

2863
int32_t asinFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3,207✔
2864
  return doScalarFunctionUnique(pInput, inputNum, pOutput, asin);
3,207✔
2865
}
2866

2867
int32_t acosFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
19,145✔
2868
  return doScalarFunctionUnique(pInput, inputNum, pOutput, acos);
19,145✔
2869
}
2870

2871
int32_t powFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
88,614✔
2872
  return doScalarFunctionUnique2(pInput, inputNum, pOutput, pow);
88,614✔
2873
}
2874

2875
int32_t logFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
182,397✔
2876
  if (inputNum == 1) {
182,397✔
2877
    return doScalarFunctionUnique(pInput, inputNum, pOutput, tlog);
60,064✔
2878
  } else {
2879
    return doScalarFunctionUnique2(pInput, inputNum, pOutput, tlog2);
122,333✔
2880
  }
2881
}
2882

2883
int32_t sqrtFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6,157✔
2884
  return doScalarFunctionUnique(pInput, inputNum, pOutput, sqrt);
6,157✔
2885
}
2886

2887
int32_t ceilFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
78,312✔
2888
  return doScalarFunction(pInput, inputNum, pOutput, ceilf, ceil);
78,312✔
2889
}
2890

2891
int32_t floorFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
81,307✔
2892
  return doScalarFunction(pInput, inputNum, pOutput, floorf, floor);
81,307✔
2893
}
2894

2895
int32_t randFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
19✔
2896
  int32_t seed;
2897
  int32_t numOfRows = inputNum == 1 ? pInput[0].numOfRows : TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
19!
2898
  for (int32_t i = 0; i < numOfRows; ++i) {
38✔
2899
    // for constant seed, only set seed once
2900
    if ((pInput[0].numOfRows == 1 && i == 0) || (pInput[0].numOfRows != 1)) {
19!
2901
      if (!IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) && !colDataIsNull_s(pInput[0].columnData, i)) {
30!
2902
        GET_TYPED_DATA(seed, int32_t, GET_PARAM_TYPE(&pInput[0]), colDataGetData(pInput[0].columnData, i));
11!
2903
        taosSeedRand(seed);
11✔
2904
      }
2905
    }
2906
    double random_value = (double)(taosRand() % RAND_MAX) / RAND_MAX;
19✔
2907
    colDataSetDouble(pOutput->columnData, i, &random_value);
19✔
2908
  }
2909
  pOutput->numOfRows = numOfRows;
19✔
2910
  return TSDB_CODE_SUCCESS;
19✔
2911
}
2912

2913
static double decimalFn(double val1, double val2, _double_fn fn) {
96✔
2914
  if (val1 > DBL_MAX || val1 < -DBL_MAX) {
96!
2915
    return val1;
×
2916
  }
2917

2918
  double scale = pow(10, val2);
96✔
2919

2920
  if (val2 < 0) {
96✔
2921
    return fn(val1 * scale) / scale;
33✔
2922
  } else {
2923
    double scaled_number = val1 * scale;
63✔
2924

2925
    if (scaled_number > DBL_MAX || scaled_number < -DBL_MAX) {
63!
2926
      return val1;
×
2927
    }
2928

2929
    return fn(scaled_number) / scale;
63✔
2930
  }
2931
}
2932

2933
static float decimalfFn(float val1, float val2, _float_fn fn) {
×
2934
  if (val1 > FLT_MAX || val1 < -FLT_MAX) {
×
2935
    return val1;
×
2936
  }
2937

2938
  float scale = powf(10, val2);
×
2939

2940
  if (val2 < 0) {
×
2941
    return fn(val1 * scale) / scale;
×
2942
  } else {
2943
    float scaled_number = val1 * scale;
×
2944

2945
    if (scaled_number > FLT_MAX || scaled_number < -FLT_MAX) {
×
2946
      return val1;
×
2947
    }
2948

2949
    return fn(scaled_number) / scale;
×
2950
  }
2951
}
2952

2953
static double roundFn(double val1, double val2) {
37✔
2954
  return decimalFn(val1, val2, round);
37✔
2955
}
2956

2957
static float roundfFn(float val1, float val2) {
×
2958
  return decimalfFn(val1, val2, roundf);
×
2959
}
2960

2961
static double truncFn(double val1, double val2) {
59✔
2962
  return decimalFn(val1, val2, trunc);
59✔
2963
}
2964

2965
static float truncfFn(float val1, float val2) {
×
2966
  return decimalfFn(val1, val2, truncf);
×
2967
}
2968

2969
static int32_t doScalarFunction2(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _float_fn_2 f1,
101✔
2970
                                 _double_fn_2 d1) {
2971
  SColumnInfoData     *pInputData[2];
2972
  SColumnInfoData     *pOutputData = pOutput->columnData;
101✔
2973
  _getDoubleValue_fn_t getValueFn[2];
2974

2975
  for (int32_t i = 0; i < inputNum; ++i) {
303✔
2976
    pInputData[i] = pInput[i].columnData;
202✔
2977
    SCL_ERR_RET(getVectorDoubleValueFn(GET_PARAM_TYPE(&pInput[i]), &getValueFn[i]));
404!
2978
  }
2979

2980
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
101!
2981

2982
  int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
101✔
2983
  if (pInput[0].numOfRows == pInput[1].numOfRows) {
101!
2984
    for (int32_t i = 0; i < numOfRows; ++i) {
202✔
2985
      if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) {
301!
2986
        colDataSetNULL(pOutputData, i);
5!
2987
        continue;
5✔
2988
      }
2989
      double in2;
2990
      GET_TYPED_DATA(in2, double, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], i));
96!
2991
      switch (GET_PARAM_TYPE(&pInput[0])) {
96!
2992
        case TSDB_DATA_TYPE_DOUBLE: {
91✔
2993
          double  *in = (double *)pInputData[0]->pData;
91✔
2994
          double  *out = (double *)pOutputData->pData;
91✔
2995
          double  result = d1(in[i], in2);
91✔
2996
          if (isinf(result) || isnan(result)) {
91!
2997
            colDataSetNULL(pOutputData, i);
×
2998
          } else {
2999
            out[i] = result;
91✔
3000
          }
3001
          break;
91✔
3002
        }
3003
        case TSDB_DATA_TYPE_FLOAT: {
×
3004
          float   *in = (float *)pInputData[0]->pData;
×
3005
          float   *out = (float *)pOutputData->pData;
×
3006
          float   result = f1(in[i], (float)in2);
×
3007
          if (isinf(result) || isnan(result)) {
×
3008
            colDataSetNULL(pOutputData, i);
×
3009
          } else {
3010
            out[i] = result;
×
3011
          }
3012
          break;
×
3013
        }
3014
        case TSDB_DATA_TYPE_TINYINT: {
×
3015
          int8_t *in = (int8_t *)pInputData[0]->pData;
×
3016
          int8_t *out = (int8_t *)pOutputData->pData;
×
3017
          int8_t result = (int8_t)d1((double)in[i], in2);
×
3018
          out[i] = result;
×
3019
          break;
×
3020
        }
3021
        case TSDB_DATA_TYPE_SMALLINT: {
×
3022
          int16_t *in = (int16_t *)pInputData[0]->pData;
×
3023
          int16_t *out = (int16_t *)pOutputData->pData;
×
3024
          int16_t result = (int16_t)d1((double)in[i], in2);
×
3025
          out[i] = result;
×
3026
          break;
×
3027
        }
3028
        case TSDB_DATA_TYPE_INT: {
×
3029
          int32_t *in = (int32_t *)pInputData[0]->pData;
×
3030
          int32_t *out = (int32_t *)pOutputData->pData;
×
3031
          int32_t result = (int32_t)d1((double)in[i], in2);
×
3032
          out[i] = result;
×
3033
          break;
×
3034
        }
3035
        case TSDB_DATA_TYPE_BIGINT: {
5✔
3036
          int64_t *in = (int64_t *)pInputData[0]->pData;
5✔
3037
          int64_t *out = (int64_t *)pOutputData->pData;
5✔
3038
          int64_t result = (int64_t)d1((double)in[i], in2);
5✔
3039
          out[i] = result;
5✔
3040
          break;
5✔
3041
        }
3042
        case TSDB_DATA_TYPE_UTINYINT: {
×
3043
          uint8_t *in = (uint8_t *)pInputData[0]->pData;
×
3044
          uint8_t *out = (uint8_t *)pOutputData->pData;
×
3045
          uint8_t result = (uint8_t)d1((double)in[i], in2);
×
3046
          out[i] = result;
×
3047
          break;
×
3048
        }
3049
        case TSDB_DATA_TYPE_USMALLINT: {
×
3050
          uint16_t *in = (uint16_t *)pInputData[0]->pData;
×
3051
          uint16_t *out = (uint16_t *)pOutputData->pData;
×
3052
          uint16_t result = (uint16_t)d1((double)in[i], in2);
×
3053
          out[i] = result;
×
3054
          break;
×
3055
        }
3056
        case TSDB_DATA_TYPE_UINT: {
×
3057
          uint32_t *in = (uint32_t *)pInputData[0]->pData;
×
3058
          uint32_t *out = (uint32_t *)pOutputData->pData;
×
3059
          uint32_t result = (uint32_t)d1((double)in[i], in2);
×
3060
          out[i] = result;
×
3061
          break;
×
3062
        }
3063
        case TSDB_DATA_TYPE_UBIGINT: {
×
3064
          uint64_t *in = (uint64_t *)pInputData[0]->pData;
×
3065
          uint64_t *out = (uint64_t *)pOutputData->pData;
×
3066
          uint64_t result = (uint64_t)d1((double)in[i], in2);
×
3067
          out[i] = result;
×
3068
          break;
×
3069
        }
3070
      }
3071
    }
3072
  } else if (pInput[0].numOfRows == 1) {  // left operand is constant
×
3073
    if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
×
3074
      colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows);
×
3075
    } else {
3076
      for (int32_t i = 0; i < numOfRows; ++i) {
×
3077
        if (colDataIsNull_s(pInputData[1], i)) {
×
3078
          colDataSetNULL(pOutputData, i);
×
3079
          continue;
×
3080
        }
3081
        double in2;
3082
        GET_TYPED_DATA(in2, double, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], i));
×
3083
        switch (GET_PARAM_TYPE(&pInput[0])) {
×
3084
          case TSDB_DATA_TYPE_DOUBLE: {
×
3085
            double   *in = (double *)pInputData[0]->pData;
×
3086
            double   *out = (double *)pOutputData->pData;
×
3087
            double   result = d1(in[0], in2);
×
3088
            if (isinf(result) || isnan(result)) {
×
3089
              colDataSetNULL(pOutputData, i);
×
3090
            } else {
3091
              out[i] = result;
×
3092
            }
3093
            break;
×
3094
          }
3095
          case TSDB_DATA_TYPE_FLOAT: {
×
3096
            float   *in = (float *)pInputData[0]->pData;
×
3097
            float   *out = (float *)pOutputData->pData;
×
3098
            float   result = f1(in[0], (float)in2);
×
3099
            if (isinf(result) || isnan(result)) {
×
3100
              colDataSetNULL(pOutputData, i);
×
3101
            } else {
3102
              out[i] = result;
×
3103
            }
3104
            break;
×
3105
          }
3106
          case TSDB_DATA_TYPE_TINYINT: {
×
3107
            int8_t *in = (int8_t *)pInputData[0]->pData;
×
3108
            int8_t *out = (int8_t *)pOutputData->pData;
×
3109
            int8_t result = (int8_t)d1((double)in[0], in2);
×
3110
            out[i] = result;
×
3111
            break;
×
3112
          }
3113
          case TSDB_DATA_TYPE_SMALLINT: {
×
3114
            int16_t *in = (int16_t *)pInputData[0]->pData;
×
3115
            int16_t *out = (int16_t *)pOutputData->pData;
×
3116
            int16_t result = (int16_t)d1((double)in[0], in2);
×
3117
            out[i] = result;
×
3118
            break;
×
3119
          }
3120
          case TSDB_DATA_TYPE_INT: {
×
3121
            int32_t *in = (int32_t *)pInputData[0]->pData;
×
3122
            int32_t *out = (int32_t *)pOutputData->pData;
×
3123
            int32_t result = (int32_t)d1((double)in[0], in2);
×
3124
            out[i] = result;
×
3125
            break;
×
3126
          }
3127
          case TSDB_DATA_TYPE_BIGINT: {
×
3128
            int64_t *in = (int64_t *)pInputData[0]->pData;
×
3129
            int64_t *out = (int64_t *)pOutputData->pData;
×
3130
            int64_t result = (int64_t)d1((double)in[0], in2);
×
3131
            out[i] = result;
×
3132
            break;
×
3133
          }
3134
          case TSDB_DATA_TYPE_UTINYINT: {
×
3135
            uint8_t *in = (uint8_t *)pInputData[0]->pData;
×
3136
            uint8_t *out = (uint8_t *)pOutputData->pData;
×
3137
            uint8_t result = (uint8_t)d1((double)in[0], in2);
×
3138
            out[i] = result;
×
3139
            break;
×
3140
          }
3141
          case TSDB_DATA_TYPE_USMALLINT: {
×
3142
            uint16_t *in = (uint16_t *)pInputData[0]->pData;
×
3143
            uint16_t *out = (uint16_t *)pOutputData->pData;
×
3144
            uint16_t result = (uint16_t)d1((double)in[0], in2);
×
3145
            out[i] = result;
×
3146
            break;
×
3147
          }
3148
          case TSDB_DATA_TYPE_UINT: {
×
3149
            uint32_t *in = (uint32_t *)pInputData[0]->pData;
×
3150
            uint32_t *out = (uint32_t *)pOutputData->pData;
×
3151
            uint32_t result = (uint32_t)d1((double)in[0], in2);
×
3152
            out[i] = result;
×
3153
            break;
×
3154
          }
3155
          case TSDB_DATA_TYPE_UBIGINT: {
×
3156
            uint64_t *in = (uint64_t *)pInputData[0]->pData;
×
3157
            uint64_t *out = (uint64_t *)pOutputData->pData;
×
3158
            uint64_t result = (uint64_t)d1((double)in[0], in2);
×
3159
            out[i] = result;
×
3160
            break;
×
3161
          }
3162
        }
3163
      }
3164
    }
3165
  } else if (pInput[1].numOfRows == 1) {
×
3166
    if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
×
3167
      colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows);
×
3168
    } else {
3169
      for (int32_t i = 0; i < numOfRows; ++i) {
×
3170
        if (colDataIsNull_s(pInputData[0], i)) {
×
3171
          colDataSetNULL(pOutputData, i);
×
3172
          continue;
×
3173
        }
3174
        double in2;
3175
        GET_TYPED_DATA(in2, double, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], 0));
×
3176
        switch (GET_PARAM_TYPE(&pInput[0])) {
×
3177
          case TSDB_DATA_TYPE_DOUBLE: {
×
3178
            double   *in = (double *)pInputData[0]->pData;
×
3179
            double   *out = (double *)pOutputData->pData;
×
3180
            double   result = d1(in[i], in2);
×
3181
            if (isinf(result) || isnan(result)) {
×
3182
              colDataSetNULL(pOutputData, i);
×
3183
            } else {
3184
              out[i] = result;
×
3185
            }
3186
            break;
×
3187
          }
3188
          case TSDB_DATA_TYPE_FLOAT: {
×
3189
            float   *in = (float *)pInputData[0]->pData;
×
3190
            float   *out = (float *)pOutputData->pData;
×
3191
            float   result = f1(in[i], in2);
×
3192
            if (isinf(result) || isnan(result)) {
×
3193
              colDataSetNULL(pOutputData, i);
×
3194
            } else {
3195
              out[i] = result;
×
3196
            }
3197
            break;
×
3198
          }
3199
          case TSDB_DATA_TYPE_TINYINT: {
×
3200
            int8_t *in = (int8_t *)pInputData[0]->pData;
×
3201
            int8_t *out = (int8_t *)pOutputData->pData;
×
3202
            int8_t result = (int8_t)d1((double)in[i], in2);
×
3203
            out[i] = result;
×
3204
            break;
×
3205
          }
3206
          case TSDB_DATA_TYPE_SMALLINT: {
×
3207
            int16_t *in = (int16_t *)pInputData[0]->pData;
×
3208
            int16_t *out = (int16_t *)pOutputData->pData;
×
3209
            int16_t result = (int16_t)d1((double)in[i], in2);
×
3210
            out[i] = result;
×
3211
            break;
×
3212
          }
3213
          case TSDB_DATA_TYPE_INT: {
×
3214
            int32_t *in = (int32_t *)pInputData[0]->pData;
×
3215
            int32_t *out = (int32_t *)pOutputData->pData;
×
3216
            int32_t result = (int32_t)d1((double)in[i], in2);
×
3217
            out[i] = result;
×
3218
            break;
×
3219
          }
3220
          case TSDB_DATA_TYPE_BIGINT: {
×
3221
            int64_t *in = (int64_t *)pInputData[0]->pData;
×
3222
            int64_t *out = (int64_t *)pOutputData->pData;
×
3223
            int64_t result = (int64_t)d1((double)in[i], in2);
×
3224
            out[i] = result;
×
3225
            break;
×
3226
          }
3227
          case TSDB_DATA_TYPE_UTINYINT: {
×
3228
            uint8_t *in = (uint8_t *)pInputData[0]->pData;
×
3229
            uint8_t *out = (uint8_t *)pOutputData->pData;
×
3230
            uint8_t result = (uint8_t)d1((double)in[i], in2);
×
3231
            out[i] = result;
×
3232
            break;
×
3233
          }
3234
          case TSDB_DATA_TYPE_USMALLINT: {
×
3235
            uint16_t *in = (uint16_t *)pInputData[0]->pData;
×
3236
            uint16_t *out = (uint16_t *)pOutputData->pData;
×
3237
            uint16_t result = (uint16_t)d1((double)in[i], in2);
×
3238
            out[i] = result;
×
3239
            break;
×
3240
          }
3241
          case TSDB_DATA_TYPE_UINT: {
×
3242
            uint32_t *in = (uint32_t *)pInputData[0]->pData;
×
3243
            uint32_t *out = (uint32_t *)pOutputData->pData;
×
3244
            uint32_t result = (uint32_t)d1((double)in[i], in2);
×
3245
            out[i] = result;
×
3246
            break;
×
3247
          }
3248
          case TSDB_DATA_TYPE_UBIGINT: {
×
3249
            uint64_t *in = (uint64_t *)pInputData[0]->pData;
×
3250
            uint64_t *out = (uint64_t *)pOutputData->pData;
×
3251
            uint64_t result = (uint64_t)d1((double)in[i], in2);
×
3252
            out[i] = result;
×
3253
            break;
×
3254
          }
3255
        }
3256
      }
3257
    }
3258
  }
3259

3260
  pOutput->numOfRows = numOfRows;
101✔
3261
  return TSDB_CODE_SUCCESS;
101✔
3262
}
3263

3264
int32_t roundFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4,981✔
3265
  if (inputNum == 1) {
4,981✔
3266
    return doScalarFunction(pInput, inputNum, pOutput, roundf, round);
4,941✔
3267
  } else {
3268
    return doScalarFunction2(pInput, inputNum, pOutput, roundfFn, roundFn);
40✔
3269
  }
3270
}
3271

3272
int32_t truncFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
61✔
3273
  return doScalarFunction2(pInput, inputNum, pOutput, truncfFn, truncFn);
61✔
3274
}
3275

3276
int32_t piFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
50✔
3277
  double_t value = M_PI;
50✔
3278
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
100✔
3279
    colDataSetDouble(pOutput->columnData, i, &value);
50✔
3280
  }
3281
  pOutput->numOfRows = pInput->numOfRows;
50✔
3282
  return TSDB_CODE_SUCCESS;
50✔
3283
}
3284

3285
int32_t expFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
43✔
3286
  return doScalarFunctionUnique(pInput, inputNum, pOutput, exp);
43✔
3287
}
3288

3289
int32_t lnFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
42✔
3290
  return doScalarFunctionUnique(pInput, inputNum, pOutput, tlog);
42✔
3291
}
3292

3293
int32_t modFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
35✔
3294
  return doScalarFunctionUnique2(pInput, inputNum, pOutput, fmod);
35✔
3295
}
3296

3297
int32_t degreesFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
46✔
3298
  return doScalarFunctionUnique(pInput, inputNum, pOutput, degrees);
46✔
3299
}
3300

3301
int32_t radiansFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
46✔
3302
  return doScalarFunctionUnique(pInput, inputNum, pOutput, radians);
46✔
3303
}
3304

3305
int32_t lowerFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
34,533✔
3306
#ifdef WINDOWS
3307
  return doCaseConvFunction(pInput, inputNum, pOutput, towlower);
3308
#else
3309
  return doCaseConvFunction(pInput, inputNum, pOutput, tolower);
34,533✔
3310
#endif
3311
}
3312

3313
int32_t upperFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
43,421✔
3314
#ifdef WINDOWS
3315
  return doCaseConvFunction(pInput, inputNum, pOutput, towupper);
3316
#else
3317
  return doCaseConvFunction(pInput, inputNum, pOutput, toupper);
43,421✔
3318
#endif
3319
}
3320

3321
int32_t ltrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
59,026✔
3322
  return doTrimFunction(pInput, inputNum, pOutput, tltrimspace, tltrim);
59,026✔
3323
}
3324

3325
int32_t rtrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
52,666✔
3326
  return doTrimFunction(pInput, inputNum, pOutput, trtrimspace, tltrim);
52,666✔
3327
}
3328

3329
int32_t lengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
16,240✔
3330
  return doLengthFunction(pInput, inputNum, pOutput, tlength);
16,240✔
3331
}
3332

3333
int32_t charLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
19,849✔
3334
  return doLengthFunction(pInput, inputNum, pOutput, tcharlength);
19,849✔
3335
}
3336

3337
bool getTimePseudoFuncEnv(SFunctionNode *UNUSED_PARAM(pFunc), SFuncExecEnv *pEnv) {
112,125✔
3338
  pEnv->calcMemSize = sizeof(int64_t);
112,125✔
3339
  return true;
112,125✔
3340
}
3341

3342
#ifdef BUILD_NO_CALL
3343
int32_t qStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3344
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 0));
3345
  return TSDB_CODE_SUCCESS;
3346
}
3347

3348
int32_t qEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3349
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 1));
3350
  return TSDB_CODE_SUCCESS;
3351
}
3352
#endif
3353

3354
int32_t winDurFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
5,724,123✔
3355
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 2));
5,724,123!
3356
  return TSDB_CODE_SUCCESS;
5,724,123✔
3357
}
3358

3359
int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
122,251,107✔
3360
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 3));
122,251,107!
3361
  return TSDB_CODE_SUCCESS;
122,251,107✔
3362
}
3363

3364
int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
52,697,990✔
3365
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 4));
52,697,990!
3366
  return TSDB_CODE_SUCCESS;
52,697,990✔
3367
}
3368

3369
int32_t qPseudoTagFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1,122,742✔
3370
  char   *p = colDataGetData(pInput->columnData, 0);
1,122,742!
3371
  int32_t code = colDataSetNItems(pOutput->columnData, pOutput->numOfRows, p, pInput->numOfRows, true);
1,122,742✔
3372
  if (code) {
1,123,506!
3373
    return code;
×
3374
  }
3375
  
3376
  pOutput->numOfRows += pInput->numOfRows;
1,123,506✔
3377
  return TSDB_CODE_SUCCESS;
1,123,506✔
3378
}
3379

3380
/** Aggregation functions **/
3381
int32_t countScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
8✔
3382
  SColumnInfoData *pInputData = pInput->columnData;
8✔
3383
  SColumnInfoData *pOutputData = pOutput->columnData;
8✔
3384

3385
  int64_t *out = (int64_t *)pOutputData->pData;
8✔
3386
  *out = 0;
8✔
3387
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
16✔
3388
    if (colDataIsNull_s(pInputData, i)) {
16!
3389
      continue;
8✔
3390
    }
3391
    (*out)++;
×
3392
  }
3393

3394
  pOutput->numOfRows = 1;
8✔
3395
  return TSDB_CODE_SUCCESS;
8✔
3396
}
3397

3398
int32_t sumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
5✔
3399
  SColumnInfoData *pInputData = pInput->columnData;
5✔
3400
  SColumnInfoData *pOutputData = pOutput->columnData;
5✔
3401

3402
  int32_t type = GET_PARAM_TYPE(pInput);
5!
3403
  bool    hasNull = false;
5✔
3404
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
9✔
3405
    if (colDataIsNull_s(pInputData, i)) {
10✔
3406
      hasNull = true;
1✔
3407
      break;
1✔
3408
    }
3409

3410
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
4!
3411
      int64_t *out = (int64_t *)pOutputData->pData;
×
3412
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
×
3413
        int8_t *in = (int8_t *)pInputData->pData;
×
3414
        *out += in[i];
×
3415
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
×
3416
        int16_t *in = (int16_t *)pInputData->pData;
×
3417
        *out += in[i];
×
3418
      } else if (type == TSDB_DATA_TYPE_INT) {
×
3419
        int32_t *in = (int32_t *)pInputData->pData;
×
3420
        *out += in[i];
×
3421
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
×
3422
        int64_t *in = (int64_t *)pInputData->pData;
×
3423
        *out += in[i];
×
3424
      }
3425
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
4!
3426
      uint64_t *out = (uint64_t *)pOutputData->pData;
×
3427
      if (type == TSDB_DATA_TYPE_UTINYINT) {
×
3428
        uint8_t *in = (uint8_t *)pInputData->pData;
×
3429
        *out += in[i];
×
3430
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
×
3431
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3432
        *out += in[i];
×
3433
      } else if (type == TSDB_DATA_TYPE_UINT) {
×
3434
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3435
        *out += in[i];
×
3436
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
×
3437
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3438
        *out += in[i];
×
3439
      }
3440
    } else if (IS_FLOAT_TYPE(type)) {
4!
3441
      double *out = (double *)pOutputData->pData;
4✔
3442
      if (type == TSDB_DATA_TYPE_FLOAT) {
4!
3443
        float *in = (float *)pInputData->pData;
×
3444
        *out += in[i];
×
3445
      } else if (type == TSDB_DATA_TYPE_DOUBLE) {
4!
3446
        double *in = (double *)pInputData->pData;
4✔
3447
        *out += in[i];
4✔
3448
      }
3449
    }
3450
  }
3451

3452
  if (hasNull) {
5✔
3453
    colDataSetNULL(pOutputData, 0);
3454
  }
3455

3456
  pOutput->numOfRows = 1;
5✔
3457
  return TSDB_CODE_SUCCESS;
5✔
3458
}
3459

3460
static int32_t doMinMaxScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, bool isMinFunc) {
8✔
3461
  SColumnInfoData *pInputData = pInput->columnData;
8✔
3462
  SColumnInfoData *pOutputData = pOutput->columnData;
8✔
3463

3464
  int32_t type = GET_PARAM_TYPE(pInput);
8!
3465

3466
  bool hasNull = false;
8✔
3467
  if (isMinFunc) {
8✔
3468
    SET_TYPED_DATA_MAX(pOutputData->pData, type);
4!
3469
  } else {
3470
    SET_TYPED_DATA_MIN(pOutputData->pData, type);
4!
3471
  }
3472

3473
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
14✔
3474
    if (colDataIsNull_s(pInputData, i)) {
16✔
3475
      hasNull = true;
2✔
3476
      break;
2✔
3477
    }
3478

3479
    switch (type) {
6!
3480
      case TSDB_DATA_TYPE_BOOL:
×
3481
      case TSDB_DATA_TYPE_TINYINT: {
3482
        int8_t *in = (int8_t *)pInputData->pData;
×
3483
        int8_t *out = (int8_t *)pOutputData->pData;
×
3484
        if ((in[i] > *out) ^ isMinFunc) {
×
3485
          *out = in[i];
×
3486
        }
3487
        break;
×
3488
      }
3489
      case TSDB_DATA_TYPE_SMALLINT: {
×
3490
        int16_t *in = (int16_t *)pInputData->pData;
×
3491
        int16_t *out = (int16_t *)pOutputData->pData;
×
3492
        if ((in[i] > *out) ^ isMinFunc) {
×
3493
          *out = in[i];
×
3494
        }
3495
        break;
×
3496
      }
3497
      case TSDB_DATA_TYPE_INT: {
×
3498
        int32_t *in = (int32_t *)pInputData->pData;
×
3499
        int32_t *out = (int32_t *)pOutputData->pData;
×
3500
        if ((in[i] > *out) ^ isMinFunc) {
×
3501
          *out = in[i];
×
3502
        }
3503
        break;
×
3504
      }
3505
      case TSDB_DATA_TYPE_BIGINT: {
×
3506
        int64_t *in = (int64_t *)pInputData->pData;
×
3507
        int64_t *out = (int64_t *)pOutputData->pData;
×
3508
        if ((in[i] > *out) ^ isMinFunc) {
×
3509
          *out = in[i];
×
3510
        }
3511
        break;
×
3512
      }
3513
      case TSDB_DATA_TYPE_UTINYINT: {
×
3514
        uint8_t *in = (uint8_t *)pInputData->pData;
×
3515
        uint8_t *out = (uint8_t *)pOutputData->pData;
×
3516
        if ((in[i] > *out) ^ isMinFunc) {
×
3517
          *out = in[i];
×
3518
        }
3519
        break;
×
3520
      }
3521
      case TSDB_DATA_TYPE_USMALLINT: {
×
3522
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3523
        uint16_t *out = (uint16_t *)pOutputData->pData;
×
3524
        if ((in[i] > *out) ^ isMinFunc) {
×
3525
          *out = in[i];
×
3526
        }
3527
        break;
×
3528
      }
3529
      case TSDB_DATA_TYPE_UINT: {
×
3530
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3531
        uint32_t *out = (uint32_t *)pOutputData->pData;
×
3532
        if ((in[i] > *out) ^ isMinFunc) {
×
3533
          *out = in[i];
×
3534
        }
3535
        break;
×
3536
      }
3537
      case TSDB_DATA_TYPE_UBIGINT: {
×
3538
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3539
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3540
        if ((in[i] > *out) ^ isMinFunc) {
×
3541
          *out = in[i];
×
3542
        }
3543
        break;
×
3544
      }
3545
      case TSDB_DATA_TYPE_FLOAT: {
×
3546
        float *in = (float *)pInputData->pData;
×
3547
        float *out = (float *)pOutputData->pData;
×
3548
        if ((in[i] > *out) ^ isMinFunc) {
×
3549
          *out = in[i];
×
3550
        }
3551
        break;
×
3552
      }
3553
      case TSDB_DATA_TYPE_DOUBLE: {
6✔
3554
        double *in = (double *)pInputData->pData;
6✔
3555
        double *out = (double *)pOutputData->pData;
6✔
3556
        if ((in[i] > *out) ^ isMinFunc) {
6!
3557
          *out = in[i];
6✔
3558
        }
3559
        break;
6✔
3560
      }
3561
    }
3562
  }
3563

3564
  if (hasNull) {
8✔
3565
    colDataSetNULL(pOutputData, 0);
3566
  }
3567

3568
  pOutput->numOfRows = 1;
8✔
3569
  return TSDB_CODE_SUCCESS;
8✔
3570
}
3571

3572
int32_t minScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
3573
  return doMinMaxScalarFunction(pInput, inputNum, pOutput, true);
4✔
3574
}
3575

3576
int32_t maxScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
3577
  return doMinMaxScalarFunction(pInput, inputNum, pOutput, false);
4✔
3578
}
3579

3580
int32_t avgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
7✔
3581
  SColumnInfoData *pInputData = pInput->columnData;
7✔
3582
  SColumnInfoData *pOutputData = pOutput->columnData;
7✔
3583

3584
  int32_t type = GET_PARAM_TYPE(pInput);
7!
3585
  int64_t count = 0;
7✔
3586
  bool    hasNull = false;
7✔
3587

3588
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
13✔
3589
    if (colDataIsNull_s(pInputData, i)) {
14✔
3590
      hasNull = true;
1✔
3591
      break;
1✔
3592
    }
3593

3594
    switch (type) {
6!
3595
      case TSDB_DATA_TYPE_TINYINT: {
×
3596
        int8_t  *in = (int8_t *)pInputData->pData;
×
3597
        int64_t *out = (int64_t *)pOutputData->pData;
×
3598
        *out += in[i];
×
3599
        count++;
×
3600
        break;
×
3601
      }
3602
      case TSDB_DATA_TYPE_SMALLINT: {
×
3603
        int16_t *in = (int16_t *)pInputData->pData;
×
3604
        int64_t *out = (int64_t *)pOutputData->pData;
×
3605
        *out += in[i];
×
3606
        count++;
×
3607
        break;
×
3608
      }
3609
      case TSDB_DATA_TYPE_INT: {
×
3610
        int32_t *in = (int32_t *)pInputData->pData;
×
3611
        int64_t *out = (int64_t *)pOutputData->pData;
×
3612
        *out += in[i];
×
3613
        count++;
×
3614
        break;
×
3615
      }
3616
      case TSDB_DATA_TYPE_BIGINT: {
3✔
3617
        int64_t *in = (int64_t *)pInputData->pData;
3✔
3618
        int64_t *out = (int64_t *)pOutputData->pData;
3✔
3619
        *out += in[i];
3✔
3620
        count++;
3✔
3621
        break;
3✔
3622
      }
3623
      case TSDB_DATA_TYPE_UTINYINT: {
×
3624
        uint8_t  *in = (uint8_t *)pInputData->pData;
×
3625
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3626
        *out += in[i];
×
3627
        count++;
×
3628
        break;
×
3629
      }
3630
      case TSDB_DATA_TYPE_USMALLINT: {
×
3631
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3632
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3633
        *out += in[i];
×
3634
        count++;
×
3635
        break;
×
3636
      }
3637
      case TSDB_DATA_TYPE_UINT: {
×
3638
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3639
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3640
        *out += in[i];
×
3641
        count++;
×
3642
        break;
×
3643
      }
3644
      case TSDB_DATA_TYPE_UBIGINT: {
×
3645
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3646
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3647
        *out += in[i];
×
3648
        count++;
×
3649
        break;
×
3650
      }
3651
      case TSDB_DATA_TYPE_FLOAT: {
×
3652
        float *in = (float *)pInputData->pData;
×
3653
        float *out = (float *)pOutputData->pData;
×
3654
        *out += in[i];
×
3655
        count++;
×
3656
        break;
×
3657
      }
3658
      case TSDB_DATA_TYPE_DOUBLE: {
3✔
3659
        double *in = (double *)pInputData->pData;
3✔
3660
        double *out = (double *)pOutputData->pData;
3✔
3661
        *out += in[i];
3✔
3662
        count++;
3✔
3663
        break;
3✔
3664
      }
3665
    }
3666
  }
3667

3668
  if (hasNull || (count == 0)) {
7!
3669
    colDataSetNULL(pOutputData, 0);
1✔
3670
  } else {
3671
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
6!
3672
      int64_t *out = (int64_t *)pOutputData->pData;
3✔
3673
      *(double *)out = *out / (double)count;
3✔
3674
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
3!
3675
      uint64_t *out = (uint64_t *)pOutputData->pData;
×
3676
      *(double *)out = *out / (double)count;
×
3677
    } else if (IS_FLOAT_TYPE(type)) {
3!
3678
      double *out = (double *)pOutputData->pData;
3✔
3679
      *(double *)out = *out / (double)count;
3✔
3680
    }
3681
  }
3682

3683
  pOutput->numOfRows = 1;
7✔
3684
  return TSDB_CODE_SUCCESS;
7✔
3685
}
3686

3687
int32_t stdScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
3688
  SColumnInfoData *pInputData = pInput->columnData;
4✔
3689
  SColumnInfoData *pOutputData = pOutput->columnData;
4✔
3690

3691
  int32_t type = GET_PARAM_TYPE(pInput);
4!
3692
  // int64_t count = 0, sum = 0, qSum = 0;
3693
  bool hasNull = false;
4✔
3694

3695
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
7✔
3696
    if (colDataIsNull_s(pInputData, i)) {
8✔
3697
      hasNull = true;
1✔
3698
      break;
1✔
3699
    }
3700
#if 0
3701
    switch(type) {
3702
      case TSDB_DATA_TYPE_TINYINT: {
3703
        int8_t *in  = (int8_t *)pInputData->pData;
3704
        sum += in[i];
3705
        qSum += in[i] * in[i];
3706
        count++;
3707
        break;
3708
      }
3709
      case TSDB_DATA_TYPE_SMALLINT: {
3710
        int16_t *in  = (int16_t *)pInputData->pData;
3711
        sum += in[i];
3712
        qSum += in[i] * in[i];
3713
        count++;
3714
        break;
3715
      }
3716
      case TSDB_DATA_TYPE_INT: {
3717
        int32_t *in  = (int32_t *)pInputData->pData;
3718
        sum += in[i];
3719
        qSum += in[i] * in[i];
3720
        count++;
3721
        break;
3722
      }
3723
      case TSDB_DATA_TYPE_BIGINT: {
3724
        int64_t *in  = (int64_t *)pInputData->pData;
3725
        sum += in[i];
3726
        qSum += in[i] * in[i];
3727
        count++;
3728
        break;
3729
      }
3730
      case TSDB_DATA_TYPE_UTINYINT: {
3731
        uint8_t *in  = (uint8_t *)pInputData->pData;
3732
        sum += in[i];
3733
        qSum += in[i] * in[i];
3734
        count++;
3735
        break;
3736
      }
3737
      case TSDB_DATA_TYPE_USMALLINT: {
3738
        uint16_t *in  = (uint16_t *)pInputData->pData;
3739
        sum += in[i];
3740
        qSum += in[i] * in[i];
3741
        count++;
3742
        break;
3743
      }
3744
      case TSDB_DATA_TYPE_UINT: {
3745
        uint32_t *in  = (uint32_t *)pInputData->pData;
3746
        sum += in[i];
3747
        qSum += in[i] * in[i];
3748
        count++;
3749
        break;
3750
      }
3751
      case TSDB_DATA_TYPE_UBIGINT: {
3752
        uint64_t *in  = (uint64_t *)pInputData->pData;
3753
        sum += in[i];
3754
        qSum += in[i] * in[i];
3755
        count++;
3756
        break;
3757
      }
3758
      case TSDB_DATA_TYPE_FLOAT: {
3759
        float *in  = (float *)pInputData->pData;
3760
        sum += in[i];
3761
        qSum += in[i] * in[i];
3762
        count++;
3763
        break;
3764
      }
3765
      case TSDB_DATA_TYPE_DOUBLE: {
3766
        double *in  = (double *)pInputData->pData;
3767
        sum += in[i];
3768
        qSum += in[i] * in[i];
3769
        count++;
3770
        break;
3771
      }
3772
    }
3773
#endif
3774
  }
3775

3776
  double *out = (double *)pOutputData->pData;
4✔
3777
  if (hasNull) {
4✔
3778
    colDataSetNULL(pOutputData, 0);
3779
  } else {
3780
    *out = 0;
3✔
3781
#if 0
3782
    double avg = 0;
3783
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
3784
      avg = (int64_t)sum / (double)count;
3785
      *out =  sqrt(fabs((int64_t)qSum / ((double)count) - avg * avg));
3786
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
3787
      avg = (uint64_t)sum / (double)count;
3788
      *out =  sqrt(fabs((uint64_t)qSum / ((double)count) - avg * avg));
3789
    } else if (IS_FLOAT_TYPE(type)) {
3790
      avg = (double)sum / (double)count;
3791
      *out =  sqrt(fabs((double)qSum / ((double)count) - avg * avg));
3792
    }
3793
#endif
3794
  }
3795

3796
  pOutput->numOfRows = 1;
4✔
3797
  return TSDB_CODE_SUCCESS;
4✔
3798
}
3799

3800
#define LEASTSQR_CAL(p, x, y, index, step) \
3801
  do {                                     \
3802
    (p)[0][0] += (double)(x) * (x);        \
3803
    (p)[0][1] += (double)(x);              \
3804
    (p)[0][2] += (double)(x) * (y)[index]; \
3805
    (p)[1][2] += (y)[index];               \
3806
    (x) += step;                           \
3807
  } while (0)
3808

3809
int32_t leastSQRScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2✔
3810
  SColumnInfoData *pInputData = pInput->columnData;
2✔
3811
  SColumnInfoData *pOutputData = pOutput->columnData;
2✔
3812

3813
  double startVal, stepVal;
3814
  double matrix[2][3] = {0};
2✔
3815
  GET_TYPED_DATA(startVal, double, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData);
2!
3816
  GET_TYPED_DATA(stepVal, double, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData);
2!
3817

3818
  int32_t type = GET_PARAM_TYPE(pInput);
2!
3819
  int64_t count = 0;
2✔
3820

3821
  switch (type) {
2!
3822
    case TSDB_DATA_TYPE_TINYINT: {
×
3823
      int8_t *in = (int8_t *)pInputData->pData;
×
3824
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3825
        if (colDataIsNull_s(pInputData, i)) {
×
3826
          continue;
×
3827
        }
3828

3829
        count++;
×
3830
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3831
      }
3832
      break;
×
3833
    }
3834
    case TSDB_DATA_TYPE_SMALLINT: {
×
3835
      int16_t *in = (int16_t *)pInputData->pData;
×
3836
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3837
        if (colDataIsNull_s(pInputData, i)) {
×
3838
          continue;
×
3839
        }
3840

3841
        count++;
×
3842
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3843
      }
3844
      break;
×
3845
    }
3846
    case TSDB_DATA_TYPE_INT: {
×
3847
      int32_t *in = (int32_t *)pInputData->pData;
×
3848
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3849
        if (colDataIsNull_s(pInputData, i)) {
×
3850
          continue;
×
3851
        }
3852

3853
        count++;
×
3854
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3855
      }
3856
      break;
×
3857
    }
3858
    case TSDB_DATA_TYPE_BIGINT: {
1✔
3859
      int64_t *in = (int64_t *)pInputData->pData;
1✔
3860
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
2✔
3861
        if (colDataIsNull_s(pInputData, i)) {
2!
3862
          continue;
×
3863
        }
3864

3865
        count++;
1✔
3866
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
1✔
3867
      }
3868
      break;
1✔
3869
    }
3870
    case TSDB_DATA_TYPE_UTINYINT: {
×
3871
      uint8_t *in = (uint8_t *)pInputData->pData;
×
3872
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3873
        if (colDataIsNull_s(pInputData, i)) {
×
3874
          continue;
×
3875
        }
3876

3877
        count++;
×
3878
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3879
      }
3880
      break;
×
3881
    }
3882
    case TSDB_DATA_TYPE_USMALLINT: {
×
3883
      uint16_t *in = (uint16_t *)pInputData->pData;
×
3884
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3885
        if (colDataIsNull_s(pInputData, i)) {
×
3886
          continue;
×
3887
        }
3888

3889
        count++;
×
3890
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3891
      }
3892
      break;
×
3893
    }
3894
    case TSDB_DATA_TYPE_UINT: {
×
3895
      uint32_t *in = (uint32_t *)pInputData->pData;
×
3896
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3897
        if (colDataIsNull_s(pInputData, i)) {
×
3898
          continue;
×
3899
        }
3900

3901
        count++;
×
3902
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3903
      }
3904
      break;
×
3905
    }
3906
    case TSDB_DATA_TYPE_UBIGINT: {
×
3907
      uint64_t *in = (uint64_t *)pInputData->pData;
×
3908
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3909
        if (colDataIsNull_s(pInputData, i)) {
×
3910
          continue;
×
3911
        }
3912

3913
        count++;
×
3914
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3915
      }
3916
      break;
×
3917
    }
3918
    case TSDB_DATA_TYPE_FLOAT: {
×
3919
      float *in = (float *)pInputData->pData;
×
3920
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3921
        if (colDataIsNull_s(pInputData, i)) {
×
3922
          continue;
×
3923
        }
3924

3925
        count++;
×
3926
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3927
      }
3928
      break;
×
3929
    }
3930
    case TSDB_DATA_TYPE_DOUBLE: {
1✔
3931
      double *in = (double *)pInputData->pData;
1✔
3932
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
2✔
3933
        if (colDataIsNull_s(pInputData, i)) {
2!
3934
          continue;
×
3935
        }
3936

3937
        count++;
1✔
3938
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
1✔
3939
      }
3940
      break;
1✔
3941
    }
3942
  }
3943

3944
  if (count == 0) {
2!
3945
    colDataSetNULL(pOutputData, 0);
3946
  } else {
3947
    matrix[1][1] = (double)count;
2✔
3948
    matrix[1][0] = matrix[0][1];
2✔
3949

3950
    double matrix00 = matrix[0][0] - matrix[1][0] * (matrix[0][1] / matrix[1][1]);
2✔
3951
    double matrix02 = matrix[0][2] - matrix[1][2] * (matrix[0][1] / matrix[1][1]);
2✔
3952
    double matrix12 = matrix[1][2] - matrix02 * (matrix[1][0] / matrix00);
2✔
3953
    matrix02 /= matrix00;
2✔
3954

3955
    matrix12 /= matrix[1][1];
2✔
3956

3957
    char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
2✔
3958
    char slopBuf[64] = {0};
2✔
3959
    char interceptBuf[64] = {0};
2✔
3960
    int  n = tsnprintf(slopBuf, 64, "%.6lf", matrix02);
2✔
3961
    if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
2!
3962
      (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, matrix02);
×
3963
    }
3964
    n = tsnprintf(interceptBuf, 64, "%.6lf", matrix12);
2✔
3965
    if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
2!
3966
      (void) snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, matrix12);
×
3967
    }
3968
    size_t len =
2✔
3969
        snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
2✔
3970
    varDataSetLen(buf, len);
2✔
3971
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, buf, false));
2!
3972
  }
3973

3974
  pOutput->numOfRows = 1;
2✔
3975
  return TSDB_CODE_SUCCESS;
2✔
3976
}
3977

3978
int32_t percentileScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
3979
  SColumnInfoData *pInputData = pInput->columnData;
4✔
3980
  SColumnInfoData *pOutputData = pOutput->columnData;
4✔
3981

3982
  int32_t type = GET_PARAM_TYPE(pInput);
4!
3983

3984
  double val;
3985
  bool   hasNull = false;
4✔
3986
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
8✔
3987
    if (colDataIsNull_s(pInputData, i)) {
8!
3988
      hasNull = true;
×
3989
      break;
×
3990
    }
3991
    char *in = pInputData->pData;
4✔
3992
    GET_TYPED_DATA(val, double, type, in);
4!
3993
  }
3994

3995
  if (hasNull) {
4!
3996
    colDataSetNULL(pOutputData, 0);
3997
  } else {
3998
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, (char *)&val, false));
4!
3999
  }
4000

4001
  pOutput->numOfRows = 1;
4✔
4002
  return TSDB_CODE_SUCCESS;
4✔
4003
}
4004

4005
int32_t apercentileScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4006
  return percentileScalarFunction(pInput, inputNum, pOutput);
1✔
4007
}
4008

4009
int32_t spreadScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4010
  SColumnInfoData *pInputData = pInput->columnData;
1✔
4011
  SColumnInfoData *pOutputData = pOutput->columnData;
1✔
4012

4013
  int32_t type = GET_PARAM_TYPE(pInput);
1!
4014

4015
  double min, max;
4016
  SET_DOUBLE_VAL(&min, DBL_MAX);
1✔
4017
  SET_DOUBLE_VAL(&max, -DBL_MAX);
1✔
4018

4019
  bool hasNull = false;
1✔
4020
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
2✔
4021
    if (colDataIsNull_s(pInputData, i)) {
2!
4022
      hasNull = true;
×
4023
      break;
×
4024
    }
4025

4026
    char *in = pInputData->pData;
1✔
4027

4028
    double val = 0;
1✔
4029
    GET_TYPED_DATA(val, double, type, in);
1!
4030

4031
    if (val < GET_DOUBLE_VAL(&min)) {
1!
4032
      SET_DOUBLE_VAL(&min, val);
1✔
4033
    }
4034

4035
    if (val > GET_DOUBLE_VAL(&max)) {
1!
4036
      SET_DOUBLE_VAL(&max, val);
1✔
4037
    }
4038
  }
4039

4040
  if (hasNull) {
1!
4041
    colDataSetNULL(pOutputData, 0);
4042
  } else {
4043
    double result = max - min;
1✔
4044
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, (char *)&result, false));
1!
4045
  }
4046

4047
  pOutput->numOfRows = 1;
1✔
4048
  return TSDB_CODE_SUCCESS;
1✔
4049
}
4050

4051
int32_t nonCalcScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3✔
4052
  SColumnInfoData *pInputData = pInput->columnData;
3✔
4053
  SColumnInfoData *pOutputData = pOutput->columnData;
3✔
4054

4055
  int32_t type = GET_PARAM_TYPE(pInput);
3!
4056
  bool    hasNull = false;
3✔
4057

4058
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
6✔
4059
    if (colDataIsNull_s(pInputData, i)) {
6!
4060
      hasNull = true;
×
4061
      break;
×
4062
    }
4063
  }
4064

4065
  double *out = (double *)pOutputData->pData;
3✔
4066
  if (hasNull) {
3!
4067
    colDataSetNULL(pOutputData, 0);
4068
  } else {
4069
    *out = 0;
3✔
4070
  }
4071

4072
  pOutput->numOfRows = 1;
3✔
4073
  return TSDB_CODE_SUCCESS;
3✔
4074
}
4075

4076
int32_t derivativeScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4077
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
1✔
4078
}
4079

4080
int32_t irateScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4081
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
1✔
4082
}
4083

4084
int32_t diffScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4085
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
1✔
4086
}
4087

4088
int32_t forecastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4089
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
×
4090
}
4091

4092
int32_t twaScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4093
  return avgScalarFunction(pInput, inputNum, pOutput);
1✔
4094
}
4095

4096
int32_t mavgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2✔
4097
  return avgScalarFunction(pInput, inputNum, pOutput);
2✔
4098
}
4099

4100
int32_t hllScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
4101
  return countScalarFunction(pInput, inputNum, pOutput);
4✔
4102
}
4103

4104
int32_t csumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4105
  return sumScalarFunction(pInput, inputNum, pOutput);
1✔
4106
}
4107

4108
typedef enum {
4109
  STATE_OPER_INVALID = 0,
4110
  STATE_OPER_LT,
4111
  STATE_OPER_GT,
4112
  STATE_OPER_LE,
4113
  STATE_OPER_GE,
4114
  STATE_OPER_NE,
4115
  STATE_OPER_EQ,
4116
} EStateOperType;
4117

4118
#define STATE_COMP(_op, _lval, _rval, _rtype) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_rval, _rtype))
4119

4120
#define GET_STATE_VAL(_val, _type) ((_type == TSDB_DATA_TYPE_BIGINT) ? (*(int64_t *)_val) : (*(double *)_val))
4121

4122
#define STATE_COMP_IMPL(_op, _lval, _rval) \
4123
  do {                                     \
4124
    switch (_op) {                         \
4125
      case STATE_OPER_LT:                  \
4126
        return ((_lval) < (_rval));        \
4127
        break;                             \
4128
      case STATE_OPER_GT:                  \
4129
        return ((_lval) > (_rval));        \
4130
        break;                             \
4131
      case STATE_OPER_LE:                  \
4132
        return ((_lval) <= (_rval));       \
4133
        break;                             \
4134
      case STATE_OPER_GE:                  \
4135
        return ((_lval) >= (_rval));       \
4136
        break;                             \
4137
      case STATE_OPER_NE:                  \
4138
        return ((_lval) != (_rval));       \
4139
        break;                             \
4140
      case STATE_OPER_EQ:                  \
4141
        return ((_lval) == (_rval));       \
4142
        break;                             \
4143
      default:                             \
4144
        break;                             \
4145
    }                                      \
4146
  } while (0)
4147

4148
static int8_t getStateOpType(char *opStr) {
24✔
4149
  int8_t opType;
4150
  if (strncasecmp(opStr, "LT", 2) == 0) {
24✔
4151
    opType = STATE_OPER_LT;
4✔
4152
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
20✔
4153
    opType = STATE_OPER_GT;
4✔
4154
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
16✔
4155
    opType = STATE_OPER_LE;
4✔
4156
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
12✔
4157
    opType = STATE_OPER_GE;
4✔
4158
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
8✔
4159
    opType = STATE_OPER_NE;
4✔
4160
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
4!
4161
    opType = STATE_OPER_EQ;
4✔
4162
  } else {
4163
    opType = STATE_OPER_INVALID;
×
4164
  }
4165

4166
  return opType;
24✔
4167
}
4168

4169
static bool checkStateOp(int8_t op, SColumnInfoData *pCol, int32_t index, SScalarParam *pCondParam) {
24✔
4170
  char   *data = colDataGetData(pCol, index);
24!
4171
  char   *param = pCondParam->columnData->pData;
24✔
4172
  int32_t paramType = GET_PARAM_TYPE(pCondParam);
24!
4173
  switch (pCol->info.type) {
24!
4174
    case TSDB_DATA_TYPE_TINYINT: {
×
4175
      int8_t v = *(int8_t *)data;
×
4176
      STATE_COMP(op, v, param, paramType);
×
4177
      break;
×
4178
    }
4179
    case TSDB_DATA_TYPE_UTINYINT: {
×
4180
      uint8_t v = *(uint8_t *)data;
×
4181
      STATE_COMP(op, v, param, paramType);
×
4182
      break;
×
4183
    }
4184
    case TSDB_DATA_TYPE_SMALLINT: {
×
4185
      int16_t v = *(int16_t *)data;
×
4186
      STATE_COMP(op, v, param, paramType);
×
4187
      break;
×
4188
    }
4189
    case TSDB_DATA_TYPE_USMALLINT: {
×
4190
      uint16_t v = *(uint16_t *)data;
×
4191
      STATE_COMP(op, v, param, paramType);
×
4192
      break;
×
4193
    }
4194
    case TSDB_DATA_TYPE_INT: {
×
4195
      int32_t v = *(int32_t *)data;
×
4196
      STATE_COMP(op, v, param, paramType);
×
4197
      break;
×
4198
    }
4199
    case TSDB_DATA_TYPE_UINT: {
×
4200
      uint32_t v = *(uint32_t *)data;
×
4201
      STATE_COMP(op, v, param, paramType);
×
4202
      break;
×
4203
    }
4204
    case TSDB_DATA_TYPE_BIGINT: {
12✔
4205
      int64_t v = *(int64_t *)data;
12✔
4206
      STATE_COMP(op, v, param, paramType);
12!
4207
      break;
×
4208
    }
4209
    case TSDB_DATA_TYPE_UBIGINT: {
×
4210
      uint64_t v = *(uint64_t *)data;
×
4211
      STATE_COMP(op, v, param, paramType);
×
4212
      break;
×
4213
    }
4214
    case TSDB_DATA_TYPE_FLOAT: {
×
4215
      float v = *(float *)data;
×
4216
      STATE_COMP(op, v, param, paramType);
×
4217
      break;
×
4218
    }
4219
    case TSDB_DATA_TYPE_DOUBLE: {
12✔
4220
      double v = *(double *)data;
12✔
4221
      STATE_COMP(op, v, param, paramType);
12!
4222
      break;
×
4223
    }
4224
    default: {
×
4225
      return false;
×
4226
    }
4227
  }
4228
  return false;
×
4229
}
4230

4231
int32_t stateCountScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
12✔
4232
  SColumnInfoData *pInputData = pInput->columnData;
12✔
4233
  SColumnInfoData *pOutputData = pOutput->columnData;
12✔
4234

4235
  int8_t  op = getStateOpType(varDataVal(pInput[1].columnData->pData));
12✔
4236
  int64_t count = 0;
12✔
4237

4238
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
24✔
4239
    if (colDataIsNull_s(pInputData, i)) {
24!
4240
      colDataSetNULL(pOutputData, i);
×
4241
      continue;
×
4242
    }
4243

4244
    bool    ret = checkStateOp(op, pInputData, i, &pInput[2]);
12✔
4245
    int64_t out = -1;
12✔
4246
    if (ret) {
12✔
4247
      out = ++count;
6✔
4248
    } else {
4249
      count = 0;
6✔
4250
    }
4251
    SCL_ERR_RET(colDataSetVal(pOutputData, i, (char *)&out, false));
12!
4252
  }
4253

4254
  pOutput->numOfRows = pInput->numOfRows;
12✔
4255
  return TSDB_CODE_SUCCESS;
12✔
4256
}
4257

4258
int32_t stateDurationScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
12✔
4259
  SColumnInfoData *pInputData = pInput->columnData;
12✔
4260
  SColumnInfoData *pOutputData = pOutput->columnData;
12✔
4261

4262
  int8_t op = getStateOpType(varDataVal(pInput[1].columnData->pData));
12✔
4263

4264
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
24✔
4265
    if (colDataIsNull_s(pInputData, i)) {
24!
4266
      colDataSetNULL(pOutputData, i);
×
4267
      continue;
×
4268
    }
4269

4270
    bool    ret = checkStateOp(op, pInputData, i, &pInput[2]);
12✔
4271
    int64_t out = -1;
12✔
4272
    if (ret) {
12✔
4273
      out = 0;
6✔
4274
    }
4275
    SCL_ERR_RET(colDataSetVal(pOutputData, i, (char *)&out, false));
12!
4276
  }
4277

4278
  pOutput->numOfRows = pInput->numOfRows;
12✔
4279
  return TSDB_CODE_SUCCESS;
12✔
4280
}
4281

4282
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
4283

4284
static int8_t getHistogramBinType(char *binTypeStr) {
6✔
4285
  int8_t binType;
4286
  if (strcasecmp(binTypeStr, "user_input") == 0) {
6✔
4287
    binType = USER_INPUT_BIN;
2✔
4288
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
4✔
4289
    binType = LINEAR_BIN;
2✔
4290
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
2!
4291
    binType = LOG_BIN;
2✔
4292
  } else {
4293
    binType = UNKNOWN_BIN;
×
4294
  }
4295

4296
  return binType;
6✔
4297
}
4298

4299
typedef struct SHistoFuncBin {
4300
  double  lower;
4301
  double  upper;
4302
  int64_t count;
4303
  double  percentage;
4304
} SHistoFuncBin;
4305

4306
static int32_t getHistogramBinDesc(SHistoFuncBin **bins, int32_t *binNum, char *binDescStr, int8_t binType,
6✔
4307
                                bool normalized) {
4308
  cJSON  *binDesc = cJSON_Parse(binDescStr);
6✔
4309
  int32_t numOfBins;
4310
  double *intervals;
4311
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
6✔
4312
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
4✔
4313
    int32_t startIndex;
4314
    if (numOfParams != 4) {
4!
4315
      cJSON_Delete(binDesc);
×
4316
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4317
    }
4318

4319
    cJSON *start = cJSON_GetObjectItem(binDesc, "start");
4✔
4320
    cJSON *factor = cJSON_GetObjectItem(binDesc, "factor");
4✔
4321
    cJSON *width = cJSON_GetObjectItem(binDesc, "width");
4✔
4322
    cJSON *count = cJSON_GetObjectItem(binDesc, "count");
4✔
4323
    cJSON *infinity = cJSON_GetObjectItem(binDesc, "infinity");
4✔
4324

4325
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
4!
4326
      cJSON_Delete(binDesc);
×
4327
      SCL_RET(TSDB_CODE_SUCCESS);
×
4328
    }
4329

4330
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
4!
4331
      cJSON_Delete(binDesc);
×
4332
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4333
    }
4334

4335
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
4!
4336
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
4!
4337
      cJSON_Delete(binDesc);
×
4338
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4339
    }
4340

4341
    int32_t counter = (int32_t)count->valueint;
4✔
4342
    if (infinity->valueint == false) {
4!
4343
      startIndex = 0;
×
4344
      numOfBins = counter + 1;
×
4345
    } else {
4346
      startIndex = 1;
4✔
4347
      numOfBins = counter + 3;
4✔
4348
    }
4349

4350
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
4✔
4351
    if (NULL == intervals) {
4!
4352
      cJSON_Delete(binDesc);
×
4353
      SCL_ERR_RET(terrno);
×
4354
    }
4355
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
4!
4356
      // linear bin process
4357
      if (width->valuedouble == 0) {
2!
4358
        taosMemoryFree(intervals);
×
4359
        cJSON_Delete(binDesc);
×
4360
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4361
      }
4362
      for (int i = 0; i < counter + 1; ++i) {
14✔
4363
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
12✔
4364
        if (isinf(intervals[startIndex])) {
12!
4365
          taosMemoryFree(intervals);
×
4366
          cJSON_Delete(binDesc);
×
4367
          SCL_ERR_RET(TSDB_CODE_FAILED);
×
4368
        }
4369
        startIndex++;
12✔
4370
      }
4371
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
2!
4372
      // log bin process
4373
      if (start->valuedouble == 0) {
2!
4374
        taosMemoryFree(intervals);
×
4375
        cJSON_Delete(binDesc);
×
4376
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4377
      }
4378
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
2!
4379
        taosMemoryFree(intervals);
×
4380
        cJSON_Delete(binDesc);
×
4381
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4382
      }
4383
      for (int i = 0; i < counter + 1; ++i) {
14✔
4384
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
12✔
4385
        if (isinf(intervals[startIndex])) {
12!
4386
          taosMemoryFree(intervals);
×
4387
          cJSON_Delete(binDesc);
×
4388
          SCL_ERR_RET(TSDB_CODE_FAILED);
×
4389
        }
4390
        startIndex++;
12✔
4391
      }
4392
    } else {
4393
      taosMemoryFree(intervals);
×
4394
      cJSON_Delete(binDesc);
×
4395
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4396
    }
4397

4398
    if (infinity->valueint == true) {
4!
4399
      intervals[0] = -INFINITY;
4✔
4400
      intervals[numOfBins - 1] = INFINITY;
4✔
4401
      // in case of desc bin orders, -inf/inf should be swapped
4402
      if (numOfBins < 4) {
4!
4403
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4404
      }
4405
      if (intervals[1] > intervals[numOfBins - 2]) {
4!
4406
        TSWAP(intervals[0], intervals[numOfBins - 1]);
×
4407
      }
4408
    }
4409
  } else if (cJSON_IsArray(binDesc)) { /* user input bins */
2!
4410
    if (binType != USER_INPUT_BIN) {
2!
4411
      cJSON_Delete(binDesc);
×
4412
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4413
    }
4414
    numOfBins = cJSON_GetArraySize(binDesc);
2✔
4415
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
2✔
4416
    if (NULL == intervals) {
2!
4417
      cJSON_Delete(binDesc);
×
4418
      SCL_ERR_RET(terrno);
×
4419
    }
4420
    cJSON *bin = binDesc->child;
2✔
4421
    if (bin == NULL) {
2!
4422
      taosMemoryFree(intervals);
×
4423
      cJSON_Delete(binDesc);
×
4424
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4425
    }
4426
    int i = 0;
2✔
4427
    while (bin) {
8✔
4428
      intervals[i] = bin->valuedouble;
6✔
4429
      if (!cJSON_IsNumber(bin)) {
6!
4430
        taosMemoryFree(intervals);
×
4431
        cJSON_Delete(binDesc);
×
4432
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4433
      }
4434
      if (i != 0 && intervals[i] <= intervals[i - 1]) {
6!
4435
        taosMemoryFree(intervals);
×
4436
        cJSON_Delete(binDesc);
×
4437
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4438
      }
4439
      bin = bin->next;
6✔
4440
      i++;
6✔
4441
    }
4442
  } else {
4443
    cJSON_Delete(binDesc);
×
4444
    SCL_RET(TSDB_CODE_FAILED);
×
4445
  }
4446

4447
  *binNum = numOfBins - 1;
6✔
4448
  *bins = taosMemoryCalloc(numOfBins, sizeof(SHistoFuncBin));
6✔
4449
  if (NULL == bins) {
6!
4450
    SCL_ERR_RET(terrno);
×
4451
  }
4452
  for (int32_t i = 0; i < *binNum; ++i) {
38✔
4453
    (*bins)[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
32!
4454
    (*bins)[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
32!
4455
    (*bins)[i].count = 0;
32✔
4456
  }
4457

4458
  taosMemoryFree(intervals);
6✔
4459
  cJSON_Delete(binDesc);
6✔
4460

4461
  SCL_RET(TSDB_CODE_SUCCESS);
6!
4462
}
4463

4464
int32_t histogramScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
4465
  SColumnInfoData *pInputData = pInput->columnData;
6✔
4466
  SColumnInfoData *pOutputData = pOutput->columnData;
6✔
4467

4468
  SHistoFuncBin *bins;
4469
  int32_t        numOfBins = 0;
6✔
4470
  int32_t        totalCount = 0;
6✔
4471

4472
  char *binTypeStr = taosStrndup(varDataVal(pInput[1].columnData->pData), varDataLen(pInput[1].columnData->pData));
6✔
4473
  if (NULL == binTypeStr) {
6!
4474
    SCL_ERR_RET(terrno);
×
4475
  }
4476
  int8_t binType = getHistogramBinType(binTypeStr);
6✔
4477
  taosMemoryFree(binTypeStr);
6✔
4478

4479
  char   *binDesc = taosStrndup(varDataVal(pInput[2].columnData->pData), varDataLen(pInput[2].columnData->pData));
6✔
4480
  if (NULL == binDesc) {
6!
4481
    SCL_ERR_RET(terrno);
×
4482
  }
4483
  int64_t normalized = *(int64_t *)(pInput[3].columnData->pData);
6✔
4484

4485
  int32_t type = GET_PARAM_TYPE(pInput);
6!
4486
  int32_t code = getHistogramBinDesc(&bins, &numOfBins, binDesc, binType, (bool)normalized);
6✔
4487
  if (TSDB_CODE_SUCCESS != code) {
6!
4488
    taosMemoryFree(binDesc);
×
4489
    return code;
×
4490
  }
4491
  taosMemoryFree(binDesc);
6✔
4492

4493
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
12✔
4494
    if (colDataIsNull_s(pInputData, i)) {
12!
4495
      continue;
×
4496
    }
4497

4498
    char  *data = colDataGetData(pInputData, i);
6!
4499
    double v;
4500
    GET_TYPED_DATA(v, double, type, data);
6!
4501

4502
    for (int32_t k = 0; k < numOfBins; ++k) {
32!
4503
      if (v > bins[k].lower && v <= bins[k].upper) {
32!
4504
        bins[k].count++;
6✔
4505
        totalCount++;
6✔
4506
        break;
6✔
4507
      }
4508
    }
4509
  }
4510

4511
  if (normalized) {
6!
4512
    for (int32_t k = 0; k < numOfBins; ++k) {
×
4513
      if (totalCount != 0) {
×
4514
        bins[k].percentage = bins[k].count / (double)totalCount;
×
4515
      } else {
4516
        bins[k].percentage = 0;
×
4517
      }
4518
    }
4519
  }
4520

4521
  SCL_ERR_JRET(colInfoDataEnsureCapacity(pOutputData, numOfBins, false));
6!
4522

4523
  for (int32_t k = 0; k < numOfBins; ++k) {
38✔
4524
    int32_t len;
4525
    char    buf[512] = {0};
32✔
4526
    if (!normalized) {
32!
4527
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}",
32✔
4528
                     bins[k].lower, bins[k].upper, bins[k].count);
32✔
4529
    } else {
4530
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}",
×
4531
                     bins[k].lower, bins[k].upper, bins[k].percentage);
×
4532
    }
4533
    varDataSetLen(buf, len);
32✔
4534
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, buf, false));
32!
4535
  }
4536
  pOutput->numOfRows = numOfBins;
6✔
4537

4538
_return:
6✔
4539
  taosMemoryFree(bins);
6✔
4540
  return code;
6✔
4541
}
4542

4543
int32_t selectScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
11✔
4544
  SColumnInfoData *pInputData = pInput->columnData;
11✔
4545
  SColumnInfoData *pOutputData = pOutput->columnData;
11✔
4546

4547
  int32_t type = GET_PARAM_TYPE(pInput);
11!
4548

4549
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
22✔
4550
    if (colDataIsNull_s(pInputData, i)) {
22✔
4551
      colDataSetNULL(pOutputData, 0);
4552
      continue;
1✔
4553
    }
4554

4555
    char *data = colDataGetData(pInputData, i);
10!
4556
    SCL_ERR_RET(colDataSetVal(pOutputData, i, data, false));
10!
4557
  }
4558

4559
  pOutput->numOfRows = 1;
11✔
4560
  return TSDB_CODE_SUCCESS;
11✔
4561
}
4562

4563
int32_t topBotScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
4564
  return selectScalarFunction(pInput, inputNum, pOutput);
4✔
4565
}
4566

4567
int32_t firstLastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
4✔
4568
  return selectScalarFunction(pInput, inputNum, pOutput);
4✔
4569
}
4570

4571
int32_t sampleScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
4572
  return selectScalarFunction(pInput, inputNum, pOutput);
1✔
4573
}
4574

4575
int32_t tailScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2✔
4576
  return selectScalarFunction(pInput, inputNum, pOutput);
2✔
4577
}
4578

4579
int32_t uniqueScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4580
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4581
}
4582

4583
int32_t modeScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4584
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4585
}
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