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

taosdata / TDengine / #5016

03 Apr 2026 03:59PM UTC coverage: 72.299% (+0.01%) from 72.289%
#5016

push

travis-ci

web-flow
merge: from main to 3.0 branch #35067

4055 of 5985 new or added lines in 68 files covered. (67.75%)

13126 existing lines in 156 files now uncovered.

257424 of 356056 relevant lines covered (72.3%)

133108577.02 hits per line

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

73.91
/source/libs/executor/src/executil.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 "function.h"
17
#include "functionMgt.h"
18
#include "index.h"
19
#include "os.h"
20
#include "query.h"
21
#include "querynodes.h"
22
#include "taoserror.h"
23
#include "tarray.h"
24
#include "tcompare.h"
25
#include "tdatablock.h"
26
#include "thash.h"
27
#include "tmsg.h"
28
#include "ttime.h"
29

30
#include "executil.h"
31
#include "executorInt.h"
32
#include "querytask.h"
33
#include "storageapi.h"
34
#include "ttypes.h"
35
#include "tutil.h"
36
#include "tjson.h"
37
#include "trpc.h"
38
#include "filter.h"
39
#include "operator.h"
40
#include "tref.h"
41
#include "streamMsg.h"
42

43
typedef struct tagFilterAssist {
44
  SHashObj* colHash;
45
  int32_t   index;
46
  SArray*   cInfoList;
47
  int32_t   code;
48
} tagFilterAssist;
49

50
typedef struct STransTagExprCtx {
51
  int32_t      code;
52
  SMetaReader* pReader;
53
} STransTagExprCtx;
54

55
typedef enum {
56
  FILTER_NO_LOGIC = 1,
57
  FILTER_AND,
58
  FILTER_OTHER,
59
} FilterCondType;
60

61
static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* list, SNode* pTagCond, SStorageAPI* pStoreAPI,
62
                                        uint64_t suid);
63

64
static int64_t getLimit(const SNode* pLimit) {
1,359,114,517✔
65
  return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->limit) ? -1 : ((SLimitNode*)pLimit)->limit->datum.i;
1,359,114,517✔
66
}
67
static int64_t getOffset(const SNode* pLimit) {
1,358,684,800✔
68
  return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->offset) ? -1 : ((SLimitNode*)pLimit)->offset->datum.i;
1,358,684,800✔
69
}
70
static void releaseColInfoData(void* pCol);
71
int32_t sendFetchRemoteNodeReq(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes, bool reset);
72

73
void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
508,308,776✔
74
  pResultRowInfo->size = 0;
508,308,776✔
75
  pResultRowInfo->cur.pageId = -1;
508,432,619✔
76
}
508,563,780✔
77

78
void closeResultRow(SResultRow* pResultRow) { pResultRow->closed = true; }
5,613,790✔
79

80
void resetResultRow(SResultRow* pResultRow, size_t entrySize) {
959,256,946✔
81
  pResultRow->numOfRows = 0;
959,256,946✔
82
  pResultRow->nOrigRows = 0;
959,259,240✔
83
  pResultRow->closed = false;
959,254,474✔
84
  pResultRow->endInterp = false;
959,257,526✔
85
  pResultRow->startInterp = false;
959,261,468✔
86

87
  if (entrySize > 0) {
959,265,354✔
88
    memset(pResultRow->pEntryInfo, 0, entrySize);
959,271,712✔
89
  }
90
}
959,297,780✔
91

92
// TODO refactor: use macro
93
SResultRowEntryInfo* getResultEntryInfo(const SResultRow* pRow, int32_t index, const int32_t* offset) {
2,147,483,647✔
94
  return (SResultRowEntryInfo*)((char*)pRow->pEntryInfo + offset[index]);
2,147,483,647✔
95
}
96

97
size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
303,828,502✔
98
  int32_t rowSize = (numOfOutput * sizeof(SResultRowEntryInfo)) + sizeof(SResultRow);
303,828,502✔
99

100
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,258,247,603✔
101
    rowSize += pCtx[i].resDataInfo.interBufSize;
954,731,062✔
102
  }
103

104
  return rowSize;
303,516,541✔
105
}
106

107
// Convert buf read from rocksdb to result row
UNCOV
108
int32_t getResultRowFromBuf(SExprSupp* pSup, const char* inBuf, size_t inBufSize, char** outBuf, size_t* outBufSize) {
×
109
  if (inBuf == NULL || pSup == NULL) {
×
110
    qError("invalid input parameters, inBuf:%p, pSup:%p", inBuf, pSup);
×
111
    return TSDB_CODE_INVALID_PARA;
×
112
  }
UNCOV
113
  SqlFunctionCtx* pCtx = pSup->pCtx;
×
114
  int32_t*        offset = pSup->rowEntryInfoOffset;
×
115
  SResultRow*     pResultRow = NULL;
×
116
  size_t          processedSize = 0;
×
117
  int32_t         code = TSDB_CODE_SUCCESS;
×
118

119
  // calculate the size of output buffer
UNCOV
120
  *outBufSize = getResultRowSize(pCtx, pSup->numOfExprs);
×
121
  *outBuf = taosMemoryMalloc(*outBufSize);
×
122
  if (*outBuf == NULL) {
×
123
    qError("failed to allocate memory for output buffer, size:%zu", *outBufSize);
×
124
    return terrno;
×
125
  }
UNCOV
126
  pResultRow = (SResultRow*)*outBuf;
×
127
  (void)memcpy(pResultRow, inBuf, sizeof(SResultRow));
×
128
  inBuf += sizeof(SResultRow);
×
129
  processedSize += sizeof(SResultRow);
×
130

UNCOV
131
  for (int32_t i = 0; i < pSup->numOfExprs; ++i) {
×
132
    int32_t len = *(int32_t*)inBuf;
×
133
    inBuf += sizeof(int32_t);
×
134
    processedSize += sizeof(int32_t);
×
135
    if (pResultRow->version != FUNCTION_RESULT_INFO_VERSION && pCtx->fpSet.decode) {
×
136
      code = pCtx->fpSet.decode(&pCtx[i], inBuf, getResultEntryInfo(pResultRow, i, offset), pResultRow->version);
×
137
      if (code != TSDB_CODE_SUCCESS) {
×
138
        qError("failed to decode result row, code:%d", code);
×
139
        return code;
×
140
      }
141
    } else {
UNCOV
142
      (void)memcpy(getResultEntryInfo(pResultRow, i, offset), inBuf, len);
×
143
    }
UNCOV
144
    inBuf += len;
×
145
    processedSize += len;
×
146
  }
147

UNCOV
148
  if (processedSize < inBufSize) {
×
149
    // stream stores extra data after result row
UNCOV
150
    size_t leftLen = inBufSize - processedSize;
×
151
    TAOS_MEMORY_REALLOC(*outBuf, *outBufSize + leftLen);
×
152
    if (*outBuf == NULL) {
×
153
      qError("failed to reallocate memory for output buffer, size:%zu", *outBufSize + leftLen);
×
154
      return terrno;
×
155
    }
UNCOV
156
    (void)memcpy(*outBuf + *outBufSize, inBuf, leftLen);
×
157
    inBuf += leftLen;
×
158
    processedSize += leftLen;
×
159
    *outBufSize += leftLen;
×
160
  }
161

UNCOV
162
  qTrace("[StreamInternal] get result inBufSize:%zu, outBufSize:%zu", inBufSize, *outBufSize);
×
163
  return TSDB_CODE_SUCCESS;
×
164
}
165

166
// Convert result row to buf for rocksdb
UNCOV
167
int32_t putResultRowToBuf(SExprSupp* pSup, const char* inBuf, size_t inBufSize, char** outBuf, size_t* outBufSize) {
×
168
  if (pSup == NULL || inBuf == NULL || outBuf == NULL || outBufSize == NULL) {
×
169
    qError("invalid input parameters, inBuf:%p, pSup:%p, outBufSize:%p, outBuf:%p", inBuf, pSup, outBufSize, outBuf);
×
170
    return TSDB_CODE_INVALID_PARA;
×
171
  }
172

UNCOV
173
  SqlFunctionCtx* pCtx = pSup->pCtx;
×
174
  int32_t*        offset = pSup->rowEntryInfoOffset;
×
175
  SResultRow*     pResultRow = (SResultRow*)inBuf;
×
176
  size_t          rowSize = getResultRowSize(pCtx, pSup->numOfExprs);
×
177

UNCOV
178
  if (rowSize > inBufSize) {
×
179
    qError("invalid input buffer size, rowSize:%zu, inBufSize:%zu", rowSize, inBufSize);
×
180
    return TSDB_CODE_INVALID_PARA;
×
181
  }
182

183
  // calculate the size of output buffer
UNCOV
184
  *outBufSize = rowSize + sizeof(int32_t) * pSup->numOfExprs;
×
185
  if (rowSize < inBufSize) {
×
186
    *outBufSize += inBufSize - rowSize;
×
187
  }
188

UNCOV
189
  *outBuf = taosMemoryMalloc(*outBufSize);
×
190
  if (*outBuf == NULL) {
×
191
    qError("failed to allocate memory for output buffer, size:%zu", *outBufSize);
×
192
    return terrno;
×
193
  }
194

UNCOV
195
  char* pBuf = *outBuf;
×
196
  pResultRow->version = FUNCTION_RESULT_INFO_VERSION;
×
197
  (void)memcpy(pBuf, pResultRow, sizeof(SResultRow));
×
198
  pBuf += sizeof(SResultRow);
×
199
  for (int32_t i = 0; i < pSup->numOfExprs; ++i) {
×
200
    size_t len = sizeof(SResultRowEntryInfo) + pCtx[i].resDataInfo.interBufSize;
×
201
    *(int32_t*)pBuf = (int32_t)len;
×
202
    pBuf += sizeof(int32_t);
×
203
    (void)memcpy(pBuf, getResultEntryInfo(pResultRow, i, offset), len);
×
204
    pBuf += len;
×
205
  }
206

UNCOV
207
  if (rowSize < inBufSize) {
×
208
    // stream stores extra data after result row
UNCOV
209
    size_t leftLen = inBufSize - rowSize;
×
210
    (void)memcpy(pBuf, inBuf + rowSize, leftLen);
×
211
    pBuf += leftLen;
×
212
  }
213

UNCOV
214
  qTrace("[StreamInternal] put result inBufSize:%zu, outBufSize:%zu", inBufSize, *outBufSize);
×
215
  return TSDB_CODE_SUCCESS;
×
216
}
217

UNCOV
218
static void freeEx(void* p) { taosMemoryFree(*(void**)p); }
×
219

220
void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) {
140,368,593✔
221
  taosMemoryFreeClear(pGroupResInfo->pBuf);
140,368,593✔
222
  if (pGroupResInfo->freeItem) {
140,383,734✔
223
    //    taosArrayDestroy(pGroupResInfo->pRows);
UNCOV
224
    taosArrayDestroyEx(pGroupResInfo->pRows, freeEx);
×
225
    pGroupResInfo->freeItem = false;
×
226
    pGroupResInfo->pRows = NULL;
×
227
  } else {
228
    taosArrayDestroy(pGroupResInfo->pRows);
140,350,767✔
229
    pGroupResInfo->pRows = NULL;
140,347,609✔
230
  }
231
  pGroupResInfo->index = 0;
140,364,815✔
232
  pGroupResInfo->delIndex = 0;
140,331,792✔
233
}
140,326,724✔
234

235
int32_t resultrowComparAsc(const void* p1, const void* p2) {
2,147,483,647✔
236
  SResKeyPos* pp1 = *(SResKeyPos**)p1;
2,147,483,647✔
237
  SResKeyPos* pp2 = *(SResKeyPos**)p2;
2,147,483,647✔
238

239
  if (pp1->groupId == pp2->groupId) {
2,147,483,647✔
240
    int64_t pts1 = *(int64_t*)pp1->key;
2,147,483,647✔
241
    int64_t pts2 = *(int64_t*)pp2->key;
2,147,483,647✔
242

243
    if (pts1 == pts2) {
2,147,483,647✔
UNCOV
244
      return 0;
×
245
    } else {
246
      return pts1 < pts2 ? -1 : 1;
2,147,483,647✔
247
    }
248
  } else {
249
    return pp1->groupId < pp2->groupId ? -1 : 1;
2,147,483,647✔
250
  }
251
}
252

253
static int32_t resultrowComparDesc(const void* p1, const void* p2) { return resultrowComparAsc(p2, p1); }
2,147,483,647✔
254

255
int32_t initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SSHashObj* pHashmap, int32_t order) {
112,054,780✔
256
  int32_t code = TSDB_CODE_SUCCESS;
112,054,780✔
257
  int32_t lino = 0;
112,054,780✔
258
  if (pGroupResInfo->pRows != NULL) {
112,054,780✔
259
    taosArrayDestroy(pGroupResInfo->pRows);
7,919,272✔
260
  }
261
  if (pGroupResInfo->pBuf) {
112,080,962✔
262
    taosMemoryFree(pGroupResInfo->pBuf);
7,919,827✔
263
    pGroupResInfo->pBuf = NULL;
7,916,497✔
264
  }
265

266
  // extract the result rows information from the hash map
267
  int32_t size = tSimpleHashGetSize(pHashmap);
112,010,856✔
268

269
  void* pData = NULL;
112,072,067✔
270
  pGroupResInfo->pRows = taosArrayInit(size, POINTER_BYTES);
112,072,067✔
271
  QUERY_CHECK_NULL(pGroupResInfo->pRows, code, lino, _end, terrno);
112,104,836✔
272

273
  size_t  keyLen = 0;
112,081,815✔
274
  int32_t iter = 0;
112,080,583✔
275
  int64_t bufLen = 0, offset = 0;
112,081,570✔
276

277
  // todo move away and record this during create window
278
  while ((pData = tSimpleHashIterate(pHashmap, pData, &iter)) != NULL) {
2,147,483,647✔
279
    /*void* key = */ (void)tSimpleHashGetKey(pData, &keyLen);
280
    bufLen += keyLen + sizeof(SResultRowPosition);
2,147,483,647✔
281
  }
282

283
  pGroupResInfo->pBuf = taosMemoryMalloc(bufLen);
111,990,202✔
284
  QUERY_CHECK_NULL(pGroupResInfo->pBuf, code, lino, _end, terrno);
112,098,491✔
285

286
  iter = 0;
112,042,704✔
287
  while ((pData = tSimpleHashIterate(pHashmap, pData, &iter)) != NULL) {
2,147,483,647✔
288
    void* key = tSimpleHashGetKey(pData, &keyLen);
2,147,483,647✔
289

290
    SResKeyPos* p = (SResKeyPos*)(pGroupResInfo->pBuf + offset);
2,147,483,647✔
291

292
    p->groupId = *(uint64_t*)key;
2,147,483,647✔
293
    p->pos = *(SResultRowPosition*)pData;
2,147,483,647✔
294
    memcpy(p->key, (char*)key + sizeof(uint64_t), keyLen - sizeof(uint64_t));
2,147,483,647✔
295
    void* tmp = taosArrayPush(pGroupResInfo->pRows, &p);
2,147,483,647✔
296
    QUERY_CHECK_NULL(pGroupResInfo->pBuf, code, lino, _end, terrno);
2,147,483,647✔
297

298
    offset += keyLen + sizeof(struct SResultRowPosition);
2,147,483,647✔
299
  }
300

301
  if (order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC) {
111,961,307✔
302
    __compar_fn_t fn = (order == TSDB_ORDER_ASC) ? resultrowComparAsc : resultrowComparDesc;
6,222,927✔
303
    size = POINTER_BYTES;
6,222,927✔
304
    taosSort(pGroupResInfo->pRows->pData, taosArrayGetSize(pGroupResInfo->pRows), size, fn);
6,222,927✔
305
  }
306

307
  pGroupResInfo->index = 0;
111,961,193✔
308

309
_end:
112,064,773✔
310
  if (code != TSDB_CODE_SUCCESS) {
112,124,763✔
UNCOV
311
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
312
  }
313
  return code;
112,124,763✔
314
}
315

UNCOV
316
void initMultiResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
×
317
  if (pGroupResInfo->pRows != NULL) {
×
318
    taosArrayDestroy(pGroupResInfo->pRows);
×
319
  }
320

UNCOV
321
  pGroupResInfo->freeItem = true;
×
322
  pGroupResInfo->pRows = pArrayList;
×
323
  pGroupResInfo->index = 0;
×
324
  pGroupResInfo->delIndex = 0;
×
325
}
×
326

327
bool hasRemainResults(SGroupResInfo* pGroupResInfo) {
432,244,992✔
328
  if (pGroupResInfo->pRows == NULL) {
432,244,992✔
UNCOV
329
    return false;
×
330
  }
331

332
  return pGroupResInfo->index < taosArrayGetSize(pGroupResInfo->pRows);
432,248,446✔
333
}
334

335
int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) {
229,262,955✔
336
  if (pGroupResInfo->pRows == 0) {
229,262,955✔
UNCOV
337
    return 0;
×
338
  }
339

340
  return (int32_t)taosArrayGetSize(pGroupResInfo->pRows);
229,310,971✔
341
}
342

343
SArray* createSortInfo(SNodeList* pNodeList) {
57,006,077✔
344
  size_t numOfCols = 0;
57,006,077✔
345

346
  if (pNodeList != NULL) {
57,006,077✔
347
    numOfCols = LIST_LENGTH(pNodeList);
56,807,379✔
348
  } else {
349
    numOfCols = 0;
198,698✔
350
  }
351

352
  SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo));
57,032,778✔
353
  if (pList == NULL) {
57,013,190✔
UNCOV
354
    return pList;
×
355
  }
356

357
  for (int32_t i = 0; i < numOfCols; ++i) {
130,377,472✔
358
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)nodesListGetNode(pNodeList, i);
73,326,903✔
359
    if (!pSortKey) {
73,362,375✔
UNCOV
360
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
361
      taosArrayDestroy(pList);
×
362
      pList = NULL;
×
363
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
364
      break;
×
365
    }
366
    SBlockOrderInfo bi = {0};
73,362,375✔
367
    bi.order = (pSortKey->order == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
73,338,377✔
368
    bi.nullFirst = (pSortKey->nullOrder == NULL_ORDER_FIRST);
73,355,387✔
369

370
    if (nodeType(pSortKey->pExpr) != QUERY_NODE_COLUMN) {
73,334,862✔
UNCOV
371
      qError("invalid order by expr type:%d", nodeType(pSortKey->pExpr));
×
372
      taosArrayDestroy(pList);
×
373
      pList = NULL;
×
374
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
375
      break;
×
376
    }
377
    
378
    SColumnNode* pColNode = (SColumnNode*)pSortKey->pExpr;
73,298,344✔
379
    bi.slotId = pColNode->slotId;
73,310,802✔
380
    void* tmp = taosArrayPush(pList, &bi);
73,357,902✔
381
    if (!tmp) {
73,357,902✔
UNCOV
382
      taosArrayDestroy(pList);
×
383
      pList = NULL;
×
384
      break;
×
385
    }
386
  }
387

388
  return pList;
57,043,923✔
389
}
390

391
SSDataBlock* createDataBlockFromDescNode(void* p) {
810,041,159✔
392
  SDataBlockDescNode* pNode = (SDataBlockDescNode*)p;
810,041,159✔
393
  int32_t      numOfCols = LIST_LENGTH(pNode->pSlots);
810,041,159✔
394
  SSDataBlock* pBlock = NULL;
810,310,296✔
395
  int32_t      code = TSDB_CODE_SUCCESS;
810,295,035✔
396
  int32_t      lino = 0;
810,295,035✔
397

398
  code = createDataBlock(&pBlock);
810,295,035✔
399
  QUERY_CHECK_CODE(code, lino, _return);
809,444,694✔
400

401
  pBlock->info.id.blockId = pNode->dataBlockId;
809,444,694✔
402
  pBlock->info.calWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
809,830,541✔
403
  pBlock->info.watermark = INT64_MIN;
809,960,992✔
404

405
  int32_t i = 0;
809,626,032✔
406
  SNode*  node = NULL;
809,626,032✔
407
  FOREACH(node, pNode->pSlots) {
2,147,483,647✔
408
    SSlotDescNode* pDescNode = (SSlotDescNode*)node;
2,147,483,647✔
409
    SColumnInfoData idata =
2,147,483,647✔
410
        createColumnInfoData(pDescNode->dataType.type, pDescNode->dataType.bytes, pDescNode->slotId);
2,147,483,647✔
411
    idata.info.scale = pDescNode->dataType.scale;
2,147,483,647✔
412
    idata.info.precision = pDescNode->dataType.precision;
2,147,483,647✔
413
    idata.info.noData = pDescNode->reserve;
2,147,483,647✔
414

415
    code = blockDataAppendColInfo(pBlock, &idata);
2,147,483,647✔
416
    QUERY_CHECK_CODE(code, lino, _return);
2,147,483,647✔
417
    ++i;
2,147,483,647✔
418
  }
419

420
  if (pBlock != NULL && i != numOfCols) {
811,261,315✔
UNCOV
421
    code = TSDB_CODE_INVALID_PARA;
×
422
    QUERY_CHECK_CODE(code, lino, _return);
×
423
  }
424

425
  return pBlock;
811,261,315✔
426
_return:
40,083✔
UNCOV
427
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
428
  blockDataDestroy(pBlock);
×
429
  terrno = code;
×
430
  return NULL;
×
431
}
432

433
int32_t prepareDataBlockBuf(SSDataBlock* pDataBlock, SColMatchInfo* pMatchInfo) {
273,783,463✔
434
  SDataBlockInfo* pBlockInfo = &pDataBlock->info;
273,783,463✔
435

436
  for (int32_t i = 0; i < taosArrayGetSize(pMatchInfo->pList); ++i) {
1,251,748,176✔
437
    SColMatchItem* pItem = taosArrayGet(pMatchInfo->pList, i);
994,676,393✔
438
    if (!pItem) {
994,053,732✔
UNCOV
439
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
440
      return terrno;
×
441
    }
442

443
    if (pItem->isPk) {
994,053,732✔
444
      SColumnInfoData* pInfoData = taosArrayGet(pDataBlock->pDataBlock, pItem->dstSlotId);
16,533,735✔
445
      if (!pInfoData) {
15,672,999✔
UNCOV
446
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
447
        return terrno;
×
448
      }
449
      pBlockInfo->pks[0].type = pInfoData->info.type;
15,672,999✔
450
      pBlockInfo->pks[1].type = pInfoData->info.type;
15,740,631✔
451

452
      // allocate enough buffer size, which is pInfoData->info.bytes
453
      if (IS_VAR_DATA_TYPE(pItem->dataType.type)) {
15,712,769✔
454
        pBlockInfo->pks[0].pData = taosMemoryCalloc(1, pInfoData->info.bytes);
4,749,954✔
455
        if (pBlockInfo->pks[0].pData == NULL) {
4,829,383✔
UNCOV
456
          return terrno;
×
457
        }
458

459
        pBlockInfo->pks[1].pData = taosMemoryCalloc(1, pInfoData->info.bytes);
4,830,751✔
460
        if (pBlockInfo->pks[1].pData == NULL) {
4,832,087✔
UNCOV
461
          taosMemoryFreeClear(pBlockInfo->pks[0].pData);
×
462
          return terrno;
×
463
        }
464

465
        pBlockInfo->pks[0].nData = pInfoData->info.bytes;
4,832,378✔
466
        pBlockInfo->pks[1].nData = pInfoData->info.bytes;
4,838,171✔
467
      }
468

469
      break;
15,728,349✔
470
    }
471
  }
472

473
  return TSDB_CODE_SUCCESS;
273,054,737✔
474
}
475

476
EDealRes doTranslateTagExpr(SNode** pNode, void* pContext) {
2,615,438✔
477
  STransTagExprCtx* pCtx = pContext;
2,615,438✔
478
  SMetaReader*      mr = pCtx->pReader;
2,615,438✔
479
  bool              isTagCol = false, isTbname = false;
2,615,438✔
480
  if (nodeType(*pNode) == QUERY_NODE_COLUMN) {
2,615,438✔
481
    SColumnNode* pCol = (SColumnNode*)*pNode;
747,268✔
482
    if (pCol->colType == COLUMN_TYPE_TBNAME)
747,268✔
UNCOV
483
      isTbname = true;
×
484
    else
485
      isTagCol = true;
747,268✔
486
  } else if (nodeType(*pNode) == QUERY_NODE_FUNCTION) {
1,868,170✔
UNCOV
487
    SFunctionNode* pFunc = (SFunctionNode*)*pNode;
×
488
    if (pFunc->funcType == FUNCTION_TYPE_TBNAME) isTbname = true;
×
489
  }
490
  if (isTagCol) {
2,615,438✔
491
    SColumnNode* pSColumnNode = *(SColumnNode**)pNode;
747,268✔
492

493
    SValueNode* res = NULL;
747,268✔
494
    pCtx->code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&res);
747,268✔
495
    if (NULL == res) {
747,268✔
UNCOV
496
      return DEAL_RES_ERROR;
×
497
    }
498

499
    res->translate = true;
747,268✔
500
    res->node.resType = pSColumnNode->node.resType;
747,268✔
501

502
    STagVal tagVal = {0};
747,268✔
503
    tagVal.cid = pSColumnNode->colId;
747,268✔
504
    const char* p = mr->pAPI->extractTagVal(mr->me.ctbEntry.pTags, pSColumnNode->node.resType.type, &tagVal);
747,268✔
505
    if (p == NULL) {
747,268✔
UNCOV
506
      res->node.resType.type = TSDB_DATA_TYPE_NULL;
×
507
    } else if (pSColumnNode->node.resType.type == TSDB_DATA_TYPE_JSON) {
747,268✔
UNCOV
508
      int32_t len = ((const STag*)p)->len;
×
509
      res->datum.p = taosMemoryCalloc(len + 1, 1);
×
510
      if (NULL == res->datum.p) {
×
511
        return DEAL_RES_ERROR;
×
512
      }
UNCOV
513
      memcpy(res->datum.p, p, len);
×
514
    } else if (IS_VAR_DATA_TYPE(pSColumnNode->node.resType.type)) {
747,268✔
515
      if (IS_STR_DATA_BLOB(pSColumnNode->node.resType.type)) {
747,268✔
UNCOV
516
        return TSDB_CODE_BLOB_NOT_SUPPORT_TAG;
×
517
      }
518

519
      res->datum.p = taosMemoryCalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1, 1);
747,268✔
520
      if (NULL == res->datum.p) {
747,268✔
UNCOV
521
        return DEAL_RES_ERROR;
×
522
      }
523

524
      if (IS_STR_DATA_BLOB(pSColumnNode->node.resType.type)) {
747,268✔
UNCOV
525
        memcpy(blobDataVal(res->datum.p), tagVal.pData, tagVal.nData);
×
526
        blobDataSetLen(res->datum.p, tagVal.nData);
×
527
      } else {
528
        memcpy(varDataVal(res->datum.p), tagVal.pData, tagVal.nData);
747,268✔
529
        varDataSetLen(res->datum.p, tagVal.nData);
747,268✔
530
      }
531
    } else {
UNCOV
532
      int32_t code = nodesSetValueNodeValue(res, &(tagVal.i64));
×
533
      if (code != TSDB_CODE_SUCCESS) {
×
534
        return DEAL_RES_ERROR;
×
535
      }
536
    }
537
    nodesDestroyNode(*pNode);
747,268✔
538
    *pNode = (SNode*)res;
747,268✔
539
  } else if (isTbname) {
1,868,170✔
UNCOV
540
    SValueNode* res = NULL;
×
541
    pCtx->code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&res);
×
542
    if (NULL == res) {
×
543
      return DEAL_RES_ERROR;
×
544
    }
545

UNCOV
546
    res->translate = true;
×
547
    res->node.resType = ((SExprNode*)(*pNode))->resType;
×
548

UNCOV
549
    int32_t len = strlen(mr->me.name);
×
550
    res->datum.p = taosMemoryCalloc(len + VARSTR_HEADER_SIZE + 1, 1);
×
551
    if (NULL == res->datum.p) {
×
552
      return DEAL_RES_ERROR;
×
553
    }
UNCOV
554
    memcpy(varDataVal(res->datum.p), mr->me.name, len);
×
555
    varDataSetLen(res->datum.p, len);
×
556
    nodesDestroyNode(*pNode);
×
557
    *pNode = (SNode*)res;
×
558
  }
559

560
  return DEAL_RES_CONTINUE;
2,615,438✔
561
}
562

563
int32_t isQualifiedTable(int64_t uid, SNode* pTagCond, void* vnode, bool* pQualified, SStorageAPI* pAPI) {
373,634✔
564
  int32_t     code = TSDB_CODE_SUCCESS;
373,634✔
565
  SMetaReader mr = {0};
373,634✔
566

567
  pAPI->metaReaderFn.initReader(&mr, vnode, META_READER_LOCK, &pAPI->metaFn);
373,634✔
568
  code = pAPI->metaReaderFn.getEntryGetUidCache(&mr, uid);
373,634✔
569
  if (TSDB_CODE_SUCCESS != code) {
373,634✔
UNCOV
570
    pAPI->metaReaderFn.clearReader(&mr);
×
571
    *pQualified = false;
×
572

UNCOV
573
    return TSDB_CODE_SUCCESS;
×
574
  }
575

576
  SNode* pTagCondTmp = NULL;
373,634✔
577
  code = nodesCloneNode(pTagCond, &pTagCondTmp);
373,634✔
578
  if (TSDB_CODE_SUCCESS != code) {
373,634✔
UNCOV
579
    *pQualified = false;
×
580
    pAPI->metaReaderFn.clearReader(&mr);
×
581
    return code;
×
582
  }
583
  STransTagExprCtx ctx = {.code = 0, .pReader = &mr};
373,634✔
584
  nodesRewriteExprPostOrder(&pTagCondTmp, doTranslateTagExpr, &ctx);
373,634✔
585
  pAPI->metaReaderFn.clearReader(&mr);
373,634✔
586
  if (TSDB_CODE_SUCCESS != ctx.code) {
373,634✔
UNCOV
587
    *pQualified = false;
×
588
    nodesDestroyNode(pTagCondTmp);
×
589
    terrno = code;
×
590
    return code;
×
591
  }
592

593
  SNode* pNew = NULL;
373,634✔
594
  code = scalarCalculateConstants(pTagCondTmp, &pNew);
373,634✔
595
  if (TSDB_CODE_SUCCESS != code) {
373,634✔
UNCOV
596
    terrno = code;
×
597
    nodesDestroyNode(pTagCondTmp);
×
598
    *pQualified = false;
×
599

UNCOV
600
    return code;
×
601
  }
602

603
  SValueNode* pValue = (SValueNode*)pNew;
373,634✔
604
  *pQualified = pValue->datum.b;
373,634✔
605

606
  nodesDestroyNode(pNew);
373,634✔
607
  return TSDB_CODE_SUCCESS;
373,634✔
608
}
609

610
static EDealRes getColumn(SNode** pNode, void* pContext) {
63,612,315✔
611
  tagFilterAssist* pData = (tagFilterAssist*)pContext;
63,612,315✔
612
  SColumnNode*     pSColumnNode = NULL;
63,612,315✔
613
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
63,634,505✔
614
    pSColumnNode = *(SColumnNode**)pNode;
21,864,674✔
615
  } else if (QUERY_NODE_FUNCTION == nodeType((*pNode))) {
41,810,967✔
616
    SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
1,230,906✔
617
    if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
1,230,771✔
618
      pData->code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pSColumnNode);
772,901✔
619
      if (NULL == pSColumnNode) {
773,434✔
UNCOV
620
        return DEAL_RES_ERROR;
×
621
      }
622
      pSColumnNode->colId = -1;
773,434✔
623
      pSColumnNode->colType = COLUMN_TYPE_TBNAME;
773,434✔
624
      pSColumnNode->node.resType.type = TSDB_DATA_TYPE_VARCHAR;
773,685✔
625
      pSColumnNode->node.resType.bytes = TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE;
773,181✔
626
      nodesDestroyNode(*pNode);
772,789✔
627
      *pNode = (SNode*)pSColumnNode;
772,901✔
628
    } else {
629
      return DEAL_RES_CONTINUE;
458,714✔
630
    }
631
  } else {
632
    return DEAL_RES_CONTINUE;
40,544,141✔
633
  }
634

635
  void* data = taosHashGet(pData->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId));
22,635,609✔
636
  if (!data) {
22,634,253✔
637
    int32_t tempRes =
638
        taosHashPut(pData->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId), pNode, sizeof((*pNode)));
19,553,254✔
639
    if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
19,580,889✔
UNCOV
640
      return DEAL_RES_ERROR;
×
641
    }
642
    pSColumnNode->slotId = pData->index++;
19,580,889✔
643
    SColumnInfo cInfo = {.colId = pSColumnNode->colId,
19,541,893✔
644
                         .type = pSColumnNode->node.resType.type,
19,529,915✔
645
                         .bytes = pSColumnNode->node.resType.bytes,
19,556,625✔
646
                         .pk = pSColumnNode->isPk};
19,531,045✔
647
#if TAG_FILTER_DEBUG
648
    qDebug("tagfilter build column info, slotId:%d, colId:%d, type:%d", pSColumnNode->slotId, cInfo.colId, cInfo.type);
649
#endif
650
    void* tmp = taosArrayPush(pData->cInfoList, &cInfo);
19,516,431✔
651
    if (!tmp) {
19,566,337✔
UNCOV
652
      return DEAL_RES_ERROR;
×
653
    }
654
  } else {
655
    SColumnNode* col = *(SColumnNode**)data;
3,080,999✔
656
    pSColumnNode->slotId = col->slotId;
3,081,509✔
657
  }
658

659
  return DEAL_RES_CONTINUE;
22,601,003✔
660
}
661

662
static int32_t createResultData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
18,214,394✔
663
  SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
18,214,394✔
664
  if (pColumnData == NULL) {
18,201,321✔
UNCOV
665
    return terrno;
×
666
  }
667

668
  pColumnData->info.type = pType->type;
18,201,321✔
669
  pColumnData->info.bytes = pType->bytes;
18,198,711✔
670
  pColumnData->info.scale = pType->scale;
18,201,096✔
671
  pColumnData->info.precision = pType->precision;
18,174,023✔
672

673
  int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true);
18,186,900✔
674
  if (code != TSDB_CODE_SUCCESS) {
18,159,653✔
UNCOV
675
    terrno = code;
×
676
    releaseColInfoData(pColumnData);
×
677
    return terrno;
×
678
  }
679

680
  pParam->columnData = pColumnData;
18,159,653✔
681
  pParam->colAlloced = true;
18,180,036✔
682
  return TSDB_CODE_SUCCESS;
18,176,671✔
683
}
684

685
static void releaseColInfoData(void* pCol) {
5,156,175✔
686
  if (pCol) {
5,156,175✔
687
    SColumnInfoData* col = (SColumnInfoData*)pCol;
5,157,703✔
688
    colDataDestroy(col);
5,157,703✔
689
    taosMemoryFree(col);
5,157,974✔
690
  }
691
}
5,156,244✔
692

693
void freeItem(void* p) {
212,108,497✔
694
  STUidTagInfo* pInfo = p;
212,108,497✔
695
  if (pInfo->pTagVal != NULL) {
212,108,497✔
696
    taosMemoryFree(pInfo->pTagVal);
211,551,373✔
697
  }
698
}
212,097,164✔
699

700
typedef struct {
701
  col_id_t  colId;
702
  SNode*    pValueNode;
703
  int32_t   bytes;  // length defined in schema
704
} STagDataEntry;
705

706
static int compareTagDataEntry(const void* a, const void* b) {
21,798✔
707
  STagDataEntry* p1 = (STagDataEntry*)a;
21,798✔
708
  STagDataEntry* p2 = (STagDataEntry*)b;
21,798✔
709
  return compareInt16Val(&p1->colId, &p2->colId);
21,798✔
710
}
711

