executorimpl.c 202.6 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 110
static int32_t setTimestampListJoinInfo(STaskRuntimeEnv* pRuntimeEnv, SVariant* pTag, STableQueryInfo* pTableQueryInfo);
static void    releaseQueryBuf(size_t numOfTables);
111

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

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 已提交
119

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

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

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

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

139
SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t streamFn,
L
Liu Jicong 已提交
140 141
                                   __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) {
142 143 144 145 146 147 148 149 150 151 152 153 154 155
  SOperatorFpSet fpSet = {
      ._openFn = openFn,
      .getNextFn = nextFn,
      .getStreamResFn = streamFn,
      .cleanupFn = cleanup,
      .closeFn = closeFn,
      .encodeResultRow = encode,
      .decodeResultRow = decode,
      .getExplainFn = explain,
  };

  return fpSet;
}

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

dengyihao's avatar
dengyihao 已提交
158 159 160
static int32_t doCopyToSDataBlock(SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf,
                                  SGroupResInfo* pGroupResInfo, int32_t orderType, int32_t* rowCellOffset,
                                  SqlFunctionCtx* pCtx);
H
Haojun Liao 已提交
161

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

H
Haojun Liao 已提交
167
SArray* getOrderCheckColumns(STaskAttr* pQuery);
168 169

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
199
  pBlock->info.blockId = pNode->dataBlockId;
dengyihao's avatar
dengyihao 已提交
200
  pBlock->info.rowSize = pNode->totalRowSize;  // todo ??
H
Haojun Liao 已提交
201

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

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

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

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

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

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

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

  return true;
}

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

242 243 244 245 246 247 248 249 250 251 252
  // 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);
  }

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

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

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

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

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

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

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

    return existed;
  }

  return p1 != NULL;
}

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

  // 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 已提交
321
    if (pData->num + interBufSize > getBufPageSize(pResultBuf)) {
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
      // 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 已提交
341
  pData->num += interBufSize;
342 343 344 345

  return pResultRow;
}

346 347 348 349 350 351 352
/**
 * the struct of key in hash table
 * +----------+---------------+
 * | group id |   key data    |
 * | 8 bytes  | actual length |
 * +----------+---------------+
 */
353 354 355
SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData,
                                   int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo,
                                   bool isIntervalQuery, SAggSupporter* pSup) {
356
  SET_RES_WINDOW_KEY(pSup->keyBuf, pData, bytes, groupId);
H
Haojun Liao 已提交
357

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

361 362
  SResultRow* pResult = NULL;

H
Haojun Liao 已提交
363 364
  // in case of repeat scan/reverse scan, no new time window added.
  if (isIntervalQuery) {
365 366
    if (masterscan && p1 != NULL) {  // the *p1 may be NULL in case of sliding+offset exists.
      pResult = getResultRowByPos(pResultBuf, p1);
H
Haojun Liao 已提交
367 368
    }
  } else {
dengyihao's avatar
dengyihao 已提交
369 370
    // In case of group by column query, the required SResultRow object must be existInCurrentResusltRowInfo in the
    // pResultRowInfo object.
H
Haojun Liao 已提交
371
    if (p1 != NULL) {
372
      pResult = getResultRowByPos(pResultBuf, p1);
H
Haojun Liao 已提交
373 374 375
    }
  }

L
Liu Jicong 已提交
376
  // 1. close current opened time window
377
  if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId &&
L
Liu Jicong 已提交
378
                                                                 pResult->offset != pResultRowInfo->cur.offset))) {
379 380 381 382 383 384 385 386 387 388 389 390 391
    // 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) {
    pResult = getNewResultRow_rv(pResultBuf, groupId, pSup->resultRowSize);
    initResultRow(pResult);
H
Haojun Liao 已提交
392

393 394
    // add a new result set for a new group
    SResultRowPosition pos = {.pageId = pResult->pageId, .offset = pResult->offset};
L
Liu Jicong 已提交
395 396
    taosHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos,
                sizeof(SResultRowPosition));
H
Haojun Liao 已提交
397 398
  }

399 400 401 402 403
  // 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 已提交
404 405 406 407 408
  // 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 已提交
409
  return pResult;
H
Haojun Liao 已提交
410 411
}

412
// get the correct time window according to the handled timestamp
L
Liu Jicong 已提交
413
static STimeWindow getCurrentActiveTimeWindow(SResultRowInfo* pResultRowInfo, int64_t ts, STaskAttr* pQueryAttr) {
414
  STimeWindow w = {0};
H
Haojun Liao 已提交
415
#if 0
L
Liu Jicong 已提交
416 417
  if (pResultRowInfo->curPos == -1) {  // the first window, from the previous stored value
                                       //    getInitialStartTimeWindow(pQueryAttr, ts, &w);
418 419

    if (pQueryAttr->interval.intervalUnit == 'n' || pQueryAttr->interval.intervalUnit == 'y') {
L
Liu Jicong 已提交
420 421 422
      w.ekey =
          taosTimeAdd(w.skey, pQueryAttr->interval.interval, pQueryAttr->interval.intervalUnit, pQueryAttr->precision) -
          1;
423 424 425 426
    } else {
      w.ekey = w.skey + pQueryAttr->interval.interval - 1;
    }
  } else {
H
Haojun Liao 已提交
427
    w = pRow->win;
428 429 430 431 432 433 434 435 436
  }

  /*
   * 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 已提交
437
#endif
438 439 440 441 442

  return w;
}

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

L
Liu Jicong 已提交
448
  SFilePage* pData = NULL;
449 450 451 452 453 454

  // 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 已提交
455
    pData = getNewBufPage(pResultBuf, tid, &pageId);
456
    pData->num = sizeof(SFilePage);
457 458
  } else {
    SPageInfo* pi = getLastPageInfo(list);
459
    pData = getBufPage(pResultBuf, getPageId(pi));
460
    pageId = getPageId(pi);
461

462
    if (pData->num + size > getBufPageSize(pResultBuf)) {
463
      // release current page first, and prepare the next one
464
      releaseBufPageInfo(pResultBuf, pi);
465

H
Haojun Liao 已提交
466
      pData = getNewBufPage(pResultBuf, tid, &pageId);
467
      if (pData != NULL) {
468
        pData->num = sizeof(SFilePage);
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
      }
    }
  }

  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 已提交
489 490 491
static bool chkWindowOutputBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultRowInfo* pResultRowInfo, STimeWindow* win,
                                    bool masterscan, SResultRow** pResult, int64_t groupId, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowCellInfoOffset) {
492
  assert(win->skey <= win->ekey);
L
Liu Jicong 已提交
493
  return chkResultRowFromKey(pRuntimeEnv, pResultRowInfo, (char*)&win->skey, TSDB_KEYSIZE, masterscan, groupId);
494 495
}

dengyihao's avatar
dengyihao 已提交
496 497
static void doUpdateResultRowIndex(SResultRowInfo* pResultRowInfo, TSKEY lastKey, bool ascQuery,
                                   bool timeWindowInterpo) {
498
  int64_t skey = TSKEY_INITIAL_VAL;
H
Haojun Liao 已提交
499
#if 0
500 501
  int32_t i = 0;
  for (i = pResultRowInfo->size - 1; i >= 0; --i) {
L
Liu Jicong 已提交
502
    SResultRow* pResult = pResultRowInfo->pResult[i];
503 504 505 506 507 508
    if (pResult->closed) {
      break;
    }

    // new closed result rows
    if (timeWindowInterpo) {
L
Liu Jicong 已提交
509 510 511
      if (pResult->endInterp &&
          ((pResult->win.skey <= lastKey && ascQuery) || (pResult->win.skey >= lastKey && !ascQuery))) {
        if (i > 0) {  // the first time window, the startInterp is false.
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
          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 已提交
531
      //      assert(pResultRowInfo->current == NULL);
532 533 534 535 536 537 538
      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 已提交
539
      SResultRow* pResult = pResultRowInfo->pResult[i];
540 541 542 543 544 545 546 547 548 549 550
      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 已提交
551
#endif
552
}
553
//
dengyihao's avatar
dengyihao 已提交
554
// static void updateResultRowInfoActiveIndex(SResultRowInfo* pResultRowInfo, const STimeWindow* pWin, TSKEY lastKey,
555 556 557 558 559 560 561 562 563
//                                           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);
//  }
//}
564

565
//  query_range_start, query_range_end, window_duration, window_start, window_end
566
void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow) {
567 568 569
  pColData->info.type = TSDB_DATA_TYPE_TIMESTAMP;
  pColData->info.bytes = sizeof(int64_t);

570
  colInfoDataEnsureCapacity(pColData, 0, 5);
571 572 573 574 575 576 577 578 579
  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);
}

dengyihao's avatar
dengyihao 已提交
580 581
void doApplyFunctions(SqlFunctionCtx* pCtx, STimeWindow* pWin, SColumnInfoData* pTimeWindowData, int32_t offset,
                      int32_t forwardStep, TSKEY* tsCol, int32_t numOfTotal, int32_t numOfOutput, int32_t order) {
582 583 584
  for (int32_t k = 0; k < numOfOutput; ++k) {
    pCtx[k].startTs = pWin->skey;

H
Haojun Liao 已提交
585
    // keep it temporarily
dengyihao's avatar
dengyihao 已提交
586 587
    bool    hasAgg = pCtx[k].input.colDataAggIsSet;
    int32_t numOfRows = pCtx[k].input.numOfRows;
H
Haojun Liao 已提交
588
    int32_t startOffset = pCtx[k].input.startRowIndex;
589

H
Haojun Liao 已提交
590
    int32_t pos = (order == TSDB_ORDER_ASC) ? offset : offset - (forwardStep - 1);
591 592
    pCtx[k].input.startRowIndex = pos;
    pCtx[k].input.numOfRows = forwardStep;
593 594

    if (tsCol != NULL) {
H
Haojun Liao 已提交
595
      pCtx[k].ptsList = tsCol;
596 597 598 599 600 601 602 603
    }

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

604 605
    if (fmIsWindowPseudoColumnFunc(pCtx[k].functionId)) {
      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[k]);
dengyihao's avatar
dengyihao 已提交
606
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
607

608
      SColumnInfoData idata = {0};
dengyihao's avatar
dengyihao 已提交
609
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
610
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
dengyihao's avatar
dengyihao 已提交
611
      idata.pData = p;
612 613 614 615

      SScalarParam out = {.columnData = &idata};
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
      pCtx[k].sfp.process(&tw, 1, &out);
616 617 618 619
      pEntryInfo->numOfRes = 1;
      continue;
    }

H
Haojun Liao 已提交
620
    if (functionNeedToExecute(&pCtx[k])) {
621
      pCtx[k].fpSet.process(&pCtx[k]);
622 623 624
    }

    // restore it
625 626 627
    pCtx[k].input.colDataAggIsSet = hasAgg;
    pCtx[k].input.startRowIndex = startOffset;
    pCtx[k].input.numOfRows = numOfRows;
628 629 630
  }
}

L
Liu Jicong 已提交
631
static FORCE_INLINE TSKEY reviseWindowEkey(STaskAttr* pQueryAttr, STimeWindow* pWindow) {
dengyihao's avatar
dengyihao 已提交
632
  TSKEY   ekey = -1;
633 634
  int32_t order = TSDB_ORDER_ASC;
  if (order == TSDB_ORDER_ASC) {
635 636 637 638 639 640 641 642 643 644 645 646 647 648
    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 已提交
649 650
static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
                                   bool createDummyCol);
651

dengyihao's avatar
dengyihao 已提交
652 653
static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock,
                                    int32_t order) {
654 655
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
    pCtx[i].order = order;
L
Liu Jicong 已提交
656
    pCtx[i].size = pBlock->info.rows;
657
    setBlockStatisInfo(&pCtx[i], &pOperator->pExpr[i], pBlock);
658 659 660
  }
}

dengyihao's avatar
dengyihao 已提交
661 662
void setInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
                       bool createDummyCol) {
663
  if (pBlock->pBlockAgg != NULL) {
H
Haojun Liao 已提交
664
    doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
665
  } else {
666
    doSetInputDataBlock(pOperator, pCtx, pBlock, order, createDummyCol);
H
Haojun Liao 已提交
667
  }
668 669
}

L
Liu Jicong 已提交
670 671
static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t paramIndex,
                                             int32_t numOfRows) {
672 673 674 675 676 677 678 679
  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)
680 681
    pColInfo->info.type = pFuncParam->param.nType;
    pColInfo->info.bytes = pFuncParam->param.nLen;
682 683

    pInput->pData[paramIndex] = pColInfo;
684 685
  } else {
    pColInfo = pInput->pData[paramIndex];
686 687
  }

688
  colInfoDataEnsureCapacity(pColInfo, 0, numOfRows);
689

690
  int8_t type = pFuncParam->param.nType;
691 692
  if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT) {
    int64_t v = pFuncParam->param.i;
dengyihao's avatar
dengyihao 已提交
693
    for (int32_t i = 0; i < numOfRows; ++i) {
694 695 696 697
      colDataAppendInt64(pColInfo, i, &v);
    }
  } else if (type == TSDB_DATA_TYPE_DOUBLE) {
    double v = pFuncParam->param.d;
dengyihao's avatar
dengyihao 已提交
698
    for (int32_t i = 0; i < numOfRows; ++i) {
699 700
      colDataAppendDouble(pColInfo, i, &v);
    }
701
  } else if (type == TSDB_DATA_TYPE_VARCHAR) {
L
Liu Jicong 已提交
702
    char* tmp = taosMemoryMalloc(pFuncParam->param.nLen + VARSTR_HEADER_SIZE);
703
    STR_WITH_SIZE_TO_VARSTR(tmp, pFuncParam->param.pz, pFuncParam->param.nLen);
L
Liu Jicong 已提交
704
    for (int32_t i = 0; i < numOfRows; ++i) {
705 706
      colDataAppend(pColInfo, i, tmp, false);
    }
707 708 709 710 711
  }

  return TSDB_CODE_SUCCESS;
}

dengyihao's avatar
dengyihao 已提交
712 713
static int32_t doSetInputDataBlock(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order,
                                   bool createDummyCol) {
714 715
  int32_t code = TSDB_CODE_SUCCESS;

716
  for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
L
Liu Jicong 已提交
717 718 719
    pCtx[i].order = order;
    pCtx[i].size = pBlock->info.rows;
    pCtx[i].pSrcBlock = pBlock;
H
Haojun Liao 已提交
720 721
    pCtx[i].currentStage = MAIN_SCAN;

722
    SInputColumnInfoData* pInput = &pCtx[i].input;
723
    pInput->uid = pBlock->info.uid;
C
Cary Xu 已提交
724
    pInput->colDataAggIsSet = false;
725

726 727
    SExprInfo* pOneExpr = &pOperator->pExpr[i];
    for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) {
dengyihao's avatar
dengyihao 已提交
728
      SFunctParam* pFuncParam = &pOneExpr->base.pParam[j];
G
Ganlin Zhao 已提交
729 730
      if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) {
        int32_t slotId = pFuncParam->pCol->slotId;
dengyihao's avatar
dengyihao 已提交
731
        pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId);
732 733 734
        pInput->totalRows = pBlock->info.rows;
        pInput->numOfRows = pBlock->info.rows;
        pInput->startRowIndex = 0;
735

736 737 738 739
        // the last parameter is the timestamp column
        if (fmIsTimelineFunc(pCtx[i].functionId) && (j == pOneExpr->base.numOfParams - 1)) {
          pInput->pPTS = pInput->pData[j];
        }
740 741
        ASSERT(pInput->pData[j] != NULL);
      } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) {
742 743 744
        // 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) {
745 746 747 748
          pInput->totalRows = pBlock->info.rows;
          pInput->numOfRows = pBlock->info.rows;
          pInput->startRowIndex = 0;

749
          code = doCreateConstantValColumnInfo(pInput, pFuncParam, j, pBlock->info.rows);
750 751 752
          if (code != TSDB_CODE_SUCCESS) {
            return code;
          }
753
        }
G
Ganlin Zhao 已提交
754 755
      }
    }
H
Haojun Liao 已提交
756

H
Haojun Liao 已提交
757
    //    setBlockStatisInfo(&pCtx[i], pBlock, pOperator->pExpr[i].base.pColumns);
H
Haojun Liao 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
    //      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);
    //        }
    //      }
  }
796 797

  return code;
H
Haojun Liao 已提交
798 799 800
}

static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SqlFunctionCtx* pCtx) {
801
  for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
H
Haojun Liao 已提交
802
    if (functionNeedToExecute(&pCtx[k])) {
L
Liu Jicong 已提交
803
      pCtx[k].startTs = startTs;  // this can be set during create the struct
H
Haojun Liao 已提交
804
      pCtx[k].fpSet.process(&pCtx[k]);
805 806 807 808
    }
  }
}

H
Haojun Liao 已提交
809
static void setPseudoOutputColInfo(SSDataBlock* pResult, SqlFunctionCtx* pCtx, SArray* pPseudoList) {
dengyihao's avatar
dengyihao 已提交
810
  size_t num = (pPseudoList != NULL) ? taosArrayGetSize(pPseudoList) : 0;
H
Haojun Liao 已提交
811 812 813 814 815
  for (int32_t i = 0; i < num; ++i) {
    pCtx[i].pOutput = taosArrayGet(pResult->pDataBlock, i);
  }
}

816
int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBlock* pSrcBlock, SqlFunctionCtx* pCtx,
X
Xiaoyu Wang 已提交
817
                              int32_t numOfOutput, SArray* pPseudoList) {
H
Haojun Liao 已提交
818
  setPseudoOutputColInfo(pResult, pCtx, pPseudoList);
H
Haojun Liao 已提交
819
  pResult->info.groupId = pSrcBlock->info.groupId;
H
Haojun Liao 已提交
820

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

825 826
  int32_t numOfRows = 0;

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

L
Liu Jicong 已提交
831
    if (pExpr[k].pExpr->nodeType == QUERY_NODE_COLUMN) {  // it is a project query
832
      SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
833
      if (pResult->info.rows > 0 && !createNewColModel) {
834
        colDataMergeCol(pColInfoData, pResult->info.rows, &pResult->info.capacity, pfCtx->input.pData[0], pfCtx->input.numOfRows);
835 836 837
      } else {
        colDataAssign(pColInfoData, pfCtx->input.pData[0], pfCtx->input.numOfRows);
      }
838

839
      numOfRows = pfCtx->input.numOfRows;
840
    } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_VALUE) {
841
      SColumnInfoData* pColInfoData = taosArrayGet(pResult->pDataBlock, outputSlotId);
842

dengyihao's avatar
dengyihao 已提交
843
      int32_t offset = createNewColModel ? 0 : pResult->info.rows;
844
      for (int32_t i = 0; i < pSrcBlock->info.rows; ++i) {
dengyihao's avatar
dengyihao 已提交
845 846 847
        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);
848
      }
849 850

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

855
      SColumnInfoData* pResColData = taosArrayGet(pResult->pDataBlock, outputSlotId);
856
      SColumnInfoData  idata = {.info = pResColData->info, .hasNull = true};
857

858
      SScalarParam dest = {.columnData = &idata};
859 860
      scalarCalculate(pExpr[k].pExpr->_optrRoot.pRootNode, pBlockList, &dest);

dengyihao's avatar
dengyihao 已提交
861
      int32_t startOffset = createNewColModel ? 0 : pResult->info.rows;
862
      colDataMergeCol(pResColData, startOffset, &pResult->info.capacity, &idata, dest.numOfRows);
863 864

      numOfRows = dest.numOfRows;
865 866
      taosArrayDestroy(pBlockList);
    } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_FUNCTION) {
867
      ASSERT(!fmIsAggFunc(pfCtx->functionId));
868

869
      if (fmIsPseudoColumnFunc(pfCtx->functionId)) {
H
Haojun Liao 已提交
870
        // do nothing
871
      } else if (fmIsNonstandardSQLFunc(pfCtx->functionId)) {
dengyihao's avatar
dengyihao 已提交
872
        SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[k]);
873
        pfCtx->fpSet.init(&pCtx[k], pResInfo);
874

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

878
        // set the timestamp(_rowts) output buffer
879 880
        if (taosArrayGetSize(pPseudoList) > 0) {
          int32_t* outputColIndex = taosArrayGet(pPseudoList, 0);
881
          pfCtx->pTsOutput = (SColumnInfoData*)pCtx[*outputColIndex].pOutput;
882
        }
H
Haojun Liao 已提交
883

884
        numOfRows = pfCtx->fpSet.process(pfCtx);
H
Haojun Liao 已提交
885 886 887
      } else {
        SArray* pBlockList = taosArrayInit(4, POINTER_BYTES);
        taosArrayPush(pBlockList, &pSrcBlock);
G
Ganlin Zhao 已提交
888

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

892
        SScalarParam dest = {.columnData = &idata};
X
Xiaoyu Wang 已提交
893
        int32_t      code = scalarCalculate((SNode*)pExpr[k].pExpr->_function.pFunctNode, pBlockList, &dest);
894 895 896 897
        if (code != TSDB_CODE_SUCCESS) {
          taosArrayDestroy(pBlockList);
          return code;
        }
898

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

        numOfRows = dest.numOfRows;
H
Haojun Liao 已提交
903 904
        taosArrayDestroy(pBlockList);
      }
905
    } else {
906
      ASSERT(0);
907 908
    }
  }
909

910 911 912
  if (!createNewColModel) {
    pResult->info.rows += numOfRows;
  }
913 914

  return TSDB_CODE_SUCCESS;
915 916
}

917 918 919 920 921 922 923 924 925 926 927 928
static void setResultRowKey(SResultRow* pResultRow, char* pData, int16_t type) {
  if (IS_VAR_DATA_TYPE(type)) {
    // todo disable this
    //    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);
929

930 931
    pResultRow->win.skey = v;
    pResultRow->win.ekey = v;
932 933 934
  }
}

935 936 937 938 939
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;
940

941 942 943
  SResultRow* pResultRow =
      doSetResultOutBufByKey(pBuf, pResultRowInfo, (char*)pData, bytes, true, groupId, pTaskInfo, false, pAggSup);
  assert(pResultRow != NULL);
944

945
  setResultRowKey(pResultRow, pData, type);
946
  setResultRowInitCtx(pResultRow, pCtx, numOfCols, binfo->rowCellInfoOffset);
947
  return TSDB_CODE_SUCCESS;
948 949
}

950 951
static bool functionNeedToExecute(SqlFunctionCtx* pCtx) {
  struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
952

953 954 955 956 957
  // in case of timestamp column, always generated results.
  int32_t functionId = pCtx->functionId;
  if (functionId == -1) {
    return false;
  }
958

959
  if (isRowEntryCompleted(pResInfo)) {
960 961 962
    return false;
  }

963 964 965 966 967 968 969
  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;
970 971
  }

972 973 974 975 976
  // 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;
  //  }
977 978 979 980

  return true;
}

981 982 983 984 985 986 987
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;
    }
988

989 990 991
    // Set the correct column info (data type and bytes)
    pInput->pData[paramIndex]->info.type = type;
    pInput->pData[paramIndex]->info.bytes = tDataTypes[type].bytes;
992
  }
H
Haojun Liao 已提交
993

994 995 996 997 998 999
  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;
1000 1001
    }
  } else {
1002
    da = pInput->pColumnDataAgg[paramIndex];
1003 1004
  }

1005
  ASSERT(!IS_VAR_DATA_TYPE(type));
1006

1007 1008 1009 1010 1011 1012
  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};
1013

1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
    *(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
1026
  } else {
1027
    ASSERT(0);
1028 1029
  }

1030 1031
  return TSDB_CODE_SUCCESS;
}
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042

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;

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

1046 1047
      if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) {
        int32_t slotId = pFuncParam->pCol->slotId;
1048 1049 1050 1051
        pInput->pColumnDataAgg[j] = pBlock->pBlockAgg[slotId];
        if (pInput->pColumnDataAgg[j] == NULL) {
          pInput->colDataAggIsSet = false;
        }
1052 1053 1054 1055

        // 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);
1056 1057
      } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) {
        doCreateConstantValColumnAggInfo(pInput, pFuncParam, pFuncParam->param.nType, j, pBlock->info.rows);
1058 1059
      }
    }
1060
  } else {
1061
    pInput->colDataAggIsSet = false;
1062 1063 1064
  }

  // set the statistics data for primary time stamp column
1065 1066 1067 1068 1069
  //  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;
  //  }
1070 1071 1072
}

// set the output buffer for the selectivity + tag query
L
Liu Jicong 已提交
1073
static int32_t setCtxTagColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1074 1075 1076
  int32_t num = 0;
  int16_t tagLen = 0;

H
Haojun Liao 已提交
1077
  SqlFunctionCtx*  p = NULL;
wafwerar's avatar
wafwerar 已提交
1078
  SqlFunctionCtx** pTagCtx = taosMemoryCalloc(numOfOutput, POINTER_BYTES);
1079 1080 1081 1082 1083 1084 1085 1086
  if (pTagCtx == NULL) {
    return TSDB_CODE_QRY_OUT_OF_MEMORY;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functionId = pCtx[i].functionId;

    if (functionId == FUNCTION_TAG_DUMMY || functionId == FUNCTION_TS_DUMMY) {
H
Haojun Liao 已提交
1087
      tagLen += pCtx[i].resDataInfo.bytes;
1088
      pTagCtx[num++] = &pCtx[i];
L
Liu Jicong 已提交
1089
    } else if (1 /*(aAggs[functionId].status & FUNCSTATE_SELECTIVITY) != 0*/) {
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
      p = &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
    }
  }
  if (p != NULL) {
1100 1101
    p->subsidiaries.pCtx = pTagCtx;
    p->subsidiaries.num = num;
1102
  } else {
wafwerar's avatar
wafwerar 已提交
1103
    taosMemoryFreeClear(pTagCtx);
1104 1105 1106 1107 1108
  }

  return TSDB_CODE_SUCCESS;
}

