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

taosdata / TDengine / #3531

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

push

travis-ci

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

fix:TD-32366/stmt add geometry datatype check

118529 of 252344 branches covered (46.97%)

Branch coverage included in aggregate %.

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

2282 existing lines in 115 files now uncovered.

199096 of 275161 relevant lines covered (72.36%)

6067577.83 hits per line

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

40.6
/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 "tdatablock.h"
25

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

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

38
  int8_t  i8;
39
  int16_t i16;
40
  int32_t i32;
41
  int64_t i64;
42

43
  double d;
44
  float  f;
45
} SDataTypeBuf;
46

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

69
typedef struct SIFParam {
70
  SHashObj *pFilter;
71
  SArray   *result;
72
  char     *condValue;
73

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

81
  SIndexMetaArg      arg;
82
  SMetaDataFilterAPI api;
83
} SIFParam;
84

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

93
static FORCE_INLINE int32_t sifGetFuncFromSql(EOperatorType src, EIndexQueryType *dst) {
94
  if (src == OP_TYPE_GREATER_THAN) {
6,014✔
95
    *dst = QUERY_GREATER_THAN;
675✔
96
  } else if (src == OP_TYPE_GREATER_EQUAL) {
5,339✔
97
    *dst = QUERY_GREATER_EQUAL;
348✔
98
  } else if (src == OP_TYPE_LOWER_THAN) {
4,991✔
99
    *dst = QUERY_LESS_THAN;
410✔
100
  } else if (src == OP_TYPE_LOWER_EQUAL) {
4,581✔
101
    *dst = QUERY_LESS_EQUAL;
1,190✔
102
  } else if (src == OP_TYPE_EQUAL) {
3,391✔
103
    *dst = QUERY_TERM;
2,723✔
104
  } else if (src == OP_TYPE_LIKE || src == OP_TYPE_MATCH || src == OP_TYPE_NMATCH) {
668!
UNCOV
105
    *dst = QUERY_REGEX;
×
106
  } else if (src == OP_TYPE_JSON_CONTAINS) {
670!
107
    *dst = QUERY_PREFIX;
×
108
  } else {
109
    return TSDB_CODE_QRY_INVALID_INPUT;
670✔
110
  }
111
  return TSDB_CODE_SUCCESS;
5,344✔
112
}
113

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

117
static FORCE_INLINE void sifFreeParam(SIFParam *param) {
118
  if (param == NULL) return;
14,190!
119

120
  taosArrayDestroy(param->result);
45,395✔
121
  taosMemoryFree(param->condValue);
45,400✔
122
  param->condValue = NULL;
45,413✔
123
  taosHashCleanup(param->pFilter);
45,413✔
124
  param->pFilter = NULL;
45,407✔
125
}
126

127
static FORCE_INLINE int32_t sifGetOperParamNum(EOperatorType ty) {
128
  if (OP_TYPE_IS_NULL == ty || OP_TYPE_IS_NOT_NULL == ty || OP_TYPE_IS_TRUE == ty || OP_TYPE_IS_NOT_TRUE == ty ||
25,281!
129
      OP_TYPE_IS_FALSE == ty || OP_TYPE_IS_NOT_FALSE == ty || OP_TYPE_IS_UNKNOWN == ty ||
25,167!
130
      OP_TYPE_IS_NOT_UNKNOWN == ty || OP_TYPE_MINUS == ty) {
25,164!
131
    return 1;
95✔
132
  }
133
  return 2;
25,165✔
134
}
135
static FORCE_INLINE int32_t sifValidOp(EOperatorType ty) {
136
  if ((ty >= OP_TYPE_ADD && ty <= OP_TYPE_BIT_OR) || (ty == OP_TYPE_IN || ty == OP_TYPE_NOT_IN) ||
14,472✔
137
      (ty == OP_TYPE_LIKE || ty == OP_TYPE_NOT_LIKE || ty == OP_TYPE_MATCH || ty == OP_TYPE_NMATCH)) {
14,318!
138
    return TSDB_CODE_INVALID_PARA;
1,533✔
139
  }
140
  return 0;
12,939✔
141
}
142
static FORCE_INLINE int32_t sifValidColumn(SColumnNode *cn) {
143
  // add more check
144
  if (cn == NULL) {
12,323✔
145
    return TSDB_CODE_QRY_INVALID_INPUT;
×
146
  }
147
  if (cn->colType != COLUMN_TYPE_TAG) {
12,323!
148
    return TSDB_CODE_QRY_INVALID_INPUT;
×
149
  }
150
  return TSDB_CODE_SUCCESS;
12,323✔
151
}
152

153
static FORCE_INLINE SIdxFltStatus sifMergeCond(ELogicConditionType type, SIdxFltStatus ls, SIdxFltStatus rs) {
154
  // enh rule later
155
  if (type == LOGIC_COND_TYPE_AND) {
478✔
156
    if (ls == SFLT_NOT_INDEX || rs == SFLT_NOT_INDEX) {
370!
157
      if (ls == SFLT_NOT_INDEX)
×
158
        return rs;
×
159
      else
160
        return ls;
×
161
    }
162
    return SFLT_COARSE_INDEX;
370✔
163
  } else if (type == LOGIC_COND_TYPE_OR) {
108!
164
    return SFLT_COARSE_INDEX;
108✔
165
  } else if (type == LOGIC_COND_TYPE_NOT) {
×
166
    return SFLT_NOT_INDEX;
×
167
  }
168
  return SFLT_NOT_INDEX;
×
169
}
170

171
static FORCE_INLINE int32_t sifGetValueFromNode(SNode *node, char **value) {
172
  // covert data From snode;
173
  SValueNode *vn = (SValueNode *)node;
12,305✔
174

175
  char      *pData = nodesGetValueFromNode(vn);
12,305✔
176
  SDataType *pType = &vn->node.resType;
12,302✔
177
  int32_t    type = pType->type;
12,302✔
178
  int32_t    valLen = 0;
12,302✔
179

180
  if (IS_VAR_DATA_TYPE(type)) {
12,302!
181
    int32_t dataLen = varDataTLen(pData);
771✔
182
    if (type == TSDB_DATA_TYPE_JSON) {
771!
183
      if (*pData == TSDB_DATA_TYPE_NULL) {
×
184
        dataLen = 0;
×
185
      } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
×
186
        dataLen = varDataTLen(pData);
×
187
      } else if (*pData == TSDB_DATA_TYPE_DOUBLE) {
×
188
        dataLen = LONG_BYTES;
×
189
      } else if (*pData == TSDB_DATA_TYPE_BOOL) {
×
190
        dataLen = CHAR_BYTES;
×
191
      }
192
      dataLen += CHAR_BYTES;
×
193
    }
194
    valLen = dataLen;
771✔
195
  } else {
196
    valLen = pType->bytes;
11,531✔
197
  }
