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

taosdata / TDengine / #3903

24 Apr 2025 11:36AM UTC coverage: 55.307% (+0.09%) from 55.213%
#3903

push

travis-ci

happyguoxy
Sync branches at 2025-04-24 19:35

175024 of 316459 relevant lines covered (55.31%)

1151858.11 hits per line

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

26.26
/source/libs/scalar/src/sclfunc.c
1
#include <stdint.h>
2
#include "cJSON.h"
3
#include "function.h"
4
#include "scalar.h"
5
#include "sclInt.h"
6
#include "sclvector.h"
7
#include "tdatablock.h"
8
#include "tdef.h"
9
#include "tjson.h"
10
#include "ttime.h"
11
#include "filter.h"
12
#include "decimal.h"
13

14
typedef float (*_float_fn)(float);
15
typedef float (*_float_fn_2)(float, float);
16
typedef double (*_double_fn)(double);
17
typedef double (*_double_fn_2)(double, double);
18
typedef int (*_conv_fn)(int);
19
typedef void (*_trim_space_fn)(char *, char *, int32_t, int32_t, void*);
20
typedef int32_t (*_trim_fn)(char *, char *, char *, int32_t, int32_t, void*);
21
typedef int32_t (*_len_fn)(char *, int32_t, VarDataLenT *);
22

23
/** Math functions **/
24
static double tlog(double v) { return log(v); }
39,922✔
25

26
static double tlog2(double v, double base) {
18✔
27
  double a = log(v);
18✔
28
  double b = log(base);
18✔
29
  if (isnan(a) || isinf(a)) {
18✔
30
    return a;
×
31
  } else if (isnan(b) || isinf(b)) {
18✔
32
    return b;
×
33
  } else if (b == 0) {
18✔
34
    return INFINITY;
×
35
  } else {
36
    return a / b;
18✔
37
  }
38
}
39

40
static double degrees(double v) {
×
41
  return v * M_1_PI * 180.0;
×
42
}
43

44
static double radians(double v) {
×
45
  return v / 180.0 * M_PI ;
×
46
}
47

48
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10,134✔
49
  SColumnInfoData *pInputData = pInput->columnData;
10,134✔
50
  SColumnInfoData *pOutputData = pOutput->columnData;
10,134✔
51

52
  int32_t type = GET_PARAM_TYPE(pInput);
10,134✔
53

54
  switch (type) {
10,134✔
55
    case TSDB_DATA_TYPE_FLOAT: {
4✔
56
      float *in = (float *)pInputData->pData;
4✔
57
      float *out = (float *)pOutputData->pData;
4✔
58
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
20✔
59
        if (colDataIsNull_s(pInputData, i)) {
32✔
60
          colDataSetNULL(pOutputData, i);
×
61
          continue;
×
62
        }
63
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
16✔
64
      }
65
      break;
4✔
66
    }
67

68
    case TSDB_DATA_TYPE_DOUBLE: {
10,083✔
69
      double *in = (double *)pInputData->pData;
10,083✔
70
      double *out = (double *)pOutputData->pData;
10,083✔
71
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
210,501✔
72
        if (colDataIsNull_s(pInputData, i)) {
400,836✔
73
          colDataSetNULL(pOutputData, i);
×
74
          continue;
×
75
        }
76
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
200,418✔
77
      }
78
      break;
10,083✔
79
    }
80

81
    case TSDB_DATA_TYPE_TINYINT: {
4✔
82
      int8_t *in = (int8_t *)pInputData->pData;
4✔
83
      int8_t *out = (int8_t *)pOutputData->pData;
4✔
84
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
20✔
85
        if (colDataIsNull_s(pInputData, i)) {
32✔
86
          colDataSetNULL(pOutputData, i);
×
87
          continue;
×
88
        }
89
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
16✔
90
      }
91
      break;
4✔
92
    }
93

94
    case TSDB_DATA_TYPE_SMALLINT: {
4✔
95
      int16_t *in = (int16_t *)pInputData->pData;
4✔
96
      int16_t *out = (int16_t *)pOutputData->pData;
4✔
97
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
20✔
98
        if (colDataIsNull_s(pInputData, i)) {
32✔
99
          colDataSetNULL(pOutputData, i);
×
100
          continue;
×
101
        }
102
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
16✔
103
      }
104
      break;
4✔
105
    }
106

107
    case TSDB_DATA_TYPE_INT: {
36✔
108
      int32_t *in = (int32_t *)pInputData->pData;
36✔
109
      int32_t *out = (int32_t *)pOutputData->pData;
36✔
110
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
440✔
111
        if (colDataIsNull_s(pInputData, i)) {
808✔
112
          colDataSetNULL(pOutputData, i);
49✔
113
          continue;
49✔
114
        }
115
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
355✔
116
      }
117
      break;
36✔
118
    }
119

120
    case TSDB_DATA_TYPE_BIGINT: {
2✔
121
      int64_t *in = (int64_t *)pInputData->pData;
2✔
122
      int64_t *out = (int64_t *)pOutputData->pData;
2✔
123
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
8✔
124
        if (colDataIsNull_s(pInputData, i)) {
12✔
125
          colDataSetNULL(pOutputData, i);
×
126
          continue;
×
127
        }
128
        out[i] = (in[i] >= 0) ? in[i] : -in[i];
6✔
129
      }
130
      break;
2✔
131
    }
132

133
    case TSDB_DATA_TYPE_NULL: {
×
134
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
135
        colDataSetNULL(pOutputData, i);
×
136
      }
137
      break;
×
138
    }
139

140
    default: {
1✔
141
      SCL_ERR_RET(colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL));
1✔
142
    }
143
  }
144

145
  pOutput->numOfRows = pInput->numOfRows;
10,136✔
146
  return TSDB_CODE_SUCCESS;
10,136✔
147
}
148

149
int32_t signFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
150
  SColumnInfoData *pInputData = pInput->columnData;
×
151
  SColumnInfoData *pOutputData = pOutput->columnData;
×
152

153
  int32_t type = GET_PARAM_TYPE(pInput);
×
154

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

169
    case TSDB_DATA_TYPE_DOUBLE: {
×
170
      double *in = (double *)pInputData->pData;
×
171
      double *out = (double *)pOutputData->pData;
×
172
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
173
        if (colDataIsNull_s(pInputData, i)) {
×
174
          colDataSetNULL(pOutputData, i);
×
175
          continue;
×
176
        }
177
        out[i] = (double)(in[i] < 0.0 ? -1 : (in[i] > 0.0 ? 1 : 0));
×
178
      }
179
      break;
×
180
    }
181

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

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

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

221
    case TSDB_DATA_TYPE_BIGINT: {
×
222
      int64_t *in = (int64_t *)pInputData->pData;
×
223
      int64_t *out = (int64_t *)pOutputData->pData;
×
224
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
225
        if (colDataIsNull_s(pInputData, i)) {
×
226
          colDataSetNULL(pOutputData, i);
×
227
          continue;
×
228
        }
229
        out[i] = (int64_t)(in[i] < 0 ? -1 : (in[i] > 0 ? 1 : 0));
×
230
      }
231
      break;
×
232
    }
233

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

289
    default: {
×
290
      SCL_ERR_RET(TSDB_CODE_FUNC_FUNTION_PARA_TYPE);
×
291
    }
292
  }
293

294
  pOutput->numOfRows = pInput->numOfRows;
×
295
  return TSDB_CODE_SUCCESS;
×
296
}
297

298
static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _double_fn valFn) {
12,190✔
299
  int32_t type = GET_PARAM_TYPE(pInput);
12,190✔
300

301
  SColumnInfoData *pInputData = pInput->columnData;
12,190✔
302
  SColumnInfoData *pOutputData = pOutput->columnData;
12,190✔
303

304
  _getDoubleValue_fn_t getValueFn;
305
  SCL_ERR_RET(getVectorDoubleValueFn(type, &getValueFn));
12,190✔
306

307
  double *out = (double *)pOutputData->pData;
12,190✔
308

309
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
249,409✔
310
    if (colDataIsNull_s(pInputData, i) || IS_NULL_TYPE(type)) {
475,872✔
311
      colDataSetNULL(pOutputData, i);
×
312
      continue;
×
313
    }
314
    double tmp = 0;
237,965✔
315
    SCL_ERR_RET(getValueFn(pInputData->pData, i, &tmp));
237,965✔
316
    double result = valFn(tmp);
237,832✔
317
    if (isinf(result) || isnan(result)) {
237,248✔
318
      colDataSetNULL(pOutputData, i);
×
319
    } else {
320
      out[i] = result;
238,068✔
321
    }
322
  }
323

324
  pOutput->numOfRows = pInput->numOfRows;
11,473✔
325
  return TSDB_CODE_SUCCESS;
11,473✔
326
}
327

328
static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput,
12,116✔
329
                                       _double_fn_2 valFn) {
330
  SColumnInfoData     *pInputData[2];
331
  SColumnInfoData     *pOutputData = pOutput->columnData;
12,116✔
332
  _getDoubleValue_fn_t getValueFn[2];
333

334
  for (int32_t i = 0; i < inputNum; ++i) {
36,350✔
335
    pInputData[i] = pInput[i].columnData;
24,234✔
336
    SCL_ERR_RET(getVectorDoubleValueFn(GET_PARAM_TYPE(&pInput[i]), &getValueFn[i]));
48,468✔
337
  }
338

339
  double *out = (double *)pOutputData->pData;
12,116✔
340
  double  result;
341

342
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
12,116✔
343

344
  int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
12,116✔
345
  if (pInput[0].numOfRows == pInput[1].numOfRows) {
12,116✔
346
    for (int32_t i = 0; i < numOfRows; ++i) {
48✔
347
      if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) {
108✔
348
        colDataSetNULL(pOutputData, i);
×
349
        continue;
×
350
      }
351
      double val1 = 0;
36✔
352
      double val2 = 0;
36✔
353
      SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, i, &val1));
36✔
354
      SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, i, &val2));
36✔
355
      result = valFn(val1, val2);
36✔
356
      if (isinf(result) || isnan(result)) {
36✔
357
        colDataSetNULL(pOutputData, i);
×
358
      } else {
359
        out[i] = result;
36✔
360
      }
361
    }
362
  } else if (pInput[0].numOfRows == 1) {  // left operand is constant
12,104✔
363
    if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
×
364
      colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows);
×
365
    } else {
366
      for (int32_t i = 0; i < numOfRows; ++i) {
×
367
        if (colDataIsNull_s(pInputData[1], i)) {
×
368
          colDataSetNULL(pOutputData, i);
×
369
          continue;
×
370
        }
371
        double val1 = 0;
×
372
        double val2 = 0;
×
373
        SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, 0, &val1));
×
374
        SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, i, &val2));
×
375
        result = valFn(val1, val2);
×
376
        if (isinf(result) || isnan(result)) {
×
377
          colDataSetNULL(pOutputData, i);
×
378
          continue;
×
379
        }
380

381
        out[i] = result;
×
382
      }
383
    }
384
  } else if (pInput[1].numOfRows == 1) {
12,104✔
385
    if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
24,204✔
386
      colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows);
×
387
    } else {
388
      for (int32_t i = 0; i < numOfRows; ++i) {
248,131✔
389
        if (colDataIsNull_s(pInputData[0], i)) {
472,254✔
390
          colDataSetNULL(pOutputData, i);
6✔
391
          continue;
×
392
        }
393
        double val1 = 0;
236,121✔
394
        double val2 = 0;
236,121✔
395
        SCL_ERR_RET(getValueFn[0](pInputData[0]->pData, i, &val1));
236,121✔
396
        SCL_ERR_RET(getValueFn[1](pInputData[1]->pData, 0, &val2));
235,125✔
397
        result = valFn(val1, val2);
235,597✔
398
        if (isinf(result) || isnan(result)) {
236,022✔
399
          colDataSetNULL(pOutputData, i);
×
400
          continue;
×
401
        }
402

403
        out[i] = result;
236,290✔
404
      }
405
    }
406
  }
407

408
  pOutput->numOfRows = numOfRows;
12,017✔
409
  return TSDB_CODE_SUCCESS;
12,017✔
410
}
411

412
static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _float_fn f1,
2,073✔
413
                                _double_fn d1) {
414
  int32_t type = GET_PARAM_TYPE(pInput);
2,073✔
415

416
  SColumnInfoData *pInputData = pInput->columnData;
2,073✔
417
  SColumnInfoData *pOutputData = pOutput->columnData;
2,073✔
418

419
  switch (type) {
2,073✔
420
    case TSDB_DATA_TYPE_FLOAT: {
6✔
421
      float *in = (float *)pInputData->pData;
6✔
422
      float *out = (float *)pOutputData->pData;
6✔
423

424
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
24✔
425
        if (colDataIsNull_s(pInputData, i)) {
36✔
426
          colDataSetNULL(pOutputData, i);
×
427
          continue;
×
428
        }
429
        out[i] = f1(in[i]) + 0;
18✔
430
      }
431
      break;
6✔
432
    }
433

434
    case TSDB_DATA_TYPE_DOUBLE: {
2,020✔
435
      double *in = (double *)pInputData->pData;
2,020✔
436
      double *out = (double *)pOutputData->pData;
2,020✔
437

438
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
42,020✔
439
        if (colDataIsNull_s(pInputData, i)) {
79,998✔
440
          colDataSetNULL(pOutputData, i);
×
441
          continue;
×
442
        }
443
        out[i] = d1(in[i]) + 0;
39,999✔
444
      }
445
      break;
2,021✔
446
    }
447

448
    case TSDB_DATA_TYPE_NULL: {
×
449
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
450
        colDataSetNULL(pOutputData, i);
×
451
      }
452
      break;
×
453
    }
454

455
    default: {
47✔
456
      SCL_ERR_RET(colDataAssign(pOutputData, pInputData, pInput->numOfRows, NULL));
47✔
457
    }
458
  }
459

460
  pOutput->numOfRows = pInput->numOfRows;
2,073✔
461
  return TSDB_CODE_SUCCESS;
2,073✔
462
}
463

464
/** String functions **/
465
static int32_t tlength(char *input, int32_t type, VarDataLenT *len) {
62✔
466
  *len = varDataLen(input);
62✔
467
  return TSDB_CODE_SUCCESS;
62✔
468
}
469

470
uint8_t getCharLen(const unsigned char *str) {
24✔
471
  if (strcasecmp(tsCharset, "UTF-8") != 0) {
24✔
472
    return 1;
×
473
  }
474
  if ((str[0] & 0x80) == 0) {
24✔
475
    return 1;
24✔
476
  } else if ((str[0] & 0xE0) == 0xC0) {
×
477
    return 2;
×
478
  } else if ((str[0] & 0xF0) == 0xE0) {
×
479
    return 3;
×
480
  } else if ((str[0] & 0xF8) == 0xF0) {
×
481
    return 4;
×
482
  } else {
483
    return 1;
×
484
  }
485
}
486

487
static int32_t tcharlength(char *input, int32_t type, VarDataLenT *len) {
2✔
488
  if (type == TSDB_DATA_TYPE_VARCHAR) {
2✔
489
    // calculate the number of characters in the string considering the multi-byte character
490
    char *str = varDataVal(input);
2✔
491
    VarDataLenT strLen = 0;
2✔
492
    VarDataLenT pos = 0;
2✔
493
    while(pos < varDataLen(input)) {
26✔
494
      strLen++;
24✔
495
      pos += getCharLen((unsigned char *)(str + pos));
24✔
496
    }
497
    *len = strLen;
2✔
498
    return TSDB_CODE_SUCCESS;
2✔
499
  } else if (type == TSDB_DATA_TYPE_GEOMETRY) {
×
500
    *len = varDataLen(input);
×
501
  } else {  // NCHAR
502
    *len = varDataLen(input) / TSDB_NCHAR_SIZE;
×
503
  }
504
  return TSDB_CODE_SUCCESS;
×
505
}
506

507
static void tltrimspace(char *input, char *output, int32_t type, int32_t charLen, void* charsetCxt) {
60✔
508
  int32_t numOfSpaces = 0;
60✔
509
  if (type == TSDB_DATA_TYPE_VARCHAR) {
60✔
510
    for (int32_t i = 0; i < charLen; ++i) {
60✔
511
      if (!isspace(*(varDataVal(input) + i))) {
60✔
512
        break;
60✔
513
      }
514
      numOfSpaces++;
×
515
    }
516
  } else {  // NCHAR
517
    for (int32_t i = 0; i < charLen; ++i) {
×
518
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
519
        break;
×
520
      }
521
      numOfSpaces++;
×
522
    }
523
  }
524

525
  int32_t resLen;
526
  if (type == TSDB_DATA_TYPE_VARCHAR) {
60✔
527
    resLen = charLen - numOfSpaces;
60✔
528
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfSpaces, resLen);
60✔
529
  } else {
530
    resLen = (charLen - numOfSpaces) * TSDB_NCHAR_SIZE;
×
531
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfSpaces * TSDB_NCHAR_SIZE, resLen);
×
532
  }
533

534
  varDataSetLen(output, resLen);
60✔
535
}
60✔
536

537
static void tlrtrimspace(char *input, char *output, int32_t type, int32_t charLen, void* charsetCxt) {
×
538
  int32_t numOfLeftSpaces = 0;
×
539
  int32_t numOfRightSpaces = 0;
×
540
  if (type == TSDB_DATA_TYPE_VARCHAR) {
×
541
    for (int32_t i = 0; i < charLen; ++i) {
×
542
      if (!isspace(*(varDataVal(input) + i))) {
×
543
        break;
×
544
      }
545
      numOfLeftSpaces++;
×
546
    }
547
  } else {  // NCHAR
548
    for (int32_t i = 0; i < charLen; ++i) {
×
549
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
550
        break;
×
551
      }
552
      numOfLeftSpaces++;
×
553
    }
554
  }
555

556
  if (type == TSDB_DATA_TYPE_VARCHAR) {
×
557
    for (int32_t i = charLen - 1; i >= 0; --i) {
×
558
      if (!isspace(*(varDataVal(input) + i))) {
×
559
        break;
×
560
      }
561
      numOfRightSpaces++;
×
562
    }
563
  } else {  // NCHAR
564
    for (int32_t i = charLen - 1; i >= 0; --i) {
×
565
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
566
        break;
×
567
      }
568
      numOfRightSpaces++;
×
569
    }
570
  }
571

572
  int32_t resLen;
573
  if (type == TSDB_DATA_TYPE_VARCHAR) {
×
574
    resLen = charLen - (numOfLeftSpaces + numOfRightSpaces);
×
575
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfLeftSpaces, resLen);
×
576
  } else {
577
    resLen = (charLen - (numOfLeftSpaces + numOfRightSpaces)) * TSDB_NCHAR_SIZE;
×
578
    (void)memcpy(varDataVal(output), varDataVal(input) + numOfLeftSpaces * TSDB_NCHAR_SIZE, resLen);
×
579
  }
580

581
  varDataSetLen(output, resLen);
×
582
}
×
583

584
static bool isCharStart(char c) {
360✔
585
  return strcasecmp(tsCharset, "UTF-8") == 0 ? ((c & 0xC0) != 0x80) : true;
360✔
586
}
587

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

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

635
static int32_t convNcharToVarchar(char *input, char **output, int32_t inputLen, int32_t *outputLen, void* charsetCxt) {
×
636
  *output = taosMemoryCalloc(inputLen, 1);
×
637
  if (NULL == *output) {
×
638
    return terrno;
×
639
  }
640
  *outputLen = taosUcs4ToMbs((TdUcs4 *)input, inputLen, *output, charsetCxt);
×
641
  if (*outputLen < 0) {
×
642
    taosMemoryFree(*output);
×
643
    return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
644
  }
645
  return TSDB_CODE_SUCCESS;
×
646
}
647

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

666
  bool    needFree = false;
×
667
  if (inputType != remType) {
×
668
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType, charsetCxt));
×
669
    needFree = true;
×
670
  }
671

672
  if (remLen == 0 || remLen > orgLen) {
×
673
    (void)memcpy(varDataVal(output), orgStr, orgLen);
×
674
    varDataSetLen(output, orgLen);
×
675
    return TSDB_CODE_SUCCESS;
×
676
  }
677

678
  pos = trimHelper(orgStr, remStr, orgLen, remLen, true, inputType == TSDB_DATA_TYPE_NCHAR);
×
679

680
  if (needFree) {
×
681
    taosMemoryFree(remStr);
×
682
  }
683

684
  int32_t resLen = orgLen - pos;
×
685
  (void)memcpy(varDataVal(output), orgStr + pos, resLen);
×
686
  varDataSetLen(output, resLen);
×
687
  return TSDB_CODE_SUCCESS;
×
688
}
689

690
static void trtrimspace(char *input, char *output, int32_t type, int32_t charLen, void *charsetCxt) {
60✔
691
  int32_t numOfSpaces = 0;
60✔
692
  if (type == TSDB_DATA_TYPE_VARCHAR) {
60✔
693
    for (int32_t i = charLen - 1; i >= 0; --i) {
60✔
694
      if (!isspace(*(varDataVal(input) + i))) {
60✔
695
        break;
60✔
696
      }
697
      numOfSpaces++;
×
698
    }
699
  } else {  // NCHAR
700
    for (int32_t i = charLen - 1; i >= 0; --i) {
×
701
      if (!iswspace(*((uint32_t *)varDataVal(input) + i))) {
×
702
        break;
×
703
      }
704
      numOfSpaces++;
×
705
    }
706
  }
707

708
  int32_t resLen;
709
  if (type == TSDB_DATA_TYPE_VARCHAR) {
60✔
710
    resLen = charLen - numOfSpaces;
60✔
711
  } else {
712
    resLen = (charLen - numOfSpaces) * TSDB_NCHAR_SIZE;
×
713
  }
714
  (void)memcpy(varDataVal(output), varDataVal(input), resLen);
60✔
715

716
  varDataSetLen(output, resLen);
60✔
717
}
60✔
718

719
static int32_t trtrim(char *input, char *remInput, char *output, int32_t inputType, int32_t remType, void* charsetCxt) {
×
720
  int32_t orgLen = varDataLen(input);
×
721
  char   *orgStr = varDataVal(input);
×
722
  int32_t remLen = varDataLen(remInput);
×
723
  char   *remStr = varDataVal(remInput);
×
724
  if (orgLen == 0) {
×
725
    varDataSetLen(output, 0);
×
726
    return TSDB_CODE_SUCCESS;
×
727
  }
728
  int32_t pos = 0;
×
729
  bool    needFree = false;
×
730

731
  if (inputType != remType) {
×
732
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType, charsetCxt));
×
733
    needFree = true;
×
734
  }
735