1109
SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, int32_t** rowCellInfoOffset) {
L
Liu Jicong 已提交
1110
  SqlFunctionCtx* pFuncCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
H
Haojun Liao 已提交
1111 1112 1113 1114
  if (pFuncCtx == NULL) {
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
1115
  *rowCellInfoOffset = taosMemoryCalloc(numOfOutput, sizeof(int32_t));
H
Haojun Liao 已提交
1116
  if (*rowCellInfoOffset == 0) {
wafwerar's avatar
wafwerar 已提交
1117
    taosMemoryFreeClear(pFuncCtx);
H
Haojun Liao 已提交
1118 1119 1120 1121
    return NULL;
  }

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

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

1127
    pCtx->functionId = -1;
1128
    pCtx->curBufPage = -1;
L
Liu Jicong 已提交
1129
    pCtx->pExpr = pExpr;
1130

H
Haojun Liao 已提交
1131
    if (pExpr->pExpr->nodeType == QUERY_NODE_FUNCTION) {
H
Haojun Liao 已提交
1132
      SFuncExecEnv env = {0};
H
Haojun Liao 已提交
1133 1134
      pCtx->functionId = pExpr->pExpr->_function.pFunctNode->funcId;

H
Haojun Liao 已提交
1135
      if (fmIsAggFunc(pCtx->functionId) || fmIsNonstandardSQLFunc(pCtx->functionId)) {
1136 1137 1138 1139
        bool isUdaf = fmIsUserDefinedFunc(pCtx->functionId);
        if (!isUdaf) {
          fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet);
        } else {
1140
          char* udfName = pExpr->pExpr->_function.pFunctNode->functionName;
1141 1142 1143
          strncpy(pCtx->udfName, udfName, strlen(udfName));
          fmGetUdafExecFuncs(pCtx->functionId, &pCtx->fpSet);
        }
1144 1145 1146
        pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
      } else {
        fmGetScalarFuncExecFuncs(pCtx->functionId, &pCtx->sfp);
1147 1148 1149
        if (pCtx->sfp.getEnv != NULL) {
          pCtx->sfp.getEnv(pExpr->pExpr->_function.pFunctNode, &env);
        }
1150
      }
H
Haojun Liao 已提交
1151
      pCtx->resDataInfo.interBufSize = env.calcMemSize;
1152 1153 1154 1155
    } else if (pExpr->pExpr->nodeType == QUERY_NODE_COLUMN || pExpr->pExpr->nodeType == QUERY_NODE_OPERATOR ||
               pExpr->pExpr->nodeType == QUERY_NODE_VALUE) {
      // for simple column, the intermediate buffer needs to hold one element.
      pCtx->resDataInfo.interBufSize = pFunct->resSchema.bytes;
H
Haojun Liao 已提交
1156
    }
H
Haojun Liao 已提交
1157

H
Haojun Liao 已提交
1158
    pCtx->input.numOfInputCols = pFunct->numOfParams;
wafwerar's avatar
wafwerar 已提交
1159 1160
    pCtx->input.pData = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
    pCtx->input.pColumnDataAgg = taosMemoryCalloc(pFunct->numOfParams, POINTER_BYTES);
H
Haojun Liao 已提交
1161

1162
    pCtx->pTsOutput = NULL;
L
Liu Jicong 已提交
1163
    pCtx->resDataInfo.bytes = pFunct->resSchema.bytes;
1164
    pCtx->resDataInfo.type = pFunct->resSchema.type;
L
Liu Jicong 已提交
1165
    pCtx->order = TSDB_ORDER_ASC;
1166
    pCtx->start.key = INT64_MIN;
L
Liu Jicong 已提交
1167
    pCtx->end.key = INT64_MIN;
1168
    pCtx->numOfParams = pExpr->base.numOfParams;
H
Haojun Liao 已提交
1169

1170
    pCtx->param = pFunct->pParam;
dengyihao's avatar
dengyihao 已提交
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
    //    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 已提交
1205 1206
  }

L
Liu Jicong 已提交
1207 1208 1209
  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 已提交
1210
  }
H
Haojun Liao 已提交
1211 1212 1213 1214 1215

  setCtxTagColumnInfo(pFuncCtx, numOfOutput);
  return pFuncCtx;
}

1216
static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1217 1218 1219 1220 1221 1222
  if (pCtx == NULL) {
    return NULL;
  }

  for (int32_t i = 0; i < numOfOutput; ++i) {
    for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) {
1223
      taosVariantDestroy(&pCtx[i].param[j].param);
1224 1225 1226
    }

    taosVariantDestroy(&pCtx[i].tag);
1227
    taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx);
1228 1229
  }

wafwerar's avatar
wafwerar 已提交
1230
  taosMemoryFreeClear(pCtx);
1231 1232 1233
  return NULL;
}

L
Liu Jicong 已提交
1234
bool isTaskKilled(SExecTaskInfo* pTaskInfo) {
1235 1236
  // query has been executed more than tsShellActivityTimer, and the retrieve has not arrived
  // abort current query execution.
L
Liu Jicong 已提交
1237 1238
  if (pTaskInfo->owner != 0 &&
      ((taosGetTimestampSec() - pTaskInfo->cost.start / 1000) > 10 * getMaximumIdleDurationSec())
1239 1240
      /*(!needBuildResAfterQueryComplete(pTaskInfo))*/) {
    assert(pTaskInfo->cost.start != 0);
L
Liu Jicong 已提交
1241 1242 1243
    //    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;
1244 1245 1246 1247 1248
  }

  return false;
}

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

L
Liu Jicong 已提交
1251
static bool isCachedLastQuery(STaskAttr* pQueryAttr) {
1252 1253 1254 1255 1256 1257 1258 1259 1260
  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;
  }

1261 1262
  int32_t order = TSDB_ORDER_ASC;
  if (order != TSDB_ORDER_DESC || !TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_DESC_INITIALIZER)) {
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
    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 已提交
1282
// todo refactor : return window
1283
void getAlignQueryTimeWindow(SInterval* pInterval, int32_t precision, int64_t key, STimeWindow* win) {
H
Haojun Liao 已提交
1284
  win->skey = taosTimeTruncate(key, pInterval, precision);
1285 1286

  /*
H
Haojun Liao 已提交
1287
   * if the realSkey > INT64_MAX - pInterval->interval, the query duration between
1288 1289
   * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges.
   */
1290 1291
  win->ekey = taosTimeAdd(win->skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
  if (win->ekey < win->skey) {
1292 1293 1294 1295
    win->ekey = INT64_MAX;
  }
}

L
Liu Jicong 已提交
1296
static int32_t updateBlockLoadStatus(STaskAttr* pQuery, int32_t status) {
1297 1298 1299
  bool hasFirstLastFunc = false;
  bool hasOtherFunc = false;

1300
  if (status == BLK_DATA_DATA_LOAD || status == BLK_DATA_FILTEROUT) {
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
    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;
    }
  }

1319
  if (hasFirstLastFunc && status == BLK_DATA_NOT_LOAD) {
L
Liu Jicong 已提交
1320
    if (!hasOtherFunc) {
1321
      return BLK_DATA_FILTEROUT;
1322
    } else {
1323
      return BLK_DATA_DATA_LOAD;
1324 1325 1326 1327 1328 1329
    }
  }

  return status;
}

L
Liu Jicong 已提交
1330 1331
// static void updateDataCheckOrder(SQInfo *pQInfo, SQueryTableReq* pQueryMsg, bool stableQuery) {
//   STaskAttr* pQueryAttr = pQInfo->runtimeEnv.pQueryAttr;
H
Haojun Liao 已提交
1332
//
L
Liu Jicong 已提交
1333 1334 1335 1336
//   // 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 已提交
1337
//
L
Liu Jicong 已提交
1338 1339 1340 1341 1342
//   // 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 已提交
1343
//
L
Liu Jicong 已提交
1344 1345
//     pQueryAttr->order.order = TSDB_ORDER_ASC;
//     if (pQueryAttr->window.skey > pQueryAttr->window.ekey) {
wafwerar's avatar
wafwerar 已提交
1346
//       TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
L
Liu Jicong 已提交
1347
//     }
H
Haojun Liao 已提交
1348
//
L
Liu Jicong 已提交
1349 1350 1351
//     pQueryAttr->needReverseScan = false;
//     return;
//   }
H
Haojun Liao 已提交
1352
//
L
Liu Jicong 已提交
1353 1354 1355
//   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 已提交
1356
//       TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
L
Liu Jicong 已提交
1357
//     }
H
Haojun Liao 已提交
1358
//
L
Liu Jicong 已提交
1359 1360 1361 1362
//     pQueryAttr->needReverseScan = false;
//     doUpdateLastKey(pQueryAttr);
//     return;
//   }
H
Haojun Liao 已提交
1363
//
L
Liu Jicong 已提交
1364 1365 1366 1367 1368 1369
//   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 已提交
1370
//
L
Liu Jicong 已提交
1371 1372 1373
//     pQueryAttr->order.order = TSDB_ORDER_ASC;
//     return;
//   }
H
Haojun Liao 已提交
1374
//
L
Liu Jicong 已提交
1375 1376 1377 1378
//   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 已提交
1379 1380
////               pQueryAttr->window.ekey, pQueryAttr->window.ekey, pQueryAttr->window.skey);
//
wafwerar's avatar
wafwerar 已提交
1381
//        TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
//        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 已提交
1392
//        TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
//        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 已提交
1405 1406
////                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey,
/// pQueryAttr->window.skey);
H
Haojun Liao 已提交
1407
//
wafwerar's avatar
wafwerar 已提交
1408
//          TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1409 1410 1411 1412 1413 1414 1415 1416
//          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 已提交
1417 1418
////                 pQueryAttr->window.skey, pQueryAttr->window.ekey, pQueryAttr->window.ekey,
/// pQueryAttr->window.skey);
H
Haojun Liao 已提交
1419
//
wafwerar's avatar
wafwerar 已提交
1420
//          TSWAP(pQueryAttr->window.skey, pQueryAttr->window.ekey);
H
Haojun Liao 已提交
1421 1422 1423 1424 1425 1426 1427 1428 1429
//          doUpdateLastKey(pQueryAttr);
//        }
//
//        pQueryAttr->order.order = TSDB_ORDER_DESC;
//        pQueryAttr->needReverseScan = false;
//      }
//    }
//  }
//}
1430

H
Haojun Liao 已提交
1431 1432
static void getIntermediateBufInfo(STaskRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) {
  STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
L
Liu Jicong 已提交
1433
  int32_t    MIN_ROWS_PER_PAGE = 4;
1434

L
Liu Jicong 已提交
1435 1436
  *rowsize = (int32_t)(pQueryAttr->resultRowSize *
                       getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
1437 1438 1439 1440
  int32_t overhead = sizeof(SFilePage);

  // one page contains at least two rows
  *ps = DEFAULT_INTERN_BUF_PAGE_SIZE;
L
Liu Jicong 已提交
1441
  while (((*rowsize) * MIN_ROWS_PER_PAGE) > (*ps) - overhead) {
1442 1443 1444 1445 1446 1447
    *ps = ((*ps) << 1u);
  }
}

#define IS_PREFILTER_TYPE(_t) ((_t) != TSDB_DATA_TYPE_BINARY && (_t) != TSDB_DATA_TYPE_NCHAR)

L
Liu Jicong 已提交
1448 1449 1450
// static FORCE_INLINE bool doFilterByBlockStatistics(STaskRuntimeEnv* pRuntimeEnv, SDataStatis *pDataStatis,
// SqlFunctionCtx *pCtx, int32_t numOfRows) {
//   STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
1451
//
L
Liu Jicong 已提交
1452 1453 1454
//   if (pDataStatis == NULL || pQueryAttr->pFilters == NULL) {
//     return true;
//   }
1455
//
L
Liu Jicong 已提交
1456 1457
//   return filterRangeExecute(pQueryAttr->pFilters, pDataStatis, pQueryAttr->numOfCols, numOfRows);
// }
1458

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

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

1465
  if (true) {
L
Liu Jicong 已提交
1466
    //    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.skey, sk, ek, &w);
1467 1468 1469 1470 1471 1472
    assert(w.ekey >= pBlockInfo->window.skey);

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

L
Liu Jicong 已提交
1473 1474
    while (1) {
      //      getNextTimeWindow(pQueryAttr, &w);
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484
      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 已提交
1485
    //    getAlignQueryTimeWindow(pQueryAttr, pBlockInfo->window.ekey, sk, ek, &w);
1486 1487 1488 1489 1490 1491
    assert(w.skey <= pBlockInfo->window.ekey);

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

L
Liu Jicong 已提交
1492 1493
    while (1) {
      //      getNextTimeWindow(pQueryAttr, &w);
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
      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 SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId);
L
Liu Jicong 已提交
1558
static void         doSetTagValueInParam(void* pTable, int32_t tagColId, SVariant* tag, int16_t type, int16_t bytes);
1559 1560

static uint32_t doFilterByBlockTimeWindow(STableScanInfo* pTableScanInfo, SSDataBlock* pBlock) {
H
Haojun Liao 已提交
1561
  SqlFunctionCtx* pCtx = pTableScanInfo->pCtx;
1562
  uint32_t        status = BLK_DATA_NOT_LOAD;
1563 1564 1565 1566

  int32_t numOfOutput = pTableScanInfo->numOfOutput;
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int32_t functionId = pCtx[i].functionId;
H
Haojun Liao 已提交
1567
    int32_t colId = pTableScanInfo->pExpr[i].base.pParam[0].pCol->colId;
1568 1569 1570

    // group by + first/last should not apply the first/last block filter
    if (functionId < 0) {
1571
      status |= BLK_DATA_DATA_LOAD;
1572 1573
      return status;
    } else {
L
Liu Jicong 已提交
1574
      //      status |= aAggs[functionId].dataReqFunc(&pTableScanInfo->pCtx[i], &pBlock->info.window, colId);
1575
      //      if ((status & BLK_DATA_DATA_LOAD) == BLK_DATA_DATA_LOAD) {
L
Liu Jicong 已提交
1576 1577
      //        return status;
      //      }
1578 1579 1580 1581 1582 1583
    }
  }

  return status;
}

L
Liu Jicong 已提交
1584 1585
int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock,
                              uint32_t* status) {
1586
  *status = BLK_DATA_NOT_LOAD;
1587

H
Haojun Liao 已提交
1588
  pBlock->pDataBlock = NULL;
L
Liu Jicong 已提交
1589
  pBlock->pBlockAgg = NULL;
H
Haojun Liao 已提交
1590

L
Liu Jicong 已提交
1591 1592
  //  int64_t groupId = pRuntimeEnv->current->groupIndex;
  //  bool    ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
1593

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

1596 1597
//  pCost->totalBlocks += 1;
//  pCost->totalRows += pBlock->info.rows;
H
Haojun Liao 已提交
1598
#if 0
1599 1600 1601
  // 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 已提交
1602
      (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pTaskInfo, &pBlock->info))) {
1603
    (*status) = BLK_DATA_DATA_LOAD;
1604 1605 1606
  }

  // check if this data block is required to load
1607
  if ((*status) != BLK_DATA_DATA_LOAD) {
1608 1609 1610 1611 1612 1613 1614
    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 已提交
1615
      bool  masterScan = IS_MAIN_SCAN(pRuntimeEnv);
1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
      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 {
1639
      (*status) = BLK_DATA_DATA_LOAD;
1640 1641 1642 1643
    }
  }

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

1646
  if ((*status) == BLK_DATA_NOT_LOAD || (*status) == BLK_DATA_FILTEROUT) {
1647 1648
    //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
//           pBlockInfo->window.ekey, pBlockInfo->rows);
1649
    pCost->skipBlocks += 1;
1650
  } else if ((*status) == BLK_DATA_SMA_LOAD) {
1651 1652
    // this function never returns error?
    pCost->loadBlockStatis += 1;
1653
//    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
1654 1655

    if (pBlock->pBlockAgg == NULL) {  // data block statistics does not exist, load data block
1656
//      pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL);
1657 1658 1659
      pCost->totalCheckedRows += pBlock->info.rows;
    }
  } else {
1660
    assert((*status) == BLK_DATA_DATA_LOAD);
1661 1662 1663

    // load the data block statistics to perform further filter
    pCost->loadBlockStatis += 1;
1664
//    tsdbRetrieveDataBlockStatisInfo(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg);
1665 1666 1667 1668 1669 1670

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

H
Haojun Liao 已提交
1671
          bool  masterScan = IS_MAIN_SCAN(pRuntimeEnv);
1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
          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
1689
            pCost->skipBlocks += 1;
1690 1691
            //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId,
//                   pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows);
1692
            (*status) = BLK_DATA_FILTEROUT;
1693 1694 1695 1696 1697 1698 1699 1700
            return TSDB_CODE_SUCCESS;
          }
        }
      }
    }

    // current block has been discard due to filter applied
//    if (!doFilterByBlockStatistics(pRuntimeEnv, pBlock->pBlockAgg, pTableScanInfo->pCtx, pBlockInfo->rows)) {
1701
//      pCost->skipBlocks += 1;
1702 1703
//      qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey,
//             pBlockInfo->window.ekey, pBlockInfo->rows);
1704
//      (*status) = BLK_DATA_FILTEROUT;
1705 1706 1707 1708 1709
//      return TSDB_CODE_SUCCESS;
//    }

    pCost->totalCheckedRows += pBlockInfo->rows;
    pCost->loadBlocks += 1;
1710
//    pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL);
1711 1712 1713 1714 1715 1716 1717
//    if (pBlock->pDataBlock == NULL) {
//      return terrno;
//    }

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

1719 1720 1721 1722
//    if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) {
//      filterColRowsInDataBlock(pRuntimeEnv, pBlock, ascQuery);
//    }
  }
H
Haojun Liao 已提交
1723
#endif
1724 1725 1726 1727
  return TSDB_CODE_SUCCESS;
}

/*
H
Haojun Liao 已提交
1728
 * set tag value in SqlFunctionCtx
1729 1730
 * e.g.,tag information into input buffer
 */
L
Liu Jicong 已提交
1731
static void doSetTagValueInParam(void* pTable, int32_t tagColId, SVariant* tag, int16_t type, int16_t bytes) {
1732 1733 1734
  taosVariantDestroy(tag);

  char* val = NULL;
L
Liu Jicong 已提交
1735 1736 1737 1738 1739 1740
  //  if (tagColId == TSDB_TBNAME_COLUMN_INDEX) {
  //    val = tsdbGetTableName(pTable);
  //    assert(val != NULL);
  //  } else {
  //    val = tsdbGetTableTagVal(pTable, tagColId, type, bytes);
  //  }
1741 1742 1743 1744 1745 1746 1747 1748

  if (val == NULL || isNull(val, type)) {
    tag->nType = TSDB_DATA_TYPE_NULL;
    return;
  }

  if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
    int32_t maxLen = bytes - VARSTR_HEADER_SIZE;
L
Liu Jicong 已提交
1749
    int32_t len = (varDataLen(val) > maxLen) ? maxLen : varDataLen(val);
1750
    taosVariantCreateFromBinary(tag, varDataVal(val), len, type);
L
Liu Jicong 已提交
1751
    // taosVariantCreateFromBinary(tag, varDataVal(val), varDataLen(val), type);
1752 1753 1754 1755 1756 1757 1758 1759
  } else {
    taosVariantCreateFromBinary(tag, val, bytes, type);
  }
}

static SColumnInfo* doGetTagColumnInfoById(SColumnInfo* pTagColList, int32_t numOfTags, int16_t colId) {
  assert(pTagColList != NULL && numOfTags > 0);

L
Liu Jicong 已提交
1760
  for (int32_t i = 0; i < numOfTags; ++i) {
1761 1762 1763 1764 1765 1766 1767 1768
    if (pTagColList[i].colId == colId) {
      return &pTagColList[i];
    }
  }

  return NULL;
}

L
Liu Jicong 已提交
1769 1770
void setTagValue(SOperatorInfo* pOperatorInfo, void* pTable, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
  SExprInfo* pExpr = pOperatorInfo->pExpr;
1771
  SExprInfo* pExprInfo = &pExpr[0];
L
Liu Jicong 已提交
1772
  int32_t    functionId = getExprFunctionId(pExprInfo);
1773
#if 0
1774 1775 1776
  if (pQueryAttr->numOfOutput == 1 && functionId == FUNCTION_TS_COMP && pQueryAttr->stableQuery) {
    assert(pExprInfo->base.numOfParams == 1);

L
Liu Jicong 已提交
1777
    //    int16_t      tagColId = (int16_t)pExprInfo->base.param[0].i;
H
Haojun Liao 已提交
1778
    int16_t      tagColId = -1;
1779 1780 1781
    SColumnInfo* pColInfo = doGetTagColumnInfoById(pQueryAttr->tagColList, pQueryAttr->numOfTags, tagColId);

    doSetTagValueInParam(pTable, tagColId, &pCtx[0].tag, pColInfo->type, pColInfo->bytes);
H
Haojun Liao 已提交
1782

1783 1784 1785 1786 1787 1788 1789 1790 1791
  } else {
    // set tag value, by which the results are aggregated.
    int32_t offset = 0;
    memset(pRuntimeEnv->tagVal, 0, pQueryAttr->tagLen);

    for (int32_t idx = 0; idx < numOfOutput; ++idx) {
      SExprInfo* pLocalExprInfo = &pExpr[idx];

      // ts_comp column required the tag value for join filter
H
Haojun Liao 已提交
1792
      if (!TSDB_COL_IS_TAG(pLocalExprInfo->base.pParam[0].pCol->flag)) {
1793 1794 1795 1796
        continue;
      }

      // todo use tag column index to optimize performance
L
Liu Jicong 已提交
1797 1798
      doSetTagValueInParam(pTable, pLocalExprInfo->base.pParam[0].pCol->colId, &pCtx[idx].tag,
                           pLocalExprInfo->base.resSchema.type, pLocalExprInfo->base.resSchema.bytes);
1799

L
Liu Jicong 已提交
1800 1801 1802
      if (IS_NUMERIC_TYPE(pLocalExprInfo->base.resSchema.type) ||
          pLocalExprInfo->base.resSchema.type == TSDB_DATA_TYPE_BOOL ||
          pLocalExprInfo->base.resSchema.type == TSDB_DATA_TYPE_TIMESTAMP) {
1803 1804 1805 1806
        memcpy(pRuntimeEnv->tagVal + offset, &pCtx[idx].tag.i, pLocalExprInfo->base.resSchema.bytes);
      } else {
        if (pCtx[idx].tag.pz != NULL) {
          memcpy(pRuntimeEnv->tagVal + offset, pCtx[idx].tag.pz, pCtx[idx].tag.nLen);
L
Liu Jicong 已提交
1807
        }
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
      }

      offset += pLocalExprInfo->base.resSchema.bytes;
    }
  }

  // set the tsBuf start position before check each data block
  if (pRuntimeEnv->pTsBuf != NULL) {
    setCtxTagForJoin(pRuntimeEnv, &pCtx[0], pExprInfo, pTable);
  }
1818
#endif
1819 1820
}

H
Haojun Liao 已提交
1821
void copyToSDataBlock(SSDataBlock* pBlock, int32_t* offset, SGroupResInfo* pGroupResInfo, SDiskbasedBuf* pResBuf) {
1822 1823 1824 1825 1826 1827 1828
  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 已提交
1829 1830 1831
      //      if ((code = mergeIntoGroupResult(&pGroupResInfo, pRuntimeEnv, offset)) != TSDB_CODE_SUCCESS) {
      return;
      //      }
1832 1833
    }

L
Liu Jicong 已提交
1834
    //    doCopyToSDataBlock(pResBuf, pGroupResInfo, TSDB_ORDER_ASC, pBlock, );
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844

    // 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 已提交
1845 1846 1847
    //    if (pBlock->info.rows >= threshold) {
    //      break;
    //    }
1848 1849 1850
  }
}

L
Liu Jicong 已提交
1851
static void updateTableQueryInfoForReverseScan(STableQueryInfo* pTableQueryInfo) {
1852 1853 1854 1855
  if (pTableQueryInfo == NULL) {
    return;
  }

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

L
Liu Jicong 已提交
1859 1860
  //  SWITCH_ORDER(pTableQueryInfo->cur.order);
  //  pTableQueryInfo->cur.vgroupIndex = -1;
1861 1862

  // set the index to be the end slot of result rows array
dengyihao's avatar
dengyihao 已提交
1863 1864 1865 1866 1867 1868
  //  SResultRowInfo* pResultRowInfo = &pTableQueryInfo->resInfo;
  //  if (pResultRowInfo->size > 0) {
  //    pResultRowInfo->curPos = pResultRowInfo->size - 1;
  //  } else {
  //    pResultRowInfo->curPos = -1;
  //  }
1869 1870
}

H
Haojun Liao 已提交
1871
void initResultRow(SResultRow* pResultRow) {
1872 1873 1874 1875 1876 1877
  pResultRow->pEntryInfo = (struct SResultRowEntryInfo*)((char*)pResultRow + sizeof(SResultRow));
}

/*
 * 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 已提交
1878 1879 1880
 * +------------+-----------------result column 1------------+------------------result column 2-----------+
 * | SResultRow | SResultRowEntryInfo | intermediate buffer1 | SResultRowEntryInfo | intermediate buffer 2|
 * +------------+--------------------------------------------+--------------------------------------------+
1881 1882
 *           offset[0]                                  offset[1]                                   offset[2]
 */
1883
// TODO refactor: some function move away
H
Haojun Liao 已提交
1884
void setFunctionResultOutput(SOptrBasicInfo* pInfo, SAggSupporter* pSup, int32_t stage, SExecTaskInfo* pTaskInfo) {
L
Liu Jicong 已提交
1885 1886 1887
  SqlFunctionCtx* pCtx = pInfo->pCtx;
  SSDataBlock*    pDataBlock = pInfo->pRes;
  int32_t*        rowCellInfoOffset = pInfo->rowCellInfoOffset;
H
Haojun Liao 已提交
1888

H
Haojun Liao 已提交
1889
  SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
H
Haojun Liao 已提交
1890
  initResultRowInfo(pResultRowInfo, 16);
H
Haojun Liao 已提交
1891

L
Liu Jicong 已提交
1892 1893
  int64_t     tid = 0;
  int64_t     groupId = 0;
1894 1895
  SResultRow* pRow = doSetResultOutBufByKey(pSup->pResultBuf, pResultRowInfo, (char*)&tid, sizeof(tid), true, groupId,
                                            pTaskInfo, false, pSup);
H
Haojun Liao 已提交
1896 1897 1898 1899 1900

  for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
    struct SResultRowEntryInfo* pEntry = getResultCell(pRow, i, rowCellInfoOffset);
    cleanupResultRowEntry(pEntry);

L
Liu Jicong 已提交
1901
    pCtx[i].resultInfo = pEntry;
H
Haojun Liao 已提交
1902 1903 1904
    pCtx[i].currentStage = stage;

    // set the timestamp output buffer for top/bottom/diff query
L
Liu Jicong 已提交
1905 1906
    //    int32_t fid = pCtx[i].functionId;
    //    if (fid == FUNCTION_TOP || fid == FUNCTION_BOTTOM || fid == FUNCTION_DIFF || fid == FUNCTION_DERIVATIVE) {
H
Haojun Liao 已提交
1907
    //      if (i > 0) pCtx[i].pTsOutput = pCtx[i-1].pOutput;
L
Liu Jicong 已提交
1908
    //    }
H
Haojun Liao 已提交
1909 1910 1911 1912 1913
  }

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

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

L
Liu Jicong 已提交
1917
  int32_t newSize = pDataBlock->info.rows + numOfInputRows + 5;  // extra output buffer
