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

H
Haojun Liao 已提交
16 17
#include "filter.h"
#include "function.h"
18 19
#include "functionMgt.h"
#include "os.h"
H
Haojun Liao 已提交
20
#include "querynodes.h"
21
#include "tfill.h"
dengyihao's avatar
dengyihao 已提交
22
#include "tname.h"
23

H
Haojun Liao 已提交
24
#include "tdatablock.h"
25
#include "tglobal.h"
H
Haojun Liao 已提交
26
#include "tmsg.h"
H
Haojun Liao 已提交
27
#include "tsort.h"
28
#include "ttime.h"
H
Haojun Liao 已提交
29

30
#include "executorimpl.h"
31
#include "query.h"
32 33
#include "tcompare.h"
#include "tcompression.h"
H
Haojun Liao 已提交
34
#include "thash.h"
35
#include "ttypes.h"
dengyihao's avatar
dengyihao 已提交
36
#include "vnode.h"
37

H
Haojun Liao 已提交
38
#define IS_MAIN_SCAN(runtime)          ((runtime)->scanFlag == MAIN_SCAN)
39 40
#define IS_REVERSE_SCAN(runtime)       ((runtime)->scanFlag == REVERSE_SCAN)
#define IS_REPEAT_SCAN(runtime)        ((runtime)->scanFlag == REPEAT_SCAN)
L
Liu Jicong 已提交
41
#define SET_MAIN_SCAN_FLAG(runtime)    ((runtime)->scanFlag = MAIN_SCAN)
42 43
#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN)

L
Liu Jicong 已提交
44 45
#define SDATA_BLOCK_INITIALIZER \
  (SDataBlockInfo) { {0}, 0 }
46 47 48 49

#define GET_FORWARD_DIRECTION_FACTOR(ord) (((ord) == TSDB_ORDER_ASC) ? QUERY_ASC_FORWARD_STEP : QUERY_DESC_FORWARD_STEP)

enum {
L
Liu Jicong 已提交
50 51
  TS_JOIN_TS_EQUAL = 0,
  TS_JOIN_TS_NOT_EQUALS = 1,
52 53 54 55 56
  TS_JOIN_TAG_NOT_EQUALS = 2,
};

#if 0
static UNUSED_FUNC void *u_malloc (size_t __size) {
wafwerar's avatar
wafwerar 已提交
57
  uint32_t v = taosRand();
58 59 60 61

  if (v % 1000 <= 0) {
    return NULL;
  } else {
wafwerar's avatar
wafwerar 已提交
62
    return taosMemoryMalloc(__size);
63 64 65 66
  }
}

static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) {
wafwerar's avatar
wafwerar 已提交
67
  uint32_t v = taosRand();
68 69 70
  if (v % 1000 <= 0) {
    return NULL;
  } else {
wafwerar's avatar
wafwerar 已提交
71
    return taosMemoryCalloc(num, __size);
72 73 74 75
  }
}

static UNUSED_FUNC void* u_realloc(void* p, size_t __size) {
wafwerar's avatar
wafwerar 已提交
76
  uint32_t v = taosRand();
77 78 79
  if (v % 5 <= 1) {
    return NULL;
  } else {
wafwerar's avatar
wafwerar 已提交
80
    return taosMemoryRealloc(p, __size);
81 82 83 84 85 86 87 88 89 90 91 92
  }
}

#define calloc  u_calloc
#define malloc  u_malloc
#define realloc u_realloc
#endif

#define CLEAR_QUERY_STATUS(q, st)   ((q)->status &= (~(st)))
#define GET_NUM_OF_TABLEGROUP(q)    taosArrayGetSize((q)->tableqinfoGroupInfo.pGroupList)
#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0)

L
Liu Jicong 已提交
93 94 95
int32_t getMaximumIdleDurationSec() { return tsShellActivityTimer * 2; }

static int32_t getExprFunctionId(SExprInfo* pExprInfo) {
96
  assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE);
97
  return 0;
98 99 100
}

static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes);
L
Liu Jicong 已提交
101
static bool functionNeedToExecute(SqlFunctionCtx* pCtx);
102

103
static void setBlockStatisInfo(SqlFunctionCtx* pCtx, SExprInfo* pExpr, SSDataBlock* pSDataBlock);
104

L
Liu Jicong 已提交
105
static void destroyTableQueryInfoImpl(STableQueryInfo* pTableQueryInfo);
106 107 108

static SColumnInfo* extractColumnFilterInfo(SExprInfo* pExpr, int32_t numOfOutput, int32_t* numOfFilterCols);

L
Liu Jicong 已提交
109
static void    releaseQueryBuf(size_t numOfTables);
110

H
Haojun Liao 已提交
111
static int32_t getNumOfScanTimes(STaskAttr* pQueryAttr);
112 113 114 115 116 117

static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput);
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput);
static void destroyAggOperatorInfo(void* param, int32_t numOfOutput);
X
Xiaoyu Wang 已提交
118

H
Haojun Liao 已提交
119
static void destroyIntervalOperatorInfo(void* param, int32_t numOfOutput);
H
Haojun Liao 已提交
120 121
static void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput);

122
static void destroyOperatorInfo(SOperatorInfo* pOperator);
123
static void destroySysTableScannerOperatorInfo(void* param, int32_t numOfOutput);
124

125
void doSetOperatorCompleted(SOperatorInfo* pOperator) {
126
  pOperator->status = OP_EXEC_DONE;
H
Haojun Liao 已提交
127
  if (pOperator->pTaskInfo != NULL) {
128
    setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
129 130
  }
}
131

H
Haojun Liao 已提交
132
int32_t operatorDummyOpenFn(SOperatorInfo* pOperator) {
133
  OPTR_SET_OPENED(pOperator);
134
  pOperator->cost.openCost = 0;
H
Haojun Liao 已提交
135
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
136 137
}

138
SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t streamFn,
L
Liu Jicong 已提交
139 140
                                   __optr_fn_t cleanup, __optr_close_fn_t closeFn, __optr_encode_fn_t encode,
                                   __optr_decode_fn_t decode, __optr_get_explain_fn_t explain) {
141 142 143 144 145 146 147 148 149 150 151 152 153 154
  SOperatorFpSet fpSet = {
      ._openFn = openFn,
      .getNextFn = nextFn,
      .getStreamResFn = streamFn,
      .cleanupFn = cleanup,
      .closeFn = closeFn,
      .encodeResultRow = encode,
      .decodeResultRow = decode,
      .getExplainFn = explain,
  };

  return fpSet;
}

H
Haojun Liao 已提交
155
void operatorDummyCloseFn(void* param, int32_t numOfCols) {}
H
Haojun Liao 已提交
156

157
static int32_t doCopyToSDataBlock(SExecTaskInfo* taskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo,
158
                                  int32_t* rowCellOffset, SqlFunctionCtx* pCtx, int32_t numOfExprs);
H
Haojun Liao 已提交
159

160
static void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size);
H
Haojun Liao 已提交
161
static void setResultBufSize(STaskAttr* pQueryAttr, SResultInfo* pResultInfo);
dengyihao's avatar
dengyihao 已提交
162 163
static void doSetTableGroupOutputBuf(SAggOperatorInfo* pAggInfo, int32_t numOfOutput, uint64_t groupId,
                                     SExecTaskInfo* pTaskInfo);
164

H
Haojun Liao 已提交
165
SArray* getOrderCheckColumns(STaskAttr* pQuery);
166 167

typedef struct SRowCompSupporter {
L
Liu Jicong 已提交
168 169 170
  STaskRuntimeEnv* pRuntimeEnv;
  int16_t          dataOffset;
  __compar_fn_t    comFunc;
171 172
} SRowCompSupporter;

L
Liu Jicong 已提交
173 174 175
static int compareRowData(const void* a, const void* b, const void* userData) {
  const SResultRow* pRow1 = (const SResultRow*)a;
  const SResultRow* pRow2 = (const SResultRow*)b;
176

L
Liu Jicong 已提交
177 178
  SRowCompSupporter* supporter = (SRowCompSupporter*)userData;
  STaskRuntimeEnv*   pRuntimeEnv = supporter->pRuntimeEnv;
179

L
Liu Jicong 已提交
180 181
  SFilePage* page1 = getBufPage(pRuntimeEnv->pResultBuf, pRow1->pageId);
  SFilePage* page2 = getBufPage(pRuntimeEnv->pResultBuf, pRow2->pageId);
182 183

  int16_t offset = supporter->dataOffset;
L
Liu Jicong 已提交
184 185
  char*   in1 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page1, pRow1->offset, offset);
  char*   in2 = getPosInResultPage(pRuntimeEnv->pQueryAttr, page2, pRow2->offset, offset);
186 187 188 189

  return (in1 != NULL && in2 != NULL) ? supporter->comFunc(in1, in2) : 0;
}

L
Liu Jicong 已提交
190
// setup the output buffer for each operator
191
SSDataBlock* createResDataBlock(SDataBlockDescNode* pNode) {
H
Haojun Liao 已提交
192
  int32_t numOfCols = LIST_LENGTH(pNode->pSlots);
H
Haojun Liao 已提交
193

wafwerar's avatar
wafwerar 已提交
194
  SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
H
Haojun Liao 已提交
195 196
  pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));

H
Haojun Liao 已提交
197
  pBlock->info.blockId = pNode->dataBlockId;
dengyihao's avatar
dengyihao 已提交
198
  pBlock->info.rowSize = pNode->totalRowSize;  // todo ??
5
54liuyao 已提交
199
  pBlock->info.type = STREAM_INVALID;
H
Haojun Liao 已提交
200

L
Liu Jicong 已提交
201
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
202
    SColumnInfoData idata = {{0}};
L
Liu Jicong 已提交
203
    SSlotDescNode*  pDescNode = nodesListGetNode(pNode->pSlots, i);
X
Xiaoyu Wang 已提交
204 205 206
    //    if (!pDescNode->output) {  // todo disable it temporarily
    //      continue;
    //    }
H
Haojun Liao 已提交
207

dengyihao's avatar
dengyihao 已提交
208
    idata.info.type = pDescNode->dataType.type;
L
Liu Jicong 已提交
209 210
    idata.info.bytes = pDescNode->dataType.bytes;
    idata.info.scale = pDescNode->dataType.scale;
H
Haojun Liao 已提交
211
    idata.info.slotId = pDescNode->slotId;
H
Haojun Liao 已提交
212 213
    idata.info.precision = pDescNode->dataType.precision;

H
Hongze Cheng 已提交
214 215 216 217
    if (IS_VAR_DATA_TYPE(idata.info.type)) {
      pBlock->info.hasVarCol = true;
    }

H
Haojun Liao 已提交
218
    taosArrayPush(pBlock->pDataBlock, &idata);
H
Haojun Liao 已提交
219
  }
H
Haojun Liao 已提交
220

221
  pBlock->info.numOfCols = taosArrayGetSize(pBlock->pDataBlock);
H
Haojun Liao 已提交
222
  return pBlock;
H
Haojun Liao 已提交
223 224
}

L
Liu Jicong 已提交
225
static bool hasNull(SColumn* pColumn, SColumnDataAgg* pStatis) {
dengyihao's avatar
dengyihao 已提交
226 227
  if (TSDB_COL_IS_TAG(pColumn->flag) || TSDB_COL_IS_UD_COL(pColumn->flag) ||
      pColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
228 229 230 231 232 233 234 235 236 237
    return false;
  }

  if (pStatis != NULL && pStatis->numOfNull == 0) {
    return false;
  }

  return true;
}

H
Haojun Liao 已提交
238
static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, jmp_buf env) {
239 240
  int64_t newCapacity = 0;

241 242 243 244 245 246 247 248 249 250 251
  // more than the capacity, reallocate the resources
  if (pResultRowInfo->size < pResultRowInfo->capacity) {
    return;
  }

  if (pResultRowInfo->capacity > 10000) {
    newCapacity = (int64_t)(pResultRowInfo->capacity * 1.25);
  } else {
    newCapacity = (int64_t)(pResultRowInfo->capacity * 1.5);
  }

252
  if (newCapacity <= pResultRowInfo->capacity) {
H
Haojun Liao 已提交
253 254 255
    newCapacity += 4;
  }

256 257 258 259 260 261
  char* p = taosMemoryRealloc(pResultRowInfo->pPosition, newCapacity * sizeof(SResultRowPosition));
  if (p == NULL) {
    longjmp(env, TSDB_CODE_OUT_OF_MEMORY);
  }

  pResultRowInfo->pPosition = (SResultRowPosition*)p;
262 263

  int32_t inc = (int32_t)newCapacity - pResultRowInfo->capacity;
wmmhello's avatar
wmmhello 已提交
264
  memset(&pResultRowInfo->pPosition[pResultRowInfo->capacity], 0, sizeof(SResultRowPosition) * inc);
265 266 267
  pResultRowInfo->capacity = (int32_t)newCapacity;
}

L
Liu Jicong 已提交
268 269
static bool chkResultRowFromKey(STaskRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, char* pData,
                                int16_t bytes, bool masterscan, uint64_t uid) {
270 271 272
  bool existed = false;
  SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid);

L
Liu Jicong 已提交
273 274
  SResultRow** p1 =
      (SResultRow**)taosHashGet(pRuntimeEnv->pResultRowHashTable, pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
275 276 277 278 279 280 281 282 283 284 285

  // in case of repeat scan/reverse scan, no new time window added.
  if (QUERY_IS_INTERVAL_QUERY(pRuntimeEnv->pQueryAttr)) {
    if (!masterscan) {  // the *p1 may be NULL in case of sliding+offset exists.
      return p1 != NULL;
    }

    if (p1 != NULL) {
      if (pResultRowInfo->size == 0) {
        existed = false;
      } else if (pResultRowInfo->size == 1) {
dengyihao's avatar
dengyihao 已提交
286
        //        existed = (pResultRowInfo->pResult[0] == (*p1));
287 288
      } else {  // check if current pResultRowInfo contains the existed pResultRow
        SET_RES_EXT_WINDOW_KEY(pRuntimeEnv->keyBuf, pData, bytes, uid, pResultRowInfo);
L
Liu Jicong 已提交
289 290
        int64_t* index =
            taosHashGet(pRuntimeEnv->pResultRowListSet, pRuntimeEnv->keyBuf, GET_RES_EXT_WINDOW_KEY_LEN(bytes));
291 292 293 294 295 296 297 298 299 300 301 302 303 304
        if (index != NULL) {
          existed = true;
        } else {
          existed = false;
        }
      }
    }

    return existed;
  }

  return p1 != NULL;
}

305
SResultRow* getNewResultRow_rv(SDiskbasedBuf* pResultBuf, int64_t tableGroupId, int32_t interBufSize) {
L
Liu Jicong 已提交
306
  SFilePage* pData = NULL;
307 308 309 310 311 312 313 314 315 316 317 318 319

  // in the first scan, new space needed for results
  int32_t pageId = -1;
  SIDList list = getDataBufPagesIdList(pResultBuf, tableGroupId);

  if (taosArrayGetSize(list) == 0) {
    pData = getNewBufPage(pResultBuf, tableGroupId, &pageId);
    pData->num = sizeof(SFilePage);
  } else {
    SPageInfo* pi = getLastPageInfo(list);
    pData = getBufPage(pResultBuf, getPageId(pi));
    pageId = getPageId(pi);

wmmhello's avatar
wmmhello 已提交
320
    if (pData->num + interBufSize > getBufPageSize(pResultBuf)) {
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
      // release current page first, and prepare the next one
      releaseBufPageInfo(pResultBuf, pi);

      pData = getNewBufPage(pResultBuf, tableGroupId, &pageId);
      if (pData != NULL) {
        pData->num = sizeof(SFilePage);
      }
    }
  }

  if (pData == NULL) {
    return NULL;
  }

  // set the number of rows in current disk page
  SResultRow* pResultRow = (SResultRow*)((char*)pData + pData->num);
  pResultRow->pageId = pageId;
  pResultRow->offset = (int32_t)pData->num;

wmmhello's avatar
wmmhello 已提交
340
  pData->num += interBufSize;
341 342 343 344

  return pResultRow;
}

5
54liuyao 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
void doClearWindow(SIntervalAggOperatorInfo* pInfo, char* pData, int16_t bytes,
    uint64_t groupId, int32_t numOfOutput) {
  SAggSupporter* pSup = &pInfo->aggSup;
  SET_RES_WINDOW_KEY(pSup->keyBuf, pData, bytes, groupId);
  SResultRowPosition* p1 =
      (SResultRowPosition*)taosHashGet(pSup->pResultRowHashTable, pSup->keyBuf,
          GET_RES_WINDOW_KEY_LEN(bytes));
  SResultRow* pResult = getResultRowByPos(pSup->pResultBuf, p1);
  SqlFunctionCtx* pCtx = pInfo->binfo.pCtx;
  for (int32_t i = 0; i < numOfOutput; ++i) {
    pCtx[i].resultInfo = getResultCell(pResult, i, pInfo->binfo.rowCellInfoOffset);
    struct SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo;
    if (fmIsWindowPseudoColumnFunc(pCtx[i].functionId)) {
      continue;
    }
    pResInfo->initialized = false;
    if (pCtx[i].functionId != -1) {
      pCtx[i].fpSet.init(&pCtx[i], pResInfo);
    }
  }
}

367 368 369 370 371 372 373
/**
 * the struct of key in hash table
 * +----------+---------------+
 * | group id |   key data    |
 * | 8 bytes  | actual length |
 * +----------+---------------+
 */
374 375 376
SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData,
                                   int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo,
                                   bool isIntervalQuery, SAggSupporter* pSup) {
377
  SET_RES_WINDOW_KEY(pSup->keyBuf, pData, bytes, groupId);
H
Haojun Liao 已提交
378

dengyihao's avatar
dengyihao 已提交
379 380
  SResultRowPosition* p1 =
      (SResultRowPosition*)taosHashGet(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
H
Haojun Liao 已提交
381

382 383
  SResultRow* pResult = NULL;

H
Haojun Liao 已提交
384 385
  // in case of repeat scan/reverse scan, no new time window added.
  if (isIntervalQuery) {
386 387
    if (masterscan && p1 != NULL) {  // the *p1 may be NULL in case of sliding+offset exists.
      pResult = getResultRowByPos(pResultBuf, p1);
H
Haojun Liao 已提交
388 389
    }
  } else {
dengyihao's avatar
dengyihao 已提交
390 391
    // In case of group by column query, the required SResultRow object must be existInCurrentResusltRowInfo in the
    // pResultRowInfo object.
H
Haojun Liao 已提交
392
    if (p1 != NULL) {
393
      pResult = getResultRowByPos(pResultBuf, p1);
H
Haojun Liao 已提交
394 395 396
    }
  }

L
Liu Jicong 已提交
397
  // 1. close current opened time window
398
  if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId &&
L
Liu Jicong 已提交
399
                                                                 pResult->offset != pResultRowInfo->cur.offset))) {
400 401 402 403 404 405 406 407 408 409 410
    // todo extract function
    SResultRowPosition pos = pResultRowInfo->cur;
    SFilePage*         pPage = getBufPage(pResultBuf, pos.pageId);
    SResultRow*        pRow = (SResultRow*)((char*)pPage + pos.offset);
    closeResultRow(pRow);
    releaseBufPage(pResultBuf, pPage);
  }

  // allocate a new buffer page
  prepareResultListBuffer(pResultRowInfo, pTaskInfo->env);
  if (pResult == NULL) {
H
Haojun Liao 已提交
411
    ASSERT(pSup->resultRowSize > 0);
412 413
    pResult = getNewResultRow_rv(pResultBuf, groupId, pSup->resultRowSize);
    initResultRow(pResult);
H
Haojun Liao 已提交
414

415 416
    // add a new result set for a new group
    SResultRowPosition pos = {.pageId = pResult->pageId, .offset = pResult->offset};
L
Liu Jicong 已提交
417 418
    taosHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos,
                sizeof(SResultRowPosition));
H
Haojun Liao 已提交
419 420
  }

421 422 423 424 425
  // 2. set the new time window to be the new active time window
  pResultRowInfo->pPosition[pResultRowInfo->size++] =
      (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
  pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};

H
Haojun Liao 已提交
426 427 428 429 430
  // too many time window in query
  if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
    longjmp(pTaskInfo->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
  }

H
Haojun Liao 已提交
431
  return pResult;
H
Haojun Liao 已提交
432 433
}

434
// get the correct time window according to the handled timestamp
L
Liu Jicong 已提交
435
static STimeWindow getCurrentActiveTimeWindow(SResultRowInfo* pResultRowInfo, int64_t ts, STaskAttr* pQueryAttr) {
436
  STimeWindow w = {0};
H
Haojun Liao 已提交
437
#if 0
L
Liu Jicong 已提交
438 439
  if (pResultRowInfo->curPos == -1) {  // the first window, from the previous stored value
                                       //    getInitialStartTimeWindow(pQueryAttr, ts, &w);
440 441

    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
L
Liu Jicong 已提交
442 443 444
      w.ekey =
          taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) -
          1;
445 446 447 448
    } else {
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
    }
  } else {
H
Haojun Liao 已提交
449
    w = pRow->win;
450 451 452 453 454 455 456 457 458
  }

  /*
   * query border check, skey should not be bounded by the query time range, since the value skey will
   * be used as the time window index value. So we only change ekey of time window accordingly.
   */
  if (w.ekey > pQueryAttr->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) {
    w.ekey = pQueryAttr->window.ekey;
  }
H
Haojun Liao 已提交
459
#endif
460 461 462 463 464

  return w;
}

// a new buffer page for each table. Needs to opt this design
L
Liu Jicong 已提交
465
static int32_t addNewWindowResultBuf(SResultRow* pWindowRes, SDiskbasedBuf* pResultBuf, int32_t tid, uint32_t size) {
466 467 468 469
  if (pWindowRes->pageId != -1) {
    return 0;
  }

L
Liu Jicong 已提交
470
  SFilePage* pData = NULL;
471 472 473 474 475 476

  // in the first scan, new space needed for results
  int32_t pageId = -1;
  SIDList list = getDataBufPagesIdList(pResultBuf, tid);

  if (taosArrayGetSize(list) == 0) {
H
Haojun Liao 已提交
477
    pData = getNewBufPage(pResultBuf, tid, &pageId);
478
    pData->num = sizeof(SFilePage);
479 480
  } else {
    SPageInfo* pi = getLastPageInfo(list);
481
    pData = getBufPage(pResultBuf, getPageId(pi));
482
    pageId = getPageId(pi);
483

484
    if (pData->num + size > getBufPageSize(pResultBuf)) {
485
      // release current page first, and prepare the next one
486
      releaseBufPageInfo(pResultBuf, pi);
487

H
Haojun Liao 已提交
488
      pData = getNewBufPage(pResultBuf, tid, &pageId);
489
      if (pData != NULL) {
490
        pData->num = sizeof(SFilePage);
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
      }
    }
  }

  if (pData == NULL) {
    return -1;
  }

  // set the number of rows in current disk page
  if (pWindowRes->pageId == -1) {  // not allocated yet, allocate new buffer
    pWindowRes->pageId = pageId;
    pWindowRes->offset = (int32_t)pData->num;

    pData->num += size;
    assert(pWindowRes->pageId >= 0);
  }

  return 0;
}

L
Liu Jicong 已提交
511 512 513
static bool chkWindowOutputBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, STimeWindow* win,
                                    bool masterscan, SResultRow** pResult, int64_t groupId, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowCellInfoOffset) {
514
  assert(win->skey <= win->ekey);
L
Liu Jicong 已提交
515
  return chkResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
516 517
}

dengyihao's avatar
dengyihao 已提交
518 519
static void doUpdateResultRowIndex(SResultRowInfo* pResultRowInfo, TSKEY lastKey, bool ascQuery,
                                   bool timeWindowInterpo) {
520
  int64_t skey = TSKEY_INITIAL_VAL;
H
Haojun Liao 已提交
521
#if 0
522 523
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
L
Liu Jicong 已提交
524
    SResultRow* pResult = pResultRowInfo->pResult[i];
525 526 527 528 529 530
    if (pResult->closed) {
      break;
    }

    // new closed result rows
    if (timeWindowInterpo) {
L
Liu Jicong 已提交
531 532 533
      if (pResult->endInterp &&
          ((pResult->win.skey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery))) {
        if (i > 0) {  // the first time window, the startInterp is false.
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
          assert(pResult->startInterp);
        }

        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
    } else {
      if ((pResult->win.ekey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery)) {
        closeResultRow(pResultRowInfo, i);
      } else {
        skey = pResult->win.skey;
      }
    }
  }

  // all result rows are closed, set the last one to be the skey
  if (skey == TSKEY_INITIAL_VAL) {
    if (pResultRowInfo->size == 0) {
L
Liu Jicong 已提交
553
      //      assert(pResultRowInfo->current == NULL);
554 555 556 557 558 559 560
      assert(pResultRowInfo->curPos == -1);
      pResultRowInfo->curPos = -1;
    } else {
      pResultRowInfo->curPos = pResultRowInfo->size - 1;
    }
  } else {
    for (i = pResultRowInfo->size - 1; i >= 0; --i) {
L
Liu Jicong 已提交
561
      SResultRow* pResult = pResultRowInfo->pResult[i];
562 563 564 565 566 567 568 569 570 571 572
      if (pResult->closed) {
        break;
      }
    }

    if (i == pResultRowInfo->size - 1) {
      pResultRowInfo->curPos = i;
    } else {
      pResultRowInfo->curPos = i + 1;  // current not closed result object
    }
  }
H
Haojun Liao 已提交
573
#endif
574
}
575
//
dengyihao's avatar
dengyihao 已提交
576
// static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, const STimeWindow* pWin, TSKEY lastKey,
577 578 579 580 581 582 583 584 585
//                                           bool ascQuery, bool interp) {
//  if ((lastKey > pWin->ekey && ascQuery) || (lastKey < pWin->ekey && (!ascQuery))) {
//    closeAllResultRows(pResultRowInfo);
//    pResultRowInfo->curPos = pResultRowInfo->size - 1;
//  } else {
//    int32_t step = ascQuery ? 1 : -1;
//    doUpdateResultRowIndex(pResultRowInfo, lastKey - step, ascQuery, interp);
//  }
//}
586

587
//  query_range_start, query_range_end, window_duration, window_start, window_end
588
void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow) {
589 590 591
  pColData->info.type = TSDB_DATA_TYPE_TIMESTAMP;
  pColData->info.bytes = sizeof(int64_t);

592
  colInfoDataEnsureCapacity(pColData, 0, 5);
593 594 595 596 597 598 599 600 601
  colDataAppendInt64(pColData, 0, &pQueryWindow->skey);
  colDataAppendInt64(pColData, 1, &pQueryWindow->ekey);

  int64_t interval = 0;
  colDataAppendInt64(pColData, 2, &interval);  // this value may be variable in case of 'n' and 'y'.
  colDataAppendInt64(pColData, 3, &pQueryWindow->skey);
  colDataAppendInt64(pColData, 4, &pQueryWindow->ekey);
}

602
void doApplyFunctions(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, STimeWindow* pWin, SColumnInfoData* pTimeWindowData, int32_t offset,
dengyihao's avatar
dengyihao 已提交
603
                      int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput, int32_t order) {
604
  for (int32_t k = 0; k < numOfOutput; ++k) {
H
Haojun Liao 已提交
605
    // keep it temporarily
dengyihao's avatar
dengyihao 已提交
606 607
    bool    hasAgg = pCtx[k].input.colDataAggIsSet;
    int32_t numOfRows = pCtx[k].input.numOfRows;
H
Haojun Liao 已提交
608
    int32_t startOffset = pCtx[k].input.startRowIndex;
609

H
Haojun Liao 已提交
610
    int32_t pos = (order == TSDB_ORDER_ASC) ? offset : offset - (forwardStep - 1);
611 612
    pCtx[k].input.startRowIndex = pos;
    pCtx[k].input.numOfRows = forwardStep;
613 614

    if (tsCol != NULL) {
H
Haojun Liao 已提交
615
      pCtx[k].ptsList = tsCol;
616 617 618 619
    }

    // not a whole block involved in query processing, statistics data can not be used
    // NOTE: the original value of isSet have been changed here
620 621
    if (pCtx[k].input.colDataAggIsSet && forwardStep < numOfTotal) {
      pCtx[k].input.colDataAggIsSet = false;
622 623
    }

624 625
    if (fmIsWindowPseudoColumnFunc(pCtx[k].functionId)) {
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[k]);
dengyihao's avatar
dengyihao 已提交
626
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
627

628
      SColumnInfoData idata = {0};
dengyihao's avatar
dengyihao 已提交
629
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
630
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
dengyihao's avatar
dengyihao 已提交
631
      idata.pData = p;
632 633 634 635

      SScalarParam out = {.columnData = &idata};
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
      pCtx[k].sfp.process(&tw, 1, &out);
636 637 638
      pEntryInfo->numOfRes = 1;
      continue;
    }
639
    int32_t code = TSDB_CODE_SUCCESS;
640
    if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) {
641 642 643 644 645 646
      code = pCtx[k].fpSet.process(&pCtx[k]);
      if (code != TSDB_CODE_SUCCESS) {
        qError("%s apply functions error, code: %s", GET_TASKID(taskInfo), tstrerror(code));
        taskInfo->code = code;
        longjmp(taskInfo->env, code);
      }
647 648 649
    }

    // restore it
650 651 652
    pCtx[k].input.colDataAggIsSet = hasAgg;
    pCtx[k].input.startRowIndex = startOffset;
    pCtx[k].input.numOfRows = numOfRows;
653 654 655
  }
}

L
Liu Jicong 已提交
656
static FORCE_INLINE TSKEY reviseWindowEkey(STaskAttr* pQueryAttr, STimeWindow* pWindow) {
dengyihao's avatar
dengyihao 已提交
657
  TSKEY   ekey = -1;
658 659
  int32_t order = TSDB_ORDER_ASC;
  if (order == TSDB_ORDER_ASC) {
660 661 662 663 664 665 666 667 668 669 670 671 672 673
    ekey = pWindow->ekey;
    if (ekey > pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
    }
  } else {
    ekey = pWindow->skey;
    if (ekey < pQueryAttr->window.ekey) {
      ekey = pQueryAttr->window.ekey;
    }
  }

  return ekey;
}

dengyihao's avatar
dengyihao 已提交
674
static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
675
                                   int32_t scanFlag, bool createDummyCol);
676

dengyihao's avatar
dengyihao 已提交
677 678
static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock,
                                    int32_t order) {
679
  for (int32_t i = 0; i < pOperator->numOfExprs; ++i) {
680
    pCtx[i].order = order;
681
    pCtx[i].input.numOfRows = pBlock->info.rows;
682
    setBlockStatisInfo(&pCtx[i], &pOperator->pExpr[i], pBlock);
683 684 685
  }
}

686
void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order, int32_t scanFlag,
dengyihao's avatar
dengyihao 已提交
687
                       bool createDummyCol) {
688
  if (pBlock->pBlockAgg != NULL) {
H
Haojun Liao 已提交
689
    doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
690
  } else {
691
    doSetInputDataBlock(pOperator, pCtx, pBlock, order, scanFlag, createDummyCol);
H
Haojun Liao 已提交
692
  }
693 694
}

L
Liu Jicong 已提交
695 696
static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t paramIndex,
                                             int32_t numOfRows) {
697 698 699 700 701 702 703 704
  SColumnInfoData* pColInfo = NULL;
  if (pInput->pData[paramIndex] == NULL) {
    pColInfo = taosMemoryCalloc(1, sizeof(SColumnInfoData));
    if (pColInfo == NULL) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }

    // Set the correct column info (data type and bytes)
705 706
    pColInfo->info.type = pFuncParam->param.nType;
    pColInfo->info.bytes = pFuncParam->param.nLen;
707 708

    pInput->pData[paramIndex] = pColInfo;
709 710
  } else {
    pColInfo = pInput->pData[paramIndex];
711 712
  }

713
  colInfoDataEnsureCapacity(pColInfo, 0, numOfRows);
714

715
  int8_t type = pFuncParam->param.nType;