736
  if (remLen == 0 || remLen > orgLen) {
×
737
    (void)memcpy(varDataVal(output), orgStr, orgLen);
×
738
    varDataSetLen(output, orgLen);
×
739
    return TSDB_CODE_SUCCESS;
×
740
  }
741

742
  pos = trimHelper(orgStr, remStr, orgLen, remLen, false, inputType == TSDB_DATA_TYPE_NCHAR);
×
743

744
  if (needFree) {
×
745
    taosMemoryFree(remStr);
×
746
  }
747

748
  (void)memcpy(varDataVal(output), orgStr, pos);
×
749
  varDataSetLen(output, pos);
×
750
  return TSDB_CODE_SUCCESS;
×
751
}
752

753
static int32_t tlrtrim(char *input, char *remInput, char *output, int32_t inputType, int32_t remType, void *charsetCxt) {
×
754
  int32_t orgLen = varDataLen(input);
×
755
  char   *orgStr = varDataVal(input);
×
756
  int32_t remLen = varDataLen(remInput);
×
757
  char   *remStr = varDataVal(remInput);
×
758
  if (orgLen == 0) {
×
759
    varDataSetLen(output, 0);
×
760
    return TSDB_CODE_SUCCESS;
×
761
  }
762

763
  bool    needFree = false;
×
764

765
  if (inputType != remType) {
×
766
    SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(remInput), &remStr, varDataLen(remInput), &remLen, inputType, charsetCxt));
×
767
    needFree = true;
×
768
  }
769

770
  if (remLen == 0 || remLen > orgLen) {
×
771
    (void)memcpy(varDataVal(output), orgStr, orgLen);
×
772
    varDataSetLen(output, orgLen);
×
773
    if (needFree) {
×
774
      taosMemoryFree(remStr);
×
775
    }
776
    return TSDB_CODE_SUCCESS;
×
777
  }
778

779
  int32_t leftPos = trimHelper(orgStr, remStr, orgLen, remLen, true, inputType == TSDB_DATA_TYPE_NCHAR);
×
780
  int32_t rightPos = trimHelper(orgStr, remStr, orgLen, remLen, false, inputType == TSDB_DATA_TYPE_NCHAR);
×
781

782
  if (needFree) {
×
783
    taosMemoryFree(remStr);
×
784
  }
785

786
  if (leftPos >= rightPos) {
×
787
    varDataSetLen(output, 0);
×
788
    return TSDB_CODE_SUCCESS;
×
789
  }
790
  (void)memcpy(varDataVal(output), orgStr + leftPos, rightPos - leftPos);
×
791
  varDataSetLen(output, rightPos - leftPos);
×
792
  return TSDB_CODE_SUCCESS;
×
793
}
794

795
static int32_t doLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _len_fn lenFn) {
10✔
796
  int32_t type = GET_PARAM_TYPE(pInput);
10✔
797

798
  SColumnInfoData *pInputData = pInput->columnData;
10✔
799
  SColumnInfoData *pOutputData = pOutput->columnData;
10✔
800

801
  int64_t *out = (int64_t *)pOutputData->pData;
10✔
802

803
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
80✔
804
    if (colDataIsNull_s(pInputData, i)) {
140✔
805
      colDataSetNULL(pOutputData, i);
6✔
806
      continue;
6✔
807
    }
808

809
    char *in = colDataGetData(pInputData, i);
64✔
810
    SCL_ERR_RET(lenFn(in, type, (VarDataLenT *)&(out[i])));
64✔
811
  }
812

813
  pOutput->numOfRows = pInput->numOfRows;
10✔
814
  return TSDB_CODE_SUCCESS;
10✔
815
}
816

817
static int32_t concatCopyHelper(const char *input, char *output, bool hasNchar, int32_t type, VarDataLenT *dataLen, void* charsetCxt) {
117,865✔
818
  if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) {
117,865✔
819
    TdUcs4 *newBuf = taosMemoryCalloc((varDataLen(input) + 1) * TSDB_NCHAR_SIZE, 1);
×
820
    if (NULL == newBuf) {
×
821
      return terrno;
×
822
    }
823
    int32_t len = varDataLen(input);
×
824
    bool    ret = taosMbsToUcs4(varDataVal(input), len, newBuf, (varDataLen(input) + 1) * TSDB_NCHAR_SIZE, &len, charsetCxt);
×
825
    if (!ret) {
×
826
      taosMemoryFree(newBuf);
×
827
      return TSDB_CODE_SCALAR_CONVERT_ERROR;
×
828
    }
829
    (void)memcpy(varDataVal(output) + *dataLen, newBuf, len);
×
830
    *dataLen += len;
×
831
    taosMemoryFree(newBuf);
×
832
  } else {
833
    (void)memcpy(varDataVal(output) + *dataLen, varDataVal(input), varDataLen(input));
117,865✔
834
    *dataLen += varDataLen(input);
117,865✔
835
  }
836
  return TSDB_CODE_SUCCESS;
117,865✔
837
}
838

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

852
int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
52,767✔
853
  int32_t           code = TSDB_CODE_SUCCESS;
52,767✔
854
  SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
52,767✔
855
  SColumnInfoData  *pOutputData = pOutput->columnData;
52,817✔
856
  char            **input = taosMemoryCalloc(inputNum, POINTER_BYTES);
52,817✔
857
  char             *outputBuf = NULL;
52,788✔
858

859
  if (NULL == pInputData) {
52,788✔
860
    SCL_ERR_JRET(terrno);
×
861
  }
862
  if (NULL == input) {
52,788✔
863
    SCL_ERR_JRET(terrno);
×
864
  }
865

866
  int32_t inputLen = 0;
52,788✔
867
  int32_t numOfRows = 0;
52,788✔
868
  bool    hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
52,788✔
869
  for (int32_t i = 0; i < inputNum; ++i) {
158,382✔
870
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
105,594✔
871
  }
872
  int32_t outputLen = VARSTR_HEADER_SIZE;
52,788✔
873
  for (int32_t i = 0; i < inputNum; ++i) {
158,382✔
874
    if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
105,594✔
875
      colDataSetNNULL(pOutputData, 0, numOfRows);
×
876
      pOutput->numOfRows = numOfRows;
×
877
      goto _return;
×
878
    }
879
    pInputData[i] = pInput[i].columnData;
105,594✔
880
    int32_t factor = 1;
105,594✔
881
    if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
105,594✔
882
      factor = TSDB_NCHAR_SIZE;
×
883
    }
884
    outputLen += pInputData[i]->info.bytes * factor;
105,594✔
885
  }
886

887
  outputBuf = taosMemoryCalloc(outputLen, 1);
52,788✔
888
  if (NULL == outputBuf) {
52,787✔
889
    SCL_ERR_JRET(terrno);
×
890
  }
891

892
  for (int32_t k = 0; k < numOfRows; ++k) {
111,646✔
893
    bool hasNull = false;
58,841✔
894
    for (int32_t i = 0; i < inputNum; ++i) {
176,532✔
895
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
235,394✔
896
        colDataSetNULL(pOutputData, k);
6✔
897
        hasNull = true;
6✔
898
        break;
6✔
899
      }
900
    }
901

902
    if (hasNull) {
58,841✔
903
      continue;
6✔
904
    }
905

906
    VarDataLenT dataLen = 0;
58,835✔
907
    char       *output = outputBuf;
58,835✔
908
    for (int32_t i = 0; i < inputNum; ++i) {
176,511✔
909
      int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
117,652✔
910
      input[i] = colDataGetData(pInputData[i], rowIdx);
117,652✔
911

912
      SCL_ERR_JRET(concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen, pInput->charsetCxt));
117,652✔
913
    }
914
    varDataSetLen(output, dataLen);
58,859✔
915
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, outputBuf, false));
58,859✔
916
  }
917

918
  pOutput->numOfRows = numOfRows;
52,805✔
919

920
_return:
52,805✔
921
  taosMemoryFree(input);
52,805✔
922
  taosMemoryFree(outputBuf);
52,792✔
923
  taosMemoryFree(pInputData);
52,813✔
924

925
  SCL_RET(code);
52,810✔
926
}
927

928
int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
9✔
929
  int32_t           code = TSDB_CODE_SUCCESS;
9✔
930
  SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
9✔
931
  SColumnInfoData  *pOutputData = pOutput->columnData;
9✔
932
  char             *outputBuf = NULL;
9✔
933

934
  if (NULL == pInputData) {
9✔
935
    SCL_ERR_JRET(terrno);
×
936
  }
937

938
  int32_t inputLen = 0;
9✔
939
  int32_t numOfRows = 0;
9✔
940
  bool    hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
9✔
941
  for (int32_t i = 0; i < inputNum; ++i) {
36✔
942
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
27✔
943
  }
944
  int32_t outputLen = VARSTR_HEADER_SIZE;
9✔
945
  for (int32_t i = 0; i < inputNum; ++i) {
36✔
946
    if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
27✔
947
      colDataSetNNULL(pOutputData, 0, numOfRows);
×
948
      pOutput->numOfRows = numOfRows;
×
949
      goto _return;
×
950
    }
951
    pInputData[i] = pInput[i].columnData;
27✔
952
    int32_t factor = 1;
27✔
953
    if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
27✔
954
      factor = TSDB_NCHAR_SIZE;
×
955
    }
956

957
    if (i == 0) {
27✔
958
      // calculate required separator space
959
      outputLen += pInputData[i]->info.bytes * factor * (inputNum - 2);
9✔
960
    } else {
961
      outputLen += pInputData[i]->info.bytes * factor;
18✔
962
    }
963
  }
964

965
  outputBuf = taosMemoryCalloc(outputLen, 1);
9✔
966
  if (NULL == outputBuf) {
9✔
967
    SCL_ERR_JRET(terrno);
×
968
  }
969

970
  for (int32_t k = 0; k < numOfRows; ++k) {
82✔
971
    if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) {
146✔
972
      colDataSetNULL(pOutputData, k);
×
973
      continue;
×
974
    }
975

976
    VarDataLenT dataLen = 0;
73✔
977
    bool        hasNull = false;
73✔
978
    char       *output = outputBuf;
73✔
979
    for (int32_t i = 1; i < inputNum; ++i) {
207✔
980
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
280✔
981
        hasNull = true;
6✔
982
        break;
6✔
983
      }
984

985
      int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
134✔
986

987
      SCL_ERR_JRET(concatCopyHelper(colDataGetData(pInputData[i], rowIdx), output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen, pInput->charsetCxt));
134✔
988

989
      if (i < inputNum - 1) {
134✔
990
        // insert the separator
991
        char *sep = (pInput[0].numOfRows == 1) ? colDataGetData(pInputData[0], 0) : colDataGetData(pInputData[0], k);
67✔
992
        SCL_ERR_JRET(concatCopyHelper(sep, output, hasNchar, GET_PARAM_TYPE(&pInput[0]), &dataLen, pInput->charsetCxt));
67✔
993
      }
994
    }
995

996
    if (hasNull) {
73✔
997
      colDataSetNULL(pOutputData, k);
6✔
998
      (void)memset(output, 0, dataLen);
6✔
999
    } else {
1000
      varDataSetLen(output, dataLen);
67✔
1001
      SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
67✔
1002
    }
1003
  }
1004

1005
  pOutput->numOfRows = numOfRows;
9✔
1006

1007
_return:
9✔
1008
  taosMemoryFree(outputBuf);
9✔
1009
  taosMemoryFree(pInputData);
9✔
1010

1011
  return code;
9✔
1012
}
1013

1014
static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _conv_fn convFn) {
12✔
1015
  int32_t type = GET_PARAM_TYPE(pInput);
12✔
1016

1017
  SColumnInfoData *pInputData = pInput->columnData;
12✔
1018
  SColumnInfoData *pOutputData = pOutput->columnData;
12✔
1019

1020
  int32_t outputLen = pInputData->varmeta.length;
12✔
1021
  char   *outputBuf = taosMemoryCalloc(outputLen, 1);
12✔
1022
  if (outputBuf == NULL) {
12✔
1023
    SCL_ERR_RET(terrno);
×
1024
  }
1025

1026
  char   *output = outputBuf;
12✔
1027

1028
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
144✔
1029
    if (colDataIsNull_s(pInputData, i)) {
264✔
1030
      colDataSetNULL(pOutputData, i);
12✔
1031
      continue;
12✔
1032
    }
1033

1034
    char   *input = colDataGetData(pInput[0].columnData, i);
120✔
1035
    int32_t len = varDataLen(input);
120✔
1036
    if (type == TSDB_DATA_TYPE_VARCHAR) {
120✔
1037
      for (int32_t j = 0; j < len; ++j) {
1,560✔
1038
        *(varDataVal(output) + j) = convFn(*(varDataVal(input) + j));
1,440✔
1039
      }
1040
    } else {  // NCHAR
1041
      for (int32_t j = 0; j < len / TSDB_NCHAR_SIZE; ++j) {
×
1042
        *((uint32_t *)varDataVal(output) + j) = convFn(*((uint32_t *)varDataVal(input) + j));
×
1043
      }
1044
    }
1045
    varDataSetLen(output, len);
120✔
1046
    int32_t code = colDataSetVal(pOutputData, i, output, false);
120✔
1047
    if (TSDB_CODE_SUCCESS != code) {
120✔
1048
      taosMemoryFree(outputBuf);
×
1049
      SCL_ERR_RET(code);
×
1050
    }
1051
    output += varDataTLen(output);
120✔
1052
  }
1053

1054
  pOutput->numOfRows = pInput->numOfRows;
12✔
1055
  taosMemoryFree(outputBuf);
12✔
1056

1057
  return TSDB_CODE_SUCCESS;
12✔
1058
}
1059

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

1080
  char   *output = outputBuf;
12✔
1081

1082
  if (inputNum == 3) {
12✔
1083
    bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
×
1084

1085
    if (hasNullType ||
×
1086
        (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
×
1087
        (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0))) {
×
1088
      colDataSetNNULL(pOutputData, 0, numOfRows);
×
1089
    }
1090

1091
    for (int32_t i = 0; i < numOfRows; ++i) {
×
1092
      int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
×
1093
      int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
×
1094
      if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2)) {
×
1095
        colDataSetNULL(pOutputData, i);
×
1096
        continue;
×
1097
      }
1098
      SCL_ERR_JRET(trimFn(colDataGetData(pInputData[1], colIdx2), colDataGetData(pInputData[0], colIdx1),
×
1099
                          output, GET_PARAM_TYPE(&pInput[1]), GET_PARAM_TYPE(&pInput[0]), pInput->charsetCxt));
1100
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
×
1101
    }
1102
  } else {
1103
    for (int32_t i = 0; i < numOfRows; ++i) {
144✔
1104
      if (colDataIsNull_s(pInputData[0], i)) {
264✔
1105
        colDataSetNULL(pOutputData, i);
12✔
1106
        continue;
12✔
1107
      }
1108
      int32_t type = GET_PARAM_TYPE(pInput);
120✔
1109
      char   *input = colDataGetData(pInputData[0], i);
120✔
1110
      int32_t len = varDataLen(input);
120✔
1111
      int32_t charLen = (type == TSDB_DATA_TYPE_VARCHAR) ? len : len / TSDB_NCHAR_SIZE;
120✔
1112
      trimSpaceFn(input, output, type, charLen, pInput->charsetCxt);
120✔
1113
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, output, false));
120✔
1114
    }
1115
  }
1116
  pOutput->numOfRows = numOfRows;
12✔
1117
_return:
12✔
1118
  taosMemoryFree(outputBuf);
12✔
1119
  return code;
12✔
1120
}
1121

1122
static int32_t findPosBytes(char *orgStr, char *delimStr, int32_t orgLen, int32_t delimLen, int32_t charNums, bool isNchar) {
120✔
1123
  int32_t charCount = 0;
120✔
1124
  if (charNums > 0) {
120✔
1125
    for (int32_t pos = 0; pos < orgLen; pos++) {
360✔
1126
      if (delimStr) {
360✔
1127
        if (pos + delimLen > orgLen)  {
×
1128
          return orgLen;
×
1129
        }
1130
        if ((isCharStart(orgStr[pos]) || isNchar) && memcmp(orgStr + pos, delimStr, delimLen) == 0) {
×
1131
          charCount++;
×
1132
          if (charCount == charNums) {
×
1133
            return pos;
×
1134
          }
1135
          pos = pos + delimLen - 1;
×
1136
        }
1137
      } else {
1138
        if ((isCharStart(orgStr[pos]) || isNchar)) {
360✔
1139
          charCount++;
360✔
1140
          if (charCount == charNums) {
360✔
1141
            return pos;
120✔
1142
          }
1143
        }
1144
      }
1145
    }
1146
    return orgLen;
×
1147
  } else {
1148
    if (delimStr) {
×
1149
      for (int32_t pos = orgLen - delimLen; pos >= 0; pos--) {
×
1150
        if ((isCharStart(orgStr[pos]) || isNchar) && memcmp(orgStr + pos, delimStr, delimLen) == 0) {
×
1151
          charCount++;
×
1152
          if (charCount == -charNums) {
×
1153
            return pos + delimLen;
×
1154
          }
1155
          pos = pos - delimLen + 1;
×
1156
        }
1157
      }
1158
    } else {
1159
      for (int32_t pos = orgLen - 1; pos >= 0; pos--) {
×
1160
        if ((isCharStart(orgStr[pos]) || isNchar)) {
×
1161
          charCount++;
×
1162
          if (charCount == -charNums) {
×
1163
            return pos;
×
1164
          }
1165
        }
1166
      }
1167
    }
1168
    return 0;
×
1169
  }
1170
}
1171

1172
int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
1173
  int32_t code = TSDB_CODE_SUCCESS;
6✔
1174
  SColumnInfoData *pInputData[3];
1175
  SColumnInfoData *pOutputData = pOutput->columnData;
6✔
1176

1177
  for (int32_t i = 0; i < inputNum; ++i) {
24✔
1178
    pInputData[i] = pInput[i].columnData;
18✔
1179
  }
1180

1181
  int32_t outputLen = pInputData[0]->info.bytes;
6✔
1182
  char *outputBuf = taosMemoryMalloc(outputLen);
6✔
1183
  if (outputBuf == NULL) {
6✔
1184
    qError("substr function memory allocation failure. size: %d", outputLen);
×
1185
    return terrno;
×
1186
  }
1187

1188
  int32_t numOfRows = 0;
6✔
1189
  for (int32_t i = 0; i < inputNum; ++i) {
24✔
1190
    numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
18✔
1191
  }
1192

1193
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])) ||
12✔
1194
                      (inputNum == 3 && IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[2]))));
6✔
1195

1196
  if (hasNullType ||
6✔
1197
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
6✔
1198
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0)) ||
12✔
1199
      (inputNum == 3 && (pInput[2].numOfRows == 1 && colDataIsNull_s(pInputData[2], 0)))) {
12✔
1200
    colDataSetNNULL(pOutputData, 0, numOfRows);
×
1201
    pOutput->numOfRows = numOfRows;
×
1202
    goto _return;
×
1203
  }
1204

1205
  int32_t colIdx[3];
1206
  for (int32_t i = 0; i < numOfRows; ++i) {
72✔
1207
    colIdx[0] = (pInput[0].numOfRows == 1) ? 0 : i;
66✔
1208
    colIdx[1] = (pInput[1].numOfRows == 1) ? 0 : i;
66✔
1209
    if (inputNum == 3) {
66✔
1210
      colIdx[2] = (pInput[2].numOfRows == 1) ? 0 : i;
66✔
1211
    }
1212

1213
    if (colDataIsNull_s(pInputData[0], colIdx[0]) || colDataIsNull_s(pInputData[1], colIdx[1]) ||
192✔
1214
        (inputNum == 3 && colDataIsNull_s(pInputData[2], colIdx[2]))) {
120✔
1215
      colDataSetNULL(pOutputData, i);
6✔
1216
      continue;
6✔
1217
    }
1218

1219
    int32_t subPos = 0;
60✔
1220
    int32_t subLen = INT16_MAX;
60✔
1221
    GET_TYPED_DATA(subPos, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], colIdx[1]), typeGetTypeModFromColInfo(&pInput[1].columnData->info));
60✔
1222
    if (inputNum == 3) {
60✔
1223
      GET_TYPED_DATA(subLen, int32_t, GET_PARAM_TYPE(&pInput[2]), colDataGetData(pInputData[2], colIdx[2]), typeGetTypeModFromColInfo(&pInput[2].columnData->info));
60✔
1224
    }
1225

1226
    if (subPos == 0 || subLen < 1) {
60✔
1227
      varDataSetLen(outputBuf, 0);
×
1228
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1229
      continue;
×
1230
    }
1231

1232
    char   *input = colDataGetData(pInputData[0], colIdx[0]);
60✔
1233
    int32_t len = varDataLen(input);
60✔
1234
    int32_t startPosBytes;
1235
    int32_t endPosBytes = len;
60✔
1236
    if (subPos > 0) {
60✔
1237
      startPosBytes = (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR) ? findPosBytes(varDataVal(input), NULL, varDataLen(input), -1, subPos, false) : (subPos - 1) * TSDB_NCHAR_SIZE;
60✔
1238
      startPosBytes = TMIN(startPosBytes, len);
60✔
1239
    } else {
1240
      startPosBytes =
×
1241
          (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR) ? findPosBytes(varDataVal(input), NULL, varDataLen(input), -1, subPos, false) : len + subPos * TSDB_NCHAR_SIZE;
×
1242
      startPosBytes = TMAX(startPosBytes, 0);
×
1243
    }
1244
    if (inputNum == 3) {
60✔
1245
      endPosBytes =
120✔
1246
          (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_VARCHAR)
60✔
1247
              ? startPosBytes + findPosBytes(varDataVal(input) + startPosBytes, NULL, varDataLen(input) - startPosBytes, -1, subLen + 1, false)
60✔
1248
              : startPosBytes + subLen * TSDB_NCHAR_SIZE;
×
1249
      endPosBytes = TMIN(endPosBytes, len);
60✔
1250
    }
1251

1252
    char   *output = outputBuf;
60✔
1253
    int32_t resLen = endPosBytes - startPosBytes;
60✔
1254
    if (resLen > 0) {
60✔
1255
      (void)memcpy(varDataVal(output), varDataVal(input) + startPosBytes, resLen);
60✔
1256
      varDataSetLen(output, resLen);
60✔
1257
    } else {
1258
      varDataSetLen(output, 0);
×
1259
    }
1260

1261
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
60✔
1262
  }
1263

1264
  pOutput->numOfRows = numOfRows;
6✔
1265
_return:
6✔
1266
  taosMemoryFree(outputBuf);
6✔
1267

1268
  return code;
6✔
1269
}
1270

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

1304
  }