1918
  if ((*bufCapacity) < newSize) {
L
Liu Jicong 已提交
1919 1920
    for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
      SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
1921

wafwerar's avatar
wafwerar 已提交
1922
      char* p = taosMemoryRealloc(pColInfo->pData, newSize * pColInfo->info.bytes);
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935
      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 已提交
1936
    SColumnInfoData* pColInfo = taosArrayGet(pDataBlock->pDataBlock, i);
1937 1938 1939 1940 1941
    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 已提交
1942 1943
    if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_DIFF ||
        functionId == FUNCTION_DERIVATIVE) {
dengyihao's avatar
dengyihao 已提交
1944
      //      if (i > 0) pBInfo->pCtx[i].pTsOutput = pBInfo->pCtx[i - 1].pOutput;
1945 1946 1947 1948
    }
  }
}

H
Haojun Liao 已提交
1949
void copyTsColoum(SSDataBlock* pRes, SqlFunctionCtx* pCtx, int32_t numOfOutput) {
1950 1951
  bool    needCopyTs = false;
  int32_t tsNum = 0;
L
Liu Jicong 已提交
1952
  char*   src = NULL;
1953 1954 1955 1956
  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 已提交
1957 1958
      if (i > 0 && pCtx[i - 1].functionId == FUNCTION_TS_DUMMY) {
        SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i - 1);  // find ts data
1959 1960
        src = pColRes->pData;
      }
L
Liu Jicong 已提交
1961
    } else if (functionId == FUNCTION_TS_DUMMY) {
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971
      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 已提交
1972
    if (functionId == FUNCTION_TS_DUMMY) {
1973 1974 1975 1976 1977 1978
      SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i);
      memcpy(pColRes->pData, src, pColRes->info.bytes * pRes->info.rows);
    }
  }
}

H
Haojun Liao 已提交
1979
void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size) {
1980 1981
  for (int32_t j = 0; j < size; ++j) {
    struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[j]);
dengyihao's avatar
dengyihao 已提交
1982 1983
    if (isRowEntryInitialized(pResInfo) || fmIsPseudoColumnFunc(pCtx[j].functionId) || pCtx[j].functionId == -1 ||
        fmIsScalarFunc(pCtx[j].functionId)) {
1984 1985 1986
      continue;
    }

H
Haojun Liao 已提交
1987
    pCtx[j].fpSet.init(&pCtx[j], pCtx[j].resultInfo);
1988 1989 1990
  }
}

L
Liu Jicong 已提交
1991
void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status) {
1992
  if (status == TASK_NOT_COMPLETED) {
H
Haojun Liao 已提交
1993
    pTaskInfo->status = status;
1994 1995
  } else {
    // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first
1996
    CLEAR_QUERY_STATUS(pTaskInfo, TASK_NOT_COMPLETED);
H
Haojun Liao 已提交
1997
    pTaskInfo->status |= status;
1998 1999 2000
  }
}

2001
// todo merged with the build group result.
L
Liu Jicong 已提交
2002 2003
void finalizeMultiTupleQueryResult(SqlFunctionCtx* pCtx, int32_t numOfOutput, SDiskbasedBuf* pBuf,
                                   SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
2004 2005 2006
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
    SResultRowPosition* pPos = &pResultRowInfo->pPosition[i];

L
Liu Jicong 已提交
2007
    SFilePage*  bufPage = getBufPage(pBuf, pPos->pageId);
2008
    SResultRow* pRow = (SResultRow*)((char*)bufPage + pPos->offset);
H
Haojun Liao 已提交
2009 2010

    // TODO ignore the close status anyway.
dengyihao's avatar
dengyihao 已提交
2011 2012 2013
    //    if (!isResultRowClosed(pRow)) {
    //      continue;
    //    }
2014

2015
    for (int32_t j = 0; j < numOfOutput; ++j) {
2016 2017
      pCtx[j].resultInfo = getResultCell(pRow, j, rowCellInfoOffset);

H
Haojun Liao 已提交
2018
      struct SResultRowEntryInfo* pResInfo = pCtx[j].resultInfo;
H
Haojun Liao 已提交
2019
      if (!isRowEntryInitialized(pResInfo)) {
2020 2021 2022
        continue;
      }

H
Haojun Liao 已提交
2023
      if (pCtx[j].fpSet.process) {  // TODO set the dummy function, to avoid the check for null ptr.
dengyihao's avatar
dengyihao 已提交
2024
                                    //        pCtx[j].fpSet.finalize(&pCtx[j]);
H
Haojun Liao 已提交
2025
      }
2026 2027 2028 2029

      if (pRow->numOfRows < pResInfo->numOfRes) {
        pRow->numOfRows = pResInfo->numOfRes;
      }
2030
    }
2031 2032 2033

    releaseBufPage(pBuf, bufPage);
  }
2034 2035
}

2036
STableQueryInfo* createTableQueryInfo(void* buf, STimeWindow win) {
L
Liu Jicong 已提交
2037
  STableQueryInfo* pTableQueryInfo = buf;
2038 2039 2040 2041
  pTableQueryInfo->lastKey = win.skey;
  return pTableQueryInfo;
}

L
Liu Jicong 已提交
2042
void destroyTableQueryInfoImpl(STableQueryInfo* pTableQueryInfo) {
2043 2044 2045 2046
  if (pTableQueryInfo == NULL) {
    return;
  }

L
Liu Jicong 已提交
2047
  //  taosVariantDestroy(&pTableQueryInfo->tag);
dengyihao's avatar
dengyihao 已提交
2048
  //  cleanupResultRowInfo(&pTableQueryInfo->resInfo);
2049 2050
}

2051
void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset) {
2052 2053 2054 2055 2056 2057 2058
  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;
    }
2059 2060 2061 2062 2063

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

2064 2065 2066 2067 2068 2069
    if (!pResInfo->initialized) {
      if (pCtx[i].functionId != -1) {
        pCtx[i].fpSet.init(&pCtx[i], pResInfo);
      } else {
        pResInfo->initialized = true;
      }
2070 2071 2072 2073
    }
  }
}

2074 2075 2076 2077 2078 2079
void doFilter(const SNode* pFilterNode, SSDataBlock* pBlock) {
  if (pFilterNode == NULL) {
    return;
  }

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

H
Haojun Liao 已提交
2081
  // todo move to the initialization function
H
Haojun Liao 已提交
2082
  int32_t code = filterInitFromNode((SNode*)pFilterNode, &filter, 0);
2083 2084 2085 2086 2087 2088

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

  int8_t* rowRes = NULL;
  bool    keep = filterExecute(filter, pBlock, &rowRes, NULL, param1.numOfCols);
D
dapan1121 已提交
2089
  filterFreeInfo(filter);
2090

2091
  SSDataBlock* px = createOneDataBlock(pBlock, false);
2092 2093
  blockDataEnsureCapacity(px, pBlock->info.rows);

H
Haojun Liao 已提交
2094
  // todo extract method
2095 2096 2097 2098
  int32_t numOfRow = 0;
  for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
    SColumnInfoData* pDst = taosArrayGet(px->pDataBlock, i);
    SColumnInfoData* pSrc = taosArrayGet(pBlock->pDataBlock, i);
D
dapan1121 已提交
2099 2100 2101 2102 2103 2104 2105 2106 2107
    if (keep) {
      colDataAssign(pDst, pSrc, pBlock->info.rows);
      numOfRow = pBlock->info.rows;
    } else if (NULL != rowRes) {
      numOfRow = 0;
      for (int32_t j = 0; j < pBlock->info.rows; ++j) {
        if (rowRes[j] == 0) {
          continue;
        }
2108

D
dapan1121 已提交
2109 2110 2111 2112 2113 2114
        if (colDataIsNull_s(pSrc, j)) {
          colDataAppendNULL(pDst, numOfRow);
        } else {
          colDataAppend(pDst, numOfRow, colDataGetData(pSrc, j), false);
        }
        numOfRow += 1;
H
Haojun Liao 已提交
2115
      }
D
dapan1121 已提交
2116 2117
    } else {
      numOfRow = 0;
2118 2119 2120 2121 2122 2123
    }

    *pSrc = *pDst;
  }

  pBlock->info.rows = numOfRow;
2124
  blockDataUpdateTsWindow(pBlock);
2125 2126
}

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

2132 2133
  SResultRowInfo* pResultRowInfo = &pAggInfo->binfo.resultRowInfo;
  SqlFunctionCtx* pCtx = pAggInfo->binfo.pCtx;
L
Liu Jicong 已提交
2134
  int32_t*        rowCellInfoOffset = pAggInfo->binfo.rowCellInfoOffset;
2135

2136
  SResultRow* pResultRow = doSetResultOutBufByKey(pAggInfo->aggSup.pResultBuf, pResultRowInfo, (char*)&groupId,
L
Liu Jicong 已提交
2137
                                                  sizeof(groupId), true, groupId, pTaskInfo, false, &pAggInfo->aggSup);
L
Liu Jicong 已提交
2138
  assert(pResultRow != NULL);
2139 2140 2141 2142 2143 2144

  /*
   * 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 已提交
2145 2146
    int32_t ret =
        addNewWindowResultBuf(pResultRow, pAggInfo->aggSup.pResultBuf, groupId, pAggInfo->binfo.pRes->info.rowSize);
2147 2148 2149 2150 2151
    if (ret != TSDB_CODE_SUCCESS) {
      return;
    }
  }

2152
  setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowCellInfoOffset);
2153 2154
}

H
Haojun Liao 已提交
2155 2156
void setExecutionContext(int32_t numOfOutput, uint64_t groupId, SExecTaskInfo* pTaskInfo, SAggOperatorInfo* pAggInfo) {
  if (pAggInfo->groupId != INT32_MIN && pAggInfo->groupId == groupId) {
2157 2158 2159
    return;
  }

H
Haojun Liao 已提交
2160
  doSetTableGroupOutputBuf(pAggInfo, numOfOutput, groupId, pTaskInfo);
2161 2162

  // record the current active group id
H
Haojun Liao 已提交
2163
  pAggInfo->groupId = groupId;
2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
}

/**
 * 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
 */
2174
int32_t doCopyToSDataBlock(SSDataBlock* pBlock, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf, SGroupResInfo* pGroupResInfo,
2175
                           int32_t orderType, int32_t* rowCellOffset, SqlFunctionCtx* pCtx) {
2176
  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);
L
Liu Jicong 已提交
2177
  int32_t numOfResult = pBlock->info.rows;  // there are already exists result rows
2178 2179 2180 2181

  int32_t start = 0;
  int32_t step = -1;

L
Liu Jicong 已提交
2182
  // qDebug("QInfo:0x%"PRIx64" start to copy data from windowResInfo to output buf", GET_TASKID(pRuntimeEnv));
2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193
  assert(orderType == TSDB_ORDER_ASC || orderType == TSDB_ORDER_DESC);

  if (orderType == TSDB_ORDER_ASC) {
    start = pGroupResInfo->index;
    step = 1;
  } else {  // desc order copy all data
    start = numOfRows - pGroupResInfo->index - 1;
    step = -1;
  }

  for (int32_t i = start; (i < numOfRows) && (i >= 0); i += step) {
L
Liu Jicong 已提交
2194 2195
    SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i);
    SFilePage*  page = getBufPage(pBuf, pPos->pos.pageId);
2196

2197
    SResultRow* pRow = (SResultRow*)((char*)page + pPos->pos.offset);
2198 2199 2200 2201 2202
    if (pRow->numOfRows == 0) {
      pGroupResInfo->index += 1;
      continue;
    }

2203
    // TODO copy multiple rows?
2204
    int32_t numOfRowsToCopy = pRow->numOfRows;
2205
    if (numOfResult + numOfRowsToCopy >= pBlock->info.capacity) {
2206 2207 2208 2209 2210 2211
      break;
    }

    pGroupResInfo->index += 1;

    for (int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
2212 2213
      int32_t slotId = pExprInfo[j].base.resSchema.slotId;

2214 2215
      pCtx[j].resultInfo = getResultCell(pRow, j, rowCellOffset);
      if (pCtx[j].fpSet.process) {
2216
        pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
2217 2218
      } else {
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
2219

2220 2221 2222
        char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
        colDataAppend(pColInfoData, pBlock->info.rows, in, pCtx[j].resultInfo->isNullRes);
      }
2223 2224
    }

2225 2226
    releaseBufPage(pBuf, page);

2227 2228
    pBlock->info.rows += pRow->numOfRows;
    if (pBlock->info.rows >= pBlock->info.capacity) {  // output buffer is full
2229 2230 2231 2232
      break;
    }
  }

L
Liu Jicong 已提交
2233
  // qDebug("QInfo:0x%"PRIx64" copy data to query buf completed", GET_TASKID(pRuntimeEnv));
2234
  blockDataUpdateTsWindow(pBlock);
2235 2236 2237
  return 0;
}

2238
void doBuildResultDatablock(SOptrBasicInfo *pbInfo, SGroupResInfo* pGroupResInfo, SExprInfo* pExprInfo, SDiskbasedBuf* pBuf) {
2239 2240
  assert(pGroupResInfo->currentGroup <= pGroupResInfo->totalGroup);

2241 2242 2243 2244
  int32_t* rowCellOffset = pbInfo->rowCellInfoOffset;
  SSDataBlock* pBlock    = pbInfo->pRes;
  SqlFunctionCtx* pCtx   = pbInfo->pCtx;

2245
  blockDataCleanup(pBlock);
2246 2247 2248 2249
  if (!hasRemainDataInCurrentGroup(pGroupResInfo)) {
    return;
  }

2250
  int32_t orderType = TSDB_ORDER_ASC;
2251
  doCopyToSDataBlock(pBlock, pExprInfo, pBuf, pGroupResInfo, orderType, rowCellOffset, pCtx);
2252

H
Haojun Liao 已提交
2253 2254
  // add condition (pBlock->info.rows >= 1) just to runtime happy
  blockDataUpdateTsWindow(pBlock);
2255 2256
}

L
Liu Jicong 已提交
2257 2258
static void updateNumOfRowsInResultRows(SqlFunctionCtx* pCtx, int32_t numOfOutput, SResultRowInfo* pResultRowInfo,
                                        int32_t* rowCellInfoOffset) {
2259
  // update the number of result for each, only update the number of rows for the corresponding window result.
L
Liu Jicong 已提交
2260 2261 2262
  //  if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) {
  //    return;
  //  }
H
Haojun Liao 已提交
2263
#if 0
2264
  for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
L
Liu Jicong 已提交
2265
    SResultRow* pResult = pResultRowInfo->pResult[i];
2266 2267 2268 2269 2270 2271 2272

    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;
      }

2273 2274
      SResultRowEntryInfo* pCell = getResultCell(pResult, j, rowCellInfoOffset);
      pResult->numOfRows = (uint16_t)(TMAX(pResult->numOfRows, pCell->numOfRes));
2275 2276
    }
  }
H
Haojun Liao 已提交
2277
#endif
2278 2279
}

L
Liu Jicong 已提交
2280
static int32_t compressQueryColData(SColumnInfoData* pColRes, int32_t numOfRows, char* data, int8_t compressed) {
2281 2282
  int32_t colSize = pColRes->info.bytes * numOfRows;
  return (*(tDataTypes[pColRes->info.type].compFunc))(pColRes->pData, colSize, numOfRows, data,
L
Liu Jicong 已提交
2283
                                                      colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0);
2284 2285
}

2286
int32_t doFillTimeIntervalGapsInResults(struct SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t capacity) {
L
Liu Jicong 已提交
2287 2288 2289 2290
  //  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);
  //  }
2291

2292 2293
  int32_t numOfRows = (int32_t)taosFillResultDataBlock(pFillInfo, pBlock, capacity - pBlock->info.rows);
  pBlock->info.rows += numOfRows;
2294

2295
  return pBlock->info.rows;
2296 2297
}

2298
void publishOperatorProfEvent(SOperatorInfo* pOperator, EQueryProfEventType eventType) {
2299 2300
  SQueryProfEvent event = {0};

L
Liu Jicong 已提交
2301 2302
  event.eventType = eventType;
  event.eventTime = taosGetTimestampUs();
2303
  event.operatorType = pOperator->operatorType;
dengyihao's avatar
dengyihao 已提交
2304 2305 2306
  //    if (pQInfo->summary.queryProfEvents) {
  //      taosArrayPush(pQInfo->summary.queryProfEvents, &event);
  //    }
2307 2308
}

L
Liu Jicong 已提交
2309
void publishQueryAbortEvent(SExecTaskInfo* pTaskInfo, int32_t code) {
2310 2311 2312 2313 2314
  SQueryProfEvent event;
  event.eventType = QUERY_PROF_QUERY_ABORT;
  event.eventTime = taosGetTimestampUs();
  event.abortCode = code;

2315 2316
  if (pTaskInfo->cost.queryProfEvents) {
    taosArrayPush(pTaskInfo->cost.queryProfEvents, &event);
2317 2318 2319
  }
}

L
Liu Jicong 已提交
2320
typedef struct {
2321 2322 2323 2324 2325 2326 2327
  uint8_t operatorType;
  int64_t beginTime;
  int64_t endTime;
  int64_t selfTime;
  int64_t descendantsTime;
} SOperatorStackItem;

L
Liu Jicong 已提交
2328 2329
static void doOperatorExecProfOnce(SOperatorStackItem* item, SQueryProfEvent* event, SArray* opStack,
                                   SHashObj* profResults) {
2330 2331 2332 2333 2334 2335 2336 2337
  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 已提交
2338
  uint8_t              operatorType = item->operatorType;
2339 2340 2341 2342 2343 2344 2345 2346 2347
  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 已提交
2348
    taosHashPut(profResults, &(operatorType), sizeof(operatorType), &opResult, sizeof(opResult));
2349 2350 2351
  }
}

2352
void calculateOperatorProfResults(void) {
dengyihao's avatar
dengyihao 已提交
2353 2354 2355 2356 2357 2358 2359 2360 2361
  //  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;
  //  }
2362 2363 2364 2365 2366

  SArray* opStack = taosArrayInit(32, sizeof(SOperatorStackItem));
  if (opStack == NULL) {
    return;
  }
2367
#if 0
L
Liu Jicong 已提交
2368
  size_t    size = taosArrayGetSize(pQInfo->summary.queryProfEvents);
2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389
  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);
      }
    }
  }
2390
#endif
2391 2392 2393
  taosArrayDestroy(opStack);
}

L
Liu Jicong 已提交
2394 2395
void queryCostStatis(SExecTaskInfo* pTaskInfo) {
  STaskCostInfo* pSummary = &pTaskInfo->cost;
2396

L
Liu Jicong 已提交
2397 2398 2399
  //  uint64_t hashSize = taosHashGetMemSize(pQInfo->runtimeEnv.pResultRowHashTable);
  //  hashSize += taosHashGetMemSize(pRuntimeEnv->tableqinfoGroupInfo.map);
  //  pSummary->hashSize = hashSize;
2400 2401 2402 2403

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

L
Liu Jicong 已提交
2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414
  //  SResultRowPool* p = pTaskInfo->pool;
  //  if (p != NULL) {
  //    pSummary->winInfoSize = getResultRowPoolMemSize(p);
  //    pSummary->numOfTimeWindows = getNumOfAllocatedResultRows(p);
  //  } else {
  //    pSummary->winInfoSize = 0;
  //    pSummary->numOfTimeWindows = 0;
  //  }
  //
  //  calculateOperatorProfResults(pQInfo);

2415 2416 2417 2418 2419 2420 2421
  SFileBlockLoadRecorder* pRecorder = pSummary->pRecoder;
  if (pSummary->pRecoder != NULL) {
    qDebug("%s :cost summary: elapsed time:%" PRId64 " us, first merge:%" PRId64 " us, total blocks:%d, "
           "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 已提交
2422 2423 2424
  // 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);
2425 2426 2427 2428

  if (pSummary->operatorProfResults) {
    SOperatorProfResult* opRes = taosHashIterate(pSummary->operatorProfResults, NULL);
    while (opRes != NULL) {
L
Liu Jicong 已提交
2429 2430
      // qDebug("QInfo:0x%" PRIx64 " :cost summary: operator : %d, exec times: %" PRId64 ", self time: %" PRId64,
      //             pQInfo->qId, opRes->operatorType, opRes->sumRunTimes, opRes->sumSelfTime);
2431 2432 2433 2434 2435
      opRes = taosHashIterate(pSummary->operatorProfResults, opRes);
    }
  }
}

L
Liu Jicong 已提交
2436 2437 2438
// static void updateOffsetVal(STaskRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBlockInfo) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
//   STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
2439
//
L
Liu Jicong 已提交
2440
//   int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
2441
//
L
Liu Jicong 已提交
2442 2443 2444 2445
//   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;
//   }
2446
//
L
Liu Jicong 已提交
2447 2448 2449 2450 2451
//   if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
//     pQueryAttr->pos = (int32_t)pQueryAttr->limit.offset;
//   } else {
//     pQueryAttr->pos = pBlockInfo->rows - (int32_t)pQueryAttr->limit.offset - 1;
//   }
2452
//
L
Liu Jicong 已提交
2453
//   assert(pQueryAttr->pos >= 0 && pQueryAttr->pos <= pBlockInfo->rows - 1);
2454
//
L
Liu Jicong 已提交
2455 2456
//   SArray *         pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL);
//   SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
2457
//
L
Liu Jicong 已提交
2458 2459
//   // update the pQueryAttr->limit.offset value, and pQueryAttr->pos value
//   TSKEY *keys = (TSKEY *) pColInfoData->pData;
2460
//
L
Liu Jicong 已提交
2461 2462 2463
//   // update the offset value
//   pTableQueryInfo->lastKey = keys[pQueryAttr->pos];
//   pQueryAttr->limit.offset = 0;
2464
//
L
Liu Jicong 已提交
2465
//   int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
2466
//
L
Liu Jicong 已提交
2467 2468 2469 2470
//   //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);
// }
2471

L
Liu Jicong 已提交
2472 2473
// void skipBlocks(STaskRuntimeEnv *pRuntimeEnv) {
//   STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
2474
//
L
Liu Jicong 已提交
2475 2476 2477
//   if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0) {
//     return;
//   }
2478
//
L
Liu Jicong 已提交
2479 2480
//   pQueryAttr->pos = 0;
//   int32_t step = GET_FORWARD_DIRECTION_FACTOR(pQueryAttr->order.order);
2481
//
L
Liu Jicong 已提交
2482 2483
//   STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
//   TsdbQueryHandleT pTsdbReadHandle = pRuntimeEnv->pTsdbReadHandle;
2484
//
L
Liu Jicong 已提交
2485 2486 2487 2488 2489
//   SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//   while (tsdbNextDataBlock(pTsdbReadHandle)) {
//     if (isTaskKilled(pRuntimeEnv->qinfo)) {
//       longjmp(pRuntimeEnv->env, TSDB_CODE_TSC_QUERY_CANCELLED);
//     }
2490
//
L
Liu Jicong 已提交
2491
//     tsdbRetrieveDataBlockInfo(pTsdbReadHandle, &blockInfo);
2492
//
L
Liu Jicong 已提交
2493 2494 2495 2496
//     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;
2497
//
L
Liu Jicong 已提交
2498 2499 2500 2501 2502 2503 2504
//       //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;
//     }
//   }
2505
//
L
Liu Jicong 已提交
2506 2507 2508 2509 2510 2511 2512 2513 2514
//   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;
2515
//
L
Liu Jicong 已提交
2516 2517 2518
//   assert(pQueryAttr->limit.offset == 0);
//   STimeWindow tw = *win;
//   getNextTimeWindow(pQueryAttr, &tw);
2519
//
L
Liu Jicong 已提交
2520 2521
//   if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) ||
//       (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) {
2522
//
L
Liu Jicong 已提交
2523 2524 2525 2526
//     // 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);
2527
//
L
Liu Jicong 已提交
2528 2529 2530 2531
//     tw = *win;
//     int32_t startPos =
//         getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1);
//     assert(startPos >= 0);
2532
//
L
Liu Jicong 已提交
2533 2534
//     // set the abort info
//     pQueryAttr->pos = startPos;
2535
//
L
Liu Jicong 已提交
2536 2537 2538 2539
//     // reset the query start timestamp
//     pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos];
//     pQueryAttr->window.skey = pTableQueryInfo->win.skey;
//     TSKEY key = pTableQueryInfo->win.skey;
2540
//
L
Liu Jicong 已提交
2541 2542
//     pWindowResInfo->prevSKey = tw.skey;
//     int32_t index = pRuntimeEnv->resultRowInfo.curIndex;
2543
//
L
Liu Jicong 已提交
2544 2545
//     int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock);
//     pRuntimeEnv->resultRowInfo.curIndex = index;  // restore the window index
2546
//
L
Liu Jicong 已提交
2547 2548 2549 2550
//     //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);
2551
//
L
Liu Jicong 已提交
2552 2553 2554 2555 2556
//     return key;
//   } else {  // do nothing
//     pQueryAttr->window.skey      = tw.skey;
//     pWindowResInfo->prevSKey = tw.skey;
//     pTableQueryInfo->lastKey = tw.skey;
2557
//
L
Liu Jicong 已提交
2558 2559
//     return tw.skey;
//   }
2560
//
L
Liu Jicong 已提交
2561 2562 2563 2564 2565 2566 2567 2568 2569 2570
//   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);
//   }
2571
//
L
Liu Jicong 已提交
2572 2573 2574 2575 2576
//   // 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;
//   }
2577
//
L
Liu Jicong 已提交
2578 2579 2580 2581 2582 2583 2584
//   /*
//    * 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);
2585
//
L
Liu Jicong 已提交
2586 2587
//   STimeWindow w = TSWINDOW_INITIALIZER;
//   bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr);
2588
//
L
Liu Jicong 已提交
2589 2590
//   SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo;
//   STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current;
2591
//
L
Liu Jicong 已提交
2592 2593 2594
//   SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER;
//   while (tsdbNextDataBlock(pRuntimeEnv->pTsdbReadHandle)) {
//     tsdbRetrieveDataBlockInfo(pRuntimeEnv->pTsdbReadHandle, &blockInfo);
2595
//
L
Liu Jicong 已提交
2596 2597 2598 2599 2600 2601 2602 2603 2604
//     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;
//     }
2605
//
L
Liu Jicong 已提交
2606 2607
//     // the first time window
//     STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr);
2608
//
L
Liu Jicong 已提交
2609 2610
//     while (pQueryAttr->limit.offset > 0) {
//       STimeWindow tw = win;
2611
//
L
Liu Jicong 已提交
2612 2613 2614
//       if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
//         pQueryAttr->limit.offset -= 1;
//         pWindowResInfo->prevSKey = win.skey;
2615
//
L
Liu Jicong 已提交
2616 2617 2618 2619 2620 2621
//         // 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;
//         }
//       }
2622
//
L
Liu Jicong 已提交
2623 2624 2625 2626
//       if (pQueryAttr->limit.offset == 0) {
//         *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
//         return true;
//       }
2627
//
L
Liu Jicong 已提交
2628 2629
//       // current window does not ended in current data block, try next data block
//       getNextTimeWindow(pQueryAttr, &tw);
2630
//
L
Liu Jicong 已提交
2631 2632 2633 2634 2635 2636 2637 2638 2639
//       /*
//        * 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)) {
2640
//
L
Liu Jicong 已提交
2641 2642
//         SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL);
//         SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
2643
//
L
Liu Jicong 已提交
2644 2645 2646
//         if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
//           pQueryAttr->limit.offset -= 1;
//         }
2647
//
L
Liu Jicong 已提交
2648 2649 2650 2651 2652 2653 2654 2655
//         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);
2656
//
L
Liu Jicong 已提交
2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
//           // 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.
//       }
//     }
//   }
2668
//
L
Liu Jicong 已提交
2669 2670 2671 2672
//   // check for error
//   if (terrno != TSDB_CODE_SUCCESS) {
//     longjmp(pRuntimeEnv->env, terrno);
//   }
2673
//
L
Liu Jicong 已提交
2674 2675
//   return true;
// }
2676

2677
int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num) {
H
Haojun Liao 已提交
2678
  if (p->pDownstream == NULL) {
H
Haojun Liao 已提交
2679
    assert(p->numOfDownstream == 0);
2680 2681
  }

wafwerar's avatar
wafwerar 已提交
2682
  p->pDownstream = taosMemoryCalloc(1, num * POINTER_BYTES);
2683 2684 2685 2686 2687 2688 2689
  if (p->pDownstream == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  memcpy(p->pDownstream, pDownstream, num * POINTER_BYTES);
  p->numOfDownstream = num;
  return TSDB_CODE_SUCCESS;
2690 2691 2692 2693
}

static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo);

2694
static void doTableQueryInfoTimeWindowCheck(SExecTaskInfo* pTaskInfo, STableQueryInfo* pTableQueryInfo, int32_t order) {
H
Haojun Liao 已提交
2695 2696
#if 0
    if (order == TSDB_ORDER_ASC) {
2697 2698
    assert(
        (pTableQueryInfo->win.skey <= pTableQueryInfo->win.ekey) &&
H
Haojun Liao 已提交
2699 2700
        (pTableQueryInfo->lastKey >= pTaskInfo->window.skey) &&
        (pTableQueryInfo->win.skey >= pTaskInfo->window.skey && pTableQueryInfo->win.ekey <= pTaskInfo->window.ekey));
2701 2702 2703
  } else {
    assert(
        (pTableQueryInfo->win.skey >= pTableQueryInfo->win.ekey) &&
H
Haojun Liao 已提交
2704 2705
        (pTableQueryInfo->lastKey <= pTaskInfo->window.skey) &&
        (pTableQueryInfo->win.skey <= pTaskInfo->window.skey && pTableQueryInfo->win.ekey >= pTaskInfo->window.ekey));
2706
  }
H
Haojun Liao 已提交
2707
#endif
2708 2709
}

L
Liu Jicong 已提交
2710 2711 2712 2713
// 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;
2714
//
L
Liu Jicong 已提交
2715 2716 2717
//   if (pTableQueryInfo->pTable == NULL) {
//     return;
//   }
2718
//
L
Liu Jicong 已提交
2719 2720 2721 2722 2723 2724 2725 2726 2727
//   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));
//   }
// }
2728

2729
int32_t loadRemoteDataCallback(void* param, const SDataBuf* pMsg, int32_t code) {
L
Liu Jicong 已提交
2730
  SSourceDataInfo* pSourceDataInfo = (SSourceDataInfo*)param;
H
Haojun Liao 已提交
2731 2732
  if (code == TSDB_CODE_SUCCESS) {
    pSourceDataInfo->pRsp = pMsg->pData;
2733

H
Haojun Liao 已提交
2734 2735
    SRetrieveTableRsp* pRsp = pSourceDataInfo->pRsp;
    pRsp->numOfRows = htonl(pRsp->numOfRows);
dengyihao's avatar
dengyihao 已提交
2736
    pRsp->compLen = htonl(pRsp->compLen);
2737
    pRsp->numOfCols = htonl(pRsp->numOfCols);
dengyihao's avatar
dengyihao 已提交
2738
    pRsp->useconds = htobe64(pRsp->useconds);
H
Haojun Liao 已提交
2739 2740 2741
  } else {
    pSourceDataInfo->code = code;
  }
H
Haojun Liao 已提交
2742

H
Haojun Liao 已提交
2743
  pSourceDataInfo->status = EX_SOURCE_DATA_READY;
2744
  tsem_post(&pSourceDataInfo->pEx->ready);
wmmhello's avatar
wmmhello 已提交
2745
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
2746 2747 2748 2749
}

static void destroySendMsgInfo(SMsgSendInfo* pMsgBody) {
  assert(pMsgBody != NULL);
wafwerar's avatar
wafwerar 已提交
2750 2751
  taosMemoryFreeClear(pMsgBody->msgInfo.pData);
  taosMemoryFreeClear(pMsgBody);
H
Haojun Liao 已提交
2752 2753
}

S
Shengliang Guan 已提交
2754
void qProcessFetchRsp(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) {
L
Liu Jicong 已提交
2755
  SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->ahandle;
H
Haojun Liao 已提交
2756 2757 2758 2759 2760
  assert(pMsg->ahandle != NULL);

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

  if (pMsg->contLen > 0) {
wafwerar's avatar
wafwerar 已提交
2761
    buf.pData = taosMemoryCalloc(1, pMsg->contLen);
H
Haojun Liao 已提交
2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772
    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);
2773 2774
}

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

wafwerar's avatar
wafwerar 已提交
2778
  SResFetchReq* pMsg = taosMemoryCalloc(1, sizeof(SResFetchReq));
2779 2780 2781 2782
  if (NULL == pMsg) {
    pTaskInfo->code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return pTaskInfo->code;
  }
2783

L
Liu Jicong 已提交
2784 2785
  SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, sourceIndex);
  SSourceDataInfo*       pDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, sourceIndex);
