timewindowoperator.c 199.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
15
#include "executorInt.h"
16
#include "filter.h"
X
Xiaoyu Wang 已提交
17
#include "function.h"
5
54liuyao 已提交
18
#include "functionMgt.h"
19 20
#include "operator.h"
#include "querytask.h"
H
Haojun Liao 已提交
21
#include "tcommon.h"
5
54liuyao 已提交
22
#include "tcompare.h"
L
Liu Jicong 已提交
23
#include "tdatablock.h"
H
Haojun Liao 已提交
24
#include "tfill.h"
dengyihao's avatar
dengyihao 已提交
25
#include "tglobal.h"
dengyihao's avatar
dengyihao 已提交
26
#include "tlog.h"
27
#include "ttime.h"
28

L
Liu Jicong 已提交
29
#define IS_FINAL_OP(op)    ((op)->isFinal)
5
54liuyao 已提交
30
#define DEAULT_DELETE_MARK (1000LL * 60LL * 60LL * 24LL * 365LL * 10LL);
L
liuyao 已提交
31
#define STREAM_INTERVAL_OP_STATE_NAME "StreamIntervalHistoryState"
L
liuyao 已提交
32 33
#define STREAM_SESSION_OP_STATE_NAME "StreamSessionHistoryState"
#define STREAM_STATE_OP_STATE_NAME "StreamStateHistoryState"
H
Haojun Liao 已提交
34

35 36 37 38 39
typedef struct SStateWindowInfo {
  SResultWindowInfo winInfo;
  SStateKeys*       pStateKey;
} SStateWindowInfo;

H
Haojun Liao 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
typedef struct SSessionAggOperatorInfo {
  SOptrBasicInfo     binfo;
  SAggSupporter      aggSup;
  SGroupResInfo      groupResInfo;
  SWindowRowsSup     winSup;
  bool               reptScan;  // next round scan
  int64_t            gap;       // session window gap
  int32_t            tsSlotId;  // primary timestamp slot id
  STimeWindowAggSupp twAggSup;
} SSessionAggOperatorInfo;

typedef struct SStateWindowOperatorInfo {
  SOptrBasicInfo     binfo;
  SAggSupporter      aggSup;
  SExprSupp          scalarSup;
  SGroupResInfo      groupResInfo;
  SWindowRowsSup     winSup;
  SColumn            stateCol;  // start row index
  bool               hasKey;
  SStateKeys         stateKey;
  int32_t            tsSlotId;  // primary timestamp column slot id
  STimeWindowAggSupp twAggSup;
} SStateWindowOperatorInfo;

64 65 66 67 68
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP = 2,
} SResultTsInterpType;

5
54liuyao 已提交
69 70
typedef struct SPullWindowInfo {
  STimeWindow window;
L
Liu Jicong 已提交
71
  uint64_t    groupId;
5
54liuyao 已提交
72
  STimeWindow calWin;
5
54liuyao 已提交
73 74
} SPullWindowInfo;

75 76
typedef struct SOpenWindowInfo {
  SResultRowPosition pos;
L
Liu Jicong 已提交
77
  uint64_t           groupId;
78 79
} SOpenWindowInfo;

80 81
static int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo);

L
Liu Jicong 已提交
82 83
static SResultRowPosition addToOpenWindowList(SResultRowInfo* pResultRowInfo, const SResultRow* pResult,
                                              uint64_t groupId);
84 85
static void doCloseWindow(SResultRowInfo* pResultRowInfo, const SIntervalAggOperatorInfo* pInfo, SResultRow* pResult);

X
Xiaoyu Wang 已提交
86
static TSKEY getStartTsKey(STimeWindow* win, const TSKEY* tsCols) { return tsCols == NULL ? win->skey : tsCols[0]; }
87 88 89

static int32_t setTimeWindowOutputBuf(SResultRowInfo* pResultRowInfo, STimeWindow* win, bool masterscan,
                                      SResultRow** pResult, int64_t tableGroupId, SqlFunctionCtx* pCtx,
90
                                      int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup,
91 92
                                      SExecTaskInfo* pTaskInfo) {
  SResultRow* pResultRow = doSetResultOutBufByKey(pAggSup->pResultBuf, pResultRowInfo, (char*)&win->skey, TSDB_KEYSIZE,
D
dapan1121 已提交
93
                                                  masterscan, tableGroupId, pTaskInfo, true, pAggSup, true);
94 95 96 97 98 99 100 101

  if (pResultRow == NULL) {
    *pResult = NULL;
    return TSDB_CODE_SUCCESS;
  }

  // set time window for current result
  pResultRow->win = (*win);
102

103
  *pResult = pResultRow;
104
  setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowEntryInfoOffset);
105

106 107 108 109 110 111 112 113 114 115 116 117 118
  return TSDB_CODE_SUCCESS;
}

static void updateTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pWin, bool includeEndpoint) {
  int64_t* ts = (int64_t*)pColData->pData;
  int32_t  delta = includeEndpoint ? 1 : 0;

  int64_t duration = pWin->ekey - pWin->skey + delta;
  ts[2] = duration;            // set the duration
  ts[3] = pWin->skey;          // window start key
  ts[4] = pWin->ekey + delta;  // window end key
}

119
static void doKeepTuple(SWindowRowsSup* pRowSup, int64_t ts, uint64_t groupId) {
120 121 122
  pRowSup->win.ekey = ts;
  pRowSup->prevTs = ts;
  pRowSup->numOfRows += 1;
123
  pRowSup->groupId = groupId;
124 125
}

dengyihao's avatar
dengyihao 已提交
126 127
static void doKeepNewWindowStartInfo(SWindowRowsSup* pRowSup, const int64_t* tsList, int32_t rowIndex,
                                     uint64_t groupId) {
128 129 130
  pRowSup->startRowIndex = rowIndex;
  pRowSup->numOfRows = 0;
  pRowSup->win.skey = tsList[rowIndex];
131
  pRowSup->groupId = groupId;
132 133
}

L
Liu Jicong 已提交
134 135
FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int32_t pos,
                                            int32_t order, int64_t* pData) {
136
  int32_t forwardRows = 0;
137 138 139 140

  if (order == TSDB_ORDER_ASC) {
    int32_t end = searchFn((char*)&pData[pos], numOfRows - pos, ekey, order);
    if (end >= 0) {
141
      forwardRows = end;
142

S
slzhou 已提交
143
      while (pData[end + pos] == ekey) {
144
        forwardRows += 1;
S
slzhou 已提交
145
        ++pos;
146 147 148
      }
    }
  } else {
149
    int32_t end = searchFn((char*)&pData[pos], numOfRows - pos, ekey, order);
150
    if (end >= 0) {
151
      forwardRows = end;
152

S
slzhou 已提交
153
      while (pData[end + pos] == ekey) {
154
        forwardRows += 1;
S
slzhou 已提交
155
        ++pos;
156 157
      }
    }
X
Xiaoyu Wang 已提交
158 159 160 161 162 163 164 165
    //    int32_t end = searchFn((char*)pData, pos + 1, ekey, order);
    //    if (end >= 0) {
    //      forwardRows = pos - end;
    //
    //      if (pData[end] == ekey) {
    //        forwardRows += 1;
    //      }
    //    }
166 167
  }

H
Haojun Liao 已提交
168
  ASSERT(forwardRows >= 0);
169
  return forwardRows;
170 171
}

5
54liuyao 已提交
172
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
173 174 175 176 177 178 179 180 181 182 183 184 185 186
  int32_t midPos = -1;
  int32_t numOfRows;

  if (num <= 0) {
    return -1;
  }

  TSKEY*  keyList = (TSKEY*)pValue;
  int32_t firstPos = 0;
  int32_t lastPos = num - 1;

  if (order == TSDB_ORDER_DESC) {
    // find the first position which is smaller than the key
    while (1) {
187 188 189 190 191 192 193 194 195 196 197
      if (key >= keyList[firstPos]) return firstPos;
      if (key == keyList[lastPos]) return lastPos;

      if (key < keyList[lastPos]) {
        lastPos += 1;
        if (lastPos >= num) {
          return -1;
        } else {
          return lastPos;
        }
      }
198 199 200 201 202 203

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;

      if (key < keyList[midPos]) {
        firstPos = midPos + 1;
204 205
      } else if (key > keyList[midPos]) {
        lastPos = midPos - 1;
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
      } else {
        break;
      }
    }

  } else {
    // find the first position which is bigger than the key
    while (1) {
      if (key <= keyList[firstPos]) return firstPos;
      if (key == keyList[lastPos]) return lastPos;

      if (key > keyList[lastPos]) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1u) + firstPos;

      if (key < keyList[midPos]) {
        lastPos = midPos - 1;
      } else if (key > keyList[midPos]) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }

  return midPos;
}

X
Xiaoyu Wang 已提交
241 242
int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimaryColumn, int32_t startPos, TSKEY ekey,
                                 __block_search_fn_t searchFn, STableQueryInfo* item, int32_t order) {
H
Haojun Liao 已提交
243
  ASSERT(startPos >= 0 && startPos < pDataBlockInfo->rows);
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263

  int32_t num = -1;
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(order);

  if (order == TSDB_ORDER_ASC) {
    if (ekey < pDataBlockInfo->window.ekey && pPrimaryColumn) {
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
      if (item != NULL) {
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
      }
    } else {
      num = pDataBlockInfo->rows - startPos;
      if (item != NULL) {
        item->lastKey = pDataBlockInfo->window.ekey + step;
      }
    }
  } else {  // desc
    if (ekey > pDataBlockInfo->window.skey && pPrimaryColumn) {
      num = getForwardStepsInBlock(pDataBlockInfo->rows, searchFn, ekey, startPos, order, pPrimaryColumn);
      if (item != NULL) {
264
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
265 266
      }
    } else {
267
      num = pDataBlockInfo->rows - startPos;
268
      if (item != NULL) {
269
        item->lastKey = pDataBlockInfo->window.ekey + step;
270 271 272 273 274 275 276
      }
    }
  }

  return num;
}

277 278
void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY prevTs, int32_t prevRowIndex, TSKEY curTs,
                               int32_t curRowIndex, TSKEY windowKey, int32_t type, SExprSupp* pSup) {
279
  SqlFunctionCtx* pCtx = pSup->pCtx;
280

281
  int32_t index = 1;
282
  for (int32_t k = 0; k < pSup->numOfExprs; ++k) {
H
Haojun Liao 已提交
283
    if (!fmIsIntervalInterpoFunc(pCtx[k].functionId)) {
284 285 286 287
      pCtx[k].start.key = INT64_MIN;
      continue;
    }

X
Xiaoyu Wang 已提交
288
    SFunctParam*     pParam = &pCtx[k].param[0];
289 290
    SColumnInfoData* pColInfo = taosArrayGet(pDataBlock, pParam->pCol->slotId);

291
    ASSERT(pColInfo->info.type == pParam->pCol->type && curTs != windowKey);
292

293
    double v1 = 0, v2 = 0, v = 0;
294
    if (prevRowIndex == -1) {
295
      SGroupKeys* p = taosArrayGet(pPrevValues, index);
296
      GET_TYPED_DATA(v1, double, pColInfo->info.type, p->pData);
297
    } else {
298
      GET_TYPED_DATA(v1, double, pColInfo->info.type, colDataGetData(pColInfo, prevRowIndex));
299 300
    }

301
    GET_TYPED_DATA(v2, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex));
302

303
#if 0
304 305 306 307 308 309 310 311
    if (functionId == FUNCTION_INTERP) {
      if (type == RESULT_ROW_START_INTERP) {
        pCtx[k].start.key = prevTs;
        pCtx[k].start.val = v1;

        pCtx[k].end.key = curTs;
        pCtx[k].end.val = v2;

D
Dingle Zhang 已提交
312 313
        if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR ||
            pColInfo->info.type == TSDB_DATA_TYPE_GEOMETRY) {
314 315 316 317 318 319 320 321 322 323
          if (prevRowIndex == -1) {
            //            pCtx[k].start.ptr = (char*)pRuntimeEnv->prevRow[index];
          } else {
            pCtx[k].start.ptr = (char*)pColInfo->pData + prevRowIndex * pColInfo->info.bytes;
          }

          pCtx[k].end.ptr = (char*)pColInfo->pData + curRowIndex * pColInfo->info.bytes;
        }
      }
    } else if (functionId == FUNCTION_TWA) {
324 325
#endif

X
Xiaoyu Wang 已提交
326 327 328
    SPoint point1 = (SPoint){.key = prevTs, .val = &v1};
    SPoint point2 = (SPoint){.key = curTs, .val = &v2};
    SPoint point = (SPoint){.key = windowKey, .val = &v};
329

X
Xiaoyu Wang 已提交
330
    taosGetLinearInterpolationVal(&point, TSDB_DATA_TYPE_DOUBLE, &point1, &point2, TSDB_DATA_TYPE_DOUBLE);
331

X
Xiaoyu Wang 已提交
332 333 334 335 336 337
    if (type == RESULT_ROW_START_INTERP) {
      pCtx[k].start.key = point.key;
      pCtx[k].start.val = v;
    } else {
      pCtx[k].end.key = point.key;
      pCtx[k].end.val = v;
338
    }
X
Xiaoyu Wang 已提交
339 340 341

    index += 1;
  }
342
#if 0
343
  }
344
#endif
345 346 347 348 349 350 351 352 353 354 355 356 357 358
}

static void setNotInterpoWindowKey(SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t type) {
  if (type == RESULT_ROW_START_INTERP) {
    for (int32_t k = 0; k < numOfOutput; ++k) {
      pCtx[k].start.key = INT64_MIN;
    }
  } else {
    for (int32_t k = 0; k < numOfOutput; ++k) {
      pCtx[k].end.key = INT64_MIN;
    }
  }
}

359 360
static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, int32_t pos, SSDataBlock* pBlock,
                                              const TSKEY* tsCols, STimeWindow* win, SExprSupp* pSup) {
361
  bool ascQuery = (pInfo->inputOrder == TSDB_ORDER_ASC);
362

363
  TSKEY curTs = tsCols[pos];
364 365

  SGroupKeys* pTsKey = taosArrayGet(pInfo->pPrevValues, 0);
X
Xiaoyu Wang 已提交
366
  TSKEY       lastTs = *(int64_t*)pTsKey->pData;
367 368 369 370 371

  // lastTs == INT64_MIN and pos == 0 means this is the first time window, interpolation is not needed.
  // start exactly from this point, no need to do interpolation
  TSKEY key = ascQuery ? win->skey : win->ekey;
  if (key == curTs) {
372
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_START_INTERP);
373 374 375
    return true;
  }

376 377
  // it is the first time window, no need to do interpolation
  if (pTsKey->isNull && pos == 0) {
378
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_START_INTERP);
379 380
  } else {
    TSKEY prevTs = ((pos == 0) ? lastTs : tsCols[pos - 1]);
381 382
    doTimeWindowInterpolation(pInfo->pPrevValues, pBlock->pDataBlock, prevTs, pos - 1, curTs, pos, key,
                              RESULT_ROW_START_INTERP, pSup);
383 384 385 386 387
  }

  return true;
}

388 389 390
static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SExprSupp* pSup, int32_t endRowIndex,
                                            SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey,
                                            STimeWindow* win) {
391
  int32_t order = pInfo->inputOrder;
392 393

  TSKEY actualEndKey = tsCols[endRowIndex];
394
  TSKEY key = (order == TSDB_ORDER_ASC) ? win->ekey : win->skey;
395 396

  // not ended in current data block, do not invoke interpolation
397
  if ((key > blockEkey && (order == TSDB_ORDER_ASC)) || (key < blockEkey && (order == TSDB_ORDER_DESC))) {
398
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_END_INTERP);
399 400 401
    return false;
  }

402
  // there is actual end point of current time window, no interpolation needs
403
  if (key == actualEndKey) {
404
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_END_INTERP);
405 406 407
    return true;
  }

408
  int32_t nextRowIndex = endRowIndex + 1;
H
Haojun Liao 已提交
409
  ASSERT(nextRowIndex >= 0);
410 411

  TSKEY nextKey = tsCols[nextRowIndex];
412 413
  doTimeWindowInterpolation(pInfo->pPrevValues, pDataBlock, actualEndKey, endRowIndex, nextKey, nextRowIndex, key,
                            RESULT_ROW_END_INTERP, pSup);
414 415 416
  return true;
}

L
liuyao 已提交
417
bool inCalSlidingWindow(SInterval* pInterval, STimeWindow* pWin, TSKEY calStart, TSKEY calEnd, EStreamType blockType) {
H
Haojun Liao 已提交
418
  if (pInterval->interval != pInterval->sliding &&
L
liuyao 已提交
419
      ((pWin->ekey < calStart || pWin->skey > calEnd) || (blockType == STREAM_PULL_DATA && pWin->skey < calStart) )) {
5
54liuyao 已提交
420 421
    return false;
  }
L
liuyao 已提交
422

5
54liuyao 已提交
423 424 425
  return true;
}

426
bool inSlidingWindow(SInterval* pInterval, STimeWindow* pWin, SDataBlockInfo* pBlockInfo) {
L
liuyao 已提交
427
  return inCalSlidingWindow(pInterval, pWin, pBlockInfo->calWin.skey, pBlockInfo->calWin.ekey, pBlockInfo->type);
428 429
}

430
static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
5
54liuyao 已提交
431
                                      TSKEY* primaryKeys, int32_t prevPosition, int32_t order) {
X
Xiaoyu Wang 已提交
432
  bool ascQuery = (order == TSDB_ORDER_ASC);
433 434

  int32_t precision = pInterval->precision;
435
  getNextTimeWindow(pInterval, pNext, order);
436 437 438 439 440 441 442

  // next time window is not in current block
  if ((pNext->skey > pDataBlockInfo->window.ekey && order == TSDB_ORDER_ASC) ||
      (pNext->ekey < pDataBlockInfo->window.skey && order == TSDB_ORDER_DESC)) {
    return -1;
  }

5
54liuyao 已提交
443 444 445 446
  if (!inSlidingWindow(pInterval, pNext, pDataBlockInfo) && order == TSDB_ORDER_ASC) {
    return -1;
  }

447
  TSKEY   skey = ascQuery ? pNext->skey : pNext->ekey;
448 449 450 451
  int32_t startPos = 0;

  // tumbling time window query, a special case of sliding time window query
  if (pInterval->sliding == pInterval->interval && prevPosition != -1) {
452
    startPos = prevPosition + 1;
453
  } else {
454
    if ((skey <= pDataBlockInfo->window.skey && ascQuery) || (skey >= pDataBlockInfo->window.ekey && !ascQuery)) {
455 456
      startPos = 0;
    } else {
457
      startPos = binarySearchForKey((char*)primaryKeys, pDataBlockInfo->rows, skey, order);
458 459 460 461 462 463 464 465 466 467 468 469 470 471
    }
  }

  /* interp query with fill should not skip time window */
  //  if (pQueryAttr->pointInterpQuery && pQueryAttr->fillType != TSDB_FILL_NONE) {
  //    return startPos;
  //  }

  /*
   * This time window does not cover any data, try next time window,
   * this case may happen when the time window is too small
   */
  if (primaryKeys == NULL) {
    if (ascQuery) {
H
Haojun Liao 已提交
472
      ASSERT(pDataBlockInfo->window.skey <= pNext->ekey);
473
    } else {
H
Haojun Liao 已提交
474
      ASSERT(pDataBlockInfo->window.ekey >= pNext->skey);
475 476 477 478 479
    }
  } else {
    if (ascQuery && primaryKeys[startPos] > pNext->ekey) {
      TSKEY next = primaryKeys[startPos];
      if (pInterval->intervalUnit == 'n' || pInterval->intervalUnit == 'y') {
480
        pNext->skey = taosTimeTruncate(next, pInterval);
481 482 483 484 485 486 487 488
        pNext->ekey = taosTimeAdd(pNext->skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
      } else {
        pNext->ekey += ((next - pNext->ekey + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
        pNext->skey = pNext->ekey - pInterval->interval + 1;
      }
    } else if ((!ascQuery) && primaryKeys[startPos] < pNext->skey) {
      TSKEY next = primaryKeys[startPos];
      if (pInterval->intervalUnit == 'n' || pInterval->intervalUnit == 'y') {
489
        pNext->skey = taosTimeTruncate(next, pInterval);
490 491 492 493 494 495 496 497 498 499 500
        pNext->ekey = taosTimeAdd(pNext->skey, pInterval->interval, pInterval->intervalUnit, precision) - 1;
      } else {
        pNext->skey -= ((pNext->skey - next + pInterval->sliding - 1) / pInterval->sliding) * pInterval->sliding;
        pNext->ekey = pNext->skey + pInterval->interval - 1;
      }
    }
  }

  return startPos;
}

501
static bool isResultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
502
  ASSERT(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
  if (type == RESULT_ROW_START_INTERP) {
    return pResult->startInterp == true;
  } else {
    return pResult->endInterp == true;
  }
}

static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) {
  if (type == RESULT_ROW_START_INTERP) {
    pResult->startInterp = true;
  } else {
    pResult->endInterp = true;
  }
}

518 519
static void doWindowBorderInterpolation(SIntervalAggOperatorInfo* pInfo, SSDataBlock* pBlock, SResultRow* pResult,
                                        STimeWindow* win, int32_t startPos, int32_t forwardRows, SExprSupp* pSup) {
520
  if (!pInfo->timeWindowInterpo) {
521 522 523
    return;
  }

524
  ASSERT(pBlock != NULL);
525 526 527 528 529
  if (pBlock->pDataBlock == NULL) {
    //    tscError("pBlock->pDataBlock == NULL");
    return;
  }

530
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
531 532

  TSKEY* tsCols = (TSKEY*)(pColInfo->pData);
533
  bool   done = isResultRowInterpolated(pResult, RESULT_ROW_START_INTERP);
534
  if (!done) {  // it is not interpolated, now start to generated the interpolated value
535
    bool interp = setTimeWindowInterpolationStartTs(pInfo, startPos, pBlock, tsCols, win, pSup);
536 537 538 539
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_START_INTERP);
    }
  } else {
540
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_START_INTERP);
541 542 543 544 545 546 547 548
  }

  // point interpolation does not require the end key time window interpolation.
  //  if (pointInterpQuery) {
  //    return;
  //  }

  // interpolation query does not generate the time window end interpolation
549
  done = isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP);
550
  if (!done) {
551
    int32_t endRowIndex = startPos + forwardRows - 1;
552

553
    TSKEY endKey = (pInfo->inputOrder == TSDB_ORDER_ASC) ? pBlock->info.window.ekey : pBlock->info.window.skey;
554
    bool  interp = setTimeWindowInterpolationEndTs(pInfo, pSup, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
555 556 557 558
    if (interp) {
      setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
    }
  } else {
559
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_END_INTERP);
560 561 562
  }
}

563 564
static void saveDataBlockLastRow(SArray* pPrevKeys, const SSDataBlock* pBlock, SArray* pCols) {
  if (pBlock->pDataBlock == NULL) {
565 566 567
    return;
  }

568 569 570 571 572 573 574
  size_t num = taosArrayGetSize(pPrevKeys);
  for (int32_t k = 0; k < num; ++k) {
    SColumn* pc = taosArrayGet(pCols, k);

    SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pc->slotId);

    SGroupKeys* pkey = taosArrayGet(pPrevKeys, k);
X
Xiaoyu Wang 已提交
575
    for (int32_t i = pBlock->info.rows - 1; i >= 0; --i) {
576 577 578 579 580 581 582
      if (colDataIsNull_s(pColInfo, i)) {
        continue;
      }

      char* val = colDataGetData(pColInfo, i);
      if (IS_VAR_DATA_TYPE(pkey->type)) {
        memcpy(pkey->pData, val, varDataTLen(val));
583
        ASSERT(varDataTLen(val) <= pkey->bytes);
584 585 586 587 588 589
      } else {
        memcpy(pkey->pData, val, pkey->bytes);
      }

      break;
    }
590 591 592
  }
}