716 717
  if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT) {
    int64_t v = pFuncParam->param.i;
dengyihao's avatar
dengyihao 已提交
718
    for (int32_t i = 0; i < numOfRows; ++i) {
719 720 721 722
      colDataAppendInt64(pColInfo, i, &v);
    }
  } else if (type == TSDB_DATA_TYPE_DOUBLE) {
    double v = pFuncParam->param.d;
dengyihao's avatar
dengyihao 已提交
723
    for (int32_t i = 0; i < numOfRows; ++i) {
724 725
      colDataAppendDouble(pColInfo, i, &v);
    }
726
  } else if (type == TSDB_DATA_TYPE_VARCHAR) {
L
Liu Jicong 已提交
727
    char* tmp = taosMemoryMalloc(pFuncParam->param.nLen + VARSTR_HEADER_SIZE);
728
    STR_WITH_SIZE_TO_VARSTR(tmp, pFuncParam->param.pz, pFuncParam->param.nLen);
L
Liu Jicong 已提交
729
    for (int32_t i = 0; i < numOfRows; ++i) {
730 731
      colDataAppend(pColInfo, i, tmp, false);
    }
732 733 734 735 736
  }

  return TSDB_CODE_SUCCESS;
}

dengyihao's avatar
dengyihao 已提交
737
static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
738
    int32_t scanFlag, bool createDummyCol) {
739 740
  int32_t code = TSDB_CODE_SUCCESS;

741
  for (int32_t i = 0; i < pOperator->numOfExprs; ++i) {
L
Liu Jicong 已提交
742
    pCtx[i].order = order;
743 744
    pCtx[i].input.numOfRows = pBlock->info.rows;

L
Liu Jicong 已提交
745
    pCtx[i].pSrcBlock = pBlock;
746
    pCtx[i].scanFlag  = scanFlag;
H
Haojun Liao 已提交
747

748
    SInputColumnInfoData* pInput = &pCtx[i].input;
749
    pInput->uid = pBlock->info.uid;
C
Cary Xu 已提交
750
    pInput->colDataAggIsSet = false;
751

752 753
    SExprInfo* pOneExpr = &pOperator->pExpr[i];
    for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) {
dengyihao's avatar
dengyihao 已提交
754
      SFunctParam* pFuncParam = &pOneExpr->base.pParam[j];
G
Ganlin Zhao 已提交
755 756
      if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) {
        int32_t slotId = pFuncParam->pCol->slotId;
dengyihao's avatar
dengyihao 已提交
757
        pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId);
758 759 760
        pInput->totalRows = pBlock->info.rows;
        pInput->numOfRows = pBlock->info.rows;
        pInput->startRowIndex = 0;
761

762
        // NOTE: the last parameter is the primary timestamp column
763 764 765
        if (fmIsTimelineFunc(pCtx[i].functionId) && (j == pOneExpr->base.numOfParams - 1)) {
          pInput->pPTS = pInput->pData[j];
        }
766 767
        ASSERT(pInput->pData[j] != NULL);
      } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) {
768 769 770
        // todo avoid case: top(k, 12), 12 is the value parameter.
        // sum(11), 11 is also the value parameter.
        if (createDummyCol && pOneExpr->base.numOfParams == 1) {
771 772 773 774
          pInput->totalRows = pBlock->info.rows;
          pInput->numOfRows = pBlock->info.rows;
          pInput->startRowIndex = 0;

775
          code = doCreateConstantValColumnInfo(pInput, pFuncParam, j, pBlock->info.rows);
776 777 778
          if (code != TSDB_CODE_SUCCESS) {
            return code;
          }
779
        }
G
Ganlin Zhao 已提交
780 781
      }
    }
H
Haojun Liao 已提交
782

H
Haojun Liao 已提交
783
    //    setBlockStatisInfo(&pCtx[i], pBlock, pOperator->pExpr[i].base.pColumns);
H
Haojun Liao 已提交
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
    //      uint32_t flag = pOperator->pExpr[i].base.pParam[0].pCol->flag;
    //      if (TSDB_COL_IS_NORMAL_COL(flag) /*|| (pCtx[i].functionId == FUNCTION_BLKINFO) ||
    //          (TSDB_COL_IS_TAG(flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)*/) {

    //        SColumn* pCol = pOperator->pExpr[i].base.pParam[0].pCol;
    //        if (pCtx[i].columnIndex == -1) {
    //          for(int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
    //            SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, j);
    //            if (pColData->info.colId == pCol->colId) {
    //              pCtx[i].columnIndex = j;
    //              break;
    //            }
    //          }
    //        }

    //        uint32_t status = aAggs[pCtx[i].functionId].status;
    //        if ((status & (FUNCSTATE_SELECTIVITY | FUNCSTATE_NEED_TS)) != 0) {
    //          SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
    // In case of the top/bottom query again the nest query result, which has no timestamp column
    // don't set the ptsList attribute.
    //          if (tsInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
    //            pCtx[i].ptsList = (int64_t*) tsInfo->pData;
    //          } else {
    //            pCtx[i].ptsList = NULL;
    //          }
    //        }
    //      } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
    //        SColIndex*       pColIndex = &pOperator->pExpr[i].base.colInfo;
    //        SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
    //
    //        pCtx[i].pInput = p->pData;
    //        assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type);
    //        for(int32_t j = 0; j < pBlock->info.rows; ++j) {
    //          char* dst = p->pData + j * p->info.bytes;
    //          taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
    //        }
    //      }
  }
822 823

  return code;
H
Haojun Liao 已提交
824 825
}

826
static int32_t doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunctionCtx* pCtx) {
827
  for (int32_t k = 0; k < pOperator->numOfExprs; ++k) {
H
Haojun Liao 已提交
828
    if (functionNeedToExecute(&pCtx[k])) {
829 830
      // todo add a dummy funtion to avoid process check
      if (pCtx[k].fpSet.process != NULL) {
831 832
        int32_t code = pCtx[k].fpSet.process(&pCtx[k]);
        if (code != TSDB_CODE_SUCCESS) {
833 834
          qError("%s aggregate function error happens, code: %s", GET_TASKID(pOperator->pTaskInfo), tstrerror(code));
          return code;
835
        }
836
      }
837 838
    }
  }
839 840

  return TSDB_CODE_SUCCESS;
841 842
}

H
Haojun Liao 已提交
843
static void setPseudoOutputColInfo(SSDataBlock* pResult, SqlFunctionCtx* pCtx, SArray* pPseudoList) {
dengyihao's avatar
dengyihao 已提交
844
  size_t num = (pPseudoList != NULL) ? taosArrayGetSize(pPseudoList) : 0;
H
Haojun Liao 已提交
845 846 847 848 849
  for (int32_t i = 0; i < num; ++i) {
    pCtx[i].pOutput = taosArrayGet(pResult->pDataBlock, i);
  }
}

850
int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBlock* pSrcBlock, SqlFunctionCtx* pCtx,
X
Xiaoyu Wang 已提交
851
                              int32_t numOfOutput, SArray* pPseudoList) {
H
Haojun Liao 已提交
852
  setPseudoOutputColInfo(pResult, pCtx, pPseudoList);
H
Haojun Liao 已提交
853
  pResult->info.groupId = pSrcBlock->info.groupId;
H
Haojun Liao 已提交
854

dengyihao's avatar
dengyihao 已提交
855 856
  // if the source equals to the destination, it is to create a new column as the result of scalar function or some
  // operators.
857 858
  bool createNewColModel = (pResult == pSrcBlock);

859 860
  int32_t numOfRows = 0;

861
  for (int32_t k = 0; k < numOfOutput; ++k) {
dengyihao's avatar
dengyihao 已提交
862
    int32_t         outputSlotId = pExpr[k].base.resSchema.slotId;
863 864
    SqlFunctionCtx* pfCtx = &pCtx[k];

L
Liu Jicong 已提交
865
    if (pExpr[k].pExpr->nodeType == QUERY_NODE_COLUMN) {  // it is a project query
866
      SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
867
      if (pResult->info.rows > 0 && !createNewColModel) {
X
Xiaoyu Wang 已提交
868 869
        colDataMergeCol(pColInfoData, pResult->info.rows, &pResult->info.capacity, pfCtx->input.pData[0],
                        pfCtx->input.numOfRows);
870 871 872
      } else {
        colDataAssign(pColInfoData, pfCtx->input.pData[0], pfCtx->input.numOfRows);
      }
873

874
      numOfRows = pfCtx->input.numOfRows;
875
    } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_VALUE) {
876
      SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
877

dengyihao's avatar
dengyihao 已提交
878
      int32_t offset = createNewColModel ? 0 : pResult->info.rows;
879
      for (int32_t i = 0; i < pSrcBlock->info.rows; ++i) {
dengyihao's avatar
dengyihao 已提交
880 881 882
        colDataAppend(pColInfoData, i + offset,
                      taosVariantGet(&pExpr[k].base.pParam[0].param, pExpr[k].base.pParam[0].param.nType),
                      TSDB_DATA_TYPE_NULL == pExpr[k].base.pParam[0].param.nType);
883
      }
884 885

      numOfRows = pSrcBlock->info.rows;
H
Haojun Liao 已提交
886
    } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_OPERATOR) {
887 888 889
      SArray* pBlockList = taosArrayInit(4, POINTER_BYTES);
      taosArrayPush(pBlockList, &pSrcBlock);

890
      SColumnInfoData* pResColData = taosArrayGet(pResult->pDataBlock, outputSlotId);
891
      SColumnInfoData  idata = {.info = pResColData->info, .hasNull = true};
892

893
      SScalarParam dest = {.columnData = &idata};
894 895
      scalarCalculate(pExpr[k].pExpr->_optrRoot.pRootNode, pBlockList, &dest);

dengyihao's avatar
dengyihao 已提交
896
      int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
897
      colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
898
      colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
899 900

      numOfRows = dest.numOfRows;
901 902
      taosArrayDestroy(pBlockList);
    } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_FUNCTION) {
903
      ASSERT(!fmIsAggFunc(pfCtx->functionId));
904

905 906
      // _rowts/_c0, not tbname column
      if (fmIsPseudoColumnFunc(pfCtx->functionId) && (!fmIsScanPseudoColumnFunc(pfCtx->functionId))) {
H
Haojun Liao 已提交
907
        // do nothing
908
      } else if (fmIsNonstandardSQLFunc(pfCtx->functionId)) {
dengyihao's avatar
dengyihao 已提交
909
        SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[k]);
910
        pfCtx->fpSet.init(&pCtx[k], pResInfo);
911

912
        pfCtx->pOutput = taosArrayGet(pResult->pDataBlock, outputSlotId);
dengyihao's avatar
dengyihao 已提交
913
        pfCtx->offset = createNewColModel ? 0 : pResult->info.rows;  // set the start offset
H
Haojun Liao 已提交
914

915
        // set the timestamp(_rowts) output buffer
916 917
        if (taosArrayGetSize(pPseudoList) > 0) {
          int32_t* outputColIndex = taosArrayGet(pPseudoList, 0);
918
          pfCtx->pTsOutput = (SColumnInfoData*)pCtx[*outputColIndex].pOutput;
919
        }
H
Haojun Liao 已提交
920

921
        numOfRows = pfCtx->fpSet.process(pfCtx);
H
Haojun Liao 已提交
922 923 924
      } else {
        SArray* pBlockList = taosArrayInit(4, POINTER_BYTES);
        taosArrayPush(pBlockList, &pSrcBlock);
G
Ganlin Zhao 已提交
925

926
        SColumnInfoData* pResColData = taosArrayGet(pResult->pDataBlock, outputSlotId);
927
        SColumnInfoData  idata = {.info = pResColData->info, .hasNull = true};
H
Haojun Liao 已提交
928

929
        SScalarParam dest = {.columnData = &idata};
X
Xiaoyu Wang 已提交
930
        int32_t      code = scalarCalculate((SNode*)pExpr[k].pExpr->_function.pFunctNode, pBlockList, &dest);
931 932 933 934
        if (code != TSDB_CODE_SUCCESS) {
          taosArrayDestroy(pBlockList);
          return code;
        }
935

dengyihao's avatar
dengyihao 已提交
936
        int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
937
        colInfoDataEnsureCapacity(pResColData, startOffset, pResult->info.capacity);
938
        colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
939 940

        numOfRows = dest.numOfRows;
H
Haojun Liao 已提交
941 942
        taosArrayDestroy(pBlockList);
      }
943
    } else {
944
      ASSERT(0);
945 946
    }
  }
947

948 949 950
  if (!createNewColModel) {
    pResult->info.rows += numOfRows;
  }
951 952

  return TSDB_CODE_SUCCESS;
953 954
}

955 956 957
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
  if (IS_VAR_DATA_TYPE(type)) {
    // todo disable this
958

959 960 961 962 963 964 965 966 967
    //    if (pResultRow->key == NULL) {
    //      pResultRow->key = taosMemoryMalloc(varDataTLen(pData));
    //      varDataCopy(pResultRow->key, pData);
    //    } else {
    //      ASSERT(memcmp(pResultRow->key, pData, varDataTLen(pData)) == 0);
    //    }
  } else {
    int64_t v = -1;
    GET_TYPED_DATA(v, int64_t, type, pData);
968

969 970
    pResultRow->win.skey = v;
    pResultRow->win.ekey = v;
971 972 973
  }
}

974 975 976 977 978
int32_t setGroupResultOutputBuf(SOptrBasicInfo* binfo, int32_t numOfCols, char* pData, int16_t type, int16_t bytes,
                                int32_t groupId, SDiskbasedBuf* pBuf, SExecTaskInfo* pTaskInfo,
                                SAggSupporter* pAggSup) {
  SResultRowInfo* pResultRowInfo = &binfo->resultRowInfo;
  SqlFunctionCtx* pCtx = binfo->pCtx;
979

980 981 982
  SResultRow* pResultRow =
      doSetResultOutBufByKey(pBuf, pResultRowInfo, (char*)pData, bytes, true, groupId, pTaskInfo, false, pAggSup);
  assert(pResultRow != NULL);
983

984
  setResultRowKey(pResultRow, pData, type);
985
  setResultRowInitCtx(pResultRow, pCtx, numOfCols, binfo->rowCellInfoOffset);
986
  return TSDB_CODE_SUCCESS;
987 988
}

989 990
static bool functionNeedToExecute(SqlFunctionCtx* pCtx) {
  struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
991

992 993 994 995 996
  // in case of timestamp column, always generated results.
  int32_t functionId = pCtx->functionId;
  if (functionId == -1) {
    return false;
  }
997

998 999
  if (pCtx->scanFlag == REPEAT_SCAN) {
    return fmIsRepeatScanFunc(pCtx->functionId);
1000 1001
  }

1002 1003
  if (isRowEntryCompleted(pResInfo)) {
    return false;
1004 1005
  }

1006 1007 1008 1009 1010 1011 1012 1013
//  if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_FIRST) {
//    //    return QUERY_IS_ASC_QUERY(pQueryAttr);
//  }
//
//  // denote the order type
//  if ((functionId == FUNCTION_LAST_DST || functionId == FUNCTION_LAST)) {
//    //    return pCtx->param[0].i == pQueryAttr->order.order;
//  }
1014

1015 1016 1017 1018 1019
  // in the reverse table scan, only the following functions need to be executed
  //  if (IS_REVERSE_SCAN(pRuntimeEnv) ||
  //      (pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != FUNCTION_STDDEV && functionId != FUNCTION_PERCT)) {
  //    return false;
  //  }
1020 1021 1022 1023

  return true;
}

1024 1025 1026 1027 1028 1029 1030
static int32_t doCreateConstantValColumnAggInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t type,
                                                int32_t paramIndex, int32_t numOfRows) {
  if (pInput->pData[paramIndex] == NULL) {
    pInput->pData[paramIndex] = taosMemoryCalloc(1, sizeof(SColumnInfoData));
    if (pInput->pData[paramIndex] == NULL) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }
1031

1032 1033 1034
    // Set the correct column info (data type and bytes)
    pInput->pData[paramIndex]->info.type = type;
    pInput->pData[paramIndex]->info.bytes = tDataTypes[type].bytes;
1035
  }
H
Haojun Liao 已提交
1036

1037 1038 1039 1040 1041 1042
  SColumnDataAgg* da = NULL;
  if (pInput->pColumnDataAgg[paramIndex] == NULL) {
    da = taosMemoryCalloc(1, sizeof(SColumnDataAgg));
    pInput->pColumnDataAgg[paramIndex] = da;
    if (da == NULL) {
      return TSDB_CODE_OUT_OF_MEMORY;
1043 1044
    }
  } else {
1045
    da = pInput->pColumnDataAgg[paramIndex];
1046 1047
  }

1048
  ASSERT(!IS_VAR_DATA_TYPE(type));
1049

1050 1051 1052 1053 1054 1055
  if (type == TSDB_DATA_TYPE_BIGINT) {
    int64_t v = pFuncParam->param.i;
    *da = (SColumnDataAgg){.numOfNull = 0, .min = v, .max = v, .maxIndex = 0, .minIndex = 0, .sum = v * numOfRows};
  } else if (type == TSDB_DATA_TYPE_DOUBLE) {
    double v = pFuncParam->param.d;
    *da = (SColumnDataAgg){.numOfNull = 0, .maxIndex = 0, .minIndex = 0};
1056

1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
    *(double*)&da->min = v;
    *(double*)&da->max = v;
    *(double*)&da->sum = v * numOfRows;
  } else if (type == TSDB_DATA_TYPE_BOOL) {  // todo validate this data type
    bool v = pFuncParam->param.i;

    *da = (SColumnDataAgg){.numOfNull = 0, .maxIndex = 0, .minIndex = 0};
    *(bool*)&da->min = 0;
    *(bool*)&da->max = v;
    *(bool*)&da->sum = v * numOfRows;
  } else if (type == TSDB_DATA_TYPE_TIMESTAMP) {
    // do nothing
1069
  } else {
1070
    ASSERT(0);
1071 1072
  }

1073 1074
  return TSDB_CODE_SUCCESS;
}
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085

void setBlockStatisInfo(SqlFunctionCtx* pCtx, SExprInfo* pExprInfo, SSDataBlock* pBlock) {
  int32_t numOfRows = pBlock->info.rows;

  SInputColumnInfoData* pInput = &pCtx->input;
  pInput->numOfRows = numOfRows;
  pInput->totalRows = numOfRows;

  if (pBlock->pBlockAgg != NULL) {
    pInput->colDataAggIsSet = true;

1086 1087
    for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) {
      SFunctParam* pFuncParam = &pExprInfo->base.pParam[j];
1088

1089 1090
      if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) {
        int32_t slotId = pFuncParam->pCol->slotId;
1091 1092 1093 1094
        pInput->pColumnDataAgg[j] = pBlock->pBlockAgg[slotId];
        if (pInput->pColumnDataAgg[j] == NULL) {
          pInput->colDataAggIsSet = false;
        }
1095 1096 1097 1098

        // Here we set the column info data since the data type for each column data is required, but
        // the data in the corresponding SColumnInfoData will not be used.
        pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId);
1099 1100
      } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) {
        doCreateConstantValColumnAggInfo(pInput, pFuncParam, pFuncParam->param.nType, j, pBlock->info.rows);
1101 1102
      }
    }
1103
  } else {
1104
    pInput->colDataAggIsSet = false;
1105 1106 1107
  }

  // set the statistics data for primary time stamp column
1108 1109 1110 1111 1112
  //  if (pCtx->functionId == FUNCTION_SPREAD && pColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
  //    pCtx->isAggSet = true;
  //    pCtx->agg.min = pBlock->info.window.skey;
  //    pCtx->agg.max = pBlock->info.window.ekey;
  //  }
1113 1114 1115
}

// set the output buffer for the selectivity + tag query
1116
static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1117 1118
  int32_t num = 0;

H
Haojun Liao 已提交
1119
  SqlFunctionCtx*  p = NULL;
1120 1121
  SqlFunctionCtx** pValCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
  if (pValCtx == NULL) {
1122 1123 1124 1125
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
1126 1127
    if (strcmp(pCtx[i].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
      pValCtx[num++] = &pCtx[i];
1128
    } else if (fmIsAggFunc(pCtx[i].functionId)) {
1129
      p = &pCtx[i];
1130
    }
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
//    if (functionId == FUNCTION_TAG_DUMMY || functionId == FUNCTION_TS_DUMMY) {
//      tagLen += pCtx[i].resDataInfo.bytes;
//      pTagCtx[num++] = &pCtx[i];
//    } else if (functionId == FUNCTION_TS || functionId == FUNCTION_TAG) {
//      // tag function may be the group by tag column
//      // ts may be the required primary timestamp column
//      continue;
//    } else {
//      // the column may be the normal column, group by normal_column, the functionId is FUNCTION_PRJ
//    }
1141
  }
1142

1143
  if (p != NULL) {
1144
    p->subsidiaries.pCtx = pValCtx;
1145
    p->subsidiaries.num = num;
1146
  } else {
1147
    taosMemoryFreeClear(pValCtx);
1148 1149 1150 1151 1152
  }

  return TSDB_CODE_SUCCESS;
}

1153
SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, int32_t** rowCellInfoOffset) {
L
Liu Jicong 已提交
1154
  SqlFunctionCtx* pFuncCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
H
Haojun Liao 已提交
1155 1156 1157 1158
  if (pFuncCtx == NULL) {
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
1159
  *rowCellInfoOffset = taosMemoryCalloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1160
  if (*rowCellInfoOffset == 0) {
wafwerar's avatar
wafwerar 已提交
1161
    taosMemoryFreeClear(pFuncCtx);
H
Haojun Liao 已提交
1162 1163 1164 1165
    return NULL;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
1166
    SExprInfo* pExpr = &pExprInfo[i];
H
Haojun Liao 已提交
1167

L
Liu Jicong 已提交
1168
    SExprBasicInfo* pFunct = &pExpr->base;
H
Haojun Liao 已提交
1169
    SqlFunctionCtx* pCtx = &pFuncCtx[i];
H
Haojun Liao 已提交
1170

1171
    pCtx->functionId = -1;
1172
    pCtx->curBufPage = -1;
L
Liu Jicong 已提交
1173
    pCtx->pExpr = pExpr;
1174

H
Haojun Liao 已提交
1175
    if (pExpr->pExpr->nodeType == QUERY_NODE_FUNCTION) {
H
Haojun Liao 已提交
1176
      SFuncExecEnv env = {0};
H
Haojun Liao 已提交
1177 1178
      pCtx->functionId = pExpr->pExpr->_function.pFunctNode->funcId;

H
Haojun Liao 已提交
1179
      if (fmIsAggFunc(pCtx->functionId) || fmIsNonstandardSQLFunc(pCtx->functionId)) {
1180 1181 1182 1183
        bool isUdaf = fmIsUserDefinedFunc(pCtx->functionId);
        if (!isUdaf) {
          fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet);
        } else {
1184
          char* udfName = pExpr->pExpr->_function.pFunctNode->functionName;
1185 1186 1187
          strncpy(pCtx->udfName, udfName, strlen(udfName));
          fmGetUdafExecFuncs(pCtx->functionId, &pCtx->fpSet);
        }
1188 1189 1190
        pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
      } else {
        fmGetScalarFuncExecFuncs(pCtx->functionId, &pCtx->sfp);
1191 1192 1193
        if (pCtx->sfp.getEnv != NULL) {
          pCtx->sfp.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
        }
1194
      }
H
Haojun Liao 已提交
1195
      pCtx->resDataInfo.interBufSize = env.calcMemSize;
1196 1197
    } else if (pExpr->pExpr->nodeType == QUERY_NODE_COLUMN || pExpr->pExpr->nodeType == QUERY_NODE_OPERATOR ||
               pExpr->pExpr->nodeType == QUERY_NODE_VALUE) {
H
Haojun Liao 已提交
1198
      // for simple column, the result buffer needs to hold at least one element.
1199
      pCtx->resDataInfo.interBufSize = pFunct->resSchema.bytes;
H
Haojun Liao 已提交
1200
    }
H
Haojun Liao 已提交
1201

H
Haojun Liao 已提交
1202
    pCtx->input.numOfInputCols = pFunct->numOfParams;
wafwerar's avatar
wafwerar 已提交
1203 1204
    pCtx->input.pData = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
    pCtx->input.pColumnDataAgg = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
H
Haojun Liao 已提交
1205

1206
    pCtx->pTsOutput = NULL;
L
Liu Jicong 已提交
1207
    pCtx->resDataInfo.bytes = pFunct->resSchema.bytes;
1208
    pCtx->resDataInfo.type = pFunct->resSchema.type;
L
Liu Jicong 已提交
1209
    pCtx->order = TSDB_ORDER_ASC;
1210
    pCtx->start.key = INT64_MIN;
L
Liu Jicong 已提交
1211
    pCtx->end.key = INT64_MIN;
1212
    pCtx->numOfParams = pExpr->base.numOfParams;
H
Haojun Liao 已提交
1213

1214
    pCtx->param = pFunct->pParam;
dengyihao's avatar
dengyihao 已提交
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
    //    for (int32_t j = 0; j < pCtx->numOfParams; ++j) {
    //      // set the order information for top/bottom query
    //      int32_t functionId = pCtx->functionId;
    //      if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_DIFF) {
    //        int32_t f = getExprFunctionId(&pExpr[0]);
    //        assert(f == FUNCTION_TS || f == FUNCTION_TS_DUMMY);
    //
    //        //      pCtx->param[2].i = pQueryAttr->order.order;
    //        //      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
    //        //      pCtx->param[3].i = functionId;
    //        //      pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT;
    //
    //        //      pCtx->param[1].i = pQueryAttr->order.col.info.colId;
    //      } else if (functionId == FUNCTION_INTERP) {
    //        //      pCtx->param[2].i = (int8_t)pQueryAttr->fillType;
    //        //      if (pQueryAttr->fillVal != NULL) {
    //        //        if (isNull((const char *)&pQueryAttr->fillVal[i], pCtx->inputType)) {
    //        //          pCtx->param[1].nType = TSDB_DATA_TYPE_NULL;
    //        //        } else {  // todo refactor, taosVariantCreateFromBinary should handle the NULL value
    //        //          if (pCtx->inputType != TSDB_DATA_TYPE_BINARY && pCtx->inputType != TSDB_DATA_TYPE_NCHAR) {
    //        //            taosVariantCreateFromBinary(&pCtx->param[1], (char *)&pQueryAttr->fillVal[i],
    //        pCtx->inputBytes, pCtx->inputType);
    //        //          }
    //        //        }
    //        //      }
    //      } else if (functionId == FUNCTION_TWA) {
    //        //      pCtx->param[1].i = pQueryAttr->window.skey;
    //        //      pCtx->param[1].nType = TSDB_DATA_TYPE_BIGINT;
    //        //      pCtx->param[2].i = pQueryAttr->window.ekey;
    //        //      pCtx->param[2].nType = TSDB_DATA_TYPE_BIGINT;
    //      } else if (functionId == FUNCTION_ARITHM) {
    //        //      pCtx->param[1].pz = (char*) getScalarFuncSupport(pRuntimeEnv->scalarSup, i);
    //      }
    //    }
H
Haojun Liao 已提交
1249 1250
  }

L
Liu Jicong 已提交
1251 1252 1253
  for (int32_t i = 1; i < numOfOutput; ++i) {
    (*rowCellInfoOffset)[i] =
        (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pFuncCtx[i - 1].resDataInfo.interBufSize);
H
Haojun Liao 已提交
1254
  }
H
Haojun Liao 已提交
1255

1256
  setSelectValueColumnInfo(pFuncCtx, numOfOutput);
H
Haojun Liao 已提交
1257 1258 1259
  return pFuncCtx;
}

1260
static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1261 1262 1263 1264 1265 1266
  if (pCtx == NULL) {
    return NULL;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) {
1267
      taosVariantDestroy(&pCtx[i].param[j].param);
1268 1269 1270
    }

    taosVariantDestroy(&pCtx[i].tag);
1271
    taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx);
H
Haojun Liao 已提交
1272 1273
    taosMemoryFree(pCtx[i].input.pData);
    taosMemoryFree(pCtx[i].input.pColumnDataAgg);
1274 1275
  }

wafwerar's avatar
wafwerar 已提交
1276
  taosMemoryFreeClear(pCtx);
1277 1278 1279
  return NULL;
}

L
Liu Jicong 已提交
1280
bool isTaskKilled(SExecTaskInfo* pTaskInfo) {
1281 1282
  // query has been executed more than tsShellActivityTimer, and the retrieve has not arrived
  // abort current query execution.
L
Liu Jicong 已提交
1283 1284
  if (pTaskInfo->owner != 0 &&
      ((taosGetTimestampSec() - pTaskInfo->cost.start / 1000) > 10 * getMaximumIdleDurationSec())
1285 1286
      /*(!needBuildResAfterQueryComplete(pTaskInfo))*/) {
    assert(pTaskInfo->cost.start != 0);
L
Liu Jicong 已提交
1287 1288 1289
    //    qDebug("QInfo:%" PRIu64 " retrieve not arrive beyond %d ms, abort current query execution, start:%" PRId64
    //           ", current:%d", pQInfo->qId, 1, pQInfo->startExecTs, taosGetTimestampSec());
    //    return true;
1290 1291 1292 1293 1294
  }

  return false;
}

L
Liu Jicong 已提交
1295
void setTaskKilled(SExecTaskInfo* pTaskInfo) { pTaskInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED; }
1296

L
Liu Jicong 已提交
1297
static bool isCachedLastQuery(STaskAttr* pQueryAttr) {
1298 1299 1300 1301 1302 1303 1304 1305 1306
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
    int32_t functionId = getExprFunctionId(&pQueryAttr->pExpr1[i]);
    if (functionId == FUNCTION_LAST || functionId == FUNCTION_LAST_DST) {
      continue;
    }

    return false;
  }

1307 1308
  int32_t order = TSDB_ORDER_ASC;
  if (order != TSDB_ORDER_DESC || !TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_DESC_INITIALIZER)) {
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
    return false;
  }

  if (pQueryAttr->groupbyColumn) {
    return false;
  }

  if (pQueryAttr->interval.interval > 0) {
    return false;
  }

  if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->havingNum > 0) {
    return false;
  }

  return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////