198
  char *tv = taosMemoryCalloc(1, valLen + 1);
12,302✔
199
  if (tv == NULL) {
12,314!
200
    return terrno;
×
201
  }
202

203
  memcpy(tv, pData, valLen);
12,319✔
204
  *value = tv;
12,319✔
205

206
  return TSDB_CODE_SUCCESS;
12,319✔
207
}
208

209
static FORCE_INLINE int32_t sifInitJsonParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
210
  SOperatorNode *nd = (SOperatorNode *)node;
×
211
  if (nodeType(node) != QUERY_NODE_OPERATOR) {
×
212
    return TSDB_CODE_INVALID_PARA;
×
213
  }
214
  SColumnNode *l = (SColumnNode *)nd->pLeft;
×
215
  SValueNode  *r = (SValueNode *)nd->pRight;
×
216

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

250
  SDataType *pVType = &vn->node.resType;
×
251
  int32_t    vtype = pVType->type;
×
252
  char      *pData = nodesGetValueFromNode(vn);
×
253
  int32_t    valLen = 0;
×
254
  char     **value = &param->condValue;
×
255

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

279
  memcpy(tv, pData, valLen);
×
280
  *value = tv;
×
281

282
  param->colId = -1;
×
283
  param->colValType = (uint8_t)(vn->node.resType.type);
×
284
  if (vn->literal != NULL && strlen(vn->literal) <= sizeof(param->colName)) {
×
285
    memcpy(param->colName, vn->literal, strlen(vn->literal));
×
286
  } else {
287
    param->status = SFLT_NOT_INDEX;
×
288
  }
289
  return 0;
