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

taosdata / TDengine / #4999

22 Mar 2026 10:21AM UTC coverage: 72.31% (-0.03%) from 72.335%
#4999

push

travis-ci

web-flow
feat(subq/some): some/any/exists for stream subq (#34860)

50 of 68 new or added lines in 1 file covered. (73.53%)

701 existing lines in 132 files now uncovered.

253472 of 350536 relevant lines covered (72.31%)

131775367.32 hits per line

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

76.17
/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

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

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

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

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

63
static int64_t getLimit(const SNode* pLimit) {
1,272,043,360✔
64
  return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->limit) ? -1 : ((SLimitNode*)pLimit)->limit->datum.i;
1,272,043,360✔
65
}
66
static int64_t getOffset(const SNode* pLimit) {
1,271,904,384✔
67
  return (NULL == pLimit || NULL == ((SLimitNode*)pLimit)->offset) ? -1 : ((SLimitNode*)pLimit)->offset->datum.i;
1,271,904,384✔
68
}
69
static void releaseColInfoData(void* pCol);
70
int32_t sendFetchRemoteNodeReq(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes, bool reset);
71

72
void initResultRowInfo(SResultRowInfo* pResultRowInfo) {
485,793,211✔
73
  pResultRowInfo->size = 0;
485,793,211✔
74
  pResultRowInfo->cur.pageId = -1;
485,823,791✔
75
}
485,834,661✔
76

77
void closeResultRow(SResultRow* pResultRow) { pResultRow->closed = true; }
5,603,084✔
78

79
void resetResultRow(SResultRow* pResultRow, size_t entrySize) {
955,815,326✔
80
  pResultRow->numOfRows = 0;
955,815,326✔
81
  pResultRow->nOrigRows = 0;
955,816,562✔
82
  pResultRow->closed = false;
955,816,562✔
83
  pResultRow->endInterp = false;
955,816,795✔
84
  pResultRow->startInterp = false;
955,817,207✔
85

86
  if (entrySize > 0) {
955,817,440✔
87
    memset(pResultRow->pEntryInfo, 0, entrySize);
955,817,028✔
88
  }
89
}
955,818,318✔
90

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

96
size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
290,469,500✔
97
  int32_t rowSize = (numOfOutput * sizeof(SResultRowEntryInfo)) + sizeof(SResultRow);
290,469,500✔
98

99
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,215,027,127✔
100
    rowSize += pCtx[i].resDataInfo.interBufSize;
924,630,896✔
101
  }
102

103
  return rowSize;
290,396,231✔
104
}
105

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

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

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

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

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

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

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

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

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

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

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

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

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

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

219
void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) {
135,090,317✔
220
  taosMemoryFreeClear(pGroupResInfo->pBuf);
135,090,317✔
221
  if (pGroupResInfo->freeItem) {
135,097,542✔
222
    //    taosArrayDestroy(pGroupResInfo->pRows);
223
    taosArrayDestroyEx(pGroupResInfo->pRows, freeEx);
×
224
    pGroupResInfo->freeItem = false;
×
225
    pGroupResInfo->pRows = NULL;
×
226
  } else {
227
    taosArrayDestroy(pGroupResInfo->pRows);
135,090,972✔
228
    pGroupResInfo->pRows = NULL;
135,087,303✔
229
  }
230
  pGroupResInfo->index = 0;
135,095,167✔
231
  pGroupResInfo->delIndex = 0;
135,094,374✔
232
}
135,076,582✔
233

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

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

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

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

254
int32_t initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SSHashObj* pHashmap, int32_t order) {
103,434,890✔
255
  int32_t code = TSDB_CODE_SUCCESS;
103,434,890✔
256
  int32_t lino = 0;
103,434,890✔
257
  if (pGroupResInfo->pRows != NULL) {
103,434,890✔
258
    taosArrayDestroy(pGroupResInfo->pRows);
4,046,512✔
259
  }
260
  if (pGroupResInfo->pBuf) {
103,438,828✔
261
    taosMemoryFree(pGroupResInfo->pBuf);
4,046,877✔
262
    pGroupResInfo->pBuf = NULL;
4,045,393✔
263
  }
264

265
  // extract the result rows information from the hash map
266
  int32_t size = tSimpleHashGetSize(pHashmap);
103,434,258✔
267

268
  void* pData = NULL;
103,437,951✔
269
  pGroupResInfo->pRows = taosArrayInit(size, POINTER_BYTES);
103,437,951✔
270
  QUERY_CHECK_NULL(pGroupResInfo->pRows, code, lino, _end, terrno);
103,441,589✔
271

272
  size_t  keyLen = 0;
103,434,566✔
273
  int32_t iter = 0;
103,436,521✔
274
  int64_t bufLen = 0, offset = 0;
103,435,877✔
275

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

282
  pGroupResInfo->pBuf = taosMemoryMalloc(bufLen);
103,416,770✔
283
  QUERY_CHECK_NULL(pGroupResInfo->pBuf, code, lino, _end, terrno);
103,444,377✔
284

285
  iter = 0;
103,435,804✔
286
  while ((pData = tSimpleHashIterate(pHashmap, pData, &iter)) != NULL) {
2,147,483,647✔
287
    void* key = tSimpleHashGetKey(pData, &keyLen);
2,147,483,647✔
288

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

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

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

300
  if (order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC) {
103,392,671✔
301
    __compar_fn_t fn = (order == TSDB_ORDER_ASC) ? resultrowComparAsc : resultrowComparDesc;
5,982,750✔
302
    size = POINTER_BYTES;
5,982,750✔
303
    taosSort(pGroupResInfo->pRows->pData, taosArrayGetSize(pGroupResInfo->pRows), size, fn);
5,982,750✔
304
  }
305

306
  pGroupResInfo->index = 0;
103,392,484✔
307

308
_end:
103,418,852✔
309
  if (code != TSDB_CODE_SUCCESS) {
103,442,094✔
310
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
311
  }
312
  return code;
103,442,094✔
313
}
314

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

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

326
bool hasRemainResults(SGroupResInfo* pGroupResInfo) {
408,149,513✔
327
  if (pGroupResInfo->pRows == NULL) {
408,149,513✔
328
    return false;
×
329
  }
330

331
  return pGroupResInfo->index < taosArrayGetSize(pGroupResInfo->pRows);
408,151,674✔
332
}
333

334
int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) {
217,385,806✔
335
  if (pGroupResInfo->pRows == 0) {
217,385,806✔
336
    return 0;
×
337
  }
338

339
  return (int32_t)taosArrayGetSize(pGroupResInfo->pRows);
217,396,106✔
340
}
341

342
SArray* createSortInfo(SNodeList* pNodeList) {
53,242,140✔
343
  size_t numOfCols = 0;
53,242,140✔
344

345
  if (pNodeList != NULL) {
53,242,140✔
346
    numOfCols = LIST_LENGTH(pNodeList);
53,031,453✔
347
  } else {
348
    numOfCols = 0;
210,687✔
349
  }
350

351
  SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo));
53,243,646✔
352
  if (pList == NULL) {
53,241,471✔
353
    return pList;
×
354
  }
355

356
  for (int32_t i = 0; i < numOfCols; ++i) {
121,124,773✔
357
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)nodesListGetNode(pNodeList, i);
67,878,766✔
358
    if (!pSortKey) {
67,882,580✔
359
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
360
      taosArrayDestroy(pList);
×
361
      pList = NULL;
×
362
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
363
      break;
×
364
    }
365
    SBlockOrderInfo bi = {0};
67,882,580✔
366
    bi.order = (pSortKey->order == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
67,881,207✔
367
    bi.nullFirst = (pSortKey->nullOrder == NULL_ORDER_FIRST);
67,879,970✔
368

369
    if (nodeType(pSortKey->pExpr) != QUERY_NODE_COLUMN) {
67,879,492✔
370
      qError("invalid order by expr type:%d", nodeType(pSortKey->pExpr));
×
371
      taosArrayDestroy(pList);
×
372
      pList = NULL;
×
373
      terrno = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
374
      break;
×
375
    }
376
    
377
    SColumnNode* pColNode = (SColumnNode*)pSortKey->pExpr;
67,874,537✔
378
    bi.slotId = pColNode->slotId;
67,879,123✔
379
    void* tmp = taosArrayPush(pList, &bi);
67,883,658✔
380
    if (!tmp) {
67,883,658✔
381
      taosArrayDestroy(pList);
×
382
      pList = NULL;
×
383
      break;
×
384
    }
385
  }
386

387
  return pList;
53,245,756✔
388
}
389

390
SSDataBlock* createDataBlockFromDescNode(void* p) {
760,227,093✔
391
  SDataBlockDescNode* pNode = (SDataBlockDescNode*)p;
760,227,093✔
392
  int32_t      numOfCols = LIST_LENGTH(pNode->pSlots);
760,227,093✔
393
  SSDataBlock* pBlock = NULL;
760,148,024✔
394
  int32_t      code = TSDB_CODE_SUCCESS;
760,156,644✔
395
  int32_t      lino = 0;
760,156,644✔
396

397
  code = createDataBlock(&pBlock);
760,156,644✔
398
  QUERY_CHECK_CODE(code, lino, _return);
760,103,106✔
399

400
  pBlock->info.id.blockId = pNode->dataBlockId;
760,103,106✔
401
  pBlock->info.calWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX};
760,176,111✔
402
  pBlock->info.watermark = INT64_MIN;
760,207,398✔
403

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

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

419
  if (pBlock != NULL && i != numOfCols) {
760,457,629✔
420
    code = TSDB_CODE_INVALID_PARA;
×
421
    QUERY_CHECK_CODE(code, lino, _return);
×
422
  }
423

424
  return pBlock;
760,457,629✔
UNCOV
425
_return:
×
426
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
427
  blockDataDestroy(pBlock);
×
428
  terrno = code;
×
429
  return NULL;
×
430
}
431

432
int32_t prepareDataBlockBuf(SSDataBlock* pDataBlock, SColMatchInfo* pMatchInfo) {
257,702,136✔
433
  SDataBlockInfo* pBlockInfo = &pDataBlock->info;
257,702,136✔
434

435
  for (int32_t i = 0; i < taosArrayGetSize(pMatchInfo->pList); ++i) {
1,160,554,477✔
436
    SColMatchItem* pItem = taosArrayGet(pMatchInfo->pList, i);
919,191,293✔
437
    if (!pItem) {
919,140,022✔
438
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
439
      return terrno;
×
440
    }
441

442
    if (pItem->isPk) {
919,140,022✔
443
      SColumnInfoData* pInfoData = taosArrayGet(pDataBlock->pDataBlock, pItem->dstSlotId);
16,356,173✔
444
      if (!pInfoData) {
16,274,291✔
445
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
446
        return terrno;
×
447
      }
448
      pBlockInfo->pks[0].type = pInfoData->info.type;
16,274,291✔
449
      pBlockInfo->pks[1].type = pInfoData->info.type;
16,289,526✔
450

451
      // allocate enough buffer size, which is pInfoData->info.bytes
452
      if (IS_VAR_DATA_TYPE(pItem->dataType.type)) {
16,290,196✔
453
        pBlockInfo->pks[0].pData = taosMemoryCalloc(1, pInfoData->info.bytes);
5,051,247✔
454
        if (pBlockInfo->pks[0].pData == NULL) {
5,034,827✔
455
          return terrno;
×
456
        }
457

458
        pBlockInfo->pks[1].pData = taosMemoryCalloc(1, pInfoData->info.bytes);
5,037,472✔
459
        if (pBlockInfo->pks[1].pData == NULL) {
5,035,522✔
460
          taosMemoryFreeClear(pBlockInfo->pks[0].pData);
×
461
          return terrno;
×
462
        }
463

464
        pBlockInfo->pks[0].nData = pInfoData->info.bytes;
5,035,522✔
465
        pBlockInfo->pks[1].nData = pInfoData->info.bytes;
5,035,483✔
466
      }
467

468
      break;
16,279,027✔
469
    }
470
  }
471

472
  return TSDB_CODE_SUCCESS;
257,589,663✔
473
}
474

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

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

498
    res->translate = true;
735,200✔
499
    res->node.resType = pSColumnNode->node.resType;
735,200✔
500

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

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

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

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

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

559
  return DEAL_RES_CONTINUE;
2,573,200✔
560
}
561

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

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

572
    return TSDB_CODE_SUCCESS;
×
573
  }
574

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

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

599
    return code;
×
600
  }
601

602
  SValueNode* pValue = (SValueNode*)pNew;
367,600✔
603
  *pQualified = pValue->datum.b;
367,600✔
604

605
  nodesDestroyNode(pNew);
367,600✔
606
  return TSDB_CODE_SUCCESS;
367,600✔
607
}
608

609
static EDealRes getColumn(SNode** pNode, void* pContext) {
61,452,277✔
610
  tagFilterAssist* pData = (tagFilterAssist*)pContext;
61,452,277✔
611
  SColumnNode*     pSColumnNode = NULL;
61,452,277✔
612
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
61,458,066✔
613
    pSColumnNode = *(SColumnNode**)pNode;
21,237,765✔
614
  } else if (QUERY_NODE_FUNCTION == nodeType((*pNode))) {
40,235,674✔
615
    SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
1,076,163✔
616
    if (pFuncNode->funcType == FUNCTION_TYPE_TBNAME) {
1,075,344✔
617
      pData->code = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pSColumnNode);
720,344✔
618
      if (NULL == pSColumnNode) {
720,577✔
619
        return DEAL_RES_ERROR;
×
620
      }
621
      pSColumnNode->colId = -1;
720,577✔
622
      pSColumnNode->colType = COLUMN_TYPE_TBNAME;
720,577✔
623
      pSColumnNode->node.resType.type = TSDB_DATA_TYPE_VARCHAR;
720,577✔
624
      pSColumnNode->node.resType.bytes = TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE;
720,577✔
625
      nodesDestroyNode(*pNode);
719,991✔
626
      *pNode = (SNode*)pSColumnNode;
720,577✔
627
    } else {
628
      return DEAL_RES_CONTINUE;
355,586✔
629
    }
630
  } else {
631
    return DEAL_RES_CONTINUE;
39,163,110✔
632
  }
633

634
  void* data = taosHashGet(pData->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId));
21,948,396✔
635
  if (!data) {
21,954,307✔
636
    int32_t tempRes =
637
        taosHashPut(pData->colHash, &pSColumnNode->colId, sizeof(pSColumnNode->colId), pNode, sizeof((*pNode)));
18,934,269✔
638
    if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
18,940,034✔
639
      return DEAL_RES_ERROR;
×
640
    }
641
    pSColumnNode->slotId = pData->index++;
18,940,034✔
642
    SColumnInfo cInfo = {.colId = pSColumnNode->colId,
18,932,285✔
643
                         .type = pSColumnNode->node.resType.type,
18,930,452✔
644
                         .bytes = pSColumnNode->node.resType.bytes,
18,930,535✔
645
                         .pk = pSColumnNode->isPk};
18,932,226✔
646
#if TAG_FILTER_DEBUG
647
    qDebug("tagfilter build column info, slotId:%d, colId:%d, type:%d", pSColumnNode->slotId, cInfo.colId, cInfo.type);
648
#endif
649
    void* tmp = taosArrayPush(pData->cInfoList, &cInfo);
18,927,252✔
650
    if (!tmp) {
18,940,848✔
651
      return DEAL_RES_ERROR;
×
652
    }
653
  } else {
654
    SColumnNode* col = *(SColumnNode**)data;
3,020,038✔
655
    pSColumnNode->slotId = col->slotId;
3,020,038✔
656
  }
657

658
  return DEAL_RES_CONTINUE;
21,946,620✔
659
}
660

661
static int32_t createResultData(SDataType* pType, int32_t numOfRows, SScalarParam* pParam) {
17,667,589✔
662
  SColumnInfoData* pColumnData = taosMemoryCalloc(1, sizeof(SColumnInfoData));
17,667,589✔
663
  if (pColumnData == NULL) {
17,668,752✔
664
    return terrno;
×
665
  }
666

667
  pColumnData->info.type = pType->type;
17,668,752✔
668
  pColumnData->info.bytes = pType->bytes;
17,665,481✔
669
  pColumnData->info.scale = pType->scale;
17,655,746✔
670
  pColumnData->info.precision = pType->precision;
17,658,374✔
671

672
  int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true);
17,660,421✔
673
  if (code != TSDB_CODE_SUCCESS) {
17,657,776✔
674
    terrno = code;
×
675
    releaseColInfoData(pColumnData);
×
676
    return terrno;
×
677
  }
678

679
  pParam->columnData = pColumnData;
17,657,776✔
680
  pParam->colAlloced = true;
17,657,961✔
681
  return TSDB_CODE_SUCCESS;
17,657,215✔
682
}
683

684
static void releaseColInfoData(void* pCol) {
4,919,559✔
685
  if (pCol) {
4,919,559✔
686
    SColumnInfoData* col = (SColumnInfoData*)pCol;
4,919,559✔
687
    colDataDestroy(col);
4,919,559✔
688
    taosMemoryFree(col);
4,920,686✔
689
  }
690
}
4,920,686✔
691

692
void freeItem(void* p) {
207,334,705✔
693
  STUidTagInfo* pInfo = p;
207,334,705✔
694
  if (pInfo->pTagVal != NULL) {
207,334,705✔
695
    taosMemoryFree(pInfo->pTagVal);
206,883,784✔
696
  }
697
}
207,332,025✔
698

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

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

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

726
    (void)memcpy(pStart, &entry->colId, sizeof(col_id_t));
22,554✔
727
    pStart += sizeof(col_id_t);
22,554✔
728

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

774
  return TSDB_CODE_SUCCESS;
11,277✔
775
}
776

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

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

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

802
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
11,277✔
803
    extractTagDataEntry((SOperatorNode*)pTagCond, pIdWithVal);
×
804
  } else if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION) {
11,277✔
805
    SNode* pChild = NULL;
11,277✔
806
    FOREACH(pChild, ((SLogicConditionNode*)pTagCond)->pParameterList) {
33,831✔
807
      extractTagDataEntry((SOperatorNode*)pChild, pIdWithVal);
22,554✔
808
    }
809
  }
810

811
  taosArraySort(pIdWithVal, compareTagDataEntry);
11,277✔
812

813
  return TSDB_CODE_SUCCESS;
11,277✔
814
}
815

816
static int32_t genStableTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) {
11,277✔
817
  if (pTagCond == NULL) {
11,277✔
818
    return TSDB_CODE_SUCCESS;
×
819
  }
820

821
  char*   payload = NULL;
11,277✔
822
  int32_t len = 0;
11,277✔
823
  int32_t code = TSDB_CODE_SUCCESS;
11,277✔
824
  int32_t lino = 0;
11,277✔
825

826
  SArray* pIdWithVal = taosArrayInit(TARRAY_MIN_SIZE, sizeof(STagDataEntry));
11,277✔
827
  code = extractTagFilterTagDataEntries(pTagCond, pIdWithVal);
11,277✔
828
  QUERY_CHECK_CODE(code, lino, _end);
11,277✔
829
  for (int32_t i = 0; i < taosArrayGetSize(pIdWithVal); ++i) {
33,831✔
830
    STagDataEntry* pEntry = taosArrayGet(pIdWithVal, i);
22,554✔
831
    len += sizeof(col_id_t) + pEntry->bytes;
22,554✔
832
  }
833
  code = buildTagDataEntryKey(pIdWithVal, &payload, len);
11,277✔
834
  QUERY_CHECK_CODE(code, lino, _end);
11,277✔
835

836
  tMD5Init(pContext);
11,277✔
837
  tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len);
11,277✔
838
  tMD5Final(pContext);
11,277✔
839

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

850
static int32_t genTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) {
32,807✔
851
  if (pTagCond == NULL) {
32,807✔
852
    return TSDB_CODE_SUCCESS;
30,915✔
853
  }
854

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

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

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

873
  taosMemoryFree(payload);
1,892✔
874
  return TSDB_CODE_SUCCESS;
1,892✔
875
}
876

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

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

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

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

904
int32_t qGetColumnsFromNodeList(void* data, bool isList, SArray** pColList) {
17,227,974✔
905
  int32_t code = TSDB_CODE_SUCCESS;
17,227,974✔
906
  tagFilterAssist ctx = {0};
17,227,974✔
907
  ctx.colHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
17,229,463✔
908
  if (ctx.colHash == NULL) {
17,228,847✔
909
    code = terrno;
×
910
    goto end;
×
911
  }
912

913
  ctx.index = 0;
17,228,847✔
914
  ctx.cInfoList = taosArrayInit(4, sizeof(SColumnInfo));
17,228,847✔
915
  if (ctx.cInfoList == NULL) {
17,229,363✔
916
    code = terrno;
6,693✔
917
    goto end;
×
918
  }
919

920
  if (isList) {
17,222,670✔
921
    SNode* pNode = NULL;
4,477,973✔
922
    FOREACH(pNode, (SNodeList*)data) {
9,397,862✔
923
      nodesRewriteExprPostOrder(&pNode, getColumn, (void*)&ctx);
4,921,375✔
924
      if (TSDB_CODE_SUCCESS != ctx.code) {
4,921,375✔
925
        code = ctx.code;
×
926
        goto end;
×
927
      }
928
      REPLACE_NODE(pNode);
4,921,375✔
929
    }
930
  } else {
931
    SNode* pNode = (SNode*)data;
12,744,697✔
932
    nodesRewriteExprPostOrder(&pNode, getColumn, (void*)&ctx);
12,745,426✔
933
    if (TSDB_CODE_SUCCESS != ctx.code) {
12,750,113✔
934
      code = ctx.code;
×
935
      goto end;
×
936
    }
937
  }
938
  
939
  if (pColList != NULL) *pColList = ctx.cInfoList;
17,231,321✔
940
  ctx.cInfoList = NULL;
17,220,825✔
941

942
end:
17,218,607✔
943
  taosHashCleanup(ctx.colHash);
17,220,314✔
944
  taosArrayDestroy(ctx.cInfoList);
17,208,206✔
945
  return code;
17,211,100✔
946
}
947

948
static int32_t buildGroupInfo(SColumnInfoData* pValue, int32_t i, SArray* gInfo) {
690,388✔
949
  int32_t code = TSDB_CODE_SUCCESS;
690,388✔
950
  SStreamGroupValue* v = taosArrayReserve(gInfo, 1);
690,388✔
951
  if (v == NULL) {
690,062✔
952
    code = terrno;
×
953
    goto end;
×
954
  }
955
  if (colDataIsNull_s(pValue, i)) {
1,379,945✔
956
    v->isNull = true;
7,160✔
957
  } else {
958
    v->isNull = false;
682,723✔
959
    char* data = colDataGetData(pValue, i);
682,872✔
960
    if (pValue->info.type == TSDB_DATA_TYPE_JSON) {
683,162✔
961
      if (tTagIsJson(data)) {
×
962
        code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
×
963
        goto end;
×
964
      }
965
      if (tTagIsJsonNull(data)) {
×
966
        v->isNull = true;
×
967
        goto end;
×
968
      }
969
      int32_t len = getJsonValueLen(data);
×
970
      v->data.type = pValue->info.type;
×
971
      v->data.nData = len;
×
972
      v->data.pData = taosMemoryCalloc(1, len + 1);
×
973
      if (v->data.pData == NULL) {
×
974
        code = terrno;
×
975
        goto end;
×
976
      }
977
      memcpy(v->data.pData, data, len);
×
978
      qDebug("buildGroupInfo:%d add json data len:%d, data:%s", i, len, (char*)v->data.pData);
×
979
    } else if (IS_VAR_DATA_TYPE(pValue->info.type)) {
682,721✔
980
      if (varDataTLen(data) > pValue->info.bytes) {
437,962✔
981
        code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
982
        goto end;
×
983
      }
984
      v->data.type = pValue->info.type;
437,729✔
985
      v->data.nData = varDataLen(data);
438,235✔
986
      v->data.pData = taosMemoryCalloc(1, varDataLen(data) + 1);
438,451✔
987
      if (v->data.pData == NULL) {
438,684✔
988
        code = terrno;
×
989
        goto end;
×
990
      }
991
      memcpy(v->data.pData, varDataVal(data), varDataLen(data));
438,684✔
992
      qDebug("buildGroupInfo:%d add var data type:%d, len:%d, data:%s", i, pValue->info.type, varDataLen(data), (char*)v->data.pData);
438,208✔
993
    } else if (pValue->info.type == TSDB_DATA_TYPE_DECIMAL) {  // reader todo decimal
244,502✔
994
      v->data.type = pValue->info.type;
×
995
      v->data.nData = pValue->info.bytes;
×
996
      v->data.pData = taosMemoryCalloc(1, pValue->info.bytes);
×
997
      if (v->data.pData == NULL) {
×
998
        code = terrno;
×
999
        goto end;
×
1000
      }
1001
      memcpy(&v->data.pData, data, pValue->info.bytes);
×
1002
      qDebug("buildGroupInfo:%d add data type:%d, data:%"PRId64, i, pValue->info.type, v->data.val);
×
1003
    } else {  // reader todo decimal
1004
      v->data.type = pValue->info.type;
244,502✔
1005
      memcpy(&v->data.val, data, pValue->info.bytes);
244,502✔
1006
      qDebug("buildGroupInfo:%d add data type:%d, data:%"PRId64, i, pValue->info.type, v->data.val);
244,558✔
1007
    }
1008
  }
1009
end:
40,288✔
1010
  if (code != TSDB_CODE_SUCCESS) {
690,771✔
1011
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1012
    v->isNull = true;
×
1013
  }
1014
  return code;
690,771✔
1015
}
1016

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

1028
  int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
81,457✔
1029
  if (rows == 0) {
81,457✔
1030
    return;
×
1031
  }
1032

1033
  pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
81,457✔
1034
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
81,457✔
1035

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

1053
  SArray* pColList = NULL;
81,457✔
1054
  code = qGetColumnsFromNodeList(group, true, &pColList);
81,457✔
1055
  if (code != TSDB_CODE_SUCCESS) {
81,457✔
1056
    goto end;
×
1057
  }
1058

1059
  for (int32_t i = 0; i < taosArrayGetSize(pColList); ++i) {
243,889✔
1060
    SColumnInfo* tmp = (SColumnInfo*)taosArrayGet(pColList, i);
162,199✔
1061
    if (tmp != NULL && tmp->colId == -1) {
162,432✔
1062
      tbNameIndex = i;
81,457✔
1063
    }
1064
  }
1065
  
1066
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
81,690✔
1067
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
81,457✔
1068
  taosArrayDestroy(pColList);
81,457✔
1069
  if (pResBlock == NULL) {
81,457✔
1070
    code = terrno;
474✔
1071
    goto end;
474✔
1072
  }
1073

1074
  pBlockList = taosArrayInit(2, POINTER_BYTES);
80,983✔
1075
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
80,983✔
1076

1077
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
80,983✔
1078
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
80,983✔
1079

1080
  groupData = taosArrayInit(2, POINTER_BYTES);
80,983✔
1081
  QUERY_CHECK_NULL(groupData, code, lino, end, terrno);
80,983✔
1082

1083
  SNode* pNode = NULL;
80,983✔
1084
  FOREACH(pNode, group) {
242,437✔
1085
    SScalarParam output = {0};
161,687✔
1086

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

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

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

1119
    if (code != TSDB_CODE_SUCCESS) {
161,687✔
1120
      releaseColInfoData(output.columnData);
×
1121
      goto end;
×
1122
    }
1123

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

1128
  for (int i = 0; i < rows; i++) {
395,008✔
1129
    gInfo = taosArrayInit(taosArrayGetSize(groupData), sizeof(SStreamGroupValue));
314,025✔
1130
    QUERY_CHECK_NULL(gInfo, code, lino, end, terrno);
314,025✔
1131

1132
    STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
314,025✔
1133
    QUERY_CHECK_NULL(info, code, lino, end, terrno);
314,258✔
1134

1135
    for (int j = 0; j < taosArrayGetSize(groupData); j++) {
889,660✔
1136
      SColumnInfoData* pValue = (SColumnInfoData*)taosArrayGetP(groupData, j);
575,142✔
1137
        int32_t ret = buildGroupInfo(pValue, i, gInfo);
575,142✔
1138
        if (ret != TSDB_CODE_SUCCESS) {
575,402✔
1139
          qError("buildGroupInfo failed at line %d since %s", __LINE__, tstrerror(ret));
×
1140
          goto end;
×
1141
        }
1142
        if (j == tbNameIndex) {
575,402✔
1143
          SStreamGroupValue* v = taosArrayGetLast(gInfo);
314,258✔
1144
          if (v != NULL){
314,258✔
1145
            v->isTbname = true;
314,258✔
1146
            v->uid = info->uid;
314,258✔
1147
          }
1148
        }
1149
    }
1150

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

1160
end:
81,457✔
1161
  blockDataDestroy(pResBlock);
81,457✔
1162
  taosArrayDestroy(pBlockList);
81,457✔
1163
  taosArrayDestroyEx(pUidTagList, freeItem);
81,457✔
1164
  taosArrayDestroyP(groupData, releaseColInfoData);
81,457✔
1165
  taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
81,457✔
1166

1167
  if (code != TSDB_CODE_SUCCESS) {
81,457✔
1168
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
474✔
1169
  }
1170
}
1171

1172
int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInfo* pTableListInfo, uint8_t* digest,
4,396,516✔
1173
                                   SStorageAPI* pAPI, bool initRemainGroups, SHashObj* groupIdMap) {
1174
  int32_t      code = TSDB_CODE_SUCCESS;
4,396,516✔
1175
  int32_t      lino = 0;
4,396,516✔
1176
  SArray*      pBlockList = NULL;
4,396,516✔
1177
  SSDataBlock* pResBlock = NULL;
4,396,516✔
1178
  void*        keyBuf = NULL;
4,396,516✔
1179
  SArray*      groupData = NULL;
4,396,516✔
1180
  SArray*      pUidTagList = NULL;
4,396,516✔
1181
  SArray*      tableList = NULL;
4,396,516✔
1182
  SArray*      gInfo = NULL;
4,396,516✔
1183

1184
  int32_t rows = taosArrayGetSize(pTableListInfo->pTableList);
4,396,516✔
1185
  if (rows == 0) {
4,396,516✔
1186
    return TSDB_CODE_SUCCESS;
×
1187
  } 
1188

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

1200
    nodesFree(listNode);
×
1201

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

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

1215
  pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo));