1305
  pOutput->numOfRows = pInput->numOfRows;
×
1306
  taosMemoryFree(pOutputBuf);
×
1307
  return TSDB_CODE_SUCCESS;
×
1308
}
1309

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

1370
_return:
×
1371
  taosMemoryFree(outputBuf);
×
1372
  return code;
×
1373
}
1374

1375
int32_t asciiFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1376
  int32_t type = GET_PARAM_TYPE(pInput);
×
1377

1378
  SColumnInfoData *pInputData = pInput->columnData;
×
1379
  SColumnInfoData *pOutputData = pOutput->columnData;
×
1380

1381
  uint8_t *out = (uint8_t *)pOutputData->pData;
×
1382

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

1402
  pOutput->numOfRows = pInput->numOfRows;
×
1403
  return TSDB_CODE_SUCCESS;
×
1404
}
1405

1406
static int32_t findPosChars(char *orgStr, char *delimStr, int32_t orgLen, int32_t delimLen, bool isNchar) {
×
1407
  int32_t charCount = 0;
×
1408
  for (int32_t pos = 0; pos < orgLen; pos += isNchar ? TSDB_NCHAR_SIZE : 1) {
×
1409
    if (isNchar || isCharStart(orgStr[pos])) {
×
1410
      if (pos + delimLen > orgLen) {
×
1411
        return 0;
×
1412
      }
1413
      if (memcmp(orgStr + pos, delimStr, delimLen) == 0) {
×
1414
        return charCount + 1;
×
1415
      } else {
1416
        charCount++;
×
1417
      }
1418
    }
1419
  }
1420
  return 0;
×
1421
}
1422

1423
int32_t positionFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1424
  int32_t          code = TSDB_CODE_SUCCESS;
×
1425
  int32_t          numOfRows = 0;
×
1426
  SColumnInfoData *pInputData[2];
1427
  SColumnInfoData *pOutputData = pOutput[0].columnData;
×
1428

1429
  pInputData[0] = pInput[0].columnData;
×
1430
  pInputData[1] = pInput[1].columnData;
×
1431
  numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
×
1432

1433
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
×
1434

1435
  if (hasNullType ||
×
1436
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
×
1437
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0))) {
×
1438
    colDataSetNNULL(pOutputData, 0, numOfRows);
×
1439
  }
1440

1441
  for (int32_t i = 0; i < numOfRows; ++i) {
×
1442
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
×
1443
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
×
1444
    if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2)) {
×
1445
      colDataSetNULL(pOutputData, i);
×
1446
      continue;
×
1447
    }
1448
    int64_t offset = 0;
×
1449
    if (varDataLen(colDataGetData(pInputData[0], colIdx1)) == 0) {
×
1450
      offset = 1;
×
1451
      colDataSetInt64(pOutputData, i, &offset);
×
1452
      continue;
×
1453
    }
1454

1455
    char   *substr = varDataVal(colDataGetData(pInputData[0], colIdx1));
×
1456
    char   *orgstr = varDataVal(colDataGetData(pInputData[1], colIdx2));
×
1457
    int32_t subLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
×
1458
    int32_t orgLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
×
1459
    bool    needFreeSub = false;
×
1460
    if (GET_PARAM_TYPE(&pInput[1]) != GET_PARAM_TYPE(&pInput[0])) {
×
1461
      SCL_ERR_RET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[0], colIdx1)), &substr,
×
1462
                                             varDataLen(colDataGetData(pInputData[0], colIdx1)), &subLen,
1463
                                             GET_PARAM_TYPE(&pInput[1]), pInput->charsetCxt));
1464
      needFreeSub = true;
×
1465
    }
1466

1467
    offset = findPosChars(orgstr, substr, orgLen, subLen, GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NCHAR);
×
1468
    if (needFreeSub) {
×
1469
      taosMemoryFree(substr);
×
1470
    }
1471
    colDataSetInt64(pOutput->columnData, i, &offset);
×
1472
  }
1473

1474
  pOutput->numOfRows = numOfRows;
×
1475
  return code;
×
1476
}
1477

1478
int32_t trimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1479
  // trim space
1480
  uint8_t trimType = 0;
×
1481
  GET_TYPED_DATA(trimType, int32_t, GET_PARAM_TYPE(&pInput[inputNum - 1]), pInput[inputNum - 1].columnData->pData,
×
1482
                 typeGetTypeModFromColInfo(&pInput[inputNum - 1].columnData->info));
1483
  switch (trimType) {
×
1484
    case TRIM_TYPE_LEADING: {
×
1485
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, tltrimspace, tltrim));
×
1486
      break;
×
1487
    }
1488
    case TRIM_TYPE_TRAILING: {
×
1489
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, trtrimspace, trtrim));
×
1490
      break;
×
1491
    }
1492
    case TRIM_TYPE_BOTH: {
×
1493
      SCL_ERR_RET(doTrimFunction(pInput, inputNum, pOutput, tlrtrimspace, tlrtrim));
×
1494
      break;
×
1495
    }
1496
  }
1497
  return TSDB_CODE_SUCCESS;
×
1498
}
1499

1500
int32_t replaceFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1501
  int32_t          code = TSDB_CODE_SUCCESS;
×
1502
  SColumnInfoData *pInputData[3];
1503
  SColumnInfoData *pOutputData = pOutput[0].columnData;
×
1504
  int32_t          outputLen;
1505
  int32_t          numOfRows = 0;
×
1506

1507
  pInputData[0] = pInput[0].columnData;
×
1508
  pInputData[1] = pInput[1].columnData;
×
1509
  pInputData[2] = pInput[2].columnData;
×
1510

1511
  for (int i = 0; i < 3; i++) {
×
1512
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
×
1513
  }
1514

1515
  int8_t  orgType = pInputData[0]->info.type;
×
1516
  int8_t  toType = pInputData[2]->info.type;
×
1517
  int32_t orgLength = pInputData[0]->info.bytes - VARSTR_HEADER_SIZE;
×
1518
  int32_t toLength = pInputData[2]->info.bytes - VARSTR_HEADER_SIZE;
×
1519

1520
  if (orgType == TSDB_DATA_TYPE_NCHAR && toType != orgType) {
×
1521
    toLength = toLength * TSDB_NCHAR_SIZE;
×
1522
  }
1523
  outputLen = toLength == 0 ? orgLength : TMIN(TSDB_MAX_FIELD_LEN, orgLength * toLength);
×
1524

1525
  if (GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NULL ||
×
1526
      GET_PARAM_TYPE(&pInput[1]) == TSDB_DATA_TYPE_NULL ||
×
1527
      GET_PARAM_TYPE(&pInput[2]) == TSDB_DATA_TYPE_NULL ||
×
1528
      (pInput[0].numOfRows == 1 && colDataIsNull_s(pInputData[0], 0)) ||
×
1529
      (pInput[1].numOfRows == 1 && colDataIsNull_s(pInputData[1], 0)) ||
×
1530
      (pInput[2].numOfRows == 1 && colDataIsNull_s(pInputData[2], 0))) {
×
1531
    colDataSetNNULL(pOutputData, 0, numOfRows);
×
1532
    pOutput->numOfRows = numOfRows;
×
1533
    return TSDB_CODE_SUCCESS;
×
1534
  }
1535

1536
  char *outputBuf = taosMemoryCalloc(outputLen + VARSTR_HEADER_SIZE, 1);
×
1537
  if (NULL == outputBuf) {
×
1538
    SCL_ERR_RET(terrno);
×
1539
  }
1540

1541
  for (int32_t i = 0; i < numOfRows; ++i) {
×
1542
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
×
1543
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
×
1544
    int32_t colIdx3 = (pInput[2].numOfRows == 1) ? 0 : i;
×
1545
    if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2) || colDataIsNull_s(pInputData[2], colIdx3)) {
×
1546
      colDataSetNULL(pOutputData, i);
×
1547
      continue;
×
1548
    }
1549
    char   *output = outputBuf + VARSTR_HEADER_SIZE;
×
1550
    int32_t totalLen = 0;
×
1551

1552
    char   *orgStr = varDataVal(colDataGetData(pInputData[0], colIdx1));
×
1553
    int32_t orgLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
×
1554
    char   *fromStr = varDataVal(colDataGetData(pInputData[1], colIdx2));
×
1555
    int32_t fromLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
×
1556
    char   *toStr = varDataVal(colDataGetData(pInputData[2], colIdx3));
×
1557
    int32_t toLen = varDataLen(colDataGetData(pInputData[2], colIdx3));
×
1558
    bool    needFreeFrom = false;
×
1559
    bool    needFreeTo = false;
×
1560

1561
    if (fromLen == 0 || orgLen == 0) {
×
1562
      (void)memcpy(output, orgStr, orgLen);
×
1563
      totalLen = orgLen;
×
1564
      varDataSetLen(outputBuf, totalLen);
×
1565
      SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1566
      continue;
×
1567
    }
1568

1569
    if (GET_PARAM_TYPE(&pInput[1]) != GET_PARAM_TYPE(&pInput[0])) {
×
1570
      SCL_ERR_JRET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[1], colIdx2)), &fromStr,
×
1571
                                             varDataLen(colDataGetData(pInputData[1], colIdx2)), &fromLen,
1572
                                             GET_PARAM_TYPE(&pInput[0]), pInput->charsetCxt));
1573
      needFreeFrom = true;
×
1574
    }
1575
    if (GET_PARAM_TYPE(&pInput[2]) != GET_PARAM_TYPE(&pInput[0])) {
×
1576
      code = convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[2], colIdx3)), &toStr,
×
1577
                                        varDataLen(colDataGetData(pInputData[2], colIdx3)), &toLen,
×
1578
                                        GET_PARAM_TYPE(&pInput[0]), pInput->charsetCxt);
×
1579
      if (TSDB_CODE_SUCCESS != code) {
×
1580
        if (needFreeFrom) {
×
1581
          taosMemoryFree(fromStr);
×
1582
        }
1583
        goto _return;
×
1584
      }
1585
      needFreeTo = true;
×
1586
    }
1587

1588
    int32_t pos = 0;
×
1589
    while (pos < orgLen) {
×
1590
      if (orgLen - pos < fromLen) {
×
1591
        (void)memcpy(output, orgStr + pos, orgLen - pos);
×
1592
        output += orgLen - pos;
×
1593
        totalLen += orgLen - pos;
×
1594
        break;
×
1595
      }
1596
      if (memcmp(orgStr + pos, fromStr, fromLen) == 0 &&
×
1597
          (pos + fromLen == orgLen ||
×
1598
           isCharStart(orgStr[pos + fromLen]) ||
×
1599
           GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR)) {
×
1600
        (void)memcpy(output, toStr, toLen);
×
1601
        output += toLen;
×
1602
        pos += fromLen;
×
1603
        totalLen += toLen;
×
1604
      } else {
1605
        int32_t charLen = GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR ? TSDB_NCHAR_SIZE : getCharLen(orgStr + pos);
×
1606
        (void)memcpy(output, orgStr + pos, charLen);
×
1607
        output += charLen;
×
1608
        totalLen += charLen;
×
1609
        pos += charLen;
×
1610
      }
1611
    }
1612
    if (needFreeTo) {
×
1613
      taosMemoryFree(toStr);
×
1614
    }
1615
    if (needFreeFrom) {
×
1616
      taosMemoryFree(fromStr);
×
1617
    }
1618
    if (totalLen > TSDB_MAX_FIELD_LEN) {
×
1619
      SCL_ERR_JRET(TSDB_CODE_FUNC_INVALID_RES_LENGTH);
×
1620
    }
1621
    varDataSetLen(outputBuf, totalLen);
×
1622
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1623
  }
1624
  pOutput->numOfRows = numOfRows;
×
1625
_return:
×
1626
  taosMemoryFree(outputBuf);
×
1627
  return code;
×
1628
}
1629

1630
int32_t substrIdxFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1631
  int32_t          code = TSDB_CODE_SUCCESS;
×
1632
  SColumnInfoData *pInputData[3];
1633
  SColumnInfoData *pOutputData = pOutput[0].columnData;
×
1634
  int32_t          outputLen;
1635
  int32_t          numOfRows = 0;
×
1636

1637
  pInputData[0] = pInput[0].columnData;
×
1638
  pInputData[1] = pInput[1].columnData;
×
1639
  pInputData[2] = pInput[2].columnData;
×
1640

1641
  for (int32_t i = 0; i < inputNum; ++i) {
×
1642
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
×
1643
  }
1644

1645
  outputLen = pInputData[0]->info.bytes;
×
1646
  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) {
×
1647
    colDataSetNNULL(pOutputData, 0, numOfRows);
×
1648
    pOutput->numOfRows = numOfRows;
×
1649
    return TSDB_CODE_SUCCESS;
×
1650
  }
1651
  char *outputBuf = taosMemoryCalloc(outputLen + VARSTR_HEADER_SIZE, 1);
×
1652
  if (NULL == outputBuf) {
×
1653
    SCL_ERR_RET(terrno);
×
1654
  }
1655

1656
  for (int32_t k = 0; k < numOfRows; ++k) {
×
1657
    bool hasNull = false;
×
1658
    for (int32_t i = 0; i < inputNum; ++i) {
×
1659
      if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
×
1660
        colDataSetNULL(pOutputData, k);
×
1661
        hasNull = true;
×
1662
        break;
×
1663
      }
1664
    }
1665
    if (hasNull) {
×
1666
      continue;
×
1667
    }
1668

1669
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : k;
×
1670
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : k;
×
1671
    int32_t count = 0;
×
1672
    char   *orgStr = varDataVal(colDataGetData(pInputData[0], colIdx1));
×
1673
    int32_t orgLen = varDataLen(colDataGetData(pInputData[0], colIdx1));
×
1674
    char   *delimStr = varDataVal(colDataGetData(pInputData[1], colIdx2));
×
1675
    int32_t delimLen = varDataLen(colDataGetData(pInputData[1], colIdx2));
×
1676
    bool    needFreeDelim = false;
×
1677
    GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[2]),
×
1678
                   colDataGetData(pInputData[2], (pInput[2].numOfRows == 1) ? 0 : k),
1679
                   typeGetTypeModFromColInfo(&pInputData[2]->info));
1680

1681
    int32_t startPosBytes;
1682
    int32_t endPosBytes;
1683
    if (GET_PARAM_TYPE(&pInput[0]) != GET_PARAM_TYPE(&pInput[1])) {
×
1684
      SCL_ERR_JRET(convBetweenNcharAndVarchar(varDataVal(colDataGetData(pInputData[1], colIdx2)), &delimStr,
×
1685
                                              varDataLen(colDataGetData(pInputData[1], colIdx2)), &delimLen,
1686
                                              GET_PARAM_TYPE(&pInput[0]), pInput->charsetCxt));
1687
      needFreeDelim = true;
×
1688
    }
1689

1690
    if (count > 0) {
×
1691
      startPosBytes = 0;
×
1692
      endPosBytes = findPosBytes(orgStr, delimStr, orgLen, delimLen, count, GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR);
×
1693
    } else if (count < 0) {
×
1694
      startPosBytes = findPosBytes(orgStr, delimStr, orgLen, delimLen, count, GET_PARAM_TYPE(&pInput[0]) == TSDB_DATA_TYPE_NCHAR);
×
1695
      endPosBytes = orgLen;
×
1696
    } else {
1697
      startPosBytes = endPosBytes = 0;
×
1698
    }
1699

1700
    char   *output = outputBuf;
×
1701
    int32_t resLen = endPosBytes - startPosBytes;
×
1702
    if (resLen > 0) {
×
1703
      (void)memcpy(varDataVal(output), orgStr + startPosBytes, resLen);
×
1704
      varDataSetLen(output, resLen);
×
1705
    } else {
1706
      varDataSetLen(output, 0);
×
1707
    }
1708
    if (needFreeDelim) {
×
1709
      taosMemoryFree(delimStr);
×
1710
    }
1711

1712
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
×
1713
  }
1714
  pOutput->numOfRows = numOfRows;
×
1715
_return:
×
1716
  taosMemoryFree(outputBuf);
×
1717
  return code;
×
1718
}
1719

1720
static char base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1721
                            "abcdefghijklmnopqrstuvwxyz"
1722
                            "0123456789+/";
1723

1724
static void base64Impl(uint8_t *base64Out, const uint8_t *inputBytes, size_t inputLen, VarDataLenT outputLen) {
×
1725
  for (size_t i = 0, j = 0; i < inputLen;) {
×
1726
    unsigned int octet_a = i < inputLen ? inputBytes[i++] : 0;
×
1727
    unsigned int octet_b = i < inputLen ? inputBytes[i++] : 0;
×
1728
    unsigned int octet_c = i < inputLen ? inputBytes[i++] : 0;
×
1729

1730
    unsigned int triple = (octet_a << 16) | (octet_b << 8) | octet_c;
×
1731

1732
    base64Out[j++] = base64Table[(triple >> 18) & 0x3F];
×
1733
    base64Out[j++] = base64Table[(triple >> 12) & 0x3F];
×
1734
    base64Out[j++] = base64Table[(triple >> 6) & 0x3F];
×
1735
    base64Out[j++] = base64Table[triple & 0x3F];
×
1736
  }
1737

1738
  for (int k = 0; k < (3 - (inputLen % 3)) % 3; k++) {
×
1739
    base64Out[outputLen - k - 1] = '=';
×
1740
  }
1741

1742
  base64Out[outputLen] = 0;
×
1743
}
×
1744

1745
uint32_t base64BufSize(size_t inputLenBytes) {
×
1746
  return 4 * ((inputLenBytes + 2) / 3);
×
1747
}
1748

1749
int32_t base64Function(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
×
1750
  int32_t code = TSDB_CODE_SUCCESS;
×
1751
  SColumnInfoData *pInputData = pInput->columnData;
×
1752
  SColumnInfoData *pOutputData = pOutput->columnData;
×
1753
  char *outputBuf = taosMemoryMalloc(TSDB_MAX_FIELD_LEN + VARSTR_HEADER_SIZE);
×
1754
  if (outputBuf == NULL) {
×
1755
    SCL_ERR_RET(terrno);
×
1756
  }
1757
  
1758
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
1759
    if (colDataIsNull_s(pInputData, i)) {
×
1760
      colDataSetNULL(pOutputData, i);
×
1761
      continue;
×
1762
    }
1763

1764
    char *input = colDataGetData(pInputData, i);
×
1765
    size_t inputLen = varDataLen(colDataGetData(pInputData, i));
×
1766
    char *out = outputBuf + VARSTR_HEADER_SIZE;
×
1767
    VarDataLenT outputLength = base64BufSize(inputLen);
×
1768
    base64Impl(out, varDataVal(input), inputLen, outputLength);
×
1769
    varDataSetLen(outputBuf, outputLength);
×
1770
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1771
  }
1772

1773
  pOutput->numOfRows = pInput->numOfRows;
×
1774
_return:
×
1775
  taosMemoryFree(outputBuf);
×
1776
  return code;
×
1777
}
1778

1779
static int32_t repeatStringHelper(char *input, int32_t inputLen, int32_t count, char *output) {
×
1780
  for (int32_t i = 0; i < count; ++i) {
×
1781
    (void)memcpy(output, input, inputLen);
×
1782
    output += inputLen;
×
1783
  }
1784
  return TSDB_CODE_SUCCESS;
×
1785
}
1786

1787
int32_t repeatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
1788
  int32_t          code = TSDB_CODE_SUCCESS;
×
1789
  SColumnInfoData *pInputData[2];
1790
  SColumnInfoData *pOutputData = pOutput[0].columnData;
×
1791
  int32_t          outputLen;
1792
  int32_t          numOfRows;
1793
  int32_t          maxCount = 0;
×
1794

1795
  for (int32_t i = 0; i < pInput[1].numOfRows; i++) {
×
1796
    int32_t tmpCount = 0;
×
1797
    if (colDataIsNull_s(pInput[1].columnData, i)) {
×
1798
      continue;
×
1799
    }
1800
    GET_TYPED_DATA(tmpCount, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i),
×
1801
                   typeGetTypeModFromColInfo(&pInput[1].columnData->info));
1802
    maxCount = TMAX(maxCount, tmpCount);
×
1803
  }
1804
  pInputData[0] = pInput[0].columnData;
×
1805
  pInputData[1] = pInput[1].columnData;
×
1806
  outputLen = (int32_t)(pInputData[0]->info.bytes * maxCount + VARSTR_HEADER_SIZE);
×
1807
  if (outputLen > TSDB_MAX_FIELD_LEN) {
×
1808
    return TSDB_CODE_FUNC_INVALID_RES_LENGTH;
×
1809
  }
1810
  numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
×
1811
  char *outputBuf = taosMemoryCalloc(outputLen, 1);
×
1812
  if (outputBuf == NULL) {
×
1813
    SCL_ERR_RET(terrno);
×
1814
  }
1815

1816
  char   *output = outputBuf;
×
1817

1818
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
×
1819
  if (pInput[0].numOfRows == pInput[1].numOfRows) {
×
1820
    for (int32_t i = 0; i < numOfRows; ++i) {
×
1821
      output = outputBuf;
×
1822
      if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) {
×
1823
        colDataSetNULL(pOutputData, i);
×
1824
        continue;
×
1825
      }
1826
      int32_t count = 0;
×
1827
      GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i),
×
1828
                     typeGetTypeModFromColInfo(&pInput[1].columnData->info));
1829
      if (count <= 0) {
×
1830
        varDataSetLen(output, 0);
×
1831
        SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1832
      } else {
1833
        char   *orgStr = colDataGetData(pInputData[0], i);
×
1834
        varDataSetLen(output, varDataLen(orgStr) * count);
×
1835
        SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
×
1836
        SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1837
      }
1838
    }
1839
  } else if (pInput[0].numOfRows == 1) {
×
1840
    if (colDataIsNull_s(pInputData[0], 0) || hasNullType) {
×
1841
      colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows);
×
1842
    } else {
1843
      for (int32_t i = 0; i < numOfRows; ++i) {
×
1844
        output = outputBuf;
×
1845
        if (colDataIsNull_s(pInputData[1], i)) {
×
1846
          colDataSetNULL(pOutputData, i);
×
1847
          continue;
×
1848
        }
1849
        int32_t count = 0;
×
1850
        GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, i),
×
1851
                       typeGetTypeModFromColInfo(&pInput[1].columnData->info));
1852
        if (count <= 0) {
×
1853
          varDataSetLen(output, 0);
×
1854
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1855
        } else {
1856
          char   *orgStr = colDataGetData(pInputData[0], 0);
×
1857
          varDataSetLen(output, varDataLen(orgStr) * count);
×
1858
          SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
×
1859
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1860
        }
1861
      }
1862
    }