712
static int32_t buildTagDataEntryKey(SArray* pIdWithValue, char** keyBuf, int32_t keyLen) {
10,899✔
713
  *keyBuf = (char*)taosMemoryCalloc(1, keyLen);
10,899✔
714
  if (NULL == *keyBuf) {
10,899✔
UNCOV
715
    qError(
×
716
      "failed to allocate memory for tag filter optimization key, size:%d",
717
      keyLen);
UNCOV
718
    return terrno;
×
719
  }
720
  char* pStart = *keyBuf;
10,899✔
721
  for (int32_t i = 0; i < taosArrayGetSize(pIdWithValue); ++i) {
32,697✔
722
    STagDataEntry* entry      = (STagDataEntry*)taosArrayGet(pIdWithValue, i);
21,798✔
723
    SValueNode*    pValueNode = (SValueNode*)entry->pValueNode;
21,798✔
724
    // num type may have different bytes length, use the smaller one
725
    int32_t        bytes = TMIN(entry->bytes, pValueNode->node.resType.bytes);
21,798✔
726

727
    (void)memcpy(pStart, &entry->colId, sizeof(col_id_t));
21,798✔
728
    pStart += sizeof(col_id_t);
21,798✔
729

730
    if (!pValueNode->isNull) {
21,798✔
731
      switch (pValueNode->node.resType.type) {
17,473✔
732
        case TSDB_DATA_TYPE_BOOL:
2,249✔
733
          (void)memcpy(
2,249✔
734
            pStart, &pValueNode->datum.b, bytes);
2,249✔
735
          pStart += bytes;
2,249✔
736
          break;
2,249✔
737
        case TSDB_DATA_TYPE_TINYINT:
7,785✔
738
        case TSDB_DATA_TYPE_SMALLINT:
739
        case TSDB_DATA_TYPE_INT:
740
        case TSDB_DATA_TYPE_BIGINT:
741
        case TSDB_DATA_TYPE_TIMESTAMP:
742
          (void)memcpy(
7,785✔
743
            pStart, &pValueNode->datum.i, bytes);
7,785✔
744
          pStart += bytes;
7,785✔
745
          break;
7,785✔
UNCOV
746
        case TSDB_DATA_TYPE_UTINYINT:
×
747
        case TSDB_DATA_TYPE_USMALLINT:
748
        case TSDB_DATA_TYPE_UINT:
749
        case TSDB_DATA_TYPE_UBIGINT:
UNCOV
750
          (void)memcpy(
×
751
            pStart, &pValueNode->datum.u, bytes);
×
752
          pStart += bytes;
×
753
          break;
×
754
        case TSDB_DATA_TYPE_FLOAT:
2,595✔
755
        case TSDB_DATA_TYPE_DOUBLE:
756
          (void)memcpy(
2,595✔
757
            pStart, &pValueNode->datum.d, bytes);
2,595✔
758
          pStart += bytes;
2,595✔
759
          break;
2,595✔
760
        case TSDB_DATA_TYPE_VARCHAR:
4,844✔
761
        case TSDB_DATA_TYPE_VARBINARY:
762
        case TSDB_DATA_TYPE_NCHAR:
763
          (void)memcpy(pStart,
4,844✔
764
            varDataVal(pValueNode->datum.p), varDataLen(pValueNode->datum.p));
4,844✔
765
          pStart += varDataLen(pValueNode->datum.p);
4,844✔
766
          break;
4,844✔
UNCOV
767
        default:
×
768
          qError("unsupported tag data type %d in tag filter optimization",
×
769
            pValueNode->node.resType.type);
UNCOV
770
          return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
771
      }
772
    }
773
  }
774

775
  return TSDB_CODE_SUCCESS;
10,899✔
776
}
777

778
static void extractTagDataEntry(
21,798✔
779
  SOperatorNode* pOpNode, SArray* pIdWithValue) {
780
  SNode* pLeft = pOpNode->pLeft;
21,798✔
781
  SNode* pRight = pOpNode->pRight;
21,798✔
782
  SColumnNode* pColNode = nodeType(pLeft) == QUERY_NODE_COLUMN ?
21,798✔
783
    (SColumnNode*)pLeft : (SColumnNode*)pRight;
21,798✔
784
  SValueNode* pValueNode = nodeType(pLeft) == QUERY_NODE_VALUE ?
21,798✔
785
    (SValueNode*)pLeft : (SValueNode*)pRight;
21,798✔
786

787
  STagDataEntry entry = {0};
21,798✔
788
  entry.colId = pColNode->colId;
21,798✔
789
  entry.pValueNode = (SNode*)pValueNode;
21,798✔
790
  entry.bytes = pColNode->node.resType.bytes;
21,798✔
791
  void* _tmp = taosArrayPush(pIdWithValue, &entry);
21,798✔
792
}
21,798✔
793

794
static int32_t extractTagFilterTagDataEntries(
10,899✔
795
  const SNode* pTagCond, SArray* pIdWithVal) {
796
  if (NULL == pTagCond || NULL == pIdWithVal ||
10,899✔
797
    (nodeType(pTagCond) != QUERY_NODE_OPERATOR &&
10,899✔
798
      nodeType(pTagCond) != QUERY_NODE_LOGIC_CONDITION)) {
10,899✔
UNCOV
799
    qError("invalid parameter to extract tag filter symbol");
×
800
    return TSDB_CODE_STREAM_INTERNAL_ERROR;
×
801
  }
802

803
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
10,899✔
UNCOV
804
    extractTagDataEntry((SOperatorNode*)pTagCond, pIdWithVal);
×
805
  } else if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION) {
10,899✔
806
    SNode* pChild = NULL;
10,899✔
807
    FOREACH(pChild, ((SLogicConditionNode*)pTagCond)->pParameterList) {
32,697✔
808
      extractTagDataEntry((SOperatorNode*)pChild, pIdWithVal);
21,798✔
809
    }
810
  }
811

812
  taosArraySort(pIdWithVal, compareTagDataEntry);
10,899✔
813

814
  return TSDB_CODE_SUCCESS;
10,899✔
815
}
816

817
static int32_t genStableTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) {
10,899✔
818
  if (pTagCond == NULL) {
10,899✔
UNCOV
819
    return TSDB_CODE_SUCCESS;
×
820
  }
821

822
  char*   payload = NULL;
10,899✔
823
  int32_t len = 0;
10,899✔
824
  int32_t code = TSDB_CODE_SUCCESS;
10,899✔
825
  int32_t lino = 0;
10,899✔
826

827
  SArray* pIdWithVal = taosArrayInit(TARRAY_MIN_SIZE, sizeof(STagDataEntry));
10,899✔
828
  code = extractTagFilterTagDataEntries(pTagCond, pIdWithVal);
10,899✔
829
  QUERY_CHECK_CODE(code, lino, _end);
10,899✔
830
  for (int32_t i = 0; i < taosArrayGetSize(pIdWithVal); ++i) {
32,697✔
831
    STagDataEntry* pEntry = taosArrayGet(pIdWithVal, i);
21,798✔
832
    len += sizeof(col_id_t) + pEntry->bytes;
21,798✔
833
  }
834
  code = buildTagDataEntryKey(pIdWithVal, &payload, len);
10,899✔
835
  QUERY_CHECK_CODE(code, lino, _end);
10,899✔
836

837
  tMD5Init(pContext);
10,899✔
838
  tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len);
10,899✔
839
  tMD5Final(pContext);
10,899✔
840

841
_end:
10,899✔
842
  if (TSDB_CODE_SUCCESS != code) {
10,899✔
UNCOV
843
    qError("%s failed at line %d since %s",
×
844
      __func__, __LINE__, tstrerror(code));
845
  }
846
  taosArrayDestroy(pIdWithVal);
10,899✔
847
  taosMemoryFree(payload);
10,899✔
848
  return code;
10,899✔
849
}
850

851
static int32_t genTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) {
34,078✔
852
  if (pTagCond == NULL) {
34,078✔
853
    return TSDB_CODE_SUCCESS;
32,194✔
854
  }
855

856
  char*   payload = NULL;
1,884✔
857
  int32_t len = 0;
1,884✔
858
  int32_t code = nodesNodeToMsg(pTagCond, &payload, &len);
1,884✔
859
  if (code != TSDB_CODE_SUCCESS) {
1,884✔
UNCOV
860
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
861
    return code;
×
862
  }
863

864
  tMD5Init(pContext);
1,884✔
865
  tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len);
1,884✔
866
  tMD5Final(pContext);
1,884✔
867

868
  // void* tmp = NULL;
869
  // uint32_t size = 0;
870
  // (void)taosAscii2Hex((const char*)pContext->digest, 16, &tmp, &size);
871
  // qInfo("tag filter digest payload: %s", tmp);
872
  // taosMemoryFree(tmp);
873

874
  taosMemoryFree(payload);
1,884✔
875
  return TSDB_CODE_SUCCESS;
1,884✔
876
}
877

UNCOV
878
static int32_t genTbGroupDigest(const SNode* pGroup, uint8_t* filterDigest, T_MD5_CTX* pContext) {
×
879
  int32_t code = TSDB_CODE_SUCCESS;
×
880
  int32_t lino = 0;
×
881
  char*   payload = NULL;
×
882
  int32_t len = 0;
×
883
  code = nodesNodeToMsg(pGroup, &payload, &len);
×
884
  QUERY_CHECK_CODE(code, lino, _end);
×
885

UNCOV
886
  if (filterDigest[0]) {
×
887
    payload = taosMemoryRealloc(payload, len + tListLen(pContext->digest));
×
888
    QUERY_CHECK_NULL(payload, code, lino, _end, terrno);
×
889
    memcpy(payload + len, filterDigest + 1, tListLen(pContext->digest));
×
890
    len += tListLen(pContext->digest);
×
891
  }
892

UNCOV
893
  tMD5Init(pContext);
×
894
  tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len);
×
895
  tMD5Final(pContext);
×
896

UNCOV
897
_end:
×
898
  taosMemoryFree(payload);
×
899
  if (code != TSDB_CODE_SUCCESS) {
×
900
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
901
  }
UNCOV
902
  return code;
×
903
}
904

905
int32_t qGetColumnsFromNodeList(void* data, bool isList, SArray** pColList) {
17,732,393✔
906
  int32_t code = TSDB_CODE_SUCCESS;
17,732,393✔
907
  tagFilterAssist ctx = {0};
17,732,393✔
908
  ctx.colHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
17,739,587✔
909
  if (ctx.colHash == NULL) {
17,736,618✔
UNCOV
910
    code = terrno;
×
911
    goto end;
×
912
  }
913

914
  ctx.index = 0;
17,736,618✔
915
  ctx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo));
17,736,618✔
916
  if (ctx.cInfoList == NULL) {
17,742,153✔
917
    code = terrno;
14,553✔
UNCOV
918
    goto end;
×
919
  }
920

921
  if (isList) {
17,727,600✔
922
    SNode* pNode = NULL;
4,662,484✔
923
    FOREACH(pNode, (SNodeList*)data) {
9,819,804✔
924
      nodesRewriteExprPostOrder(&pNode, getColumn, (void*)&ctx);
5,158,177✔
925
      if (TSDB_CODE_SUCCESS != ctx.code) {
5,155,997✔
UNCOV
926
        code = ctx.code;
×
927
        goto end;
×
928
      }
929
      REPLACE_NODE(pNode);
5,155,997✔
930
    }
931
  } else {
932
    SNode* pNode = (SNode*)data;
13,065,116✔
933
    nodesRewriteExprPostOrder(&pNode, getColumn, (void*)&ctx);
13,070,339✔
934
    if (TSDB_CODE_SUCCESS != ctx.code) {
13,068,645✔
UNCOV
935
      code = ctx.code;
×
936
      goto end;
×
937
    }
938
  }
939
  
940
  if (pColList != NULL) *pColList = ctx.cInfoList;
17,692,138✔
941
  ctx.cInfoList = NULL;
17,714,290✔
942

943
end:
17,755,150✔
944
  taosHashCleanup(ctx.colHash);
17,715,229✔
945
  taosArrayDestroy(ctx.cInfoList);
17,680,245✔
946
  return code;
17,690,590✔
947
}
948

949
static int32_t buildGroupInfo(SColumnInfoData* pValue, int32_t i, SArray* gInfo) {
731,393✔
950
  int32_t code = TSDB_CODE_SUCCESS;
731,393✔
951
  SStreamGroupValue* v = taosArrayReserve(gInfo, 1);
731,393✔
952
  if (v == NULL) {
731,267✔
UNCOV
953
    code = terrno;
×
954
    goto end;
×
955
  }
956
  if (colDataIsNull_s(pValue, i)) {
1,462,960✔
957
    v->isNull = true;
4,325✔
958
  } else {
959
    v->isNull = false;
727,368✔
960
    char* data = colDataGetData(pValue, i);
727,368✔
961
    if (pValue->info.type == TSDB_DATA_TYPE_JSON) {
727,174✔
UNCOV
962
      if (tTagIsJson(data)) {
×
963
        code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
×
964
        goto end;
×
965
      }
UNCOV
966
      if (tTagIsJsonNull(data)) {
×
967
        v->isNull = true;
×
968
        goto end;
×
969
      }
UNCOV
970
      int32_t len = getJsonValueLen(data);
×
971
      v->data.type = pValue->info.type;
×
972
      v->data.nData = len;
×
973
      v->data.pData = taosMemoryCalloc(1, len + 1);
×
974
      if (v->data.pData == NULL) {
×
975
        code = terrno;
×
976
        goto end;
×
977
      }
UNCOV
978
      memcpy(v->data.pData, data, len);
×
979
      qDebug("buildGroupInfo:%d add json data len:%d, data:%s", i, len, (char*)v->data.pData);
×
980
    } else if (IS_VAR_DATA_TYPE(pValue->info.type)) {
727,180✔
981
      if (varDataTLen(data) > pValue->info.bytes) {
455,563✔
UNCOV
982
        code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
983
        goto end;
×
984
      }
985
      v->data.type = pValue->info.type;
456,083✔
986
      v->data.nData = varDataLen(data);
456,130✔
987
      v->data.pData = taosMemoryCalloc(1, varDataLen(data) + 1);
456,130✔
988
      if (v->data.pData == NULL) {
456,318✔
UNCOV
989
        code = terrno;
×
990
        goto end;
×
991
      }
992
      memcpy(v->data.pData, varDataVal(data), varDataLen(data));
456,318✔
993
      qDebug("buildGroupInfo:%d add var data type:%d, len:%d, data:%s", i, pValue->info.type, varDataLen(data), (char*)v->data.pData);
456,318✔
994
    } else if (pValue->info.type == TSDB_DATA_TYPE_DECIMAL) {  // reader todo decimal
271,018✔
UNCOV
995
      v->data.type = pValue->info.type;
×
996
      v->data.nData = pValue->info.bytes;
×
997
      v->data.pData = taosMemoryCalloc(1, pValue->info.bytes);
×
998
      if (v->data.pData == NULL) {
×
999
        code = terrno;
×
1000
        goto end;
×
1001
      }
UNCOV
1002
      memcpy(&v->data.pData, data, pValue->info.bytes);
×
1003
      qDebug("buildGroupInfo:%d add data type:%d, data:%"PRId64, i, pValue->info.type, v->data.val);
×
1004
    } else {  // reader todo decimal
1005
      v->data.type = pValue->info.type;
271,191✔
1006
      memcpy(&v->data.val, data, pValue->info.bytes);
271,191✔
1007
      qDebug("buildGroupInfo:%d add data type:%d, data:%"PRId64, i, pValue->info.type, v->data.val);
271,018✔
1008
    }
1009
  }
1010
end:
35,616✔
1011
  if (code != TSDB_CODE_SUCCESS) {
731,834✔
UNCOV
1012
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1013
    v->isNull = true;
×
1014
  }
1015
  return code;
731,834✔
1016
}
1017

1018
static void getColInfoResultForGroupbyForStream(void* pVnode, SNodeList* group, STableListInfo* pTableListInfo,
86,333✔
1019
                                   SStorageAPI* pAPI, SHashObj* groupIdMap) {
1020
  int32_t      code = TSDB_CODE_SUCCESS;
86,333✔
1021
  int32_t      lino = 0;
86,333✔
1022
  SArray*      pBlockList = NULL;
86,333✔
1023
  SSDataBlock* pResBlock = NULL;
86,333✔
1024
  SArray*      groupData = NULL;
86,538✔
1025
  SArray*      pUidTagList = NULL;
86,538✔
1026
  SArray*      gInfo = NULL;
86,538✔
1027
  int32_t      tbNameIndex = 0;
86,538✔
1028

1029
  int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
86,538✔
1030
  if (rows == 0) {
86,538✔
UNCOV
1031
    return;
×
1032
  }
1033

1034
  pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
86,538✔
1035
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
86,538✔
1036

1037
  for (int32_t i = 0; i < rows; ++i) {
411,275✔
1038
    STableKeyInfo* pkeyInfo = taosArrayGet(pTableListInfo->pTableList, i);
324,737✔
1039
    QUERY_CHECK_NULL(pkeyInfo, code, lino, end, terrno);
324,737✔
1040
    STUidTagInfo info = {.uid = pkeyInfo->uid};
324,737✔
1041
    void*        tmp = taosArrayPush(pUidTagList, &info);
324,737✔
1042
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
324,737✔
1043
  }
1044
 
1045
  if (taosArrayGetSize(pUidTagList) > 0) {
86,538✔
1046
    code = pAPI->metaFn.getTableTagsByUid(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
86,538✔
1047
  } else {
UNCOV
1048
    code = pAPI->metaFn.getTableTags(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
×
1049
  }
1050
  if (code != TSDB_CODE_SUCCESS) {
86,538✔
UNCOV
1051
    goto end;
×
1052
  }
1053

1054
  SArray* pColList = NULL;
86,538✔
1055
  code = qGetColumnsFromNodeList(group, true, &pColList);
86,538✔
1056
  if (code != TSDB_CODE_SUCCESS) {
86,397✔
UNCOV
1057
    goto end;
×
1058
  }
1059

1060
  for (int32_t i = 0; i < taosArrayGetSize(pColList); ++i) {
259,532✔
1061
    SColumnInfo* tmp = (SColumnInfo*)taosArrayGet(pColList, i);
173,276✔
1062
    if (tmp != NULL && tmp->colId == -1) {
173,276✔
1063
      tbNameIndex = i;
86,397✔
1064
    }
1065
  }
1066
  
1067
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
86,397✔
1068
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
86,397✔
1069
  taosArrayDestroy(pColList);
86,538✔
1070
  if (pResBlock == NULL) {
86,538✔
1071
    code = terrno;
275✔
1072
    goto end;
275✔
1073
  }
1074

1075
  pBlockList = taosArrayInit(2, POINTER_BYTES);
86,263✔
1076
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
86,263✔
1077

1078
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
86,263✔
1079
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
86,263✔
1080

1081
  groupData = taosArrayInit(2, POINTER_BYTES);
86,263✔
1082
  QUERY_CHECK_NULL(groupData, code, lino, end, terrno);
86,263✔
1083

1084
  SNode* pNode = NULL;
86,263✔
1085
  FOREACH(pNode, group) {
259,835✔
1086
    SScalarParam output = {0};
173,572✔
1087

1088
    switch (nodeType(pNode)) {
173,572✔
UNCOV
1089
      case QUERY_NODE_VALUE:
×
1090
        break;
×
1091
      case QUERY_NODE_COLUMN:
173,572✔
1092
      case QUERY_NODE_OPERATOR:
1093
      case QUERY_NODE_FUNCTION: {
1094
        SExprNode* expNode = (SExprNode*)pNode;
173,572✔
1095
        code = createResultData(&expNode->resType, rows, &output);
173,572✔
1096
        if (code != TSDB_CODE_SUCCESS) {
173,572✔
UNCOV
1097
          goto end;
×
1098
        }
1099
        break;
173,572✔
1100
      }
1101

UNCOV
1102
      default:
×
1103
        code = TSDB_CODE_OPS_NOT_SUPPORT;
×
1104
        goto end;
×
1105
    }
1106

1107
    if (nodeType(pNode) == QUERY_NODE_COLUMN) {
173,572✔
1108
      SColumnNode*     pSColumnNode = (SColumnNode*)pNode;
173,572✔
1109
      SColumnInfoData* pColInfo = (SColumnInfoData*)taosArrayGet(pResBlock->pDataBlock, pSColumnNode->slotId);
173,572✔
1110
      QUERY_CHECK_NULL(pColInfo, code, lino, end, terrno);
173,337✔
1111
      code = colDataAssign(output.columnData, pColInfo, rows, NULL);
173,337✔
UNCOV
1112
    } else if (nodeType(pNode) == QUERY_NODE_VALUE) {
×
1113
      continue;
×
1114
    } else {
UNCOV
1115
      gTaskScalarExtra.pStreamInfo = NULL;
×
1116
      gTaskScalarExtra.pStreamRange = NULL;
×
1117
      code = scalarCalculate(pNode, pBlockList, &output, &gTaskScalarExtra);
×
1118
    }
1119

1120
    if (code != TSDB_CODE_SUCCESS) {
173,152✔
UNCOV
1121
      releaseColInfoData(output.columnData);
×
1122
      goto end;
×
1123
    }
1124

1125
    void* tmp = taosArrayPush(groupData, &output.columnData);
173,109✔
1126
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
173,109✔
1127
  }
1128

1129
  for (int i = 0; i < rows; i++) {
410,725✔
1130
    gInfo = taosArrayInit(taosArrayGetSize(groupData), sizeof(SStreamGroupValue));
324,209✔
1131
    QUERY_CHECK_NULL(gInfo, code, lino, end, terrno);
324,274✔
1132

1133
    STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
324,274✔
1134
    QUERY_CHECK_NULL(info, code, lino, end, terrno);
324,274✔
1135

1136
    for (int j = 0; j < taosArrayGetSize(groupData); j++) {
925,689✔
1137
      SColumnInfoData* pValue = (SColumnInfoData*)taosArrayGetP(groupData, j);
601,227✔
1138
        int32_t ret = buildGroupInfo(pValue, i, gInfo);
600,974✔
1139
        if (ret != TSDB_CODE_SUCCESS) {
601,415✔
UNCOV
1140
          qError("buildGroupInfo failed at line %d since %s", __LINE__, tstrerror(ret));
×
1141
          goto end;
×
1142
        }
1143
        if (j == tbNameIndex) {
601,415✔
1144
          SStreamGroupValue* v = taosArrayGetLast(gInfo);
324,227✔
1145
          if (v != NULL){
324,462✔
1146
            v->isTbname = true;
324,227✔
1147
            v->uid = info->uid;
323,974✔
1148
          }
1149
        }
1150
    }
1151

1152
    int32_t ret = taosHashPut(groupIdMap, &info->uid, sizeof(info->uid), &gInfo, POINTER_BYTES);
324,462✔
1153
    if (ret != TSDB_CODE_SUCCESS) {
324,462✔
UNCOV
1154
      qError("put groupid to map failed at line %d since %s", __LINE__, tstrerror(ret));
×
1155
      goto end;
×
1156
    }
1157
    qDebug("put groupid to map gid:%" PRIu64, info->uid);
324,462✔
1158
    gInfo = NULL;
324,462✔
1159
  }
1160

1161
end:
86,791✔
1162
  blockDataDestroy(pResBlock);
86,538✔
1163
  taosArrayDestroy(pBlockList);
86,538✔
1164
  taosArrayDestroyEx(pUidTagList, freeItem);
86,538✔
1165
  taosArrayDestroyP(groupData, releaseColInfoData);
86,538✔
1166
  taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
86,538✔
1167

1168
  if (code != TSDB_CODE_SUCCESS) {
86,538✔
1169
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
275✔
1170
  }
1171
}
1172

1173
int32_t getColInfoResultForGroupby(SReadHandle* pHandle, SNodeList* group, STableListInfo* pTableListInfo, uint8_t* digest,
4,576,133✔
1174
                                   SStorageAPI* pAPI, bool initRemainGroups, SHashObj* groupIdMap, bool gIdFromBaseId) {
1175
  int32_t      code = TSDB_CODE_SUCCESS;
4,576,133✔
1176
  int32_t      lino = 0;
4,576,133✔
1177
  SArray*      pBlockList = NULL;
4,576,133✔
1178
  SSDataBlock* pResBlock = NULL;
4,576,133✔
1179
  void*        keyBuf = NULL;
4,577,883✔
1180
  SArray*      groupData = NULL;
4,577,883✔
1181
  SArray*      pUidTagList = NULL;
4,577,883✔
1182
  SArray*      tableList = NULL;
4,577,883✔
1183
  SArray*      gInfo = NULL;
4,577,883✔
1184
  void*        pVnode = pHandle->vnode;
4,577,883✔
1185

1186
  int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
4,577,883✔
1187
  if (rows == 0) {
4,577,883✔
UNCOV
1188
    return TSDB_CODE_SUCCESS;
×
1189
  } 
1190

1191
  T_MD5_CTX context = {0};
4,577,883✔
1192
  if (tsTagFilterCache && groupIdMap == NULL && digest) {
4,577,883✔
UNCOV
1193
    SNodeListNode* listNode = NULL;
×
UNCOV
1194
    code = nodesMakeNode(QUERY_NODE_NODE_LIST, (SNode**)&listNode);
×
1195
    if (TSDB_CODE_SUCCESS != code) {
×
1196
      goto end;
×
1197
    }
1198
    listNode->pNodeList = group;
×
UNCOV
1199
    code = genTbGroupDigest((SNode*)listNode, digest, &context);
×
1200
    QUERY_CHECK_CODE(code, lino, end);
×
1201

1202
    nodesFree(listNode);
×
1203

1204
    code = pAPI->metaFn.metaGetCachedTbGroup(pVnode, pTableListInfo->idInfo.suid, context.digest,
×
1205
                                             tListLen(context.digest), &tableList);
1206
    QUERY_CHECK_CODE(code, lino, end);
×
1207

1208
    if (tableList) {
×
UNCOV
1209
      taosArrayDestroy(pTableListInfo->pTableList);
×
1210
      pTableListInfo->pTableList = tableList;
×
1211
      qDebug("retrieve tb group list from cache, numOfTables:%d",
×
1212
             (int32_t)taosArrayGetSize(pTableListInfo->pTableList));
1213
      goto end;
×
1214
    }
1215
  }
1216

1217
  pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
4,577,883✔
1218
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
4,576,674✔
1219

1220
  for (int32_t i = 0; i < rows; ++i) {
29,301,186✔
1221
    STableKeyInfo* pkeyInfo = taosArrayGet(pTableListInfo->pTableList, i);
24,722,535✔
1222
    QUERY_CHECK_NULL(pkeyInfo, code, lino, end, terrno);
24,722,708✔
1223
    STUidTagInfo info = {.uid = pkeyInfo->uid};
24,722,708✔
1224
    void*        tmp = taosArrayPush(pUidTagList, &info);
24,726,069✔
1225
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
24,726,069✔
1226
  }
1227

1228
  if (taosArrayGetSize(pUidTagList) > 0) {
4,578,651✔
1229
    code = pAPI->metaFn.getTableTagsByUid(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
4,577,212✔
1230
  } else {
UNCOV
1231
    code = pAPI->metaFn.getTableTags(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
×
1232
  }
1233
  if (code != TSDB_CODE_SUCCESS) {
4,577,883✔
UNCOV
1234
    goto end;
×
1235
  }
1236

1237
  SArray* pColList = NULL;
4,577,883✔
1238
  code = qGetColumnsFromNodeList(group, true, &pColList); 
4,577,883✔
1239
  if (code != TSDB_CODE_SUCCESS) {
4,574,141✔
UNCOV
1240
    goto end;
×
1241
  }
1242

1243
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
4,574,141✔
1244
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
4,573,580✔
1245
  taosArrayDestroy(pColList);
4,577,338✔
1246
  if (pResBlock == NULL) {
4,576,231✔
UNCOV
1247
    code = terrno;
×
UNCOV
1248
    goto end;
×
1249
  }
1250

1251
  //  int64_t st1 = taosGetTimestampUs();
1252
  //  qDebug("generate tag block rows:%d, cost:%ld us", rows, st1-st);
1253

1254
  pBlockList = taosArrayInit(2, POINTER_BYTES);
4,576,231✔
1255
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
4,575,115✔
1256

1257
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
4,575,567✔
1258
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
4,575,567✔
1259

1260
  groupData = taosArrayInit(2, POINTER_BYTES);
4,575,567✔
1261
  QUERY_CHECK_NULL(groupData, code, lino, end, terrno);
4,576,221✔
1262

1263
  SNode* pNode = NULL;
4,575,115✔
1264
  FOREACH(pNode, group) {
9,557,603✔
1265
    SScalarParam output = {0};
4,984,183✔
1266

1267
    switch (nodeType(pNode)) {
4,984,042✔
UNCOV
1268
      case QUERY_NODE_VALUE:
×
UNCOV
1269
        break;
×
1270
      case QUERY_NODE_COLUMN:
4,982,769✔
1271
      case QUERY_NODE_OPERATOR:
1272
      case QUERY_NODE_FUNCTION: {
1273
        SExprNode* expNode = (SExprNode*)pNode;
4,982,769✔
1274
        code = createResultData(&expNode->resType, rows, &output);
4,982,769✔
1275
        if (code != TSDB_CODE_SUCCESS) {
4,980,950✔
UNCOV
1276
          goto end;
×
1277
        }
1278
        break;
4,980,950✔
1279
      }
UNCOV
1280
      case QUERY_NODE_REMOTE_VALUE: {
×
UNCOV
1281
        SRemoteValueNode* pRemote = (SRemoteValueNode*)pNode;
×
1282
        code = qFetchRemoteNode(gTaskScalarExtra.pSubJobCtx, pRemote->subQIdx, pNode);
×
1283
        QUERY_CHECK_CODE(code, lino, end);
×
1284
        break;
×
1285
      }
1286
      
UNCOV
1287
      default:
×
UNCOV
1288
        code = TSDB_CODE_OPS_NOT_SUPPORT;
×
1289
        goto end;
×
1290
    }
1291

1292
    if (nodeType(pNode) == QUERY_NODE_COLUMN) {
4,980,950✔
1293
      SColumnNode*     pSColumnNode = (SColumnNode*)pNode;
4,846,489✔
1294
      SColumnInfoData* pColInfo = (SColumnInfoData*)taosArrayGet(pResBlock->pDataBlock, pSColumnNode->slotId);
4,846,489✔
1295
      QUERY_CHECK_NULL(pColInfo, code, lino, end, terrno);
4,841,209✔
1296
      code = colDataAssign(output.columnData, pColInfo, rows, NULL);
4,841,209✔
1297
    } else if (nodeType(pNode) == QUERY_NODE_VALUE) {
131,245✔
UNCOV
1298
      continue;
×
1299
    } else {
1300
      gTaskScalarExtra.pStreamInfo = NULL;
134,707✔
1301
      gTaskScalarExtra.pStreamRange = NULL;
134,707✔
1302
      code = scalarCalculate(pNode, pBlockList, &output, &gTaskScalarExtra);
134,707✔
1303
    }
1304

1305
    if (code != TSDB_CODE_SUCCESS) {
4,974,826✔
UNCOV
1306
      releaseColInfoData(output.columnData);
×
UNCOV
1307
      goto end;
×
1308
    }
1309

1310
    void* tmp = taosArrayPush(groupData, &output.columnData);
4,983,532✔
1311
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
4,983,532✔
1312
  }
1313

1314
  int32_t baseIdLen = gIdFromBaseId ? sizeof(int64_t) : 0;
4,573,341✔
1315
  int32_t keyLen = baseIdLen;
4,573,341✔
1316
  SNode*  node;
1317
  FOREACH(node, group) {
9,543,944✔
1318
    SExprNode* pExpr = (SExprNode*)node;
4,976,749✔
1319
    keyLen += pExpr->resType.bytes;
4,976,749✔
1320
  }
1321

1322
  int32_t nullFlagSize = sizeof(int8_t) * LIST_LENGTH(group);
4,565,119✔
1323
  keyLen += nullFlagSize;
4,563,419✔
1324

1325
  keyBuf = taosMemoryCalloc(1, keyLen);
4,563,419✔
1326
  if (keyBuf == NULL) {
4,565,837✔
UNCOV
1327
    code = terrno;
×
UNCOV
1328
    goto end;
×
1329
  }
1330

1331
  if (initRemainGroups) {
4,565,837✔
1332
    pTableListInfo->remainGroups =
2,090,846✔
1333
        taosHashInit(rows, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
2,079,402✔
1334
    if (pTableListInfo->remainGroups == NULL) {
2,091,510✔
UNCOV
1335
      code = terrno;
×
UNCOV
1336
      goto end;
×
1337
    }
1338
  }
1339

1340
  for (int i = 0; i < rows; i++) {
29,267,146✔
1341
    STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
24,693,721✔
1342
    QUERY_CHECK_NULL(info, code, lino, end, terrno);
24,697,044✔
1343

1344
    if (groupIdMap != NULL){
24,697,044✔
1345
      gInfo = taosArrayInit(taosArrayGetSize(groupData), sizeof(SStreamGroupValue));
83,573✔
1346
    }
1347

1348
    if (baseIdLen > 0) {
24,697,217✔
NEW
1349
      *(uint64_t*)keyBuf = info->baseGId;
×
1350
    }
1351
    char* isNull = (char*)keyBuf + baseIdLen;
24,697,217✔
1352
    char* pStart = (char*)keyBuf + baseIdLen + sizeof(int8_t) * LIST_LENGTH(group);
24,692,590✔
1353
    for (int j = 0; j < taosArrayGetSize(groupData); j++) {
51,137,173✔
1354
      SColumnInfoData* pValue = (SColumnInfoData*)taosArrayGetP(groupData, j);
26,435,274✔
1355

1356
      if (groupIdMap != NULL && gInfo != NULL) {
26,442,350✔
1357
        int32_t ret = buildGroupInfo(pValue, i, gInfo);
130,246✔
1358
        if (ret != TSDB_CODE_SUCCESS) {
130,419✔
UNCOV
1359
          qError("buildGroupInfo failed at line %d since %s", __LINE__, tstrerror(ret));
×
UNCOV
1360
          taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
×
UNCOV
1361
          gInfo = NULL;
×
1362
        }
1363
      }
1364
      
1365
      if (colDataIsNull_s(pValue, i)) {
52,879,137✔
1366
        isNull[j] = 1;
101,257✔
1367
      } else {
1368
        isNull[j] = 0;
26,335,357✔
1369
        char* data = colDataGetData(pValue, i);
26,335,575✔
1370
        if (pValue->info.type == TSDB_DATA_TYPE_JSON) {
26,335,063✔
1371
          // if (tTagIsJson(data)) {
1372
          //   code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
1373
          //   goto end;
1374
          // }
1375
          if (tTagIsJsonNull(data)) {
78,892✔
UNCOV
1376
            isNull[j] = 1;
×
UNCOV
1377
            continue;
×
1378
          }
1379
          int32_t len = getJsonValueLen(data);
78,892✔
1380
          memcpy(pStart, data, len);
78,892✔
1381
          pStart += len;
78,892✔
1382
        } else if (IS_VAR_DATA_TYPE(pValue->info.type)) {
26,253,346✔
1383
          if (IS_STR_DATA_BLOB(pValue->info.type)) {
22,500,312✔
1384
            if (blobDataTLen(data) > TSDB_MAX_BLOB_LEN) {
7,172✔
UNCOV
1385
              code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
UNCOV
1386
              goto end;
×
1387
            }
UNCOV
1388
            memcpy(pStart, data, blobDataTLen(data));
×
UNCOV
1389
            pStart += blobDataTLen(data);
×
1390
          } else {
1391
            if (varDataTLen(data) > pValue->info.bytes) {
22,511,123✔
1392
              code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
UNCOV
1393
              goto end;
×
1394
            }
1395
            memcpy(pStart, data, varDataTLen(data));
22,519,642✔
1396
            pStart += varDataTLen(data);
22,520,892✔
1397
          }
1398
        } else {
1399
          memcpy(pStart, data, pValue->info.bytes);
3,739,951✔
1400
          pStart += pValue->info.bytes;
3,746,959✔
1401
        }
1402
      }
1403
    }
1404

1405
    int32_t len = (int32_t)(pStart - (char*)keyBuf);
24,673,292✔
1406
    info->groupId = calcGroupId(keyBuf, len);
24,673,292✔
1407
    if (groupIdMap != NULL && gInfo != NULL) {
24,691,102✔
1408
      int32_t ret = taosHashPut(groupIdMap, &info->groupId, sizeof(info->groupId), &gInfo, POINTER_BYTES);
83,746✔
1409
      if (ret != TSDB_CODE_SUCCESS) {
83,746✔
UNCOV
1410
        qError("put groupid to map failed at line %d since %s", __LINE__, tstrerror(ret));
×
UNCOV
1411
        taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
×
1412
      }
1413
      qDebug("put groupid to map gid:%" PRIu64, info->groupId);
83,746✔
1414
      gInfo = NULL;
83,746✔
1415
    }
1416
    if (initRemainGroups) {
24,691,102✔
1417
      // groupId ~ table uid
1418
      code = taosHashPut(pTableListInfo->remainGroups, &(info->groupId), sizeof(info->groupId), &(info->uid),
11,915,567✔
1419
                         sizeof(info->uid));
1420
      if (code == TSDB_CODE_DUP_KEY) {
11,918,385✔
1421
        code = TSDB_CODE_SUCCESS;
808,386✔
1422
      }
1423
      QUERY_CHECK_CODE(code, lino, end);
11,918,385✔
1424
    }
1425
  }
1426

1427
  if (tsTagFilterCache && groupIdMap == NULL && digest) {
4,573,425✔
UNCOV
1428
    tableList = taosArrayDup(pTableListInfo->pTableList, NULL);
×
UNCOV
1429
    QUERY_CHECK_NULL(tableList, code, lino, end, terrno);
×
1430

UNCOV
1431
    code = pAPI->metaFn.metaPutTbGroupToCache(pVnode, pTableListInfo->idInfo.suid, context.digest,
×
1432
                                              tListLen(context.digest), tableList,
UNCOV
1433
                                              taosArrayGetSize(tableList) * sizeof(STableKeyInfo));
×
1434
    QUERY_CHECK_CODE(code, lino, end);
×
1435
  }
1436

1437
  //  int64_t st2 = taosGetTimestampUs();
1438
  //  qDebug("calculate tag block rows:%d, cost:%ld us", rows, st2-st1);
1439

1440
end:
4,573,551✔
1441
  taosMemoryFreeClear(keyBuf);
4,576,914✔
1442
  blockDataDestroy(pResBlock);
4,576,337✔
1443
  taosArrayDestroy(pBlockList);
4,574,632✔
1444
  taosArrayDestroyEx(pUidTagList, freeItem);
4,574,226✔
1445
  taosArrayDestroyP(groupData, releaseColInfoData);
4,576,354✔
1446
  taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
4,570,176✔
1447

1448
  if (code != TSDB_CODE_SUCCESS) {
4,570,667✔
UNCOV
1449
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1450
  }
1451
  return code;
4,572,265✔
1452
}
1453

1454
static int32_t nameComparFn(const void* p1, const void* p2) {
1,943,715✔
1455
  const char* pName1 = *(const char**)p1;
1,943,715✔
1456
  const char* pName2 = *(const char**)p2;
1,944,270✔
1457

1458
  int32_t ret = strcmp(pName1, pName2);
1,940,949✔
1459
  if (ret == 0) {
1,940,949✔
1460
    return 0;
14,913✔
1461
  } else {
1462
    return (ret > 0) ? 1 : -1;
1,926,036✔
1463
  }
1464
}
1465

1466
static SArray* getTableNameList(const SNodeListNode* pList) {
1,004,309✔
1467
  int32_t    code = TSDB_CODE_SUCCESS;
1,004,309✔
1468
  int32_t    lino = 0;
1,004,309✔
1469
  int32_t    len = LIST_LENGTH(pList->pNodeList);
1,004,309✔
1470
  SListCell* cell = pList->pNodeList->pHead;
1,003,754✔
1471

1472
  SArray* pTbList = taosArrayInit(len, POINTER_BYTES);
1,004,309✔
1473
  QUERY_CHECK_NULL(pTbList, code, lino, _end, terrno);
1,004,309✔
1474

1475
  for (int i = 0; i < pList->pNodeList->length; i++) {
2,925,429✔
1476
    SValueNode* valueNode = (SValueNode*)cell->pNode;
1,920,010✔
1477
    if (!IS_VAR_DATA_TYPE(valueNode->node.resType.type)) {
1,920,565✔
UNCOV
1478
      terrno = TSDB_CODE_INVALID_PARA;
×
UNCOV
1479
      taosArrayDestroy(pTbList);
×
UNCOV
1480
      return NULL;
×
1481
    }
1482

1483
    char* name = varDataVal(valueNode->datum.p);
1,920,565✔
1484
    void* tmp = taosArrayPush(pTbList, &name);
1,920,019✔
1485
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,920,019✔
1486
    cell = cell->pNext;
1,920,019✔
1487
  }
1488

1489
  size_t numOfTables = taosArrayGetSize(pTbList);
1,004,864✔
1490

1491
  // order the name
1492
  taosArraySort(pTbList, nameComparFn);
1,004,864✔
1493

1494
  // remove the duplicates
1495
  SArray* pNewList = taosArrayInit(taosArrayGetSize(pTbList), sizeof(void*));
1,004,309✔
1496
  QUERY_CHECK_NULL(pNewList, code, lino, _end, terrno);
1,004,864✔
1497
  void* tmpTbl = taosArrayGet(pTbList, 0);
1,004,864✔
1498
  QUERY_CHECK_NULL(tmpTbl, code, lino, _end, terrno);
1,004,864✔
1499
  void* tmp = taosArrayPush(pNewList, tmpTbl);
1,004,309✔
1500
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,004,309✔
1501

1502
  for (int32_t i = 1; i < numOfTables; ++i) {
1,920,019✔
1503
    char** name = taosArrayGetLast(pNewList);
915,701✔
1504
    char** nameInOldList = taosArrayGet(pTbList, i);
915,710✔
1505
    QUERY_CHECK_NULL(nameInOldList, code, lino, _end, terrno);
915,710✔
1506
    if (strcmp(*name, *nameInOldList) == 0) {
915,710✔
1507
      continue;
7,792✔
1508
    }
1509

1510
    tmp = taosArrayPush(pNewList, nameInOldList);
907,918✔
1511
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
907,918✔
1512
  }
1513

1514
_end:
1,004,318✔
1515
  taosArrayDestroy(pTbList);
1,004,318✔
1516
  if (code != TSDB_CODE_SUCCESS) {
1,003,754✔
UNCOV
1517
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
1518
    return NULL;
×
1519
  }
1520
  return pNewList;
1,003,859✔
1521
}
1522

1523
static int tableUidCompare(const void* a, const void* b) {
×
1524
  uint64_t u1 = *(uint64_t*)a;
×
UNCOV
1525
  uint64_t u2 = *(uint64_t*)b;
×
1526

UNCOV
1527
  if (u1 == u2) {
×
UNCOV
1528
    return 0;
×
1529
  }
1530

1531
  return u1 < u2 ? -1 : 1;
×
1532
}
1533

1534
static int32_t filterTableInfoCompare(const void* a, const void* b) {
343,050✔
1535
  STUidTagInfo* p1 = (STUidTagInfo*)a;
343,050✔
1536
  STUidTagInfo* p2 = (STUidTagInfo*)b;
343,050✔
1537

1538
  if (p1->uid == p2->uid) {
343,050✔
UNCOV
1539
    return 0;
×
1540
  }
1541

1542
  return p1->uid < p2->uid ? -1 : 1;
343,050✔
1543
}
1544

1545
static FilterCondType checkTagCond(SNode* cond) {
16,396,226✔
1546
  if (nodeType(cond) == QUERY_NODE_OPERATOR) {
16,396,226✔
1547
    return FILTER_NO_LOGIC;
11,988,081✔
1548
  }
1549
  if (nodeType(cond) == QUERY_NODE_LOGIC_CONDITION && ((SLogicConditionNode*)cond)->condType == LOGIC_COND_TYPE_AND) {
4,422,305✔
1550
    return FILTER_AND;
3,840,092✔
1551
  }
1552
  return FILTER_OTHER;
576,358✔
1553
}
1554

1555
static int32_t doInWithAnd(SNode* cond, void* pVnode, SArray* list, SStorageAPI* pAPI, uint64_t suid) {
4,428,667✔
1556
  if (nodeType(cond) != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) {
4,428,667✔
1557
    return -1;
576,750✔
1558
  }
1559

1560
  SLogicConditionNode* pNode = (SLogicConditionNode*)cond;
3,846,435✔
1561
  SNodeList*           pList = (SNodeList*)pNode->pParameterList;
3,846,435✔
1562

1563
  int32_t len = LIST_LENGTH(pList);
3,847,140✔
1564
  if (len <= 0) {
3,848,273✔
UNCOV
1565
    return -1;
×
1566
  }
1567

1568
  SListCell* cell = pList->pHead;
3,848,273✔
1569
  for (int i = 0; i < len; i++) {
11,931,534✔
1570
    if (cell == NULL) break;
8,090,307✔
1571
    if (nodeType(cell->pNode) == QUERY_NODE_OPERATOR && optimizeTbnameInCondImpl(pVnode, list, cell->pNode, pAPI, suid) == 0) {
8,090,307✔
1572
      return 0;
8,059✔
1573
    }
1574
    cell = cell->pNext;
8,081,465✔
1575
  }
1576
  return -1;
3,841,227✔
1577
}
1578

1579
static int32_t optimizeTbnameInCond(void* pVnode, int64_t suid, SArray* list, SNode* cond, SStorageAPI* pAPI) {
17,415,581✔
1580
  int32_t code = 0;
17,415,581✔
1581
  int32_t lino = 0;
17,415,581✔
1582
  if (nodeType(cond) == QUERY_NODE_OPERATOR) {
17,415,581✔
1583
    code = optimizeTbnameInCondImpl(pVnode, list, cond, pAPI, suid);
12,988,837✔
1584
  } else {
1585
    code = doInWithAnd(cond, pVnode, list, pAPI, suid);
4,429,687✔
1586
    QUERY_CHECK_CODE(code, lino, end);
4,428,102✔
1587
    code = pAPI->metaFn.getTableTagsByUid(pVnode, suid, list);
8,443✔
1588
  }
1589
  
1590
end:
17,404,634✔
1591
  return code;
17,404,634✔
1592
}
1593

1594
static int32_t getTableListInInOperator(void* pVnode, SArray* pExistedUidList, SNodeListNode* pList, SStorageAPI* pStoreAPI,
1,004,309✔
1595
                                        uint64_t suid) {
1596
  int32_t   code = 0;                                          
1,004,309✔
1597
  SArray*   pTbList = getTableNameList(pList);
1,004,309✔
1598
  int32_t   numOfTables = taosArrayGetSize(pTbList);
1,003,763✔
1599
  SHashObj* uHash = NULL;
1,003,763✔
1600

1601
  size_t numOfExisted = taosArrayGetSize(pExistedUidList);  // len > 0 means there already have uids
1,003,763✔
1602
  if (numOfExisted > 0) {
1,003,763✔
1603
    uHash = taosHashInit(numOfExisted / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
2,150✔
1604
    if (!uHash) {
2,150✔
UNCOV
1605
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
1606
      code = terrno;
×
UNCOV
1607
      goto end;
×
1608
    }
1609

1610
    for (int i = 0; i < numOfExisted; i++) {
2,147,851✔
1611
      STUidTagInfo* pTInfo = taosArrayGet(pExistedUidList, i);
2,145,701✔
1612
      if (!pTInfo) {
2,146,775✔
1613
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
1614
        code = terrno;
×
UNCOV
1615
        goto end;
×
1616
      }
1617
      code = taosHashPut(uHash, &pTInfo->uid, sizeof(uint64_t), &i, sizeof(i));
2,146,775✔
1618
      if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_DUP_KEY) {
2,145,701✔
1619
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1620
        goto end;
×
1621
      }
1622
    }
1623
  }
1624
  taosArrayClear(pExistedUidList);
1,003,763✔
1625

1626
  for (int i = 0; i < numOfTables; i++) {
2,917,196✔
1627
    char* name = taosArrayGetP(pTbList, i);
1,911,314✔
1628
    uint64_t uid = 0, csuid = 0;
1,912,227✔
1629
    if (pStoreAPI->metaFn.getTableUidByName(pVnode, name, &uid) != 0) {
1,912,227✔
1630
      continue;
1,310,061✔
1631
    }
1632

1633
    ETableType tbType = TSDB_TABLE_MAX;
603,267✔
1634
    if (pStoreAPI->metaFn.getTableTypeSuidByName(pVnode, name, &tbType, &csuid) == 0 &&
603,267✔
1635
        (tbType == TSDB_CHILD_TABLE || tbType == TSDB_VIRTUAL_CHILD_TABLE) &&
602,804✔
1636
        csuid == suid) {
596,759✔
1637
      if (NULL == uHash || taosHashGet(uHash, &uid, sizeof(uid)) != NULL) {
594,148✔
1638
        STUidTagInfo s = {.uid = uid, .name = name, .pTagVal = NULL};
593,536✔
1639
        void*        tmp = taosArrayPush(pExistedUidList, &s);
593,999✔
1640
        if (!tmp) {
593,999✔
UNCOV
1641
          code = terrno;
×
UNCOV
1642
          goto end;
×
1643
        }
1644
      }
1645
    } 
1646
  }
1647
  taosArraySort(pExistedUidList, filterTableInfoCompare);
1,005,882✔
1648
  taosArrayRemoveDuplicate(pExistedUidList, filterTableInfoCompare, NULL);
1,004,864✔
1649
end:
1,004,864✔
1650
  taosArrayDestroy(pTbList);
1,004,864✔
1651
  taosHashCleanup(uHash);
1,004,414✔
1652
  return code;
1,004,414✔
1653
}
1654

1655
// only return uid that does not contained in pExistedUidList
1656
static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* pExistedUidList, SNode* pTagCond, SStorageAPI* pStoreAPI,
21,086,231✔
1657
                                        uint64_t suid) {
1658
  SOperatorNode* pNode = (SOperatorNode*)pTagCond;
21,086,231✔
1659
  if (pNode->opType != OP_TYPE_IN) {
21,086,231✔
1660
    return -1;
18,336,636✔
1661
  }
1662

1663
  if ((pNode->pLeft != NULL && ((nodeType(pNode->pLeft) == QUERY_NODE_FUNCTION &&
2,740,543✔
1664
                                 ((SFunctionNode*)pNode->pLeft)->funcType == FUNCTION_TYPE_TBNAME)) ||
1,007,076✔
1665
       (nodeType(pNode->pLeft) == QUERY_NODE_COLUMN && ((SColumnNode*)pNode->pLeft)->colType == COLUMN_TYPE_TBNAME)) &&
1,732,512✔
1666
      (pNode->pRight != NULL && nodeType(pNode->pRight) == QUERY_NODE_NODE_LIST)) {
1,005,045✔
1667
    SNodeListNode* pList = (SNodeListNode*)pNode->pRight;
1,004,864✔
1668

1669
    int32_t len = LIST_LENGTH(pList->pNodeList);
1,003,754✔
1670
    if (len <= 0) {
1,004,309✔
UNCOV
1671
      return -1;
×
1672
    }
1673

1674
    return getTableListInInOperator(pVnode, pExistedUidList, pList, pStoreAPI, suid);
1,004,309✔
1675
  }
1676

1677
  return -1;
1,737,344✔
1678
}
1679

1680
SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, void* pVnode,
19,385,816✔
1681
                                        SStorageAPI* pStorageAPI) {
1682
  int32_t      code = TSDB_CODE_SUCCESS;
19,385,816✔
1683
  int32_t      lino = 0;
19,385,816✔
1684
  SSDataBlock* pResBlock = NULL;
19,385,816✔
1685
  code = createDataBlock(&pResBlock);
19,400,891✔
1686
  QUERY_CHECK_CODE(code, lino, _end);
19,370,984✔
1687

1688
  for (int32_t i = 0; i < taosArrayGetSize(pColList); ++i) {
40,594,093✔
1689
    SColumnInfoData colInfo = {0};
21,239,376✔
1690
    void*           tmp = taosArrayGet(pColList, i);
21,226,811✔
1691
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
21,165,948✔
1692
    colInfo.info = *(SColumnInfo*)tmp;
21,165,948✔
1693
    code = blockDataAppendColInfo(pResBlock, &colInfo);
21,163,078✔
1694
    QUERY_CHECK_CODE(code, lino, _end);
21,205,417✔
1695
  }
1696

1697
  code = blockDataEnsureCapacity(pResBlock, numOfTables);
19,380,949✔
1698
  if (code != TSDB_CODE_SUCCESS) {
19,343,254✔
UNCOV
1699
    terrno = code;
×
UNCOV
1700
    blockDataDestroy(pResBlock);
×
UNCOV
1701
    return NULL;
×
1702
  }
1703

1704
  pResBlock->info.rows = numOfTables;
19,343,254✔
1705

1706
  int32_t numOfCols = taosArrayGetSize(pResBlock->pDataBlock);
19,342,630✔
1707

1708
  for (int32_t i = 0; i < numOfTables; i++) {
233,356,134✔
1709
    STUidTagInfo* p1 = taosArrayGet(pUidTagList, i);
213,927,959✔
1710
    QUERY_CHECK_NULL(p1, code, lino, _end, terrno);
213,941,452✔
1711

1712
    for (int32_t j = 0; j < numOfCols; j++) {
437,976,198✔
1713
      SColumnInfoData* pColInfo = (SColumnInfoData*)taosArrayGet(pResBlock->pDataBlock, j);
223,849,684✔
1714
      QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
223,763,036✔
1715

1716
      if (pColInfo->info.colId == -1) {  // tbname
223,763,036✔
1717
        char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
7,629,597✔
1718
        if (p1->name != NULL) {
7,633,744✔
1719
          STR_TO_VARSTR(str, p1->name);
5,910✔
1720
        } else {  // name is not retrieved during filter
1721
          code = pStorageAPI->metaFn.getTableNameByUid(pVnode, p1->uid, str);
7,629,075✔
1722
          QUERY_CHECK_CODE(code, lino, _end);
7,620,351✔
1723
        }
1724

1725
        code = colDataSetVal(pColInfo, i, str, false);
7,625,986✔
1726
        QUERY_CHECK_CODE(code, lino, _end);
7,635,031✔
1727
#if TAG_FILTER_DEBUG
1728
        qDebug("tagfilter uid:%ld, tbname:%s", *uid, str + 2);
1729
#endif
1730
      } else {
1731
        STagVal tagVal = {0};
216,072,193✔
1732
        tagVal.cid = pColInfo->info.colId;
216,189,201✔
1733
        if (p1->pTagVal == NULL) {
216,207,133✔
UNCOV
1734
          colDataSetNULL(pColInfo, i);
×
1735
        } else {
1736
          const char* p = pStorageAPI->metaFn.extractTagVal(p1->pTagVal, pColInfo->info.type, &tagVal);
216,171,543✔
1737

1738
          if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) {
216,210,796✔
1739
            colDataSetNULL(pColInfo, i);
2,216,300✔
1740
          } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) {
213,995,227✔
1741
            code = colDataSetVal(pColInfo, i, p, false);
623,725✔
1742
            QUERY_CHECK_CODE(code, lino, _end);
623,725✔
1743
          } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
354,521,964✔
1744
            if (IS_STR_DATA_BLOB(pColInfo->info.type)) {
140,916,720✔
UNCOV
1745
              QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_TAG, lino, _end);
×
1746
            }
1747
            char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1);
141,067,718✔
1748
            QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
141,174,397✔
1749
            varDataSetLen(tmp, tagVal.nData);
141,174,397✔
1750
            memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData);
141,176,872✔
1751
            code = colDataSetVal(pColInfo, i, tmp, false);
141,175,645✔
1752
#if TAG_FILTER_DEBUG
1753
            qDebug("tagfilter varch:%s", tmp + 2);
1754
#endif
1755
            taosMemoryFree(tmp);
141,213,979✔
1756
            QUERY_CHECK_CODE(code, lino, _end);
141,183,550✔
1757
          } else {
1758
            code = colDataSetVal(pColInfo, i, (const char*)&tagVal.i64, false);
72,339,718✔
1759
            QUERY_CHECK_CODE(code, lino, _end);
72,387,438✔
1760
#if TAG_FILTER_DEBUG
1761
            if (pColInfo->info.type == TSDB_DATA_TYPE_INT) {
1762
              qDebug("tagfilter int:%d", *(int*)(&tagVal.i64));
1763
            } else if (pColInfo->info.type == TSDB_DATA_TYPE_DOUBLE) {
1764
              qDebug("tagfilter double:%f", *(double*)(&tagVal.i64));
1765
            }
1766
#endif
1767
          }
1768
        }
1769
      }