L
Liu Jicong 已提交
1328
// todo refactor : return window
1329
void getAlignQueryTimeWindow(SInterval* pInterval, int32_t precision, int64_t key, STimeWindow* win) {
H
Haojun Liao 已提交
1330
  win->skey = taosTimeTruncate(key, pInterval, precision);
1331 1332

  /*
H
Haojun Liao 已提交
1333
   * if the realSkey > INT64_MAX - pInterval->interval, the query duration between
1334 1335
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
1336 1337
  win->ekey = taosTimeAdd(win->skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
  if (win->ekey < win->skey) {
1338 1339 1340 1341
    win->ekey = INT64_MAX;
  }
}

L
Liu Jicong 已提交
1342
static int32_t updateBlockLoadStatus(STaskAttr* pQuery, int32_t status) {
1343 1344 1345
  bool hasFirstLastFunc = false;
  bool hasOtherFunc = false;

1346
  if (status == BLK_DATA_DATA_LOAD || status == BLK_DATA_FILTEROUT) {
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364
    return status;
  }

  for (int32_t i = 0; i < pQuery->numOfOutput; ++i) {
    int32_t functionId = getExprFunctionId(&pQuery->pExpr1[i]);

    if (functionId == FUNCTION_TS || functionId == FUNCTION_TS_DUMMY || functionId == FUNCTION_TAG ||
        functionId == FUNCTION_TAG_DUMMY) {
      continue;
    }

    if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_LAST_DST) {
      hasFirstLastFunc = true;
    } else {
      hasOtherFunc = true;
    }
  }

1365
  if (hasFirstLastFunc && status == BLK_DATA_NOT_LOAD) {
L
Liu Jicong 已提交
1366
    if (!hasOtherFunc) {
1367
      return BLK_DATA_FILTEROUT;
1368
    } else {
1369
      return BLK_DATA_DATA_LOAD;
1370 1371 1372 1373 1374 1375
    }
  }

  return status;
}

L
Liu Jicong 已提交
1376 1377
// static void updateDataCheckOrder(SQInfo *pQInfo, SQueryTableReq* pQueryMsg, bool stableQuery) {
//   STaskAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
1378
//
L
Liu Jicong 已提交
1379 1380 1381 1382
//   // in case of point-interpolation query, use asc order scan
//   char msg[] = "QInfo:0x%"PRIx64" scan order changed for %s query, old:%d, new:%d, qrange exchanged, old qrange:%"
//   PRId64
//                "-%" PRId64 ", new qrange:%" PRId64 "-%" PRId64;
H
Haojun Liao 已提交
1383
//
L
Liu Jicong 已提交
1384 1385 1386 1387 1388
//   // todo handle the case the the order irrelevant query type mixed up with order critical query type
//   // descending order query for last_row query
//   if (isFirstLastRowQuery(pQueryAttr)) {
//     //qDebug("QInfo:0x%"PRIx64" scan order changed for last_row query, old:%d, new:%d", pQInfo->qId,
//     pQueryAttr->order.order, TSDB_ORDER_ASC);
H
Haojun Liao 已提交
1389
//
L
Liu Jicong 已提交
1390 1391
//     pQueryAttr->order.order = TSDB_ORDER_ASC;
//     if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
wafwerar's avatar
wafwerar 已提交
1392
//       TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
L
Liu Jicong 已提交
1393
//     }
H
Haojun Liao 已提交
1394
//
L
Liu Jicong 已提交
1395 1396 1397
//     pQueryAttr->needReverseScan = false;
//     return;
//   }
H
Haojun Liao 已提交
1398
//
L
Liu Jicong 已提交
1399 1400 1401
//   if (pQueryAttr->groupbyColumn && pQueryAttr->order.order == TSDB_ORDER_DESC) {
//     pQueryAttr->order.order = TSDB_ORDER_ASC;
//     if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
wafwerar's avatar
wafwerar 已提交
1402
//       TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
L
Liu Jicong 已提交
1403
//     }
H
Haojun Liao 已提交
1404
//
L
Liu Jicong 已提交
1405 1406 1407 1408
//     pQueryAttr->needReverseScan = false;
//     doUpdateLastKey(pQueryAttr);
//     return;
//   }
H
Haojun Liao 已提交
1409
//
L
Liu Jicong 已提交
1410 1411 1412 1413 1414 1415
//   if (pQueryAttr->pointInterpQuery && pQueryAttr->interval.interval == 0) {
//     if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
//       //qDebug(msg, pQInfo->qId, "interp", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey,
//       pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey); TSWAP(pQueryAttr->window.skey,
//       pQueryAttr->window.ekey, TSKEY);
//     }
H
Haojun Liao 已提交
1416
//
L
Liu Jicong 已提交
1417 1418 1419
//     pQueryAttr->order.order = TSDB_ORDER_ASC;
//     return;
//   }
H
Haojun Liao 已提交
1420
//
L
Liu Jicong 已提交
1421 1422 1423 1424
//   if (pQueryAttr->interval.interval == 0) {
//     if (onlyFirstQuery(pQueryAttr)) {
//       if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
//         //qDebug(msg, pQInfo->qId, "only-first", pQueryAttr->order.order, TSDB_ORDER_ASC, pQueryAttr->window.skey,
H
Haojun Liao 已提交
1425 1426
////               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
//
wafwerar's avatar
wafwerar 已提交
1427
//        TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
//        doUpdateLastKey(pQueryAttr);
//      }
//
//      pQueryAttr->order.order = TSDB_ORDER_ASC;
//      pQueryAttr->needReverseScan = false;
//    } else if (onlyLastQuery(pQueryAttr) && notContainSessionOrStateWindow(pQueryAttr)) {
//      if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//        //qDebug(msg, pQInfo->qId, "only-last", pQueryAttr->order.order, TSDB_ORDER_DESC, pQueryAttr->window.skey,
////               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
//
wafwerar's avatar
wafwerar 已提交
1438
//        TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
//        doUpdateLastKey(pQueryAttr);
//      }
//
//      pQueryAttr->order.order = TSDB_ORDER_DESC;
//      pQueryAttr->needReverseScan = false;
//    }
//
//  } else {  // interval query
//    if (stableQuery) {
//      if (onlyFirstQuery(pQueryAttr)) {
//        if (!QUERY_IS_ASC_QUERY(pQueryAttr)) {
//          //qDebug(msg, pQInfo->qId, "only-first stable", pQueryAttr->order.order, TSDB_ORDER_ASC,
L
Liu Jicong 已提交
1451 1452
////                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey,
/// pQueryAttr->window.skey);
H
Haojun Liao 已提交
1453
//
wafwerar's avatar
wafwerar 已提交
1454
//          TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1455 1456 1457 1458 1459 1460 1461 1462
//          doUpdateLastKey(pQueryAttr);
//        }
//
//        pQueryAttr->order.order = TSDB_ORDER_ASC;
//        pQueryAttr->needReverseScan = false;
//      } else if (onlyLastQuery(pQueryAttr)) {
//        if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//          //qDebug(msg, pQInfo->qId, "only-last stable", pQueryAttr->order.order, TSDB_ORDER_DESC,
L
Liu Jicong 已提交
1463 1464
////                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey,
/// pQueryAttr->window.skey);
H
Haojun Liao 已提交
1465
//
wafwerar's avatar
wafwerar 已提交
1466
//          TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1467 1468 1469 1470 1471 1472 1473 1474 1475
//          doUpdateLastKey(pQueryAttr);
//        }
//
//        pQueryAttr->order.order = TSDB_ORDER_DESC;
//        pQueryAttr->needReverseScan = false;
//      }
//    }
//  }
//}
1476

H
Haojun Liao 已提交
1477 1478
static void getIntermediateBufInfo(STaskRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
L
Liu Jicong 已提交
1479
  int32_t    MIN_ROWS_PER_PAGE = 4;
1480

L
Liu Jicong 已提交
1481 1482
  *rowsize = (int32_t)(pQueryAttr->resultRowSize *
                       getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
1483 1484 1485 1486
  int32_t overhead = sizeof(SFilePage);

  // one page contains at least two rows
  *ps = DEFAULT_INTERN_BUF_PAGE_SIZE;
L
Liu Jicong 已提交
1487
  while (((*rowsize) * MIN_ROWS_PER_PAGE) > (*ps) - overhead) {
1488 1489 1490 1491
    *ps = ((*ps) << 1u);
  }
}

L
Liu Jicong 已提交
1492 1493 1494
// static FORCE_INLINE bool doFilterByBlockStatistics(STaskRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis,
// SqlFunctionCtx *pCtx, int32_t numOfRows) {
//   STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
1495
//
L
Liu Jicong 已提交
1496 1497 1498
//   if (pDataStatis == NULL || pQueryAttr->pFilters == NULL) {
//     return true;
//   }
1499
//
L
Liu Jicong 已提交
1500 1501
//   return filterRangeExecute(pQueryAttr->pFilters, pDataStatis, pQueryAttr->numOfCols, numOfRows);
// }
1502

H
Haojun Liao 已提交
1503
static bool overlapWithTimeWindow(STaskAttr* pQueryAttr, SDataBlockInfo* pBlockInfo) {
1504 1505
  STimeWindow w = {0};

dengyihao's avatar
dengyihao 已提交
1506 1507
  TSKEY sk = TMIN(pQueryAttr->window.skey, pQueryAttr->window.ekey);
  TSKEY ek = TMAX(pQueryAttr->window.skey, pQueryAttr->window.ekey);
1508

1509
  if (true) {
L
Liu Jicong 已提交
1510
    //    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.skey, sk, ek, &w);
1511 1512 1513 1514 1515 1516
    assert(w.ekey >= pBlockInfo->window.skey);

    if (w.ekey < pBlockInfo->window.ekey) {
      return true;
    }

L
Liu Jicong 已提交
1517 1518
    while (1) {
      //      getNextTimeWindow(pQueryAttr, &w);
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528
      if (w.skey > pBlockInfo->window.ekey) {
        break;
      }

      assert(w.ekey > pBlockInfo->window.ekey);
      if (w.skey <= pBlockInfo->window.ekey && w.skey > pBlockInfo->window.skey) {
        return true;
      }
    }
  } else {
L
Liu Jicong 已提交
1529
    //    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.ekey, sk, ek, &w);
1530 1531 1532 1533 1534 1535
    assert(w.skey <= pBlockInfo->window.ekey);

    if (w.skey > pBlockInfo->window.skey) {
      return true;
    }

L
Liu Jicong 已提交
1536 1537
    while (1) {
      //      getNextTimeWindow(pQueryAttr, &w);
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601
      if (w.ekey < pBlockInfo->window.skey) {
        break;
      }

      assert(w.skey < pBlockInfo->window.skey);
      if (w.ekey < pBlockInfo->window.ekey && w.ekey >= pBlockInfo->window.skey) {
        return true;
      }
    }
  }

  return false;
}

void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p) {
  int32_t len = 0;
  int32_t start = 0;
  for (int32_t j = 0; j < numOfRows; ++j) {
    if (p[j] == 1) {
      len++;
    } else {
      if (len > 0) {
        int32_t cstart = j - len;
        for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
          SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i);

          int16_t bytes = pColumnInfoData->info.bytes;
          memmove(((char*)pColumnInfoData->pData) + start * bytes, pColumnInfoData->pData + cstart * bytes,
                  len * bytes);
        }

        start += len;
        len = 0;
      }
    }
  }

  if (len > 0) {
    int32_t cstart = numOfRows - len;
    for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
      SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, i);

      int16_t bytes = pColumnInfoData->info.bytes;
      memmove(pColumnInfoData->pData + start * bytes, pColumnInfoData->pData + cstart * bytes, len * bytes);
    }

    start += len;
    len = 0;
  }

  pBlock->info.rows = start;
  pBlock->pBlockAgg = NULL;  // clean the block statistics info

  if (start > 0) {
    SColumnInfoData* pColumnInfoData = taosArrayGet(pBlock->pDataBlock, 0);
    if (pColumnInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP &&
        pColumnInfoData->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
      pBlock->info.window.skey = *(int64_t*)pColumnInfoData->pData;
      pBlock->info.window.ekey = *(int64_t*)(pColumnInfoData->pData + TSDB_KEYSIZE * (start - 1));
    }
  }
}

static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
1602
  SqlFunctionCtx* pCtx = pTableScanInfo->pCtx;
1603
  uint32_t        status = BLK_DATA_NOT_LOAD;
1604 1605 1606 1607

  int32_t numOfOutput = pTableScanInfo->numOfOutput;
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
1608
    int32_t colId = pTableScanInfo->pExpr[i].base.pParam[0].pCol->colId;
1609 1610 1611

    // group by + first/last should not apply the first/last block filter
    if (functionId < 0) {
1612
      status |= BLK_DATA_DATA_LOAD;
1613 1614
      return status;
    } else {
L
Liu Jicong 已提交
1615
      //      status |= aAggs[functionId].dataReqFunc(&pTableScanInfo->pCtx[i], &pBlock->info.window, colId);
1616
      //      if ((status & BLK_DATA_DATA_LOAD) == BLK_DATA_DATA_LOAD) {
L
Liu Jicong 已提交
1617 1618
      //        return status;
      //      }
1619 1620 1621 1622 1623 1624
    }
  }

  return status;
}

L
Liu Jicong 已提交
1625 1626
int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
1627
  *status = BLK_DATA_NOT_LOAD;
1628

H
Haojun Liao 已提交
1629
  pBlock->pDataBlock = NULL;
L
Liu Jicong 已提交
1630
  pBlock->pBlockAgg = NULL;
H
Haojun Liao 已提交
1631

L
Liu Jicong 已提交
1632 1633
  //  int64_t groupId = pRuntimeEnv->current->groupIndex;
  //  bool    ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
1634

H
Haojun Liao 已提交
1635
  STaskCostInfo* pCost = &pTaskInfo->cost;
1636

1637 1638
//  pCost->totalBlocks += 1;
//  pCost->totalRows += pBlock->info.rows;
H
Haojun Liao 已提交
1639
#if 0
1640 1641 1642
  // Calculate all time windows that are overlapping or contain current data block.
  // If current data block is contained by all possible time window, do not load current data block.
  if (/*pQueryAttr->pFilters || */pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 ||
H
Haojun Liao 已提交
1643
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pTaskInfo, &pBlock->info))) {
1644
    (*status) = BLK_DATA_DATA_LOAD;
1645 1646 1647
  }

  // check if this data block is required to load
1648
  if ((*status) != BLK_DATA_DATA_LOAD) {
1649 1650 1651 1652 1653 1654 1655
    bool needFilter = true;

    // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet,
    // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer
    if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
      SResultRow* pResult = NULL;

H
Haojun Liao 已提交
1656
      bool  masterScan = IS_MAIN_SCAN(pRuntimeEnv);
1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
      TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey;

      STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
      if (pQueryAttr->pointInterpQuery) {
        needFilter = chkWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId,
                                    pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                    pTableScanInfo->rowCellInfoOffset);
      } else {
        if (setResultOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pBlock->info.uid, &win, masterScan, &pResult, groupId,
                                    pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                    pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
          longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
        }
      }
    } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery) && (!pQueryAttr->diffQuery)) { // stable aggregate, not interval aggregate or normal column aggregate
      doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx,
                               pTableScanInfo->rowCellInfoOffset, pTableScanInfo->numOfOutput,
                               pRuntimeEnv->current->groupIndex);
    }

    if (needFilter) {
      (*status) = doFilterByBlockTimeWindow(pTableScanInfo, pBlock);
    } else {
1680
      (*status) = BLK_DATA_DATA_LOAD;
1681 1682 1683 1684
    }
  }

  SDataBlockInfo* pBlockInfo = &pBlock->info;
H
Haojun Liao 已提交
1685
//  *status = updateBlockLoadStatus(pRuntimeEnv->pQueryAttr, *status);
1686

1687
  if ((*status) == BLK_DATA_NOT_LOAD || (*status) == BLK_DATA_FILTEROUT) {
1688 1689
    //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
//           pBlockInfo->window.ekey, pBlockInfo->rows);
1690
    pCost->skipBlocks += 1;
1691
  } else if ((*status) == BLK_DATA_SMA_LOAD) {
1692 1693
    // this function never returns error?
    pCost->loadBlockStatis += 1;
1694
//    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
1695 1696

    if (pBlock->pBlockAgg == NULL) {  // data block statistics does not exist, load data block
1697
//      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL);
1698 1699 1700
      pCost->totalCheckedRows += pBlock->info.rows;
    }
  } else {
1701
    assert((*status) == BLK_DATA_DATA_LOAD);
1702 1703 1704

    // load the data block statistics to perform further filter
    pCost->loadBlockStatis += 1;
1705
//    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
1706 1707 1708 1709 1710 1711

    if (pQueryAttr->topBotQuery && pBlock->pBlockAgg != NULL) {
      { // set previous window
        if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
          SResultRow* pResult = NULL;

H
Haojun Liao 已提交
1712
          bool  masterScan = IS_MAIN_SCAN(pRuntimeEnv);
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
          TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey;

          STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr);
          if (setResultOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pBlock->info.uid, &win, masterScan, &pResult, groupId,
                                      pTableScanInfo->pCtx, pTableScanInfo->numOfOutput,
                                      pTableScanInfo->rowCellInfoOffset) != TSDB_CODE_SUCCESS) {
            longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
          }
        }
      }
      bool load = false;
      for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
        int32_t functionId = pTableScanInfo->pCtx[i].functionId;
        if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) {
//          load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockAgg[i].min),
//                                         (char*)&(pBlock->pBlockAgg[i].max));
          if (!load) { // current block has been discard due to filter applied
1730
            pCost->skipBlocks += 1;
1731 1732
            //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
//                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
1733
            (*status) = BLK_DATA_FILTEROUT;
1734 1735 1736 1737 1738 1739 1740 1741
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
//    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockAgg, pTableScanInfo->pCtx, pBlockInfo->rows)) {
1742
//      pCost->skipBlocks += 1;
1743 1744
//      qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
//             pBlockInfo->window.ekey, pBlockInfo->rows);
1745
//      (*status) = BLK_DATA_FILTEROUT;
1746 1747 1748 1749 1750
//      return TSDB_CODE_SUCCESS;
//    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
1751
//    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL);
1752 1753 1754 1755 1756 1757 1758
//    if (pBlock->pDataBlock == NULL) {
//      return terrno;
//    }

//    if (pQueryAttr->pFilters != NULL) {
//      filterSetColFieldData(pQueryAttr->pFilters, pBlock->info.numOfCols, pBlock->pDataBlock);
//    }
1759

1760 1761 1762 1763
//    if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) {
//      filterColRowsInDataBlock(pRuntimeEnv, pBlock, ascQuery);
//    }
  }
H
Haojun Liao 已提交
1764
#endif
1765 1766 1767
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
1768
void copyToSDataBlock(SSDataBlock* pBlock, int32_t* offset, SGroupResInfo* pGroupResInfo, SDiskbasedBuf* pResBuf) {
1769 1770 1771 1772 1773 1774 1775
  pBlock->info.rows = 0;

  int32_t code = TSDB_CODE_SUCCESS;
  while (pGroupResInfo->currentGroup < pGroupResInfo->totalGroup) {
    // all results in current group have been returned to client, try next group
    if ((pGroupResInfo->pRows == NULL) || taosArrayGetSize(pGroupResInfo->pRows) == 0) {
      assert(pGroupResInfo->index == 0);
L
Liu Jicong 已提交
1776 1777 1778
      //      if ((code = mergeIntoGroupResult(&pGroupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
      return;
      //      }
1779 1780
    }

L
Liu Jicong 已提交
1781
    //    doCopyToSDataBlock(pResBuf, pGroupResInfo, TSDB_ORDER_ASC, pBlock, );
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791

    // current data are all dumped to result buffer, clear it
    if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
      cleanupGroupResInfo(pGroupResInfo);
      if (!incNextGroup(pGroupResInfo)) {
        break;
      }
    }

    // enough results in data buffer, return
L
Liu Jicong 已提交
1792 1793 1794
    //    if (pBlock->info.rows >= threshold) {
    //      break;
    //    }
1795 1796 1797
  }
}

L
Liu Jicong 已提交
1798
static void updateTableQueryInfoForReverseScan(STableQueryInfo* pTableQueryInfo) {
1799 1800 1801 1802
  if (pTableQueryInfo == NULL) {
    return;
  }

wafwerar's avatar
wafwerar 已提交
1803
  //  TSWAP(pTableQueryInfo->win.skey, pTableQueryInfo->win.ekey);
L
Liu Jicong 已提交
1804
  //  pTableQueryInfo->lastKey = pTableQueryInfo->win.skey;
1805

L
Liu Jicong 已提交
1806 1807
  //  SWITCH_ORDER(pTableQueryInfo->cur.order);
  //  pTableQueryInfo->cur.vgroupIndex = -1;
1808 1809

  // set the index to be the end slot of result rows array
dengyihao's avatar
dengyihao 已提交
1810 1811 1812 1813 1814 1815
  //  SResultRowInfo* pResultRowInfo = &pTableQueryInfo->resInfo;
  //  if (pResultRowInfo->size > 0) {
  //    pResultRowInfo->curPos = pResultRowInfo->size - 1;
  //  } else {
  //    pResultRowInfo->curPos = -1;
  //  }
1816 1817
}

H
Haojun Liao 已提交
1818
void initResultRow(SResultRow* pResultRow) {
X
Xiaoyu Wang 已提交
1819
  //  pResultRow->pEntryInfo = (struct SResultRowEntryInfo*)((char*)pResultRow + sizeof(SResultRow));
1820 1821 1822 1823 1824
}

/*
 * The start of each column SResultRowEntryInfo is denote by RowCellInfoOffset.
 * Note that in case of top/bottom query, the whole multiple rows of result is treated as only one row of results.
H
Haojun Liao 已提交
1825 1826 1827
 * +------------+-----------------result column 1------------+------------------result column 2-----------+
 * | SResultRow | SResultRowEntryInfo | intermediate buffer1 | SResultRowEntryInfo | intermediate buffer 2|
 * +------------+--------------------------------------------+--------------------------------------------+
1828 1829
 *           offset[0]                                  offset[1]                                   offset[2]
 */
1830
// TODO refactor: some function move away
X
Xiaoyu Wang 已提交
1831 1832
void setFunctionResultOutput(SOptrBasicInfo* pInfo, SAggSupporter* pSup, int32_t stage, int32_t numOfExprs,
                             SExecTaskInfo* pTaskInfo) {
L
Liu Jicong 已提交
1833 1834 1835
  SqlFunctionCtx* pCtx = pInfo->pCtx;
  SSDataBlock*    pDataBlock = pInfo->pRes;
  int32_t*        rowCellInfoOffset = pInfo->rowCellInfoOffset;
H
Haojun Liao 已提交
1836

H
Haojun Liao 已提交
1837
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
1838
  initResultRowInfo(pResultRowInfo, 16);
H
Haojun Liao 已提交
1839

L
Liu Jicong 已提交
1840 1841
  int64_t     tid = 0;
  int64_t     groupId = 0;
1842 1843
  SResultRow* pRow = doSetResultOutBufByKey(pSup->pResultBuf, pResultRowInfo, (char*)&tid, sizeof(tid), true, groupId,
                                            pTaskInfo, false, pSup);
H
Haojun Liao 已提交
1844

H
Haojun Liao 已提交
1845
  ASSERT(pDataBlock->info.numOfCols == numOfExprs);
H
Haojun Liao 已提交
1846 1847 1848 1849
  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
    struct SResultRowEntryInfo* pEntry = getResultCell(pRow, i, rowCellInfoOffset);
    cleanupResultRowEntry(pEntry);

L
Liu Jicong 已提交
1850
    pCtx[i].resultInfo = pEntry;
1851
    pCtx[i].scanFlag = stage;
H
Haojun Liao 已提交
1852 1853

    // set the timestamp output buffer for top/bottom/diff query
L
Liu Jicong 已提交
1854 1855
    //    int32_t fid = pCtx[i].functionId;
    //    if (fid == FUNCTION_TOP || fid == FUNCTION_BOTTOM || fid == FUNCTION_DIFF || fid == FUNCTION_DERIVATIVE) {
H
Haojun Liao 已提交
1856
    //      if (i > 0) pCtx[i].pTsOutput = pCtx[i-1].pOutput;
L
Liu Jicong 已提交
1857
    //    }
H
Haojun Liao 已提交
1858 1859 1860 1861 1862
  }

  initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
}

L
Liu Jicong 已提交
1863
void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t* bufCapacity, int32_t numOfInputRows) {
1864 1865
  SSDataBlock* pDataBlock = pBInfo->pRes;

L
Liu Jicong 已提交
1866
  int32_t newSize = pDataBlock->info.rows + numOfInputRows + 5;  // extra output buffer
1867
  if ((*bufCapacity) < newSize) {
L
Liu Jicong 已提交
1868 1869
    for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
1870

wafwerar's avatar
wafwerar 已提交
1871
      char* p = taosMemoryRealloc(pColInfo->pData, newSize * pColInfo->info.bytes);
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
      if (p != NULL) {
        pColInfo->pData = p;

        // it starts from the tail of the previously generated results.
        pBInfo->pCtx[i].pOutput = pColInfo->pData;
        (*bufCapacity) = newSize;
      } else {
        // longjmp
      }
    }
  }

  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
L
Liu Jicong 已提交
1885
    SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
1886 1887 1888 1889 1890
    pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows;

    // set the correct pointer after the memory buffer reallocated.
    int32_t functionId = pBInfo->pCtx[i].functionId;

L
Liu Jicong 已提交
1891 1892
    if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_DIFF ||
        functionId == FUNCTION_DERIVATIVE) {
dengyihao's avatar
dengyihao 已提交
1893
      //      if (i > 0) pBInfo->pCtx[i].pTsOutput = pBInfo->pCtx[i - 1].pOutput;
1894 1895 1896 1897
    }
  }
}

H
Haojun Liao 已提交
1898
void copyTsColoum(SSDataBlock* pRes, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1899 1900
  bool    needCopyTs = false;
  int32_t tsNum = 0;
L
Liu Jicong 已提交
1901
  char*   src = NULL;
1902 1903 1904 1905
  for (int32_t i = 0; i < numOfOutput; i++) {
    int32_t functionId = pCtx[i].functionId;
    if (functionId == FUNCTION_DIFF || functionId == FUNCTION_DERIVATIVE) {
      needCopyTs = true;
L
Liu Jicong 已提交
1906 1907
      if (i > 0 && pCtx[i - 1].functionId == FUNCTION_TS_DUMMY) {
        SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i - 1);  // find ts data
1908 1909
        src = pColRes->pData;
      }
L
Liu Jicong 已提交
1910
    } else if (functionId == FUNCTION_TS_DUMMY) {
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920
      tsNum++;
    }
  }

  if (!needCopyTs) return;
  if (tsNum < 2) return;
  if (src == NULL) return;

  for (int32_t i = 0; i < numOfOutput; i++) {
    int32_t functionId = pCtx[i].functionId;
L
Liu Jicong 已提交
1921
    if (functionId == FUNCTION_TS_DUMMY) {
1922 1923 1924 1925 1926 1927
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i);
      memcpy(pColRes->pData, src, pColRes->info.bytes * pRes->info.rows);
    }
  }
}

H
Haojun Liao 已提交
1928
void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size) {
1929 1930
  for (int32_t j = 0; j < size; ++j) {
    struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
dengyihao's avatar
dengyihao 已提交
1931 1932
    if (isRowEntryInitialized(pResInfo) || fmIsPseudoColumnFunc(pCtx[j].functionId) || pCtx[j].functionId == -1 ||
        fmIsScalarFunc(pCtx[j].functionId)) {
1933 1934 1935
      continue;
    }

H
Haojun Liao 已提交
1936
    pCtx[j].fpSet.init(&pCtx[j], pCtx[j].resultInfo);
1937 1938 1939
  }
}

L
Liu Jicong 已提交
1940
void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status) {
1941
  if (status == TASK_NOT_COMPLETED) {
H
Haojun Liao 已提交
1942
    pTaskInfo->status = status;
1943 1944
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
1945
    CLEAR_QUERY_STATUS(pTaskInfo, TASK_NOT_COMPLETED);
H
Haojun Liao 已提交
1946
    pTaskInfo->status |= status;
1947 1948 1949
  }
}

1950
// todo merged with the build group result.
1951 1952
void finalizeMultiTupleQueryResult(int32_t numOfOutput, SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo,
                                   int32_t* rowCellInfoOffset) {
1953 1954 1955
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRowPosition* pPos = &pResultRowInfo->pPosition[i];

L
Liu Jicong 已提交
1956
    SFilePage*  bufPage = getBufPage(pBuf, pPos->pageId);
1957
    SResultRow* pRow = (SResultRow*)((char*)bufPage + pPos->offset);
H
Haojun Liao 已提交
1958 1959

    // TODO ignore the close status anyway.
dengyihao's avatar
dengyihao 已提交
1960 1961 1962
    //    if (!isResultRowClosed(pRow)) {
    //      continue;
    //    }
1963

1964
    for (int32_t j = 0; j < numOfOutput; ++j) {
1965
      struct SResultRowEntryInfo* pResInfo = getResultCell(pRow, j, rowCellInfoOffset);
H
Haojun Liao 已提交
1966
      if (!isRowEntryInitialized(pResInfo)) {
1967 1968 1969 1970 1971 1972
        continue;
      }

      if (pRow->numOfRows < pResInfo->numOfRes) {
        pRow->numOfRows = pResInfo->numOfRes;
      }
1973
    }
1974 1975 1976

    releaseBufPage(pBuf, bufPage);
  }
1977 1978
}

1979
STableQueryInfo* createTableQueryInfo(void* buf, STimeWindow win) {
L
Liu Jicong 已提交
1980
  STableQueryInfo* pTableQueryInfo = buf;
1981 1982 1983 1984
  pTableQueryInfo->lastKey = win.skey;
  return pTableQueryInfo;
}

L
Liu Jicong 已提交
1985
void destroyTableQueryInfoImpl(STableQueryInfo* pTableQueryInfo) {
1986 1987 1988 1989
  if (pTableQueryInfo == NULL) {
    return;
  }

L
Liu Jicong 已提交
1990
  //  taosVariantDestroy(&pTableQueryInfo->tag);
dengyihao's avatar
dengyihao 已提交
1991
  //  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
1992 1993
}

1994
void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset) {
1995 1996 1997 1998 1999 2000 2001
  for (int32_t i = 0; i < numOfOutput; ++i) {
    pCtx[i].resultInfo = getResultCell(pResult, i, rowCellInfoOffset);

    struct SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo;
    if (isRowEntryCompleted(pResInfo) && isRowEntryInitialized(pResInfo)) {
      continue;
    }
2002 2003 2004 2005 2006

    if (fmIsWindowPseudoColumnFunc(pCtx[i].functionId)) {
      continue;
    }

2007 2008 2009 2010 2011 2012
    if (!pResInfo->initialized) {
      if (pCtx[i].functionId != -1) {
        pCtx[i].fpSet.init(&pCtx[i], pResInfo);
      } else {
        pResInfo->initialized = true;
      }
2013 2014 2015 2016
    }
  }
}

2017
static void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowRes, bool keep);
2018
void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock, SArray* pColMatchInfo) {
2019 2020 2021 2022 2023
  if (pFilterNode == NULL) {
    return;
  }

  SFilterInfo* filter = NULL;
H
Haojun Liao 已提交
2024

H
Haojun Liao 已提交
2025
  // todo move to the initialization function
H
Haojun Liao 已提交
2026
  int32_t code = filterInitFromNode((SNode*)pFilterNode, &filter, 0);
2027 2028 2029 2030 2031

  SFilterColumnParam param1 = {.numOfCols = pBlock->info.numOfCols, .pDataBlock = pBlock->pDataBlock};
  code = filterSetDataFromSlotId(filter, &param1);

  int8_t* rowRes = NULL;
2032

2033
  // todo the keep seems never to be True??
2034
  bool keep = filterExecute(filter, pBlock, &rowRes, NULL, param1.numOfCols);
D
dapan1121 已提交
2035
  filterFreeInfo(filter);
2036

2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049
  extractQualifiedTupleByFilterResult(pBlock, rowRes, keep);
  blockDataUpdateTsWindow(pBlock);
}

void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const int8_t* rowRes, bool keep) {
  if (keep) {
    return;
  }

  if (rowRes != NULL) {
    SSDataBlock* px = createOneDataBlock(pBlock, false);
    blockDataEnsureCapacity(px, pBlock->info.rows);

2050 2051
    int32_t totalRows = pBlock->info.rows;

2052 2053 2054 2055
    for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
      SColumnInfoData* pDst = taosArrayGet(px->pDataBlock, i);
      SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, i);

2056 2057 2058 2059 2060
      // it is a reserved column for scalar function, and no data in this column yet.
      if (pSrc->pData == NULL) {
        continue;
      }

2061
      int32_t numOfRows = 0;
2062
      for (int32_t j = 0; j < totalRows; ++j) {
D
dapan1121 已提交
2063 2064 2065
        if (rowRes[j] == 0) {
          continue;
        }
2066

D
dapan1121 已提交
2067
        if (colDataIsNull_s(pSrc, j)) {
2068
          colDataAppendNULL(pDst, numOfRows);
D
dapan1121 已提交
2069
        } else {
2070
          colDataAppend(pDst, numOfRows, colDataGetData(pSrc, j), false);
D
dapan1121 已提交
2071
        }
2072
        numOfRows += 1;
H
Haojun Liao 已提交
2073
      }
2074

2075 2076 2077 2078 2079 2080
      if (pBlock->info.rows == totalRows) {
        pBlock->info.rows = numOfRows;
      } else {
        ASSERT(pBlock->info.rows == numOfRows);
      }

2081 2082 2083 2084 2085
      *pSrc = *pDst;
    }
  } else {
    // do nothing
    pBlock->info.rows = 0;
2086 2087 2088
  }
}