×
290
}
291
static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) {
25,107✔
292
  param->status = SFLT_COARSE_INDEX;
25,107✔
293
  param->api = *ctx->pAPI;
25,107✔
294

295
  switch (nodeType(node)) {
25,107!
296
    case QUERY_NODE_VALUE: {
12,329✔
297
      SValueNode *vn = (SValueNode *)node;
12,329✔
298
      if (vn->typeData == TSDB_DATA_TYPE_NULL && (vn->literal == NULL || strlen(vn->literal) == 0)) {
12,329!
299
        param->status = SFLT_NOT_INDEX;
24✔
300
        return 0;
24✔
301
      }
302
      SIF_ERR_RET(sifGetValueFromNode(node, &param->condValue));
24,624!
303
      param->colId = -1;
12,319✔
304
      param->colValType = (uint8_t)(vn->node.resType.type);
12,319✔
305
      if (vn->literal != NULL && strlen(vn->literal) <= sizeof(param->colName)) {
12,319✔
306
        memcpy(param->colName, vn->literal, strlen(vn->literal));
12,307✔
307
      } else {
308
        param->status = SFLT_NOT_INDEX;
12✔
309
      }
310
      break;
12,319✔
311
    }
312
    case QUERY_NODE_COLUMN: {
12,323✔
313
      SColumnNode *cn = (SColumnNode *)node;
12,323!
314
      /*only support tag column*/
315
      SIF_ERR_RET(sifValidColumn(cn));
12,323!
316

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

355
static int32_t sifInitOperParams(SIFParam **params, SOperatorNode *node, SIFCtx *ctx) {
12,328✔
356
  int32_t code = 0;
12,328✔
357
  int32_t nParam = sifGetOperParamNum(node->opType);
12,328!
358
  if (NULL == node->pLeft || (nParam == 2 && NULL == node->pRight)) {
12,328!
359
    indexError("invalid operation node, left: %p, rigth: %p", node->pLeft, node->pRight);
×
360
    SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
×
361
  }
362
  if (node->opType == OP_TYPE_JSON_GET_VALUE) {
12,355!
363
    return code;
×
364
  }
365
  if ((node->pLeft != NULL && nodeType(node->pLeft) == QUERY_NODE_COLUMN) &&
12,355!
366
      (node->pRight != NULL && nodeType(node->pRight) == QUERY_NODE_VALUE)) {
12,357!
367
    SColumnNode *cn = (SColumnNode *)(node->pLeft);
12,356✔
368
    if (cn->node.resType.type == TSDB_DATA_TYPE_JSON) {
12,356✔
369
      SIF_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT);
20!
370
    }
371
  }
372

373
  SIFParam *paramList = taosMemoryCalloc(nParam, sizeof(SIFParam));
12,335✔
374

375
  if (NULL == paramList) {
12,323!
376
    SIF_ERR_RET(terrno);
×
377
  }
378

379
  if (nodeType(node->pLeft) == QUERY_NODE_OPERATOR &&
12,323!
380
      (((SOperatorNode *)(node->pLeft))->opType == OP_TYPE_JSON_GET_VALUE)) {
×
381
    SNode *interNode = (node->pLeft);
×
382
    SIF_ERR_JRET(sifInitJsonParam(interNode, &paramList[0], ctx));
×
383
    if (nParam > 1) {
×
384
      SIF_ERR_JRET(sifInitParam(node->pRight, &paramList[1], ctx));
×
385
    }
386
    paramList[0].colValType = TSDB_DATA_TYPE_JSON;
×
387
    *params = paramList;
×
388
    return TSDB_CODE_SUCCESS;
×
389
  } else {
390
    SIF_ERR_JRET(sifInitParam(node->pLeft, &paramList[0], ctx));
12,323!
391

392
    if (nParam > 1) {
12,325!
393
      SIF_ERR_JRET(sifInitParam(node->pRight, &paramList[1], ctx));
12,330!
394
    }
395
    *params = paramList;
12,336✔
396
    return TSDB_CODE_SUCCESS;
12,336✔
397
  }
398
_return:
×
399
  for (int i = 0; i < nParam; i++) sifFreeParam(&paramList[i]);
×
400
  taosMemoryFree(paramList);
×
401
  SIF_RET(code);
×
402
}
403
static int32_t sifInitParamList(SIFParam **params, SNodeList *nodeList, SIFCtx *ctx) {
223✔
404
  int32_t   code = 0;
223✔
405
  SIFParam *tParams = taosMemoryCalloc(nodeList->length, sizeof(SIFParam));
223✔
406
  if (tParams == NULL) {
223!
407
    indexError("failed to calloc, nodeList: %p", nodeList);
×
408
    SIF_ERR_RET(terrno);
×
409
  }
410

411
  SListCell *cell = nodeList->pHead;
223✔
412
  for (int32_t i = 0; i < nodeList->length; i++) {
701✔
413
    if (NULL == cell || NULL == cell->pNode) {
478!
414
      SIF_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT);
×
415
    }
416
    SIF_ERR_JRET(sifInitParam(cell->pNode, &tParams[i], ctx));
478!
417
    cell = cell->pNext;
478✔
418
  }
419
  *params = tParams;
223✔
420
  return TSDB_CODE_SUCCESS;
223✔
421

422
_return:
×
423
  taosMemoryFree(tParams);
×
424
  SIF_RET(code);
×
425
}
426
static int32_t sifExecFunction(SFunctionNode *node, SIFCtx *ctx, SIFParam *output) {
80✔
427
  indexError("index-filter not support buildin function");
80!
428
  return TSDB_CODE_QRY_INVALID_INPUT;
80✔
429
}
430

431
typedef int (*FilterFunc)(void *a, void *b, int16_t dtype);
432

433
static FORCE_INLINE int sifGreaterThan(void *a, void *b, int16_t dtype) {
2,776✔
434
  __compar_fn_t func = getComparFunc(dtype, 0);
2,776✔
435
  if (func == NULL) {
2,774!
436
    return -1;
×
437
  }
438
  return tDoCompare(func, QUERY_GREATER_THAN, a, b);
2,774✔
439
}
440
static FORCE_INLINE int sifGreaterEqual(void *a, void *b, int16_t dtype) {
×
441
  __compar_fn_t func = getComparFunc(dtype, 0);
×
442
  if (func == NULL) {
×
443
    return -1;
×
444
  }
445
  return tDoCompare(func, QUERY_GREATER_EQUAL, a, b);
×
446
}
447
static FORCE_INLINE int sifLessEqual(void *a, void *b, int16_t dtype) {
8,359✔
448
  __compar_fn_t func = getComparFunc(dtype, 0);
8,359✔
449
  if (func == NULL) {
8,357!
450
    return -1;
×
451
  }
452
  return tDoCompare(func, QUERY_LESS_EQUAL, a, b);
8,357✔
453
}
454
static FORCE_INLINE int sifLessThan(void *a, void *b, int16_t dtype) {
×
455
  __compar_fn_t func = getComparFunc(dtype, 0);
×
456
  if (func == NULL) {
×
457
    return -1;
×
458
  }
459
  return (int)tDoCompare(func, QUERY_LESS_THAN, a, b);
×
460
}
461
static FORCE_INLINE int sifEqual(void *a, void *b, int16_t dtype) {
391✔
462
  __compar_fn_t func = getComparFunc(dtype, 0);
391✔
463
  if (func == NULL) {
392!
464
    return -1;
×
465
  }
466
  //__compar_fn_t func = idxGetCompar(dtype);
467
  return (int)tDoCompare(func, QUERY_TERM, a, b);
392✔
468
}
469
static FORCE_INLINE FilterFunc sifGetFilterFunc(EIndexQueryType type, bool *reverse, bool *equal) {
470
  if (type == QUERY_LESS_EQUAL || type == QUERY_LESS_THAN) {
714✔
471
    *reverse = true;
258✔
472
  } else {
473
    *reverse = false;
710✔
474
  }
475

476
  if (type == QUERY_LESS_EQUAL)
968✔
477
    return sifLessEqual;
256✔
478
  else if (type == QUERY_LESS_THAN)
712✔
479
    return sifLessThan;
4✔
480
  else if (type == QUERY_GREATER_EQUAL)
708✔
481
    return sifGreaterEqual;
13✔
482
  else if (type == QUERY_GREATER_THAN)
695✔
483
    return sifGreaterThan;
108✔
484
  else if (type == QUERY_TERM) {
587!
485
    *equal = true;
589✔
486
    return sifEqual;
589✔
487
  }
488
  return NULL;
×
489
}
490
int32_t sifStr2Num(char *buf, int32_t len, int8_t type, void *val) {
×
491
  // signed/unsigned/float
492
  if (IS_SIGNED_NUMERIC_TYPE(type)) {
×
493
    int64_t v = 0;
×
494
    if (0 != toInteger(buf, len, 10, &v)) {
×
495
      return TSDB_CODE_INVALID_PARA;
×
496
    }
497
    if (type == TSDB_DATA_TYPE_BIGINT) {
×
498
      *(int64_t *)val = v;
×
499
    } else if (type == TSDB_DATA_TYPE_INT) {
×
500
      *(int32_t *)val = v;
×
501
    } else if (type == TSDB_DATA_TYPE_TINYINT) {
×
502
      *(int8_t *)val = v;
×
503
    } else if (type == TSDB_DATA_TYPE_SMALLINT) {
×
504
      *(int16_t *)val = v;
×
505
    }
506
  } else if (IS_FLOAT_TYPE(type)) {
×
507
    if (type == TSDB_DATA_TYPE_FLOAT) {
×
508
      *(float *)val = taosStr2Float(buf, NULL);
×
509
    } else {
510
      *(double *)val = taosStr2Double(buf, NULL);
×
511
    }
512
  } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) {
×
513
    uint64_t v = 0;
×
514
    if (0 != toUInteger(buf, len, 10, &v)) {
×
515
      return TSDB_CODE_INVALID_PARA;
×
516
    }
517
    if (type == TSDB_DATA_TYPE_UBIGINT) {
×
518
      *(uint64_t *)val = v;
×
519
    } else if (type == TSDB_DATA_TYPE_UINT) {
×
520
      *(uint32_t *)val = v;
×
521
    } else if (type == TSDB_DATA_TYPE_UTINYINT) {
×
522
      *(uint8_t *)val = v;
×
523
    } else if (type == TSDB_DATA_TYPE_USMALLINT) {
×
524
      *(uint16_t *)val = v;
×
525
    }
526
  } else {
527
    return TSDB_CODE_INVALID_PARA;
×
528
  }
529
  return 0;
×
530
}
531

