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

taosdata / TDengine / #4720

08 Sep 2025 08:43AM UTC coverage: 58.139% (-0.6%) from 58.762%
#4720

push

travis-ci

web-flow
Merge pull request #32881 from taosdata/enh/add-new-windows-ci

fix(ci): update workflow reference to use new Windows CI YAML

133181 of 292179 branches covered (45.58%)

Branch coverage included in aggregate %.

201691 of 283811 relevant lines covered (71.07%)

5442780.71 hits per line

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

45.54
/source/libs/index/src/indexFilter.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#include "filter.h"
17
#include "index.h"
18
#include "indexComm.h"
19
#include "indexInt.h"
20
#include "indexUtil.h"
21
#include "nodes.h"
22
#include "querynodes.h"
23
#include "scalar.h"
24
#include "taos.h"
25
#include "tdatablock.h"
26
#include "ttypes.h"
27

28
// clang-format off
29
#define SIF_ERR_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; return _code; } } while (0)
30
#define SIF_RET(c) do { int32_t _code = c; if (_code != TSDB_CODE_SUCCESS) { terrno = _code; } return _code; } while (0)
31
#define SIF_ERR_JRET(c) do { code = c; if (code != TSDB_CODE_SUCCESS) { terrno = code; goto _return; } } while (0)
32
// clang-format on
33

34
typedef union {
35
  uint8_t  u8;
36
  uint16_t u16;
37
  uint32_t u32;
38
  uint64_t u64;
39

40
  int8_t  i8;
41
  int16_t i16;
42
  int32_t i32;
43
  int64_t i64;
44

45
  double d;
46
  float  f;
47
} SDataTypeBuf;
48

49
#define SIF_DATA_CONVERT(type, val, dst)       \
50
  do {                                         \
51
    if (type == TSDB_DATA_TYPE_DOUBLE)         \
52
      dst = GET_DOUBLE_VAL(val);               \
53
    else if (type == TSDB_DATA_TYPE_BIGINT)    \
54
      dst = *(int64_t *)val;                   \
55
    else if (type == TSDB_DATA_TYPE_INT)       \
56
      dst = *(int32_t *)val;                   \
57
    else if (type == TSDB_DATA_TYPE_SMALLINT)  \
58
      dst = *(int16_t *)val;                   \
59
    else if (type == TSDB_DATA_TYPE_TINYINT)   \
60
      dst = *(int8_t *)val;                    \
61
    else if (type == TSDB_DATA_TYPE_UTINYINT)  \
62
      dst = *(uint8_t *)val;                   \
63
    else if (type == TSDB_DATA_TYPE_USMALLINT) \
64
      dst = *(uint16_t *)val;                  \
65
    else if (type == TSDB_DATA_TYPE_UINT)      \
66
      dst = *(uint32_t *)val;                  \
67
    else if (type == TSDB_DATA_TYPE_UBIGINT)   \
68
      dst = *(uint64_t *)val;                  \
69
  } while (0);
70

71
typedef struct SIFParam {
72
  SHashObj *pFilter;
73
  SArray   *result;
74
  char     *condValue;
75

76
  SIdxFltStatus status;
77
  uint8_t       colValType;
78
  col_id_t      colId;
79
  int64_t       suid;  // add later
80
  char          dbName[TSDB_DB_NAME_LEN];
81
  char          colName[TSDB_COL_NAME_LEN * 2 + 4];
82

83
  SIndexMetaArg      arg;
84
  SMetaDataFilterAPI api;
85
} SIFParam;
86

87
typedef struct SIFCtx {
88
  int32_t             code;
89
  SHashObj           *pRes;    /* element is SIFParam */
90
  bool                noExec;  // true: just iterate condition tree, and add hint to executor plan
91
  SIndexMetaArg       arg;
92
  SMetaDataFilterAPI *pAPI;
93
} SIFCtx;
94

95
static FORCE_INLINE int32_t sifGetFuncFromSql(EOperatorType src, EIndexQueryType *dst) {
96
  if (src == OP_TYPE_GREATER_THAN) {
8,309✔
97
    *dst = QUERY_GREATER_THAN;
935✔
98
  } else if (src == OP_TYPE_GREATER_EQUAL) {
7,374✔
99
    *dst = QUERY_GREATER_EQUAL;
747✔
100
  } else if (src == OP_TYPE_LOWER_THAN) {
6,627✔
101
    *dst = QUERY_LESS_THAN;
812✔
102
  } else if (src == OP_TYPE_LOWER_EQUAL) {
5,815✔
103
    *dst = QUERY_LESS_EQUAL;
1,520✔
104
  } else if (src == OP_TYPE_EQUAL) {
4,295✔
105
    *dst = QUERY_TERM;
3,755✔
106
  } else if (src == OP_TYPE_LIKE || src == OP_TYPE_MATCH || src == OP_TYPE_NMATCH) {
540!
107
    *dst = QUERY_REGEX;
×
108
  } else if (src == OP_TYPE_JSON_CONTAINS) {
546!
109
    *dst = QUERY_PREFIX;
×
110
  } else {
111
    return TSDB_CODE_QRY_INVALID_INPUT;
546✔
112
  }
113
  return TSDB_CODE_SUCCESS;
7,763✔
114
}
115

116
typedef int32_t (*sif_func_t)(SIFParam *left, SIFParam *rigth, SIFParam *output);
117
static sif_func_t sifNullFunc = NULL;
118

119
static FORCE_INLINE void sifFreeParam(SIFParam *param) {
120
  if (param == NULL) return;
12,527!
121

122
  taosArrayDestroy(param->result);
64,482✔
123
  taosMemoryFree(param->condValue);
64,519!
124
  param->condValue = NULL;
64,569✔
125
  taosHashCleanup(param->pFilter);
64,569✔
126
  param->pFilter = NULL;
64,542✔
127
}
128

129
static FORCE_INLINE int32_t sifGetOperParamNum(EOperatorType ty) {
130
  if (OP_TYPE_IS_NULL == ty || OP_TYPE_IS_NOT_NULL == ty || OP_TYPE_IS_TRUE == ty || OP_TYPE_IS_NOT_TRUE == ty ||
35,709!
131
      OP_TYPE_IS_FALSE == ty || OP_TYPE_IS_NOT_FALSE == ty || OP_TYPE_IS_UNKNOWN == ty ||
35,595!
132
      OP_TYPE_IS_NOT_UNKNOWN == ty || OP_TYPE_MINUS == ty) {
35,591!
133
    return 1;
101✔
134
  }
135
  return 2;
35,593✔
136
}
137
static FORCE_INLINE int32_t sifValidOp(EOperatorType ty) {
138
  if ((ty >= OP_TYPE_ADD && ty <= OP_TYPE_BIT_OR) || (ty == OP_TYPE_IN || ty == OP_TYPE_NOT_IN) ||
19,790✔
139
      (ty == OP_TYPE_LIKE || ty == OP_TYPE_NOT_LIKE || ty == OP_TYPE_MATCH || ty == OP_TYPE_NMATCH)) {
19,489!
140
    return TSDB_CODE_INVALID_PARA;
1,615✔
141
  }
142
  return 0;
18,175✔
143
}
144
static FORCE_INLINE int32_t sifValidColumn(SColumnNode *cn) {
145
  // add more check
146
  if (cn == NULL) {
17,527✔
147
    return TSDB_CODE_QRY_INVALID_INPUT;
×
148
  }
149
  if (cn->colType != COLUMN_TYPE_TAG) {
17,527!
150
    return TSDB_CODE_QRY_INVALID_INPUT;
×
151
  }
152
  return TSDB_CODE_SUCCESS;
17,527✔
153
}
154