dengyihao's avatar
dengyihao 已提交
2089 2090
void doSetTableGroupOutputBuf(SAggOperatorInfo* pAggInfo, int32_t numOfOutput, uint64_t groupId,
                              SExecTaskInfo* pTaskInfo) {
2091 2092 2093
  // for simple group by query without interval, all the tables belong to one group result.
  int64_t uid = 0;

2094 2095
  SResultRowInfo* pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
  SqlFunctionCtx* pCtx = pAggInfo->binfo.pCtx;
L
Liu Jicong 已提交
2096
  int32_t*        rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
2097

2098
  SResultRow* pResultRow = doSetResultOutBufByKey(pAggInfo->aggSup.pResultBuf, pResultRowInfo, (char*)&groupId,
L
Liu Jicong 已提交
2099
                                                  sizeof(groupId), true, groupId, pTaskInfo, false, &pAggInfo->aggSup);
L
Liu Jicong 已提交
2100
  assert(pResultRow != NULL);
2101 2102 2103 2104 2105 2106

  /*
   * not assign result buffer yet, add new result buffer
   * all group belong to one result set, and each group result has different group id so set the id to be one
   */
  if (pResultRow->pageId == -1) {
dengyihao's avatar
dengyihao 已提交
2107 2108
    int32_t ret =
        addNewWindowResultBuf(pResultRow, pAggInfo->aggSup.pResultBuf, groupId, pAggInfo->binfo.pRes->info.rowSize);
2109 2110 2111 2112 2113
    if (ret != TSDB_CODE_SUCCESS) {
      return;
    }
  }

2114
  setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
2115 2116
}

H
Haojun Liao 已提交
2117 2118
void setExecutionContext(int32_t numOfOutput, uint64_t groupId, SExecTaskInfo* pTaskInfo, SAggOperatorInfo* pAggInfo) {
  if (pAggInfo->groupId != INT32_MIN && pAggInfo->groupId == groupId) {
2119 2120 2121
    return;
  }

H
Haojun Liao 已提交
2122
  doSetTableGroupOutputBuf(pAggInfo, numOfOutput, groupId, pTaskInfo);
2123 2124

  // record the current active group id
H
Haojun Liao 已提交
2125
  pAggInfo->groupId = groupId;
2126 2127 2128 2129 2130 2131 2132 2133 2134 2135
}

/**
 * For interval query of both super table and table, copy the data in ascending order, since the output results are
 * ordered in SWindowResutl already. While handling the group by query for both table and super table,
 * all group result are completed already.
 *
 * @param pQInfo
 * @param result
 */
2136
int32_t doCopyToSDataBlock(SExecTaskInfo* taskInfo, SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo,
2137
                           int32_t* rowCellOffset, SqlFunctionCtx* pCtx, int32_t numOfExprs) {
2138
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
2139
  int32_t start = pGroupResInfo->index;
2140

L
Liu Jicong 已提交
2141
  // qDebug("QInfo:0x%"PRIx64" start to copy data from windowResInfo to output buf", GET_TASKID(pRuntimeEnv));
2142

2143
  for (int32_t i = start; i < numOfRows; i += 1) {
L
Liu Jicong 已提交
2144 2145
    SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
    SFilePage*  page = getBufPage(pBuf, pPos->pos.pageId);
2146

2147
    SResultRow* pRow = (SResultRow*)((char*)page + pPos->pos.offset);
2148 2149 2150 2151 2152
    if (pRow->numOfRows == 0) {
      pGroupResInfo->index += 1;
      continue;
    }

2153
    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
2154 2155 2156 2157 2158
      break;
    }

    pGroupResInfo->index += 1;

2159
    for (int32_t j = 0; j < numOfExprs; ++j) {
2160 2161
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;

2162
      pCtx[j].resultInfo = getResultCell(pRow, j, rowCellOffset);
2163
      if (pCtx[j].fpSet.finalize) {
2164
        int32_t code = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
2165
        if (TAOS_FAILED(code)) {
2166 2167 2168 2169
          qError("%s build result data block error, code %s", GET_TASKID(taskInfo), tstrerror(code));
          taskInfo->code = code;
          longjmp(taskInfo->env, code);
        }
2170 2171
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
        // do nothing, todo refactor
2172
      } else {
2173 2174 2175 2176 2177 2178 2179
        // expand the result into multiple rows. E.g., _wstartts, top(k, 20)
        // the _wstartts needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
          SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
          char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
          for(int32_t k = 0; k < pRow->numOfRows; ++k) {
            colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
          }
2180
      }
2181 2182
    }

2183
    releaseBufPage(pBuf, page);
2184 2185
    pBlock->info.rows += pRow->numOfRows;
    if (pBlock->info.rows >= pBlock->info.capacity) {  // output buffer is full
2186 2187 2188 2189
      break;
    }
  }

L
Liu Jicong 已提交
2190
  // qDebug("QInfo:0x%"PRIx64" copy data to query buf completed", GET_TASKID(pRuntimeEnv));
2191
  blockDataUpdateTsWindow(pBlock);
2192 2193 2194
  return 0;
}

2195
void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, SDiskbasedBuf* pBuf) {
2196 2197
  assert(pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup);

2198 2199 2200 2201
  SExprInfo* pExprInfo = pOperator->pExpr;
  int32_t numOfExprs = pOperator->numOfExprs;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;

X
Xiaoyu Wang 已提交
2202 2203 2204
  int32_t*        rowCellOffset = pbInfo->rowCellInfoOffset;
  SSDataBlock*    pBlock = pbInfo->pRes;
  SqlFunctionCtx* pCtx = pbInfo->pCtx;
2205

2206
  blockDataCleanup(pBlock);
2207 2208 2209 2210
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
    return;
  }

2211
  doCopyToSDataBlock(pTaskInfo, pBlock, pExprInfo, pBuf, pGroupResInfo, rowCellOffset, pCtx, numOfExprs);
2212

H
Haojun Liao 已提交
2213 2214
  // add condition (pBlock->info.rows >= 1) just to runtime happy
  blockDataUpdateTsWindow(pBlock);
2215 2216
}

L
Liu Jicong 已提交
2217 2218
static void updateNumOfRowsInResultRows(SqlFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo,
                                        int32_t* rowCellInfoOffset) {
2219
  // update the number of result for each, only update the number of rows for the corresponding window result.
L
Liu Jicong 已提交
2220 2221 2222
  //  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
  //    return;
  //  }
H
Haojun Liao 已提交
2223
#if 0
2224
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
L
Liu Jicong 已提交
2225
    SResultRow* pResult = pResultRowInfo->pResult[i];
2226 2227 2228 2229 2230 2231 2232

    for (int32_t j = 0; j < numOfOutput; ++j) {
      int32_t functionId = pCtx[j].functionId;
      if (functionId == FUNCTION_TS || functionId == FUNCTION_TAG || functionId == FUNCTION_TAGPRJ) {
        continue;
      }

2233 2234
      SResultRowEntryInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
      pResult->numOfRows = (uint16_t)(TMAX(pResult->numOfRows, pCell->numOfRes));
2235 2236
    }
  }
H
Haojun Liao 已提交
2237
#endif
2238 2239
}

L
Liu Jicong 已提交
2240
static int32_t compressQueryColData(SColumnInfoData* pColRes, int32_t numOfRows, char* data, int8_t compressed) {
2241 2242
  int32_t colSize = pColRes->info.bytes * numOfRows;
  return (*(tDataTypes[pColRes->info.type].compFunc))(pColRes->pData, colSize, numOfRows, data,
L
Liu Jicong 已提交
2243
                                                      colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0);
2244 2245
}

2246
int32_t doFillTimeIntervalGapsInResults(struct SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t capacity) {
L
Liu Jicong 已提交
2247 2248 2249 2250
  //  for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
  //    SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i);
  //    p[i] = pColInfoData->pData + (pColInfoData->info.bytes * pOutput->info.rows);
  //  }
2251

2252 2253
  int32_t numOfRows = (int32_t)taosFillResultDataBlock(pFillInfo, pBlock, capacity - pBlock->info.rows);
  pBlock->info.rows += numOfRows;
2254

2255
  return pBlock->info.rows;
2256 2257
}

2258
void publishOperatorProfEvent(SOperatorInfo* pOperator, EQueryProfEventType eventType) {
2259 2260
  SQueryProfEvent event = {0};

L
Liu Jicong 已提交
2261 2262
  event.eventType = eventType;
  event.eventTime = taosGetTimestampUs();
2263
  event.operatorType = pOperator->operatorType;
dengyihao's avatar
dengyihao 已提交
2264 2265 2266
  //    if (pQInfo->summary.queryProfEvents) {
  //      taosArrayPush(pQInfo->summary.queryProfEvents, &event);
  //    }
2267 2268
}

L
Liu Jicong 已提交
2269
void publishQueryAbortEvent(SExecTaskInfo* pTaskInfo, int32_t code) {
2270 2271 2272 2273 2274
  SQueryProfEvent event;
  event.eventType = QUERY_PROF_QUERY_ABORT;
  event.eventTime = taosGetTimestampUs();
  event.abortCode = code;

2275 2276
  if (pTaskInfo->cost.queryProfEvents) {
    taosArrayPush(pTaskInfo->cost.queryProfEvents, &event);
2277 2278 2279
  }
}

L
Liu Jicong 已提交
2280
typedef struct {
2281 2282 2283 2284 2285 2286 2287
  uint8_t operatorType;
  int64_t beginTime;
  int64_t endTime;
  int64_t selfTime;
  int64_t descendantsTime;
} SOperatorStackItem;

L
Liu Jicong 已提交
2288 2289
static void doOperatorExecProfOnce(SOperatorStackItem* item, SQueryProfEvent* event, SArray* opStack,
                                   SHashObj* profResults) {
2290 2291 2292 2293 2294 2295 2296 2297
  item->endTime = event->eventTime;
  item->selfTime = (item->endTime - item->beginTime) - (item->descendantsTime);

  for (int32_t j = 0; j < taosArrayGetSize(opStack); ++j) {
    SOperatorStackItem* ancestor = taosArrayGet(opStack, j);
    ancestor->descendantsTime += item->selfTime;
  }

L
Liu Jicong 已提交
2298
  uint8_t              operatorType = item->operatorType;
2299 2300 2301 2302 2303 2304 2305 2306 2307
  SOperatorProfResult* result = taosHashGet(profResults, &operatorType, sizeof(operatorType));
  if (result != NULL) {
    result->sumRunTimes++;
    result->sumSelfTime += item->selfTime;
  } else {
    SOperatorProfResult opResult;
    opResult.operatorType = operatorType;
    opResult.sumSelfTime = item->selfTime;
    opResult.sumRunTimes = 1;
L
Liu Jicong 已提交
2308
    taosHashPut(profResults, &(operatorType), sizeof(operatorType), &opResult, sizeof(opResult));
2309 2310 2311
  }
}

2312
void calculateOperatorProfResults(void) {
dengyihao's avatar
dengyihao 已提交
2313 2314 2315 2316 2317 2318 2319 2320 2321
  //  if (pQInfo->summary.queryProfEvents == NULL) {
  //    // qDebug("QInfo:0x%"PRIx64" query prof events array is null", pQInfo->qId);
  //    return;
  //  }
  //
  //  if (pQInfo->summary.operatorProfResults == NULL) {
  //    // qDebug("QInfo:0x%"PRIx64" operator prof results hash is null", pQInfo->qId);
  //    return;
  //  }
2322 2323 2324 2325 2326

  SArray* opStack = taosArrayInit(32, sizeof(SOperatorStackItem));
  if (opStack == NULL) {
    return;
  }
2327
#if 0
L
Liu Jicong 已提交
2328
  size_t    size = taosArrayGetSize(pQInfo->summary.queryProfEvents);
2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
  SHashObj* profResults = pQInfo->summary.operatorProfResults;

  for (int i = 0; i < size; ++i) {
    SQueryProfEvent* event = taosArrayGet(pQInfo->summary.queryProfEvents, i);
    if (event->eventType == QUERY_PROF_BEFORE_OPERATOR_EXEC) {
      SOperatorStackItem opItem;
      opItem.operatorType = event->operatorType;
      opItem.beginTime = event->eventTime;
      opItem.descendantsTime = 0;
      taosArrayPush(opStack, &opItem);
    } else if (event->eventType == QUERY_PROF_AFTER_OPERATOR_EXEC) {
      SOperatorStackItem* item = taosArrayPop(opStack);
      assert(item->operatorType == event->operatorType);
      doOperatorExecProfOnce(item, event, opStack, profResults);
    } else if (event->eventType == QUERY_PROF_QUERY_ABORT) {
      SOperatorStackItem* item;
      while ((item = taosArrayPop(opStack)) != NULL) {
        doOperatorExecProfOnce(item, event, opStack, profResults);
      }
    }
  }
2350
#endif
2351 2352 2353
  taosArrayDestroy(opStack);
}

L
Liu Jicong 已提交
2354 2355
void queryCostStatis(SExecTaskInfo* pTaskInfo) {
  STaskCostInfo* pSummary = &pTaskInfo->cost;
2356

L
Liu Jicong 已提交
2357 2358 2359
  //  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
  //  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
  //  pSummary->hashSize = hashSize;
2360 2361 2362 2363

  // add the merge time
  pSummary->elapsedTime += pSummary->firstStageMergeTime;

L
Liu Jicong 已提交
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374
  //  SResultRowPool* p = pTaskInfo->pool;
  //  if (p != NULL) {
  //    pSummary->winInfoSize = getResultRowPoolMemSize(p);
  //    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  //  } else {
  //    pSummary->winInfoSize = 0;
  //    pSummary->numOfTimeWindows = 0;
  //  }
  //
  //  calculateOperatorProfResults(pQInfo);

2375 2376
  SFileBlockLoadRecorder* pRecorder = pSummary->pRecoder;
  if (pSummary->pRecoder != NULL) {
X
Xiaoyu Wang 已提交
2377 2378
    qDebug("%s :cost summary: elapsed time:%" PRId64 " us, first merge:%" PRId64
           " us, total blocks:%d, "
2379 2380 2381 2382
           "load block statis:%d, load data block:%d, total rows:%" PRId64 ", check rows:%" PRId64,
           GET_TASKID(pTaskInfo), pSummary->elapsedTime, pSummary->firstStageMergeTime, pRecorder->totalBlocks,
           pRecorder->loadBlockStatis, pRecorder->loadBlocks, pRecorder->totalRows, pRecorder->totalCheckedRows);
  }
L
Liu Jicong 已提交
2383 2384 2385
  // qDebug("QInfo:0x%"PRIx64" :cost summary: winResPool size:%.2f Kb, numOfWin:%"PRId64", tableInfoSize:%.2f Kb,
  // hashTable:%.2f Kb", pQInfo->qId, pSummary->winInfoSize/1024.0,
  //      pSummary->numOfTimeWindows, pSummary->tableInfoSize/1024.0, pSummary->hashSize/1024.0);
2386 2387 2388 2389

  if (pSummary->operatorProfResults) {
    SOperatorProfResult* opRes = taosHashIterate(pSummary->operatorProfResults, NULL);
    while (opRes != NULL) {
L
Liu Jicong 已提交
2390 2391
      // qDebug("QInfo:0x%" PRIx64 " :cost summary: operator : %d, exec times: %" PRId64 ", self time: %" PRId64,
      //             pQInfo->qId, opRes->operatorType, opRes->sumRunTimes, opRes->sumSelfTime);
2392 2393 2394 2395 2396
      opRes = taosHashIterate(pSummary->operatorProfResults, opRes);
    }
  }
}

L
Liu Jicong 已提交
2397 2398 2399
// static void updateOffsetVal(STaskRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//   STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
2400
//
L
Liu Jicong 已提交
2401
//   int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
2402
//
L
Liu Jicong 已提交
2403 2404 2405 2406
//   if (pQueryAttr->limit.offset == pBlockInfo->rows) {  // current block will ignore completed
//     pTableQueryInfo->lastKey = QUERY_IS_ASC_QUERY(pQueryAttr) ? pBlockInfo->window.ekey + step :
//     pBlockInfo->window.skey + step; pQueryAttr->limit.offset = 0; return;
//   }
2407
//
L
Liu Jicong 已提交
2408 2409 2410 2411 2412
//   if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//     pQueryAttr->pos = (int32_t)pQueryAttr->limit.offset;
//   } else {
//     pQueryAttr->pos = pBlockInfo->rows - (int32_t)pQueryAttr->limit.offset - 1;
//   }
2413
//
L
Liu Jicong 已提交
2414
//   assert(pQueryAttr->pos >= 0 && pQueryAttr->pos <= pBlockInfo->rows - 1);
2415
//
L
Liu Jicong 已提交
2416 2417
//   SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL);
//   SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
2418
//
L
Liu Jicong 已提交
2419 2420
//   // update the pQueryAttr->limit.offset value, and pQueryAttr->pos value
//   TSKEY *keys = (TSKEY *) pColInfoData->pData;
2421
//
L
Liu Jicong 已提交
2422 2423 2424
//   // update the offset value
//   pTableQueryInfo->lastKey = keys[pQueryAttr->pos];
//   pQueryAttr->limit.offset = 0;
2425
//
L
Liu Jicong 已提交
2426
//   int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
2427
//
L
Liu Jicong 已提交
2428 2429 2430 2431
//   //qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numBlocksOfStep:%d, numOfRes:%d,
//   lastKey:%"PRId64, GET_TASKID(pRuntimeEnv),
//          pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, pQuery->current->lastKey);
// }
2432

L
Liu Jicong 已提交
2433 2434
// void skipBlocks(STaskRuntimeEnv *pRuntimeEnv) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
2435
//
L
Liu Jicong 已提交
2436 2437 2438
//   if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0) {
//     return;
//   }
2439
//
L
Liu Jicong 已提交
2440 2441
//   pQueryAttr->pos = 0;
//   int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
2442
//
L
Liu Jicong 已提交
2443 2444
//   STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
//   TsdbQueryHandleT pTsdbReadHandle = pRuntimeEnv->pTsdbReadHandle;
2445
//
L
Liu Jicong 已提交
2446 2447 2448 2449 2450
//   SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//   while (tsdbNextDataBlock(pTsdbReadHandle)) {
//     if (isTaskKilled(pRuntimeEnv->qinfo)) {
//       longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//     }
2451
//
L
Liu Jicong 已提交
2452
//     tsdbRetrieveDataBlockInfo(pTsdbReadHandle, &blockInfo);
2453
//
L
Liu Jicong 已提交
2454 2455 2456 2457
//     if (pQueryAttr->limit.offset > blockInfo.rows) {
//       pQueryAttr->limit.offset -= blockInfo.rows;
//       pTableQueryInfo->lastKey = (QUERY_IS_ASC_QUERY(pQueryAttr)) ? blockInfo.window.ekey : blockInfo.window.skey;
//       pTableQueryInfo->lastKey += step;
2458
//
L
Liu Jicong 已提交
2459 2460 2461 2462 2463 2464 2465
//       //qDebug("QInfo:0x%"PRIx64" skip rows:%d, offset:%" PRId64, GET_TASKID(pRuntimeEnv), blockInfo.rows,
//              pQuery->limit.offset);
//     } else {  // find the appropriated start position in current block
//       updateOffsetVal(pRuntimeEnv, &blockInfo);
//       break;
//     }
//   }
2466
//
L
Liu Jicong 已提交
2467 2468 2469 2470 2471 2472 2473 2474 2475
//   if (terrno != TSDB_CODE_SUCCESS) {
//     longjmp(pRuntimeEnv->env, terrno);
//   }
// }

// static TSKEY doSkipIntervalProcess(STaskRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo,
// STableQueryInfo* pTableQueryInfo) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//   SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
2476
//
L
Liu Jicong 已提交
2477 2478 2479
//   assert(pQueryAttr->limit.offset == 0);
//   STimeWindow tw = *win;
//   getNextTimeWindow(pQueryAttr, &tw);
2480
//
L
Liu Jicong 已提交
2481 2482
//   if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//       (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
2483
//
L
Liu Jicong 已提交
2484 2485 2486 2487
//     // load the data block and check data remaining in current data block
//     // TODO optimize performance
//     SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL);
//     SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
2488
//
L
Liu Jicong 已提交
2489 2490 2491 2492
//     tw = *win;
//     int32_t startPos =
//         getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
//     assert(startPos >= 0);
2493
//
L
Liu Jicong 已提交
2494 2495
//     // set the abort info
//     pQueryAttr->pos = startPos;
2496
//
L
Liu Jicong 已提交
2497 2498 2499 2500
//     // reset the query start timestamp
//     pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
//     pQueryAttr->window.skey = pTableQueryInfo->win.skey;
//     TSKEY key = pTableQueryInfo->win.skey;
2501
//
L
Liu Jicong 已提交
2502 2503
//     pWindowResInfo->prevSKey = tw.skey;
//     int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
2504
//
L
Liu Jicong 已提交
2505 2506
//     int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//     pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
2507
//
L
Liu Jicong 已提交
2508 2509 2510 2511
//     //qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d,
//     lastKey:%" PRId64,
//            GET_TASKID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes,
//            pQueryAttr->current->lastKey);
2512
//
L
Liu Jicong 已提交
2513 2514 2515 2516 2517
//     return key;
//   } else {  // do nothing
//     pQueryAttr->window.skey      = tw.skey;
//     pWindowResInfo->prevSKey = tw.skey;
//     pTableQueryInfo->lastKey = tw.skey;
2518
//
L
Liu Jicong 已提交
2519 2520
//     return tw.skey;
//   }
2521
//
L
Liu Jicong 已提交
2522 2523 2524 2525 2526 2527 2528 2529 2530 2531
//   return true;
// }

// static bool skipTimeInterval(STaskRuntimeEnv *pRuntimeEnv, TSKEY* start) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//   if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//     assert(*start <= pRuntimeEnv->current->lastKey);
//   } else {
//     assert(*start >= pRuntimeEnv->current->lastKey);
//   }
2532
//
L
Liu Jicong 已提交
2533 2534 2535 2536 2537
//   // if queried with value filter, do NOT forward query start position
//   if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL ||
//   pRuntimeEnv->pFillInfo != NULL) {
//     return true;
//   }
2538
//
L
Liu Jicong 已提交
2539 2540 2541 2542 2543 2544 2545
//   /*
//    * 1. for interval without interpolation query we forward pQueryAttr->interval.interval at a time for
//    *    pQueryAttr->limit.offset times. Since hole exists, pQueryAttr->interval.interval*pQueryAttr->limit.offset
//    value is
//    *    not valid. otherwise, we only forward pQueryAttr->limit.offset number of points
//    */
//   assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL);
2546
//
L
Liu Jicong 已提交
2547 2548
//   STimeWindow w = TSWINDOW_INITIALIZER;
//   bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
2549
//
L
Liu Jicong 已提交
2550 2551
//   SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//   STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
2552
//
L
Liu Jicong 已提交
2553 2554 2555
//   SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//   while (tsdbNextDataBlock(pRuntimeEnv->pTsdbReadHandle)) {
//     tsdbRetrieveDataBlockInfo(pRuntimeEnv->pTsdbReadHandle, &blockInfo);
2556
//
L
Liu Jicong 已提交
2557 2558 2559 2560 2561 2562 2563 2564 2565
//     if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//       if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) {
//         getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey,
//         &w); pWindowResInfo->prevSKey = w.skey;
//       }
//     } else {
//       getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w);
//       pWindowResInfo->prevSKey = w.skey;
//     }
2566
//
L
Liu Jicong 已提交
2567 2568
//     // the first time window
//     STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
2569
//
L
Liu Jicong 已提交
2570 2571
//     while (pQueryAttr->limit.offset > 0) {
//       STimeWindow tw = win;
2572
//
L
Liu Jicong 已提交
2573 2574 2575
//       if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
//         pQueryAttr->limit.offset -= 1;
//         pWindowResInfo->prevSKey = win.skey;
2576
//
L
Liu Jicong 已提交
2577 2578 2579 2580 2581 2582
//         // current time window is aligned with blockInfo.window.ekey
//         // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL;
//         if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) {
//           pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
//         }
//       }
2583
//
L
Liu Jicong 已提交
2584 2585 2586 2587
//       if (pQueryAttr->limit.offset == 0) {
//         *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//         return true;
//       }
2588
//
L
Liu Jicong 已提交
2589 2590
//       // current window does not ended in current data block, try next data block
//       getNextTimeWindow(pQueryAttr, &tw);
2591
//
L
Liu Jicong 已提交
2592 2593 2594 2595 2596 2597 2598 2599 2600
//       /*
//        * If the next time window still starts from current data block,
//        * load the primary timestamp column first, and then find the start position for the next queried time window.
//        * Note that only the primary timestamp column is required.
//        * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually
//        required
//        * time window resides in current data block.
//        */
//       if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) {
2601
//
L
Liu Jicong 已提交
2602 2603
//         SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL);
//         SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
2604
//
L
Liu Jicong 已提交
2605 2606 2607
//         if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
//           pQueryAttr->limit.offset -= 1;
//         }
2608
//
L
Liu Jicong 已提交
2609 2610 2611 2612 2613 2614 2615 2616
//         if (pQueryAttr->limit.offset == 0) {
//           *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//           return true;
//         } else {
//           tw = win;
//           int32_t startPos =
//               getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1);
//           assert(startPos >= 0);
2617
//
L
Liu Jicong 已提交
2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628
//           // set the abort info
//           pQueryAttr->pos = startPos;
//           pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos];
//           pWindowResInfo->prevSKey = tw.skey;
//           win = tw;
//         }
//       } else {
//         break;  // offset is not 0, and next time window begins or ends in the next block.
//       }
//     }
//   }
2629
//
L
Liu Jicong 已提交
2630 2631 2632 2633
//   // check for error
//   if (terrno != TSDB_CODE_SUCCESS) {
//     longjmp(pRuntimeEnv->env, terrno);
//   }
2634
//
L
Liu Jicong 已提交
2635 2636
//   return true;
// }
2637

2638
int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num) {
H
Haojun Liao 已提交
2639
  if (p->pDownstream == NULL) {
H
Haojun Liao 已提交
2640
    assert(p->numOfDownstream == 0);
2641 2642
  }

wafwerar's avatar
wafwerar 已提交
2643
  p->pDownstream = taosMemoryCalloc(1, num * POINTER_BYTES);
2644 2645 2646 2647 2648 2649 2650
  if (p->pDownstream == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  memcpy(p->pDownstream, pDownstream, num * POINTER_BYTES);
  p->numOfDownstream = num;
  return TSDB_CODE_SUCCESS;
2651 2652 2653 2654
}

static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

2655
static void doTableQueryInfoTimeWindowCheck(SExecTaskInfo* pTaskInfo, STableQueryInfo* pTableQueryInfo, int32_t order) {
H
Haojun Liao 已提交
2656 2657
#if 0
    if (order == TSDB_ORDER_ASC) {
2658 2659
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
H
Haojun Liao 已提交
2660 2661
        (pTableQueryInfo->lastKey >= pTaskInfo->window.skey) &&
        (pTableQueryInfo->win.skey >= pTaskInfo->window.skey && pTableQueryInfo->win.ekey <= pTaskInfo->window.ekey));
2662 2663 2664
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
H
Haojun Liao 已提交
2665 2666
        (pTableQueryInfo->lastKey <= pTaskInfo->window.skey) &&
        (pTableQueryInfo->win.skey <= pTaskInfo->window.skey && pTableQueryInfo->win.ekey >= pTaskInfo->window.ekey));
2667
  }
H
Haojun Liao 已提交
2668
#endif
2669 2670
}

L
Liu Jicong 已提交
2671 2672 2673 2674
// static void updateTableIdInfo(STableQueryInfo* pTableQueryInfo, SSDataBlock* pBlock, SHashObj* pTableIdInfo, int32_t
// order) {
//   int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);
//   pTableQueryInfo->lastKey = ((order == TSDB_ORDER_ASC)? pBlock->info.window.ekey:pBlock->info.window.skey) + step;
2675
//
L
Liu Jicong 已提交
2676 2677 2678
//   if (pTableQueryInfo->pTable == NULL) {
//     return;
//   }
2679
//
L
Liu Jicong 已提交
2680 2681 2682 2683 2684 2685 2686 2687 2688
//   STableIdInfo tidInfo = createTableIdInfo(pTableQueryInfo);
//   STableIdInfo *idinfo = taosHashGet(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid));
//   if (idinfo != NULL) {
//     assert(idinfo->tid == tidInfo.tid && idinfo->uid == tidInfo.uid);
//     idinfo->key = tidInfo.key;
//   } else {
//     taosHashPut(pTableIdInfo, &tidInfo.tid, sizeof(tidInfo.tid), &tidInfo, sizeof(STableIdInfo));
//   }
// }
2689

2690
int32_t loadRemoteDataCallback(void* param, const SDataBuf* pMsg, int32_t code) {
L
Liu Jicong 已提交
2691
  SSourceDataInfo* pSourceDataInfo = (SSourceDataInfo*)param;
H
Haojun Liao 已提交
2692 2693
  if (code == TSDB_CODE_SUCCESS) {
    pSourceDataInfo->pRsp = pMsg->pData;
2694

H
Haojun Liao 已提交
2695 2696
    SRetrieveTableRsp* pRsp = pSourceDataInfo->pRsp;
    pRsp->numOfRows = htonl(pRsp->numOfRows);
dengyihao's avatar
dengyihao 已提交
2697
    pRsp->compLen = htonl(pRsp->compLen);
2698
    pRsp->numOfCols = htonl(pRsp->numOfCols);
dengyihao's avatar
dengyihao 已提交
2699
    pRsp->useconds = htobe64(pRsp->useconds);
H
Haojun Liao 已提交
2700 2701 2702
  } else {
    pSourceDataInfo->code = code;
  }
H
Haojun Liao 已提交
2703

H
Haojun Liao 已提交
2704
  pSourceDataInfo->status = EX_SOURCE_DATA_READY;
2705
  tsem_post(&pSourceDataInfo->pEx->ready);
wmmhello's avatar
wmmhello 已提交
2706
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2707 2708 2709 2710
}

static void destroySendMsgInfo(SMsgSendInfo* pMsgBody) {
  assert(pMsgBody != NULL);
wafwerar's avatar
wafwerar 已提交
2711 2712
  taosMemoryFreeClear(pMsgBody->msgInfo.pData);
  taosMemoryFreeClear(pMsgBody);
H
Haojun Liao 已提交
2713 2714
}

S
Shengliang Guan 已提交
2715
void qProcessFetchRsp(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
S
Shengliang Guan 已提交
2716 2717
  SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->info.ahandle;
  assert(pMsg->info.ahandle != NULL);
H
Haojun Liao 已提交
2718 2719 2720 2721

  SDataBuf buf = {.len = pMsg->contLen, .pData = NULL};

  if (pMsg->contLen > 0) {
wafwerar's avatar
wafwerar 已提交
2722
    buf.pData = taosMemoryCalloc(1, pMsg->contLen);
H
Haojun Liao 已提交
2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733
    if (buf.pData == NULL) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      pMsg->code = TSDB_CODE_OUT_OF_MEMORY;
    } else {
      memcpy(buf.pData, pMsg->pCont, pMsg->contLen);
    }
  }

  pSendInfo->fp(pSendInfo->param, &buf, pMsg->code);
  rpcFreeCont(pMsg->pCont);
  destroySendMsgInfo(pSendInfo);
2734 2735
}

L
Liu Jicong 已提交
2736
static int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTaskInfo, int32_t sourceIndex) {
2737
  size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources);
2738

wafwerar's avatar
wafwerar 已提交
2739
  SResFetchReq* pMsg = taosMemoryCalloc(1, sizeof(SResFetchReq));
2740 2741 2742 2743
  if (NULL == pMsg) {
    pTaskInfo->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return pTaskInfo->code;
  }
2744

L
Liu Jicong 已提交
2745 2746
  SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, sourceIndex);
  SSourceDataInfo*       pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, sourceIndex);
2747

L
Liu Jicong 已提交
2748 2749
  qDebug("%s build fetch msg and send to vgId:%d, ep:%s, taskId:0x%" PRIx64 ", %d/%" PRIzu, GET_TASKID(pTaskInfo),
         pSource->addr.nodeId, pSource->addr.epSet.eps[0].fqdn, pSource->taskId, sourceIndex, totalSources);