2786

L
Liu Jicong 已提交
2787 2788
  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);
2789 2790 2791 2792 2793 2794 2795

  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 已提交
2796
  SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
2797
  if (NULL == pMsgSendInfo) {
wafwerar's avatar
wafwerar 已提交
2798
    taosMemoryFreeClear(pMsg);
2799 2800 2801
    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 已提交
2802 2803
  }

2804 2805 2806 2807 2808
  pMsgSendInfo->param = pDataInfo;
  pMsgSendInfo->msgInfo.pData = pMsg;
  pMsgSendInfo->msgInfo.len = sizeof(SResFetchReq);
  pMsgSendInfo->msgType = TDMT_VND_FETCH;
  pMsgSendInfo->fp = loadRemoteDataCallback;
2809

2810
  int64_t transporterId = 0;
L
Liu Jicong 已提交
2811
  int32_t code = asyncSendMsgToServer(pExchangeInfo->pTransporter, &pSource->addr.epSet, &transporterId, pMsgSendInfo);
2812 2813 2814
  return TSDB_CODE_SUCCESS;
}

2815
// NOTE: sources columns are more than the destination SSDatablock columns.
2816
void relocateColumnData(SSDataBlock* pBlock, const SArray* pColMatchInfo, SArray* pCols) {
2817 2818 2819 2820
  size_t numOfSrcCols = taosArrayGetSize(pCols);
  ASSERT(numOfSrcCols >= pBlock->info.numOfCols);

  int32_t i = 0, j = 0;
L
Liu Jicong 已提交
2821
  while (i < numOfSrcCols && j < taosArrayGetSize(pColMatchInfo)) {
2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840
    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);
    }
  }
}

2841
int32_t setSDataBlockFromFetchRsp(SSDataBlock* pRes, SLoadRemoteDataInfo* pLoadInfo, int32_t numOfRows, char* pData,
dengyihao's avatar
dengyihao 已提交
2842 2843
                                  int32_t compLen, int32_t numOfOutput, int64_t startTs, uint64_t* total,
                                  SArray* pColList) {
H
Haojun Liao 已提交
2844
  blockDataEnsureCapacity(pRes, numOfRows);
2845

H
Haojun Liao 已提交
2846
  if (pColList == NULL) {  // data from other sources
L
Liu Jicong 已提交
2847
    int32_t dataLen = *(int32_t*)pData;
2848 2849
    pData += sizeof(int32_t);

L
Liu Jicong 已提交
2850
    pRes->info.groupId = *(uint64_t*)pData;
2851 2852
    pData += sizeof(uint64_t);

H
Haojun Liao 已提交
2853 2854
    int32_t* colLen = (int32_t*)pData;

2855
    char* pStart = pData + sizeof(int32_t) * numOfOutput;
2856
    for (int32_t i = 0; i < numOfOutput; ++i) {
H
Haojun Liao 已提交
2857
      colLen[i] = htonl(colLen[i]);
2858
      ASSERT(colLen[i] >= 0);
H
Haojun Liao 已提交
2859

2860
      SColumnInfoData* pColInfoData = taosArrayGet(pRes->pDataBlock, i);
H
Haojun Liao 已提交
2861 2862 2863
      if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) {
        pColInfoData->varmeta.length = colLen[i];
        pColInfoData->varmeta.allocLen = colLen[i];
2864

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

2868 2869 2870
        if (colLen[i] > 0) {
          pColInfoData->pData = taosMemoryMalloc(colLen[i]);
        }
H
Haojun Liao 已提交
2871 2872 2873
      } else {
        memcpy(pColInfoData->nullbitmap, pStart, BitmapLen(numOfRows));
        pStart += BitmapLen(numOfRows);
2874
      }
H
Haojun Liao 已提交
2875

2876 2877 2878 2879
      if (colLen[i] > 0) {
        memcpy(pColInfoData->pData, pStart, colLen[i]);
      }

L
Liu Jicong 已提交
2880 2881
      // TODO setting this flag to true temporarily so aggregate function on stable will
      // examine NULL value for non-primary key column
2882
      pColInfoData->hasNull = true;
H
Haojun Liao 已提交
2883
      pStart += colLen[i];
2884
    }
H
Haojun Liao 已提交
2885
  } else {  // extract data according to pColList
2886
    ASSERT(numOfOutput == taosArrayGetSize(pColList));
2887 2888 2889 2890 2891
    char* pStart = pData;

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

2892
    // todo refactor:extract method
2893
    SSysTableSchema* pSchema = (SSysTableSchema*)pStart;
dengyihao's avatar
dengyihao 已提交
2894
    for (int32_t i = 0; i < numOfCols; ++i) {
2895 2896 2897 2898 2899 2900 2901 2902
      SSysTableSchema* p = (SSysTableSchema*)pStart;

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

    SSDataBlock block = {.pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData)), .info.numOfCols = numOfCols};
dengyihao's avatar
dengyihao 已提交
2903
    for (int32_t i = 0; i < numOfCols; ++i) {
2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916
      SColumnInfoData idata = {0};
      idata.info.type = pSchema[i].type;
      idata.info.bytes = pSchema[i].bytes;
      idata.info.colId = pSchema[i].colId;

      taosArrayPush(block.pDataBlock, &idata);
      if (IS_VAR_DATA_TYPE(idata.info.type)) {
        block.info.hasVarCol = true;
      }
    }

    blockDataEnsureCapacity(&block, numOfRows);

L
Liu Jicong 已提交
2917 2918
    int32_t  dataLen = *(int32_t*)pStart;
    uint64_t groupId = *(uint64_t*)(pStart + sizeof(int32_t));
2919 2920
    pStart += sizeof(int32_t) + sizeof(uint64_t);

L
Liu Jicong 已提交
2921
    int32_t* colLen = (int32_t*)(pStart);
2922 2923 2924 2925
    pStart += sizeof(int32_t) * numOfCols;

    for (int32_t i = 0; i < numOfCols; ++i) {
      colLen[i] = htonl(colLen[i]);
2926
      ASSERT(colLen[i] >= 0);
2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944

      SColumnInfoData* pColInfoData = taosArrayGet(block.pDataBlock, i);
      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 已提交
2945 2946

    // data from mnode
L
Liu Jicong 已提交
2947
    relocateColumnData(pRes, pColList, block.pDataBlock);
2948
  }
2949

H
Haojun Liao 已提交
2950
  pRes->info.rows = numOfRows;
2951
  blockDataUpdateTsWindow(pRes);
2952

2953
  int64_t el = taosGetTimestampUs() - startTs;
2954

H
Haojun Liao 已提交
2955 2956
  pLoadInfo->totalRows += numOfRows;
  pLoadInfo->totalSize += compLen;
2957

H
Haojun Liao 已提交
2958 2959 2960
  if (total != NULL) {
    *total += numOfRows;
  }
2961

H
Haojun Liao 已提交
2962
  pLoadInfo->totalElapsed += el;
2963 2964
  return TSDB_CODE_SUCCESS;
}
2965

L
Liu Jicong 已提交
2966 2967
static void* setAllSourcesCompleted(SOperatorInfo* pOperator, int64_t startTs) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
2968
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
H
Haojun Liao 已提交
2969

L
Liu Jicong 已提交
2970
  int64_t              el = taosGetTimestampUs() - startTs;
H
Haojun Liao 已提交
2971 2972
  SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
  pLoadInfo->totalElapsed += el;
H
Haojun Liao 已提交
2973

2974
  size_t totalSources = taosArrayGetSize(pExchangeInfo->pSources);
L
Liu Jicong 已提交
2975 2976 2977
  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);
2978 2979 2980 2981 2982

  doSetOperatorCompleted(pOperator);
  return NULL;
}

L
Liu Jicong 已提交
2983 2984
static SSDataBlock* concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SExchangeInfo* pExchangeInfo,
                                                   SExecTaskInfo* pTaskInfo) {
2985 2986 2987 2988 2989 2990 2991 2992 2993
  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);

2994
      if (pDataInfo->status == EX_SOURCE_DATA_EXHAUSTED) {
2995
        completed += 1;
H
Haojun Liao 已提交
2996 2997
        continue;
      }
2998

2999
      if (pDataInfo->status != EX_SOURCE_DATA_READY) {
3000 3001 3002
        continue;
      }

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

L
Liu Jicong 已提交
3006
      SSDataBlock*         pRes = pExchangeInfo->pResult;
H
Haojun Liao 已提交
3007
      SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
3008
      if (pRsp->numOfRows == 0) {
L
Liu Jicong 已提交
3009 3010
        qDebug("%s vgId:%d, taskID:0x%" PRIx64 " index:%d completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
               " try next",
3011
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, i + 1, pDataInfo->totalRows,
H
Haojun Liao 已提交
3012
               pExchangeInfo->loadInfo.totalRows);
3013
        pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3014 3015 3016
        completed += 1;
        continue;
      }
H
Haojun Liao 已提交
3017

H
Haojun Liao 已提交
3018
      SRetrieveTableRsp* pTableRsp = pDataInfo->pRsp;
X
Xiaoyu Wang 已提交
3019 3020
      code = setSDataBlockFromFetchRsp(pExchangeInfo->pResult, pLoadInfo, pTableRsp->numOfRows, pTableRsp->data,
                                       pTableRsp->compLen, pTableRsp->numOfCols, startTs, &pDataInfo->totalRows, NULL);
3021
      if (code != 0) {
3022 3023 3024
        goto _error;
      }

3025 3026 3027
      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 已提交
3028 3029
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pDataInfo->totalRows,
               pLoadInfo->totalRows, pLoadInfo->totalSize, i + 1, totalSources);
3030
        pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3031
      } else {
dengyihao's avatar
dengyihao 已提交
3032 3033
        qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, totalRows:%" PRIu64
               ", totalBytes:%" PRIu64,
H
Haojun Liao 已提交
3034 3035
               GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pRes->info.rows, pLoadInfo->totalRows,
               pLoadInfo->totalSize);
3036 3037
      }

3038 3039
      if (pDataInfo->status != EX_SOURCE_DATA_EXHAUSTED) {
        pDataInfo->status = EX_SOURCE_DATA_NOT_READY;
3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058
        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 已提交
3059 3060 3061
static SSDataBlock* concurrentlyLoadRemoteData(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
H
Haojun Liao 已提交
3062

H
Haojun Liao 已提交
3063 3064 3065
  if (pOperator->status == OP_RES_TO_RETURN) {
    return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo);
  }
3066

L
Liu Jicong 已提交
3067
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3068 3069 3070
  int64_t startTs = taosGetTimestampUs();

  // Asynchronously send all fetch requests to all sources.
L
Liu Jicong 已提交
3071
  for (int32_t i = 0; i < totalSources; ++i) {
3072 3073
    int32_t code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i);
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3074
      return NULL;
3075 3076 3077 3078
    }
  }

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

  tsem_wait(&pExchangeInfo->ready);
H
Haojun Liao 已提交
3083 3084
  pOperator->status = OP_RES_TO_RETURN;
  return concurrentlyLoadRemoteDataImpl(pOperator, pExchangeInfo, pTaskInfo);
3085 3086
}

L
Liu Jicong 已提交
3087 3088 3089
static int32_t prepareConcurrentlyLoad(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3090

L
Liu Jicong 已提交
3091
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3092 3093 3094
  int64_t startTs = taosGetTimestampUs();

  // Asynchronously send all fetch requests to all sources.
L
Liu Jicong 已提交
3095
  for (int32_t i = 0; i < totalSources; ++i) {
3096 3097
    int32_t code = doSendFetchDataRequest(pExchangeInfo, pTaskInfo, i);
    if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3098 3099
      pTaskInfo->code = code;
      return code;
3100 3101 3102 3103
    }
  }

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

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

H
Haojun Liao 已提交
3110
  return TSDB_CODE_SUCCESS;
3111 3112
}

L
Liu Jicong 已提交
3113 3114 3115
static SSDataBlock* seqLoadRemoteData(SOperatorInfo* pOperator) {
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3116

L
Liu Jicong 已提交
3117
  size_t  totalSources = taosArrayGetSize(pExchangeInfo->pSources);
3118
  int64_t startTs = taosGetTimestampUs();
3119

L
Liu Jicong 已提交
3120
  while (1) {
3121 3122
    if (pExchangeInfo->current >= totalSources) {
      return setAllSourcesCompleted(pOperator, startTs);
3123
    }
3124

3125 3126 3127
    doSendFetchDataRequest(pExchangeInfo, pTaskInfo, pExchangeInfo->current);
    tsem_wait(&pExchangeInfo->ready);

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

H
Haojun Liao 已提交
3131
    if (pDataInfo->code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
3132 3133
      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 已提交
3134 3135 3136 3137
      pOperator->pTaskInfo->code = pDataInfo->code;
      return NULL;
    }

L
Liu Jicong 已提交
3138
    SRetrieveTableRsp*   pRsp = pDataInfo->pRsp;
H
Haojun Liao 已提交
3139
    SLoadRemoteDataInfo* pLoadInfo = &pExchangeInfo->loadInfo;
3140
    if (pRsp->numOfRows == 0) {
dengyihao's avatar
dengyihao 已提交
3141 3142
      qDebug("%s vgId:%d, taskID:0x%" PRIx64 " %d of total completed, rowsOfSource:%" PRIu64 ", totalRows:%" PRIu64
             " try next",
3143
             GET_TASKID(pTaskInfo), pSource->addr.nodeId, pSource->taskId, pExchangeInfo->current + 1,
H
Haojun Liao 已提交
3144
             pDataInfo->totalRows, pLoadInfo->totalRows);
H
Haojun Liao 已提交
3145

3146
      pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3147 3148 3149
      pExchangeInfo->current += 1;
      continue;
    }
H
Haojun Liao 已提交
3150

L
Liu Jicong 已提交
3151
    SSDataBlock*       pRes = pExchangeInfo->pResult;
H
Haojun Liao 已提交
3152
    SRetrieveTableRsp* pTableRsp = pDataInfo->pRsp;
L
Liu Jicong 已提交
3153 3154
    int32_t            code =
        setSDataBlockFromFetchRsp(pExchangeInfo->pResult, pLoadInfo, pTableRsp->numOfRows, pTableRsp->data,
3155
                                  pTableRsp->compLen, pTableRsp->numOfCols, startTs, &pDataInfo->totalRows, NULL);
3156 3157

    if (pRsp->completed == 1) {
H
Haojun Liao 已提交
3158
      qDebug("%s fetch msg rsp from vgId:%d, taskId:0x%" PRIx64 " numOfRows:%d, rowsOfSource:%" PRIu64
L
Liu Jicong 已提交
3159 3160 3161
             ", 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);
3162

3163
      pDataInfo->status = EX_SOURCE_DATA_EXHAUSTED;
3164 3165
      pExchangeInfo->current += 1;
    } else {
L
Liu Jicong 已提交
3166 3167 3168 3169
      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);
3170 3171 3172 3173
    }

    return pExchangeInfo->pResult;
  }
3174 3175
}

L
Liu Jicong 已提交
3176
static int32_t prepareLoadRemoteData(SOperatorInfo* pOperator) {
3177
  if (OPTR_IS_OPENED(pOperator)) {
H
Haojun Liao 已提交
3178 3179 3180
    return TSDB_CODE_SUCCESS;
  }

L
Liu Jicong 已提交
3181
  SExchangeInfo* pExchangeInfo = pOperator->info;
H
Haojun Liao 已提交
3182 3183 3184 3185 3186 3187 3188 3189 3190
  if (pExchangeInfo->seqLoadData) {
    // do nothing for sequentially load data
  } else {
    int32_t code = prepareConcurrentlyLoad(pOperator);
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
  }

3191
  OPTR_SET_OPENED(pOperator);
H
Haojun Liao 已提交
3192 3193 3194
  return TSDB_CODE_SUCCESS;
}

3195
static SSDataBlock* doLoadRemoteData(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
3196 3197
  SExchangeInfo* pExchangeInfo = pOperator->info;
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3198

3199
  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
3200
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
3201 3202
    return NULL;
  }
3203

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

3207
  if (pOperator->status == OP_EXEC_DONE) {
L
Liu Jicong 已提交
3208 3209 3210
    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);
3211 3212 3213 3214 3215 3216
    return NULL;
  }

  if (pExchangeInfo->seqLoadData) {
    return seqLoadRemoteData(pOperator);
  } else {
H
Haojun Liao 已提交
3217
    return concurrentlyLoadRemoteData(pOperator);
3218
  }
H
Haojun Liao 已提交
3219

3220
#if 0
H
Haojun Liao 已提交
3221
  _error:
wafwerar's avatar
wafwerar 已提交
3222 3223
  taosMemoryFreeClear(pMsg);
  taosMemoryFreeClear(pMsgSendInfo);
H
Haojun Liao 已提交
3224 3225 3226

  terrno = pTaskInfo->code;
  return NULL;
3227
#endif
H
Haojun Liao 已提交
3228
}
3229

H
Haojun Liao 已提交
3230
static int32_t initDataSource(int32_t numOfSources, SExchangeInfo* pInfo) {
3231
  pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo));
H
Haojun Liao 已提交
3232 3233
  if (pInfo->pSourceDataInfo == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
3234 3235
  }

L
Liu Jicong 已提交
3236
  for (int32_t i = 0; i < numOfSources; ++i) {
3237
    SSourceDataInfo dataInfo = {0};
H
Haojun Liao 已提交
3238
    dataInfo.status = EX_SOURCE_DATA_NOT_READY;
L
Liu Jicong 已提交
3239 3240
    dataInfo.pEx = pInfo;
    dataInfo.index = i;
3241

H
Haojun Liao 已提交
3242 3243 3244 3245 3246 3247 3248 3249 3250 3251
    void* ret = taosArrayPush(pInfo->pSourceDataInfo, &dataInfo);
    if (ret == NULL) {
      taosArrayDestroy(pInfo->pSourceDataInfo);
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
3252
SOperatorInfo* createExchangeOperatorInfo(const SNodeList* pSources, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) {
L
Liu Jicong 已提交
3253
  SExchangeInfo* pInfo = taosMemoryCalloc(1, sizeof(SExchangeInfo));
wafwerar's avatar
wafwerar 已提交
3254
  SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
3255 3256

  if (pInfo == NULL || pOperator == NULL) {
wafwerar's avatar
wafwerar 已提交
3257 3258
    taosMemoryFreeClear(pInfo);
    taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
3259 3260
    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return NULL;
H
Haojun Liao 已提交
3261 3262
  }

H
Haojun Liao 已提交
3263
  size_t numOfSources = LIST_LENGTH(pSources);
H
Haojun Liao 已提交
3264
  pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode));
H
Haojun Liao 已提交
3265 3266 3267
  pInfo->pSourceDataInfo = taosArrayInit(numOfSources, sizeof(SSourceDataInfo));
  if (pInfo->pSourceDataInfo == NULL || pInfo->pSources == NULL) {
    goto _error;
H
Haojun Liao 已提交
3268 3269
  }

L
Liu Jicong 已提交
3270 3271
  for (int32_t i = 0; i < numOfSources; ++i) {
    SNodeListNode* pNode = nodesListGetNode((SNodeList*)pSources, i);
H
Haojun Liao 已提交
3272 3273
    taosArrayPush(pInfo->pSources, pNode);
  }
3274

H
Haojun Liao 已提交
3275 3276 3277
  int32_t code = initDataSource(numOfSources, pInfo);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
3278
  }
H
Haojun Liao 已提交
3279

dengyihao's avatar
dengyihao 已提交
3280
  pInfo->pResult = pBlock;
3281 3282 3283
  pInfo->seqLoadData = true;

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

dengyihao's avatar
dengyihao 已提交
3285
  pOperator->name = "ExchangeOperator";
X
Xiaoyu Wang 已提交
3286
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_EXCHANGE;
3287
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
3288 3289 3290 3291
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->numOfOutput = pBlock->info.numOfCols;
  pOperator->pTaskInfo = pTaskInfo;
3292

L
Liu Jicong 已提交
3293 3294
  pOperator->fpSet = createOperatorFpSet(prepareLoadRemoteData, doLoadRemoteData, NULL, NULL,
                                         destroyExchangeOperatorInfo, NULL, NULL, NULL);
3295

S
Shengliang Guan 已提交
3296
#if 1
L
Liu Jicong 已提交
3297
  {  // todo refactor
H
Haojun Liao 已提交
3298 3299 3300
    SRpcInit rpcInit;
    memset(&rpcInit, 0, sizeof(rpcInit));
    rpcInit.localPort = 0;
H
Haojun Liao 已提交
3301
    rpcInit.label = "EX";
H
Haojun Liao 已提交
3302
    rpcInit.numOfThreads = 1;
S
Shengliang Guan 已提交
3303
    rpcInit.cfp = qProcessFetchRsp;
S
Shengliang Guan 已提交
3304
    rpcInit.sessions = tsMaxConnections;
H
Haojun Liao 已提交
3305
    rpcInit.connType = TAOS_CONN_CLIENT;
L
Liu Jicong 已提交
3306
    rpcInit.user = (char*)"root";
S
Shengliang Guan 已提交
3307
    rpcInit.idleTime = tsShellActivityTimer * 1000;
H
Haojun Liao 已提交
3308
    rpcInit.ckey = "key";
S
Shengliang Guan 已提交
3309
    rpcInit.spi = 1;
L
Liu Jicong 已提交
3310
    rpcInit.secret = (char*)"dcc5bed04851fec854c035b2e40263b6";
H
Haojun Liao 已提交
3311 3312 3313

    pInfo->pTransporter = rpcOpen(&rpcInit);
    if (pInfo->pTransporter == NULL) {
L
Liu Jicong 已提交
3314
      return NULL;  // todo
H
Haojun Liao 已提交
3315 3316
    }
  }