155
static FORCE_INLINE SIdxFltStatus sifMergeCond(ELogicConditionType type, SIdxFltStatus ls, SIdxFltStatus rs) {
156
  // enh rule later
157
  if (type == LOGIC_COND_TYPE_AND) {
1,538✔
158
    if (ls == SFLT_NOT_INDEX || rs == SFLT_NOT_INDEX) {
354!
159
      if (ls == SFLT_NOT_INDEX)
1!
160
        return rs;
×
161
      else
162
        return ls;
1✔
163
    }
164
    return SFLT_COARSE_INDEX;
353✔
165
  } else if (type == LOGIC_COND_TYPE_OR) {
1,184✔
166
    return SFLT_COARSE_INDEX;
86✔
167
  } else if (type == LOGIC_COND_TYPE_NOT) {
1,098!
168
    return SFLT_NOT_INDEX;
1,098✔
169
  }
170
  return SFLT_NOT_INDEX;
×
171
}
172

173
static FORCE_INLINE int32_t sifGetValueFromNode(SNode *node, char **value) {
174
  // covert data From snode;
175
  SValueNode *vn = (SValueNode *)node;
17,510✔
176

177
  char      *pData = nodesGetValueFromNode(vn);
17,510✔
178
  SDataType *pType = &vn->node.resType;
17,514✔
179
  int32_t    type = pType->type;
17,514✔
180
  int32_t    valLen = 0;
17,514✔
181

182
  if (IS_VAR_DATA_TYPE(type)) {
17,514!
183
    int32_t dataLen = varDataTLen(pData);
877✔
184
    if (IS_STR_DATA_BLOB(type)) {
877!
185
      dataLen = blobDataTLen(pData);
×
186
    }
187
    if (type == TSDB_DATA_TYPE_JSON) {
877!
188
      if (*pData == TSDB_DATA_TYPE_NULL) {
×
189
        dataLen = 0;
×
190
      } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
×
191
        dataLen = varDataTLen(pData);
×
192
      } else if (*pData == TSDB_DATA_TYPE_DOUBLE) {
×
193
        dataLen = LONG_BYTES;
×
194
      } else if (*pData == TSDB_DATA_TYPE_BOOL) {
×
195
        dataLen = CHAR_BYTES;
×
196
      }
197
      dataLen += CHAR_BYTES;
×
198
    }
199
    valLen = dataLen;
877✔
200
  } else {
201
    valLen = pType->bytes;
16,637✔
202
  }
203
  char *tv = taosMemoryCalloc(1, valLen + 1);
17,514✔
204
  if (tv == NULL) {
17,533!
205
    return terrno;
×
206
  }
207

208
  memcpy(tv, pData, valLen);
17,533✔
209
  *value = tv;
17,533✔
210

211
  return TSDB_CODE_SUCCESS;
17,533✔
212
}
213

214
static FORCE_INLINE int32_t sifInitJsonParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
215
  SOperatorNode *nd = (SOperatorNode *)node;
×
216
  if (nodeType(node) != QUERY_NODE_OPERATOR) {
×
217
    return TSDB_CODE_INVALID_PARA;
×
218
  }
219
  SColumnNode *l = (SColumnNode *)nd->pLeft;
×
220
  SValueNode  *r = (SValueNode *)nd->pRight;
×
221

222
  param->colId = l->colId;
×
223
  param->colValType = l->node.resType.type;
×
224
  memcpy(param->dbName, l->dbName, sizeof(l->dbName));
×
225
  if (r->literal == NULL) return TSDB_CODE_QRY_INVALID_INPUT;
×
226
  memcpy(param->colName, r->literal, strlen(r->literal));
×
227
  param->colValType = r->typeData;
×
228
  param->status = SFLT_COARSE_INDEX;
×
229
  return 0;
×
230
}
231
static int32_t sifNeedConvertCond(SNode *l, SNode *r) {
×
232
  if (nodeType(l) != QUERY_NODE_COLUMN || nodeType(r) != QUERY_NODE_VALUE) {
×
233
    return 0;
×
234
  }
235
  SColumnNode *c = (SColumnNode *)l;
×
236
  SValueNode  *v = (SValueNode *)r;
×
237
  int32_t      ctype = c->node.resType.type;
×
238
  int32_t      vtype = v->node.resType.type;
×
239
  if (!IS_VAR_DATA_TYPE(ctype) && IS_VAR_DATA_TYPE(vtype)) {
×
240
    return 1;
×
241
  }
242
  return 0;
×
243
}
244
static int32_t sifInitParamValByCol(SNode *r, SNode *l, SIFParam *param, SIFCtx *ctx) {
×
245
  param->status = SFLT_COARSE_INDEX;
×
246
  SColumnNode *cn = (SColumnNode *)r;
×
247
  SValueNode  *vn = (SValueNode *)l;
×
248
  if (vn->typeData == TSDB_DATA_TYPE_NULL && (vn->literal == NULL || strlen(vn->literal) == 0)) {
×
249
    param->status = SFLT_NOT_INDEX;
×
250
    return 0;
×
251
  }
252
  SDataType *pType = &cn->node.resType;
×
253
  int32_t    type = pType->type;
×
254

255
  SDataType *pVType = &vn->node.resType;
×
256
  int32_t    vtype = pVType->type;
×
257
  char      *pData = nodesGetValueFromNode(vn);
×
258
  int32_t    valLen = 0;
×
259
  char     **value = &param->condValue;
×
260

261
  if (IS_VAR_DATA_TYPE(type)) {
×
262
    int32_t dataLen = varDataTLen(pData);
×
263
    if (type == TSDB_DATA_TYPE_JSON) {
×
264
      if (*pData == TSDB_DATA_TYPE_NULL) {
×
265
        dataLen = 0;
×
266
      } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
×
267
        dataLen = varDataTLen(pData);
×
268
      } else if (*pData == TSDB_DATA_TYPE_DOUBLE) {
×
269
        dataLen = LONG_BYTES;
×
270
      } else if (*pData == TSDB_DATA_TYPE_BOOL) {
×
271
        dataLen = CHAR_BYTES;
×
272
      }
273
      dataLen += CHAR_BYTES;
×
274
    }
275
    valLen = dataLen;
×
276
  } else {
277
    valLen = pType->bytes;
×
278
  }
279
  char *tv = taosMemoryCalloc(1, valLen + 1);
×
280
  if (tv == NULL) {
×
281
    return terrno;
×
282
  }
283

284
  memcpy(tv, pData, valLen);
×
285
  *value = tv;
×
286

287
  param->colId = -1;
×
288
  param->colValType = (uint8_t)(vn->node.resType.type);
×
289
  if (vn->literal != NULL && strlen(vn->literal) <= sizeof(param->colName)) {
×
290
    memcpy(param->colName, vn->literal, strlen(vn->literal));
×
291
  } else {
292
    param->status = SFLT_NOT_INDEX;
×
293
  }
294
  return 0;
×
295
}
296
static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
36,882✔
297
  param->status = SFLT_COARSE_INDEX;