1863
  } else if (pInput[1].numOfRows == 1) {
×
1864
    if (colDataIsNull_s(pInputData[1], 0) || hasNullType) {
×
1865
      colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows);
×
1866
    } else {
1867
      for (int32_t i = 0; i < numOfRows; ++i) {
×
1868
        output = outputBuf;
×
1869
        if (colDataIsNull_s(pInputData[0], i)) {
×
1870
          colDataSetNULL(pOutputData, i);
×
1871
          continue;
×
1872
        }
1873
        int32_t count = 0;
×
1874
        GET_TYPED_DATA(count, int32_t, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInput[1].columnData, 0),
×
1875
                       typeGetTypeModFromColInfo(&pInput[1].columnData->info));
1876
        if (count <= 0) {
×
1877
          varDataSetLen(output, 0);
×
1878
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1879
        } else {
1880
          char   *orgStr = colDataGetData(pInputData[0], i);
×
1881
          varDataSetLen(output, varDataLen(orgStr) * count);
×
1882
          SCL_ERR_JRET(repeatStringHelper(varDataVal(orgStr), varDataLen(orgStr), count, varDataVal(output)));
×
1883
          SCL_ERR_JRET(colDataSetVal(pOutputData, i, outputBuf, false));
×
1884
        }
1885
      }
1886
    }
1887
  }
1888

1889
  pOutput->numOfRows = numOfRows;
×
1890
_return:
×
1891
  taosMemoryFree(outputBuf);
×
1892
  return code;
×
1893
}
1894

1895
/** Conversion functions **/
1896
int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
48✔
1897
  int16_t inputType = GET_PARAM_TYPE(&pInput[0]);
48✔
1898
  int32_t inputLen = GET_PARAM_BYTES(&pInput[0]);
48✔
1899
  int16_t outputType = GET_PARAM_TYPE(&pOutput[0]);
48✔
1900
  int64_t outputLen = GET_PARAM_BYTES(&pOutput[0]);
48✔
1901

1902
  int32_t code = TSDB_CODE_SUCCESS;
48✔
1903
  char   *convBuf = taosMemoryMalloc(inputLen);
48✔
1904
  char   *output = taosMemoryCalloc(1, outputLen + TSDB_NCHAR_SIZE);
48✔
1905
  int32_t bufSize = TSDB_MAX_FIELD_LEN + 1;
48✔
1906
  char   *buf = taosMemoryMalloc(bufSize);
48✔
1907

1908
  if (convBuf == NULL || output == NULL || buf == NULL) {
48✔
1909
    code = terrno;
×
1910
    goto _end;
×
1911
  }
1912

1913
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
96✔
1914
    if (colDataIsNull_s(pInput[0].columnData, i)) {
96✔
1915
      colDataSetNULL(pOutput->columnData, i);
×
1916
      continue;
×
1917
    }
1918

1919
    char *input = colDataGetData(pInput[0].columnData, i);
48✔
1920

1921
    switch (outputType) {
48✔
1922
      case TSDB_DATA_TYPE_TINYINT: {
×
1923
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
1924
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
1925
          buf[varDataLen(input)] = 0;
×
1926
          *(int8_t *)output = taosStr2Int8(buf, NULL, 10);
×
1927
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
1928
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
1929
          if (len < 0) {
×
1930
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1931
            goto _end;
×
1932
          }
1933

1934
          convBuf[len] = 0;
×
1935
          *(int8_t *)output = taosStr2Int8(convBuf, NULL, 10);
×
1936
        } else {
1937
          GET_TYPED_DATA(*(int8_t *)output, int8_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
1938
        }
1939
        break;
×
1940
      }
1941
      case TSDB_DATA_TYPE_SMALLINT: {
×
1942
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
1943
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
1944
          buf[varDataLen(input)] = 0;
×
1945
          *(int16_t *)output = taosStr2Int16(buf, NULL, 10);
×
1946
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
1947
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
1948
          if (len < 0) {
×
1949
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1950
            goto _end;
×
1951
          }
1952
          convBuf[len] = 0;
×
1953
          *(int16_t *)output = taosStr2Int16(convBuf, NULL, 10);
×
1954
        } else {
1955
          GET_TYPED_DATA(*(int16_t *)output, int16_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
1956
        }
1957
        break;
×
1958
      }
1959
      case TSDB_DATA_TYPE_INT: {
19✔
1960
        if (inputType == TSDB_DATA_TYPE_BINARY) {
19✔
1961
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
1962
          buf[varDataLen(input)] = 0;
×
1963
          *(int32_t *)output = taosStr2Int32(buf, NULL, 10);
×
1964
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
19✔
1965
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
1966
          if (len < 0) {
×
1967
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1968
            goto _end;
×
1969
          }
1970

1971
          convBuf[len] = 0;
×
1972
          *(int32_t *)output = taosStr2Int32(convBuf, NULL, 10);
×
1973
        } else {
1974
          GET_TYPED_DATA(*(int32_t *)output, int32_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
19✔
1975
        }
1976
        break;
19✔
1977
      }
1978
      case TSDB_DATA_TYPE_BIGINT: {
×
1979
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
1980
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
1981
          buf[varDataLen(input)] = 0;
×
1982
          *(int64_t *)output = taosStr2Int64(buf, NULL, 10);
×
1983
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
1984
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
1985
          if (len < 0) {
×
1986
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
1987
            goto _end;
×
1988
          }
1989
          convBuf[len] = 0;
×
1990
          *(int64_t *)output = taosStr2Int64(convBuf, NULL, 10);
×
1991
        } else {
1992
          GET_TYPED_DATA(*(int64_t *)output, int64_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
1993
        }
1994
        break;
×
1995
      }
1996
      case TSDB_DATA_TYPE_UTINYINT: {
×
1997
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
1998
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
1999
          buf[varDataLen(input)] = 0;
×
2000
          *(uint8_t *)output = taosStr2UInt8(buf, NULL, 10);
×
2001
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2002
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2003
          if (len < 0) {
×
2004
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2005
            goto _end;
×
2006
          }
2007
          convBuf[len] = 0;
×
2008
          *(uint8_t *)output = taosStr2UInt8(convBuf, NULL, 10);
×
2009
        } else {
2010
          GET_TYPED_DATA(*(uint8_t *)output, uint8_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2011
        }
2012
        break;
×
2013
      }
2014
      case TSDB_DATA_TYPE_USMALLINT: {
×
2015
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2016
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2017
          buf[varDataLen(input)] = 0;
×
2018
          *(uint16_t *)output = taosStr2UInt16(buf, NULL, 10);
×
2019
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2020
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2021
          if (len < 0) {
×
2022
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2023
            goto _end;
×
2024
          }
2025
          convBuf[len] = 0;
×
2026
          *(uint16_t *)output = taosStr2UInt16(convBuf, NULL, 10);
×
2027
        } else {
2028
          GET_TYPED_DATA(*(uint16_t *)output, uint16_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2029
        }
2030
        break;
×
2031
      }
2032
      case TSDB_DATA_TYPE_UINT: {
×
2033
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2034
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2035
          buf[varDataLen(input)] = 0;
×
2036
          *(uint32_t *)output = taosStr2UInt32(buf, NULL, 10);
×
2037
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2038
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2039
          if (len < 0) {
×
2040
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2041
            goto _end;
×
2042
          }
2043
          convBuf[len] = 0;
×
2044
          *(uint32_t *)output = taosStr2UInt32(convBuf, NULL, 10);
×
2045
        } else {
2046
          GET_TYPED_DATA(*(uint32_t *)output, uint32_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2047
        }
2048
        break;
×
2049
      }
2050
      case TSDB_DATA_TYPE_UBIGINT: {
×
2051
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2052
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2053
          buf[varDataLen(input)] = 0;
×
2054
          *(uint64_t *)output = taosStr2UInt64(buf, NULL, 10);
×
2055
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2056
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2057
          if (len < 0) {
×
2058
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2059
            goto _end;
×
2060
          }
2061

2062
          convBuf[len] = 0;
×
2063
          *(uint64_t *)output = taosStr2UInt64(convBuf, NULL, 10);
×
2064
        } else {
2065
          GET_TYPED_DATA(*(uint64_t *)output, uint64_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2066
        }
2067
        break;
×
2068
      }
2069
      case TSDB_DATA_TYPE_FLOAT: {
×
2070
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2071
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2072
          buf[varDataLen(input)] = 0;
×
2073
          *(float *)output = taosStr2Float(buf, NULL);
×
2074
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2075
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2076
          if (len < 0) {
×
2077
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2078
            goto _end;
×
2079
          }
2080
          convBuf[len] = 0;
×
2081
          *(float *)output = taosStr2Float(convBuf, NULL);
×
2082
        } else {
2083
          GET_TYPED_DATA(*(float *)output, float, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2084
        }
2085
        break;
×
2086
      }
2087
      case TSDB_DATA_TYPE_DOUBLE: {
9✔
2088
        if (inputType == TSDB_DATA_TYPE_BINARY) {
9✔
2089
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2090
          buf[varDataLen(input)] = 0;
×
2091
          *(double *)output = taosStr2Double(buf, NULL);
×
2092
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
9✔
2093
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2094
          if (len < 0) {
×
2095
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2096
            goto _end;
×
2097
          }
2098
          convBuf[len] = 0;
×
2099
          *(double *)output = taosStr2Double(convBuf, NULL);
×
2100
        } else {
2101
          GET_TYPED_DATA(*(double *)output, double, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
9✔
2102
        }
2103
        break;
9✔
2104
      }
2105
      case TSDB_DATA_TYPE_BOOL: {
×
2106
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2107
          (void)memcpy(buf, varDataVal(input), varDataLen(input));
×
2108
          buf[varDataLen(input)] = 0;
×
2109
          *(bool *)output = taosStr2Int8(buf, NULL, 10);
×
2110
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2111
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2112
          if (len < 0) {
×
2113
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2114
            goto _end;
×
2115
          }
2116
          convBuf[len] = 0;
×
2117
          *(bool *)output = taosStr2Int8(convBuf, NULL, 10);
×
2118
        } else {
2119
          GET_TYPED_DATA(*(bool *)output, bool, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2120
        }
2121
        break;
×
2122
      }
2123
      case TSDB_DATA_TYPE_TIMESTAMP: {
15✔
2124
        int64_t timeVal;
2125
        if (inputType == TSDB_DATA_TYPE_BINARY || inputType == TSDB_DATA_TYPE_NCHAR) {
25✔
2126
          int64_t timePrec;
2127
          GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData, typeGetTypeModFromColInfo(&pInput[1].columnData->info));
20✔
2128
          int32_t ret = convertStringToTimestamp(inputType, input, timePrec, &timeVal, pInput->tz, pInput->charsetCxt);
10✔
2129
          if (ret != TSDB_CODE_SUCCESS) {
10✔
2130
            *(int64_t *)output = 0;
×
2131
          } else {
2132
            *(int64_t *)output = timeVal;
10✔
2133
          }
2134
        } else {
2135
          GET_TYPED_DATA(*(int64_t *)output, int64_t, inputType, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
5✔
2136
        }
2137
        break;
15✔
2138
      }
2139
      case TSDB_DATA_TYPE_BINARY:
5✔
2140
      case TSDB_DATA_TYPE_GEOMETRY: {
2141
        if (inputType == TSDB_DATA_TYPE_BOOL) {
5✔
2142
          // NOTE: snprintf will append '\0' at the end of string
2143
          int32_t len = tsnprintf(varDataVal(output), outputLen + TSDB_NCHAR_SIZE - VARSTR_HEADER_SIZE, "%.*s",
×
2144
                                 (int32_t)(outputLen - VARSTR_HEADER_SIZE), *(int8_t *)input ? "true" : "false");
×
2145
          varDataSetLen(output, len);
×
2146
        } else if (inputType == TSDB_DATA_TYPE_BINARY) {
5✔
2147
          int32_t len = TMIN(varDataLen(input), outputLen - VARSTR_HEADER_SIZE);
×
2148
          (void)memcpy(varDataVal(output), varDataVal(input), len);
×
2149
          varDataSetLen(output, len);
×
2150
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
5✔
2151
          int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(input), varDataLen(input), convBuf, pInput->charsetCxt);
×
2152
          if (len < 0) {
×
2153
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2154
            goto _end;
×
2155
          }
2156
          len = TMIN(len, outputLen - VARSTR_HEADER_SIZE);
×
2157
          (void)memcpy(varDataVal(output), convBuf, len);
×
2158
          varDataSetLen(output, len);
×
2159
        } else {
2160
          int32_t outputSize = (outputLen - VARSTR_HEADER_SIZE) < bufSize ? (outputLen - VARSTR_HEADER_SIZE + 1): bufSize;
5✔
2161
          if (IS_DECIMAL_TYPE(inputType)) {
5✔
2162
            if (outputType == TSDB_DATA_TYPE_GEOMETRY) return TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2163
            uint8_t inputPrec = GET_PARAM_PRECISON(&pInput[0]), inputScale = GET_PARAM_SCALE(&pInput[0]);
×
2164
            code = decimalToStr(input, inputType, inputPrec, inputScale, buf, outputSize);
×
2165
            if (code != 0) goto _end;
×
2166
          } else {
2167
            NUM_TO_STRING(inputType, input, outputSize, buf);
5✔
2168
          }
2169
          int32_t len = (int32_t)strlen(buf);
5✔
2170
          len = (outputLen - VARSTR_HEADER_SIZE) > len ? len : (outputLen - VARSTR_HEADER_SIZE);
5✔
2171
          (void)memcpy(varDataVal(output), buf, len);
5✔
2172
          varDataSetLen(output, len);
5✔
2173
        }
2174
        break;
5✔
2175
      }
2176
      case TSDB_DATA_TYPE_VARBINARY:{
×
2177
        if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2178
          int32_t len = TMIN(varDataLen(input), outputLen - VARSTR_HEADER_SIZE);
×
2179
          (void)memcpy(varDataVal(output), varDataVal(input), len);
×
2180
          varDataSetLen(output, len);
×
2181
        }else{
2182
          code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
×
2183
          goto _end;
×
2184
        }
2185
        break;
×
2186
      }
2187
      case TSDB_DATA_TYPE_NCHAR: {
×
2188
        int32_t outputCharLen = (outputLen - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
×
2189
        int32_t len;
2190
        if (inputType == TSDB_DATA_TYPE_BOOL) {
×
2191
          char tmp[8] = {0};
×
2192
          len = tsnprintf(tmp, sizeof(tmp), "%.*s", outputCharLen, *(int8_t *)input ? "true" : "false");
×
2193
          bool ret = taosMbsToUcs4(tmp, len, (TdUcs4 *)varDataVal(output), outputLen - VARSTR_HEADER_SIZE, &len, pInput->charsetCxt);
×
2194
          if (!ret) {
×
2195
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2196
            goto _end;
×
2197
          }
2198

2199
          varDataSetLen(output, len);
×
2200
        } else if (inputType == TSDB_DATA_TYPE_BINARY) {
×
2201
          len = outputCharLen > varDataLen(input) ? varDataLen(input) : outputCharLen;
×
2202
          bool ret = taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, (TdUcs4 *)varDataVal(output),
×
2203
                                   outputLen - VARSTR_HEADER_SIZE, &len, pInput->charsetCxt);
×
2204
          if (!ret) {
×
2205
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2206
            goto _end;
×
2207
          }
2208
          varDataSetLen(output, len);
×
2209
        } else if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2210
          len = TMIN(outputLen - VARSTR_HEADER_SIZE, varDataLen(input));
×
2211
          (void)memcpy(output, input, len + VARSTR_HEADER_SIZE);
×
2212
          varDataSetLen(output, len);
×
2213
        } else {
2214
          if (IS_DECIMAL_TYPE(inputType)) {
×
2215
            uint8_t inputPrec = GET_PARAM_PRECISON(&pInput[0]), inputScale = GET_PARAM_SCALE(&pInput[0]);
×
2216
            code = decimalToStr(input, inputType, inputPrec, inputScale, buf, bufSize);
×
2217
            if (code != 0) goto _end;
×
2218
          } else {
2219
            NUM_TO_STRING(inputType, input, bufSize, buf);
×
2220
          }
2221
          len = (int32_t)strlen(buf);
×
2222
          len = outputCharLen > len ? len : outputCharLen;
×
2223
          bool ret = taosMbsToUcs4(buf, len, (TdUcs4 *)varDataVal(output), outputLen - VARSTR_HEADER_SIZE, &len, pInput->charsetCxt);
×
2224
          if (!ret) {
×
2225
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2226
            goto _end;
×
2227
          }
2228
          varDataSetLen(output, len);
×
2229
        }
2230

2231
        // for constant conversion, need to set proper length of pOutput description
2232
        if (len < outputLen) {
×
2233
          pOutput->columnData->info.bytes = len + VARSTR_HEADER_SIZE;
×
2234
        }
2235

2236
        break;
×
2237
      }
2238
      case TSDB_DATA_TYPE_DECIMAL64:
×
2239
      case TSDB_DATA_TYPE_DECIMAL: {
2240
        SDataType iT = GET_COL_DATA_TYPE(pInput[0].columnData->info), oT = GET_COL_DATA_TYPE(pOutput->columnData->info);
×
2241
        if (inputType == TSDB_DATA_TYPE_NCHAR) {
×
2242
          int32_t len = taosUcs4ToMbs((TdUcs4 *)(varDataVal(input)), varDataLen(input), convBuf, pInput->charsetCxt);
×
2243
          if (len < 0) {
×
2244
            code = TSDB_CODE_SCALAR_CONVERT_ERROR;
×
2245
            goto _end;
×
2246
          }
2247
          convBuf[len] = 0;
×
2248
          iT.bytes = len;
×
2249
          code = convertToDecimal(convBuf, &iT, output, &oT);
×
2250
        } else {
2251
          if (IS_VAR_DATA_TYPE(iT.type)) {
×
2252
            iT.bytes = varDataLen(input);
×
2253
            code = convertToDecimal(varDataVal(input), &iT, output, &oT);
×
2254
          } else {
2255
            code = convertToDecimal(input, &iT, output, &oT);
×
2256
          }
2257
        }
2258
        if (code != TSDB_CODE_SUCCESS) {
×
2259
          terrno = code;
×
2260
          goto _end;
×
2261
        }
2262
      } break;
×
2263
      default: {
×
2264
        code = TSDB_CODE_FAILED;
×
2265
        goto _end;
×
2266
      }
2267
    }
2268

2269
    code = colDataSetVal(pOutput->columnData, i, output, false);
48✔
2270
    if (TSDB_CODE_SUCCESS != code) {
48✔
2271
      goto _end;
×
2272
    }
2273
  }
2274

2275
  pOutput->numOfRows = pInput->numOfRows;
48✔
2276

2277
_end:
48✔
2278
  taosMemoryFree(buf);
48✔
2279
  taosMemoryFree(output);
48✔
2280
  taosMemoryFree(convBuf);
48✔
2281
  return code;
48✔
2282
}
2283

2284
int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
27✔
2285
  int32_t type = GET_PARAM_TYPE(pInput);
27✔
2286

2287
  bool    tzPresent = (inputNum == 2) ? true : false;
27✔
2288
  char    tz[20] = {0};
27✔
2289
  int32_t tzLen = 0;
27✔
2290
  if (tzPresent) {
27✔
2291
    tzLen = varDataLen(pInput[1].columnData->pData);
27✔
2292
    (void)memcpy(tz, varDataVal(pInput[1].columnData->pData), tzLen);
27✔
2293
  }
2294

2295
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
54✔
2296
    if (colDataIsNull_s(pInput[0].columnData, i)) {
54✔
2297
      colDataSetNULL(pOutput->columnData, i);
×
2298
      continue;
×
2299
    }
2300

2301
    char *input = colDataGetData(pInput[0].columnData, i);
27✔
2302
    char  fraction[20] = {0};
27✔
2303
    bool  hasFraction = false;
27✔
2304
    NUM_TO_STRING(type, input, sizeof(fraction), fraction);
27✔
2305
    int32_t fractionLen;
2306

2307
    char    buf[TD_TIME_STR_LEN] = {0};
27✔
2308
    int64_t timeVal;
2309
    char*   format = NULL;
27✔
2310
    int64_t  quot = 0;
27✔
2311
    long    mod = 0;
27✔
2312

2313
    GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
27✔
2314

2315
    switch (pInput->columnData[0].info.precision) {
27✔
2316
      case TSDB_TIME_PRECISION_MILLI: {
27✔
2317
        quot = timeVal / 1000;
27✔
2318
        fractionLen = 5;
27✔
2319
        format = ".%03" PRId64;
27✔
2320
        mod = timeVal % 1000;
27✔
2321
        break;
27✔
2322
      }
2323

2324
      case TSDB_TIME_PRECISION_MICRO: {
×
2325
        quot = timeVal / 1000000;
×
2326
        fractionLen = 8;
×
2327
        format = ".%06" PRId64;
×
2328
        mod = timeVal % 1000000;
×
2329
        break;
×
2330
      }
2331

2332
      case TSDB_TIME_PRECISION_NANO: {
×
2333
        quot = timeVal / 1000000000;
×
2334
        fractionLen = 11;
×
2335
        format = ".%09" PRId64;
×
2336
        mod = timeVal % 1000000000;
×
2337
        break;
×
2338
      }
2339

2340
      default: {
×
2341
        colDataSetNULL(pOutput->columnData, i);
×
2342
        continue;
×
2343
      }
2344
    }
2345

2346
    // trans current timezone's unix ts to dest timezone
2347
    // offset = delta from dest timezone to zero
2348
    // delta from zero to current timezone = 3600 * (cur)tsTimezone
2349
    int64_t offset = 0;
27✔
2350
    if (0 != offsetOfTimezone(tz, &offset)) {
27✔
2351
      goto _end;
×
2352
    }
2353
    quot -= offset;
27✔
2354

2355
    struct tm tmInfo;
2356
    if (taosGmTimeR((const time_t *)&quot, &tmInfo) == NULL) {
27✔
2357
      goto _end;
×
2358
    }
2359

2360
    int32_t len = (int32_t)taosStrfTime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
27✔
2361

2362
    len += tsnprintf(buf + len, fractionLen, format, mod);
27✔
2363

2364
    // add timezone string
2365
    if (tzLen > 0) {
27✔
2366
      (void)snprintf(buf + len, tzLen + 1, "%s", tz);
27✔
2367
      len += tzLen;
27✔
2368
    }
2369

2370
    memmove(buf + VARSTR_HEADER_SIZE, buf, len);
27✔
2371
    varDataSetLen(buf, len);
27✔
2372

2373
  _end:
27✔
2374
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, buf, false));
27✔
2375
  }
2376