2750 2751 2752 2753 2754 2755 2756

  pMsg->header.vgId = htonl(pSource->addr.nodeId);
  pMsg->sId = htobe64(pSource->schedId);
  pMsg->taskId = htobe64(pSource->taskId);
  pMsg->queryId = htobe64(pTaskInfo->id.queryId);

  // send the fetch remote task result reques
wafwerar's avatar
wafwerar 已提交
2757
  SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
2758
  if (NULL == pMsgSendInfo) {
wafwerar's avatar
wafwerar 已提交
2759
    taosMemoryFreeClear(pMsg);
2760 2761 2762
    qError("%s prepare message %d failed", GET_TASKID(pTaskInfo), (int32_t)sizeof(SMsgSendInfo));
    pTaskInfo->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return pTaskInfo->code;
H
Haojun Liao 已提交
2763 2764
  }

2765 2766 2767 2768 2769
  pMsgSendInfo->param = pDataInfo;
  pMsgSendInfo->msgInfo.pData = pMsg;
  pMsgSendInfo->msgInfo.len = sizeof(SResFetchReq);
  pMsgSendInfo->msgType = TDMT_VND_FETCH;
  pMsgSendInfo->fp = loadRemoteDataCallback;
2770

2771
  int64_t transporterId = 0;
L
Liu Jicong 已提交
2772
  int32_t code = asyncSendMsgToServer(pExchangeInfo->pTransporter, &pSource->addr.epSet, &transporterId, pMsgSendInfo);
2773 2774 2775
  return TSDB_CODE_SUCCESS;
}

2776
// NOTE: sources columns are more than the destination SSDatablock columns.
2777
void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols) {
2778 2779 2780
  size_t numOfSrcCols = taosArrayGetSize(pCols);

  int32_t i = 0, j = 0;
L
Liu Jicong 已提交
2781
  while (i < numOfSrcCols && j < taosArrayGetSize(pColMatchInfo)) {
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800
    SColumnInfoData* p = taosArrayGet(pCols, i);
    SColMatchInfo*   pmInfo = taosArrayGet(pColMatchInfo, j);
    if (!pmInfo->output) {
      j++;
      continue;
    }

    if (p->info.colId == pmInfo->colId) {
      taosArraySet(pBlock->pDataBlock, pmInfo->targetSlotId, p);
      i++;
      j++;
    } else if (p->info.colId < pmInfo->colId) {
      i++;
    } else {
      ASSERT(0);
    }
  }
}

2801
int32_t setSDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadInfo, int32_t numOfRows, char* pData,
dengyihao's avatar
dengyihao 已提交
2802 2803
                                  int32_t compLen, int32_t numOfOutput, int64_t startTs, uint64_t* total,
                                  SArray* pColList) {
H
Haojun Liao 已提交
2804
  if (pColList == NULL) {  // data from other sources
H
Haojun Liao 已提交
2805 2806
    blockDataEnsureCapacity(pRes, numOfRows);

L
Liu Jicong 已提交
2807
    int32_t dataLen = *(int32_t*)pData;
2808 2809
    pData += sizeof(int32_t);

L
Liu Jicong 已提交
2810
    pRes->info.groupId = *(uint64_t*)pData;
2811 2812
    pData += sizeof(uint64_t);

H
Haojun Liao 已提交
2813 2814
    int32_t* colLen = (int32_t*)pData;

2815
    char* pStart = pData + sizeof(int32_t) * numOfOutput;
2816
    for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
2817
      colLen[i] = htonl(colLen[i]);
2818
      ASSERT(colLen[i] >= 0);
H
Haojun Liao 已提交
2819

2820
      SColumnInfoData* pColInfoData = taosArrayGet(pRes->pDataBlock, i);
H
Haojun Liao 已提交
2821 2822 2823
      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
        pColInfoData->varmeta.length = colLen[i];
        pColInfoData->varmeta.allocLen = colLen[i];
2824

L
Liu Jicong 已提交
2825 2826
        memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
        pStart += sizeof(int32_t) * numOfRows;
H
Haojun Liao 已提交
2827

2828 2829 2830
        if (colLen[i] > 0) {
          pColInfoData->pData = taosMemoryMalloc(colLen[i]);
        }
H
Haojun Liao 已提交
2831 2832 2833
      } else {
        memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
        pStart += BitmapLen(numOfRows);
2834
      }
H
Haojun Liao 已提交
2835

2836 2837 2838 2839
      if (colLen[i] > 0) {
        memcpy(pColInfoData->pData, pStart, colLen[i]);
      }

L
Liu Jicong 已提交
2840 2841
      // TODO setting this flag to true temporarily so aggregate function on stable will
      // examine NULL value for non-primary key column
2842
      pColInfoData->hasNull = true;
H
Haojun Liao 已提交
2843
      pStart += colLen[i];
2844
    }
H
Haojun Liao 已提交
2845
  } else {  // extract data according to pColList
2846
    ASSERT(numOfOutput == taosArrayGetSize(pColList));
2847 2848 2849 2850 2851
    char* pStart = pData;

    int32_t numOfCols = htonl(*(int32_t*)pStart);
    pStart += sizeof(int32_t);

2852
    // todo refactor:extract method
2853
    SSysTableSchema* pSchema = (SSysTableSchema*)pStart;
dengyihao's avatar
dengyihao 已提交
2854
    for (int32_t i = 0; i < numOfCols; ++i) {
2855 2856 2857 2858 2859 2860 2861
      SSysTableSchema* p = (SSysTableSchema*)pStart;

      p->colId = htons(p->colId);
      p->bytes = htonl(p->bytes);
      pStart += sizeof(SSysTableSchema);
    }

H
Haojun Liao 已提交
2862 2863 2864 2865
    SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock));
    pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData));
    pBlock->info.numOfCols = numOfCols;

dengyihao's avatar
dengyihao 已提交
2866
    for (int32_t i = 0; i < numOfCols; ++i) {
2867 2868 2869 2870 2871
      SColumnInfoData idata = {0};
      idata.info.type = pSchema[i].type;
      idata.info.bytes = pSchema[i].bytes;
      idata.info.colId = pSchema[i].colId;

H
Haojun Liao 已提交
2872
      taosArrayPush(pBlock->pDataBlock, &idata);
2873
      if (IS_VAR_DATA_TYPE(idata.info.type)) {
H
Haojun Liao 已提交
2874
        pBlock->info.hasVarCol = true;
2875 2876 2877
      }
    }

H
Haojun Liao 已提交
2878
    blockDataEnsureCapacity(pBlock, numOfRows);
2879

L
Liu Jicong 已提交
2880 2881
    int32_t  dataLen = *(int32_t*)pStart;
    uint64_t groupId = *(uint64_t*)(pStart + sizeof(int32_t));
2882 2883
    pStart += sizeof(int32_t) + sizeof(uint64_t);

L
Liu Jicong 已提交
2884
    int32_t* colLen = (int32_t*)(pStart);
2885 2886 2887 2888
    pStart += sizeof(int32_t) * numOfCols;

    for (int32_t i = 0; i < numOfCols; ++i) {
      colLen[i] = htonl(colLen[i]);
2889
      ASSERT(colLen[i] >= 0);
2890

H
Haojun Liao 已提交
2891
      SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, i);
2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907
      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
        pColInfoData->varmeta.length = colLen[i];
        pColInfoData->varmeta.allocLen = colLen[i];

        memcpy(pColInfoData->varmeta.offset, pStart, sizeof(int32_t) * numOfRows);
        pStart += sizeof(int32_t) * numOfRows;

        pColInfoData->pData = taosMemoryMalloc(colLen[i]);
      } else {
        memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
        pStart += BitmapLen(numOfRows);
      }

      memcpy(pColInfoData->pData, pStart, colLen[i]);
      pStart += colLen[i];
    }
H
Haojun Liao 已提交
2908 2909

    // data from mnode
H
Haojun Liao 已提交
2910 2911 2912
    relocateColumnData(pRes, pColList, pBlock->pDataBlock);
    taosArrayDestroy(pBlock->pDataBlock);
    taosMemoryFree(pBlock);
X
Xiaoyu Wang 已提交
2913
    //    blockDataDestroy(pBlock);
2914
  }
2915

H
Haojun Liao 已提交
2916
  pRes->info.rows = numOfRows;
2917
  blockDataUpdateTsWindow(pRes);
2918

2919
  int64_t el = taosGetTimestampUs() - startTs;
2920

H
Haojun Liao 已提交
2921 2922
  pLoadInfo->totalRows += numOfRows;
  pLoadInfo->totalSize += compLen;
2923

H
Haojun Liao 已提交
2924 2925 2926
  if (total != NULL) {
    *total += numOfRows;
  }
2927

H
Haojun Liao 已提交
2928
  pLoadInfo->totalElapsed += el;
2929 2930
  return TSDB_CODE_SUCCESS;
}
2931

L
Liu Jicong 已提交
2932 2933
static void* setAllSourcesCompleted(SOperatorInfo* pOperator, int64_t startTs) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
2934
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
H
Haojun Liao 已提交
2935

L
Liu Jicong 已提交
2936
  int64_t              el = taosGetTimestampUs() - startTs;
H
Haojun Liao 已提交
2937 2938
  SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
  pLoadInfo->totalElapsed += el;
H
Haojun Liao 已提交
2939

2940
  size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources);
L
Liu Jicong 已提交
2941 2942 2943
  qDebug("%s all %" PRIzu " sources are exhausted, total rows: %" PRIu64 " bytes:%" PRIu64 ", elapsed:%.2f ms",
         GET_TASKID(pTaskInfo), totalSources, pLoadInfo->totalRows, pLoadInfo->totalSize,
         pLoadInfo->totalElapsed / 1000.0);
2944 2945 2946 2947 2948

  doSetOperatorCompleted(pOperator);
  return NULL;
}

L
Liu Jicong 已提交
2949 2950
static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SExchangeInfo* pExchangeInfo,
                                                   SExecTaskInfo* pTaskInfo) {
2951 2952 2953 2954 2955 2956 2957 2958 2959
  int32_t code = 0;
  int64_t startTs = taosGetTimestampUs();
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);

  while (1) {
    int32_t completed = 0;
    for (int32_t i = 0; i < totalSources; ++i) {
      SSourceDataInfo* pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, i);

2960
      if (pDataInfo->status == EX_SOURCE_DATA_EXHAUSTED) {
2961
        completed += 1;
H
Haojun Liao 已提交
2962 2963
        continue;
      }
2964

2965
      if (pDataInfo->status != EX_SOURCE_DATA_READY) {
2966 2967 2968
        continue;
      }

L
Liu Jicong 已提交
2969
      SRetrieveTableRsp*     pRsp = pDataInfo->pRsp;
X
Xiaoyu Wang 已提交
2970
      SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, i);
2971

L
Liu Jicong 已提交
2972
      SSDataBlock*         pRes = pExchangeInfo->pResult;
H
Haojun Liao 已提交
2973
      SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
2974
      if (pRsp->numOfRows == 0) {
L
Liu Jicong 已提交
2975 2976
        qDebug("%s vgId:%d, taskID:0x%" PRIx64 " index:%d completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
               " try next",
2977
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, i + 1, pDataInfo->totalRows,
H
Haojun Liao 已提交
2978
               pExchangeInfo->loadInfo.totalRows);
2979
        pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
2980 2981 2982
        completed += 1;
        continue;
      }
H
Haojun Liao 已提交
2983

H
Haojun Liao 已提交
2984
      SRetrieveTableRsp* pTableRsp = pDataInfo->pRsp;
X
Xiaoyu Wang 已提交
2985 2986
      code = setSDataBlockFromFetchRsp(pExchangeInfo->pResult, pLoadInfo, pTableRsp->numOfRows, pTableRsp->data,
                                       pTableRsp->compLen, pTableRsp->numOfCols, startTs, &pDataInfo->totalRows, NULL);
2987
      if (code != 0) {
2988 2989 2990
        goto _error;
      }

2991 2992 2993
      if (pRsp->completed == 1) {
        qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, rowsOfSource:%" PRIu64
               ", totalRows:%" PRIu64 ", totalBytes:%" PRIu64 " try next %d/%" PRIzu,
L
Liu Jicong 已提交
2994 2995
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pDataInfo->totalRows,
               pLoadInfo->totalRows, pLoadInfo->totalSize, i + 1, totalSources);
2996
        pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
2997
      } else {
dengyihao's avatar
dengyihao 已提交
2998 2999
        qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64
               ", totalBytes:%" PRIu64,
H
Haojun Liao 已提交
3000 3001
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pLoadInfo->totalRows,
               pLoadInfo->totalSize);
3002 3003
      }

3004 3005
      if (pDataInfo->status != EX_SOURCE_DATA_EXHAUSTED) {
        pDataInfo->status = EX_SOURCE_DATA_NOT_READY;
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
        code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i);
        if (code != TSDB_CODE_SUCCESS) {
          goto _error;
        }
      }

      return pExchangeInfo->pResult;
    }

    if (completed == totalSources) {
      return setAllSourcesCompleted(pOperator, startTs);
    }
  }

_error:
  pTaskInfo->code = code;
  return NULL;
}

L
Liu Jicong 已提交
3025 3026 3027
static SSDataBlock* concurrentlyLoadRemoteData(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
H
Haojun Liao 已提交
3028

H
Haojun Liao 已提交
3029 3030 3031
  if (pOperator->status == OP_RES_TO_RETURN) {
    return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo);
  }
3032

L
Liu Jicong 已提交
3033
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3034 3035 3036
  int64_t startTs = taosGetTimestampUs();

  // Asynchronously send all fetch requests to all sources.
L
Liu Jicong 已提交
3037
  for (int32_t i = 0; i < totalSources; ++i) {
3038 3039
    int32_t code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i);
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3040
      return NULL;
3041 3042 3043 3044
    }
  }

  int64_t endTs = taosGetTimestampUs();
L
Liu Jicong 已提交
3045 3046
  qDebug("%s send all fetch request to %" PRIzu " sources completed, elapsed:%" PRId64, GET_TASKID(pTaskInfo),
         totalSources, endTs - startTs);
3047 3048

  tsem_wait(&pExchangeInfo->ready);
H
Haojun Liao 已提交
3049 3050
  pOperator->status = OP_RES_TO_RETURN;
  return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo);
3051 3052
}

L
Liu Jicong 已提交
3053 3054 3055
static int32_t prepareConcurrentlyLoad(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3056

L
Liu Jicong 已提交
3057
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3058 3059 3060
  int64_t startTs = taosGetTimestampUs();

  // Asynchronously send all fetch requests to all sources.
L
Liu Jicong 已提交
3061
  for (int32_t i = 0; i < totalSources; ++i) {
3062 3063
    int32_t code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i);
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3064 3065
      pTaskInfo->code = code;
      return code;
3066 3067 3068 3069
    }
  }

  int64_t endTs = taosGetTimestampUs();
L
Liu Jicong 已提交
3070 3071
  qDebug("%s send all fetch request to %" PRIzu " sources completed, elapsed:%" PRId64, GET_TASKID(pTaskInfo),
         totalSources, endTs - startTs);
3072 3073

  tsem_wait(&pExchangeInfo->ready);
H
Haojun Liao 已提交
3074
  pOperator->cost.openCost = taosGetTimestampUs() - startTs;
3075

H
Haojun Liao 已提交
3076
  return TSDB_CODE_SUCCESS;
3077 3078
}

L
Liu Jicong 已提交
3079 3080 3081
static SSDataBlock* seqLoadRemoteData(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3082

L
Liu Jicong 已提交
3083
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3084
  int64_t startTs = taosGetTimestampUs();
3085

L
Liu Jicong 已提交
3086
  while (1) {
3087 3088
    if (pExchangeInfo->current >= totalSources) {
      return setAllSourcesCompleted(pOperator, startTs);
3089
    }
3090

3091 3092 3093
    doSendFetchDataRequest(pExchangeInfo, pTaskInfo, pExchangeInfo->current);
    tsem_wait(&pExchangeInfo->ready);

dengyihao's avatar
dengyihao 已提交
3094
    SSourceDataInfo*       pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, pExchangeInfo->current);
X
Xiaoyu Wang 已提交
3095
    SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current);
3096

H
Haojun Liao 已提交
3097
    if (pDataInfo->code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
3098 3099
      qError("%s vgId:%d, taskID:0x%" PRIx64 " error happens, code:%s", GET_TASKID(pTaskInfo), pSource->addr.nodeId,
             pSource->taskId, tstrerror(pDataInfo->code));
H
Haojun Liao 已提交
3100 3101 3102 3103
      pOperator->pTaskInfo->code = pDataInfo->code;
      return NULL;
    }

L
Liu Jicong 已提交
3104
    SRetrieveTableRsp*   pRsp = pDataInfo->pRsp;
H
Haojun Liao 已提交
3105
    SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
3106
    if (pRsp->numOfRows == 0) {
dengyihao's avatar
dengyihao 已提交
3107 3108
      qDebug("%s vgId:%d, taskID:0x%" PRIx64 " %d of total completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
             " try next",
3109
             GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pExchangeInfo->current + 1,
H
Haojun Liao 已提交
3110
             pDataInfo->totalRows, pLoadInfo->totalRows);
H
Haojun Liao 已提交
3111

3112
      pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3113 3114 3115
      pExchangeInfo->current += 1;
      continue;
    }
H
Haojun Liao 已提交
3116

L
Liu Jicong 已提交
3117
    SSDataBlock*       pRes = pExchangeInfo->pResult;
H
Haojun Liao 已提交
3118
    SRetrieveTableRsp* pTableRsp = pDataInfo->pRsp;
L
Liu Jicong 已提交
3119 3120
    int32_t            code =
        setSDataBlockFromFetchRsp(pExchangeInfo->pResult, pLoadInfo, pTableRsp->numOfRows, pTableRsp->data,
3121
                                  pTableRsp->compLen, pTableRsp->numOfCols, startTs, &pDataInfo->totalRows, NULL);
3122 3123

    if (pRsp->completed == 1) {
H
Haojun Liao 已提交
3124
      qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, rowsOfSource:%" PRIu64
L
Liu Jicong 已提交
3125 3126 3127
             ", totalRows:%" PRIu64 ", totalBytes:%" PRIu64 " try next %d/%" PRIzu,
             GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pDataInfo->totalRows,
             pLoadInfo->totalRows, pLoadInfo->totalSize, pExchangeInfo->current + 1, totalSources);
3128

3129
      pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3130 3131
      pExchangeInfo->current += 1;
    } else {
L
Liu Jicong 已提交
3132 3133 3134 3135
      qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64
             ", totalBytes:%" PRIu64,
             GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pLoadInfo->totalRows,
             pLoadInfo->totalSize);
3136 3137 3138 3139
    }

    return pExchangeInfo->pResult;
  }
3140 3141
}

L
Liu Jicong 已提交
3142
static int32_t prepareLoadRemoteData(SOperatorInfo* pOperator) {
3143
  if (OPTR_IS_OPENED(pOperator)) {
H
Haojun Liao 已提交
3144 3145 3146
    return TSDB_CODE_SUCCESS;
  }

L
Liu Jicong 已提交
3147
  SExchangeInfo* pExchangeInfo = pOperator->info;
H
Haojun Liao 已提交
3148 3149 3150 3151 3152 3153 3154 3155 3156
  if (pExchangeInfo->seqLoadData) {
    // do nothing for sequentially load data
  } else {
    int32_t code = prepareConcurrentlyLoad(pOperator);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
  }

3157
  OPTR_SET_OPENED(pOperator);
H
Haojun Liao 已提交
3158 3159 3160
  return TSDB_CODE_SUCCESS;
}

3161
static SSDataBlock* doLoadRemoteData(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
3162 3163
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3164

3165
  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
3166
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3167 3168
    return NULL;
  }
3169

L
Liu Jicong 已提交
3170
  size_t               totalSources = taosArrayGetSize(pExchangeInfo->pSources);
H
Haojun Liao 已提交
3171
  SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
H
Haojun Liao 已提交
3172

3173
  if (pOperator->status == OP_EXEC_DONE) {
L
Liu Jicong 已提交
3174 3175 3176
    qDebug("%s all %" PRIzu " source(s) are exhausted, total rows:%" PRIu64 " bytes:%" PRIu64 ", elapsed:%.2f ms",
           GET_TASKID(pTaskInfo), totalSources, pLoadInfo->totalRows, pLoadInfo->totalSize,
           pLoadInfo->totalElapsed / 1000.0);
3177 3178 3179 3180 3181 3182
    return NULL;
  }

  if (pExchangeInfo->seqLoadData) {
    return seqLoadRemoteData(pOperator);
  } else {
H
Haojun Liao 已提交
3183
    return concurrentlyLoadRemoteData(pOperator);
3184
  }
H
Haojun Liao 已提交
3185

3186
#if 0
H
Haojun Liao 已提交
3187
  _error:
wafwerar's avatar
wafwerar 已提交
3188 3189
  taosMemoryFreeClear(pMsg);
  taosMemoryFreeClear(pMsgSendInfo);
H
Haojun Liao 已提交
3190 3191 3192

  terrno = pTaskInfo->code;
  return NULL;
3193
#endif
H
Haojun Liao 已提交
3194
}
3195

H
Haojun Liao 已提交
3196
static int32_t initDataSource(int32_t numOfSources, SExchangeInfo* pInfo) {
3197
  pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo));
H
Haojun Liao 已提交
3198 3199
  if (pInfo->pSourceDataInfo == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
3200 3201
  }

L
Liu Jicong 已提交
3202
  for (int32_t i = 0; i < numOfSources; ++i) {
3203
    SSourceDataInfo dataInfo = {0};
H
Haojun Liao 已提交
3204
    dataInfo.status = EX_SOURCE_DATA_NOT_READY;
L
Liu Jicong 已提交
3205 3206
    dataInfo.pEx = pInfo;
    dataInfo.index = i;
3207

H
Haojun Liao 已提交
3208 3209 3210 3211 3212 3213 3214 3215 3216 3217
    void* ret = taosArrayPush(pInfo->pSourceDataInfo, &dataInfo);
    if (ret == NULL) {
      taosArrayDestroy(pInfo->pSourceDataInfo);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  return TSDB_CODE_SUCCESS;
}

3218
SOperatorInfo* createExchangeOperatorInfo(void *pTransporter, const SNodeList* pSources, SSDataBlock* pBlock,
3219
                                          SExecTaskInfo* pTaskInfo) {
L
Liu Jicong 已提交
3220
  SExchangeInfo* pInfo = taosMemoryCalloc(1, sizeof(SExchangeInfo));
wafwerar's avatar
wafwerar 已提交
3221
  SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
3222 3223

  if (pInfo == NULL || pOperator == NULL) {
wafwerar's avatar
wafwerar 已提交
3224 3225
    taosMemoryFreeClear(pInfo);
    taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
3226 3227
    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return NULL;
H
Haojun Liao 已提交
3228 3229
  }

H
Haojun Liao 已提交
3230
  size_t numOfSources = LIST_LENGTH(pSources);
H
Haojun Liao 已提交
3231
  pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode));
H
Haojun Liao 已提交
3232 3233 3234
  pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo));
  if (pInfo->pSourceDataInfo == NULL || pInfo->pSources == NULL) {
    goto _error;
H
Haojun Liao 已提交
3235 3236
  }

L
Liu Jicong 已提交
3237 3238
  for (int32_t i = 0; i < numOfSources; ++i) {
    SNodeListNode* pNode = nodesListGetNode((SNodeList*)pSources, i);
H
Haojun Liao 已提交
3239 3240
    taosArrayPush(pInfo->pSources, pNode);
  }
3241

H
Haojun Liao 已提交
3242 3243 3244
  int32_t code = initDataSource(numOfSources, pInfo);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
3245
  }
H
Haojun Liao 已提交
3246

dengyihao's avatar
dengyihao 已提交
3247
  pInfo->pResult = pBlock;
3248 3249 3250
  pInfo->seqLoadData = true;

  tsem_init(&pInfo->ready, 0, 0);
3251

dengyihao's avatar
dengyihao 已提交
3252
  pOperator->name = "ExchangeOperator";
X
Xiaoyu Wang 已提交
3253
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_EXCHANGE;
3254
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
3255 3256
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
3257
  pOperator->numOfExprs = pBlock->info.numOfCols;
dengyihao's avatar
dengyihao 已提交
3258
  pOperator->pTaskInfo = pTaskInfo;
3259

L
Liu Jicong 已提交
3260 3261
  pOperator->fpSet = createOperatorFpSet(prepareLoadRemoteData, doLoadRemoteData, NULL, NULL,
                                         destroyExchangeOperatorInfo, NULL, NULL, NULL);
3262
  pInfo->pTransporter = pTransporter;
3263

3264
  return pOperator;
H
Haojun Liao 已提交
3265

L
Liu Jicong 已提交
3266
_error:
H
Haojun Liao 已提交
3267
  if (pInfo != NULL) {
H
Haojun Liao 已提交
3268
    destroyExchangeOperatorInfo(pInfo, numOfSources);
H
Haojun Liao 已提交
3269 3270
  }

wafwerar's avatar
wafwerar 已提交
3271 3272
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
3273
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
H
Haojun Liao 已提交
3274
  return NULL;
3275 3276
}

dengyihao's avatar
dengyihao 已提交
3277 3278
static int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize,
                                const char* pKey);
3279

3280
static void destroySortedMergeOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
3281
  SSortedMergeOperatorInfo* pInfo = (SSortedMergeOperatorInfo*)param;
H
Haojun Liao 已提交
3282
  taosArrayDestroy(pInfo->pSortInfo);
3283 3284 3285
  taosArrayDestroy(pInfo->groupInfo);

  if (pInfo->pSortHandle != NULL) {
H
Haojun Liao 已提交
3286
    tsortDestroySortHandle(pInfo->pSortHandle);
3287 3288
  }

H
Haojun Liao 已提交
3289
  blockDataDestroy(pInfo->binfo.pRes);
H
Haojun Liao 已提交
3290
  cleanupAggSup(&pInfo->aggSup);
3291
}
H
Haojun Liao 已提交
3292

L
Liu Jicong 已提交
3293
static bool needToMerge(SSDataBlock* pBlock, SArray* groupInfo, char** buf, int32_t rowIndex) {
3294 3295 3296 3297
  size_t size = taosArrayGetSize(groupInfo);
  if (size == 0) {
    return true;
  }
3298

3299 3300
  for (int32_t i = 0; i < size; ++i) {
    int32_t* index = taosArrayGet(groupInfo, i);
3301

3302
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, *index);
L
Liu Jicong 已提交
3303
    bool             isNull = colDataIsNull(pColInfo, rowIndex, pBlock->info.rows, NULL);
3304

3305 3306 3307
    if ((isNull && buf[i] != NULL) || (!isNull && buf[i] == NULL)) {
      return false;
    }
3308

3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321
    char* pCell = colDataGetData(pColInfo, rowIndex);
    if (IS_VAR_DATA_TYPE(pColInfo->info.type)) {
      if (varDataLen(pCell) != varDataLen(buf[i])) {
        return false;
      } else {
        if (memcmp(varDataVal(pCell), varDataVal(buf[i]), varDataLen(pCell)) != 0) {
          return false;
        }
      }
    } else {
      if (memcmp(pCell, buf[i], pColInfo->info.bytes) != 0) {
        return false;
      }
3322 3323 3324
    }
  }

3325
  return 0;
3326 3327
}

L
Liu Jicong 已提交
3328 3329 3330
static void doMergeResultImpl(SSortedMergeOperatorInfo* pInfo, SqlFunctionCtx* pCtx, int32_t numOfExpr,
                              int32_t rowIndex) {
  for (int32_t j = 0; j < numOfExpr; ++j) {  // TODO set row index
3331
//    pCtx[j].startRow = rowIndex;
3332 3333
  }

3334 3335
  for (int32_t j = 0; j < numOfExpr; ++j) {
    int32_t functionId = pCtx[j].functionId;
L
Liu Jicong 已提交
3336 3337 3338 3339 3340 3341 3342 3343 3344
    //    pCtx[j].fpSet->addInput(&pCtx[j]);

    //    if (functionId < 0) {
    //      SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
    //      doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE);
    //    } else {
    //      assert(!TSDB_FUNC_IS_SCALAR(functionId));
    //      aAggs[functionId].mergeFunc(&pCtx[j]);
    //    }
3345
  }
3346
}
3347

L
Liu Jicong 已提交
3348 3349
static void doFinalizeResultImpl(SqlFunctionCtx* pCtx, int32_t numOfExpr) {
  for (int32_t j = 0; j < numOfExpr; ++j) {
3350 3351 3352 3353
    int32_t functionId = pCtx[j].functionId;
    //    if (functionId == FUNC_TAG_DUMMY || functionId == FUNC_TS_DUMMY) {
    //      continue;
    //    }
3354

3355 3356 3357 3358
    //    if (functionId < 0) {
    //      SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1);
    //      doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
    //    } else {
dengyihao's avatar
dengyihao 已提交
3359
    //    pCtx[j].fpSet.finalize(&pCtx[j]);
3360 3361
  }
}
3362

3363
static bool saveCurrentTuple(char** rowColData, SArray* pColumnList, SSDataBlock* pBlock, int32_t rowIndex) {
L
Liu Jicong 已提交
3364
  int32_t size = (int32_t)taosArrayGetSize(pColumnList);
3365

L
Liu Jicong 已提交
3366 3367
  for (int32_t i = 0; i < size; ++i) {
    int32_t*         index = taosArrayGet(pColumnList, i);
3368
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, *index);
H
Haojun Liao 已提交
3369

3370 3371 3372
    char* data = colDataGetData(pColInfo, rowIndex);
    memcpy(rowColData[i], data, colDataGetLength(pColInfo, rowIndex));
  }
3373

3374 3375
  return true;
}
3376

3377 3378
static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock* pBlock) {
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
3379

3380
  SqlFunctionCtx* pCtx = pInfo->binfo.pCtx;
L
Liu Jicong 已提交
3381
  for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
3382
//    pCtx[i].size = 1;
3383
  }
3384

L
Liu Jicong 已提交
3385
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
3386 3387 3388 3389 3390 3391 3392 3393 3394
    if (!pInfo->hasGroupVal) {
      ASSERT(i == 0);
      doMergeResultImpl(pInfo, pCtx, numOfExpr, i);
      pInfo->hasGroupVal = saveCurrentTuple(pInfo->groupVal, pInfo->groupInfo, pBlock, i);
    } else {
      if (needToMerge(pBlock, pInfo->groupInfo, pInfo->groupVal, i)) {
        doMergeResultImpl(pInfo, pCtx, numOfExpr, i);
      } else {
        doFinalizeResultImpl(pCtx, numOfExpr);
3395 3396
        int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfExprs, NULL);
        //        setTagValueForMultipleRows(pCtx, pOperator->numOfExprs, numOfRows);
3397

3398
        // TODO check for available buffer;
H
Haojun Liao 已提交
3399

3400 3401 3402 3403 3404
        // next group info data
        pInfo->binfo.pRes->info.rows += numOfRows;
        for (int32_t j = 0; j < numOfExpr; ++j) {
          if (pCtx[j].functionId < 0) {
            continue;
3405
          }
3406

H
Haojun Liao 已提交
3407
          pCtx[j].fpSet.process(&pCtx[j]);
3408
        }
3409 3410 3411

        doMergeResultImpl(pInfo, pCtx, numOfExpr, i);
        pInfo->hasGroupVal = saveCurrentTuple(pInfo->groupVal, pInfo->groupInfo, pBlock, i);
H
Haojun Liao 已提交
3412
      }
3413 3414 3415 3416
    }
  }
}