36,882✔
298
  param->api = *ctx->pAPI;
36,882✔
299

300
  switch (nodeType(node)) {
36,882!
301
    case QUERY_NODE_VALUE: {
17,534✔
302
      SValueNode *vn = (SValueNode *)node;
17,534✔
303
      if (vn->typeData == TSDB_DATA_TYPE_NULL && (vn->literal == NULL || strlen(vn->literal) == 0)) {
17,534!
304
        param->status = SFLT_NOT_INDEX;
24✔
305
        return 0;
24✔
306
      }
307
      SIF_ERR_RET(sifGetValueFromNode(node, &param->condValue));
35,043!
308
      param->colId = -1;
17,533✔
309
      param->colValType = (uint8_t)(vn->node.resType.type);
17,533✔
310
      if (vn->literal != NULL && strlen(vn->literal) <= sizeof(param->colName)) {
17,533✔
311
        memcpy(param->colName, vn->literal, strlen(vn->literal));
17,513✔
312
      } else {
313
        param->status = SFLT_NOT_INDEX;
20✔
314
      }
315
      break;
17,533✔
316
    }
317
    case QUERY_NODE_COLUMN: {
17,527✔
318
      SColumnNode *cn = (SColumnNode *)node;
17,527!
319
      /*only support tag column*/
320
      SIF_ERR_RET(sifValidColumn(cn));
17,527!
321

322
      param->colId = cn->colId;
17,527✔
323
      param->colValType = cn->node.resType.type;
17,527✔
324
      memcpy(param->dbName, cn->dbName, sizeof(cn->dbName));
17,527✔
325
      memcpy(param->colName, cn->colName, sizeof(cn->colName));
17,527✔
326
      break;
17,527✔
327
    }
328
    case QUERY_NODE_NODE_LIST: {
×
329
      SNodeListNode *nl = (SNodeListNode *)node;
×
330
      if (LIST_LENGTH(nl->pNodeList) <= 0) {
×
331
        indexError("invalid length for node:%p, length: %d", node, LIST_LENGTH(nl->pNodeList));
×
332
        SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
×
333
      }
334
      SIF_ERR_RET(scalarGenerateSetFromList((void **)&param->pFilter, node, nl->node.resType.type, 0, 0));
×
335
      if (taosHashPut(ctx->pRes, &node, POINTER_BYTES, param, sizeof(*param))) {
×
336
        taosHashCleanup(param->pFilter);
×
337
        param->pFilter = NULL;
×
338
        indexError("taosHashPut nodeList failed, size:%d", (int32_t)sizeof(*param));
×
339
        SIF_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
×
340
      }
341
      break;
×
342
    }
343
    case QUERY_NODE_FUNCTION:
1,876✔
344
    case QUERY_NODE_OPERATOR:
345
    case QUERY_NODE_LOGIC_CONDITION: {
346
      SIFParam *res = (SIFParam *)taosHashGet(ctx->pRes, &node, POINTER_BYTES);
1,876✔
347
      if (NULL == res) {
1,877!
348
        indexError("no result for node, type:%d, node:%p", nodeType(node), node);
×
349
        SIF_ERR_RET(TSDB_CODE_APP_ERROR);
×
350
      }
351
      *param = *res;
1,877✔
352
      break;
1,877✔
353
    }
354
    default:
×
355
      break;
×
356
  }
357
  return TSDB_CODE_SUCCESS;
36,882✔
358
}
359

360
static int32_t sifInitOperParams(SIFParam **params, SOperatorNode *node, SIFCtx *ctx) {
17,530✔
361
  int32_t code = 0;
17,530✔
362
  int32_t nParam = sifGetOperParamNum(node->opType);
17,530!
363
  if (NULL == node->pLeft || (nParam == 2 && NULL == node->pRight)) {
17,530!
364
    indexError("invalid operation node, left: %p, rigth: %p", node->pLeft, node->pRight);
×
365
    SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
×
366
  }
367
  if (node->opType == OP_TYPE_JSON_GET_VALUE) {
17,559!
368
    return code;
×
369
  }
370
  if ((node->pLeft != NULL && nodeType(node->pLeft) == QUERY_NODE_COLUMN) &&
17,559!
371
      (node->pRight != NULL && nodeType(node->pRight) == QUERY_NODE_VALUE)) {
17,558!
372
    SColumnNode *cn = (SColumnNode *)(node->pLeft);
17,559✔
373
    if (cn->node.resType.type == TSDB_DATA_TYPE_JSON) {
17,559✔
374
      SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
22!
375
    }
376
  }
377

378
  SIFParam *paramList = taosMemoryCalloc(nParam, sizeof(SIFParam));
17,537!
379

380
  if (NULL == paramList) {
17,526!
381
    SIF_ERR_RET(terrno);
×
382
  }
383

384
  if (nodeType(node->pLeft) == QUERY_NODE_OPERATOR &&
17,526!
385
      (((SOperatorNode *)(node->pLeft))->opType == OP_TYPE_JSON_GET_VALUE)) {
×
386
    SNode *interNode = (node->pLeft);
×
387
    SIF_ERR_JRET(sifInitJsonParam(interNode, &paramList[0], ctx));
×
388
    if (nParam > 1) {
×
389
      SIF_ERR_JRET(sifInitParam(node->pRight, &paramList[1], ctx));
×
390
    }
391
    paramList[0].colValType = TSDB_DATA_TYPE_JSON;
×
392
    *params = paramList;
×
393
    return TSDB_CODE_SUCCESS;
×
394
  } else {
395
    SIF_ERR_JRET(sifInitParam(node->pLeft, &paramList[0], ctx));
17,526!
396

397
    if (nParam > 1) {
17,521!
398
      SIF_ERR_JRET(sifInitParam(node->pRight, &paramList[1], ctx));
17,526!
399
    }
400
    *params = paramList;
17,550✔
401
    return TSDB_CODE_SUCCESS;
17,550✔
402
  }
403
_return:
×
404
  for (int i = 0; i < nParam; i++) sifFreeParam(&paramList[i]);
×
405
  taosMemoryFree(paramList);
×
406
  SIF_RET(code);
×
407
}
408
static int32_t sifInitParamList(SIFParam **params, SNodeList *nodeList, SIFCtx *ctx) {
1,475✔
409
  int32_t   code = 0;
1,475✔
410
  SIFParam *tParams = taosMemoryCalloc(nodeList->length, sizeof(SIFParam));
1,475!
411
  if (tParams == NULL) {
1,478!
412
    indexError("failed to calloc, nodeList: %p", nodeList);
×
413
    SIF_ERR_RET(terrno);
×
414
  }
415

416
  SListCell *cell = nodeList->pHead;
1,478✔
417
  for (int32_t i = 0; i < nodeList->length; i++) {
3,355✔
418
    if (NULL == cell || NULL == cell->pNode) {
1,874!
419
      SIF_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
×
420
    }
421
    SIF_ERR_JRET(sifInitParam(cell->pNode, &tParams[i], ctx));
1,874!
422
    cell = cell->pNext;
1,877✔
423
  }
424
  *params = tParams;
1,481✔
425
  return TSDB_CODE_SUCCESS;
1,481✔
426

427
_return:
×
428
  taosMemoryFree(tParams);
×
429
  SIF_RET(code);
×
430
}
431
static int32_t sifExecFunction(SFunctionNode *node, SIFCtx *ctx, SIFParam *output) {
87✔
432
  indexError("index-filter not support buildin function");
87!
433
  return TSDB_CODE_QRY_INVALID_INPUT;
88✔
434
}
435