4,396,516✔
1216
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
4,396,516✔
1217

1218
  for (int32_t i = 0; i < rows; ++i) {
28,540,384✔
1219
    STableKeyInfo* pkeyInfo = taosArrayGet(pTableListInfo->pTableList, i);
24,143,868✔
1220
    QUERY_CHECK_NULL(pkeyInfo, code, lino, end, terrno);
24,143,868✔
1221
    STUidTagInfo info = {.uid = pkeyInfo->uid};
24,143,868✔
1222
    void*        tmp = taosArrayPush(pUidTagList, &info);
24,143,868✔
1223
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
24,143,868✔
1224
  }
1225

1226
  if (taosArrayGetSize(pUidTagList) > 0) {
4,396,516✔
1227
    code = pAPI->metaFn.getTableTagsByUid(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
4,396,516✔
1228
  } else {
1229
    code = pAPI->metaFn.getTableTags(pVnode, pTableListInfo->idInfo.suid, pUidTagList);
×
1230
  }
1231
  if (code != TSDB_CODE_SUCCESS) {
4,396,337✔
1232
    goto end;
×
1233
  }
1234

1235
  SArray* pColList = NULL;
4,396,337✔
1236
  code = qGetColumnsFromNodeList(group, true, &pColList); 
4,396,516✔
1237
  if (code != TSDB_CODE_SUCCESS) {
4,396,516✔
1238
    goto end;
×
1239
  }
1240

1241
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
4,396,516✔
1242
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
4,396,516✔
1243
  taosArrayDestroy(pColList);
4,396,516✔
1244
  if (pResBlock == NULL) {
4,396,516✔
1245
    code = terrno;
×
1246
    goto end;
×
1247
  }
1248

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

1252
  pBlockList = taosArrayInit(2, POINTER_BYTES);
4,396,516✔
1253
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
4,396,516✔
1254

1255
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
4,396,516✔
1256
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
4,396,516✔
1257

1258
  groupData = taosArrayInit(2, POINTER_BYTES);
4,396,516✔
1259
  QUERY_CHECK_NULL(groupData, code, lino, end, terrno);
4,396,516✔
1260

1261
  SNode* pNode = NULL;
4,396,516✔
1262
  FOREACH(pNode, group) {
9,155,182✔
1263
    SScalarParam output = {0};
4,758,685✔
1264

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

1290
    if (nodeType(pNode) == QUERY_NODE_COLUMN) {
4,758,876✔
1291
      SColumnNode*     pSColumnNode = (SColumnNode*)pNode;
4,651,866✔
1292
      SColumnInfoData* pColInfo = (SColumnInfoData*)taosArrayGet(pResBlock->pDataBlock, pSColumnNode->slotId);
4,651,866✔
1293
      QUERY_CHECK_NULL(pColInfo, code, lino, end, terrno);
4,651,120✔
1294
      code = colDataAssign(output.columnData, pColInfo, rows, NULL);
4,651,120✔
1295
    } else if (nodeType(pNode) == QUERY_NODE_VALUE) {
106,341✔
1296
      continue;
×
1297
    } else {
1298
      gTaskScalarExtra.pStreamInfo = NULL;
106,341✔
1299
      gTaskScalarExtra.pStreamRange = NULL;
106,341✔
1300
      code = scalarCalculate(pNode, pBlockList, &output, &gTaskScalarExtra);
106,341✔
1301
    }
1302

1303
    if (code != TSDB_CODE_SUCCESS) {
4,756,837✔
1304
      releaseColInfoData(output.columnData);
×
1305
      goto end;
×
1306
    }
1307

1308
    void* tmp = taosArrayPush(groupData, &output.columnData);
4,758,459✔
1309
    QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
4,758,459✔
1310
  }
1311

1312
  int32_t keyLen = 0;
4,396,516✔
1313
  SNode*  node;
1314
  FOREACH(node, group) {
9,150,707✔
1315
    SExprNode* pExpr = (SExprNode*)node;
4,757,917✔
1316
    keyLen += pExpr->resType.bytes;
4,757,917✔
1317
  }
1318

1319
  int32_t nullFlagSize = sizeof(int8_t) * LIST_LENGTH(group);
4,394,862✔
1320
  keyLen += nullFlagSize;
4,394,862✔
1321

1322
  keyBuf = taosMemoryCalloc(1, keyLen);
4,394,862✔
1323
  if (keyBuf == NULL) {
4,395,563✔
1324
    code = terrno;
×
1325
    goto end;
×
1326
  }
1327

1328
  if (initRemainGroups) {
4,395,563✔
1329
    pTableListInfo->remainGroups =
2,049,591✔
1330
        taosHashInit(rows, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
2,049,056✔
1331
    if (pTableListInfo->remainGroups == NULL) {
2,049,591✔
1332
      code = terrno;
×
1333
      goto end;
×
1334
    }
1335
  }
1336

1337
  for (int i = 0; i < rows; i++) {
28,537,368✔
1338
    STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
24,139,792✔
1339
    QUERY_CHECK_NULL(info, code, lino, end, terrno);
24,141,006✔
1340

1341
    if (groupIdMap != NULL){
24,141,006✔
1342
      gInfo = taosArrayInit(taosArrayGetSize(groupData), sizeof(SStreamGroupValue));
72,558✔
1343
    }
1344
    
1345
    char* isNull = (char*)keyBuf;
24,141,073✔
1346
    char* pStart = (char*)keyBuf + sizeof(int8_t) * LIST_LENGTH(group);
24,141,073✔
1347
    for (int j = 0; j < taosArrayGetSize(groupData); j++) {
49,917,088✔
1348
      SColumnInfoData* pValue = (SColumnInfoData*)taosArrayGetP(groupData, j);
25,776,685✔
1349

1350
      if (groupIdMap != NULL && gInfo != NULL) {
25,775,520✔
1351
        int32_t ret = buildGroupInfo(pValue, i, gInfo);
115,123✔
1352
        if (ret != TSDB_CODE_SUCCESS) {
115,369✔
1353
          qError("buildGroupInfo failed at line %d since %s", __LINE__, tstrerror(ret));
×
1354
          taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
×
1355
          gInfo = NULL;
×
1356
        }
1357
      }
1358
      
1359
      if (colDataIsNull_s(pValue, i)) {
51,550,331✔
1360
        isNull[j] = 1;
103,899✔
1361
      } else {
1362
        isNull[j] = 0;
25,670,666✔
1363
        char* data = colDataGetData(pValue, i);
25,673,682✔
1364
        if (pValue->info.type == TSDB_DATA_TYPE_JSON) {
25,672,351✔
1365
          // if (tTagIsJson(data)) {
1366
          //   code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR;
1367
          //   goto end;
1368
          // }
1369
          if (tTagIsJsonNull(data)) {
79,707✔
1370
            isNull[j] = 1;
×
1371
            continue;
×
1372
          }
1373
          int32_t len = getJsonValueLen(data);
79,707✔
1374
          memcpy(pStart, data, len);
79,707✔
1375
          pStart += len;
79,707✔
1376
        } else if (IS_VAR_DATA_TYPE(pValue->info.type)) {
25,593,750✔
1377
          if (IS_STR_DATA_BLOB(pValue->info.type)) {
22,023,154✔
1378
            if (blobDataTLen(data) > TSDB_MAX_BLOB_LEN) {
536✔
1379
              code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
1380
              goto end;
×
1381
            }
1382
            memcpy(pStart, data, blobDataTLen(data));
×
1383
            pStart += blobDataTLen(data);
×
1384
          } else {
1385
            if (varDataTLen(data) > pValue->info.bytes) {
22,026,794✔
1386
              code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER;
×
1387
              goto end;
×
1388
            }
1389
            memcpy(pStart, data, varDataTLen(data));
22,026,795✔
1390
            pStart += varDataTLen(data);
22,028,299✔
1391
          }
1392
        } else {
1393
          memcpy(pStart, data, pValue->info.bytes);
3,564,737✔
1394
          pStart += pValue->info.bytes;
3,564,737✔
1395
        }
1396
      }
1397
    }
1398

1399
    int32_t len = (int32_t)(pStart - (char*)keyBuf);
24,138,219✔
1400
    info->groupId = calcGroupId(keyBuf, len);
24,138,219✔
1401
    if (groupIdMap != NULL && gInfo != NULL) {
24,141,936✔
1402
      int32_t ret = taosHashPut(groupIdMap, &info->groupId, sizeof(info->groupId), &gInfo, POINTER_BYTES);
72,558✔
1403
      if (ret != TSDB_CODE_SUCCESS) {
72,804✔
1404
        qError("put groupid to map failed at line %d since %s", __LINE__, tstrerror(ret));
×
1405
        taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
×
1406
      }
1407
      qDebug("put groupid to map gid:%" PRIu64, info->groupId);
72,804✔
1408
      gInfo = NULL;
72,804✔
1409
    }
1410
    if (initRemainGroups) {
24,142,182✔
1411
      // groupId ~ table uid
1412
      code = taosHashPut(pTableListInfo->remainGroups, &(info->groupId), sizeof(info->groupId), &(info->uid),
11,693,155✔
1413
                         sizeof(info->uid));
1414
      if (code == TSDB_CODE_DUP_KEY) {
11,691,825✔
1415
        code = TSDB_CODE_SUCCESS;
801,079✔
1416
      }
1417
      QUERY_CHECK_CODE(code, lino, end);
11,691,825✔
1418
    }
1419
  }
1420

1421
  if (tsTagFilterCache && groupIdMap == NULL) {
4,397,576✔
1422
    tableList = taosArrayDup(pTableListInfo->pTableList, NULL);
×
1423
    QUERY_CHECK_NULL(tableList, code, lino, end, terrno);
×
1424

1425
    code = pAPI->metaFn.metaPutTbGroupToCache(pVnode, pTableListInfo->idInfo.suid, context.digest,
×
1426
                                              tListLen(context.digest), tableList,
1427
                                              taosArrayGetSize(tableList) * sizeof(STableKeyInfo));
×
1428
    QUERY_CHECK_CODE(code, lino, end);
×
1429
  }
1430

1431
  //  int64_t st2 = taosGetTimestampUs();
1432
  //  qDebug("calculate tag block rows:%d, cost:%ld us", rows, st2-st1);
1433

1434
end:
4,397,576✔
1435
  taosMemoryFreeClear(keyBuf);
4,395,857✔
1436
  blockDataDestroy(pResBlock);
4,396,516✔
1437
  taosArrayDestroy(pBlockList);
4,396,516✔
1438
  taosArrayDestroyEx(pUidTagList, freeItem);
4,396,393✔
1439
  taosArrayDestroyP(groupData, releaseColInfoData);
4,395,858✔
1440
  taosArrayDestroyEx(gInfo, tDestroySStreamGroupValue);
4,395,750✔
1441

1442
  if (code != TSDB_CODE_SUCCESS) {
4,395,313✔
1443
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1444
  }
1445
  return code;
4,394,500✔
1446
}
1447

1448
static int32_t nameComparFn(const void* p1, const void* p2) {
1,409,421✔
1449
  const char* pName1 = *(const char**)p1;
1,409,421✔
1450
  const char* pName2 = *(const char**)p2;
1,409,421✔
1451

1452
  int32_t ret = strcmp(pName1, pName2);
1,409,794✔
1453
  if (ret == 0) {
1,409,794✔
1454
    return 0;
14,847✔
1455
  } else {
1456
    return (ret > 0) ? 1 : -1;
1,394,947✔
1457
  }
1458
}
1459

1460
static SArray* getTableNameList(const SNodeListNode* pList) {
731,854✔
1461
  int32_t    code = TSDB_CODE_SUCCESS;
731,854✔
1462
  int32_t    lino = 0;
731,854✔
1463
  int32_t    len = LIST_LENGTH(pList->pNodeList);
731,854✔
1464
  SListCell* cell = pList->pNodeList->pHead;
731,854✔
1465

1466
  SArray* pTbList = taosArrayInit(len, POINTER_BYTES);
731,854✔
1467
  QUERY_CHECK_NULL(pTbList, code, lino, _end, terrno);
731,854✔
1468

1469
  for (int i = 0; i < pList->pNodeList->length; i++) {
2,109,630✔
1470
    SValueNode* valueNode = (SValueNode*)cell->pNode;
1,377,776✔
1471
    if (!IS_VAR_DATA_TYPE(valueNode->node.resType.type)) {
1,377,776✔
1472
      terrno = TSDB_CODE_INVALID_PARA;
×
1473
      taosArrayDestroy(pTbList);
×
1474
      return NULL;
×
1475
    }
1476

1477
    char* name = varDataVal(valueNode->datum.p);
1,377,776✔
1478
    void* tmp = taosArrayPush(pTbList, &name);
1,377,776✔
1479
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,377,776✔
1480
    cell = cell->pNext;
1,377,776✔
1481
  }
1482

1483
  size_t numOfTables = taosArrayGetSize(pTbList);
731,854✔
1484

1485
  // order the name
1486
  taosArraySort(pTbList, nameComparFn);
731,854✔
1487

1488
  // remove the duplicates
1489
  SArray* pNewList = taosArrayInit(taosArrayGetSize(pTbList), sizeof(void*));
731,854✔
1490
  QUERY_CHECK_NULL(pNewList, code, lino, _end, terrno);
731,854✔
1491
  void* tmpTbl = taosArrayGet(pTbList, 0);
731,854✔
1492
  QUERY_CHECK_NULL(tmpTbl, code, lino, _end, terrno);
731,854✔
1493
  void* tmp = taosArrayPush(pNewList, tmpTbl);
731,481✔
1494
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
731,481✔
1495

1496
  for (int32_t i = 1; i < numOfTables; ++i) {
1,377,403✔
1497
    char** name = taosArrayGetLast(pNewList);
645,549✔
1498
    char** nameInOldList = taosArrayGet(pTbList, i);
645,549✔
1499
    QUERY_CHECK_NULL(nameInOldList, code, lino, _end, terrno);
645,549✔
1500
    if (strcmp(*name, *nameInOldList) == 0) {
645,549✔
1501
      continue;
7,758✔
1502
    }
1503

1504
    tmp = taosArrayPush(pNewList, nameInOldList);
638,164✔
1505
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
638,164✔
1506
  }
1507

1508
_end:
731,854✔
1509
  taosArrayDestroy(pTbList);
731,854✔
1510
  if (code != TSDB_CODE_SUCCESS) {
731,481✔
UNCOV
1511
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
1512
    return NULL;
×
1513
  }
1514
  return pNewList;
731,481✔
1515
}
1516

1517
static int tableUidCompare(const void* a, const void* b) {
×
1518
  uint64_t u1 = *(uint64_t*)a;
×
1519
  uint64_t u2 = *(uint64_t*)b;
×
1520

1521
  if (u1 == u2) {
×
1522
    return 0;
×
1523
  }
1524

1525
  return u1 < u2 ? -1 : 1;
×
1526
}
1527

1528
static int32_t filterTableInfoCompare(const void* a, const void* b) {
141,993✔
1529
  STUidTagInfo* p1 = (STUidTagInfo*)a;
141,993✔
1530
  STUidTagInfo* p2 = (STUidTagInfo*)b;
141,993✔
1531

1532
  if (p1->uid == p2->uid) {
141,993✔
1533
    return 0;
×
1534
  }
1535

1536
  return p1->uid < p2->uid ? -1 : 1;
141,993✔
1537
}
1538

1539
static FilterCondType checkTagCond(SNode* cond) {
14,579,784✔
1540
  if (nodeType(cond) == QUERY_NODE_OPERATOR) {
14,579,784✔
1541
    return FILTER_NO_LOGIC;
10,696,995✔
1542
  }
1543
  if (nodeType(cond) == QUERY_NODE_LOGIC_CONDITION && ((SLogicConditionNode*)cond)->condType == LOGIC_COND_TYPE_AND) {
3,887,812✔
1544
    return FILTER_AND;
3,331,210✔
1545
  }
1546
  return FILTER_OTHER;
553,101✔
1547
}
1548

1549
static int32_t doInWithAnd(SNode* cond, void* pVnode, SArray* list, SStorageAPI* pAPI, uint64_t suid) {
3,895,944✔
1550
  if (nodeType(cond) != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) {
3,895,944✔
1551
    return -1;
553,475✔
1552
  }
1553

1554
  SLogicConditionNode* pNode = (SLogicConditionNode*)cond;
3,341,702✔
1555
  SNodeList*           pList = (SNodeList*)pNode->pParameterList;
3,341,702✔
1556

1557
  int32_t len = LIST_LENGTH(pList);
3,339,921✔
1558
  if (len <= 0) {
3,340,444✔
1559
    return -1;
×
1560
  }
1561

1562
  SListCell* cell = pList->pHead;
3,340,444✔
1563
  for (int i = 0; i < len; i++) {
10,415,575✔
1564
    if (cell == NULL) break;
7,079,529✔
1565
    if (nodeType(cell->pNode) == QUERY_NODE_OPERATOR && optimizeTbnameInCondImpl(pVnode, list, cell->pNode, pAPI, suid) == 0) {
7,079,529✔
1566
      return 0;
8,025✔
1567
    }
1568
    cell = cell->pNext;
7,068,774✔
1569
  }
1570
  return -1;
3,336,046✔
1571
}
1572

1573
static int32_t optimizeTbnameInCond(void* pVnode, int64_t suid, SArray* list, SNode* cond, SStorageAPI* pAPI) {
15,317,211✔
1574
  int32_t code = 0;
15,317,211✔
1575
  int32_t lino = 0;
15,317,211✔
1576
  if (nodeType(cond) == QUERY_NODE_OPERATOR) {
15,317,211✔
1577
    code = optimizeTbnameInCondImpl(pVnode, list, cond, pAPI, suid);
11,421,958✔
1578
  } else {
1579
    code = doInWithAnd(cond, pVnode, list, pAPI, suid);
3,897,023✔
1580
    QUERY_CHECK_CODE(code, lino, end);
3,896,649✔
1581
    code = pAPI->metaFn.getTableTagsByUid(pVnode, suid, list);
7,651✔
1582
  }
1583
  
1584
end:
15,316,375✔
1585
  return code;
15,316,375✔
1586
}
1587

1588
static int32_t getTableListInInOperator(void* pVnode, SArray* pExistedUidList, SNodeListNode* pList, SStorageAPI* pStoreAPI,
731,854✔
1589
                                        uint64_t suid) {
1590
  int32_t   code = 0;                                          
731,854✔
1591
  SArray*   pTbList = getTableNameList(pList);
731,854✔
1592
  int32_t   numOfTables = taosArrayGetSize(pTbList);
731,481✔
1593
  SHashObj* uHash = NULL;
731,481✔
1594

1595
  size_t numOfExisted = taosArrayGetSize(pExistedUidList);  // len > 0 means there already have uids
731,481✔
1596
  if (numOfExisted > 0) {
731,854✔
1597
    uHash = taosHashInit(numOfExisted / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
2,140✔
1598
    if (!uHash) {
2,140✔
1599
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1600
      code = terrno;
×
1601
      goto end;
×
1602
    }
1603

1604
    for (int i = 0; i < numOfExisted; i++) {
2,132,510✔
1605
      STUidTagInfo* pTInfo = taosArrayGet(pExistedUidList, i);
2,130,905✔
1606
      if (!pTInfo) {
2,131,440✔
1607
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1608
        code = terrno;
×
1609
        goto end;
×
1610
      }
1611
      code = taosHashPut(uHash, &pTInfo->uid, sizeof(uint64_t), &i, sizeof(i));
2,131,440✔
1612
      if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_DUP_KEY) {
2,130,370✔
1613
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
1614
        goto end;
×
1615
      }
1616
    }
1617
  }
1618
  taosArrayClear(pExistedUidList);
731,854✔
1619

1620
  for (int i = 0; i < numOfTables; i++) {
2,100,661✔
1621
    char* name = taosArrayGetP(pTbList, i);
1,369,272✔
1622
    uint64_t uid = 0, csuid = 0;
1,369,645✔
1623
    if (pStoreAPI->metaFn.getTableUidByName(pVnode, name, &uid) != 0) {
1,370,018✔
1624
      continue;
905,089✔
1625
    }
1626

1627
    ETableType tbType = TSDB_TABLE_MAX;
464,183✔
1628
    if (pStoreAPI->metaFn.getTableTypeSuidByName(pVnode, name, &tbType, &csuid) == 0 &&
464,183✔
1629
        (tbType == TSDB_CHILD_TABLE || tbType == TSDB_VIRTUAL_CHILD_TABLE) &&
463,253✔
1630
        csuid == suid) {
457,234✔
1631
      if (NULL == uHash || taosHashGet(uHash, &uid, sizeof(uid)) != NULL) {
455,094✔
1632
        STUidTagInfo s = {.uid = uid, .name = name, .pTagVal = NULL};
454,489✔
1633
        void*        tmp = taosArrayPush(pExistedUidList, &s);
454,954✔
1634
        if (!tmp) {
454,954✔
1635
          code = terrno;
×
1636
          goto end;
×
1637
        }
1638
      }
1639
    } 
1640
  }
1641
  taosArraySort(pExistedUidList, filterTableInfoCompare);
731,389✔
1642
  taosArrayRemoveDuplicate(pExistedUidList, filterTableInfoCompare, NULL);
731,854✔
1643
end:
731,946✔
1644
  taosArrayDestroy(pTbList);
731,946✔
1645
  taosHashCleanup(uHash);
731,481✔
1646
  return code;
731,481✔
1647
}
1648

1649
// only return uid that does not contained in pExistedUidList
1650
static int32_t optimizeTbnameInCondImpl(void* pVnode, SArray* pExistedUidList, SNode* pTagCond, SStorageAPI* pStoreAPI,
18,497,305✔
1651
                                        uint64_t suid) {
1652
  SOperatorNode* pNode = (SOperatorNode*)pTagCond;
18,497,305✔
1653
  if (pNode->opType != OP_TYPE_IN) {
18,497,305✔
1654
    return -1;
16,548,826✔
1655
  }
1656

1657
  if ((pNode->pLeft != NULL && ((nodeType(pNode->pLeft) == QUERY_NODE_FUNCTION &&
1,947,446✔
1658
                                 ((SFunctionNode*)pNode->pLeft)->funcType == FUNCTION_TYPE_TBNAME)) ||
734,054✔
1659
       (nodeType(pNode->pLeft) == QUERY_NODE_COLUMN && ((SColumnNode*)pNode->pLeft)->colType == COLUMN_TYPE_TBNAME)) &&
1,213,765✔
1660
      (pNode->pRight != NULL && nodeType(pNode->pRight) == QUERY_NODE_NODE_LIST)) {
733,904✔
1661
    SNodeListNode* pList = (SNodeListNode*)pNode->pRight;
731,854✔
1662

1663
    int32_t len = LIST_LENGTH(pList->pNodeList);
731,854✔
1664
    if (len <= 0) {
731,854✔
1665
      return -1;
×
1666
    }
1667

1668
    return getTableListInInOperator(pVnode, pExistedUidList, pList, pStoreAPI, suid);
731,854✔
1669
  }
1670

1671
  return -1;
1,216,338✔
1672
}
1673

1674
SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, void* pVnode,
18,923,762✔
1675
                                        SStorageAPI* pStorageAPI) {
1676
  int32_t      code = TSDB_CODE_SUCCESS;
18,923,762✔
1677
  int32_t      lino = 0;
18,923,762✔
1678
  SSDataBlock* pResBlock = NULL;
18,923,762✔
1679
  code = createDataBlock(&pResBlock);
18,928,213✔
1680
  QUERY_CHECK_CODE(code, lino, _end);
18,917,485✔
1681

1682
  for (int32_t i = 0; i < taosArrayGetSize(pColList); ++i) {
39,549,906✔
1683
    SColumnInfoData colInfo = {0};
20,643,937✔
1684
    void*           tmp = taosArrayGet(pColList, i);
20,635,514✔
1685
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
20,617,781✔
1686
    colInfo.info = *(SColumnInfo*)tmp;
20,617,781✔
1687
    code = blockDataAppendColInfo(pResBlock, &colInfo);
20,618,424✔
1688
    QUERY_CHECK_CODE(code, lino, _end);
20,626,977✔
1689
  }
1690

1691
  code = blockDataEnsureCapacity(pResBlock, numOfTables);
18,917,098✔
1692
  if (code != TSDB_CODE_SUCCESS) {
18,917,256✔
1693
    terrno = code;
×
1694
    blockDataDestroy(pResBlock);
×
1695
    return NULL;
×
1696
  }
1697

1698
  pResBlock->info.rows = numOfTables;
18,917,256✔
1699

1700
  int32_t numOfCols = taosArrayGetSize(pResBlock->pDataBlock);
18,911,182✔
1701

1702
  for (int32_t i = 0; i < numOfTables; i++) {
228,312,152✔
1703
    STUidTagInfo* p1 = taosArrayGet(pUidTagList, i);
209,381,194✔
1704
    QUERY_CHECK_NULL(p1, code, lino, _end, terrno);
209,363,008✔
1705

1706
    for (int32_t j = 0; j < numOfCols; j++) {
428,615,499✔
1707
      SColumnInfoData* pColInfo = (SColumnInfoData*)taosArrayGet(pResBlock->pDataBlock, j);
219,148,916✔
1708
      QUERY_CHECK_NULL(pColInfo, code, lino, _end, terrno);
219,094,968✔
1709

1710
      if (pColInfo->info.colId == -1) {  // tbname
219,094,968✔
1711
        char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0};
7,463,736✔
1712
        if (p1->name != NULL) {
7,465,552✔
1713
          STR_TO_VARSTR(str, p1->name);
5,885✔
1714
        } else {  // name is not retrieved during filter
1715
          code = pStorageAPI->metaFn.getTableNameByUid(pVnode, p1->uid, str);
7,459,689✔
1716
          QUERY_CHECK_CODE(code, lino, _end);
7,461,157✔
1717
        }
1718

1719
        code = colDataSetVal(pColInfo, i, str, false);
7,466,568✔
1720
        QUERY_CHECK_CODE(code, lino, _end);
7,464,108✔
1721
#if TAG_FILTER_DEBUG
1722
        qDebug("tagfilter uid:%ld, tbname:%s", *uid, str + 2);
1723
#endif
1724
      } else {
1725
        STagVal tagVal = {0};
211,636,113✔
1726
        tagVal.cid = pColInfo->info.colId;
211,646,765✔
1727
        if (p1->pTagVal == NULL) {
211,678,845✔
1728
          colDataSetNULL(pColInfo, i);
4,475✔
1729
        } else {
1730
          const char* p = pStorageAPI->metaFn.extractTagVal(p1->pTagVal, pColInfo->info.type, &tagVal);
211,673,281✔
1731

1732
          if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) {
211,769,439✔
1733
            colDataSetNULL(pColInfo, i);
2,392,921✔
1734
          } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) {
209,377,619✔
1735
            code = colDataSetVal(pColInfo, i, p, false);
630,124✔
1736
            QUERY_CHECK_CODE(code, lino, _end);
630,124✔
1737
          } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
345,675,194✔
1738
            if (IS_STR_DATA_BLOB(pColInfo->info.type)) {
136,916,585✔
UNCOV
1739
              QUERY_CHECK_CODE(code = TSDB_CODE_BLOB_NOT_SUPPORT_TAG, lino, _end);
×
1740
            }
1741
            char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1);
136,951,393✔
1742
            QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
136,948,414✔
1743
            varDataSetLen(tmp, tagVal.nData);
136,948,414✔
1744
            memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData);