2377
  pOutput->numOfRows = pInput->numOfRows;
27✔
2378

2379
  return TSDB_CODE_SUCCESS;
27✔
2380
}
2381

2382
int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3✔
2383
  int32_t type = GET_PARAM_TYPE(pInput);
3✔
2384
  int64_t timePrec;
2385
  int32_t idx = (inputNum == 2) ? 1 : 2;
3✔
2386
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[idx]), pInput[idx].columnData->pData,
3✔
2387
                 typeGetTypeModFromColInfo(&pInput[idx].columnData->info));
2388

2389
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
6✔
2390
    if (colDataIsNull_s(pInput[0].columnData, i)) {
6✔
2391
      colDataSetNULL(pOutput->columnData, i);
×
2392
      continue;
×
2393
    }
2394
    char *input = colDataGetData(pInput[0].columnData, i);
3✔
2395

2396
    int64_t timeVal = 0;
3✔
2397
    int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz, pInput->charsetCxt);
3✔
2398
    if (ret != TSDB_CODE_SUCCESS) {
3✔
2399
      colDataSetNULL(pOutput->columnData, i);
×
2400
    } else {
2401
      SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false));
3✔
2402
    }
2403
  }
2404

2405
  pOutput->numOfRows = pInput->numOfRows;
3✔
2406

2407
  return TSDB_CODE_SUCCESS;
3✔
2408
}
2409

2410
int32_t toJsonFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
2411
  int32_t type = GET_PARAM_TYPE(pInput);
×
2412

2413
  char tmp[TSDB_MAX_JSON_TAG_LEN] = {0};
×
2414
  int32_t code = TSDB_CODE_SUCCESS;
×
2415
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
×
2416
    SArray *pTagVals = taosArrayInit(8, sizeof(STagVal));
×
2417
    if (NULL == pTagVals) {
×
2418
      return terrno;
×
2419
    }
2420
    STag   *pTag = NULL;
×
2421

2422
    if (colDataIsNull_s(pInput[0].columnData, i)) {
×
2423
      code = tTagNew(pTagVals, 1, true, &pTag);
×
2424
      if (TSDB_CODE_SUCCESS != code) {
×
2425
        tTagFree(pTag);
×
2426
        taosArrayDestroy(pTagVals);
×
2427
        SCL_ERR_RET(code);
×
2428
      }
2429
    } else {
2430
      char *input = pInput[0].columnData->pData + pInput[0].columnData->varmeta.offset[i];
×
2431
      if (varDataLen(input) > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
×
2432
        taosArrayDestroy(pTagVals);
×
2433
        return TSDB_CODE_FAILED;
×
2434
      }
2435
      (void)memcpy(tmp, varDataVal(input), varDataLen(input));
×
2436
      tmp[varDataLen(input)] = 0;
×
2437
      if (parseJsontoTagData(tmp, pTagVals, &pTag, NULL, pInput->charsetCxt)) {
×
2438
        code = tTagNew(pTagVals, 1, true, &pTag);
×
2439
        if (TSDB_CODE_SUCCESS != code) {
×
2440
          tTagFree(pTag);
×
2441
          taosArrayDestroy(pTagVals);
×
2442
          SCL_ERR_RET(code);
×
2443
        }
2444
      }
2445
    }
2446

2447
    code = colDataSetVal(pOutput->columnData, i, (const char *)pTag, false);
×
2448
    tTagFree(pTag);
×
2449
    taosArrayDestroy(pTagVals);
×
2450
    if (TSDB_CODE_SUCCESS != code ) {
×
2451
      SCL_ERR_RET(code);
×
2452
    }
2453
  }
2454

2455
  pOutput->numOfRows = pInput->numOfRows;
×
2456
  return TSDB_CODE_SUCCESS;
×
2457
}
2458

2459
#define TS_FORMAT_MAX_LEN 4096
2460
int32_t toTimestampFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
3✔
2461
  int64_t ts;
2462
  char *  tsStr = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
3✔
2463
  char *  format = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
3✔
2464
  int32_t len, code = TSDB_CODE_SUCCESS;
3✔
2465
  SArray *formats = NULL;
3✔
2466

2467
  if (tsStr == NULL || format == NULL) {
3✔
2468
    SCL_ERR_JRET(terrno);
×
2469
  }
2470
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
6✔
2471
    if (colDataIsNull_s(pInput[1].columnData, i) || colDataIsNull_s(pInput[0].columnData, i)) {
9✔
2472
      colDataSetNULL(pOutput->columnData, i);
×
2473
      continue;
×
2474
    }
2475

2476
    char *tsData = colDataGetData(pInput[0].columnData, i);
3✔
2477
    char *formatData = colDataGetData(pInput[1].columnData, pInput[1].numOfRows > 1 ? i : 0);
3✔
2478
    len = TMIN(TS_FORMAT_MAX_LEN - 1, varDataLen(tsData));
3✔
2479
    (void)strncpy(tsStr, varDataVal(tsData), len);  // No need to handle the return value.
3✔
2480
    tsStr[len] = '\0';
3✔
2481
    len = TMIN(TS_FORMAT_MAX_LEN - 1, varDataLen(formatData));
3✔
2482
    if (pInput[1].numOfRows > 1 || i == 0) {
3✔
2483
      (void)strncpy(format, varDataVal(formatData), len);  // No need to handle the return value.
3✔
2484
      format[len] = '\0';
3✔
2485
      if (formats) {
3✔
2486
        taosArrayDestroy(formats);
×
2487
        formats = NULL;
×
2488
      }
2489
    }
2490
    int32_t precision = pOutput->columnData->info.precision;
3✔
2491
    char    errMsg[128] = {0};
3✔
2492
    code = taosChar2Ts(format, &formats, tsStr, &ts, precision, errMsg, 128, pInput->tz);
3✔
2493
    if (code) {
3✔
2494
      qError("func to_timestamp failed %s", errMsg);
×
2495
      SCL_ERR_JRET(code);
×
2496
    }
2497
    SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, (char *)&ts, false));
3✔
2498
  }
2499

2500
_return:
3✔
2501
  if (formats) taosArrayDestroy(formats);
3✔
2502
  taosMemoryFree(tsStr);
3✔
2503
  taosMemoryFree(format);
3✔
2504
  return code;
3✔
2505
}
2506

2507
int32_t toCharFunction(SScalarParam* pInput, int32_t inputNum, SScalarParam* pOutput) {
2✔
2508
  char *  format = taosMemoryMalloc(TS_FORMAT_MAX_LEN);
2✔
2509
  char *  out = taosMemoryCalloc(1, TS_FORMAT_MAX_LEN + VARSTR_HEADER_SIZE);
2✔
2510
  int32_t len;
2511
  SArray *formats = NULL;
2✔
2512
  int32_t code = 0;
2✔
2513

2514
  if (format == NULL || out == NULL) {
2✔
2515
    SCL_ERR_JRET(terrno);
×
2516
  }
2517
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
4✔
2518
    if (colDataIsNull_s(pInput[1].columnData, i) || colDataIsNull_s(pInput[0].columnData, i)) {
6✔
2519
      colDataSetNULL(pOutput->columnData, i);
×
2520
      continue;
×
2521
    }
2522

2523
    char *ts = colDataGetData(pInput[0].columnData, i);
2✔
2524
    char *formatData = colDataGetData(pInput[1].columnData, pInput[1].numOfRows > 1 ? i : 0);
2✔
2525
    len = TMIN(TS_FORMAT_MAX_LEN - VARSTR_HEADER_SIZE, varDataLen(formatData));
2✔
2526
    if (pInput[1].numOfRows > 1 || i == 0) {
2✔
2527
      (void)strncpy(format, varDataVal(formatData), len);
2✔
2528
      format[len] = '\0';
2✔
2529
      if (formats) {
2✔
2530
        taosArrayDestroy(formats);
×
2531
        formats = NULL;
×
2532
      }
2533
    }
2534
    int32_t precision = pInput[0].columnData->info.precision;
2✔
2535
    SCL_ERR_JRET(taosTs2Char(format, &formats, *(int64_t *)ts, precision, varDataVal(out), TS_FORMAT_MAX_LEN, pInput->tz));
2✔
2536
    varDataSetLen(out, strlen(varDataVal(out)));
2✔
2537
    SCL_ERR_JRET(colDataSetVal(pOutput->columnData, i, out, false));
2✔
2538
  }
2539

2540
_return:
2✔
2541
  if (formats) taosArrayDestroy(formats);
2✔
2542
  taosMemoryFree(format);
2✔
2543
  taosMemoryFree(out);
2✔
2544
  return code;
2✔
2545
}
2546

2547
/** Time functions **/
2548
int64_t offsetFromTz(char *timezoneStr, int64_t factor) {
8✔
2549
  char *minStr = &timezoneStr[3];
8✔
2550
  int64_t minutes = taosStr2Int64(minStr, NULL, 10);
8✔
2551
  (void)memset(minStr, 0, strlen(minStr));
8✔
2552
  int64_t hours = taosStr2Int64(timezoneStr, NULL, 10);
8✔
2553
  int64_t seconds = hours * 3600 + minutes * 60;
8✔
2554

2555
  return seconds * factor;
8✔
2556

2557
}
2558

2559
int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
17✔
2560
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
17✔
2561

2562
  int64_t timeUnit, timePrec, timeVal = 0;
17✔
2563
  bool    ignoreTz = true;
17✔
2564
  char    timezoneStr[20] = {0};
17✔
2565

2566
  GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
17✔
2567
                 typeGetTypeModFromColInfo(&pInput[1].columnData->info));
2568

2569
  int32_t timePrecIdx = 2, timeZoneIdx = 3;
17✔
2570
  if (inputNum == 5) {
17✔
2571
    timePrecIdx += 1;
17✔
2572
    timeZoneIdx += 1;
17✔
2573
    GET_TYPED_DATA(ignoreTz, bool, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData,
17✔
2574
                   typeGetTypeModFromColInfo(&pInput[2].columnData->info));
2575
  }
2576

2577
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[timePrecIdx]), pInput[timePrecIdx].columnData->pData,
17✔
2578
                 typeGetTypeModFromColInfo(&pInput[timePrecIdx].columnData->info));
2579
  (void)memcpy(timezoneStr, varDataVal(pInput[timeZoneIdx].columnData->pData), varDataLen(pInput[timeZoneIdx].columnData->pData));
17✔
2580

2581
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
34✔
2582
    if (colDataIsNull_s(pInput[0].columnData, i)) {
34✔
2583
      colDataSetNULL(pOutput->columnData, i);
×
2584
      continue;
×
2585
    }
2586

2587
    char *input = colDataGetData(pInput[0].columnData, i);
17✔
2588

2589
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
33✔
2590
      int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz, pInput->charsetCxt);
16✔
2591
      if (ret != TSDB_CODE_SUCCESS) {
16✔
2592
        colDataSetNULL(pOutput->columnData, i);
×
2593
        continue;
×
2594
      }
2595
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
1✔
2596
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
1✔
2597
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
×
2598
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2599
    }
2600

2601
    char buf[20] = {0};
17✔
2602
    NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal, sizeof(buf), buf);
17✔
2603

2604
    // truncate the timestamp to time_unit precision
2605
    int64_t seconds = timeUnit / TSDB_TICK_PER_SECOND(timePrec);
17✔
2606
    if (ignoreTz && (seconds == 604800 || seconds == 86400)) {
17✔
2607
      timeVal = timeVal - (timeVal + offsetFromTz(timezoneStr, TSDB_TICK_PER_SECOND(timePrec))) % timeUnit;
8✔
2608
    } else {
2609
      timeVal = timeVal / timeUnit * timeUnit;
9✔
2610
    }
2611
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false));
17✔
2612
  }
2613

2614
  pOutput->numOfRows = pInput->numOfRows;
17✔
2615

2616
  return TSDB_CODE_SUCCESS;
17✔
2617
}
2618

2619
int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
1✔
2620
  int64_t timeUnit = -1, timePrec, timeVal[2] = {0};
1✔
2621
  if (inputNum == 4) {
1✔
2622
    GET_TYPED_DATA(timeUnit, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData,
×
2623
                   typeGetTypeModFromColInfo(&pInput[2].columnData->info));
2624
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[3]), pInput[3].columnData->pData,
×
2625
                   typeGetTypeModFromColInfo(&pInput[3].columnData->info));
2626
  } else {
2627
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData,
1✔
2628
                   typeGetTypeModFromColInfo(&pInput[2].columnData->info));
2629
  }
2630

2631
  int64_t factor = TSDB_TICK_PER_SECOND(timePrec);
1✔
2632
  int32_t numOfRows = 0;
1✔
2633
  for (int32_t i = 0; i < inputNum; ++i) {
4✔
2634
    if (pInput[i].numOfRows > numOfRows) {
3✔
2635
      numOfRows = pInput[i].numOfRows;
1✔
2636
    }
2637
  }
2638

2639
  char *input[2];
2640
  for (int32_t i = 0; i < numOfRows; ++i) {
2✔
2641
    bool hasNull = false;
1✔
2642
    for (int32_t k = 0; k < 2; ++k) {
3✔
2643
      if (colDataIsNull_s(pInput[k].columnData, i)) {
4✔
2644
        hasNull = true;
×
2645
        break;
×
2646
      }
2647

2648
      int32_t rowIdx = (pInput[k].numOfRows == 1) ? 0 : i;
2✔
2649
      input[k] = colDataGetData(pInput[k].columnData, rowIdx);
2✔
2650

2651
      int32_t type = GET_PARAM_TYPE(&pInput[k]);
2✔
2652
      if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
4✔
2653
        int32_t ret = convertStringToTimestamp(type, input[k], TSDB_TIME_PRECISION_NANO, &timeVal[k], pInput->tz, pInput->charsetCxt);
2✔
2654
        if (ret != TSDB_CODE_SUCCESS) {
2✔
2655
          hasNull = true;
×
2656
          break;
×
2657
        }
2658
      } else if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_TIMESTAMP) { /* unix timestamp or ts column*/
×
2659
        GET_TYPED_DATA(timeVal[k], int64_t, type, input[k], typeGetTypeModFromColInfo(&pInput[k].columnData->info));
×
2660
        if (type == TSDB_DATA_TYPE_TIMESTAMP) {
×
2661
          int64_t timeValSec = timeVal[k] / factor;
×
2662
          if (timeValSec < 1000000000) {
×
2663
            timeVal[k] = timeValSec;
×
2664
          }
2665
        }
2666

2667
        char buf[20] = {0};
×
2668
        NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal[k], sizeof(buf), buf);
×
2669
        int32_t tsDigits = (int32_t)strlen(buf);
×
2670
        if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
×
2671
          timeVal[k] = timeVal[k] * 1000000000;
×
2672
        } else if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
×
2673
          timeVal[k] = timeVal[k] * 1000000;
×
2674
        } else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
×
2675
          timeVal[k] = timeVal[k] * 1000;
×
2676
        } else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
×
2677
          timeVal[k] = timeVal[k] * 1;
×
2678
        } else {
2679
          hasNull = true;
×
2680
          break;
×
2681
        }
2682
      }
2683
    }
2684

2685
    if (hasNull) {
1✔
2686
      colDataSetNULL(pOutput->columnData, i);
×
2687
      continue;
×
2688
    }
2689

2690
    int64_t result = timeVal[0] - timeVal[1];
1✔
2691

2692
    if (timeUnit < 0) {  // if no time unit given use db precision
1✔
2693
      switch (timePrec) {
1✔
2694
        case TSDB_TIME_PRECISION_MILLI: {
1✔
2695
          result = result / 1000000;
1✔
2696
          break;
1✔
2697
        }
2698
        case TSDB_TIME_PRECISION_MICRO: {
×
2699
          result = result / 1000;
×
2700
          break;
×
2701
        }
2702
        case TSDB_TIME_PRECISION_NANO: {
×
2703
          result = result / 1;
×
2704
          break;
×
2705
        }
2706
      }
2707
    } else {
1✔
2708
      int64_t unit = timeUnit * 1000 / factor;
×
2709
      switch (unit) {
×
2710
        case 0: { /* 1u or 1b */
×
2711
          if (timePrec == TSDB_TIME_PRECISION_NANO && timeUnit == 1) {
×
2712
            result = result / 1;
×
2713
          } else {
2714
            result = result / 1000;
×
2715
          }
2716
          break;
×
2717
        }
2718
        case 1: { /* 1a */
×
2719
          result = result / 1000000;
×
2720
          break;
×
2721
        }
2722
        case 1000: { /* 1s */
×
2723
          result = result / 1000000000;
×
2724
          break;
×
2725
        }
2726
        case 60000: { /* 1m */
×
2727
          result = result / 1000000000 / 60;
×
2728
          break;
×
2729
        }
2730
        case 3600000: { /* 1h */
×
2731
          result = result / 1000000000 / 3600;
×
2732
          break;
×
2733
        }
2734
        case 86400000: { /* 1d */
×
2735
          result = result / 1000000000 / 86400;
×
2736
          break;
×
2737
        }
2738
        case 604800000: { /* 1w */
×
2739
          result = result / 1000000000 / 604800;
×
2740
          break;
×
2741
        }
2742
        default: {
×
2743
          break;
×
2744
        }
2745
      }
2746
    }
2747

2748
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, (char *)&result, false));
1✔
2749
  }
2750

2751
  pOutput->numOfRows = numOfRows;
1✔
2752

2753
  return TSDB_CODE_SUCCESS;
1✔
2754
}
2755

2756
int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
51✔
2757
  int64_t timePrec;
2758
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData,
51✔
2759
                 typeGetTypeModFromColInfo(&pInput[0].columnData->info));
2760

2761
  int64_t ts = taosGetTimestamp(timePrec);
51✔
2762
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
102✔
2763
    colDataSetInt64(pOutput->columnData, i, &ts);
51✔
2764
  }
2765
  pOutput->numOfRows = pInput->numOfRows;
51✔
2766
  return TSDB_CODE_SUCCESS;
51✔
2767
}
2768

2769
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2✔
2770
  int64_t timePrec;
2771
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[0]), pInput[0].columnData->pData,
2✔
2772
                 typeGetTypeModFromColInfo(&pInput[0].columnData->info));
2773

2774
  int64_t ts = taosGetTimestampToday(timePrec, pInput->tz);
2✔
2775
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
4✔
2776
    colDataSetInt64(pOutput->columnData, i, &ts);
2✔
2777
  }
2778
  pOutput->numOfRows = pInput->numOfRows;
2✔
2779
  return TSDB_CODE_SUCCESS;
2✔
2780
}
2781

2782
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
8✔
2783
  char output[TD_TIMEZONE_LEN + VARSTR_HEADER_SIZE] = {0};
8✔
2784
  char* tmp = NULL;
8✔
2785
  if (pInput->tz == NULL) {
8✔
2786
    (void)memcpy(varDataVal(output), tsTimezoneStr, TD_TIMEZONE_LEN);
3✔
2787
  } else{
2788
    char *tzName  = (char*)taosHashGet(pTimezoneNameMap, &pInput->tz, sizeof(timezone_t));
5✔
2789
    if (tzName == NULL){
5✔
2790
      tzName = TZ_UNKNOWN;
×
2791
    }
2792
    tstrncpy(varDataVal(output), tzName, strlen(tzName) + 1);
5✔
2793
  }
2794

2795
  varDataSetLen(output, strlen(varDataVal(output)));
8✔
2796
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
16✔
2797
    SCL_ERR_RET(colDataSetVal(pOutput->columnData, i, output, false));
8✔
2798
  }
2799
  pOutput->numOfRows = pInput->numOfRows;
8✔
2800
  return TSDB_CODE_SUCCESS;
8✔
2801
}
2802

2803
int32_t weekdayFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, bool startFromZero) {
10✔
2804
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
10✔
2805

2806
  int64_t timePrec, timeVal = 0;
10✔
2807

2808
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
10✔
2809
                 typeGetTypeModFromColInfo(&pInput[1].columnData->info));
2810

2811
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
20✔
2812
    if (colDataIsNull_s(pInput[0].columnData, i)) {
20✔
2813
      colDataSetNULL(pOutput->columnData, i);
×
2814
      continue;
×
2815
    }
2816

2817
    char *input = colDataGetData(pInput[0].columnData, i);
10✔
2818

2819
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
18✔
2820
      int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal, pInput->tz, pInput->charsetCxt);
8✔
2821
      if (ret != TSDB_CODE_SUCCESS) {
8✔
2822
        colDataSetNULL(pOutput->columnData, i);
×
2823
        continue;
×
2824
      }
2825
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
2✔
2826
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
2✔
2827
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
×
2828
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2829
    }
2830
    struct STm tm;
2831
    TAOS_CHECK_RETURN(taosTs2Tm(timeVal, timePrec, &tm, pInput->tz));
10✔
2832
    int64_t ret = startFromZero ?  (tm.tm.tm_wday + 6) % 7 : tm.tm.tm_wday + 1;
10✔
2833
    colDataSetInt64(pOutput->columnData, i, &ret);
10✔
2834
  }
2835

2836
  pOutput->numOfRows = pInput->numOfRows;
10✔
2837

2838
  return TSDB_CODE_SUCCESS;
10✔
2839
}
2840

2841
int32_t weekdayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
5✔
2842
  return weekdayFunctionImpl(pInput, inputNum, pOutput, true);
5✔
2843
}
2844

2845
int32_t dayofweekFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
5✔
2846
  return weekdayFunctionImpl(pInput, inputNum, pOutput, false);
5✔
2847
}
2848

2849
// calculate day number from 0000-00-00
2850
static int32_t getDayNum(int32_t year, int32_t month, int32_t day) {
30✔
2851
  int32_t delsum;
2852
  int32_t temp;
2853
  int32_t y = year;
30✔
2854

2855
  if (y == 0 && month == 0) {
30✔
2856
    return 0;
×
2857
  }
2858

2859
  delsum = 365 * y + 31 * (month - 1) + day;
30✔
2860
  if (month <= 2)
30✔
2861
    y--;
28✔
2862
  else
2863
    delsum -= (month * 4 + 23) / 10;
2✔
2864
  temp = ((y / 100 + 1) * 3) / 4;
30✔
2865
  return (delsum + y / 4 - temp);
30✔
2866
}
2867

2868
static int32_t getDaysInYear(int32_t year) {
16✔
2869
  return (((year % 100) == 0) ? ((year % 400) == 0) : ((year % 4) == 0)) ? 366 : 365;
16✔
2870
}
2871

2872
static int32_t getWeekday(int32_t daynr, bool sundayFirstDay) {
15✔
2873
  return (daynr + 5 + (sundayFirstDay ? 1 : 0)) % 7;
15✔
2874
}
2875