S
Shengliang 已提交
3317
#endif
3318

3319
  return pOperator;
H
Haojun Liao 已提交
3320

L
Liu Jicong 已提交
3321
_error:
H
Haojun Liao 已提交
3322
  if (pInfo != NULL) {
H
Haojun Liao 已提交
3323
    destroyExchangeOperatorInfo(pInfo, numOfSources);
H
Haojun Liao 已提交
3324 3325
  }

wafwerar's avatar
wafwerar 已提交
3326 3327
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
3328
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
H
Haojun Liao 已提交
3329
  return NULL;
3330 3331
}

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

3335
static void destroySortedMergeOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
3336
  SSortedMergeOperatorInfo* pInfo = (SSortedMergeOperatorInfo*)param;
H
Haojun Liao 已提交
3337
  taosArrayDestroy(pInfo->pSortInfo);
3338 3339 3340
  taosArrayDestroy(pInfo->groupInfo);

  if (pInfo->pSortHandle != NULL) {
H
Haojun Liao 已提交
3341
    tsortDestroySortHandle(pInfo->pSortHandle);
3342 3343
  }

H
Haojun Liao 已提交
3344
  blockDataDestroy(pInfo->binfo.pRes);
H
Haojun Liao 已提交
3345
  cleanupAggSup(&pInfo->aggSup);
3346
}
H
Haojun Liao 已提交
3347

H
Haojun Liao 已提交
3348
// TODO merge aggregate super table
L
Liu Jicong 已提交
3349
static void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle) {
3350 3351
  for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i);
3352

H
Haojun Liao 已提交
3353
    bool isNull = tsortIsNullVal(pTupleHandle, i);
H
Haojun Liao 已提交
3354 3355 3356
    if (isNull) {
      colDataAppend(pColInfo, pBlock->info.rows, NULL, true);
    } else {
H
Haojun Liao 已提交
3357
      char* pData = tsortGetValue(pTupleHandle, i);
H
Haojun Liao 已提交
3358 3359
      colDataAppend(pColInfo, pBlock->info.rows, pData, false);
    }
3360 3361
  }

3362 3363
  pBlock->info.rows += 1;
}
3364

H
Haojun Liao 已提交
3365
SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, int32_t capacity) {
3366
  blockDataCleanup(pDataBlock);
D
dapan1121 已提交
3367
  blockDataEnsureCapacity(pDataBlock, capacity);
3368

wmmhello's avatar
wmmhello 已提交
3369 3370
  blockDataEnsureCapacity(pDataBlock, capacity);

L
Liu Jicong 已提交
3371
  while (1) {
H
Haojun Liao 已提交
3372
    STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
3373 3374 3375
    if (pTupleHandle == NULL) {
      break;
    }
3376

3377 3378 3379
    appendOneRowToDataBlock(pDataBlock, pTupleHandle);
    if (pDataBlock->info.rows >= capacity) {
      return pDataBlock;
H
Haojun Liao 已提交
3380 3381
    }
  }
3382

L
Liu Jicong 已提交
3383
  return (pDataBlock->info.rows > 0) ? pDataBlock : NULL;
3384
}
3385

3386
SSDataBlock* loadNextDataBlock(void* param) {
L
Liu Jicong 已提交
3387
  SOperatorInfo* pOperator = (SOperatorInfo*)param;
3388
  return pOperator->fpSet.getNextFn(pOperator);
3389 3390
}

L
Liu Jicong 已提交
3391
static bool needToMerge(SSDataBlock* pBlock, SArray* groupInfo, char** buf, int32_t rowIndex) {
3392 3393 3394 3395
  size_t size = taosArrayGetSize(groupInfo);
  if (size == 0) {
    return true;
  }
3396

3397 3398
  for (int32_t i = 0; i < size; ++i) {
    int32_t* index = taosArrayGet(groupInfo, i);
3399

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

3403 3404 3405
    if ((isNull && buf[i] != NULL) || (!isNull && buf[i] == NULL)) {
      return false;
    }
3406

3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419
    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;
      }
3420 3421 3422
    }
  }

3423
  return 0;
3424 3425
}

L
Liu Jicong 已提交
3426 3427 3428
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
3429
    pCtx[j].startRow = rowIndex;
3430 3431
  }

3432 3433
  for (int32_t j = 0; j < numOfExpr; ++j) {
    int32_t functionId = pCtx[j].functionId;
L
Liu Jicong 已提交
3434 3435 3436 3437 3438 3439 3440 3441 3442
    //    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]);
    //    }
3443
  }
3444
}
3445

L
Liu Jicong 已提交
3446 3447
static void doFinalizeResultImpl(SqlFunctionCtx* pCtx, int32_t numOfExpr) {
  for (int32_t j = 0; j < numOfExpr; ++j) {
3448 3449 3450 3451
    int32_t functionId = pCtx[j].functionId;
    //    if (functionId == FUNC_TAG_DUMMY || functionId == FUNC_TS_DUMMY) {
    //      continue;
    //    }
3452

3453 3454 3455 3456
    //    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 已提交
3457
    //    pCtx[j].fpSet.finalize(&pCtx[j]);
3458 3459
  }
}
3460

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

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

3468 3469 3470
    char* data = colDataGetData(pColInfo, rowIndex);
    memcpy(rowColData[i], data, colDataGetLength(pColInfo, rowIndex));
  }
3471

3472 3473
  return true;
}
3474

3475 3476
static void doMergeImpl(SOperatorInfo* pOperator, int32_t numOfExpr, SSDataBlock* pBlock) {
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
3477

3478
  SqlFunctionCtx* pCtx = pInfo->binfo.pCtx;
L
Liu Jicong 已提交
3479
  for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) {
3480 3481
    pCtx[i].size = 1;
  }
3482

L
Liu Jicong 已提交
3483
  for (int32_t i = 0; i < pBlock->info.rows; ++i) {
3484 3485 3486 3487 3488 3489 3490 3491 3492
    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);
H
Haojun Liao 已提交
3493
        int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput, NULL);
3494
        //        setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows);
3495

3496
        // TODO check for available buffer;
H
Haojun Liao 已提交
3497

3498 3499 3500 3501 3502
        // next group info data
        pInfo->binfo.pRes->info.rows += numOfRows;
        for (int32_t j = 0; j < numOfExpr; ++j) {
          if (pCtx[j].functionId < 0) {
            continue;
3503
          }
3504

H
Haojun Liao 已提交
3505
          pCtx[j].fpSet.process(&pCtx[j]);
3506
        }
3507 3508 3509

        doMergeResultImpl(pInfo, pCtx, numOfExpr, i);
        pInfo->hasGroupVal = saveCurrentTuple(pInfo->groupVal, pInfo->groupInfo, pBlock, i);
H
Haojun Liao 已提交
3510
      }
3511 3512 3513 3514
    }
  }
}

3515 3516
static SSDataBlock* doMerge(SOperatorInfo* pOperator) {
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
L
Liu Jicong 已提交
3517
  SSortHandle*              pHandle = pInfo->pSortHandle;
3518

3519
  SSDataBlock* pDataBlock = createOneDataBlock(pInfo->binfo.pRes, false);
3520
  blockDataEnsureCapacity(pDataBlock, pOperator->resultInfo.capacity);
3521

L
Liu Jicong 已提交
3522
  while (1) {
3523
    blockDataCleanup(pDataBlock);
3524
    while (1) {
H
Haojun Liao 已提交
3525
      STupleHandle* pTupleHandle = tsortNextTuple(pHandle);
3526 3527
      if (pTupleHandle == NULL) {
        break;
3528
      }
3529

3530 3531
      // build datablock for merge for one group
      appendOneRowToDataBlock(pDataBlock, pTupleHandle);
3532
      if (pDataBlock->info.rows >= pOperator->resultInfo.capacity) {
3533 3534
        break;
      }
3535
    }
3536

3537 3538 3539
    if (pDataBlock->info.rows == 0) {
      break;
    }
3540

3541
    setInputDataBlock(pOperator, pInfo->binfo.pCtx, pDataBlock, TSDB_ORDER_ASC, true);
L
Liu Jicong 已提交
3542 3543
    //  updateOutputBuf(&pInfo->binfo, &pAggInfo->bufCapacity, pBlock->info.rows * pAggInfo->resultRowFactor,
    //  pOperator->pRuntimeEnv, true);
3544 3545 3546
    doMergeImpl(pOperator, pOperator->numOfOutput, pDataBlock);
    // flush to tuple store, and after all data have been handled, return to upstream node or sink node
  }
3547

3548
  doFinalizeResultImpl(pInfo->binfo.pCtx, pOperator->numOfOutput);
H
Haojun Liao 已提交
3549
  int32_t numOfRows = getNumOfResult(pInfo->binfo.pCtx, pOperator->numOfOutput, NULL);
3550
  //        setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows);
3551

3552
  // TODO check for available buffer;
3553

3554 3555
  // next group info data
  pInfo->binfo.pRes->info.rows += numOfRows;
L
Liu Jicong 已提交
3556
  return (pInfo->binfo.pRes->info.rows > 0) ? pInfo->binfo.pRes : NULL;
3557
}
3558

3559
static SSDataBlock* doSortedMerge(SOperatorInfo* pOperator) {
3560 3561
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3562 3563
  }

L
Liu Jicong 已提交
3564
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
3565
  SSortedMergeOperatorInfo* pInfo = pOperator->info;
H
Haojun Liao 已提交
3566
  if (pOperator->status == OP_RES_TO_RETURN) {
3567
    return getSortedBlockData(pInfo->pSortHandle, pInfo->binfo.pRes, pOperator->resultInfo.capacity);
3568 3569
  }

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

H
Haojun Liao 已提交
3574
  tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock);
3575

L
Liu Jicong 已提交
3576
  for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
wmmhello's avatar
wmmhello 已提交
3577
    SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
H
Haojun Liao 已提交
3578
    ps->param = pOperator->pDownstream[i];
H
Haojun Liao 已提交
3579
    tsortAddSource(pInfo->pSortHandle, ps);
3580 3581
  }

H
Haojun Liao 已提交
3582
  int32_t code = tsortOpen(pInfo->pSortHandle);
3583
  if (code != TSDB_CODE_SUCCESS) {
3584
    longjmp(pTaskInfo->env, terrno);
3585 3586
  }

H
Haojun Liao 已提交
3587
  pOperator->status = OP_RES_TO_RETURN;
3588
  return doMerge(pOperator);
3589
}
3590

L
Liu Jicong 已提交
3591 3592
static int32_t initGroupCol(SExprInfo* pExprInfo, int32_t numOfCols, SArray* pGroupInfo,
                            SSortedMergeOperatorInfo* pInfo) {
3593 3594
  if (pGroupInfo == NULL || taosArrayGetSize(pGroupInfo) == 0) {
    return 0;
H
Haojun Liao 已提交
3595 3596
  }

3597 3598 3599 3600 3601 3602 3603 3604
  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 已提交
3605 3606
  size_t numOfGroupCol = taosArrayGetSize(pInfo->groupInfo);
  for (int32_t i = 0; i < numOfGroupCol; ++i) {
3607
    SColumn* pCol = taosArrayGet(pGroupInfo, i);
L
Liu Jicong 已提交
3608
    for (int32_t j = 0; j < numOfCols; ++j) {
H
Haojun Liao 已提交
3609
      SExprInfo* pe = &pExprInfo[j];
3610
      if (pe->base.resSchema.slotId == pCol->colId) {
3611 3612
        taosArrayPush(plist, pCol);
        taosArrayPush(pInfo->groupInfo, &j);
H
Haojun Liao 已提交
3613
        len += pCol->bytes;
3614 3615
        break;
      }
H
Haojun Liao 已提交
3616 3617 3618
    }
  }

3619
  ASSERT(taosArrayGetSize(pGroupInfo) == taosArrayGetSize(plist));
H
Haojun Liao 已提交
3620

wafwerar's avatar
wafwerar 已提交
3621
  pInfo->groupVal = taosMemoryCalloc(1, (POINTER_BYTES * numOfGroupCol + len));
3622 3623 3624 3625
  if (pInfo->groupVal == NULL) {
    taosArrayDestroy(plist);
    return TSDB_CODE_OUT_OF_MEMORY;
  }
H
Haojun Liao 已提交
3626

3627
  int32_t offset = 0;
L
Liu Jicong 已提交
3628 3629
  char*   start = (char*)(pInfo->groupVal + (POINTER_BYTES * numOfGroupCol));
  for (int32_t i = 0; i < numOfGroupCol; ++i) {
3630 3631
    pInfo->groupVal[i] = start + offset;
    SColumn* pCol = taosArrayGet(plist, i);
H
Haojun Liao 已提交
3632
    offset += pCol->bytes;
3633
  }
H
Haojun Liao 已提交
3634

3635
  taosArrayDestroy(plist);
H
Haojun Liao 已提交
3636

3637 3638
  return TSDB_CODE_SUCCESS;
}
H
Haojun Liao 已提交
3639

L
Liu Jicong 已提交
3640 3641 3642
SOperatorInfo* createSortedMergeOperatorInfo(SOperatorInfo** downstream, int32_t numOfDownstream, SExprInfo* pExprInfo,
                                             int32_t num, SArray* pSortInfo, SArray* pGroupInfo,
                                             SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
3643
  SSortedMergeOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortedMergeOperatorInfo));
L
Liu Jicong 已提交
3644
  SOperatorInfo*            pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
3645
  if (pInfo == NULL || pOperator == NULL) {
3646
    goto _error;
3647
  }
H
Haojun Liao 已提交
3648

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

3652 3653 3654
  if (pInfo->binfo.pCtx == NULL || pInfo->binfo.pRes == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3655

dengyihao's avatar
dengyihao 已提交
3656
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
3657
  int32_t code = doInitAggInfoSup(&pInfo->aggSup, pInfo->binfo.pCtx, num, keyBufSize, pTaskInfo->id.str);
3658 3659 3660
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
H
Haojun Liao 已提交
3661

H
Haojun Liao 已提交
3662
  setFunctionResultOutput(&pInfo->binfo, &pInfo->aggSup, MAIN_SCAN, pTaskInfo);
H
Haojun Liao 已提交
3663
  code = initGroupCol(pExprInfo, num, pGroupInfo, pInfo);
3664 3665 3666
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
H
Haojun Liao 已提交
3667

L
Liu Jicong 已提交
3668 3669 3670 3671 3672
  //  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 已提交
3673

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

L
Liu Jicong 已提交
3676
  pOperator->name = "SortedMerge";
X
Xiaoyu Wang 已提交
3677
  // pOperator->operatorType = OP_SortedMerge;
3678
  pOperator->blocking = true;
L
Liu Jicong 已提交
3679 3680 3681 3682
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->numOfOutput = num;
  pOperator->pExpr = pExprInfo;
H
Haojun Liao 已提交
3683

L
Liu Jicong 已提交
3684
  pOperator->pTaskInfo = pTaskInfo;
H
Haojun Liao 已提交
3685

3686 3687
  pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doSortedMerge, NULL, NULL, destroySortedMergeOperatorInfo,
                                         NULL, NULL, NULL);
3688 3689 3690
  code = appendDownstream(pOperator, downstream, numOfDownstream);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
3691
  }
H
Haojun Liao 已提交
3692

3693
  return pOperator;
H
Haojun Liao 已提交
3694

L
Liu Jicong 已提交
3695
_error:
3696
  if (pInfo != NULL) {
H
Haojun Liao 已提交
3697
    destroySortedMergeOperatorInfo(pInfo, num);
H
Haojun Liao 已提交
3698 3699
  }

wafwerar's avatar
wafwerar 已提交
3700 3701
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
3702 3703
  terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
  return NULL;
H
Haojun Liao 已提交
3704 3705
}

3706
static SSDataBlock* doSort(SOperatorInfo* pOperator) {
3707 3708 3709 3710
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

L
Liu Jicong 已提交
3711
  SExecTaskInfo*     pTaskInfo = pOperator->pTaskInfo;
H
Haojun Liao 已提交
3712 3713
  SSortOperatorInfo* pInfo = pOperator->info;

H
Haojun Liao 已提交
3714
  if (pOperator->status == OP_RES_TO_RETURN) {
H
Haojun Liao 已提交
3715
    return getSortedBlockData(pInfo->pSortHandle, pInfo->pDataBlock, pInfo->numOfRowsInRes);
H
Haojun Liao 已提交
3716 3717
  }

3718
  int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
dengyihao's avatar
dengyihao 已提交
3719 3720
  pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, pInfo->inputSlotMap, SORT_SINGLESOURCE_SORT,
                                             pInfo->bufPageSize, numOfBufPage, pInfo->pDataBlock, pTaskInfo->id.str);
3721

H
Haojun Liao 已提交
3722
  tsortSetFetchRawDataFp(pInfo->pSortHandle, loadNextDataBlock);
H
Haojun Liao 已提交
3723

wmmhello's avatar
wmmhello 已提交
3724
  SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
H
Haojun Liao 已提交
3725
  ps->param = pOperator->pDownstream[0];
H
Haojun Liao 已提交
3726
  tsortAddSource(pInfo->pSortHandle, ps);
3727

H
Haojun Liao 已提交
3728
  int32_t code = tsortOpen(pInfo->pSortHandle);
3729
  taosMemoryFreeClear(ps);
3730
  if (code != TSDB_CODE_SUCCESS) {
3731
    longjmp(pTaskInfo->env, terrno);
3732
  }
3733

H
Haojun Liao 已提交
3734
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
3735
  return getSortedBlockData(pInfo->pSortHandle, pInfo->pDataBlock, pInfo->numOfRowsInRes);
3736 3737
}

dengyihao's avatar
dengyihao 已提交
3738 3739
SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSDataBlock* pResBlock, SArray* pSortInfo,
                                      SArray* pIndexMap, SExecTaskInfo* pTaskInfo) {
H
Haojun Liao 已提交
3740
  SSortOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSortOperatorInfo));
L
Liu Jicong 已提交
3741
  SOperatorInfo*     pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
dengyihao's avatar
dengyihao 已提交
3742
  int32_t            rowSize = pResBlock->info.rowSize;
3743 3744

  if (pInfo == NULL || pOperator == NULL || rowSize > 100 * 1024 * 1024) {
wafwerar's avatar
wafwerar 已提交
3745 3746
    taosMemoryFreeClear(pInfo);
    taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
3747 3748 3749
    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
    return NULL;
  }
3750

dengyihao's avatar
dengyihao 已提交
3751
  pInfo->bufPageSize = rowSize < 1024 ? 1024 * 2 : rowSize * 2;  // there are headers, so pageSize = rowSize + header
3752

wmmhello's avatar
wmmhello 已提交
3753
  pInfo->sortBufSize = pInfo->bufPageSize * 16;  // TODO dynamic set the available sort buffer
L
Liu Jicong 已提交
3754 3755 3756
  pInfo->numOfRowsInRes = 1024;
  pInfo->pDataBlock = pResBlock;
  pInfo->pSortInfo = pSortInfo;
3757
  pInfo->inputSlotMap = pIndexMap;
H
Haojun Liao 已提交
3758

dengyihao's avatar
dengyihao 已提交
3759
  pOperator->name = "SortOperator";
L
Liu Jicong 已提交
3760
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_SORT;
3761
  pOperator->blocking = true;
dengyihao's avatar
dengyihao 已提交
3762 3763
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
3764

dengyihao's avatar
dengyihao 已提交
3765
  pOperator->pTaskInfo = pTaskInfo;
L
Liu Jicong 已提交
3766 3767
  pOperator->fpSet =
      createOperatorFpSet(operatorDummyOpenFn, doSort, NULL, NULL, destroyOrderOperatorInfo, NULL, NULL, NULL);
3768

3769
  int32_t code = appendDownstream(pOperator, &downstream, 1);
3770
  return pOperator;
H
Haojun Liao 已提交
3771

dengyihao's avatar
dengyihao 已提交
3772
_error:
H
Haojun Liao 已提交
3773 3774 3775 3776
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  taosMemoryFree(pInfo);
  taosMemoryFree(pOperator);
  return NULL;
3777 3778
}

3779 3780
int32_t getTableScanOrder(SOperatorInfo* pOperator) {
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) {
H
Haojun Liao 已提交
3781
    if (pOperator->pDownstream == NULL || pOperator->pDownstream[0] == NULL) {
3782
      return TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3783 3784
    } else {
      return getTableScanOrder(pOperator->pDownstream[0]);
3785 3786 3787 3788 3789 3790
    }
  }

  STableScanInfo* pTableScanInfo = pOperator->info;
  return pTableScanInfo->cond.order;
}
3791 3792

// this is a blocking operator
L
Liu Jicong 已提交
3793
static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
H
Haojun Liao 已提交
3794 3795
  if (OPTR_IS_OPENED(pOperator)) {
    return TSDB_CODE_SUCCESS;
3796 3797
  }

H
Haojun Liao 已提交
3798
  SExecTaskInfo*    pTaskInfo = pOperator->pTaskInfo;
3799
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
3800

dengyihao's avatar
dengyihao 已提交
3801
  SOptrBasicInfo* pInfo = &pAggInfo->binfo;
3802

H
Haojun Liao 已提交
3803
  int32_t        order = TSDB_ORDER_ASC;
H
Haojun Liao 已提交
3804
  SOperatorInfo* downstream = pOperator->pDownstream[0];
3805

H
Haojun Liao 已提交
3806 3807
  bool newgroup = true;
  while (1) {
H
Haojun Liao 已提交
3808
    publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
3809
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
3810
    publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
3811 3812 3813 3814

    if (pBlock == NULL) {
      break;
    }
H
Haojun Liao 已提交
3815 3816 3817
    //    if (pAggInfo->current != NULL) {
    //      setTagValue(pOperator, pAggInfo->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
    //    }
3818

3819 3820
    // there is an scalar expression that needs to be calculated before apply the group aggregation.
    if (pAggInfo->pScalarExprInfo != NULL) {
X
Xiaoyu Wang 已提交
3821 3822
      int32_t code = projectApplyFunctions(pAggInfo->pScalarExprInfo, pBlock, pBlock, pAggInfo->pScalarCtx,
                                           pAggInfo->numOfScalarExpr, NULL);
3823 3824 3825 3826
      if (code != TSDB_CODE_SUCCESS) {
        pTaskInfo->code = code;
        longjmp(pTaskInfo->env, pTaskInfo->code);
      }
3827 3828
    }

3829
    // the pDataBlock are always the same one, no need to call this again
H
Haojun Liao 已提交
3830
    setExecutionContext(pOperator->numOfOutput, pBlock->info.groupId, pTaskInfo, pAggInfo);
3831
    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order, true);
H
Haojun Liao 已提交
3832
    doAggregateImpl(pOperator, 0, pInfo->pCtx);
3833

dengyihao's avatar
dengyihao 已提交
3834
#if 0  // test for encode/decode result info
3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845
    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);
      }
3846
    }
3847
#endif
3848 3849
  }

H
Haojun Liao 已提交
3850 3851 3852
  closeAllResultRows(&pAggInfo->binfo.resultRowInfo);
  finalizeMultiTupleQueryResult(pAggInfo->binfo.pCtx, pOperator->numOfOutput, pAggInfo->aggSup.pResultBuf,
                                &pAggInfo->binfo.resultRowInfo, pAggInfo->binfo.rowCellInfoOffset);
H
Haojun Liao 已提交
3853

3854
  initGroupedResultInfo(&pAggInfo->groupResInfo, pAggInfo->aggSup.pResultRowHashTable, false);
H
Haojun Liao 已提交
3855 3856 3857 3858
  OPTR_SET_OPENED(pOperator);
  return TSDB_CODE_SUCCESS;
}

3859
static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
3860
  SAggOperatorInfo* pAggInfo = pOperator->info;
H
Haojun Liao 已提交
3861 3862 3863 3864 3865 3866
  SOptrBasicInfo*   pInfo = &pAggInfo->binfo;

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

L
Liu Jicong 已提交
3867
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
3868
  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
H
Haojun Liao 已提交
3869 3870 3871 3872
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
    return NULL;
  }

H
Haojun Liao 已提交
3873
  blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
3874
  doBuildResultDatablock(pInfo, &pAggInfo->groupResInfo, pOperator->pExpr, pAggInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
3875 3876 3877
  if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pAggInfo->groupResInfo)) {
    doSetOperatorCompleted(pOperator);
  }
3878

H
Haojun Liao 已提交
3879
  doSetOperatorCompleted(pOperator);
L
Liu Jicong 已提交
3880
  return (blockDataGetNumOfRows(pInfo->pRes) != 0) ? pInfo->pRes : NULL;
3881 3882
}