593 594 595 596
static void doInterpUnclosedTimeWindow(SOperatorInfo* pOperatorInfo, int32_t numOfExprs, SResultRowInfo* pResultRowInfo,
                                       SSDataBlock* pBlock, int32_t scanFlag, int64_t* tsCols, SResultRowPosition* p) {
  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;

597
  SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
598
  SExprSupp*                pSup = &pOperatorInfo->exprSupp;
599

L
Liu Jicong 已提交
600 601
  int32_t startPos = 0;
  int32_t numOfOutput = pSup->numOfExprs;
602

603
  SResultRow* pResult = NULL;
604

605
  while (1) {
L
Liu Jicong 已提交
606 607 608
    SListNode*          pn = tdListGetHead(pResultRowInfo->openWindow);
    SOpenWindowInfo*    pOpenWin = (SOpenWindowInfo*)pn->data;
    uint64_t            groupId = pOpenWin->groupId;
609
    SResultRowPosition* p1 = &pOpenWin->pos;
610 611 612
    if (p->pageId == p1->pageId && p->offset == p1->offset) {
      break;
    }
613

614
    SResultRow* pr = getResultRowByPos(pInfo->aggSup.pResultBuf, p1, false);
615 616 617
    if (NULL == pr) {
      T_LONG_JMP(pTaskInfo->env, terrno);
    }
618

619
    ASSERT(pr->offset == p1->offset && pr->pageId == p1->pageId);
620

621
    if (pr->closed) {
622
      ASSERT(isResultRowInterpolated(pr, RESULT_ROW_START_INTERP) &&
X
Xiaoyu Wang 已提交
623
             isResultRowInterpolated(pr, RESULT_ROW_END_INTERP));
624 625
      SListNode* pNode = tdListPopHead(pResultRowInfo->openWindow);
      taosMemoryFree(pNode);
626 627
      continue;
    }
628

629
    STimeWindow w = pr->win;
630 631
    int32_t     ret = setTimeWindowOutputBuf(pResultRowInfo, &w, (scanFlag == MAIN_SCAN), &pResult, groupId, pSup->pCtx,
                                             numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
632
    if (ret != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
633
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
634 635
    }

636
    ASSERT(!isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
637

X
Xiaoyu Wang 已提交
638 639
    SGroupKeys* pTsKey = taosArrayGet(pInfo->pPrevValues, 0);
    int64_t     prevTs = *(int64_t*)pTsKey->pData;
H
Haojun Liao 已提交
640
    if (groupId == pBlock->info.id.groupId) {
641 642 643
      doTimeWindowInterpolation(pInfo->pPrevValues, pBlock->pDataBlock, prevTs, -1, tsCols[startPos], startPos, w.ekey,
                                RESULT_ROW_END_INTERP, pSup);
    }
644 645

    setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
646
    setNotInterpoWindowKey(pSup->pCtx, numOfExprs, RESULT_ROW_START_INTERP);
647

648
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &w, true);
L
Liu Jicong 已提交
649 650
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, 0,
                                    pBlock->info.rows, numOfExprs);
651 652 653

    if (isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) {
      closeResultRow(pr);
654 655
      SListNode* pNode = tdListPopHead(pResultRowInfo->openWindow);
      taosMemoryFree(pNode);
X
Xiaoyu Wang 已提交
656
    } else {  // the remains are can not be closed yet.
657
      break;
658
    }
659
  }
660
}
661

5
54liuyao 已提交
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
typedef int32_t (*__compare_fn_t)(void* pKey, void* data, int32_t index);

int32_t binarySearchCom(void* keyList, int num, void* pKey, int order, __compare_fn_t comparefn) {
  int firstPos = 0, lastPos = num - 1, midPos = -1;
  int numOfRows = 0;

  if (num <= 0) return -1;
  if (order == TSDB_ORDER_DESC) {
    // find the first position which is smaller or equal than the key
    while (1) {
      if (comparefn(pKey, keyList, lastPos) >= 0) return lastPos;
      if (comparefn(pKey, keyList, firstPos) == 0) return firstPos;
      if (comparefn(pKey, keyList, firstPos) < 0) return firstPos - 1;

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;

      if (comparefn(pKey, keyList, midPos) < 0) {
        lastPos = midPos - 1;
      } else if (comparefn(pKey, keyList, midPos) > 0) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }

  } else {
    // find the first position which is bigger or equal than the key
    while (1) {
      if (comparefn(pKey, keyList, firstPos) <= 0) return firstPos;
      if (comparefn(pKey, keyList, lastPos) == 0) return lastPos;

      if (comparefn(pKey, keyList, lastPos) > 0) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;

      if (comparefn(pKey, keyList, midPos) < 0) {
        lastPos = midPos - 1;
      } else if (comparefn(pKey, keyList, midPos) > 0) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
  }

  return midPos;
}

5
54liuyao 已提交
718
typedef int64_t (*__get_value_fn_t)(void* data, int32_t index);
719

X
Xiaoyu Wang 已提交
720 721 722
int32_t binarySearch(void* keyList, int num, TSKEY key, int order, __get_value_fn_t getValuefn) {
  int firstPos = 0, lastPos = num - 1, midPos = -1;
  int numOfRows = 0;
5
54liuyao 已提交
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768

  if (num <= 0) return -1;
  if (order == TSDB_ORDER_DESC) {
    // find the first position which is smaller or equal than the key
    while (1) {
      if (key >= getValuefn(keyList, lastPos)) return lastPos;
      if (key == getValuefn(keyList, firstPos)) return firstPos;
      if (key < getValuefn(keyList, firstPos)) return firstPos - 1;

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;

      if (key < getValuefn(keyList, midPos)) {
        lastPos = midPos - 1;
      } else if (key > getValuefn(keyList, midPos)) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }

  } else {
    // find the first position which is bigger or equal than the key
    while (1) {
      if (key <= getValuefn(keyList, firstPos)) return firstPos;
      if (key == getValuefn(keyList, lastPos)) return lastPos;

      if (key > getValuefn(keyList, lastPos)) {
        lastPos = lastPos + 1;
        if (lastPos >= num)
          return -1;
        else
          return lastPos;
      }

      numOfRows = lastPos - firstPos + 1;
      midPos = (numOfRows >> 1) + firstPos;

      if (key < getValuefn(keyList, midPos)) {
        lastPos = midPos - 1;
      } else if (key > getValuefn(keyList, midPos)) {
        firstPos = midPos + 1;
      } else {
        break;
      }
    }
769 770
  }

5
54liuyao 已提交
771 772 773
  return midPos;
}

5
54liuyao 已提交
774
int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
L
Liu Jicong 已提交
775
  SArray*          res = (SArray*)data;
5
54liuyao 已提交
776
  SPullWindowInfo* pos = taosArrayGet(res, index);
L
Liu Jicong 已提交
777
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
5
54liuyao 已提交
778
  if (pData->groupId > pos->groupId) {
5
54liuyao 已提交
779
    return 1;
5
54liuyao 已提交
780 781 782 783 784 785 786 787
  } else if (pData->groupId < pos->groupId) {
    return -1;
  }

  if (pData->window.skey > pos->window.ekey) {
    return 1;
  } else if (pData->window.ekey < pos->window.skey) {
    return -1;
5
54liuyao 已提交
788
  }
5
54liuyao 已提交
789
  return 0;
5
54liuyao 已提交
790 791 792 793 794 795 796 797
}

static int32_t savePullWindow(SPullWindowInfo* pPullInfo, SArray* pPullWins) {
  int32_t size = taosArrayGetSize(pPullWins);
  int32_t index = binarySearchCom(pPullWins, size, pPullInfo, TSDB_ORDER_DESC, comparePullWinKey);
  if (index == -1) {
    index = 0;
  } else {
5
54liuyao 已提交
798 799
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
    if (code == 0) {
L
Liu Jicong 已提交
800
      SPullWindowInfo* pos = taosArrayGet(pPullWins, index);
5
54liuyao 已提交
801 802 803 804
      pos->window.skey = TMIN(pos->window.skey, pPullInfo->window.skey);
      pos->window.ekey = TMAX(pos->window.ekey, pPullInfo->window.ekey);
      pos->calWin.skey = TMIN(pos->calWin.skey, pPullInfo->calWin.skey);
      pos->calWin.ekey = TMAX(pos->calWin.ekey, pPullInfo->calWin.ekey);
5
54liuyao 已提交
805
      return TSDB_CODE_SUCCESS;
L
Liu Jicong 已提交
806
    } else if (code > 0) {
5
54liuyao 已提交
807
      index++;
5
54liuyao 已提交
808 809 810 811 812 813 814 815
    }
  }
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
816 817 818
static int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) {
  winInfo.sessionWin.win.ekey = winInfo.sessionWin.win.skey;
  return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
5
54liuyao 已提交
819 820
}

5
54liuyao 已提交
821 822
static int32_t saveWinResult(SWinKey* pKey, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
  tSimpleHashPut(pUpdatedMap, pKey, sizeof(SWinKey), &pPos, POINTER_BYTES);
5
54liuyao 已提交
823
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
824 825
}

5
54liuyao 已提交
826 827 828 829
static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SRowBuffPos* pPos, SSHashObj* pUpdatedMap) {
  SWinKey key = {.ts = ts, .groupId = groupId};
  saveWinResult(&key, pPos, pUpdatedMap);
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
830 831
}

832
static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) {
5
54liuyao 已提交
833 834
  int32_t size = taosArrayGetSize(pWins);
  for (int32_t i = 0; i < size; i++) {
H
Haojun Liao 已提交
835
    SWinKey* pW = taosArrayGet(pWins, i);
836
    void*    tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey));
5
54liuyao 已提交
837 838 839
    if (tmp) {
      void* value = *(void**)tmp;
      taosMemoryFree(value);
840
      tSimpleHashRemove(pUpdatedMap, pW, sizeof(SWinKey));
5
54liuyao 已提交
841
    }
5
54liuyao 已提交
842 843 844
  }
}

845
int32_t compareWinKey(void* pKey, void* data, int32_t index) {
L
liuyao 已提交
846 847
  void* pDataPos = taosArrayGet((SArray*)data, index);
  return winKeyCmprImpl(pKey, pDataPos);
5
54liuyao 已提交
848 849
}

850
static void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
5
54liuyao 已提交
851 852
  taosArraySort(pDelWins, winKeyCmprImpl);
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
L
Liu Jicong 已提交
853
  int32_t delSize = taosArrayGetSize(pDelWins);
854
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
5
54liuyao 已提交
855
    return;
dengyihao's avatar
dengyihao 已提交
856
  }
857 858 859 860 861 862
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) {
    SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL);
    int32_t  index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey);
    if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) {
863
      taosArrayRemove(pDelWins, index);
864
      delSize = taosArrayGetSize(pDelWins);
865 866 867 868
    }
  }
}

5
54liuyao 已提交
869
bool isOverdue(TSKEY ekey, STimeWindowAggSupp* pTwSup) {
5
54liuyao 已提交
870
  ASSERTS(pTwSup->maxTs == INT64_MIN || pTwSup->maxTs > 0, "maxts should greater than 0");
5
54liuyao 已提交
871
  return pTwSup->maxTs != INT64_MIN && ekey < pTwSup->maxTs - pTwSup->waterMark;
5
54liuyao 已提交
872 873
}

5
54liuyao 已提交
874 875 876 877 878
bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) { return isOverdue(pWin->ekey, pTwSup); }

bool needDeleteWindowBuf(STimeWindow* pWin, STimeWindowAggSupp* pTwSup) {
  return pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark;
}
5
54liuyao 已提交
879

5
54liuyao 已提交
880
static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
881
                            int32_t scanFlag) {
882
  SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
883

884
  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
885
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
886

X
Xiaoyu Wang 已提交
887
  int32_t     startPos = 0;
888
  int32_t     numOfOutput = pSup->numOfExprs;
X
Xiaoyu Wang 已提交
889
  int64_t*    tsCols = extractTsCol(pBlock, pInfo);
H
Haojun Liao 已提交
890
  uint64_t    tableGroupId = pBlock->info.id.groupId;
891
  bool        ascScan = (pInfo->inputOrder == TSDB_ORDER_ASC);
X
Xiaoyu Wang 已提交
892 893
  TSKEY       ts = getStartTsKey(&pBlock->info.window, tsCols);
  SResultRow* pResult = NULL;
894

895 896
  STimeWindow win =
      getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, pInfo->inputOrder);
897 898
  int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
                                       pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
899
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
900
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
901
  }
902

X
Xiaoyu Wang 已提交
903 904
  TSKEY   ekey = ascScan ? win.ekey : win.skey;
  int32_t forwardRows =
905
      getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->inputOrder);
906 907

  // prev time window not interpolation yet.
908
  if (pInfo->timeWindowInterpo) {
909
    SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
910
    doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);
911 912

    // restore current time window
913 914
    ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pSup->pCtx,
                                 numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
915
    if (ret != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
916
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
917 918
    }

919
    // window start key interpolation
920
    doWindowBorderInterpolation(pInfo, pBlock, pResult, &win, startPos, forwardRows, pSup);
921
  }
922

923
  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &win, true);
L
Liu Jicong 已提交
924 925
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
                                  pBlock->info.rows, numOfOutput);
926 927

  doCloseWindow(pResultRowInfo, pInfo, pResult);
928 929 930

  STimeWindow nextWin = win;
  while (1) {
931
    int32_t prevEndPos = forwardRows - 1 + startPos;
932
    startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, pInfo->inputOrder);
933 934 935 936
    if (startPos < 0) {
      break;
    }
    // null data, failed to allocate more memory buffer
X
Xiaoyu Wang 已提交
937
    int32_t code = setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
938
                                          pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
939
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
940
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
941 942
    }

X
Xiaoyu Wang 已提交
943
    ekey = ascScan ? nextWin.ekey : nextWin.skey;
944
    forwardRows =
945
        getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->inputOrder);
946
    // window start(end) key interpolation
947
    doWindowBorderInterpolation(pInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pSup);
L
Liu Jicong 已提交
948
    // TODO: add to open window? how to close the open windows after input blocks exhausted?
S
shenglian zhou 已提交
949
#if 0
950 951 952 953
    if ((ascScan && ekey <= pBlock->info.window.ekey) ||
        (!ascScan && ekey >= pBlock->info.window.skey)) {
      // window start(end) key interpolation
      doWindowBorderInterpolation(pInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pSup);
954
    } else if (pInfo->timeWindowInterpo) {
955 956
      addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
    }
S
shenglian zhou 已提交
957
#endif
958
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
L
Liu Jicong 已提交
959 960
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
                                    pBlock->info.rows, numOfOutput);
961
    doCloseWindow(pResultRowInfo, pInfo, pResult);
962 963 964
  }

  if (pInfo->timeWindowInterpo) {
965
    saveDataBlockLastRow(pInfo->pPrevValues, pBlock, pInfo->pInterpCols);
966
  }
967 968 969 970 971 972
}

void doCloseWindow(SResultRowInfo* pResultRowInfo, const SIntervalAggOperatorInfo* pInfo, SResultRow* pResult) {
  // current result is done in computing final results.
  if (pInfo->timeWindowInterpo && isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP)) {
    closeResultRow(pResult);
973
    SListNode* pNode = tdListPopHead(pResultRowInfo->openWindow);
D
dapan1121 已提交
974
    taosMemoryFree(pNode);
975 976 977
  }
}

978 979 980 981 982
SResultRowPosition addToOpenWindowList(SResultRowInfo* pResultRowInfo, const SResultRow* pResult, uint64_t groupId) {
  SOpenWindowInfo openWin = {0};
  openWin.pos.pageId = pResult->pageId;
  openWin.pos.offset = pResult->offset;
  openWin.groupId = groupId;
L
Liu Jicong 已提交
983
  SListNode* pn = tdListGetTail(pResultRowInfo->openWindow);
984
  if (pn == NULL) {
985 986
    tdListAppend(pResultRowInfo->openWindow, &openWin);
    return openWin.pos;
987 988
  }

L
Liu Jicong 已提交
989
  SOpenWindowInfo* px = (SOpenWindowInfo*)pn->data;
990 991
  if (px->pos.pageId != openWin.pos.pageId || px->pos.offset != openWin.pos.offset || px->groupId != openWin.groupId) {
    tdListAppend(pResultRowInfo->openWindow, &openWin);
992 993
  }

994
  return openWin.pos;
995 996 997 998
}

int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo) {
  TSKEY* tsCols = NULL;
999

D
dapan1121 已提交
1000
  if (pBlock->pDataBlock != NULL && pBlock->info.dataLoad) {
1001 1002
    SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
    tsCols = (int64_t*)pColDataInfo->pData;
H
Haojun Liao 已提交
1003
    ASSERT(tsCols[0] != 0);
1004

1005 1006 1007 1008 1009 1010
    // no data in primary ts
    if (tsCols[0] == 0 && tsCols[pBlock->info.rows - 1] == 0) {
      return NULL;
    }

    if (tsCols[0] != 0 && (pBlock->info.window.skey == 0 && pBlock->info.window.ekey == 0)) {
1011 1012 1013 1014 1015
      blockDataUpdateTsWindow(pBlock, pInfo->primaryTsIndex);
    }
  }

  return tsCols;
1016 1017 1018 1019 1020 1021 1022
}

static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
  if (OPTR_IS_OPENED(pOperator)) {
    return TSDB_CODE_SUCCESS;
  }

1023 1024 1025
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SOperatorInfo* downstream = pOperator->pDownstream[0];

1026
  SIntervalAggOperatorInfo* pInfo = pOperator->info;
1027
  SExprSupp*                pSup = &pOperator->exprSupp;
1028

1029
  int32_t scanFlag = MAIN_SCAN;
1030
  int64_t st = taosGetTimestampUs();
1031 1032

  while (1) {
1033
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
1034 1035 1036 1037
    if (pBlock == NULL) {
      break;
    }

1038
    getTableScanInfo(pOperator, &pInfo->inputOrder, &scanFlag, true);
1039

1040
    if (pInfo->scalarSupp.pExprInfo != NULL) {
L
Liu Jicong 已提交
1041 1042
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
1043 1044
    }

1045
    // the pDataBlock are always the same one, no need to call this again
1046
    setInputDataBlock(pSup, pBlock, pInfo->inputOrder, scanFlag, true);
1047
    hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, scanFlag);
1048 1049
  }

1050
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, pInfo->resultTsOrder);
1051
  OPTR_SET_OPENED(pOperator);
1052 1053

  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
1054 1055 1056
  return TSDB_CODE_SUCCESS;
}

1057 1058 1059 1060 1061
static bool compareVal(const char* v, const SStateKeys* pKey) {
  if (IS_VAR_DATA_TYPE(pKey->type)) {
    if (varDataLen(v) != varDataLen(pKey->pData)) {
      return false;
    } else {
D
dapan1121 已提交
1062
      return memcmp(varDataVal(v), varDataVal(pKey->pData), varDataLen(v)) == 0;
1063 1064 1065 1066 1067 1068
    }
  } else {
    return memcmp(pKey->pData, v, pKey->bytes) == 0;
  }
}

1069
static void doStateWindowAggImpl(SOperatorInfo* pOperator, SStateWindowOperatorInfo* pInfo, SSDataBlock* pBlock) {
L
Liu Jicong 已提交
1070
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
1071
  SExprSupp*     pSup = &pOperator->exprSupp;
1072

1073
  SColumnInfoData* pStateColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->stateCol.slotId);
H
Haojun Liao 已提交
1074
  int64_t          gid = pBlock->info.id.groupId;
1075 1076

  bool    masterScan = true;
1077
  int32_t numOfOutput = pOperator->exprSupp.numOfExprs;
1078
  int32_t bytes = pStateColInfoData->info.bytes;
1079

1080
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
1081 1082 1083 1084 1085
  TSKEY*           tsList = (TSKEY*)pColInfoData->pData;

  SWindowRowsSup* pRowSup = &pInfo->winSup;
  pRowSup->numOfRows = 0;

1086
  struct SColumnDataAgg* pAgg = NULL;
1087
  for (int32_t j = 0; j < pBlock->info.rows; ++j) {
X
Xiaoyu Wang 已提交
1088
    pAgg = (pBlock->pBlockAgg != NULL) ? pBlock->pBlockAgg[pInfo->stateCol.slotId] : NULL;
1089
    if (colDataIsNull(pStateColInfoData, pBlock->info.rows, j, pAgg)) {
1090 1091 1092 1093 1094
      continue;
    }

    char* val = colDataGetData(pStateColInfoData, j);

1095
    if (gid != pRowSup->groupId || !pInfo->hasKey) {
1096 1097 1098 1099 1100 1101 1102
      // todo extract method
      if (IS_VAR_DATA_TYPE(pInfo->stateKey.type)) {
        varDataCopy(pInfo->stateKey.pData, val);
      } else {
        memcpy(pInfo->stateKey.pData, val, bytes);
      }

1103 1104
      pInfo->hasKey = true;

1105 1106
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
1107
    } else if (compareVal(val, &pInfo->stateKey)) {
1108
      doKeepTuple(pRowSup, tsList[j], gid);
1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
      if (j == 0 && pRowSup->startRowIndex != 0) {
        pRowSup->startRowIndex = 0;
      }
    } else {  // a new state window started
      SResultRow* pResult = NULL;

      // keep the time window for the closed time window.
      STimeWindow window = pRowSup->win;

      pRowSup->win.ekey = pRowSup->win.skey;
1119 1120
      int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
                                           numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1121
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1122
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1123 1124 1125
      }

      updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &window, false);
H
Haojun Liao 已提交
1126
      applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
L
Liu Jicong 已提交
1127
                                      pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
1128 1129

      // here we start a new session window
1130 1131
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
1132 1133 1134 1135 1136 1137 1138

      // todo extract method
      if (IS_VAR_DATA_TYPE(pInfo->stateKey.type)) {
        varDataCopy(pInfo->stateKey.pData, val);
      } else {
        memcpy(pInfo->stateKey.pData, val, bytes);
      }
1139 1140 1141 1142 1143
    }
  }

  SResultRow* pResult = NULL;
  pRowSup->win.ekey = tsList[pBlock->info.rows - 1];
1144 1145
  int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid,
                                       pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1146
  if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1147
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1148 1149 1150
  }

  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pRowSup->win, false);
L
Liu Jicong 已提交
1151 1152
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
                                  pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
1153 1154
}

H
Hongze Cheng 已提交
1155
static int32_t openStateWindowAggOptr(SOperatorInfo* pOperator) {
1156 1157
  if (OPTR_IS_OPENED(pOperator)) {
    return TSDB_CODE_SUCCESS;
1158 1159 1160
  }

  SStateWindowOperatorInfo* pInfo = pOperator->info;
1161
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
1162

1163 1164 1165
  SExprSupp* pSup = &pOperator->exprSupp;
  int32_t    order = TSDB_ORDER_ASC;
  int64_t    st = taosGetTimestampUs();
1166 1167 1168

  SOperatorInfo* downstream = pOperator->pDownstream[0];
  while (1) {
1169
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
1170 1171 1172 1173
    if (pBlock == NULL) {
      break;
    }

1174
    setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
1175 1176
    blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);

1177 1178 1179 1180 1181 1182 1183 1184 1185
    // there is an scalar expression that needs to be calculated right before apply the group aggregation.
    if (pInfo->scalarSup.pExprInfo != NULL) {
      pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
                                              pInfo->scalarSup.numOfExprs, NULL);
      if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
        T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
      }
    }

1186 1187 1188
    doStateWindowAggImpl(pOperator, pInfo, pBlock);
  }

X
Xiaoyu Wang 已提交
1189
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
1190
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, TSDB_ORDER_ASC);
1191 1192
  pOperator->status = OP_RES_TO_RETURN;

1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
  return TSDB_CODE_SUCCESS;
}

static SSDataBlock* doStateWindowAgg(SOperatorInfo* pOperator) {
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SStateWindowOperatorInfo* pInfo = pOperator->info;
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
  SOptrBasicInfo*           pBInfo = &pInfo->binfo;

  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
H
Haojun Liao 已提交
1207
    setOperatorCompleted(pOperator);
1208 1209 1210
    return NULL;
  }

1211
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
1212
  while (1) {
1213
    doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
1214
    doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
1215

1216
    bool hasRemain = hasRemainResults(&pInfo->groupResInfo);
1217
    if (!hasRemain) {
H
Haojun Liao 已提交
1218
      setOperatorCompleted(pOperator);
1219 1220
      break;
    }
1221

1222 1223 1224 1225
    if (pBInfo->pRes->info.rows > 0) {
      break;
    }
  }
1226

1227
  pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
1228
  return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
1229 1230
}

1231
static SSDataBlock* doBuildIntervalResult(SOperatorInfo* pOperator) {
1232
  SIntervalAggOperatorInfo* pInfo = pOperator->info;
L
Liu Jicong 已提交
1233
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
1234 1235 1236 1237 1238 1239

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

  SSDataBlock* pBlock = pInfo->binfo.pRes;
1240 1241 1242 1243
  pTaskInfo->code = pOperator->fpSet._openFn(pOperator);
  if (pTaskInfo->code != TSDB_CODE_SUCCESS) {
    return NULL;
  }
1244

1245 1246 1247
  while (1) {
    doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
    doFilter(pBlock, pOperator->exprSupp.pFilterInfo, NULL);
1248

1249 1250
    bool hasRemain = hasRemainResults(&pInfo->groupResInfo);
    if (!hasRemain) {
H
Haojun Liao 已提交
1251
      setOperatorCompleted(pOperator);
1252
      break;
1253 1254
    }

1255 1256 1257
    if (pBlock->info.rows > 0) {
      break;
    }
1258
  }
1259 1260 1261 1262 1263

  size_t rows = pBlock->info.rows;
  pOperator->resultInfo.totalRows += rows;

  return (rows == 0) ? NULL : pBlock;
1264 1265
}

5
54liuyao 已提交
1266
static void setInverFunction(SqlFunctionCtx* pCtx, int32_t num, EStreamType type) {
L
Liu Jicong 已提交
1267
  for (int i = 0; i < num; i++) {
5
54liuyao 已提交
1268 1269
    if (type == STREAM_INVERT) {
      fmSetInvertFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
L
Liu Jicong 已提交
1270
    } else if (type == STREAM_NORMAL) {
5
54liuyao 已提交
1271 1272 1273 1274
      fmSetNormalFunc(pCtx[i].functionId, &(pCtx[i].fpSet));
    }
  }
}
5
54liuyao 已提交
1275