2876
static int32_t calculateWeekNum(struct tm date, int32_t weekFlag) {
15✔
2877
  int32_t days;
2878
  int32_t year = date.tm_year + 1900;
15✔
2879
  int32_t month = date.tm_mon + 1;
15✔
2880
  int32_t day = date.tm_mday;
15✔
2881
  int32_t dayNum = getDayNum(year, month, day);
15✔
2882
  int32_t firstDayNum = getDayNum(year, 1, 1);
15✔
2883
  bool mondayFirst = (weekFlag & WEEK_FLAG_MONDAY_FIRST);
15✔
2884
  bool weekStartFromOne = (weekFlag & WEEK_FLAG_FROM_ONE);
15✔
2885
  bool firstWeekday = (weekFlag & WEEK_FLAG_INCLUDE_FIRST_DAY);
15✔
2886

2887
  int32_t weekday = getWeekday(firstDayNum, !mondayFirst);
15✔
2888
  if (month == 1 && day <= 7 - weekday) {
15✔
2889
    if (!weekStartFromOne && ((firstWeekday && weekday != 0) || (!firstWeekday && weekday >= 4))) {
10✔
2890
      return 0;
2✔
2891
    }
2892
    weekStartFromOne = true;
8✔
2893
    days = getDaysInYear(--year);
8✔
2894
    firstDayNum -= days;
8✔
2895
    weekday = (weekday + 53 * 7 - days) % 7;
8✔
2896
  }
2897

2898
  if ((firstWeekday && weekday != 0) || (!firstWeekday && weekday >= 4))
13✔
2899
    days = dayNum - (firstDayNum + (7 - weekday));
13✔
2900
  else
2901
    days = dayNum - (firstDayNum - weekday);
×
2902

2903
  if (weekStartFromOne && days >= 52 * 7) {
13✔
2904
    weekday = (weekday + getDaysInYear(year)) % 7;
8✔
2905
    if ((!firstWeekday && weekday < 4) || (firstWeekday && weekday == 0)) {
8✔
2906
      return 1;
8✔
2907
    }
2908
  }
2909
  return days / 7 + 1;
5✔
2910
}
2911

2912
static int32_t weekMode(int32_t mode) {
15✔
2913
  return mode & WEEK_FLAG_MONDAY_FIRST ? mode : mode ^ WEEK_FLAG_INCLUDE_FIRST_DAY;
15✔
2914
}
2915

2916
int32_t weekFunctionImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, int64_t prec, int32_t mode) {
15✔
2917
  int32_t type = GET_PARAM_TYPE(&pInput[0]);
15✔
2918

2919
  int64_t timeVal = 0;
15✔
2920

2921
  for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
30✔
2922
    if (colDataIsNull_s(pInput[0].columnData, i)) {
30✔
2923
      colDataSetNULL(pOutput->columnData, i);
×
2924
      continue;
×
2925
    }
2926

2927
    char *input = colDataGetData(pInput[0].columnData, i);
15✔
2928

2929
    if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
27✔
2930
      int32_t ret = convertStringToTimestamp(type, input, prec, &timeVal, pInput->tz, pInput->charsetCxt);
12✔
2931
      if (ret != TSDB_CODE_SUCCESS) {
12✔
2932
        colDataSetNULL(pOutput->columnData, i);
×
2933
        continue;
×
2934
      }
2935
    } else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
3✔
2936
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
3✔
2937
    } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
×
2938
      GET_TYPED_DATA(timeVal, int64_t, type, input, typeGetTypeModFromColInfo(&pInput[0].columnData->info));
×
2939
    }
2940
    struct STm tm;
2941
    SCL_ERR_RET(taosTs2Tm(timeVal, prec, &tm, pInput->tz));
15✔
2942
    int64_t ret = calculateWeekNum(tm.tm, weekMode(mode));
15✔
2943
    colDataSetInt64(pOutput->columnData, i, &ret);
15✔
2944
  }
2945

2946
  pOutput->numOfRows = pInput->numOfRows;
15✔
2947

2948
  return TSDB_CODE_SUCCESS;
15✔
2949
}
2950

2951
int32_t weekFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10✔
2952
  int64_t timePrec;
2953
  int32_t mode = 0;
10✔
2954
  if (inputNum == 2) {
10✔
2955
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
5✔
2956
                   typeGetTypeModFromColInfo(&pInput[1].columnData->info));
2957
    return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, mode);
5✔
2958
  } else {
2959
    GET_TYPED_DATA(mode, int32_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
5✔
2960
                   typeGetTypeModFromColInfo(&pInput[1].columnData->info));
2961
    GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData,
5✔
2962
                   typeGetTypeModFromColInfo(&pInput[2].columnData->info));
2963
    return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, mode);
5✔
2964
  }
2965
}
2966

2967
int32_t weekofyearFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
5✔
2968
  int64_t timePrec;
2969
  GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
5✔
2970
                 typeGetTypeModFromColInfo(&pInput[1].columnData->info));
2971
  return weekFunctionImpl(pInput, inputNum, pOutput, timePrec, 3);
5✔
2972
}
2973

2974
int32_t atanFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
16✔
2975
  return doScalarFunctionUnique(pInput, inputNum, pOutput, atan);
16✔
2976
}
2977

2978
int32_t sinFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10,096✔
2979
  return doScalarFunctionUnique(pInput, inputNum, pOutput, sin);
10,096✔
2980
}
2981

2982
int32_t cosFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
13✔
2983
  return doScalarFunctionUnique(pInput, inputNum, pOutput, cos);
13✔
2984
}
2985

2986
int32_t tanFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10✔
2987
  return doScalarFunctionUnique(pInput, inputNum, pOutput, tan);
10✔
2988
}
2989

2990
int32_t asinFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10✔
2991
  return doScalarFunctionUnique(pInput, inputNum, pOutput, asin);
10✔
2992
}
2993

2994
int32_t acosFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10✔
2995
  return doScalarFunctionUnique(pInput, inputNum, pOutput, acos);
10✔
2996
}
2997

2998
int32_t powFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
12,114✔
2999
  return doScalarFunctionUnique2(pInput, inputNum, pOutput, pow);
12,114✔
3000
}
3001

3002
int32_t logFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2,032✔
3003
  if (inputNum == 1) {
2,032✔
3004
    return doScalarFunctionUnique(pInput, inputNum, pOutput, tlog);
2,026✔
3005
  } else {
3006
    return doScalarFunctionUnique2(pInput, inputNum, pOutput, tlog2);
6✔
3007
  }
3008
}
3009

3010
int32_t sqrtFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
10✔
3011
  return doScalarFunctionUnique(pInput, inputNum, pOutput, sqrt);
10✔
3012
}
3013

3014
int32_t ceilFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2,041✔
3015
  return doScalarFunction(pInput, inputNum, pOutput, ceilf, ceil);
2,041✔
3016
}
3017

3018
int32_t floorFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
21✔
3019
  return doScalarFunction(pInput, inputNum, pOutput, floorf, floor);
21✔
3020
}
3021

3022
int32_t randFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3023
  int32_t seed;
3024
  int32_t numOfRows = inputNum == 1 ? pInput[0].numOfRows : TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
×
3025
  for (int32_t i = 0; i < numOfRows; ++i) {
×
3026
    // for constant seed, only set seed once
3027
    if ((pInput[0].numOfRows == 1 && i == 0) || (pInput[0].numOfRows != 1)) {
×
3028
      if (!IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) && !colDataIsNull_s(pInput[0].columnData, i)) {
×
3029
        GET_TYPED_DATA(seed, int32_t, GET_PARAM_TYPE(&pInput[0]), colDataGetData(pInput[0].columnData, i),
×
3030
                       typeGetTypeModFromColInfo(&pInput[0].columnData->info));
3031
        taosSeedRand(seed);
×
3032
      }
3033
    }
3034
    double random_value = (double)(taosRand() % RAND_MAX) / RAND_MAX;
×
3035
    colDataSetDouble(pOutput->columnData, i, &random_value);
×
3036
  }
3037
  pOutput->numOfRows = numOfRows;
×
3038
  return TSDB_CODE_SUCCESS;
×
3039
}
3040

3041
static double decimalFn(double val1, double val2, _double_fn fn) {
×
3042
  if (val1 > DBL_MAX || val1 < -DBL_MAX) {
×
3043
    return val1;
×
3044
  }
3045

3046
  double scale = pow(10, val2);
×
3047

3048
  if (val2 < 0) {
×
3049
    return fn(val1 * scale) / scale;
×
3050
  } else {
3051
    double scaled_number = val1 * scale;
×
3052

3053
    if (scaled_number > DBL_MAX || scaled_number < -DBL_MAX) {
×
3054
      return val1;
×
3055
    }
3056

3057
    return fn(scaled_number) / scale;
×
3058
  }
3059
}
3060

3061
static float decimalfFn(float val1, float val2, _float_fn fn) {
×
3062
  if (val1 > FLT_MAX || val1 < -FLT_MAX) {
×
3063
    return val1;
×
3064
  }
3065

3066
  float scale = powf(10, val2);
×
3067

3068
  if (val2 < 0) {
×
3069
    return fn(val1 * scale) / scale;
×
3070
  } else {
3071
    float scaled_number = val1 * scale;
×
3072

3073
    if (scaled_number > FLT_MAX || scaled_number < -FLT_MAX) {
×
3074
      return val1;
×
3075
    }
3076

3077
    return fn(scaled_number) / scale;
×
3078
  }
3079
}
3080

3081
static double roundFn(double val1, double val2) {
×
3082
  return decimalFn(val1, val2, round);
×
3083
}
3084

3085
static float roundfFn(float val1, float val2) {
×
3086
  return decimalfFn(val1, val2, roundf);
×
3087
}
3088

3089
static double truncFn(double val1, double val2) {
×
3090
  return decimalFn(val1, val2, trunc);
×
3091
}
3092

3093
static float truncfFn(float val1, float val2) {
×
3094
  return decimalfFn(val1, val2, truncf);
×
3095
}
3096

3097
static int32_t doScalarFunction2(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, _float_fn_2 f1,
×
3098
                                 _double_fn_2 d1) {
3099
  SColumnInfoData     *pInputData[2];
3100
  SColumnInfoData     *pOutputData = pOutput->columnData;
×
3101
  _getDoubleValue_fn_t getValueFn[2];
3102

3103
  for (int32_t i = 0; i < inputNum; ++i) {
×
3104
    pInputData[i] = pInput[i].columnData;
×
3105
    SCL_ERR_RET(getVectorDoubleValueFn(GET_PARAM_TYPE(&pInput[i]), &getValueFn[i]));
×
3106
  }
3107

3108
  bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
×
3109

3110
  int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
×
3111
  for (int32_t i = 0; i < numOfRows; ++i) {
×
3112
    int32_t colIdx1 = (pInput[0].numOfRows == 1) ? 0 : i;
×
3113
    int32_t colIdx2 = (pInput[1].numOfRows == 1) ? 0 : i;
×
3114
    if (colDataIsNull_s(pInputData[0], colIdx1) || colDataIsNull_s(pInputData[1], colIdx2) || hasNullType) {
×
3115
      colDataSetNULL(pOutputData, i);
×
3116
      continue;
×
3117
    }
3118
    double in2;
3119
    GET_TYPED_DATA(in2, double, GET_PARAM_TYPE(&pInput[1]), colDataGetData(pInputData[1], colIdx2),
×
3120
                   typeGetTypeModFromColInfo(&pInputData[1]->info));
3121
    switch (GET_PARAM_TYPE(&pInput[0])) {
×
3122
      case TSDB_DATA_TYPE_DOUBLE: {
×
3123
        double  *in = (double *)pInputData[0]->pData;
×
3124
        double  *out = (double *)pOutputData->pData;
×
3125
        double  result = d1(in[colIdx1], in2);
×
3126
        if (isinf(result) || isnan(result)) {
×
3127
          colDataSetNULL(pOutputData, i);
×
3128
        } else {
3129
          out[i] = result;
×
3130
        }
3131
        break;
×
3132
      }
3133
      case TSDB_DATA_TYPE_FLOAT: {
×
3134
        float   *in = (float *)pInputData[0]->pData;
×
3135
        float   *out = (float *)pOutputData->pData;
×
3136
        float   result = f1(in[colIdx1], (float)in2);
×
3137
        if (isinf(result) || isnan(result)) {
×
3138
          colDataSetNULL(pOutputData, i);
×
3139
        } else {
3140
          out[i] = result;
×
3141
        }
3142
        break;
×
3143
      }
3144
      case TSDB_DATA_TYPE_TINYINT: {
×
3145
        int8_t *in = (int8_t *)pInputData[0]->pData;
×
3146
        int8_t *out = (int8_t *)pOutputData->pData;
×
3147
        int8_t result = (int8_t)d1((double)in[colIdx1], in2);
×
3148
        out[i] = result;
×
3149
        break;
×
3150
      }
3151
      case TSDB_DATA_TYPE_SMALLINT: {
×
3152
        int16_t *in = (int16_t *)pInputData[0]->pData;
×
3153
        int16_t *out = (int16_t *)pOutputData->pData;
×
3154
        int16_t result = (int16_t)d1((double)in[colIdx1], in2);
×
3155
        out[i] = result;
×
3156
        break;
×
3157
      }
3158
      case TSDB_DATA_TYPE_INT: {
×
3159
        int32_t *in = (int32_t *)pInputData[0]->pData;
×
3160
        int32_t *out = (int32_t *)pOutputData->pData;
×
3161
        int32_t result = (int32_t)d1((double)in[colIdx1], in2);
×
3162
        out[i] = result;
×
3163
        break;
×
3164
      }
3165
      case TSDB_DATA_TYPE_BIGINT: {
×
3166
        int64_t *in = (int64_t *)pInputData[0]->pData;
×
3167
        int64_t *out = (int64_t *)pOutputData->pData;
×
3168
        int64_t result = (int64_t)d1((double)in[colIdx1], in2);
×
3169
        out[i] = result;
×
3170
        break;
×
3171
      }
3172
      case TSDB_DATA_TYPE_UTINYINT: {
×
3173
        uint8_t *in = (uint8_t *)pInputData[0]->pData;
×
3174
        uint8_t *out = (uint8_t *)pOutputData->pData;
×
3175
        uint8_t result = (uint8_t)d1((double)in[colIdx1], in2);
×
3176
        out[i] = result;
×
3177
        break;
×
3178
      }
3179
      case TSDB_DATA_TYPE_USMALLINT: {
×
3180
        uint16_t *in = (uint16_t *)pInputData[0]->pData;
×
3181
        uint16_t *out = (uint16_t *)pOutputData->pData;
×
3182
        uint16_t result = (uint16_t)d1((double)in[colIdx1], in2);
×
3183
        out[i] = result;
×
3184
        break;
×
3185
      }
3186
      case TSDB_DATA_TYPE_UINT: {
×
3187
        uint32_t *in = (uint32_t *)pInputData[0]->pData;
×
3188
        uint32_t *out = (uint32_t *)pOutputData->pData;
×
3189
        uint32_t result = (uint32_t)d1((double)in[colIdx1], in2);
×
3190
        out[i] = result;
×
3191
        break;
×
3192
      }
3193
      case TSDB_DATA_TYPE_UBIGINT: {
×
3194
        uint64_t *in = (uint64_t *)pInputData[0]->pData;
×
3195
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3196
        uint64_t result = (uint64_t)d1((double)in[colIdx1], in2);
×
3197
        out[i] = result;
×
3198
        break;
×
3199
      }
3200
    }
3201
  }
×
3202

3203
  pOutput->numOfRows = numOfRows;
×
3204
  return TSDB_CODE_SUCCESS;
×
3205
}
3206

3207
int32_t roundFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
11✔
3208
  if (inputNum == 1) {
11✔
3209
    return doScalarFunction(pInput, inputNum, pOutput, roundf, round);
11✔
3210
  } else {
3211
    return doScalarFunction2(pInput, inputNum, pOutput, roundfFn, roundFn);
×
3212
  }
3213
}
3214

3215
int32_t truncFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3216
  return doScalarFunction2(pInput, inputNum, pOutput, truncfFn, truncFn);
×
3217
}
3218

3219
int32_t piFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3220
  double_t value = M_PI;
×
3221
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3222
    colDataSetDouble(pOutput->columnData, i, &value);
×
3223
  }
3224
  pOutput->numOfRows = pInput->numOfRows;
×
3225
  return TSDB_CODE_SUCCESS;
×
3226
}
3227

3228
int32_t expFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3229
  return doScalarFunctionUnique(pInput, inputNum, pOutput, exp);
×
3230
}
3231

3232
int32_t lnFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3233
  return doScalarFunctionUnique(pInput, inputNum, pOutput, tlog);
×
3234
}
3235

3236
int32_t modFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3237
  return doScalarFunctionUnique2(pInput, inputNum, pOutput, fmod);
×
3238
}
3239

3240
int32_t degreesFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3241
  return doScalarFunctionUnique(pInput, inputNum, pOutput, degrees);
×
3242
}
3243

3244
int32_t radiansFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3245
  return doScalarFunctionUnique(pInput, inputNum, pOutput, radians);
×
3246
}
3247

3248
int32_t lowerFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
3249
#ifdef WINDOWS
3250
  return doCaseConvFunction(pInput, inputNum, pOutput, towlower);
3251
#else
3252
  return doCaseConvFunction(pInput, inputNum, pOutput, tolower);
6✔
3253
#endif
3254
}
3255

3256
int32_t upperFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
3257
#ifdef WINDOWS
3258
  return doCaseConvFunction(pInput, inputNum, pOutput, towupper);
3259
#else
3260
  return doCaseConvFunction(pInput, inputNum, pOutput, toupper);
6✔
3261
#endif
3262
}
3263

3264
int32_t ltrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
3265
  return doTrimFunction(pInput, inputNum, pOutput, tltrimspace, tltrim);
6✔
3266
}
3267

3268
int32_t rtrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6✔
3269
  return doTrimFunction(pInput, inputNum, pOutput, trtrimspace, tltrim);
6✔
3270
}
3271

3272
int32_t lengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
8✔
3273
  return doLengthFunction(pInput, inputNum, pOutput, tlength);
8✔
3274
}
3275

3276
int32_t charLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
2✔
3277
  return doLengthFunction(pInput, inputNum, pOutput, tcharlength);
2✔
3278
}
3279

3280
bool getTimePseudoFuncEnv(SFunctionNode *UNUSED_PARAM(pFunc), SFuncExecEnv *pEnv) {
147✔
3281
  pEnv->calcMemSize = sizeof(int64_t);
147✔
3282
  return true;
147✔
3283
}
3284

3285
#ifdef BUILD_NO_CALL
3286
int32_t qStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3287
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 0));
3288
  return TSDB_CODE_SUCCESS;
3289
}
3290

3291
int32_t qEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3292
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 1));
3293
  return TSDB_CODE_SUCCESS;
3294
}
3295
#endif
3296

3297
int32_t winDurFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
77✔
3298
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 2));
77✔
3299
  return TSDB_CODE_SUCCESS;
77✔
3300
}
3301

3302
int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
3,290✔
3303
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 3));
3,290✔
3304
  return TSDB_CODE_SUCCESS;
3,290✔
3305
}
3306

3307
int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
81✔
3308
  colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 4));
81✔
3309
  return TSDB_CODE_SUCCESS;
81✔
3310
}
3311

3312
int32_t isWinFilledFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3313
  int8_t data = 0;
×
3314
  colDataSetInt8(pOutput->columnData, pOutput->numOfRows, &data);
×
3315
  return TSDB_CODE_SUCCESS;
×
3316
}
3317

3318
int32_t qPseudoTagFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
6,562✔
3319
  char   *p = colDataGetData(pInput->columnData, 0);
6,562✔
3320
  int32_t code = colDataSetNItems(pOutput->columnData, pOutput->numOfRows, p, pInput->numOfRows, true);
6,562✔
3321
  if (code) {
6,563✔
3322
    return code;
×
3323
  }
3324
  
3325
  pOutput->numOfRows += pInput->numOfRows;
6,563✔
3326
  return TSDB_CODE_SUCCESS;
6,563✔
3327
}
3328

3329
/** Aggregation functions **/
3330
int32_t countScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3331
  SColumnInfoData *pInputData = pInput->columnData;
×
3332
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3333

3334
  int64_t *out = (int64_t *)pOutputData->pData;
×
3335
  *out = 0;
×
3336
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3337
    if (colDataIsNull_s(pInputData, i)) {
×
3338
      continue;
×
3339
    }
3340
    (*out)++;
×
3341
  }
3342

3343
  pOutput->numOfRows = 1;
×
3344
  return TSDB_CODE_SUCCESS;
×
3345
}
3346

3347
int32_t sumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3348
  SColumnInfoData *pInputData = pInput->columnData;
×
3349
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3350

3351
  int32_t type = GET_PARAM_TYPE(pInput);
×
3352
  bool    hasNull = false;
×
3353
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3354
    if (colDataIsNull_s(pInputData, i)) {
×
3355
      hasNull = true;
×
3356
      break;
×
3357
    }
3358

3359
    if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) {
×
3360
      int64_t *out = (int64_t *)pOutputData->pData;
×
3361
      if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) {
×
3362
        int8_t *in = (int8_t *)pInputData->pData;
×
3363
        *out += in[i];
×
3364
      } else if (type == TSDB_DATA_TYPE_SMALLINT) {
×
3365
        int16_t *in = (int16_t *)pInputData->pData;
×
3366
        *out += in[i];
×
3367
      } else if (type == TSDB_DATA_TYPE_INT) {
×
3368
        int32_t *in = (int32_t *)pInputData->pData;
×
3369
        *out += in[i];
×
3370
      } else if (type == TSDB_DATA_TYPE_BIGINT) {
×
3371
        int64_t *in = (int64_t *)pInputData->pData;
×
3372
        *out += in[i];
×
3373
      }
3374
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
3375
      uint64_t *out = (uint64_t *)pOutputData->pData;
×
3376
      if (type == TSDB_DATA_TYPE_UTINYINT) {
×
3377
        uint8_t *in = (uint8_t *)pInputData->pData;
×
3378
        *out += in[i];
×
3379
      } else if (type == TSDB_DATA_TYPE_USMALLINT) {
×
3380
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3381
        *out += in[i];
×
3382
      } else if (type == TSDB_DATA_TYPE_UINT) {
×
3383
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3384
        *out += in[i];
×
3385
      } else if (type == TSDB_DATA_TYPE_UBIGINT) {
×
3386
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3387
        *out += in[i];
×
3388
      }