1770
    }
1771
  }
1772

1773
_end:
19,408,853✔
1774
  if (code != TSDB_CODE_SUCCESS) {
19,429,353✔
1775
    blockDataDestroy(pResBlock);
24,187✔
1776
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
275✔
1777
    terrno = code;
275✔
1778
    return NULL;
275✔
1779
  }
1780
  return pResBlock;
19,405,166✔
1781
}
1782

1783
static int32_t doSetQualifiedUid(SArray* pUidList, const SArray* pUidTagList, SColumnInfoData* colData) {
17,334,511✔
1784
  taosArrayClear(pUidList);
17,334,511✔
1785

1786
  int32_t       numOfTables = taosArrayGetSize(pUidTagList);
17,317,909✔
1787
  bool* pResultList = colData == NULL ? NULL : (bool*)colData->pData;
17,323,701✔
1788
  for (int32_t i = 0; i < numOfTables; ++i) {
204,547,956✔
1789
    if (pResultList != NULL && !pResultList[i]) {
187,118,027✔
1790
       continue;
106,295,007✔
1791
    }
1792
    STUidTagInfo* tmpTag = (STUidTagInfo*)taosArrayGet(pUidTagList, i);
80,886,114✔
1793
    if (!tmpTag) {
80,842,086✔
UNCOV
1794
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
1795
      return terrno;
×
1796
    }
1797
    uint64_t uid = tmpTag->uid;
80,842,086✔
1798
    qDebug("tagfilter get uid:%" PRId64, uid);
80,870,741✔
1799

1800
    void* tmp = taosArrayPush(pUidList, &uid);
80,946,079✔
1801
    if (tmp == NULL) {
80,946,079✔
UNCOV
1802
      return terrno;
×
1803
    }
1804
  }
1805

1806
  return TSDB_CODE_SUCCESS;
17,429,929✔
1807
}
1808

1809
static int32_t copyExistedUids(SArray* pUidTagList, const SArray* pUidList) {
17,415,968✔
1810
  int32_t code = TSDB_CODE_SUCCESS;
17,415,968✔
1811
  int32_t numOfExisted = taosArrayGetSize(pUidList);
17,415,968✔
1812
  if (numOfExisted == 0) {
17,416,267✔
1813
    return code;
14,661,308✔
1814
  }
1815

1816
  for (int32_t i = 0; i < numOfExisted; ++i) {
31,187,536✔
1817
    uint64_t* uid = taosArrayGet(pUidList, i);
28,430,681✔
1818
    if (!uid) {
28,431,424✔
UNCOV
1819
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
1820
      return terrno;
×
1821
    }
1822
    STUidTagInfo info = {.uid = *uid};
28,431,424✔
1823
    void*        tmp = taosArrayPush(pUidTagList, &info);
28,432,049✔
1824
    if (!tmp) {
28,432,049✔
1825
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1826
      return code;
×
1827
    }
1828
  }
1829
  return code;
2,756,855✔
1830
}
1831

1832
static EDealRes getCids(SNode** pNode, void* pContext) {
6,570✔
1833
  SHashObj* colHash = (SHashObj*)pContext;
6,570✔
1834
  col_id_t colId = 0;
6,570✔
1835
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
6,570✔
1836
    colId = (*(SColumnNode**)pNode)->colId;
2,190✔
1837
  } else {
1838
    return DEAL_RES_CONTINUE;
4,380✔
1839
  }
1840

1841
  int32_t tempRes = taosHashPut(colHash, &colId, sizeof(colId), pNode, sizeof((*pNode)));
2,190✔
1842
  if (tempRes != TSDB_CODE_SUCCESS ) {
2,190✔
UNCOV
1843
    return DEAL_RES_ERROR;
×
1844
  }
1845

1846
  return DEAL_RES_CONTINUE;
2,190✔
1847
}
1848

1849
SNode* getTagCondNodeForQueryTmq(void* tinfo) {
693✔
1850
  SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
693✔
1851
  const char*    id = GET_TASKID(pTaskInfo);
693✔
1852
  int32_t        code = 0;
693✔
1853

1854
  // traverse to the stream scanner node to add this table id
1855
  SOperatorInfo* pInfo = NULL;
693✔
1856
  code = extractOperatorInTree(pTaskInfo->pRoot, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, id, &pInfo);
693✔
1857
  if (code != 0 || pInfo == NULL) {
693✔
UNCOV
1858
    return NULL;
×
1859
  }
1860

1861
  STmqQueryScanInfo* pScanInfo = pInfo->info;
693✔
1862
  return pScanInfo->pTagCond;
693✔
1863
}
1864

1865
SNode* getTagCondNodeForStableTmq(void* node) {
2,190✔
1866
  return node == NULL ? NULL : ((SSubplan*)node)->pTagCond;
2,190✔
1867
}
1868

1869
bool checkCidInTagCondition(SNode* pTagCond, SArray* cidList) {
2,883✔
1870
  if (pTagCond == NULL) { 
2,883✔
1871
    return false;
693✔
1872
  }
1873
  bool result = true;
2,190✔
1874
  SHashObj *colHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), true, HASH_NO_LOCK);
2,190✔
1875
  if (colHash == NULL) {
2,190✔
UNCOV
1876
    goto end;
×
1877
  }
1878

1879
  nodesRewriteExprPostOrder(&pTagCond, getCids, (void*)colHash);
2,190✔
1880
  if (cidList != NULL) {
2,190✔
UNCOV
1881
    int32_t numOfCols = taosArrayGetSize(cidList);
×
1882
    int32_t i = 0;
×
UNCOV
1883
    for (; i < numOfCols; ++i) {
×
UNCOV
1884
      col_id_t* pCid = taosArrayGet(cidList, i);
×
UNCOV
1885
      void* data = taosHashGet(colHash, pCid, sizeof(*pCid));
×
UNCOV
1886
      if (data != NULL) break;
×
1887
    }
1888
    if (i == numOfCols) { // no tag column involved in condition
×
1889
      result = false;
×
1890
      goto end;
×
1891
    }
1892
  }
1893

1894
end:
2,190✔
1895
  taosHashCleanup(colHash);
2,190✔
1896
  return result;
2,190✔
1897
}
1898

1899
int32_t doFilterByTagCond(int64_t suid, SArray* pUidList, SNode* pTagCond, void* pVnode,
280,871,553✔
1900
                                 SIdxFltStatus status, SStorageAPI* pAPI, void* pStreamInfo) {
1901
  if (pTagCond == NULL) {
280,871,553✔
1902
    return TSDB_CODE_SUCCESS;
263,450,890✔
1903
  }
1904

1905
  terrno = TSDB_CODE_SUCCESS;
17,420,663✔
1906

1907
  int32_t      lino = 0;
17,418,366✔
1908
  int32_t      code = TSDB_CODE_SUCCESS;
17,418,366✔
1909
  SArray*      pBlockList = NULL;
17,418,366✔
1910
  SSDataBlock* pResBlock = NULL;
17,418,366✔
1911
  SScalarParam output = {0};
17,413,568✔
1912
  SArray*      pUidTagList = NULL;
17,407,962✔
1913

1914
  SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
17,407,962✔
1915

1916
  pUidTagList = taosArrayInit(10, sizeof(STUidTagInfo));
17,398,626✔
1917
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
17,391,807✔
1918

1919
  // pUidList size is 0 if tagIndex is NULL and in query condition
1920
  code = copyExistedUids(pUidTagList, pUidList);
17,391,807✔
1921
  QUERY_CHECK_CODE(code, lino, end);
17,400,774✔
1922

1923
  // Narrow down the scope of the tablelist set if there is tbname in condition and And Logical operator
1924
  code = optimizeTbnameInCond(pVnode, suid, pUidTagList, pTagCond, pAPI);
17,400,774✔
1925
  if (code == 0) {
17,399,268✔
1926
    if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
1,004,864✔
1927
      goto end;
996,355✔
1928
    }
1929
  } else {
1930
    qDebug("pUidTagList size:%d", (int32_t)taosArrayGetSize(pUidTagList));
16,394,404✔
1931

1932
    FilterCondType condType = checkTagCond(pTagCond);
16,396,722✔
1933
    if (((condType == FILTER_NO_LOGIC || condType == FILTER_AND) && status != SFLT_NOT_INDEX) || // (super table) use tagIndex and operator is and
16,396,081✔
1934
        (status == SFLT_NOT_INDEX && taosArrayGetSize(pUidTagList) > 0)) {                       // (child table with tagCond)
16,398,329✔
1935
      code = pAPI->metaFn.getTableTagsByUid(pVnode, suid, pUidTagList);
2,753,741✔
1936
    } else {
1937
      taosArrayClearEx(pUidTagList, freeItem);       // clear tablelist if using tagIndex and or condition
13,646,874✔
1938
      code = pAPI->metaFn.getTableTags(pVnode, suid, pUidTagList);
13,640,634✔
1939
    }
1940
    if (code != TSDB_CODE_SUCCESS) {
16,397,465✔
UNCOV
1941
      qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code),suid);
×
UNCOV
1942
      terrno = code;
×
UNCOV
1943
      QUERY_CHECK_CODE(code, lino, end);
×
1944
    }
1945
  }
1946

1947
  qDebug("final pUidTagList size:%d", (int32_t)taosArrayGetSize(pUidTagList));
16,405,974✔
1948

1949
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
16,416,498✔
1950
  if (numOfTables == 0) {
16,415,775✔
1951
    goto end;
3,348,870✔
1952
  }
1953

1954
  SArray* pColList = NULL;
13,066,905✔
1955
  code = qGetColumnsFromNodeList(pTagCond, false, &pColList); 
13,069,434✔
1956
  if (code != TSDB_CODE_SUCCESS) {
13,016,691✔
UNCOV
1957
    goto end;
×
1958
  }
1959
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
13,016,691✔
1960
  taosArrayDestroy(pColList);
13,046,624✔
1961
  if (pResBlock == NULL) {
13,055,670✔
UNCOV
1962
    code = terrno;
×
1963
    QUERY_CHECK_CODE(code, lino, end);
×
1964
  }
1965

1966
  //fprintDataBlock(pResBlock, "tagFilter", "", 0);
1967

1968
  //  int64_t st1 = taosGetTimestampUs();
1969
  //  qDebug("generate tag block rows:%d, cost:%ld us", rows, st1-st);
1970
  pBlockList = taosArrayInit(2, POINTER_BYTES);
13,055,670✔
1971
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
13,054,490✔
1972

1973
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
13,070,723✔
1974
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
13,070,723✔
1975

1976
  code = createResultData(&type, numOfTables, &output);
13,070,723✔
1977
  if (code != TSDB_CODE_SUCCESS) {
13,026,444✔
UNCOV
1978
    terrno = code;
×
UNCOV
1979
    QUERY_CHECK_CODE(code, lino, end);
×
1980
  }
1981

1982
  gTaskScalarExtra.pStreamInfo = pStreamInfo;
13,026,444✔
1983
  gTaskScalarExtra.pStreamRange = NULL;
13,026,444✔
1984
  code = scalarCalculate(pTagCond, pBlockList, &output, &gTaskScalarExtra);
12,981,678✔
1985
  if (code != TSDB_CODE_SUCCESS) {
12,975,347✔
1986
    qError("failed to calculate scalar, reason:%s", tstrerror(code));
968✔
1987
    terrno = code;
968✔
1988
    QUERY_CHECK_CODE(code, lino, end);
968✔
1989
  }
1990

1991
end:
17,320,572✔
1992
  if (code == 0) {
17,377,602✔
1993
    code = doSetQualifiedUid(pUidList, pUidTagList, output.columnData);
17,383,510✔
1994
    lino = __LINE__;
17,412,741✔
1995
  }
1996
  
1997
  if (code != 0) {
17,406,833✔
1998
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
968✔
1999
  }
2000
  blockDataDestroy(pResBlock);
17,406,833✔
2001
  taosArrayDestroy(pBlockList);
17,380,304✔
2002
  taosArrayDestroyEx(pUidTagList, freeItem);
17,380,089✔
2003

2004
  colDataDestroy(output.columnData);
17,399,338✔
2005
  taosMemoryFreeClear(output.columnData);
17,388,830✔
2006
  return code;
17,386,359✔
2007
}
2008

2009
typedef struct {
2010
  int32_t code;
2011
  SStreamRuntimeFuncInfo* pStreamRuntimeInfo;
2012
} PlaceHolderContext;
2013

2014
static EDealRes replacePlaceHolderColumn(SNode** pNode, void* pContext) {
80,307✔
2015
  PlaceHolderContext* pData = (PlaceHolderContext*)pContext;
80,307✔
2016
  if (QUERY_NODE_FUNCTION != nodeType((*pNode))) {
80,307✔
2017
    return DEAL_RES_CONTINUE;
66,140✔
2018
  }
2019
  SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
14,167✔
2020
  if (!fmIsStreamPesudoColVal(pFuncNode->funcId)) {
14,167✔
2021
    return DEAL_RES_CONTINUE;
546✔
2022
  }
2023
  pData->code = fmSetStreamPseudoFuncParamVal(pFuncNode->funcId, pFuncNode->pParameterList, pData->pStreamRuntimeInfo);
13,621✔
2024
  if (pData->code != TSDB_CODE_SUCCESS) {
13,621✔
UNCOV
2025
    return DEAL_RES_ERROR;
×
2026
  }
2027
  SNode* pFirstParam = nodesListGetNode(pFuncNode->pParameterList, 0);
13,621✔
2028
  ((SValueNode*)pFirstParam)->translate = true;
13,621✔
2029
  SValueNode* res = NULL;
13,621✔
2030
  pData->code = nodesCloneNode(pFirstParam, (SNode**)&res);
13,621✔
2031
  if (NULL == res) {
13,621✔
UNCOV
2032
    return DEAL_RES_ERROR;
×
2033
  }
2034
  nodesDestroyNode(*pNode);
13,621✔
2035
  *pNode = (SNode*)res;
13,621✔
2036

2037
  return DEAL_RES_CONTINUE;
13,621✔
2038
}
2039

2040
static void extractTagColId(SOperatorNode* pOpNode, SArray* pColIdArray) {
21,798✔
2041
  SNode* pLeft = pOpNode->pLeft;
21,798✔
2042
  SNode* pRight = pOpNode->pRight;
21,798✔
2043
  SColumnNode* pColNode = nodeType(pLeft) == QUERY_NODE_COLUMN ?
21,798✔
2044
    (SColumnNode*)pLeft : (SColumnNode*)pRight;
21,798✔
2045

2046
  col_id_t colId = pColNode->colId;
21,798✔
2047
  void* _tmp = taosArrayPush(pColIdArray, &colId);
21,798✔
2048
}
21,798✔
2049

2050
static int32_t buildTagCondKey(
10,899✔
2051
  const SNode* pTagCond, char** pTagCondKey,
2052
  int32_t* tagCondKeyLen, SArray** pTagColIds) {
2053
  if (NULL == pTagCond ||
10,899✔
2054
    (nodeType(pTagCond) != QUERY_NODE_OPERATOR &&
10,899✔
2055
      nodeType(pTagCond) != QUERY_NODE_LOGIC_CONDITION)) {
10,899✔
UNCOV
2056
    qError("invalid parameter to extract tag filter symbol");
×
UNCOV
2057
    return TSDB_CODE_INTERNAL_ERROR;
×
2058
  }
2059
  int32_t code = TSDB_CODE_SUCCESS;
10,899✔
2060
  int32_t lino = 0;
10,899✔
2061
  *pTagColIds = taosArrayInit(4, sizeof(col_id_t));
10,899✔
2062

2063
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
10,899✔
UNCOV
2064
    extractTagColId((SOperatorNode*)pTagCond, *pTagColIds);
×
2065
  } else if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION) {
10,899✔
2066
    SNode* pChild = NULL;
10,899✔
2067
    FOREACH(pChild, ((SLogicConditionNode*)pTagCond)->pParameterList) {
32,697✔
2068
      extractTagColId((SOperatorNode*)pChild, *pTagColIds);
21,798✔
2069
    }
2070
  }