3417 3418
static SSDataBlock* doMerge(SOperatorInfo* pOperator) {
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
L
Liu Jicong 已提交
3419
  SSortHandle*              pHandle = pInfo->pSortHandle;
3420

3421
  SSDataBlock* pDataBlock = createOneDataBlock(pInfo->binfo.pRes, false);
3422
  blockDataEnsureCapacity(pDataBlock, pOperator->resultInfo.capacity);
3423

L
Liu Jicong 已提交
3424
  while (1) {
3425
    blockDataCleanup(pDataBlock);
3426
    while (1) {
H
Haojun Liao 已提交
3427
      STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
3428 3429
      if (pTupleHandle == NULL) {
        break;
3430
      }
3431

3432 3433
      // build datablock for merge for one group
      appendOneRowToDataBlock(pDataBlock, pTupleHandle);
3434
      if (pDataBlock->info.rows >= pOperator->resultInfo.capacity) {
3435 3436
        break;
      }
3437
    }
3438

3439 3440 3441
    if (pDataBlock->info.rows == 0) {
      break;
    }
3442

3443
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pDataBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
L
Liu Jicong 已提交
3444 3445
    //  updateOutputBuf(&pInfo->binfo, &pAggInfo->bufCapacity, pBlock->info.rows * pAggInfo->resultRowFactor,
    //  pOperator->pRuntimeEnv, true);
3446
    doMergeImpl(pOperator, pOperator->numOfExprs, pDataBlock);
3447 3448
    // flush to tuple store, and after all data have been handled, return to upstream node or sink node
  }
3449

3450 3451 3452
  doFinalizeResultImpl(pInfo->binfo.pCtx, pOperator->numOfExprs);
  int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfExprs, NULL);
  //        setTagValueForMultipleRows(pCtx, pOperator->numOfExprs, numOfRows);
3453

3454
  // TODO check for available buffer;
3455

3456 3457
  // next group info data
  pInfo->binfo.pRes->info.rows += numOfRows;
L
Liu Jicong 已提交
3458
  return (pInfo->binfo.pRes->info.rows > 0) ? pInfo->binfo.pRes : NULL;
3459
}
3460

3461
static SSDataBlock* doSortedMerge(SOperatorInfo* pOperator) {
3462 3463
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3464 3465
  }

L
Liu Jicong 已提交
3466
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
3467
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
3468
  if (pOperator->status == OP_RES_TO_RETURN) {
3469
    return getSortedBlockData(pInfo->pSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity, NULL);
3470 3471
  }

3472
  int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
dengyihao's avatar
dengyihao 已提交
3473 3474
  pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, NULL, SORT_MULTISOURCE_MERGE, pInfo->bufPageSize,
                                             numOfBufPage, pInfo->binfo.pRes, "GET_TASKID(pTaskInfo)");
H
Haojun Liao 已提交
3475

3476
  tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock, NULL, NULL);
3477

L
Liu Jicong 已提交
3478
  for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
wmmhello's avatar
wmmhello 已提交
3479
    SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
H
Haojun Liao 已提交
3480
    ps->param = pOperator->pDownstream[i];
H
Haojun Liao 已提交
3481
    tsortAddSource(pInfo->pSortHandle, ps);
3482 3483
  }

H
Haojun Liao 已提交
3484
  int32_t code = tsortOpen(pInfo->pSortHandle);
3485
  if (code != TSDB_CODE_SUCCESS) {
3486
    longjmp(pTaskInfo->env, terrno);
3487 3488
  }

H
Haojun Liao 已提交
3489
  pOperator->status = OP_RES_TO_RETURN;
3490
  return doMerge(pOperator);
3491
}
3492

L
Liu Jicong 已提交
3493 3494
static int32_t initGroupCol(SExprInfo* pExprInfo, int32_t numOfCols, SArray* pGroupInfo,
                            SSortedMergeOperatorInfo* pInfo) {
3495 3496
  if (pGroupInfo == NULL || taosArrayGetSize(pGroupInfo) == 0) {
    return 0;
H
Haojun Liao 已提交
3497 3498
  }

3499 3500 3501 3502 3503 3504 3505 3506
  int32_t len = 0;
  SArray* plist = taosArrayInit(3, sizeof(SColumn));
  pInfo->groupInfo = taosArrayInit(3, sizeof(int32_t));

  if (plist == NULL || pInfo->groupInfo == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

L
Liu Jicong 已提交
3507 3508
  size_t numOfGroupCol = taosArrayGetSize(pInfo->groupInfo);
  for (int32_t i = 0; i < numOfGroupCol; ++i) {
3509
    SColumn* pCol = taosArrayGet(pGroupInfo, i);
L
Liu Jicong 已提交
3510
    for (int32_t j = 0; j < numOfCols; ++j) {
H
Haojun Liao 已提交
3511
      SExprInfo* pe = &pExprInfo[j];
3512
      if (pe->base.resSchema.slotId == pCol->colId) {
3513 3514
        taosArrayPush(plist, pCol);
        taosArrayPush(pInfo->groupInfo, &j);
H
Haojun Liao 已提交
3515
        len += pCol->bytes;
3516 3517
        break;
      }
H
Haojun Liao 已提交
3518 3519 3520
    }
  }

3521
  ASSERT(taosArrayGetSize(pGroupInfo) == taosArrayGetSize(plist));
H
Haojun Liao 已提交
3522

wafwerar's avatar
wafwerar 已提交
3523
  pInfo->groupVal = taosMemoryCalloc(1, (POINTER_BYTES * numOfGroupCol + len));
3524 3525 3526 3527
  if (pInfo->groupVal == NULL) {
    taosArrayDestroy(plist);
    return TSDB_CODE_OUT_OF_MEMORY;
  }
H
Haojun Liao 已提交
3528

3529
  int32_t offset = 0;
L
Liu Jicong 已提交
3530 3531
  char*   start = (char*)(pInfo->groupVal + (POINTER_BYTES * numOfGroupCol));
  for (int32_t i = 0; i < numOfGroupCol; ++i) {
3532 3533
    pInfo->groupVal[i] = start + offset;
    SColumn* pCol = taosArrayGet(plist, i);
H
Haojun Liao 已提交
3534
    offset += pCol->bytes;
3535
  }
H
Haojun Liao 已提交
3536

3537
  taosArrayDestroy(plist);
H
Haojun Liao 已提交
3538

3539 3540
  return TSDB_CODE_SUCCESS;
}
H
Haojun Liao 已提交
3541

L
Liu Jicong 已提交
3542 3543 3544
SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t numOfDownstream, SExprInfo* pExprInfo,
                                             int32_t num, SArray* pSortInfo, SArray* pGroupInfo,
                                             SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
3545
  SSortedMergeOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortedMergeOperatorInfo));
L
Liu Jicong 已提交
3546
  SOperatorInfo*            pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3547
  if (pInfo == NULL || pOperator == NULL) {
3548
    goto _error;
3549
  }
H
Haojun Liao 已提交
3550

3551
  pInfo->binfo.pCtx = createSqlFunctionCtx(pExprInfo, num, &pInfo->binfo.rowCellInfoOffset);
3552
  initResultRowInfo(&pInfo->binfo.resultRowInfo, (int32_t)1);
H
Haojun Liao 已提交
3553

3554 3555 3556
  if (pInfo->binfo.pCtx == NULL || pInfo->binfo.pRes == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3557

dengyihao's avatar
dengyihao 已提交
3558
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
3559
  int32_t code = doInitAggInfoSup(&pInfo->aggSup, pInfo->binfo.pCtx, num, keyBufSize, pTaskInfo->id.str);
3560 3561 3562
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
H
Haojun Liao 已提交
3563

H
Haojun Liao 已提交
3564
  setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, num, pTaskInfo);
H
Haojun Liao 已提交
3565
  code = initGroupCol(pExprInfo, num, pGroupInfo, pInfo);
3566 3567 3568
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
H
Haojun Liao 已提交
3569

L
Liu Jicong 已提交
3570 3571 3572 3573 3574
  //  pInfo->resultRowFactor = (int32_t)(getRowNumForMultioutput(pRuntimeEnv->pQueryAttr,
  //      pRuntimeEnv->pQueryAttr->topBotQuery, false));
  pInfo->sortBufSize = 1024 * 16;  // 1MB
  pInfo->bufPageSize = 1024;
  pInfo->pSortInfo = pSortInfo;
H
Haojun Liao 已提交
3575

3576
  pOperator->resultInfo.capacity = blockDataGetCapacityInRow(pInfo->binfo.pRes, pInfo->bufPageSize);
H
Haojun Liao 已提交
3577

L
Liu Jicong 已提交
3578
  pOperator->name = "SortedMerge";
X
Xiaoyu Wang 已提交
3579
  // pOperator->operatorType = OP_SortedMerge;
3580
  pOperator->blocking = true;
L
Liu Jicong 已提交
3581 3582
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
3583
  pOperator->numOfExprs = num;
L
Liu Jicong 已提交
3584
  pOperator->pExpr = pExprInfo;
H
Haojun Liao 已提交
3585

L
Liu Jicong 已提交
3586
  pOperator->pTaskInfo = pTaskInfo;
H
Haojun Liao 已提交
3587

3588 3589
  pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doSortedMerge, NULL, NULL, destroySortedMergeOperatorInfo,
                                         NULL, NULL, NULL);
3590 3591 3592
  code = appendDownstream(pOperator, downstream, numOfDownstream);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
3593
  }
H
Haojun Liao 已提交
3594

3595
  return pOperator;
H
Haojun Liao 已提交
3596

L
Liu Jicong 已提交
3597
_error:
3598
  if (pInfo != NULL) {
H
Haojun Liao 已提交
3599
    destroySortedMergeOperatorInfo(pInfo, num);
H
Haojun Liao 已提交
3600 3601
  }

wafwerar's avatar
wafwerar 已提交
3602 3603
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
3604 3605
  terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
  return NULL;
H
Haojun Liao 已提交
3606 3607
}

3608
int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t *order, int32_t* scanFlag) {
3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619
  // todo add more information about exchange operation
  if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE) {
    *order = TSDB_ORDER_ASC;
    *scanFlag = MAIN_SCAN;
    return TSDB_CODE_SUCCESS;
  } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) {
    STableScanInfo* pTableScanInfo = pOperator->info;
    *order = pTableScanInfo->cond.order;
    *scanFlag = pTableScanInfo->scanFlag;
    return TSDB_CODE_SUCCESS;
  } else {
H
Haojun Liao 已提交
3620
    if (pOperator->pDownstream == NULL || pOperator->pDownstream[0] == NULL) {
3621
      return TSDB_CODE_INVALID_PARA;
H
Haojun Liao 已提交
3622
    } else {
3623
      return getTableScanInfo(pOperator->pDownstream[0], order, scanFlag);
3624 3625 3626
    }
  }
}
3627 3628

// this is a blocking operator
L
Liu Jicong 已提交
3629
static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
H
Haojun Liao 已提交
3630 3631
  if (OPTR_IS_OPENED(pOperator)) {
    return TSDB_CODE_SUCCESS;
3632 3633
  }

H
Haojun Liao 已提交
3634
  SExecTaskInfo*    pTaskInfo = pOperator->pTaskInfo;
3635
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
3636

dengyihao's avatar
dengyihao 已提交
3637
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;
H
Haojun Liao 已提交
3638
  SOperatorInfo* downstream = pOperator->pDownstream[0];
3639

3640 3641 3642
  int32_t order = TSDB_ORDER_ASC;
  int32_t scanFlag = MAIN_SCAN;

H
Haojun Liao 已提交
3643
  while (1) {
H
Haojun Liao 已提交
3644
    publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
3645
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
3646
    publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
3647 3648 3649 3650 3651

    if (pBlock == NULL) {
      break;
    }

3652 3653 3654 3655
    int32_t code = getTableScanInfo(pOperator, &order, &scanFlag);
    if (code != TSDB_CODE_SUCCESS) {
      longjmp(pTaskInfo->env, code);
    }
3656

3657 3658
    // there is an scalar expression that needs to be calculated before apply the group aggregation.
    if (pAggInfo->pScalarExprInfo != NULL) {
3659
      code = projectApplyFunctions(pAggInfo->pScalarExprInfo, pBlock, pBlock, pAggInfo->pScalarCtx,
3660
                                   pAggInfo->numOfScalarExpr, NULL);
3661
      if (code != TSDB_CODE_SUCCESS) {
3662
        longjmp(pTaskInfo->env, code);
3663
      }
3664 3665
    }

3666
    // the pDataBlock are always the same one, no need to call this again
3667
    setExecutionContext(pOperator->numOfExprs, pBlock->info.groupId, pTaskInfo, pAggInfo);
3668
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order, scanFlag, true);
3669 3670 3671 3672
    code = doAggregateImpl(pOperator, 0, pInfo->pCtx);
    if (code != 0) {
      longjmp(pTaskInfo->env, code);
    }
3673

dengyihao's avatar
dengyihao 已提交
3674
#if 0  // test for encode/decode result info
3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
    if(pOperator->encodeResultRow){
      char *result = NULL;
      int32_t length = 0;
      SAggSupporter   *pSup = &pAggInfo->aggSup;
      pOperator->encodeResultRow(pOperator, pSup, pInfo, &result, &length);
      taosHashClear(pSup->pResultRowHashTable);
      pInfo->resultRowInfo.size = 0;
      pOperator->decodeResultRow(pOperator, pSup, pInfo, result, length);
      if(result){
        taosMemoryFree(result);
      }
3686
    }
3687
#endif
3688 3689
  }

H
Haojun Liao 已提交
3690
  closeAllResultRows(&pAggInfo->binfo.resultRowInfo);
3691 3692
  finalizeMultiTupleQueryResult(pOperator->numOfExprs, pAggInfo->aggSup.pResultBuf, &pAggInfo->binfo.resultRowInfo,
                                pAggInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
3693

3694
  initGroupedResultInfo(&pAggInfo->groupResInfo, pAggInfo->aggSup.pResultRowHashTable, 0);
H
Haojun Liao 已提交
3695 3696 3697 3698
  OPTR_SET_OPENED(pOperator);
  return TSDB_CODE_SUCCESS;
}

3699
static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
3700
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
3701 3702 3703 3704 3705 3706
  SOptrBasicInfo*   pInfo = &pAggInfo->binfo;

  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

L
Liu Jicong 已提交
3707
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3708
  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
H
Haojun Liao 已提交
3709 3710 3711 3712
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
    return NULL;
  }

H
Haojun Liao 已提交
3713
  blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
3714
  doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
3715 3716 3717
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pAggInfo->groupResInfo)) {
    doSetOperatorCompleted(pOperator);
  }
3718

H
Haojun Liao 已提交
3719
  doSetOperatorCompleted(pOperator);
L
Liu Jicong 已提交
3720
  return (blockDataGetNumOfRows(pInfo->pRes) != 0) ? pInfo->pRes : NULL;
3721 3722
}

dengyihao's avatar
dengyihao 已提交
3723 3724
void aggEncodeResultRow(SOperatorInfo* pOperator, SAggSupporter* pSup, SOptrBasicInfo* pInfo, char** result,
                        int32_t* length) {
wmmhello's avatar
wmmhello 已提交
3725
  int32_t size = taosHashGetSize(pSup->pResultRowHashTable);
3726
  size_t  keyLen = sizeof(uint64_t) * 2;  // estimate the key length
wmmhello's avatar
wmmhello 已提交
3727
  int32_t totalSize = sizeof(int32_t) + size * (sizeof(int32_t) + keyLen + sizeof(int32_t) + pSup->resultRowSize);
wafwerar's avatar
wafwerar 已提交
3728
  *result = taosMemoryCalloc(1, totalSize);
L
Liu Jicong 已提交
3729
  if (*result == NULL) {
3730
    longjmp(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
wmmhello's avatar
wmmhello 已提交
3731 3732 3733
  }
  *(int32_t*)(*result) = size;
  int32_t offset = sizeof(int32_t);
3734 3735

  // prepare memory
3736
  SResultRowPosition* pos = &pInfo->resultRowInfo.cur;
dengyihao's avatar
dengyihao 已提交
3737 3738
  void*               pPage = getBufPage(pSup->pResultBuf, pos->pageId);
  SResultRow*         pRow = (SResultRow*)((char*)pPage + pos->offset);
3739 3740 3741
  setBufPageDirty(pPage, true);
  releaseBufPage(pSup->pResultBuf, pPage);

dengyihao's avatar
dengyihao 已提交
3742
  void* pIter = taosHashIterate(pSup->pResultRowHashTable, NULL);
wmmhello's avatar
wmmhello 已提交
3743
  while (pIter) {
dengyihao's avatar
dengyihao 已提交
3744
    void*               key = taosHashGetKey(pIter, &keyLen);
3745
    SResultRowPosition* p1 = (SResultRowPosition*)pIter;
3746

dengyihao's avatar
dengyihao 已提交
3747
    pPage = (SFilePage*)getBufPage(pSup->pResultBuf, p1->pageId);
3748
    pRow = (SResultRow*)((char*)pPage + p1->offset);
3749 3750
    setBufPageDirty(pPage, true);
    releaseBufPage(pSup->pResultBuf, pPage);
wmmhello's avatar
wmmhello 已提交
3751 3752 3753

    // recalculate the result size
    int32_t realTotalSize = offset + sizeof(int32_t) + keyLen + sizeof(int32_t) + pSup->resultRowSize;
L
Liu Jicong 已提交
3754 3755 3756
    if (realTotalSize > totalSize) {
      char* tmp = taosMemoryRealloc(*result, realTotalSize);
      if (tmp == NULL) {
wmmhello's avatar
wmmhello 已提交
3757
        terrno = TSDB_CODE_OUT_OF_MEMORY;
wafwerar's avatar
wafwerar 已提交
3758
        taosMemoryFree(*result);
wmmhello's avatar
wmmhello 已提交
3759
        *result = NULL;
3760
        longjmp(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
L
Liu Jicong 已提交
3761
      } else {
wmmhello's avatar
wmmhello 已提交
3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773
        *result = tmp;
      }
    }
    // save key
    *(int32_t*)(*result + offset) = keyLen;
    offset += sizeof(int32_t);
    memcpy(*result + offset, key, keyLen);
    offset += keyLen;

    // save value
    *(int32_t*)(*result + offset) = pSup->resultRowSize;
    offset += sizeof(int32_t);
3774
    memcpy(*result + offset, pRow, pSup->resultRowSize);
wmmhello's avatar
wmmhello 已提交
3775 3776 3777 3778 3779
    offset += pSup->resultRowSize;

    pIter = taosHashIterate(pSup->pResultRowHashTable, pIter);
  }

L
Liu Jicong 已提交
3780
  if (length) {
wmmhello's avatar
wmmhello 已提交
3781 3782 3783 3784 3785
    *length = offset;
  }
  return;
}

dengyihao's avatar
dengyihao 已提交
3786 3787
bool aggDecodeResultRow(SOperatorInfo* pOperator, SAggSupporter* pSup, SOptrBasicInfo* pInfo, char* result,
                        int32_t length) {
L
Liu Jicong 已提交
3788
  if (!result || length <= 0) {
wmmhello's avatar
wmmhello 已提交
3789 3790 3791 3792 3793 3794 3795
    return false;
  }

  //  int32_t size = taosHashGetSize(pSup->pResultRowHashTable);
  int32_t count = *(int32_t*)(result);

  int32_t offset = sizeof(int32_t);
L
Liu Jicong 已提交
3796
  while (count-- > 0 && length > offset) {
wmmhello's avatar
wmmhello 已提交
3797 3798 3799
    int32_t keyLen = *(int32_t*)(result + offset);
    offset += sizeof(int32_t);

L
Liu Jicong 已提交
3800 3801 3802
    uint64_t    tableGroupId = *(uint64_t*)(result + offset);
    SResultRow* resultRow = getNewResultRow_rv(pSup->pResultBuf, tableGroupId, pSup->resultRowSize);
    if (!resultRow) {
3803
      longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3804
    }
3805

wmmhello's avatar
wmmhello 已提交
3806
    // add a new result set for a new group
3807 3808
    SResultRowPosition pos = {.pageId = resultRow->pageId, .offset = resultRow->offset};
    taosHashPut(pSup->pResultRowHashTable, result + offset, keyLen, &pos, sizeof(SResultRowPosition));
wmmhello's avatar
wmmhello 已提交
3809 3810 3811

    offset += keyLen;
    int32_t valueLen = *(int32_t*)(result + offset);
L
Liu Jicong 已提交
3812
    if (valueLen != pSup->resultRowSize) {
3813
      longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3814 3815 3816 3817 3818 3819 3820 3821 3822 3823
    }
    offset += sizeof(int32_t);
    int32_t pageId = resultRow->pageId;
    int32_t pOffset = resultRow->offset;
    memcpy(resultRow, result + offset, valueLen);
    resultRow->pageId = pageId;
    resultRow->offset = pOffset;
    offset += valueLen;

    initResultRow(resultRow);
3824
    prepareResultListBuffer(&pInfo->resultRowInfo, pOperator->pTaskInfo->env);
dengyihao's avatar
dengyihao 已提交
3825
    //    pInfo->resultRowInfo.cur = pInfo->resultRowInfo.size;
L
Liu Jicong 已提交
3826 3827
    //    pInfo->resultRowInfo.pPosition[pInfo->resultRowInfo.size++] =
    //        (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
dengyihao's avatar
dengyihao 已提交
3828
    pInfo->resultRowInfo.cur = (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
wmmhello's avatar
wmmhello 已提交
3829 3830
  }

L
Liu Jicong 已提交
3831
  if (offset != length) {
3832
    longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3833 3834 3835 3836
  }
  return true;
}

3837 3838
enum {
  PROJECT_RETRIEVE_CONTINUE = 0x1,
L
Liu Jicong 已提交
3839
  PROJECT_RETRIEVE_DONE = 0x2,
3840 3841 3842 3843 3844
};

static int32_t handleLimitOffset(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
  SProjectOperatorInfo* pProjectInfo = pOperator->info;
  SOptrBasicInfo*       pInfo = &pProjectInfo->binfo;
L
Liu Jicong 已提交
3845
  SSDataBlock*          pRes = pInfo->pRes;
3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893

  if (pProjectInfo->curSOffset > 0) {
    if (pProjectInfo->groupId == 0) {  // it is the first group
      pProjectInfo->groupId = pBlock->info.groupId;
      blockDataCleanup(pInfo->pRes);
      return PROJECT_RETRIEVE_CONTINUE;
    } else if (pProjectInfo->groupId != pBlock->info.groupId) {
      pProjectInfo->curSOffset -= 1;

      // ignore data block in current group
      if (pProjectInfo->curSOffset > 0) {
        blockDataCleanup(pInfo->pRes);
        return PROJECT_RETRIEVE_CONTINUE;
      }
    }

    // set current group id of the project operator
    pProjectInfo->groupId = pBlock->info.groupId;
  }

  if (pProjectInfo->groupId != 0 && pProjectInfo->groupId != pBlock->info.groupId) {
    pProjectInfo->curGroupOutput += 1;
    if ((pProjectInfo->slimit.limit > 0) && (pProjectInfo->slimit.limit <= pProjectInfo->curGroupOutput)) {
      pOperator->status = OP_EXEC_DONE;
      blockDataCleanup(pRes);

      return PROJECT_RETRIEVE_DONE;
    }

    // reset the value for a new group data
    pProjectInfo->curOffset = 0;
    pProjectInfo->curOutput = 0;
  }

  // here we reach the start position, according to the limit/offset requirements.

  // set current group id
  pProjectInfo->groupId = pBlock->info.groupId;

  if (pProjectInfo->curOffset >= pRes->info.rows) {
    pProjectInfo->curOffset -= pRes->info.rows;
    blockDataCleanup(pRes);
    return PROJECT_RETRIEVE_CONTINUE;
  } else if (pProjectInfo->curOffset < pRes->info.rows && pProjectInfo->curOffset > 0) {
    blockDataTrimFirstNRows(pRes, pProjectInfo->curOffset);
    pProjectInfo->curOffset = 0;
  }

3894 3895 3896
  // check for the limitation in each group
  if (pProjectInfo->limit.limit > 0 && pProjectInfo->curOutput + pRes->info.rows >= pProjectInfo->limit.limit) {
    pRes->info.rows = (int32_t)(pProjectInfo->limit.limit - pProjectInfo->curOutput);
3897 3898 3899 3900 3901

    if (pProjectInfo->slimit.limit == -1 || pProjectInfo->slimit.limit <= pProjectInfo->curGroupOutput) {
      pOperator->status = OP_EXEC_DONE;
    }

3902
    return PROJECT_RETRIEVE_DONE;
3903
  }
3904

3905
  // todo optimize performance
3906 3907
  // If there are slimit/soffset value exists, multi-round result can not be packed into one group, since the
  // they may not belong to the same group the limit/offset value is not valid in this case.
L
Liu Jicong 已提交
3908 3909
  if (pRes->info.rows >= pOperator->resultInfo.threshold || pProjectInfo->slimit.offset != -1 ||
      pProjectInfo->slimit.limit != -1) {
3910
    return PROJECT_RETRIEVE_DONE;
L
Liu Jicong 已提交
3911
  } else {  // not full enough, continue to accumulate the output data in the buffer.
3912 3913 3914 3915
    return PROJECT_RETRIEVE_CONTINUE;
  }
}

3916
static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
3917
  SProjectOperatorInfo* pProjectInfo = pOperator->info;
L
Liu Jicong 已提交
3918
  SOptrBasicInfo*       pInfo = &pProjectInfo->binfo;
3919 3920

  SSDataBlock* pRes = pInfo->pRes;
3921
  blockDataCleanup(pRes);
3922

3923
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3924 3925 3926
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
3927

H
Haojun Liao 已提交
3928
#if 0
3929 3930 3931 3932 3933
  if (pProjectInfo->existDataBlock) {  // TODO refactor
    SSDataBlock* pBlock = pProjectInfo->existDataBlock;
    pProjectInfo->existDataBlock = NULL;

    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
3934
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, TSDB_ORDER_ASC);
3935

H
Haojun Liao 已提交
3936
    blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
3937
    projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfExprs);
L
Liu Jicong 已提交
3938
    if (pRes->info.rows >= pProjectInfo->binfo.capacity * 0.8) {
3939 3940
      copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfExprs);
      resetResultRowEntryResult(pInfo->pCtx, pOperator->numOfExprs);
3941 3942 3943
      return pRes;
    }
  }
H
Haojun Liao 已提交
3944
#endif
3945

3946 3947 3948
  int32_t order = 0;
  int32_t scanFlag = 0;

H
Haojun Liao 已提交
3949 3950
  SOperatorInfo* downstream = pOperator->pDownstream[0];

L
Liu Jicong 已提交
3951
  while (1) {
H
Haojun Liao 已提交
3952
    // The downstream exec may change the value of the newgroup, so use a local variable instead.
H
Haojun Liao 已提交
3953
    publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
3954
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
3955
    publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
3956 3957

    if (pBlock == NULL) {
3958
      setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
3959 3960 3961 3962
      break;
    }

    // Return result of the previous group in the firstly.
3963
    if (false) {
3964 3965 3966
      if (pRes->info.rows > 0) {
        pProjectInfo->existDataBlock = pBlock;
        break;
L
Liu Jicong 已提交
3967
      } else {  // init output buffer for a new group data
3968
        initCtxOutputBuffer(pInfo->pCtx, pOperator->numOfExprs);
3969 3970 3971 3972
      }
    }

    // the pDataBlock are always the same one, no need to call this again
3973
    int32_t code = getTableScanInfo(pOperator->pDownstream[0], &order, &scanFlag);
3974

3975
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order, scanFlag, false);
3976 3977
    blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);

3978 3979 3980
    code = projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfExprs, pProjectInfo->pPseudoColInfo);
    if (code != TSDB_CODE_SUCCESS) {
      longjmp(pTaskInfo->env, code);
3981 3982
    }

3983 3984
    int32_t status = handleLimitOffset(pOperator, pBlock);
    if (status == PROJECT_RETRIEVE_CONTINUE) {
H
Haojun Liao 已提交
3985
      continue;
L
Liu Jicong 已提交
3986
    } else if (status == PROJECT_RETRIEVE_DONE) {
3987 3988 3989
      break;
    }
  }
dengyihao's avatar
dengyihao 已提交
3990

H
Haojun Liao 已提交
3991
  pProjectInfo->curOutput += pInfo->pRes->info.rows;
H
Haojun Liao 已提交
3992

3993
  //  copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfExprs);
L
Liu Jicong 已提交
3994
  return (pInfo->pRes->info.rows > 0) ? pInfo->pRes : NULL;
3995 3996
}

L
Liu Jicong 已提交
3997 3998
static void doHandleRemainBlockForNewGroupImpl(SFillOperatorInfo* pInfo, SResultInfo* pResultInfo, bool* newgroup,
                                               SExecTaskInfo* pTaskInfo) {
3999
  pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows;
H
Haojun Liao 已提交
4000

L
Liu Jicong 已提交
4001 4002
  int64_t ekey = Q_STATUS_EQUAL(pTaskInfo->status, TASK_COMPLETED) ? pTaskInfo->window.ekey
                                                                   : pInfo->existNewGroupBlock->info.window.ekey;
4003 4004
  taosResetFillInfo(pInfo->pFillInfo, getFillInfoStart(pInfo->pFillInfo));

4005
  taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
4006 4007
  taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

4008
  doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pResultInfo->capacity);
4009 4010 4011 4012
  pInfo->existNewGroupBlock = NULL;
  *newgroup = true;
}

L
Liu Jicong 已提交
4013 4014
static void doHandleRemainBlockFromNewGroup(SFillOperatorInfo* pInfo, SResultInfo* pResultInfo, bool* newgroup,
                                            SExecTaskInfo* pTaskInfo) {
4015 4016
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
    *newgroup = false;
4017
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pResultInfo->capacity);
H
Haojun Liao 已提交
4018
    if (pInfo->pRes->info.rows > pResultInfo->threshold || (!pInfo->multigroupResult)) {
4019 4020 4021 4022 4023 4024
      return;
    }
  }

  // handle the cached new group data block
  if (pInfo->existNewGroupBlock) {
4025
    doHandleRemainBlockForNewGroupImpl(pInfo, pResultInfo, newgroup, pTaskInfo);
4026 4027 4028
  }
}