436
typedef int (*FilterFunc)(void *a, void *b, int16_t dtype);
437

438
static FORCE_INLINE int sifGreaterThan(void *a, void *b, int16_t dtype) {
20,015✔
439
  __compar_fn_t func = getComparFunc(dtype, 0);
20,015✔
440
  if (func == NULL) {
20,011!
441
    return -1;
×
442
  }
443
  return tDoCompare(func, QUERY_GREATER_THAN, a, b);
20,011✔
444
}
445
static FORCE_INLINE int sifGreaterEqual(void *a, void *b, int16_t dtype) {
13,076✔
446
  __compar_fn_t func = getComparFunc(dtype, 0);
13,076✔
447
  if (func == NULL) {
13,078!
448
    return -1;
×
449
  }
450
  return tDoCompare(func, QUERY_GREATER_EQUAL, a, b);
13,078✔
451
}
452
static FORCE_INLINE int sifLessEqual(void *a, void *b, int16_t dtype) {
22,334✔
453
  __compar_fn_t func = getComparFunc(dtype, 0);
22,334✔
454
  if (func == NULL) {
22,328!
455
    return -1;
×
456
  }
457
  return tDoCompare(func, QUERY_LESS_EQUAL, a, b);
22,328✔
458
}
459
static FORCE_INLINE int sifLessThan(void *a, void *b, int16_t dtype) {
13,498✔
460
  __compar_fn_t func = getComparFunc(dtype, 0);
13,498✔
461
  if (func == NULL) {
13,501!
462
    return -1;
×
463
  }
464
  return (int)tDoCompare(func, QUERY_LESS_THAN, a, b);
13,501✔
465
}
466
static FORCE_INLINE int sifEqual(void *a, void *b, int16_t dtype) {
7,229✔
467
  __compar_fn_t func = getComparFunc(dtype, 0);
7,229✔
468
  if (func == NULL) {
7,236!
469
    return -1;
×
470
  }
471
  //__compar_fn_t func = idxGetCompar(dtype);
472
  return (int)tDoCompare(func, QUERY_TERM, a, b);
7,236✔
473
}
474
static FORCE_INLINE FilterFunc sifGetFilterFunc(EIndexQueryType type, bool *reverse, bool *equal) {
475
  if (type == QUERY_LESS_EQUAL || type == QUERY_LESS_THAN) {
5,703✔
476
    *reverse = true;
1,774✔
477
  } else {
478
    *reverse = false;
4,900✔
479
  }
480

481
  if (type == QUERY_LESS_EQUAL)
6,674✔
482
    return sifLessEqual;
980✔
483
  else if (type == QUERY_LESS_THAN)
5,694✔
484
    return sifLessThan;
804✔
485
  else if (type == QUERY_GREATER_EQUAL)
4,890✔
486
    return sifGreaterEqual;
745✔
487
  else if (type == QUERY_GREATER_THAN)
4,145✔
488
    return sifGreaterThan;
931✔
489
  else if (type == QUERY_TERM) {
3,214!
490
    *equal = true;
3,216✔
491
    return sifEqual;
3,216✔
492
  }
493
  return NULL;
×
494
}
495
int32_t sifStr2Num(char *buf, int32_t len, int8_t type, void *val) {
×
496
  // signed/unsigned/float
497
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
498
    int64_t v = 0;
×
499
    if (0 != toInteger(buf, len, 10, &v)) {
×
500
      return TSDB_CODE_INVALID_PARA;
×
501
    }
502
    if (type == TSDB_DATA_TYPE_BIGINT) {
×
503
      *(int64_t *)val = v;
×
504
    } else if (type == TSDB_DATA_TYPE_INT) {
×
505
      *(int32_t *)val = v;
×
506
    } else if (type == TSDB_DATA_TYPE_TINYINT) {
×
507
      *(int8_t *)val = v;
×
508
    } else if (type == TSDB_DATA_TYPE_SMALLINT) {
×
509
      *(int16_t *)val = v;
×
510
    }
511
  } else if (IS_FLOAT_TYPE(type)) {
×
512
    if (type == TSDB_DATA_TYPE_FLOAT) {
×
513
      *(float *)val = taosStr2Float(buf, NULL);
×
514
    } else {
515
      *(double *)val = taosStr2Double(buf, NULL);
×
516
    }
517
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
518
    uint64_t v = 0;
×
519
    if (0 != toUInteger(buf, len, 10, &v)) {
×
520
      return TSDB_CODE_INVALID_PARA;
×
521
    }
522
    if (type == TSDB_DATA_TYPE_UBIGINT) {
×
523
      *(uint64_t *)val = v;
×
524
    } else if (type == TSDB_DATA_TYPE_UINT) {
×
525
      *(uint32_t *)val = v;
×
526
    } else if (type == TSDB_DATA_TYPE_UTINYINT) {
×
527
      *(uint8_t *)val = v;
×
528
    } else if (type == TSDB_DATA_TYPE_USMALLINT) {
×
529
      *(uint16_t *)val = v;
×
530
    }
531
  } else {
532
    return TSDB_CODE_INVALID_PARA;
×
533
  }
534
  return 0;
×
535
}
536

537
static int32_t sifSetFltParam(SIFParam *left, SIFParam *right, SDataTypeBuf *typedata, SMetaFltParam *param) {
6,643✔
538
  int32_t code = 0;
6,643✔
539
  int8_t  ltype = left->colValType, rtype = right->colValType;
6,643✔
540
  // if (!IS_NUMERIC_TYPE(ltype) || !((IS_NUMERIC_TYPE(rtype)) || rtype == TSDB_DATA_TYPE_VARCHAR)) {
541
  //   return TSDB_CODE_INVALID_PARA;
542
  // }
543
  if (IS_VAR_DATA_TYPE(ltype)) {
6,643!
544
    if (ltype == TSDB_DATA_TYPE_VARCHAR || ltype == TSDB_DATA_TYPE_BINARY || ltype == TSDB_DATA_TYPE_VARBINARY ||
333!
545
        ltype == TSDB_DATA_TYPE_NCHAR) {
546
      return 0;
333✔
547
    } else {
548
      return TSDB_CODE_INVALID_PARA;
×
549
    }
550
  }
551

552
  if (ltype == TSDB_DATA_TYPE_FLOAT) {
6,310!
553
    float f = 0;
×
554
    if (IS_NUMERIC_TYPE(rtype)) {
×
555
      SIF_DATA_CONVERT(rtype, right->condValue, f);
×
556
    } else {
557
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_FLOAT, &f));
×
558
    }
559
    typedata->f = f;
×
560
    param->val = &typedata->f;
×
561
  } else if (ltype == TSDB_DATA_TYPE_DOUBLE) {
6,310!
562
    double d = 0;
×
563
    if (IS_NUMERIC_TYPE(rtype)) {
×
564
      SIF_DATA_CONVERT(rtype, right->condValue, d);
×
565
    } else {
566
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_DOUBLE, &d));
×
567
    }
568
    typedata->d = d;
×
569
    param->val = &typedata->d;