dengyihao's avatar
dengyihao 已提交
3883 3884
void aggEncodeResultRow(SOperatorInfo* pOperator, SAggSupporter* pSup, SOptrBasicInfo* pInfo, char** result,
                        int32_t* length) {
wmmhello's avatar
wmmhello 已提交
3885
  int32_t size = taosHashGetSize(pSup->pResultRowHashTable);
3886
  size_t  keyLen = sizeof(uint64_t) * 2;  // estimate the key length
wmmhello's avatar
wmmhello 已提交
3887
  int32_t totalSize = sizeof(int32_t) + size * (sizeof(int32_t) + keyLen + sizeof(int32_t) + pSup->resultRowSize);
wafwerar's avatar
wafwerar 已提交
3888
  *result = taosMemoryCalloc(1, totalSize);
L
Liu Jicong 已提交
3889
  if (*result == NULL) {
3890
    longjmp(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
wmmhello's avatar
wmmhello 已提交
3891 3892 3893
  }
  *(int32_t*)(*result) = size;
  int32_t offset = sizeof(int32_t);
3894 3895

  // prepare memory
3896
  SResultRowPosition* pos = &pInfo->resultRowInfo.cur;
dengyihao's avatar
dengyihao 已提交
3897 3898
  void*               pPage = getBufPage(pSup->pResultBuf, pos->pageId);
  SResultRow*         pRow = (SResultRow*)((char*)pPage + pos->offset);
3899 3900 3901
  setBufPageDirty(pPage, true);
  releaseBufPage(pSup->pResultBuf, pPage);

dengyihao's avatar
dengyihao 已提交
3902
  void* pIter = taosHashIterate(pSup->pResultRowHashTable, NULL);
wmmhello's avatar
wmmhello 已提交
3903
  while (pIter) {
dengyihao's avatar
dengyihao 已提交
3904
    void*               key = taosHashGetKey(pIter, &keyLen);
3905
    SResultRowPosition* p1 = (SResultRowPosition*)pIter;
3906

dengyihao's avatar
dengyihao 已提交
3907
    pPage = (SFilePage*)getBufPage(pSup->pResultBuf, p1->pageId);
3908
    pRow = (SResultRow*)((char*)pPage + p1->offset);
3909 3910
    setBufPageDirty(pPage, true);
    releaseBufPage(pSup->pResultBuf, pPage);
wmmhello's avatar
wmmhello 已提交
3911 3912 3913

    // recalculate the result size
    int32_t realTotalSize = offset + sizeof(int32_t) + keyLen + sizeof(int32_t) + pSup->resultRowSize;
L
Liu Jicong 已提交
3914 3915 3916
    if (realTotalSize > totalSize) {
      char* tmp = taosMemoryRealloc(*result, realTotalSize);
      if (tmp == NULL) {
wmmhello's avatar
wmmhello 已提交
3917
        terrno = TSDB_CODE_OUT_OF_MEMORY;
wafwerar's avatar
wafwerar 已提交
3918
        taosMemoryFree(*result);
wmmhello's avatar
wmmhello 已提交
3919
        *result = NULL;
3920
        longjmp(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
L
Liu Jicong 已提交
3921
      } else {
wmmhello's avatar
wmmhello 已提交
3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933
        *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);
3934
    memcpy(*result + offset, pRow, pSup->resultRowSize);
wmmhello's avatar
wmmhello 已提交
3935 3936 3937 3938 3939
    offset += pSup->resultRowSize;

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

L
Liu Jicong 已提交
3940
  if (length) {
wmmhello's avatar
wmmhello 已提交
3941 3942 3943 3944 3945
    *length = offset;
  }
  return;
}

dengyihao's avatar
dengyihao 已提交
3946 3947
bool aggDecodeResultRow(SOperatorInfo* pOperator, SAggSupporter* pSup, SOptrBasicInfo* pInfo, char* result,
                        int32_t length) {
L
Liu Jicong 已提交
3948
  if (!result || length <= 0) {
wmmhello's avatar
wmmhello 已提交
3949 3950 3951 3952 3953 3954 3955
    return false;
  }

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

  int32_t offset = sizeof(int32_t);
L
Liu Jicong 已提交
3956
  while (count-- > 0 && length > offset) {
wmmhello's avatar
wmmhello 已提交
3957 3958 3959
    int32_t keyLen = *(int32_t*)(result + offset);
    offset += sizeof(int32_t);

L
Liu Jicong 已提交
3960 3961 3962
    uint64_t    tableGroupId = *(uint64_t*)(result + offset);
    SResultRow* resultRow = getNewResultRow_rv(pSup->pResultBuf, tableGroupId, pSup->resultRowSize);
    if (!resultRow) {
3963
      longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3964
    }
3965

wmmhello's avatar
wmmhello 已提交
3966
    // add a new result set for a new group
3967 3968
    SResultRowPosition pos = {.pageId = resultRow->pageId, .offset = resultRow->offset};
    taosHashPut(pSup->pResultRowHashTable, result + offset, keyLen, &pos, sizeof(SResultRowPosition));
wmmhello's avatar
wmmhello 已提交
3969 3970 3971

    offset += keyLen;
    int32_t valueLen = *(int32_t*)(result + offset);
L
Liu Jicong 已提交
3972
    if (valueLen != pSup->resultRowSize) {
3973
      longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3974 3975 3976 3977 3978 3979 3980 3981 3982 3983
    }
    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);
3984
    prepareResultListBuffer(&pInfo->resultRowInfo, pOperator->pTaskInfo->env);
dengyihao's avatar
dengyihao 已提交
3985
    //    pInfo->resultRowInfo.cur = pInfo->resultRowInfo.size;
L
Liu Jicong 已提交
3986 3987
    //    pInfo->resultRowInfo.pPosition[pInfo->resultRowInfo.size++] =
    //        (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
dengyihao's avatar
dengyihao 已提交
3988
    pInfo->resultRowInfo.cur = (SResultRowPosition){.pageId = resultRow->pageId, .offset = resultRow->offset};
wmmhello's avatar
wmmhello 已提交
3989 3990
  }

L
Liu Jicong 已提交
3991
  if (offset != length) {
3992
    longjmp(pOperator->pTaskInfo->env, TSDB_CODE_TSC_INVALID_INPUT);
wmmhello's avatar
wmmhello 已提交
3993 3994 3995 3996
  }
  return true;
}

3997 3998
enum {
  PROJECT_RETRIEVE_CONTINUE = 0x1,
L
Liu Jicong 已提交
3999
  PROJECT_RETRIEVE_DONE = 0x2,
4000 4001 4002 4003 4004
};

static int32_t handleLimitOffset(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
  SProjectOperatorInfo* pProjectInfo = pOperator->info;
  SOptrBasicInfo*       pInfo = &pProjectInfo->binfo;
L
Liu Jicong 已提交
4005
  SSDataBlock*          pRes = pInfo->pRes;
4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053

  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;
  }

4054 4055 4056
  // 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);
4057 4058 4059 4060 4061

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

4062
    return PROJECT_RETRIEVE_DONE;
4063
  }
4064

4065
  // todo optimize performance
4066 4067
  // 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 已提交
4068 4069
  if (pRes->info.rows >= pOperator->resultInfo.threshold || pProjectInfo->slimit.offset != -1 ||
      pProjectInfo->slimit.limit != -1) {
4070
    return PROJECT_RETRIEVE_DONE;
L
Liu Jicong 已提交
4071
  } else {  // not full enough, continue to accumulate the output data in the buffer.
4072 4073 4074 4075
    return PROJECT_RETRIEVE_CONTINUE;
  }
}

4076
static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
4077
  SProjectOperatorInfo* pProjectInfo = pOperator->info;
L
Liu Jicong 已提交
4078
  SOptrBasicInfo*       pInfo = &pProjectInfo->binfo;
4079 4080

  SSDataBlock* pRes = pInfo->pRes;
4081
  blockDataCleanup(pRes);
4082 4083 4084 4085

  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }
dengyihao's avatar
dengyihao 已提交
4086

H
Haojun Liao 已提交
4087
#if 0
4088 4089 4090 4091 4092 4093
  if (pProjectInfo->existDataBlock) {  // TODO refactor
    SSDataBlock* pBlock = pProjectInfo->existDataBlock;
    pProjectInfo->existDataBlock = NULL;
    *newgroup = true;

    // todo dynamic set tags
L
Liu Jicong 已提交
4094 4095 4096
    //    if (pTableQueryInfo != NULL) {
    //      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    //    }
4097 4098

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

H
Haojun Liao 已提交
4101
    blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
4102
    projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfOutput);
L
Liu Jicong 已提交
4103
    if (pRes->info.rows >= pProjectInfo->binfo.capacity * 0.8) {
4104 4105 4106 4107 4108
      copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfOutput);
      resetResultRowEntryResult(pInfo->pCtx, pOperator->numOfOutput);
      return pRes;
    }
  }
H
Haojun Liao 已提交
4109
#endif
4110

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

L
Liu Jicong 已提交
4113
  while (1) {
H
Haojun Liao 已提交
4114
    // The downstream exec may change the value of the newgroup, so use a local variable instead.
H
Haojun Liao 已提交
4115
    publishOperatorProfEvent(downstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
4116
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
H
Haojun Liao 已提交
4117
    publishOperatorProfEvent(downstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
4118 4119

    if (pBlock == NULL) {
4120
      setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
4121 4122 4123 4124
      break;
    }

    // Return result of the previous group in the firstly.
4125
    if (false) {
4126 4127 4128
      if (pRes->info.rows > 0) {
        pProjectInfo->existDataBlock = pBlock;
        break;
L
Liu Jicong 已提交
4129
      } else {  // init output buffer for a new group data
4130 4131 4132 4133 4134
        initCtxOutputBuffer(pInfo->pCtx, pOperator->numOfOutput);
      }
    }

    // todo dynamic set tags
H
Haojun Liao 已提交
4135 4136 4137 4138
    //    STableQueryInfo* pTableQueryInfo = pRuntimeEnv->current;
    //    if (pTableQueryInfo != NULL) {
    //      setTagValue(pOperator, pTableQueryInfo->pTable, pInfo->pCtx, pOperator->numOfOutput);
    //    }
4139 4140

    // the pDataBlock are always the same one, no need to call this again
4141 4142 4143
    int32_t order = getTableScanOrder(pOperator->pDownstream[0]);

    setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order, false);
4144 4145
    blockDataEnsureCapacity(pInfo->pRes, pInfo->pRes->info.rows + pBlock->info.rows);

dengyihao's avatar
dengyihao 已提交
4146 4147
    projectApplyFunctions(pOperator->pExpr, pInfo->pRes, pBlock, pInfo->pCtx, pOperator->numOfOutput,
                          pProjectInfo->pPseudoColInfo);
H
Haojun Liao 已提交
4148

4149 4150
    int32_t status = handleLimitOffset(pOperator, pBlock);
    if (status == PROJECT_RETRIEVE_CONTINUE) {
H
Haojun Liao 已提交
4151
      continue;
L
Liu Jicong 已提交
4152
    } else if (status == PROJECT_RETRIEVE_DONE) {
4153 4154 4155
      break;
    }
  }
dengyihao's avatar
dengyihao 已提交
4156

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

L
Liu Jicong 已提交
4159 4160
  //  copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfOutput);
  return (pInfo->pRes->info.rows > 0) ? pInfo->pRes : NULL;
4161 4162
}

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

L
Liu Jicong 已提交
4167 4168
  int64_t ekey = Q_STATUS_EQUAL(pTaskInfo->status, TASK_COMPLETED) ? pTaskInfo->window.ekey
                                                                   : pInfo->existNewGroupBlock->info.window.ekey;
4169 4170
  taosResetFillInfo(pInfo->pFillInfo, getFillInfoStart(pInfo->pFillInfo));

4171
  taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey);
4172 4173
  taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock);

4174
  doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pResultInfo->capacity);
4175 4176 4177 4178
  pInfo->existNewGroupBlock = NULL;
  *newgroup = true;
}

L
Liu Jicong 已提交
4179 4180
static void doHandleRemainBlockFromNewGroup(SFillOperatorInfo* pInfo, SResultInfo* pResultInfo, bool* newgroup,
                                            SExecTaskInfo* pTaskInfo) {
4181 4182
  if (taosFillHasMoreResults(pInfo->pFillInfo)) {
    *newgroup = false;
4183
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pResultInfo->capacity);
H
Haojun Liao 已提交
4184
    if (pInfo->pRes->info.rows > pResultInfo->threshold || (!pInfo->multigroupResult)) {
4185 4186 4187 4188 4189 4190
      return;
    }
  }

  // handle the cached new group data block
  if (pInfo->existNewGroupBlock) {
4191
    doHandleRemainBlockForNewGroupImpl(pInfo, pResultInfo, newgroup, pTaskInfo);
4192 4193 4194
  }
}

4195
static SSDataBlock* doFill(SOperatorInfo* pOperator) {
L
Liu Jicong 已提交
4196 4197
  SFillOperatorInfo* pInfo = pOperator->info;
  SExecTaskInfo*     pTaskInfo = pOperator->pTaskInfo;
4198

H
Haojun Liao 已提交
4199
  SResultInfo* pResultInfo = &pOperator->resultInfo;
4200 4201 4202
  SSDataBlock* pResBlock = pInfo->pRes;

  blockDataCleanup(pResBlock);
4203 4204 4205 4206
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

4207 4208 4209
  // todo handle different group data interpolation
  bool n = false;
  bool *newgroup = &n;
4210
  doHandleRemainBlockFromNewGroup(pInfo, pResultInfo, newgroup, pTaskInfo);
4211 4212
  if (pResBlock->info.rows > pResultInfo->threshold || (!pInfo->multigroupResult && pResBlock->info.rows > 0)) {
    return pResBlock;
H
Haojun Liao 已提交
4213
  }
4214

H
Haojun Liao 已提交
4215
  SOperatorInfo* pDownstream = pOperator->pDownstream[0];
L
Liu Jicong 已提交
4216
  while (1) {
H
Haojun Liao 已提交
4217
    publishOperatorProfEvent(pDownstream, QUERY_PROF_BEFORE_OPERATOR_EXEC);
4218
    SSDataBlock* pBlock = pDownstream->fpSet.getNextFn(pDownstream);
H
Haojun Liao 已提交
4219
    publishOperatorProfEvent(pDownstream, QUERY_PROF_AFTER_OPERATOR_EXEC);
4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230

    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
4231
      taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
4232 4233 4234 4235 4236 4237 4238
    } else {
      if (pBlock == NULL) {
        if (pInfo->totalInputRows == 0) {
          pOperator->status = OP_EXEC_DONE;
          return NULL;
        }

4239
        taosFillSetStartInfo(pInfo->pFillInfo, 0, pTaskInfo->window.ekey);
4240 4241 4242 4243 4244 4245 4246
      } else {
        pInfo->totalInputRows += pBlock->info.rows;
        taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey);
        taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock);
      }
    }

4247 4248
    blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
    doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pResBlock, pOperator->resultInfo.capacity);
4249 4250

    // current group has no more result to return
4251
    if (pResBlock->info.rows > 0) {
4252 4253
      // 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
4254 4255
      if (pResBlock->info.rows > pResultInfo->threshold || pBlock == NULL || (!pInfo->multigroupResult)) {
        return pResBlock;
4256 4257
      }

4258
      doHandleRemainBlockFromNewGroup(pInfo, pResultInfo, newgroup, pTaskInfo);
4259 4260
      if (pResBlock->info.rows > pOperator->resultInfo.threshold || pBlock == NULL) {
        return pResBlock;
4261 4262 4263
      }
    } else if (pInfo->existNewGroupBlock) {  // try next group
      assert(pBlock != NULL);
4264
      doHandleRemainBlockForNewGroupImpl(pInfo, pResultInfo, newgroup, pTaskInfo);
4265 4266
      if (pResBlock->info.rows > pResultInfo->threshold) {
        return pResBlock;
4267 4268 4269 4270 4271 4272 4273 4274
      }
    } else {
      return NULL;
    }
  }
}

// todo set the attribute of query scan count
H
Haojun Liao 已提交
4275
static int32_t getNumOfScanTimes(STaskAttr* pQueryAttr) {
L
Liu Jicong 已提交
4276
  for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290
    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;
  }

4291 4292
  if (pOperator->fpSet.closeFn != NULL) {
    pOperator->fpSet.closeFn(pOperator->info, pOperator->numOfOutput);
4293 4294
  }

H
Haojun Liao 已提交
4295
  if (pOperator->pDownstream != NULL) {
L
Liu Jicong 已提交
4296
    for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) {
H
Haojun Liao 已提交
4297
      destroyOperatorInfo(pOperator->pDownstream[i]);
4298 4299
    }

wafwerar's avatar
wafwerar 已提交
4300
    taosMemoryFreeClear(pOperator->pDownstream);
H
Haojun Liao 已提交
4301
    pOperator->numOfDownstream = 0;
4302 4303
  }

wafwerar's avatar
wafwerar 已提交
4304 4305
  taosMemoryFreeClear(pOperator->info);
  taosMemoryFreeClear(pOperator);
4306 4307
}

dengyihao's avatar
dengyihao 已提交
4308 4309
int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize,
                         const char* pKey) {
4310 4311
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);

dengyihao's avatar
dengyihao 已提交
4312 4313
  pAggSup->resultRowSize = getResultRowSize(pCtx, numOfOutput);
  pAggSup->keyBuf = taosMemoryCalloc(1, keyBufSize + POINTER_BYTES + sizeof(int64_t));
4314
  pAggSup->pResultRowHashTable = taosHashInit(10, hashFn, true, HASH_NO_LOCK);
L
Liu Jicong 已提交
4315 4316
  //  pAggSup->pResultRowListSet = taosHashInit(100, hashFn, false, HASH_NO_LOCK);
  //  pAggSup->pResultRowArrayList = taosArrayInit(10, sizeof(SResultRowCell));
4317

4318
  if (pAggSup->keyBuf == NULL /*|| pAggSup->pResultRowArrayList == NULL || pAggSup->pResultRowListSet == NULL*/ ||
4319
      pAggSup->pResultRowHashTable == NULL) {
4320 4321 4322
    return TSDB_CODE_OUT_OF_MEMORY;
  }

H
Haojun Liao 已提交
4323 4324 4325 4326 4327
  int32_t code = createDiskbasedBuf(&pAggSup->pResultBuf, 4096, 4096 * 256, pKey, "/tmp/");
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }

4328 4329 4330
  return TSDB_CODE_SUCCESS;
}

4331
void cleanupAggSup(SAggSupporter* pAggSup) {
wafwerar's avatar
wafwerar 已提交
4332
  taosMemoryFreeClear(pAggSup->keyBuf);
4333
  taosHashCleanup(pAggSup->pResultRowHashTable);
H
Haojun Liao 已提交
4334
  destroyDiskbasedBuf(pAggSup->pResultBuf);
4335 4336
}

H
Haojun Liao 已提交
4337
int32_t initAggInfo(SOptrBasicInfo* pBasicInfo, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols,
4338
                    SSDataBlock* pResultBlock, size_t keyBufSize, const char* pkey) {
4339
  pBasicInfo->pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pBasicInfo->rowCellInfoOffset);
H
Haojun Liao 已提交
4340 4341
  pBasicInfo->pRes = pResultBlock;

4342
  doInitAggInfoSup(pAggSup, pBasicInfo->pCtx, numOfCols, keyBufSize, pkey);
4343

L
Liu Jicong 已提交
4344
  for (int32_t i = 0; i < numOfCols; ++i) {
4345 4346 4347
    pBasicInfo->pCtx[i].pBuf = pAggSup->pResultBuf;
  }

4348
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
4349 4350
}

4351 4352 4353 4354 4355 4356 4357 4358 4359
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 已提交
4360
static STableQueryInfo* initTableQueryInfo(const STableGroupInfo* pTableGroupInfo) {
L
Liu Jicong 已提交
4361 4362 4363 4364
  if (pTableGroupInfo->numOfTables == 0) {
    return NULL;
  }

wafwerar's avatar
wafwerar 已提交
4365
  STableQueryInfo* pTableQueryInfo = taosMemoryCalloc(pTableGroupInfo->numOfTables, sizeof(STableQueryInfo));
H
Haojun Liao 已提交
4366 4367
  if (pTableQueryInfo == NULL) {
    return NULL;
H
Haojun Liao 已提交
4368
  }
H
Haojun Liao 已提交
4369 4370

  int32_t index = 0;
L
Liu Jicong 已提交
4371
  for (int32_t i = 0; i < taosArrayGetSize(pTableGroupInfo->pGroupList); ++i) {
H
Haojun Liao 已提交
4372
    SArray* pa = taosArrayGetP(pTableGroupInfo->pGroupList, i);
L
Liu Jicong 已提交
4373
    for (int32_t j = 0; j < taosArrayGetSize(pa); ++j) {
H
Haojun Liao 已提交
4374 4375
      STableKeyInfo* pk = taosArrayGet(pa, j);

H
Haojun Liao 已提交
4376
      STableQueryInfo* pTQueryInfo = &pTableQueryInfo[index++];
dengyihao's avatar
dengyihao 已提交
4377
      //      pTQueryInfo->uid = pk->uid;
L
Liu Jicong 已提交
4378
      pTQueryInfo->lastKey = pk->lastKey;
dengyihao's avatar
dengyihao 已提交
4379
      //      pTQueryInfo->groupIndex = i;
H
Haojun Liao 已提交
4380 4381
    }
  }
H
Haojun Liao 已提交
4382 4383

  STimeWindow win = {0, INT64_MAX};
4384
  createTableQueryInfo(pTableQueryInfo, win);
H
Haojun Liao 已提交
4385
  return pTableQueryInfo;
H
Haojun Liao 已提交
4386 4387
}

L
Liu Jicong 已提交
4388
SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t numOfCols,
4389
                                           SSDataBlock* pResultBlock, SExprInfo* pScalarExprInfo,
L
Liu Jicong 已提交
4390 4391
                                           int32_t numOfScalarExpr, SExecTaskInfo* pTaskInfo,
                                           const STableGroupInfo* pTableGroupInfo) {
wafwerar's avatar
wafwerar 已提交
4392
  SAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAggOperatorInfo));
L
Liu Jicong 已提交
4393
  SOperatorInfo*    pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4394 4395 4396
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
4397

H
Haojun Liao 已提交
4398
  int32_t numOfRows = 1;
dengyihao's avatar
dengyihao 已提交
4399
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
4400 4401

  initResultSizeInfo(pOperator, numOfRows);
dengyihao's avatar
dengyihao 已提交
4402 4403
  int32_t code =
      initAggInfo(&pInfo->binfo, &pInfo->aggSup, pExprInfo, numOfCols, pResultBlock, keyBufSize, pTaskInfo->id.str);
H
Haojun Liao 已提交
4404
  pInfo->pTableQueryInfo = initTableQueryInfo(pTableGroupInfo);
L
Liu Jicong 已提交
4405
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4406 4407
    goto _error;
  }
H
Haojun Liao 已提交
4408

H
Haojun Liao 已提交
4409 4410 4411 4412 4413 4414 4415
  pOperator->resultInfo.capacity = 4096;
  pOperator->resultInfo.threshold = 4096 * 0.75;

  int32_t numOfGroup = 10;  // todo replaced with true value
  pInfo->groupId = INT32_MIN;
  initResultRowInfo(&pInfo->binfo.resultRowInfo, numOfGroup);

4416 4417
  pInfo->pScalarExprInfo = pScalarExprInfo;
  pInfo->numOfScalarExpr = numOfScalarExpr;
4418 4419 4420
  if (pInfo->pScalarExprInfo != NULL) {
    pInfo->pScalarCtx = createSqlFunctionCtx(pScalarExprInfo, numOfCols, &pInfo->rowCellInfoOffset);
  }
4421

dengyihao's avatar
dengyihao 已提交
4422
  pOperator->name = "TableAggregate";
X
Xiaoyu Wang 已提交
4423
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_AGG;
4424
  pOperator->blocking = true;
dengyihao's avatar
dengyihao 已提交
4425 4426 4427 4428 4429
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->pExpr = pExprInfo;
  pOperator->numOfOutput = numOfCols;
  pOperator->pTaskInfo = pTaskInfo;
H
Haojun Liao 已提交
4430

4431 4432
  pOperator->fpSet = createOperatorFpSet(doOpenAggregateOptr, getAggregateResult, NULL, NULL, destroyAggOperatorInfo,
                                         aggEncodeResultRow, aggDecodeResultRow, NULL);
H
Haojun Liao 已提交
4433 4434 4435 4436 4437

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

  return pOperator;
L
Liu Jicong 已提交
4440
_error:
H
Haojun Liao 已提交
4441
  destroyAggOperatorInfo(pInfo, numOfCols);
wafwerar's avatar
wafwerar 已提交
4442 4443
  taosMemoryFreeClear(pInfo);
  taosMemoryFreeClear(pOperator);
H
Haojun Liao 已提交
4444 4445
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  return NULL;
4446 4447
}

H
Haojun Liao 已提交
4448
void doDestroyBasicInfo(SOptrBasicInfo* pInfo, int32_t numOfOutput) {
4449 4450
  assert(pInfo != NULL);

4451
  destroySqlFunctionCtx(pInfo->pCtx, numOfOutput);
wafwerar's avatar
wafwerar 已提交
4452
  taosMemoryFreeClear(pInfo->rowCellInfoOffset);
4453 4454

  cleanupResultRowInfo(&pInfo->resultRowInfo);
H
Haojun Liao 已提交
4455
  pInfo->pRes = blockDataDestroy(pInfo->pRes);
4456 4457
}

H
Haojun Liao 已提交
4458
void destroyBasicOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4459
  SOptrBasicInfo* pInfo = (SOptrBasicInfo*)param;
4460 4461
  doDestroyBasicInfo(pInfo, numOfOutput);
}
H
Haojun Liao 已提交
4462 4463

void destroyAggOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4464
  SAggOperatorInfo* pInfo = (SAggOperatorInfo*)param;
4465 4466
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}
4467

H
Haojun Liao 已提交
4468
void destroySFillOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4469
  SFillOperatorInfo* pInfo = (SFillOperatorInfo*)param;
4470
  pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo);
H
Haojun Liao 已提交
4471
  pInfo->pRes = blockDataDestroy(pInfo->pRes);
wafwerar's avatar
wafwerar 已提交
4472
  taosMemoryFreeClear(pInfo->p);
4473 4474
}

H
Haojun Liao 已提交
4475
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4476
  SProjectOperatorInfo* pInfo = (SProjectOperatorInfo*)param;
4477 4478 4479
  doDestroyBasicInfo(&pInfo->binfo, numOfOutput);
}

H
Haojun Liao 已提交
4480
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4481
  SSortOperatorInfo* pInfo = (SSortOperatorInfo*)param;
H
Haojun Liao 已提交
4482 4483
  pInfo->pDataBlock = blockDataDestroy(pInfo->pDataBlock);

H
Haojun Liao 已提交
4484
  taosArrayDestroy(pInfo->pSortInfo);
4485
  taosArrayDestroy(pInfo->inputSlotMap);
4486 4487
}

H
Haojun Liao 已提交
4488
void destroyExchangeOperatorInfo(void* param, int32_t numOfOutput) {
L
Liu Jicong 已提交
4489
  SExchangeInfo* pExInfo = (SExchangeInfo*)param;
H
Haojun Liao 已提交
4490 4491 4492 4493 4494 4495 4496 4497 4498
  taosArrayDestroy(pExInfo->pSources);
  taosArrayDestroy(pExInfo->pSourceDataInfo);
  if (pExInfo->pResult != NULL) {
    blockDataDestroy(pExInfo->pResult);
  }

  tsem_destroy(&pExInfo->ready);
}

H
Haojun Liao 已提交
4499 4500
static SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols) {
  SArray* pList = taosArrayInit(4, sizeof(int32_t));
dengyihao's avatar
dengyihao 已提交
4501
  for (int32_t i = 0; i < numOfCols; ++i) {
H
Haojun Liao 已提交
4502 4503 4504 4505 4506 4507 4508 4509
    if (fmIsPseudoColumnFunc(pCtx[i].functionId)) {
      taosArrayPush(pList, &i);
    }
  }

  return pList;
}

L
Liu Jicong 已提交
4510
SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExprInfo, int32_t num,
dengyihao's avatar
dengyihao 已提交
4511 4512
                                         SSDataBlock* pResBlock, SLimit* pLimit, SLimit* pSlimit,
                                         SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