4029
static SSDataBlock* doFill(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
4030 4031
  SFillOperatorInfo* pInfo = pOperator->info;
  SExecTaskInfo*     pTaskInfo = pOperator->pTaskInfo;
4032

H
Haojun Liao 已提交
4033
  SResultInfo* pResultInfo = &pOperator->resultInfo;
4034 4035 4036
  SSDataBlock* pResBlock = pInfo->pRes;

  blockDataCleanup(pResBlock);
4037 4038 4039 4040
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

4041
  // todo handle different group data interpolation
X
Xiaoyu Wang 已提交
4042 4043
  bool  n = false;
  bool* newgroup = &n;
4044
  doHandleRemainBlockFromNewGroup(pInfo, pResultInfo, newgroup, pTaskInfo);
4045 4046
  if (pResBlock->info.rows > pResultInfo->threshold || (!pInfo->multigroupResult && pResBlock->info.rows > 0)) {
    return pResBlock;
H
Haojun Liao 已提交
4047
  }
4048

H
Haojun Liao 已提交
4049
  SOperatorInfo* pDownstream = pOperator->pDownstream[0];
L
Liu Jicong 已提交
4050
  while (1) {
H
Haojun Liao 已提交
4051
    publishOperatorProfEvent(pDownstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
4052
    SSDataBlock* pBlock = pDownstream->fpSet.getNextFn(pDownstream);
H
Haojun Liao 已提交
4053
    publishOperatorProfEvent(pDownstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064

    if (*newgroup) {
      assert(pBlock != NULL);
    }

    if (*newgroup && pInfo->totalInputRows > 0) {  // there are already processed current group data block
      pInfo->existNewGroupBlock = pBlock;
      *newgroup = false;

      // Fill the previous group data block, before handle the data block of new group.
      // Close the fill operation for previous group data block
4065
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
4066 4067 4068 4069 4070 4071 4072
    } else {
      if (pBlock == NULL) {
        if (pInfo->totalInputRows == 0) {
          pOperator->status = OP_EXEC_DONE;
          return NULL;
        }

4073
        taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
4074 4075 4076 4077 4078 4079 4080
      } else {
        pInfo->totalInputRows += pBlock->info.rows;
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
    }

4081 4082
    blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pResBlock, pOperator->resultInfo.capacity);
4083 4084

    // current group has no more result to return
4085
    if (pResBlock->info.rows > 0) {
4086 4087
      // 1. The result in current group not reach the threshold of output result, continue
      // 2. If multiple group results existing in one SSDataBlock is not allowed, return immediately
4088 4089
      if (pResBlock->info.rows > pResultInfo->threshold || pBlock == NULL || (!pInfo->multigroupResult)) {
        return pResBlock;
4090 4091
      }

4092
      doHandleRemainBlockFromNewGroup(pInfo, pResultInfo, newgroup, pTaskInfo);
4093 4094
      if (pResBlock->info.rows > pOperator->resultInfo.threshold || pBlock == NULL) {
        return pResBlock;
4095 4096 4097
      }
    } else if (pInfo->existNewGroupBlock) {  // try next group
      assert(pBlock != NULL);
4098
      doHandleRemainBlockForNewGroupImpl(pInfo, pResultInfo, newgroup, pTaskInfo);
4099 4100
      if (pResBlock->info.rows > pResultInfo->threshold) {
        return pResBlock;
4101 4102 4103 4104 4105 4106 4107 4108
      }
    } else {
      return NULL;
    }
  }
}

// todo set the attribute of query scan count
H
Haojun Liao 已提交
4109
static int32_t getNumOfScanTimes(STaskAttr* pQueryAttr) {
L
Liu Jicong 已提交
4110
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124
    int32_t functionId = getExprFunctionId(&pQueryAttr->pExpr1[i]);
    if (functionId == FUNCTION_STDDEV || functionId == FUNCTION_PERCT) {
      return 2;
    }
  }

  return 1;
}

static void destroyOperatorInfo(SOperatorInfo* pOperator) {
  if (pOperator == NULL) {
    return;
  }

4125
  if (pOperator->fpSet.closeFn != NULL) {
4126
    pOperator->fpSet.closeFn(pOperator->info, pOperator->numOfExprs);
4127 4128
  }

H
Haojun Liao 已提交
4129
  if (pOperator->pDownstream != NULL) {
L
Liu Jicong 已提交
4130
    for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
H
Haojun Liao 已提交
4131
      destroyOperatorInfo(pOperator->pDownstream[i]);
4132 4133
    }

wafwerar's avatar
wafwerar 已提交
4134
    taosMemoryFreeClear(pOperator->pDownstream);
H
Haojun Liao 已提交
4135
    pOperator->numOfDownstream = 0;
4136 4137
  }

H
Haojun Liao 已提交
4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148
  if (pOperator->pExpr != NULL) {
    for (int32_t i = 0; i < pOperator->numOfExprs; ++i) {
      SExprInfo* pExprInfo = &pOperator->pExpr[i];
      if (pExprInfo->pExpr->nodeType == QUERY_NODE_COLUMN) {
        taosMemoryFree(pExprInfo->base.pParam[0].pCol);
      }
      taosMemoryFree(pExprInfo->base.pParam);
      taosMemoryFree(pExprInfo->pExpr);
    }
  }

D
fix bug  
dapan 已提交
4149
  taosMemoryFreeClear(pOperator->pExpr);
wafwerar's avatar
wafwerar 已提交
4150 4151
  taosMemoryFreeClear(pOperator->info);
  taosMemoryFreeClear(pOperator);
4152 4153
}

dengyihao's avatar
dengyihao 已提交
4154 4155
int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize,
                         const char* pKey) {
4156 4157
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);

dengyihao's avatar
dengyihao 已提交
4158 4159
  pAggSup->resultRowSize = getResultRowSize(pCtx, numOfOutput);
  pAggSup->keyBuf = taosMemoryCalloc(1, keyBufSize + POINTER_BYTES + sizeof(int64_t));
4160 4161
  pAggSup->pResultRowHashTable = taosHashInit(10, hashFn, true, HASH_NO_LOCK);

H
Haojun Liao 已提交
4162
  if (pAggSup->keyBuf == NULL || pAggSup->pResultRowHashTable == NULL) {
4163 4164 4165
    return TSDB_CODE_OUT_OF_MEMORY;
  }

H
Haojun Liao 已提交
4166
  uint32_t defaultPgsz = 4096;
X
Xiaoyu Wang 已提交
4167
  while (defaultPgsz < pAggSup->resultRowSize * 4) {
H
Haojun Liao 已提交
4168 4169 4170 4171 4172 4173 4174 4175 4176 4177
    defaultPgsz <<= 1u;
  }

  // at least four pages need to be in buffer
  int32_t defaultBufsz = 4096 * 256;
  if (defaultBufsz <= defaultPgsz) {
    defaultBufsz = defaultPgsz * 4;
  }

  int32_t code = createDiskbasedBuf(&pAggSup->pResultBuf, defaultPgsz, defaultBufsz, pKey, "/tmp/");
H
Haojun Liao 已提交
4178 4179 4180 4181
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

4182 4183 4184
  return TSDB_CODE_SUCCESS;
}

4185
void cleanupAggSup(SAggSupporter* pAggSup) {
wafwerar's avatar
wafwerar 已提交
4186
  taosMemoryFreeClear(pAggSup->keyBuf);
4187
  taosHashCleanup(pAggSup->pResultRowHashTable);
H
Haojun Liao 已提交
4188
  destroyDiskbasedBuf(pAggSup->pResultBuf);
4189 4190
}

H
Haojun Liao 已提交
4191
int32_t initAggInfo(SOptrBasicInfo* pBasicInfo, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols,
4192
                    SSDataBlock* pResultBlock, size_t keyBufSize, const char* pkey) {
4193
  pBasicInfo->pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pBasicInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4194 4195
  pBasicInfo->pRes = pResultBlock;

4196
  doInitAggInfoSup(pAggSup, pBasicInfo->pCtx, numOfCols, keyBufSize, pkey);
4197

L
Liu Jicong 已提交
4198
  for (int32_t i = 0; i < numOfCols; ++i) {
4199 4200 4201
    pBasicInfo->pCtx[i].pBuf = pAggSup->pResultBuf;
  }

4202
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
4203 4204
}

4205 4206 4207 4208 4209 4210 4211 4212 4213
void initResultSizeInfo(SOperatorInfo* pOperator, int32_t numOfRows) {
  pOperator->resultInfo.capacity = numOfRows;
  pOperator->resultInfo.threshold = numOfRows * 0.75;

  if (pOperator->resultInfo.threshold == 0) {
    pOperator->resultInfo.capacity = numOfRows;
  }
}

H
Haojun Liao 已提交
4214
static STableQueryInfo* initTableQueryInfo(const STableGroupInfo* pTableGroupInfo) {
L
Liu Jicong 已提交
4215 4216 4217 4218
  if (pTableGroupInfo->numOfTables == 0) {
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
4219
  STableQueryInfo* pTableQueryInfo = taosMemoryCalloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4220 4221
  if (pTableQueryInfo == NULL) {
    return NULL;
H
Haojun Liao 已提交
4222
  }
H
Haojun Liao 已提交
4223 4224

  int32_t index = 0;
L
Liu Jicong 已提交
4225
  for (int32_t i = 0; i < taosArrayGetSize(pTableGroupInfo->pGroupList); ++i) {
H
Haojun Liao 已提交
4226
    SArray* pa = taosArrayGetP(pTableGroupInfo->pGroupList, i);
L
Liu Jicong 已提交
4227
    for (int32_t j = 0; j < taosArrayGetSize(pa); ++j) {
H
Haojun Liao 已提交
4228
      STableKeyInfo* pk = taosArrayGet(pa, j);
H
Haojun Liao 已提交
4229
      STableQueryInfo* pTQueryInfo = &pTableQueryInfo[index++];
L
Liu Jicong 已提交
4230
      pTQueryInfo->lastKey = pk->lastKey;
H
Haojun Liao 已提交
4231 4232
    }
  }
H
Haojun Liao 已提交
4233 4234

  STimeWindow win = {0, INT64_MAX};
4235
  createTableQueryInfo(pTableQueryInfo, win);
H
Haojun Liao 已提交
4236
  return pTableQueryInfo;
H
Haojun Liao 已提交
4237 4238
}

L
Liu Jicong 已提交
4239
SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
4240
                                           SSDataBlock* pResultBlock, SExprInfo* pScalarExprInfo,
L
Liu Jicong 已提交
4241 4242
                                           int32_t numOfScalarExpr, SExecTaskInfo* pTaskInfo,
                                           const STableGroupInfo* pTableGroupInfo) {
wafwerar's avatar
wafwerar 已提交
4243
  SAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAggOperatorInfo));
L
Liu Jicong 已提交
4244
  SOperatorInfo*    pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4245 4246 4247
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
4248

4249
  int32_t numOfRows = 1024;
dengyihao's avatar
dengyihao 已提交
4250
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
4251 4252

  initResultSizeInfo(pOperator, numOfRows);
dengyihao's avatar
dengyihao 已提交
4253 4254
  int32_t code =
      initAggInfo(&pInfo->binfo, &pInfo->aggSup, pExprInfo, numOfCols, pResultBlock, keyBufSize, pTaskInfo->id.str);
H
Haojun Liao 已提交
4255
  pInfo->pTableQueryInfo = initTableQueryInfo(pTableGroupInfo);
L
Liu Jicong 已提交
4256
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4257 4258
    goto _error;
  }
H
Haojun Liao 已提交
4259

H
Haojun Liao 已提交
4260 4261 4262 4263
  int32_t numOfGroup = 10;  // todo replaced with true value
  pInfo->groupId = INT32_MIN;
  initResultRowInfo(&pInfo->binfo.resultRowInfo, numOfGroup);

4264 4265
  pInfo->pScalarExprInfo = pScalarExprInfo;
  pInfo->numOfScalarExpr = numOfScalarExpr;
4266 4267 4268
  if (pInfo->pScalarExprInfo != NULL) {
    pInfo->pScalarCtx = createSqlFunctionCtx(pScalarExprInfo, numOfCols, &pInfo->rowCellInfoOffset);
  }
4269

dengyihao's avatar
dengyihao 已提交
4270
  pOperator->name = "TableAggregate";
X
Xiaoyu Wang 已提交
4271
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_AGG;
4272
  pOperator->blocking = true;
dengyihao's avatar
dengyihao 已提交
4273 4274 4275
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->pExpr = pExprInfo;
4276
  pOperator->numOfExprs = numOfCols;
dengyihao's avatar
dengyihao 已提交
4277
  pOperator->pTaskInfo = pTaskInfo;
H
Haojun Liao 已提交
4278

4279 4280
  pOperator->fpSet = createOperatorFpSet(doOpenAggregateOptr, getAggregateResult, NULL, NULL, destroyAggOperatorInfo,
                                         aggEncodeResultRow, aggDecodeResultRow, NULL);
H
Haojun Liao 已提交
4281 4282 4283 4284 4285

  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4286 4287

  return pOperator;
L
Liu Jicong 已提交
4288
_error:
H
Haojun Liao 已提交
4289
  destroyAggOperatorInfo(pInfo, numOfCols);
wafwerar's avatar
wafwerar 已提交
4290 4291
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
4292 4293
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  return NULL;
4294 4295
}

H
Haojun Liao 已提交
4296
void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) {
4297 4298
  assert(pInfo != NULL);

4299
  destroySqlFunctionCtx(pInfo->pCtx, numOfOutput);
wafwerar's avatar
wafwerar 已提交
4300
  taosMemoryFreeClear(pInfo->rowCellInfoOffset);
4301 4302

  cleanupResultRowInfo(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4303
  pInfo->pRes = blockDataDestroy(pInfo->pRes);
4304 4305
}

H
Haojun Liao 已提交
4306
void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4307
  SOptrBasicInfo* pInfo = (SOptrBasicInfo*)param;
4308 4309
  doDestroyBasicInfo(pInfo, numOfOutput);
}
H
Haojun Liao 已提交
4310 4311

void destroyAggOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4312
  SAggOperatorInfo* pInfo = (SAggOperatorInfo*)param;
4313 4314
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}
4315

H
Haojun Liao 已提交
4316
void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4317
  SFillOperatorInfo* pInfo = (SFillOperatorInfo*)param;
4318
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
4319
  pInfo->pRes = blockDataDestroy(pInfo->pRes);
wafwerar's avatar
wafwerar 已提交
4320
  taosMemoryFreeClear(pInfo->p);
4321 4322
}

H
Haojun Liao 已提交
4323
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) {
D
fix bug  
dapan 已提交
4324 4325 4326
  if (NULL == param) {
    return;
  }
L
Liu Jicong 已提交
4327
  SProjectOperatorInfo* pInfo = (SProjectOperatorInfo*)param;
4328
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
H
Haojun Liao 已提交
4329
  cleanupAggSup(&pInfo->aggSup);
H
Haojun Liao 已提交
4330
  taosArrayDestroy(pInfo->pPseudoColInfo);
4331 4332
}

H
Haojun Liao 已提交
4333
void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4334
  SExchangeInfo* pExInfo = (SExchangeInfo*)param;
H
Haojun Liao 已提交
4335 4336 4337 4338 4339 4340 4341 4342 4343
  taosArrayDestroy(pExInfo->pSources);
  taosArrayDestroy(pExInfo->pSourceDataInfo);
  if (pExInfo->pResult != NULL) {
    blockDataDestroy(pExInfo->pResult);
  }

  tsem_destroy(&pExInfo->ready);
}

H
Haojun Liao 已提交
4344 4345
static SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols) {
  SArray* pList = taosArrayInit(4, sizeof(int32_t));
dengyihao's avatar
dengyihao 已提交
4346
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4347 4348 4349 4350 4351 4352 4353 4354
    if (fmIsPseudoColumnFunc(pCtx[i].functionId)) {
      taosArrayPush(pList, &i);
    }
  }

  return pList;
}

L
Liu Jicong 已提交
4355
SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t num,
dengyihao's avatar
dengyihao 已提交
4356 4357
                                         SSDataBlock* pResBlock, SLimit* pLimit, SLimit* pSlimit,
                                         SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
4358
  SProjectOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SProjectOperatorInfo));
L
Liu Jicong 已提交
4359
  SOperatorInfo*        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4360 4361 4362
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
4363

4364 4365 4366
  pInfo->limit      = *pLimit;
  pInfo->slimit     = *pSlimit;
  pInfo->curOffset  = pLimit->offset;
H
Haojun Liao 已提交
4367 4368
  pInfo->curSOffset = pSlimit->offset;

H
Haojun Liao 已提交
4369
  pInfo->binfo.pRes = pResBlock;
H
Haojun Liao 已提交
4370 4371 4372

  int32_t numOfCols = num;
  int32_t numOfRows = 4096;
dengyihao's avatar
dengyihao 已提交
4373
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
4374 4375 4376

  initResultSizeInfo(pOperator, numOfRows);
  initAggInfo(&pInfo->binfo, &pInfo->aggSup, pExprInfo, numOfCols, pResBlock, keyBufSize, pTaskInfo->id.str);
H
Haojun Liao 已提交
4377
  setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, numOfCols, pTaskInfo);
H
Haojun Liao 已提交
4378
  pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pInfo->binfo.pCtx, numOfCols);
4379

dengyihao's avatar
dengyihao 已提交
4380
  pOperator->name = "ProjectOperator";
H
Haojun Liao 已提交
4381
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT;
4382
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
4383 4384 4385
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->pExpr = pExprInfo;
4386
  pOperator->numOfExprs = num;
4387

L
Liu Jicong 已提交
4388 4389
  pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doProjectOperation, NULL, NULL,
                                         destroyProjectOperatorInfo, NULL, NULL, NULL);
L
Liu Jicong 已提交
4390 4391

  pOperator->pTaskInfo = pTaskInfo;
4392
  int32_t code = appendDownstream(pOperator, &downstream, 1);
H
Haojun Liao 已提交
4393
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4394 4395
    goto _error;
  }
4396 4397

  return pOperator;
H
Haojun Liao 已提交
4398

L
Liu Jicong 已提交
4399
_error:
H
Haojun Liao 已提交
4400 4401
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  return NULL;
4402 4403
}

4404
static int32_t initFillInfo(SFillOperatorInfo* pInfo, SExprInfo* pExpr, int32_t numOfCols, SNodeListNode* pValNode,
L
Liu Jicong 已提交
4405
                            STimeWindow win, int32_t capacity, const char* id, SInterval* pInterval, int32_t fillType) {
4406
  SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfCols, pValNode);
H
Haojun Liao 已提交
4407 4408

  STimeWindow w = TSWINDOW_INITIALIZER;
4409
  getAlignQueryTimeWindow(pInterval, pInterval->precision, win.skey, &w);
H
Haojun Liao 已提交
4410 4411

  int32_t order = TSDB_ORDER_ASC;
4412
  pInfo->pFillInfo = taosCreateFillInfo(order, w.skey, 0, capacity, numOfCols, pInterval, fillType, pColInfo, id);
H
Haojun Liao 已提交
4413

wafwerar's avatar
wafwerar 已提交
4414
  pInfo->p = taosMemoryCalloc(numOfCols, POINTER_BYTES);
H
Haojun Liao 已提交
4415 4416 4417 4418 4419 4420 4421
  if (pInfo->pFillInfo == NULL || pInfo->p == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  } else {
    return TSDB_CODE_SUCCESS;
  }
}

L
Liu Jicong 已提交
4422
SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfCols,
X
Xiaoyu Wang 已提交
4423 4424 4425
                                      SInterval* pInterval, STimeWindow* pWindow, SSDataBlock* pResBlock,
                                      int32_t fillType, SNodeListNode* pValueNode, bool multigroupResult,
                                      SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
4426
  SFillOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SFillOperatorInfo));
L
Liu Jicong 已提交
4427
  SOperatorInfo*     pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4428

L
Liu Jicong 已提交
4429
  pInfo->pRes = pResBlock;
4430 4431
  pInfo->multigroupResult = multigroupResult;

4432 4433
  int32_t type = TSDB_FILL_NONE;
  switch (fillType) {
dengyihao's avatar
dengyihao 已提交
4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451
    case FILL_MODE_PREV:
      type = TSDB_FILL_PREV;
      break;
    case FILL_MODE_NONE:
      type = TSDB_FILL_NONE;
      break;
    case FILL_MODE_NULL:
      type = TSDB_FILL_NULL;
      break;
    case FILL_MODE_NEXT:
      type = TSDB_FILL_NEXT;
      break;
    case FILL_MODE_VALUE:
      type = TSDB_FILL_SET_VALUE;
      break;
    case FILL_MODE_LINEAR:
      type = TSDB_FILL_LINEAR;
      break;
4452 4453 4454 4455
    default:
      type = TSDB_FILL_NONE;
  }

H
Haojun Liao 已提交
4456
  SResultInfo* pResultInfo = &pOperator->resultInfo;
4457 4458
  initResultSizeInfo(pOperator, 4096);

X
Xiaoyu Wang 已提交
4459 4460
  int32_t code = initFillInfo(pInfo, pExpr, numOfCols, pValueNode, *pWindow, pResultInfo->capacity, pTaskInfo->id.str,
                              pInterval, type);
4461 4462 4463
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4464

dengyihao's avatar
dengyihao 已提交
4465
  pOperator->name = "FillOperator";
4466
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
4467
  pOperator->status = OP_NOT_OPENED;
4468
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_FILL;
dengyihao's avatar
dengyihao 已提交
4469
  pOperator->pExpr = pExpr;
4470
  pOperator->numOfExprs = numOfCols;
dengyihao's avatar
dengyihao 已提交
4471
  pOperator->info = pInfo;
H
Haojun Liao 已提交
4472

L
Liu Jicong 已提交
4473 4474
  pOperator->fpSet =
      createOperatorFpSet(operatorDummyOpenFn, doFill, NULL, NULL, destroySFillOperatorInfo, NULL, NULL, NULL);
4475
  pOperator->pTaskInfo = pTaskInfo;
4476
  code = appendDownstream(pOperator, &downstream, 1);
4477
  return pOperator;
H
Haojun Liao 已提交
4478

L
Liu Jicong 已提交
4479
_error:
wafwerar's avatar
wafwerar 已提交
4480 4481
  taosMemoryFreeClear(pOperator);
  taosMemoryFreeClear(pInfo);
H
Haojun Liao 已提交
4482
  return NULL;
4483 4484
}

L
Liu Jicong 已提交
4485 4486
static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, int32_t scale, int32_t precision,
                                  const char* name) {
H
Haojun Liao 已提交
4487
  SResSchema s = {0};
dengyihao's avatar
dengyihao 已提交
4488 4489 4490 4491
  s.scale = scale;
  s.type = type;
  s.bytes = bytes;
  s.slotId = slotId;
H
Haojun Liao 已提交
4492
  s.precision = precision;
H
Haojun Liao 已提交
4493 4494 4495 4496
  strncpy(s.name, name, tListLen(s.name));

  return s;
}
H
Haojun Liao 已提交
4497

4498
static SColumn* createColumn(int32_t blockId, int32_t slotId, int32_t colId, SDataType* pType) {
H
Haojun Liao 已提交
4499 4500 4501 4502 4503 4504
  SColumn* pCol = taosMemoryCalloc(1, sizeof(SColumn));
  if (pCol == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

dengyihao's avatar
dengyihao 已提交
4505
  pCol->slotId = slotId;
4506 4507 4508 4509
  pCol->colId  = colId;
  pCol->bytes  = pType->bytes;
  pCol->type   = pType->type;
  pCol->scale  = pType->scale;
dengyihao's avatar
dengyihao 已提交
4510
  pCol->precision = pType->precision;
H
Haojun Liao 已提交
4511 4512 4513 4514 4515
  pCol->dataBlockId = blockId;

  return pCol;
}

H
Haojun Liao 已提交
4516
SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs) {
H
Haojun Liao 已提交
4517
  int32_t numOfFuncs = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
4518 4519 4520 4521
  int32_t numOfGroupKeys = 0;
  if (pGroupKeys != NULL) {
    numOfGroupKeys = LIST_LENGTH(pGroupKeys);
  }
H
Haojun Liao 已提交
4522

H
Haojun Liao 已提交
4523
  *numOfExprs = numOfFuncs + numOfGroupKeys;
wafwerar's avatar
wafwerar 已提交
4524
  SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo));
H
Haojun Liao 已提交
4525

L
Liu Jicong 已提交
4526
  for (int32_t i = 0; i < (*numOfExprs); ++i) {
H
Haojun Liao 已提交
4527 4528 4529 4530 4531 4532
    STargetNode* pTargetNode = NULL;
    if (i < numOfFuncs) {
      pTargetNode = (STargetNode*)nodesListGetNode(pNodeList, i);
    } else {
      pTargetNode = (STargetNode*)nodesListGetNode(pGroupKeys, i - numOfFuncs);
    }
H
Haojun Liao 已提交
4533

4534
    SExprInfo* pExp = &pExprs[i];
H
Haojun Liao 已提交
4535

wafwerar's avatar
wafwerar 已提交
4536
    pExp->pExpr = taosMemoryCalloc(1, sizeof(tExprNode));
H
Haojun Liao 已提交
4537
    pExp->pExpr->_function.num = 1;
H
Haojun Liao 已提交
4538
    pExp->pExpr->_function.functionId = -1;
H
Haojun Liao 已提交
4539

4540
    int32_t type = nodeType(pTargetNode->pExpr);
H
Haojun Liao 已提交
4541
    // it is a project query, or group by column
4542
    if (type == QUERY_NODE_COLUMN) {
H
Haojun Liao 已提交
4543
      pExp->pExpr->nodeType = QUERY_NODE_COLUMN;
L
Liu Jicong 已提交
4544
      SColumnNode* pColNode = (SColumnNode*)pTargetNode->pExpr;
H
Haojun Liao 已提交
4545

G
Ganlin Zhao 已提交
4546 4547 4548
      pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
      pExp->base.numOfParams = 1;

H
Haojun Liao 已提交
4549
      SDataType* pType = &pColNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4550 4551
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pColNode->colName);
4552
      pExp->base.pParam[0].pCol = createColumn(pColNode->dataBlockId, pColNode->slotId, pColNode->colId, pType);
H
Haojun Liao 已提交
4553
      pExp->base.pParam[0].type = FUNC_PARAM_TYPE_COLUMN;
4554
    } else if (type == QUERY_NODE_VALUE) {
4555 4556 4557 4558 4559 4560 4561
      pExp->pExpr->nodeType = QUERY_NODE_VALUE;
      SValueNode* pValNode = (SValueNode*)pTargetNode->pExpr;

      pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
      pExp->base.numOfParams = 1;

      SDataType* pType = &pValNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4562 4563
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pValNode->node.aliasName);
4564 4565
      pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
      valueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
4566
    } else if (type == QUERY_NODE_FUNCTION) {
H
Haojun Liao 已提交
4567
      pExp->pExpr->nodeType = QUERY_NODE_FUNCTION;
H
Haojun Liao 已提交
4568 4569 4570
      SFunctionNode* pFuncNode = (SFunctionNode*)pTargetNode->pExpr;

      SDataType* pType = &pFuncNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4571 4572
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pFuncNode->node.aliasName);
H
Haojun Liao 已提交
4573

H
Haojun Liao 已提交
4574
      pExp->pExpr->_function.functionId = pFuncNode->funcId;
H
Haojun Liao 已提交
4575
      pExp->pExpr->_function.pFunctNode = pFuncNode;
4576

dengyihao's avatar
dengyihao 已提交
4577 4578
      strncpy(pExp->pExpr->_function.functionName, pFuncNode->functionName,
              tListLen(pExp->pExpr->_function.functionName));
4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591
#if 1
      // todo refactor: add the parameter for tbname function
      if (strcmp(pExp->pExpr->_function.functionName, "tbname") == 0) {
        pFuncNode->pParameterList = nodesMakeList();
        ASSERT(LIST_LENGTH(pFuncNode->pParameterList) == 0);
        SValueNode *res = (SValueNode *)nodesMakeNode(QUERY_NODE_VALUE);
        if (NULL == res) { // todo handle error
        } else {
          res->node.resType = (SDataType) {.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
          nodesListAppend(pFuncNode->pParameterList, res);
        }
      }
#endif
H
Haojun Liao 已提交
4592 4593

      int32_t numOfParam = LIST_LENGTH(pFuncNode->pParameterList);
G
Ganlin Zhao 已提交
4594 4595 4596 4597

      pExp->base.pParam = taosMemoryCalloc(numOfParam, sizeof(SFunctParam));
      pExp->base.numOfParams = numOfParam;

H
Haojun Liao 已提交
4598
      for (int32_t j = 0; j < numOfParam; ++j) {
4599
        SNode* p1 = nodesListGetNode(pFuncNode->pParameterList, j);
G
Ganlin Zhao 已提交
4600
        if (p1->type == QUERY_NODE_COLUMN) {
dengyihao's avatar
dengyihao 已提交
4601
          SColumnNode* pcn = (SColumnNode*)p1;
G
Ganlin Zhao 已提交
4602 4603

          pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN;
4604
          pExp->base.pParam[j].pCol = createColumn(pcn->dataBlockId, pcn->slotId, pcn->colId, &pcn->node.resType);
G
Ganlin Zhao 已提交
4605 4606 4607
        } else if (p1->type == QUERY_NODE_VALUE) {
          SValueNode* pvn = (SValueNode*)p1;
          pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
4608
          valueNodeToVariant(pvn, &pExp->base.pParam[j].param);
G
Ganlin Zhao 已提交
4609
        }
H
Haojun Liao 已提交
4610
      }
4611
    } else if (type == QUERY_NODE_OPERATOR) {
H
Haojun Liao 已提交
4612
      pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
L
Liu Jicong 已提交
4613
      SOperatorNode* pNode = (SOperatorNode*)pTargetNode->pExpr;
4614

G
Ganlin Zhao 已提交
4615 4616 4617
      pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
      pExp->base.numOfParams = 1;

4618
      SDataType* pType = &pNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4619 4620
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pNode->node.aliasName);
4621 4622 4623
      pExp->pExpr->_optrRoot.pRootNode = pTargetNode->pExpr;
    } else {
      ASSERT(0);
H
Haojun Liao 已提交
4624 4625 4626
    }
  }

H
Haojun Liao 已提交
4627
  return pExprs;
H
Haojun Liao 已提交
4628 4629
}

4630
static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPTR_EXEC_MODEL model) {
wafwerar's avatar
wafwerar 已提交
4631
  SExecTaskInfo* pTaskInfo = taosMemoryCalloc(1, sizeof(SExecTaskInfo));
4632
  setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
H
Haojun Liao 已提交
4633

4634
  pTaskInfo->cost.created = taosGetTimestampMs();
H
Haojun Liao 已提交
4635
  pTaskInfo->id.queryId = queryId;
dengyihao's avatar
dengyihao 已提交
4636
  pTaskInfo->execModel = model;
H
Haojun Liao 已提交
4637

wafwerar's avatar
wafwerar 已提交
4638
  char* p = taosMemoryCalloc(1, 128);
L
Liu Jicong 已提交
4639
  snprintf(p, 128, "TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, queryId);
H
Haojun Liao 已提交
4640
  pTaskInfo->id.str = p;
H
Haojun Liao 已提交
4641

4642 4643
  return pTaskInfo;
}
H
Haojun Liao 已提交
4644

L
Liu Jicong 已提交
4645 4646
static tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
                                      STableGroupInfo* pTableGroupInfo, uint64_t queryId, uint64_t taskId);
H
Haojun Liao 已提交
4647

L
Liu Jicong 已提交
4648 4649
static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo,
                                  uint64_t queryId, uint64_t taskId);
4650
static SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo);
H
Haojun Liao 已提交
4651
static SArray* extractColumnInfo(SNodeList* pNodeList);
4652

4653
static SArray* createSortInfo(SNodeList* pNodeList);
4654
static SArray* extractPartitionColInfo(SNodeList* pNodeList);
4655

H
Haojun Liao 已提交
4656
SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
4657
                                  uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) {
4658 4659
  int32_t type = nodeType(pPhyNode);

X
Xiaoyu Wang 已提交
4660
  if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) {
H
Haojun Liao 已提交
4661
    if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == type) {
dengyihao's avatar
dengyihao 已提交
4662
      STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4663

H
Haojun Liao 已提交
4664
      tsdbReaderT pDataReader = doCreateDataReader(pTableScanNode, pHandle, pTableGroupInfo, (uint64_t)queryId, taskId);
4665
      if (pDataReader == NULL && terrno != 0) {
4666 4667
        return NULL;
      }
4668

4669
      SOperatorInfo* pOperator = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
4670

4671 4672
      STableScanInfo* pScanInfo = pOperator->info;
      pTaskInfo->cost.pRecoder = &pScanInfo->readRecorder;
4673

4674
      return pOperator;
H
Haojun Liao 已提交
4675
    } else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == type) {
H
Haojun Liao 已提交
4676
      SExchangePhysiNode* pExchange = (SExchangePhysiNode*)pPhyNode;
4677
      SSDataBlock*        pResBlock = createResDataBlock(pExchange->node.pOutputDataBlockDesc);
4678
      return createExchangeOperatorInfo(pHandle->pMsgCb->clientRpc, pExchange->pSrcEndPoints, pResBlock, pTaskInfo);
H
Haojun Liao 已提交
4679
    } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) {
H
Haojun Liao 已提交
4680
      SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode;  // simple child table.
5
54liuyao 已提交
4681
      STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
4682

4683
      int32_t numOfCols = 0;
5
54liuyao 已提交
4684 4685 4686 4687 4688 4689 4690 4691

      tsdbReaderT pDataReader = NULL;
      if (pHandle->vnode) {
        pDataReader = doCreateDataReader(pTableScanNode, pHandle, pTableGroupInfo, (uint64_t)queryId, taskId);
      } else {
        doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, 
            queryId, taskId);
      }
4692

5
54liuyao 已提交
4693 4694 4695 4696 4697 4698
      if (pDataReader == NULL && terrno != 0) {
        qDebug("pDataReader is     NULL");
        // return NULL;
      } else {
        qDebug("pDataReader is not NULL");
      }
H
Haojun Liao 已提交
4699

4700
      SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;