5
54liuyao 已提交
1276
static void doClearWindowImpl(SResultRowPosition* p1, SDiskbasedBuf* pResultBuf, SExprSupp* pSup, int32_t numOfOutput) {
1277
  SResultRow* pResult = getResultRowByPos(pResultBuf, p1, false);
1278 1279 1280
  if (NULL == pResult) {
    return;
  }
1281

1282
  SqlFunctionCtx* pCtx = pSup->pCtx;
5
54liuyao 已提交
1283
  for (int32_t i = 0; i < numOfOutput; ++i) {
1284
    pCtx[i].resultInfo = getResultEntryInfo(pResult, i, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
1285 1286 1287 1288 1289 1290 1291 1292 1293
    struct SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo;
    if (fmIsWindowPseudoColumnFunc(pCtx[i].functionId)) {
      continue;
    }
    pResInfo->initialized = false;
    if (pCtx[i].functionId != -1) {
      pCtx[i].fpSet.init(&pCtx[i], pResInfo);
    }
  }
5
54liuyao 已提交
1294
  SFilePage* bufPage = getBufPage(pResultBuf, p1->pageId);
1295 1296 1297
  if (NULL == bufPage) {
    return;
  }
5
54liuyao 已提交
1298 1299
  setBufPageDirty(bufPage, true);
  releaseBufPage(pResultBuf, bufPage);
5
54liuyao 已提交
1300 1301
}

1302
static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) {
1303 1304
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
1305 1306 1307
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
  SWinKey                      key = {.ts = ts, .groupId = groupId};
  tSimpleHashRemove(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey));
1308
  pAPI->stateStore.streamStateDel(pInfo->pState, &key);
5
54liuyao 已提交
1309 1310 1311
  return true;
}

L
liuyao 已提交
1312 1313
static int32_t getChildIndex(SSDataBlock* pBlock) { return pBlock->info.childId; }

1314
static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins,
1315
                            SSHashObj* pUpdatedMap) {
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
  SColumnInfoData*             pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
  TSKEY*                       startTsCols = (TSKEY*)pStartTsCol->pData;
  SColumnInfoData*             pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
  TSKEY*                       endTsCols = (TSKEY*)pEndTsCol->pData;
  SColumnInfoData*             pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
  TSKEY*                       calStTsCols = (TSKEY*)pCalStTsCol->pData;
  SColumnInfoData*             pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
  TSKEY*                       calEnTsCols = (TSKEY*)pCalEnTsCol->pData;
  SColumnInfoData*             pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
  uint64_t*                    pGpDatas = (uint64_t*)pGpCol->pData;
5
54liuyao 已提交
1327
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
H
Haojun Liao 已提交
1328
    SResultRowInfo dumyInfo = {0};
5
54liuyao 已提交
1329
    dumyInfo.cur.pageId = -1;
H
Haojun Liao 已提交
1330

1331 1332 1333 1334 1335 1336 1337 1338
    STimeWindow win = {0};
    if (IS_FINAL_OP(pInfo)) {
      win.skey = startTsCols[i];
      win.ekey = endTsCols[i];
    } else {
      win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC);
    }

5
54liuyao 已提交
1339
    do {
L
liuyao 已提交
1340
      if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i], pBlock->info.type)) {
1341
        getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
1342 1343
        continue;
      }
5
54liuyao 已提交
1344 1345
      uint64_t winGpId = pGpDatas[i];
      SWinKey  winRes = {.ts = win.skey, .groupId = winGpId};
dengyihao's avatar
dengyihao 已提交
1346
      void*    chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
L
liuyao 已提交
1347
      if (chIds) {
L
liuyao 已提交
1348 1349 1350 1351 1352 1353 1354 1355
        int32_t childId = getChildIndex(pBlock);
        SArray* chArray = *(void**)chIds;
        int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
        if (index != -1) {
          qDebug("===stream===try push delete window%" PRId64 "chId:%d ,continue", win.skey, childId);
          getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
          continue;
        }
L
liuyao 已提交
1356
      }
dengyihao's avatar
dengyihao 已提交
1357
      bool res = doDeleteWindow(pOperator, win.skey, winGpId);
5
54liuyao 已提交
1358 1359 1360 1361
      if (pUpWins && res) {
        taosArrayPush(pUpWins, &winRes);
      }
      if (pUpdatedMap) {
1362
        tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey));
5
54liuyao 已提交
1363
      }
1364
      getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
5
54liuyao 已提交
1365
    } while (win.ekey <= endTsCols[i]);
5
54liuyao 已提交
1366 1367 1368
  }
}

1369
static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) {
1370 1371 1372
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1373 1374 1375
    SWinKey* pKey = tSimpleHashGetKey(pIte, NULL);
    uint64_t groupId = pKey->groupId;
    TSKEY    ts = pKey->ts;
5
54liuyao 已提交
1376
    int32_t  code = saveWinResultInfo(ts, groupId, *(SRowBuffPos**)pIte, resWins);
5
54liuyao 已提交
1377 1378 1379 1380 1381 1382 1383
    if (code != TSDB_CODE_SUCCESS) {
      return code;
    }
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
1384
static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval,
1385
                                         SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins,
1386
                                         SOperatorInfo* pOperator) {
5
54liuyao 已提交
1387
  qDebug("===stream===close interval window");
1388 1389 1390
  void*                        pIte = NULL;
  int32_t                      iter = 0;
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1391
  int32_t                      delSize = taosArrayGetSize(pDelWins);
5
54liuyao 已提交
1392
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1393
    void*    key = tSimpleHashGetKey(pIte, NULL);
1394 1395 1396 1397 1398 1399 1400 1401 1402
    SWinKey* pWinKey = (SWinKey*)key;
    if (delSize > 0) {
      int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey);
      if (index >= 0 && 0 == compareWinKey(pWinKey, pDelWins, index)) {
        taosArrayRemove(pDelWins, index);
        delSize = taosArrayGetSize(pDelWins);
      }
    }

5
54liuyao 已提交
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
    void*       chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey));
    STimeWindow win = {
        .skey = pWinKey->ts,
        .ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1,
    };
    if (isCloseWindow(&win, pTwSup)) {
      if (chIds && pPullDataMap) {
        SArray* chAy = *(SArray**)chIds;
        int32_t size = taosArrayGetSize(chAy);
        qDebug("===stream===window %" PRId64 " wait child size:%d", pWinKey->ts, size);
        for (int32_t i = 0; i < size; i++) {
          qDebug("===stream===window %" PRId64 " wait child id:%d", pWinKey->ts, *(int32_t*)taosArrayGet(chAy, i));
        }
        continue;
      } else if (pPullDataMap) {
        qDebug("===stream===close window %" PRId64, pWinKey->ts);
      }

      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
1422
        int32_t code = saveWinResult(pWinKey, *(SRowBuffPos**)pIte, closeWins);
5
54liuyao 已提交
1423 1424 1425 1426 1427
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
      }
      tSimpleHashIterateRemove(pHashMap, pWinKey, sizeof(SWinKey), &pIte, &iter);
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
    }
  }
  return TSDB_CODE_SUCCESS;
}

STimeWindow getFinalTimeWindow(int64_t ts, SInterval* pInterval) {
  STimeWindow w = {.skey = ts, .ekey = INT64_MAX};
  w.ekey = taosTimeAdd(w.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
  return w;
}

1439 1440
static void doBuildDeleteResult(SStreamIntervalOperatorInfo* pInfo, SArray* pWins, int32_t* index,
                                SSDataBlock* pBlock) {
1441 1442 1443 1444 1445 1446 1447 1448
  blockDataCleanup(pBlock);
  int32_t size = taosArrayGetSize(pWins);
  if (*index == size) {
    *index = 0;
    taosArrayClear(pWins);
    return;
  }
  blockDataEnsureCapacity(pBlock, size - *index);
1449
  uint64_t uid = 0;
1450
  for (int32_t i = *index; i < size; i++) {
H
Haojun Liao 已提交
1451
    SWinKey* pWin = taosArrayGet(pWins, i);
1452
    void*    tbname = NULL;
1453
    pInfo->statestore.streamStateGetParName(pInfo->pState, pWin->groupId, &tbname);
1454 1455 1456 1457 1458 1459 1460
    if (tbname == NULL) {
      appendOneRowToStreamSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, NULL);
    } else {
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
      appendOneRowToStreamSpecialBlock(pBlock, &pWin->ts, &pWin->ts, &uid, &pWin->groupId, parTbName);
    }
1461
    pInfo->statestore.streamStateFreeVal(tbname);
1462
    (*index)++;
5
54liuyao 已提交
1463 1464 1465
  }
}

1466
static void destroyStateWindowOperatorInfo(void* param) {
1467
  SStateWindowOperatorInfo* pInfo = (SStateWindowOperatorInfo*)param;
1468
  cleanupBasicInfo(&pInfo->binfo);
1469
  taosMemoryFreeClear(pInfo->stateKey.pData);
1470
  cleanupExprSupp(&pInfo->scalarSup);
D
dapan1121 已提交
1471 1472 1473
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  cleanupAggSup(&pInfo->aggSup);
  cleanupGroupResInfo(&pInfo->groupResInfo);
1474

D
dapan1121 已提交
1475
  taosMemoryFreeClear(param);
1476 1477
}

H
Haojun Liao 已提交
1478
static void freeItem(void* param) {
L
Liu Jicong 已提交
1479
  SGroupKeys* pKey = (SGroupKeys*)param;
H
Haojun Liao 已提交
1480 1481 1482
  taosMemoryFree(pKey->pData);
}

1483
void destroyIntervalOperatorInfo(void* param) {
1484
  SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)param;
1485
  cleanupBasicInfo(&pInfo->binfo);
1486
  cleanupAggSup(&pInfo->aggSup);
1487 1488 1489 1490
  cleanupExprSupp(&pInfo->scalarSupp);

  tdListFree(pInfo->binfo.resultRowInfo.openWindow);

H
Haojun Liao 已提交
1491 1492 1493 1494
  pInfo->pInterpCols = taosArrayDestroy(pInfo->pInterpCols);
  taosArrayDestroyEx(pInfo->pPrevValues, freeItem);

  pInfo->pPrevValues = NULL;
1495

H
Haojun Liao 已提交
1496 1497
  cleanupGroupResInfo(&pInfo->groupResInfo);
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
D
dapan1121 已提交
1498
  taosMemoryFreeClear(param);
1499 1500
}

1501
void destroyStreamFinalIntervalOperatorInfo(void* param) {
1502
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)param;
1503
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
1504
  cleanupAggSup(&pInfo->aggSup);
L
Liu Jicong 已提交
1505
  // it should be empty.
L
liuyao 已提交
1506 1507 1508 1509
  void* pIte = NULL;
  while ((pIte = taosHashIterate(pInfo->pPullDataMap, pIte)) != NULL) {
    taosArrayDestroy(*(void**)pIte);
  }
5
54liuyao 已提交
1510
  taosHashCleanup(pInfo->pPullDataMap);
L
liuyao 已提交
1511
  taosHashCleanup(pInfo->pFinalPullDataMap);
5
54liuyao 已提交
1512 1513
  taosArrayDestroy(pInfo->pPullWins);
  blockDataDestroy(pInfo->pPullDataRes);
L
Liu Jicong 已提交
1514 1515
  taosArrayDestroy(pInfo->pDelWins);
  blockDataDestroy(pInfo->pDelRes);
1516
  pInfo->statestore.streamFileStateDestroy(pInfo->pState->pFileState);
1517
  taosMemoryFreeClear(pInfo->pState);
5
54liuyao 已提交
1518

1519
  nodesDestroyNode((SNode*)pInfo->pPhyNode);
5
54liuyao 已提交
1520
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
5
54liuyao 已提交
1521
  pInfo->groupResInfo.pRows = taosArrayDestroy(pInfo->groupResInfo.pRows);
5
54liuyao 已提交
1522
  cleanupExprSupp(&pInfo->scalarSupp);
1523

D
dapan1121 已提交
1524
  taosMemoryFreeClear(param);
5
54liuyao 已提交
1525 1526
}

1527
static bool allInvertible(SqlFunctionCtx* pFCtx, int32_t numOfCols) {
5
54liuyao 已提交
1528
  for (int32_t i = 0; i < numOfCols; i++) {
5
54liuyao 已提交
1529
    if (fmIsUserDefinedFunc(pFCtx[i].functionId) || !fmIsInvertible(pFCtx[i].functionId)) {
5
54liuyao 已提交
1530 1531 1532 1533 1534 1535
      return false;
    }
  }
  return true;
}

1536
static bool timeWindowinterpNeeded(SqlFunctionCtx* pCtx, int32_t numOfCols, SIntervalAggOperatorInfo* pInfo) {
1537 1538 1539
  // the primary timestamp column
  bool needed = false;

L
Liu Jicong 已提交
1540
  for (int32_t i = 0; i < numOfCols; ++i) {
1541
    SExprInfo* pExpr = pCtx[i].pExpr;
H
Haojun Liao 已提交
1542
    if (fmIsIntervalInterpoFunc(pCtx[i].functionId)) {
1543
      needed = true;
H
Haojun Liao 已提交
1544
      break;
1545 1546 1547
    }
  }

H
Haojun Liao 已提交
1548 1549 1550
  if (needed) {
    pInfo->pInterpCols = taosArrayInit(4, sizeof(SColumn));
    pInfo->pPrevValues = taosArrayInit(4, sizeof(SGroupKeys));
1551

H
Haojun Liao 已提交
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566
    {  // ts column
      SColumn c = {0};
      c.colId = 1;
      c.slotId = pInfo->primaryTsIndex;
      c.type = TSDB_DATA_TYPE_TIMESTAMP;
      c.bytes = sizeof(int64_t);
      taosArrayPush(pInfo->pInterpCols, &c);

      SGroupKeys key;
      key.bytes = c.bytes;
      key.type = c.type;
      key.isNull = true;  // to denote no value is assigned yet
      key.pData = taosMemoryCalloc(1, c.bytes);
      taosArrayPush(pInfo->pPrevValues, &key);
    }
1567 1568
  }

X
Xiaoyu Wang 已提交
1569
  for (int32_t i = 0; i < numOfCols; ++i) {
1570 1571
    SExprInfo* pExpr = pCtx[i].pExpr;

H
Haojun Liao 已提交
1572
    if (fmIsIntervalInterpoFunc(pCtx[i].functionId)) {
1573 1574 1575
      SFunctParam* pParam = &pExpr->base.pParam[0];

      SColumn c = *pParam->pCol;
1576
      taosArrayPush(pInfo->pInterpCols, &c);
1577 1578

      SGroupKeys key = {0};
X
Xiaoyu Wang 已提交
1579 1580
      key.bytes = c.bytes;
      key.type = c.type;
1581
      key.isNull = false;
X
Xiaoyu Wang 已提交
1582
      key.pData = taosMemoryCalloc(1, c.bytes);
1583
      taosArrayPush(pInfo->pPrevValues, &key);
1584 1585 1586 1587 1588 1589
    }
  }

  return needed;
}

L
liuyao 已提交
1590
void initIntervalDownStream(SOperatorInfo* downstream, uint16_t type, SStreamIntervalOperatorInfo* pInfo) {
1591 1592
  SStateStore* pAPI = &downstream->pTaskInfo->storageAPI.stateStore;

1593
  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
L
liuyao 已提交
1594
    initIntervalDownStream(downstream->pDownstream[0], type, pInfo);
1595 1596
    return;
  }
1597

5
54liuyao 已提交
1598
  SStreamScanInfo* pScanInfo = downstream->info;
1599
  pScanInfo->windowSup.parentType = type;
dengyihao's avatar
dengyihao 已提交
1600
  pScanInfo->windowSup.pIntervalAggSup = &pInfo->aggSup;
L
liuyao 已提交
1601
  if (!pScanInfo->pUpdateInfo) {
1602
    pScanInfo->pUpdateInfo = pAPI->updateInfoInitP(&pInfo->interval, pInfo->twAggSup.waterMark);
5
54liuyao 已提交
1603
  }
1604

L
liuyao 已提交
1605 1606 1607
  pScanInfo->interval = pInfo->interval;
  pScanInfo->twAggSup = pInfo->twAggSup;
  pScanInfo->pState = pInfo->pState;
5
54liuyao 已提交
1608 1609
}

H
Haojun Liao 已提交
1610 1611
void initStreamFunciton(SqlFunctionCtx* pCtx, int32_t numOfExpr) {
  for (int32_t i = 0; i < numOfExpr; i++) {
L
Liu Jicong 已提交
1612
    //    pCtx[i].isStream = true;
H
Haojun Liao 已提交
1613 1614 1615
  }
}

H
Haojun Liao 已提交
1616
SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode* pPhyNode,
5
54liuyao 已提交
1617
                                          SExecTaskInfo* pTaskInfo) {
1618
  SIntervalAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
L
Liu Jicong 已提交
1619
  SOperatorInfo*            pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
1620 1621 1622 1623
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

H
Haojun Liao 已提交
1624
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->window.node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
1625 1626 1627 1628 1629 1630
  initBasicInfo(&pInfo->binfo, pResBlock);

  SExprSupp* pSup = &pOperator->exprSupp;
  pInfo->primaryTsIndex = ((SColumnNode*)pPhyNode->window.pTspk)->slotId;

  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
H
Haojun Liao 已提交
1631 1632
  initResultSizeInfo(&pOperator->resultInfo, 512);
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
H
Haojun Liao 已提交
1633 1634 1635

  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pPhyNode->window.pFuncs, NULL, &num);
L
Liu Jicong 已提交
1636
  int32_t    code =
1637
      initAggSup(pSup, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str, pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
H
Haojun Liao 已提交
1638 1639 1640 1641 1642
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  SInterval interval = {.interval = pPhyNode->interval,
1643 1644 1645 1646 1647
                        .sliding = pPhyNode->sliding,
                        .intervalUnit = pPhyNode->intervalUnit,
                        .slidingUnit = pPhyNode->slidingUnit,
                        .offset = pPhyNode->offset,
                        .precision = ((SColumnNode*)pPhyNode->window.pTspk)->node.resType.precision};
H
Haojun Liao 已提交
1648 1649 1650 1651 1652 1653 1654

  STimeWindowAggSupp as = {
      .waterMark = pPhyNode->window.watermark,
      .calTrigger = pPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
  };

L
Liu Jicong 已提交
1655
  pInfo->win = pTaskInfo->window;
1656 1657
  pInfo->inputOrder = (pPhyNode->window.inputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
  pInfo->resultTsOrder = (pPhyNode->window.outputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
H
Haojun Liao 已提交
1658 1659
  pInfo->interval = interval;
  pInfo->twAggSup = as;
1660
  pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock;
1661 1662 1663 1664

  if (pPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pPhyNode->window.pExprs, NULL, &numOfScalar);
1665
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
1666 1667 1668 1669
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }
1670

H
Haojun Liao 已提交
1671 1672 1673 1674 1675
  code = filterInitFromNode((SNode*)pPhyNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

1676
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pInfo->win);
H
Haojun Liao 已提交
1677
  pInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, num, pInfo);
1678
  if (pInfo->timeWindowInterpo) {
1679
    pInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
H
Haojun Liao 已提交
1680 1681 1682
    if (pInfo->binfo.resultRowInfo.openWindow == NULL) {
      goto _error;
    }
1683
  }
1684

1685
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
1686 1687
  setOperatorInfo(pOperator, "TimeIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
1688

L
Liu Jicong 已提交
1689 1690
  pOperator->fpSet = createOperatorFpSet(doOpenIntervalAgg, doBuildIntervalResult, NULL, destroyIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
1691 1692 1693 1694 1695 1696 1697 1698

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

  return pOperator;

L
Liu Jicong 已提交
1699
_error:
H
Haojun Liao 已提交
1700 1701 1702
  if (pInfo != NULL) {
    destroyIntervalOperatorInfo(pInfo);
  }
1703 1704 1705 1706 1707
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}

1708
// todo handle multiple timeline cases. assume no timeline interweaving
1709 1710
static void doSessionWindowAggImpl(SOperatorInfo* pOperator, SSessionAggOperatorInfo* pInfo, SSDataBlock* pBlock) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
1711
  SExprSupp*     pSup = &pOperator->exprSupp;
1712

1713
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
1714 1715

  bool    masterScan = true;
1716
  int32_t numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
1717
  int64_t gid = pBlock->info.id.groupId;
1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731

  int64_t gap = pInfo->gap;

  if (!pInfo->reptScan) {
    pInfo->reptScan = true;
    pInfo->winSup.prevTs = INT64_MIN;
  }

  SWindowRowsSup* pRowSup = &pInfo->winSup;
  pRowSup->numOfRows = 0;

  // In case of ascending or descending order scan data, only one time window needs to be kepted for each table.
  TSKEY* tsList = (TSKEY*)pColInfoData->pData;
  for (int32_t j = 0; j < pBlock->info.rows; ++j) {
1732 1733 1734
    if (gid != pRowSup->groupId || pInfo->winSup.prevTs == INT64_MIN) {
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
H
Haojun Liao 已提交
1735 1736
    } else if (((tsList[j] - pRowSup->prevTs >= 0) && (tsList[j] - pRowSup->prevTs <= gap)) ||
               ((pRowSup->prevTs - tsList[j] >= 0) && (pRowSup->prevTs - tsList[j] <= gap))) {
1737
      // The gap is less than the threshold, so it belongs to current session window that has been opened already.
1738
      doKeepTuple(pRowSup, tsList[j], gid);
1739 1740 1741 1742 1743 1744 1745 1746 1747 1748
      if (j == 0 && pRowSup->startRowIndex != 0) {
        pRowSup->startRowIndex = 0;
      }
    } else {  // start a new session window
      SResultRow* pResult = NULL;

      // keep the time window for the closed time window.
      STimeWindow window = pRowSup->win;

      pRowSup->win.ekey = pRowSup->win.skey;
1749 1750
      int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
                                           numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1751
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1752
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1753 1754 1755 1756
      }

      // pInfo->numOfRows data belong to the current session window
      updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &window, false);
H
Haojun Liao 已提交
1757
      applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
L
Liu Jicong 已提交
1758
                                      pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
1759 1760

      // here we start a new session window
1761 1762
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
1763 1764 1765 1766 1767
    }
  }

  SResultRow* pResult = NULL;
  pRowSup->win.ekey = tsList[pBlock->info.rows - 1];
1768 1769
  int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &pRowSup->win, masterScan, &pResult, gid,
                                       pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1770
  if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1771
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1772 1773 1774
  }

  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pRowSup->win, false);
L
Liu Jicong 已提交
1775 1776
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
                                  pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
1777 1778
}

1779
static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
1780 1781 1782 1783 1784 1785
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SSessionAggOperatorInfo* pInfo = pOperator->info;
  SOptrBasicInfo*          pBInfo = &pInfo->binfo;
1786
  SExprSupp*               pSup = &pOperator->exprSupp;
1787 1788

  if (pOperator->status == OP_RES_TO_RETURN) {
1789
    while (1) {
1790
      doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
1791
      doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
1792

1793
      bool hasRemain = hasRemainResults(&pInfo->groupResInfo);
1794
      if (!hasRemain) {
H
Haojun Liao 已提交
1795
        setOperatorCompleted(pOperator);
1796 1797
        break;
      }
1798

1799 1800 1801 1802 1803
      if (pBInfo->pRes->info.rows > 0) {
        break;
      }
    }
    pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
1804
    return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
1805 1806
  }

1807 1808 1809
  int64_t st = taosGetTimestampUs();
  int32_t order = TSDB_ORDER_ASC;

1810 1811 1812
  SOperatorInfo* downstream = pOperator->pDownstream[0];

  while (1) {
1813
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
1814 1815 1816 1817 1818
    if (pBlock == NULL) {
      break;
    }

    // the pDataBlock are always the same one, no need to call this again
1819
    setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
1820 1821
    blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);

1822 1823 1824
    doSessionWindowAggImpl(pOperator, pInfo, pBlock);
  }

1825 1826
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;

1827 1828 1829
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;

1830
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, TSDB_ORDER_ASC);
1831
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
1832
  while (1) {
1833
    doBuildResultDatablock(pOperator, &pInfo->binfo, &pInfo->groupResInfo, pInfo->aggSup.pResultBuf);
H
Haojun Liao 已提交
1834
    doFilter(pBInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL);
1835

1836
    bool hasRemain = hasRemainResults(&pInfo->groupResInfo);
1837
    if (!hasRemain) {
H
Haojun Liao 已提交
1838
      setOperatorCompleted(pOperator);
1839 1840
      break;
    }
1841

1842 1843 1844 1845 1846
    if (pBInfo->pRes->info.rows > 0) {
      break;
    }
  }
  pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
1847
  return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
1848 1849
}

H
Haojun Liao 已提交
1850
// todo make this as an non-blocking operator
1851 1852
SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWinodwPhysiNode* pStateNode,
                                             SExecTaskInfo* pTaskInfo) {
1853 1854 1855 1856 1857 1858
  SStateWindowOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStateWindowOperatorInfo));
  SOperatorInfo*            pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

1859 1860 1861
  int32_t      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
  SColumnNode* pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;

1862 1863 1864
  if (pStateNode->window.pExprs != NULL) {
    int32_t    numOfScalarExpr = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalarExpr);
1865
    int32_t    code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr, &pTaskInfo->storageAPI.functionStore);
1866 1867 1868 1869 1870
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

1871
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
1872 1873 1874 1875 1876 1877 1878
  pInfo->stateKey.type = pInfo->stateCol.type;
  pInfo->stateKey.bytes = pInfo->stateCol.bytes;
  pInfo->stateKey.pData = taosMemoryCalloc(1, pInfo->stateCol.bytes);
  if (pInfo->stateKey.pData == NULL) {
    goto _error;
  }

H
Haojun Liao 已提交
1879 1880 1881 1882 1883
  int32_t code = filterInitFromNode((SNode*)pStateNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

1884 1885
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;

1886 1887
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &num);
1888
  initResultSizeInfo(&pOperator->resultInfo, 4096);
H
Haojun Liao 已提交
1889

L
Liu Jicong 已提交
1890
  code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
1891
                    pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
1892 1893 1894 1895
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
1896
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pStateNode->window.node.pOutputDataBlockDesc);
1897
  initBasicInfo(&pInfo->binfo, pResBlock);