3389
    } else if (IS_FLOAT_TYPE(type)) {
×
3390
      double *out = (double *)pOutputData->pData;
×
3391
      if (type == TSDB_DATA_TYPE_FLOAT) {
×
3392
        float *in = (float *)pInputData->pData;
×
3393
        *out += in[i];
×
3394
      } else if (type == TSDB_DATA_TYPE_DOUBLE) {
×
3395
        double *in = (double *)pInputData->pData;
×
3396
        *out += in[i];
×
3397
      }
3398
    } else if (type == TSDB_DATA_TYPE_DECIMAL) {
×
3399
      Decimal128* pOut = (Decimal128*)pOutputData->pData;
×
3400
      if (type == TSDB_DATA_TYPE_DECIMAL64) {
×
3401
        const Decimal64* pIn = (Decimal64*)pInputData->pData;
×
3402
        const SDecimalOps *pOps = getDecimalOps(type);
×
3403
        pOps->add(pOut, pIn + i, DECIMAL_WORD_NUM(Decimal64));
×
3404
      } else if (type == TSDB_DATA_TYPE_DECIMAL) {
×
3405
        const Decimal128* pIn = (Decimal128*)pInputData->pData;
×
3406
        const SDecimalOps *pOps = getDecimalOps(type);
×
3407
        pOps->add(pOut, pIn + i, DECIMAL_WORD_NUM(Decimal128));
×
3408
      }
3409
    }
3410
  }
3411

3412
  if (hasNull) {
×
3413
    colDataSetNULL(pOutputData, 0);
3414
  }
3415

3416
  pOutput->numOfRows = 1;
×
3417
  return TSDB_CODE_SUCCESS;
×
3418
}
3419

3420
static int32_t doMinMaxScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, bool isMinFunc) {
×
3421
  SColumnInfoData *pInputData = pInput->columnData;
×
3422
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3423

3424
  int32_t type = GET_PARAM_TYPE(pInput);
×
3425

3426
  bool hasNull = false;
×
3427
  if (isMinFunc) {
×
3428
    SET_TYPED_DATA_MAX(pOutputData->pData, type);
×
3429
  } else {
3430
    SET_TYPED_DATA_MIN(pOutputData->pData, type);
×
3431
  }
3432

3433
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3434
    if (colDataIsNull_s(pInputData, i)) {
×
3435
      hasNull = true;
×
3436
      break;
×
3437
    }
3438

3439
    switch (type) {
×
3440
      case TSDB_DATA_TYPE_BOOL:
×
3441
      case TSDB_DATA_TYPE_TINYINT: {
3442
        int8_t *in = (int8_t *)pInputData->pData;
×
3443
        int8_t *out = (int8_t *)pOutputData->pData;
×
3444
        if ((in[i] > *out) ^ isMinFunc) {
×
3445
          *out = in[i];
×
3446
        }
3447
        break;
×
3448
      }
3449
      case TSDB_DATA_TYPE_SMALLINT: {
×
3450
        int16_t *in = (int16_t *)pInputData->pData;
×
3451
        int16_t *out = (int16_t *)pOutputData->pData;
×
3452
        if ((in[i] > *out) ^ isMinFunc) {
×
3453
          *out = in[i];
×
3454
        }
3455
        break;
×
3456
      }
3457
      case TSDB_DATA_TYPE_INT: {
×
3458
        int32_t *in = (int32_t *)pInputData->pData;
×
3459
        int32_t *out = (int32_t *)pOutputData->pData;
×
3460
        if ((in[i] > *out) ^ isMinFunc) {
×
3461
          *out = in[i];
×
3462
        }
3463
        break;
×
3464
      }
3465
      case TSDB_DATA_TYPE_BIGINT: {
×
3466
        int64_t *in = (int64_t *)pInputData->pData;
×
3467
        int64_t *out = (int64_t *)pOutputData->pData;
×
3468
        if ((in[i] > *out) ^ isMinFunc) {
×
3469
          *out = in[i];
×
3470
        }
3471
        break;
×
3472
      }
3473
      case TSDB_DATA_TYPE_UTINYINT: {
×
3474
        uint8_t *in = (uint8_t *)pInputData->pData;
×
3475
        uint8_t *out = (uint8_t *)pOutputData->pData;
×
3476
        if ((in[i] > *out) ^ isMinFunc) {
×
3477
          *out = in[i];
×
3478
        }
3479
        break;
×
3480
      }
3481
      case TSDB_DATA_TYPE_USMALLINT: {
×
3482
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3483
        uint16_t *out = (uint16_t *)pOutputData->pData;
×
3484
        if ((in[i] > *out) ^ isMinFunc) {
×
3485
          *out = in[i];
×
3486
        }
3487
        break;
×
3488
      }
3489
      case TSDB_DATA_TYPE_UINT: {
×
3490
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3491
        uint32_t *out = (uint32_t *)pOutputData->pData;
×
3492
        if ((in[i] > *out) ^ isMinFunc) {
×
3493
          *out = in[i];
×
3494
        }
3495
        break;
×
3496
      }
3497
      case TSDB_DATA_TYPE_UBIGINT: {
×
3498
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3499
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3500
        if ((in[i] > *out) ^ isMinFunc) {
×
3501
          *out = in[i];
×
3502
        }
3503
        break;
×
3504
      }
3505
      case TSDB_DATA_TYPE_FLOAT: {
×
3506
        float *in = (float *)pInputData->pData;
×
3507
        float *out = (float *)pOutputData->pData;
×
3508
        if ((in[i] > *out) ^ isMinFunc) {
×
3509
          *out = in[i];
×
3510
        }
3511
        break;
×
3512
      }
3513
      case TSDB_DATA_TYPE_DOUBLE: {
×
3514
        double *in = (double *)pInputData->pData;
×
3515
        double *out = (double *)pOutputData->pData;
×
3516
        if ((in[i] > *out) ^ isMinFunc) {
×
3517
          *out = in[i];
×
3518
        }
3519
        break;
×
3520
      }
3521
      case TSDB_DATA_TYPE_DECIMAL64: {
×
3522
        Decimal64* p1 = (Decimal64*)pInputData->pData;
×
3523
        Decimal64* p2 = (Decimal64*)pOutputData->pData;
×
3524
        const SDecimalOps *pOps = getDecimalOps(type);
×
3525
        if (pOps->gt(p1 + i, p2, DECIMAL_WORD_NUM(Decimal64)) ^ isMinFunc) {
×
3526
          *p2 = p1[i];
×
3527
        }
3528
        break;
×
3529
      }
3530
      case TSDB_DATA_TYPE_DECIMAL: {
×
3531
        Decimal128 *p1 = (Decimal128 *)pInputData->pData;
×
3532
        Decimal128 *p2 = (Decimal128 *)pOutputData->pData;
×
3533
        const SDecimalOps *pOps = getDecimalOps(type);
×
3534
        if (pOps->gt(p1 + i, p2, DECIMAL_WORD_NUM(Decimal128)) ^ isMinFunc) {
×
3535
          *p2 = p1[i];
×
3536
        }
3537
        break;
×
3538
      }
3539
    }
3540
  }
×
3541

3542
  if (hasNull) {
×
3543
    colDataSetNULL(pOutputData, 0);
3544
  }
3545

3546
  pOutput->numOfRows = 1;
×
3547
  return TSDB_CODE_SUCCESS;
×
3548
}
3549

3550
int32_t minScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3551
  return doMinMaxScalarFunction(pInput, inputNum, pOutput, true);
×
3552
}
3553

3554
int32_t maxScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3555
  return doMinMaxScalarFunction(pInput, inputNum, pOutput, false);
×
3556
}
3557

3558
int32_t avgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3559
  SColumnInfoData *pInputData = pInput->columnData;
×
3560
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3561

3562
  int32_t type = GET_PARAM_TYPE(pInput);
×
3563
  int64_t count = 0;
×
3564
  bool    hasNull = false;
×
3565

3566
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3567
    if (colDataIsNull_s(pInputData, i)) {
×
3568
      hasNull = true;
×
3569
      break;
×
3570
    }
3571

3572
    switch (type) {
×
3573
      case TSDB_DATA_TYPE_TINYINT: {
×
3574
        int8_t  *in = (int8_t *)pInputData->pData;
×
3575
        int64_t *out = (int64_t *)pOutputData->pData;
×
3576
        *out += in[i];
×
3577
        count++;
×
3578
        break;
×
3579
      }
3580
      case TSDB_DATA_TYPE_SMALLINT: {
×
3581
        int16_t *in = (int16_t *)pInputData->pData;
×
3582
        int64_t *out = (int64_t *)pOutputData->pData;
×
3583
        *out += in[i];
×
3584
        count++;
×
3585
        break;
×
3586
      }
3587
      case TSDB_DATA_TYPE_INT: {
×
3588
        int32_t *in = (int32_t *)pInputData->pData;
×
3589
        int64_t *out = (int64_t *)pOutputData->pData;
×
3590
        *out += in[i];
×
3591
        count++;
×
3592
        break;
×
3593
      }
3594
      case TSDB_DATA_TYPE_BIGINT: {
×
3595
        int64_t *in = (int64_t *)pInputData->pData;
×
3596
        int64_t *out = (int64_t *)pOutputData->pData;
×
3597
        *out += in[i];
×
3598
        count++;
×
3599
        break;
×
3600
      }
3601
      case TSDB_DATA_TYPE_UTINYINT: {
×
3602
        uint8_t  *in = (uint8_t *)pInputData->pData;
×
3603
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3604
        *out += in[i];
×
3605
        count++;
×
3606
        break;
×
3607
      }
3608
      case TSDB_DATA_TYPE_USMALLINT: {
×
3609
        uint16_t *in = (uint16_t *)pInputData->pData;
×
3610
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3611
        *out += in[i];
×
3612
        count++;
×
3613
        break;
×
3614
      }
3615
      case TSDB_DATA_TYPE_UINT: {
×
3616
        uint32_t *in = (uint32_t *)pInputData->pData;
×
3617
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3618
        *out += in[i];
×
3619
        count++;
×
3620
        break;
×
3621
      }
3622
      case TSDB_DATA_TYPE_UBIGINT: {
×
3623
        uint64_t *in = (uint64_t *)pInputData->pData;
×
3624
        uint64_t *out = (uint64_t *)pOutputData->pData;
×
3625
        *out += in[i];
×
3626
        count++;
×
3627
        break;
×
3628
      }
3629
      case TSDB_DATA_TYPE_FLOAT: {
×
3630
        float *in = (float *)pInputData->pData;
×
3631
        double *out = (double *)pOutputData->pData;
×
3632
        *out += in[i];
×
3633
        count++;
×
3634
        break;
×
3635
      }
3636
      case TSDB_DATA_TYPE_DOUBLE: {
×
3637
        double *in = (double *)pInputData->pData;
×
3638
        double *out = (double *)pOutputData->pData;
×
3639
        *out += in[i];
×
3640
        count++;
×
3641
        break;
×
3642
      }
3643
      case TSDB_DATA_TYPE_DECIMAL64: {
×
3644
        const Decimal64   *in = (Decimal64 *)pInputData->pData;
×
3645
        Decimal128        *out = (Decimal128 *)pOutputData->pData;
×
3646
        const SDecimalOps *pOps = getDecimalOps(type);
×
3647
        // check overflow
3648
        pOps->add(out, in + i, DECIMAL_WORD_NUM(Decimal64));
×
3649
        count++;
×
3650
      } break;
×
3651
      case TSDB_DATA_TYPE_DECIMAL: {
×
3652
        const Decimal128  *in = (Decimal128 *)pInputData->pData;
×
3653
        Decimal128        *out = (Decimal128 *)pOutputData->pData;
×
3654
        const SDecimalOps *pOps = getDecimalOps(type);
×
3655
        // check overflow
3656
        pOps->add(out, in + i, DECIMAL_WORD_NUM(Decimal128));
×
3657
        count++;
×
3658
      } break;
×
3659
    }
3660
  }
×
3661

3662
  if (hasNull || (count == 0)) {
×
3663
    colDataSetNULL(pOutputData, 0);
×
3664
  } else {
3665
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
3666
      int64_t *out = (int64_t *)pOutputData->pData;
×
3667
      *(double *)out = *out / (double)count;
×
3668
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
3669
      uint64_t *out = (uint64_t *)pOutputData->pData;
×
3670
      *(double *)out = *out / (double)count;
×
3671
    } else if (IS_FLOAT_TYPE(type)) {
×
3672
      double *out = (double *)pOutputData->pData;
×
3673
      *(double *)out = *out / (double)count;
×
3674
    } else if (IS_DECIMAL_TYPE(type)) {
×
3675
      Decimal128 *out = (Decimal128 *)pOutputData->pData;
×
3676
      SDataType   sumDt = {.type = TSDB_DATA_TYPE_DECIMAL,
×
3677
                           .bytes = DECIMAL128_BYTES,
3678
                           .precision = TSDB_DECIMAL128_MAX_PRECISION,
3679
                           .scale = pInputData->info.scale};
×
3680
      SDataType   countDt = {
×
3681
            .type = TSDB_DATA_TYPE_BIGINT, .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .precision = 0, .scale = 0};
×
3682
      SDataType avgDt = {.type = TSDB_DATA_TYPE_DECIMAL,
×
3683
                         .bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes,
×
3684
                         .precision = pOutputData->info.precision,
×
3685
                         .scale = pOutputData->info.scale};
×
3686
      int32_t   code = decimalOp(OP_TYPE_DIV, &sumDt, &countDt, &avgDt, out, &count, out);
×
3687
      if (code != 0) return code;
×
3688
    }
3689
  }
3690

3691
  pOutput->numOfRows = 1;
×
3692
  return TSDB_CODE_SUCCESS;
×
3693
}
3694

3695
int32_t stdScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3696
  SColumnInfoData *pInputData = pInput->columnData;
×
3697
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3698

3699
  int32_t type = GET_PARAM_TYPE(pInput);
×
3700
  // int64_t count = 0, sum = 0, qSum = 0;
3701
  bool hasNull = false;
×
3702

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

3784
  double *out = (double *)pOutputData->pData;
×
3785
  if (hasNull) {
×
3786
    colDataSetNULL(pOutputData, 0);
3787
  } else {
3788
    *out = 0;
×
3789
#if 0
3790
    double avg = 0;
3791
    if (IS_SIGNED_NUMERIC_TYPE(type)) {
3792
      avg = (int64_t)sum / (double)count;
3793
      *out =  sqrt(fabs((int64_t)qSum / ((double)count) - avg * avg));
3794
    } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
3795
      avg = (uint64_t)sum / (double)count;
3796
      *out =  sqrt(fabs((uint64_t)qSum / ((double)count) - avg * avg));
3797
    } else if (IS_FLOAT_TYPE(type)) {
3798
      avg = (double)sum / (double)count;
3799
      *out =  sqrt(fabs((double)qSum / ((double)count) - avg * avg));
3800
    }
3801
#endif
3802
  }
3803

3804
  pOutput->numOfRows = 1;
×
3805
  return TSDB_CODE_SUCCESS;
×
3806
}
3807

3808
#define LEASTSQR_CAL(p, x, y, index, step) \
3809
  do {                                     \
3810
    (p)[0][0] += (double)(x) * (x);        \
3811
    (p)[0][1] += (double)(x);              \
3812
    (p)[0][2] += (double)(x) * (y)[index]; \
3813
    (p)[1][2] += (y)[index];               \
3814
    (x) += step;                           \
3815
  } while (0)
3816

3817
int32_t leastSQRScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3818
  SColumnInfoData *pInputData = pInput->columnData;
×
3819
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3820

3821
  double startVal, stepVal;
3822
  double matrix[2][3] = {0};
×
3823
  GET_TYPED_DATA(startVal, double, GET_PARAM_TYPE(&pInput[1]), pInput[1].columnData->pData,
×
3824
                 typeGetTypeModFromColInfo(&pInput[1].columnData->info));
3825
  GET_TYPED_DATA(stepVal, double, GET_PARAM_TYPE(&pInput[2]), pInput[2].columnData->pData,
×
3826
                 typeGetTypeModFromColInfo(&pInput[2].columnData->info));
3827

3828
  int32_t type = GET_PARAM_TYPE(pInput);
×
3829
  int64_t count = 0;
×
3830

3831
  switch (type) {
×
3832
    case TSDB_DATA_TYPE_TINYINT: {
×
3833
      int8_t *in = (int8_t *)pInputData->pData;
×
3834
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3835
        if (colDataIsNull_s(pInputData, i)) {
×
3836
          continue;
×
3837
        }
3838

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

3851
        count++;
×
3852
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3853
      }
3854
      break;
×
3855
    }
3856
    case TSDB_DATA_TYPE_INT: {
×
3857
      int32_t *in = (int32_t *)pInputData->pData;
×
3858
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3859
        if (colDataIsNull_s(pInputData, i)) {
×
3860
          continue;
×
3861
        }
3862

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

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

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

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

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

3923
        count++;
×
3924
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3925
      }
3926
      break;
×
3927
    }
3928
    case TSDB_DATA_TYPE_FLOAT: {
×
3929
      float *in = (float *)pInputData->pData;
×
3930
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3931
        if (colDataIsNull_s(pInputData, i)) {
×
3932
          continue;
×
3933
        }
3934

3935
        count++;
×
3936
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3937
      }
3938
      break;
×
3939
    }
3940
    case TSDB_DATA_TYPE_DOUBLE: {
×
3941
      double *in = (double *)pInputData->pData;
×
3942
      for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3943
        if (colDataIsNull_s(pInputData, i)) {
×
3944
          continue;
×
3945
        }
3946

3947
        count++;
×
3948
        LEASTSQR_CAL(matrix, startVal, in, i, stepVal);
×
3949
      }
3950
      break;
×
3951
    }
3952
  }
3953

3954
  if (count == 0) {
×
3955
    colDataSetNULL(pOutputData, 0);
3956
  } else {
3957
    matrix[1][1] = (double)count;
×
3958
    matrix[1][0] = matrix[0][1];
×
3959

3960
    double matrix00 = matrix[0][0] - matrix[1][0] * (matrix[0][1] / matrix[1][1]);
×
3961
    double matrix02 = matrix[0][2] - matrix[1][2] * (matrix[0][1] / matrix[1][1]);
×
3962
    double matrix12 = matrix[1][2] - matrix02 * (matrix[1][0] / matrix00);
×
3963
    matrix02 /= matrix00;
×
3964

3965
    matrix12 /= matrix[1][1];
×
3966

3967
    char buf[LEASTSQUARES_BUFF_LENGTH] = {0};
×
3968
    char slopBuf[64] = {0};
×
3969
    char interceptBuf[64] = {0};
×
3970
    int  n = tsnprintf(slopBuf, 64, "%.6lf", matrix02);
×
3971
    if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
×
3972
      (void)snprintf(slopBuf, 64, "%." DOUBLE_PRECISION_DIGITS, matrix02);
×
3973
    }
3974
    n = tsnprintf(interceptBuf, 64, "%.6lf", matrix12);
×
3975
    if (n > LEASTSQUARES_DOUBLE_ITEM_LENGTH) {
×
3976
      (void) snprintf(interceptBuf, 64, "%." DOUBLE_PRECISION_DIGITS, matrix12);
×
3977
    }
3978
    size_t len =
×
3979
        snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%s, intercept:%s}", slopBuf, interceptBuf);
×
3980
    varDataSetLen(buf, len);
×
3981
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, buf, false));
×
3982
  }
3983

3984
  pOutput->numOfRows = 1;
×
3985
  return TSDB_CODE_SUCCESS;
×
3986
}
3987

3988
int32_t percentileScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
3989
  SColumnInfoData *pInputData = pInput->columnData;
×
3990
  SColumnInfoData *pOutputData = pOutput->columnData;
×
3991

3992
  int32_t type = GET_PARAM_TYPE(pInput);
×
3993

3994
  double val;
3995
  bool   hasNull = false;
×
3996
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
3997
    if (colDataIsNull_s(pInputData, i)) {
×
3998
      hasNull = true;
×
3999
      break;
×
4000
    }
4001
    char *in = pInputData->pData;
×
4002
    GET_TYPED_DATA(val, double, type, in, typeGetTypeModFromColInfo(&pInputData->info));
×
4003
  }
4004

4005
  if (hasNull) {
×
4006
    colDataSetNULL(pOutputData, 0);
4007
  } else {
4008
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, (char *)&val, false));
×
4009
  }
4010

4011
  pOutput->numOfRows = 1;
×
4012
  return TSDB_CODE_SUCCESS;
×
4013
}
4014

4015
int32_t apercentileScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4016
  return percentileScalarFunction(pInput, inputNum, pOutput);
×
4017
}
4018

4019
int32_t spreadScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4020
  SColumnInfoData *pInputData = pInput->columnData;
×
4021
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4022

4023
  int32_t type = GET_PARAM_TYPE(pInput);
×
4024

4025
  double min, max;
4026
  SET_DOUBLE_VAL(&min, DBL_MAX);
×
4027
  SET_DOUBLE_VAL(&max, -DBL_MAX);
×
4028

4029
  bool hasNull = false;
×
4030
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4031
    if (colDataIsNull_s(pInputData, i)) {
×
4032
      hasNull = true;
×
4033
      break;
×
4034
    }
4035

4036
    char *in = pInputData->pData;
×
4037

4038
    double val = 0;
×
4039
    GET_TYPED_DATA(val, double, type, in, typeGetTypeModFromColInfo(&pInputData->info));
×
4040

4041
    if (val < GET_DOUBLE_VAL(&min)) {
×
4042
      SET_DOUBLE_VAL(&min, val);
×
4043
    }
4044

4045
    if (val > GET_DOUBLE_VAL(&max)) {
×
4046
      SET_DOUBLE_VAL(&max, val);
×
4047
    }
4048
  }
4049

4050
  if (hasNull) {
×
4051
    colDataSetNULL(pOutputData, 0);
4052
  } else {
4053
    double result = max - min;
×
4054
    SCL_ERR_RET(colDataSetVal(pOutputData, 0, (char *)&result, false));
×
4055
  }
4056

4057
  pOutput->numOfRows = 1;
×
4058
  return TSDB_CODE_SUCCESS;
×
4059
}
4060

4061
int32_t nonCalcScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4062
  SColumnInfoData *pInputData = pInput->columnData;
×
4063
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4064

4065
  int32_t type = GET_PARAM_TYPE(pInput);
×
4066
  bool    hasNull = false;
×
4067

4068
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4069
    if (colDataIsNull_s(pInputData, i)) {
×
4070
      hasNull = true;
×
4071
      break;
×
4072
    }
4073
  }
4074

4075
  double *out = (double *)pOutputData->pData;
×
4076
  if (hasNull) {
×
4077
    colDataSetNULL(pOutputData, 0);
4078
  } else {
4079
    *out = 0;
×
4080
  }
4081