532
static int32_t sifSetFltParam(SIFParam *left, SIFParam *right, SDataTypeBuf *typedata, SMetaFltParam *param) {
964✔
533
  int32_t code = 0;
964✔
534
  int8_t  ltype = left->colValType, rtype = right->colValType;
964✔
535
  if (!IS_NUMERIC_TYPE(ltype) || !((IS_NUMERIC_TYPE(rtype)) || rtype == TSDB_DATA_TYPE_VARCHAR)) {
964!
536
    return TSDB_CODE_INVALID_PARA;
520✔
537
  }
538
  if (ltype == TSDB_DATA_TYPE_FLOAT) {
444!
539
    float f = 0;
×
540
    if (IS_NUMERIC_TYPE(rtype)) {
×
541
      SIF_DATA_CONVERT(rtype, right->condValue, f);
×
542
    } else {
543
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_FLOAT, &f));
×
544
    }
545
    typedata->f = f;
×
546
    param->val = &typedata->f;
×
547
  } else if (ltype == TSDB_DATA_TYPE_DOUBLE) {
444!
548
    double d = 0;
×
549
    if (IS_NUMERIC_TYPE(rtype)) {
×
550
      SIF_DATA_CONVERT(rtype, right->condValue, d);
×
551
    } else {
552
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_DOUBLE, &d));
×
553
    }
554
    typedata->d = d;
×
555
    param->val = &typedata->d;
×
556
  } else if (ltype == TSDB_DATA_TYPE_BIGINT) {
444!
557
    int64_t i64 = 0;
×
558
    if (IS_NUMERIC_TYPE(rtype)) {
×
559
      SIF_DATA_CONVERT(rtype, right->condValue, i64);
×
560
    } else {
561
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_BIGINT, &i64));
×
562
    }
563
    typedata->i64 = i64;
×
564
    param->val = &typedata->i64;
×
565
  } else if (ltype == TSDB_DATA_TYPE_INT) {
444!
566
    int32_t i32 = 0;
×
567
    if (IS_NUMERIC_TYPE(rtype)) {
×
568
      SIF_DATA_CONVERT(rtype, right->condValue, i32);
×
569
    } else {
570
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_INT, &i32));
×
571
    }
572
    typedata->i32 = i32;
×
573
    param->val = &typedata->i32;
×
574
  } else if (ltype == TSDB_DATA_TYPE_SMALLINT) {
444!
575
    int16_t i16 = 0;
×
576
    if (IS_NUMERIC_TYPE(rtype)) {
×
577
      SIF_DATA_CONVERT(rtype, right->condValue, i16);
×
578
    } else {
579
      SIF_ERR_RET(
×
580
          sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_SMALLINT, &i16));
581
    }
582

583
    typedata->i16 = i16;
×
584
    param->val = &typedata->i16;
×
585
  } else if (ltype == TSDB_DATA_TYPE_TINYINT) {
444!
586
    int8_t i8 = 0;
448✔
587
    if (IS_NUMERIC_TYPE(rtype)) {
448!
588
      SIF_DATA_CONVERT(rtype, right->condValue, i8);
448!
589
    } else {
590
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_TINYINT, &i8));
×
591
    }
592
    typedata->i8 = i8;
450✔
593
    param->val = &typedata->i8;
450✔
594
  } else if (ltype == TSDB_DATA_TYPE_UBIGINT) {
×
595
    uint64_t u64 = 0;
×
596
    if (IS_NUMERIC_TYPE(rtype)) {
×
597
      SIF_DATA_CONVERT(rtype, right->condValue, u64);
×
598
    } else {
599
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UBIGINT, &u64));
×
600
    }
601
    typedata->u64 = u64;
×
602
    param->val = &typedata->u64;
×
603
  } else if (ltype == TSDB_DATA_TYPE_UINT) {
×
604
    uint32_t u32 = 0;
×
605
    if (IS_NUMERIC_TYPE(rtype)) {
×
606
      SIF_DATA_CONVERT(rtype, right->condValue, u32);
×
607
    } else {
608
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UINT, &u32));
×
609
    }
610
    typedata->u32 = u32;
×
611
    param->val = &typedata->u32;
×
612
  } else if (ltype == TSDB_DATA_TYPE_USMALLINT) {
×
613
    uint16_t u16 = 0;
×
614
    if (IS_NUMERIC_TYPE(rtype)) {
×
615
      SIF_DATA_CONVERT(rtype, right->condValue, u16);
×
616
    } else {
617
      SIF_ERR_RET(
×
618
          sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_USMALLINT, &u16));
619
    }
620
    typedata->u16 = u16;
×
621
    param->val = &typedata->u16;
×
622
  } else if (ltype == TSDB_DATA_TYPE_UTINYINT) {
×
623
    uint8_t u8 = 0;
×
624
    if (IS_NUMERIC_TYPE(rtype)) {
×
625
      SIF_DATA_CONVERT(rtype, right->condValue, u8);
×
626
    } else {
627
      SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UTINYINT, &u8));
×
628
    }
629
    typedata->u8 = u8;
×
630
    param->val = &typedata->u8;
×
631
  }
632
  return 0;
446✔
633
}
634