1898
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
1899

L
Liu Jicong 已提交
1900 1901
  pInfo->twAggSup =
      (STimeWindowAggSupp){.waterMark = pStateNode->window.watermark, .calTrigger = pStateNode->window.triggerType};
1902

1903 1904
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);

X
Xiaoyu Wang 已提交
1905
  pInfo->tsSlotId = tsSlotId;
1906

L
Liu Jicong 已提交
1907 1908
  setOperatorInfo(pOperator, "StateWindowOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE, true, OP_NOT_OPENED, pInfo,
                  pTaskInfo);
L
Liu Jicong 已提交
1909 1910
  pOperator->fpSet = createOperatorFpSet(openStateWindowAggOptr, doStateWindowAgg, NULL, destroyStateWindowOperatorInfo,
                                         optrDefaultBufFn, NULL);
1911

1912 1913 1914 1915 1916
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

1917 1918
  return pOperator;

L
Liu Jicong 已提交
1919
_error:
H
Haojun Liao 已提交
1920 1921 1922 1923
  if (pInfo != NULL) {
    destroyStateWindowOperatorInfo(pInfo);
  }

1924 1925
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
1926 1927 1928
  return NULL;
}

1929
void destroySWindowOperatorInfo(void* param) {
1930
  SSessionAggOperatorInfo* pInfo = (SSessionAggOperatorInfo*)param;
1931 1932 1933
  if (pInfo == NULL) {
    return;
  }
1934

1935
  cleanupBasicInfo(&pInfo->binfo);
H
Haojun Liao 已提交
1936 1937 1938 1939
  colDataDestroy(&pInfo->twAggSup.timeWindowData);

  cleanupAggSup(&pInfo->aggSup);
  cleanupGroupResInfo(&pInfo->groupResInfo);
D
dapan1121 已提交
1940
  taosMemoryFreeClear(param);
1941 1942
}

H
Haojun Liao 已提交
1943
SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionWinodwPhysiNode* pSessionNode,
1944
                                            SExecTaskInfo* pTaskInfo) {
1945 1946 1947 1948 1949 1950
  SSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SSessionAggOperatorInfo));
  SOperatorInfo*           pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

1951
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
1952
  initResultSizeInfo(&pOperator->resultInfo, 4096);
1953

1954
  int32_t      numOfCols = 0;
H
Haojun Liao 已提交
1955
  SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
1956
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pSessionNode->window.node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
1957
  initBasicInfo(&pInfo->binfo, pResBlock);
H
Haojun Liao 已提交
1958

L
Liu Jicong 已提交
1959
  int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
1960
                            pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
1961 1962 1963 1964
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
1965 1966 1967 1968
  pInfo->twAggSup.waterMark = pSessionNode->window.watermark;
  pInfo->twAggSup.calTrigger = pSessionNode->window.triggerType;
  pInfo->gap = pSessionNode->gap;

1969
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
1970 1971
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);

1972
  pInfo->tsSlotId = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
L
Liu Jicong 已提交
1973 1974 1975
  pInfo->binfo.pRes = pResBlock;
  pInfo->winSup.prevTs = INT64_MIN;
  pInfo->reptScan = false;
H
Haojun Liao 已提交
1976 1977 1978 1979
  code = filterInitFromNode((SNode*)pSessionNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
H
Haojun Liao 已提交
1980

L
Liu Jicong 已提交
1981 1982
  setOperatorInfo(pOperator, "SessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
L
Liu Jicong 已提交
1983 1984
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doSessionWindowAgg, NULL, destroySWindowOperatorInfo,
                                         optrDefaultBufFn, NULL);
1985 1986
  pOperator->pTaskInfo = pTaskInfo;
  code = appendDownstream(pOperator, &downstream, 1);
1987 1988 1989 1990
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

1991 1992
  return pOperator;

L
Liu Jicong 已提交
1993
_error:
1994
  destroySWindowOperatorInfo(pInfo);
1995 1996 1997
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
1998
}
5
54liuyao 已提交
1999

5
54liuyao 已提交
2000
void compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t numOfOutput,
2001
                      SExecTaskInfo* pTaskInfo, SColumnInfoData* pTimeWindowData) {
5
54liuyao 已提交
2002 2003
  for (int32_t k = 0; k < numOfOutput; ++k) {
    if (fmIsWindowPseudoColumnFunc(pDestCtx[k].functionId)) {
2004 2005 2006 2007 2008
      if (!pTimeWindowData) {
        continue;
      }

      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pDestCtx[k]);
L
Liu Jicong 已提交
2009 2010
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
      SColumnInfoData      idata = {0};
2011 2012 2013 2014 2015 2016 2017 2018
      idata.info.type = TSDB_DATA_TYPE_BIGINT;
      idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
      idata.pData = p;

      SScalarParam out = {.columnData = &idata};
      SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData};
      pDestCtx[k].sfp.process(&tw, 1, &out);
      pEntryInfo->numOfRes = 1;
L
Liu Jicong 已提交
2019
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
2020
      int32_t code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
5
54liuyao 已提交
2021
      if (code != TSDB_CODE_SUCCESS) {
5
54liuyao 已提交
2022
        qError("%s apply combine functions error, code: %s", GET_TASKID(pTaskInfo), tstrerror(code));
5
54liuyao 已提交
2023
      }
5
54liuyao 已提交
2024 2025 2026 2027
    } else if (pDestCtx[k].fpSet.combine == NULL) {
      char* funName = fmGetFuncName(pDestCtx[k].functionId);
      qError("%s error, combine funcion for %s is not implemented", GET_TASKID(pTaskInfo), funName);
      taosMemoryFreeClear(funName);
5
54liuyao 已提交
2028 2029 2030 2031
    }
  }
}

2032
bool hasIntervalWindow(void* pState, SWinKey* pKey, SStateStore* pStore) { return pStore->streamStateCheck(pState, pKey); }
5
54liuyao 已提交
2033

2034
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
dengyihao's avatar
dengyihao 已提交
2035
                             SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset,
2036 2037 2038
                             SAggSupporter* pAggSup, SStateStore* pStore) {

  SWinKey key = { .ts = win->skey, .groupId = groupId };
5
54liuyao 已提交
2039 2040 2041
  char*   value = NULL;
  int32_t size = pAggSup->resultRowSize;

2042
  if (pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size) < 0) {
5
54liuyao 已提交
2043 2044
    return TSDB_CODE_OUT_OF_MEMORY;
  }
2045

5
54liuyao 已提交
2046 2047
  *pResult = (SRowBuffPos*)value;
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
2048

5
54liuyao 已提交
2049
  // set time window for current result
dengyihao's avatar
dengyihao 已提交
2050
  res->win = (*win);
5
54liuyao 已提交
2051 2052
  setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
  return TSDB_CODE_SUCCESS;
2053 2054
}

2055
bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, void* pState, STimeWindowAggSupp* pTwSup, SStateStore* pStore) {
L
liuyao 已提交
2056
  if (pTwSup->maxTs != INT64_MIN && pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) {
5
54liuyao 已提交
2057
    SWinKey key = {.ts = pWin->skey, .groupId = groupId};
2058
    if (!hasIntervalWindow(pState, &key, pStore)) {
5
54liuyao 已提交
2059
      return true;
5
54liuyao 已提交
2060
    }
5
54liuyao 已提交
2061
    return false;
5
54liuyao 已提交
2062 2063 2064 2065
  }
  return false;
}

L
Liu Jicong 已提交
2066 2067 2068 2069
int32_t getNexWindowPos(SInterval* pInterval, SDataBlockInfo* pBlockInfo, TSKEY* tsCols, int32_t startPos, TSKEY eKey,
                        STimeWindow* pNextWin) {
  int32_t forwardRows =
      getNumOfRowsInTimeWindow(pBlockInfo, tsCols, startPos, eKey, binarySearchForKey, NULL, TSDB_ORDER_ASC);
5
54liuyao 已提交
2070 2071 2072 2073
  int32_t prevEndPos = forwardRows - 1 + startPos;
  return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
}

H
Haojun Liao 已提交
2074
void addPullWindow(SHashObj* pMap, SWinKey* pWinRes, int32_t size) {
5
54liuyao 已提交
2075 2076 2077 2078
  SArray* childIds = taosArrayInit(8, sizeof(int32_t));
  for (int32_t i = 0; i < size; i++) {
    taosArrayPush(childIds, &i);
  }
H
Haojun Liao 已提交
2079
  taosHashPut(pMap, pWinRes, sizeof(SWinKey), &childIds, sizeof(void*));
5
54liuyao 已提交
2080 2081
}

2082
static void clearStreamIntervalOperator(SStreamIntervalOperatorInfo* pInfo) {
2083
  tSimpleHashClear(pInfo->aggSup.pResultRowHashTable);
5
54liuyao 已提交
2084
  clearDiskbasedBuf(pInfo->aggSup.pResultBuf);
2085
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
2086
  pInfo->aggSup.currentPageId = -1;
2087
  pInfo->statestore.streamStateClear(pInfo->pState);
5
54liuyao 已提交
2088 2089
}

5
54liuyao 已提交
2090 2091 2092 2093
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
  if (pBlock->info.rows <= 0) {
    return;
  }
5
54liuyao 已提交
2094 2095 2096
  blockDataCleanup(pBlock);
}

5
54liuyao 已提交
2097 2098 2099 2100 2101 2102
static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pBlock) {
  clearSpecialDataBlock(pBlock);
  int32_t size = taosArrayGetSize(array);
  if (size - (*pIndex) == 0) {
    return;
  }
L
Liu Jicong 已提交
2103
  blockDataEnsureCapacity(pBlock, size - (*pIndex));
2104 2105 2106 2107 2108
  SColumnInfoData* pStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
  SColumnInfoData* pEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
  SColumnInfoData* pGroupId = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
  SColumnInfoData* pCalStartTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
  SColumnInfoData* pCalEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
5
54liuyao 已提交
2109
  for (; (*pIndex) < size; (*pIndex)++) {
L
Liu Jicong 已提交
2110
    SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
2111 2112 2113 2114 2115
    colDataSetVal(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false);
    colDataSetVal(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false);
    colDataSetVal(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false);
    colDataSetVal(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false);
    colDataSetVal(pCalEndTs, pBlock->info.rows, (const char*)&pWin->calWin.ekey, false);
5
54liuyao 已提交
2116 2117 2118 2119 2120 2121 2122 2123 2124
    pBlock->info.rows++;
  }
  if ((*pIndex) == size) {
    *pIndex = 0;
    taosArrayClear(array);
  }
  blockDataUpdateTsWindow(pBlock, 0);
}

L
liuyao 已提交
2125
void processPullOver(SSDataBlock* pBlock, SHashObj* pMap, SHashObj* pFinalMap, SInterval* pInterval, SArray* pPullWins, int32_t numOfCh, SOperatorInfo* pOperator) {
L
liuyao 已提交
2126
  SColumnInfoData* pStartCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
L
Liu Jicong 已提交
2127
  TSKEY*           tsData = (TSKEY*)pStartCol->pData;
L
liuyao 已提交
2128
  SColumnInfoData* pEndCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
5
54liuyao 已提交
2129
  TSKEY*           tsEndData = (TSKEY*)pEndCol->pData;
5
54liuyao 已提交
2130
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
L
Liu Jicong 已提交
2131 2132
  uint64_t*        groupIdData = (uint64_t*)pGroupCol->pData;
  int32_t          chId = getChildIndex(pBlock);
5
54liuyao 已提交
2133
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5
54liuyao 已提交
2134
    TSKEY winTs = tsData[i];
L
liuyao 已提交
2135
    while (winTs <= tsEndData[i]) {
5
54liuyao 已提交
2136 2137 2138 2139 2140 2141
      SWinKey winRes = {.ts = winTs, .groupId = groupIdData[i]};
      void*   chIds = taosHashGet(pMap, &winRes, sizeof(SWinKey));
      if (chIds) {
        SArray* chArray = *(SArray**)chIds;
        int32_t index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
        if (index != -1) {
L
liuyao 已提交
2142
          qDebug("===stream===retrive window %" PRId64 " delete child id %d", winRes.ts, chId);
5
54liuyao 已提交
2143 2144 2145 2146 2147
          taosArrayRemove(chArray, index);
          if (taosArrayGetSize(chArray) == 0) {
            // pull data is over
            taosArrayDestroy(chArray);
            taosHashRemove(pMap, &winRes, sizeof(SWinKey));
L
liuyao 已提交
2148
            qDebug("===stream===retrive pull data over.window %" PRId64 , winRes.ts);
L
liuyao 已提交
2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164

            void* pFinalCh = taosHashGet(pFinalMap, &winRes, sizeof(SWinKey));
            if (pFinalCh) {
              taosHashRemove(pFinalMap, &winRes, sizeof(SWinKey));
              doDeleteWindow(pOperator, winRes.ts, winRes.groupId);
              STimeWindow nextWin = getFinalTimeWindow(winRes.ts, pInterval);
              SPullWindowInfo pull = {.window = nextWin,
                                      .groupId = winRes.groupId,
                                      .calWin.skey = nextWin.skey,
                                      .calWin.ekey = nextWin.skey};
              // add pull data request
              if (savePullWindow(&pull, pPullWins) == TSDB_CODE_SUCCESS) {
                addPullWindow(pMap, &winRes, numOfCh);
                qDebug("===stream===prepare final retrive for delete %" PRId64 ", size:%d", winRes.ts, numOfCh);
              }
            }
5
54liuyao 已提交
2165
          }
5
54liuyao 已提交
2166 2167
        }
      }
5
54liuyao 已提交
2168
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
5
54liuyao 已提交
2169 2170 2171
    }
  }
}
5
54liuyao 已提交
2172

L
liuyao 已提交
2173
static void addRetriveWindow(SArray* wins, SStreamIntervalOperatorInfo* pInfo, int32_t childId) {
2174 2175
  int32_t size = taosArrayGetSize(wins);
  for (int32_t i = 0; i < size; i++) {
L
Liu Jicong 已提交
2176
    SWinKey*    winKey = taosArrayGet(wins, i);
2177
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
L
liuyao 已提交
2178 2179 2180 2181 2182 2183 2184 2185 2186
    if (isOverdue(nextWin.ekey, &pInfo->twAggSup) && pInfo->ignoreExpiredData) {
      continue;
    }
    void* chIds = taosHashGet(pInfo->pPullDataMap, winKey, sizeof(SWinKey));
    if (!chIds) {
      SPullWindowInfo pull = {
          .window = nextWin, .groupId = winKey->groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
      // add pull data request
      if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
L
liuyao 已提交
2187 2188
        addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
        qDebug("===stream===prepare retrive for delete %" PRId64 ", size:%d", winKey->ts, pInfo->numOfChild);
2189
      }
L
liuyao 已提交
2190 2191 2192 2193 2194 2195 2196 2197
    } else {
      SArray* chArray = *(void**)chIds;
      int32_t index = taosArraySearchIdx(chArray, &childId, compareInt32Val, TD_EQ);
      qDebug("===stream===check final retrive %" PRId64",chid:%d", winKey->ts, index);
      if (index == -1) {
        qDebug("===stream===add final retrive %" PRId64, winKey->ts);
        taosHashPut(pInfo->pFinalPullDataMap, winKey, sizeof(SWinKey), NULL, 0);
      }
2198 2199 2200 2201
    }
  }
}

5
54liuyao 已提交
2202 2203 2204 2205 2206 2207
static void clearFunctionContext(SExprSupp* pSup) {
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
    pSup->pCtx[i].saveHandle.currentPage = -1;
  }
}

2208 2209
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
5
54liuyao 已提交
2210 2211
}

2212
int32_t buildDataBlockFromGroupRes(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
5
54liuyao 已提交
2213 2214
                                   SGroupResInfo* pGroupResInfo) {
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2215 2216
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
2217 2218 2219 2220 2221 2222 2223 2224 2225 2226
  SExprInfo*      pExprInfo = pSup->pExprInfo;
  int32_t         numOfExprs = pSup->numOfExprs;
  int32_t*        rowEntryOffset = pSup->rowEntryInfoOffset;
  SqlFunctionCtx* pCtx = pSup->pCtx;

  int32_t numOfRows = getNumOfTotalRes(pGroupResInfo);

  for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) {
    SRowBuffPos* pPos = *(SRowBuffPos**)taosArrayGet(pGroupResInfo->pRows, i);
    SResultRow*  pRow = NULL;
2227
    int32_t      code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
5
54liuyao 已提交
2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
    uint64_t     groupId = ((SWinKey*)pPos->pKey)->groupId;
    ASSERT(code == 0);
    doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset);
    // no results, continue to check the next one
    if (pRow->numOfRows == 0) {
      pGroupResInfo->index += 1;
      continue;
    }
    if (pBlock->info.id.groupId == 0) {
      pBlock->info.id.groupId = groupId;
      void* tbname = NULL;
2239
      if (pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) {
5
54liuyao 已提交
2240 2241 2242 2243
        pBlock->info.parTbName[0] = 0;
      } else {
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
      }
2244
      pAPI->stateStore.streamStateFreeVal(tbname);
5
54liuyao 已提交
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262
    } else {
      // current value belongs to different group, it can't be packed into one datablock
      if (pBlock->info.id.groupId != groupId) {
        break;
      }
    }

    if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) {
      ASSERT(pBlock->info.rows > 0);
      break;
    }
    pGroupResInfo->index += 1;

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

      pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset);
      SResultRowEntryInfo* pEnryInfo = pCtx[j].resultInfo;
H
Haojun Liao 已提交
2263

5
54liuyao 已提交
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284
      if (pCtx[j].fpSet.finalize) {
        int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock);
        if (TAOS_FAILED(code1)) {
          qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1));
          T_LONG_JMP(pTaskInfo->env, code1);
        }
      } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) {
        // do nothing, todo refactor
      } else {
        // expand the result into multiple rows. E.g., _wstart, top(k, 20)
        // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows.
        SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId);
        char*            in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo);
        for (int32_t k = 0; k < pRow->numOfRows; ++k) {
          colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes);
        }
      }
    }

    pBlock->info.rows += pRow->numOfRows;
  }
H
Haojun Liao 已提交
2285

5
54liuyao 已提交
2286 2287 2288 2289 2290
  pBlock->info.dataLoad = 1;
  blockDataUpdateTsWindow(pBlock, 0);
  return TSDB_CODE_SUCCESS;
}

2291
void doBuildStreamIntervalResult(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock,
2292
                                 SGroupResInfo* pGroupResInfo) {
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  // set output datablock version
  pBlock->info.version = pTaskInfo->version;

  blockDataCleanup(pBlock);
  if (!hasRemainResults(pGroupResInfo)) {
    return;
  }

  // clear the existed group id
H
Haojun Liao 已提交
2303
  pBlock->info.id.groupId = 0;
2304
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
2305 2306
}

5
54liuyao 已提交
2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317
static int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo,
                                           TSKEY* primaryKeys, int32_t prevPosition) {
  int32_t startPos = prevPosition + 1;
  if (startPos == pDataBlockInfo->rows) {
    startPos = -1;
  } else {
    *pNext = getFinalTimeWindow(primaryKeys[startPos], pInterval);
  }
  return startPos;
}

dengyihao's avatar
dengyihao 已提交
2318
static void setStreamDataVersion(SExecTaskInfo* pTaskInfo, int64_t version, int64_t ckId) {
L
liuyao 已提交
2319
  pTaskInfo->streamInfo.dataVersion = version;
L
liuyao 已提交
2320
  pTaskInfo->streamInfo.checkPointId = ckId;
L
liuyao 已提交
2321 2322
}

2323
static void doStreamIntervalAggImpl(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataBlock, uint64_t groupId,
2324
                                    SSHashObj* pUpdatedMap) {
2325
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperatorInfo->info;
L
liuyao 已提交
2326
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
2327 2328 2329 2330 2331 2332 2333

  SResultRowInfo* pResultRowInfo = &(pInfo->binfo.resultRowInfo);
  SExecTaskInfo*  pTaskInfo = pOperatorInfo->pTaskInfo;
  SExprSupp*      pSup = &pOperatorInfo->exprSupp;
  int32_t         numOfOutput = pSup->numOfExprs;
  int32_t         step = 1;
  TSKEY*          tsCols = NULL;
5
54liuyao 已提交
2334
  SRowBuffPos*    pResPos = NULL;
2335 2336 2337 2338 2339 2340 2341 2342
  SResultRow*     pResult = NULL;
  int32_t         forwardRows = 0;

  SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
  tsCols = (int64_t*)pColDataInfo->pData;

  int32_t     startPos = 0;
  TSKEY       ts = getStartTsKey(&pSDataBlock->info.window, tsCols);
5
54liuyao 已提交
2343 2344 2345 2346 2347 2348
  STimeWindow nextWin = {0};
  if (IS_FINAL_OP(pInfo)) {
    nextWin = getFinalTimeWindow(ts, &pInfo->interval);
  } else {
    nextWin = getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, TSDB_ORDER_ASC);
  }
2349 2350
  while (1) {
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
L
liuyao 已提交
2351
    if ((pInfo->ignoreExpiredData && isClosed && !IS_FINAL_OP(pInfo)) || !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
2352 2353 2354 2355 2356 2357 2358
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
      if (startPos < 0) {
        break;
      }
      continue;
    }

L
liuyao 已提交
2359
    if (IS_FINAL_OP(pInfo) && pInfo->numOfChild > 0) {
2360 2361 2362 2363 2364 2365
      bool    ignore = true;
      SWinKey winRes = {
          .ts = nextWin.skey,
          .groupId = groupId,
      };
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
2366
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->statestore) && isClosed && !chIds) {
L
Liu Jicong 已提交
2367 2368
        SPullWindowInfo pull = {
            .window = nextWin, .groupId = groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
2369
        // add pull data request
5
54liuyao 已提交
2370
        if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
L
liuyao 已提交
2371
          addPullWindow(pInfo->pPullDataMap, &winRes, pInfo->numOfChild);
5
54liuyao 已提交
2372
        }
2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
      } else {
        int32_t index = -1;
        SArray* chArray = NULL;
        int32_t chId = 0;
        if (chIds) {
          chArray = *(void**)chIds;
          chId = getChildIndex(pSDataBlock);
          index = taosArraySearchIdx(chArray, &chId, compareInt32Val, TD_EQ);
        }
        if (index == -1 || pSDataBlock->info.type == STREAM_PULL_DATA) {
          ignore = false;
        }
      }

      if (ignore) {
L
liuyao 已提交
2388
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
2389 2390 2391 2392 2393 2394 2395
        if (startPos < 0) {
          break;
        }
        continue;
      }
    }

5
54liuyao 已提交
2396
    int32_t code = setIntervalOutputBuf(pInfo->pState, &nextWin, &pResPos, groupId, pSup->pCtx, numOfOutput,
2397
                                        pSup->rowEntryInfoOffset, &pInfo->aggSup, &pInfo->statestore);
dengyihao's avatar
dengyihao 已提交
2398
    pResult = (SResultRow*)pResPos->pRowBuff;
2399
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
2400
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
2401
    }
5
54liuyao 已提交
2402 2403 2404 2405 2406 2407
    if (IS_FINAL_OP(pInfo)) {
      forwardRows = 1;
    } else {
      forwardRows = getNumOfRowsInTimeWindow(&pSDataBlock->info, tsCols, startPos, nextWin.ekey, binarySearchForKey,
                                             NULL, TSDB_ORDER_ASC);
    }
5
54liuyao 已提交
2408 2409

    SWinKey key = {
dengyihao's avatar
dengyihao 已提交
2410 2411
        .ts = pResult->win.skey,
        .groupId = groupId,
5
54liuyao 已提交
2412
    };
2413
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
5
54liuyao 已提交
2414
      saveWinResult(&key, pResPos, pUpdatedMap);
2415
    }
5
54liuyao 已提交
2416 2417

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
2418
      tSimpleHashPut(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey), &pResPos, POINTER_BYTES);
5
54liuyao 已提交
2419
    }
dengyihao's avatar
dengyihao 已提交
2420

2421
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true);
H
Haojun Liao 已提交
2422
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
2423
                                    pSDataBlock->info.rows, numOfOutput);
5
54liuyao 已提交
2424
    key.ts = nextWin.skey;
dengyihao's avatar
dengyihao 已提交
2425

2426 2427 2428 2429
    if (pInfo->delKey.ts > key.ts) {
      pInfo->delKey = key;
    }
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
    if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
      qError("table uid %" PRIu64 " data block timestamp range may not be calculated! minKey %" PRId64
             ",maxKey %" PRId64,
             pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
      blockDataUpdateTsWindow(pSDataBlock, 0);

      // timestamp of the data is incorrect
      if (pSDataBlock->info.window.skey <= 0 || pSDataBlock->info.window.ekey <= 0) {
        qError("table uid %" PRIu64 " data block timestamp is out of range! minKey %" PRId64 ",maxKey %" PRId64,
               pSDataBlock->info.id.uid, pSDataBlock->info.window.skey, pSDataBlock->info.window.ekey);
      }
    }

5
54liuyao 已提交
2443 2444 2445 2446 2447 2448
    if (IS_FINAL_OP(pInfo)) {
      startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos);
    } else {
      startPos =
          getNextQualifiedWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, prevEndPos, TSDB_ORDER_ASC);
    }
2449 2450 2451 2452 2453 2454
    if (startPos < 0) {
      break;
    }
  }
}