×
570
  } else if (ltype == TSDB_DATA_TYPE_BIGINT) {
6,310✔
571
    int64_t i64 = 0;
43✔
572
    if (IS_NUMERIC_TYPE(rtype)) {
43!
573
      SIF_DATA_CONVERT(rtype, right->condValue, i64);
43!
574
    } else {
575
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_BIGINT, &i64));
×
576
    }
577
    typedata->i64 = i64;
43✔
578
    param->val = &typedata->i64;
43✔
579
  } else if (ltype == TSDB_DATA_TYPE_INT) {
6,267✔
580
    int32_t i32 = 0;
5,388✔
581
    if (IS_NUMERIC_TYPE(rtype)) {
5,388!
582
      SIF_DATA_CONVERT(rtype, right->condValue, i32);
5,388!
583
    } else {
584
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_INT, &i32));
×
585
    }
586
    typedata->i32 = i32;
5,407✔
587
    param->val = &typedata->i32;
5,407✔
588
  } else if (ltype == TSDB_DATA_TYPE_SMALLINT) {
879✔
589
    int16_t i16 = 0;
118✔
590
    if (IS_NUMERIC_TYPE(rtype)) {
118!
591
      SIF_DATA_CONVERT(rtype, right->condValue, i16);
118!
592
    } else {
593
      SIF_ERR_RET(
×
594
          sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_SMALLINT, &i16));
595
    }
596

597
    typedata->i16 = i16;
118✔
598
    param->val = &typedata->i16;
118✔
599
  } else if (ltype == TSDB_DATA_TYPE_TINYINT) {
761✔
600
    int8_t i8 = 0;
447✔
601
    if (IS_NUMERIC_TYPE(rtype)) {
447!
602
      SIF_DATA_CONVERT(rtype, right->condValue, i8);
447!
603
    } else {
604
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_TINYINT, &i8));
×
605
    }
606
    typedata->i8 = i8;
447✔
607
    param->val = &typedata->i8;
447✔
608
  } else if (ltype == TSDB_DATA_TYPE_UBIGINT) {
314!
609
    uint64_t u64 = 0;
×
610
    if (IS_NUMERIC_TYPE(rtype)) {
×
611
      SIF_DATA_CONVERT(rtype, right->condValue, u64);
×
612
    } else {
613
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UBIGINT, &u64));
×
614
    }
615
    typedata->u64 = u64;
×
616
    param->val = &typedata->u64;
×
617
  } else if (ltype == TSDB_DATA_TYPE_UINT) {
314!
618
    uint32_t u32 = 0;
×
619
    if (IS_NUMERIC_TYPE(rtype)) {
×
620
      SIF_DATA_CONVERT(rtype, right->condValue, u32);
×
621
    } else {
622
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UINT, &u32));
×
623
    }
624
    typedata->u32 = u32;
×
625
    param->val = &typedata->u32;
×
626
  } else if (ltype == TSDB_DATA_TYPE_USMALLINT) {
314!
627
    uint16_t u16 = 0;
×
628
    if (IS_NUMERIC_TYPE(rtype)) {
×
629
      SIF_DATA_CONVERT(rtype, right->condValue, u16);
×
630
    } else {
631
      SIF_ERR_RET(
×
632
          sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_USMALLINT, &u16));
633
    }
634
    typedata->u16 = u16;
×
635
    param->val = &typedata->u16;
×
636
  } else if (ltype == TSDB_DATA_TYPE_UTINYINT) {
314!
637
    uint8_t u8 = 0;
×
638
    if (IS_NUMERIC_TYPE(rtype)) {
×
639
      SIF_DATA_CONVERT(rtype, right->condValue, u8);
×
640
    } else {
641
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UTINYINT, &u8));
×
642
    }
643
    typedata->u8 = u8;
×
644
    param->val = &typedata->u8;
×
645
  }
646
  return 0;
6,329✔
647
}
648

649
static int8_t sifShouldUseIndexBasedOnType(SIFParam *left, SIFParam *right) {
7,751✔
650
  // not compress
651
  if (left->colValType == TSDB_DATA_TYPE_FLOAT) return 0;
7,751✔
652

653
  if (left->colValType == TSDB_DATA_TYPE_GEOMETRY || right->colValType == TSDB_DATA_TYPE_GEOMETRY ||
7,719!
654
      left->colValType == TSDB_DATA_TYPE_JSON || right->colValType == TSDB_DATA_TYPE_JSON) {
7,742!
655
    return 0;
×
656
  }
657

658
  if (IS_VAR_DATA_TYPE(left->colValType)) {
7,741!
659
    if (!IS_VAR_DATA_TYPE(right->colValType)) return 0;
904!
660
  } else if (IS_NUMERIC_TYPE(left->colValType)) {
6,837!
661
    if (IS_SIGNED_NUMERIC_TYPE(left->colValType) && IS_SIGNED_NUMERIC_TYPE(right->colValType)) {
6,559!
662
      if (left->colValType >= right->colValType) {
6,475✔
663
        return 1;  // use index
6,031✔
664
      } else {
665
        return 0;  // not use index
444✔
666
      }
667
    } else {
668
      return 0;
84✔
669
    }
670
  }
671
  return 1;
638✔
672
}
673
static int32_t sifDoIndex(SIFParam *left, SIFParam *right, int8_t operType, SIFParam *output) {
8,309✔
674
  int             ret = 0;
8,309✔
675
  SIndexMetaArg  *arg = &output->arg;
8,309✔
676
  EIndexQueryType qtype = 0;
8,309✔
677
  SIF_ERR_RET(sifGetFuncFromSql(operType, &qtype));
16,618✔
678
  if (left->colValType == TSDB_DATA_TYPE_JSON) {
7,762!
679
    SIndexTerm *tm = indexTermCreate(arg->suid, DEFAULT, right->colValType, left->colName, strlen(left->colName),
×
680
                                     right->condValue, strlen(right->condValue));
×
681
    if (tm == NULL) {
×
682
      return TSDB_CODE_OUT_OF_MEMORY;
×
683
    }
684

685
    SIndexMultiTermQuery *mtm = indexMultiTermQueryCreate(MUST);
×
686
    if (mtm == NULL) {
×
687
      indexTermDestroy(tm);
×
688
      return TSDB_CODE_OUT_OF_MEMORY;
×
689
    }
690

691
    if ((ret = indexMultiTermQueryAdd(mtm, tm, qtype)) != 0) {
×
692
      indexMultiTermQueryDestroy(mtm);
×
693
      return ret;
×
694
    }
695

696
    ret = indexJsonSearch(arg->ivtIdx, mtm, output->result);
×
697
    indexMultiTermQueryDestroy(mtm);
×
698
  } else {
699
    int8_t useIndex = sifShouldUseIndexBasedOnType(left, right);
7,762✔
700
    if (!useIndex) {
7,776✔
701
      output->status = SFLT_NOT_INDEX;
1,102✔
702
      return TSDB_CODE_INVALID_PARA;
1,102✔
703
    }
704

705
    bool       reverse = false, equal = false;
6,674✔
706
    FilterFunc filterFunc = sifGetFilterFunc(qtype, &reverse, &equal);
6,674✔
707

708
    SMetaFltParam param = {.suid = arg->suid,
6,674✔
709
                           .cid = left->colId,
6,674✔
710
                           .type = left->colValType,
6,674✔
711
                           .val = right->condValue,
6,674✔
712
                           .reverse = reverse,
713
                           .equal = equal,
714
                           .filterFunc = filterFunc};
715

716
    char buf[128] = {0};
6,674✔
717

718
    SDataTypeBuf typedata;
719
    memset(&typedata, 0, sizeof(typedata));
6,674✔
720

721
    if (sifSetFltParam(left, right, &typedata, &param) != 0) {
6,674!
722
      output->status = SFLT_NOT_INDEX;
×
723
      return TSDB_CODE_INVALID_PARA;
×
724
    }
725

726
    ret = left->api.metaFilterTableIds(arg->metaEx, &param, output->result);
6,656✔
727
    if (ret == 0) {
6,684!
728
      taosArraySort(output->result, uidCompare);
6,685✔
729
      taosArrayRemoveDuplicate(output->result, uidCompare, NULL);
6,668✔
730
    }
731
  }
732
  return ret;
6,672✔
733
}
734