635
static int8_t sifShouldUseIndexBasedOnType(SIFParam *left, SIFParam *right) {
5,339✔
636
  // not compress
637
  if (left->colValType == TSDB_DATA_TYPE_FLOAT) return 0;
5,339✔
638

639
  if (left->colValType == TSDB_DATA_TYPE_GEOMETRY || right->colValType == TSDB_DATA_TYPE_GEOMETRY ||
5,313!
640
      left->colValType == TSDB_DATA_TYPE_JSON || right->colValType == TSDB_DATA_TYPE_JSON) {
5,322!
641
    return 0;
×
642
  }
643

644
  if (IS_VAR_DATA_TYPE(left->colValType)) {
5,321!
645
    if (!IS_VAR_DATA_TYPE(right->colValType)) return 0;
810!
646
  } else if (IS_NUMERIC_TYPE(left->colValType)) {
4,511!
647
    if (left->colValType != right->colValType) return 0;
4,296✔
648
  }
649
  return 1;
970✔
650
}
651
static int32_t sifDoIndex(SIFParam *left, SIFParam *right, int8_t operType, SIFParam *output) {
6,014✔
652
  int             ret = 0;
6,014✔
653
  SIndexMetaArg  *arg = &output->arg;
6,014✔
654
  EIndexQueryType qtype = 0;
6,014✔
655
  SIF_ERR_RET(sifGetFuncFromSql(operType, &qtype));
12,028✔
656
  if (left->colValType == TSDB_DATA_TYPE_JSON) {
5,343!
657
    SIndexTerm *tm = indexTermCreate(arg->suid, DEFAULT, right->colValType, left->colName, strlen(left->colName),
×
658
                                     right->condValue, strlen(right->condValue));
×
659
    if (tm == NULL) {
×
660
      return TSDB_CODE_OUT_OF_MEMORY;
×
661
    }
662

663
    SIndexMultiTermQuery *mtm = indexMultiTermQueryCreate(MUST);
×
664
    if (mtm == NULL) {
×
665
      indexTermDestroy(tm);
×
666
      return TSDB_CODE_OUT_OF_MEMORY;
×
667
    }
668

669
    if ((ret = indexMultiTermQueryAdd(mtm, tm, qtype)) != 0) {
×
670
      indexMultiTermQueryDestroy(mtm);
×
671
      return ret;
×
672
    }
673

674
    ret = indexJsonSearch(arg->ivtIdx, mtm, output->result);
×
675
    indexMultiTermQueryDestroy(mtm);
×
676
  } else {
677
    int8_t useIndex = sifShouldUseIndexBasedOnType(left, right);
5,343✔
678
    if (!useIndex) {
5,345✔
679
      output->status = SFLT_NOT_INDEX;
4,377✔
680
      return TSDB_CODE_INVALID_PARA;
4,895✔
681
    }
682

683
    bool       reverse = false, equal = false;
968✔
684
    FilterFunc filterFunc = sifGetFilterFunc(qtype, &reverse, &equal);
968✔
685

686
    SMetaFltParam param = {.suid = arg->suid,
968✔
687
                           .cid = left->colId,
968✔
688
                           .type = left->colValType,
968✔
689
                           .val = right->condValue,
968✔
690
                           .reverse = reverse,
691
                           .equal = equal,
692
                           .filterFunc = filterFunc};
693

694
    char buf[128] = {0};
968✔
695

696
    SDataTypeBuf typedata;
697
    memset(&typedata, 0, sizeof(typedata));
968✔
698

699
    if (sifSetFltParam(left, right, &typedata, &param) != 0) {
968✔
700
      output->status = SFLT_NOT_INDEX;
518✔
701
      return TSDB_CODE_INVALID_PARA;
518✔
702
    }
703

704
    ret = left->api.metaFilterTableIds(arg->metaEx, &param, output->result);
448✔
705
    if (ret == 0) {
450✔
706
      taosArraySort(output->result, uidCompare);
100✔
707
      taosArrayRemoveDuplicate(output->result, uidCompare, NULL);
100✔
708
    }
709
  }
710
  return ret;
450✔
711
}
712

713
static FORCE_INLINE int32_t sifLessThanFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
410✔
714
  int id = OP_TYPE_LOWER_THAN;
410✔
715
  return sifDoIndex(left, right, id, output);
410✔
716
}
717
static FORCE_INLINE int32_t sifLessEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
1,190✔
718
  int id = OP_TYPE_LOWER_EQUAL;
1,190✔
719
  return sifDoIndex(left, right, id, output);
1,190✔
720
}
721

722
static FORCE_INLINE int32_t sifGreaterThanFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
675✔
723
  int id = OP_TYPE_GREATER_THAN;
675✔
724
  return sifDoIndex(left, right, id, output);
675✔
725
}
726
static FORCE_INLINE int32_t sifGreaterEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
347✔
727
  int id = OP_TYPE_GREATER_EQUAL;
347✔
728
  return sifDoIndex(left, right, id, output);
347✔
729
}
730

731
static FORCE_INLINE int32_t sifEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
2,722✔
732
  int id = OP_TYPE_EQUAL;
2,722✔
733
  return sifDoIndex(left, right, id, output);
2,722✔
734
}
735
static FORCE_INLINE int32_t sifNotEqualFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
670✔
736
  int id = OP_TYPE_NOT_EQUAL;
670✔
737
  return sifDoIndex(left, right, id, output);
670✔
738
}
739
static FORCE_INLINE int32_t sifInFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
740
  int id = OP_TYPE_IN;
×
741
  return sifDoIndex(left, right, id, output);
×
742
}
743
static FORCE_INLINE int32_t sifNotInFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
744
  int id = OP_TYPE_NOT_IN;
×
745
  return sifDoIndex(left, right, id, output);
×
746
}
747
static FORCE_INLINE int32_t sifLikeFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
748
  int id = OP_TYPE_LIKE;
×
749
  return sifDoIndex(left, right, id, output);
×
750
}
751
static FORCE_INLINE int32_t sifNotLikeFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
752
  int id = OP_TYPE_NOT_LIKE;
×
753
  return sifDoIndex(left, right, id, output);
×
754
}
755

756
static FORCE_INLINE int32_t sifMatchFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
757
  int id = OP_TYPE_MATCH;
×
758
  return sifDoIndex(left, right, id, output);
×
759
}
760
static FORCE_INLINE int32_t sifNotMatchFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
×
761
  int id = OP_TYPE_NMATCH;
×
762
  return sifDoIndex(left, right, id, output);