5
54liuyao 已提交
2455 2456 2457
static inline int winPosCmprImpl(const void* pKey1, const void* pKey2) {
  SRowBuffPos* pos1 = *(SRowBuffPos**)pKey1;
  SRowBuffPos* pos2 = *(SRowBuffPos**)pKey2;
dengyihao's avatar
dengyihao 已提交
2458 2459
  SWinKey*     pWin1 = (SWinKey*)pos1->pKey;
  SWinKey*     pWin2 = (SWinKey*)pos2->pKey;
5
54liuyao 已提交
2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475

  if (pWin1->groupId > pWin2->groupId) {
    return 1;
  } else if (pWin1->groupId < pWin2->groupId) {
    return -1;
  }

  if (pWin1->ts > pWin2->ts) {
    return 1;
  } else if (pWin1->ts < pWin2->ts) {
    return -1;
  }

  return 0;
}

L
liuyao 已提交
2476 2477 2478 2479 2480 2481 2482 2483 2484
static void resetUnCloseWinInfo(SSHashObj* winMap) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
    SRowBuffPos* pPos = *(SRowBuffPos**)pIte;
    pPos->beUsed = true;
  }
}

5
54liuyao 已提交
2485
static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
2486
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
L
Liu Jicong 已提交
2487
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2488 2489
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
2490 2491
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
  SExprSupp*                   pSup = &pOperator->exprSupp;
2492

5
54liuyao 已提交
2493
  qDebug("interval status %d %s", pOperator->status, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
L
Liu Jicong 已提交
2494

5
54liuyao 已提交
2495 2496 2497
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  } else if (pOperator->status == OP_RES_TO_RETURN) {
5
54liuyao 已提交
2498 2499 2500
    doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
    if (pInfo->pPullDataRes->info.rows != 0) {
      // process the rest of the data
5
54liuyao 已提交
2501
      printDataBlock(pInfo->pPullDataRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
5
54liuyao 已提交
2502 2503 2504
      return pInfo->pPullDataRes;
    }

2505
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
2506 2507 2508 2509 2510 2511
    if (pInfo->pDelRes->info.rows != 0) {
      // process the rest of the data
      printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
      return pInfo->pDelRes;
    }

2512
    doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
2513 2514 2515
    if (pInfo->binfo.pRes->info.rows != 0) {
      printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
      return pInfo->binfo.pRes;
5
54liuyao 已提交
2516
    }
5
54liuyao 已提交
2517

L
liuyao 已提交
2518 2519 2520 2521 2522
    if (pInfo->recvGetAll) {
      pInfo->recvGetAll = false;
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
    }

H
Haojun Liao 已提交
2523
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
2524 2525 2526 2527
    if (!IS_FINAL_OP(pInfo)) {
      clearFunctionContext(&pOperator->exprSupp);
      // semi interval operator clear disk buffer
      clearStreamIntervalOperator(pInfo);
L
liuyao 已提交
2528
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
5
54liuyao 已提交
2529 2530
      qDebug("===stream===clear semi operator");
    } else {
dengyihao's avatar
dengyihao 已提交
2531 2532
      if (pInfo->twAggSup.maxTs > 0 &&
          pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
2533 2534
        pAPI->stateStore.streamStateCommit(pInfo->pState);
        pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
2535 2536
        pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
      }
L
liuyao 已提交
2537
      qDebug("===stream===interval final close");
5
54liuyao 已提交
2538 2539
    }
    return NULL;
5
54liuyao 已提交
2540
  } else {
5
54liuyao 已提交
2541
    if (!IS_FINAL_OP(pInfo)) {
2542
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
2543 2544 2545 2546 2547
      if (pInfo->pDelRes->info.rows != 0) {
        // process the rest of the data
        printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
        return pInfo->pDelRes;
      }
5
54liuyao 已提交
2548
    }
5
54liuyao 已提交
2549 2550
  }

5
54liuyao 已提交
2551
  if (!pInfo->pUpdated) {
L
liuyao 已提交
2552
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
2553 2554 2555
  }
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
2556
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
2557 2558
  }

5
54liuyao 已提交
2559
  while (1) {
H
Haojun Liao 已提交
2560
    if (isTaskKilled(pTaskInfo)) {
H
Haojun Liao 已提交
2561 2562 2563 2564 2565 2566 2567 2568 2569
      if (pInfo->pUpdated != NULL) {
        pInfo->pUpdated = taosArrayDestroy(pInfo->pUpdated);
      }

      if (pInfo->pUpdatedMap != NULL) {
        tSimpleHashCleanup(pInfo->pUpdatedMap);
        pInfo->pUpdatedMap = NULL;
      }

H
Haojun Liao 已提交
2570 2571 2572
      T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
    }

5
54liuyao 已提交
2573 2574
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
2575
      pOperator->status = OP_RES_TO_RETURN;
L
Liu Jicong 已提交
2576 2577
      qDebug("===stream===return data:%s. recv datablock num:%" PRIu64,
             IS_FINAL_OP(pInfo) ? "interval final" : "interval semi", pInfo->numOfDatapack);
5
54liuyao 已提交
2578
      pInfo->numOfDatapack = 0;
5
54liuyao 已提交
2579 2580
      break;
    }
5
54liuyao 已提交
2581
    pInfo->numOfDatapack++;
5
54liuyao 已提交
2582
    printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "interval final recv" : "interval semi recv");
2583

H
Haojun Liao 已提交
2584
    if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) {
5
54liuyao 已提交
2585
      pInfo->binfo.pRes->info.type = pBlock->info.type;
2586 2587
    } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
               pBlock->info.type == STREAM_CLEAR) {
2588
      SArray* delWins = taosArrayInit(8, sizeof(SWinKey));
5
54liuyao 已提交
2589
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap);
2590
      if (IS_FINAL_OP(pInfo)) {
L
liuyao 已提交
2591 2592
        int32_t chId = getChildIndex(pBlock);
        addRetriveWindow(delWins, pInfo, chId);
L
liuyao 已提交
2593 2594 2595
        if (pBlock->info.type != STREAM_CLEAR) {
          taosArrayAddAll(pInfo->pDelWins, delWins);
        }
2596
        taosArrayDestroy(delWins);
2597 2598
        continue;
      }
5
54liuyao 已提交
2599
      removeResults(delWins, pInfo->pUpdatedMap);
2600 2601
      taosArrayAddAll(pInfo->pDelWins, delWins);
      taosArrayDestroy(delWins);
L
liuyao 已提交
2602 2603 2604 2605 2606

      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
      if (pInfo->pDelRes->info.rows != 0) {
        // process the rest of the data
        printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
L
liuyao 已提交
2607 2608 2609 2610 2611
        if (pBlock->info.type == STREAM_CLEAR) {
          pInfo->pDelRes->info.type = STREAM_CLEAR;
        } else {
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
        }
L
liuyao 已提交
2612 2613 2614
        return pInfo->pDelRes;
      }

2615
      break;
5
54liuyao 已提交
2616
    } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_OP(pInfo)) {
L
liuyao 已提交
2617
      pInfo->recvGetAll = true;
5
54liuyao 已提交
2618
      getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
5
54liuyao 已提交
2619
      continue;
5
54liuyao 已提交
2620
    } else if (pBlock->info.type == STREAM_RETRIEVE && !IS_FINAL_OP(pInfo)) {
5
54liuyao 已提交
2621 2622
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap);
      if (taosArrayGetSize(pInfo->pUpdated) > 0) {
5
54liuyao 已提交
2623 2624 2625
        break;
      }
      continue;
L
Liu Jicong 已提交
2626
    } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_OP(pInfo)) {
L
liuyao 已提交
2627
      processPullOver(pBlock, pInfo->pPullDataMap, pInfo->pFinalPullDataMap, &pInfo->interval, pInfo->pPullWins, pInfo->numOfChild, pOperator);
5
54liuyao 已提交
2628
      continue;
5
54liuyao 已提交
2629 2630 2631 2632
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5
54liuyao 已提交
2633
    }
5
54liuyao 已提交
2634

5
54liuyao 已提交
2635 2636 2637 2638
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
2639
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
2640 2641 2642 2643
    doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
5
54liuyao 已提交
2644
  }
S
shenglian zhou 已提交
2645

5
54liuyao 已提交
2646
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
5
54liuyao 已提交
2647
  if (IS_FINAL_OP(pInfo)) {
2648
    closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
5
54liuyao 已提交
2649
                              pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5
54liuyao 已提交
2650
  }
2651
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
5
54liuyao 已提交
2652

2653 2654 2655
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
2656
    taosArrayPush(pInfo->pUpdated, pIte);
5
54liuyao 已提交
2657
  }
H
Haojun Liao 已提交
2658

2659
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
2660
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
2661
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
5
54liuyao 已提交
2662

5
54liuyao 已提交
2663 2664
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
2665
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
2666 2667 2668 2669

  doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes);
  if (pInfo->pPullDataRes->info.rows != 0) {
    // process the rest of the data
5
54liuyao 已提交
2670
    printDataBlock(pInfo->pPullDataRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
5
54liuyao 已提交
2671 2672 2673
    return pInfo->pPullDataRes;
  }

2674
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
5
54liuyao 已提交
2675 2676 2677 2678 2679 2680
  if (pInfo->pDelRes->info.rows != 0) {
    // process the rest of the data
    printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
    return pInfo->pDelRes;
  }

2681
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
2682
  if (pInfo->binfo.pRes->info.rows != 0) {
5
54liuyao 已提交
2683
    printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi");
5
54liuyao 已提交
2684 2685 2686 2687 2688 2689
    return pInfo->binfo.pRes;
  }

  return NULL;
}

5
54liuyao 已提交
2690 2691 2692 2693
int64_t getDeleteMark(SIntervalPhysiNode* pIntervalPhyNode) {
  if (pIntervalPhyNode->window.deleteMark <= 0) {
    return DEAULT_DELETE_MARK;
  }
L
Liu Jicong 已提交
2694
  int64_t deleteMark = TMAX(pIntervalPhyNode->window.deleteMark, pIntervalPhyNode->window.watermark);
5
54liuyao 已提交
2695 2696 2697 2698
  deleteMark = TMAX(deleteMark, pIntervalPhyNode->interval);
  return deleteMark;
}

5
54liuyao 已提交
2699
TSKEY compareTs(void* pKey) {
dengyihao's avatar
dengyihao 已提交
2700
  SWinKey* pWinKey = (SWinKey*)pKey;
5
54liuyao 已提交
2701 2702 2703
  return pWinKey->ts;
}

L
liuyao 已提交
2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726
int32_t getSelectivityBufSize(SqlFunctionCtx* pCtx) {
  if (pCtx->subsidiaries.rowLen == 0) {
    int32_t rowLen = 0;
    for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) {
      SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j];
      rowLen += pc->pExpr->base.resSchema.bytes;
    }

    return rowLen + pCtx->subsidiaries.num * sizeof(bool);
  } else {
    return pCtx->subsidiaries.rowLen;
  }
}

int32_t getMaxFunResSize(SExprSupp* pSup, int32_t numOfCols) {
  int32_t size = 0;
  for (int32_t i = 0; i < numOfCols; ++i) {
      int32_t resSize = getSelectivityBufSize(pSup->pCtx + i);
      size = TMAX(size, resSize);
  }
  return size;
}

L
liuyao 已提交
2727
void streamIntervalReleaseState(SOperatorInfo* pOperator) {
L
liuyao 已提交
2728 2729 2730 2731
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL) {
    SStreamIntervalOperatorInfo* pInfo = pOperator->info;
    int32_t resSize = sizeof(TSKEY);
    pInfo->statestore.streamStateSaveInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME, strlen(STREAM_INTERVAL_OP_STATE_NAME), &pInfo->twAggSup.maxTs, resSize);
L
liuyao 已提交
2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742
  }
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;
  pAPI->stateStore.streamStateCommit(pInfo->pState);
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.releaseStreamStateFn) {
    downstream->fpSet.releaseStreamStateFn(downstream);
  }
}

void streamIntervalReloadState(SOperatorInfo* pOperator) {
L
liuyao 已提交
2743 2744 2745 2746 2747 2748 2749 2750 2751
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL) {
    SStreamIntervalOperatorInfo* pInfo = pOperator->info;
    int32_t size = 0;
    void* pBuf = NULL;
    int32_t code = pInfo->statestore.streamStateGetInfo(pInfo->pState, STREAM_INTERVAL_OP_STATE_NAME,
                                                        strlen(STREAM_INTERVAL_OP_STATE_NAME), &pBuf, &size);
    TSKEY ts = *(TSKEY*)pBuf;
    pInfo->statestore.streamStateReloadInfo(pInfo->pState, ts);
  }
L
liuyao 已提交
2752 2753 2754 2755 2756 2757
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.reloadStreamStateFn) {
    downstream->fpSet.reloadStreamStateFn(downstream);
  }
}

S
shenglian zhou 已提交
2758 2759
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                     SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
2760 2761 2762
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
2763 2764 2765
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
2766

2767
  pOperator->pTaskInfo = pTaskInfo;
2768 2769
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;

S
shenglian zhou 已提交
2770 2771 2772 2773 2774 2775 2776 2777
  pInfo->interval = (SInterval){.interval = pIntervalPhyNode->interval,
                                .sliding = pIntervalPhyNode->sliding,
                                .intervalUnit = pIntervalPhyNode->intervalUnit,
                                .slidingUnit = pIntervalPhyNode->slidingUnit,
                                .offset = pIntervalPhyNode->offset,
                                .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision};
  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pIntervalPhyNode->window.watermark,
5
54liuyao 已提交
2778 2779
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
2780
      .minTs = INT64_MAX,
5
54liuyao 已提交
2781
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
Liu Jicong 已提交
2782 2783
      .deleteMarkSaved = 0,
      .calTriggerSaved = 0,
L
liuyao 已提交
2784
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
2785 2786
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
S
shenglian zhou 已提交
2787
  };
5
54liuyao 已提交
2788
  ASSERTS(pInfo->twAggSup.calTrigger != STREAM_TRIGGER_MAX_DELAY, "trigger type should not be max delay");
5
54liuyao 已提交
2789 2790
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
2791
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
2792 2793 2794
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
2795
    int32_t    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
2796 2797 2798 2799 2800
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

S
shenglian zhou 已提交
2801 2802
  int32_t      numOfCols = 0;
  SExprInfo*   pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
2803
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
5
54liuyao 已提交
2804
  initBasicInfo(&pInfo->binfo, pResBlock);
2805

L
liuyao 已提交
2806 2807
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2808

2809
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
Liu Jicong 已提交
2810
  int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
2811
                            pInfo->pState, &pTaskInfo->storageAPI.functionStore);
2812 2813 2814 2815
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
2816
  initStreamFunciton(pOperator->exprSupp.pCtx, pOperator->exprSupp.numOfExprs);
5
54liuyao 已提交
2817
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2818
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2819

L
liuyao 已提交
2820
  pInfo->numOfChild = numOfChild;
5
54liuyao 已提交
2821

2822
  pInfo->pPhyNode = (SPhysiNode*)nodesCloneNode((SNode*)pPhyNode);
5
54liuyao 已提交
2823

5
54liuyao 已提交
2824 2825 2826 2827
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL) {
    pInfo->isFinal = true;
    pOperator->name = "StreamFinalIntervalOperator";
  } else {
5
54liuyao 已提交
2828
    // semi interval operator does not catch result
5
54liuyao 已提交
2829 2830 2831 2832
    pInfo->isFinal = false;
    pOperator->name = "StreamSemiIntervalOperator";
  }

5
54liuyao 已提交
2833
  if (!IS_FINAL_OP(pInfo) || numOfChild == 0) {
5
54liuyao 已提交
2834 2835
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
  }
2836

5
54liuyao 已提交
2837 2838 2839 2840
  pInfo->pPullWins = taosArrayInit(8, sizeof(SPullWindowInfo));
  pInfo->pullIndex = 0;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
  pInfo->pPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK);
L
liuyao 已提交
2841
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK);
2842
  pInfo->pPullDataRes = createSpecialDataBlock(STREAM_RETRIEVE);
5
54liuyao 已提交
2843
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2844
  pInfo->ignoreExpiredDataSaved = false;
2845
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
2846
  pInfo->delIndex = 0;
H
Haojun Liao 已提交
2847
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
2848 2849
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
2850
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
2851 2852
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
2853
  int32_t funResSize= getMaxFunResSize(&pOperator->exprSupp, numOfCols);
2854
  pInfo->pState->pFileState = pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
2855
                                                  compareTs, pInfo->pState, pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo));
L
liuyao 已提交
2856
  pInfo->dataVersion = 0;
2857
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
2858
  pInfo->recvGetAll = false;
5
54liuyao 已提交
2859

5
54liuyao 已提交
2860
  pOperator->operatorType = pPhyNode->type;
5
54liuyao 已提交
2861 2862 2863 2864
  pOperator->blocking = true;
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;

L
Liu Jicong 已提交
2865 2866
  pOperator->fpSet = createOperatorFpSet(NULL, doStreamFinalIntervalAgg, NULL, destroyStreamFinalIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
2867
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
2868
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL) {
L
liuyao 已提交
2869
    initIntervalDownStream(downstream, pPhyNode->type, pInfo);
2870
  }
5
54liuyao 已提交
2871 2872 2873 2874 2875 2876 2877 2878
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
2879
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5
54liuyao 已提交
2880 2881 2882
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
5
54liuyao 已提交
2883
}
5
54liuyao 已提交
2884 2885

void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
5
54liuyao 已提交
2886
  tSimpleHashCleanup(pSup->pResultRows);
5
54liuyao 已提交
2887 2888
  destroyDiskbasedBuf(pSup->pResultBuf);
  blockDataDestroy(pSup->pScanBlock);
5
54liuyao 已提交
2889 2890
  taosMemoryFreeClear(pSup->pState);
  taosMemoryFreeClear(pSup->pDummyCtx);
5
54liuyao 已提交
2891 2892
}

2893
void destroyStreamSessionAggOperatorInfo(void* param) {
5
54liuyao 已提交
2894
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
2895
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
2896
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
2897

2898 2899 2900
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
2901
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
2902
      destroyOperator(pChild);
2903
    }
5
54liuyao 已提交
2904
    taosArrayDestroy(pInfo->pChildren);
2905
  }
H
Haojun Liao 已提交
2906

5
54liuyao 已提交
2907 2908 2909 2910
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
  blockDataDestroy(pInfo->pWinBlock);
  blockDataDestroy(pInfo->pUpdateRes);
5
54liuyao 已提交
2911
  tSimpleHashCleanup(pInfo->pStDeleted);
2912

H
Haojun Liao 已提交
2913
  taosArrayDestroy(pInfo->historyWins);
D
dapan1121 已提交
2914
  taosMemoryFreeClear(param);
5
54liuyao 已提交
2915 2916
}

2917
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
2918
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
H
Haojun Liao 已提交
2919
  initBasicInfo(pBasicInfo, pResultBlock);
2920
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
2921 2922 2923
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
2924

H
Haojun Liao 已提交
2925
  initStreamFunciton(pSup->pCtx, pSup->numOfExprs);
5
54liuyao 已提交
2926
  for (int32_t i = 0; i < numOfCols; ++i) {
2927
    pSup->pCtx[i].saveHandle.pBuf = NULL;
5
54liuyao 已提交
2928
  }
2929

2930
  ASSERT(numOfCols > 0);
5
54liuyao 已提交
2931 2932 2933 2934 2935 2936
  return TSDB_CODE_SUCCESS;
}

void initDummyFunction(SqlFunctionCtx* pDummy, SqlFunctionCtx* pCtx, int32_t nums) {
  for (int i = 0; i < nums; i++) {
    pDummy[i].functionId = pCtx[i].functionId;
2937 2938
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
5
54liuyao 已提交
2939 2940
  }
}
5
54liuyao 已提交
2941

5
54liuyao 已提交
2942 2943
void initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
                    STimeWindowAggSupp* pTwSup) {
2944 2945 2946 2947 2948 2949
  if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION) {
    SStreamPartitionOperatorInfo* pScanInfo = downstream->info;
    pScanInfo->tsColIndex = tsColIndex;
  }

  if (downstream->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) {
5
54liuyao 已提交
2950
    initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup);
2951 2952
    return;
  }
2953
  SStreamScanInfo* pScanInfo = downstream->info;
5
54liuyao 已提交
2954
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
L
fix bug  
liuyao 已提交
2955
  pScanInfo->pState = pAggSup->pState;
J
jiajingbin 已提交
2956
  if (!pScanInfo->pUpdateInfo) {
2957
    pScanInfo->pUpdateInfo = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark);
5
54liuyao 已提交
2958
  }
5
54liuyao 已提交
2959
  pScanInfo->twAggSup = *pTwSup;
5
54liuyao 已提交
2960 2961
}

5
54liuyao 已提交
2962
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, int64_t gap,
H
Haojun Liao 已提交
2963
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore) {
5
54liuyao 已提交
2964 2965 2966 2967 2968 2969 2970 2971
  pSup->resultRowSize = keySize + getResultRowSize(pCtx, numOfOutput);
  pSup->pScanBlock = createSpecialDataBlock(STREAM_CLEAR);
  pSup->gap = gap;
  pSup->stateKeySize = keySize;
  pSup->stateKeyType = keyType;
  pSup->pDummyCtx = (SqlFunctionCtx*)taosMemoryCalloc(numOfOutput, sizeof(SqlFunctionCtx));
  if (pSup->pDummyCtx == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
2972
  }
H
Haojun Liao 已提交
2973

2974 2975
  pSup->stateStore = *pStore;

5
54liuyao 已提交
2976 2977 2978
  initDummyFunction(pSup->pDummyCtx, pCtx, numOfOutput);
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pSup->pState) = *pState;
2979
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1);
2980

5
54liuyao 已提交
2981 2982
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
  pSup->pResultRows = tSimpleHashInit(32, hashFn);
X
Xiaoyu Wang 已提交
2983

5
54liuyao 已提交
2984 2985 2986
  int32_t pageSize = 4096;
  while (pageSize < pSup->resultRowSize * 4) {
    pageSize <<= 1u;
5
54liuyao 已提交
2987
  }
5
54liuyao 已提交
2988 2989 2990 2991
  // at least four pages need to be in buffer
  int32_t bufSize = 4096 * 256;
  if (bufSize <= pageSize) {
    bufSize = pageSize * 4;
5
54liuyao 已提交
2992
  }
2993

5
54liuyao 已提交
2994
  if (!osTempSpaceAvailable()) {
2995 2996
    terrno = TSDB_CODE_NO_DISKSPACE;
    qError("Init stream agg supporter failed since %s, tempDir:%s", terrstr(), tsTempDir);
5
54liuyao 已提交
2997
    return terrno;
5
54liuyao 已提交
2998
  }
H
Haojun Liao 已提交
2999

5
54liuyao 已提交
3000 3001 3002
  int32_t code = createDiskbasedBuf(&pSup->pResultBuf, pageSize, bufSize, "function", tsTempDir);
  for (int32_t i = 0; i < numOfOutput; ++i) {
    pCtx[i].saveHandle.pBuf = pSup->pResultBuf;
5
54liuyao 已提交
3003 3004
  }

5
54liuyao 已提交
3005
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3006
}
5
54liuyao 已提交
3007 3008

bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5
54liuyao 已提交
3009
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5
54liuyao 已提交
3010 3011 3012 3013 3014
    return true;
  }
  return false;
}

5
54liuyao 已提交
3015 3016
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
5
54liuyao 已提交
3017 3018
}

5
54liuyao 已提交
3019 3020 3021 3022 3023
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SSessionKey* pKey) {
  pKey->win.skey = startTs;
  pKey->win.ekey = endTs;
  pKey->groupId = groupId;
3024
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
5
54liuyao 已提交
3025 3026
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_KEY_INVALID(pKey);
3027 3028 3029
  }
}

5
54liuyao 已提交
3030
bool isInvalidSessionWin(SResultWindowInfo* pWinInfo) { return pWinInfo->sessionWin.win.skey == 0; }
5
54liuyao 已提交
3031

5
54liuyao 已提交
3032 3033 3034
void setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SResultWindowInfo* pCurWin) {
  pCurWin->sessionWin.groupId = groupId;
3035 3036
  pCurWin->sessionWin.win.skey = startTs;
  pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3037
  int32_t size = pAggSup->resultRowSize;
3038 3039
  int32_t code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin,
                                                                     pAggSup->gap, &pCurWin->pOutputBuf, &size);
5
54liuyao 已提交
3040 3041 3042 3043 3044
  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->isOutput = true;
  } else {
    pCurWin->sessionWin.win.skey = startTs;
    pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3045
  }
5
54liuyao 已提交
3046
}
5
54liuyao 已提交
3047

5
54liuyao 已提交
3048 3049
int32_t getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo) {
  int32_t size = 0;
3050
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin, &pWinInfo->pOutputBuf, &size);
5
54liuyao 已提交
3051 3052
  if (code != TSDB_CODE_SUCCESS) {
    return code;
5
54liuyao 已提交
3053
  }
3054 3055

  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
5
54liuyao 已提交
3056 3057 3058 3059 3060
  return TSDB_CODE_SUCCESS;
}
void saveDeleteInfo(SArray* pWins, SSessionKey key) {
  // key.win.ekey = key.win.skey;
  taosArrayPush(pWins, &key);
5
54liuyao 已提交
3061 3062
}

5
54liuyao 已提交
3063 3064 3065 3066
void saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
  key.win.ekey = key.win.skey;
  tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
}
3067

5
54liuyao 已提交
3068 3069 3070 3071 3072
static void removeSessionResult(SSHashObj* pHashMap, SSHashObj* pResMap, SSessionKey key) {
  key.win.ekey = key.win.skey;
  tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
  tSimpleHashRemove(pResMap, &key, sizeof(SSessionKey));
}
5
54liuyao 已提交
3073