4701
      SOperatorInfo* pOperatorDumy = createTableScanOperatorInfo(pTableScanNode, pDataReader, pHandle, pTaskInfo);
5
54liuyao 已提交
4702 4703

      SArray* tableIdList = extractTableIdList(pTableGroupInfo);
4704

4705 4706 4707 4708
      SSDataBlock* pResBlock = createResDataBlock(pDescNode);
      SArray*      pCols = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID);

      SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pDataReader, pHandle, pScanPhyNode->uid, pResBlock, pCols, tableIdList, pTaskInfo,
5
54liuyao 已提交
4709
                                                              pScanPhyNode->node.pConditions, pOperatorDumy);
4710
      taosArrayDestroy(tableIdList);
H
Haojun Liao 已提交
4711
      return pOperator;
H
Haojun Liao 已提交
4712
    } else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
L
Liu Jicong 已提交
4713
      SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode;
L
Liu Jicong 已提交
4714
      SScanPhysiNode*            pScanNode = &pSysScanPhyNode->scan;
H
Haojun Liao 已提交
4715

4716 4717 4718
      SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc;

      SSDataBlock* pResBlock = createResDataBlock(pDescNode);
4719

4720
      int32_t numOfOutputCols = 0;
4721
      SArray* colList = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfOutputCols, COL_MATCH_FROM_COL_ID);
L
Liu Jicong 已提交
4722
      SOperatorInfo* pOperator = createSysTableScanOperatorInfo(
L
Liu Jicong 已提交
4723 4724
          pHandle, pResBlock, &pScanNode->tableName, pScanNode->node.pConditions, pSysScanPhyNode->mgmtEpSet, colList,
          pTaskInfo, pSysScanPhyNode->showRewrite, pSysScanPhyNode->accountId);
H
Haojun Liao 已提交
4725
      return pOperator;
4726
    } else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) {
X
Xiaoyu Wang 已提交
4727
      STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode;
4728 4729 4730 4731

      SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc;

      SSDataBlock* pResBlock = createResDataBlock(pDescNode);
4732

X
Xiaoyu Wang 已提交
4733 4734
      int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo,
                                        queryId, taskId);
4735 4736 4737 4738
      if (code != TSDB_CODE_SUCCESS) {
        return NULL;
      }

X
Xiaoyu Wang 已提交
4739
      int32_t    num = 0;
4740 4741 4742
      SExprInfo* pExprInfo = createExprInfo(pScanPhyNode->pScanPseudoCols, NULL, &num);

      int32_t numOfOutputCols = 0;
X
Xiaoyu Wang 已提交
4743 4744
      SArray* colList =
          extractColMatchInfo(pScanPhyNode->pScanPseudoCols, pDescNode, &numOfOutputCols, COL_MATCH_FROM_COL_ID);
4745

X
Xiaoyu Wang 已提交
4746 4747
      SOperatorInfo* pOperator =
          createTagScanOperatorInfo(pHandle, pExprInfo, num, pResBlock, colList, pTableGroupInfo, pTaskInfo);
4748
      return pOperator;
H
Haojun Liao 已提交
4749 4750
    } else {
      ASSERT(0);
H
Haojun Liao 已提交
4751 4752 4753
    }
  }

4754 4755
  int32_t num = 0;
  size_t  size = LIST_LENGTH(pPhyNode->pChildren);
H
Haojun Liao 已提交
4756

4757
  SOperatorInfo** ops = taosMemoryCalloc(size, POINTER_BYTES);
dengyihao's avatar
dengyihao 已提交
4758
  for (int32_t i = 0; i < size; ++i) {
4759 4760
    SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i);
    ops[i] = createOperatorTree(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
4761 4762 4763
    if (ops[i] == NULL) {
      return NULL;
    }
4764
  }
H
Haojun Liao 已提交
4765

4766
  SOperatorInfo* pOptr = NULL;
H
Haojun Liao 已提交
4767
  if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) {
dengyihao's avatar
dengyihao 已提交
4768 4769
    SProjectPhysiNode* pProjPhyNode = (SProjectPhysiNode*)pPhyNode;
    SExprInfo*         pExprInfo = createExprInfo(pProjPhyNode->pProjections, NULL, &num);
H
Haojun Liao 已提交
4770

4771
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
4772 4773
    SLimit       limit = {.limit = pProjPhyNode->limit, .offset = pProjPhyNode->offset};
    SLimit       slimit = {.limit = pProjPhyNode->slimit, .offset = pProjPhyNode->soffset};
4774
    pOptr = createProjectOperatorInfo(ops[0], pExprInfo, num, pResBlock, &limit, &slimit, pTaskInfo);
H
Haojun Liao 已提交
4775 4776 4777
  } else if (QUERY_NODE_PHYSICAL_PLAN_AGG == type) {
    SAggPhysiNode* pAggNode = (SAggPhysiNode*)pPhyNode;
    SExprInfo*     pExprInfo = createExprInfo(pAggNode->pAggFuncs, pAggNode->pGroupKeys, &num);
4778
    SSDataBlock*   pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
H
Haojun Liao 已提交
4779

dengyihao's avatar
dengyihao 已提交
4780
    int32_t    numOfScalarExpr = 0;
4781 4782 4783 4784 4785
    SExprInfo* pScalarExprInfo = NULL;
    if (pAggNode->pExprs != NULL) {
      pScalarExprInfo = createExprInfo(pAggNode->pExprs, NULL, &numOfScalarExpr);
    }

H
Haojun Liao 已提交
4786 4787
    if (pAggNode->pGroupKeys != NULL) {
      SArray* pColList = extractColumnInfo(pAggNode->pGroupKeys);
dengyihao's avatar
dengyihao 已提交
4788 4789
      pOptr = createGroupOperatorInfo(ops[0], pExprInfo, num, pResBlock, pColList, pAggNode->node.pConditions,
                                      pScalarExprInfo, numOfScalarExpr, pTaskInfo, NULL);
H
Haojun Liao 已提交
4790
    } else {
dengyihao's avatar
dengyihao 已提交
4791 4792
      pOptr = createAggregateOperatorInfo(ops[0], pExprInfo, num, pResBlock, pScalarExprInfo, numOfScalarExpr,
                                          pTaskInfo, pTableGroupInfo);
H
Haojun Liao 已提交
4793
    }
X
Xiaoyu Wang 已提交
4794
  } else if (QUERY_NODE_PHYSICAL_PLAN_INTERVAL == type || QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type) {
H
Haojun Liao 已提交
4795
    SIntervalPhysiNode* pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4796

H
Haojun Liao 已提交
4797
    SExprInfo*   pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
4798
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
H
Haojun Liao 已提交
4799

dengyihao's avatar
dengyihao 已提交
4800 4801 4802 4803 4804 4805
    SInterval interval = {.interval = pIntervalPhyNode->interval,
                          .sliding = pIntervalPhyNode->sliding,
                          .intervalUnit = pIntervalPhyNode->intervalUnit,
                          .slidingUnit = pIntervalPhyNode->slidingUnit,
                          .offset = pIntervalPhyNode->offset,
                          .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision};
H
Haojun Liao 已提交
4806

dengyihao's avatar
dengyihao 已提交
4807 4808
    STimeWindowAggSupp as = {.waterMark = pIntervalPhyNode->window.watermark,
                             .calTrigger = pIntervalPhyNode->window.triggerType};
4809

4810 4811 4812 4813
    int32_t tsSlotId = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
    pOptr = createIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, &as, pTableGroupInfo,
                                       pTaskInfo);

H
Haojun Liao 已提交
4814
  } else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) {
H
Haojun Liao 已提交
4815
    SSortPhysiNode* pSortPhyNode = (SSortPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4816

4817 4818 4819
    SDataBlockDescNode* pDescNode = pPhyNode->pOutputDataBlockDesc;

    SSDataBlock* pResBlock = createResDataBlock(pDescNode);
4820
    SArray*      info = createSortInfo(pSortPhyNode->pSortKeys);
4821 4822

    int32_t    numOfCols = 0;
4823 4824 4825
    SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols);

    int32_t numOfOutputCols = 0;
4826
    SArray* pColList = extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID);
4827

4828
    pOptr = createSortOperatorInfo(ops[0], pResBlock, info, pExprInfo, numOfCols, pColList, pTaskInfo);
H
Haojun Liao 已提交
4829
  } else if (QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW == type) {
H
Haojun Liao 已提交
4830 4831
    SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;

X
Xiaoyu Wang 已提交
4832 4833
    STimeWindowAggSupp as = {.waterMark = pSessionNode->window.watermark,
                             .calTrigger = pSessionNode->window.triggerType};
4834

H
Haojun Liao 已提交
4835
    SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &num);
4836
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4837 4838
    int32_t      tsSlotId = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;

X
Xiaoyu Wang 已提交
4839 4840
    pOptr =
        createSessionAggOperatorInfo(ops[0], pExprInfo, num, pResBlock, pSessionNode->gap, tsSlotId, &as, pTaskInfo);
H
Haojun Liao 已提交
4841
  } else if (QUERY_NODE_PHYSICAL_PLAN_PARTITION == type) {
dengyihao's avatar
dengyihao 已提交
4842 4843 4844
    SPartitionPhysiNode* pPartNode = (SPartitionPhysiNode*)pPhyNode;
    SArray*              pColList = extractPartitionColInfo(pPartNode->pPartitionKeys);
    SSDataBlock*         pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4845 4846

    SExprInfo* pExprInfo = createExprInfo(pPartNode->pTargets, NULL, &num);
4847
    pOptr = createPartitionOperatorInfo(ops[0], pExprInfo, num, pResBlock, pColList, pTaskInfo, NULL);
4848
  } else if (QUERY_NODE_PHYSICAL_PLAN_STATE_WINDOW == type) {
dengyihao's avatar
dengyihao 已提交
4849
    SStateWinodwPhysiNode* pStateNode = (SStateWinodwPhysiNode*)pPhyNode;
4850

4851 4852
    STimeWindowAggSupp as = {.waterMark = pStateNode->window.watermark, .calTrigger = pStateNode->window.triggerType};

dengyihao's avatar
dengyihao 已提交
4853
    SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &num);
4854
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4855 4856
    int32_t      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;

4857 4858 4859
    SColumnNode* pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
    SColumn col = extractColumnFromColumnNode(pColNode);
    pOptr = createStatewindowOperatorInfo(ops[0], pExprInfo, num, pResBlock, &as, tsSlotId, &col, pTaskInfo);
4860
  } else if (QUERY_NODE_PHYSICAL_PLAN_JOIN == type) {
dengyihao's avatar
dengyihao 已提交
4861 4862
    SJoinPhysiNode* pJoinNode = (SJoinPhysiNode*)pPhyNode;
    SSDataBlock*    pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4863 4864

    SExprInfo* pExprInfo = createExprInfo(pJoinNode->pTargets, NULL, &num);
H
Haojun Liao 已提交
4865
    pOptr = createMergeJoinOperatorInfo(ops, size, pExprInfo, num, pResBlock, pJoinNode->pOnConditions, pTaskInfo);
4866 4867
  } else if (QUERY_NODE_PHYSICAL_PLAN_FILL == type) {
    SFillPhysiNode* pFillNode = (SFillPhysiNode*)pPhyNode;
X
Xiaoyu Wang 已提交
4868 4869
    SSDataBlock*    pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
    SExprInfo*      pExprInfo = createExprInfo(pFillNode->pTargets, NULL, &num);
4870

4871
    SInterval* pInterval = &((SIntervalAggOperatorInfo*)ops[0]->info)->interval;
X
Xiaoyu Wang 已提交
4872 4873
    pOptr = createFillOperatorInfo(ops[0], pExprInfo, num, pInterval, &pFillNode->timeRange, pResBlock, pFillNode->mode,
                                   (SNodeListNode*)pFillNode->pValues, false, pTaskInfo);
H
Haojun Liao 已提交
4874 4875
  } else {
    ASSERT(0);
H
Haojun Liao 已提交
4876
  }
4877 4878 4879

  taosMemoryFree(ops);
  return pOptr;
4880
}
H
Haojun Liao 已提交
4881

4882
int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode) {
4883 4884 4885 4886 4887 4888
  pCond->loadExternalRows = false;

  pCond->order = pTableScanNode->scanSeq[0] > 0 ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
  pCond->numOfCols = LIST_LENGTH(pTableScanNode->scan.pScanCols);
  pCond->colList = taosMemoryCalloc(pCond->numOfCols, sizeof(SColumnInfo));
  if (pCond->colList == NULL) {
H
Haojun Liao 已提交
4889
    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
4890 4891 4892 4893 4894 4895
    return terrno;
  }

  pCond->twindow = pTableScanNode->scanRange;

#if 1
L
Liu Jicong 已提交
4896
  // todo work around a problem, remove it later
4897 4898
  if ((pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey > pCond->twindow.ekey) ||
      (pCond->order == TSDB_ORDER_DESC && pCond->twindow.skey < pCond->twindow.ekey)) {
wafwerar's avatar
wafwerar 已提交
4899
    TSWAP(pCond->twindow.skey, pCond->twindow.ekey);
H
Haojun Liao 已提交
4900
  }
4901
#endif
H
Haojun Liao 已提交
4902

4903 4904
  pCond->type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
  //  pCond->type = pTableScanNode->scanFlag;
H
Haojun Liao 已提交
4905

H
Haojun Liao 已提交
4906
  int32_t j = 0;
4907
  for (int32_t i = 0; i < pCond->numOfCols; ++i) {
H
Haojun Liao 已提交
4908 4909
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pTableScanNode->scan.pScanCols, i);
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
H
Haojun Liao 已提交
4910 4911 4912
    if (pColNode->colType == COLUMN_TYPE_TAG) {
      continue;
    }
H
Haojun Liao 已提交
4913

4914 4915 4916
    pCond->colList[j].type = pColNode->node.resType.type;
    pCond->colList[j].bytes = pColNode->node.resType.bytes;
    pCond->colList[j].colId = pColNode->colId;
H
Haojun Liao 已提交
4917
    j += 1;
H
Haojun Liao 已提交
4918 4919
  }

4920 4921
  pCond->numOfCols = j;
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
4922
}
H
Haojun Liao 已提交
4923

4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934
SColumn extractColumnFromColumnNode(SColumnNode* pColNode) {
  SColumn c = {0};
  c.slotId    = pColNode->slotId;
  c.colId     = pColNode->colId;
  c.type      = pColNode->node.resType.type;
  c.bytes     = pColNode->node.resType.bytes;
  c.scale     = pColNode->node.resType.scale;
  c.precision = pColNode->node.resType.precision;
  return c;
}

H
Haojun Liao 已提交
4935
SArray* extractColumnInfo(SNodeList* pNodeList) {
L
Liu Jicong 已提交
4936
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
4937 4938 4939 4940 4941 4942
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

L
Liu Jicong 已提交
4943 4944
  for (int32_t i = 0; i < numOfCols; ++i) {
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pNodeList, i);
H
Haojun Liao 已提交
4945

4946 4947 4948
    if (nodeType(pNode->pExpr) == QUERY_NODE_COLUMN) {
      SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;

4949
      SColumn c = extractColumnFromColumnNode(pColNode);
4950 4951
      taosArrayPush(pList, &c);
    } else if (nodeType(pNode->pExpr) == QUERY_NODE_VALUE) {
L
Liu Jicong 已提交
4952 4953
      SValueNode* pValNode = (SValueNode*)pNode->pExpr;
      SColumn     c = {0};
4954
      c.slotId = pNode->slotId;
L
Liu Jicong 已提交
4955 4956 4957 4958
      c.colId = pNode->slotId;
      c.type = pValNode->node.type;
      c.bytes = pValNode->node.resType.bytes;
      c.scale = pValNode->node.resType.scale;
4959 4960 4961 4962
      c.precision = pValNode->node.resType.precision;

      taosArrayPush(pList, &c);
    }
H
Haojun Liao 已提交
4963 4964 4965 4966 4967
  }

  return pList;
}

4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981
SArray* extractPartitionColInfo(SNodeList* pNodeList) {
  size_t  numOfCols = LIST_LENGTH(pNodeList);
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

  for (int32_t i = 0; i < numOfCols; ++i) {
    SColumnNode* pColNode = (SColumnNode*)nodesListGetNode(pNodeList, i);

    // todo extract method
    SColumn c = {0};
    c.slotId = pColNode->slotId;
dengyihao's avatar
dengyihao 已提交
4982 4983 4984
    c.colId = pColNode->colId;
    c.type = pColNode->node.resType.type;
    c.bytes = pColNode->node.resType.bytes;
4985 4986 4987 4988 4989 4990 4991 4992 4993
    c.precision = pColNode->node.resType.precision;
    c.scale = pColNode->node.resType.scale;

    taosArrayPush(pList, &c);
  }

  return pList;
}

4994
SArray* createSortInfo(SNodeList* pNodeList) {
L
Liu Jicong 已提交
4995
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
4996 4997 4998 4999 5000 5001
  SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return pList;
  }

L
Liu Jicong 已提交
5002
  for (int32_t i = 0; i < numOfCols; ++i) {
5003
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)nodesListGetNode(pNodeList, i);
L
Liu Jicong 已提交
5004 5005
    SBlockOrderInfo   bi = {0};
    bi.order = (pSortKey->order == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
H
Haojun Liao 已提交
5006 5007 5008
    bi.nullFirst = (pSortKey->nullOrder == NULL_ORDER_FIRST);

    SColumnNode* pColNode = (SColumnNode*)pSortKey->pExpr;
5009
    bi.slotId = pColNode->slotId;
H
Haojun Liao 已提交
5010 5011 5012 5013 5014 5015
    taosArrayPush(pList, &bi);
  }

  return pList;
}

X
Xiaoyu Wang 已提交
5016 5017
SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols,
                            int32_t type) {
L
Liu Jicong 已提交
5018
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
5019 5020 5021 5022 5023 5024
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColMatchInfo));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

L
Liu Jicong 已提交
5025 5026 5027
  for (int32_t i = 0; i < numOfCols; ++i) {
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pNodeList, i);
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
H
Haojun Liao 已提交
5028 5029

    SColMatchInfo c = {0};
X
Xiaoyu Wang 已提交
5030 5031 5032 5033
    c.output = true;
    c.colId = pColNode->colId;
    c.srcSlotId = pColNode->slotId;
    c.matchType = type;
H
Haojun Liao 已提交
5034 5035 5036 5037
    c.targetSlotId = pNode->slotId;
    taosArrayPush(pList, &c);
  }

H
Haojun Liao 已提交
5038 5039
  *numOfOutputCols = 0;
  int32_t num = LIST_LENGTH(pOutputNodeList->pSlots);
L
Liu Jicong 已提交
5040 5041
  for (int32_t i = 0; i < num; ++i) {
    SSlotDescNode* pNode = (SSlotDescNode*)nodesListGetNode(pOutputNodeList->pSlots, i);
5042

5043
    // todo: add reserve flag check
5044 5045
    // it is a column reserved for the arithmetic expression calculation
    if (pNode->slotId >= numOfCols) {
5046 5047 5048 5049
      (*numOfOutputCols) += 1;
      continue;
    }

H
Haojun Liao 已提交
5050
    SColMatchInfo* info = taosArrayGet(pList, pNode->slotId);
H
Haojun Liao 已提交
5051 5052 5053 5054 5055
    if (pNode->output) {
      (*numOfOutputCols) += 1;
    } else {
      info->output = false;
    }
H
Haojun Liao 已提交
5056 5057
  }

H
Haojun Liao 已提交
5058 5059 5060
  return pList;
}

dengyihao's avatar
dengyihao 已提交
5061 5062
int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo,
                           uint64_t queryId, uint64_t taskId) {
5063
  int32_t code = 0;
H
Haojun Liao 已提交
5064
  if (tableType == TSDB_SUPER_TABLE) {
H
Haojun Liao 已提交
5065
    code = tsdbQuerySTableByTagCond(metaHandle, tableUid, 0, NULL, 0, 0, NULL, pGroupInfo, NULL, 0, queryId, taskId);
H
Haojun Liao 已提交
5066
  } else {  // Create one table group.
H
Haojun Liao 已提交
5067
    code = tsdbGetOneTableGroup(metaHandle, tableUid, 0, pGroupInfo);
5068 5069 5070 5071
  }

  return code;
}
H
Haojun Liao 已提交
5072

5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090
SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo) {
  SArray* tableIdList = taosArrayInit(4, sizeof(uint64_t));

  if (pTableGroupInfo->numOfTables > 0) {
    SArray* pa = taosArrayGetP(pTableGroupInfo->pGroupList, 0);
    ASSERT(taosArrayGetSize(pTableGroupInfo->pGroupList) == 1);

    // Transfer the Array of STableKeyInfo into uid list.
    size_t numOfTables = taosArrayGetSize(pa);
    for (int32_t i = 0; i < numOfTables; ++i) {
      STableKeyInfo* pkeyInfo = taosArrayGet(pa, i);
      taosArrayPush(tableIdList, &pkeyInfo->uid);
    }
  }

  return tableIdList;
}

L
Liu Jicong 已提交
5091 5092
tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
                               STableGroupInfo* pTableGroupInfo, uint64_t queryId, uint64_t taskId) {
5093
  uint64_t uid = pTableScanNode->scan.uid;
L
Liu Jicong 已提交
5094 5095
  int32_t  code =
      doCreateTableGroup(pHandle->meta, pTableScanNode->scan.tableType, uid, pTableGroupInfo, queryId, taskId);
5096 5097
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
H
Haojun Liao 已提交
5098
  }
H
Haojun Liao 已提交
5099

H
Haojun Liao 已提交
5100
  if (pTableGroupInfo->numOfTables == 0) {
H
Haojun Liao 已提交
5101
    code = 0;
L
Liu Jicong 已提交
5102
    qDebug("no table qualified for query, TID:0x%" PRIx64 ", QID:0x%" PRIx64, taskId, queryId);
H
Haojun Liao 已提交
5103 5104
    goto _error;
  }
H
Haojun Liao 已提交
5105

5106 5107 5108 5109
  SQueryTableDataCond cond = {0};
  code = initQueryTableDataCond(&cond, pTableScanNode);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
X
Xiaoyu Wang 已提交
5110
  }
5111

5112
  return tsdbQueryTables(pHandle->vnode, &cond, pTableGroupInfo, queryId, taskId);
H
Haojun Liao 已提交
5113

L
Liu Jicong 已提交
5114
_error:
H
Haojun Liao 已提交
5115 5116 5117 5118
  terrno = code;
  return NULL;
}

dengyihao's avatar
dengyihao 已提交
5119 5120
int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId,
                               EOPTR_EXEC_MODEL model) {
H
Haojun Liao 已提交
5121 5122
  uint64_t queryId = pPlan->id.queryId;

H
Haojun Liao 已提交
5123
  int32_t code = TSDB_CODE_SUCCESS;
5124
  *pTaskInfo = createExecTaskInfo(queryId, taskId, model);
H
Haojun Liao 已提交
5125 5126 5127 5128
  if (*pTaskInfo == NULL) {
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _complete;
  }
H
Haojun Liao 已提交
5129

L
Liu Jicong 已提交
5130 5131
  (*pTaskInfo)->pRoot =
      createOperatorTree(pPlan->pNode, *pTaskInfo, pHandle, queryId, taskId, &(*pTaskInfo)->tableqinfoGroupInfo);
D
dapan1121 已提交
5132
  if (NULL == (*pTaskInfo)->pRoot) {
L
Liu Jicong 已提交
5133
    code = terrno;
D
dapan1121 已提交
5134 5135
    goto _complete;
  }
H
Haojun Liao 已提交
5136

5137
  if ((*pTaskInfo)->pRoot == NULL) {
H
Haojun Liao 已提交
5138
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
H
Haojun Liao 已提交
5139
    goto _complete;
5140 5141
  }

H
Haojun Liao 已提交
5142 5143
  return code;

H
Haojun Liao 已提交
5144
_complete:
wafwerar's avatar
wafwerar 已提交
5145
  taosMemoryFreeClear(*pTaskInfo);
H
Haojun Liao 已提交
5146 5147 5148

  terrno = code;
  return code;
H
Haojun Liao 已提交
5149 5150
}

H
Haojun Liao 已提交
5151
void setResultBufSize(STaskAttr* pQueryAttr, SResultInfo* pResultInfo) {
5152 5153 5154 5155 5156 5157 5158 5159
  const int32_t DEFAULT_RESULT_MSG_SIZE = 1024 * (1024 + 512);

  // the minimum number of rows for projection query
  const int32_t MIN_ROWS_FOR_PRJ_QUERY = 8192;
  const int32_t DEFAULT_MIN_ROWS = 4096;

  const float THRESHOLD_RATIO = 0.85f;

dengyihao's avatar
dengyihao 已提交
5160 5161 5162 5163 5164 5165 5166 5167 5168 5169
  //  if (isProjQuery(pQueryAttr)) {
  //    int32_t numOfRes = DEFAULT_RESULT_MSG_SIZE / pQueryAttr->resultRowSize;
  //    if (numOfRes < MIN_ROWS_FOR_PRJ_QUERY) {
  //      numOfRes = MIN_ROWS_FOR_PRJ_QUERY;
  //    }
  //
  //    pResultInfo->capacity = numOfRes;
  //  } else {  // in case of non-prj query, a smaller output buffer will be used.
  //    pResultInfo->capacity = DEFAULT_MIN_ROWS;
  //  }
5170 5171

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
H
Haojun Liao 已提交
5172
  pResultInfo->totalRows = 0;
5173 5174
}

L
Liu Jicong 已提交
5175
// TODO refactor
5176
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
L
Liu Jicong 已提交
5177 5178 5179
  if (pFilter == NULL || numOfFilters == 0) {
    return;
  }
5180

L
Liu Jicong 已提交
5181 5182 5183
  for (int32_t i = 0; i < numOfFilters; i++) {
    if (pFilter[i].filterstr && pFilter[i].pz) {
      taosMemoryFree((void*)(pFilter[i].pz));
5184
    }
L
Liu Jicong 已提交
5185
  }
5186

L
Liu Jicong 已提交
5187
  taosMemoryFree(pFilter);
5188 5189 5190 5191
}

static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
L
Liu Jicong 已提交
5192
    int32_t numOfGroups = (int32_t)taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
5193
    for (int32_t i = 0; i < numOfGroups; ++i) {
L
Liu Jicong 已提交
5194
      SArray* p = taosArrayGetP(pTableqinfoGroupInfo->pGroupList, i);
5195 5196

      size_t num = taosArrayGetSize(p);
L
Liu Jicong 已提交
5197
      for (int32_t j = 0; j < num; ++j) {
5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213
        STableQueryInfo* item = taosArrayGetP(p, j);
        destroyTableQueryInfoImpl(item);
      }

      taosArrayDestroy(p);
    }
  }

  taosArrayDestroy(pTableqinfoGroupInfo->pGroupList);
  taosHashCleanup(pTableqinfoGroupInfo->map);

  pTableqinfoGroupInfo->pGroupList = NULL;
  pTableqinfoGroupInfo->map = NULL;
  pTableqinfoGroupInfo->numOfTables = 0;
}

L
Liu Jicong 已提交
5214
void doDestroyTask(SExecTaskInfo* pTaskInfo) {
H
Haojun Liao 已提交
5215 5216
  qDebug("%s execTask is freed", GET_TASKID(pTaskInfo));

H
Haojun Liao 已提交
5217
  doDestroyTableQueryInfo(&pTaskInfo->tableqinfoGroupInfo);
H
Haojun Liao 已提交
5218
  destroyOperatorInfo(pTaskInfo->pRoot);
L
Liu Jicong 已提交
5219 5220
  //  taosArrayDestroy(pTaskInfo->summary.queryProfEvents);
  //  taosHashCleanup(pTaskInfo->summary.operatorProfResults);
5221

wafwerar's avatar
wafwerar 已提交
5222 5223 5224
  taosMemoryFreeClear(pTaskInfo->sql);
  taosMemoryFreeClear(pTaskInfo->id.str);
  taosMemoryFreeClear(pTaskInfo);
5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236
}

static void doSetTagValueToResultBuf(char* output, const char* val, int16_t type, int16_t bytes) {
  if (val == NULL) {
    setNull(output, type, bytes);
    return;
  }

  if (IS_VAR_DATA_TYPE(type)) {
    // Binary data overflows for sort of unknown reasons. Let trim the overflow data
    if (varDataTLen(val) > bytes) {
      int32_t maxLen = bytes - VARSTR_HEADER_SIZE;
L
Liu Jicong 已提交
5237
      int32_t len = (varDataLen(val) > maxLen) ? maxLen : varDataLen(val);
5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249
      memcpy(varDataVal(output), varDataVal(val), len);
      varDataSetLen(output, len);
    } else {
      varDataCopy(output, val);
    }
  } else {
    memcpy(output, val, bytes);
  }
}

static int64_t getQuerySupportBufSize(size_t numOfTables) {
  size_t s1 = sizeof(STableQueryInfo);
L
Liu Jicong 已提交
5250 5251
  //  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
  return (int64_t)(s1 * 1.5 * numOfTables);
5252 5253 5254 5255 5256 5257 5258
}

int32_t checkForQueryBuf(size_t numOfTables) {
  int64_t t = getQuerySupportBufSize(numOfTables);
  if (tsQueryBufferSizeBytes < 0) {
    return TSDB_CODE_SUCCESS;
  } else if (tsQueryBufferSizeBytes > 0) {
L
Liu Jicong 已提交
5259
    while (1) {
5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285
      int64_t s = tsQueryBufferSizeBytes;
      int64_t remain = s - t;
      if (remain >= 0) {
        if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) {
          return TSDB_CODE_SUCCESS;
        }
      } else {
        return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER;
      }
    }
  }

  // disable query processing if the value of tsQueryBufferSize is zero.
  return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER;
}

void releaseQueryBuf(size_t numOfTables) {
  if (tsQueryBufferSizeBytes < 0) {
    return;
  }

  int64_t t = getQuerySupportBufSize(numOfTables);

  // restore value is not enough buffer available
  atomic_add_fetch_64(&tsQueryBufferSizeBytes, t);
}
D
dapan1121 已提交
5286

dengyihao's avatar
dengyihao 已提交
5287 5288
int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SExplainExecInfo** pRes, int32_t* capacity,
                                   int32_t* resNum) {
D
dapan1121 已提交
5289 5290
  if (*resNum >= *capacity) {
    *capacity += 10;
dengyihao's avatar
dengyihao 已提交
5291

D
dapan1121 已提交
5292 5293
    *pRes = taosMemoryRealloc(*pRes, (*capacity) * sizeof(SExplainExecInfo));
    if (NULL == *pRes) {
D
dapan1121 已提交
5294
      qError("malloc %d failed", (*capacity) * (int32_t)sizeof(SExplainExecInfo));
D
dapan1121 已提交
5295 5296 5297 5298
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
  }

D
dapan1121 已提交
5299 5300 5301 5302
  (*pRes)[*resNum].numOfRows = operatorInfo->resultInfo.totalRows;
  (*pRes)[*resNum].startupCost = operatorInfo->cost.openCost;
  (*pRes)[*resNum].totalCost = operatorInfo->cost.totalCost;

5303 5304
  if (operatorInfo->fpSet.getExplainFn) {
    int32_t code = (*operatorInfo->fpSet.getExplainFn)(operatorInfo, &(*pRes)->verboseInfo);
D
dapan1121 已提交
5305 5306 5307 5308 5309
    if (code) {
      qError("operator getExplainFn failed, error:%s", tstrerror(code));
      return code;
    }
  }
dengyihao's avatar
dengyihao 已提交
5310

D
dapan1121 已提交
5311
  ++(*resNum);
dengyihao's avatar
dengyihao 已提交
5312

D
dapan1121 已提交
5313
  int32_t code = 0;
D
dapan1121 已提交
5314 5315
  for (int32_t i = 0; i < operatorInfo->numOfDownstream; ++i) {
    code = getOperatorExplainExecInfo(operatorInfo->pDownstream[i], pRes, capacity, resNum);
D
dapan1121 已提交
5316 5317 5318 5319 5320 5321 5322
    if (code) {
      taosMemoryFreeClear(*pRes);
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
5323
}