136,949,130✔
1745
            code = colDataSetVal(pColInfo, i, tmp, false);
136,954,194✔
1746
#if TAG_FILTER_DEBUG
1747
            qDebug("tagfilter varch:%s", tmp + 2);
1748
#endif
1749
            taosMemoryFree(tmp);
136,934,894✔
1750
            QUERY_CHECK_CODE(code, lino, _end);
136,952,572✔
1751
          } else {
1752
            code = colDataSetVal(pColInfo, i, (const char*)&tagVal.i64, false);
71,780,917✔
1753
            QUERY_CHECK_CODE(code, lino, _end);
71,800,809✔
1754
#if TAG_FILTER_DEBUG
1755
            if (pColInfo->info.type == TSDB_DATA_TYPE_INT) {
1756
              qDebug("tagfilter int:%d", *(int*)(&tagVal.i64));
1757
            } else if (pColInfo->info.type == TSDB_DATA_TYPE_DOUBLE) {
1758
              qDebug("tagfilter double:%f", *(double*)(&tagVal.i64));
1759
            }
1760
#endif
1761
          }
1762
        }
1763
      }
1764
    }
1765
  }
1766

1767
_end:
18,927,855✔
1768
  if (code != TSDB_CODE_SUCCESS) {
18,931,550✔
1769
    blockDataDestroy(pResBlock);
5,843✔
1770
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
474✔
1771
    terrno = code;
474✔
1772
    return NULL;
474✔
1773
  }
1774
  return pResBlock;
18,925,707✔
1775
}
1776

1777
static int32_t doSetQualifiedUid(SArray* pUidList, const SArray* pUidTagList, SColumnInfoData* colData) {
15,297,290✔
1778
  taosArrayClear(pUidList);
15,297,290✔
1779

1780
  int32_t       numOfTables = taosArrayGetSize(pUidTagList);
15,292,295✔
1781
  bool* pResultList = colData == NULL ? NULL : (bool*)colData->pData;
15,294,427✔
1782
  for (int32_t i = 0; i < numOfTables; ++i) {
198,169,087✔
1783
    if (pResultList != NULL && !pResultList[i]) {
182,847,238✔
1784
       continue;
103,797,719✔
1785
    }
1786
    STUidTagInfo* tmpTag = (STUidTagInfo*)taosArrayGet(pUidTagList, i);
79,059,312✔
1787
    if (!tmpTag) {
79,055,244✔
1788
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1789
      return terrno;
×
1790
    }
1791
    uint64_t uid = tmpTag->uid;
79,055,244✔
1792
    qDebug("tagfilter get uid:%" PRId64, uid);
79,061,850✔
1793

1794
    void* tmp = taosArrayPush(pUidList, &uid);
79,078,902✔
1795
    if (tmp == NULL) {
79,078,902✔
1796
      return terrno;
×
1797
    }
1798
  }
1799

1800
  return TSDB_CODE_SUCCESS;
15,321,849✔
1801
}
1802

1803
static int32_t copyExistedUids(SArray* pUidTagList, const SArray* pUidList) {
15,316,837✔
1804
  int32_t code = TSDB_CODE_SUCCESS;
15,316,837✔
1805
  int32_t numOfExisted = taosArrayGetSize(pUidList);
15,316,837✔
1806
  if (numOfExisted == 0) {
15,316,590✔
1807
    return code;
12,600,955✔
1808
  }
1809

1810
  for (int32_t i = 0; i < numOfExisted; ++i) {
30,745,271✔
1811
    uint64_t* uid = taosArrayGet(pUidList, i);
28,029,636✔
1812
    if (!uid) {
28,029,636✔
1813
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1814
      return terrno;
×
1815
    }
1816
    STUidTagInfo info = {.uid = *uid};
28,029,636✔
1817
    void*        tmp = taosArrayPush(pUidTagList, &info);
28,029,636✔
1818
    if (!tmp) {
28,029,636✔
1819
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
1820
      return code;
×
1821
    }
1822
  }
1823
  return code;
2,715,635✔
1824
}
1825

1826
static EDealRes getCids(SNode** pNode, void* pContext) {
6,606✔
1827
  SHashObj* colHash = (SHashObj*)pContext;
6,606✔
1828
  col_id_t colId = 0;
6,606✔
1829
  if (QUERY_NODE_COLUMN == nodeType((*pNode))) {
6,606✔
1830
    colId = (*(SColumnNode**)pNode)->colId;
2,202✔
1831
  } else {
1832
    return DEAL_RES_CONTINUE;
4,404✔
1833
  }
1834

1835
  int32_t tempRes = taosHashPut(colHash, &colId, sizeof(colId), pNode, sizeof((*pNode)));
2,202✔
1836
  if (tempRes != TSDB_CODE_SUCCESS ) {
2,202✔
1837
    return DEAL_RES_ERROR;
×
1838
  }
1839

1840
  return DEAL_RES_CONTINUE;
2,202✔
1841
}
1842

1843
SNode* getTagCondNodeForQueryTmq(void* tinfo) {
685✔
1844
  SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo;
685✔
1845
  const char*    id = GET_TASKID(pTaskInfo);
685✔
1846
  int32_t        code = 0;
685✔
1847

1848
  // traverse to the stream scanner node to add this table id
1849
  SOperatorInfo* pInfo = NULL;
685✔
1850
  code = extractOperatorInTree(pTaskInfo->pRoot, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, id, &pInfo);
685✔
1851
  if (code != 0 || pInfo == NULL) {
685✔
1852
    return NULL;
×
1853
  }
1854

1855
  STmqQueryScanInfo* pScanInfo = pInfo->info;
685✔
1856
  return pScanInfo->pTagCond;
685✔
1857
}
1858

1859
SNode* getTagCondNodeForStableTmq(void* node) {
2,202✔
1860
  return node == NULL ? NULL : ((SSubplan*)node)->pTagCond;
2,202✔
1861
}
1862

1863
bool checkCidInTagCondition(SNode* pTagCond, SArray* cidList) {
2,887✔
1864
  if (pTagCond == NULL) { 
2,887✔
1865
    return false;
685✔
1866
  }
1867
  bool result = true;
2,202✔
1868
  SHashObj *colHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), true, HASH_NO_LOCK);
2,202✔
1869
  if (colHash == NULL) {
2,202✔
1870
    goto end;
×
1871
  }
1872

1873
  nodesRewriteExprPostOrder(&pTagCond, getCids, (void*)colHash);
2,202✔
1874
  if (cidList != NULL) {
2,202✔
1875
    int32_t numOfCols = taosArrayGetSize(cidList);
×
1876
    int32_t i = 0;
×
1877
    for (; i < numOfCols; ++i) {
×
1878
      col_id_t* pCid = taosArrayGet(cidList, i);
×
1879
      void* data = taosHashGet(colHash, pCid, sizeof(*pCid));
×
1880
      if (data != NULL) break;
×
1881
    }
1882
    if (i == numOfCols) { // no tag column involved in condition
×
1883
      result = false;
×
1884
      goto end;
×
1885
    }
1886
  }
1887

1888
end:
2,202✔
1889
  taosHashCleanup(colHash);
2,202✔
1890
  return result;
2,202✔
1891
}
1892

1893
int32_t doFilterByTagCond(int64_t suid, SArray* pUidList, SNode* pTagCond, void* pVnode,
263,028,231✔
1894
                                 SIdxFltStatus status, SStorageAPI* pAPI, void* pStreamInfo) {
1895
  if (pTagCond == NULL) {
263,028,231✔
1896
    return TSDB_CODE_SUCCESS;
247,718,456✔
1897
  }
1898

1899
  terrno = TSDB_CODE_SUCCESS;
15,309,775✔
1900

1901
  int32_t      lino = 0;
15,321,399✔
1902
  int32_t      code = TSDB_CODE_SUCCESS;
15,321,399✔
1903
  SArray*      pBlockList = NULL;
15,321,399✔
1904
  SSDataBlock* pResBlock = NULL;
15,321,399✔
1905
  SScalarParam output = {0};
15,319,481✔
1906
  SArray*      pUidTagList = NULL;
15,318,882✔
1907

1908
  SDataType type = {.type = TSDB_DATA_TYPE_BOOL, .bytes = sizeof(bool)};
15,318,882✔
1909

1910
  pUidTagList = taosArrayInit(10, sizeof(STUidTagInfo));
15,314,257✔
1911
  QUERY_CHECK_NULL(pUidTagList, code, lino, end, terrno);
15,309,897✔
1912

1913
  // pUidList size is 0 if tagIndex is NULL and in query condition
1914
  code = copyExistedUids(pUidTagList, pUidList);
15,309,897✔
1915
  QUERY_CHECK_CODE(code, lino, end);
15,311,332✔
1916

1917
  // Narrow down the scope of the tablelist set if there is tbname in condition and And Logical operator
1918
  code = optimizeTbnameInCond(pVnode, suid, pUidTagList, pTagCond, pAPI);
15,311,332✔
1919
  if (code == 0) {
15,315,567✔
1920
    if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
731,481✔
1921
      goto end;
723,456✔
1922
    }
1923
  } else {
1924
    qDebug("pUidTagList size:%d", (int32_t)taosArrayGetSize(pUidTagList));
14,584,086✔
1925

1926
    FilterCondType condType = checkTagCond(pTagCond);
14,584,086✔
1927
    if (((condType == FILTER_NO_LOGIC || condType == FILTER_AND) && status != SFLT_NOT_INDEX) || // (super table) use tagIndex and operator is and
14,581,631✔
1928
        (status == SFLT_NOT_INDEX && taosArrayGetSize(pUidTagList) > 0)) {                       // (child table with tagCond)
14,583,275✔
1929
      code = pAPI->metaFn.getTableTagsByUid(pVnode, suid, pUidTagList);
2,713,769✔
1930
    } else {
1931
      taosArrayClearEx(pUidTagList, freeItem);       // clear tablelist if using tagIndex and or condition
11,867,517✔
1932
      code = pAPI->metaFn.getTableTags(pVnode, suid, pUidTagList);
11,870,941✔
1933
    }
1934
    if (code != TSDB_CODE_SUCCESS) {
14,585,540✔
1935
      qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code),suid);
×
1936
      terrno = code;
×
1937
      QUERY_CHECK_CODE(code, lino, end);
×
1938
    }
1939
  }
1940

1941
  qDebug("final pUidTagList size:%d", (int32_t)taosArrayGetSize(pUidTagList));
14,593,565✔
1942

1943
  int32_t numOfTables = taosArrayGetSize(pUidTagList);
14,595,653✔
1944
  if (numOfTables == 0) {
14,596,691✔
1945
    goto end;
1,845,955✔
1946
  }
1947

1948
  SArray* pColList = NULL;
12,750,736✔
1949
  code = qGetColumnsFromNodeList(pTagCond, false, &pColList); 
12,751,110✔
1950
  if (code != TSDB_CODE_SUCCESS) {
12,737,175✔
1951
    goto end;
×
1952
  }
1953
  pResBlock = createTagValBlockForFilter(pColList, numOfTables, pUidTagList, pVnode, pAPI);
12,737,175✔
1954
  taosArrayDestroy(pColList);
12,745,147✔
1955
  if (pResBlock == NULL) {
12,745,708✔
1956
    code = terrno;
×
1957
    QUERY_CHECK_CODE(code, lino, end);
×
1958
  }
1959

1960
  //fprintDataBlock(pResBlock, "tagFilter", "", 0);
1961

1962
  //  int64_t st1 = taosGetTimestampUs();
1963
  //  qDebug("generate tag block rows:%d, cost:%ld us", rows, st1-st);
1964
  pBlockList = taosArrayInit(2, POINTER_BYTES);
12,745,708✔
1965
  QUERY_CHECK_NULL(pBlockList, code, lino, end, terrno);
12,746,001✔
1966

1967
  void* tmp = taosArrayPush(pBlockList, &pResBlock);
12,749,357✔
1968
  QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
12,749,357✔
1969

1970
  code = createResultData(&type, numOfTables, &output);
12,749,357✔
1971
  if (code != TSDB_CODE_SUCCESS) {
12,736,970✔
1972
    terrno = code;
×
1973
    QUERY_CHECK_CODE(code, lino, end);
×
1974
  }
1975

1976
  gTaskScalarExtra.pStreamInfo = pStreamInfo;
12,736,970✔
1977
  gTaskScalarExtra.pStreamRange = NULL;
12,736,970✔
1978
  code = scalarCalculate(pTagCond, pBlockList, &output, &gTaskScalarExtra);
12,731,368✔
1979
  if (code != TSDB_CODE_SUCCESS) {
12,724,881✔
1980
    qError("failed to calculate scalar, reason:%s", tstrerror(code));
978✔
1981
    terrno = code;
978✔
1982
    QUERY_CHECK_CODE(code, lino, end);
978✔
1983
  }
1984

1985
end:
15,294,292✔
1986
  if (code == 0) {
15,310,615✔
1987
    code = doSetQualifiedUid(pUidList, pUidTagList, output.columnData);
15,310,519✔
1988
    lino = __LINE__;
15,317,634✔
1989
  }
1990
  
1991
  if (code != 0) {
15,317,730✔
1992
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
978✔
1993
  }
1994
  blockDataDestroy(pResBlock);
15,317,730✔
1995
  taosArrayDestroy(pBlockList);
15,314,290✔
1996
  taosArrayDestroyEx(pUidTagList, freeItem);
15,304,533✔
1997

1998
  colDataDestroy(output.columnData);
15,318,742✔
1999
  taosMemoryFreeClear(output.columnData);
15,317,770✔
2000
  return code;
15,317,231✔
2001
}
2002

2003
typedef struct {
2004
  int32_t code;
2005
  SStreamRuntimeFuncInfo* pStreamRuntimeInfo;
2006
} PlaceHolderContext;
2007

2008
static EDealRes replacePlaceHolderColumn(SNode** pNode, void* pContext) {
82,989✔
2009
  PlaceHolderContext* pData = (PlaceHolderContext*)pContext;
82,989✔
2010
  if (QUERY_NODE_FUNCTION != nodeType((*pNode))) {
82,989✔
2011
    return DEAL_RES_CONTINUE;
68,388✔
2012
  }
2013
  SFunctionNode* pFuncNode = *(SFunctionNode**)(pNode);
14,601✔
2014
  if (!fmIsStreamPesudoColVal(pFuncNode->funcId)) {
14,601✔
2015
    return DEAL_RES_CONTINUE;
542✔
2016
  }
2017
  pData->code = fmSetStreamPseudoFuncParamVal(pFuncNode->funcId, pFuncNode->pParameterList, pData->pStreamRuntimeInfo);
14,059✔
2018
  if (pData->code != TSDB_CODE_SUCCESS) {
14,059✔
2019
    return DEAL_RES_ERROR;
×
2020
  }
2021
  SNode* pFirstParam = nodesListGetNode(pFuncNode->pParameterList, 0);
14,059✔
2022
  ((SValueNode*)pFirstParam)->translate = true;
14,059✔
2023
  SValueNode* res = NULL;
14,059✔
2024
  pData->code = nodesCloneNode(pFirstParam, (SNode**)&res);
14,059✔
2025
  if (NULL == res) {
14,059✔
2026
    return DEAL_RES_ERROR;
×
2027
  }
2028
  nodesDestroyNode(*pNode);
14,059✔
2029
  *pNode = (SNode*)res;
14,059✔
2030

2031
  return DEAL_RES_CONTINUE;
14,059✔
2032
}
2033

2034
static void extractTagColId(SOperatorNode* pOpNode, SArray* pColIdArray) {
22,554✔
2035
  SNode* pLeft = pOpNode->pLeft;
22,554✔
2036
  SNode* pRight = pOpNode->pRight;
22,554✔
2037
  SColumnNode* pColNode = nodeType(pLeft) == QUERY_NODE_COLUMN ?
22,554✔
2038
    (SColumnNode*)pLeft : (SColumnNode*)pRight;
22,554✔
2039

2040
  col_id_t colId = pColNode->colId;
22,554✔
2041
  void* _tmp = taosArrayPush(pColIdArray, &colId);
22,554✔
2042
}
22,554✔
2043

2044
static int32_t buildTagCondKey(
11,277✔
2045
  const SNode* pTagCond, char** pTagCondKey,
2046
  int32_t* tagCondKeyLen, SArray** pTagColIds) {
2047
  if (NULL == pTagCond ||
11,277✔
2048
    (nodeType(pTagCond) != QUERY_NODE_OPERATOR &&
11,277✔
2049
      nodeType(pTagCond) != QUERY_NODE_LOGIC_CONDITION)) {
11,277✔
2050
    qError("invalid parameter to extract tag filter symbol");
×
2051
    return TSDB_CODE_INTERNAL_ERROR;
×
2052
  }
2053
  int32_t code = TSDB_CODE_SUCCESS;
11,277✔
2054
  int32_t lino = 0;
11,277✔
2055
  *pTagColIds = taosArrayInit(4, sizeof(col_id_t));
11,277✔
2056

2057
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR) {
11,277✔
2058
    extractTagColId((SOperatorNode*)pTagCond, *pTagColIds);
×
2059
  } else if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION) {
11,277✔
2060
    SNode* pChild = NULL;
11,277✔
2061
    FOREACH(pChild, ((SLogicConditionNode*)pTagCond)->pParameterList) {
33,831✔
2062
      extractTagColId((SOperatorNode*)pChild, *pTagColIds);
22,554✔
2063
    }
2064
  }
2065

2066
  taosArraySort(*pTagColIds, compareUint16Val);
11,277✔
2067

2068
  // encode ordered colIds into key string, separated by ','
2069
  *tagCondKeyLen =
22,554✔
2070
    (int32_t)(taosArrayGetSize(*pTagColIds) * (sizeof(col_id_t) + 1) - 1);
11,277✔
2071
  *pTagCondKey = (char*)taosMemoryCalloc(1, *tagCondKeyLen);
11,277✔
2072
  TSDB_CHECK_NULL(*pTagCondKey, code, lino, _end, terrno);
11,277✔
2073
  char* pStart = *pTagCondKey;
11,277✔
2074
  for (int32_t i = 0; i < taosArrayGetSize(*pTagColIds); ++i) {
33,831✔
2075
    col_id_t* pColId = (col_id_t*)taosArrayGet(*pTagColIds, i);
22,554✔
2076
    TSDB_CHECK_NULL(pColId, code, lino, _end, terrno);
22,554✔
2077
    memcpy(pStart, pColId, sizeof(col_id_t));
22,554✔
2078
    pStart += sizeof(col_id_t);
22,554✔
2079
    if (i != taosArrayGetSize(*pTagColIds) - 1) {
22,554✔
2080
      *pStart = ',';
11,277✔
2081
      pStart += 1;
11,277✔
2082
    }
2083
  }
2084

2085
_end:
11,277✔
2086
  if (TSDB_CODE_SUCCESS != code) {
11,277✔
2087
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2088
    terrno = code;
×
2089
  }
2090
  return code;
11,277✔
2091
}
2092

2093
static EDealRes canOptimizeTagCondFilter(SNode* pTagCond, void* pContext) {
104,894✔
2094
  if (NULL == pTagCond) {
104,894✔
2095
    *(bool*)pContext = false;
×
2096
    return DEAL_RES_END;
×
2097
  }
2098
  if (nodeType(pTagCond) == QUERY_NODE_VALUE ||
104,894✔
2099
    nodeType(pTagCond) == QUERY_NODE_COLUMN) {
69,631✔
2100
    return DEAL_RES_CONTINUE;
57,817✔
2101
  }
2102
  if (nodeType(pTagCond) == QUERY_NODE_OPERATOR &&
47,077✔
2103
    ((SOperatorNode*)pTagCond)->opType == OP_TYPE_EQUAL) {
23,091✔
2104
    return DEAL_RES_CONTINUE;
22,554✔
2105
  }
2106
  if (nodeType(pTagCond) == QUERY_NODE_LOGIC_CONDITION &&
24,523✔
2107
    ((SLogicConditionNode*)pTagCond)->condType == LOGIC_COND_TYPE_AND) {
11,277✔
2108
    return DEAL_RES_CONTINUE;
11,277✔
2109
  }
2110
  if (nodeType(pTagCond) == QUERY_NODE_FUNCTION &&
25,955✔
2111
    fmIsStreamPesudoColVal(((SFunctionNode*)pTagCond)->funcId)) {
12,709✔
2112
    return DEAL_RES_CONTINUE;
12,709✔
2113
  }
2114
  *(bool*)pContext = false;
537✔
2115
  return DEAL_RES_END;
537✔
2116
}
2117

2118
int32_t getTableList(void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond,
262,974,110✔
2119
                     STableListInfo* pListInfo, uint8_t* digest, const char* idstr, SStorageAPI* pStorageAPI, void* pStreamInfo) {
2120
  int32_t code = TSDB_CODE_SUCCESS;
262,974,110✔
2121
  int32_t lino = 0;
262,974,110✔
2122
  size_t  numOfTables = 0;
262,974,110✔
2123

2124
  pListInfo->idInfo.suid = pScanNode->suid;
262,974,110✔
2125
  pListInfo->idInfo.tableType = pScanNode->tableType;
262,946,079✔
2126

2127
  SArray* pUidList = taosArrayInit(8, sizeof(uint64_t));
262,864,216✔
2128
  QUERY_CHECK_NULL(pUidList, code, lino, end, terrno);
262,902,377✔
2129

2130
  char*   pTagCondKey = NULL;
262,902,377✔
2131
  int32_t tagCondKeyLen;
262,883,011✔
2132
  SArray* pTagColIds = NULL;
262,932,166✔
2133
  char*   pPayload = NULL;
262,946,208✔
2134
  SIdxFltStatus status = SFLT_NOT_INDEX;
262,946,208✔
2135

2136
  qTrace("getTableList called, suid:%" PRIu64
262,946,208✔
2137
    ", tagCond:%p, tagIndexCond:%p, %d %d", pScanNode->suid, pTagCond,
2138
    pTagIndexCond, pScanNode->tableType, pScanNode->virtualStableScan);
2139
  if (pScanNode->tableType != TSDB_SUPER_TABLE && !pScanNode->virtualStableScan) {
262,948,947✔
2140
    pListInfo->idInfo.uid = pScanNode->uid;
145,900,816✔
2141
    if (pStorageAPI->metaFn.isTableExisted(pVnode, pScanNode->uid)) {
145,892,428✔
2142
      void* tmp = taosArrayPush(pUidList, &pScanNode->uid);
145,892,918✔
2143
      QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
145,894,868✔
2144
    }
2145
    code = doFilterByTagCond(pScanNode->suid, pUidList, pTagCond, pVnode, status, pStorageAPI, pStreamInfo);
145,942,285✔
2146
    QUERY_CHECK_CODE(code, lino, end);
145,930,999✔
2147
  } else {
2148
    bool      isStream = (pStreamInfo != NULL);
117,034,858✔
2149
    bool      hasTagCond = (pTagCond != NULL);
117,034,858✔
2150
    bool      canCacheTagEqCondFilter = false;
117,034,858✔
2151
    T_MD5_CTX context = {0};
117,057,828✔
2152

2153
    qTrace("start to get table list by tag filter, suid:%" PRIu64
117,124,564✔
2154
      ",tsStableTagFilterCache:%d, tsTagFilterCache:%d", 
2155
      pScanNode->suid, tsStableTagFilterCache, tsTagFilterCache);
2156

2157
    bool acquired = false;
117,124,564✔
2158
    // first, check whether we can use stable tag filter cache
2159
    if (tsStableTagFilterCache && isStream && hasTagCond) {
117,029,361✔
2160
      canCacheTagEqCondFilter = true;
11,814✔
2161
      nodesWalkExpr(pTagCond, canOptimizeTagCondFilter,
11,814✔
2162
        (void*)&canCacheTagEqCondFilter);
2163
    }
2164
    if (canCacheTagEqCondFilter) {
116,956,787✔
2165
      qDebug("%s, stable tag filter condition can be optimized", idstr);
11,277✔
2166
      if (((SStreamRuntimeFuncInfo*)pStreamInfo)->hasPlaceHolder) {
11,277✔
2167
        SNode* tmp = NULL;
11,277✔
2168
        code = nodesCloneNode((SNode*)pTagCond, &tmp);
11,277✔
2169
        QUERY_CHECK_CODE(code, lino, end);
11,277✔
2170

2171
        PlaceHolderContext ctx = {.code = TSDB_CODE_SUCCESS, .pStreamRuntimeInfo = (SStreamRuntimeFuncInfo*)pStreamInfo};
11,277✔
2172
        nodesRewriteExpr(&tmp, replacePlaceHolderColumn, (void*)&ctx);
11,277✔
2173
        if (TSDB_CODE_SUCCESS != ctx.code) {
11,277✔
2174
          nodesDestroyNode(tmp);
×
2175
          code = ctx.code;
×
2176
          goto end;
×
2177
        }
2178
        code = genStableTagFilterDigest(tmp, &context);
11,277✔
2179
        nodesDestroyNode(tmp);
11,277✔
2180
      } else {
2181
        code = genStableTagFilterDigest(pTagCond, &context);
×
2182
      }
2183
      QUERY_CHECK_CODE(code, lino, end);
11,277✔
2184

2185
      code = buildTagCondKey(
11,277✔
2186
        pTagCond, &pTagCondKey, &tagCondKeyLen, &pTagColIds);
2187
      QUERY_CHECK_CODE(code, lino, end);
11,277✔
2188
      code = pStorageAPI->metaFn.getStableCachedTableList(
11,277✔
2189
        pVnode, pScanNode->suid, pTagCondKey, tagCondKeyLen,
11,277✔
2190
        context.digest, tListLen(context.digest), pUidList, &acquired);
2191
      QUERY_CHECK_CODE(code, lino, end);
11,277✔
2192
    } else if (tsTagFilterCache) {
116,945,510✔
2193
      // second, try to use normal tag filter cache
2194
      qDebug("%s using normal tag filter cache", idstr);
32,807✔
2195
      if (pStreamInfo != NULL && ((SStreamRuntimeFuncInfo*)pStreamInfo)->hasPlaceHolder) {
34,157✔
2196
        SNode* tmp = NULL;
1,350✔
2197
        code = nodesCloneNode((SNode*)pTagCond, &tmp);
1,350✔
2198
        QUERY_CHECK_CODE(code, lino, end);
1,350✔
2199

2200
        PlaceHolderContext ctx = {.code = TSDB_CODE_SUCCESS, .pStreamRuntimeInfo = (SStreamRuntimeFuncInfo*)pStreamInfo};
1,350✔
2201
        nodesRewriteExpr(&tmp, replacePlaceHolderColumn, (void*)&ctx);
1,350✔
2202
        if (TSDB_CODE_SUCCESS != ctx.code) {
1,350✔
2203
          nodesDestroyNode(tmp);
×
2204
          code = ctx.code;
×
2205
          goto end;
×
2206
        }
2207
        code = genTagFilterDigest(tmp, &context);
1,350✔
2208
        nodesDestroyNode(tmp);
1,350✔
2209
      } else {
2210
        code = genTagFilterDigest(pTagCond, &context);
31,457✔
2211
      }
2212
      // try to retrieve the result from meta cache
2213
      QUERY_CHECK_CODE(code, lino, end);      
32,807✔
2214
      code = pStorageAPI->metaFn.getCachedTableList(
32,807✔
2215
        pVnode, pScanNode->suid, context.digest,
32,807✔
2216
        tListLen(context.digest), pUidList, &acquired);
2217
      QUERY_CHECK_CODE(code, lino, end);
44,123✔
2218
    }
2219
    if (acquired) {
116,967,908✔
2220
      taosArrayDestroy(pTagColIds);
30,905✔
2221
      pTagColIds = NULL;
30,905✔
2222
      
2223
      if (digest != NULL) {
30,905✔
2224
        digest[0] = 1;
30,905✔
2225
        memcpy(digest + 1, context.digest, tListLen(context.digest));
30,905✔
2226
      }
2227
      
2228
      qDebug("suid:%" PRIu64 ", %s retrieve table uid list from cache, numOfTables:%d", 
30,905✔
2229
        pScanNode->suid, idstr, (int32_t)taosArrayGetSize(pUidList));
2230
      goto end;
30,905✔
2231
    } else {
2232
      qDebug("suid:%" PRIu64 
116,937,003✔
2233
        ", failed to get table uid list from cache", pScanNode->suid);
2234
    }
2235

2236
    if (!pTagCond) {  // no tag filter condition exists, let's fetch all tables of this super table
117,089,318✔
2237
      code = pStorageAPI->metaFn.getChildTableList(pVnode, pScanNode->suid, pUidList);
102,094,890✔
2238
      QUERY_CHECK_CODE(code, lino, end);
102,047,697✔
2239
      qTrace("no tag filter, get all child tables, numOfTables:%d", (int32_t)taosArrayGetSize(pUidList));
102,047,697✔
2240
    } else {
2241
      SIdxFltStatus status = SFLT_NOT_INDEX;
14,994,428✔
2242
      if (pTagIndexCond) {
14,995,805✔
2243
        void* pIndex = pStorageAPI->metaFn.getInvertIndex(pVnode);
4,193,552✔
2244

2245
        SIndexMetaArg metaArg = {.metaEx = pVnode,
4,193,580✔
2246
                                 .idx = pStorageAPI->metaFn.storeGetIndexInfo(pVnode),
4,193,552✔
2247
                                 .ivtIdx = pIndex,
2248
                                 .suid = pScanNode->uid};
4,193,552✔
2249
        code = doFilterTag(pTagIndexCond, &metaArg, pUidList, &status, &pStorageAPI->metaFilter);
4,193,552✔
2250
        if (code != 0 || status == SFLT_NOT_INDEX) {  // temporarily disable it for performance sake
4,187,573✔
2251
          qDebug("failed to get tableIds from index, suid:%" PRIu64 ", uidListSize:%d", pScanNode->uid, (int32_t)taosArrayGetSize(pUidList));
1,205,795✔
2252
        } else {
2253
          qDebug("succ to get filter result, table num: %d", (int)taosArrayGetSize(pUidList));
2,981,778✔
2254
        }
2255
      }
2256
    }
2257
    qTrace("after index filter, pTagCond:%p uidListSize:%d", pTagCond, (int32_t)taosArrayGetSize(pUidList));
117,043,440✔
2258
    code = doFilterByTagCond(pScanNode->suid, pUidList, pTagCond, pVnode, status, pStorageAPI, pStreamInfo);
117,043,440✔
2259
    QUERY_CHECK_CODE(code, lino, end);
117,025,686✔
2260

2261
    // let's add the filter results into meta-cache
2262
    numOfTables = taosArrayGetSize(pUidList);
117,024,708✔
2263

2264
    if (canCacheTagEqCondFilter) {
117,052,087✔
2265
      qInfo("%s, suid:%" PRIu64 ", add uid list to stable tag filter cache, "
5,012✔
2266
            "uidListSize:%d, origin key:%" PRIu64 ",%" PRIu64,
2267
            idstr, pScanNode->suid, (int32_t)numOfTables,
2268
            *(uint64_t*)context.digest, *(uint64_t*)(context.digest + 8));
2269

2270
      code = pStorageAPI->metaFn.putStableCachedTableList(
5,012✔
2271
        pVnode, pScanNode->suid, pTagCondKey, tagCondKeyLen,
2272
        context.digest, tListLen(context.digest),
2273
        pUidList, &pTagColIds);
2274
      QUERY_CHECK_CODE(code, lino, end);
5,012✔
2275

2276
      if (digest != NULL) {
5,012✔
2277
        digest[0] = 1;
5,012✔
2278
        memcpy(digest + 1, context.digest, tListLen(context.digest));
5,012✔
2279
      }
2280
    } else if (tsTagFilterCache) {
117,047,075✔
2281
      qInfo("%s, suid:%" PRIu64 ", add uid list to normal tag filter cache, "
8,167✔
2282
            "uidListSize:%d, origin key:%" PRIu64 ",%" PRIu64,
2283
            idstr, pScanNode->suid, (int32_t)numOfTables,
2284
            *(uint64_t*)context.digest, *(uint64_t*)(context.digest + 8));
2285
      size_t size = numOfTables * sizeof(uint64_t) + sizeof(int32_t);
8,167✔
2286
      pPayload = taosMemoryMalloc(size);
8,167✔
2287
      QUERY_CHECK_NULL(pPayload, code, lino, end, terrno);
8,167✔
2288

2289
      *(int32_t*)pPayload = (int32_t)numOfTables;
8,167✔
2290
      if (numOfTables > 0) {
8,167✔
2291
        void* tmp = taosArrayGet(pUidList, 0);
6,730✔
2292
        QUERY_CHECK_NULL(tmp, code, lino, end, terrno);
6,730✔
2293
        memcpy(pPayload + sizeof(int32_t), tmp, numOfTables * sizeof(uint64_t));
6,730✔
2294
      }
2295

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

2317

2318
      if (digest != NULL) {
8,167✔
2319
        digest[0] = 1;
8,167✔
2320
        memcpy(digest + 1, context.digest, tListLen(context.digest));
8,167✔
2321
      }
2322
    }
2323
  }
2324

2325
  qDebug("%s, table list with %d uids built", idstr, (int32_t)numOfTables);
262,931,950✔
2326

2327
end:
262,981,095✔
2328
  if (code == 0) {
263,020,439✔
2329
     STableKeyInfo info = {.uid = 0, .groupId = 0};
263,019,461✔
2330
    for (int32_t i = 0; i < taosArrayGetSize(pUidList); ++i) {
961,626,852✔
2331
      int64_t* uid = (int64_t*)taosArrayGet(pUidList, i);
698,469,451✔
2332
      QUERY_CHECK_NULL(uid, code, lino, end, terrno);
698,586,373✔
2333

2334
      info.uid = *uid;
698,586,373✔
2335
        //qInfo("doSetQualifiedUid row:%d added to pTableList", i);
2336
      void* p = taosArrayPush(pListInfo->pTableList, &info);
698,530,915✔
2337
      QUERY_CHECK_NULL(p, code, lino, end, terrno);
698,596,767✔
2338
    }
2339
  } else {
2340
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
978✔
2341
  }
2342
  taosArrayDestroy(pUidList);
263,078,759✔
2343
  taosArrayDestroy(pTagColIds);
262,997,771✔
2344
  taosMemFreeClear(pTagCondKey);
263,008,754✔
2345
  taosMemFreeClear(pPayload);
263,008,754✔
2346
  return code;
263,008,754✔
2347
}
2348