735
static FORCE_INLINE int32_t sifLessThanFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
811✔
736
  int id = OP_TYPE_LOWER_THAN;
811✔
737
  return sifDoIndex(left, right, id, output);
811✔
738
}
739
static FORCE_INLINE int32_t sifLessEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
1,520✔
740
  int id = OP_TYPE_LOWER_EQUAL;
1,520✔
741
  return sifDoIndex(left, right, id, output);
1,520✔
742
}
743

744
static FORCE_INLINE int32_t sifGreaterThanFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
934✔
745
  int id = OP_TYPE_GREATER_THAN;
934✔
746
  return sifDoIndex(left, right, id, output);
934✔
747
}
748
static FORCE_INLINE int32_t sifGreaterEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
747✔
749
  int id = OP_TYPE_GREATER_EQUAL;
747✔
750
  return sifDoIndex(left, right, id, output);
747✔
751
}
752

753
static FORCE_INLINE int32_t sifEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
3,755✔
754
  int id = OP_TYPE_EQUAL;
3,755✔
755
  return sifDoIndex(left, right, id, output);
3,755✔
756
}
757
static FORCE_INLINE int32_t sifNotEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
546✔
758
  int id = OP_TYPE_NOT_EQUAL;
546✔
759
  return sifDoIndex(left, right, id, output);
546✔
760
}
761
static FORCE_INLINE int32_t sifInFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
762
  int id = OP_TYPE_IN;
×
763
  return sifDoIndex(left, right, id, output);
×
764
}
765
static FORCE_INLINE int32_t sifNotInFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
766
  int id = OP_TYPE_NOT_IN;
×
767
  return sifDoIndex(left, right, id, output);
×
768
}
769
static FORCE_INLINE int32_t sifLikeFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
770
  int id = OP_TYPE_LIKE;
×
771
  return sifDoIndex(left, right, id, output);
×
772
}
773
static FORCE_INLINE int32_t sifNotLikeFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
774
  int id = OP_TYPE_NOT_LIKE;
×
775
  return sifDoIndex(left, right, id, output);
×
776
}
777

778
static FORCE_INLINE int32_t sifMatchFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
779
  int id = OP_TYPE_MATCH;
×
780
  return sifDoIndex(left, right, id, output);
×
781
}
782
static FORCE_INLINE int32_t sifNotMatchFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
783
  int id = OP_TYPE_NMATCH;
×
784
  return sifDoIndex(left, right, id, output);
×
785
}
786
static FORCE_INLINE int32_t sifJsonContains(SIFParam *left, SIFParam *right, SIFParam *output) {
×
787
  int id = OP_TYPE_JSON_CONTAINS;
×
788
  return sifDoIndex(left, right, id, output);
×
789
}
790
static FORCE_INLINE int32_t sifJsonGetValue(SIFParam *left, SIFParam *rigth, SIFParam *output) {
×
791
  // return 0
792
  return 0;
×
793
}
794

795
static FORCE_INLINE int32_t sifDefaultFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
796
  // add more except
797
  return TSDB_CODE_QRY_INVALID_INPUT;
798
}
799

800
static FORCE_INLINE int32_t sifGetOperFn(int32_t funcId, sif_func_t *func, SIdxFltStatus *status) {
801
  // impl later
802
  *status = SFLT_ACCURATE_INDEX;
17,496✔
803
  switch (funcId) {
17,496✔
804
    case OP_TYPE_GREATER_THAN:
2,084✔
805
      *func = sifGreaterThanFunc;
2,084✔
806
      return 0;
2,084✔
807
    case OP_TYPE_GREATER_EQUAL:
1,493✔
808
      *func = sifGreaterEqualFunc;
1,493✔
809
      return 0;
1,493✔
810
    case OP_TYPE_LOWER_THAN:
1,631✔
811
      *func = sifLessThanFunc;
1,631✔
812
      return 0;
1,631✔
813
    case OP_TYPE_LOWER_EQUAL:
3,041✔
814
      *func = sifLessEqualFunc;
3,041✔
815
      return 0;
3,041✔
816
    case OP_TYPE_EQUAL:
7,728✔
817
      *func = sifEqualFunc;
7,728✔
818
      return 0;
7,728✔
819
    case OP_TYPE_NOT_EQUAL:
1,489✔
820
      *status = SFLT_NOT_INDEX;
1,489✔
821
      *func = sifNotEqualFunc;
1,489✔
822
      return 0;
1,489✔
823
    case OP_TYPE_IN:
×
824
      *status = SFLT_NOT_INDEX;
×
825
      *func = sifInFunc;
×
826
      return 0;
×
827
    case OP_TYPE_NOT_IN:
×
828
      *status = SFLT_NOT_INDEX;
×
829
      *func = sifNotInFunc;
×
830
      return 0;
×
831
    case OP_TYPE_LIKE:
×
832
      *status = SFLT_NOT_INDEX;
×
833
      *func = sifLikeFunc;
×
834
      return 0;
×
835
    case OP_TYPE_NOT_LIKE:
×
836
      *status = SFLT_NOT_INDEX;
×
837
      *func = sifNotLikeFunc;
×
838
      return 0;
×
839
    case OP_TYPE_MATCH:
×
840
      *status = SFLT_NOT_INDEX;
×
841
      *func = sifMatchFunc;
×
842
      return 0;
×
843
    case OP_TYPE_NMATCH:
×
844
      *status = SFLT_NOT_INDEX;
×
845
      *func = sifNotMatchFunc;
×
846
      return 0;
×
847
    case OP_TYPE_JSON_CONTAINS:
×
848
      *status = SFLT_ACCURATE_INDEX;
×
849
      *func = sifJsonContains;
×
850
      return 0;
×
851
    case OP_TYPE_JSON_GET_VALUE:
×
852
      *status = SFLT_ACCURATE_INDEX;
×
853
      *func = sifJsonGetValue;
×
854
      return 0;
×
855
    default:
30✔
856
      *status = SFLT_NOT_INDEX;
30✔
857
      *func = sifNullFunc;
30✔
858
      return 0;
30✔
859
  }
860
  return 0;
861
}
862