4513
  SProjectOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SProjectOperatorInfo));
L
Liu Jicong 已提交
4514
  SOperatorInfo*        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4515 4516 4517
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
4518

dengyihao's avatar
dengyihao 已提交
4519 4520 4521
  pInfo->limit = *pLimit;
  pInfo->slimit = *pSlimit;
  pInfo->curOffset = pLimit->offset;
H
Haojun Liao 已提交
4522 4523
  pInfo->curSOffset = pSlimit->offset;

H
Haojun Liao 已提交
4524
  pInfo->binfo.pRes = pResBlock;
H
Haojun Liao 已提交
4525 4526 4527

  int32_t numOfCols = num;
  int32_t numOfRows = 4096;
dengyihao's avatar
dengyihao 已提交
4528
  size_t  keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
4529 4530 4531

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

dengyihao's avatar
dengyihao 已提交
4535
  pOperator->name = "ProjectOperator";
H
Haojun Liao 已提交
4536
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_PROJECT;
4537
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
4538 4539 4540 4541
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;
  pOperator->pExpr = pExprInfo;
  pOperator->numOfOutput = num;
4542

L
Liu Jicong 已提交
4543 4544
  pOperator->fpSet = createOperatorFpSet(operatorDummyOpenFn, doProjectOperation, NULL, NULL,
                                         destroyProjectOperatorInfo, NULL, NULL, NULL);
L
Liu Jicong 已提交
4545 4546

  pOperator->pTaskInfo = pTaskInfo;
4547
  int32_t code = appendDownstream(pOperator, &downstream, 1);
H
Haojun Liao 已提交
4548
  if (code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
4549 4550
    goto _error;
  }
4551 4552

  return pOperator;
H
Haojun Liao 已提交
4553

L
Liu Jicong 已提交
4554
_error:
H
Haojun Liao 已提交
4555 4556
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  return NULL;
4557 4558
}

4559
static int32_t initFillInfo(SFillOperatorInfo* pInfo, SExprInfo* pExpr, int32_t numOfCols, SNodeListNode* pValNode,
L
Liu Jicong 已提交
4560
                            STimeWindow win, int32_t capacity, const char* id, SInterval* pInterval, int32_t fillType) {
4561
  SFillColInfo* pColInfo = createFillColInfo(pExpr, numOfCols, pValNode);
H
Haojun Liao 已提交
4562 4563

  STimeWindow w = TSWINDOW_INITIALIZER;
4564
  getAlignQueryTimeWindow(pInterval, pInterval->precision, win.skey, &w);
H
Haojun Liao 已提交
4565 4566

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

wafwerar's avatar
wafwerar 已提交
4569
  pInfo->p = taosMemoryCalloc(numOfCols, POINTER_BYTES);
H
Haojun Liao 已提交
4570 4571 4572 4573 4574 4575 4576
  if (pInfo->pFillInfo == NULL || pInfo->p == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  } else {
    return TSDB_CODE_SUCCESS;
  }
}

L
Liu Jicong 已提交
4577
SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfCols,
4578
                                      SInterval* pInterval, STimeWindow* pWindow, SSDataBlock* pResBlock, int32_t fillType, SNodeListNode* pValueNode,
L
Liu Jicong 已提交
4579
                                      bool multigroupResult, SExecTaskInfo* pTaskInfo) {
wafwerar's avatar
wafwerar 已提交
4580
  SFillOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SFillOperatorInfo));
L
Liu Jicong 已提交
4581
  SOperatorInfo*     pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
H
Haojun Liao 已提交
4582

L
Liu Jicong 已提交
4583
  pInfo->pRes = pResBlock;
4584 4585
  pInfo->multigroupResult = multigroupResult;

4586 4587
  int32_t type = TSDB_FILL_NONE;
  switch (fillType) {
dengyihao's avatar
dengyihao 已提交
4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605
    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;
4606 4607 4608 4609
    default:
      type = TSDB_FILL_NONE;
  }

H
Haojun Liao 已提交
4610
  SResultInfo* pResultInfo = &pOperator->resultInfo;
4611 4612
  initResultSizeInfo(pOperator, 4096);

4613
  int32_t code = initFillInfo(pInfo, pExpr, numOfCols, pValueNode, *pWindow, pResultInfo->capacity,
4614
                              pTaskInfo->id.str, pInterval, type);
4615 4616 4617
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4618

dengyihao's avatar
dengyihao 已提交
4619
  pOperator->name = "FillOperator";
4620
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
4621
  pOperator->status = OP_NOT_OPENED;
4622
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_FILL;
dengyihao's avatar
dengyihao 已提交
4623 4624 4625
  pOperator->pExpr = pExpr;
  pOperator->numOfOutput = numOfCols;
  pOperator->info = pInfo;
H
Haojun Liao 已提交
4626

L
Liu Jicong 已提交
4627 4628
  pOperator->fpSet =
      createOperatorFpSet(operatorDummyOpenFn, doFill, NULL, NULL, destroySFillOperatorInfo, NULL, NULL, NULL);
4629
  pOperator->pTaskInfo = pTaskInfo;
4630
  code = appendDownstream(pOperator, &downstream, 1);
4631
  return pOperator;
H
Haojun Liao 已提交
4632

L
Liu Jicong 已提交
4633
_error:
wafwerar's avatar
wafwerar 已提交
4634 4635
  taosMemoryFreeClear(pOperator);
  taosMemoryFreeClear(pInfo);
H
Haojun Liao 已提交
4636
  return NULL;
4637 4638
}

L
Liu Jicong 已提交
4639
static int32_t getColumnIndexInSource(SQueriedTableInfo* pTableInfo, SExprBasicInfo* pExpr, SColumnInfo* pTagCols) {
4640 4641
  int32_t j = 0;

H
Haojun Liao 已提交
4642 4643
  if (TSDB_COL_IS_TAG(pExpr->pParam[0].pCol->type)) {
    if (pExpr->pParam[0].pCol->colId == TSDB_TBNAME_COLUMN_INDEX) {
4644 4645 4646
      return TSDB_TBNAME_COLUMN_INDEX;
    }

L
Liu Jicong 已提交
4647
    while (j < pTableInfo->numOfTags) {
H
Haojun Liao 已提交
4648
      if (pExpr->pParam[0].pCol->colId == pTagCols[j].colId) {
4649 4650 4651 4652 4653 4654
        return j;
      }

      j += 1;
    }

4655
  } /*else if (TSDB_COL_IS_UD_COL(pExpr->colInfo.flag)) {  // user specified column data
4656 4657 4658 4659 4660 4661 4662 4663 4664
    return TSDB_UD_COLUMN_INDEX;
  } else {
    while (j < pTableInfo->numOfCols) {
      if (pExpr->colInfo.colId == pTableInfo->colList[j].colId) {
        return j;
      }

      j += 1;
    }
4665
  }*/
4666 4667 4668 4669

  return INT32_MIN;  // return a less than TSDB_TBNAME_COLUMN_INDEX value
}

L
Liu Jicong 已提交
4670
bool validateExprColumnInfo(SQueriedTableInfo* pTableInfo, SExprBasicInfo* pExpr, SColumnInfo* pTagCols) {
4671 4672 4673 4674
  int32_t j = getColumnIndexInSource(pTableInfo, pExpr, pTagCols);
  return j != INT32_MIN;
}

L
Liu Jicong 已提交
4675 4676
static SResSchema createResSchema(int32_t type, int32_t bytes, int32_t slotId, int32_t scale, int32_t precision,
                                  const char* name) {
H
Haojun Liao 已提交
4677
  SResSchema s = {0};
dengyihao's avatar
dengyihao 已提交
4678 4679 4680 4681
  s.scale = scale;
  s.type = type;
  s.bytes = bytes;
  s.slotId = slotId;
H
Haojun Liao 已提交
4682
  s.precision = precision;
H
Haojun Liao 已提交
4683 4684 4685 4686
  strncpy(s.name, name, tListLen(s.name));

  return s;
}
H
Haojun Liao 已提交
4687

H
Haojun Liao 已提交
4688 4689 4690 4691 4692 4693 4694
static SColumn* createColumn(int32_t blockId, int32_t slotId, SDataType* pType) {
  SColumn* pCol = taosMemoryCalloc(1, sizeof(SColumn));
  if (pCol == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

dengyihao's avatar
dengyihao 已提交
4695 4696 4697 4698 4699
  pCol->slotId = slotId;
  pCol->bytes = pType->bytes;
  pCol->type = pType->type;
  pCol->scale = pType->scale;
  pCol->precision = pType->precision;
H
Haojun Liao 已提交
4700 4701 4702 4703 4704
  pCol->dataBlockId = blockId;

  return pCol;
}

H
Haojun Liao 已提交
4705
SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs) {
H
Haojun Liao 已提交
4706
  int32_t numOfFuncs = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
4707 4708 4709 4710
  int32_t numOfGroupKeys = 0;
  if (pGroupKeys != NULL) {
    numOfGroupKeys = LIST_LENGTH(pGroupKeys);
  }
H
Haojun Liao 已提交
4711

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

L
Liu Jicong 已提交
4715
  for (int32_t i = 0; i < (*numOfExprs); ++i) {
H
Haojun Liao 已提交
4716 4717 4718 4719 4720 4721
    STargetNode* pTargetNode = NULL;
    if (i < numOfFuncs) {
      pTargetNode = (STargetNode*)nodesListGetNode(pNodeList, i);
    } else {
      pTargetNode = (STargetNode*)nodesListGetNode(pGroupKeys, i - numOfFuncs);
    }
H
Haojun Liao 已提交
4722

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

wafwerar's avatar
wafwerar 已提交
4725
    pExp->pExpr = taosMemoryCalloc(1, sizeof(tExprNode));
H
Haojun Liao 已提交
4726
    pExp->pExpr->_function.num = 1;
H
Haojun Liao 已提交
4727
    pExp->pExpr->_function.functionId = -1;
H
Haojun Liao 已提交
4728

4729
    int32_t type = nodeType(pTargetNode->pExpr);
H
Haojun Liao 已提交
4730
    // it is a project query, or group by column
4731
    if (type == QUERY_NODE_COLUMN) {
H
Haojun Liao 已提交
4732
      pExp->pExpr->nodeType = QUERY_NODE_COLUMN;
L
Liu Jicong 已提交
4733
      SColumnNode* pColNode = (SColumnNode*)pTargetNode->pExpr;
H
Haojun Liao 已提交
4734

G
Ganlin Zhao 已提交
4735 4736 4737
      pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
      pExp->base.numOfParams = 1;

H
Haojun Liao 已提交
4738
      SDataType* pType = &pColNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4739 4740
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pColNode->colName);
H
Haojun Liao 已提交
4741 4742
      pExp->base.pParam[0].pCol = createColumn(pColNode->dataBlockId, pColNode->slotId, pType);
      pExp->base.pParam[0].type = FUNC_PARAM_TYPE_COLUMN;
4743
    } else if (type == QUERY_NODE_VALUE) {
4744 4745 4746 4747 4748 4749 4750
      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 已提交
4751 4752
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pValNode->node.aliasName);
4753 4754
      pExp->base.pParam[0].type = FUNC_PARAM_TYPE_VALUE;
      valueNodeToVariant(pValNode, &pExp->base.pParam[0].param);
4755
    } else if (type == QUERY_NODE_FUNCTION) {
H
Haojun Liao 已提交
4756
      pExp->pExpr->nodeType = QUERY_NODE_FUNCTION;
H
Haojun Liao 已提交
4757 4758 4759
      SFunctionNode* pFuncNode = (SFunctionNode*)pTargetNode->pExpr;

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

H
Haojun Liao 已提交
4763
      pExp->pExpr->_function.functionId = pFuncNode->funcId;
H
Haojun Liao 已提交
4764
      pExp->pExpr->_function.pFunctNode = pFuncNode;
dengyihao's avatar
dengyihao 已提交
4765 4766
      strncpy(pExp->pExpr->_function.functionName, pFuncNode->functionName,
              tListLen(pExp->pExpr->_function.functionName));
H
Haojun Liao 已提交
4767 4768

      int32_t numOfParam = LIST_LENGTH(pFuncNode->pParameterList);
G
Ganlin Zhao 已提交
4769 4770 4771 4772

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

H
Haojun Liao 已提交
4773
      for (int32_t j = 0; j < numOfParam; ++j) {
4774
        SNode* p1 = nodesListGetNode(pFuncNode->pParameterList, j);
G
Ganlin Zhao 已提交
4775
        if (p1->type == QUERY_NODE_COLUMN) {
dengyihao's avatar
dengyihao 已提交
4776
          SColumnNode* pcn = (SColumnNode*)p1;
G
Ganlin Zhao 已提交
4777 4778

          pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN;
H
Haojun Liao 已提交
4779
          pExp->base.pParam[j].pCol = createColumn(pcn->dataBlockId, pcn->slotId, &pcn->node.resType);
G
Ganlin Zhao 已提交
4780 4781 4782
        } else if (p1->type == QUERY_NODE_VALUE) {
          SValueNode* pvn = (SValueNode*)p1;
          pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE;
4783
          valueNodeToVariant(pvn, &pExp->base.pParam[j].param);
G
Ganlin Zhao 已提交
4784
        }
H
Haojun Liao 已提交
4785
      }
4786
    } else if (type == QUERY_NODE_OPERATOR) {
H
Haojun Liao 已提交
4787
      pExp->pExpr->nodeType = QUERY_NODE_OPERATOR;
L
Liu Jicong 已提交
4788
      SOperatorNode* pNode = (SOperatorNode*)pTargetNode->pExpr;
4789

G
Ganlin Zhao 已提交
4790 4791 4792
      pExp->base.pParam = taosMemoryCalloc(1, sizeof(SFunctParam));
      pExp->base.numOfParams = 1;

4793
      SDataType* pType = &pNode->node.resType;
dengyihao's avatar
dengyihao 已提交
4794 4795
      pExp->base.resSchema = createResSchema(pType->type, pType->bytes, pTargetNode->slotId, pType->scale,
                                             pType->precision, pNode->node.aliasName);
4796 4797 4798
      pExp->pExpr->_optrRoot.pRootNode = pTargetNode->pExpr;
    } else {
      ASSERT(0);
H
Haojun Liao 已提交
4799 4800 4801
    }
  }

H
Haojun Liao 已提交
4802
  return pExprs;
H
Haojun Liao 已提交
4803 4804
}

4805
static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPTR_EXEC_MODEL model) {
wafwerar's avatar
wafwerar 已提交
4806
  SExecTaskInfo* pTaskInfo = taosMemoryCalloc(1, sizeof(SExecTaskInfo));
4807
  setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED);
H
Haojun Liao 已提交
4808

4809
  pTaskInfo->cost.created = taosGetTimestampMs();
H
Haojun Liao 已提交
4810
  pTaskInfo->id.queryId = queryId;
dengyihao's avatar
dengyihao 已提交
4811
  pTaskInfo->execModel = model;
H
Haojun Liao 已提交
4812

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

4817 4818
  return pTaskInfo;
}
H
Haojun Liao 已提交
4819

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

L
Liu Jicong 已提交
4823 4824
static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo,
                                  uint64_t queryId, uint64_t taskId);
4825
static SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo);
H
Haojun Liao 已提交
4826
static SArray* extractColumnInfo(SNodeList* pNodeList);
H
Haojun Liao 已提交
4827
static SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols);
4828

4829
static SArray* createSortInfo(SNodeList* pNodeList, SNodeList* pNodeListTarget);
4830
static SArray* createIndexMap(SNodeList* pNodeList);
4831
static SArray* extractPartitionColInfo(SNodeList* pNodeList);
4832 4833 4834 4835
static int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode);

static SInterval extractIntervalInfo(const STableScanPhysiNode* pTableScanNode) {
  SInterval interval = {
L
Liu Jicong 已提交
4836 4837
      .interval = pTableScanNode->interval,
      .sliding = pTableScanNode->sliding,
4838
      .intervalUnit = pTableScanNode->intervalUnit,
L
Liu Jicong 已提交
4839 4840
      .slidingUnit = pTableScanNode->slidingUnit,
      .offset = pTableScanNode->offset,
4841 4842 4843 4844
  };

  return interval;
}
H
Haojun Liao 已提交
4845

H
Haojun Liao 已提交
4846
SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle,
4847
                                  uint64_t queryId, uint64_t taskId, STableGroupInfo* pTableGroupInfo) {
4848 4849
  int32_t type = nodeType(pPhyNode);

X
Xiaoyu Wang 已提交
4850
  if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) {
H
Haojun Liao 已提交
4851
    if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == type) {
dengyihao's avatar
dengyihao 已提交
4852 4853
      SScanPhysiNode*      pScanPhyNode = (SScanPhysiNode*)pPhyNode;
      STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4854

L
Liu Jicong 已提交
4855
      int32_t     numOfCols = 0;
H
Haojun Liao 已提交
4856
      tsdbReaderT pDataReader = doCreateDataReader(pTableScanNode, pHandle, pTableGroupInfo, (uint64_t)queryId, taskId);
4857
      if (pDataReader == NULL && terrno != 0) {
4858 4859
        return NULL;
      }
4860

dengyihao's avatar
dengyihao 已提交
4861 4862
      SArray* pColList =
          extractColMatchInfo(pScanPhyNode->pScanCols, pScanPhyNode->node.pOutputDataBlockDesc, &numOfCols);
4863
      SSDataBlock* pResBlock = createResDataBlock(pScanPhyNode->node.pOutputDataBlockDesc);
4864

4865
      SQueryTableDataCond cond = {0};
4866 4867

      int32_t code = initQueryTableDataCond(&cond, pTableScanNode);
4868 4869 4870
      if (code != TSDB_CODE_SUCCESS) {
        return NULL;
      }
4871

4872
      SInterval interval = extractIntervalInfo(pTableScanNode);
4873
      SOperatorInfo* pOperator = createTableScanOperatorInfo(pDataReader, &cond, numOfCols, pTableScanNode->dataRequired,
L
Liu Jicong 已提交
4874 4875
                                         pTableScanNode->scanSeq, pColList, pResBlock, pScanPhyNode->node.pConditions,
                                         &interval, pTableScanNode->ratio, pTaskInfo);
4876 4877 4878
      STableScanInfo* pScanInfo = pOperator->info;
      pTaskInfo->cost.pRecoder = &pScanInfo->readRecorder;
      return pOperator;
H
Haojun Liao 已提交
4879
    } else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == type) {
H
Haojun Liao 已提交
4880
      SExchangePhysiNode* pExchange = (SExchangePhysiNode*)pPhyNode;
4881
      SSDataBlock*        pResBlock = createResDataBlock(pExchange->node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
4882
      return createExchangeOperatorInfo(pExchange->pSrcEndPoints, pResBlock, pTaskInfo);
H
Haojun Liao 已提交
4883
    } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) {
H
Haojun Liao 已提交
4884
      SScanPhysiNode* pScanPhyNode = (SScanPhysiNode*)pPhyNode;  // simple child table.
4885

4886
      int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId);
H
Haojun Liao 已提交
4887
      SArray* tableIdList = extractTableIdList(pTableGroupInfo);
H
Haojun Liao 已提交
4888

4889
      SSDataBlock* pResBlock = createResDataBlock(pScanPhyNode->node.pOutputDataBlockDesc);
4890 4891

      int32_t numOfCols = 0;
4892
      SArray* pCols = extractColMatchInfo(pScanPhyNode->pScanCols, pScanPhyNode->node.pOutputDataBlockDesc, &numOfCols);
X
Xiaoyu Wang 已提交
4893 4894
      SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pResBlock, pCols, tableIdList, pTaskInfo,
                                                              pScanPhyNode->node.pConditions);
4895
      taosArrayDestroy(tableIdList);
H
Haojun Liao 已提交
4896
      return pOperator;
H
Haojun Liao 已提交
4897
    } else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) {
L
Liu Jicong 已提交
4898
      SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode;
L
Liu Jicong 已提交
4899
      SScanPhysiNode*            pScanNode = &pSysScanPhyNode->scan;
H
Haojun Liao 已提交
4900

4901
      SSDataBlock* pResBlock = createResDataBlock(pScanNode->node.pOutputDataBlockDesc);
4902

4903
      int32_t numOfOutputCols = 0;
L
Liu Jicong 已提交
4904 4905
      SArray* colList =
          extractColMatchInfo(pScanNode->pScanCols, pScanNode->node.pOutputDataBlockDesc, &numOfOutputCols);
L
Liu Jicong 已提交
4906
      SOperatorInfo* pOperator = createSysTableScanOperatorInfo(
L
Liu Jicong 已提交
4907 4908
          pHandle, pResBlock, &pScanNode->tableName, pScanNode->node.pConditions, pSysScanPhyNode->mgmtEpSet, colList,
          pTaskInfo, pSysScanPhyNode->showRewrite, pSysScanPhyNode->accountId);
H
Haojun Liao 已提交
4909 4910 4911
      return pOperator;
    } else {
      ASSERT(0);
H
Haojun Liao 已提交
4912 4913 4914
    }
  }

4915 4916
  int32_t num = 0;
  size_t  size = LIST_LENGTH(pPhyNode->pChildren);
H
Haojun Liao 已提交
4917

4918
  SOperatorInfo** ops = taosMemoryCalloc(size, POINTER_BYTES);
dengyihao's avatar
dengyihao 已提交
4919
  for (int32_t i = 0; i < size; ++i) {
4920 4921
    SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i);
    ops[i] = createOperatorTree(pChildNode, pTaskInfo, pHandle, queryId, taskId, pTableGroupInfo);
4922 4923 4924
    if (ops[i] == NULL) {
      return NULL;
    }
4925
  }
H
Haojun Liao 已提交
4926

4927
  SOperatorInfo* pOptr = NULL;
H
Haojun Liao 已提交
4928
  if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) {
dengyihao's avatar
dengyihao 已提交
4929 4930
    SProjectPhysiNode* pProjPhyNode = (SProjectPhysiNode*)pPhyNode;
    SExprInfo*         pExprInfo = createExprInfo(pProjPhyNode->pProjections, NULL, &num);
H
Haojun Liao 已提交
4931

4932
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
4933 4934
    SLimit       limit = {.limit = pProjPhyNode->limit, .offset = pProjPhyNode->offset};
    SLimit       slimit = {.limit = pProjPhyNode->slimit, .offset = pProjPhyNode->soffset};
4935
    pOptr = createProjectOperatorInfo(ops[0], pExprInfo, num, pResBlock, &limit, &slimit, pTaskInfo);
H
Haojun Liao 已提交
4936 4937 4938
  } else if (QUERY_NODE_PHYSICAL_PLAN_AGG == type) {
    SAggPhysiNode* pAggNode = (SAggPhysiNode*)pPhyNode;
    SExprInfo*     pExprInfo = createExprInfo(pAggNode->pAggFuncs, pAggNode->pGroupKeys, &num);
4939
    SSDataBlock*   pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
H
Haojun Liao 已提交
4940

dengyihao's avatar
dengyihao 已提交
4941
    int32_t    numOfScalarExpr = 0;
4942 4943 4944 4945 4946
    SExprInfo* pScalarExprInfo = NULL;
    if (pAggNode->pExprs != NULL) {
      pScalarExprInfo = createExprInfo(pAggNode->pExprs, NULL, &numOfScalarExpr);
    }

H
Haojun Liao 已提交
4947 4948
    if (pAggNode->pGroupKeys != NULL) {
      SArray* pColList = extractColumnInfo(pAggNode->pGroupKeys);
dengyihao's avatar
dengyihao 已提交
4949 4950
      pOptr = createGroupOperatorInfo(ops[0], pExprInfo, num, pResBlock, pColList, pAggNode->node.pConditions,
                                      pScalarExprInfo, numOfScalarExpr, pTaskInfo, NULL);
H
Haojun Liao 已提交
4951
    } else {
dengyihao's avatar
dengyihao 已提交
4952 4953
      pOptr = createAggregateOperatorInfo(ops[0], pExprInfo, num, pResBlock, pScalarExprInfo, numOfScalarExpr,
                                          pTaskInfo, pTableGroupInfo);
H
Haojun Liao 已提交
4954
    }
H
Haojun Liao 已提交
4955 4956
  } else if (QUERY_NODE_PHYSICAL_PLAN_INTERVAL == type) {
    SIntervalPhysiNode* pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4957

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

dengyihao's avatar
dengyihao 已提交
4961 4962 4963 4964 4965 4966
    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 已提交
4967

dengyihao's avatar
dengyihao 已提交
4968 4969
    STimeWindowAggSupp as = {.waterMark = pIntervalPhyNode->window.watermark,
                             .calTrigger = pIntervalPhyNode->window.triggerType};
4970

4971 4972 4973 4974
    int32_t tsSlotId = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
    pOptr = createIntervalOperatorInfo(ops[0], pExprInfo, num, pResBlock, &interval, tsSlotId, &as, pTableGroupInfo,
                                       pTaskInfo);

H
Haojun Liao 已提交
4975
  } else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) {
H
Haojun Liao 已提交
4976
    SSortPhysiNode* pSortPhyNode = (SSortPhysiNode*)pPhyNode;
H
Haojun Liao 已提交
4977

4978
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4979
    SArray*      info = createSortInfo(pSortPhyNode->pSortKeys, pSortPhyNode->pTargets);
4980
    SArray*      slotMap = createIndexMap(pSortPhyNode->pTargets);
4981
    pOptr = createSortOperatorInfo(ops[0], pResBlock, info, slotMap, pTaskInfo);
H
Haojun Liao 已提交
4982
  } else if (QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW == type) {
H
Haojun Liao 已提交
4983 4984
    SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;

4985
    STimeWindowAggSupp as = {.waterMark = pSessionNode->window.watermark, .calTrigger = pSessionNode->window.triggerType};
4986

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

4991
    pOptr = createSessionAggOperatorInfo(ops[0], pExprInfo, num, pResBlock, pSessionNode->gap, tsSlotId, &as, pTaskInfo);
H
Haojun Liao 已提交
4992
  } else if (QUERY_NODE_PHYSICAL_PLAN_PARTITION == type) {
dengyihao's avatar
dengyihao 已提交
4993 4994 4995
    SPartitionPhysiNode* pPartNode = (SPartitionPhysiNode*)pPhyNode;
    SArray*              pColList = extractPartitionColInfo(pPartNode->pPartitionKeys);
    SSDataBlock*         pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
4996 4997

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

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

dengyihao's avatar
dengyihao 已提交
5004
    SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &num);
5005
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
5006 5007 5008
    int32_t      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;

    pOptr = createStatewindowOperatorInfo(ops[0], pExprInfo, num, pResBlock, &as, tsSlotId, pTaskInfo);