2349
int32_t qGetTableList(int64_t suid, void* pVnode, void* node, SArray** tableList, void* pTaskInfo) {
24,680✔
2350
  int32_t        code = TSDB_CODE_SUCCESS;
24,680✔
2351
  int32_t        lino = 0;
24,680✔
2352
  SSubplan*      pSubplan = (SSubplan*)node;
24,680✔
2353
  SScanPhysiNode pNode = {0};
24,680✔
2354
  pNode.suid = suid;
24,680✔
2355
  pNode.uid = suid;
24,680✔
2356
  pNode.tableType = TSDB_SUPER_TABLE;
24,680✔
2357

2358
  STableListInfo* pTableListInfo = tableListCreate();
24,680✔
2359
  QUERY_CHECK_NULL(pTableListInfo, code, lino, _end, terrno);
24,680✔
2360
  code = getTableList(pVnode, &pNode, pSubplan ? pSubplan->pTagCond : NULL, pSubplan ? pSubplan->pTagIndexCond : NULL,
24,680✔
2361
                      pTableListInfo, NULL, "qGetTableList", &((SExecTaskInfo*)pTaskInfo)->storageAPI, NULL);
2362
  QUERY_CHECK_CODE(code, lino, _end);
24,680✔
2363
  *tableList = pTableListInfo->pTableList;
24,680✔
2364
  pTableListInfo->pTableList = NULL;
24,680✔
2365

2366
_end:
24,680✔
2367
  tableListDestroy(pTableListInfo);
24,680✔
2368
  if (code != TSDB_CODE_SUCCESS) {
24,680✔
2369
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2370
  }
2371
  return code;
24,680✔
2372
}
2373

2374
size_t getTableTagsBufLen(const SNodeList* pGroups) {
×
2375
  size_t keyLen = 0;
×
2376

2377
  SNode* node;
2378
  FOREACH(node, pGroups) {
×
2379
    SExprNode* pExpr = (SExprNode*)node;
×
2380
    keyLen += pExpr->resType.bytes;
×
2381
  }
2382

2383
  keyLen += sizeof(int8_t) * LIST_LENGTH(pGroups);
×
2384
  return keyLen;
×
2385
}
2386

2387
int32_t getGroupIdFromTagsVal(void* pVnode, uint64_t uid, SNodeList* pGroupNode, char* keyBuf, uint64_t* pGroupId,
×
2388
                              SStorageAPI* pAPI) {
2389
  SMetaReader mr = {0};
×
2390

2391
  pAPI->metaReaderFn.initReader(&mr, pVnode, META_READER_LOCK, &pAPI->metaFn);
×
2392
  if (pAPI->metaReaderFn.getEntryGetUidCache(&mr, uid) != 0) {  // table not exist
×
2393
    pAPI->metaReaderFn.clearReader(&mr);
×
2394
    return TSDB_CODE_PAR_TABLE_NOT_EXIST;
×
2395
  }
2396

2397
  SNodeList* groupNew = NULL;
×
2398
  int32_t    code = nodesCloneList(pGroupNode, &groupNew);
×
2399
  if (TSDB_CODE_SUCCESS != code) {
×
2400
    pAPI->metaReaderFn.clearReader(&mr);
×
2401
    return code;
×
2402
  }
2403

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

2414
  SNode*  pNode;
2415
  int32_t index = 0;
×
2416
  FOREACH(pNode, groupNew) {
×
2417
    SNode*  pNew = NULL;
×
2418
    int32_t code = scalarCalculateConstants(pNode, &pNew);
×
2419
    if (TSDB_CODE_SUCCESS == code) {
×
2420
      REPLACE_NODE(pNew);
×
2421
    } else {
2422
      nodesDestroyList(groupNew);
×
2423
      pAPI->metaReaderFn.clearReader(&mr);
×
2424
      return code;
×
2425
    }
2426

2427
    if (nodeType(pNew) != QUERY_NODE_VALUE) {
×
2428
      nodesDestroyList(groupNew);
×
2429
      pAPI->metaReaderFn.clearReader(&mr);
×
2430
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
2431
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2432
    }
2433
    SValueNode* pValue = (SValueNode*)pNew;
×
2434

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

2464
  int32_t len = (int32_t)(pStart - (char*)keyBuf);
×
2465
  *pGroupId = calcGroupId(keyBuf, len);
×
2466

2467
  nodesDestroyList(groupNew);
×
2468
  pAPI->metaReaderFn.clearReader(&mr);
×
2469

2470
  return TSDB_CODE_SUCCESS;
×
2471
}
2472

2473
SArray* makeColumnArrayFromList(SNodeList* pNodeList) {
3,337,759✔
2474
  if (!pNodeList) {
3,337,759✔
2475
    return NULL;
×
2476
  }
2477

2478
  size_t  numOfCols = LIST_LENGTH(pNodeList);
3,337,759✔
2479
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
3,345,255✔
2480
  if (pList == NULL) {
3,337,527✔
2481
    return NULL;
×
2482
  }
2483

2484
  for (int32_t i = 0; i < numOfCols; ++i) {
7,630,615✔
2485
    SColumnNode* pColNode = (SColumnNode*)nodesListGetNode(pNodeList, i);
4,289,904✔
2486
    if (!pColNode) {
4,294,799✔
2487
      taosArrayDestroy(pList);
×
2488
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
2489
      return NULL;
×
2490
    }
2491

2492
    // todo extract method
2493
    SColumn c = {0};
4,294,799✔
2494
    c.slotId = pColNode->slotId;
4,291,755✔
2495
    c.colId = pColNode->colId;
4,293,935✔
2496
    c.type = pColNode->node.resType.type;
4,295,272✔
2497
    c.bytes = pColNode->node.resType.bytes;
4,293,724✔
2498
    c.precision = pColNode->node.resType.precision;
4,292,476✔
2499
    c.scale = pColNode->node.resType.scale;
4,295,768✔
2500

2501
    void* tmp = taosArrayPush(pList, &c);
4,296,389✔
2502
    if (!tmp) {
4,296,389✔
2503
      taosArrayDestroy(pList);
×
2504
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
2505
      return NULL;
×
2506
    }
2507
  }
2508

2509
  return pList;
3,340,711✔
2510
}
2511

2512
int32_t extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols,
332,926,522✔
2513
                            int32_t type, SColMatchInfo* pMatchInfo) {
2514
  size_t  numOfCols = LIST_LENGTH(pNodeList);
332,926,522✔
2515
  int32_t code = TSDB_CODE_SUCCESS;
332,960,572✔
2516
  int32_t lino = 0;
332,960,572✔
2517
  bool    colIdOrdered = true;
332,960,572✔
2518
  bool    hasPrevColId = false;
332,960,572✔
2519
  int32_t prevColId = 0;
332,960,572✔
2520

2521
  pMatchInfo->matchType = type;
332,960,572✔
2522

2523
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColMatchItem));
332,882,187✔
2524
  if (pList == NULL) {
332,805,011✔
2525
    code = terrno;
×
2526
    return code;
×
2527
  }
2528

2529
  SColMatchItem** infoBySlot = NULL;
332,805,011✔
2530
  if (numOfCols > 0) {
332,805,011✔
2531
    infoBySlot = taosMemoryCalloc(numOfCols, sizeof(*infoBySlot));
332,713,885✔
2532
    if (infoBySlot == NULL) {
332,788,863✔
2533
      code = terrno;
×
2534
      goto _end;
×
2535
    }
2536
  }
2537

2538
  SNode* node = NULL;
332,879,989✔
2539
  FOREACH(node, pNodeList) {
1,600,458,690✔
2540
    STargetNode* pNode = (STargetNode*)node;
1,267,337,234✔
2541
    QUERY_CHECK_NULL(pNode, code, lino, _end, terrno);
1,267,337,234✔
2542
    if (nodeType(pNode->pExpr) == QUERY_NODE_COLUMN) {
1,267,337,234✔
2543
      SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
1,255,603,518✔
2544

2545
      SColMatchItem c = {.needOutput = true};
1,255,699,105✔
2546
      c.colId = pColNode->colId;
1,255,667,501✔
2547
      c.srcSlotId = pColNode->slotId;
1,255,756,781✔
2548
      c.dstSlotId = pNode->slotId;
1,255,748,730✔
2549
      c.isPk = pColNode->isPk;
1,255,774,128✔
2550
      c.dataType = pColNode->node.resType;
1,255,753,938✔
2551
      void* tmp = taosArrayPush(pList, &c);
1,255,891,745✔
2552
      QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,255,891,745✔
2553
      if (hasPrevColId) {
1,255,891,745✔
2554
        if (c.colId < prevColId) {
923,369,973✔
2555
          colIdOrdered = false;
14,796,052✔
2556
        }
2557
      } else {
2558
        hasPrevColId = true;
332,521,772✔
2559
      }
2560
      prevColId = c.colId;
1,255,891,745✔
2561
      if (pNode->slotId >= 0 && pNode->slotId < numOfCols) {
1,255,891,745✔
2562
        infoBySlot[pNode->slotId] = (SColMatchItem*)taosArrayGet(pList, taosArrayGetSize(pList) - 1);
1,255,354,934✔
2563
      }
2564
    }
2565
  }
2566
  // set the output flag for each column in SColMatchInfo, according to the
2567
  *numOfOutputCols = 0;
332,979,353✔
2568
  SNode* slotNode = NULL;
332,978,088✔
2569
  FOREACH(slotNode, pOutputNodeList->pSlots) {
1,764,938,171✔
2570
    SSlotDescNode* pNode = (SSlotDescNode*)slotNode;
1,431,362,536✔
2571
    QUERY_CHECK_NULL(pNode, code, lino, _end, terrno);
1,431,362,536✔
2572

2573
    // todo: add reserve flag check
2574
    // it is a column reserved for the arithmetic expression calculation
2575
    if (pNode->slotId >= numOfCols) {
1,431,362,536✔
2576
      (*numOfOutputCols) += 1;
165,322,480✔
2577
      continue;
165,330,128✔
2578
    }
2579

2580
    SColMatchItem* info = infoBySlot ? infoBySlot[pNode->slotId] : NULL;
1,266,654,914✔
2581

2582
    if (pNode->output) {
1,266,644,302✔
2583
      (*numOfOutputCols) += 1;
1,248,661,880✔
2584
    } else if (info != NULL) {
18,072,195✔
2585
      // select distinct tbname from stb where tbname='abc';
2586
      info->needOutput = false;
18,123,322✔
2587
    }
2588
  }
2589

2590
  pMatchInfo->pList = pList;
332,879,668✔
2591
  pMatchInfo->colIdOrdered = colIdOrdered;
332,884,274✔
2592

2593
_end:
332,964,964✔
2594
  taosMemoryFree(infoBySlot);
332,964,964✔
2595
  if (code != TSDB_CODE_SUCCESS) {
332,868,079✔
2596
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2597
  }
2598
  return code;
332,829,922✔
2599
}
2600

2601
static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, int32_t scale, int32_t precision,
1,166,704,802✔
2602
                                  const char* name) {
2603
  SResSchema s = {0};
1,166,704,802✔
2604
  s.scale = scale;
1,166,758,229✔
2605
  s.type = type;
1,166,758,229✔
2606
  s.bytes = bytes;
1,166,758,229✔
2607
  s.slotId = slotId;
1,166,758,229✔
2608
  s.precision = precision;
1,166,758,229✔
2609
  tstrncpy(s.name, name, tListLen(s.name));
1,166,758,229✔
2610

2611
  return s;
1,166,615,559✔
2612
}
2613

2614
static SColumn* createColumn(int32_t blockId, int32_t slotId, int32_t colId, SDataType* pType, EColumnType colType) {
1,099,447,302✔
2615
  SColumn* pCol = taosMemoryCalloc(1, sizeof(SColumn));
1,099,447,302✔
2616
  if (pCol == NULL) {
1,099,238,004✔
2617
    return NULL;
×
2618
  }
2619

2620
  pCol->slotId = slotId;
1,099,238,004✔
2621
  pCol->colId = colId;
1,099,248,010✔
2622
  pCol->bytes = pType->bytes;
1,099,319,392✔
2623
  pCol->type = pType->type;
1,099,419,542✔
2624
  pCol->scale = pType->scale;
1,099,468,294✔
2625
  pCol->precision = pType->precision;
1,099,597,061✔
2626
  pCol->dataBlockId = blockId;
1,099,597,540✔
2627
  pCol->colType = colType;
1,099,548,557✔
2628
  return pCol;
1,099,575,178✔
2629
}
2630

2631
int32_t createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) {
1,166,886,148✔
2632
  int32_t code = TSDB_CODE_SUCCESS;
1,166,886,148✔
2633
  int32_t lino = 0;
1,166,886,148✔
2634
  pExp->base.numOfParams = 0;
1,166,886,148✔
2635
  pExp->base.pParam = NULL;
1,167,036,394✔
2636
  pExp->pExpr = taosMemoryCalloc(1, sizeof(tExprNode));
1,167,046,889✔
2637
  QUERY_CHECK_NULL(pExp->pExpr, code, lino, _end, terrno);
1,166,608,053✔
2638

2639
  pExp->pExpr->_function.num = 1;
1,166,692,342✔
2640
  pExp->pExpr->_function.functionId = -1;
1,166,717,382✔
2641

2642
  int32_t type = nodeType(pNode);
1,166,784,324✔
2643
  // it is a project query, or group by column
2644
  if (type == QUERY_NODE_COLUMN) {
1,166,969,666✔
2645
    pExp->pExpr->nodeType = QUERY_NODE_COLUMN;
664,253,224✔
2646
    SColumnNode* pColNode = (SColumnNode*)pNode;
664,283,958✔
2647

2648
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
664,283,958✔
2649
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
664,195,074✔
2650

2651
    pExp->base.numOfParams = 1;
664,147,496✔
2652

2653
    SDataType* pType = &pColNode->node.resType;
664,170,024✔
2654
    pExp->base.resSchema =
2655
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pColNode->colName);
664,181,297✔
2656

2657
    pExp->base.pParam[0].pCol =
1,328,440,199✔
2658
        createColumn(pColNode->dataBlockId, pColNode->slotId, pColNode->colId, pType, pColNode->colType);
1,328,498,830✔
2659
    QUERY_CHECK_NULL(pExp->base.pParam[0].pCol, code, lino, _end, terrno);
664,232,207✔
2660

2661
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_COLUMN;
664,146,281✔
2662
  } else if (type == QUERY_NODE_VALUE) {
502,716,442✔
2663
    pExp->pExpr->nodeType = QUERY_NODE_VALUE;
17,865,970✔
2664
    SValueNode* pValNode = (SValueNode*)pNode;
17,871,743✔
2665

2666
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
17,871,743✔
2667
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
17,864,686✔
2668

2669
    pExp->base.numOfParams = 1;
17,861,815✔
2670

2671
    SDataType* pType = &pValNode->node.resType;
17,862,085✔
2672
    pExp->base.resSchema =
2673
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pValNode->node.aliasName);
17,857,757✔
2674
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
17,858,579✔
2675
    code = nodesValueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
17,872,061✔
2676
    QUERY_CHECK_CODE(code, lino, _end);
17,866,680✔
2677
  } else if (type == QUERY_NODE_REMOTE_VALUE) {
484,850,472✔
2678
    SRemoteValueNode* pRemote = (SRemoteValueNode*)pNode;
1,441,781✔
2679
    code = qFetchRemoteNode(gTaskScalarExtra.pSubJobCtx, pRemote->subQIdx, pNode);
1,441,781✔
2680
    QUERY_CHECK_CODE(code, lino, _end);
1,443,440✔
2681

2682
    pExp->pExpr->nodeType = QUERY_NODE_VALUE;
1,014,312✔
2683
    SValueNode* pValNode = (SValueNode*)pNode;
1,014,312✔
2684

2685
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
1,014,312✔
2686
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
1,014,312✔
2687

2688
    pExp->base.numOfParams = 1;
1,014,312✔
2689

2690
    SDataType* pType = &pValNode->node.resType;
1,014,312✔
2691
    pExp->base.resSchema =
2692
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pValNode->node.aliasName);
1,014,312✔
2693
    pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
1,014,312✔
2694
    code = nodesValueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
1,014,312✔
2695
    QUERY_CHECK_CODE(code, lino, _end);
1,014,312✔
2696
  } else if (type == QUERY_NODE_FUNCTION) {
483,408,691✔
2697
    pExp->pExpr->nodeType = QUERY_NODE_FUNCTION;
443,174,419✔
2698
    SFunctionNode* pFuncNode = (SFunctionNode*)pNode;
443,181,723✔
2699

2700
    SDataType* pType = &pFuncNode->node.resType;
443,181,723✔
2701
    pExp->base.resSchema =
2702
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pFuncNode->node.aliasName);
443,183,032✔
2703
    tExprNode* pExprNode = pExp->pExpr;
443,185,092✔
2704

2705
    pExprNode->_function.functionId = pFuncNode->funcId;
443,212,111✔
2706
    pExprNode->_function.pFunctNode = pFuncNode;
443,235,798✔
2707
    pExprNode->_function.functionType = pFuncNode->funcType;
443,223,433✔
2708

2709
    tstrncpy(pExprNode->_function.functionName, pFuncNode->functionName, tListLen(pExprNode->_function.functionName));
443,235,979✔
2710

2711
    pExp->base.pParamList = pFuncNode->pParameterList;
443,250,814✔
2712
#if 1
2713
    // todo refactor: add the parameter for tbname function
2714
    const char* name = "tbname";
443,234,689✔
2715
    int32_t     len = strlen(name);
443,234,689✔
2716

2717
    if (!pFuncNode->pParameterList && (memcmp(pExprNode->_function.functionName, name, len) == 0) &&
443,234,689✔
2718
        pExprNode->_function.functionName[len] == 0) {
29,308,972✔
2719
      pFuncNode->pParameterList = NULL;
29,303,000✔
2720
      int32_t     code = nodesMakeList(&pFuncNode->pParameterList);
29,299,168✔
2721
      SValueNode* res = NULL;
29,305,732✔
2722
      if (TSDB_CODE_SUCCESS == code) {
29,308,160✔
2723
        code = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&res);
29,309,927✔
2724
      }
2725
      QUERY_CHECK_CODE(code, lino, _end);
29,313,887✔
2726
      res->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
29,313,887✔
2727
      code = nodesListAppend(pFuncNode->pParameterList, (SNode*)res);
29,303,032✔
2728
      if (code != TSDB_CODE_SUCCESS) {
29,308,737✔
2729
        nodesDestroyNode((SNode*)res);
×
2730
        res = NULL;
×
2731
      }
2732
      QUERY_CHECK_CODE(code, lino, _end);
29,308,737✔
2733
    }
2734
#endif
2735

2736
    int32_t numOfParam = LIST_LENGTH(pFuncNode->pParameterList);
443,132,248✔
2737

2738
    pExp->base.pParam = taosMemoryCalloc(numOfParam, sizeof(SFunctParam));
443,241,112✔
2739
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
443,151,753✔
2740
    pExp->base.numOfParams = numOfParam;
443,123,464✔
2741

2742
    for (int32_t j = 0; j < numOfParam && TSDB_CODE_SUCCESS == code; ++j) {
1,045,736,574✔
2743
      SNode* p1 = nodesListGetNode(pFuncNode->pParameterList, j);
602,602,240✔
2744
      QUERY_CHECK_NULL(p1, code, lino, _end, terrno);
602,677,336✔
2745
      if (p1->type == QUERY_NODE_COLUMN) {
602,677,336✔
2746
        SColumnNode* pcn = (SColumnNode*)p1;
435,387,345✔
2747

2748
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN;
435,387,345✔
2749
        pExp->base.pParam[j].pCol =
870,702,303✔
2750
            createColumn(pcn->dataBlockId, pcn->slotId, pcn->colId, &pcn->node.resType, pcn->colType);
870,697,607✔
2751
        QUERY_CHECK_NULL(pExp->base.pParam[j].pCol, code, lino, _end, terrno);
435,337,034✔
2752
      } else if (p1->type == QUERY_NODE_VALUE) {
167,272,366✔
2753
        SValueNode* pvn = (SValueNode*)p1;
110,624,946✔
2754
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
110,624,946✔
2755
        code = nodesValueNodeToVariant(pvn, &pExp->base.pParam[j].param);
110,591,782✔
2756
        QUERY_CHECK_CODE(code, lino, _end);
110,594,817✔
2757
      } else if (p1->type == QUERY_NODE_REMOTE_VALUE) {
56,677,557✔
2758
        SRemoteValueNode* pRemote = (SRemoteValueNode*)p1;
74,102✔
2759
        code = qFetchRemoteNode(gTaskScalarExtra.pSubJobCtx, pRemote->subQIdx, p1);
74,102✔
2760
        QUERY_CHECK_CODE(code, lino, _end);
74,102✔
2761

2762
        SValueNode* pvn = (SValueNode*)pRemote;
53,641✔
2763
        pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
53,641✔
2764
        code = nodesValueNodeToVariant(pvn, &pExp->base.pParam[j].param);
53,641✔
2765
        QUERY_CHECK_CODE(code, lino, _end);
20,501✔
2766
      }
2767
    }
2768
    pExp->pExpr->_function.bindExprID = ((SExprNode*)pNode)->bindExprID;
443,134,334✔
2769
  } else if (type == QUERY_NODE_OPERATOR) {
40,234,272✔
2770
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
38,776,321✔
2771
    SOperatorNode* pOpNode = (SOperatorNode*)pNode;
38,773,072✔
2772

2773
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
38,773,072✔
2774
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
38,762,869✔
2775
    pExp->base.numOfParams = 1;
38,755,363✔
2776

2777
    SDataType* pType = &pOpNode->node.resType;
38,759,162✔
2778
    pExp->base.resSchema =
2779
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pOpNode->node.aliasName);
38,762,882✔
2780
    pExp->pExpr->_optrRoot.pRootNode = pNode;
38,766,101✔
2781
  } else if (type == QUERY_NODE_CASE_WHEN) {
1,458,085✔
2782
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
1,351,559✔
2783
    SCaseWhenNode* pCaseNode = (SCaseWhenNode*)pNode;
1,351,559✔
2784

2785
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
1,351,559✔
2786
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
1,351,559✔
2787
    pExp->base.numOfParams = 1;
1,351,559✔
2788

2789
    SDataType* pType = &pCaseNode->node.resType;
1,351,559✔
2790
    pExp->base.resSchema =
2791
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pCaseNode->node.aliasName);
1,351,559✔
2792
    pExp->pExpr->_optrRoot.pRootNode = pNode;
1,351,559✔
2793
  } else if (type == QUERY_NODE_LOGIC_CONDITION) {
106,666✔
2794
    pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
105,222✔
2795
    SLogicConditionNode* pCond = (SLogicConditionNode*)pNode;
105,222✔
2796
    pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
105,222✔
2797
    QUERY_CHECK_NULL(pExp->base.pParam, code, lino, _end, terrno);
105,222✔
2798
    pExp->base.numOfParams = 1;
105,222✔
2799
    SDataType* pType = &pCond->node.resType;
105,222✔
2800
    pExp->base.resSchema =
2801
        createResSchema(pType->type, pType->bytes, slotId, pType->scale, pType->precision, pCond->node.aliasName);
105,222✔
2802
    pExp->pExpr->_optrRoot.pRootNode = pNode;
104,682✔
2803
  } else {
2804
    code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
2,462✔
2805
    QUERY_CHECK_CODE(code, lino, _end);
2,462✔
2806
  }