2071

2072
  taosArraySort(*pTagColIds, compareUint16Val);
10,899✔
2073

2074
  // encode ordered colIds into key string, separated by ','
2075
  *tagCondKeyLen =
21,798✔
2076
    (int32_t)(taosArrayGetSize(*pTagColIds) * (sizeof(col_id_t) + 1) - 1);
10,899✔
2077
  *pTagCondKey = (char*)taosMemoryCalloc(1, *tagCondKeyLen);
10,899✔
2078
  TSDB_CHECK_NULL(*pTagCondKey, code, lino, _end, terrno);
10,899✔
2079
  char* pStart = *pTagCondKey;
10,899✔
2080
  for (int32_t i = 0; i < taosArrayGetSize(*pTagColIds); ++i) {
32,697✔
2081
    col_id_t* pColId = (col_id_t*)taosArrayGet(*pTagColIds, i);
21,798✔
2082
    TSDB_CHECK_NULL(pColId, code, lino, _end, terrno);
21,798✔
2083
    memcpy(pStart, pColId, sizeof(col_id_t));
21,798✔
2084
    pStart += sizeof(col_id_t);
21,798✔
2085
    if (i != taosArrayGetSize(*pTagColIds) - 1) {
21,798✔
2086
      *pStart = ',';
10,899✔
2087
      pStart += 1;
10,899✔
2088
    }
2089
  }
2090

2091
_end:
10,899✔
2092
  if (TSDB_CODE_SUCCESS != code) {
10,899✔
UNCOV
2093
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
2094
    terrno = code;
×
2095
  }
2096
  return code;
10,899✔
2097
}
2098

2099
static EDealRes canOptimizeTagCondFilter(SNode* pTagCond, void* pContext) {
100,686✔
2100
  if (NULL == pTagCond) {
100,686✔
UNCOV
2101
    *(bool*)pContext = false;
×
UNCOV
2102
    return DEAL_RES_END;
×
2103
  }
2104
  if (nodeType(pTagCond) == QUERY_NODE_VALUE ||
100,686✔
2105
    nodeType(pTagCond) == QUERY_NODE_COLUMN) {
66,778✔
2106
    return DEAL_RES_CONTINUE;
55,879✔
2107
  }
2108
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR &&
44,807✔
2109
    ((SOperatorNode*)pTagCond)->opType == OP_TYPE_EQUAL) {
22,317✔
2110
    return DEAL_RES_CONTINUE;
21,798✔
2111
  }
2112
  if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION &&
23,528✔
2113
    ((SLogicConditionNode*)pTagCond)->condType == LOGIC_COND_TYPE_AND) {
10,899✔
2114
    return DEAL_RES_CONTINUE;
10,726✔
2115
  }
2116
  if (nodeType(pTagCond) == QUERY_NODE_FUNCTION &&
25,085✔
2117
    fmIsStreamPesudoColVal(((SFunctionNode*)pTagCond)->funcId)) {
12,283✔
2118
    return DEAL_RES_CONTINUE;
12,110✔
2119
  }
2120
  *(bool*)pContext = false;
519✔
2121
  return DEAL_RES_END;
519✔
2122
}
2123

2124
int32_t getTableList(void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond,
280,568,524✔
2125
                     STableListInfo* pListInfo, uint8_t* digest, const char* idstr, SStorageAPI* pStorageAPI, void* pStreamInfo) {
2126
  int32_t code = TSDB_CODE_SUCCESS;
280,568,524✔
2127
  int32_t lino = 0;
280,568,524✔
2128
  size_t  numOfTables = 0;
280,568,524✔
2129

2130
  pListInfo->idInfo.suid = pScanNode->suid;
280,568,524✔
2131
  pListInfo->idInfo.tableType = pScanNode->tableType;
280,597,829✔
2132

2133
  SArray* pUidList = taosArrayInit(8, sizeof(uint64_t));
279,546,293✔
2134
  QUERY_CHECK_NULL(pUidList, code, lino, end, terrno);
280,121,897✔
2135

2136
  char*   pTagCondKey = NULL;
280,121,897✔
2137
  int32_t tagCondKeyLen;
279,158,067✔
2138
  SArray* pTagColIds = NULL;
280,139,138✔
2139
  char*   pPayload = NULL;
280,225,625✔
2140
  SIdxFltStatus status = SFLT_NOT_INDEX;
280,225,625✔
2141

2142
  qTrace("getTableList called, suid:%" PRIu64
280,225,625✔
2143
    ", tagCond:%p, tagIndexCond:%p, %d %d", pScanNode->suid, pTagCond,
2144
    pTagIndexCond, pScanNode->tableType, pScanNode->virtualStableScan);
2145
  if (pScanNode->tableType != TSDB_SUPER_TABLE && !pScanNode->virtualStableScan) {
280,236,562✔
2146
    pListInfo->idInfo.uid = pScanNode->uid;
152,975,784✔
2147
    if (pStorageAPI->metaFn.isTableExisted(pVnode, pScanNode->uid)) {
152,907,899✔
2148
      void* tmp = taosArrayPush(pUidList, &pScanNode->uid);
153,098,272✔
2149
      QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
153,096,315✔
2150
    }
2151
    code = doFilterByTagCond(pScanNode->suid, pUidList, pTagCond, pVnode, status, pStorageAPI, pStreamInfo);
153,144,250✔
2152
    QUERY_CHECK_CODE(code, lino, end);
153,116,633✔
2153
  } else {
2154
    bool      isStream = (pStreamInfo != NULL);
127,235,190✔
2155
    bool      hasTagCond = (pTagCond != NULL);
127,235,190✔
2156
    bool      canCacheTagEqCondFilter = false;
127,235,190✔
2157
    T_MD5_CTX context = {0};
127,533,593✔
2158

2159
    qTrace("start to get table list by tag filter, suid:%" PRIu64
127,600,667✔
2160
      ",tsStableTagFilterCache:%d, tsTagFilterCache:%d", 
2161
      pScanNode->suid, tsStableTagFilterCache, tsTagFilterCache);
2162

2163
    bool acquired = false;
127,599,863✔
2164
    // first, check whether we can use stable tag filter cache
2165
    if (tsStableTagFilterCache && isStream && hasTagCond) {
127,486,523✔
2166
      canCacheTagEqCondFilter = true;
11,245✔
2167
      nodesWalkExpr(pTagCond, canOptimizeTagCondFilter,
11,245✔
2168
        (void*)&canCacheTagEqCondFilter);
2169
    }
2170
    if (canCacheTagEqCondFilter) {
126,849,304✔
2171
      qDebug("%s, stable tag filter condition can be optimized", idstr);
10,899✔
2172
      if (((SStreamRuntimeFuncInfo*)pStreamInfo)->hasPlaceHolder) {
10,899✔
2173
        SNode* tmp = NULL;
10,899✔
2174
        code = nodesCloneNode((SNode*)pTagCond, &tmp);
10,899✔
2175
        QUERY_CHECK_CODE(code, lino, end);
10,899✔
2176

2177
        PlaceHolderContext ctx = {.code = TSDB_CODE_SUCCESS, .pStreamRuntimeInfo = (SStreamRuntimeFuncInfo*)pStreamInfo};
10,899✔
2178
        nodesRewriteExpr(&tmp, replacePlaceHolderColumn, (void*)&ctx);
10,899✔
2179
        if (TSDB_CODE_SUCCESS != ctx.code) {
10,899✔
UNCOV
2180
          nodesDestroyNode(tmp);
×
UNCOV
2181
          code = ctx.code;
×
UNCOV
2182
          goto end;
×
2183
        }
2184
        code = genStableTagFilterDigest(tmp, &context);
10,899✔
2185
        nodesDestroyNode(tmp);
10,899✔
2186
      } else {
2187
        code = genStableTagFilterDigest(pTagCond, &context);
×
2188
      }
2189
      QUERY_CHECK_CODE(code, lino, end);
10,899✔
2190

2191
      code = buildTagCondKey(
10,899✔
2192
        pTagCond, &pTagCondKey, &tagCondKeyLen, &pTagColIds);
2193
      QUERY_CHECK_CODE(code, lino, end);
10,899✔
2194
      code = pStorageAPI->metaFn.getStableCachedTableList(
10,899✔
2195
        pVnode, pScanNode->suid, pTagCondKey, tagCondKeyLen,
10,899✔
2196
        context.digest, tListLen(context.digest), pUidList, &acquired);
2197
      QUERY_CHECK_CODE(code, lino, end);
10,899✔
2198
    } else if (tsTagFilterCache) {
126,838,405✔
2199
      // second, try to use normal tag filter cache
2200
      qDebug("%s using normal tag filter cache", idstr);
34,078✔
2201
      if (pStreamInfo != NULL && ((SStreamRuntimeFuncInfo*)pStreamInfo)->hasPlaceHolder) {
35,416✔
2202
        SNode* tmp = NULL;
1,338✔
2203
        code = nodesCloneNode((SNode*)pTagCond, &tmp);
1,338✔
2204
        QUERY_CHECK_CODE(code, lino, end);
1,338✔
2205

2206
        PlaceHolderContext ctx = {.code = TSDB_CODE_SUCCESS, .pStreamRuntimeInfo = (SStreamRuntimeFuncInfo*)pStreamInfo};
1,338✔
2207
        nodesRewriteExpr(&tmp, replacePlaceHolderColumn, (void*)&ctx);
1,338✔
2208
        if (TSDB_CODE_SUCCESS != ctx.code) {
1,338✔
UNCOV
2209
          nodesDestroyNode(tmp);
×
UNCOV
2210
          code = ctx.code;
×
UNCOV
2211
          goto end;
×
2212
        }
2213
        code = genTagFilterDigest(tmp, &context);
1,338✔
2214
        nodesDestroyNode(tmp);
1,338✔
2215
      } else {
2216
        code = genTagFilterDigest(pTagCond, &context);
32,740✔
2217
      }
2218
      // try to retrieve the result from meta cache
2219
      QUERY_CHECK_CODE(code, lino, end);      
34,078✔
2220
      code = pStorageAPI->metaFn.getCachedTableList(
34,078✔
2221
        pVnode, pScanNode->suid, context.digest,
34,078✔
2222
        tListLen(context.digest), pUidList, &acquired);
2223
      QUERY_CHECK_CODE(code, lino, end);
176,524✔
2224
    }
2225
    if (acquired) {
126,991,749✔
2226
      taosArrayDestroy(pTagColIds);
32,140✔
2227
      pTagColIds = NULL;
32,140✔
2228
      
2229
      if (digest != NULL) {
32,140✔
2230
        digest[0] = 1;
32,140✔
2231
        memcpy(digest + 1, context.digest, tListLen(context.digest));
32,140✔
2232
      }
2233
      
2234
      qDebug("suid:%" PRIu64 ", %s retrieve table uid list from cache, numOfTables:%d", 
32,140✔
2235
        pScanNode->suid, idstr, (int32_t)taosArrayGetSize(pUidList));
2236
      goto end;
32,140✔
2237
    } else {
2238
      qDebug("suid:%" PRIu64 
126,959,609✔
2239
        ", failed to get table uid list from cache", pScanNode->suid);
2240
    }
2241

2242
    if (!pTagCond) {  // no tag filter condition exists, let's fetch all tables of this super table
127,975,153✔
2243
      code = pStorageAPI->metaFn.getChildTableList(pVnode, pScanNode->suid, pUidList);
110,887,128✔
2244
      QUERY_CHECK_CODE(code, lino, end);
110,669,121✔
2245
      qTrace("no tag filter, get all child tables, numOfTables:%d", (int32_t)taosArrayGetSize(pUidList));
110,669,121✔
2246
    } else {
2247
      SIdxFltStatus status = SFLT_NOT_INDEX;
17,088,025✔
2248
      if (pTagIndexCond) {
17,087,405✔
2249
        void* pIndex = pStorageAPI->metaFn.getInvertIndex(pVnode);
4,296,343✔
2250

2251
        SIndexMetaArg metaArg = {.metaEx = pVnode,
4,296,761✔
2252
                                 .idx = pStorageAPI->metaFn.storeGetIndexInfo(pVnode),
4,296,735✔
2253
                                 .ivtIdx = pIndex,
2254
                                 .suid = pScanNode->uid};
4,296,343✔
2255
        code = doFilterTag(pTagIndexCond, &metaArg, pUidList, &status, &pStorageAPI->metaFilter);
4,296,735✔
2256
        if (code != 0 || status == SFLT_NOT_INDEX) {  // temporarily disable it for performance sake
4,257,892✔
2257
          qDebug("failed to get tableIds from index, suid:%" PRIu64 ", uidListSize:%d", pScanNode->uid, (int32_t)taosArrayGetSize(pUidList));
1,256,505✔
2258
        } else {
2259
          qDebug("succ to get filter result, table num: %d", (int)taosArrayGetSize(pUidList));
3,001,387✔
2260
        }
2261
      }
2262
    }
2263
    qTrace("after index filter, pTagCond:%p uidListSize:%d", pTagCond, (int32_t)taosArrayGetSize(pUidList));
127,746,348✔
2264
    code = doFilterByTagCond(pScanNode->suid, pUidList, pTagCond, pVnode, status, pStorageAPI, pStreamInfo);
127,746,342✔
2265
    QUERY_CHECK_CODE(code, lino, end);
127,708,782✔
2266

2267
    // let's add the filter results into meta-cache
2268
    numOfTables = taosArrayGetSize(pUidList);
127,707,814✔
2269

2270
    if (canCacheTagEqCondFilter) {
127,794,678✔
2271
      qInfo("%s, suid:%" PRIu64 ", add uid list to stable tag filter cache, "
4,880✔
2272
            "uidListSize:%d, origin key:%" PRIu64 ",%" PRIu64,
2273
            idstr, pScanNode->suid, (int32_t)numOfTables,
2274
            *(uint64_t*)context.digest, *(uint64_t*)(context.digest + 8));
2275

2276
      code = pStorageAPI->metaFn.putStableCachedTableList(
4,880✔
2277
        pVnode, pScanNode->suid, pTagCondKey, tagCondKeyLen,
2278
        context.digest, tListLen(context.digest),
2279
        pUidList, &pTagColIds);
2280
      QUERY_CHECK_CODE(code, lino, end);
4,844✔
2281

2282
      if (digest != NULL) {
4,844✔
2283
        digest[0] = 1;
4,844✔
2284
        memcpy(digest + 1, context.digest, tListLen(context.digest));
4,844✔
2285
      }
2286
    } else if (tsTagFilterCache) {
127,789,798✔
2287
      qInfo("%s, suid:%" PRIu64 ", add uid list to normal tag filter cache, "
7,993✔
2288
            "uidListSize:%d, origin key:%" PRIu64 ",%" PRIu64,
2289
            idstr, pScanNode->suid, (int32_t)numOfTables,
2290
            *(uint64_t*)context.digest, *(uint64_t*)(context.digest + 8));
2291
      size_t size = numOfTables * sizeof(uint64_t) + sizeof(int32_t);
7,993✔
2292
      pPayload = taosMemoryMalloc(size);
7,993✔
2293
      QUERY_CHECK_NULL(pPayload, code, lino, end, terrno);
7,993✔
2294

2295
      *(int32_t*)pPayload = (int32_t)numOfTables;
7,993✔
2296
      if (numOfTables > 0) {
7,993✔
2297
        void* tmp = taosArrayGet(pUidList, 0);
6,582✔
2298
        QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
6,582✔
2299
        memcpy(pPayload + sizeof(int32_t), tmp, numOfTables * sizeof(uint64_t));
6,582✔
2300
      }
2301

2302
      code = pStorageAPI->metaFn.putCachedTableList(pVnode, pScanNode->suid,
7,993✔
2303
                                                    context.digest,
2304
                                                    tListLen(context.digest),
2305
                                                    pPayload, size, 1);
2306
      if (TSDB_CODE_SUCCESS == code) {
7,993✔
2307
        /*
2308
          data referenced by pPayload is used in lru cache,
2309
          reset pPayload to NULL to avoid being freed in _error block
2310
        */
2311
        pPayload = NULL;
7,993✔
2312
      } else {
UNCOV
2313
        if (TSDB_CODE_DUP_KEY == code) {
×
2314
          /*
2315
            another thread has already put the same key into cache,
2316
            we can just ignore this error
2317
          */
UNCOV
2318
          code = TSDB_CODE_SUCCESS;
×
2319
        }
UNCOV
2320
        QUERY_CHECK_CODE(code, lino, end);
×
2321
      }
2322

2323
      if (digest != NULL) {
7,993✔
2324
        digest[0] = 1;
7,993✔
2325
        memcpy(digest + 1, context.digest, tListLen(context.digest));
7,993✔
2326
      }
2327
    }
2328
  }
2329

2330
  qDebug("%s, table list with %d uids built", idstr, (int32_t)numOfTables);
280,737,680✔
2331

2332
end:
281,041,196✔
2333
  if (code == 0) {
281,091,288✔
2334
     STableKeyInfo info = {.uid = 0, .groupId = 0};
281,090,320✔
2335
    for (int32_t i = 0; i < taosArrayGetSize(pUidList); ++i) {
995,694,385✔
2336
      int64_t* uid = (int64_t*)taosArrayGet(pUidList, i);
714,271,214✔
2337
      QUERY_CHECK_NULL(uid, code, lino, end, terrno);
714,481,842✔
2338

2339
      info.uid = *uid;
714,481,842✔
2340
        //qInfo("doSetQualifiedUid row:%d added to pTableList", i);
2341
      void* p = taosArrayPush(pListInfo->pTableList, &info);
714,413,063✔
2342
      QUERY_CHECK_NULL(p, code, lino, end, terrno);
714,570,021✔
2343
    }
2344
  } else {
2345
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
968✔
2346
  }
2347
  taosArrayDestroy(pUidList);
281,222,504✔
2348
  taosArrayDestroy(pTagColIds);
281,047,665✔
2349
  taosMemFreeClear(pTagCondKey);
281,083,069✔
2350
  taosMemFreeClear(pPayload);
281,083,069✔
2351
  return code;
281,083,069✔
2352
}
2353

2354
int32_t qGetTableList(int64_t suid, void* pVnode, void* node, SArray** tableList, void* pTaskInfo) {
23,614✔
2355
  int32_t        code = TSDB_CODE_SUCCESS;
23,614✔
2356
  int32_t        lino = 0;
23,614✔
2357
  SSubplan*      pSubplan = (SSubplan*)node;
23,614✔
2358
  SScanPhysiNode pNode = {0};
23,614✔
2359
  pNode.suid = suid;
23,614✔
2360
  pNode.uid = suid;
23,614✔
2361
  pNode.tableType = TSDB_SUPER_TABLE;
23,614✔
2362

2363
  STableListInfo* pTableListInfo = tableListCreate();
23,614✔
2364
  QUERY_CHECK_NULL(pTableListInfo, code, lino, _end, terrno);
23,614✔
2365
  code = getTableList(pVnode, &pNode, pSubplan ? pSubplan->pTagCond : NULL, pSubplan ? pSubplan->pTagIndexCond : NULL,
23,614✔
2366
                      pTableListInfo, NULL, "qGetTableList", &((SExecTaskInfo*)pTaskInfo)->storageAPI, NULL);
2367
  QUERY_CHECK_CODE(code, lino, _end);
23,614✔
2368
  *tableList = pTableListInfo->pTableList;
23,614✔
2369
  pTableListInfo->pTableList = NULL;
23,614✔
2370

2371
_end:
23,614✔
2372
  tableListDestroy(pTableListInfo);
23,614✔
2373
  if (code != TSDB_CODE_SUCCESS) {
23,614✔
UNCOV
2374
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2375
  }
2376
  return code;
23,614✔
2377
}
2378

2379
size_t getTableTagsBufLen(const SNodeList* pGroups) {
×
UNCOV
2380
  size_t keyLen = 0;
×
2381

2382
  SNode* node;
UNCOV
2383
  FOREACH(node, pGroups) {
×
2384
    SExprNode* pExpr = (SExprNode*)node;
×
2385
    keyLen += pExpr->resType.bytes;
×
2386
  }
2387

2388
  keyLen += sizeof(int8_t) * LIST_LENGTH(pGroups);
×
2389
  return keyLen;
×
2390
}
2391

UNCOV
2392
int32_t getGroupIdFromTagsVal(void* pVnode, uint64_t uid, SNodeList* pGroupNode, char* keyBuf, uint64_t* pGroupId,
×
2393
                              SStorageAPI* pAPI) {
2394
  SMetaReader mr = {0};
×
2395

UNCOV
2396
  pAPI->metaReaderFn.initReader(&mr, pVnode, META_READER_LOCK, &pAPI->metaFn);
×
2397
  if (pAPI->metaReaderFn.getEntryGetUidCache(&mr, uid) != 0) {  // table not exist
×
UNCOV
2398
    pAPI->metaReaderFn.clearReader(&mr);
×
2399
    return TSDB_CODE_PAR_TABLE_NOT_EXIST;
×
2400
  }
2401

2402
  SNodeList* groupNew = NULL;
×
2403
  int32_t    code = nodesCloneList(pGroupNode, &groupNew);
×
2404
  if (TSDB_CODE_SUCCESS != code) {
×
UNCOV
2405
    pAPI->metaReaderFn.clearReader(&mr);
×
UNCOV
2406
    return code;
×
2407
  }
2408

2409
  STransTagExprCtx ctx = {.code = 0, .pReader = &mr};
×
2410
  nodesRewriteExprsPostOrder(groupNew, doTranslateTagExpr, &ctx);
×
2411
  if (TSDB_CODE_SUCCESS != ctx.code) {
×
UNCOV
2412
    nodesDestroyList(groupNew);
×
UNCOV
2413
    pAPI->metaReaderFn.clearReader(&mr);
×
2414
    return code;
×
2415
  }
2416
  char* isNull = (char*)keyBuf;
×
2417
  char* pStart = (char*)keyBuf + sizeof(int8_t) * LIST_LENGTH(pGroupNode);
×
2418

2419
  SNode*  pNode;
UNCOV
2420
  int32_t index = 0;
×
2421
  FOREACH(pNode, groupNew) {
×
2422
    SNode*  pNew = NULL;
×
UNCOV
2423
    int32_t code = scalarCalculateConstants(pNode, &pNew);
×
UNCOV
2424
    if (TSDB_CODE_SUCCESS == code) {
×
2425
      REPLACE_NODE(pNew);
×
2426
    } else {
2427
      nodesDestroyList(groupNew);
×
2428
      pAPI->metaReaderFn.clearReader(&mr);
×
2429
      return code;
×
2430
    }
2431

2432
    if (nodeType(pNew) != QUERY_NODE_VALUE) {
×
2433
      nodesDestroyList(groupNew);
×
2434
      pAPI->metaReaderFn.clearReader(&mr);
×
UNCOV
2435
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
UNCOV
2436
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2437
    }
2438
    SValueNode* pValue = (SValueNode*)pNew;
×
2439

2440
    if (pValue->node.resType.type == TSDB_DATA_TYPE_NULL || pValue->isNull) {
×
2441
      isNull[index++] = 1;
×
UNCOV
2442
      continue;
×
2443
    } else {
UNCOV
2444
      isNull[index++] = 0;
×
2445
      char* data = nodesGetValueFromNode(pValue);
×
2446
      if (pValue->node.resType.type == TSDB_DATA_TYPE_JSON) {
×
2447
        if (tTagIsJson(data)) {
×
UNCOV
2448
          terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
×
2449
          nodesDestroyList(groupNew);
×
2450
          pAPI->metaReaderFn.clearReader(&mr);
×
2451
          return terrno;
×
2452
        }
2453
        int32_t len = getJsonValueLen(data);
×
2454
        memcpy(pStart, data, len);
×
2455
        pStart += len;
×
2456
      } else if (IS_VAR_DATA_TYPE(pValue->node.resType.type)) {
×
UNCOV
2457
        if (IS_STR_DATA_BLOB(pValue->node.resType.type)) {
×
2458
          return TSDB_CODE_BLOB_NOT_SUPPORT_TAG;
×
2459
        }
2460
        memcpy(pStart, data, varDataTLen(data));
×
2461
        pStart += varDataTLen(data);
×
2462
      } else {
2463
        memcpy(pStart, data, pValue->node.resType.bytes);
×
UNCOV
2464
        pStart += pValue->node.resType.bytes;
×
2465
      }
2466
    }
2467
  }
2468

2469
  int32_t len = (int32_t)(pStart - (char*)keyBuf);
×
UNCOV
2470
  *pGroupId = calcGroupId(keyBuf, len);
×
2471

UNCOV
2472
  nodesDestroyList(groupNew);
×
UNCOV
2473
  pAPI->metaReaderFn.clearReader(&mr);
×
2474

2475
  return TSDB_CODE_SUCCESS;
×
2476
}
2477

2478
SArray* makeColumnArrayFromList(SNodeList* pNodeList) {
4,052,287✔
2479
  if (!pNodeList) {
4,052,287✔
2480
    return NULL;
×
2481
  }
2482

2483
  size_t  numOfCols = LIST_LENGTH(pNodeList);
4,052,287✔
2484
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
4,056,156✔
2485
  if (pList == NULL) {
4,053,044✔
UNCOV
2486
    return NULL;
×
2487
  }
2488

2489
  for (int32_t i = 0; i < numOfCols; ++i) {
9,101,110✔
2490
    SColumnNode* pColNode = (SColumnNode*)nodesListGetNode(pNodeList, i);
5,049,885✔
2491
    if (!pColNode) {
5,062,085✔
UNCOV
2492
      taosArrayDestroy(pList);
×
UNCOV
2493
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
UNCOV
2494
      return NULL;
×
2495
    }
2496

2497
    // todo extract method
2498
    SColumn c = {0};
5,062,085✔
2499
    c.slotId = pColNode->slotId;
5,051,565✔
2500
    c.colId = pColNode->colId;
5,061,590✔
2501
    c.type = pColNode->node.resType.type;
5,060,997✔
2502
    c.bytes = pColNode->node.resType.bytes;
5,053,549✔
2503
    c.precision = pColNode->node.resType.precision;
5,056,783✔
2504
    c.scale = pColNode->node.resType.scale;
5,058,326✔
2505

2506
    void* tmp = taosArrayPush(pList, &c);
5,058,590✔
2507
    if (!tmp) {
5,058,590✔
UNCOV
2508
      taosArrayDestroy(pList);
×
UNCOV
2509
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
2510
      return NULL;
×
2511
    }
2512
  }
2513

2514
  return pList;
4,051,225✔
2515
}
2516

2517
int32_t extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols,
363,062,941✔
2518
                            int32_t type, SColMatchInfo* pMatchInfo) {
2519
  size_t  numOfCols = LIST_LENGTH(pNodeList);
363,062,941✔
2520
  int32_t code = TSDB_CODE_SUCCESS;
363,291,642✔
2521
  int32_t lino = 0;
363,291,642✔
2522
  bool    colIdOrdered = true;
363,291,642✔
2523
  bool    hasPrevColId = false;
363,291,642✔
2524
  int32_t prevColId = 0;
363,291,642✔
2525

2526
  pMatchInfo->matchType = type;
363,291,642✔
2527

2528
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColMatchItem));
362,991,503✔
2529
  if (pList == NULL) {
362,892,905✔
UNCOV
2530
    code = terrno;
×
UNCOV
2531
    return code;
×
2532
  }
2533

2534
  SColMatchItem** infoBySlot = NULL;
362,892,905✔
2535
  if (numOfCols > 0) {
362,892,905✔
2536
    infoBySlot = taosMemoryCalloc(numOfCols, sizeof(*infoBySlot));
362,793,122✔
2537
    if (infoBySlot == NULL) {
362,901,548✔
UNCOV
2538
      code = terrno;
×
UNCOV
2539
      goto _end;
×
2540
    }
2541
  }
2542

2543
  SNode* node = NULL;
363,001,331✔
2544
  FOREACH(node, pNodeList) {
1,805,827,940✔
2545
    STargetNode* pNode = (STargetNode*)node;
1,442,179,632✔
2546
    QUERY_CHECK_NULL(pNode, code, lino, _end, terrno);
1,442,179,632✔
2547
    if (nodeType(pNode->pExpr) == QUERY_NODE_COLUMN) {
1,442,179,632✔
2548
      SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
1,428,722,805✔
2549

2550
      SColMatchItem c = {.needOutput = true};
1,428,968,053✔
2551
      c.colId = pColNode->colId;
1,428,879,422✔
2552
      c.srcSlotId = pColNode->slotId;
1,429,275,601✔
2553
      c.dstSlotId = pNode->slotId;
1,429,210,520✔
2554
      c.isPk = pColNode->isPk;
1,429,195,440✔
2555
      c.dataType = pColNode->node.resType;
1,429,169,421✔
2556
      void* tmp = taosArrayPush(pList, &c);
1,429,223,948✔
2557
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,429,223,948✔
2558
      if (hasPrevColId) {
1,429,223,948✔
2559
        if (c.colId < prevColId) {
1,066,873,976✔
2560
          colIdOrdered = false;
16,206,367✔
2561
        }
2562
      } else {
2563
        hasPrevColId = true;
362,349,972✔
2564
      }
2565
      prevColId = c.colId;
1,429,223,948✔
2566
      if (pNode->slotId >= 0 && pNode->slotId < numOfCols) {
1,429,223,948✔
2567
        infoBySlot[pNode->slotId] = (SColMatchItem*)taosArrayGet(pList, taosArrayGetSize(pList) - 1);
1,428,510,537✔
2568
      }
2569
    }
2570
  }
2571
  // set the output flag for each column in SColMatchInfo, according to the
2572
  *numOfOutputCols = 0;
363,278,790✔
2573
  SNode* slotNode = NULL;
363,276,584✔
2574
  FOREACH(slotNode, pOutputNodeList->pSlots) {
1,974,406,027✔
2575
    SSlotDescNode* pNode = (SSlotDescNode*)slotNode;
1,610,887,881✔
2576
    QUERY_CHECK_NULL(pNode, code, lino, _end, terrno);
1,610,887,881✔
2577

2578
    // todo: add reserve flag check
2579
    // it is a column reserved for the arithmetic expression calculation
2580
    if (pNode->slotId >= numOfCols) {
1,610,887,881✔
2581
      (*numOfOutputCols) += 1;
169,270,068✔
2582
      continue;
169,300,673✔
2583
    }
2584

2585
    SColMatchItem* info = infoBySlot ? infoBySlot[pNode->slotId] : NULL;
1,442,420,603✔
2586

2587
    if (pNode->output) {
1,442,278,713✔
2588
      (*numOfOutputCols) += 1;
1,421,918,094✔
2589
    } else if (info != NULL) {
20,513,664✔
2590
      // select distinct tbname from stb where tbname='abc';
2591
      info->needOutput = false;
20,493,247✔
2592
    }
2593
  }
2594

2595
  pMatchInfo->pList = pList;
362,994,580✔
2596
  pMatchInfo->colIdOrdered = colIdOrdered;
363,010,601✔
2597

2598
_end:
362,898,616✔
2599
  taosMemoryFree(infoBySlot);
362,898,616✔
2600
  if (code != TSDB_CODE_SUCCESS) {
362,841,086✔
UNCOV
2601
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2602
  }
2603
  return code;
362,695,490✔
2604
}
2605

2606
static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, int32_t scale, int32_t precision,
1,208,990,404✔
2607
                                  const char* name) {
2608
  SResSchema s = {0};
1,208,990,404✔
2609
  s.scale = scale;
1,209,263,808✔
2610
  s.type = type;
1,209,263,808✔
2611
  s.bytes = bytes;
1,209,263,808✔
2612
  s.slotId = slotId;
1,209,263,808✔
2613
  s.precision = precision;
1,209,263,808✔
2614
  tstrncpy(s.name, name, tListLen(s.name));
1,209,263,808✔
2615

2616
  return s;
1,208,589,976✔
2617
}
2618

2619
static SColumn* createColumn(int32_t blockId, int32_t slotId, int32_t colId, SDataType* pType, EColumnType colType) {
1,136,965,513✔
2620
  SColumn* pCol = taosMemoryCalloc(1, sizeof(SColumn));
1,136,965,513✔
2621
  if (pCol == NULL) {
1,135,495,995✔
UNCOV
2622
    return NULL;
×
2623
  }
2624

2625
  pCol->slotId = slotId;
1,135,495,995✔
2626
  pCol->colId = colId;
1,135,541,121✔
2627
  pCol->bytes = pType->bytes;
1,135,805,072✔
2628
  pCol->type = pType->type;
1,136,297,101✔
2629
  pCol->scale = pType->scale;
1,136,423,966✔
2630
  pCol->precision = pType->precision;
1,136,646,440✔
2631
  pCol->dataBlockId = blockId;
1,136,637,460✔
2632
  pCol->colType = colType;
1,136,344,173✔
2633
  return pCol;
1,136,421,483✔
2634
}
2635

2636
int32_t createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) {
1,208,591,966✔
2637
  int32_t code = TSDB_CODE_SUCCESS;
1,208,591,966✔
2638
  int32_t lino = 0;
1,208,591,966✔
2639
  pExp->base.numOfParams = 0;
1,208,591,966✔
2640
  pExp->base.pParam = NULL;
1,209,195,069✔
2641
  pExp->pExpr = taosMemoryCalloc(1, sizeof(tExprNode));
1,208,832,793✔
2642
  QUERY_CHECK_NULL(pExp->pExpr, code, lino, _end, terrno);
1,207,529,778✔
2643

2644
  pExp->pExpr->_function.num = 1;
1,207,959,733✔
2645
  pExp->pExpr->_function.functionId = -1;
1,208,182,738✔
2646

2647
  int32_t type = nodeType(pNode);
1,208,259,164✔
2648
  // it is a project query, or group by column
2649
  if (type == QUERY_NODE_COLUMN) {
1,208,818,748✔
2650
    pExp->pExpr->nodeType = QUERY_NODE_COLUMN;
691,009,483✔
2651
    SColumnNode* pColNode = (SColumnNode*)pNode;
691,078,662✔
2652

2653
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
691,078,662✔
2654
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
690,892,573✔
2655

2656
    pExp->base.numOfParams = 1;
690,656,601✔
2657

2658
    SDataType* pType = &pColNode->node.resType;
690,802,691✔
2659
    pExp->base.resSchema =
2660
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pColNode->colName);
690,836,277✔
2661

2662
    pExp->base.pParam[0].pCol =
1,381,560,650✔
2663
        createColumn(pColNode->dataBlockId, pColNode->slotId, pColNode->colId, pType, pColNode->colType);
1,377,099,072✔
2664
    QUERY_CHECK_NULL(pExp->base.pParam[0].pCol, code, lino, _end, terrno);
690,875,685✔
2665

2666
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_COLUMN;
690,370,871✔
2667
  } else if (type == QUERY_NODE_VALUE) {
517,809,265✔
2668
    pExp->pExpr->nodeType = QUERY_NODE_VALUE;
18,320,493✔
2669
    SValueNode* pValNode = (SValueNode*)pNode;
18,341,989✔
2670

2671
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
18,341,989✔
2672
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
18,322,548✔
2673

2674
    pExp->base.numOfParams = 1;
18,307,901✔
2675

2676
    SDataType* pType = &pValNode->node.resType;
18,320,845✔
2677
    pExp->base.resSchema =
2678
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pValNode->node.aliasName);
18,321,282✔
2679
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
18,309,601✔
2680
    code = nodesValueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
18,347,552✔
2681
    QUERY_CHECK_CODE(code, lino, _end);