863
static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) {
19,790✔
864
  int32_t code = TSDB_CODE_INVALID_PARA;
19,790✔
865
  if (sifValidOp(node->opType) < 0) {
39,580!
866
    code = TSDB_CODE_QRY_INVALID_INPUT;
1,626✔
867
    ctx->code = code;
1,626✔
868
    output->status = SFLT_NOT_INDEX;
1,626✔
869
    return code;
1,626✔
870
  }
871

872
  int32_t nParam = sifGetOperParamNum(node->opType);
18,164✔
873
  if (nParam <= 1) {
18,164✔
874
    output->status = SFLT_NOT_INDEX;
153✔
875
    return code;
153✔
876
  }
877
  if (node->opType == OP_TYPE_JSON_GET_VALUE) {
18,011✔
878
    return code;
452✔
879
  }
880

881
  SIFParam *params = NULL;
17,559✔
882
  SIF_ERR_RET(sifInitOperParams(&params, node, ctx));
17,559✔
883

884
  if (params[0].status == SFLT_NOT_INDEX || (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) {
17,534!
885
    output->status = SFLT_NOT_INDEX;
38✔
886
    goto _return;
38✔
887
  }
888

889
  // ugly code, refactor later
890
  output->arg = ctx->arg;
17,496✔
891
  sif_func_t operFn = sifNullFunc;
17,496✔
892

893
  if (!ctx->noExec) {
17,496✔
894
    code = 0;
8,336✔
895
    SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status));
16,672!
896
    SIF_ERR_JRET(operFn(&params[0], nParam > 1 ? &params[1] : NULL, output));
8,336✔
897
  } else {
898
    // ugly code, refactor later
899
    if (nParam > 1 && params[1].status == SFLT_NOT_INDEX) {
9,160!
900
      output->status = SFLT_NOT_INDEX;
×
901
      goto _return;
×
902
    }
903
    code = 0;
9,160✔
904
    SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status));
18,320!
905
  }
906
_return:
9,160✔
907
  for (int i = 0; i < nParam; i++) sifFreeParam(&params[i]);
52,537!
908
  taosMemoryFree(params);
17,533!
909
  if (code != 0) {
17,557✔
910
    output->status = SFLT_NOT_INDEX;
1,687✔
911
  } else {
912
    output->status = SFLT_COARSE_INDEX;
15,870✔
913
  }
914
  return code;
17,557✔
915
}
916

917
static int32_t sifExecLogic(SLogicConditionNode *node, SIFCtx *ctx, SIFParam *output) {
1,476✔
918
  if (NULL == node->pParameterList || node->pParameterList->length <= 0) {
1,476!
919
    indexError("invalid logic parameter list, list:%p, paramNum:%d", node->pParameterList,
×
920
               node->pParameterList ? node->pParameterList->length : 0);
921
    return TSDB_CODE_QRY_INVALID_INPUT;
×
922
  }
923

924
  int32_t   code = TSDB_CODE_SUCCESS;
1,476✔
925
  SIFParam *params = NULL;
1,476✔
926
  SIF_ERR_RET(sifInitParamList(&params, node->pParameterList, ctx));
1,476✔
927

928
  if (ctx->noExec == false) {
1,477✔
929
    for (int32_t m = 0; m < node->pParameterList->length; m++) {
507✔
930
      if (node->condType == LOGIC_COND_TYPE_AND) {
338✔
931
        if (taosArrayAddAll(output->result, params[m].result) == NULL) return terrno;
302!
932
      } else if (node->condType == LOGIC_COND_TYPE_OR) {
36!
933
        if (taosArrayAddAll(output->result, params[m].result) == NULL) return terrno;
36!
934
      } else if (node->condType == LOGIC_COND_TYPE_NOT) {
×
935
      }
936
      taosArraySort(output->result, uidCompare);
338✔
937
      taosArrayRemoveDuplicate(output->result, uidCompare, NULL);
337✔
938
    }
939
  } else {
940
    for (int32_t m = 0; m < node->pParameterList->length; m++) {
2,846✔
941
      output->status = sifMergeCond(node->condType, output->status, params[m].status);
3,076✔
942
    }
943
  }
944
_return:
1,308✔
945
  taosMemoryFree(params);
1,477!
946
  SIF_RET(code);
1,479!
947
}
948

949
static EDealRes sifWalkFunction(SNode *pNode, void *context) {
88✔
950
  SIFCtx        *ctx = context;
88✔
951
  SFunctionNode *node = (SFunctionNode *)pNode;
88✔
952
  SIFParam       output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
88✔
953
  if (output.result == NULL) {
88!
954
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
955
    return DEAL_RES_ERROR;
×
956
  }
957
  ctx->code = sifExecFunction(node, ctx, &output);
88✔
958
  if (ctx->code != TSDB_CODE_SUCCESS) {
88!
959
    sifFreeParam(&output);
960
    return DEAL_RES_ERROR;
88✔
961
  }
962

963
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
×
964
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
965
    return DEAL_RES_ERROR;
×
966
  }
967
  return DEAL_RES_CONTINUE;
×
968
}
969
static EDealRes sifWalkLogic(SNode *pNode, void *context) {
1,479✔
970
  SIFCtx              *ctx = context;
1,479✔
971
  SLogicConditionNode *node = (SLogicConditionNode *)pNode;
1,479✔
972

973
  SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
1,479✔
974
  if (output.result == NULL) {
1,478!
975
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
976
    return DEAL_RES_ERROR;
×
977
  }
978

979
  ctx->code = sifExecLogic(node, ctx, &output);
1,478✔
980
  if (ctx->code) {
1,479!
981
    sifFreeParam(&output);
982
    return DEAL_RES_ERROR;
×
983
  }
984

985
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
1,479!
986
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
987
    return DEAL_RES_ERROR;
×
988
  }
989
  return DEAL_RES_CONTINUE;
1,479✔
990
}
991
static EDealRes sifWalkOper(SNode *pNode, void *context) {
19,766✔
992
  SIFCtx        *ctx = context;
19,766✔
993
  SOperatorNode *node = (SOperatorNode *)pNode;
19,766✔
994
  SIFParam       output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
19,766✔
995
  if (output.result == NULL) {
19,810!
996
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
997
    return DEAL_RES_ERROR;
×
998
  }
999

1000
  ctx->code = sifExecOper(node, ctx, &output);
19,810✔
1001
  if (ctx->code) {
19,799✔
1002
    sifFreeParam(&output);
1003
    return DEAL_RES_ERROR;
3,936✔
1004
  }
1005
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
15,861!
1006
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
1007
    return DEAL_RES_ERROR;
×
1008
  }
1009

1010
  return DEAL_RES_CONTINUE;
15,843✔
1011
}
1012

1013
EDealRes sifCalcWalker(SNode *node, void *context) {
61,231✔
1014
  if (QUERY_NODE_VALUE == nodeType(node) || QUERY_NODE_NODE_LIST == nodeType(node) ||
61,231✔
1015
      QUERY_NODE_COLUMN == nodeType(node)) {
41,200✔
1016
    return DEAL_RES_CONTINUE;
39,882✔
1017
  }
1018
  SIFCtx *ctx = (SIFCtx *)context;
21,349✔
1019
  if (QUERY_NODE_FUNCTION == nodeType(node)) {
21,349✔
1020
    return sifWalkFunction(node, ctx);
88✔
1021
  }
1022
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(node)) {
21,261✔
1023
    return sifWalkLogic(node, ctx);
1,479✔
1024
  }
1025

1026
  if (QUERY_NODE_OPERATOR == nodeType(node)) {
19,782!
1027
    // indexInfo("node type for index filter, type: %d", nodeType(node));
1028
    return sifWalkOper(node, ctx);
19,783✔
1029
  }