2807
  pExp->pExpr->relatedTo = ((SExprNode*)pNode)->relatedTo;
1,166,455,288✔
2808
_end:
1,167,026,679✔
2809
  if (code != TSDB_CODE_SUCCESS) {
1,167,026,679✔
2810
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
449,589✔
2811
  }
2812
  return code;
1,166,908,173✔
2813
}
2814

2815
int32_t createExprFromTargetNode(SExprInfo* pExp, STargetNode* pTargetNode) {
1,166,981,003✔
2816
  return createExprFromOneNode(pExp, pTargetNode->pExpr, pTargetNode->slotId);
1,166,981,003✔
2817
}
2818

2819
SExprInfo* createExpr(SNodeList* pNodeList, int32_t* numOfExprs) {
×
2820
  *numOfExprs = LIST_LENGTH(pNodeList);
×
2821
  SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo));
×
2822
  if (!pExprs) {
×
2823
    return NULL;
×
2824
  }
2825

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

2837
  return pExprs;
×
2838
}
2839

2840
int32_t createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, SExprInfo** pExprInfo, int32_t* numOfExprs) {
444,596,479✔
2841
  QRY_PARAM_CHECK(pExprInfo);
444,596,479✔
2842

2843
  int32_t code = 0;
444,640,890✔
2844
  int32_t lino = 0;
444,640,890✔
2845
  int32_t numOfFuncs = LIST_LENGTH(pNodeList);
444,640,890✔
2846
  int32_t numOfGroupKeys = 0;
444,584,980✔
2847
  if (pGroupKeys != NULL) {
444,584,980✔
2848
    numOfGroupKeys = LIST_LENGTH(pGroupKeys);
30,887,707✔
2849
  }
2850

2851
  *numOfExprs = numOfFuncs + numOfGroupKeys;
444,584,474✔
2852
  if (*numOfExprs == 0) {
444,622,691✔
2853
    return code;
39,472,777✔
2854
  }
2855

2856
  SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo));
405,165,627✔
2857
  QUERY_CHECK_NULL(pExprs, code, lino, _return, terrno);
404,943,738✔
2858

2859
  int32_t i = 0;
404,943,738✔
2860
  if (pNodeList != NULL) {
404,943,738✔
2861
    SNode* node = NULL;
377,743,960✔
2862
    FOREACH(node, pNodeList) {
1,496,305,485✔
2863
      STargetNode* pTargetNode = (STargetNode*)node;
1,119,180,353✔
2864
      SExprInfo*   pExp = &pExprs[i++];
1,119,180,353✔
2865
      code = createExprFromTargetNode(pExp, pTargetNode);
1,119,105,148✔
2866
      QUERY_CHECK_CODE(code, lino, _return);
1,119,011,114✔
2867
    }
2868
  }
2869

2870
  if (pGroupKeys != NULL) {
404,508,856✔
2871
    SNode* node = NULL;
30,871,409✔
2872
    FOREACH(node, pGroupKeys) {
78,614,730✔
2873
      STargetNode* pTargetNode = (STargetNode*)node;
47,747,511✔
2874
      SExprInfo*   pExp = &pExprs[i++];
47,747,511✔
2875
      code = createExprFromTargetNode(pExp, pTargetNode);
47,739,175✔
2876
      QUERY_CHECK_CODE(code, lino, _return);
47,743,321✔
2877
    }
2878
  }
2879

2880
  *pExprInfo = pExprs;
404,510,420✔
2881
  return code;
404,669,315✔
2882

2883
_return:
449,589✔
2884
  qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
449,589✔
2885
  destroyExprInfo(pExprs, *numOfExprs);
449,589✔
2886
  taosMemoryFreeClear(pExprs);
449,589✔
2887
  return code;
449,589✔
2888
}
2889

2890
static void deleteSubsidiareCtx(void* pData) {
×
2891
  SSubsidiaryResInfo* pCtx = (SSubsidiaryResInfo*)pData;
×
2892
  if (pCtx->pCtx) {
×
2893
    taosMemoryFreeClear(pCtx->pCtx);
×
2894
  }
2895
}
×
2896

2897
// set the output buffer for the selectivity + tag query
2898
static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
432,207,962✔
2899
  int32_t num = 0;
432,207,962✔
2900
  int32_t code = TSDB_CODE_SUCCESS;
432,207,962✔
2901
  int32_t lino = 0;
432,207,962✔
2902

2903
  SArray* pValCtxArray = NULL;
432,207,962✔
2904
  for (int32_t i = numOfOutput - 1; i > 0; --i) {  // select Func is at the end of the list
1,185,822,791✔
2905
    int32_t funcIdx = pCtx[i].pExpr->pExpr->_function.bindExprID;
753,663,141✔
2906
    if (funcIdx > 0) {
753,663,932✔
2907
      if (pValCtxArray == NULL) {
1,588,320✔
2908
        // the end of the list is the select function of biggest index
2909
        pValCtxArray = taosArrayInit_s(sizeof(SSubsidiaryResInfo*), funcIdx);
1,138,984✔
2910
        if (pValCtxArray == NULL) {
1,138,120✔
2911
          return terrno;
×
2912
        }
2913
      }
2914
      if (funcIdx > pValCtxArray->size) {
1,587,456✔
2915
        qError("funcIdx:%d is out of range", funcIdx);
×
2916
        taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
2917
        return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
2918
      }
2919
      SSubsidiaryResInfo* pSubsidiary = &pCtx[i].subsidiaries;
1,587,888✔
2920
      pSubsidiary->pCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
1,587,456✔
2921
      if (pSubsidiary->pCtx == NULL) {
1,587,024✔
2922
        taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
2923
        return terrno;
×
2924
      }
2925
      pSubsidiary->num = 0;
1,587,456✔
2926
      taosArraySet(pValCtxArray, funcIdx - 1, &pSubsidiary);
1,587,024✔
2927
    }
2928
  }
2929

2930
  SqlFunctionCtx*  p = NULL;
432,159,650✔
2931
  SqlFunctionCtx** pValCtx = NULL;
432,159,650✔
2932
  if (pValCtxArray == NULL) {
432,159,650✔
2933
    pValCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
431,014,671✔
2934
    if (pValCtx == NULL) {
431,132,964✔
2935
      QUERY_CHECK_CODE(terrno, lino, _end);
×
2936
    }
2937
  }
2938

2939
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,585,962,408✔
2940
    const char* pName = pCtx[i].pExpr->pExpr->_function.functionName;
1,153,642,795✔
2941
    if ((strcmp(pName, "_select_value") == 0)) {
1,153,808,877✔
2942
      if (pValCtxArray == NULL) {
8,704,482✔
2943
        pValCtx[num++] = &pCtx[i];
6,473,226✔
2944
      } else {
2945
        int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->relatedTo;  // start from index 1;
2,231,256✔
2946
        if (bindFuncIndex > 0) {                                  // 0 is default index related to the select function
2,229,960✔
2947
          bindFuncIndex -= 1;
2,178,120✔
2948
        }
2949
        SSubsidiaryResInfo** pSubsidiary = taosArrayGet(pValCtxArray, bindFuncIndex);
2,229,960✔
2950
        if (pSubsidiary == NULL) {
2,230,392✔
2951
          QUERY_CHECK_CODE(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR, lino, _end);
×
2952
        }
2953
        (*pSubsidiary)->pCtx[(*pSubsidiary)->num] = &pCtx[i];
2,230,392✔
2954
        (*pSubsidiary)->num++;
2,231,256✔
2955
      }
2956
    } else if (fmIsSelectFunc(pCtx[i].functionId)) {
1,145,104,395✔
2957
      if (pValCtxArray == NULL) {
110,302,754✔
2958
        p = &pCtx[i];
108,365,299✔
2959
      }
2960
    }
2961
  }
2962

2963
  if (p != NULL) {
432,319,613✔
2964
    p->subsidiaries.pCtx = pValCtx;
50,102,111✔
2965
    p->subsidiaries.num = num;
50,100,016✔
2966
  } else {
2967
    taosMemoryFreeClear(pValCtx);
382,217,502✔
2968
  }
2969

2970
_end:
1,255,880✔
2971
  if (code != TSDB_CODE_SUCCESS) {
432,216,695✔
2972
    taosArrayDestroyP(pValCtxArray, deleteSubsidiareCtx);
×
2973
    taosMemoryFreeClear(pValCtx);
×
2974
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
2975
  } else {
2976
    taosArrayDestroy(pValCtxArray);
432,216,695✔
2977
  }
2978
  return code;
432,218,763✔
2979
}
2980

2981
SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, int32_t** rowEntryInfoOffset,
432,364,977✔
2982
                                     SFunctionStateStore* pStore) {
2983
  int32_t         code = TSDB_CODE_SUCCESS;
432,364,977✔
2984
  int32_t         lino = 0;
432,364,977✔
2985
  SqlFunctionCtx* pFuncCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
432,364,977✔
2986
  if (pFuncCtx == NULL) {
432,128,483✔
2987
    return NULL;
×
2988
  }
2989

2990
  *rowEntryInfoOffset = taosMemoryCalloc(numOfOutput, sizeof(int32_t));
432,128,483✔
2991
  if (*rowEntryInfoOffset == 0) {
432,374,382✔
2992
    taosMemoryFreeClear(pFuncCtx);
×
2993
    return NULL;
×
2994
  }
2995

2996
  for (int32_t i = 0; i < numOfOutput; ++i) {
1,586,258,486✔
2997
    SExprInfo* pExpr = &pExprInfo[i];
1,153,926,675✔
2998

2999
    SExprBasicInfo* pFunct = &pExpr->base;
1,153,793,029✔
3000
    SqlFunctionCtx* pCtx = &pFuncCtx[i];
1,153,842,662✔
3001

3002
    pCtx->functionId = -1;
1,153,849,152✔
3003
    pCtx->pExpr = pExpr;
1,153,859,421✔
3004

3005
    if (pExpr->pExpr->nodeType == QUERY_NODE_FUNCTION) {
1,153,822,382✔
3006
      SFuncExecEnv env = {0};
441,891,935✔
3007
      pCtx->functionId = pExpr->pExpr->_function.pFunctNode->funcId;
441,891,018✔
3008
      pCtx->isPseudoFunc = fmIsWindowPseudoColumnFunc(pCtx->functionId) || fmIsPlaceHolderFunc(pCtx->functionId);
441,873,734✔
3009
      pCtx->isNotNullFunc = fmIsNotNullOutputFunc(pCtx->functionId);
441,911,137✔
3010

3011
      bool isUdaf = fmIsUserDefinedFunc(pCtx->functionId);
441,888,181✔
3012
      if (fmIsAggFunc(pCtx->functionId) || fmIsIndefiniteRowsFunc(pCtx->functionId)) {
739,842,838✔
3013
        if (!isUdaf) {
298,064,996✔
3014
          code = fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet);
298,028,798✔
3015
          QUERY_CHECK_CODE(code, lino, _end);
297,916,970✔
3016
        } else {
3017
          char* udfName = pExpr->pExpr->_function.pFunctNode->functionName;
36,198✔
3018
          pCtx->udfName = taosStrdup(udfName);
36,198✔
3019
          QUERY_CHECK_NULL(pCtx->udfName, code, lino, _end, terrno);
36,198✔
3020

3021
          code = fmGetUdafExecFuncs(pCtx->functionId, &pCtx->fpSet);
36,198✔
3022
          QUERY_CHECK_CODE(code, lino, _end);
36,198✔
3023
        }
3024
        bool tmp = pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
297,953,168✔
3025
        if (!tmp) {
298,017,960✔
3026
          code = terrno;
×
3027
          QUERY_CHECK_CODE(code, lino, _end);
593✔
3028
        }
3029
      } else {
3030
        if (fmIsPlaceHolderFunc(pCtx->functionId)) {
143,827,908✔
3031
          code = fmGetStreamPesudoFuncEnv(pCtx->functionId, pExpr->base.pParamList, &env);
7,182,802✔
3032
          QUERY_CHECK_CODE(code, lino, _end);
7,183,002✔
3033
        }      
3034
        
3035
        code = fmGetScalarFuncExecFuncs(pCtx->functionId, &pCtx->sfp);
143,833,658✔
3036
        if (code != TSDB_CODE_SUCCESS && isUdaf) {
143,860,808✔
3037
          code = TSDB_CODE_SUCCESS;
60,408✔
3038
        }
3039
        QUERY_CHECK_CODE(code, lino, _end);
143,860,808✔
3040

3041
        if (pCtx->sfp.getEnv != NULL) {
143,860,808✔
3042
          bool tmp = pCtx->sfp.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
27,310,134✔
3043
          if (!tmp) {
27,310,484✔
3044
            code = terrno;
×
3045
            QUERY_CHECK_CODE(code, lino, _end);
×
3046
          }
3047
        }
3048
      }
3049
      pCtx->resDataInfo.interBufSize = env.calcMemSize;
441,875,637✔
3050
    } else if (pExpr->pExpr->nodeType == QUERY_NODE_COLUMN || pExpr->pExpr->nodeType == QUERY_NODE_OPERATOR ||
711,865,930✔
3051
               pExpr->pExpr->nodeType == QUERY_NODE_VALUE) {
18,867,501✔
3052
      // for simple column, the result buffer needs to hold at least one element.
3053
      pCtx->resDataInfo.interBufSize = pFunct->resSchema.bytes;
711,940,660✔
3054
    }
3055

3056
    pCtx->input.numOfInputCols = pFunct->numOfParams;
1,153,926,698✔
3057
    pCtx->input.pData = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
1,153,795,821✔
3058
    QUERY_CHECK_NULL(pCtx->input.pData, code, lino, _end, terrno);
1,153,878,099✔
3059
    pCtx->input.pColumnDataAgg = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
1,153,735,236✔
3060
    QUERY_CHECK_NULL(pCtx->input.pColumnDataAgg, code, lino, _end, terrno);
1,153,854,909✔
3061

3062
    pCtx->pTsOutput = NULL;
1,153,643,763✔
3063
    pCtx->resDataInfo.bytes = pFunct->resSchema.bytes;
1,153,849,569✔
3064
    pCtx->resDataInfo.type = pFunct->resSchema.type;
1,153,797,818✔
3065
    pCtx->order = TSDB_ORDER_ASC;
1,153,721,238✔
3066
    pCtx->start.key = INT64_MIN;
1,153,832,301✔
3067
    pCtx->end.key = INT64_MIN;
1,153,725,663✔
3068
    pCtx->numOfParams = pExpr->base.numOfParams;
1,153,842,275✔
3069
    pCtx->param = pFunct->pParam;
1,153,890,030✔
3070
    pCtx->saveHandle.currentPage = -1;
1,153,907,142✔
3071
    pCtx->pStore = pStore;
1,153,893,998✔
3072
    pCtx->hasWindowOrGroup = false;
1,153,871,626✔
3073
    pCtx->needCleanup = false;
1,153,807,462✔
3074
    pCtx->skipDynDataCheck = false;
1,153,900,642✔
3075
  }
3076

3077
  for (int32_t i = 1; i < numOfOutput; ++i) {
1,186,034,824✔
3078
    (*rowEntryInfoOffset)[i] = (int32_t)((*rowEntryInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) +
1,507,566,247✔
3079
                                         pFuncCtx[i - 1].resDataInfo.interBufSize);
753,774,081✔
3080
  }
3081

3082
  code = setSelectValueColumnInfo(pFuncCtx, numOfOutput);
432,222,869✔
3083
  QUERY_CHECK_CODE(code, lino, _end);
432,219,831✔
3084

3085
_end:
432,219,831✔
3086
  if (code != TSDB_CODE_SUCCESS) {
432,117,703✔
3087
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3088
    for (int32_t i = 0; i < numOfOutput; ++i) {
×
3089
      taosMemoryFree(pFuncCtx[i].input.pData);
×
3090
      taosMemoryFree(pFuncCtx[i].input.pColumnDataAgg);
×
3091
    }
3092
    taosMemoryFreeClear(*rowEntryInfoOffset);
×
3093
    taosMemoryFreeClear(pFuncCtx);
×
3094

3095
    terrno = code;
×
3096
    return NULL;
×
3097
  }
3098
  return pFuncCtx;
432,117,703✔
3099
}
3100

3101
// NOTE: sources columns are more than the destination SSDatablock columns.
3102
// doFilter in table scan needs every column even its output is false
3103
int32_t relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols, bool outputEveryColumn) {
15,258,574✔
3104
  int32_t code = TSDB_CODE_SUCCESS;
15,258,574✔
3105
  size_t  numOfSrcCols = taosArrayGetSize(pCols);
15,258,574✔
3106

3107
  int32_t i = 0, j = 0;
15,259,160✔
3108
  while (i < numOfSrcCols && j < taosArrayGetSize(pColMatchInfo)) {
123,112,867✔
3109
    SColumnInfoData* p = taosArrayGet(pCols, i);
107,857,062✔
3110
    if (!p) {
107,854,259✔
3111
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3112
      return terrno;
×
3113
    }
3114
    SColMatchItem* pmInfo = taosArrayGet(pColMatchInfo, j);
107,854,259✔
3115
    if (!pmInfo) {
107,852,400✔
3116
      return terrno;
×
3117
    }
3118

3119
    if (p->info.colId == pmInfo->colId) {
107,852,400✔
3120
      SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, pmInfo->dstSlotId);
101,007,193✔
3121
      if (!pDst) {
101,008,885✔
3122
        return terrno;
×
3123
      }
3124
      code = colDataAssign(pDst, p, pBlock->info.rows, &pBlock->info);
101,008,885✔
3125
      if (code != TSDB_CODE_SUCCESS) {
101,007,180✔
3126
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
3127
        return code;
×
3128
      }
3129
      i++;
101,007,180✔
3130
      j++;
101,007,180✔
3131
    } else if (p->info.colId < pmInfo->colId) {
6,846,527✔
3132
      i++;
6,846,527✔
3133
    } else {
3134
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
3135
      return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3136
    }
3137
  }
3138
  return code;
15,258,391✔
3139
}
3140

3141
SInterval extractIntervalInfo(const STableScanPhysiNode* pTableScanNode) {
232,694,131✔
3142
  SInterval interval = {
465,475,844✔
3143
      .interval = pTableScanNode->interval,
232,733,744✔
3144
      .sliding = pTableScanNode->sliding,
232,727,727✔
3145
      .intervalUnit = pTableScanNode->intervalUnit,
232,714,650✔
3146
      .slidingUnit = pTableScanNode->slidingUnit,
232,723,186✔
3147
      .offset = pTableScanNode->offset,
232,666,314✔
3148
      .precision = pTableScanNode->scan.node.pOutputDataBlockDesc->precision,
232,720,279✔
3149
      .timeRange = pTableScanNode->scanRange,
3150
  };
3151
  calcIntervalAutoOffset(&interval);
232,821,325✔
3152

3153
  return interval;
232,674,631✔
3154
}
3155

3156
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
52,358,122✔
3157
  SColumn c = {0};
52,358,122✔
3158

3159
  c.slotId = pColNode->slotId;
52,358,122✔
3160
  c.colId = pColNode->colId;
52,363,103✔
3161
  c.type = pColNode->node.resType.type;
52,362,883✔
3162
  c.bytes = pColNode->node.resType.bytes;
52,366,646✔
3163
  c.scale = pColNode->node.resType.scale;
52,356,597✔
3164
  c.precision = pColNode->node.resType.precision;
52,366,239✔
3165
  return c;
52,359,960✔
3166
}
3167

3168

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

3183
  if (cond->skey > cond->ekey || range->skey > range->ekey) {
3,261,162✔
3184
    *twindow = extTwindows[0] = extTwindows[1] = TSWINDOW_DESC_INITIALIZER;
4,995✔
3185
    return code;
4,995✔
3186
  }
3187

3188
  if (range->ekey < cond->skey) {
3,256,167✔
3189
    extTwindows[1] = *cond;
516,894✔
3190
    *twindow = extTwindows[0] = TSWINDOW_DESC_INITIALIZER;
516,894✔
3191
    return code;
516,894✔
3192
  }
3193

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

3200
  // Only scan data in the time range intersecion.
3201
  extTwindows[0] = extTwindows[1] = *cond;
2,378,791✔
3202
  twindow->skey = TMAX(cond->skey, range->skey);
2,378,791✔
3203
  twindow->ekey = TMIN(cond->ekey, range->ekey);
2,378,791✔
3204
  extTwindows[0].ekey = twindow->skey - 1;
2,378,791✔
3205
  extTwindows[1].skey = twindow->ekey + 1;
2,378,791✔
3206

3207
  return code;
2,378,791✔
3208
}
3209

3210
static int32_t getPrimaryTimeRange(SNode** pPrimaryKeyCond, STimeWindow* pTimeRange, bool* isStrict) {
624,444✔
3211
  SNode*  pNew = NULL;
624,444✔
3212
  int32_t code = scalarCalculateRemoteConstants(*pPrimaryKeyCond, &pNew);
624,444✔
3213
  if (TSDB_CODE_SUCCESS == code) {
624,444✔
3214
    *pPrimaryKeyCond = pNew;
624,444✔
3215
    if (nodeType(pNew) != QUERY_NODE_VALUE) {
624,444✔
3216
      code = filterGetTimeRange(*pPrimaryKeyCond, pTimeRange, isStrict, NULL);
624,444✔
3217
    }
3218
  }
3219
  return code;
624,444✔
3220
}
3221

3222
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, STableScanPhysiNode* pTableScanNode,
261,246,445✔
3223
                               const SReadHandle* readHandle, bool applyExtWin) {
3224
  int32_t code = 0;                             
261,246,445✔
3225
  pCond->order = pTableScanNode->scanSeq[0] > 0 ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
261,246,445✔
3226
  pCond->numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols);
261,182,524✔
3227

3228
  pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
261,117,126✔
3229
  if (!pCond->colList) {
261,127,039✔
3230
    return terrno;
×
3231
  }
3232
  pCond->pSlotList = taosMemoryMalloc(sizeof(int32_t) * pCond->numOfCols);
261,094,422✔
3233
  if (pCond->pSlotList == NULL) {
261,140,376✔
3234
    taosMemoryFreeClear(pCond->colList);
×
3235
    return terrno;
×
3236
  }
3237

3238
  // TODO: get it from stable scan node
3239
  pCond->twindows = pTableScanNode->scanRange;
261,033,502✔
3240
  pCond->suid = pTableScanNode->scan.suid;
261,209,066✔
3241
  pCond->type = TIMEWINDOW_RANGE_CONTAINED;
261,157,184✔
3242
  pCond->startVersion = -1;
261,006,432✔
3243
  pCond->endVersion = -1;
261,121,843✔
3244
  pCond->skipRollup = readHandle->skipRollup;
260,981,131✔
3245
  if (readHandle->winRangeValid) {
261,108,505✔
3246
    pCond->twindows = readHandle->winRange;
478,657✔
3247
  }
3248
  pCond->cacheSttStatis = readHandle->cacheSttStatis;
261,100,167✔
3249
  // allowed read stt file optimization mode
3250
  pCond->notLoadData = (pTableScanNode->dataRequired == FUNC_DATA_REQUIRED_NOT_LOAD) &&
522,209,442✔
3251
                       (pTableScanNode->scan.node.pConditions == NULL) && (pTableScanNode->interval == 0);
261,034,494✔
3252

3253
  int32_t j = 0;
261,142,589✔
3254
  SNode*  node = NULL;
261,142,589✔
3255
  FOREACH(node, pTableScanNode->scan.pScanCols) {
1,220,613,761✔
3256
    STargetNode* pNode = (STargetNode*)node;
959,213,734✔
3257
    if (!pNode) {
959,213,734✔
3258
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3259
      return terrno;
×
3260
    }
3261
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
959,213,734✔
3262
    if (pColNode->colType == COLUMN_TYPE_TAG) {
959,244,209✔
3263
      continue;
×
3264
    }
3265

3266
    pCond->colList[j].type = pColNode->node.resType.type;
959,342,015✔
3267
    pCond->colList[j].bytes = pColNode->node.resType.bytes;
959,453,448✔
3268
    pCond->colList[j].colId = pColNode->colId;
959,550,119✔
3269
    pCond->colList[j].pk = pColNode->isPk;
959,385,112✔
3270

3271
    pCond->pSlotList[j] = pNode->slotId;
959,425,047✔
3272
    j += 1;
959,471,172✔
3273
  }
3274

3275
  pCond->numOfCols = j;
261,275,753✔
3276

3277
  if (applyExtWin) {
261,267,695✔
3278
    if (NULL != pTableScanNode->pExtScanRange) {
233,405,286✔
3279
      pCond->type = TIMEWINDOW_RANGE_EXTERNAL;
3,190,233✔
3280
      code = getQueryExtWindow(&pCond->twindows, pTableScanNode->pExtScanRange, &pCond->twindows, pCond->extTwindows);
3,190,233✔
3281
    } else if (readHandle->extWinRangeValid) {
230,084,387✔
3282
      pCond->type = TIMEWINDOW_RANGE_EXTERNAL;
70,929✔
3283
      code = getQueryExtWindow(&pCond->twindows, &readHandle->extWinRange, &pCond->twindows, pCond->extTwindows);
70,929✔
3284
    }
3285
  }
3286

3287
  if (pTableScanNode->pPrimaryCond) {
261,092,791✔
3288
    bool isStrict = false;
624,444✔
3289
    code = getPrimaryTimeRange((SNode**)&pTableScanNode->pPrimaryCond, &pCond->twindows, &isStrict);
624,444✔
3290
    if (code || !isStrict) {
624,444✔
3291
      code = nodesMergeNode((SNode**)&pTableScanNode->scan.node.pConditions, &pTableScanNode->pPrimaryCond);
612,472✔
3292
    }
3293
  }
3294

3295
  return code;
260,949,391✔
3296
}
3297

3298
int32_t initQueryTableDataCondWithColArray(SQueryTableDataCond* pCond, SQueryTableDataCond* pOrgCond,
103,344,989✔
3299
                                           const SReadHandle* readHandle, SArray* colArray) {
3300
  int32_t code = TSDB_CODE_SUCCESS;
103,344,989✔
3301
  int32_t lino = 0;
103,344,989✔
3302

3303
  pCond->order = TSDB_ORDER_ASC;
103,344,989✔
3304
  pCond->numOfCols = (int32_t)taosArrayGetSize(colArray);
103,378,573✔
3305

3306
  pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
103,384,892✔
3307
  QUERY_CHECK_NULL(pCond->colList, code, lino, _return, terrno);
103,357,177✔
3308

3309
  pCond->pSlotList = taosMemoryMalloc(sizeof(int32_t) * pCond->numOfCols);
103,357,629✔
3310
  QUERY_CHECK_NULL(pCond->pSlotList, code, lino, _return, terrno);
103,365,678✔
3311

3312
  pCond->twindows = pOrgCond->twindows;
103,341,515✔
3313
  pCond->order = pOrgCond->order;
103,366,696✔
3314
  pCond->type = pOrgCond->type;
103,382,883✔
3315
  pCond->startVersion = -1;
103,364,491✔
3316
  pCond->endVersion = -1;
103,370,486✔
3317
  pCond->skipRollup = true;
103,383,675✔
3318
  pCond->notLoadData = false;
103,379,124✔
3319

3320
  for (int32_t i = 0; i < pCond->numOfCols; ++i) {
465,014,175✔
3321
    SColIdPair* pColPair = taosArrayGet(colArray, i);
361,679,821✔
3322
    QUERY_CHECK_NULL(pColPair, code, lino, _return, terrno);
361,707,071✔
3323

3324
    bool find = false;
361,694,303✔
3325
    for (int32_t j = 0; j < pOrgCond->numOfCols; ++j) {
1,959,223,233✔
3326
      if (pOrgCond->colList[j].colId == pColPair->vtbColId) {
1,958,808,928✔
3327
        pCond->colList[i].type = pOrgCond->colList[j].type;
361,710,352✔
3328
        // For variable-length types (nchar/binary/varchar/varbinary), use the source table's bytes
3329
        // to avoid tsdb reader doCopyColVal length check failure when source data is longer
3330
        // than the virtual table's defined length.
3331
        if (IS_VAR_DATA_TYPE(pOrgCond->colList[j].type) && pColPair->type.bytes > 0) {
361,702,030✔
3332
          pCond->colList[i].bytes = TMAX(pOrgCond->colList[j].bytes, pColPair->type.bytes);
45,941,525✔
3333
        } else {
3334
          pCond->colList[i].bytes = pOrgCond->colList[j].bytes;
315,799,332✔
3335
        }
3336
        pCond->colList[i].colId = pColPair->orgColId;
361,729,137✔
3337
        pCond->colList[i].pk = pOrgCond->colList[j].pk;
361,712,462✔
3338
        pCond->pSlotList[i] = i;
361,719,640✔
3339
        find = true;
361,725,857✔
3340
        qDebug("%s mapped vtb colId:%d to org colId:%d, type:%d, bytes:%d", __func__, pColPair->vtbColId,
361,725,857✔
3341
               pColPair->orgColId, pCond->colList[i].type, pCond->colList[i].bytes);
3342
        break;
361,629,098✔
3343
      }
3344
    }
3345
    QUERY_CHECK_CONDITION(find, code, lino, _return, TSDB_CODE_NOT_FOUND);
361,642,679✔
3346
  }
3347

3348
  return code;
103,402,567✔
3349
_return:
×
3350
  qError("%s failed at line %d since %s", __func__, lino, tstrerror(terrno));
×
3351
  taosMemoryFreeClear(pCond->colList);
×
3352
  taosMemoryFreeClear(pCond->pSlotList);
×
3353
  return code;
×
3354
}
3355