5
54liuyao 已提交
3074 3075 3076 3077 3078
static void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
  *pHashKey = *pKey;
  pHashKey->win.ekey = pKey->win.skey;
}

5
54liuyao 已提交
3079 3080 3081
static void removeSessionResults(SSHashObj* pHashMap, SArray* pWins) {
  if (tSimpleHashGetSize(pHashMap) == 0) {
    return;
5
54liuyao 已提交
3082
  }
5
54liuyao 已提交
3083 3084 3085 3086
  int32_t size = taosArrayGetSize(pWins);
  for (int32_t i = 0; i < size; i++) {
    SSessionKey* pWin = taosArrayGet(pWins, i);
    if (!pWin) continue;
5
54liuyao 已提交
3087 3088
    SSessionKey key = {0};
    getSessionHashKey(pWin, &key);
5
54liuyao 已提交
3089
    tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
5
54liuyao 已提交
3090 3091 3092
  }
}

dengyihao's avatar
dengyihao 已提交
3093
int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t groupId,
5
54liuyao 已提交
3094 3095
                                int32_t rows, int32_t start, int64_t gap, SSHashObj* pResultRows, SSHashObj* pStUpdated,
                                SSHashObj* pStDeleted) {
5
54liuyao 已提交
3096
  for (int32_t i = start; i < rows; ++i) {
3097
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
5
54liuyao 已提交
3098 3099
      return i - start;
    }
5
54liuyao 已提交
3100
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
5
54liuyao 已提交
3101
      if (pStDeleted && pWinInfo->isOutput) {
5
54liuyao 已提交
3102
        saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
5
54liuyao 已提交
3103
      }
5
54liuyao 已提交
3104 3105
      removeSessionResult(pStUpdated, pResultRows, pWinInfo->sessionWin);
      pWinInfo->sessionWin.win.skey = pStartTs[i];
5
54liuyao 已提交
3106
    }
5
54liuyao 已提交
3107
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
5
54liuyao 已提交
3108
    if (pEndTs) {
5
54liuyao 已提交
3109
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
5
54liuyao 已提交
3110 3111 3112 3113 3114
    }
  }
  return rows - start;
}

5
54liuyao 已提交
3115 3116
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
3117
  ASSERT(pWinInfo->sessionWin.win.skey <= pWinInfo->sessionWin.win.ekey);
5
54liuyao 已提交
3118
  *pResult = (SResultRow*)pWinInfo->pOutputBuf;
5
54liuyao 已提交
3119
  // set time window for current result
5
54liuyao 已提交
3120
  (*pResult)->win = pWinInfo->sessionWin.win;
3121
  setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
5
54liuyao 已提交
3122 3123 3124
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3125 3126 3127
static int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
                                  int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
                                  SOperatorInfo* pOperator) {
3128
  SExprSupp*     pSup = &pOperator->exprSupp;
3129
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3130
  int32_t        code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
3131
  if (code != TSDB_CODE_SUCCESS || (*pResult) == NULL) {
S
Shengliang Guan 已提交
3132
    return TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
3133
  }
5
54liuyao 已提交
3134
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, false);
H
Haojun Liao 已提交
3135
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
5
54liuyao 已提交
3136 3137 3138
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3139
static bool doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
3140
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
5
54liuyao 已提交
3141 3142 3143
  SSessionKey hashKey = {0};
  getSessionHashKey(pKey, &hashKey);
  tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
5
54liuyao 已提交
3144 3145 3146 3147 3148 3149 3150 3151 3152 3153
  return true;
}

static int32_t setSessionWinOutputInfo(SSHashObj* pStUpdated, SResultWindowInfo* pWinInfo) {
  void* pVal = tSimpleHashGet(pStUpdated, &pWinInfo->sessionWin, sizeof(SSessionKey));
  if (pVal) {
    SResultWindowInfo* pWin = pVal;
    pWinInfo->isOutput = pWin->isOutput;
  }
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3154 3155
}

5
54liuyao 已提交
3156 3157
SStreamStateCur* getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
                                       SResultWindowInfo* pNextWin) {
3158
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
5
54liuyao 已提交
3159 3160 3161 3162
  pNextWin->isOutput = true;
  setSessionWinOutputInfo(pStUpdated, pNextWin);
  int32_t size = 0;
  pNextWin->sessionWin = pCurWin->sessionWin;
3163
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin, &pNextWin->pOutputBuf, &size);
5
54liuyao 已提交
3164
  if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
3165
    taosMemoryFreeClear(pNextWin->pOutputBuf);
5
54liuyao 已提交
3166 3167 3168
    SET_SESSION_WIN_INVALID(*pNextWin);
  }
  return pCur;
5
54liuyao 已提交
3169 3170
}

5
54liuyao 已提交
3171 3172 3173 3174
static void compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
                                 SSHashObj* pStDeleted) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3175 3176
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3177 3178 3179 3180 3181
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SResultRow*                    pCurResult = NULL;
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  initSessionOutputBuf(pCurWin, &pCurResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
3182
  // Just look for the window behind StartIndex
5
54liuyao 已提交
3183 3184 3185 3186
  while (1) {
    SResultWindowInfo winInfo = {0};
    SStreamStateCur*  pCur = getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap)) {
dengyihao's avatar
dengyihao 已提交
3187
      taosMemoryFree(winInfo.pOutputBuf);
3188
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3189
      break;
5
54liuyao 已提交
3190
    }
5
54liuyao 已提交
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201
    SResultRow* pWinResult = NULL;
    initSessionOutputBuf(&winInfo, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, true);
    compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pInfo->twAggSup.timeWindowData);
    tSimpleHashRemove(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey));
    if (winInfo.isOutput && pStDeleted) {
      saveDeleteRes(pStDeleted, winInfo.sessionWin);
    }
    removeSessionResult(pStUpdated, pAggSup->pResultRows, winInfo.sessionWin);
    doDeleteSessionWindow(pAggSup, &winInfo.sessionWin);
3202
    pAPI->stateStore.streamStateFreeCur(pCur);
dengyihao's avatar
dengyihao 已提交
3203
    taosMemoryFree(winInfo.pOutputBuf);
5
54liuyao 已提交
3204 3205 3206
  }
}

5
54liuyao 已提交
3207
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
3208
  saveSessionDiscBuf(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pOutputBuf, pAggSup->resultRowSize, &pAggSup->stateStore);
5
54liuyao 已提交
3209
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3210 3211
}

5
54liuyao 已提交
3212 3213
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
                                   SSHashObj* pStDeleted, bool hasEndTs) {
X
Xiaoyu Wang 已提交
3214
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3215
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3216
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
3217
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
3218
  int64_t                        code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3219 3220 3221
  SResultRow*                    pResult = NULL;
  int32_t                        rows = pSDataBlock->info.rows;
  int32_t                        winRows = 0;
X
Xiaoyu Wang 已提交
3222

L
liuyao 已提交
3223 3224
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);

5
54liuyao 已提交
3225
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3226
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
5
54liuyao 已提交
3227 3228 3229
  SColumnInfoData* pEndTsCol = NULL;
  if (hasEndTs) {
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
5
54liuyao 已提交
3230
  } else {
5
54liuyao 已提交
3231
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3232
  }
X
Xiaoyu Wang 已提交
3233

5
54liuyao 已提交
3234
  TSKEY*               endTsCols = (int64_t*)pEndTsCol->pData;
5
54liuyao 已提交
3235
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3236
  for (int32_t i = 0; i < rows;) {
5
54liuyao 已提交
3237
    if (pInfo->ignoreExpiredData && isOverdue(endTsCols[i], &pInfo->twAggSup)) {
5
54liuyao 已提交
3238 3239 3240
      i++;
      continue;
    }
5
54liuyao 已提交
3241 3242 3243 3244 3245
    SResultWindowInfo winInfo = {0};
    setSessionOutputBuf(pAggSup, startTsCols[i], endTsCols[i], groupId, &winInfo);
    setSessionWinOutputInfo(pStUpdated, &winInfo);
    winRows = updateSessionWindowInfo(&winInfo, startTsCols, endTsCols, groupId, rows, i, pAggSup->gap,
                                      pAggSup->pResultRows, pStUpdated, pStDeleted);
5
54liuyao 已提交
3246 3247
    // coverity scan error
    if (!winInfo.pOutputBuf) {
S
Shengliang Guan 已提交
3248
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3249
    }
L
Liu Jicong 已提交
3250

5
54liuyao 已提交
3251 3252
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
                              pOperator);
5
54liuyao 已提交
3253
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
3254
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3255
    }
5
54liuyao 已提交
3256 3257
    compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted);
    saveSessionOutputBuf(pAggSup, &winInfo);
5
54liuyao 已提交
3258 3259

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
5
54liuyao 已提交
3260
      code = saveResult(winInfo, pStUpdated);
5
54liuyao 已提交
3261
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
3262
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3263
      }
5
54liuyao 已提交
3264
    }
5
54liuyao 已提交
3265
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
3266 3267
      SSessionKey key = {0};
      getSessionHashKey(&winInfo.sessionWin, &key);
5
54liuyao 已提交
3268 3269 3270
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
    }

5
54liuyao 已提交
3271 3272 3273 3274
    i += winRows;
  }
}

5
54liuyao 已提交
3275
static void doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
5
54liuyao 已提交
3276
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3277
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
5
54liuyao 已提交
3278
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3279
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
3280
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3281
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
5
54liuyao 已提交
3282
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5
54liuyao 已提交
3283 3284 3285 3286
    while (1) {
      SSessionKey curWin = {0};
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
3287 3288
        break;
      }
5
54liuyao 已提交
3289 3290 3291 3292
      doDeleteSessionWindow(pAggSup, &curWin);
      if (result) {
        saveDeleteInfo(result, curWin);
      }
3293
    }
5
54liuyao 已提交
3294 3295 3296
  }
}

5
54liuyao 已提交
3297 3298 3299 3300 3301 3302 3303 3304
static inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) {
  SSessionKey* pWin1 = (SSessionKey*)pKey1;
  SSessionKey* pWin2 = (SSessionKey*)pKey2;

  if (pWin1->groupId > pWin2->groupId) {
    return 1;
  } else if (pWin1->groupId < pWin2->groupId) {
    return -1;
5
54liuyao 已提交
3305 3306
  }

5
54liuyao 已提交
3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319
  if (pWin1->win.skey > pWin2->win.skey) {
    return 1;
  } else if (pWin1->win.skey < pWin2->win.skey) {
    return -1;
  }

  return 0;
}

static int32_t copyUpdateResult(SSHashObj* pStUpdated, SArray* pUpdated) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pStUpdated, pIte, &iter)) != NULL) {
3320
    void* key = tSimpleHashGetKey(pIte, NULL);
5
54liuyao 已提交
3321 3322 3323 3324 3325 3326
    taosArrayPush(pUpdated, key);
  }
  taosArraySort(pUpdated, sessionKeyCompareAsc);
  return TSDB_CODE_SUCCESS;
}

3327
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
3328 3329
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;

5
54liuyao 已提交
3330 3331 3332 3333
  blockDataCleanup(pBlock);
  int32_t size = tSimpleHashGetSize(pStDeleted);
  if (size == 0) {
    return;
3334 3335
  }
  blockDataEnsureCapacity(pBlock, size);
5
54liuyao 已提交
3336 3337 3338 3339 3340
  int32_t iter = 0;
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
      break;
    }
3341
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
3342
    SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3343
    colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3344
    SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3345
    colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3346
    SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
3347
    colDataSetNULL(pUidCol, pBlock->info.rows);
5
54liuyao 已提交
3348
    SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3349
    colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false);
3350
    SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
3351
    colDataSetNULL(pCalStCol, pBlock->info.rows);
3352
    SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
3353
    colDataSetNULL(pCalEdCol, pBlock->info.rows);
3354 3355

    SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
3356 3357

    void* tbname = NULL;
3358
    pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, res->groupId, &tbname);
3359
    if (tbname == NULL) {
3360
      colDataSetNULL(pTableCol, pBlock->info.rows);
3361 3362 3363
    } else {
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
3364
      colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
3365
      pAPI->stateStore.streamStateFreeVal(tbname);
3366
    }
5
54liuyao 已提交
3367 3368 3369
    pBlock->info.rows += 1;
  }
  if ((*Ite) == NULL) {
5
54liuyao 已提交
3370
    tSimpleHashClear(pStDeleted);
5
54liuyao 已提交
3371 3372 3373
  }
}

5
54liuyao 已提交
3374 3375 3376
static void rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3377 3378
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3379 3380 3381 3382
  int32_t                        size = taosArrayGetSize(pWinArray);
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  int32_t                        numOfOutput = pSup->numOfExprs;
L
liuyao 已提交
3383
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
3384

3385
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3386 3387 3388
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
    int32_t           num = 0;
    SResultWindowInfo parentWin = {0};
L
liuyao 已提交
3389
    for (int32_t j = 0; j < numOfChild; j++) {
X
Xiaoyu Wang 已提交
3390
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
3391
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
5
54liuyao 已提交
3392
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
5
54liuyao 已提交
3393 3394
      SSessionKey                    chWinKey = {0};
      getSessionHashKey(pWinKey, &chWinKey);
3395
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
3396 3397
      SResultRow*      pResult = NULL;
      SResultRow*      pChResult = NULL;
5
54liuyao 已提交
3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409
      while (1) {
        SResultWindowInfo childWin = {0};
        childWin.sessionWin = *pWinKey;
        int32_t code = getSessionWinBuf(pChAggSup, pCur, &childWin);
        if (code == TSDB_CODE_SUCCESS && pWinKey->win.skey <= childWin.sessionWin.win.skey &&
            childWin.sessionWin.win.ekey <= pWinKey->win.ekey) {
          if (num == 0) {
            setSessionOutputBuf(pAggSup, pWinKey->win.skey, pWinKey->win.ekey, pWinKey->groupId, &parentWin);
            code = initSessionOutputBuf(&parentWin, &pResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
            if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
              break;
            }
3410
          }
5
54liuyao 已提交
3411 3412 3413 3414 3415 3416 3417 3418
          num++;
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, true);
          initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
                               pChild->exprSupp.rowEntryInfoOffset);
          compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo, &pInfo->twAggSup.timeWindowData);
          compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL);
          saveResult(parentWin, pStUpdated);
        } else {
5
54liuyao 已提交
3419
          break;
3420 3421
        }
      }
3422
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3423 3424 3425
    }
    if (num > 0) {
      saveSessionOutputBuf(pAggSup, &parentWin);
3426 3427 3428 3429
    }
  }
}

5
54liuyao 已提交
3430 3431 3432 3433 3434 3435 3436 3437 3438 3439
int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
    SResultWindowInfo* pWinInfo = pIte;
    if (isCloseWindow(&pWinInfo->sessionWin.win, pTwSup)) {
      if (pTwSup->calTrigger == STREAM_TRIGGER_WINDOW_CLOSE && pClosed) {
        int32_t code = saveResult(*pWinInfo, pClosed);
        if (code != TSDB_CODE_SUCCESS) {
          return code;
5
54liuyao 已提交
3440 3441
        }
      }
3442
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
3443
      tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
5
54liuyao 已提交
3444 3445 3446 3447 3448
    }
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3449
static void closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
5
54liuyao 已提交
3450 3451 3452 3453 3454
  int32_t size = taosArrayGetSize(pChildren);
  for (int32_t i = 0; i < size; i++) {
    SOperatorInfo*                 pChildOp = taosArrayGetP(pChildren, i);
    SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
    pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs);
5
54liuyao 已提交
3455
    closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
5
54liuyao 已提交
3456 3457 3458
  }
}

5
54liuyao 已提交
3459 3460 3461 3462
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
3463
    SResultWindowInfo* pWinInfo = pIte;
5
54liuyao 已提交
3464
    saveResult(*pWinInfo, pStUpdated);
5
54liuyao 已提交
3465 3466 3467 3468
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3469
static void copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
5
54liuyao 已提交
3470 3471
  int32_t size = taosArrayGetSize(pResWins);
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3472 3473
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
    if (!pWinKey) continue;
5
54liuyao 已提交
3474 3475
    SSessionKey winInfo = {0};
    getSessionHashKey(pWinKey, &winInfo);
5
54liuyao 已提交
3476
    tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
3477 3478 3479
  }
}

H
Haojun Liao 已提交
3480
// the allocated memory comes from outer function.
5
54liuyao 已提交
3481 3482 3483
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
  pGroupResInfo->pRows = pArrayList;
  pGroupResInfo->index = 0;
H
Haojun Liao 已提交
3484
  pGroupResInfo->pBuf = NULL;
3485 3486
}

3487
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo,
5
54liuyao 已提交
3488 3489 3490 3491 3492 3493 3494
                          SSDataBlock* pBlock) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  // set output datablock version
  pBlock->info.version = pTaskInfo->version;

  blockDataCleanup(pBlock);
  if (!hasRemainResults(pGroupResInfo)) {
H
Haojun Liao 已提交
3495
    cleanupGroupResInfo(pGroupResInfo);
3496 3497 3498
    return;
  }

5
54liuyao 已提交
3499
  // clear the existed group id
H
Haojun Liao 已提交
3500
  pBlock->info.id.groupId = 0;
3501
  buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
5
54liuyao 已提交
3502
}
L
liuyao 已提交
3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522
void getMaxTsWins(const SArray* pAllWins, SArray* pMaxWins) {
  int32_t size = taosArrayGetSize(pAllWins);
  if (size == 0) {
    return;
  }

  SSessionKey* pSeKey = taosArrayGet(pAllWins, size - 1);
  taosArrayPush(pMaxWins, pSeKey);
  if (pSeKey->groupId == 0) {
    return;
  }
  uint64_t preGpId = pSeKey->groupId;
  for (int32_t i = size - 2; i >= 0; i--) {
    pSeKey = taosArrayGet(pAllWins, i);
    if (preGpId != pSeKey->groupId) {
      taosArrayPush(pMaxWins, pSeKey);
      preGpId = pSeKey->groupId;
    }
  }
}
5
54liuyao 已提交
3523

5
54liuyao 已提交
3524
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
5
54liuyao 已提交
3525
  SExprSupp*                     pSup = &pOperator->exprSupp;
5
54liuyao 已提交
3526
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
3527
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
5
54liuyao 已提交
3528
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3529 3530 3531
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  } else if (pOperator->status == OP_RES_TO_RETURN) {
3532
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3533
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3534
      printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3535 3536
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3537 3538 3539 3540
    doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
    if (pBInfo->pRes->info.rows > 0) {
      printDataBlock(pBInfo->pRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
      return pBInfo->pRes;
5
54liuyao 已提交
3541
    }
5
54liuyao 已提交
3542

H
Haojun Liao 已提交
3543
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
3544
    return NULL;
5
54liuyao 已提交
3545 3546 3547
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3548 3549 3550 3551
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3552
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3553 3554
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3555 3556 3557 3558 3559
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
3560
    printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "final session recv" : "single session recv");
3561

5
54liuyao 已提交
3562 3563 3564
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
5
54liuyao 已提交
3565
      // gap must be 0
5
54liuyao 已提交
3566
      doDeleteTimeWindows(pAggSup, pBlock, pWins);
5
54liuyao 已提交
3567
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3568 3569 3570 3571 3572
      if (IS_FINAL_OP(pInfo)) {
        int32_t                        childIndex = getChildIndex(pBlock);
        SOperatorInfo*                 pChildOp = taosArrayGetP(pInfo->pChildren, childIndex);
        SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info;
        // gap must be 0
5
54liuyao 已提交
3573
        doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
5
54liuyao 已提交
3574
        rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
5
54liuyao 已提交
3575 3576 3577 3578
      }
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
      taosArrayDestroy(pWins);
      continue;
3579
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3580
      getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3581
      continue;
5
54liuyao 已提交
3582 3583 3584 3585
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5
54liuyao 已提交
3586
    }
5
54liuyao 已提交
3587

5
54liuyao 已提交
3588 3589 3590 3591
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
3592
    // the pDataBlock are always the same one, no need to call this again
3593
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3594
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo));
5
54liuyao 已提交
3595 3596 3597 3598 3599
    if (IS_FINAL_OP(pInfo)) {
      int32_t chIndex = getChildIndex(pBlock);
      int32_t size = taosArrayGetSize(pInfo->pChildren);
      // if chIndex + 1 - size > 0, add new child
      for (int32_t i = 0; i < chIndex + 1 - size; i++) {
3600 3601
        SOperatorInfo* pChildOp =
            createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0);
5
54liuyao 已提交
3602
        if (!pChildOp) {
S
Shengliang Guan 已提交
3603
          T_LONG_JMP(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3604 3605 3606
        }
        taosArrayPush(pInfo->pChildren, &pChildOp);
      }
3607
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
3608
      setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3609
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true);
3610
    }
5
54liuyao 已提交
3611 3612
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
5
54liuyao 已提交
3613 3614 3615
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
3616

5
54liuyao 已提交
3617
  closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
5
54liuyao 已提交
3618
  closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
5
54liuyao 已提交
3619 3620 3621 3622
  copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pStUpdated);
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3623 3624 3625
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }
5
54liuyao 已提交
3626 3627
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
3628
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3629

3630 3631 3632 3633 3634 3635
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

3636
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3637
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3638
    printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3639 3640
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3641 3642 3643 3644 3645 3646 3647

  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
  if (pBInfo->pRes->info.rows > 0) {
    printDataBlock(pBInfo->pRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
    return pBInfo->pRes;
  }

H
Haojun Liao 已提交
3648
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3649
  return NULL;
5
54liuyao 已提交
3650 3651
}

L
liuyao 已提交
3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686
void streamSessionReleaseState(SOperatorInfo* pOperator) {
  if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION) {
    SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
    int32_t resSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
    pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_SESSION_OP_STATE_NAME, strlen(STREAM_SESSION_OP_STATE_NAME), pInfo->historyWins->pData, resSize);
  }
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.releaseStreamStateFn) {
    downstream->fpSet.releaseStreamStateFn(downstream);
  }
}

void streamSessionReloadState(SOperatorInfo* pOperator) {
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
  SResultWindowInfo winInfo = {0};
  int32_t size = 0;
  void* pBuf = NULL;
  int32_t code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
                                                        strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
  int32_t num = size / sizeof(SSessionKey);
  SSessionKey* pSeKeyBuf = (SSessionKey*) pBuf;
  ASSERT(size == num * sizeof(SSessionKey));
  for (int32_t i = 0; i < num; i++) {
    SResultWindowInfo winInfo = {0};
    setSessionOutputBuf(pAggSup, pSeKeyBuf[i].win.skey, pSeKeyBuf[i].win.ekey, pSeKeyBuf[i].groupId, &winInfo);
    compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted);
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.reloadStreamStateFn) {
    downstream->fpSet.reloadStreamStateFn(downstream);
  } 
}

5
54liuyao 已提交
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703
SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                  SExecTaskInfo* pTaskInfo) {
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
  int32_t                        numOfCols = 0;
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

  pOperator->pTaskInfo = pTaskInfo;

  initResultSizeInfo(&pOperator->resultInfo, 4096);
  if (pSessionNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pSessionNode->window.pExprs, NULL, &numOfScalar);
3704
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3705 3706
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
5
54liuyao 已提交
3707 3708
    }
  }
5
54liuyao 已提交
3709 3710 3711
  SExprSupp* pSup = &pOperator->exprSupp;

  SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
3712
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3713
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3714 3715 3716 3717 3718
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, pSessionNode->gap,
H
Haojun Liao 已提交
3719
                                pTaskInfo->streamInfo.pState, 0, 0, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pSessionNode->window.watermark,
      .calTrigger = pSessionNode->window.triggerType,
      .maxTs = INT64_MIN,
      .minTs = INT64_MAX,
  };

  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);

  pInfo->primaryTsIndex = ((SColumnNode*)pSessionNode->window.pTspk)->slotId;
  if (pSessionNode->window.pTsEnd) {
    pInfo->endTsIndex = ((SColumnNode*)pSessionNode->window.pTsEnd)->slotId;
  }
  pInfo->binfo.pRes = pResBlock;
  pInfo->order = TSDB_ORDER_ASC;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
  pInfo->pStDeleted = tSimpleHashInit(64, hashFn);
  pInfo->pDelIterator = NULL;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
  pInfo->pChildren = NULL;
  pInfo->isFinal = false;
  pInfo->pPhyNode = pPhyNode;
  pInfo->ignoreExpiredData = pSessionNode->window.igExpired;
3747
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
3748 3749
  pInfo->pUpdated = NULL;
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3750
  pInfo->dataVersion = 0;
L
liuyao 已提交
3751 3752 3753 3754 3755
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
  pInfo->isHistoryOp = false;
5
54liuyao 已提交
3756

H
Haojun Liao 已提交
3757 3758
  setOperatorInfo(pOperator, "StreamSessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
                  OP_NOT_OPENED, pInfo, pTaskInfo);
L
Liu Jicong 已提交
3759 3760
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionAgg, NULL, destroyStreamSessionAggOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
3761
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
H
Haojun Liao 已提交
3762

5
54liuyao 已提交
3763
  if (downstream) {
5
54liuyao 已提交
3764
    initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780
    code = appendDownstream(pOperator, &downstream, 1);
  }
  return pOperator;

_error:
  if (pInfo != NULL) {
    destroyStreamSessionAggOperatorInfo(pInfo);
  }

  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}