×
763
}
764
static FORCE_INLINE int32_t sifJsonContains(SIFParam *left, SIFParam *right, SIFParam *output) {
×
765
  int id = OP_TYPE_JSON_CONTAINS;
×
766
  return sifDoIndex(left, right, id, output);
×
767
}
768
static FORCE_INLINE int32_t sifJsonGetValue(SIFParam *left, SIFParam *rigth, SIFParam *output) {
×
769
  // return 0
770
  return 0;
×
771
}
772

773
static FORCE_INLINE int32_t sifDefaultFunc(SIFParam *left, SIFParam *right, SIFParam *output) {
774
  // add more except
775
  return TSDB_CODE_QRY_INVALID_INPUT;
776
}
777

778
static FORCE_INLINE int32_t sifGetOperFn(int32_t funcId, sif_func_t *func, SIdxFltStatus *status) {
779
  // impl later
780
  *status = SFLT_ACCURATE_INDEX;
12,301✔
781
  switch (funcId) {
12,301✔
782
    case OP_TYPE_GREATER_THAN:
1,375✔
783
      *func = sifGreaterThanFunc;
1,375✔
784
      return 0;
1,375✔
785
    case OP_TYPE_GREATER_EQUAL:
696✔
786
      *func = sifGreaterEqualFunc;
696✔
787
      return 0;
696✔
788
    case OP_TYPE_LOWER_THAN:
986✔
789
      *func = sifLessThanFunc;
986✔
790
      return 0;
986✔
791
    case OP_TYPE_LOWER_EQUAL:
2,399✔
792
      *func = sifLessEqualFunc;
2,399✔
793
      return 0;
2,399✔
794
    case OP_TYPE_EQUAL:
5,482✔
795
      *func = sifEqualFunc;
5,482✔
796
      return 0;
5,482✔
797
    case OP_TYPE_NOT_EQUAL:
1,357✔
798
      *status = SFLT_NOT_INDEX;
1,357✔
799
      *func = sifNotEqualFunc;
1,357✔
800
      return 0;
1,357✔
801
    case OP_TYPE_IN:
×
802
      *status = SFLT_NOT_INDEX;
×
803
      *func = sifInFunc;
×
804
      return 0;
×
805
    case OP_TYPE_NOT_IN:
×
806
      *status = SFLT_NOT_INDEX;
×
807
      *func = sifNotInFunc;
×
808
      return 0;
×
809
    case OP_TYPE_LIKE:
×
810
      *status = SFLT_NOT_INDEX;
×
811
      *func = sifLikeFunc;
×
812
      return 0;
×
813
    case OP_TYPE_NOT_LIKE:
×
814
      *status = SFLT_NOT_INDEX;
×
815
      *func = sifNotLikeFunc;
×
816
      return 0;
×
817
    case OP_TYPE_MATCH:
×
818
      *status = SFLT_NOT_INDEX;
×
819
      *func = sifMatchFunc;
×
820
      return 0;
×
821
    case OP_TYPE_NMATCH:
×
822
      *status = SFLT_NOT_INDEX;
×
823
      *func = sifNotMatchFunc;
×
824
      return 0;
×
825
    case OP_TYPE_JSON_CONTAINS:
×
826
      *status = SFLT_ACCURATE_INDEX;
×
827
      *func = sifJsonContains;
×
828
      return 0;
×
829
    case OP_TYPE_JSON_GET_VALUE:
×
830
      *status = SFLT_ACCURATE_INDEX;
×
831
      *func = sifJsonGetValue;
×
832
      return 0;
×
833
    default:
6✔
834
      *status = SFLT_NOT_INDEX;
6✔
835
      *func = sifNullFunc;
6✔
836
      return 0;
6✔
837
  }
838
  return 0;
839
}
840

841
static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) {
14,472✔
842
  int32_t code = TSDB_CODE_INVALID_PARA;
14,472✔
843
  if (sifValidOp(node->opType) < 0) {
28,944!
844
    code = TSDB_CODE_QRY_INVALID_INPUT;
1,540✔
845
    ctx->code = code;
1,540✔
846
    output->status = SFLT_NOT_INDEX;
1,540✔
847
    return code;
1,540✔
848
  }
849

850
  int32_t nParam = sifGetOperParamNum(node->opType);
12,932✔
851
  if (nParam <= 1) {
12,932✔
852
    output->status = SFLT_NOT_INDEX;
128✔
853
    return code;
128✔
854
  }
855
  if (node->opType == OP_TYPE_JSON_GET_VALUE) {
12,804✔
856
    return code;
452✔
857
  }
858

859
  SIFParam *params = NULL;
12,352✔
860
  SIF_ERR_RET(sifInitOperParams(&params, node, ctx));
12,352✔
861

862
  if (params[0].status == SFLT_NOT_INDEX || (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) {
12,331!
863
    output->status = SFLT_NOT_INDEX;
30✔
864
    goto _return;
30✔
865
  }
866

867
  // ugly code, refactor later
868
  output->arg = ctx->arg;
12,301✔
869
  sif_func_t operFn = sifNullFunc;
12,301✔
870

871
  if (!ctx->noExec) {
12,301✔
872
    code = 0;
6,026✔
873
    SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status));
12,052!
874
    SIF_ERR_JRET(operFn(&params[0], nParam > 1 ? &params[1] : NULL, output));
6,026✔
875
  } else {
876
    // ugly code, refactor later
877
    if (nParam > 1 && params[1].status == SFLT_NOT_INDEX) {
6,275!
878
      output->status = SFLT_NOT_INDEX;
×
879
      goto _return;
×
880
    }
881
    code = 0;
6,275✔
882
    SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status));
12,550!
883
  }
884
_return:
6,275✔
885
  for (int i = 0; i < nParam; i++) sifFreeParam(&params[i]);
36,923!
886
  taosMemoryFree(params);
12,313✔
887
  if (code != 0) {
12,327✔
888
    output->status = SFLT_NOT_INDEX;
5,950✔
889
  } else {
890
    output->status = SFLT_COARSE_INDEX;
6,377✔
891
  }
892
  return code;
12,327✔
893
}
894