18,339,297✔
2682
  } else if (type == QUERY_NODE_REMOTE_VALUE) {
499,488,772✔
2683
    SRemoteValueNode* pRemote = (SRemoteValueNode*)pNode;
1,441,766✔
2684
    code = qFetchRemoteNode(gTaskScalarExtra.pSubJobCtx, pRemote->subQIdx, pNode);
1,441,766✔
2685
    QUERY_CHECK_CODE(code, lino, _end);
1,450,076✔
2686

2687
    pExp->pExpr->nodeType = QUERY_NODE_VALUE;
1,020,172✔
2688
    SValueNode* pValNode = (SValueNode*)pNode;
1,020,172✔
2689

2690
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
1,020,172✔
2691
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
1,020,172✔
2692

2693
    pExp->base.numOfParams = 1;
1,020,172✔
2694

2695
    SDataType* pType = &pValNode->node.resType;
1,020,172✔
2696
    pExp->base.resSchema =
2697
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pValNode->node.aliasName);
1,020,172✔
2698
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
1,020,172✔
2699
    code = nodesValueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
1,020,172✔
2700
    QUERY_CHECK_CODE(code, lino, _end);
1,020,210✔
2701
  } else if (type == QUERY_NODE_FUNCTION) {
498,047,006✔
2702
    pExp->pExpr->nodeType = QUERY_NODE_FUNCTION;
455,867,554✔
2703
    SFunctionNode* pFuncNode = (SFunctionNode*)pNode;
455,921,536✔
2704

2705
    SDataType* pType = &pFuncNode->node.resType;
455,921,536✔
2706
    pExp->base.resSchema =
2707
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pFuncNode->node.aliasName);
455,929,671✔
2708
    tExprNode* pExprNode = pExp->pExpr;
455,945,244✔
2709

2710
    pExprNode->_function.functionId = pFuncNode->funcId;
456,063,517✔
2711
    pExprNode->_function.pFunctNode = pFuncNode;
456,230,914✔
2712
    pExprNode->_function.functionType = pFuncNode->funcType;
456,132,446✔
2713

2714
    tstrncpy(pExprNode->_function.functionName, pFuncNode->functionName, tListLen(pExprNode->_function.functionName));
456,060,079✔
2715

2716
    pExp->base.pParamList = pFuncNode->pParameterList;
456,463,231✔
2717
#if 1
2718
    // todo refactor: add the parameter for tbname function
2719
    const char* name = "tbname";
456,265,353✔
2720
    int32_t     len = strlen(name);
456,265,353✔
2721

2722
    if (!pFuncNode->pParameterList && (memcmp(pExprNode->_function.functionName, name, len) == 0) &&
456,265,353✔
2723
        pExprNode->_function.functionName[len] == 0) {
29,882,693✔
2724
      pFuncNode->pParameterList = NULL;
29,926,279✔
2725
      int32_t     code = nodesMakeList(&pFuncNode->pParameterList);
29,880,987✔
2726
      SValueNode* res = NULL;
29,917,564✔
2727
      if (TSDB_CODE_SUCCESS == code) {
29,926,583✔
2728
        code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&res);
29,939,825✔
2729
      }
2730
      QUERY_CHECK_CODE(code, lino, _end);
29,967,149✔
2731
      res->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
29,967,149✔
2732
      code = nodesListAppend(pFuncNode->pParameterList, (SNode*)res);
29,935,850✔
2733
      if (code != TSDB_CODE_SUCCESS) {
29,944,503✔
UNCOV
2734
        nodesDestroyNode((SNode*)res);
×
UNCOV
2735
        res = NULL;
×
2736
      }
2737
      QUERY_CHECK_CODE(code, lino, _end);
29,944,503✔
2738
    }
2739
#endif
2740

2741
    int32_t numOfParam = LIST_LENGTH(pFuncNode->pParameterList);
455,855,212✔
2742

2743
    pExp->base.pParam = taosMemoryCalloc(numOfParam, sizeof(SFunctParam));
456,289,265✔
2744
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
455,789,577✔
2745
    pExp->base.numOfParams = numOfParam;
455,740,803✔
2746

2747
    for (int32_t j = 0; j < numOfParam && TSDB_CODE_SUCCESS == code; ++j) {
1,068,607,665✔
2748
      SNode* p1 = nodesListGetNode(pFuncNode->pParameterList, j);
612,805,874✔
2749
      QUERY_CHECK_NULL(p1, code, lino, _end, terrno);
612,853,275✔
2750
      if (p1->type == QUERY_NODE_COLUMN) {
612,853,306✔
2751
        SColumnNode* pcn = (SColumnNode*)p1;
445,922,081✔
2752

2753
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN;
445,922,081✔
2754
        pExp->base.pParam[j].pCol =
891,404,002✔
2755
            createColumn(pcn->dataBlockId, pcn->slotId, pcn->colId, &pcn->node.resType, pcn->colType);
891,370,209✔
2756
        QUERY_CHECK_NULL(pExp->base.pParam[j].pCol, code, lino, _end, terrno);
445,674,436✔
2757
      } else if (p1->type == QUERY_NODE_VALUE) {
166,909,212✔
2758
        SValueNode* pvn = (SValueNode*)p1;
108,284,389✔
2759
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
108,284,389✔
2760
        code = nodesValueNodeToVariant(pvn, &pExp->base.pParam[j].param);
108,122,683✔
2761
        QUERY_CHECK_CODE(code, lino, _end);
108,258,520✔
2762
      } else if (p1->type == QUERY_NODE_REMOTE_VALUE) {
58,845,287✔
2763
        SRemoteValueNode* pRemote = (SRemoteValueNode*)p1;
73,682✔
2764
        code = qFetchRemoteNode(gTaskScalarExtra.pSubJobCtx, pRemote->subQIdx, p1);
73,682✔
2765
        QUERY_CHECK_CODE(code, lino, _end);
74,236✔
2766

2767
        SValueNode* pvn = (SValueNode*)pRemote;
53,738✔
2768
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
53,738✔
2769
        code = nodesValueNodeToVariant(pvn, &pExp->base.pParam[j].param);
53,738✔
UNCOV
2770
        QUERY_CHECK_CODE(code, lino, _end);
×
2771
      }
2772
    }
2773
    pExp->pExpr->_function.bindExprID = ((SExprNode*)pNode)->bindExprID;
455,801,791✔
2774
  } else if (type == QUERY_NODE_OPERATOR) {
42,179,547✔
2775
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
40,695,550✔
2776
    SOperatorNode* pOpNode = (SOperatorNode*)pNode;
40,672,590✔
2777

2778
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
40,672,590✔
2779
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
40,614,162✔
2780
    pExp->base.numOfParams = 1;
40,572,615✔
2781

2782
    SDataType* pType = &pOpNode->node.resType;
40,598,790✔
2783
    pExp->base.resSchema =
2784
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pOpNode->node.aliasName);
40,604,934✔
2785
    pExp->pExpr->_optrRoot.pRootNode = pNode;
40,650,263✔
2786
  } else if (type == QUERY_NODE_CASE_WHEN) {
1,484,894✔
2787
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
1,385,319✔
2788
    SCaseWhenNode* pCaseNode = (SCaseWhenNode*)pNode;
1,384,322✔
2789

2790
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
1,384,322✔
2791
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
1,384,361✔
2792
    pExp->base.numOfParams = 1;
1,384,322✔
2793

2794
    SDataType* pType = &pCaseNode->node.resType;
1,384,395✔
2795
    pExp->base.resSchema =
2796
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pCaseNode->node.aliasName);
1,384,395✔
2797
    pExp->pExpr->_optrRoot.pRootNode = pNode;
1,384,395✔
2798
  } else if (type == QUERY_NODE_LOGIC_CONDITION) {
99,575✔
2799
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
106,134✔
2800
    SLogicConditionNode* pCond = (SLogicConditionNode*)pNode;
106,134✔
2801
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
106,134✔
2802
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
106,134✔
2803
    pExp->base.numOfParams = 1;
105,590✔
2804
    SDataType* pType = &pCond->node.resType;
106,134✔
2805
    pExp->base.resSchema =
2806
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pCond->node.aliasName);
106,134✔
2807
    pExp->pExpr->_optrRoot.pRootNode = pNode;
105,590✔
2808
  } else {
2809
    code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
5,148✔
2810
    QUERY_CHECK_CODE(code, lino, _end);
5,148✔
2811
  }
2812
  pExp->pExpr->relatedTo = ((SExprNode*)pNode)->relatedTo;
1,207,853,634✔
2813
_end:
1,208,875,505✔
2814
  if (code != TSDB_CODE_SUCCESS) {
1,208,875,505✔
2815
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
450,402✔
2816
  }
2817
  return code;
1,208,376,548✔
2818
}
2819

2820
int32_t createExprFromTargetNode(SExprInfo* pExp, STargetNode* pTargetNode) {
1,209,047,203✔
2821
  return createExprFromOneNode(pExp, pTargetNode->pExpr, pTargetNode->slotId);
1,209,047,203✔
2822
}
2823

UNCOV
2824
SExprInfo* createExpr(SNodeList* pNodeList, int32_t* numOfExprs) {
×
UNCOV
2825
  *numOfExprs = LIST_LENGTH(pNodeList);
×
UNCOV
2826
  SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo));
×
UNCOV
2827
  if (!pExprs) {
×
UNCOV
2828
    return NULL;
×
2829
  }
2830

2831
  for (int32_t i = 0; i < (*numOfExprs); ++i) {
×
2832
    SExprInfo* pExp = &pExprs[i];
×
2833
    int32_t    code = createExprFromOneNode(pExp, nodesListGetNode(pNodeList, i), i + UD_TAG_COLUMN_INDEX);
×
UNCOV
2834
    if (code != TSDB_CODE_SUCCESS) {
×
UNCOV
2835
      taosMemoryFreeClear(pExprs);
×
2836
      terrno = code;
×
2837
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
2838
      return NULL;
×
2839
    }
2840
  }
2841

2842
  return pExprs;
×
2843
}
2844

2845
int32_t createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, SExprInfo** pExprInfo, int32_t* numOfExprs) {
467,498,171✔
2846
  QRY_PARAM_CHECK(pExprInfo);
467,498,171✔
2847

2848
  int32_t code = 0;
467,720,287✔
2849
  int32_t lino = 0;
467,720,287✔
2850
  int32_t numOfFuncs = LIST_LENGTH(pNodeList);
467,720,287✔
2851
  int32_t numOfGroupKeys = 0;
467,554,115✔
2852
  if (pGroupKeys != NULL) {
467,554,115✔
2853
    numOfGroupKeys = LIST_LENGTH(pGroupKeys);
31,152,455✔
2854
  }
2855

2856
  *numOfExprs = numOfFuncs + numOfGroupKeys;
467,554,296✔
2857
  if (*numOfExprs == 0) {
467,383,495✔
2858
    return code;
42,096,230✔
2859
  }
2860

2861
  SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo));
425,183,237✔
2862
  QUERY_CHECK_NULL(pExprs, code, lino, _return, terrno);
424,527,783✔
2863

2864
  int32_t i = 0;
424,527,783✔
2865
  if (pNodeList != NULL) {
424,527,783✔
2866
    SNode* node = NULL;
397,054,629✔
2867
    FOREACH(node, pNodeList) {
1,563,555,012✔
2868
      STargetNode* pTargetNode = (STargetNode*)node;
1,167,923,288✔
2869
      SExprInfo*   pExp = &pExprs[i++];
1,167,923,288✔
2870
      code = createExprFromTargetNode(pExp, pTargetNode);
1,167,639,751✔
2871
      QUERY_CHECK_CODE(code, lino, _return);
1,166,950,785✔
2872
    }
2873
  }
2874

2875
  if (pGroupKeys != NULL) {
424,214,973✔
2876
    SNode* node = NULL;
31,110,112✔
2877
    FOREACH(node, pGroupKeys) {
71,849,401✔
2878
      STargetNode* pTargetNode = (STargetNode*)node;
40,760,421✔
2879
      SExprInfo*   pExp = &pExprs[i++];
40,760,421✔
2880
      code = createExprFromTargetNode(pExp, pTargetNode);
40,724,820✔
2881
      QUERY_CHECK_CODE(code, lino, _return);
40,739,289✔
2882
    }
2883
  }
2884

2885
  *pExprInfo = pExprs;
424,233,289✔
2886
  return code;
424,949,814✔
2887

2888
_return:
450,402✔
2889
  qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
450,402✔
2890
  destroyExprInfo(pExprs, *numOfExprs);
450,402✔
2891
  taosMemoryFreeClear(pExprs);
450,402✔
2892
  return code;
450,402✔
2893
}
2894

UNCOV
2895
static void deleteSubsidiareCtx(void* pData) {
×
UNCOV
2896
  SSubsidiaryResInfo* pCtx = (SSubsidiaryResInfo*)pData;
×
UNCOV
2897
  if (pCtx->pCtx) {
×
UNCOV
2898
    taosMemoryFreeClear(pCtx->pCtx);
×
2899
  }
2900
}
×
2901

2902
// set the output buffer for the selectivity + tag query
2903
static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
452,593,377✔
2904
  int32_t num = 0;
452,593,377✔
2905
  int32_t code = TSDB_CODE_SUCCESS;
452,593,377✔
2906
  int32_t lino = 0;
452,593,377✔
2907

2908
  SArray* pValCtxArray = NULL;
452,593,377✔
2909
  for (int32_t i = numOfOutput - 1; i > 0; --i) {  // select Func is at the end of the list
1,225,164,056✔
2910
    int32_t funcIdx = pCtx[i].pExpr->pExpr->_function.bindExprID;
772,777,524✔
2911
    if (funcIdx > 0) {
772,913,146✔
2912
      if (pValCtxArray == NULL) {
1,603,751✔
2913
        // the end of the list is the select function of biggest index
2914
        pValCtxArray = taosArrayInit_s(sizeof(SSubsidiaryResInfo*), funcIdx);
1,152,045✔
2915
        if (pValCtxArray == NULL) {
1,145,899✔
UNCOV
2916
          return terrno;
×
2917
        }
2918
      }
2919
      if (funcIdx > pValCtxArray->size) {
1,597,605✔
UNCOV
2920
        qError("funcIdx:%d is out of range", funcIdx);
×
2921
        taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
UNCOV
2922
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2923
      }
2924
      SSubsidiaryResInfo* pSubsidiary = &pCtx[i].subsidiaries;
1,599,361✔
2925
      pSubsidiary->pCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
1,598,086✔
2926
      if (pSubsidiary->pCtx == NULL) {
1,604,629✔
2927
        taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
UNCOV
2928
        return terrno;
×
2929
      }
2930
      pSubsidiary->num = 0;
1,597,166✔
2931
      taosArraySet(pValCtxArray, funcIdx - 1, &pSubsidiary);
1,602,434✔
2932
    }
2933
  }
2934

2935
  SqlFunctionCtx*  p = NULL;
452,386,532✔
2936
  SqlFunctionCtx** pValCtx = NULL;
452,386,532✔
2937
  if (pValCtxArray == NULL) {
452,386,532✔
2938
    pValCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
451,239,931✔
2939
    if (pValCtx == NULL) {
451,646,318✔
UNCOV
2940
      QUERY_CHECK_CODE(terrno, lino, _end);
×
2941
    }
2942
  }
2943

2944
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,644,982,133✔
2945
    const char* pName = pCtx[i].pExpr->pExpr->_function.functionName;
1,191,566,048✔
2946
    if ((strcmp(pName, "_select_value") == 0)) {
1,192,315,722✔
2947
      if (pValCtxArray == NULL) {
8,907,892✔
2948
        pValCtx[num++] = &pCtx[i];
6,655,883✔
2949
      } else {
2950
        int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->relatedTo;  // start from index 1;
2,252,138✔
2951
        if (bindFuncIndex > 0) {                                  // 0 is default index related to the select function
2,248,687✔
2952
          bindFuncIndex -= 1;
2,197,763✔
2953
        }
2954
        SSubsidiaryResInfo** pSubsidiary = taosArrayGet(pValCtxArray, bindFuncIndex);
2,248,687✔
2955
        if (pSubsidiary == NULL) {
2,251,321✔
UNCOV
2956
          QUERY_CHECK_CODE(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR, lino, _end);
×
2957
        }
2958
        (*pSubsidiary)->pCtx[(*pSubsidiary)->num] = &pCtx[i];
2,251,321✔
2959
        (*pSubsidiary)->num++;
2,251,321✔
2960
      }
2961
    } else if (fmIsSelectFunc(pCtx[i].functionId)) {
1,183,407,830✔
2962
      if (pValCtxArray == NULL) {
126,288,547✔
2963
        p = &pCtx[i];
124,336,432✔
2964
      }
2965
    }
2966
  }
2967

2968
  if (p != NULL) {
453,416,085✔
2969
    p->subsidiaries.pCtx = pValCtx;
52,801,982✔
2970
    p->subsidiaries.num = num;
52,794,189✔
2971
  } else {
2972
    taosMemoryFreeClear(pValCtx);
400,614,103✔
2973
  }
2974

2975
_end:
1,730,612✔
2976
  if (code != TSDB_CODE_SUCCESS) {
452,680,837✔
UNCOV
2977
    taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
UNCOV
2978
    taosMemoryFreeClear(pValCtx);
×
UNCOV
2979
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2980
  } else {
2981
    taosArrayDestroy(pValCtxArray);
452,680,837✔
2982
  }
2983
  return code;
452,666,483✔
2984
}
2985

2986
SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, int32_t** rowEntryInfoOffset,
453,423,372✔
2987
                                     SFunctionStateStore* pStore) {
2988
  int32_t         code = TSDB_CODE_SUCCESS;
453,423,372✔
2989
  int32_t         lino = 0;
453,423,372✔
2990
  SqlFunctionCtx* pFuncCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
453,423,372✔
2991
  if (pFuncCtx == NULL) {
452,433,512✔
UNCOV
2992
    return NULL;
×
2993
  }
2994

2995
  *rowEntryInfoOffset = taosMemoryCalloc(numOfOutput, sizeof(int32_t));
452,433,512✔
2996
  if (*rowEntryInfoOffset == 0) {
453,357,307✔
2997
    taosMemoryFreeClear(pFuncCtx);
×
UNCOV
2998
    return NULL;
×
2999
  }
3000

3001
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,646,390,733✔
3002
    SExprInfo* pExpr = &pExprInfo[i];
1,193,181,393✔
3003

3004
    SExprBasicInfo* pFunct = &pExpr->base;
1,192,562,363✔
3005
    SqlFunctionCtx* pCtx = &pFuncCtx[i];
1,192,819,183✔
3006

3007
    pCtx->functionId = -1;
1,192,861,175✔
3008
    pCtx->pExpr = pExpr;
1,193,016,544✔
3009

3010
    if (pExpr->pExpr->nodeType == QUERY_NODE_FUNCTION) {
1,192,725,583✔
3011
      SFuncExecEnv env = {0};
454,589,048✔
3012
      pCtx->functionId = pExpr->pExpr->_function.pFunctNode->funcId;
454,728,161✔
3013
      pCtx->isPseudoFunc = fmIsWindowPseudoColumnFunc(pCtx->functionId) || fmIsPlaceHolderFunc(pCtx->functionId);
454,722,775✔
3014
      pCtx->isNotNullFunc = fmIsNotNullOutputFunc(pCtx->functionId);
454,787,348✔
3015

3016
      bool isUdaf = fmIsUserDefinedFunc(pCtx->functionId);
454,517,047✔
3017
      if (fmIsAggFunc(pCtx->functionId) || fmIsIndefiniteRowsFunc(pCtx->functionId) ||
598,221,881✔
3018
          fmIsProcessByRowFunc(pCtx->functionId)) {
454,365,449✔
3019
        if (!isUdaf) {
310,141,965✔
3020
          code = fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet);
310,105,506✔
3021
          QUERY_CHECK_CODE(code, lino, _end);
309,839,418✔
3022
        } else {
3023
          char* udfName = pExpr->pExpr->_function.pFunctNode->functionName;
36,459✔
3024
          pCtx->udfName = taosStrdup(udfName);
36,459✔
3025
          QUERY_CHECK_NULL(pCtx->udfName, code, lino, _end, terrno);
36,459✔
3026

3027
          code = fmGetUdafExecFuncs(pCtx->functionId, &pCtx->fpSet);
36,459✔
3028
          QUERY_CHECK_CODE(code, lino, _end);
36,459✔
3029
        }
3030
        bool tmp = pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
309,875,877✔
3031
        if (!tmp) {
309,882,201✔
UNCOV
3032
          code = terrno;
×
3033
          QUERY_CHECK_CODE(code, lino, _end);
8,986✔
3034
        }
3035
      } else {
3036
        if (fmIsPlaceHolderFunc(pCtx->functionId)) {
144,147,548✔
3037
          code = fmGetStreamPesudoFuncEnv(pCtx->functionId, pExpr->base.pParamList, &env);
7,545,528✔
3038
          QUERY_CHECK_CODE(code, lino, _end);
7,546,758✔
3039
        }      
3040
        
3041
        code = fmGetScalarFuncExecFuncs(pCtx->functionId, &pCtx->sfp);
144,238,663✔
3042
        if (code != TSDB_CODE_SUCCESS && isUdaf) {
144,431,332✔
3043
          code = TSDB_CODE_SUCCESS;
59,748✔
3044
        }
3045
        QUERY_CHECK_CODE(code, lino, _end);
144,431,332✔
3046

3047
        if (pCtx->sfp.getEnv != NULL) {
144,431,332✔
3048
          bool tmp = pCtx->sfp.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
29,019,744✔
3049
          if (!tmp) {
29,030,872✔
UNCOV
3050
            code = terrno;
×
UNCOV
3051
            QUERY_CHECK_CODE(code, lino, _end);
×
3052
          }
3053
        }
3054
      }
3055
      pCtx->resDataInfo.interBufSize = env.calcMemSize;
454,269,804✔
3056
    } else if (pExpr->pExpr->nodeType == QUERY_NODE_COLUMN || pExpr->pExpr->nodeType == QUERY_NODE_OPERATOR ||
738,023,292✔
3057
               pExpr->pExpr->nodeType == QUERY_NODE_VALUE) {
19,344,261✔
3058
      // for simple column, the result buffer needs to hold at least one element.
3059
      pCtx->resDataInfo.interBufSize = pFunct->resSchema.bytes;
738,461,583✔
3060
    }
3061

3062
    pCtx->input.numOfInputCols = pFunct->numOfParams;
1,192,606,733✔
3063
    pCtx->input.pData = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
1,192,566,942✔
3064
    QUERY_CHECK_NULL(pCtx->input.pData, code, lino, _end, terrno);
1,193,118,019✔
3065
    pCtx->input.pColumnDataAgg = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
1,192,502,444✔
3066
    QUERY_CHECK_NULL(pCtx->input.pColumnDataAgg, code, lino, _end, terrno);
1,192,990,550✔
3067

3068
    pCtx->pTsOutput = NULL;
1,192,427,165✔
3069
    pCtx->resDataInfo.bytes = pFunct->resSchema.bytes;
1,192,375,600✔
3070
    pCtx->resDataInfo.type = pFunct->resSchema.type;
1,192,947,577✔
3071
    pCtx->order = TSDB_ORDER_ASC;
1,192,534,918✔
3072
    pCtx->start.key = INT64_MIN;
1,192,546,669✔
3073
    pCtx->end.key = INT64_MIN;
1,192,613,430✔
3074
    pCtx->numOfParams = pExpr->base.numOfParams;
1,193,076,078✔
3075
    pCtx->param = pFunct->pParam;
1,193,035,993✔
3076
    pCtx->saveHandle.currentPage = -1;
1,193,267,897✔
3077
    pCtx->pStore = pStore;
1,193,428,496✔
3078
    pCtx->hasWindowOrGroup = false;
1,192,890,173✔
3079
    pCtx->needCleanup = false;
1,192,412,293✔
3080
    pCtx->skipDynDataCheck = false;
1,193,068,875✔
3081
  }
3082

3083
  for (int32_t i = 1; i < numOfOutput; ++i) {
1,226,214,235✔
3084
    (*rowEntryInfoOffset)[i] = (int32_t)((*rowEntryInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) +
1,543,464,581✔
3085
                                         pFuncCtx[i - 1].resDataInfo.interBufSize);
773,389,314✔
3086
  }
3087

3088
  code = setSelectValueColumnInfo(pFuncCtx, numOfOutput);
452,705,155✔
3089
  QUERY_CHECK_CODE(code, lino, _end);
452,613,822✔
3090

3091
_end:
452,613,822✔
3092
  if (code != TSDB_CODE_SUCCESS) {
452,594,498✔
UNCOV
3093
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
UNCOV
3094
    for (int32_t i = 0; i < numOfOutput; ++i) {
×
UNCOV
3095
      taosMemoryFree(pFuncCtx[i].input.pData);
×
UNCOV
3096
      taosMemoryFree(pFuncCtx[i].input.pColumnDataAgg);
×
3097
    }
UNCOV
3098
    taosMemoryFreeClear(*rowEntryInfoOffset);
×
3099
    taosMemoryFreeClear(pFuncCtx);
×
3100

3101
    terrno = code;
×
3102
    return NULL;
×
3103
  }
3104
  return pFuncCtx;
452,594,498✔
3105
}
3106

3107
// NOTE: sources columns are more than the destination SSDatablock columns.
3108
// doFilter in table scan needs every column even its output is false
3109
int32_t relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols, bool outputEveryColumn) {
17,125,174✔
3110
  int32_t code = TSDB_CODE_SUCCESS;
17,125,174✔
3111
  size_t  numOfSrcCols = taosArrayGetSize(pCols);
17,125,174✔
3112

3113
  int32_t i = 0, j = 0;
17,127,497✔
3114
  while (i < numOfSrcCols && j < taosArrayGetSize(pColMatchInfo)) {
140,811,062✔
3115
    SColumnInfoData* p = taosArrayGet(pCols, i);
123,685,789✔
3116
    if (!p) {
123,687,202✔
UNCOV
3117
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3118
      return terrno;
×
3119
    }
3120
    SColMatchItem* pmInfo = taosArrayGet(pColMatchInfo, j);
123,687,202✔
3121
    if (!pmInfo) {
123,685,463✔
UNCOV
3122
      return terrno;
×
3123
    }
3124

3125
    if (p->info.colId == pmInfo->colId) {
123,685,463✔
3126
      SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, pmInfo->dstSlotId);
116,503,912✔
3127
      if (!pDst) {
116,499,304✔
3128
        return terrno;
×
3129
      }
3130
      code = colDataAssign(pDst, p, pBlock->info.rows, &pBlock->info);
116,499,304✔
3131
      if (code != TSDB_CODE_SUCCESS) {
116,497,019✔
UNCOV
3132
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
3133
        return code;
×
3134
      }
3135
      i++;
116,497,019✔
3136
      j++;
116,497,019✔
3137
    } else if (p->info.colId < pmInfo->colId) {
7,185,565✔
3138
      i++;
7,186,546✔
3139
    } else {
UNCOV
3140
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
UNCOV
3141
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3142
    }
3143
  }
3144
  return code;
17,128,178✔
3145
}
3146

3147
SInterval extractIntervalInfo(const STableScanPhysiNode* pTableScanNode) {
247,340,173✔
3148
  SInterval interval = {
494,408,111✔
3149
      .interval = pTableScanNode->interval,
247,343,669✔
3150
      .sliding = pTableScanNode->sliding,
247,237,414✔
3151
      .intervalUnit = pTableScanNode->intervalUnit,
247,478,541✔
3152
      .slidingUnit = pTableScanNode->slidingUnit,
247,393,167✔
3153
      .offset = pTableScanNode->offset,
247,532,781✔
3154
      .precision = pTableScanNode->scan.node.pOutputDataBlockDesc->precision,
247,463,720✔
3155
      .timeRange = pTableScanNode->scanRange,
3156
  };
3157
  calcIntervalAutoOffset(&interval);
247,090,288✔
3158

3159
  return interval;
247,704,772✔
3160
}
3161

3162
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
45,470,860✔
3163
  SColumn c = {0};
45,470,860✔
3164

3165
  c.slotId = pColNode->slotId;
45,470,860✔
3166
  c.colId = pColNode->colId;
45,471,821✔
3167
  c.type = pColNode->node.resType.type;
45,486,594✔
3168
  c.bytes = pColNode->node.resType.bytes;
45,473,796✔
3169
  c.scale = pColNode->node.resType.scale;
45,447,124✔
3170
  c.precision = pColNode->node.resType.precision;
45,472,952✔
3171
  return c;
45,437,138✔
3172
}
3173

3174

3175
/**
3176
 * @brief Determine the actual time range for reading data based on the RANGE clause and the WHERE conditions.
3177
 * @param[in] cond The range specified by WHERE condition.
3178
 * @param[in] range The range specified by RANGE clause.
3179
 * @param[out] twindow The range to be read in DESC order, and only one record is needed.
3180
 * @param[out] extTwindow The external range to read for only one record, which is used for FILL clause.
3181
 * @note `cond` and `twindow` may be the same address.
3182
 */
3183
static int32_t getQueryExtWindow(const STimeWindow* cond, const STimeWindow* range, STimeWindow* twindow,
3,364,864✔
3184
                                 STimeWindow* extTwindows) {
3185
  int32_t     code = TSDB_CODE_SUCCESS;
3,364,864✔
3186
  int32_t     lino = 0;
3,364,864✔
3187
  STimeWindow tempWindow;
3188

3189
  if (cond->skey > cond->ekey || range->skey > range->ekey) {
3,364,864✔
3190
    *twindow = extTwindows[0] = extTwindows[1] = TSWINDOW_DESC_INITIALIZER;
5,588✔
3191
    return code;
5,160✔
3192
  }
3193

3194
  if (range->ekey < cond->skey) {
3,360,132✔
3195
    extTwindows[1] = *cond;
540,540✔
3196
    *twindow = extTwindows[0] = TSWINDOW_DESC_INITIALIZER;
540,540✔
3197
    return code;
540,540✔
3198
  }
3199

3200
  if (cond->ekey < range->skey) {
2,819,592✔
3201
    extTwindows[0] = *cond;
353,268✔
3202
    *twindow = extTwindows[1] = TSWINDOW_DESC_INITIALIZER;
353,268✔
3203
    return code;
353,268✔
3204
  }
3205

3206
  // Only scan data in the time range intersecion.
3207
  extTwindows[0] = extTwindows[1] = *cond;
2,466,752✔
3208
  twindow->skey = TMAX(cond->skey, range->skey);
2,466,752✔
3209
  twindow->ekey = TMIN(cond->ekey, range->ekey);
2,466,752✔
3210
  extTwindows[0].ekey = twindow->skey - 1;
2,466,752✔
3211
  extTwindows[1].skey = twindow->ekey + 1;
2,466,324✔
3212

3213
  return code;
2,466,752✔
3214
}
3215

3216
static int32_t getPrimaryTimeRange(SNode** pPrimaryKeyCond, STimeWindow* pTimeRange, bool* isStrict) {
671,916✔
3217
  SNode*  pNew = NULL;
671,916✔
3218
  int32_t code = scalarCalculateRemoteConstants(*pPrimaryKeyCond, &pNew);
671,916✔
3219
  if (TSDB_CODE_SUCCESS == code) {
671,916✔
3220
    *pPrimaryKeyCond = pNew;
671,916✔
3221
    if (nodeType(pNew) != QUERY_NODE_VALUE) {
671,916✔
3222
      code = filterGetTimeRange(*pPrimaryKeyCond, pTimeRange, isStrict, NULL);
671,916✔
3223
    }
3224
  }
3225
  return code;
671,916✔
3226
}
3227

3228
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, STableScanPhysiNode* pTableScanNode,
277,687,373✔
3229
                               const SReadHandle* readHandle, bool applyExtWin) {
3230
  int32_t code = 0;                             
277,687,373✔
3231
  pCond->order = pTableScanNode->scanSeq[0] > 0 ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
277,687,373✔
3232
  pCond->numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols);
277,762,736✔
3233

3234
  pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
277,530,627✔
3235
  if (!pCond->colList) {
277,427,566✔
UNCOV
3236
    return terrno;
×
3237
  }
3238
  pCond->pSlotList = taosMemoryMalloc(sizeof(int32_t) * pCond->numOfCols);
277,065,621✔
3239
  if (pCond->pSlotList == NULL) {
277,421,541✔
UNCOV
3240
    taosMemoryFreeClear(pCond->colList);
×
UNCOV
3241
    return terrno;
×
3242
  }
3243

3244
  // TODO: get it from stable scan node
3245
  pCond->twindows = pTableScanNode->scanRange;
276,750,279✔
3246
  pCond->suid = pTableScanNode->scan.suid;
277,713,644✔
3247
  pCond->type = TIMEWINDOW_RANGE_CONTAINED;
276,963,938✔
3248
  pCond->startVersion = -1;
277,061,846✔
3249
  pCond->endVersion = -1;
276,921,640✔
3250
  pCond->skipRollup = readHandle->skipRollup;
277,118,879✔
3251
  if (readHandle->winRangeValid) {
276,851,442✔
3252
    pCond->twindows = readHandle->winRange;
1,150,159✔
3253
  }
3254
  pCond->cacheSttStatis = readHandle->cacheSttStatis;
277,481,343✔
3255
  // allowed read stt file optimization mode
3256
  pCond->notLoadData = (pTableScanNode->dataRequired == FUNC_DATA_REQUIRED_NOT_LOAD) &&
554,612,239✔
3257
                       (pTableScanNode->scan.node.pConditions == NULL) && (pTableScanNode->interval == 0);
276,595,236✔
3258

3259
  int32_t j = 0;
277,465,530✔
3260
  SNode*  node = NULL;
277,465,530✔
3261
  FOREACH(node, pTableScanNode->scan.pScanCols) {
1,311,548,041✔
3262
    STargetNode* pNode = (STargetNode*)node;
1,032,537,676✔
3263
    if (!pNode) {
1,032,537,676✔
UNCOV
3264
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3265
      return terrno;
×
3266
    }
3267
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
1,032,537,676✔
3268
    if (pColNode->colType == COLUMN_TYPE_TAG) {
1,033,254,195✔
UNCOV
3269
      continue;
×
3270
    }
3271

3272
    pCond->colList[j].type = pColNode->node.resType.type;
1,033,865,023✔
3273
    pCond->colList[j].bytes = pColNode->node.resType.bytes;
1,033,570,557✔
3274
    pCond->colList[j].colId = pColNode->colId;
1,033,881,704✔
3275
    pCond->colList[j].pk = pColNode->isPk;
1,034,009,262✔
3276

3277
    pCond->pSlotList[j] = pNode->slotId;
1,033,563,009✔
3278
    j += 1;
1,034,082,511✔
3279
  }
3280

3281
  pCond->numOfCols = j;
277,795,412✔
3282

3283
  if (applyExtWin) {
277,842,878✔
3284
    if (NULL != pTableScanNode->pExtScanRange) {
249,619,305✔
3285
      pCond->type = TIMEWINDOW_RANGE_EXTERNAL;
3,292,448✔
3286
      code = getQueryExtWindow(&pCond->twindows, pTableScanNode->pExtScanRange, &pCond->twindows, pCond->extTwindows);
3,292,448✔
3287
    } else if (readHandle->extWinRangeValid) {
245,388,127✔
3288
      pCond->type = TIMEWINDOW_RANGE_EXTERNAL;
73,272✔
3289
      code = getQueryExtWindow(&pCond->twindows, &readHandle->extWinRange, &pCond->twindows, pCond->extTwindows);
73,272✔
3290
    }
3291
  }
3292

3293
  if (pTableScanNode->pPrimaryCond) {
276,863,160✔
3294
    bool isStrict = false;
671,916✔
3295
    code = getPrimaryTimeRange((SNode**)&pTableScanNode->pPrimaryCond, &pCond->twindows, &isStrict);
671,916✔
3296
    if (code || !isStrict) {
671,916✔
3297
      code = nodesMergeNode((SNode**)&pTableScanNode->scan.node.pConditions, &pTableScanNode->pPrimaryCond);
659,908✔
3298
    }
3299
  }
3300

3301
  return code;
276,568,495✔
3302
}
3303