3356
void cleanupQueryTableDataCond(SQueryTableDataCond* pCond) {
647,065,818✔
3357
  taosMemoryFreeClear(pCond->colList);
647,065,818✔
3358
  taosMemoryFreeClear(pCond->pSlotList);
647,063,225✔
3359
}
647,010,902✔
3360

3361
int32_t convertFillType(int32_t mode) {
3,891,214✔
3362
  int32_t type = TSDB_FILL_NONE;
3,891,214✔
3363
  switch (mode) {
3,891,214✔
3364
    case FILL_MODE_PREV:
197,715✔
3365
      type = TSDB_FILL_PREV;
197,715✔
3366
      break;
197,715✔
3367
    case FILL_MODE_NONE:
×
3368
      type = TSDB_FILL_NONE;
×
3369
      break;
×
3370
    case FILL_MODE_NULL:
180,563✔
3371
      type = TSDB_FILL_NULL;
180,563✔
3372
      break;
180,563✔
3373
    case FILL_MODE_NULL_F:
33,096✔
3374
      type = TSDB_FILL_NULL_F;
33,096✔
3375
      break;
33,096✔
3376
    case FILL_MODE_NEXT:
195,894✔
3377
      type = TSDB_FILL_NEXT;
195,894✔
3378
      break;
195,894✔
3379
    case FILL_MODE_VALUE:
166,642✔
3380
      type = TSDB_FILL_SET_VALUE;
166,642✔
3381
      break;
166,642✔
3382
    case FILL_MODE_VALUE_F:
12,036✔
3383
      type = TSDB_FILL_SET_VALUE_F;
12,036✔
3384
      break;
12,036✔
3385
    case FILL_MODE_LINEAR:
235,138✔
3386
      type = TSDB_FILL_LINEAR;
235,138✔
3387
      break;
235,138✔
3388
    case FILL_MODE_NEAR:
2,870,130✔
3389
      type = TSDB_FILL_NEAR;
2,870,130✔
3390
      break;
2,870,130✔
3391
    default:
×
3392
      type = TSDB_FILL_NONE;
×
3393
  }
3394

3395
  return type;
3,891,214✔
3396
}
3397

3398
void getInitialStartTimeWindow(SInterval* pInterval, TSKEY ts, STimeWindow* w, bool ascQuery) {
2,147,483,647✔
3399
  if (ascQuery) {
2,147,483,647✔
3400
    *w = getAlignQueryTimeWindow(pInterval, ts);
2,147,483,647✔
3401
  } else {
3402
    // the start position of the first time window in the endpoint that spreads beyond the queried last timestamp
3403
    *w = getAlignQueryTimeWindow(pInterval, ts);
20,430✔
3404

3405
    int64_t key = w->skey;
269,737✔
3406
    while (key < ts) {  // moving towards end
286,433✔
3407
      key = getNextTimeWindowStart(pInterval, key, TSDB_ORDER_ASC);
134,428✔
3408
      if (key > ts) {
133,797✔
3409
        break;
117,101✔
3410
      }
3411

3412
      w->skey = key;
16,696✔
3413
    }
3414
    w->ekey = taosTimeAdd(w->skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision, NULL) - 1;
269,106✔
3415
  }
3416
}
2,147,483,647✔
3417

3418
static STimeWindow doCalculateTimeWindow(int64_t ts, SInterval* pInterval) {
74,375,609✔
3419
  STimeWindow w = {0};
74,375,609✔
3420

3421
  w.skey = taosTimeTruncate(ts, pInterval);
74,375,609✔
3422
  w.ekey = taosTimeGetIntervalEnd(w.skey, pInterval);
74,365,331✔
3423
  return w;
74,377,041✔
3424
}
3425

3426
STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order) {
1,534,904✔
3427
  STimeWindow win = *pWindow;
1,534,904✔
3428
  STimeWindow save = win;
1,534,904✔
3429
  while (win.skey <= ts && win.ekey >= ts) {
8,696,731✔
3430
    save = win;
7,161,827✔
3431
    // get previous time window
3432
    getNextTimeWindow(pInterval, &win, order == TSDB_ORDER_DESC ? TSDB_ORDER_ASC : TSDB_ORDER_DESC);
7,161,827✔
3433
  }
3434

3435
  return save;
1,534,904✔
3436
}
3437

3438
// get the correct time window according to the handled timestamp
3439
// todo refactor
3440
STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval,
114,237,497✔
3441
                                int32_t order) {
3442
  STimeWindow w = {0};
114,237,497✔
3443
  if (pResultRowInfo->cur.pageId == -1) {  // the first window, from the previous stored value
114,246,550✔
3444
    getInitialStartTimeWindow(pInterval, ts, &w, (order != TSDB_ORDER_DESC));
3,251,369✔
3445
    return w;
3,254,026✔
3446
  }
3447

3448
  SResultRow* pRow = getResultRowByPos(pBuf, &pResultRowInfo->cur, false);
111,001,370✔
3449
  if (pRow) {
111,003,670✔
3450
    TAOS_SET_OBJ_ALIGNED(&w, pRow->win);
111,005,073✔
3451
  }
3452

3453
  // in case of typical time window, we can calculate time window directly.
3454
  if (w.skey > ts || w.ekey < ts) {
111,004,203✔
3455
    w = doCalculateTimeWindow(ts, pInterval);
74,375,541✔
3456
  }
3457

3458
  if (pInterval->interval != pInterval->sliding) {
111,005,703✔
3459
    // it is an sliding window query, in which sliding value is not equalled to
3460
    // interval value, and we need to find the first qualified time window.
3461
    w = getFirstQualifiedTimeWindow(ts, &w, pInterval, order);
1,534,904✔
3462
  }
3463

3464
  return w;
110,996,419✔
3465
}
3466

3467
void getNextTimeWindow(const SInterval* pInterval, STimeWindow* tw, int32_t order) {
2,147,483,647✔
3468
  tw->skey = getNextTimeWindowStart(pInterval, tw->skey, order);
2,147,483,647✔
3469
  tw->ekey = taosTimeGetIntervalEnd(tw->skey, pInterval);
2,147,483,647✔
3470
}
2,147,483,647✔
3471

3472
bool hasLimitOffsetInfo(SLimitInfo* pLimitInfo) {
541,016,886✔
3473
  return (pLimitInfo->limit.limit != -1 || pLimitInfo->limit.offset != -1 || pLimitInfo->slimit.limit != -1 ||
1,078,217,511✔
3474
          pLimitInfo->slimit.offset != -1);
537,200,362✔
3475
}
3476

3477
bool hasSlimitOffsetInfo(SLimitInfo* pLimitInfo) {
×
3478
  return (pLimitInfo->slimit.limit != -1 || pLimitInfo->slimit.offset != -1);
×
3479
}
3480

3481
void initLimitInfo(const SNode* pLimit, const SNode* pSLimit, SLimitInfo* pLimitInfo) {
636,161,851✔
3482
  SLimit limit = {.limit = getLimit(pLimit), .offset = getOffset(pLimit)};
636,161,851✔
3483
  SLimit slimit = {.limit = getLimit(pSLimit), .offset = getOffset(pSLimit)};
635,987,378✔
3484

3485
  pLimitInfo->limit = limit;
635,985,683✔
3486
  pLimitInfo->slimit = slimit;
635,987,101✔
3487
  pLimitInfo->remainOffset = limit.offset;
635,970,804✔
3488
  pLimitInfo->remainGroupOffset = slimit.offset;
635,951,279✔
3489
  pLimitInfo->numOfOutputRows = 0;
635,996,848✔
3490
  pLimitInfo->numOfOutputGroups = 0;
636,033,721✔
3491
  pLimitInfo->currentGroupId = 0;
636,031,873✔
3492
}
636,057,566✔
3493

3494
void resetLimitInfoForNextGroup(SLimitInfo* pLimitInfo) {
97,716,235✔
3495
  pLimitInfo->numOfOutputRows = 0;
97,716,235✔
3496
  pLimitInfo->remainOffset = pLimitInfo->limit.offset;
97,749,017✔
3497
}
97,767,344✔
3498

3499
int32_t tableListGetSize(const STableListInfo* pTableList, int32_t* pRes) {
660,232,176✔
3500
  if (taosArrayGetSize(pTableList->pTableList) != taosHashGetSize(pTableList->map)) {
660,232,176✔
3501
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR));
×
3502
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
3503
  }
3504
  (*pRes) = taosArrayGetSize(pTableList->pTableList);
660,191,568✔
3505
  return TSDB_CODE_SUCCESS;
660,199,012✔
3506
}
3507

3508
uint64_t tableListGetSuid(const STableListInfo* pTableList) { return pTableList->idInfo.suid; }
3,561,076✔
3509

3510
STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index) {
214,322,202✔
3511
  if (taosArrayGetSize(pTableList->pTableList) == 0) {
214,322,202✔
3512
    return NULL;
2,197✔
3513
  }
3514

3515
  return taosArrayGet(pTableList->pTableList, index);
214,266,333✔
3516
}
3517

3518
int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t startIndex) {
49,348✔
3519
  int32_t numOfTables = taosArrayGetSize(pTableList->pTableList);
49,348✔
3520
  if (startIndex >= numOfTables) {
49,348✔
3521
    return -1;
×
3522
  }
3523

3524
  for (int32_t i = startIndex; i < numOfTables; ++i) {
544,631✔
3525
    STableKeyInfo* p = taosArrayGet(pTableList->pTableList, i);
544,631✔
3526
    if (!p) {
544,631✔
3527
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3528
      return -1;
×
3529
    }
3530
    if (p->uid == uid) {
544,631✔
3531
      return i;
49,348✔
3532
    }
3533
  }
3534
  return -1;
×
3535
}
3536

3537
void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type) {
416,300✔
3538
  *psuid = pTableList->idInfo.suid;
416,300✔
3539
  *uid = pTableList->idInfo.uid;
416,300✔
3540
  *type = pTableList->idInfo.tableType;
416,300✔
3541
}
416,300✔
3542

3543
uint64_t tableListGetTableGroupId(const STableListInfo* pTableList, uint64_t tableUid) {
830,425,540✔
3544
  int32_t* slot = taosHashGet(pTableList->map, &tableUid, sizeof(tableUid));
830,425,540✔
3545
  if (slot == NULL) {
830,681,261✔
3546
    qDebug("table:%" PRIu64 " not found in table list", tableUid);
×
3547
    return -1;
×
3548
  }
3549

3550
  STableKeyInfo* pKeyInfo = taosArrayGet(pTableList->pTableList, *slot);
830,681,261✔
3551
  if (pKeyInfo == NULL) {
830,793,424✔
3552
    qDebug("table:%" PRIu64 " not found in table list", tableUid);
×
3553
    return -1;
×
3554
  }
3555
  return pKeyInfo->groupId;
830,793,424✔
3556
}
3557

3558
// TODO handle the group offset info, fix it, the rule of group output will be broken by this function
3559
// int32_t tableListRemoveTableInfo(STableListInfo* pTableList, uint64_t uid) {
3560
//   int32_t code = TSDB_CODE_SUCCESS;
3561
//   int32_t lino = 0;
3562

3563
//   int32_t* slot = taosHashGet(pTableList->map, &uid, sizeof(uid));
3564
//   if (slot == NULL) {
3565
//     qDebug("table:%" PRIu64 " not found in table list", uid);
3566
//     return 0;
3567
//   }
3568

3569
//   taosArrayRemove(pTableList->pTableList, *slot);
3570
//   code = taosHashRemove(pTableList->map, &uid, sizeof(uid));
3571

3572
//   _end:
3573
//   if (code != TSDB_CODE_SUCCESS) {
3574
//     qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
3575
//   } else {
3576
//     qDebug("uid:%" PRIu64 ", remove from table list", uid);
3577
//   }
3578

3579
//   return code;
3580
// }
3581

3582
int32_t tableListAddTableInfo(STableListInfo* pTableList, uint64_t uid, uint64_t gid) {
1,083,404✔
3583
  int32_t code = TSDB_CODE_SUCCESS;
1,083,404✔
3584
  int32_t lino = 0;
1,083,404✔
3585
  if (pTableList->map == NULL) {
1,083,404✔
3586
    pTableList->map = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
×
3587
    QUERY_CHECK_NULL(pTableList->map, code, lino, _end, terrno);
×
3588
  }
3589

3590
  STableKeyInfo keyInfo = {.uid = uid, .groupId = gid};
1,083,393✔
3591
  void*         p = taosHashGet(pTableList->map, &uid, sizeof(uid));
1,084,040✔
3592
  if (p != NULL) {
1,083,415✔
3593
    qInfo("table:%" PRId64 " already in tableIdList, ignore it", uid);
×
3594
    goto _end;
×
3595
  }
3596

3597
  void* tmp = taosArrayPush(pTableList->pTableList, &keyInfo);
1,083,415✔
3598
  QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
1,084,676✔
3599

3600
  int32_t slot = (int32_t)taosArrayGetSize(pTableList->pTableList) - 1;
1,084,676✔
3601
  code = taosHashPut(pTableList->map, &uid, sizeof(uid), &slot, sizeof(slot));
1,084,040✔
3602
  if (code != TSDB_CODE_SUCCESS) {
1,084,676✔
3603
    // we have checked the existence of uid in hash map above
3604
    QUERY_CHECK_CONDITION((code != TSDB_CODE_DUP_KEY), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
3605
    taosArrayPopTailBatch(pTableList->pTableList, 1);  // let's pop the last element in the array list
×
3606
  }
3607

3608
_end:
1,084,676✔
3609
  if (code != TSDB_CODE_SUCCESS) {
1,084,358✔
3610
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
3611
  } else {
3612
    qDebug("uid:%" PRIu64 ", groupId:%" PRIu64 " added into table list, slot:%d, total:%d", uid, gid, slot, slot + 1);
1,084,358✔
3613
  }
3614

3615
  return code;
1,085,323✔
3616
}
3617

3618
int32_t tableListGetGroupList(const STableListInfo* pTableList, int32_t ordinalGroupIndex, STableKeyInfo** pKeyInfo,
249,944,732✔
3619
                              int32_t* size) {
3620
  int32_t totalGroups = tableListGetOutputGroups(pTableList);
249,944,732✔
3621
  int32_t numOfTables = 0;
249,939,005✔
3622
  int32_t code = tableListGetSize(pTableList, &numOfTables);
249,935,653✔
3623
  if (code != TSDB_CODE_SUCCESS) {
249,974,796✔
3624
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
3625
    return code;
×
3626
  }
3627

3628
  if (ordinalGroupIndex < 0 || ordinalGroupIndex >= totalGroups) {
249,974,796✔
3629
    return TSDB_CODE_INVALID_PARA;
×
3630
  }
3631

3632
  // here handle two special cases:
3633
  // 1. only one group exists, and 2. one table exists for each group.
3634
  if (totalGroups == 1) {
249,974,796✔
3635
    *size = numOfTables;
249,451,475✔
3636
    *pKeyInfo = (*size == 0) ? NULL : taosArrayGet(pTableList->pTableList, 0);
249,499,565✔
3637
    return TSDB_CODE_SUCCESS;
249,425,482✔
3638
  } else if (totalGroups == numOfTables) {
523,321✔
3639
    *size = 1;
477,652✔
3640
    *pKeyInfo = taosArrayGet(pTableList->pTableList, ordinalGroupIndex);
477,652✔
3641
    return TSDB_CODE_SUCCESS;
478,151✔
3642
  }
3643

3644
  int32_t offset = pTableList->groupOffset[ordinalGroupIndex];
45,712✔
3645
  if (ordinalGroupIndex < totalGroups - 1) {
58,787✔
3646
    *size = pTableList->groupOffset[ordinalGroupIndex + 1] - offset;
44,211✔
3647
  } else {
3648
    *size = numOfTables - offset;
14,576✔
3649
  }
3650

3651
  *pKeyInfo = taosArrayGet(pTableList->pTableList, offset);
58,787✔
3652
  return TSDB_CODE_SUCCESS;
58,787✔
3653
}
3654

3655
int32_t tableListGetOutputGroups(const STableListInfo* pTableList) { return pTableList->numOfOuputGroups; }
702,479,649✔
3656

3657
bool oneTableForEachGroup(const STableListInfo* pTableList) { return pTableList->oneTableForEachGroup; }
690,538✔
3658

3659
STableListInfo* tableListCreate() {
280,252,775✔
3660
  STableListInfo* pListInfo = taosMemoryCalloc(1, sizeof(STableListInfo));
280,252,775✔
3661
  if (pListInfo == NULL) {
280,122,531✔
3662
    return NULL;
×
3663
  }
3664

3665
  pListInfo->remainGroups = NULL;
280,122,531✔
3666
  pListInfo->pTableList = taosArrayInit(4, sizeof(STableKeyInfo));
280,124,089✔
3667
  if (pListInfo->pTableList == NULL) {
280,186,830✔
3668
    goto _error;
×
3669
  }
3670

3671
  pListInfo->map = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK);
280,218,568✔
3672
  if (pListInfo->map == NULL) {
280,317,222✔
3673
    goto _error;
×
3674
  }
3675

3676
  pListInfo->numOfOuputGroups = 1;
280,312,522✔
3677
  return pListInfo;
280,312,125✔
3678

3679
_error:
×
3680
  tableListDestroy(pListInfo);
×
3681
  return NULL;
×
3682
}
3683

3684
void tableListDestroy(STableListInfo* pTableListInfo) {
291,454,698✔
3685
  if (pTableListInfo == NULL) {
291,454,698✔
3686
    return;
11,201,293✔
3687
  }
3688

3689
  taosArrayDestroy(pTableListInfo->pTableList);
280,253,405✔
3690
  taosMemoryFreeClear(pTableListInfo->groupOffset);
280,236,773✔
3691

3692
  taosHashCleanup(pTableListInfo->map);
280,225,931✔
3693
  taosHashCleanup(pTableListInfo->remainGroups);
280,283,300✔
3694
  pTableListInfo->pTableList = NULL;
280,289,834✔
3695
  pTableListInfo->map = NULL;
280,284,606✔
3696
  taosMemoryFree(pTableListInfo);
280,263,269✔
3697
}
3698

3699
void tableListClear(STableListInfo* pTableListInfo) {
779,521✔
3700
  if (pTableListInfo == NULL) {
779,521✔
3701
    return;
×
3702
  }
3703

3704
  taosArrayClear(pTableListInfo->pTableList);
779,521✔
3705
  taosHashClear(pTableListInfo->map);
779,510✔
3706
  taosHashClear(pTableListInfo->remainGroups);
779,839✔
3707
  taosMemoryFree(pTableListInfo->groupOffset);
779,839✔
3708
  pTableListInfo->numOfOuputGroups = 1;
779,839✔
3709
  pTableListInfo->oneTableForEachGroup = false;
779,839✔
3710
}
3711

3712
static int32_t orderbyGroupIdComparFn(const void* p1, const void* p2) {
597,764,734✔
3713
  STableKeyInfo* pInfo1 = (STableKeyInfo*)p1;
597,764,734✔
3714
  STableKeyInfo* pInfo2 = (STableKeyInfo*)p2;
597,764,734✔
3715

3716
  if (pInfo1->groupId == pInfo2->groupId) {
597,764,734✔
3717
    return 0;
562,072,438✔
3718
  } else {
3719
    return pInfo1->groupId < pInfo2->groupId ? -1 : 1;
35,713,860✔
3720
  }
3721
}
3722

3723
int32_t sortTableGroup(STableListInfo* pTableListInfo) {
27,354,844✔
3724
  int32_t code = TSDB_CODE_SUCCESS;
27,354,844✔
3725
  taosArraySort(pTableListInfo->pTableList, orderbyGroupIdComparFn);
27,354,844✔
3726
  int32_t size = taosArrayGetSize(pTableListInfo->pTableList);
27,425,077✔
3727
  if (size == 0) {
27,412,958✔
3728
    pTableListInfo->numOfOuputGroups = 0;
×
3729
    return code;
×
3730
  }
3731

3732
  SArray* pList = taosArrayInit(4, sizeof(int32_t));
27,412,958✔
3733
  if (!pList) {
27,414,179✔
3734
    code = terrno;
×
3735
    goto end;
×
3736
  }
3737

3738
  STableKeyInfo* pInfo = taosArrayGet(pTableListInfo->pTableList, 0);
27,414,179✔
3739
  if (pInfo == NULL) {
27,366,593✔
3740
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3741
    code = terrno;
×
3742
    goto end;
×
3743
  }
3744
  uint64_t gid = pInfo->groupId;
27,366,593✔
3745

3746
  int32_t start = 0;
27,369,961✔
3747
  void*   tmp = taosArrayPush(pList, &start);
27,409,017✔
3748
  if (tmp == NULL) {
27,409,017✔
3749
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3750
    code = terrno;
×
3751
    goto end;
×
3752
  }
3753

3754
  for (int32_t i = 1; i < size; ++i) {
156,450,031✔
3755
    pInfo = taosArrayGet(pTableListInfo->pTableList, i);
129,045,315✔
3756
    if (pInfo == NULL) {
129,040,952✔
3757
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3758
      code = terrno;
×
3759
      goto end;
×
3760
    }
3761
    if (pInfo->groupId != gid) {
129,040,952✔
3762
      tmp = taosArrayPush(pList, &i);
7,312,362✔
3763
      if (tmp == NULL) {
7,312,362✔
3764
        qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3765
        code = terrno;
×
3766
        goto end;
×
3767
      }
3768
      gid = pInfo->groupId;
7,312,362✔
3769
    }
3770
  }
3771

3772
  pTableListInfo->numOfOuputGroups = taosArrayGetSize(pList);
27,409,431✔
3773
  pTableListInfo->groupOffset = taosMemoryMalloc(sizeof(int32_t) * pTableListInfo->numOfOuputGroups);
27,411,432✔
3774
  if (pTableListInfo->groupOffset == NULL) {
27,393,403✔
3775
    code = terrno;
×
3776
    goto end;
×
3777
  }
3778

3779
  memcpy(pTableListInfo->groupOffset, taosArrayGet(pList, 0), sizeof(int32_t) * pTableListInfo->numOfOuputGroups);
27,367,205✔
3780

3781
end:
27,385,419✔
3782
  taosArrayDestroy(pList);
27,366,362✔
3783
  return code;
27,373,085✔
3784
}
3785

3786
int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SScanPhysiNode* pScanNode,
246,556,364✔
3787
                                    SNodeList* group, bool groupSort, uint8_t* digest, SStorageAPI* pAPI, SHashObj* groupIdMap) {
3788
  int32_t code = TSDB_CODE_SUCCESS;
246,556,364✔
3789

3790
  bool   groupByTbname = groupbyTbname(group);
246,556,364✔
3791
  size_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
246,532,326✔
3792
  if (!numOfTables) {
246,534,584✔
3793
    return code;
×
3794
  }
3795
  qDebug("numOfTables:%zu, groupByTbname:%d, group:%p", numOfTables, groupByTbname, group);
246,534,584✔
3796
  if (group == NULL || groupByTbname) {
246,501,501✔
3797
    if (tsCountAlwaysReturnValue && QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode) &&
242,104,985✔
3798
        ((STableScanPhysiNode*)pScanNode)->needCountEmptyTable) {
199,145,979✔
3799
      pTableListInfo->remainGroups =
13,281,278✔
3800
          taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK);
13,281,278✔
3801
      if (pTableListInfo->remainGroups == NULL) {
13,281,278✔
3802
        return terrno;
×
3803
      }
3804

3805
      for (int i = 0; i < numOfTables; i++) {
70,139,801✔
3806
        STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
56,858,331✔
3807
        if (!info) {
56,857,453✔
3808
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3809
          return terrno;
×
3810
        }
3811
        info->groupId = groupByTbname ? info->uid : 0;
56,857,453✔
3812
        int32_t tempRes = taosHashPut(pTableListInfo->remainGroups, &(info->groupId), sizeof(info->groupId),
56,859,593✔
3813
                                      &(info->uid), sizeof(info->uid));
56,860,128✔
3814
        if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
56,858,523✔
3815
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(tempRes));
×
3816
          return tempRes;
×
3817
        }
3818
      }
3819
    } else {
3820
      for (int32_t i = 0; i < numOfTables; i++) {
846,146,648✔
3821
        STableKeyInfo* info = taosArrayGet(pTableListInfo->pTableList, i);
617,293,751✔
3822
        if (!info) {
617,222,684✔
3823
          qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3824
          return terrno;
×
3825
        }
3826
        info->groupId = groupByTbname ? info->uid : 0;
617,222,684✔
3827
        
3828
      }
3829
    }
3830
    if (groupIdMap && group != NULL){
242,134,367✔
3831
      getColInfoResultForGroupbyForStream(pHandle->vnode, group, pTableListInfo, pAPI, groupIdMap);
81,457✔
3832
    }
3833

3834
    pTableListInfo->oneTableForEachGroup = groupByTbname;
242,134,367✔
3835
    if (numOfTables == 1 && pTableListInfo->idInfo.tableType == TSDB_CHILD_TABLE) {
242,137,347✔
3836
      pTableListInfo->oneTableForEachGroup = true;
102,603,269✔
3837
    }
3838

3839
    if (groupSort && groupByTbname) {
242,126,769✔
3840
      taosArraySort(pTableListInfo->pTableList, orderbyGroupIdComparFn);
2,345,698✔
3841
      pTableListInfo->numOfOuputGroups = numOfTables;
2,345,698✔
3842
    } else if (groupByTbname && pScanNode->groupOrderScan) {
239,781,071✔
3843
      pTableListInfo->numOfOuputGroups = numOfTables;
25,775✔
3844
    } else {
3845
      pTableListInfo->numOfOuputGroups = 1;
239,757,868✔
3846
    }
3847
    if (groupSort || pScanNode->groupOrderScan) {
242,070,448✔
3848
      code = sortTableGroup(pTableListInfo);
27,210,432✔
3849
    }
3850
  } else {
3851
    bool initRemainGroups = false;
4,396,516✔
3852
    if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanNode)) {
4,396,516✔
3853
      STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pScanNode;
4,291,774✔
3854
      if (tsCountAlwaysReturnValue && pTableScanNode->needCountEmptyTable &&
4,291,774✔
3855
          !(groupSort || pScanNode->groupOrderScan)) {
2,074,315✔
3856
        initRemainGroups = true;
2,049,591✔
3857
      }
3858
    }
3859

3860
    code = getColInfoResultForGroupby(pHandle->vnode, group, pTableListInfo, digest, pAPI, initRemainGroups, groupIdMap);
4,396,516✔
3861
    if (code != TSDB_CODE_SUCCESS) {
4,395,322✔
3862
      return code;
×
3863
    }
3864

3865
    if (pScanNode->groupOrderScan) pTableListInfo->numOfOuputGroups = taosArrayGetSize(pTableListInfo->pTableList);
4,395,322✔
3866

3867
    if (groupSort || pScanNode->groupOrderScan) {
4,395,322✔
3868
      code = sortTableGroup(pTableListInfo);
152,950✔
3869
    }
3870
  }
3871

3872
  // add all table entry in the hash map
3873
  size_t size = taosArrayGetSize(pTableListInfo->pTableList);
246,481,075✔
3874
  for (int32_t i = 0; i < size; ++i) {
944,904,086✔
3875
    STableKeyInfo* p = taosArrayGet(pTableListInfo->pTableList, i);
698,307,576✔
3876
    if (!p) {
698,184,017✔
3877
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
3878
      return terrno;
×
3879
    }
3880
    int32_t tempRes = taosHashPut(pTableListInfo->map, &p->uid, sizeof(uint64_t), &i, sizeof(int32_t));
698,184,017✔
3881
    if (tempRes != TSDB_CODE_SUCCESS && tempRes != TSDB_CODE_DUP_KEY) {
698,453,714✔
3882
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(tempRes));
×
3883
      return tempRes;
×
3884
    }