5009
  } else if (QUERY_NODE_PHYSICAL_PLAN_JOIN == type) {
dengyihao's avatar
dengyihao 已提交
5010 5011
    SJoinPhysiNode* pJoinNode = (SJoinPhysiNode*)pPhyNode;
    SSDataBlock*    pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
5012 5013

    SExprInfo* pExprInfo = createExprInfo(pJoinNode->pTargets, NULL, &num);
5014
    pOptr = createJoinOperatorInfo(ops, size, pExprInfo, num, pResBlock, pJoinNode->pOnConditions, pTaskInfo);
5015 5016 5017 5018 5019
  } else if (QUERY_NODE_PHYSICAL_PLAN_FILL == type) {
    SFillPhysiNode* pFillNode = (SFillPhysiNode*)pPhyNode;
    SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc);
    SExprInfo* pExprInfo = createExprInfo(pFillNode->pTargets, NULL, &num);

5020
    SInterval* pInterval = &((SIntervalAggOperatorInfo*)ops[0]->info)->interval;
5021
    pOptr = createFillOperatorInfo(ops[0], pExprInfo, num, pInterval, &pFillNode->timeRange, pResBlock, pFillNode->mode, (SNodeListNode*)pFillNode->pValues, false, pTaskInfo);
H
Haojun Liao 已提交
5022 5023
  } else {
    ASSERT(0);
H
Haojun Liao 已提交
5024
  }
5025 5026 5027

  taosMemoryFree(ops);
  return pOptr;
5028
}
H
Haojun Liao 已提交
5029

L
Liu Jicong 已提交
5030
static int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode) {
5031 5032 5033 5034 5035 5036
  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 已提交
5037
    terrno = TSDB_CODE_QRY_OUT_OF_MEMORY;
5038 5039 5040 5041 5042 5043
    return terrno;
  }

  pCond->twindow = pTableScanNode->scanRange;

#if 1
L
Liu Jicong 已提交
5044
  // todo work around a problem, remove it later
5045 5046
  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 已提交
5047
    TSWAP(pCond->twindow.skey, pCond->twindow.ekey);
H
Haojun Liao 已提交
5048
  }
5049
#endif
H
Haojun Liao 已提交
5050

5051 5052
  pCond->type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
  //  pCond->type = pTableScanNode->scanFlag;
H
Haojun Liao 已提交
5053

H
Haojun Liao 已提交
5054
  int32_t j = 0;
5055
  for (int32_t i = 0; i < pCond->numOfCols; ++i) {
H
Haojun Liao 已提交
5056 5057
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pTableScanNode->scan.pScanCols, i);
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
H
Haojun Liao 已提交
5058 5059 5060
    if (pColNode->colType == COLUMN_TYPE_TAG) {
      continue;
    }
H
Haojun Liao 已提交
5061

5062 5063 5064
    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 已提交
5065
    j += 1;
H
Haojun Liao 已提交
5066 5067
  }

5068 5069
  pCond->numOfCols = j;
  return TSDB_CODE_SUCCESS;
H
Haojun Liao 已提交
5070
}
H
Haojun Liao 已提交
5071

H
Haojun Liao 已提交
5072
SArray* extractColumnInfo(SNodeList* pNodeList) {
L
Liu Jicong 已提交
5073
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
5074 5075 5076 5077 5078 5079
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColumn));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

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

5083 5084 5085 5086 5087
    if (nodeType(pNode->pExpr) == QUERY_NODE_COLUMN) {
      SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;

      // todo extract method
      SColumn c = {0};
L
Liu Jicong 已提交
5088 5089 5090 5091 5092
      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;
5093 5094 5095 5096
      c.precision = pColNode->node.resType.precision;

      taosArrayPush(pList, &c);
    } else if (nodeType(pNode->pExpr) == QUERY_NODE_VALUE) {
L
Liu Jicong 已提交
5097 5098
      SValueNode* pValNode = (SValueNode*)pNode->pExpr;
      SColumn     c = {0};
5099
      c.slotId = pNode->slotId;
L
Liu Jicong 已提交
5100 5101 5102 5103
      c.colId = pNode->slotId;
      c.type = pValNode->node.type;
      c.bytes = pValNode->node.resType.bytes;
      c.scale = pValNode->node.resType.scale;
5104 5105 5106 5107
      c.precision = pValNode->node.resType.precision;

      taosArrayPush(pList, &c);
    }
H
Haojun Liao 已提交
5108 5109 5110 5111 5112
  }

  return pList;
}

5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126
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 已提交
5127 5128 5129
    c.colId = pColNode->colId;
    c.type = pColNode->node.resType.type;
    c.bytes = pColNode->node.resType.bytes;
5130 5131 5132 5133 5134 5135 5136 5137 5138
    c.precision = pColNode->node.resType.precision;
    c.scale = pColNode->node.resType.scale;

    taosArrayPush(pList, &c);
  }

  return pList;
}

5139
SArray* createSortInfo(SNodeList* pNodeList, SNodeList* pNodeListTarget) {
L
Liu Jicong 已提交
5140
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
5141 5142 5143 5144 5145 5146
  SArray* pList = taosArrayInit(numOfCols, sizeof(SBlockOrderInfo));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return pList;
  }

L
Liu Jicong 已提交
5147
  for (int32_t i = 0; i < numOfCols; ++i) {
5148
    SOrderByExprNode* pSortKey = (SOrderByExprNode*)nodesListGetNode(pNodeList, i);
L
Liu Jicong 已提交
5149 5150
    SBlockOrderInfo   bi = {0};
    bi.order = (pSortKey->order == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
H
Haojun Liao 已提交
5151 5152 5153 5154
    bi.nullFirst = (pSortKey->nullOrder == NULL_ORDER_FIRST);

    SColumnNode* pColNode = (SColumnNode*)pSortKey->pExpr;

5155 5156 5157 5158 5159
    bool found = false;
    for (int32_t j = 0; j < LIST_LENGTH(pNodeListTarget); ++j) {
      STargetNode* pTarget = (STargetNode*)nodesListGetNode(pNodeListTarget, j);

      SColumnNode* pColNodeT = (SColumnNode*)pTarget->pExpr;
dengyihao's avatar
dengyihao 已提交
5160
      if (pColNode->slotId == pColNodeT->slotId) {  // to find slotId in PhysiSort OutputDataBlockDesc
5161 5162 5163 5164 5165 5166
        bi.slotId = pTarget->slotId;
        found = true;
        break;
      }
    }

dengyihao's avatar
dengyihao 已提交
5167
    if (!found) {
5168 5169
      qError("sort slot id does not found");
    }
H
Haojun Liao 已提交
5170 5171 5172 5173 5174 5175
    taosArrayPush(pList, &bi);
  }

  return pList;
}

5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193
SArray* createIndexMap(SNodeList* pNodeList) {
  size_t  numOfCols = LIST_LENGTH(pNodeList);
  SArray* pList = taosArrayInit(numOfCols, sizeof(int32_t));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return pList;
  }

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

    SColumnNode* pColNode = (SColumnNode*)pTarget->pExpr;
    taosArrayPush(pList, &pColNode->slotId);
  }

  return pList;
}

H
Haojun Liao 已提交
5194
SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols) {
L
Liu Jicong 已提交
5195
  size_t  numOfCols = LIST_LENGTH(pNodeList);
H
Haojun Liao 已提交
5196 5197 5198 5199 5200 5201
  SArray* pList = taosArrayInit(numOfCols, sizeof(SColMatchInfo));
  if (pList == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

L
Liu Jicong 已提交
5202 5203 5204
  for (int32_t i = 0; i < numOfCols; ++i) {
    STargetNode* pNode = (STargetNode*)nodesListGetNode(pNodeList, i);
    SColumnNode* pColNode = (SColumnNode*)pNode->pExpr;
H
Haojun Liao 已提交
5205 5206

    SColMatchInfo c = {0};
5207
    c.output = true;
L
Liu Jicong 已提交
5208
    c.colId = pColNode->colId;
H
Haojun Liao 已提交
5209 5210 5211 5212
    c.targetSlotId = pNode->slotId;
    taosArrayPush(pList, &c);
  }

H
Haojun Liao 已提交
5213 5214
  *numOfOutputCols = 0;
  int32_t num = LIST_LENGTH(pOutputNodeList->pSlots);
L
Liu Jicong 已提交
5215 5216
  for (int32_t i = 0; i < num; ++i) {
    SSlotDescNode* pNode = (SSlotDescNode*)nodesListGetNode(pOutputNodeList->pSlots, i);
5217

5218
    // todo: add reserve flag check
5219 5220
    // it is a column reserved for the arithmetic expression calculation
    if (pNode->slotId >= numOfCols) {
5221 5222 5223 5224
      (*numOfOutputCols) += 1;
      continue;
    }

H
Haojun Liao 已提交
5225
    SColMatchInfo* info = taosArrayGet(pList, pNode->slotId);
H
Haojun Liao 已提交
5226 5227 5228 5229 5230
    if (pNode->output) {
      (*numOfOutputCols) += 1;
    } else {
      info->output = false;
    }
H
Haojun Liao 已提交
5231 5232
  }

H
Haojun Liao 已提交
5233 5234 5235
  return pList;
}

dengyihao's avatar
dengyihao 已提交
5236 5237
int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t tableUid, STableGroupInfo* pGroupInfo,
                           uint64_t queryId, uint64_t taskId) {
5238
  int32_t code = 0;
H
Haojun Liao 已提交
5239
  if (tableType == TSDB_SUPER_TABLE) {
H
Haojun Liao 已提交
5240
    code = tsdbQuerySTableByTagCond(metaHandle, tableUid, 0, NULL, 0, 0, NULL, pGroupInfo, NULL, 0, queryId, taskId);
H
Haojun Liao 已提交
5241
  } else {  // Create one table group.
H
Haojun Liao 已提交
5242
    code = tsdbGetOneTableGroup(metaHandle, tableUid, 0, pGroupInfo);
5243 5244 5245 5246
  }

  return code;
}
H
Haojun Liao 已提交
5247

5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265
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 已提交
5266 5267
tsdbReaderT doCreateDataReader(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle,
                               STableGroupInfo* pTableGroupInfo, uint64_t queryId, uint64_t taskId) {
5268
  uint64_t uid = pTableScanNode->scan.uid;
L
Liu Jicong 已提交
5269 5270
  int32_t  code =
      doCreateTableGroup(pHandle->meta, pTableScanNode->scan.tableType, uid, pTableGroupInfo, queryId, taskId);
5271 5272
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
H
Haojun Liao 已提交
5273
  }
H
Haojun Liao 已提交
5274

H
Haojun Liao 已提交
5275
  if (pTableGroupInfo->numOfTables == 0) {
H
Haojun Liao 已提交
5276
    code = 0;
L
Liu Jicong 已提交
5277
    qDebug("no table qualified for query, TID:0x%" PRIx64 ", QID:0x%" PRIx64, taskId, queryId);
H
Haojun Liao 已提交
5278 5279
    goto _error;
  }
H
Haojun Liao 已提交
5280

5281 5282 5283 5284
  SQueryTableDataCond cond = {0};
  code = initQueryTableDataCond(&cond, pTableScanNode);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
X
Xiaoyu Wang 已提交
5285
  }
5286
#if 0
5287
  return tsdbQueryTables(pHandle->reader, &cond, pTableGroupInfo, queryId, taskId);
5288 5289
#endif
  return tsdbQueryTables(pHandle->vnode, &cond, pTableGroupInfo, queryId, taskId);
H
Haojun Liao 已提交
5290

L
Liu Jicong 已提交
5291
_error:
H
Haojun Liao 已提交
5292 5293 5294 5295
  terrno = code;
  return NULL;
}

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

H
Haojun Liao 已提交
5300
  int32_t code = TSDB_CODE_SUCCESS;
5301
  *pTaskInfo = createExecTaskInfo(queryId, taskId, model);
H
Haojun Liao 已提交
5302 5303 5304 5305
  if (*pTaskInfo == NULL) {
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
    goto _complete;
  }
H
Haojun Liao 已提交
5306

L
Liu Jicong 已提交
5307 5308
  (*pTaskInfo)->pRoot =
      createOperatorTree(pPlan->pNode, *pTaskInfo, pHandle, queryId, taskId, &(*pTaskInfo)->tableqinfoGroupInfo);
D
dapan1121 已提交
5309
  if (NULL == (*pTaskInfo)->pRoot) {
L
Liu Jicong 已提交
5310
    code = terrno;
D
dapan1121 已提交
5311 5312
    goto _complete;
  }
H
Haojun Liao 已提交
5313

5314
  if ((*pTaskInfo)->pRoot == NULL) {
H
Haojun Liao 已提交
5315
    code = TSDB_CODE_QRY_OUT_OF_MEMORY;
H
Haojun Liao 已提交
5316
    goto _complete;
5317 5318
  }

H
Haojun Liao 已提交
5319 5320
  return code;

H
Haojun Liao 已提交
5321
_complete:
wafwerar's avatar
wafwerar 已提交
5322
  taosMemoryFreeClear(*pTaskInfo);
H
Haojun Liao 已提交
5323 5324 5325

  terrno = code;
  return code;
H
Haojun Liao 已提交
5326 5327
}

L
Liu Jicong 已提交
5328 5329
static int32_t updateOutputBufForTopBotQuery(SQueriedTableInfo* pTableInfo, SColumnInfo* pTagCols, SExprInfo* pExprs,
                                             int32_t numOfOutput, int32_t tagLen, bool superTable) {
5330 5331 5332 5333 5334 5335 5336 5337 5338
  for (int32_t i = 0; i < numOfOutput; ++i) {
    int16_t functId = getExprFunctionId(&pExprs[i]);

    if (functId == FUNCTION_TOP || functId == FUNCTION_BOTTOM) {
      int32_t j = getColumnIndexInSource(pTableInfo, &pExprs[i].base, pTagCols);
      if (j < 0 || j >= pTableInfo->numOfCols) {
        return TSDB_CODE_QRY_INVALID_MSG;
      } else {
        SColumnInfo* pCol = &pTableInfo->colList[j];
L
Liu Jicong 已提交
5339 5340 5341 5342
        //        int32_t ret = getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.param[0].i,
        //                                        &pExprs[i].base.resSchema.type, &pExprs[i].base.resSchema.bytes,
        //                                        &pExprs[i].base.interBytes, tagLen, superTable, NULL);
        //        assert(ret == TSDB_CODE_SUCCESS);
5343 5344 5345 5346 5347 5348 5349
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
5350
void setResultBufSize(STaskAttr* pQueryAttr, SResultInfo* pResultInfo) {
5351 5352 5353 5354 5355 5356 5357 5358
  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 已提交
5359 5360 5361 5362 5363 5364 5365 5366 5367 5368
  //  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;
  //  }
5369 5370

  pResultInfo->threshold = (int32_t)(pResultInfo->capacity * THRESHOLD_RATIO);
H
Haojun Liao 已提交
5371
  pResultInfo->totalRows = 0;
5372 5373
}

L
Liu Jicong 已提交
5374
// TODO refactor
5375
void freeColumnFilterInfo(SColumnFilterInfo* pFilter, int32_t numOfFilters) {
L
Liu Jicong 已提交
5376 5377 5378
  if (pFilter == NULL || numOfFilters == 0) {
    return;
  }
5379

L
Liu Jicong 已提交
5380 5381 5382
  for (int32_t i = 0; i < numOfFilters; i++) {
    if (pFilter[i].filterstr && pFilter[i].pz) {
      taosMemoryFree((void*)(pFilter[i].pz));
5383
    }
L
Liu Jicong 已提交
5384
  }
5385

L
Liu Jicong 已提交
5386
  taosMemoryFree(pFilter);
5387 5388 5389 5390
}

static void doDestroyTableQueryInfo(STableGroupInfo* pTableqinfoGroupInfo) {
  if (pTableqinfoGroupInfo->pGroupList != NULL) {
L
Liu Jicong 已提交
5391
    int32_t numOfGroups = (int32_t)taosArrayGetSize(pTableqinfoGroupInfo->pGroupList);
5392
    for (int32_t i = 0; i < numOfGroups; ++i) {
L
Liu Jicong 已提交
5393
      SArray* p = taosArrayGetP(pTableqinfoGroupInfo->pGroupList, i);
5394 5395

      size_t num = taosArrayGetSize(p);
L
Liu Jicong 已提交
5396
      for (int32_t j = 0; j < num; ++j) {
5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412
        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 已提交
5413
void doDestroyTask(SExecTaskInfo* pTaskInfo) {
H
Haojun Liao 已提交
5414 5415
  qDebug("%s execTask is freed", GET_TASKID(pTaskInfo));

H
Haojun Liao 已提交
5416
  doDestroyTableQueryInfo(&pTaskInfo->tableqinfoGroupInfo);
L
Liu Jicong 已提交
5417 5418
  //  taosArrayDestroy(pTaskInfo->summary.queryProfEvents);
  //  taosHashCleanup(pTaskInfo->summary.operatorProfResults);
5419

wafwerar's avatar
wafwerar 已提交
5420 5421 5422
  taosMemoryFreeClear(pTaskInfo->sql);
  taosMemoryFreeClear(pTaskInfo->id.str);
  taosMemoryFreeClear(pTaskInfo);
5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434
}

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 已提交
5435
      int32_t len = (varDataLen(val) > maxLen) ? maxLen : varDataLen(val);
5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447
      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 已提交
5448 5449
  //  size_t s3 = sizeof(STableCheckInfo);  buffer consumption in tsdb
  return (int64_t)(s1 * 1.5 * numOfTables);
5450 5451 5452 5453 5454 5455 5456
}

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 已提交
5457
    while (1) {
5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483
      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 已提交
5484

dengyihao's avatar
dengyihao 已提交
5485 5486
int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SExplainExecInfo** pRes, int32_t* capacity,
                                   int32_t* resNum) {
D
dapan1121 已提交
5487 5488
  if (*resNum >= *capacity) {
    *capacity += 10;
dengyihao's avatar
dengyihao 已提交
5489

D
dapan1121 已提交
5490 5491
    *pRes = taosMemoryRealloc(*pRes, (*capacity) * sizeof(SExplainExecInfo));
    if (NULL == *pRes) {
D
dapan1121 已提交
5492
      qError("malloc %d failed", (*capacity) * (int32_t)sizeof(SExplainExecInfo));
D
dapan1121 已提交
5493 5494 5495 5496
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
  }

D
dapan1121 已提交
5497 5498 5499 5500
  (*pRes)[*resNum].numOfRows = operatorInfo->resultInfo.totalRows;
  (*pRes)[*resNum].startupCost = operatorInfo->cost.openCost;
  (*pRes)[*resNum].totalCost = operatorInfo->cost.totalCost;

5501 5502
  if (operatorInfo->fpSet.getExplainFn) {
    int32_t code = (*operatorInfo->fpSet.getExplainFn)(operatorInfo, &(*pRes)->verboseInfo);
D
dapan1121 已提交
5503 5504 5505 5506 5507
    if (code) {
      qError("operator getExplainFn failed, error:%s", tstrerror(code));
      return code;
    }
  }
dengyihao's avatar
dengyihao 已提交
5508

D
dapan1121 已提交
5509
  ++(*resNum);
dengyihao's avatar
dengyihao 已提交
5510

D
dapan1121 已提交
5511
  int32_t code = 0;
D
dapan1121 已提交
5512 5513
  for (int32_t i = 0; i < operatorInfo->numOfDownstream; ++i) {
    code = getOperatorExplainExecInfo(operatorInfo->pDownstream[i], pRes, capacity, resNum);
D
dapan1121 已提交
5514 5515 5516 5517 5518 5519 5520
    if (code) {
      taosMemoryFreeClear(*pRes);
      return TSDB_CODE_QRY_OUT_OF_MEMORY;
    }
  }

  return TSDB_CODE_SUCCESS;
D
dapan1121 已提交
5521 5522
}

5523
static SSDataBlock* doMergeJoin(struct SOperatorInfo* pOperator) {
5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535
  SJoinOperatorInfo* pJoinInfo = pOperator->info;

  SSDataBlock* pRes = pJoinInfo->pRes;
  blockDataCleanup(pRes);
  blockDataEnsureCapacity(pRes, 4096);

  int32_t nrows = 0;

  while (1) {
    if (pJoinInfo->pLeft == NULL || pJoinInfo->leftPos >= pJoinInfo->pLeft->info.rows) {
      SOperatorInfo* ds1 = pOperator->pDownstream[0];
      publishOperatorProfEvent(ds1, QUERY_PROF_BEFORE_OPERATOR_EXEC);
5536
      pJoinInfo->pLeft = ds1->fpSet.getNextFn(ds1);
5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548
      publishOperatorProfEvent(ds1, QUERY_PROF_AFTER_OPERATOR_EXEC);

      pJoinInfo->leftPos = 0;
      if (pJoinInfo->pLeft == NULL) {
        setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
        break;
      }
    }

    if (pJoinInfo->pRight == NULL || pJoinInfo->rightPos >= pJoinInfo->pRight->info.rows) {
      SOperatorInfo* ds2 = pOperator->pDownstream[1];
      publishOperatorProfEvent(ds2, QUERY_PROF_BEFORE_OPERATOR_EXEC);
5549
      pJoinInfo->pRight = ds2->fpSet.getNextFn(ds2);
5550 5551 5552 5553 5554 5555 5556 5557 5558 5559
      publishOperatorProfEvent(ds2, QUERY_PROF_AFTER_OPERATOR_EXEC);

      pJoinInfo->rightPos = 0;
      if (pJoinInfo->pRight == NULL) {
        setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
        break;
      }
    }

    SColumnInfoData* pLeftCol = taosArrayGet(pJoinInfo->pLeft->pDataBlock, pJoinInfo->leftCol.slotId);
dengyihao's avatar
dengyihao 已提交
5560
    char*            pLeftVal = colDataGetData(pLeftCol, pJoinInfo->leftPos);
5561 5562

    SColumnInfoData* pRightCol = taosArrayGet(pJoinInfo->pRight->pDataBlock, pJoinInfo->rightCol.slotId);
dengyihao's avatar
dengyihao 已提交
5563
    char*            pRightVal = colDataGetData(pRightCol, pJoinInfo->rightPos);
5564 5565

    // only the timestamp match support for ordinary table
dengyihao's avatar
dengyihao 已提交
5566 5567 5568 5569
    ASSERT(pLeftCol->info.type == TSDB_DATA_TYPE_TIMESTAMP);
    if (*(int64_t*)pLeftVal == *(int64_t*)pRightVal) {
      for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
        SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, i);
5570

dengyihao's avatar
dengyihao 已提交
5571
        SExprInfo* pExprInfo = &pOperator->pExpr[i];
5572

dengyihao's avatar
dengyihao 已提交
5573 5574
        int32_t blockId = pExprInfo->base.pParam[0].pCol->dataBlockId;
        int32_t slotId = pExprInfo->base.pParam[0].pCol->slotId;
5575

dengyihao's avatar
dengyihao 已提交
5576 5577 5578 5579 5580 5581
        SColumnInfoData* pSrc = NULL;
        if (pJoinInfo->pLeft->info.blockId == blockId) {
          pSrc = taosArrayGet(pJoinInfo->pLeft->pDataBlock, slotId);
        } else {
          pSrc = taosArrayGet(pJoinInfo->pRight->pDataBlock, slotId);
        }
5582

dengyihao's avatar
dengyihao 已提交
5583 5584 5585 5586 5587
        if (colDataIsNull_s(pSrc, pJoinInfo->leftPos)) {
          colDataAppendNULL(pDst, nrows);
        } else {
          char* p = colDataGetData(pSrc, pJoinInfo->leftPos);
          colDataAppend(pDst, nrows, p, false);
5588
        }
dengyihao's avatar
dengyihao 已提交
5589
      }
5590

dengyihao's avatar
dengyihao 已提交
5591 5592
      pJoinInfo->leftPos += 1;
      pJoinInfo->rightPos += 1;
5593

dengyihao's avatar
dengyihao 已提交
5594 5595 5596
      nrows += 1;
    } else if (*(int64_t*)pLeftVal < *(int64_t*)pRightVal) {
      pJoinInfo->leftPos += 1;
D
dapan1121 已提交
5597

dengyihao's avatar
dengyihao 已提交
5598 5599
      if (pJoinInfo->leftPos >= pJoinInfo->pLeft->info.rows) {
        continue;
5600
      }
dengyihao's avatar
dengyihao 已提交
5601 5602 5603 5604
    } else if (*(int64_t*)pLeftVal > *(int64_t*)pRightVal) {
      pJoinInfo->rightPos += 1;
      if (pJoinInfo->rightPos >= pJoinInfo->pRight->info.rows) {
        continue;
5605
      }
dengyihao's avatar
dengyihao 已提交
5606
    }
5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617

    // the pDataBlock are always the same one, no need to call this again
    pRes->info.rows = nrows;
    if (pRes->info.rows >= pOperator->resultInfo.threshold) {
      break;
    }
  }

  return (pRes->info.rows > 0) ? pRes : NULL;
}

dengyihao's avatar
dengyihao 已提交
5618 5619 5620
SOperatorInfo* createJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SExprInfo* pExprInfo,
                                      int32_t numOfCols, SSDataBlock* pResBlock, SNode* pOnCondition,
                                      SExecTaskInfo* pTaskInfo) {
5621
  SJoinOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SJoinOperatorInfo));
dengyihao's avatar
dengyihao 已提交
5622
  SOperatorInfo*     pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5623 5624 5625 5626 5627 5628 5629
  if (pOperator == NULL || pInfo == NULL) {
    goto _error;
  }

  pOperator->resultInfo.capacity = 4096;
  pOperator->resultInfo.threshold = 4096 * 0.75;

dengyihao's avatar
dengyihao 已提交
5630 5631 5632
  //  initResultRowInf
  //  o(&pInfo->binfo.resultRowInfo, 8);
  pInfo->pRes = pResBlock;
5633

dengyihao's avatar
dengyihao 已提交
5634
  pOperator->name = "JoinOperator";
5635
  pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_JOIN;
5636
  pOperator->blocking = false;
dengyihao's avatar
dengyihao 已提交
5637 5638 5639 5640 5641
  pOperator->status = OP_NOT_OPENED;
  pOperator->pExpr = pExprInfo;
  pOperator->numOfOutput = numOfCols;
  pOperator->info = pInfo;
  pOperator->pTaskInfo = pTaskInfo;
5642

L
Liu Jicong 已提交
5643 5644
  pOperator->fpSet =
      createOperatorFpSet(operatorDummyOpenFn, doMergeJoin, NULL, NULL, destroyBasicOperatorInfo, NULL, NULL, NULL);
5645 5646 5647
  int32_t code = appendDownstream(pOperator, pDownstream, numOfDownstream);
  return pOperator;

dengyihao's avatar
dengyihao 已提交
5648
_error:
5649 5650 5651 5652
  taosMemoryFree(pInfo);
  taosMemoryFree(pOperator);
  pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY;
  return NULL;
dengyihao's avatar
dengyihao 已提交
5653
}