3304
int32_t initQueryTableDataCondWithColArray(SQueryTableDataCond* pCond, SQueryTableDataCond* pOrgCond,
144,414,580✔
3305
                                           const SReadHandle* readHandle, SArray* colArray) {
3306
  int32_t code = TSDB_CODE_SUCCESS;
144,414,580✔
3307
  int32_t lino = 0;
144,414,580✔
3308

3309
  pCond->order = TSDB_ORDER_ASC;
144,414,580✔
3310
  pCond->numOfCols = (int32_t)taosArrayGetSize(colArray);
144,493,094✔
3311

3312
  pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
144,489,615✔
3313
  QUERY_CHECK_NULL(pCond->colList, code, lino, _return, terrno);
144,420,046✔
3314

3315
  pCond->pSlotList = taosMemoryMalloc(sizeof(int32_t) * pCond->numOfCols);
144,431,555✔
3316
  QUERY_CHECK_NULL(pCond->pSlotList, code, lino, _return, terrno);
144,449,173✔
3317

3318
  pCond->twindows = pOrgCond->twindows;
144,440,439✔
3319
  pCond->order = pOrgCond->order;
144,447,855✔
3320
  pCond->type = pOrgCond->type;
144,501,703✔
3321
  pCond->startVersion = -1;
144,474,134✔
3322
  pCond->endVersion = -1;
144,482,488✔
3323
  pCond->skipRollup = true;
144,458,815✔
3324
  pCond->notLoadData = false;
144,467,373✔
3325

3326
  for (int32_t i = 0; i < pCond->numOfCols; ++i) {
620,541,717✔
3327
    SColIdPair* pColPair = taosArrayGet(colArray, i);
476,133,908✔
3328
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
476,104,393✔
3329

3330
    bool find = false;
476,086,180✔
3331
    for (int32_t j = 0; j < pOrgCond->numOfCols; ++j) {
2,147,483,647✔
3332
      if (pOrgCond->colList[j].colId == pColPair->vtbColId) {
2,147,483,647✔
3333
        pCond->colList[i].type = pOrgCond->colList[j].type;
476,074,113✔
3334
        // For variable-length types (nchar/binary/varchar/varbinary), use the source table's bytes
3335
        // to avoid tsdb reader doCopyColVal length check failure when source data is longer
3336
        // than the virtual table's defined length.
3337
        if (IS_VAR_DATA_TYPE(pOrgCond->colList[j].type) && pColPair->type.bytes > 0) {
476,106,930✔
3338
          pCond->colList[i].bytes = TMAX(pOrgCond->colList[j].bytes, pColPair->type.bytes);
61,652,279✔
3339
        } else {
3340
          pCond->colList[i].bytes = pOrgCond->colList[j].bytes;
414,529,118✔
3341
        }
3342
        pCond->colList[i].colId = pColPair->orgColId;
476,214,455✔
3343
        pCond->colList[i].pk = pOrgCond->colList[j].pk;
476,185,402✔
3344
        pCond->pSlotList[i] = i;
476,150,273✔
3345
        find = true;
476,177,597✔
3346
        qDebug("%s mapped vtb colId:%d to org colId:%d, type:%d, bytes:%d", __func__, pColPair->vtbColId,
476,177,597✔
3347
               pColPair->orgColId, pCond->colList[i].type, pCond->colList[i].bytes);
3348
        break;
476,084,161✔
3349
      }
3350
    }
3351
    QUERY_CHECK_CONDITION(find, code, lino, _return, TSDB_CODE_NOT_FOUND);
476,113,149✔
3352
  }
3353

3354
  return code;
144,536,553✔
UNCOV
3355
_return:
×
UNCOV
3356
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(terrno));
×
UNCOV
3357
  taosMemoryFreeClear(pCond->colList);
×
UNCOV
3358
  taosMemoryFreeClear(pCond->pSlotList);
×
UNCOV
3359
  return code;
×
3360
}
3361

3362
void cleanupQueryTableDataCond(SQueryTableDataCond* pCond) {
721,732,152✔
3363
  taosMemoryFreeClear(pCond->colList);
721,732,152✔
3364
  taosMemoryFreeClear(pCond->pSlotList);
721,842,304✔
3365
}
721,680,926✔
3366

3367
int32_t convertFillType(int32_t mode) {
3,996,653✔
3368
  int32_t type = TSDB_FILL_NONE;
3,996,653✔
3369
  switch (mode) {
3,996,653✔
3370
    case FILL_MODE_PREV:
193,554✔
3371
      type = TSDB_FILL_PREV;
193,554✔
3372
      break;
193,554✔
UNCOV
3373
    case FILL_MODE_NONE:
×
UNCOV
3374
      type = TSDB_FILL_NONE;
×
UNCOV
3375
      break;
×
3376
    case FILL_MODE_NULL:
170,586✔
3377
      type = TSDB_FILL_NULL;
170,586✔
3378
      break;
170,586✔
3379
    case FILL_MODE_NULL_F:
40,270✔
3380
      type = TSDB_FILL_NULL_F;
40,270✔
3381
      break;
40,270✔
3382
    case FILL_MODE_NEXT:
207,307✔
3383
      type = TSDB_FILL_NEXT;
207,307✔
3384
      break;
207,307✔
3385
    case FILL_MODE_VALUE:
169,097✔
3386
      type = TSDB_FILL_SET_VALUE;
169,097✔
3387
      break;
169,097✔
3388
    case FILL_MODE_VALUE_F:
12,186✔
3389
      type = TSDB_FILL_SET_VALUE_F;
12,186✔
3390
      break;
12,186✔
3391
    case FILL_MODE_LINEAR:
240,241✔
3392
      type = TSDB_FILL_LINEAR;
240,241✔
3393
      break;
240,241✔
3394
    case FILL_MODE_NEAR:
2,962,172✔
3395
      type = TSDB_FILL_NEAR;
2,962,172✔
3396
      break;
2,962,172✔
3397
    default:
1,240✔
3398
      type = TSDB_FILL_NONE;
1,240✔
3399
  }
3400

3401
  return type;
3,996,653✔
3402
}
3403

3404
void getInitialStartTimeWindow(SInterval* pInterval, TSKEY ts, STimeWindow* w, bool ascQuery) {
2,147,483,647✔
3405
  if (ascQuery) {
2,147,483,647✔
3406
    *w = getAlignQueryTimeWindow(pInterval, ts);
2,147,483,647✔
3407
  } else {
3408
    // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
3409
    *w = getAlignQueryTimeWindow(pInterval, ts);
30,226✔
3410

3411
    int64_t key = w->skey;
309,912✔
3412
    while (key < ts) {  // moving towards end
326,597✔
3413
      key = getNextTimeWindowStart(pInterval, key, TSDB_ORDER_ASC);
165,983✔
3414
      if (key > ts) {
165,042✔
3415
        break;
148,357✔
3416
      }
3417

3418
      w->skey = key;
16,685✔
3419
    }
3420
    w->ekey = taosTimeAdd(w->skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1;
308,971✔
3421
  }
3422
}
2,147,483,647✔
3423

3424
static STimeWindow doCalculateTimeWindow(int64_t ts, SInterval* pInterval) {
76,127,377✔
3425
  STimeWindow w = {0};
76,127,377✔
3426

3427
  w.skey = taosTimeTruncate(ts, pInterval);
76,127,377✔
3428
  w.ekey = taosTimeGetIntervalEnd(w.skey, pInterval);
76,106,045✔
3429
  return w;
76,162,881✔
3430
}
3431

3432
STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order) {
1,545,125✔
3433
  STimeWindow win = *pWindow;
1,545,125✔
3434
  STimeWindow save = win;
1,545,125✔
3435
  while (win.skey <= ts && win.ekey >= ts) {
8,558,432✔
3436
    save = win;
7,013,307✔
3437
    // get previous time window
3438
    getNextTimeWindow(pInterval, &win, order == TSDB_ORDER_DESC ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
7,013,307✔
3439
  }
3440

3441
  return save;
1,545,125✔
3442
}
3443

3444
// get the correct time window according to the handled timestamp
3445
// todo refactor
3446
STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval,
117,000,879✔
3447
                                int32_t order) {
3448
  STimeWindow w = {0};
117,000,879✔
3449
  if (pResultRowInfo->cur.pageId == -1) {  // the first window, from the previous stored value
117,029,720✔
3450
    getInitialStartTimeWindow(pInterval, ts, &w, (order != TSDB_ORDER_DESC));
3,387,058✔
3451
    return w;
3,391,883✔
3452
  }
3453

3454
  SResultRow* pRow = getResultRowByPos(pBuf, &pResultRowInfo->cur, false);
113,641,054✔
3455
  if (pRow) {
113,644,526✔
3456
    TAOS_SET_OBJ_ALIGNED(&w, pRow->win);
113,658,492✔
3457
  }
3458

3459
  // in case of typical time window, we can calculate time window directly.
3460
  if (w.skey > ts || w.ekey < ts) {
113,657,207✔
3461
    w = doCalculateTimeWindow(ts, pInterval);
76,140,558✔
3462
  }
3463

3464
  if (pInterval->interval != pInterval->sliding) {
113,679,530✔
3465
    // it is an sliding window query, in which sliding value is not equalled to
3466
    // interval value, and we need to find the first qualified time window.
3467
    w = getFirstQualifiedTimeWindow(ts, &w, pInterval, order);
1,544,571✔
3468
  }
3469

3470
  return w;
113,643,546✔
3471
}
3472

3473
void getNextTimeWindow(const SInterval* pInterval, STimeWindow* tw, int32_t order) {
2,147,483,647✔
3474
  tw->skey = getNextTimeWindowStart(pInterval, tw->skey, order);
2,147,483,647✔
3475
  tw->ekey = taosTimeGetIntervalEnd(tw->skey, pInterval);
2,147,483,647✔
3476
}
2,147,483,647✔
3477

3478
bool hasLimitOffsetInfo(SLimitInfo* pLimitInfo) {
527,643,169✔
3479
  return (pLimitInfo->limit.limit != -1 || pLimitInfo->limit.offset != -1 || pLimitInfo->slimit.limit != -1 ||
1,051,044,703✔
3480
          pLimitInfo->slimit.offset != -1);
523,401,250✔
3481
}
3482

UNCOV
3483
bool hasSlimitOffsetInfo(SLimitInfo* pLimitInfo) {
×
UNCOV
3484
  return (pLimitInfo->slimit.limit != -1 || pLimitInfo->slimit.offset != -1);
×
3485
}
3486

3487
void initLimitInfo(const SNode* pLimit, const SNode* pSLimit, SLimitInfo* pLimitInfo) {
680,025,352✔
3488
  SLimit limit = {.limit = getLimit(pLimit), .offset = getOffset(pLimit)};
680,025,352✔
3489
  SLimit slimit = {.limit = getLimit(pSLimit), .offset = getOffset(pSLimit)};
679,447,928✔
3490

3491
  pLimitInfo->limit = limit;
679,277,839✔
3492
  pLimitInfo->slimit = slimit;
679,422,661✔
3493
  pLimitInfo->remainOffset = limit.offset;
679,549,928✔
3494
  pLimitInfo->remainGroupOffset = slimit.offset;
679,475,643✔
3495
  pLimitInfo->numOfOutputRows = 0;
679,634,346✔
3496
  pLimitInfo->numOfOutputGroups = 0;
679,524,772✔
3497
  pLimitInfo->currentGroupId = 0;
679,739,263✔
3498
}
679,755,236✔
3499

3500
void resetLimitInfoForNextGroup(SLimitInfo* pLimitInfo) {
94,998,492✔
3501
  pLimitInfo->numOfOutputRows = 0;
94,998,492✔
3502
  pLimitInfo->remainOffset = pLimitInfo->limit.offset;
95,097,559✔
3503
}
95,074,906✔
3504

3505
int32_t tableListGetSize(const STableListInfo* pTableList, int32_t* pRes) {
722,447,124✔
3506
  if (taosArrayGetSize(pTableList->pTableList) != taosHashGetSize(pTableList->map)) {
722,447,124✔
UNCOV
3507
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
UNCOV
3508
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3509
  }
3510
  (*pRes) = taosArrayGetSize(pTableList->pTableList);
722,237,858✔
3511
  return TSDB_CODE_SUCCESS;
722,173,483✔
3512
}
3513

3514
uint64_t tableListGetSuid(const STableListInfo* pTableList) { return pTableList->idInfo.suid; }
4,283,421✔
3515

3516
STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index) {
222,761,725✔
3517
  if (taosArrayGetSize(pTableList->pTableList) == 0) {
222,761,725✔
3518
    return NULL;
2,178✔
3519
  }
3520

3521
  return taosArrayGet(pTableList->pTableList, index);
222,686,058✔
3522
}
3523

3524
int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t startIndex) {
48,628✔
3525
  int32_t numOfTables = taosArrayGetSize(pTableList->pTableList);
48,628✔
3526
  if (startIndex >= numOfTables) {
48,628✔
UNCOV
3527
    return -1;
×
3528
  }
3529

3530
  for (int32_t i = startIndex; i < numOfTables; ++i) {
550,714✔
3531
    STableKeyInfo* p = taosArrayGet(pTableList->pTableList, i);
550,714✔
3532
    if (!p) {
550,714✔
3533
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3534
      return -1;
×
3535
    }
3536
    if (p->uid == uid) {
550,714✔
3537
      return i;
48,628✔
3538
    }
3539
  }
3540
  return -1;
×
3541
}
3542

3543
void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type) {
442,831✔
3544
  *psuid = pTableList->idInfo.suid;
442,831✔
3545
  *uid = pTableList->idInfo.uid;
442,831✔
3546
  *type = pTableList->idInfo.tableType;
442,831✔
3547
}
442,831✔
3548

3549
int32_t tableListGetTableGroupId(const STableListInfo* pTableList, uint64_t tableUid, uint64_t* gid, uint64_t* baseGid) {
883,777,730✔
3550
  int32_t* slot = taosHashGet(pTableList->map, &tableUid, sizeof(tableUid));
883,777,730✔
3551
  if (slot == NULL) {
883,927,929✔
UNCOV
3552
    qDebug("table:%" PRIu64 " not found in table list", tableUid);
×
NEW
3553
    return TSDB_CODE_PAR_TABLE_NOT_EXIST;
×
3554
  }
3555

3556
  STableKeyInfo* pKeyInfo = taosArrayGet(pTableList->pTableList, *slot);
883,927,929✔
3557
  if (pKeyInfo == NULL) {
885,035,758✔
3558
    qDebug("table:%" PRIu64 " not found in table list", tableUid);
59✔
NEW
3559
    return TSDB_CODE_PAR_TABLE_NOT_EXIST;
×
3560
  }
3561

3562
  *gid = pKeyInfo->groupId;
885,035,699✔
3563
  *baseGid = pKeyInfo->baseGId;
885,006,604✔
3564
  
3565
  return 0;
884,888,976✔
3566
}
3567

3568
// TODO handle the group offset info, fix it, the rule of group output will be broken by this function
3569
// int32_t tableListRemoveTableInfo(STableListInfo* pTableList, uint64_t uid) {
3570
//   int32_t code = TSDB_CODE_SUCCESS;
3571
//   int32_t lino = 0;
3572

3573
//   int32_t* slot = taosHashGet(pTableList->map, &uid, sizeof(uid));
3574
//   if (slot == NULL) {
3575
//     qDebug("table:%" PRIu64 " not found in table list", uid);
3576
//     return 0;
3577
//   }
3578

3579
//   taosArrayRemove(pTableList->pTableList, *slot);
3580
//   code = taosHashRemove(pTableList->map, &uid, sizeof(uid));
3581

3582
//   _end:
3583
//   if (code != TSDB_CODE_SUCCESS) {
3584
//     qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
3585
//   } else {
3586
//     qDebug("uid:%" PRIu64 ", remove from table list", uid);
3587
//   }
3588

3589
//   return code;
3590
// }
3591

3592
int32_t tableListAddTableInfo(STableListInfo* pTableList, uint64_t uid, uint64_t gid) {
1,265,796✔
3593
  int32_t code = TSDB_CODE_SUCCESS;
1,265,796✔
3594
  int32_t lino = 0;
1,265,796✔
3595
  if (pTableList->map == NULL) {
1,265,796✔
UNCOV
3596
    pTableList->map = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
×
UNCOV
3597
    QUERY_CHECK_NULL(pTableList->map, code, lino, _end, terrno);
×
3598
  }
3599

3600
  STableKeyInfo keyInfo = {.uid = uid, .groupId = gid};
1,269,948✔
3601
  void*         p = taosHashGet(pTableList->map, &uid, sizeof(uid));
1,269,943✔
3602
  if (p != NULL) {
1,265,725✔
UNCOV
3603
    qInfo("table:%" PRId64 " already in tableIdList, ignore it", uid);
×
UNCOV
3604
    goto _end;
×
3605
  }
3606

3607
  void* tmp = taosArrayPush(pTableList->pTableList, &keyInfo);
1,265,725✔
3608
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,271,790✔
3609

3610
  int32_t slot = (int32_t)taosArrayGetSize(pTableList->pTableList) - 1;
1,271,790✔
3611
  code = taosHashPut(pTableList->map, &uid, sizeof(uid), &slot, sizeof(slot));
1,272,430✔
3612
  if (code != TSDB_CODE_SUCCESS) {
1,273,069✔
3613
    // we have checked the existence of uid in hash map above
3614
    QUERY_CHECK_CONDITION((code != TSDB_CODE_DUP_KEY), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
UNCOV
3615
    taosArrayPopTailBatch(pTableList->pTableList, 1);  // let's pop the last element in the array list
×
3616
  }
3617

3618
_end:
1,273,069✔
3619
  if (code != TSDB_CODE_SUCCESS) {
1,265,676✔
UNCOV
3620
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3621
  } else {
3622
    qDebug("uid:%" PRIu64 ", groupId:%" PRIu64 " added into table list, slot:%d, total:%d", uid, gid, slot, slot + 1);
1,265,676✔
3623
  }
3624

3625
  return code;
1,273,660✔
3626
}
3627

3628
int32_t tableListGetGroupList(const STableListInfo* pTableList, int32_t ordinalGroupIndex, STableKeyInfo** pKeyInfo,
285,365,895✔
3629
                              int32_t* size) {
3630
  int32_t totalGroups = tableListGetOutputGroups(pTableList);
285,365,895✔
3631
  int32_t numOfTables = 0;
285,361,445✔
3632
  int32_t code = tableListGetSize(pTableList, &numOfTables);
285,345,634✔
3633
  if (code != TSDB_CODE_SUCCESS) {
285,351,697✔
UNCOV
3634
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
3635
    return code;
×
3636
  }
3637

3638
  if (ordinalGroupIndex < 0 || ordinalGroupIndex >= totalGroups) {
285,351,697✔
UNCOV
3639
    return TSDB_CODE_INVALID_PARA;
×
3640
  }
3641

3642
  // here handle two special cases:
3643
  // 1. only one group exists, and 2. one table exists for each group.
3644
  if (totalGroups == 1) {
285,351,697✔
3645
    *size = numOfTables;
284,914,548✔
3646
    *pKeyInfo = (*size == 0) ? NULL : taosArrayGet(pTableList->pTableList, 0);
285,006,841✔
3647
    return TSDB_CODE_SUCCESS;
284,789,753✔
3648
  } else if (totalGroups == numOfTables) {
437,358✔
3649
    *size = 1;
478,862✔
3650
    *pKeyInfo = taosArrayGet(pTableList->pTableList, ordinalGroupIndex);
479,254✔
3651
    return TSDB_CODE_SUCCESS;
478,422✔
3652
  }
3653

UNCOV
3654
  int32_t offset = pTableList->groupOffset[ordinalGroupIndex];
×
3655
  if (ordinalGroupIndex < totalGroups - 1) {
59,753✔
3656
    *size = pTableList->groupOffset[ordinalGroupIndex + 1] - offset;
44,972✔
3657
  } else {
3658
    *size = numOfTables - offset;
14,781✔
3659
  }
3660

3661
  *pKeyInfo = taosArrayGet(pTableList->pTableList, offset);
59,753✔
3662
  return TSDB_CODE_SUCCESS;
59,753✔
3663
}
3664

3665
int32_t tableListGetOutputGroups(const STableListInfo* pTableList) { return pTableList->numOfOuputGroups; }
769,525,265✔
3666

3667
bool oneTableForEachGroup(const STableListInfo* pTableList) { return pTableList->oneTableForEachGroup; }
981,269✔
3668

3669
STableListInfo* tableListCreate() {
307,887,128✔
3670
  STableListInfo* pListInfo = taosMemoryCalloc(1, sizeof(STableListInfo));
307,887,128✔
3671
  if (pListInfo == NULL) {
307,515,083✔
UNCOV
3672
    return NULL;
×
3673
  }
3674

3675
  pListInfo->remainGroups = NULL;
307,515,083✔
3676
  pListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
307,531,814✔
3677
  if (pListInfo->pTableList == NULL) {
307,766,342✔
UNCOV
3678
    goto _error;
×
3679
  }
3680

3681
  pListInfo->map = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK);
307,685,462✔
3682
  if (pListInfo->map == NULL) {
308,247,201✔
UNCOV
3683
    goto _error;
×
3684
  }
3685

3686
  pListInfo->numOfOuputGroups = 1;
308,211,705✔
3687
  return pListInfo;
308,232,616✔
3688

UNCOV
3689
_error:
×
UNCOV
3690
  tableListDestroy(pListInfo);
×
UNCOV
3691
  return NULL;
×
3692
}
3693

3694
void tableListDestroy(STableListInfo* pTableListInfo) {
319,402,929✔
3695
  if (pTableListInfo == NULL) {
319,402,929✔
3696
    return;
11,439,638✔
3697
  }
3698

3699
  taosArrayDestroy(pTableListInfo->pTableList);
307,963,291✔
3700
  taosMemoryFreeClear(pTableListInfo->groupOffset);
307,971,144✔
3701

3702
  taosHashCleanup(pTableListInfo->map);
307,950,099✔
3703
  taosHashCleanup(pTableListInfo->remainGroups);
308,099,382✔
3704
  pTableListInfo->pTableList = NULL;
308,149,938✔
3705
  pTableListInfo->map = NULL;
308,096,659✔
3706
  taosMemoryFree(pTableListInfo);
308,004,149✔
3707
}
3708

3709
void tableListClear(STableListInfo* pTableListInfo) {
772,486✔
3710
  if (pTableListInfo == NULL) {
772,486✔
UNCOV
3711
    return;
×
3712
  }
3713

3714
  taosArrayClear(pTableListInfo->pTableList);
772,486✔
3715
  taosHashClear(pTableListInfo->map);
775,628✔
3716
  taosHashClear(pTableListInfo->remainGroups);
778,233✔
3717
  taosMemoryFree(pTableListInfo->groupOffset);
778,233✔
3718
  pTableListInfo->numOfOuputGroups = 1;
776,956✔
3719
  pTableListInfo->oneTableForEachGroup = false;
777,275✔
3720
}
3721

3722
static int32_t orderbyGroupIdComparFn(const void* p1, const void* p2) {
582,631,611✔
3723
  STableKeyInfo* pInfo1 = (STableKeyInfo*)p1;
582,631,611✔
3724
  STableKeyInfo* pInfo2 = (STableKeyInfo*)p2;
582,631,611✔
3725

3726
  if (pInfo1->groupId == pInfo2->groupId) {
582,631,611✔
3727
    return 0;
546,247,663✔
3728
  } else {
3729
    return pInfo1->groupId < pInfo2->groupId ? -1 : 1;
36,419,535✔
3730
  }
3731
}
3732

3733
int32_t sortTableGroup(STableListInfo* pTableListInfo) {
28,615,773✔
3734
  int32_t code = TSDB_CODE_SUCCESS;
28,615,773✔
3735
  taosArraySort(pTableListInfo->pTableList, orderbyGroupIdComparFn);
28,615,773✔
3736
  int32_t size = taosArrayGetSize(pTableListInfo->pTableList);
28,772,827✔
3737
  if (size == 0) {
28,745,748✔
UNCOV
3738
    pTableListInfo->numOfOuputGroups = 0;
×
UNCOV
3739
    return code;
×
3740
  }
3741

3742
  SArray* pList = taosArrayInit(4, sizeof(int32_t));
28,745,748✔
3743
  if (!pList) {
28,776,065✔
UNCOV
3744
    code = terrno;
×
UNCOV
3745
    goto end;
×
3746
  }
3747

3748
  STableKeyInfo* pInfo = taosArrayGet(pTableListInfo->pTableList, 0);
28,776,065✔
3749
  if (pInfo == NULL) {
28,681,597✔
UNCOV
3750
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3751
    code = terrno;
×
UNCOV
3752
    goto end;
×
3753
  }
3754
  uint64_t gid = pInfo->groupId;
28,681,597✔
3755

3756
  int32_t start = 0;
28,683,139✔
3757
  void*   tmp = taosArrayPush(pList, &start);
28,771,386✔
3758
  if (tmp == NULL) {
28,771,386✔
UNCOV
3759
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3760
    code = terrno;
×
3761
    goto end;
×
3762
  }
3763

3764
  for (int32_t i = 1; i < size; ++i) {
159,891,774✔
3765
    pInfo = taosArrayGet(pTableListInfo->pTableList, i);
131,146,958✔
3766
    if (pInfo == NULL) {
131,122,082✔
UNCOV
3767
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3768
      code = terrno;
×
3769
      goto end;
×
3770
    }
3771
    if (pInfo->groupId != gid) {
131,122,082✔
3772
      tmp = taosArrayPush(pList, &i);
7,454,419✔
3773
      if (tmp == NULL) {
7,454,419✔
UNCOV
3774
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3775
        code = terrno;
×
UNCOV
3776
        goto end;
×
3777
      }
3778
      gid = pInfo->groupId;
7,454,419✔
3779
    }
3780
  }
3781

3782
  pTableListInfo->numOfOuputGroups = taosArrayGetSize(pList);
28,727,337✔
3783
  pTableListInfo->groupOffset = taosMemoryMalloc(sizeof(int32_t) * pTableListInfo->numOfOuputGroups);
28,733,996✔
3784
  if (pTableListInfo->groupOffset == NULL) {
28,703,062✔
3785
    code = terrno;
×
3786
    goto end;
×
3787
  }
3788

3789
  memcpy(pTableListInfo->groupOffset, taosArrayGet(pList, 0), sizeof(int32_t) * pTableListInfo->numOfOuputGroups);
28,647,077✔
3790

3791
end:
28,704,100✔
3792
  taosArrayDestroy(pList);
28,652,333✔
3793
  return code;
28,685,749✔
3794
}
3795

3796
int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SScanPhysiNode* pScanNode,
256,096,920✔
3797
                                    SNodeList* group, bool groupSort, uint8_t* digest, SStorageAPI* pAPI, SHashObj* groupIdMap, bool gIdFromBaseId) {
3798
  int32_t code = TSDB_CODE_SUCCESS;
256,096,920✔
3799

3800
  bool   groupByTbname = groupbyTbname(group);
256,096,920✔
3801
  size_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
255,976,305✔
3802
  if (!numOfTables) {
255,991,651✔
UNCOV
3803
    return code;
×
3804
  }
3805
  qDebug("numOfTables:%zu, groupByTbname:%d, group:%p", numOfTables, groupByTbname, group);
255,991,651✔
3806
  if (group == NULL || groupByTbname) {
255,968,004✔
3807
    if (tsCountAlwaysReturnValue && QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode) &&
251,390,262✔
3808
        ((STableScanPhysiNode*)pScanNode)->needCountEmptyTable) {
207,307,098✔
3809
      pTableListInfo->remainGroups =
12,394,593✔
3810
          taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
12,395,685✔
3811
      if (pTableListInfo->remainGroups == NULL) {
12,395,139✔
UNCOV
3812
        return terrno;
×
3813
      }
3814

3815
      for (int i = 0; i < numOfTables; i++) {
70,469,808✔
3816
        STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
58,078,798✔
3817
        if (!info) {
58,069,646✔
UNCOV
3818
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3819
          return terrno;
×
3820
        }
3821
        info->groupId = groupByTbname ? info->uid : 0;
58,069,646✔
3822
        int32_t tempRes = taosHashPut(pTableListInfo->remainGroups, &(info->groupId), sizeof(info->groupId),
58,071,885✔
3823
                                      &(info->uid), sizeof(info->uid));
58,068,063✔
3824
        if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
58,074,669✔
UNCOV
3825
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(tempRes));
×
UNCOV
3826
          return tempRes;
×
3827
        }
3828
      }
3829
    } else {
3830
      for (int32_t i = 0; i < numOfTables; i++) {
870,231,512✔
3831
        STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
631,342,431✔
3832
        if (!info) {
631,258,211✔
UNCOV
3833
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3834
          return terrno;
×
3835
        }
3836
        info->groupId = groupByTbname ? info->uid : 0;
631,258,211✔
3837
        
3838
      }
3839
    }
3840
    if (groupIdMap && group != NULL){
251,280,091✔
3841
      getColInfoResultForGroupbyForStream(pHandle->vnode, group, pTableListInfo, pAPI, groupIdMap);
86,538✔
3842
    }
3843

3844
    pTableListInfo->oneTableForEachGroup = groupByTbname;
251,280,091✔
3845
    if (numOfTables == 1 && pTableListInfo->idInfo.tableType == TSDB_CHILD_TABLE) {
251,390,302✔
3846
      pTableListInfo->oneTableForEachGroup = true;
108,381,957✔
3847
    }
3848

3849
    if (groupSort && groupByTbname) {
251,466,503✔
3850
      taosArraySort(pTableListInfo->pTableList, orderbyGroupIdComparFn);
2,409,423✔
3851
      pTableListInfo->numOfOuputGroups = numOfTables;
2,411,013✔
3852
    } else if (groupByTbname && pScanNode->groupOrderScan) {
249,057,080✔
3853
      pTableListInfo->numOfOuputGroups = numOfTables;
26,034✔
3854
    } else {
3855
      pTableListInfo->numOfOuputGroups = 1;
249,032,421✔
3856
    }
3857
    if (groupSort || pScanNode->groupOrderScan) {
251,447,239✔
3858
      code = sortTableGroup(pTableListInfo);
28,750,285✔
3859
    }
3860
  } else {
3861
    bool initRemainGroups = false;
4,577,742✔
3862
    if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode)) {
4,577,742✔
3863
      STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pScanNode;
4,469,145✔
3864
      if (tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable &&
4,469,145✔
3865
          !(groupSort || pScanNode->groupOrderScan)) {
2,116,626✔
3866
        initRemainGroups = true;
2,092,056✔
3867
      }
3868
    }
3869

3870
    code = getColInfoResultForGroupby(pHandle, group, pTableListInfo, digest, pAPI, initRemainGroups, groupIdMap, gIdFromBaseId);
4,577,742✔
3871
    if (code != TSDB_CODE_SUCCESS) {
4,574,543✔
UNCOV
3872
      return code;
×
3873
    }
3874

3875
    if (pScanNode->groupOrderScan) pTableListInfo->numOfOuputGroups = taosArrayGetSize(pTableListInfo->pTableList);
4,574,543✔
3876

3877
    if (groupSort || pScanNode->groupOrderScan) {
4,573,982✔
3878
      code = sortTableGroup(pTableListInfo);
191,304✔
3879
    }
3880
  }
3881

3882
  qTrace("EXEC_GROUP_TRACE build_group_map done scanType:%d group:%p groupByTbname:%d groupSort:%d groupOrderScan:%d "
255,850,230✔
3883
         "oneTableEachGroup:%d numTables:%zu numOutputGroups:%d code:%d",
3884
         nodeType((SNode*)pScanNode), group, groupByTbname, groupSort, pScanNode->groupOrderScan,
3885
         pTableListInfo->oneTableForEachGroup, taosArrayGetSize(pTableListInfo->pTableList),
3886
         pTableListInfo->numOfOuputGroups, code);
3887

3888
  // add all table entry in the hash map
3889
  size_t size = taosArrayGetSize(pTableListInfo->pTableList);
255,861,106✔
3890
  for (int32_t i = 0; i < size; ++i) {
969,880,388✔
3891
    STableKeyInfo* p = taosArrayGet(pTableListInfo->pTableList, i);
713,755,658✔
3892
    if (!p) {
713,452,914✔
UNCOV
3893
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
UNCOV
3894
      return terrno;
×
3895
    }
3896
    int32_t tempRes = taosHashPut(pTableListInfo->map, &p->uid, sizeof(uint64_t), &i, sizeof(int32_t));
713,452,914✔
3897
    if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
714,166,439✔
UNCOV
3898
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(tempRes));
×
UNCOV
3899
      return tempRes;
×
3900
    }
3901
  }
3902

3903
  return code;
256,278,561✔
3904
}
3905

3906
int32_t createNonStreamScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags, bool groupSort, SReadHandle* pHandle,
280,574,943✔
3907
                                STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
3908
                                SExecTaskInfo* pTaskInfo, SHashObj* groupIdMap) {
3909
  int64_t     st = taosGetTimestampUs();
280,532,836✔
3910
  const char* idStr = GET_TASKID(pTaskInfo);
280,532,836✔
3911

3912
  if (pHandle == NULL) {
279,705,477✔
UNCOV
3913
    qError("invalid handle, in creating operator tree, %s", idStr);
×
3914
    return TSDB_CODE_INVALID_PARA;
×
3915
  }
3916

3917
  if (pHandle->uid != 0) {
279,705,477✔
3918
    pScanNode->uid = pHandle->uid;
129,443✔
3919
    pScanNode->tableType = TSDB_CHILD_TABLE;
129,443✔
3920
  }
3921
  uint8_t digest[17] = {0};
280,247,888✔
3922
  int32_t code = getTableList(pHandle->vnode, pScanNode, pTagCond, pTagIndexCond, pTableListInfo, digest, idStr,
280,179,466✔
3923
                              &pTaskInfo->storageAPI, pTaskInfo->pStreamRuntimeInfo);
280,130,773✔
3924
  if (code != TSDB_CODE_SUCCESS) {
280,934,083✔
3925
    qError("failed to getTableList, code:%s", tstrerror(code));
968✔
3926
    return code;
968✔
3927
  }
3928

3929
  int32_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
280,933,115✔
3930

3931
  int64_t st1 = taosGetTimestampUs();
281,052,291✔
3932
  pTaskInfo->cost.extractListTime = (st1 - st) / 1000.0;
281,052,291✔
3933
  qDebug("extract queried table list completed, %d tables, elapsed time:%.2f ms %s", numOfTables,
280,981,280✔
3934
         pTaskInfo->cost.extractListTime, idStr);
3935

3936
  if (numOfTables == 0) {
280,976,886✔
3937
    qDebug("no table qualified for query, %s", idStr);
24,961,410✔
3938
    return TSDB_CODE_SUCCESS;
24,965,974✔
3939
  }
3940

3941
  code = buildGroupIdMapForAllTables(pTableListInfo, pHandle, pScanNode, pGroupTags, groupSort, digest, &pTaskInfo->storageAPI, groupIdMap, false);
256,015,476✔
3942
  if (code != TSDB_CODE_SUCCESS) {
256,213,602✔
UNCOV
3943
    return code;
×
3944
  }
3945

3946
  pTaskInfo->cost.groupIdMapTime = (taosGetTimestampUs() - st1) / 1000.0;
256,220,998✔
3947
  qDebug("generate group id map completed, elapsed time:%.2f ms %s", pTaskInfo->cost.groupIdMapTime, idStr);
256,234,334✔
3948

3949
  return TSDB_CODE_SUCCESS;
256,173,395✔
3950
}
3951