3885
  }
3886

3887
  return code;
246,652,152✔
3888
}
3889

3890
int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags, bool groupSort, SReadHandle* pHandle,
262,960,333✔
3891
                                STableListInfo* pTableListInfo, SNode* pTagCond, SNode* pTagIndexCond,
3892
                                SExecTaskInfo* pTaskInfo, SHashObj* groupIdMap) {
3893
  int64_t     st = taosGetTimestampUs();
262,950,702✔
3894
  const char* idStr = GET_TASKID(pTaskInfo);
262,950,702✔
3895

3896
  if (pHandle == NULL) {
262,659,372✔
3897
    qError("invalid handle, in creating operator tree, %s", idStr);
×
3898
    return TSDB_CODE_INVALID_PARA;
×
3899
  }
3900

3901
  if (pHandle->uid != 0) {
262,659,372✔
3902
    pScanNode->uid = pHandle->uid;
120,504✔
3903
    pScanNode->tableType = TSDB_CHILD_TABLE;
120,504✔
3904
  }
3905
  uint8_t digest[17] = {0};
262,743,683✔
3906
  int32_t code = getTableList(pHandle->vnode, pScanNode, pTagCond, pTagIndexCond, pTableListInfo, digest, idStr,
262,875,724✔
3907
                              &pTaskInfo->storageAPI, pTaskInfo->pStreamRuntimeInfo);
262,815,424✔
3908
  if (code != TSDB_CODE_SUCCESS) {
262,959,307✔
3909
    qError("failed to getTableList, code:%s", tstrerror(code));
978✔
3910
    return code;
978✔
3911
  }
3912

3913
  int32_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList);
262,958,329✔
3914

3915
  int64_t st1 = taosGetTimestampUs();
262,986,794✔
3916
  pTaskInfo->cost.extractListTime = (st1 - st) / 1000.0;
262,986,794✔
3917
  qDebug("extract queried table list completed, %d tables, elapsed time:%.2f ms %s", numOfTables,
263,052,499✔
3918
         pTaskInfo->cost.extractListTime, idStr);
3919

3920
  if (numOfTables == 0) {
262,968,041✔
3921
    qDebug("no table qualified for query, %s", idStr);
16,445,775✔
3922
    return TSDB_CODE_SUCCESS;
16,444,754✔
3923
  }
3924

3925
  code = buildGroupIdMapForAllTables(pTableListInfo, pHandle, pScanNode, pGroupTags, groupSort, digest, &pTaskInfo->storageAPI, groupIdMap);
246,522,266✔
3926
  if (code != TSDB_CODE_SUCCESS) {
246,614,014✔
3927
    return code;
×
3928
  }
3929

3930
  pTaskInfo->cost.groupIdMapTime = (taosGetTimestampUs() - st1) / 1000.0;
246,619,149✔
3931
  qDebug("generate group id map completed, elapsed time:%.2f ms %s", pTaskInfo->cost.groupIdMapTime, idStr);
246,609,885✔
3932

3933
  return TSDB_CODE_SUCCESS;
246,604,698✔
3934
}
3935

3936
char* getStreamOpName(uint16_t opType) {
8,300,736✔
3937
  switch (opType) {
8,300,736✔
3938
    case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN:
×
3939
      return "stream scan";
×
3940
    case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
7,924,673✔
3941
      return "project";
7,924,673✔
3942
    case QUERY_NODE_PHYSICAL_PLAN_EXTERNAL_WINDOW:
376,063✔
3943
      return "external window";
376,063✔
3944
  }
3945
  return "error name";
×
3946
}
3947

3948
void printDataBlock(SSDataBlock* pBlock, const char* flag, const char* taskIdStr, int64_t qId) {
739,514,438✔
3949
  if (qDebugFlag & DEBUG_TRACE) {
739,514,438✔
3950
    if (!pBlock) {
1,346,077✔
3951
      qDebug("%" PRIx64 " %s %s %s: Block is Null", qId, taskIdStr, flag, __func__);
29,020✔
3952
      return;
30,175✔
3953
    } else if (pBlock->info.rows == 0) {
1,317,057✔
3954
      qDebug("%" PRIx64 " %s %s %s: Block is Empty.", qId, taskIdStr, flag, __func__);
7,432✔
3955
      return;
7,432✔
3956
    }
3957
    
3958
    char*   pBuf = NULL;
1,309,625✔
3959
    int32_t code = dumpBlockData(pBlock, flag, &pBuf, taskIdStr, qId);
1,309,625✔
3960
    if (code == 0) {
1,309,625✔
3961
      qDebugL("%" PRIx64 " %s %s", qId, __func__, pBuf);
1,309,625✔
3962
      taosMemoryFree(pBuf);
1,309,625✔
3963
    }
3964
  }
3965
}
3966

3967
void printSpecDataBlock(SSDataBlock* pBlock, const char* flag, const char* opStr, const char* taskIdStr) {
×
3968
  if (!pBlock) {
×
3969
    qDebug("%s===stream===%s %s: Block is Null", taskIdStr, flag, opStr);
×
3970
    return;
×
3971
  } else if (pBlock->info.rows == 0) {
×
3972
    qDebug("%s===stream===%s %s: Block is Empty.skey:%" PRId64 ",ekey:%" PRId64 ",version%" PRId64,
×
3973
           taskIdStr, flag, opStr, pBlock->info.window.skey, pBlock->info.window.ekey,
3974
           pBlock->info.version);
3975
    return;
×
3976
  }
3977
  if (qDebugFlag & DEBUG_TRACE) {
×
3978
    char* pBuf = NULL;
×
3979
    char  flagBuf[64];
×
3980
    snprintf(flagBuf, sizeof(flagBuf), "%s %s", flag, opStr);
×
3981
    int32_t code = dumpBlockData(pBlock, flagBuf, &pBuf, taskIdStr, 0);
×
3982
    if (code == 0) {
×
3983
      qDebug("%s", pBuf);
×
3984
      taosMemoryFree(pBuf);
×
3985
    }
3986
  }
3987
}
3988

3989
TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols) { return tsCols == NULL ? win->skey : tsCols[0]; }
13,747,175✔
3990

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

3994
  int64_t duration = pWin->ekey > pWin->skey ? pWin->ekey - pWin->skey + delta : pWin->skey - pWin->ekey + delta;
2,147,483,647✔
3995
  ts[2] = duration;            // set the duration
2,147,483,647✔
3996
  ts[3] = pWin->skey;          // window start key
2,147,483,647✔
3997
  ts[4] = pWin->ekey + delta;  // window end key
2,147,483,647✔
3998
}
2,147,483,647✔
3999

4000
int32_t compKeys(const SArray* pSortGroupCols, const char* oldkeyBuf, int32_t oldKeysLen, const SSDataBlock* pBlock,
2,147,483,647✔
4001
                 int32_t rowIndex) {
4002
  SColumnDataAgg* pColAgg = NULL;
2,147,483,647✔
4003
  const char*     isNull = oldkeyBuf;
2,147,483,647✔
4004
  const char*     p = oldkeyBuf + sizeof(int8_t) * pSortGroupCols->size;
2,147,483,647✔
4005

4006
  for (int32_t i = 0; i < pSortGroupCols->size; ++i) {
2,147,483,647✔
4007
    const SColumn*         pCol = (SColumn*)TARRAY_GET_ELEM(pSortGroupCols, i);
2,147,483,647✔
4008
    const SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, pCol->slotId);
2,147,483,647✔
4009
    if (pBlock->pBlockAgg) pColAgg = &pBlock->pBlockAgg[pCol->slotId];
2,147,483,647✔
4010

4011
    if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) {
2,147,483,647✔
4012
      if (isNull[i] != 1) return 1;
272,776,568✔
4013
    } else {
4014
      if (isNull[i] != 0) return 1;
2,147,483,647✔
4015
      const char* val = colDataGetData(pColInfoData, rowIndex);
2,147,483,647✔
4016
      if (pCol->type == TSDB_DATA_TYPE_JSON) {
2,147,483,647✔
4017
        int32_t len = getJsonValueLen(val);
×
4018
        if (memcmp(p, val, len) != 0) return 1;
×
4019
        p += len;
×
4020
      } else if (IS_VAR_DATA_TYPE(pCol->type)) {
2,147,483,647✔
4021
        if (IS_STR_DATA_BLOB(pCol->type)) {
1,258,898,438✔
4022
          if (memcmp(p, val, blobDataTLen(val)) != 0) return 1;
×
4023
          p += blobDataTLen(val);
×
4024
        } else {
4025
          if (memcmp(p, val, varDataTLen(val)) != 0) return 1;
1,259,140,344✔
4026
          p += varDataTLen(val);
1,258,485,610✔
4027
        }
4028
      } else {
4029
        if (0 != memcmp(p, val, pCol->bytes)) return 1;
2,147,483,647✔
4030
        p += pCol->bytes;
2,147,483,647✔
4031
      }
4032
    }
4033
  }
4034
  if ((int32_t)(p - oldkeyBuf) != oldKeysLen) return 1;
2,147,483,647✔
4035
  return 0;
2,147,483,647✔
4036
}
4037

4038
int32_t buildKeys(char* keyBuf, const SArray* pSortGroupCols, const SSDataBlock* pBlock, int32_t rowIndex) {
1,667,190✔
4039
  uint32_t        colNum = pSortGroupCols->size;
1,667,190✔
4040
  SColumnDataAgg* pColAgg = NULL;
1,667,190✔
4041
  char*           isNull = keyBuf;
1,667,190✔
4042
  char*           p = keyBuf + sizeof(int8_t) * colNum;
1,667,190✔
4043

4044
  for (int32_t i = 0; i < colNum; ++i) {
4,562,123✔
4045
    const SColumn*         pCol = (SColumn*)TARRAY_GET_ELEM(pSortGroupCols, i);
2,894,933✔
4046
    const SColumnInfoData* pColInfoData = TARRAY_GET_ELEM(pBlock->pDataBlock, pCol->slotId);
2,895,400✔
4047
    if (pCol->slotId > pBlock->pDataBlock->size) continue;
2,895,400✔
4048

4049
    if (pBlock->pBlockAgg) pColAgg = &pBlock->pBlockAgg[pCol->slotId];
2,895,400✔
4050

4051
    if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) {
5,790,800✔
4052
      isNull[i] = 1;
140,100✔
4053
    } else {
4054
      isNull[i] = 0;
2,755,300✔
4055
      const char* val = colDataGetData(pColInfoData, rowIndex);
2,754,833✔
4056
      if (pCol->type == TSDB_DATA_TYPE_JSON) {
2,754,366✔
4057
        int32_t len = getJsonValueLen(val);
×
4058
        memcpy(p, val, len);
×
4059
        p += len;
×
4060
      } else if (IS_VAR_DATA_TYPE(pCol->type)) {
2,754,366✔
4061
        if (IS_STR_DATA_BLOB(pCol->type)) {
1,028,801✔
4062
          blobDataCopy(p, val);
×
4063
          p += blobDataTLen(val);
×
4064
        } else {
4065
          varDataCopy(p, val);
1,028,334✔
4066
          p += varDataTLen(val);
1,028,334✔
4067
        }
4068
      } else {
4069
        memcpy(p, val, pCol->bytes);
1,726,032✔
4070
        p += pCol->bytes;
1,726,032✔
4071
      }
4072
    }
4073
  }
4074
  return (int32_t)(p - keyBuf);
1,667,190✔
4075
}
4076

4077
uint64_t calcGroupId(char* pData, int32_t len) {
2,147,483,647✔
4078
  T_MD5_CTX context;
2,147,483,647✔
4079
  tMD5Init(&context);
2,147,483,647✔
4080
  tMD5Update(&context, (uint8_t*)pData, len);
2,147,483,647✔
4081
  tMD5Final(&context);
2,147,483,647✔
4082

4083
  // NOTE: only extract the initial 8 bytes of the final MD5 digest
4084
  uint64_t id = 0;
2,147,483,647✔
4085
  memcpy(&id, context.digest, sizeof(uint64_t));
2,147,483,647✔
4086
  if (0 == id) memcpy(&id, context.digest + 8, sizeof(uint64_t));
2,147,483,647✔
4087
  return id;
2,147,483,647✔
4088
}
4089

4090
SNodeList* makeColsNodeArrFromSortKeys(SNodeList* pSortKeys) {
109,745✔
4091
  SNode*     node;
4092
  SNodeList* ret = NULL;
109,745✔
4093
  FOREACH(node, pSortKeys) {
335,773✔
4094
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)node;
225,561✔
4095
    int32_t           code = nodesListMakeAppend(&ret, pSortKey->pExpr);
225,561✔
4096
    if (code != TSDB_CODE_SUCCESS) {
226,028✔
4097
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
4098
      terrno = code;
×
4099
      return NULL;
×
4100
    }
4101
  }
4102
  return ret;
110,212✔
4103
}
4104

4105
int32_t extractKeysLen(const SArray* keys, int32_t* pLen) {
109,745✔
4106
  int32_t code = TSDB_CODE_SUCCESS;
109,745✔
4107
  int32_t lino = 0;
109,745✔
4108
  int32_t len = 0;
109,745✔
4109
  int32_t keyNum = taosArrayGetSize(keys);
109,745✔
4110
  for (int32_t i = 0; i < keyNum; ++i) {
279,266✔
4111
    SColumn* pCol = (SColumn*)taosArrayGet(keys, i);
169,521✔
4112
    QUERY_CHECK_NULL(pCol, code, lino, _end, terrno);
169,988✔
4113
    len += pCol->bytes;
169,988✔
4114
  }
4115
  len += sizeof(int8_t) * keyNum;  // null flag
109,745✔
4116
  *pLen = len;
109,745✔
4117

4118
_end:
109,745✔
4119
  if (code != TSDB_CODE_SUCCESS) {
109,745✔
4120
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4121
  }
4122
  return code;
109,745✔
4123
}
4124

4125
int32_t parseErrorMsgFromAnalyticServer(SJson* pJson, const char* typeStr, const char* pId) {
×
4126
  int32_t code = TSDB_CODE_ANA_ANODE_RETURN_ERROR;
×
4127
  char*   pMsg = NULL;
×
4128
  if (pJson == NULL) {
×
4129
    return code;
×
4130
  }
4131

4132
  int32_t ret = tjsonDupStringValue(pJson, "msg", &pMsg);
×
4133
  if (ret == 0 && pMsg != NULL) {
×
4134
    qError("%s failed to exec %s operation, msg:%s", pId, typeStr, pMsg);
×
4135
    if (strstr(pMsg, "white noise") != NULL) {
×
4136
      code = TSDB_CODE_ANA_WN_DATA;
×
4137
    } else if (strstr(pMsg, "white-noise") != NULL) {
×
4138
      code = TSDB_CODE_ANA_WN_DATA;
×
4139
    } else if (strstr(pMsg, "[Errno 111] Connection refused") != NULL) {
×
4140
      code = TSDB_CODE_ANA_ALGO_NOT_LOAD;
×
4141
    } else if (strstr(pMsg, "failed to load model") != NULL) {
×
4142
      code = TSDB_CODE_ANA_ALGO_NOT_LOAD;
×
4143
    }
4144
  } else {
4145
    qError("%s failed to extract msg from server, unknown error", pId);
×
4146
  }
4147

4148
  taosMemoryFreeClear(pMsg);
×
4149
  return code;
×
4150
}
4151

4152

4153
int32_t createExprSubQResBlock(SSDataBlock** ppBlock, SDataType* pResType) {
28,371,717✔
4154
  int32_t code = 0;
28,371,717✔
4155
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
28,371,717✔
4156
  if (pBlock == NULL) {
28,371,704✔
4157
    return terrno;
×
4158
  }
4159

4160
  pBlock->pDataBlock = taosArrayInit(1, sizeof(SColumnInfoData));
28,371,704✔
4161
  if (pBlock->pDataBlock == NULL) {
28,371,691✔
4162
    code = terrno;
×
4163
    taosMemoryFree(pBlock);
×
4164
    return code;
×
4165
  }
4166

4167
  SColumnInfoData idata =
28,372,244✔
4168
      createColumnInfoData(pResType->type, pResType->bytes, 0);
28,372,244✔
4169
  idata.info.scale = pResType->scale;
28,372,797✔
4170
  idata.info.precision = pResType->precision;
28,372,797✔
4171

4172
  code = blockDataAppendColInfo(pBlock, &idata);
28,372,797✔
4173
  if (code != TSDB_CODE_SUCCESS) {
28,371,717✔
4174
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
4175
    blockDataDestroy(pBlock);
×
4176
    *ppBlock = NULL;
×
4177
    return code;
×
4178
  }
4179

4180
  *ppBlock = pBlock;
28,371,717✔
4181

4182
  return code;
28,371,717✔
4183
}
4184

4185

4186
int32_t extractSingleRspBlock(SRetrieveTableRsp* pRetrieveRsp, SSDataBlock* pb) {
28,372,257✔
4187
  int32_t            code = TSDB_CODE_SUCCESS;
28,372,257✔
4188
  int32_t            lino = 0;
28,372,257✔
4189
  void*              decompBuf = NULL;
28,372,257✔
4190

4191
  char* pNextStart = pRetrieveRsp->data;
28,372,257✔
4192
  char* pStart = pNextStart;
28,371,704✔
4193

4194
  int32_t index = 0;
28,371,704✔
4195

4196
  if (pRetrieveRsp->compressed) {  // decompress the data
28,371,704✔
4197
    decompBuf = taosMemoryMalloc(pRetrieveRsp->payloadLen);
×
4198
    QUERY_CHECK_NULL(decompBuf, code, lino, _end, terrno);
×
4199
  }
4200

4201
  int32_t compLen = *(int32_t*)pStart;
28,371,151✔
4202
  pStart += sizeof(int32_t);
28,371,704✔
4203

4204
  int32_t rawLen = *(int32_t*)pStart;
28,372,257✔
4205
  pStart += sizeof(int32_t);
28,372,244✔
4206
  QUERY_CHECK_CONDITION((compLen <= rawLen && compLen != 0), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
28,372,244✔
4207

4208
  pNextStart = pStart + compLen;
28,372,244✔
4209
  if (pRetrieveRsp->compressed && (compLen < rawLen)) {
28,372,244✔
4210
    int32_t t = tsDecompressString(pStart, compLen, 1, decompBuf, rawLen, ONE_STAGE_COMP, NULL, 0);
×
4211
    QUERY_CHECK_CONDITION((t == rawLen), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
×
4212
    pStart = decompBuf;
×
4213
  }
4214

4215
  code = blockDecodeInternal(pb, pStart, (const char**)&pStart);
28,371,151✔
4216
  if (code != 0) {
28,371,164✔
4217
    taosMemoryFreeClear(pRetrieveRsp);
×
4218
    goto _end;
×
4219
  }
4220

4221
_end:
28,371,164✔
4222
  if (code != TSDB_CODE_SUCCESS) {
28,371,151✔
4223
    blockDataDestroy(pb);
×
4224
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4225
  }
4226
  return code;
28,371,151✔
4227
}
4228

4229
int32_t setValueFromResBlock(STaskSubJobCtx* ctx, SValueNode* pRes, SSDataBlock* pBlock) {
18,524,980✔
4230
  int32_t code = 0;
18,524,980✔
4231
  bool needFree = true;
18,524,980✔
4232
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
18,524,980✔
4233
  if (NULL == pBlock->pDataBlock || 1 > colNum || pBlock->info.rows > 1) {
18,524,980✔
4234
    qError("%s invalid scl fetch res block, pDataBlock:%p, colNum:%d, rows:%" PRId64, 
×
4235
      ctx->idStr, pBlock->pDataBlock, colNum, pBlock->info.rows);
4236
    return TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
×
4237
  }
4238
  
4239
  pRes->flag &= (~VALUE_FLAG_VAL_UNSET);
18,524,980✔
4240
  pRes->translate = true;
18,525,533✔
4241
  
4242
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
18,524,980✔
4243
  if (colDataIsNull_s(pCol, 0)) {
18,524,427✔
4244
    pRes->isNull = true;
4,989,891✔
4245
  } else {
4246
    code = nodesSetValueNodeValueExt(pRes, colDataGetData(pCol, 0), &needFree);
13,534,536✔
4247
  }
4248

4249
  if (!needFree) {
18,523,887✔
4250
    pCol->pData = NULL;
1,832,688✔
4251
  }
4252

4253
  return code;
18,523,887✔
4254
}
4255

4256
void handleRemoteValueRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
3,380,816✔
4257
  SSDataBlock*      pResBlock = NULL;
3,380,816✔
4258
  SExecTaskInfo*    pTaskInfo = ctx->pTaskInfo;
3,380,816✔
4259
  SRemoteValueNode* pRemote = (SRemoteValueNode*)pParam->pRes;
3,380,816✔
4260

4261
  qDebug("%s scl fetch value rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
3,380,276✔
4262

4263
  if (IS_STREAM_MODE(pTaskInfo)) {
3,380,276✔
4264
    SNode** ppRes = taosArrayGet(ctx->subResNodes, pParam->subQIdx);
111,520✔
4265
    if (NULL == *ppRes && 0 == pRsp->numOfRows) {
111,520✔
4266
      pRemote->val.node.type = QUERY_NODE_VALUE;
×
4267
      pRemote->val.isNull = true;
×
4268
      pRemote->val.translate = true;
×
4269
      pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
×
4270
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
×
4271
    } else if (pRsp->numOfRows > 0 || pRsp->numOfBlocks > 0) {
111,520✔
4272
      ctx->code = createExprSubQResBlock(&pResBlock, &((SRemoteValueNode*)pParam->pRes)->val.node.resType);
55,760✔
4273
      if (TSDB_CODE_SUCCESS == ctx->code) {
55,760✔
4274
        ctx->code = blockDataEnsureCapacity(pResBlock, 1);
55,760✔
4275
      }
4276
      if (TSDB_CODE_SUCCESS == ctx->code) {
55,760✔
4277
        ctx->code = extractSingleRspBlock(pRsp, pResBlock);
55,760✔
4278
      }
4279
      if (TSDB_CODE_SUCCESS == ctx->code) {
55,760✔
4280
        ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
55,760✔
4281
        pRemote->val.node.type = QUERY_NODE_REMOTE_VALUE;
55,760✔
4282
      }
4283
      if (TSDB_CODE_SUCCESS == ctx->code) {
55,760✔
4284
        taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
55,760✔
4285
      }
4286

4287
      blockDataDestroy(pResBlock);
55,760✔
4288
    } else if (NULL != *ppRes && 0 == pRsp->numOfRows) {
55,760✔
4289
      pRemote->val.node.type = QUERY_NODE_VALUE;
55,760✔
4290
      pRsp->completed = true;
55,760✔
4291
    }
4292

4293
    *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
111,520✔
4294

4295
    if (!(*fetchDone)) {
111,520✔
4296
      int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
55,760✔
4297
      if (TSDB_CODE_SUCCESS != code) {
55,760✔
4298
        ctx->code = code;
×
4299
        *fetchDone = true;
×
4300
      }
4301
    }
4302

4303
    return;
111,520✔
4304
  }
4305

4306
  *fetchDone = true;
3,268,190✔
4307

4308
  if (pRsp->numOfRows > 1 || pRsp->numOfBlocks > 1 || !pRsp->completed) {
3,269,296✔
4309
    qError("%s invalid scl value fetch rsp received, subQIdx:%d, rows:%" PRId64 ", blocks:%d, completed:%d", 
1,119✔
4310
      ctx->idStr, pParam->subQIdx, pRsp->numOfRows, pRsp->numOfBlocks, pRsp->completed);
4311
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
1,119✔
4312

4313
    return;
×
4314
  }
4315

4316
  if (1 != pRsp->numOfCols && pRsp->numOfRows > 0) {
3,268,743✔
4317
    qError("%s invalid scl value fetch rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
4318
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_COLS;
×
4319

4320
    return;
×
4321
  }
4322

4323
  if (0 == pRsp->numOfRows) {
3,269,296✔
4324
    pRemote->val.node.type = QUERY_NODE_VALUE;
175,815✔
4325
    pRemote->val.isNull = true;
176,355✔
4326
    pRemote->val.translate = true;
175,262✔
4327
    pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
175,815✔
4328
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
176,355✔
4329

4330
    return;
175,815✔
4331
  }
4332
  
4333
  ctx->code = createExprSubQResBlock(&pResBlock, &((SRemoteValueNode*)pParam->pRes)->val.node.resType);
3,092,941✔
4334
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,092,941✔
4335
    ctx->code = blockDataEnsureCapacity(pResBlock, 1);
3,092,941✔
4336
  }
4337
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,092,388✔
4338
    ctx->code = extractSingleRspBlock(pRsp, pResBlock);
3,092,388✔
4339
  }
4340
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,092,388✔
4341
    ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
3,092,388✔
4342
  }
4343
  if (TSDB_CODE_SUCCESS == ctx->code) {
3,092,388✔
4344
    pRemote->val.node.type = QUERY_NODE_VALUE;
3,092,388✔
4345
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
3,092,941✔
4346
  }
4347

4348
  blockDataDestroy(pResBlock);  
3,092,388✔
4349
}
4350

4351

4352
int32_t updateValueListFromResBlock(STaskSubJobCtx* ctx, SRemoteValueListNode* pRes, SSDataBlock* pBlock) {
9,846,724✔
4353
  int32_t code = 0, lino = 0;
9,846,724✔
4354
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
9,846,724✔
4355
  if (NULL == pBlock->pDataBlock || 1 != colNum) {
9,846,724✔
UNCOV
4356
    qError("%s invalid scl fetch res block, pDataBlock:%p, colNum:%d", ctx->idStr, pBlock->pDataBlock, colNum);
×
4357
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4358
  }
4359

4360
  pRes->hasValue = true;
9,846,724✔
4361
  
4362
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 0);
9,847,264✔
4363
  TAOS_CHECK_EXIT(scalarBuildRemoteListHash(ctx->idStr, pRes, pCol, pBlock->info.rows));
9,846,724✔
4364

4365
_exit:
9,135,722✔
4366

4367
  if (code) {
9,846,476✔
4368
    qError("%s %s failed with error: %s", ctx->idStr, __func__, tstrerror(code));
710,754✔
4369
  }
4370
  
4371
  return code;
9,847,264✔
4372
}
4373

4374

4375

4376
void handleRemoteValueListRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
12,750,125✔
4377
  SSDataBlock* pResBlock = NULL;
12,750,125✔
4378
  SRemoteValueListNode* pRemote = (SRemoteValueListNode*)pParam->pRes;
12,750,125✔
4379
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
12,750,125✔
4380

4381
  qDebug("%s scl fetch valueList rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
12,750,125✔
4382

4383
  if (pRsp->numOfRows > 0) {
12,750,125✔
4384
    if (1 != pRsp->numOfCols) {
9,846,724✔
4385
      qError("%s invalid scl valueList fetch rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
4386
      ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_COLS;
×
4387
      *fetchDone = true;
×
4388
      return;
×
4389
    }
4390

4391
    ctx->code = createExprSubQResBlock(&pResBlock, &((SExprNode*)pParam->pRes)->resType);
9,846,724✔
4392
    if (TSDB_CODE_SUCCESS == ctx->code) {
9,846,724✔
4393
      ctx->code = blockDataEnsureCapacity(pResBlock, pRsp->numOfRows);
9,846,724✔
4394
    }
4395
    if (TSDB_CODE_SUCCESS == ctx->code) {
9,847,264✔
4396
      ctx->code = extractSingleRspBlock(pRsp, pResBlock);
9,846,724✔
4397
    }
4398
    if (TSDB_CODE_SUCCESS == ctx->code) {
9,847,264✔
4399
      ctx->code = updateValueListFromResBlock(ctx, pRemote, pResBlock);
9,846,724✔
4400
    }
4401
    if (TSDB_CODE_SUCCESS == ctx->code && pRsp->completed) {
9,846,724✔
4402
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
7,801,994✔
4403
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
7,802,534✔
4404
    }
4405

4406
    blockDataDestroy(pResBlock);  
9,847,264✔
4407
  } else if (0 == pRsp->numOfRows && pRsp->completed) {
2,902,861✔
4408
    if (!pRemote->hasValue) {
2,902,861✔
4409
      ctx->code = scalarBuildRemoteListHash(ctx->idStr, pRemote, NULL, 0);
2,884,631✔
4410
    }
4411
    if (TSDB_CODE_SUCCESS == ctx->code) {    
2,902,861✔
4412
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
2,662,027✔
4413
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
2,662,027✔
4414
    }
4415
  }
4416

4417
  if (IS_STREAM_MODE(pTaskInfo) && 0 == pRsp->numOfRows) {
12,749,585✔
4418
    if (!pRemote->hasValue) {
18,727✔
4419
      ctx->code = scalarBuildRemoteListHash(ctx->idStr, pRemote, NULL, 0);
497✔
4420
    }
4421
    if (TSDB_CODE_SUCCESS == ctx->code) {
18,727✔
4422
      pRemote->flag &= (~VALUELIST_FLAG_VAL_UNSET);
18,727✔
4423
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
18,727✔
4424
    }
4425

4426
    pRsp->completed = true;
18,727✔
4427
  }
4428

4429
  *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
12,749,585✔
4430

4431
  if (!(*fetchDone)) {
12,749,585✔
4432
    int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
1,333,976✔
4433
    if (TSDB_CODE_SUCCESS != code) {
1,333,976✔
4434
      ctx->code = code;
×
4435
      *fetchDone = true;
×
4436
    }
4437
  }
4438
}
4439

4440
int32_t setRowHasNullFromResBlock(STaskSubJobCtx* ctx, bool* hasNull, SSDataBlock* pBlock) {
15,376,292✔
4441
  int32_t code = 0;
15,376,292✔
4442
  int32_t colNum = taosArrayGetSize(pBlock->pDataBlock);
15,376,292✔
4443
  if (2 != colNum) {
15,376,292✔
4444
    qError("%s invalid scl fetch res block, colNum:%d", ctx->idStr, colNum);
×
4445
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4446
  }
4447
  
4448
  SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, 1);
15,376,292✔
4449
  if (colDataIsNull_s(pCol, 0)) {
15,376,292✔
4450
    qError("%s invalid has_null res since it's null", ctx->idStr);
×
4451
    return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4452
  } else {
4453
    *hasNull = *(bool*)colDataGetData(pCol, 0);
15,376,292✔
4454
  }
4455

4456
  return code;
15,376,832✔
4457
}
4458