1030

1031
  // indexError("invalid node type for index filter calculating, type:%d", nodeType(node));
1032
  ctx->code = TSDB_CODE_QRY_INVALID_INPUT;
×
1033
  return DEAL_RES_ERROR;
×
1034
}
1035

1036
void sifFreeRes(SHashObj *res) {
10,519✔
1037
  void *pIter = taosHashIterate(res, NULL);
10,519✔
1038
  while (pIter) {
10,863✔
1039
    SIFParam *p = pIter;
363✔
1040
    if (p) {
363!
1041
      sifFreeParam(p);
1042
    }
1043
    pIter = taosHashIterate(res, pIter);
364✔
1044
  }
1045
  taosHashCleanup(res);
10,500✔
1046
}
10,530✔
1047
static int32_t sifCalculate(SNode *pNode, SIFParam *pDst) {
8,125✔
1048
  if (pNode == NULL || pDst == NULL) {
8,125!
1049
    return TSDB_CODE_QRY_INVALID_INPUT;
×
1050
  }
1051

1052
  int32_t code = 0;
8,128✔
1053
  SIFCtx  ctx = {.code = 0, .noExec = false, .arg = pDst->arg, .pAPI = &pDst->api};
8,128✔
1054
  ctx.pRes = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
8,128✔
1055

1056
  if (NULL == ctx.pRes) {
8,141!
1057
    indexError("index-filter failed to taosHashInit");
×
1058
    return terrno;
×
1059
  }
1060

1061
  nodesWalkExprPostOrder(pNode, sifCalcWalker, &ctx);
8,141✔
1062

1063
  if (ctx.code != 0) {
8,137✔
1064
    sifFreeRes(ctx.pRes);
1,647✔
1065
    return ctx.code;
1,648✔
1066
  }
1067

1068
  if (pDst) {
6,490✔
1069
    SIFParam *res = (SIFParam *)taosHashGet(ctx.pRes, (void *)&pNode, POINTER_BYTES);
6,484✔
1070
    if (res == NULL) {
6,501!
1071
      indexError("no valid res in hash, node:(%p), type(%d)", (void *)&pNode, nodeType(pNode));
×
1072
      SIF_ERR_RET(TSDB_CODE_APP_ERROR);
×
1073
    }
1074
    if (res->result != NULL) {
6,491!
1075
      if (taosArrayAddAll(pDst->result, res->result) == NULL) {
6,497!
1076
        SIF_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
×
1077
      }
1078
    }
1079
    pDst->status = res->status;
6,491!
1080

1081
    sifFreeParam(res);
1082
    TAOS_UNUSED(taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES));
6,497✔
1083
  }
1084
  sifFreeRes(ctx.pRes);
6,505✔
1085
  return code;
6,501✔
1086
}
1087

1088
static int32_t sifGetFltHint(SNode *pNode, SIdxFltStatus *status, SMetaDataFilterAPI *pAPI) {
11,314✔
1089
  int32_t code = TSDB_CODE_SUCCESS;
11,314✔
1090
  if (pNode == NULL) {
11,314!
1091
    return TSDB_CODE_QRY_INVALID_INPUT;
×
1092
  }
1093

1094
  SIFCtx ctx = {.code = 0, .noExec = true, .pAPI = pAPI};
11,314✔
1095
  ctx.pRes = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
11,314✔
1096
  if (NULL == ctx.pRes) {
11,332!
1097
    indexError("index-filter failed to taosHashInit");
×
1098
    return terrno;
×
1099
  }
1100

1101
  nodesWalkExprPostOrder(pNode, sifCalcWalker, &ctx);
11,332✔
1102
  if (ctx.code != 0) {
11,309✔
1103
    sifFreeRes(ctx.pRes);
2,377✔
1104
    return ctx.code;
2,381✔
1105
  }
1106

1107
  SIFParam *res = (SIFParam *)taosHashGet(ctx.pRes, (void *)&pNode, POINTER_BYTES);
8,932✔
1108
  if (res == NULL) {
8,944!
1109
    indexError("no valid res in hash, node:(%p), type(%d)", (void *)&pNode, nodeType(pNode));
×
1110
    SIF_ERR_RET(TSDB_CODE_APP_ERROR);
×
1111
  }
1112
  *status = res->status;
8,922!
1113
  sifFreeParam(res);
1114
  TAOS_UNUSED(taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES));
8,944✔
1115

1116
  void *iter = taosHashIterate(ctx.pRes, NULL);
8,936✔
1117
  while (iter != NULL) {
10,446✔
1118
    SIFParam *data = (SIFParam *)iter;
1,538!
1119
    sifFreeParam(data);
1120
    iter = taosHashIterate(ctx.pRes, iter);
1,539✔
1121
  }
1122
  taosHashCleanup(ctx.pRes);
8,908✔
1123
  return code;
8,946✔
1124
}
1125

1126
int32_t doFilterTag(SNode *pFilterNode, SIndexMetaArg *metaArg, SArray *result, SIdxFltStatus *status,
11,300✔
1127
                    SMetaDataFilterAPI *pAPI) {
1128
  SIdxFltStatus st = idxGetFltStatus(pFilterNode, pAPI);
11,300✔
1129
  if (st == SFLT_NOT_INDEX) {
11,322✔
1130
    *status = st;
3,181✔
1131
    return 0;
3,181✔
1132
  }
1133

1134
  SFilterInfo *filter = NULL;
8,141✔
1135

1136
  SArray *output = taosArrayInit(8, sizeof(uint64_t));
8,141✔
1137
  if (output == NULL) {
8,145!
1138
    return terrno;
×
1139
  }
1140

1141
  SIFParam param = {.arg = *metaArg, .result = output, .status = SFLT_NOT_INDEX, .api = *pAPI};
8,145✔
1142
  int32_t  code = sifCalculate((SNode *)pFilterNode, &param);
8,145✔
1143
  if (code != 0) {
8,139✔
1144
    sifFreeParam(&param);
1145
    return code;
1,647✔
1146
  }
1147
  if (param.status == SFLT_NOT_INDEX) {
6,495!
1148
    *status = param.status;
×
1149
  } else {
1150
    *status = st;
6,495✔
1151
  }
1152

1153
  if (taosArrayAddAll(result, param.result) == NULL) {
6,495!
1154
    sifFreeParam(&param);
1155
    return TSDB_CODE_OUT_OF_MEMORY;
×
1156
  }
1157

1158
  sifFreeParam(&param);
1159
  return TSDB_CODE_SUCCESS;
6,495✔
1160
}
1161

1162
SIdxFltStatus idxGetFltStatus(SNode *pFilterNode, SMetaDataFilterAPI *pAPI) {
11,313✔
1163
  SIdxFltStatus st = SFLT_NOT_INDEX;
11,313✔
1164
  if (pFilterNode == NULL) {
11,313!
1165
    return SFLT_NOT_INDEX;
×
1166
  }
1167

1168
  if (sifGetFltHint((SNode *)pFilterNode, &st, pAPI) != TSDB_CODE_SUCCESS) {
11,313✔
1169
    st = SFLT_NOT_INDEX;
2,381✔
1170
  }
1171
  return st;
11,326✔
1172
}
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

© 2025 Coveralls, Inc