NEW
3952
int32_t createStreamGrpTableListFromCond(SScanPhysiNode* pScanNode, SReadHandle* pHandle, SExecTaskInfo* pTaskInfo, SStreamRuntimeFuncInfo* pStream, STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond, int32_t grpNum, bool hasCalcGrp) {
×
NEW
3953
  int32_t code = 0, lino = 0;
×
3954

NEW
3955
  for (int32_t i = 0; i < grpNum; ++i) {
×
NEW
3956
    SSTriggerGroupReadInfo* pGrpRead = taosArrayGet(pStream->curGrpRead, i);
×
NEW
3957
    SSTriggerGroupCalcInfo* pGrpCalc = tSimpleHashGet(pStream->pGroupCalcInfos, &pGrpRead->gid, sizeof(pGrpRead->gid));
×
3958

NEW
3959
    pStream->pStreamPartColVals = pGrpCalc->pGroupColVals;
×
3960

NEW
3961
    int32_t oldSize = taosArrayGetSize(pTableListInfo->pTableList);
×
NEW
3962
    TAOS_CHECK_EXIT(getTableList(pHandle->vnode, pScanNode, pTagCond, pTagIndexCond, pTableListInfo, NULL, GET_TASKID(pTaskInfo),
×
3963
                                &pTaskInfo->storageAPI, pTaskInfo->pStreamRuntimeInfo));
NEW
3964
    int32_t newSize = taosArrayGetSize(pTableListInfo->pTableList);
×
NEW
3965
    for (int32_t i = oldSize; i < newSize; ++i) {
×
NEW
3966
      STableKeyInfo* pKey = taosArrayGet(pTableListInfo->pTableList, i);
×
NEW
3967
      pKey->baseGId = pGrpRead->gid;
×
NEW
3968
      if (!hasCalcGrp) {
×
NEW
3969
        pKey->groupId = pGrpRead->gid;
×
3970
      }
3971
    }
3972
    
NEW
3973
    qDebug("%s get %d tables for tgrp %" PRIu64, GET_TASKID(pTaskInfo), newSize - oldSize, pGrpRead->gid);
×
3974
  }
3975

NEW
3976
  qDebug("%s get total %d tables in table list from cond", GET_TASKID(pTaskInfo), (int32_t)taosArrayGetSize(pTableListInfo->pTableList));
×
3977

NEW
3978
_exit:
×
3979

NEW
3980
  if (code) {
×
NEW
3981
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, __LINE__, tstrerror(code));
×
3982
  }
3983
  
NEW
3984
  return code;}
×
3985

NEW
3986
int32_t createStreamGrpTableListFromTrig(SExecTaskInfo* pTaskInfo, SStreamRuntimeFuncInfo* pStream, STableListInfo* pTableListInfo, int32_t grpNum, bool hasCalcGrp) {
×
NEW
3987
  STableKeyInfo tableKey = {0};
×
NEW
3988
  int32_t tblNum = 0, idx = 0;
×
NEW
3989
  int32_t code = 0, lino = 0;
×
3990

NEW
3991
  if (!hasCalcGrp) {
×
NEW
3992
    pTableListInfo->numOfOuputGroups = grpNum;
×
3993
  }
3994
  
NEW
3995
  for (int32_t i = 0; i < grpNum; ++i) {
×
NEW
3996
    SSTriggerGroupReadInfo* pGrp = taosArrayGet(pStream->curGrpRead, i);
×
NEW
3997
    tableKey.baseGId = pGrp->gid;
×
NEW
3998
    tblNum = taosArrayGetSize(pGrp->pTables);
×
3999

NEW
4000
    if (pStream->stbPartByTbname) {
×
NEW
4001
      tableKey.uid = pGrp->gid;
×
NEW
4002
      if (!hasCalcGrp) {
×
NEW
4003
        tableKey.groupId = pGrp->gid;
×
NEW
4004
        pTableListInfo->oneTableForEachGroup = true;
×
4005
      }
4006
      
NEW
4007
      TSDB_CHECK_NULL(taosArrayPush(pTableListInfo->pTableList, &tableKey), code, lino, _exit, terrno);
×
NEW
4008
      if (!hasCalcGrp) {
×
NEW
4009
        int32_t tempRes = taosHashPut(pTableListInfo->map, &tableKey.uid, sizeof(uint64_t), &idx, sizeof(int32_t));
×
NEW
4010
        if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
×
NEW
4011
          TAOS_CHECK_EXIT(tempRes);
×
4012
        }      
4013
      }      
4014
      
NEW
4015
      qDebug("%s gid:%" PRIu64 " table:%" PRIu64 " added to stream table list, partByTbname", GET_TASKID(pTaskInfo), tableKey.groupId, tableKey.uid);
×
NEW
4016
      idx++;
×
NEW
4017
      continue;
×
4018
    }
4019
    
NEW
4020
    for (int32_t n = 0; n < tblNum; ++n, ++idx) {
×
NEW
4021
      uint64_t* pUid = taosArrayGet(pGrp->pTables, n);
×
NEW
4022
      tableKey.uid = *pUid;
×
NEW
4023
      if (!hasCalcGrp) {
×
NEW
4024
        tableKey.groupId = pGrp->gid;
×
4025
      }
4026
      
NEW
4027
      TSDB_CHECK_NULL(taosArrayPush(pTableListInfo->pTableList, &tableKey), code, lino, _exit, terrno);
×
NEW
4028
      if (!hasCalcGrp) {
×
NEW
4029
        int32_t tempRes = taosHashPut(pTableListInfo->map, &tableKey.uid, sizeof(uint64_t), &idx, sizeof(int32_t));
×
NEW
4030
        if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
×
NEW
4031
          TAOS_CHECK_EXIT(tempRes);
×
4032
        }
4033
      }
4034

NEW
4035
      qDebug("%s gid:%" PRIu64 " table:%" PRIu64 " added to stream table list", GET_TASKID(pTaskInfo), tableKey.groupId, tableKey.uid);
×
4036
    }
4037
  }
4038

NEW
4039
  qDebug("%s get total %d tables in table list from trig", GET_TASKID(pTaskInfo), (int32_t)taosArrayGetSize(pTableListInfo->pTableList));
×
4040

NEW
4041
_exit:
×
4042

NEW
4043
  if (code) {
×
NEW
4044
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, __LINE__, tstrerror(code));
×
4045
  }
4046
  
NEW
4047
  return code;
×
4048
}
4049

NEW
4050
int32_t createStreamMultiGrpTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags, bool groupSort, SReadHandle* pHandle,
×
4051
                                STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
4052
                                SExecTaskInfo* pTaskInfo, SHashObj* groupIdMap) {
NEW
4053
  int32_t code = 0, lino = 0;
×
NEW
4054
  const char* idStr = GET_TASKID(pTaskInfo);
×
NEW
4055
  SStreamRuntimeFuncInfo* pStream = &pTaskInfo->pStreamRuntimeInfo->funcInfo;
×
NEW
4056
  bool hasCalcGrp = (pGroupTags && pGroupTags->length > 0);
×
NEW
4057
  int32_t grpNum = taosArrayGetSize(pStream->curGrpRead);
×
NEW
4058
  SSTriggerGroupReadInfo* pGrp = taosArrayGet(pStream->curGrpRead, 0);
×
NEW
4059
  int64_t     st = taosGetTimestampUs();
×
4060

NEW
4061
  qDebug("%s start to create table list, hasCalcGrp:%d, tgrpNum:%d", idStr, hasCalcGrp, grpNum);
×
4062
  
NEW
4063
  if (taosArrayGetSize(pGrp->pTables) <= 0) {
×
NEW
4064
    TAOS_CHECK_EXIT(createStreamGrpTableListFromCond(pScanNode, pHandle, pTaskInfo, pStream, pTableListInfo, pTagCond, pTagIndexCond, grpNum, hasCalcGrp));
×
4065
  } else {
NEW
4066
    TAOS_CHECK_EXIT(createStreamGrpTableListFromTrig(pTaskInfo, pStream, pTableListInfo, grpNum, hasCalcGrp));
×
4067
  }
4068
  
NEW
4069
  pTableListInfo->idInfo.suid = pScanNode->suid;
×
NEW
4070
  pTableListInfo->idInfo.tableType = pScanNode->tableType;
×
4071

NEW
4072
  int32_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
×
4073

NEW
4074
  int64_t st1 = taosGetTimestampUs();
×
NEW
4075
  qDebug("%s build multi tgrp table list completed, elapsed time:%.2f ms", idStr, (st1 - st) / 1000.0);
×
4076

NEW
4077
  if (numOfTables == 0) {
×
NEW
4078
    qDebug("%s no table qualified for stream multi tgrp", idStr);
×
NEW
4079
    return TSDB_CODE_SUCCESS;
×
4080
  }
4081

NEW
4082
  code = buildGroupIdMapForAllTables(pTableListInfo, pHandle, pScanNode, pGroupTags, groupSort, NULL, &pTaskInfo->storageAPI, groupIdMap, true);
×
NEW
4083
  if (code != TSDB_CODE_SUCCESS) {
×
NEW
4084
    return code;
×
4085
  }
4086

NEW
4087
  pTaskInfo->cost.groupIdMapTime = (taosGetTimestampUs() - st1) / 1000.0;
×
NEW
4088
  qDebug("%s generate stream group id map completed, elapsed time:%.2f ms", idStr, pTaskInfo->cost.groupIdMapTime);
×
4089

NEW
4090
_exit:
×
4091

NEW
4092
  if (code) {
×
NEW
4093
    qError("%s %s failed at line %d since %s", GET_TASKID(pTaskInfo), __func__, lino, tstrerror(code));
×
4094
  }
4095
  
NEW
4096
  return code;
×
4097
}
4098

4099

4100
int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags, bool groupSort, SReadHandle* pHandle,
283,345,261✔
4101
                                STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
4102
                                SExecTaskInfo* pTaskInfo, SHashObj* groupIdMap) {
4103
  int32_t code = 0;
283,345,261✔
4104
  // Ensure curGrpRead is prepared from pre-initialized group calc infos for non-stream external-window initialization.
4105
  if (pTaskInfo->pStreamRuntimeInfo) {
283,345,261✔
4106
    SStreamRuntimeFuncInfo* pStream = &pTaskInfo->pStreamRuntimeInfo->funcInfo;
4,900,053✔
4107
    if (pStream->isMultiGroupCalc && pStream->curGrpRead == NULL && pStream->pGroupCalcInfos != NULL) {
4,900,053✔
NEW
4108
      int32_t n = tSimpleHashGetSize(pStream->pGroupCalcInfos);
×
NEW
4109
      if (n < 0) n = 0;
×
NEW
4110
      pStream->curGrpRead = taosArrayInit_s(sizeof(SSTriggerGroupReadInfo), n > 0 ? n : 4);
×
NEW
4111
      if (pStream->curGrpRead == NULL) {
×
NEW
4112
        return terrno;
×
4113
      }
NEW
4114
      int32_t iter = 0;
×
NEW
4115
      SSTriggerGroupCalcInfo* pGrp = tSimpleHashIterate(pStream->pGroupCalcInfos, NULL, &iter);
×
NEW
4116
      while (pGrp != NULL) {
×
NEW
4117
        uint64_t gid = *(uint64_t*)tSimpleHashGetKey(pGrp, NULL);
×
NEW
4118
        SSTriggerGroupReadInfo readInfo = {0};
×
NEW
4119
        readInfo.gid = gid;
×
NEW
4120
        readInfo.pTables = NULL;  // tables decided by getTableList when needed
×
NEW
4121
        if (taosArrayPush(pStream->curGrpRead, &readInfo) == NULL) {
×
NEW
4122
          return terrno;
×
4123
        }
NEW
4124
        pGrp = tSimpleHashIterate(pStream->pGroupCalcInfos, pGrp, &iter);
×
4125
      }
4126
    }
4127
  }
4128
  if (pTaskInfo->pStreamRuntimeInfo && pTaskInfo->pStreamRuntimeInfo->funcInfo.isMultiGroupCalc /*&&got table list*/) {
283,650,779✔
NEW
4129
    code = createStreamMultiGrpTableListInfo(pScanNode, pGroupTags, groupSort,
×
4130
                                    pHandle, pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo, groupIdMap);
NEW
4131
    if (code) {
×
NEW
4132
      qError("%s failed to createStreamMultiGrpTableListInfo, code:%s", __func__, tstrerror(code));
×
NEW
4133
      return code;
×
4134
    }
4135
  } else if (!pScanNode->node.dynamicOp) {
283,560,255✔
4136
    code = createNonStreamScanTableListInfo(pScanNode, pGroupTags, groupSort,
280,477,865✔
4137
                                    pHandle, pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo, groupIdMap);
4138
    if (code) {
281,140,707✔
4139
      qError("%s failed to createScanTableListInfo, code:%s", __func__, tstrerror(code));
36✔
4140
      return code;
968✔
4141
    }
4142
  }
4143

4144
  return TSDB_CODE_SUCCESS;
283,847,354✔
4145
}
4146

4147

4148
char* getStreamOpName(uint16_t opType) {
9,955,693✔
4149
  switch (opType) {
9,955,693✔
UNCOV
4150
    case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
×
UNCOV
4151
      return "stream scan";
×
4152
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
8,919,693✔
4153
      return "project";
8,919,693✔
4154
    case QUERY_NODE_PHYSICAL_PLAN_EXTERNAL_WINDOW:
1,036,000✔
4155
      return "external window";
1,036,000✔
4156
  }
UNCOV
4157
  return "error name";
×
4158
}
4159

4160
void printDataBlock(SSDataBlock* pBlock, const char* flag, const char* taskIdStr, int64_t qId) {
1,028,299,481✔
4161
  if (qDebugFlag & DEBUG_TRACE) {
1,028,299,481✔
4162
    if (!pBlock) {
8,355,783✔
4163
      qDebug("%" PRIx64 " %s %s %s: Block is Null", qId, taskIdStr, flag, __func__);
671,565✔
4164
      return;
1,290,454✔
4165
    } else if (pBlock->info.rows == 0) {
7,684,218✔
4166
      qDebug("%" PRIx64 " %s %s %s: Block is Empty.", qId, taskIdStr, flag, __func__);
627,020✔
4167
      return;
627,020✔
4168
    }
4169
    
4170
    char*   pBuf = NULL;
7,057,198✔
4171
    int32_t code = dumpBlockData(pBlock, flag, &pBuf, taskIdStr, qId);
7,057,198✔
4172
    if (code == 0) {
7,056,784✔
4173
      qDebugL("%" PRIx64 " %s %s", qId, __func__, pBuf);
7,056,876✔
4174
      taosMemoryFree(pBuf);
7,057,313✔
4175
    }
4176
  }
4177
}
4178

4179
void printSpecDataBlock(SSDataBlock* pBlock, const char* flag, const char* opStr, const char* taskIdStr) {
×
4180
  if (!pBlock) {
×
4181
    qDebug("%s===stream===%s %s: Block is Null", taskIdStr, flag, opStr);
×
UNCOV
4182
    return;
×
UNCOV
4183
  } else if (pBlock->info.rows == 0) {
×
UNCOV
4184
    qDebug("%s===stream===%s %s: Block is Empty.skey:%" PRId64 ",ekey:%" PRId64 ",version%" PRId64,
×
4185
           taskIdStr, flag, opStr, pBlock->info.window.skey, pBlock->info.window.ekey,
4186
           pBlock->info.version);
UNCOV
4187
    return;
×
4188
  }
UNCOV
4189
  if (qDebugFlag & DEBUG_TRACE) {
×
4190
    char* pBuf = NULL;
×
UNCOV
4191
    char  flagBuf[64];
×
4192
    snprintf(flagBuf, sizeof(flagBuf), "%s %s", flag, opStr);
×
4193
    int32_t code = dumpBlockData(pBlock, flagBuf, &pBuf, taskIdStr, 0);
×
UNCOV
4194
    if (code == 0) {
×
UNCOV
4195
      qDebug("%s", pBuf);
×
4196
      taosMemoryFree(pBuf);
×
4197
    }
4198
  }
4199
}
4200

4201
TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols) { return tsCols == NULL ? win->skey : tsCols[0]; }
12,630,293✔
4202

4203
void updateTimeWindowInfo(SColumnInfoData* pColData, const STimeWindow* pWin, int64_t delta) {
2,147,483,647✔
4204
  int64_t* ts = (int64_t*)pColData->pData;
2,147,483,647✔
4205

4206
  int64_t duration = pWin->ekey > pWin->skey ? pWin->ekey - pWin->skey + delta : pWin->skey - pWin->ekey + delta;
2,147,483,647✔
4207
  ts[2] = duration;            // set the duration
2,147,483,647✔
4208
  ts[3] = pWin->skey;          // window start key
2,147,483,647✔
4209
  ts[4] = pWin->ekey + delta;  // window end key
2,147,483,647✔
4210
}
2,147,483,647✔
4211

4212
int32_t compKeys(const SArray* pSortGroupCols, const char* oldkeyBuf, int32_t oldKeysLen, const SSDataBlock* pBlock,
2,147,483,647✔
4213
                 int32_t rowIndex) {
4214
  SColumnDataAgg* pColAgg = NULL;
2,147,483,647✔
4215
  const char*     isNull = oldkeyBuf;
2,147,483,647✔
4216
  const char*     p = oldkeyBuf + sizeof(int8_t) * pSortGroupCols->size;
2,147,483,647✔
4217

4218
  for (int32_t i = 0; i < pSortGroupCols->size; ++i) {
2,147,483,647✔
4219
    const SColumn*         pCol = (SColumn*)TARRAY_GET_ELEM(pSortGroupCols, i);
2,147,483,647✔
4220
    const SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, pCol->slotId);
2,147,483,647✔
4221
    if (pBlock->pBlockAgg) pColAgg = &pBlock->pBlockAgg[pCol->slotId];
2,147,483,647✔
4222

4223
    if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) {
2,147,483,647✔
4224
      if (isNull[i] != 1) return 1;
286,425,832✔
4225
    } else {
4226
      if (isNull[i] != 0) return 1;
2,147,483,647✔
4227
      const char* val = colDataGetData(pColInfoData, rowIndex);
2,147,483,647✔
4228
      if (pCol->type == TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
4229
        int32_t len = getJsonValueLen(val);
×
UNCOV
4230
        if (memcmp(p, val, len) != 0) return 1;
×
UNCOV
4231
        p += len;
×
4232
      } else if (IS_VAR_DATA_TYPE(pCol->type)) {
2,147,483,647✔
4233
        if (IS_STR_DATA_BLOB(pCol->type)) {
1,322,315,537✔
4234
          if (memcmp(p, val, blobDataTLen(val)) != 0) return 1;
×
4235
          p += blobDataTLen(val);
×
4236
        } else {
4237
          if (memcmp(p, val, varDataTLen(val)) != 0) return 1;
1,322,841,889✔
4238
          p += varDataTLen(val);
1,322,183,458✔
4239
        }
4240
      } else {
4241
        if (0 != memcmp(p, val, pCol->bytes)) return 1;
2,147,483,647✔
4242
        p += pCol->bytes;
2,147,483,647✔
4243
      }
4244
    }
4245
  }
4246
  if ((int32_t)(p - oldkeyBuf) != oldKeysLen) return 1;
2,147,483,647✔
4247
  return 0;
2,147,483,647✔
4248
}
4249

4250
int32_t buildKeys(char* keyBuf, const SArray* pSortGroupCols, const SSDataBlock* pBlock, int32_t rowIndex) {
1,748,942✔
4251
  uint32_t        colNum = pSortGroupCols->size;
1,748,942✔
4252
  SColumnDataAgg* pColAgg = NULL;
1,748,942✔
4253
  char*           isNull = keyBuf;
1,748,942✔
4254
  char*           p = keyBuf + sizeof(int8_t) * colNum;
1,748,942✔
4255

4256
  for (int32_t i = 0; i < colNum; ++i) {
4,789,214✔
4257
    const SColumn*         pCol = (SColumn*)TARRAY_GET_ELEM(pSortGroupCols, i);
3,040,272✔
4258
    const SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, pCol->slotId);
3,040,272✔
4259
    if (pCol->slotId > pBlock->pDataBlock->size) continue;
3,040,272✔
4260

4261
    if (pBlock->pBlockAgg) pColAgg = &pBlock->pBlockAgg[pCol->slotId];
3,040,272✔
4262

4263
    if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) {
6,080,544✔
4264
      isNull[i] = 1;
147,300✔
4265
    } else {
4266
      isNull[i] = 0;
2,892,972✔
4267
      const char* val = colDataGetData(pColInfoData, rowIndex);
2,892,972✔
4268
      if (pCol->type == TSDB_DATA_TYPE_JSON) {
2,892,972✔
4269
        int32_t len = getJsonValueLen(val);
×
4270
        memcpy(p, val, len);
×
4271
        p += len;
×
4272
      } else if (IS_VAR_DATA_TYPE(pCol->type)) {
2,892,972✔
4273
        if (IS_STR_DATA_BLOB(pCol->type)) {
1,081,182✔
UNCOV
4274
          blobDataCopy(p, val);
×
4275
          p += blobDataTLen(val);
×
4276
        } else {
4277
          varDataCopy(p, val);
1,081,182✔
4278
          p += varDataTLen(val);
1,081,182✔
4279
        }
4280
      } else {
4281
        memcpy(p, val, pCol->bytes);
1,811,790✔
4282
        p += pCol->bytes;
1,811,790✔
4283
      }
4284
    }
4285
  }
4286
  return (int32_t)(p - keyBuf);
1,748,942✔
4287
}
4288

4289
uint64_t calcGroupId(char* pData, int32_t len) {
2,147,483,647✔
4290
  T_MD5_CTX context;
2,147,483,647✔
4291
  tMD5Init(&context);
2,147,483,647✔
4292
  tMD5Update(&context, (uint8_t*)pData, len);
2,147,483,647✔
4293
  tMD5Final(&context);
2,147,483,647✔
4294

4295
  // NOTE: only extract the initial 8 bytes of the final MD5 digest
4296
  uint64_t id = 0;
2,147,483,647✔
4297
  memcpy(&id, context.digest, sizeof(uint64_t));
2,147,483,647✔
4298
  if (0 == id) memcpy(&id, context.digest + 8, sizeof(uint64_t));
2,147,483,647✔
4299
  return id;
2,147,483,647✔
4300
}
4301

4302
SNodeList* makeColsNodeArrFromSortKeys(SNodeList* pSortKeys) {
115,876✔
4303
  SNode*     node;
4304
  SNodeList* ret = NULL;
115,876✔
4305
  FOREACH(node, pSortKeys) {
353,520✔
4306
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)node;
236,662✔
4307
    int32_t           code = nodesListMakeAppend(&ret, pSortKey->pExpr);
236,662✔
4308
    if (code != TSDB_CODE_SUCCESS) {
237,644✔
UNCOV
4309
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
UNCOV
4310
      terrno = code;
×
UNCOV
4311
      return NULL;
×
4312
    }
4313
  }
4314
  return ret;
115,876✔
4315
}
4316

4317
int32_t extractKeysLen(const SArray* keys, int32_t* pLen) {
115,876✔
4318
  int32_t code = TSDB_CODE_SUCCESS;
115,876✔
4319
  int32_t lino = 0;
115,876✔
4320
  int32_t len = 0;
115,876✔
4321
  int32_t keyNum = taosArrayGetSize(keys);
115,876✔
4322
  for (int32_t i = 0; i < keyNum; ++i) {
292,636✔
4323
    SColumn* pCol = (SColumn*)taosArrayGet(keys, i);
177,742✔
4324
    QUERY_CHECK_NULL(pCol, code, lino, _end, terrno);
176,760✔
4325
    len += pCol->bytes;
176,760✔
4326
  }
4327
  len += sizeof(int8_t) * keyNum;  // null flag
114,894✔
4328
  *pLen = len;
114,894✔
4329

4330
_end:
115,385✔
4331
  if (code != TSDB_CODE_SUCCESS) {
115,385✔
4332
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4333
  }
4334
  return code;
114,403✔
4335
}
4336

UNCOV
4337
int32_t parseErrorMsgFromAnalyticServer(SJson* pJson, const char* typeStr, const char* pId) {
×
UNCOV
4338
  int32_t code = TSDB_CODE_ANA_ANODE_RETURN_ERROR;
×
UNCOV
4339
  char*   pMsg = NULL;
×
UNCOV
4340
  if (pJson == NULL) {
×
4341
    return code;
×
4342
  }
4343

4344
  int32_t ret = tjsonDupStringValue(pJson, "msg", &pMsg);
×
4345
  if (ret == 0 && pMsg != NULL) {
×
UNCOV
4346
    qError("%s failed to exec %s operation, msg:%s", pId, typeStr, pMsg);
×
UNCOV
4347
    if (strstr(pMsg, "white noise") != NULL) {
×
UNCOV
4348
      code = TSDB_CODE_ANA_WN_DATA;
×
UNCOV
4349
    } else if (strstr(pMsg, "white-noise") != NULL) {
×
UNCOV
4350
      code = TSDB_CODE_ANA_WN_DATA;
×
UNCOV
4351
    } else if (strstr(pMsg, "[Errno 111] Connection refused") != NULL) {
×
UNCOV
4352
      code = TSDB_CODE_ANA_ALGO_NOT_LOAD;
×
UNCOV
4353
    } else if (strstr(pMsg, "failed to load model") != NULL) {
×
UNCOV
4354
      code = TSDB_CODE_ANA_ALGO_NOT_LOAD;
×
4355
    }
4356
  } else {
UNCOV
4357
    qError("%s failed to extract msg from server, unknown error", pId);
×
4358
  }
4359

UNCOV
4360
  taosMemoryFreeClear(pMsg);
×
UNCOV
4361
  return code;
×
4362
}
4363

4364

4365
int32_t createExprSubQResBlock(SSDataBlock** ppBlock, SDataType* pResType, int32_t cols) {
30,787,090✔
4366
  int32_t code = 0;
30,787,090✔
4367
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
30,787,090✔
4368
  if (pBlock == NULL) {
30,785,973✔
4369
    return terrno;
×
4370
  }
4371

4372
  pBlock->pDataBlock = taosArrayInit(cols, sizeof(SColumnInfoData));
30,785,973✔
4373
  if (pBlock->pDataBlock == NULL) {
30,787,635✔
UNCOV
4374
    code = terrno;
×
UNCOV
4375
    taosMemoryFree(pBlock);
×
UNCOV
4376
    return code;
×
4377
  }
4378

4379
  for (int32_t i = 0; i < cols; ++i) {
62,560,051✔
4380
    SColumnInfoData idata = {0};
31,773,373✔
4381
    if (pResType) {
31,773,373✔
4382
      idata = createColumnInfoData(pResType->type, pResType->bytes, 0);
30,277,034✔
4383
      idata.info.scale = pResType->scale;
30,277,034✔
4384
      idata.info.precision = pResType->precision;
30,277,034✔
4385
    }
4386
    
4387
    code = blockDataAppendColInfo(pBlock, &idata);
31,772,265✔
4388
    if (code != TSDB_CODE_SUCCESS) {
31,772,416✔
NEW
4389
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
NEW
4390
      blockDataDestroy(pBlock);
×
NEW
4391
      *ppBlock = NULL;
×
NEW
4392
      return code;
×
4393
    }
4394
  }
4395

4396
  *ppBlock = pBlock;
30,786,678✔
4397

4398
  return code;
30,787,081✔
4399
}
4400

4401

4402
int32_t extractSingleRspBlock(SRetrieveTableRsp* pRetrieveRsp, SSDataBlock* pb) {
30,787,635✔
4403
  int32_t            code = TSDB_CODE_SUCCESS;
30,787,635✔
4404
  int32_t            lino = 0;
30,787,635✔
4405
  void*              decompBuf = NULL;
30,787,635✔
4406

4407
  char* pNextStart = pRetrieveRsp->data;
30,787,635✔
4408
  char* pStart = pNextStart;
30,787,635✔
4409

4410
  int32_t index = 0;
30,787,635✔
4411

4412
  if (pRetrieveRsp->compressed) {  // decompress the data
30,787,635✔
UNCOV
4413
    decompBuf = taosMemoryMalloc(pRetrieveRsp->payloadLen);
×
UNCOV
4414
    QUERY_CHECK_NULL(decompBuf, code, lino, _end, terrno);
×
4415
  }
4416

4417
  int32_t compLen = *(int32_t*)pStart;
30,787,635✔
4418
  pStart += sizeof(int32_t);
30,787,635✔
4419

4420
  int32_t rawLen = *(int32_t*)pStart;
30,787,635✔
4421
  pStart += sizeof(int32_t);
30,787,081✔
4422
  QUERY_CHECK_CONDITION((compLen <= rawLen && compLen != 0), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
30,787,081✔
4423

4424
  pNextStart = pStart + compLen;
30,787,081✔
4425
  if (pRetrieveRsp->compressed && (compLen < rawLen)) {
30,785,429✔
UNCOV
4426
    int32_t t = tsDecompressString(pStart, compLen, 1, decompBuf, rawLen, ONE_STAGE_COMP, NULL, 0);
×
UNCOV
4427
    QUERY_CHECK_CONDITION((t == rawLen), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
UNCOV
4428
    pStart = decompBuf;
×
4429
  }
4430

4431
  code = blockDecodeInternal(pb, pStart, (const char**)&pStart);
30,787,081✔
4432
  if (code != 0) {
30,786,527✔
UNCOV
4433
    taosMemoryFreeClear(pRetrieveRsp);
×
UNCOV
4434
    goto _end;
×
4435
  }
4436

4437
_end:
30,786,527✔
4438
  if (code != TSDB_CODE_SUCCESS) {
30,787,081✔
UNCOV
4439
    blockDataDestroy(pb);
×
UNCOV
4440
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4441
  }
4442
  return code;
30,787,081✔
4443
}
4444

4445
int32_t setValueFromResBlock(STaskSubJobCtx* ctx, SValueNode* pRes, SSDataBlock* pBlock) {
19,792,987✔
4446
  int32_t code = 0;
19,792,987✔
4447
  bool needFree = true;
19,792,987✔
4448
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
19,792,987✔
4449
  if (NULL == pBlock->pDataBlock || 1 > colNum || pBlock->info.rows > 1) {
19,792,997✔
4450
    qError("%s invalid scl fetch res block, pDataBlock:%p, colNum:%d, rows:%" PRId64, 
×
4451
      ctx->idStr, pBlock->pDataBlock, colNum, pBlock->info.rows);
UNCOV
4452
    return TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
×
4453
  }
4454
  
4455
  pRes->flag &= (~VALUE_FLAG_VAL_UNSET);
19,794,105✔
4456
  pRes->translate = true;
19,793,551✔
4457
  
4458
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
19,792,443✔
4459
  if (colDataIsNull_s(pCol, 0)) {
19,794,095✔
4460
    pRes->isNull = true;
5,363,598✔
4461
  } else {
4462
    code = nodesSetValueNodeValueExt(pRes, colDataGetData(pCol, 0), &needFree);
14,430,497✔
4463
  }
4464

4465
  if (!needFree) {
19,792,997✔
4466
    pCol->pData = NULL;
1,973,088✔
4467
  }
4468

4469
  return code;
19,792,997✔
4470
}
4471

4472
void handleRemoteValueRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
3,484,644✔
4473
  SSDataBlock*      pResBlock = NULL;
3,484,644✔
4474
  SExecTaskInfo*    pTaskInfo = ctx->pTaskInfo;
3,484,644✔
4475
  SRemoteValueNode* pRemote = (SRemoteValueNode*)pParam->pRes;
3,484,644✔
4476

4477
  qDebug("%s scl fetch value rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
3,484,644✔
4478

4479
  if (IS_STREAM_MODE(pTaskInfo)) {
3,484,644✔
4480
    SNode** ppRes = taosArrayGet(ctx->subResNodes, pParam->subQIdx);
113,934✔
4481
    if (NULL == *ppRes && 0 == pRsp->numOfRows) {
113,934✔
UNCOV
4482
      pRemote->val.node.type = QUERY_NODE_VALUE;
×
UNCOV
4483
      pRemote->val.isNull = true;
×
UNCOV
4484
      pRemote->val.translate = true;
×
4485
      pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
×
4486
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
×
4487
    } else if (pRsp->numOfRows > 0 || pRsp->numOfBlocks > 0) {
113,934✔
4488
      ctx->code = createExprSubQResBlock(&pResBlock, &((SRemoteValueNode*)pParam->pRes)->val.node.resType, 1);
56,967✔
4489
      if (TSDB_CODE_SUCCESS == ctx->code) {
56,967✔
4490
        ctx->code = blockDataEnsureCapacity(pResBlock, 1);
56,967✔
4491
      }
4492
      if (TSDB_CODE_SUCCESS == ctx->code) {
56,967✔
4493
        ctx->code = extractSingleRspBlock(pRsp, pResBlock);
56,967✔
4494
      }
4495
      if (TSDB_CODE_SUCCESS == ctx->code) {
56,967✔
4496
        ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
56,967✔
4497
        pRemote->val.node.type = QUERY_NODE_REMOTE_VALUE;
56,967✔
4498
      }
4499
      if (TSDB_CODE_SUCCESS == ctx->code) {
56,967✔
4500
        taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
56,967✔
4501
      }
4502

4503
      blockDataDestroy(pResBlock);
56,967✔
4504
    } else if (NULL != *ppRes && 0 == pRsp->numOfRows) {
56,967✔
4505
      pRemote->val.node.type = QUERY_NODE_VALUE;
56,967✔
4506
      pRsp->completed = true;
56,967✔
4507
    }
4508

4509
    *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
113,934✔
4510

4511
    if (!(*fetchDone)) {
113,934✔
4512
      int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
56,967✔
4513
      if (TSDB_CODE_SUCCESS != code) {
56,967✔
UNCOV
4514
        ctx->code = code;
×
UNCOV
4515
        *fetchDone = true;
×
4516
      }
4517
    }
4518

4519
    return;
113,934✔
4520
  }
4521

4522
  *fetchDone = true;
3,370,710✔
4523

4524
  if (pRsp->numOfRows > 1 || pRsp->numOfBlocks > 1 || !pRsp->completed) {
3,370,710✔
4525
    qError("%s invalid scl value fetch rsp received, subQIdx:%d, rows:%" PRId64 ", blocks:%d, completed:%d", 
1,108✔
4526
      ctx->idStr, pParam->subQIdx, pRsp->numOfRows, pRsp->numOfBlocks, pRsp->completed);
4527
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
1,108✔
4528

UNCOV
4529
    return;
×
4530
  }
4531

4532
  if (1 != pRsp->numOfCols && pRsp->numOfRows > 0) {
3,369,602✔
UNCOV
4533
    qError("%s invalid scl value fetch rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
UNCOV
4534
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_COLS;
×
4535

UNCOV
4536
    return;
×
4537
  }
4538

4539
  if (0 == pRsp->numOfRows) {
3,370,156✔
4540
    pRemote->val.node.type = QUERY_NODE_VALUE;
176,690✔
4541
    pRemote->val.isNull = true;
176,690✔
4542
    pRemote->val.translate = true;
176,690✔
4543
    pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
176,690✔
4544
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
176,690✔
4545

4546
    return;
176,690✔
4547
  }
4548
  
4549
  ctx->code = createExprSubQResBlock(&pResBlock, &((SRemoteValueNode*)pParam->pRes)->val.node.resType, 1);
3,192,912✔
4550
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,194,020✔
4551
    ctx->code = blockDataEnsureCapacity(pResBlock, 1);
3,193,466✔
4552
  }
4553
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,194,020✔
4554
    ctx->code = extractSingleRspBlock(pRsp, pResBlock);
3,193,466✔
4555
  }
4556
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,192,358✔
4557
    ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
3,192,358✔
4558
  }
4559
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,192,358✔
4560
    pRemote->val.node.type = QUERY_NODE_VALUE;
3,192,912✔
4561
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
3,191,804✔
4562
  }
4563

4564
  blockDataDestroy(pResBlock);  
3,192,358✔
4565
}
4566

4567

4568
int32_t setValueListFromResBlock(STaskSubJobCtx* ctx, SRemoteValueListNode* pRes, SSDataBlock* pBlock) {
10,482,385✔
4569
  int32_t code = 0, lino = 0;
10,482,385✔
4570
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
10,482,385✔
4571
  if (NULL == pBlock->pDataBlock || 1 != colNum) {
10,482,385✔
4572
    qError("%s invalid scl fetch res block, pDataBlock:%p, colNum:%d", ctx->idStr, pBlock->pDataBlock, colNum);
251✔
4573
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4574
  }
4575

4576
  pRes->hasValue = true;
10,482,134✔
4577
  
4578
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
10,482,385✔
4579
  TAOS_CHECK_EXIT(scalarBuildRemoteListHash(ctx->idStr, pRes, pCol, pBlock->info.rows));
10,482,385✔
4580

4581
_exit:
9,717,181✔
4582

4583
  if (code) {
10,482,385✔
4584
    qError("%s %s failed with error: %s", ctx->idStr, __func__, tstrerror(code));
765,204✔
4585
  }
4586
  
4587
  return code;
10,482,385✔
4588
}
4589