4459
void handleRemoteRowRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
20,840,148✔
4460
  SSDataBlock* pResBlock = NULL;
20,840,148✔
4461
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
20,840,148✔
4462

4463
  qDebug("%s scl fetch row rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
20,840,148✔
4464

4465
  SRemoteRowNode* pRemote = (SRemoteRowNode*)pParam->pRes;
20,840,148✔
4466

4467
  if (IS_STREAM_MODE(pTaskInfo)) {
20,840,148✔
4468
    SNode** ppRes = taosArrayGet(ctx->subResNodes, pParam->subQIdx);
992✔
4469
    if (NULL == *ppRes && 0 == pRsp->numOfRows) {
992✔
NEW
4470
      pRemote->valSet = true;
×
NEW
4471
      pRemote->hasValue = false;
×
NEW
4472
      pRemote->hasNull = false;
×
NEW
4473
      pRemote->val.isNull = true;
×
NEW
4474
      pRemote->val.translate = true;
×
NEW
4475
      pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
×
NEW
4476
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
×
4477
    } else if (pRsp->numOfRows > 0 || pRsp->numOfBlocks > 0) {
992✔
4478
      if (2 != pRsp->numOfCols) {
496✔
NEW
4479
        qError("%s invalid scl fetch row rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
NEW
4480
        ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
NEW
4481
        *fetchDone = true;
×
NEW
4482
        return;
×
4483
      }
4484

4485
      ctx->code = createExprSubQResBlock(&pResBlock, &pRemote->val.node.resType);
496✔
4486
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4487
        SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_BOOL, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, 0);
496✔
4488
        ctx->code = blockDataAppendColInfo(pResBlock, &idata);
496✔
4489
      }
4490
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4491
        ctx->code = blockDataEnsureCapacity(pResBlock, 1);
496✔
4492
      }
4493
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4494
        ctx->code = extractSingleRspBlock(pRsp, pResBlock);
496✔
4495
      }
4496
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4497
        ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
496✔
4498
      }
4499
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4500
        ctx->code = setRowHasNullFromResBlock(ctx, &pRemote->hasNull, pResBlock);
496✔
4501
      }
4502
      if (TSDB_CODE_SUCCESS == ctx->code) {
496✔
4503
        pRemote->valSet = true;
496✔
4504
        pRemote->hasValue = true;
496✔
4505
        pRemote->val.node.type = QUERY_NODE_REMOTE_ROW;
496✔
4506
        taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
496✔
4507
      }
4508

4509
      blockDataDestroy(pResBlock);
496✔
4510
    } else if (NULL != *ppRes && 0 == pRsp->numOfRows) {
496✔
4511
      pRemote->val.node.type = QUERY_NODE_VALUE;
496✔
4512
      pRsp->completed = true;
496✔
4513
    }
4514

4515
    *fetchDone = (TSDB_CODE_SUCCESS != ctx->code || pRsp->completed) ? true : false;
992✔
4516

4517
    if (!(*fetchDone)) {
992✔
4518
      ctx->code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
496✔
4519
      if (TSDB_CODE_SUCCESS != ctx->code) {
496✔
NEW
4520
        *fetchDone = true;
×
4521
      }
4522
    }
4523

4524
    return;
992✔
4525
  }
4526

4527
  *fetchDone = true;
20,839,156✔
4528

4529
  if (pRsp->numOfRows > 1 || pRsp->numOfBlocks > 1 || !pRsp->completed) {
20,839,156✔
NEW
4530
    qError("%s invalid scl fetch row rsp received, subQIdx:%d, rows:%" PRId64 ", blocks:%d, completed:%d",
×
4531
      ctx->idStr, pParam->subQIdx, pRsp->numOfRows, pRsp->numOfBlocks, pRsp->completed);
4532
    ctx->code = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_RES_ROWS;
×
4533

4534
    return;
×
4535
  }
4536

4537
  if (0 == pRsp->numOfRows) {
20,839,156✔
4538
    pRemote->valSet = true;
5,462,820✔
4539
    pRemote->hasValue = false;
5,462,820✔
4540
    pRemote->hasNull = false;
5,462,820✔
4541
    pRemote->val.isNull = true;
5,462,820✔
4542
    pRemote->val.translate = true;
5,462,820✔
4543
    pRemote->val.flag &= (~VALUE_FLAG_VAL_UNSET);
5,462,820✔
4544
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
5,462,820✔
4545

4546
    return;
5,462,820✔
4547
  }
4548

4549
  if (2 != pRsp->numOfCols) {
15,376,336✔
4550
    qError("%s invalid scl fetch row rsp received, subQIdx:%d, cols:%" PRId64, ctx->idStr, pParam->subQIdx, pRsp->numOfCols);
×
4551
    ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4552

4553
    return;
×
4554
  }
4555

4556
  ctx->code = createExprSubQResBlock(&pResBlock, &pRemote->val.node.resType);
15,376,336✔
4557
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,375,796✔
4558
    SColumnInfoData idata = createColumnInfoData(TSDB_DATA_TYPE_BOOL, tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, 0);
15,375,796✔
4559
    ctx->code = blockDataAppendColInfo(pResBlock, &idata);
15,376,336✔
4560
  }
4561
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,376,336✔
4562
    ctx->code = blockDataEnsureCapacity(pResBlock, 1);
15,376,336✔
4563
  }
4564
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,376,336✔
4565
    ctx->code = extractSingleRspBlock(pRsp, pResBlock);
15,376,336✔
4566
  }
4567
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,376,336✔
4568
    ctx->code = setValueFromResBlock(ctx, &pRemote->val, pResBlock);
15,376,336✔
4569
  }
4570
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,375,796✔
4571
    ctx->code = setRowHasNullFromResBlock(ctx, &pRemote->hasNull, pResBlock);
15,375,796✔
4572
  }
4573
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,376,336✔
4574
    taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
15,376,336✔
4575
  }
4576
  if (TSDB_CODE_SUCCESS == ctx->code) {
15,375,796✔
4577
    pRemote->valSet = true;
15,376,336✔
4578
    pRemote->hasValue = true;
15,376,336✔
4579
  }
4580

4581
  blockDataDestroy(pResBlock);
15,376,336✔
4582
}
4583

4584

4585
int32_t setZeroRowsResValue(STaskSubJobCtx* ctx, SValueNode* pRes, int32_t rows) {
276,696✔
4586
  pRes->node.type = QUERY_NODE_VALUE;
276,696✔
4587
  pRes->flag &= (~VALUE_FLAG_VAL_UNSET);
276,696✔
4588
  pRes->translate = true;
276,696✔
4589
  
4590
  return nodesSetValueNodeValue(pRes, &rows);
276,696✔
4591
}
4592

4593
void handleRemoteZeroRowsRes(SScalarFetchParam* pParam, STaskSubJobCtx* ctx, SRetrieveTableRsp* pRsp, bool* fetchDone) {
276,448✔
4594
  SRemoteZeroRowsNode* pRemote = (SRemoteZeroRowsNode*)pParam->pRes;
276,448✔
4595
  SExecTaskInfo* pTaskInfo = ctx->pTaskInfo;
276,448✔
4596

4597
  qDebug("%s scl fetch zeroRows rsp received, subQIdx:%d, rows:%" PRId64 , ctx->idStr, pParam->subQIdx, pRsp->numOfRows);
275,908✔
4598

4599
  int32_t resRows = (pRsp->numOfRows > 0) ? 1 : 0;
275,908✔
4600
  if (resRows > 0 || pRsp->completed) {
276,448✔
4601
    ctx->code = setZeroRowsResValue(ctx, &pRemote->val, resRows);
276,448✔
4602
    if (TSDB_CODE_SUCCESS == ctx->code) {
276,448✔
4603
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
276,448✔
4604
    }
4605

4606
    *fetchDone = true;
276,448✔
4607
  } else {
4608
    *fetchDone = false;
×
4609
  }
4610

4611
  if (IS_STREAM_MODE(pTaskInfo) && 0 == pRsp->numOfRows) {
276,448✔
4612
    ctx->code = setZeroRowsResValue(ctx, &pRemote->val, 0);
248✔
4613
    if (TSDB_CODE_SUCCESS == ctx->code) {
248✔
4614
      taosArraySet(ctx->subResNodes, pParam->subQIdx, &pParam->pRes);
248✔
4615
    }
4616

4617
    pRsp->completed = true;
248✔
4618
    *fetchDone = true;
248✔
4619
  }
4620

4621
  if (!(*fetchDone)) {
276,448✔
4622
    int32_t code = sendFetchRemoteNodeReq(ctx, pParam->subQIdx, pParam->pRes, false);
×
4623
    if (TSDB_CODE_SUCCESS != code) {
×
4624
      ctx->code = code;
×
4625
      *fetchDone = true;
×
4626
    }
4627
  }
4628
}
276,448✔
4629

4630

4631
int32_t remoteFetchCallBack(void* param, SDataBuf* pMsg, int32_t code) {
38,130,678✔
4632
  taosMemoryFreeClear(pMsg->pEpSet);
38,130,678✔
4633

4634
  SScalarFetchParam* pParam = (SScalarFetchParam*)param;
38,130,678✔
4635
  STaskSubJobCtx* ctx = taosAcquireRef(fetchObjRefPool, pParam->subJobRefId);
38,130,678✔
4636
  if (ctx == NULL) {
38,130,678✔
4637
    qWarn("failed to acquire subJobCtx, since it may have been released, refId:%" PRIu64, pParam->subJobRefId);
4,977✔
4638
    taosMemoryFree(pMsg->pData);
4,977✔
4639
    return TSDB_CODE_SUCCESS;
4,977✔
4640
  }
4641

4642
  char idStr[64];
38,125,701✔
4643
  if (qDebugFlag & DEBUG_DEBUG) {
38,125,701✔
4644
    tstrncpy(idStr, ctx->idStr, sizeof(idStr));
1,438,464✔
4645
  }
4646
  
4647
  qDebug("%s subQIdx %d got rsp, blockIdx:%" PRId64 ", code:%d, rsp:%p", ctx->idStr, pParam->subQIdx, ctx->blockIdx, code, pMsg->pData);
38,125,701✔
4648

4649
  if (ctx->transporterId > 0) {
38,125,701✔
4650
    int32_t ret = asyncFreeConnById(ctx->rpcHandle, ctx->transporterId);
38,125,701✔
4651
    if (ret != 0) {
38,124,621✔
4652
      qDebug("%s failed to free subQ rpc handle, code:%s, subQIdx:%d", ctx->idStr, tstrerror(ret), pParam->subQIdx);
×
4653
    }
4654
    ctx->transporterId = -1;
38,124,621✔
4655
  }
4656

4657
  if (0 == code && NULL == pMsg->pData) {
38,124,042✔
4658
    qError("%s invalid rsp msg, msgType:%d, len:%d", ctx->idStr, pMsg->msgType, pMsg->len);
×
4659
    code = TSDB_CODE_QRY_INVALID_MSG;
×
4660
  }
4661

4662
  if (code == TSDB_CODE_SUCCESS) {
38,125,161✔
4663
    SRetrieveTableRsp* pRsp = pMsg->pData;
37,246,997✔
4664
    pRsp->numOfRows = htobe64(pRsp->numOfRows);
37,247,537✔
4665
    pRsp->compLen = htonl(pRsp->compLen);
37,246,997✔
4666
    pRsp->payloadLen = htonl(pRsp->payloadLen);
37,245,364✔
4667
    pRsp->numOfCols = htonl(pRsp->numOfCols);
37,246,444✔
4668
    pRsp->useconds = htobe64(pRsp->useconds);
37,246,457✔
4669
    pRsp->numOfBlocks = htonl(pRsp->numOfBlocks);
37,245,891✔
4670

4671
    qDebug("%s subQIdx %d blockIdx:%" PRIu64 " rsp detail, numOfBlocks:%d, numOfRows:%" PRId64 ", numOfCols:%" PRId64 ", completed:%d", 
37,247,537✔
4672
      ctx->idStr, pParam->subQIdx, ctx->blockIdx, pRsp->numOfBlocks, pRsp->numOfRows, pRsp->numOfCols, pRsp->completed);
4673

4674
    ctx->blockIdx++;
37,247,537✔
4675

4676
    switch (nodeType(pParam->pRes)) {
37,246,984✔
4677
      case QUERY_NODE_REMOTE_VALUE: {
3,379,170✔
4678
        bool fetchDone = false;
3,379,170✔
4679
        handleRemoteValueRes(pParam, ctx, pRsp, &fetchDone);
3,379,170✔
4680
        qDebug("%s subQIdx %d handle remote value, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
3,378,617✔
4681
        if (!fetchDone) {
3,380,263✔
4682
          goto _exit;
55,760✔
4683
        }
4684
        break;
3,324,503✔
4685
      }
4686
      case QUERY_NODE_REMOTE_VALUE_LIST: {
12,750,125✔
4687
        bool fetchDone = false;
12,750,125✔
4688
        handleRemoteValueListRes(pParam, ctx, pRsp, &fetchDone);
12,750,125✔
4689
        qDebug("%s subQIdx %d handle remote value list finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
12,749,585✔
4690
        if (!fetchDone) {
12,750,125✔
4691
          goto _exit;
1,333,976✔
4692
        }
4693
        break;
11,416,149✔
4694
      }  
4695
      case QUERY_NODE_REMOTE_ROW: {
20,840,148✔
4696
        bool fetchDone = false;
20,840,148✔
4697
        handleRemoteRowRes(pParam, ctx, pRsp, &fetchDone);
20,840,148✔
4698
        qDebug("%s subQIdx %d handle remote row finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
20,840,148✔
4699
        if (!fetchDone) {
20,840,148✔
4700
          goto _exit;
496✔
4701
        }
4702
        break;
20,839,652✔
4703
      }
4704
      case QUERY_NODE_REMOTE_ZERO_ROWS: {
276,448✔
4705
        bool fetchDone = false;
276,448✔
4706
        handleRemoteZeroRowsRes(pParam, ctx, pRsp, &fetchDone);
276,448✔
4707
        qDebug("%s subQIdx %d handle remote zeroRows finished, fetchDone:%d", idStr, pParam->subQIdx, fetchDone);
276,448✔
4708
        if (!fetchDone) {
275,908✔
4709
          goto _exit;
×
4710
        }
4711
        break;
275,908✔
4712
      }
4713
      default:
×
4714
        qError("%s invalid scl fetch res node %d, subQIdx:%d", ctx->idStr, nodeType(pParam->pRes), pParam->subQIdx);
×
4715
        ctx->code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
4716
        break;
×
4717
    }
4718
  } else {
4719
    ctx->code = rpcCvtErrCode(code);
878,164✔
4720
    if (ctx->code != code) {
878,164✔
4721
      qError("%s scl fetch rsp received, subQIdx:%d, error:%s, cvted error: %s", ctx->idStr, pParam->subQIdx,
×
4722
             tstrerror(code), tstrerror(ctx->code));
4723
    } else {
4724
      qError("%s scl fetch rsp received, subQIdx:%d, error:%s", ctx->idStr, pParam->subQIdx, tstrerror(code));
877,611✔
4725
    }
4726
  }
4727

4728
  qDebug("%s subQIdx %d sem_post subQ ready", ctx->idStr, pParam->subQIdx);
36,731,624✔
4729
  
4730
  code = tsem_post(&ctx->ready);
36,731,624✔
4731
  if (code != TSDB_CODE_SUCCESS) {
36,735,469✔
4732
    qError("failed to invoke post when scl fetch rsp is ready, code:%s", tstrerror(code));
×
4733
  }
4734

4735
_exit:
38,127,373✔
4736

4737
  code = taosReleaseRef(fetchObjRefPool, pParam->subJobRefId);
38,125,701✔
4738
  if (code != TSDB_CODE_SUCCESS) {
38,125,701✔
4739
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
4740
  }
4741

4742
  taosMemoryFree(pMsg->pData);
38,125,701✔
4743

4744
  return code;
38,125,701✔
4745
}
4746

4747
#define STREAM_TASK_REPLICA_NUM 5
4748
#define STREAM_TASK_DEPLOY_NUM 3
4749

4750
int32_t sendFetchRemoteNodeReq(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes, bool reset) {
38,130,482✔
4751
  int32_t          code = TSDB_CODE_SUCCESS;
38,130,482✔
4752
  int32_t          lino = 0;
38,130,482✔
4753
  int32_t          innerIdx = 0;
38,130,482✔
4754
  SExecTaskInfo*   pTaskInfo = ctx->pTaskInfo;
38,130,482✔
4755
  bool             needStreamPesudoFuncVals = false;
38,127,399✔
4756

4757
  if (IS_STREAM_MODE(pTaskInfo)) {
38,127,399✔
4758
    innerIdx = pTaskInfo->pStreamRuntimeInfo->execId / STREAM_TASK_REPLICA_NUM;
1,180,901✔
4759
    subQIdx = subQIdx * STREAM_TASK_DEPLOY_NUM + innerIdx;
1,181,149✔
4760
  }
4761

4762
  SDownstreamSourceNode* pSource = (SDownstreamSourceNode*)taosArrayGetP(ctx->subEndPoints, subQIdx);
38,125,174✔
4763

4764
  SResFetchReq req = {0};
38,120,301✔
4765
  req.header.vgId = pSource->addr.nodeId;
38,120,301✔
4766
  req.sId = pSource->sId;
38,121,934✔
4767
  req.clientId = pSource->clientId;
38,127,373✔
4768
  req.taskId = pSource->taskId;
38,121,882✔
4769
  req.srcTaskId = ctx->taskId;
38,120,554✔
4770
  req.blockIdx = ctx->blockIdx;
38,115,603✔
4771
  req.queryId = ctx->queryId;
38,119,169✔
4772
  req.execId = pSource->execId;
38,118,024✔
4773

4774
  if (IS_STREAM_MODE(pTaskInfo)) {
38,118,908✔
4775
    req.queryId = pSource->clientId;
1,180,901✔
4776
    req.execId = pTaskInfo->pStreamRuntimeInfo->execId;
1,180,901✔
4777
    req.pStRtFuncInfo = &pTaskInfo->pStreamRuntimeInfo->funcInfo;
1,181,149✔
4778
    req.reset = reset;
1,181,149✔
4779

4780
    needStreamPesudoFuncVals = true;
1,181,149✔
4781
    subQIdx = (subQIdx - innerIdx) / STREAM_TASK_DEPLOY_NUM;
1,181,149✔
4782
  }
4783

4784
  int32_t msgSize = tSerializeSResFetchReq(NULL, 0, &req, needStreamPesudoFuncVals);
38,118,603✔
4785
  if (msgSize < 0) {
38,129,624✔
4786
    return msgSize;
×
4787
  }
4788

4789
  void* msg = taosMemoryCalloc(1, msgSize);
38,129,624✔
4790
  if (NULL == msg) {
38,117,549✔
4791
    return terrno;
×
4792
  }
4793

4794
  msgSize = tSerializeSResFetchReq(msg, msgSize, &req, needStreamPesudoFuncVals);
38,117,549✔
4795
  if (msgSize < 0) {
38,122,971✔
4796
    taosMemoryFree(msg);
×
4797
    return msgSize;
×
4798
  }
4799

4800
  qDebug("%s scl build fetch msg and send to nodeId:%d, ep:%s, clientId:0x%" PRIx64 " taskId:0x%" PRIx64
38,122,971✔
4801
         ", execId:%d, blockIdx:%" PRId64,
4802
         ctx->idStr, pSource->addr.nodeId, pSource->addr.epSet.eps[0].fqdn, pSource->clientId,
4803
         pSource->taskId, pSource->execId, req.blockIdx);
4804

4805
  // send the fetch remote task result reques
4806
  SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
38,127,425✔
4807
  if (NULL == pMsgSendInfo) {
38,119,670✔
4808
    taosMemoryFreeClear(msg);
×
4809
    qError("%s prepare message %d failed", ctx->idStr, (int32_t)sizeof(SMsgSendInfo));
×
4810
    return terrno;
×
4811
  }
4812

4813
  SScalarFetchParam* param = taosMemoryMalloc(sizeof(SScalarFetchParam));
38,119,670✔
4814
  if (NULL == param) {
38,124,660✔
4815
    taosMemoryFreeClear(msg);
×
4816
    taosMemoryFreeClear(pMsgSendInfo);
×
4817
    qError("%s prepare param %d failed", ctx->idStr, (int32_t)sizeof(SScalarFetchParam));
×
4818
    return terrno;
×
4819
  }
4820

4821
  if (ctx->code) {
38,124,660✔
4822
    qError("task has been killed, error:%s", tstrerror(ctx->code));
×
4823
    taosMemoryFree(param);
×
4824
    taosMemoryFreeClear(msg);
×
4825
    taosMemoryFreeClear(pMsgSendInfo);
×
4826
    code = ctx->code;
×
4827
    goto _end;
×
4828
  }
4829
  
4830
  param->subQIdx = subQIdx;
38,118,063✔
4831
  param->pRes = pRes;
38,122,461✔
4832
  param->subJobRefId = ctx->subJobRefId;
38,125,766✔
4833

4834
  pMsgSendInfo->param = param;
38,121,882✔
4835
  pMsgSendInfo->paramFreeFp = taosAutoMemoryFree;
38,123,014✔
4836
  pMsgSendInfo->msgInfo.pData = msg;
38,115,285✔
4837
  pMsgSendInfo->msgInfo.len = msgSize;
38,118,076✔
4838
  pMsgSendInfo->msgType = pSource->fetchMsgType;
38,121,908✔
4839
  pMsgSendInfo->fp = remoteFetchCallBack;
38,116,996✔
4840
  pMsgSendInfo->requestId = ctx->queryId;
38,121,921✔
4841

4842
  code = asyncSendMsgToServer(ctx->rpcHandle, &pSource->addr.epSet, &ctx->transporterId, pMsgSendInfo);
38,124,647✔
4843
  QUERY_CHECK_CODE(code, lino, _end);
38,132,890✔
4844
      
4845
_end:
38,132,890✔
4846

4847
  if (code != TSDB_CODE_SUCCESS) {
38,132,890✔
4848
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
×
4849
  }
4850
  
4851
  return code;
38,129,598✔
4852
}
4853

4854
int32_t fetchRemoteNodeImpl(STaskSubJobCtx* ctx, int32_t subQIdx, SNode* pRes) {
36,739,932✔
4855
  int32_t          code = TSDB_CODE_SUCCESS;
36,739,932✔
4856
  int32_t          lino = 0;
36,739,932✔
4857

4858
  ctx->blockIdx = 0;
36,739,932✔
4859

4860
  code = sendFetchRemoteNodeReq(ctx, subQIdx, pRes, true);
36,740,472✔
4861
  QUERY_CHECK_CODE(code, lino, _end);
36,740,459✔
4862

4863
  code = qSemWait(ctx->pTaskInfo, &ctx->ready);
36,740,459✔
4864
  if (isTaskKilled(ctx->pTaskInfo)) {
36,744,317✔
4865
    code = getTaskCode(ctx->pTaskInfo);
13,825✔
4866
  } else {
4867
    code = ctx->code;
36,730,492✔
4868
  }
4869
      
4870
_end:
36,744,317✔
4871

4872
  if (code != TSDB_CODE_SUCCESS) {
36,744,317✔
4873
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
1,838,600✔
4874
  }
4875
  return code;
36,744,317✔
4876
}
4877

4878
int32_t remoteNodeCopy(SNode* pSrc, SNode* pDst) {
118,018✔
4879
  int32_t code = 0, lino = 0;
118,018✔
4880
  
4881
  switch (nodeType(pSrc)) {
118,018✔
4882
    case QUERY_NODE_VALUE:
84,538✔
4883
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &((SRemoteValueNode*)pDst)->val));
84,538✔
4884
      ((SRemoteValueNode*)pDst)->val.node.type = QUERY_NODE_VALUE;
84,538✔
4885
      break;
84,538✔
4886
    case QUERY_NODE_REMOTE_VALUE_LIST: {
24,840✔
4887
      SRemoteValueListNode* pDstNode = (SRemoteValueListNode*)pDst;
24,840✔
4888
      memcpy(pDst, pSrc, sizeof(SRemoteValueListNode));
24,840✔
4889
      pDstNode->hashAllocated = false;      
24,840✔
4890
      break;
24,840✔
4891
    } 
4892
    case QUERY_NODE_REMOTE_ROW: {
8,640✔
4893
      SRemoteRowNode* pRemote = (SRemoteRowNode*)pDst;
8,640✔
4894
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &pRemote->val));
8,640✔
4895
      pRemote->valSet = true;
8,640✔
4896
      pRemote->hasValue = ((SRemoteRowNode*)pSrc)->hasValue;
8,640✔
4897
      pRemote->hasNull = ((SRemoteRowNode*)pSrc)->hasNull;
8,640✔
4898
      break;
8,640✔
4899
    }
NEW
4900
    case QUERY_NODE_REMOTE_ZERO_ROWS: {
×
NEW
4901
      SRemoteZeroRowsNode* pRemote = (SRemoteZeroRowsNode*)pDst;
×
NEW
4902
      TAOS_CHECK_EXIT(valueNodeCopy((SValueNode*)pSrc, &pRemote->val));
×
NEW
4903
      pRemote->val.node.type = QUERY_NODE_VALUE;
×
NEW
4904
      break;
×
4905
    }
4906
    default:
×
4907
      break;
×
4908
  }
4909

4910
_exit:
118,018✔
4911

4912
  if (code) {
118,018✔
4913
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
4914
  }
4915

4916
  return code;
118,018✔
4917
}
4918

4919
int32_t qFetchRemoteNode(void* pCtx, int32_t subQIdx, SNode* pRes) {
36,859,056✔
4920
  STaskSubJobCtx*  ctx = (STaskSubJobCtx*)pCtx;
36,859,056✔
4921
  int32_t code = 0, lino = 0;
36,859,056✔
4922
  int32_t       subEndPoinsNum = taosArrayGetSize(ctx->subEndPoints);
36,859,056✔
4923
  if (subQIdx >= subEndPoinsNum) {
36,853,552✔
4924
    qError("%s invalid subQIdx %d, subEndPointsNum:%d", ctx->idStr, subQIdx, subEndPoinsNum);
×
4925
    return TSDB_CODE_QRY_SUBQ_NOT_FOUND;
×
4926
  }
4927

4928
  SNode** ppRes = taosArrayGet(ctx->subResNodes, subQIdx);
36,853,552✔
4929
  if (NULL == *ppRes) {
36,856,857✔
4930
    TAOS_CHECK_EXIT(fetchRemoteNodeImpl(ctx, subQIdx, pRes));
36,739,932✔
4931
    *ppRes = pRes;
34,905,177✔
4932
  } else {
4933
    TAOS_CHECK_EXIT(remoteNodeCopy(*ppRes, pRes));
118,018✔
4934
  }
4935

4936
_exit:
118,558✔
4937

4938
  if (code) {
36,862,335✔
4939
    qError("%s %s failed at line %d since %s", ctx->idStr, __func__, lino, tstrerror(code));
1,838,600✔
4940
  } else {
4941
    qDebug("%s %s subQIdx %d succeed", ctx->idStr, __func__, subQIdx);
35,023,735✔
4942
  }
4943

4944
  return code;
36,861,795✔
4945
}
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