static void clearStreamSessionOperator(SStreamSessionAggOperatorInfo* pInfo) {
  tSimpleHashClear(pInfo->streamAggSup.pResultRows);
3781
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
5
54liuyao 已提交
3782 3783 3784 3785 3786 3787 3788
}

static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) {
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
  TSKEY                          maxTs = INT64_MIN;
  SExprSupp*                     pSup = &pOperator->exprSupp;
5
54liuyao 已提交
3789
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
3790

5
54liuyao 已提交
3791 3792
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3793
  }
L
Liu Jicong 已提交
3794

3795
  {
5
54liuyao 已提交
3796
    doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3797
    if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3798
      printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3799 3800 3801
      return pBInfo->pRes;
    }

3802
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3803
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3804
      printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3805 3806
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3807

3808
    if (pOperator->status == OP_RES_TO_RETURN) {
5
54liuyao 已提交
3809
      clearFunctionContext(&pOperator->exprSupp);
3810 3811
      // semi interval operator clear disk buffer
      clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3812
      setOperatorCompleted(pOperator);
3813 3814
      return NULL;
    }
5
54liuyao 已提交
3815 3816 3817
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3818 3819 3820 3821
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3822
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3823 3824
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3825 3826 3827
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
3828
      clearSpecialDataBlock(pInfo->pUpdateRes);
3829
      pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
3830 3831
      break;
    }
H
Haojun Liao 已提交
3832
    printDataBlock(pBlock, "semi session recv");
5
54liuyao 已提交
3833

5
54liuyao 已提交
3834 3835
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
3836
      // gap must be 0
3837
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
5
54liuyao 已提交
3838
      doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins);
5
54liuyao 已提交
3839
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3840
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
3841
      taosArrayDestroy(pWins);
5
54liuyao 已提交
3842
      break;
5
54liuyao 已提交
3843
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3844
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3845
      continue;
5
54liuyao 已提交
3846 3847 3848 3849
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5
54liuyao 已提交
3850 3851
    }

5
54liuyao 已提交
3852 3853 3854 3855
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
5
54liuyao 已提交
3856
    // the pDataBlock are always the same one, no need to call this again
3857
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3858
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false);
5
54liuyao 已提交
3859 3860 3861 3862
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
  }

  pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs);
3863
  pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs;
3864

5
54liuyao 已提交
3865 3866 3867 3868 3869 3870
  copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pStUpdated);
  pInfo->pStUpdated = NULL;
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
3871
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3872

3873 3874 3875 3876 3877 3878
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===semi session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5
54liuyao 已提交
3879
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3880
  if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3881
    printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3882 3883 3884
    return pBInfo->pRes;
  }

3885
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3886
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3887
    printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3888 3889
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3890

5
54liuyao 已提交
3891 3892 3893
  clearFunctionContext(&pOperator->exprSupp);
  // semi interval operator clear disk buffer
  clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3894
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3895
  return NULL;
5
54liuyao 已提交
3896
}
3897

3898 3899
SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                       SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
3900 3901
  int32_t        code = TSDB_CODE_OUT_OF_MEMORY;
  SOperatorInfo* pOperator = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo);
3902 3903 3904
  if (pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3905

3906
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
3907
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
5
54liuyao 已提交
3908

H
Haojun Liao 已提交
3909
  pInfo->isFinal = (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION);
L
Liu Jicong 已提交
3910
  char* name = (pInfo->isFinal) ? "StreamSessionFinalAggOperator" : "StreamSessionSemiAggOperator";
H
Haojun Liao 已提交
3911 3912

  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
H
Haojun Liao 已提交
3913
    pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR);
5
54liuyao 已提交
3914
    blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
3915 3916
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAgg, NULL,
                                           destroyStreamSessionAggOperatorInfo, optrDefaultBufFn, NULL);
5
54liuyao 已提交
3917
  }
L
liuyao 已提交
3918
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
L
Liu Jicong 已提交
3919
  setOperatorInfo(pOperator, name, pPhyNode->type, false, OP_NOT_OPENED, pInfo, pTaskInfo);
H
Haojun Liao 已提交
3920

5
54liuyao 已提交
3921 3922 3923 3924
  pOperator->operatorType = pPhyNode->type;
  if (numOfChild > 0) {
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
    for (int32_t i = 0; i < numOfChild; i++) {
5
54liuyao 已提交
3925 3926
      SOperatorInfo* pChildOp = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
      if (pChildOp == NULL) {
5
54liuyao 已提交
3927 3928
        goto _error;
      }
5
54liuyao 已提交
3929 3930
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
3931
      pAPI->stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i);
5
54liuyao 已提交
3932
      taosArrayPush(pInfo->pChildren, &pChildOp);
3933 3934
    }
  }
3935 3936 3937 3938 3939

  if (!IS_FINAL_OP(pInfo) || numOfChild == 0) {
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
  }

3940 3941 3942 3943
  return pOperator;

_error:
  if (pInfo != NULL) {
3944
    destroyStreamSessionAggOperatorInfo(pInfo);
3945 3946 3947 3948 3949
  }
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
5
54liuyao 已提交
3950

3951
void destroyStreamStateOperatorInfo(void* param) {
X
Xiaoyu Wang 已提交
3952
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
3953
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
3954
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
3955 3956 3957 3958
  cleanupGroupResInfo(&pInfo->groupResInfo);
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3959
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
3960
      destroyOperator(pChild);
5
54liuyao 已提交
3961
    }
5
54liuyao 已提交
3962
    taosArrayDestroy(pInfo->pChildren);
5
54liuyao 已提交
3963
  }
5
54liuyao 已提交
3964 3965
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
5
54liuyao 已提交
3966
  tSimpleHashCleanup(pInfo->pSeDeleted);
D
dapan1121 已提交
3967
  taosMemoryFreeClear(param);
5
54liuyao 已提交
3968 3969 3970
}

bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
5
54liuyao 已提交
3971
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
5
54liuyao 已提交
3972 3973 3974 3975 3976 3977
    return true;
  }
  return false;
}

bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
5
54liuyao 已提交
3978 3979 3980 3981
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
}

bool compareStateKey(void* data, void* key) {
L
liuyao 已提交
3982 3983 3984
  if (!data || !key) {
    return true;
  }
5
54liuyao 已提交
3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996
  SStateKeys* stateKey = (SStateKeys*)key;
  stateKey->pData = (char*)key + sizeof(SStateKeys);
  return compareVal(data, stateKey);
}

void setStateOutputBuf(SStreamAggSupporter* pAggSup, TSKEY ts, uint64_t groupId, char* pKeyData,
                       SStateWindowInfo* pCurWin, SStateWindowInfo* pNextWin) {
  int32_t size = pAggSup->resultRowSize;
  pCurWin->winInfo.sessionWin.groupId = groupId;
  pCurWin->winInfo.sessionWin.win.skey = ts;
  pCurWin->winInfo.sessionWin.win.ekey = ts;
  int32_t code =
3997
      pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData, pAggSup->stateKeySize,
5
54liuyao 已提交
3998 3999 4000 4001 4002 4003 4004 4005 4006 4007
                                    compareStateKey, &pCurWin->winInfo.pOutputBuf, &size);
  pCurWin->pStateKey =
      (SStateKeys*)((char*)pCurWin->winInfo.pOutputBuf + (pAggSup->resultRowSize - pAggSup->stateKeySize));
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
  pCurWin->pStateKey->isNull = false;

  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->winInfo.isOutput = true;
L
liuyao 已提交
4008
  } else if (pKeyData) {
5
54liuyao 已提交
4009 4010 4011 4012
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
    } else {
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
5
54liuyao 已提交
4013 4014 4015
    }
  }

5
54liuyao 已提交
4016 4017
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
  pNextWin->winInfo.pOutputBuf = NULL;
4018 4019
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->winInfo.sessionWin);
  code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin, NULL, 0);
5
54liuyao 已提交
4020 4021
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
5
54liuyao 已提交
4022
  }
4023
  pAggSup->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
4024 4025
}

5
54liuyao 已提交
4026
int32_t updateStateWindowInfo(SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin, TSKEY* pTs, uint64_t groupId,
H
Haojun Liao 已提交
4027
                              SColumnInfoData* pKeyCol, int32_t rows, int32_t start, bool* allEqual,
5
54liuyao 已提交
4028
                              SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted) {
5
54liuyao 已提交
4029 4030 4031 4032
  *allEqual = true;
  for (int32_t i = start; i < rows; ++i) {
    char* pKeyData = colDataGetData(pKeyCol, i);
    if (!isTsInWindow(pWinInfo, pTs[i])) {
X
Xiaoyu Wang 已提交
4033
      if (isEqualStateKey(pWinInfo, pKeyData)) {
5
54liuyao 已提交
4034
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
5
54liuyao 已提交
4035
          // ts belongs to the next window
5
54liuyao 已提交
4036
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
5
54liuyao 已提交
4037 4038 4039 4040 4041 4042 4043
            return i - start;
          }
        }
      } else {
        return i - start;
      }
    }
5
54liuyao 已提交
4044 4045

    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
H
Haojun Liao 已提交
4046
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
5
54liuyao 已提交
4047
        saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
5
54liuyao 已提交
4048
      }
5
54liuyao 已提交
4049 4050
      removeSessionResult(pSeUpdated, pResultRows, pWinInfo->winInfo.sessionWin);
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
5
54liuyao 已提交
4051
    }
5
54liuyao 已提交
4052
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
5
54liuyao 已提交
4053 4054 4055 4056 4057 4058 4059
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
      *allEqual = false;
    }
  }
  return rows - start;
}

5
54liuyao 已提交
4060 4061
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
                                 SSHashObj* pStDeleted) {
4062 4063 4064
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
4065
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4066
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
4067
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
4068 4069 4070 4071
  int64_t                      code = TSDB_CODE_SUCCESS;
  TSKEY*                       tsCols = NULL;
  SResultRow*                  pResult = NULL;
  int32_t                      winRows = 0;
L
liuyao 已提交
4072 4073 4074

  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);

5
54liuyao 已提交
4075
  if (pSDataBlock->pDataBlock != NULL) {
X
Xiaoyu Wang 已提交
4076 4077
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
    tsCols = (int64_t*)pColDataInfo->pData;
5
54liuyao 已提交
4078
  } else {
X
Xiaoyu Wang 已提交
4079
    return;
5
54liuyao 已提交
4080
  }
L
Liu Jicong 已提交
4081

5
54liuyao 已提交
4082
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
4083 4084
  int32_t              rows = pSDataBlock->info.rows;
  blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
L
Liu Jicong 已提交
4085
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
5
54liuyao 已提交
4086
  for (int32_t i = 0; i < rows; i += winRows) {
4087
    if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup) || colDataIsNull_s(pKeyColInfo, i)) {
5
54liuyao 已提交
4088 4089 4090
      i++;
      continue;
    }
5
54liuyao 已提交
4091 4092 4093 4094 4095 4096 4097 4098 4099
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
    int32_t          winIndex = 0;
    bool             allEqual = true;
    SStateWindowInfo curWin = {0};
    SStateWindowInfo nextWin = {0};
    setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin);
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
    winRows = updateStateWindowInfo(&curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
                                    pAggSup->pResultRows, pSeUpdated, pStDeleted);
5
54liuyao 已提交
4100
    if (!allEqual) {
4101
      uint64_t uid = 0;
5
54liuyao 已提交
4102 4103 4104 4105
      appendOneRowToStreamSpecialBlock(pAggSup->pScanBlock, &curWin.winInfo.sessionWin.win.skey,
                                       &curWin.winInfo.sessionWin.win.ekey, &uid, &groupId, NULL);
      tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
      doDeleteSessionWindow(pAggSup, &curWin.winInfo.sessionWin);
4106
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)curWin.winInfo.pOutputBuf, &pAPI->stateStore);
5
54liuyao 已提交
4107 4108
      continue;
    }
5
54liuyao 已提交
4109 4110
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
                              pOperator);
5
54liuyao 已提交
4111
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4112
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4113
    }
5
54liuyao 已提交
4114 4115
    saveSessionOutputBuf(pAggSup, &curWin.winInfo);

5
54liuyao 已提交
4116
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
5
54liuyao 已提交
4117
      code = saveResult(curWin.winInfo, pSeUpdated);
5
54liuyao 已提交
4118
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
4119
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4120 4121
      }
    }
4122 4123

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
4124 4125
      SSessionKey key = {0};
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
4126 4127
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
    }
5
54liuyao 已提交
4128 4129 4130 4131 4132 4133 4134 4135
  }
}

static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) {
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

4136
  SExprSupp*                   pSup = &pOperator->exprSupp;
5
54liuyao 已提交
4137
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
4138
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
5
54liuyao 已提交
4139
  if (pOperator->status == OP_RES_TO_RETURN) {
4140
    doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4141
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4142
      printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4143 4144
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
4145 4146 4147 4148 4149

    doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes);
    if (pBInfo->pRes->info.rows > 0) {
      printDataBlock(pBInfo->pRes, "single state");
      return pBInfo->pRes;
5
54liuyao 已提交
4150
    }
5
54liuyao 已提交
4151

H
Haojun Liao 已提交
4152
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
4153
    return NULL;
5
54liuyao 已提交
4154 4155 4156
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
4157 4158 4159 4160
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pSeUpdated) {
4161
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4162 4163
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
4164 4165 4166 4167 4168
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
4169
    printDataBlock(pBlock, "single state recv");
4170

5
54liuyao 已提交
4171 4172 4173 4174
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
      doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins);
5
54liuyao 已提交
4175
      removeSessionResults(pInfo->pSeUpdated, pWins);
5
54liuyao 已提交
4176
      copyDeleteWindowInfo(pWins, pInfo->pSeDeleted);
4177 4178
      taosArrayDestroy(pWins);
      continue;
4179
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
4180
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
5
54liuyao 已提交
4181
      continue;
5
54liuyao 已提交
4182 4183 4184 4185
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5
54liuyao 已提交
4186
    }
4187

5
54liuyao 已提交
4188 4189 4190 4191
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
4192
    // the pDataBlock are always the same one, no need to call this again
4193
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
4194 4195
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
5
54liuyao 已提交
4196 4197 4198
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
X
Xiaoyu Wang 已提交
4199

5
54liuyao 已提交
4200 4201 4202 4203 4204
  closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated);
  copyUpdateResult(pInfo->pSeUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pSeDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pSeUpdated);
  pInfo->pSeUpdated = NULL;
5
54liuyao 已提交
4205

L
liuyao 已提交
4206 4207 4208 4209
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }

5
54liuyao 已提交
4210 4211
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
4212
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
4213

5
54liuyao 已提交
4214 4215 4216 4217 4218 4219
#if 0
  char* pBuf = streamStateSessionDump(pInfo->streamAggSup.pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

4220
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4221
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4222
    printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4223 4224 4225
    return pInfo->pDelRes;
  }

5
54liuyao 已提交
4226 4227 4228 4229 4230
  doBuildSessionResult(pOperator, pInfo->streamAggSup.pState, &pInfo->groupResInfo, pBInfo->pRes);
  if (pBInfo->pRes->info.rows > 0) {
    printDataBlock(pBInfo->pRes, "single state");
    return pBInfo->pRes;
  }
H
Haojun Liao 已提交
4231
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
4232
  return NULL;
4233 4234
}

L
liuyao 已提交
4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296
void streamStateReleaseState(SOperatorInfo* pOperator) {
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
  int32_t resSize = taosArrayGetSize(pInfo->historyWins) * sizeof(SSessionKey);
  pInfo->streamAggSup.stateStore.streamStateSaveInfo(pInfo->streamAggSup.pState, STREAM_STATE_OP_STATE_NAME, strlen(STREAM_STATE_OP_STATE_NAME), pInfo->historyWins->pData, resSize);
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.releaseStreamStateFn) {
    downstream->fpSet.releaseStreamStateFn(downstream);
  }
}

static void compactStateWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SResultWindowInfo* pNextWin,
                               SSHashObj* pStUpdated, SSHashObj* pStDeleted) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

  SStreamStateAggOperatorInfo*   pInfo = pOperator->info;
  SResultRow*                    pCurResult = NULL;
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  initSessionOutputBuf(pCurWin, &pCurResult, pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset);
  SResultRow* pWinResult = NULL;
  initSessionOutputBuf(pNextWin, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);

  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, true);
  compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pInfo->twAggSup.timeWindowData);
  tSimpleHashRemove(pStUpdated, &pNextWin->sessionWin, sizeof(SSessionKey));
  if (pNextWin->isOutput && pStDeleted) {
    saveDeleteRes(pStDeleted, pNextWin->sessionWin);
  }
  removeSessionResult(pStUpdated, pAggSup->pResultRows, pNextWin->sessionWin);
  doDeleteSessionWindow(pAggSup, &pNextWin->sessionWin);
  taosMemoryFree(pNextWin->pOutputBuf);
  saveSessionOutputBuf(pAggSup, pCurWin);
}

void streamStateReloadState(SOperatorInfo* pOperator) {
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
  SSessionKey seKey = {.win.skey = INT64_MIN, .win.ekey = INT64_MIN, .groupId = 0};
  int32_t size = 0;
  void* pBuf = NULL;
  int32_t code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_STATE_OP_STATE_NAME,
                                                        strlen(STREAM_STATE_OP_STATE_NAME), &pBuf, &size);
  int32_t num = size / sizeof(SSessionKey);
  SSessionKey* pSeKeyBuf = (SSessionKey*) pBuf;
  ASSERT(size == num * sizeof(SSessionKey));
  for (int32_t i = 0; i < num; i++) {
    SStateWindowInfo curInfo = {0};
    SStateWindowInfo nextInfo = {0};
    setStateOutputBuf(pAggSup, pSeKeyBuf[i].win.skey, pSeKeyBuf[i].groupId, NULL, &curInfo, &nextInfo);
    if (compareStateKey(curInfo.pStateKey,nextInfo.pStateKey)) {
      compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pStUpdated, pInfo->pStDeleted);
    }
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.reloadStreamStateFn) {
    downstream->fpSet.reloadStreamStateFn(downstream);
  } 
}

X
Xiaoyu Wang 已提交
4297 4298 4299 4300 4301
SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
  SColumnNode*                 pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
H
Haojun Liao 已提交
4302
  int32_t                      code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
4303

X
Xiaoyu Wang 已提交
4304 4305
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
4306
  if (pInfo == NULL || pOperator == NULL) {
H
Haojun Liao 已提交
4307
    code = TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
4308 4309 4310 4311
    goto _error;
  }

  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
4312
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
4313 4314 4315
  if (pStateNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalar);
4316
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4317 4318 4319 4320 4321
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

X
Xiaoyu Wang 已提交
4322 4323
  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pStateNode->window.watermark,
5
54liuyao 已提交
4324 4325
      .calTrigger = pStateNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
4326
      .minTs = INT64_MAX,
X
Xiaoyu Wang 已提交
4327
  };
4328

5
54liuyao 已提交
4329
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
4330

5
54liuyao 已提交
4331 4332 4333
  SExprSupp*   pSup = &pOperator->exprSupp;
  int32_t      numOfCols = 0;
  SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
4334
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
4335
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4336 4337 4338
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
5
54liuyao 已提交
4339 4340 4341
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
  int16_t type = pColNode->node.resType.type;
  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize,
H
Haojun Liao 已提交
4342
                                type, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
4343 4344 4345 4346 4347 4348
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  pInfo->primaryTsIndex = tsSlotId;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4349
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
5
54liuyao 已提交
4350
  pInfo->pDelIterator = NULL;
H
Haojun Liao 已提交
4351
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
5
54liuyao 已提交
4352
  pInfo->pChildren = NULL;
5
54liuyao 已提交
4353
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
4354
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
4355 4356
  pInfo->pUpdated = NULL;
  pInfo->pSeUpdated = NULL;
L
liuyao 已提交
4357
  pInfo->dataVersion = 0;
L
liuyao 已提交
4358 4359 4360 4361 4362
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
  pInfo->isHistoryOp = false;
5
54liuyao 已提交
4363

L
Liu Jicong 已提交
4364 4365
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
L
Liu Jicong 已提交
4366 4367
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAgg, NULL, destroyStreamStateOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
4368
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
5
54liuyao 已提交
4369
  initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
4370 4371 4372 4373 4374 4375 4376
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
  return pOperator;

_error:
4377
  destroyStreamStateOperatorInfo(pInfo);
5
54liuyao 已提交
4378 4379 4380 4381
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4382

4383
void destroyMAIOperatorInfo(void* param) {
4384
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
4385
  destroyIntervalOperatorInfo(miaInfo->intervalAggOperatorInfo);
D
dapan1121 已提交
4386
  taosMemoryFreeClear(param);
4387 4388
}

4389
static SResultRow* doSetSingleOutputTupleBuf(SResultRowInfo* pResultRowInfo, SAggSupporter* pSup) {
H
Haojun Liao 已提交
4390
  SResultRow* pResult = getNewResultRow(pSup->pResultBuf, &pSup->currentPageId, pSup->resultRowSize);
4391 4392 4393
  if (NULL == pResult) {
    return pResult;
  }
H
Haojun Liao 已提交
4394
  pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
4395 4396
  return pResult;
}
4397

4398 4399 4400 4401 4402 4403 4404 4405
static int32_t setSingleOutputTupleBuf(SResultRowInfo* pResultRowInfo, STimeWindow* win, SResultRow** pResult,
                                       SExprSupp* pExprSup, SAggSupporter* pAggSup) {
  if (*pResult == NULL) {
    *pResult = doSetSingleOutputTupleBuf(pResultRowInfo, pAggSup);
    if (*pResult == NULL) {
      return terrno;
    }
  }
4406

4407
  // set time window for current result
4408 4409
  (*pResult)->win = (*win);
  setResultRowInitCtx((*pResult), pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset);
4410
  return TSDB_CODE_SUCCESS;
4411 4412
}

4413
static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
4414
                                          SSDataBlock* pBlock, SSDataBlock* pResultBlock) {
4415
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
D
dapan1121 已提交
4416
  SIntervalAggOperatorInfo*             iaInfo = miaInfo->intervalAggOperatorInfo;
4417 4418

  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
4419
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
4420
  SInterval*     pInterval = &iaInfo->interval;
4421

5
54liuyao 已提交
4422 4423
  int32_t  startPos = 0;
  int64_t* tsCols = extractTsCol(pBlock, iaInfo);
4424

4425 4426
  TSKEY ts = getStartTsKey(&pBlock->info.window, tsCols);

4427 4428
  // there is an result exists
  if (miaInfo->curTs != INT64_MIN) {
4429
    if (ts != miaInfo->curTs) {
4430
      finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4431
      resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4432
      miaInfo->curTs = ts;
4433
    }
4434 4435
  } else {
    miaInfo->curTs = ts;
4436 4437 4438
  }

  STimeWindow win = {0};
4439
  win.skey = miaInfo->curTs;
4440
  win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4441

5
54liuyao 已提交
4442
  int32_t ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4443 4444
  if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
    T_LONG_JMP(pTaskInfo->env, ret);
4445 4446
  }

4447 4448
  int32_t currPos = startPos;

4449
  STimeWindow currWin = win;
4450
  while (++currPos < pBlock->info.rows) {
4451
    if (tsCols[currPos] == miaInfo->curTs) {
4452
      continue;
4453 4454 4455
    }

    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, true);
H
Haojun Liao 已提交
4456 4457
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos,
                                    currPos - startPos, pBlock->info.rows, pSup->numOfExprs);
4458

4459
    finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4460
    resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4461
    miaInfo->curTs = tsCols[currPos];
4462

4463
    currWin.skey = miaInfo->curTs;
4464
    currWin.ekey = taosTimeAdd(currWin.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4465 4466

    startPos = currPos;
5
54liuyao 已提交
4467
    ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4468 4469
    if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
      T_LONG_JMP(pTaskInfo->env, ret);
4470
    }
4471 4472

    miaInfo->curTs = currWin.skey;
4473
  }
4474

4475
  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, true);
H
Haojun Liao 已提交
4476
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
L
Liu Jicong 已提交
4477
                                  pBlock->info.rows, pSup->numOfExprs);
4478 4479
}

4480
static void cleanupAfterGroupResultGen(SMergeAlignedIntervalAggOperatorInfo* pMiaInfo, SSDataBlock* pRes) {
H
Haojun Liao 已提交
4481
  pRes->info.id.groupId = pMiaInfo->groupId;
4482 4483
  pMiaInfo->curTs = INT64_MIN;
  pMiaInfo->groupId = 0;
4484 4485
}

4486
static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
S
shenglian zhou 已提交
4487
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4488

4489 4490
  SMergeAlignedIntervalAggOperatorInfo* pMiaInfo = pOperator->info;
  SIntervalAggOperatorInfo*             pIaInfo = pMiaInfo->intervalAggOperatorInfo;
4491

4492 4493 4494 4495 4496
  SExprSupp*      pSup = &pOperator->exprSupp;
  SSDataBlock*    pRes = pIaInfo->binfo.pRes;
  SResultRowInfo* pResultRowInfo = &pIaInfo->binfo.resultRowInfo;
  SOperatorInfo*  downstream = pOperator->pDownstream[0];
  int32_t         scanFlag = MAIN_SCAN;
4497