4590

4591

4592
void handleRemoteValueListRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
13,606,092✔
4593
  SSDataBlock* pResBlock = NULL;
13,606,092✔
4594
  SRemoteValueListNode* pRemote = (SRemoteValueListNode*)pParam->pRes;
13,606,637✔
4595
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
13,606,637✔
4596

4597
  qDebug("%s scl fetch valueList rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
13,606,637✔
4598

4599
  if (pRsp->numOfRows > 0) {
13,606,637✔
4600
    if (1 != pRsp->numOfCols) {
10,481,840✔
UNCOV
4601
      qError("%s invalid scl valueList fetch rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
UNCOV
4602
      ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_COLS;
×
UNCOV
4603
      *fetchDone = true;
×
UNCOV
4604
      return;
×
4605
    }
4606

4607
    ctx->code = createExprSubQResBlock(&pResBlock, &((SExprNode*)pParam->pRes)->resType, 1);
10,481,840✔
4608
    if (TSDB_CODE_SUCCESS == ctx->code) {
10,482,385✔
4609
      ctx->code = blockDataEnsureCapacity(pResBlock, pRsp->numOfRows);
10,482,385✔
4610
    }
4611
    if (TSDB_CODE_SUCCESS == ctx->code) {
10,482,385✔
4612
      ctx->code = extractSingleRspBlock(pRsp, pResBlock);
10,482,385✔
4613
    }
4614
    if (TSDB_CODE_SUCCESS == ctx->code) {
10,482,385✔
4615
      ctx->code = setValueListFromResBlock(ctx, pRemote, pResBlock);
10,482,385✔
4616
    }
4617
    if (TSDB_CODE_SUCCESS == ctx->code && pRsp->completed) {
10,482,134✔
4618
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
8,368,593✔
4619
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
8,368,593✔
4620
    }
4621

4622
    blockDataDestroy(pResBlock);  
10,482,134✔
4623
  } else if (0 == pRsp->numOfRows && pRsp->completed) {
3,124,252✔
4624
    if (!pRemote->hasValue) {
3,124,252✔
4625
      ctx->code = scalarBuildRemoteListHash(ctx->idStr, pRemote, NULL, 0);
3,105,582✔
4626
    }
4627
    if (TSDB_CODE_SUCCESS == ctx->code) {    
3,124,252✔
4628
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
2,864,968✔
4629
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
2,864,968✔
4630
    }
4631
  }
4632

4633
  if (IS_STREAM_MODE(pTaskInfo) && 0 == pRsp->numOfRows) {
13,606,637✔
4634
    if (!pRemote->hasValue) {
19,168✔
4635
      ctx->code = scalarBuildRemoteListHash(ctx->idStr, pRemote, NULL, 0);
498✔
4636
    }
4637
    if (TSDB_CODE_SUCCESS == ctx->code) {
19,168✔
4638
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
19,168✔
4639
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
19,168✔
4640
    }
4641

4642
    pRsp->completed = true;
19,168✔
4643
  }
4644

4645
  *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
13,606,637✔
4646

4647
  if (!(*fetchDone)) {
13,606,637✔
4648
    int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
1,348,588✔
4649
    if (TSDB_CODE_SUCCESS != code) {
1,348,588✔
4650
      ctx->code = code;
×
UNCOV
4651
      *fetchDone = true;
×
4652
    }
4653
  }
4654
}
4655

4656
int32_t setRowHasNullFromResBlock(STaskSubJobCtx* ctx, bool* hasNull, SSDataBlock* pBlock) {
16,543,662✔
4657
  int32_t code = 0;
16,543,662✔
4658
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
16,543,662✔
4659
  if (2 != colNum) {
16,543,662✔
UNCOV
4660
    qError("%s invalid scl fetch res block, colNum:%d", ctx->idStr, colNum);
×
UNCOV
4661
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4662
  }
4663
  
4664
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 1);
16,543,662✔
4665
  if (colDataIsNull_s(pCol, 0)) {
16,543,662✔
4666
    qError("%s invalid has_null res since it's null", ctx->idStr);
×
UNCOV
4667
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4668
  } else {
4669
    *hasNull = *(bool*)colDataGetData(pCol, 0);
16,543,662✔
4670
  }
4671

4672
  return code;
16,543,662✔
4673
}
4674

4675
void handleRemoteRowRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
22,425,472✔
4676
  SSDataBlock* pResBlock = NULL;
22,425,472✔
4677
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
22,425,472✔
4678

4679
  qDebug("%s scl fetch row rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
22,425,472✔
4680

4681
  SRemoteRowNode* pRemote = (SRemoteRowNode*)pParam->pRes;
22,425,472✔
4682

4683
  if (IS_STREAM_MODE(pTaskInfo)) {
22,425,472✔
4684
    SNode** ppRes = taosArrayGet(ctx->subResNodes, pParam->subQIdx);
980✔
4685
    if (NULL == *ppRes && 0 == pRsp->numOfRows) {
980✔
UNCOV
4686
      pRemote->valSet = true;
×
UNCOV
4687
      pRemote->hasValue = false;
×
UNCOV
4688
      pRemote->hasNull = false;
×
UNCOV
4689
      pRemote->val.isNull = true;
×
UNCOV
4690
      pRemote->val.translate = true;
×
UNCOV
4691
      pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
×
UNCOV
4692
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
×
4693
    } else if (pRsp->numOfRows > 0 || pRsp->numOfBlocks > 0) {
980✔
4694
      if (2 != pRsp->numOfCols) {
490✔
UNCOV
4695
        qError("%s invalid scl fetch row rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
UNCOV
4696
        ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
UNCOV
4697
        *fetchDone = true;
×
4698
        return;
×
4699
      }
4700

4701
      ctx->code = createExprSubQResBlock(&pResBlock, &pRemote->val.node.resType, 1);
490✔
4702
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4703
        SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_BOOL, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, 0);
490✔
4704
        ctx->code = blockDataAppendColInfo(pResBlock, &idata);
490✔
4705
      }
4706
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4707
        ctx->code = blockDataEnsureCapacity(pResBlock, 1);
490✔
4708
      }
4709
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4710
        ctx->code = extractSingleRspBlock(pRsp, pResBlock);
490✔
4711
      }
4712
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4713
        ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
490✔
4714
      }
4715
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4716
        ctx->code = setRowHasNullFromResBlock(ctx, &pRemote->hasNull, pResBlock);
490✔
4717
      }
4718
      if (TSDB_CODE_SUCCESS == ctx->code) {
490✔
4719
        pRemote->valSet = true;
490✔
4720
        pRemote->hasValue = true;
490✔
4721
        pRemote->val.node.type = QUERY_NODE_REMOTE_ROW;
490✔
4722
        taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
490✔
4723
      }
4724

4725
      blockDataDestroy(pResBlock);
490✔
4726
    } else if (NULL != *ppRes && 0 == pRsp->numOfRows) {
490✔
4727
      pRemote->val.node.type = QUERY_NODE_VALUE;
490✔
4728
      pRsp->completed = true;
490✔
4729
    }
4730

4731
    *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
980✔
4732

4733
    if (!(*fetchDone)) {
980✔
4734
      ctx->code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
490✔
4735
      if (TSDB_CODE_SUCCESS != ctx->code) {
490✔
UNCOV
4736
        *fetchDone = true;
×
4737
      }
4738
    }
4739

4740
    return;
980✔
4741
  }
4742

4743
  *fetchDone = true;
22,424,492✔
4744

4745
  if (pRsp->numOfRows > 1 || pRsp->numOfBlocks > 1 || !pRsp->completed) {
22,424,492✔
UNCOV
4746
    qError("%s invalid scl fetch row rsp received, subQIdx:%d, rows:%" PRId64 ", blocks:%d, completed:%d",
×
4747
      ctx->idStr, pParam->subQIdx, pRsp->numOfRows, pRsp->numOfBlocks, pRsp->completed);
UNCOV
4748
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
×
4749

4750
    return;
×
4751
  }
4752

4753
  if (0 == pRsp->numOfRows) {
22,424,492✔
4754
    pRemote->valSet = true;
5,881,320✔
4755
    pRemote->hasValue = false;
5,881,320✔
4756
    pRemote->hasNull = false;
5,881,320✔
4757
    pRemote->val.isNull = true;
5,881,320✔
4758
    pRemote->val.translate = true;
5,881,320✔
4759
    pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
5,881,320✔
4760
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
5,881,320✔
4761

4762
    return;
5,881,320✔
4763
  }
4764

4765
  if (2 != pRsp->numOfCols) {
16,543,172✔
UNCOV
4766
    qError("%s invalid scl fetch row rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
UNCOV
4767
    ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4768

UNCOV
4769
    return;
×
4770
  }
4771

4772
  ctx->code = createExprSubQResBlock(&pResBlock, &pRemote->val.node.resType, 1);
16,543,172✔
4773
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,543,172✔
4774
    SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_BOOL, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, 0);
16,543,172✔
4775
    ctx->code = blockDataAppendColInfo(pResBlock, &idata);
16,543,172✔
4776
  }
4777
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,543,172✔
4778
    ctx->code = blockDataEnsureCapacity(pResBlock, 1);
16,543,172✔
4779
  }
4780
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,543,172✔
4781
    ctx->code = extractSingleRspBlock(pRsp, pResBlock);
16,543,172✔
4782
  }
4783
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,543,172✔
4784
    ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
16,543,172✔
4785
  }
4786
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,542,628✔
4787
    ctx->code = setRowHasNullFromResBlock(ctx, &pRemote->hasNull, pResBlock);
16,543,172✔
4788
  }
4789
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,543,172✔
4790
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
16,542,628✔
4791
  }
4792
  if (TSDB_CODE_SUCCESS == ctx->code) {
16,542,628✔
4793
    pRemote->valSet = true;
16,542,628✔
4794
    pRemote->hasValue = true;
16,542,628✔
4795
  }
4796

4797
  blockDataDestroy(pResBlock);
16,543,172✔
4798
}
4799

4800

4801
int32_t setZeroRowsResValue(STaskSubJobCtx* ctx, SValueNode* pRes, int32_t rows) {
279,320✔
4802
  pRes->node.type = QUERY_NODE_VALUE;
279,320✔
4803
  pRes->flag &= (~VALUE_FLAG_VAL_UNSET);
279,320✔
4804
  pRes->translate = true;
279,320✔
4805
  
4806
  return nodesSetValueNodeValue(pRes, &rows);
279,320✔
4807
}
4808

4809
void handleRemoteZeroRowsRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
279,075✔
4810
  SRemoteZeroRowsNode* pRemote = (SRemoteZeroRowsNode*)pParam->pRes;
279,075✔
4811
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
279,075✔
4812

4813
  qDebug("%s scl fetch zeroRows rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
279,075✔
4814

4815
  int32_t resRows = (pRsp->numOfRows > 0) ? 1 : 0;
279,075✔
4816
  if (resRows > 0 || pRsp->completed) {
279,075✔
4817
    ctx->code = setZeroRowsResValue(ctx, &pRemote->val, resRows);
279,075✔
4818
    if (TSDB_CODE_SUCCESS == ctx->code) {
279,075✔
4819
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
279,075✔
4820
    }
4821

4822
    *fetchDone = true;
279,075✔
4823
  } else {
UNCOV
4824
    *fetchDone = false;
×
4825
  }
4826

4827
  if (IS_STREAM_MODE(pTaskInfo) && 0 == pRsp->numOfRows) {
279,075✔
4828
    ctx->code = setZeroRowsResValue(ctx, &pRemote->val, 0);
245✔
4829
    if (TSDB_CODE_SUCCESS == ctx->code) {
245✔
4830
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
245✔
4831
    }
4832

4833
    pRsp->completed = true;
245✔
4834
    *fetchDone = true;
245✔
4835
  }
4836

4837
  if (!(*fetchDone)) {
279,075✔
UNCOV
4838
    int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
×
UNCOV
4839
    if (TSDB_CODE_SUCCESS != code) {
×
UNCOV
4840
      ctx->code = code;
×
UNCOV
4841
      *fetchDone = true;
×
4842
    }
4843
  }
4844
}
279,075✔
4845

4846

4847

4848
int32_t setTableFromResBlock(STaskSubJobCtx* ctx, SRemoteTableNode* pRes, SSDataBlock** ppBlock) {
510,601✔
4849
  int32_t code = 0, lino = 0;
510,601✔
4850
  
4851
  if (NULL == pRes->pResBlks) {
510,601✔
4852
    pRes->pResBlks = taosArrayInit(10, POINTER_BYTES);
396,149✔
4853
    TSDB_CHECK_NULL(pRes->pResBlks, code, lino, _exit, terrno);
396,149✔
4854
  }
4855

4856
  TSDB_CHECK_NULL(taosArrayPush(pRes->pResBlks, ppBlock), code, lino, _exit, terrno);
1,021,202✔
4857

4858
_exit:
510,601✔
4859

4860
  if (code) {
510,601✔
NEW
4861
    blockDataDestroy(*ppBlock);    
×
NEW
4862
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4863
  }
4864

4865
  *ppBlock = NULL;
510,601✔
4866
  
4867
  return code;
510,601✔
4868
}
4869

4870

4871
void handleRemoteTableRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
513,019✔
4872
  SSDataBlock* pResBlock = NULL;
513,019✔
4873
  SRemoteTableNode* pRemote = (SRemoteTableNode*)pParam->pRes;
513,019✔
4874

4875
  qDebug("%s scl fetch remoteTable rsp received, subQIdx:%d, rows:%" PRId64 ", cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfRows, pRsp->numOfCols);
513,019✔
4876

4877
  if (pRsp->numOfRows > 0) {
513,019✔
4878
    ctx->code = createExprSubQResBlock(&pResBlock, NULL, pRemote->resCols);
510,601✔
4879
    if (TSDB_CODE_SUCCESS == ctx->code) {
510,601✔
4880
      ctx->code = extractSingleRspBlock(pRsp, pResBlock);
510,601✔
4881
    }
4882
    if (TSDB_CODE_SUCCESS == ctx->code) {
510,601✔
4883
      ctx->code = setTableFromResBlock(ctx, pRemote, &pResBlock);
510,601✔
4884
    }
4885
    if (TSDB_CODE_SUCCESS == ctx->code && pRsp->completed) {
510,601✔
4886
      pRemote->flag &= (~REMOTE_TABLE_FLAG_VAL_UNSET);
396,149✔
4887
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
396,149✔
4888
    }
4889

4890
    blockDataDestroy(pResBlock);  
510,601✔
4891
  } else if (0 == pRsp->numOfRows && pRsp->completed) {
2,418✔
4892
    pRemote->flag &= (~REMOTE_TABLE_FLAG_VAL_UNSET);
2,418✔
4893
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
2,418✔
4894
  }
4895

4896
  *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
513,019✔
4897

4898
  if (!(*fetchDone)) {
513,019✔
4899
    int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, 1);
114,452✔
4900
    if (TSDB_CODE_SUCCESS != code) {
114,452✔
NEW
4901
      ctx->code = code;
×
NEW
4902
      *fetchDone = true;
×
4903
    }
4904
  }
4905
}
513,019✔
4906

4907

4908
int32_t remoteFetchCallBack(void* param, SDataBuf* pMsg, int32_t code) {
41,193,585✔
4909
  taosMemoryFreeClear(pMsg->pEpSet);
41,193,585✔
4910

4911
  SScalarFetchParam* pParam = (SScalarFetchParam*)param;
41,193,585✔
4912
  STaskSubJobCtx* ctx = taosAcquireRef(fetchObjRefPool, pParam->subJobRefId);
41,193,585✔
4913
  if (ctx == NULL) {
41,192,628✔
4914
    qWarn("failed to acquire subJobCtx, since it may have been released, refId:%" PRIu64, pParam->subJobRefId);
1,108✔
4915
    taosMemoryFree(pMsg->pData);
1,108✔
4916
    return TSDB_CODE_SUCCESS;
1,108✔
4917
  }
4918

4919
  char idStr[64];
41,191,520✔
4920
  if (qDebugFlag & DEBUG_DEBUG) {
41,192,477✔
4921
    tstrncpy(idStr, ctx->idStr, sizeof(idStr));
1,972,440✔
4922
  }
4923
  
4924
  qDebug("%s subQIdx %d got rsp, blockIdx:%" PRId64 ", code:%d, rsp:%p", ctx->idStr, pParam->subQIdx, ctx->blockIdx, code, pMsg->pData);
41,192,477✔
4925

4926
  if (ctx->transporterId > 0) {
41,192,477✔
4927
    int32_t ret = asyncFreeConnById(ctx->rpcHandle, ctx->transporterId);
41,192,477✔
4928
    if (ret != 0) {
41,193,031✔
UNCOV
4929
      qDebug("%s failed to free subQ rpc handle, code:%s, subQIdx:%d", ctx->idStr, tstrerror(ret), pParam->subQIdx);
×
4930
    }
4931
    ctx->transporterId = -1;
41,193,031✔
4932
  }
4933

4934
  if (0 == code && NULL == pMsg->pData) {
41,193,040✔
UNCOV
4935
    qError("%s invalid rsp msg, msgType:%d, len:%d", ctx->idStr, pMsg->msgType, pMsg->len);
×
UNCOV
4936
    code = TSDB_CODE_QRY_INVALID_MSG;
×
4937
  }
4938

4939
  if (code == TSDB_CODE_SUCCESS) {
41,192,486✔
4940
    SRetrieveTableRsp* pRsp = pMsg->pData;
40,308,302✔
4941
    pRsp->numOfRows = htobe64(pRsp->numOfRows);
40,308,302✔
4942
    pRsp->compLen = htonl(pRsp->compLen);
40,308,847✔
4943
    pRsp->payloadLen = htonl(pRsp->payloadLen);
40,308,847✔
4944
    pRsp->numOfCols = htonl(pRsp->numOfCols);
40,308,293✔
4945
    pRsp->useconds = htobe64(pRsp->useconds);
40,307,748✔
4946
    pRsp->numOfBlocks = htonl(pRsp->numOfBlocks);
40,307,739✔
4947

4948
    qDebug("%s subQIdx %d blockIdx:%" PRIu64 " rsp detail, numOfBlocks:%d, numOfRows:%" PRId64 ", numOfCols:%" PRId64 ", completed:%d", 
40,308,293✔
4949
      ctx->idStr, pParam->subQIdx, ctx->blockIdx, pRsp->numOfBlocks, pRsp->numOfRows, pRsp->numOfCols, pRsp->completed);
4950

4951
    ctx->blockIdx++;
40,308,293✔
4952

4953
    switch (nodeType(pParam->pRes)) {
40,308,847✔
4954
      case QUERY_NODE_REMOTE_VALUE: {
3,484,644✔
4955
        bool fetchDone = false;
3,484,644✔
4956
        handleRemoteValueRes(pParam, ctx, pRsp, &fetchDone);
3,484,644✔
4957
        qDebug("%s subQIdx %d handle remote value, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
3,484,090✔
4958
        if (!fetchDone) {
3,482,982✔
4959
          goto _exit;
56,967✔
4960
        }
4961
        break;
3,426,015✔
4962
      }
4963
      case QUERY_NODE_REMOTE_VALUE_LIST: {
13,606,092✔
4964
        bool fetchDone = false;
13,606,092✔
4965
        handleRemoteValueListRes(pParam, ctx, pRsp, &fetchDone);
13,606,092✔
4966
        qDebug("%s subQIdx %d handle remote value list finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
13,606,637✔
4967
        if (!fetchDone) {
13,606,637✔
4968
          goto _exit;
1,348,588✔
4969
        }
4970
        break;
12,258,049✔
4971
      }  
4972
      case QUERY_NODE_REMOTE_ROW: {
22,425,472✔
4973
        bool fetchDone = false;
22,425,472✔
4974
        handleRemoteRowRes(pParam, ctx, pRsp, &fetchDone);
22,425,472✔
4975
        qDebug("%s subQIdx %d handle remote row finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
22,425,472✔
4976
        if (!fetchDone) {
22,425,472✔
4977
          goto _exit;
490✔
4978
        }
4979
        break;
22,424,982✔
4980
      }
4981
      case QUERY_NODE_REMOTE_ZERO_ROWS: {
279,075✔
4982
        bool fetchDone = false;
279,075✔
4983
        handleRemoteZeroRowsRes(pParam, ctx, pRsp, &fetchDone);
279,075✔
4984
        qDebug("%s subQIdx %d handle remote zeroRows finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
279,075✔
4985
        if (!fetchDone) {
279,075✔
UNCOV
4986
          goto _exit;
×
4987
        }
4988
        break;
279,075✔
4989
      }
4990
      case QUERY_NODE_REMOTE_TABLE: {
513,019✔
4991
        bool fetchDone = false;
513,019✔
4992
        handleRemoteTableRes(pParam, ctx, pRsp, &fetchDone);
513,019✔
4993
        qDebug("%s subQIdx %d handle remote table finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
513,019✔
4994
        if (!fetchDone) {
513,019✔
4995
          goto _exit;
114,452✔
4996
        }
4997
        break;
398,567✔
4998
      }
UNCOV
4999
      default:
×
UNCOV
5000
        qError("%s invalid scl fetch res node %d, subQIdx:%d", ctx->idStr, nodeType(pParam->pRes), pParam->subQIdx);
×
UNCOV
5001
        ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
UNCOV
5002
        break;
×
5003
    }
5004
  } else {
5005
    ctx->code = rpcCvtErrCode(code);
884,184✔
5006
    if (ctx->code != code) {
884,184✔
UNCOV
5007
      qError("%s scl fetch rsp received, subQIdx:%d, error:%s, cvted error: %s", ctx->idStr, pParam->subQIdx,
×
5008
             tstrerror(code), tstrerror(ctx->code));
5009
    } else {
5010
      qError("%s scl fetch rsp received, subQIdx:%d, error:%s", ctx->idStr, pParam->subQIdx, tstrerror(code));
884,184✔
5011
    }
5012
  }
5013

5014
  qDebug("%s subQIdx %d sem_post subQ ready", ctx->idStr, pParam->subQIdx);
39,671,426✔
5015
  
5016
  code = tsem_post(&ctx->ready);
39,671,426✔
5017
  if (code != TSDB_CODE_SUCCESS) {
39,672,534✔
UNCOV
5018
    qError("failed to invoke post when scl fetch rsp is ready, code:%s", tstrerror(code));
×
5019
  }
5020

5021
_exit:
41,192,477✔
5022

5023
  code = taosReleaseRef(fetchObjRefPool, pParam->subJobRefId);
41,192,477✔
5024
  if (code != TSDB_CODE_SUCCESS) {
41,192,477✔
UNCOV
5025
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
5026
  }
5027

5028
  taosMemoryFree(pMsg->pData);
41,192,477✔
5029

5030
  return code;
41,192,487✔
5031
}
5032

5033
#define STREAM_TASK_REPLICA_NUM 5
5034
#define STREAM_TASK_DEPLOY_NUM 3
5035

5036
int32_t sendFetchRemoteNodeReq(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes, bool reset) {
41,189,726✔
5037
  int32_t          code = TSDB_CODE_SUCCESS;
41,189,726✔
5038
  int32_t          lino = 0;
41,189,726✔
5039
  int32_t          innerIdx = 0;
41,189,726✔
5040
  SExecTaskInfo*   pTaskInfo = ctx->pTaskInfo;
41,189,726✔
5041
  bool             needStreamPesudoFuncVals = false;
41,183,117✔
5042

5043
  if (IS_STREAM_MODE(pTaskInfo)) {
41,183,117✔
5044
    innerIdx = pTaskInfo->pStreamRuntimeInfo->execId / STREAM_TASK_REPLICA_NUM;
1,196,393✔
5045
    subQIdx = subQIdx * STREAM_TASK_DEPLOY_NUM + innerIdx;
1,196,649✔
5046
  }
5047

5048
  SDownstreamSourceNode* pSource = (SDownstreamSourceNode*)taosArrayGetP(ctx->subEndPoints, subQIdx);
41,173,171✔
5049

5050
  SResFetchReq req = {0};
41,165,709✔
5051
  req.header.vgId = pSource->addr.nodeId;
41,165,709✔
5052
  req.sId = pSource->sId;
41,174,294✔
5053
  req.clientId = pSource->clientId;
41,186,413✔
5054
  req.taskId = pSource->taskId;
41,174,910✔
5055
  req.srcTaskId = ctx->taskId;
41,169,717✔
5056
  req.blockIdx = ctx->blockIdx;
41,168,789✔
5057
  req.queryId = ctx->queryId;
41,165,212✔
5058
  req.execId = pSource->execId;
41,168,226✔
5059

5060
  if (IS_STREAM_MODE(pTaskInfo)) {
41,168,330✔
5061
    req.queryId = pSource->clientId;
1,196,393✔
5062
    req.execId = pTaskInfo->pStreamRuntimeInfo->execId;
1,196,900✔
5063
    req.pStRtFuncInfo = &pTaskInfo->pStreamRuntimeInfo->funcInfo;
1,196,393✔
5064
    req.reset = reset;
1,196,644✔
5065

5066
    needStreamPesudoFuncVals = true;
1,196,644✔
5067
    subQIdx = (subQIdx - innerIdx) / STREAM_TASK_DEPLOY_NUM;
1,196,644✔
5068
  }
5069

5070
  int32_t msgSize = tSerializeSResFetchReq(NULL, 0, &req, needStreamPesudoFuncVals, false);
41,164,713✔
5071
  if (msgSize < 0) {
41,187,642✔
UNCOV
5072
    return msgSize;
×
5073
  }
5074

5075
  void* msg = taosMemoryCalloc(1, msgSize);
41,187,642✔
5076
  if (NULL == msg) {
41,163,334✔
UNCOV
5077
    return terrno;
×
5078
  }
5079

5080
  msgSize = tSerializeSResFetchReq(msg, msgSize, &req, needStreamPesudoFuncVals, false);
41,163,334✔
5081
  if (msgSize < 0) {
41,170,708✔
UNCOV
5082
    taosMemoryFree(msg);
×
UNCOV
5083
    return msgSize;
×
5084
  }
5085

5086
  qDebug("%s scl build fetch msg and send to nodeId:%d, ep:%s, clientId:0x%" PRIx64 " taskId:0x%" PRIx64
41,170,708✔
5087
         ", execId:%d, blockIdx:%" PRId64,
5088
         ctx->idStr, pSource->addr.nodeId, pSource->addr.epSet.eps[0].fqdn, pSource->clientId,
5089
         pSource->taskId, pSource->execId, req.blockIdx);
5090

5091
  // send the fetch remote task result reques
5092
  SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
41,172,621✔
5093
  if (NULL == pMsgSendInfo) {
41,172,601✔
UNCOV
5094
    taosMemoryFreeClear(msg);
×
UNCOV
5095
    qError("%s prepare message %d failed", ctx->idStr, (int32_t)sizeof(SMsgSendInfo));
×
UNCOV
5096
    return terrno;
×
5097
  }
5098

5099
  SScalarFetchParam* param = taosMemoryMalloc(sizeof(SScalarFetchParam));
41,172,601✔
5100
  if (NULL == param) {
41,180,348✔
UNCOV
5101
    taosMemoryFreeClear(msg);
×
UNCOV
5102
    taosMemoryFreeClear(pMsgSendInfo);
×
UNCOV
5103
    qError("%s prepare param %d failed", ctx->idStr, (int32_t)sizeof(SScalarFetchParam));
×
UNCOV
5104
    return terrno;
×
5105
  }
5106

5107
  if (ctx->code) {
41,180,348✔
UNCOV
5108
    qError("task has been killed, error:%s", tstrerror(ctx->code));
×
UNCOV
5109
    taosMemoryFree(param);
×
5110
    taosMemoryFreeClear(msg);
×
UNCOV
5111
    taosMemoryFreeClear(pMsgSendInfo);
×
UNCOV
5112
    code = ctx->code;
×
UNCOV
5113
    goto _end;
×
5114
  }
5115
  
5116
  param->subQIdx = subQIdx;
41,173,670✔
5117
  param->pRes = pRes;
41,164,242✔
5118
  param->subJobRefId = ctx->subJobRefId;
41,183,623✔
5119

5120
  pMsgSendInfo->param = param;
41,174,283✔
5121
  pMsgSendInfo->paramFreeFp = taosAutoMemoryFree;
41,174,244✔
5122
  pMsgSendInfo->msgInfo.pData = msg;
41,172,057✔
5123
  pMsgSendInfo->msgInfo.len = msgSize;
41,160,968✔
5124
  pMsgSendInfo->msgType = pSource->fetchMsgType;
41,176,450✔
5125
  pMsgSendInfo->fp = remoteFetchCallBack;
41,170,366✔
5126
  pMsgSendInfo->requestId = ctx->queryId;
41,168,180✔
5127

5128
  code = asyncSendMsgToServer(ctx->rpcHandle, &pSource->addr.epSet, &ctx->transporterId, pMsgSendInfo);
41,168,170✔
5129
  QUERY_CHECK_CODE(code, lino, _end);
41,193,059✔
5130
      
5131
_end:
41,193,059✔
5132

5133
  if (code != TSDB_CODE_SUCCESS) {
41,193,059✔
UNCOV
5134
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
×
5135
  }
5136
  
5137
  return code;
41,190,843✔
5138
}
5139

5140
int32_t fetchRemoteNodeImpl(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes) {
39,670,081✔
5141
  int32_t          code = TSDB_CODE_SUCCESS;
39,670,081✔
5142
  int32_t          lino = 0;
39,670,081✔
5143

5144
  ctx->blockIdx = 0;
39,670,081✔
5145

5146
  code = sendFetchRemoteNodeReq(ctx, subQIdx, pRes, true);
39,671,456✔
5147
  QUERY_CHECK_CODE(code, lino, _end);
39,671,998✔
5148

5149
  code = qSemWait(ctx->pTaskInfo, &ctx->ready);
39,671,998✔
5150
  if (isTaskKilled(ctx->pTaskInfo)) {
39,675,858✔
5151
    code = getTaskCode(ctx->pTaskInfo);
11,080✔
5152
  } else {
5153
    code = ctx->code;
39,664,778✔
5154
  }
5155
      
5156
_end:
39,675,858✔
5157

5158
  if (code != TSDB_CODE_SUCCESS) {
39,675,858✔
5159
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
1,911,996✔
5160
  }
5161
  return code;
39,675,858✔
5162
}
5163

5164
int32_t remoteNodeCopy(SNode* pSrc, SNode* pDst) {
118,564✔
5165
  int32_t code = 0, lino = 0;
118,564✔
5166
  
5167
  switch (nodeType(pSrc)) {
118,564✔
5168
    case QUERY_NODE_VALUE:
84,836✔
5169
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &((SRemoteValueNode*)pDst)->val));
84,836✔
5170
      ((SRemoteValueNode*)pDst)->val.node.type = QUERY_NODE_VALUE;
84,836✔
5171
      break;
84,836✔
5172
    case QUERY_NODE_REMOTE_VALUE_LIST: {
25,024✔
5173
      SRemoteValueListNode* pDstNode = (SRemoteValueListNode*)pDst;
25,024✔
5174
      memcpy(pDst, pSrc, sizeof(SRemoteValueListNode));
25,024✔
5175
      pDstNode->hashAllocated = false;      
25,024✔
5176
      break;
25,024✔
5177
    } 
5178
    case QUERY_NODE_REMOTE_ROW: {
8,704✔
5179
      SRemoteRowNode* pRemote = (SRemoteRowNode*)pDst;
8,704✔
5180
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &pRemote->val));
8,704✔
5181
      pRemote->valSet = true;
8,704✔
5182
      pRemote->hasValue = ((SRemoteRowNode*)pSrc)->hasValue;
8,704✔
5183
      pRemote->hasNull = ((SRemoteRowNode*)pSrc)->hasNull;
8,704✔
5184
      break;
8,704✔
5185
    }
NEW
5186
    case QUERY_NODE_REMOTE_TABLE: {
×
NEW
5187
      SRemoteTableNode* pDstNode = (SRemoteTableNode*)pDst;
×
NEW
5188
      SRemoteTableNode* pSrcNode = (SRemoteTableNode*)pSrc;
×
NEW
5189
      pDstNode->pResBlks = pSrcNode->pResBlks;
×
NEW
5190
      pDstNode->flag = 0;      
×
NEW
5191
      break;
×
5192
    }
5193
    case QUERY_NODE_REMOTE_ZERO_ROWS: {
×
5194
      SRemoteZeroRowsNode* pRemote = (SRemoteZeroRowsNode*)pDst;
×
5195
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &pRemote->val));
×
UNCOV
5196
      pRemote->val.node.type = QUERY_NODE_VALUE;
×
UNCOV
5197
      break;
×
5198
    }
UNCOV
5199
    default:
×
UNCOV
5200
      break;
×
5201
  }
5202

5203
_exit:
118,564✔
5204

5205
  if (code) {
118,564✔
UNCOV
5206
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
5207
  }
5208

5209
  return code;
118,564✔
5210
}
5211

5212
int32_t qFetchRemoteNode(void* pCtx, int32_t subQIdx, SNode* pRes) {
39,788,091✔
5213
  STaskSubJobCtx*  ctx = (STaskSubJobCtx*)pCtx;
39,788,091✔
5214
  int32_t code = 0, lino = 0;
39,788,091✔
5215
  int32_t       subEndPoinsNum = taosArrayGetSize(ctx->subEndPoints);
39,788,091✔
5216
  if (subQIdx >= subEndPoinsNum) {
39,759,599✔
UNCOV
5217
    qError("%s invalid subQIdx %d, subEndPointsNum:%d", ctx->idStr, subQIdx, subEndPoinsNum);
×
UNCOV
5218
    return TSDB_CODE_QRY_SUBQ_NOT_FOUND;
×
5219
  }
5220

5221
  SNode** ppRes = taosArrayGet(ctx->subResNodes, subQIdx);
39,759,599✔
5222
  if (NULL == *ppRes) {
39,770,679✔
5223
    TAOS_CHECK_EXIT(fetchRemoteNodeImpl(ctx, subQIdx, pRes));
39,660,406✔
5224
    *ppRes = pRes;
37,763,862✔
5225
  } else {
5226
    TAOS_CHECK_EXIT(remoteNodeCopy(*ppRes, pRes));
118,564✔
5227
  }
5228

5229
_exit:
118,564✔
5230

5231
  if (code) {
39,794,422✔
5232
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
1,911,996✔
5233
  } else {
5234
    qDebug("%s %s subQIdx %d succeed", ctx->idStr, __func__, subQIdx);
37,882,426✔
5235
  }
5236

5237
  return code;
39,794,422✔
5238
}
5239

5240
int32_t findDataBlockColIndexBySlotId(const SSDataBlock* pBlock, int32_t slotId) {
195,374,083✔
5241
  if (NULL == pBlock || NULL == pBlock->pDataBlock) {
195,374,083✔
NEW
5242
    return -1;
×
5243
  }
5244

5245
  int32_t numOfCols = (int32_t)taosArrayGetSize(pBlock->pDataBlock);
195,374,083✔
5246
  if (slotId >= 0 && slotId < numOfCols) {
195,374,495✔
5247
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId);
195,374,495✔
5248
    if (NULL != pCol && pCol->info.slotId == slotId) {
195,374,083✔
5249
      return slotId;
195,374,224✔
5250
    }
5251
  }
5252

NEW
5253
  for (int32_t i = 0; i < numOfCols; ++i) {
×
NEW
5254
    SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, i);
×
NEW
5255
    if (NULL != pCol && pCol->info.slotId == slotId) {
×
NEW
5256
      return i;
×
5257
    }
5258
  }
5259

NEW
5260
  return -1;
×
5261
}
5262

5263
SColumnInfoData* getDataBlockColBySlotId(const SSDataBlock* pBlock, int32_t slotId, int32_t* pIndex) {
195,374,083✔
5264
  int32_t index = findDataBlockColIndexBySlotId(pBlock, slotId);
195,374,083✔
5265
  if (NULL != pIndex) {
195,374,224✔
NEW
5266
    *pIndex = index;
×
5267
  }
5268
  return (index >= 0) ? taosArrayGet(pBlock->pDataBlock, index) : NULL;
195,374,224✔
5269
}
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