895
static int32_t sifExecLogic(SLogicConditionNode *node, SIFCtx *ctx, SIFParam *output) {
223✔
896
  if (NULL == node->pParameterList || node->pParameterList->length <= 0) {
223!
897
    indexError("invalid logic parameter list, list:%p, paramNum:%d", node->pParameterList,
×
898
               node->pParameterList ? node->pParameterList->length : 0);
899
    return TSDB_CODE_QRY_INVALID_INPUT;
×
900
  }
901

902
  int32_t   code = TSDB_CODE_SUCCESS;
223✔
903
  SIFParam *params = NULL;
223✔
904
  SIF_ERR_RET(sifInitParamList(&params, node->pParameterList, ctx));
223!
905

906
  if (ctx->noExec == false) {
223!
907
    for (int32_t m = 0; m < node->pParameterList->length; m++) {
×
908
      if (node->condType == LOGIC_COND_TYPE_AND) {
×
909
        if (taosArrayAddAll(output->result, params[m].result) == NULL) return terrno;
×
910
      } else if (node->condType == LOGIC_COND_TYPE_OR) {
×
911
        if (taosArrayAddAll(output->result, params[m].result) == NULL) return terrno;
×
912
      } else if (node->condType == LOGIC_COND_TYPE_NOT) {
×
913
      }
914
      taosArraySort(output->result, uidCompare);
×
915
      taosArrayRemoveDuplicate(output->result, uidCompare, NULL);
×
916
    }
917
  } else {
918
    for (int32_t m = 0; m < node->pParameterList->length; m++) {
701✔
919
      output->status = sifMergeCond(node->condType, output->status, params[m].status);
956✔
920
    }
921
  }
922
_return:
223✔
923
  taosMemoryFree(params);
223✔
924
  SIF_RET(code);
223!
925
}
926

927
static EDealRes sifWalkFunction(SNode *pNode, void *context) {
80✔
928
  SIFCtx        *ctx = context;
80✔
929
  SFunctionNode *node = (SFunctionNode *)pNode;
80✔
930
  SIFParam       output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
80✔
931
  if (output.result == NULL) {
80!
932
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
933
    return DEAL_RES_ERROR;
×
934
  }
935
  ctx->code = sifExecFunction(node, ctx, &output);
80✔
936
  if (ctx->code != TSDB_CODE_SUCCESS) {
80!
937
    sifFreeParam(&output);
938
    return DEAL_RES_ERROR;
80✔
939
  }
940

941
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
×
942
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
943
    return DEAL_RES_ERROR;
×
944
  }
945
  return DEAL_RES_CONTINUE;
×
946
}
947
static EDealRes sifWalkLogic(SNode *pNode, void *context) {
223✔
948
  SIFCtx              *ctx = context;
223✔
949
  SLogicConditionNode *node = (SLogicConditionNode *)pNode;
223✔
950

951
  SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
223✔
952
  if (output.result == NULL) {
223!
953
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
954
    return DEAL_RES_ERROR;
×
955
  }
956

957
  ctx->code = sifExecLogic(node, ctx, &output);
223✔
958
  if (ctx->code) {
223!
959
    sifFreeParam(&output);
960
    return DEAL_RES_ERROR;
×
961
  }
962

963
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
223!
964
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
965
    return DEAL_RES_ERROR;
×
966
  }
967
  return DEAL_RES_CONTINUE;
223✔
968
}
969
static EDealRes sifWalkOper(SNode *pNode, void *context) {
14,458✔
970
  SIFCtx        *ctx = context;
14,458✔
971
  SOperatorNode *node = (SOperatorNode *)pNode;
14,458✔
972
  SIFParam       output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX};
14,458✔
973
  if (output.result == NULL) {
14,484!
974
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
975
    return DEAL_RES_ERROR;
×
976
  }
977

978
  ctx->code = sifExecOper(node, ctx, &output);
14,484✔
979
  if (ctx->code) {
14,462✔
980
    sifFreeParam(&output);
981
    return DEAL_RES_ERROR;
8,089✔
982
  }
983
  if (taosHashPut(ctx->pRes, &pNode, POINTER_BYTES, &output, sizeof(output))) {
6,375!
984
    ctx->code = TSDB_CODE_OUT_OF_MEMORY;
×
985
    return DEAL_RES_ERROR;
×
986
  }
987

988
  return DEAL_RES_CONTINUE;
6,387✔
989
}
990

991
EDealRes sifCalcWalker(SNode *node, void *context) {
43,787✔
992
  if (QUERY_NODE_VALUE == nodeType(node) || QUERY_NODE_NODE_LIST == nodeType(node) ||
43,787✔
993
      QUERY_NODE_COLUMN == nodeType(node)) {
29,307✔
994
    return DEAL_RES_CONTINUE;
29,019✔
995
  }
996
  SIFCtx *ctx = (SIFCtx *)context;
14,768✔
997
  if (QUERY_NODE_FUNCTION == nodeType(node)) {
14,768✔
998
    return sifWalkFunction(node, ctx);
80✔
999
  }
1000
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(node)) {
14,688✔
1001
    return sifWalkLogic(node, ctx);
223✔
1002
  }
1003

1004
  if (QUERY_NODE_OPERATOR == nodeType(node)) {
14,465!
1005
    // indexInfo("node type for index filter, type: %d", nodeType(node));
1006
    return sifWalkOper(node, ctx);
14,465✔
1007
  }
1008

1009
  // indexError("invalid node type for index filter calculating, type:%d", nodeType(node));
1010
  ctx->code = TSDB_CODE_QRY_INVALID_INPUT;
×
1011
  return DEAL_RES_ERROR;
×
1012
}
1013