4498 4499
  while (1) {
    SSDataBlock* pBlock = NULL;
4500
    if (pMiaInfo->prefetchedBlock == NULL) {
4501 4502
      pBlock = downstream->fpSet.getNextFn(downstream);
    } else {
4503 4504
      pBlock = pMiaInfo->prefetchedBlock;
      pMiaInfo->prefetchedBlock = NULL;
4505

H
Haojun Liao 已提交
4506
      pMiaInfo->groupId = pBlock->info.id.groupId;
4507
    }
4508

4509
    // no data exists, all query processing is done
4510
    if (pBlock == NULL) {
4511 4512 4513
      // close last unclosed time window
      if (pMiaInfo->curTs != INT64_MIN) {
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4514 4515
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
4516
      }
4517

H
Haojun Liao 已提交
4518
      setOperatorCompleted(pOperator);
4519
      break;
4520
    }
4521

H
Haojun Liao 已提交
4522
    if (pMiaInfo->groupId == 0) {
H
Haojun Liao 已提交
4523 4524 4525
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
        pMiaInfo->groupId = pBlock->info.id.groupId;
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4526 4527
      }
    } else {
H
Haojun Liao 已提交
4528
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
H
Haojun Liao 已提交
4529
        // if there are unclosed time window, close it firstly.
4530
        ASSERT(pMiaInfo->curTs != INT64_MIN);
H
Haojun Liao 已提交
4531
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4532
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
H
Haojun Liao 已提交
4533

4534 4535
        pMiaInfo->prefetchedBlock = pBlock;
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
H
Haojun Liao 已提交
4536
        break;
5
54liuyao 已提交
4537
      } else {
H
Haojun Liao 已提交
4538
        // continue
H
Haojun Liao 已提交
4539
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4540
      }
4541
    }
4542

4543
    getTableScanInfo(pOperator, &pIaInfo->inputOrder, &scanFlag, false);
4544
    setInputDataBlock(pSup, pBlock, pIaInfo->inputOrder, scanFlag, true);
4545
    doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes);
4546

H
Haojun Liao 已提交
4547
    doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
4548 4549 4550
    if (pRes->info.rows >= pOperator->resultInfo.capacity) {
      break;
    }
4551
  }
4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566
}

static SSDataBlock* mergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;

  SMergeAlignedIntervalAggOperatorInfo* pMiaInfo = pOperator->info;
  SIntervalAggOperatorInfo*             iaInfo = pMiaInfo->intervalAggOperatorInfo;
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SSDataBlock* pRes = iaInfo->binfo.pRes;
  blockDataCleanup(pRes);

  if (iaInfo->binfo.mergeResultBlock) {
dengyihao's avatar
dengyihao 已提交
4567
    while (1) {
4568
      if (pOperator->status == OP_EXEC_DONE) {
4569 4570
        break;
      }
4571

4572
      if (pRes->info.rows >= pOperator->resultInfo.threshold) {
4573 4574 4575
        break;
      }

4576 4577 4578 4579
      doMergeAlignedIntervalAgg(pOperator);
    }
  } else {
    doMergeAlignedIntervalAgg(pOperator);
4580 4581 4582 4583 4584 4585 4586
  }

  size_t rows = pRes->info.rows;
  pOperator->resultInfo.totalRows += rows;
  return (rows == 0) ? NULL : pRes;
}

4587
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode,
4588
                                                      SExecTaskInfo* pTaskInfo) {
4589
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
4590
  SOperatorInfo*                        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4591 4592 4593 4594
  if (miaInfo == NULL || pOperator == NULL) {
    goto _error;
  }

D
dapan1121 已提交
4595 4596 4597 4598 4599
  miaInfo->intervalAggOperatorInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
  if (miaInfo->intervalAggOperatorInfo == NULL) {
    goto _error;
  }

4600 4601 4602 4603 4604 4605 4606
  SInterval interval = {.interval = pNode->interval,
                        .sliding = pNode->sliding,
                        .intervalUnit = pNode->intervalUnit,
                        .slidingUnit = pNode->slidingUnit,
                        .offset = pNode->offset,
                        .precision = ((SColumnNode*)pNode->window.pTspk)->node.resType.precision};

D
dapan1121 已提交
4607
  SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
4608
  SExprSupp*                pSup = &pOperator->exprSupp;
4609

H
Haojun Liao 已提交
4610 4611 4612 4613 4614
  int32_t code = filterInitFromNode((SNode*)pNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

L
Liu Jicong 已提交
4615 4616 4617 4618
  miaInfo->curTs = INT64_MIN;
  iaInfo->win = pTaskInfo->window;
  iaInfo->inputOrder = TSDB_ORDER_ASC;
  iaInfo->interval = interval;
4619 4620
  iaInfo->primaryTsIndex = ((SColumnNode*)pNode->window.pTspk)->slotId;
  iaInfo->binfo.mergeResultBlock = pNode->window.mergeDataBlock;
4621 4622

  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
H
Haojun Liao 已提交
4623
  initResultSizeInfo(&pOperator->resultInfo, 512);
4624

H
Haojun Liao 已提交
4625 4626
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pNode->window.pFuncs, NULL, &num);
H
Haojun Liao 已提交
4627

L
Liu Jicong 已提交
4628
  code = initAggSup(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4629
                    pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4630 4631 4632
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4633

H
Haojun Liao 已提交
4634
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pNode->window.node.pOutputDataBlockDesc);
4635
  initBasicInfo(&iaInfo->binfo, pResBlock);
4636
  initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
4637

4638
  iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, num, iaInfo);
4639
  if (iaInfo->timeWindowInterpo) {
4640
    iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4641 4642
  }

4643
  initResultRowInfo(&iaInfo->binfo.resultRowInfo);
4644
  blockDataEnsureCapacity(iaInfo->binfo.pRes, pOperator->resultInfo.capacity);
L
Liu Jicong 已提交
4645 4646
  setOperatorInfo(pOperator, "TimeMergeAlignedIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
                  false, OP_NOT_OPENED, miaInfo, pTaskInfo);
4647

L
Liu Jicong 已提交
4648 4649
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, mergeAlignedIntervalAgg, NULL, destroyMAIOperatorInfo,
                                         optrDefaultBufFn, NULL);
4650 4651 4652 4653 4654 4655 4656 4657 4658

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

  return pOperator;

_error:
4659
  destroyMAIOperatorInfo(miaInfo);
4660 4661 4662 4663
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4664 4665 4666 4667 4668

//=====================================================================================================================
// merge interval operator
typedef struct SMergeIntervalAggOperatorInfo {
  SIntervalAggOperatorInfo intervalAggOperatorInfo;
L
Liu Jicong 已提交
4669 4670 4671 4672 4673 4674
  SList*                   groupIntervals;
  SListIter                groupIntervalsIter;
  bool                     hasGroupId;
  uint64_t                 groupId;
  SSDataBlock*             prefetchedBlock;
  bool                     inputBlocksFinished;
4675 4676
} SMergeIntervalAggOperatorInfo;

S
slzhou 已提交
4677
typedef struct SGroupTimeWindow {
L
Liu Jicong 已提交
4678
  uint64_t    groupId;
S
slzhou 已提交
4679 4680 4681
  STimeWindow window;
} SGroupTimeWindow;

4682
void destroyMergeIntervalOperatorInfo(void* param) {
4683
  SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
S
slzhou 已提交
4684
  tdListFree(miaInfo->groupIntervals);
4685
  destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo);
4686

D
dapan1121 已提交
4687
  taosMemoryFreeClear(param);
4688 4689 4690 4691 4692 4693
}

static int32_t outputPrevIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock,
                                        STimeWindow* newWin) {
  SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
  SIntervalAggOperatorInfo*      iaInfo = &miaInfo->intervalAggOperatorInfo;
4694
  bool                           ascScan = (iaInfo->inputOrder == TSDB_ORDER_ASC);
4695

S
slzhou 已提交
4696 4697
  SGroupTimeWindow groupTimeWindow = {.groupId = tableGroupId, .window = *newWin};
  tdListAppend(miaInfo->groupIntervals, &groupTimeWindow);
4698

S
slzhou 已提交
4699 4700 4701 4702 4703
  SListIter iter = {0};
  tdListInitIter(miaInfo->groupIntervals, &iter, TD_LIST_FORWARD);
  SListNode* listNode = NULL;
  while ((listNode = tdListNext(&iter)) != NULL) {
    SGroupTimeWindow* prevGrpWin = (SGroupTimeWindow*)listNode->data;
L
Liu Jicong 已提交
4704
    if (prevGrpWin->groupId != tableGroupId) {
S
slzhou 已提交
4705 4706
      continue;
    }
4707

S
slzhou 已提交
4708
    STimeWindow* prevWin = &prevGrpWin->window;
H
Haojun Liao 已提交
4709
    if ((ascScan && newWin->skey > prevWin->ekey) || ((!ascScan) && newWin->skey < prevWin->ekey)) {
S
slzhou 已提交
4710 4711
      tdListPopNode(miaInfo->groupIntervals, listNode);
    }
4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727
  }

  return 0;
}

static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo, SSDataBlock* pBlock,
                                   int32_t scanFlag, SSDataBlock* pResultBlock) {
  SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
  SIntervalAggOperatorInfo*      iaInfo = &miaInfo->intervalAggOperatorInfo;

  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
  SExprSupp*     pExprSup = &pOperatorInfo->exprSupp;

  int32_t     startPos = 0;
  int32_t     numOfOutput = pExprSup->numOfExprs;
  int64_t*    tsCols = extractTsCol(pBlock, iaInfo);
H
Haojun Liao 已提交
4728
  uint64_t    tableGroupId = pBlock->info.id.groupId;
4729
  bool        ascScan = (iaInfo->inputOrder == TSDB_ORDER_ASC);
4730 4731 4732
  TSKEY       blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
  SResultRow* pResult = NULL;

4733 4734
  STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
                                        iaInfo->inputOrder);
4735 4736 4737 4738 4739

  int32_t ret =
      setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
                             numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
  if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4740
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4741 4742 4743 4744
  }

  TSKEY   ekey = ascScan ? win.ekey : win.skey;
  int32_t forwardRows =
4745
      getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->inputOrder);
4746
  ASSERT(forwardRows > 0);
4747 4748 4749

  // prev time window not interpolation yet.
  if (iaInfo->timeWindowInterpo) {
4750
    SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
4751 4752 4753 4754 4755 4756
    doInterpUnclosedTimeWindow(pOperatorInfo, numOfOutput, pResultRowInfo, pBlock, scanFlag, tsCols, &pos);

    // restore current time window
    ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
                                 numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
    if (ret != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
4757
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4758 4759 4760 4761 4762 4763 4764
    }

    // window start key interpolation
    doWindowBorderInterpolation(iaInfo, pBlock, pResult, &win, startPos, forwardRows, pExprSup);
  }

  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, true);
H
Haojun Liao 已提交
4765
  applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4766
                                  pBlock->info.rows, numOfOutput);
4767 4768 4769 4770 4771 4772 4773 4774
  doCloseWindow(pResultRowInfo, iaInfo, pResult);

  // output previous interval results after this interval (&win) is closed
  outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &win);

  STimeWindow nextWin = win;
  while (1) {
    int32_t prevEndPos = forwardRows - 1 + startPos;
4775 4776
    startPos =
        getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->inputOrder);
4777 4778 4779 4780 4781 4782 4783 4784 4785
    if (startPos < 0) {
      break;
    }

    // null data, failed to allocate more memory buffer
    int32_t code =
        setTimeWindowOutputBuf(pResultRowInfo, &nextWin, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
                               pExprSup->pCtx, numOfOutput, pExprSup->rowEntryInfoOffset, &iaInfo->aggSup, pTaskInfo);
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4786
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4787 4788 4789 4790
    }

    ekey = ascScan ? nextWin.ekey : nextWin.skey;
    forwardRows =
4791
        getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->inputOrder);
4792 4793 4794 4795 4796

    // window start(end) key interpolation
    doWindowBorderInterpolation(iaInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pExprSup);

    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, true);
H
Haojun Liao 已提交
4797
    applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4798
                                    pBlock->info.rows, numOfOutput);
4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833
    doCloseWindow(pResultRowInfo, iaInfo, pResult);

    // output previous interval results after this interval (&nextWin) is closed
    outputPrevIntervalResult(pOperatorInfo, tableGroupId, pResultBlock, &nextWin);
  }

  if (iaInfo->timeWindowInterpo) {
    saveDataBlockLastRow(iaInfo->pPrevValues, pBlock, iaInfo->pInterpCols);
  }
}

static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;

  SMergeIntervalAggOperatorInfo* miaInfo = pOperator->info;
  SIntervalAggOperatorInfo*      iaInfo = &miaInfo->intervalAggOperatorInfo;
  SExprSupp*                     pExpSupp = &pOperator->exprSupp;

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

  SSDataBlock* pRes = iaInfo->binfo.pRes;
  blockDataCleanup(pRes);
  blockDataEnsureCapacity(pRes, pOperator->resultInfo.capacity);

  if (!miaInfo->inputBlocksFinished) {
    SOperatorInfo* downstream = pOperator->pDownstream[0];
    int32_t        scanFlag = MAIN_SCAN;
    while (1) {
      SSDataBlock* pBlock = NULL;
      if (miaInfo->prefetchedBlock == NULL) {
        pBlock = downstream->fpSet.getNextFn(downstream);
      } else {
        pBlock = miaInfo->prefetchedBlock;
H
Haojun Liao 已提交
4834
        miaInfo->groupId = pBlock->info.id.groupId;
4835 4836 4837 4838
        miaInfo->prefetchedBlock = NULL;
      }

      if (pBlock == NULL) {
S
slzhou 已提交
4839
        tdListInitIter(miaInfo->groupIntervals, &miaInfo->groupIntervalsIter, TD_LIST_FORWARD);
4840 4841 4842 4843 4844 4845
        miaInfo->inputBlocksFinished = true;
        break;
      }

      if (!miaInfo->hasGroupId) {
        miaInfo->hasGroupId = true;
H
Haojun Liao 已提交
4846 4847
        miaInfo->groupId = pBlock->info.id.groupId;
      } else if (miaInfo->groupId != pBlock->info.id.groupId) {
4848 4849 4850 4851
        miaInfo->prefetchedBlock = pBlock;
        break;
      }

4852
      getTableScanInfo(pOperator, &iaInfo->inputOrder, &scanFlag, false);
4853
      setInputDataBlock(pExpSupp, pBlock, iaInfo->inputOrder, scanFlag, true);
4854 4855 4856 4857 4858 4859 4860
      doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);

      if (pRes->info.rows >= pOperator->resultInfo.threshold) {
        break;
      }
    }

H
Haojun Liao 已提交
4861
    pRes->info.id.groupId = miaInfo->groupId;
4862 4863 4864
  }

  if (miaInfo->inputBlocksFinished) {
S
slzhou 已提交
4865
    SListNode* listNode = tdListNext(&miaInfo->groupIntervalsIter);
4866

S
slzhou 已提交
4867 4868
    if (listNode != NULL) {
      SGroupTimeWindow* grpWin = (SGroupTimeWindow*)(listNode->data);
H
Haojun Liao 已提交
4869
      pRes->info.id.groupId = grpWin->groupId;
4870 4871 4872 4873
    }
  }

  if (pRes->info.rows == 0) {
H
Haojun Liao 已提交
4874
    setOperatorCompleted(pOperator);
4875 4876 4877 4878 4879 4880 4881
  }

  size_t rows = pRes->info.rows;
  pOperator->resultInfo.totalRows += rows;
  return (rows == 0) ? NULL : pRes;
}

4882 4883 4884
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode,
                                               SExecTaskInfo* pTaskInfo) {
  SMergeIntervalAggOperatorInfo* pMergeIntervalInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
4885
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4886
  if (pMergeIntervalInfo == NULL || pOperator == NULL) {
4887 4888 4889
    goto _error;
  }

5
54liuyao 已提交
4890 4891
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
4892 4893 4894 4895 4896 4897 4898

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

4900
  pMergeIntervalInfo->groupIntervals = tdListNew(sizeof(SGroupTimeWindow));
4901

4902
  SIntervalAggOperatorInfo* pIntervalInfo = &pMergeIntervalInfo->intervalAggOperatorInfo;
L
Liu Jicong 已提交
4903
  pIntervalInfo->win = pTaskInfo->window;
4904
  pIntervalInfo->inputOrder = TSDB_ORDER_ASC;
L
Liu Jicong 已提交
4905
  pIntervalInfo->interval = interval;
4906 4907
  pIntervalInfo->binfo.mergeResultBlock = pIntervalPhyNode->window.mergeDataBlock;
  pIntervalInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
4908 4909 4910 4911

  SExprSupp* pExprSupp = &pOperator->exprSupp;

  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
4912
  initResultSizeInfo(&pOperator->resultInfo, 4096);
4913

L
Liu Jicong 已提交
4914
  int32_t code = initAggSup(pExprSupp, &pIntervalInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4915
                            pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4916 4917 4918
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4919

H
Haojun Liao 已提交
4920
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pIntervalPhyNode->window.node.pOutputDataBlockDesc);
4921 4922
  initBasicInfo(&pIntervalInfo->binfo, pResBlock);
  initExecTimeWindowInfo(&pIntervalInfo->twAggSup.timeWindowData, &pIntervalInfo->win);
4923

4924 4925
  pIntervalInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, num, pIntervalInfo);
  if (pIntervalInfo->timeWindowInterpo) {
4926
    pIntervalInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4927
    if (pIntervalInfo->binfo.resultRowInfo.openWindow == NULL) {
4928 4929 4930 4931
      goto _error;
    }
  }

4932
  initResultRowInfo(&pIntervalInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
4933 4934
  setOperatorInfo(pOperator, "TimeMergeIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, false,
                  OP_NOT_OPENED, pMergeIntervalInfo, pTaskInfo);
L
Liu Jicong 已提交
4935 4936
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doMergeIntervalAgg, NULL, destroyMergeIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
4937 4938 4939 4940 4941 4942 4943 4944 4945

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

  return pOperator;

_error:
H
Haojun Liao 已提交
4946 4947 4948 4949
  if (pMergeIntervalInfo != NULL) {
    destroyMergeIntervalOperatorInfo(pMergeIntervalInfo);
  }

4950 4951 4952
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
4953
}
4954 4955 4956

static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
4957
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4958 4959
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

4960
  SExprSupp* pSup = &pOperator->exprSupp;
4961 4962 4963 4964 4965 4966

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

  if (pOperator->status == OP_RES_TO_RETURN) {
4967
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
4968
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4969
      printDataBlock(pInfo->pDelRes, "single interval delete");
4970 4971 4972
      return pInfo->pDelRes;
    }

4973
    doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
4974 4975 4976
    if (pInfo->binfo.pRes->info.rows > 0) {
      printDataBlock(pInfo->binfo.pRes, "single interval");
      return pInfo->binfo.pRes;
4977
    }
L
liuyao 已提交
4978 4979 4980 4981 4982 4983

    if (pInfo->recvGetAll) {
      pInfo->recvGetAll = false;
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
    }

H
Haojun Liao 已提交
4984
    setOperatorCompleted(pOperator);
dengyihao's avatar
dengyihao 已提交
4985 4986
    if (pInfo->twAggSup.maxTs > 0 &&
        pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
4987 4988
      pAPI->stateStore.streamStateCommit(pInfo->pState);
      pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
4989
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
L
liuyao 已提交
4990 4991
      pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
    }
5
54liuyao 已提交
4992
    return NULL;
4993 4994 4995 4996
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];

5
54liuyao 已提交
4997
  if (!pInfo->pUpdated) {
L
liuyao 已提交
4998
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
4999
  }
5000

5
54liuyao 已提交
5001 5002
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
5003
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
5004 5005
  }

5006 5007 5008
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
5009 5010
      qDebug("===stream===return data:single interval. recv datablock num:%" PRIu64, pInfo->numOfDatapack);
      pInfo->numOfDatapack = 0;
5011 5012
      break;
    }
5013

5
54liuyao 已提交
5014
    pInfo->numOfDatapack++;
5015 5016
    printDataBlock(pBlock, "single interval recv");

5017 5018
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
5019
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap);
5020 5021
      continue;
    } else if (pBlock->info.type == STREAM_GET_ALL) {
L
liuyao 已提交
5022
      qDebug("===stream===single interval recv|block type STREAM_GET_ALL");
L
liuyao 已提交
5023
      pInfo->recvGetAll = true;
5
54liuyao 已提交
5024
      getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
5025
      continue;
5
54liuyao 已提交
5026
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
5
54liuyao 已提交
5027
      printDataBlock(pBlock, "single interval");
5
54liuyao 已提交
5028 5029 5030
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045
    }

    if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) {
      // set input version
      pTaskInfo->version = pBlock->info.version;
    }

    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }

    // The timewindow that overlaps the timestamps of the input pBlock need to be recalculated and return to the
    // caller. Note that all the time window are not close till now.
    // the pDataBlock are always the same one, no need to call this again
5046
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5047 5048 5049 5050
    if (pInfo->invertible) {
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
    }

5
54liuyao 已提交
5051
    doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap);
5
54liuyao 已提交
5052 5053
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
5054 5055
  }
  pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
5056
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
5057 5058
  closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
                            pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5059

5060 5061 5062
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
5063
    taosArrayPush(pInfo->pUpdated, pIte);
5064
  }
5
54liuyao 已提交
5065
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
5066

5
54liuyao 已提交
5067 5068
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5069
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5070
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
5071
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
5072

5
54liuyao 已提交
5073 5074 5075 5076 5077 5078
#if 0
  char* pBuf = streamStateIntervalDump(pInfo->pState);
  qDebug("===stream===interval state%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5079
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
5080
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
5081
    printDataBlock(pInfo->pDelRes, "single interval delete");
5082 5083 5084
    return pInfo->pDelRes;
  }

5085
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
5086 5087 5088 5089 5090 5091
  if (pInfo->binfo.pRes->info.rows > 0) {
    printDataBlock(pInfo->binfo.pRes, "single interval");
    return pInfo->binfo.pRes;
  }

  return NULL;
5092 5093 5094 5095 5096
}

SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
5097
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5098 5099 5100 5101 5102
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;

H
Haojun Liao 已提交
5103
  int32_t    code = TSDB_CODE_SUCCESS;
5104 5105
  int32_t    numOfCols = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
5106

H
Haojun Liao 已提交
5107
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
5108 5109 5110 5111 5112 5113 5114
  pInfo->interval = (SInterval){
      .interval = pIntervalPhyNode->interval,
      .sliding = pIntervalPhyNode->sliding,
      .intervalUnit = pIntervalPhyNode->intervalUnit,
      .slidingUnit = pIntervalPhyNode->slidingUnit,
      .offset = pIntervalPhyNode->offset,
      .precision = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->node.resType.precision,
5115
  };
H
Haojun Liao 已提交
5116

dengyihao's avatar
dengyihao 已提交
5117
  pInfo->twAggSup = (STimeWindowAggSupp){
5118 5119 5120
      .waterMark = pIntervalPhyNode->window.watermark,
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
5121
      .minTs = INT64_MAX,
5
54liuyao 已提交
5122
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
liuyao 已提交
5123
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
5124 5125
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
5126
  };
H
Haojun Liao 已提交
5127

L
liuyao 已提交
5128
  ASSERTS(pInfo->twAggSup.calTrigger != STREAM_TRIGGER_MAX_DELAY, "trigger type should not be max delay");
5129

5130
  pOperator->pTaskInfo = pTaskInfo;
5131 5132
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5133
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
5134
  pInfo->ignoreExpiredDataSaved = false;
5135 5136 5137
  pInfo->isFinal = false;

  SExprSupp* pSup = &pOperator->exprSupp;
H
Haojun Liao 已提交
5138 5139 5140 5141
  initBasicInfo(&pInfo->binfo, pResBlock);
  initStreamFunciton(pSup->pCtx, pSup->numOfExprs);
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);

5142
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
5143
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5144

L
liuyao 已提交
5145 5146
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
5147
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
liuyao 已提交
5148

5149
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
L
Liu Jicong 已提交
5150
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
5151
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
5152 5153 5154 5155
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
5156 5157 5158
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
5159
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
H
Haojun Liao 已提交
5160 5161 5162 5163
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }
5164 5165

  pInfo->invertible = allInvertible(pSup->pCtx, numOfCols);
5166
  pInfo->invertible = false;
5167 5168 5169 5170 5171
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
  pInfo->delIndex = 0;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
  initResultRowInfo(&pInfo->binfo.resultRowInfo);

5172 5173
  pInfo->pPhyNode = NULL;  // create new child
  pInfo->pPullDataMap = NULL;
L
liuyao 已提交
5174
  pInfo->pFinalPullDataMap = NULL;
5175 5176 5177 5178
  pInfo->pPullWins = NULL;  // SPullWindowInfo
  pInfo->pullIndex = 0;
  pInfo->pPullDataRes = NULL;
  pInfo->isFinal = false;
L
liuyao 已提交
5179
  pInfo->numOfChild = 0;
5180 5181
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
5182
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
5183 5184
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
5185
  int32_t funResSize= getMaxFunResSize(pSup, numOfCols);
5186 5187 5188 5189

  pInfo->pState->pFileState = pTaskInfo->storageAPI.stateStore.streamFileStateInit(
      tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize, compareTs, pInfo->pState,
      pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo));
5190

L
Liu Jicong 已提交
5191 5192
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
5193 5194
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAgg, NULL,
                                         destroyStreamFinalIntervalOperatorInfo, optrDefaultBufFn, NULL);
L
liuyao 已提交
5195
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
5196

5197
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
5198 5199
  pInfo->recvGetAll = false;

L
liuyao 已提交
5200
  initIntervalDownStream(downstream, pPhyNode->type, pInfo);
5201 5202 5203 5204 5205 5206 5207 5208
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
5209
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5210 5211 5212 5213
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}