4082
  pOutput->numOfRows = 1;
×
4083
  return TSDB_CODE_SUCCESS;
×
4084
}
4085

4086
int32_t derivativeScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4087
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
×
4088
}
4089

4090
int32_t irateScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4091
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
×
4092
}
4093

4094
int32_t diffScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4095
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
×
4096
}
4097

4098
int32_t forecastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4099
  return nonCalcScalarFunction(pInput, inputNum, pOutput);
×
4100
}
4101

4102
int32_t twaScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4103
  return avgScalarFunction(pInput, inputNum, pOutput);
×
4104
}
4105

4106
int32_t mavgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4107
  return avgScalarFunction(pInput, inputNum, pOutput);
×
4108
}
4109

4110
int32_t hllScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4111
  return countScalarFunction(pInput, inputNum, pOutput);
×
4112
}
4113

4114
int32_t csumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4115
  return sumScalarFunction(pInput, inputNum, pOutput);
×
4116
}
4117

4118
typedef enum {
4119
  STATE_OPER_INVALID = 0,
4120
  STATE_OPER_LT,
4121
  STATE_OPER_GT,
4122
  STATE_OPER_LE,
4123
  STATE_OPER_GE,
4124
  STATE_OPER_NE,
4125
  STATE_OPER_EQ,
4126
} EStateOperType;
4127

4128
#define STATE_COMP(_op, _lval, _rval, _rtype) STATE_COMP_IMPL(_op, _lval, GET_STATE_VAL(_rval, _rtype))
4129

4130
#define GET_STATE_VAL(_val, _type) ((_type == TSDB_DATA_TYPE_BIGINT) ? (*(int64_t *)_val) : (*(double *)_val))
4131

4132
#define STATE_COMP_IMPL(_op, _lval, _rval) \
4133
  do {                                     \
4134
    switch (_op) {                         \
4135
      case STATE_OPER_LT:                  \
4136
        return ((_lval) < (_rval));        \
4137
        break;                             \
4138
      case STATE_OPER_GT:                  \
4139
        return ((_lval) > (_rval));        \
4140
        break;                             \
4141
      case STATE_OPER_LE:                  \
4142
        return ((_lval) <= (_rval));       \
4143
        break;                             \
4144
      case STATE_OPER_GE:                  \
4145
        return ((_lval) >= (_rval));       \
4146
        break;                             \
4147
      case STATE_OPER_NE:                  \
4148
        return ((_lval) != (_rval));       \
4149
        break;                             \
4150
      case STATE_OPER_EQ:                  \
4151
        return ((_lval) == (_rval));       \
4152
        break;                             \
4153
      default:                             \
4154
        break;                             \
4155
    }                                      \
4156
  } while (0)
4157

4158
static int8_t getStateOpType(char *opStr) {
×
4159
  int8_t opType;
4160
  if (strncasecmp(opStr, "LT", 2) == 0) {
×
4161
    opType = STATE_OPER_LT;
×
4162
  } else if (strncasecmp(opStr, "GT", 2) == 0) {
×
4163
    opType = STATE_OPER_GT;
×
4164
  } else if (strncasecmp(opStr, "LE", 2) == 0) {
×
4165
    opType = STATE_OPER_LE;
×
4166
  } else if (strncasecmp(opStr, "GE", 2) == 0) {
×
4167
    opType = STATE_OPER_GE;
×
4168
  } else if (strncasecmp(opStr, "NE", 2) == 0) {
×
4169
    opType = STATE_OPER_NE;
×
4170
  } else if (strncasecmp(opStr, "EQ", 2) == 0) {
×
4171
    opType = STATE_OPER_EQ;
×
4172
  } else {
4173
    opType = STATE_OPER_INVALID;
×
4174
  }
4175

4176
  return opType;
×
4177
}
4178

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

4241
int32_t stateCountScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4242
  SColumnInfoData *pInputData = pInput->columnData;
×
4243
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4244

4245
  int8_t  op = getStateOpType(varDataVal(pInput[1].columnData->pData));
×
4246
  int64_t count = 0;
×
4247

4248
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4249
    if (colDataIsNull_s(pInputData, i)) {
×
4250
      colDataSetNULL(pOutputData, i);
×
4251
      continue;
×
4252
    }
4253

4254
    bool    ret = checkStateOp(op, pInputData, i, &pInput[2]);
×
4255
    int64_t out = -1;
×
4256
    if (ret) {
×
4257
      out = ++count;
×
4258
    } else {
4259
      count = 0;
×
4260
    }
4261
    SCL_ERR_RET(colDataSetVal(pOutputData, i, (char *)&out, false));
×
4262
  }
4263

4264
  pOutput->numOfRows = pInput->numOfRows;
×
4265
  return TSDB_CODE_SUCCESS;
×
4266
}
4267

4268
int32_t stateDurationScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4269
  SColumnInfoData *pInputData = pInput->columnData;
×
4270
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4271

4272
  int8_t op = getStateOpType(varDataVal(pInput[1].columnData->pData));
×
4273

4274
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4275
    if (colDataIsNull_s(pInputData, i)) {
×
4276
      colDataSetNULL(pOutputData, i);
×
4277
      continue;
×
4278
    }
4279

4280
    bool    ret = checkStateOp(op, pInputData, i, &pInput[2]);
×
4281
    int64_t out = -1;
×
4282
    if (ret) {
×
4283
      out = 0;
×
4284
    }
4285
    SCL_ERR_RET(colDataSetVal(pOutputData, i, (char *)&out, false));
×
4286
  }
4287

4288
  pOutput->numOfRows = pInput->numOfRows;
×
4289
  return TSDB_CODE_SUCCESS;
×
4290
}
4291

4292
typedef enum { UNKNOWN_BIN = 0, USER_INPUT_BIN, LINEAR_BIN, LOG_BIN } EHistoBinType;
4293

4294
static int8_t getHistogramBinType(char *binTypeStr) {
×
4295
  int8_t binType;
4296
  if (strcasecmp(binTypeStr, "user_input") == 0) {
×
4297
    binType = USER_INPUT_BIN;
×
4298
  } else if (strcasecmp(binTypeStr, "linear_bin") == 0) {
×
4299
    binType = LINEAR_BIN;
×
4300
  } else if (strcasecmp(binTypeStr, "log_bin") == 0) {
×
4301
    binType = LOG_BIN;
×
4302
  } else {
4303
    binType = UNKNOWN_BIN;
×
4304
  }
4305

4306
  return binType;
×
4307
}
4308

4309
typedef struct SHistoFuncBin {
4310
  double  lower;
4311
  double  upper;
4312
  int64_t count;
4313
  double  percentage;
4314
} SHistoFuncBin;
4315

4316
static int32_t getHistogramBinDesc(SHistoFuncBin **bins, int32_t *binNum, char *binDescStr, int8_t binType,
×
4317
                                bool normalized) {
4318
  cJSON  *binDesc = cJSON_Parse(binDescStr);
×
4319
  int32_t numOfBins;
4320
  double *intervals;
4321
  if (cJSON_IsObject(binDesc)) { /* linaer/log bins */
×
4322
    int32_t numOfParams = cJSON_GetArraySize(binDesc);
×
4323
    int32_t startIndex;
4324
    if (numOfParams != 4) {
×
4325
      cJSON_Delete(binDesc);
×
4326
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4327
    }
4328

4329
    cJSON *start = cJSON_GetObjectItem(binDesc, "start");
×
4330
    cJSON *factor = cJSON_GetObjectItem(binDesc, "factor");
×
4331
    cJSON *width = cJSON_GetObjectItem(binDesc, "width");
×
4332
    cJSON *count = cJSON_GetObjectItem(binDesc, "count");
×
4333
    cJSON *infinity = cJSON_GetObjectItem(binDesc, "infinity");
×
4334

4335
    if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) {
×
4336
      cJSON_Delete(binDesc);
×
4337
      SCL_RET(TSDB_CODE_SUCCESS);
×
4338
    }
4339

4340
    if (count->valueint <= 0 || count->valueint > 1000) {  // limit count to 1000
×
4341
      cJSON_Delete(binDesc);
×
4342
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4343
    }
4344

4345
    if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) ||
×
4346
        (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) {
×
4347
      cJSON_Delete(binDesc);
×
4348
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4349
    }
4350

4351
    int32_t counter = (int32_t)count->valueint;
×
4352
    if (infinity->valueint == false) {
×
4353
      startIndex = 0;
×
4354
      numOfBins = counter + 1;
×
4355
    } else {
4356
      startIndex = 1;
×
4357
      numOfBins = counter + 3;
×
4358
    }
4359

4360
    intervals = taosMemoryCalloc(numOfBins, sizeof(double));
×
4361
    if (NULL == intervals) {
×
4362
      cJSON_Delete(binDesc);
×
4363
      SCL_ERR_RET(terrno);
×
4364
    }
4365
    if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) {
×
4366
      // linear bin process
4367
      if (width->valuedouble == 0) {
×
4368
        taosMemoryFree(intervals);
×
4369
        cJSON_Delete(binDesc);
×
4370
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4371
      }
4372
      for (int i = 0; i < counter + 1; ++i) {
×
4373
        intervals[startIndex] = start->valuedouble + i * width->valuedouble;
×
4374
        if (isinf(intervals[startIndex])) {
×
4375
          taosMemoryFree(intervals);
×
4376
          cJSON_Delete(binDesc);
×
4377
          SCL_ERR_RET(TSDB_CODE_FAILED);
×
4378
        }
4379
        startIndex++;
×
4380
      }
4381
    } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) {
×
4382
      // log bin process
4383
      if (start->valuedouble == 0) {
×
4384
        taosMemoryFree(intervals);
×
4385
        cJSON_Delete(binDesc);
×
4386
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4387
      }
4388
      if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) {
×
4389
        taosMemoryFree(intervals);
×
4390
        cJSON_Delete(binDesc);
×
4391
        SCL_ERR_RET(TSDB_CODE_FAILED);
×
4392
      }
4393
      for (int i = 0; i < counter + 1; ++i) {
×
4394
        intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0);
×
4395
        if (isinf(intervals[startIndex])) {
×
4396
          taosMemoryFree(intervals);
×
4397
          cJSON_Delete(binDesc);
×
4398
          SCL_ERR_RET(TSDB_CODE_FAILED);
×
4399
        }
4400
        startIndex++;
×
4401
      }
4402
    } else {
4403
      taosMemoryFree(intervals);
×
4404
      cJSON_Delete(binDesc);
×
4405
      SCL_ERR_RET(TSDB_CODE_FAILED);
×
4406
    }
4407

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

4457
  *binNum = numOfBins - 1;
×
4458
  *bins = taosMemoryCalloc(numOfBins, sizeof(SHistoFuncBin));
×
4459
  if (NULL == bins) {
×
4460
    SCL_ERR_RET(terrno);
×
4461
  }
4462
  for (int32_t i = 0; i < *binNum; ++i) {
×
4463
    (*bins)[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1];
×
4464
    (*bins)[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i];
×
4465
    (*bins)[i].count = 0;
×
4466
  }
4467

4468
  taosMemoryFree(intervals);
×
4469
  cJSON_Delete(binDesc);
×
4470

4471
  SCL_RET(TSDB_CODE_SUCCESS);
×
4472
}
4473

4474
int32_t histogramScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4475
  SColumnInfoData *pInputData = pInput->columnData;
×
4476
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4477

4478
  SHistoFuncBin *bins;
4479
  int32_t        numOfBins = 0;
×
4480
  int32_t        totalCount = 0;
×
4481

4482
  char *binTypeStr = taosStrndup(varDataVal(pInput[1].columnData->pData), varDataLen(pInput[1].columnData->pData));
×
4483
  if (NULL == binTypeStr) {
×
4484
    SCL_ERR_RET(terrno);
×
4485
  }
4486
  int8_t binType = getHistogramBinType(binTypeStr);
×
4487
  taosMemoryFree(binTypeStr);
×
4488

4489
  char   *binDesc = taosStrndup(varDataVal(pInput[2].columnData->pData), varDataLen(pInput[2].columnData->pData));
×
4490
  if (NULL == binDesc) {
×
4491
    SCL_ERR_RET(terrno);
×
4492
  }
4493
  int64_t normalized = *(int64_t *)(pInput[3].columnData->pData);
×
4494

4495
  int32_t type = GET_PARAM_TYPE(pInput);
×
4496
  int32_t code = getHistogramBinDesc(&bins, &numOfBins, binDesc, binType, (bool)normalized);
×
4497
  if (TSDB_CODE_SUCCESS != code) {
×
4498
    taosMemoryFree(binDesc);
×
4499
    return code;
×
4500
  }
4501
  taosMemoryFree(binDesc);
×
4502

4503
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4504
    if (colDataIsNull_s(pInputData, i)) {
×
4505
      continue;
×
4506
    }
4507

4508
    char  *data = colDataGetData(pInputData, i);
×
4509
    double v;
4510
    GET_TYPED_DATA(v, double, type, data, typeGetTypeModFromColInfo(&pInputData->info));
×
4511

4512
    for (int32_t k = 0; k < numOfBins; ++k) {
×
4513
      if (v > bins[k].lower && v <= bins[k].upper) {
×
4514
        bins[k].count++;
×
4515
        totalCount++;
×
4516
        break;
×
4517
      }
4518
    }
4519
  }
4520

4521
  if (normalized) {
×
4522
    for (int32_t k = 0; k < numOfBins; ++k) {
×
4523
      if (totalCount != 0) {
×
4524
        bins[k].percentage = bins[k].count / (double)totalCount;
×
4525
      } else {
4526
        bins[k].percentage = 0;
×
4527
      }
4528
    }
4529
  }
4530

4531
  SCL_ERR_JRET(colInfoDataEnsureCapacity(pOutputData, numOfBins, false));
×
4532

4533
  for (int32_t k = 0; k < numOfBins; ++k) {
×
4534
    int32_t len;
4535
    char    buf[512] = {0};
×
4536
    if (!normalized) {
×
4537
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%" PRId64 "}",
×
4538
                     bins[k].lower, bins[k].upper, bins[k].count);
×
4539
    } else {
4540
      len = tsnprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}",
×
4541
                     bins[k].lower, bins[k].upper, bins[k].percentage);
×
4542
    }
4543
    varDataSetLen(buf, len);
×
4544
    SCL_ERR_JRET(colDataSetVal(pOutputData, k, buf, false));
×
4545
  }
4546
  pOutput->numOfRows = numOfBins;
×
4547

4548
_return:
×
4549
  taosMemoryFree(bins);
×
4550
  return code;
×
4551
}
4552

4553
int32_t selectScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4554
  SColumnInfoData *pInputData = pInput->columnData;
×
4555
  SColumnInfoData *pOutputData = pOutput->columnData;
×
4556

4557
  int32_t type = GET_PARAM_TYPE(pInput);
×
4558

4559
  for (int32_t i = 0; i < pInput->numOfRows; ++i) {
×
4560
    if (colDataIsNull_s(pInputData, i)) {
×
4561
      colDataSetNULL(pOutputData, 0);
4562
      continue;
×
4563
    }
4564

4565
    char *data = colDataGetData(pInputData, i);
×
4566
    SCL_ERR_RET(colDataSetVal(pOutputData, i, data, false));
×
4567
  }
4568

4569
  pOutput->numOfRows = 1;
×
4570
  return TSDB_CODE_SUCCESS;
×
4571
}
4572

4573
int32_t topBotScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4574
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4575
}
4576

4577
int32_t firstLastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4578
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4579
}
4580

4581
int32_t sampleScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4582
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4583
}
4584

4585
int32_t tailScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4586
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4587
}
4588

4589
int32_t uniqueScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4590
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4591
}
4592

4593
int32_t modeScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4594
  return selectScalarFunction(pInput, inputNum, pOutput);
×
4595
}
4596

4597
typedef struct SCovertScarlarParam {
4598
  SScalarParam covertParam;
4599
  SScalarParam *param;
4600
  bool converted;
4601
} SCovertScarlarParam;
4602

4603
void freeSCovertScarlarParams(SCovertScarlarParam *pCovertParams, int32_t num) {
×
4604
  if (pCovertParams == NULL) {
×
4605
    return;
×
4606
  }
4607
  for (int32_t i = 0; i < num; i++) {
×
4608
    if (pCovertParams[i].converted) {
×
4609
      sclFreeParam(pCovertParams[i].param);
×
4610
    }
4611
  }
4612
  taosMemoryFree(pCovertParams);
×
4613
}
4614

4615
static int32_t vectorCompareAndSelect(SCovertScarlarParam *pParams, int32_t numOfRows, int numOfCols,
×
4616
                                      int32_t *resultColIndex, EOperatorType optr) {
4617
  int32_t code = TSDB_CODE_SUCCESS;
×
4618
  int32_t type = GET_PARAM_TYPE(pParams[0].param);
×
4619

4620
  __compar_fn_t fp = NULL;
×
4621
  code = filterGetCompFunc(&fp, type, optr);
×
4622
  if(code != TSDB_CODE_SUCCESS) {
×
4623
    qError("failed to get compare function, func:%s type:%d, optr:%d", __FUNCTION__, type, optr);
×
4624
    return code;
×
4625
  }
4626

4627
  for (int32_t i = 0; i < numOfRows; i++) {
×
4628
    int selectIndex = 0;
×
4629
    if (colDataIsNull_s(pParams[selectIndex].param->columnData, i)) {
×
4630
      resultColIndex[i] = -1;
×
4631
      continue;
×
4632
    }
4633
    for (int32_t j = 1; j < numOfCols; j++) {
×
4634
      if (colDataIsNull_s(pParams[j].param->columnData, i)) {
×
4635
        resultColIndex[i] = -1;
×
4636
        break;
×
4637
      } else {
4638
        int32_t leftRowNo = pParams[selectIndex].param->numOfRows == 1 ? 0 : i;
×
4639
        int32_t rightRowNo = pParams[j].param->numOfRows == 1 ? 0 : i;
×
4640
        char   *pLeftData = colDataGetData(pParams[selectIndex].param->columnData, leftRowNo);
×
4641
        char   *pRightData = colDataGetData(pParams[j].param->columnData, rightRowNo);
×
4642
        bool    pRes = filterDoCompare(fp, optr, pLeftData, pRightData);
×
4643
        if (!pRes) {
×
4644
          selectIndex = j;
×
4645
        }
4646
      }
4647
      resultColIndex[i] = selectIndex;
×
4648
    }
4649
  }
4650

4651
  return code;
×
4652
}
4653

4654
static int32_t greatestLeastImpl(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput, EOperatorType order) {
×
4655
  int32_t          code = TSDB_CODE_SUCCESS;
×
4656
  SColumnInfoData *pOutputData = pOutput[0].columnData;
×
4657
  int16_t          outputType = GET_PARAM_TYPE(&pOutput[0]);
×
4658
  int64_t          outputLen = GET_PARAM_BYTES(&pOutput[0]);
×
4659

4660
  SCovertScarlarParam *pCovertParams = NULL;
×
4661
  int32_t             *resultColIndex = NULL;
×
4662

4663
  int32_t numOfRows = 0;
×
4664
  bool    IsNullType = outputType == TSDB_DATA_TYPE_NULL ? true : false;
×
4665
  // If any column is NULL type, the output is NULL type
4666
  for (int32_t i = 0; i < inputNum; i++) {
×
4667
    if (IsNullType) {
×
4668
      break;
×
4669
    }
4670
    if (numOfRows != 0 && numOfRows != pInput[i].numOfRows && pInput[i].numOfRows != 1 && numOfRows != 1) {
×
4671
      qError("input rows not match, func:%s, rows:%d, %d", __FUNCTION__, numOfRows, pInput[i].numOfRows);
×
4672
      code = TSDB_CODE_TSC_INTERNAL_ERROR;
×
4673
      goto _return;
×
4674
    }
4675
    numOfRows = TMAX(numOfRows, pInput[i].numOfRows);
×
4676
    IsNullType |= IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]));
×
4677
  }
4678

4679
  if (IsNullType) {
×
4680
    colDataSetNNULL(pOutputData, 0, numOfRows);
×
4681
    pOutput->numOfRows = numOfRows;
×
4682
    return TSDB_CODE_SUCCESS;
×
4683
  }
4684
  pCovertParams = taosMemoryMalloc(inputNum * sizeof(SCovertScarlarParam));
×
4685
  for (int32_t j = 0; j < inputNum; j++) {
×
4686
    SScalarParam *pParam = &pInput[j];
×
4687
    int16_t       oldType = GET_PARAM_TYPE(&pInput[j]);
×
4688
    if (oldType != outputType) {
×
4689
      pCovertParams[j].covertParam = (SScalarParam){0};
×
4690
      setTzCharset(&pCovertParams[j].covertParam, pParam->tz, pParam->charsetCxt);
×
4691
      SCL_ERR_JRET(vectorConvertSingleCol(pParam, &pCovertParams[j].covertParam, outputType, 0, 0, pParam->numOfRows));
×
4692
      pCovertParams[j].param = &pCovertParams[j].covertParam;
×
4693
      pCovertParams[j].converted = true;
×
4694
    } else {
4695
      pCovertParams[j].param = pParam;
×
4696
      pCovertParams[j].converted = false;
×
4697
    }
4698
  }
4699

4700
  resultColIndex = taosMemoryCalloc(numOfRows, sizeof(int32_t));
×
4701
  SCL_ERR_JRET(vectorCompareAndSelect(pCovertParams, numOfRows, inputNum, resultColIndex, order));
×
4702

4703
  for (int32_t i = 0; i < numOfRows; i++) {
×
4704
    int32_t index = resultColIndex[i];
×
4705
    if (index == -1) {
×
4706
      colDataSetNULL(pOutputData, i);
×
4707
      continue;
×
4708
    }
4709
    int32_t rowNo = pCovertParams[index].param->numOfRows == 1 ? 0 : i;
×
4710
    char   *data = colDataGetData(pCovertParams[index].param->columnData, rowNo);
×
4711
    SCL_ERR_JRET(colDataSetVal(pOutputData, i, data, false));
×
4712
  }
4713

4714
  pOutput->numOfRows = numOfRows;
×
4715

4716
_return:
×
4717
  freeSCovertScarlarParams(pCovertParams, inputNum);
×
4718
  taosMemoryFree(resultColIndex);
×
4719
  return code;
×
4720
}
4721

4722
int32_t greatestFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4723
  return greatestLeastImpl(pInput, inputNum, pOutput, OP_TYPE_GREATER_THAN);
×
4724
}
4725

4726
int32_t leastFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
×
4727
  return greatestLeastImpl(pInput, inputNum, pOutput, OP_TYPE_LOWER_THAN);
×
4728
}
4729

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