1014
void sifFreeRes(SHashObj *res) {
8,267✔
1015
  void *pIter = taosHashIterate(res, NULL);
8,267✔
1016
  while (pIter) {
8,269✔
1017
    SIFParam *p = pIter;
8✔
1018
    if (p) {
8!
1019
      sifFreeParam(p);
1020
    }
1021
    pIter = taosHashIterate(res, pIter);
8✔
1022
  }
1023
  taosHashCleanup(res);
8,261✔
1024
}
8,272✔
1025
static int32_t sifCalculate(SNode *pNode, SIFParam *pDst) {
6,015✔
1026
  if (pNode == NULL || pDst == NULL) {
6,015!
1027
    return TSDB_CODE_QRY_INVALID_INPUT;
×
1028
  }
1029

1030
  int32_t code = 0;
6,018✔
1031
  SIFCtx  ctx = {.code = 0, .noExec = false, .arg = pDst->arg, .pAPI = &pDst->api};
6,018✔
1032
  ctx.pRes = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
6,018✔
1033

1034
  if (NULL == ctx.pRes) {
6,022!
1035
    indexError("index-filter failed to taosHashInit");
×
1036
    return terrno;
×
1037
  }
1038

1039
  nodesWalkExprPostOrder(pNode, sifCalcWalker, &ctx);
6,022✔
1040

1041
  if (ctx.code != 0) {
6,020✔
1042
    sifFreeRes(ctx.pRes);
5,920✔
1043
    return ctx.code;
5,922✔
1044
  }
1045

1046
  if (pDst) {
100!
1047
    SIFParam *res = (SIFParam *)taosHashGet(ctx.pRes, (void *)&pNode, POINTER_BYTES);
100✔
1048
    if (res == NULL) {
100!
1049
      indexError("no valid res in hash, node:(%p), type(%d)", (void *)&pNode, nodeType(pNode));
×
1050
      SIF_ERR_RET(TSDB_CODE_APP_ERROR);
×
1051
    }
1052
    if (res->result != NULL) {
100!
1053
      if (taosArrayAddAll(pDst->result, res->result) == NULL) {
100!
1054
        SIF_ERR_RET(TSDB_CODE_OUT_OF_MEMORY);
×
1055
      }
1056
    }
1057
    pDst->status = res->status;
100!
1058

1059
    sifFreeParam(res);
1060
    TAOS_UNUSED(taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES));
100✔
1061
  }
1062
  sifFreeRes(ctx.pRes);
100✔
1063
  return code;
100✔
1064
}
1065

1066
static int32_t sifGetFltHint(SNode *pNode, SIdxFltStatus *status, SMetaDataFilterAPI *pAPI) {
8,271✔
1067
  int32_t code = TSDB_CODE_SUCCESS;
8,271✔
1068
  if (pNode == NULL) {
8,271!
1069
    return TSDB_CODE_QRY_INVALID_INPUT;
×
1070
  }
1071

1072
  SIFCtx ctx = {.code = 0, .noExec = true, .pAPI = pAPI};
8,271✔
1073
  ctx.pRes = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
8,271✔
1074
  if (NULL == ctx.pRes) {
8,279!
1075
    indexError("index-filter failed to taosHashInit");
×
1076
    return terrno;
×
1077
  }
1078

1079
  nodesWalkExprPostOrder(pNode, sifCalcWalker, &ctx);
8,279✔
1080
  if (ctx.code != 0) {
8,270✔
1081
    sifFreeRes(ctx.pRes);
2,249✔
1082
    return ctx.code;
2,250✔
1083
  }
1084

1085
  SIFParam *res = (SIFParam *)taosHashGet(ctx.pRes, (void *)&pNode, POINTER_BYTES);
6,021✔
1086
  if (res == NULL) {
6,025!
1087
    indexError("no valid res in hash, node:(%p), type(%d)", (void *)&pNode, nodeType(pNode));
×
1088
    SIF_ERR_RET(TSDB_CODE_APP_ERROR);
×
1089
  }
1090
  *status = res->status;
6,017!
1091
  sifFreeParam(res);
1092
  TAOS_UNUSED(taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES));
6,025✔
1093

1094
  void *iter = taosHashIterate(ctx.pRes, NULL);
6,027✔
1095
  while (iter != NULL) {
6,496✔
1096
    SIFParam *data = (SIFParam *)iter;
478!
1097
    sifFreeParam(data);
1098
    iter = taosHashIterate(ctx.pRes, iter);
478✔
1099
  }
1100
  taosHashCleanup(ctx.pRes);
6,018✔
1101
  return code;
6,023✔
1102
}
1103

1104
int32_t doFilterTag(SNode *pFilterNode, SIndexMetaArg *metaArg, SArray *result, SIdxFltStatus *status,
8,255✔
1105
                    SMetaDataFilterAPI *pAPI) {
1106
  SIdxFltStatus st = idxGetFltStatus(pFilterNode, pAPI);
8,255✔
1107
  if (st == SFLT_NOT_INDEX) {
8,274✔
1108
    *status = st;
2,252✔
1109
    return 0;
2,252✔
1110
  }
1111

1112
  SFilterInfo *filter = NULL;
6,022✔
1113

1114
  SArray *output = taosArrayInit(8, sizeof(uint64_t));
6,022✔
1115
  if (output == NULL) {
6,025!
1116
    return terrno;
×
1117
  }
1118

1119
  SIFParam param = {.arg = *metaArg, .result = output, .status = SFLT_NOT_INDEX, .api = *pAPI};
6,025✔
1120
  int32_t  code = sifCalculate((SNode *)pFilterNode, &param);
6,025✔
1121
  if (code != 0) {
6,022✔
1122
    sifFreeParam(&param);
1123
    return code;
5,925✔
1124
  }
1125
  if (param.status == SFLT_NOT_INDEX) {
107!
1126
    *status = param.status;
×
1127
  } else {
1128
    *status = st;
107✔
1129
  }
1130

1131
  if (taosArrayAddAll(result, param.result) == NULL) {
107!
1132
    sifFreeParam(&param);
1133
    return TSDB_CODE_OUT_OF_MEMORY;
×
1134
  }
1135

1136
  sifFreeParam(&param);
1137
  return TSDB_CODE_SUCCESS;
100✔
1138
}
1139

1140
SIdxFltStatus idxGetFltStatus(SNode *pFilterNode, SMetaDataFilterAPI *pAPI) {
8,270✔
1141
  SIdxFltStatus st = SFLT_NOT_INDEX;
8,270✔
1142
  if (pFilterNode == NULL) {
8,270!
1143
    return SFLT_NOT_INDEX;
×
1144
  }
1145

1146
  if (sifGetFltHint((SNode *)pFilterNode, &st, pAPI) != TSDB_CODE_SUCCESS) {
8,270✔
1147
    st = SFLT_NOT_INDEX;
2,252✔
1148
  }
1149
  return st;
8,275✔
1150
}
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