timewindowoperator.c 204.5 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
  return TSDB_CODE_SUCCESS;
}

L
liuyao 已提交
109
static void updateTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pWin, int64_t  delta) {
110 111 112 113 114 115 116 117
  int64_t* ts = (int64_t*)pColData->pData;

  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
}

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

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

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

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

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

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

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

5
54liuyao 已提交
171
int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) {
172 173 174 175 176 177 178 179 180 181 182 183 184 185
  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) {
186 187 188 189 190 191 192 193 194 195 196
      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;
        }
      }
197 198 199 200 201 202

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

      if (key < keyList[midPos]) {
        firstPos = midPos + 1;
203 204
      } else if (key > keyList[midPos]) {
        lastPos = midPos - 1;
205 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
      } 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 已提交
240 241
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 已提交
242
  ASSERT(startPos >= 0 && startPos < pDataBlockInfo->rows);
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

  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) {
263
        item->lastKey = pPrimaryColumn[startPos + (num - 1)] + step;
264 265
      }
    } else {
266
      num = pDataBlockInfo->rows - startPos;
267
      if (item != NULL) {
268
        item->lastKey = pDataBlockInfo->window.ekey + step;
269 270 271 272 273 274 275
      }
    }
  }

  return num;
}

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

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

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

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

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

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

302
#if 0
303 304 305 306 307 308 309 310
    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 已提交
311 312
        if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR ||
            pColInfo->info.type == TSDB_DATA_TYPE_GEOMETRY) {
313 314 315 316 317 318 319 320 321 322
          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) {
323 324
#endif

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

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

X
Xiaoyu Wang 已提交
331 332 333 334 335 336
    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;
337
    }
X
Xiaoyu Wang 已提交
338 339 340

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

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

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

362
  TSKEY curTs = tsCols[pos];
363 364

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

  // 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) {
371
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_START_INTERP);
372 373 374
    return true;
  }

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

  return true;
}

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

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

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

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

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

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

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

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

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

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

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

  // 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 已提交
442 443 444 445
  if (!inSlidingWindow(pInterval, pNext, pDataBlockInfo) && order == TSDB_ORDER_ASC) {
    return -1;
  }

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

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

  /* 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 已提交
471
      ASSERT(pDataBlockInfo->window.skey <= pNext->ekey);
472
    } else {
H
Haojun Liao 已提交
473
      ASSERT(pDataBlockInfo->window.ekey >= pNext->skey);
474 475 476 477 478
    }
  } else {
    if (ascQuery && primaryKeys[startPos] > pNext->ekey) {
      TSKEY next = primaryKeys[startPos];
      if (pInterval->intervalUnit == 'n' || pInterval->intervalUnit == 'y') {
479
        pNext->skey = taosTimeTruncate(next, pInterval);
480 481 482 483 484 485 486 487
        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') {
488
        pNext->skey = taosTimeTruncate(next, pInterval);
489 490 491 492 493 494 495 496 497 498 499
        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;
}

500
static bool isResultRowInterpolated(SResultRow* pResult, SResultTsInterpType type) {
501
  ASSERT(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP));
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
  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;
  }
}

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

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

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

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

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

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

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

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

567 568 569 570 571 572 573
  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 已提交
574
    for (int32_t i = pBlock->info.rows - 1; i >= 0; --i) {
575 576 577 578 579 580 581
      if (colDataIsNull_s(pColInfo, i)) {
        continue;
      }

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

      break;
    }
589 590 591
  }
}

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

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

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

602
  SResultRow* pResult = NULL;
603

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

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

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

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

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

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

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

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

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

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

5
54liuyao 已提交
661 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
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 已提交
717
typedef int64_t (*__get_value_fn_t)(void* data, int32_t index);
718

X
Xiaoyu Wang 已提交
719 720 721
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 已提交
722 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

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

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

5
54liuyao 已提交
773
int32_t comparePullWinKey(void* pKey, void* data, int32_t index) {
L
Liu Jicong 已提交
774
  SArray*          res = (SArray*)data;
5
54liuyao 已提交
775
  SPullWindowInfo* pos = taosArrayGet(res, index);
L
Liu Jicong 已提交
776
  SPullWindowInfo* pData = (SPullWindowInfo*)pKey;
5
54liuyao 已提交
777
  if (pData->groupId > pos->groupId) {
5
54liuyao 已提交
778
    return 1;
5
54liuyao 已提交
779 780 781 782 783 784 785 786
  } 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 已提交
787
  }
5
54liuyao 已提交
788
  return 0;
5
54liuyao 已提交
789 790 791 792 793 794 795 796
}

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 已提交
797 798
    int32_t code = comparePullWinKey(pPullInfo, pPullWins, index);
    if (code == 0) {
L
Liu Jicong 已提交
799
      SPullWindowInfo* pos = taosArrayGet(pPullWins, index);
5
54liuyao 已提交
800 801 802 803
      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 已提交
804
      return TSDB_CODE_SUCCESS;
L
Liu Jicong 已提交
805
    } else if (code > 0) {
5
54liuyao 已提交
806
      index++;
5
54liuyao 已提交
807 808 809 810 811 812 813 814
    }
  }
  if (taosArrayInsert(pPullWins, index, pPullInfo) == NULL) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
815 816 817
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 已提交
818 819
}

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

5
54liuyao 已提交
825 826 827 828
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 已提交
829 830
}

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

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

849
static void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) {
5
54liuyao 已提交
850 851
  taosArraySort(pDelWins, winKeyCmprImpl);
  taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL);
L
Liu Jicong 已提交
852
  int32_t delSize = taosArrayGetSize(pDelWins);
853
  if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) {
5
54liuyao 已提交
854
    return;
dengyihao's avatar
dengyihao 已提交
855
  }
856 857 858 859 860 861
  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)) {
862
      taosArrayRemove(pDelWins, index);
863
      delSize = taosArrayGetSize(pDelWins);
864 865 866 867
    }
  }
}

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

5
54liuyao 已提交
873 874 875 876 877
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 已提交
878

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

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

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

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

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

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

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

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

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

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

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

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

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

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);
972
    SListNode* pNode = tdListPopHead(pResultRowInfo->openWindow);
D
dapan1121 已提交
973
    taosMemoryFree(pNode);
974 975 976
  }
}

977 978 979 980 981
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 已提交
982
  SListNode* pn = tdListGetTail(pResultRowInfo->openWindow);
983
  if (pn == NULL) {
984 985
    tdListAppend(pResultRowInfo->openWindow, &openWin);
    return openWin.pos;
986 987
  }

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

993
  return openWin.pos;
994 995 996 997
}

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

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

1004 1005 1006 1007 1008 1009
    // 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)) {
1010 1011 1012 1013 1014
      blockDataUpdateTsWindow(pBlock, pInfo->primaryTsIndex);
    }
  }

  return tsCols;
1015 1016 1017 1018 1019 1020 1021
}

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

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

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

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

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

1037
    pInfo->binfo.pRes->info.scanFlag = scanFlag = pBlock->info.scanFlag;
1038

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

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

1049
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, pInfo->binfo.outputTsOrder);
1050
  OPTR_SET_OPENED(pOperator);
1051 1052

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

1056 1057 1058 1059 1060
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 已提交
1061
      return memcmp(varDataVal(v), varDataVal(pKey->pData), varDataLen(v)) == 0;
1062 1063 1064 1065 1066 1067
    }
  } else {
    return memcmp(pKey->pData, v, pKey->bytes) == 0;
  }
}

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

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

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

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

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

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

    char* val = colDataGetData(pStateColInfoData, j);

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

1102 1103
      pInfo->hasKey = true;

1104 1105
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
1106
    } else if (compareVal(val, &pInfo->stateKey)) {
1107
      doKeepTuple(pRowSup, tsList[j], gid);
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
      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;
1118 1119
      int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
                                           numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1120
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1121
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1122 1123
      }

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

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

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

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

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

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

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

1162
  SExprSupp* pSup = &pOperator->exprSupp;
1163
  int32_t    order = pInfo->binfo.inputTsOrder;
1164
  int64_t    st = taosGetTimestampUs();
1165 1166 1167

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

W
wangjiaming0909 已提交
1173
    pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
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->binfo.inputTsOrder = pPhyNode->window.node.inputTsOrder;
  pInfo->binfo.outputTsOrder = pPhyNode->window.node.outputTsOrder;
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
      }

      // pInfo->numOfRows data belong to the current session window
L
liuyao 已提交
1756
      updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &window, 0);
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
  }

L
liuyao 已提交
1774
  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pRowSup->win, 0);
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
  int64_t st = taosGetTimestampUs();
1808
  int32_t order = pInfo->binfo.inputTsOrder;
1809

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

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

W
wangjiaming0909 已提交
1818
    pBInfo->pRes->info.scanFlag = pBlock->info.scanFlag;
1819
    // the pDataBlock are always the same one, no need to call this again
1820
    setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
1821 1822
    blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);

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

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

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

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

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

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

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

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

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

1872
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
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;
  }
1879 1880
  pInfo->binfo.inputTsOrder = pStateNode->window.node.inputTsOrder;
  pInfo->binfo.outputTsOrder = pStateNode->window.node.outputTsOrder;
1881

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

1887 1888
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;

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

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

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

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

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

X
Xiaoyu Wang 已提交
1908
  pInfo->tsSlotId = tsSlotId;
1909

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

1915 1916 1917 1918 1919
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

1920 1921
  return pOperator;

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

1927 1928
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
1929 1930 1931
  return NULL;
}

1932
void destroySWindowOperatorInfo(void* param) {
1933
  SSessionAggOperatorInfo* pInfo = (SSessionAggOperatorInfo*)param;
1934 1935 1936
  if (pInfo == NULL) {
    return;
  }
1937

1938
  cleanupBasicInfo(&pInfo->binfo);
H
Haojun Liao 已提交
1939 1940 1941 1942
  colDataDestroy(&pInfo->twAggSup.timeWindowData);

  cleanupAggSup(&pInfo->aggSup);
  cleanupGroupResInfo(&pInfo->groupResInfo);
D
dapan1121 已提交
1943
  taosMemoryFreeClear(param);
1944 1945
}

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

1954
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
1955
  initResultSizeInfo(&pOperator->resultInfo, 4096);
1956

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

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

H
Haojun Liao 已提交
1968 1969 1970 1971
  pInfo->twAggSup.waterMark = pSessionNode->window.watermark;
  pInfo->twAggSup.calTrigger = pSessionNode->window.triggerType;
  pInfo->gap = pSessionNode->gap;

1972
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
1973 1974
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);

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

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

1996 1997
  return pOperator;

L
Liu Jicong 已提交
1998
_error:
1999
  destroySWindowOperatorInfo(pInfo);
2000 2001 2002
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
2003
}
5
54liuyao 已提交
2004

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

      SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pDestCtx[k]);
L
Liu Jicong 已提交
2014 2015
      char*                p = GET_ROWCELL_INTERBUF(pEntryInfo);
      SColumnInfoData      idata = {0};
2016 2017 2018 2019 2020 2021 2022 2023
      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 已提交
2024
    } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) {
2025
      int32_t code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]);
5
54liuyao 已提交
2026
      if (code != TSDB_CODE_SUCCESS) {
5
54liuyao 已提交
2027
        qError("%s apply combine functions error, code: %s", GET_TASKID(pTaskInfo), tstrerror(code));
5
54liuyao 已提交
2028
      }
5
54liuyao 已提交
2029 2030 2031 2032
    } 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 已提交
2033 2034 2035 2036
    }
  }
}

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

2039
int32_t setIntervalOutputBuf(void* pState, STimeWindow* win, SRowBuffPos** pResult, int64_t groupId,
dengyihao's avatar
dengyihao 已提交
2040
                             SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset,
2041 2042 2043
                             SAggSupporter* pAggSup, SStateStore* pStore) {

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

2047
  if (pStore->streamStateAddIfNotExist(pState, &key, (void**)&value, &size) < 0) {
5
54liuyao 已提交
2048 2049
    return TSDB_CODE_OUT_OF_MEMORY;
  }
2050

5
54liuyao 已提交
2051 2052
  *pResult = (SRowBuffPos*)value;
  SResultRow* res = (SResultRow*)((*pResult)->pRowBuff);
2053

5
54liuyao 已提交
2054
  // set time window for current result
dengyihao's avatar
dengyihao 已提交
2055
  res->win = (*win);
5
54liuyao 已提交
2056 2057
  setResultRowInitCtx(res, pCtx, numOfOutput, rowEntryInfoOffset);
  return TSDB_CODE_SUCCESS;
2058 2059
}

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

L
Liu Jicong 已提交
2071 2072 2073 2074
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 已提交
2075 2076 2077 2078
  int32_t prevEndPos = forwardRows - 1 + startPos;
  return getNextQualifiedWindow(pInterval, pNextWin, pBlockInfo, tsCols, prevEndPos, TSDB_ORDER_ASC);
}

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

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

5
54liuyao 已提交
2095 2096 2097 2098
static void clearSpecialDataBlock(SSDataBlock* pBlock) {
  if (pBlock->info.rows <= 0) {
    return;
  }
5
54liuyao 已提交
2099 2100 2101
  blockDataCleanup(pBlock);
}

5
54liuyao 已提交
2102 2103 2104 2105 2106 2107
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 已提交
2108
  blockDataEnsureCapacity(pBlock, size - (*pIndex));
2109 2110 2111 2112 2113
  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 已提交
2114
  for (; (*pIndex) < size; (*pIndex)++) {
L
Liu Jicong 已提交
2115
    SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex));
2116 2117 2118 2119 2120
    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 已提交
2121 2122 2123 2124 2125 2126 2127 2128 2129
    pBlock->info.rows++;
  }
  if ((*pIndex) == size) {
    *pIndex = 0;
    taosArrayClear(array);
  }
  blockDataUpdateTsWindow(pBlock, 0);
}

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

            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 已提交
2170
          }
5
54liuyao 已提交
2171 2172
        }
      }
5
54liuyao 已提交
2173
      winTs = taosTimeAdd(winTs, pInterval->sliding, pInterval->slidingUnit, pInterval->precision);
5
54liuyao 已提交
2174 2175 2176
    }
  }
}
5
54liuyao 已提交
2177

L
liuyao 已提交
2178
static void addRetriveWindow(SArray* wins, SStreamIntervalOperatorInfo* pInfo, int32_t childId) {
2179 2180
  int32_t size = taosArrayGetSize(wins);
  for (int32_t i = 0; i < size; i++) {
L
Liu Jicong 已提交
2181
    SWinKey*    winKey = taosArrayGet(wins, i);
2182
    STimeWindow nextWin = getFinalTimeWindow(winKey->ts, &pInfo->interval);
L
liuyao 已提交
2183 2184 2185 2186 2187 2188 2189 2190 2191
    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 已提交
2192 2193
        addPullWindow(pInfo->pPullDataMap, winKey, pInfo->numOfChild);
        qDebug("===stream===prepare retrive for delete %" PRId64 ", size:%d", winKey->ts, pInfo->numOfChild);
2194
      }
L
liuyao 已提交
2195 2196 2197 2198 2199 2200 2201 2202
    } 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);
      }
2203 2204 2205 2206
    }
  }
}

5
54liuyao 已提交
2207 2208 2209 2210 2211 2212
static void clearFunctionContext(SExprSupp* pSup) {
  for (int32_t i = 0; i < pSup->numOfExprs; i++) {
    pSup->pCtx[i].saveHandle.currentPage = -1;
  }
}

2213 2214
int32_t getOutputBuf(void* pState, SRowBuffPos* pPos, SResultRow** pResult, SStateStore* pStore) {
  return pStore->streamStateGetByPos(pState, pPos, (void**)pResult);
5
54liuyao 已提交
2215 2216
}

2217
int32_t buildDataBlockFromGroupRes(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock, SExprSupp* pSup,
5
54liuyao 已提交
2218 2219
                                   SGroupResInfo* pGroupResInfo) {
  SExecTaskInfo*  pTaskInfo = pOperator->pTaskInfo;
2220 2221
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
2222 2223 2224 2225 2226 2227 2228 2229 2230 2231
  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;
2232
    int32_t      code = getOutputBuf(pState, pPos, &pRow, &pAPI->stateStore);
5
54liuyao 已提交
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
    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;
2244
      if (pAPI->stateStore.streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) {
5
54liuyao 已提交
2245 2246 2247 2248
        pBlock->info.parTbName[0] = 0;
      } else {
        memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN);
      }
2249
      pAPI->stateStore.streamStateFreeVal(tbname);
5
54liuyao 已提交
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
    } 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 已提交
2268

5
54liuyao 已提交
2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289
      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 已提交
2290

5
54liuyao 已提交
2291 2292 2293 2294 2295
  pBlock->info.dataLoad = 1;
  blockDataUpdateTsWindow(pBlock, 0);
  return TSDB_CODE_SUCCESS;
}

2296
void doBuildStreamIntervalResult(SOperatorInfo* pOperator, void* pState, SSDataBlock* pBlock,
2297
                                 SGroupResInfo* pGroupResInfo) {
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
  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 已提交
2308
  pBlock->info.id.groupId = 0;
2309
  buildDataBlockFromGroupRes(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
2310 2311
}

5
54liuyao 已提交
2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322
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 已提交
2323
static void setStreamDataVersion(SExecTaskInfo* pTaskInfo, int64_t version, int64_t ckId) {
L
liuyao 已提交
2324
  pTaskInfo->streamInfo.dataVersion = version;
L
liuyao 已提交
2325
  pTaskInfo->streamInfo.checkPointId = ckId;
L
liuyao 已提交
2326 2327
}

2328
static void doStreamIntervalAggImpl(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataBlock, uint64_t groupId,
2329
                                    SSHashObj* pUpdatedMap) {
2330
  SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperatorInfo->info;
L
liuyao 已提交
2331
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
2332 2333 2334 2335 2336 2337 2338

  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 已提交
2339
  SRowBuffPos*    pResPos = NULL;
2340 2341 2342 2343 2344 2345 2346 2347
  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 已提交
2348 2349 2350 2351 2352 2353
  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);
  }
2354 2355
  while (1) {
    bool isClosed = isCloseWindow(&nextWin, &pInfo->twAggSup);
L
liuyao 已提交
2356
    if ((pInfo->ignoreExpiredData && isClosed && !IS_FINAL_OP(pInfo)) || !inSlidingWindow(&pInfo->interval, &nextWin, &pSDataBlock->info)) {
2357 2358 2359 2360 2361 2362 2363
      startPos = getNexWindowPos(&pInfo->interval, &pSDataBlock->info, tsCols, startPos, nextWin.ekey, &nextWin);
      if (startPos < 0) {
        break;
      }
      continue;
    }

L
liuyao 已提交
2364
    if (IS_FINAL_OP(pInfo) && pInfo->numOfChild > 0) {
2365 2366 2367 2368 2369 2370
      bool    ignore = true;
      SWinKey winRes = {
          .ts = nextWin.skey,
          .groupId = groupId,
      };
      void* chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
2371
      if (isDeletedStreamWindow(&nextWin, groupId, pInfo->pState, &pInfo->twAggSup, &pInfo->statestore) && isClosed && !chIds) {
L
Liu Jicong 已提交
2372 2373
        SPullWindowInfo pull = {
            .window = nextWin, .groupId = groupId, .calWin.skey = nextWin.skey, .calWin.ekey = nextWin.skey};
2374
        // add pull data request
5
54liuyao 已提交
2375
        if (savePullWindow(&pull, pInfo->pPullWins) == TSDB_CODE_SUCCESS) {
L
liuyao 已提交
2376
          addPullWindow(pInfo->pPullDataMap, &winRes, pInfo->numOfChild);
5
54liuyao 已提交
2377
        }
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392
      } 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 已提交
2393
        startPos = getNextQualifiedFinalWindow(&pInfo->interval, &nextWin, &pSDataBlock->info, tsCols, startPos);
2394 2395 2396 2397 2398 2399 2400
        if (startPos < 0) {
          break;
        }
        continue;
      }
    }

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

    SWinKey key = {
dengyihao's avatar
dengyihao 已提交
2415 2416
        .ts = pResult->win.skey,
        .groupId = groupId,
5
54liuyao 已提交
2417
    };
2418
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pUpdatedMap) {
5
54liuyao 已提交
2419
      saveWinResult(&key, pResPos, pUpdatedMap);
2420
    }
5
54liuyao 已提交
2421 2422

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

L
liuyao 已提交
2426
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, 1);
H
Haojun Liao 已提交
2427
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
2428
                                    pSDataBlock->info.rows, numOfOutput);
5
54liuyao 已提交
2429
    key.ts = nextWin.skey;
dengyihao's avatar
dengyihao 已提交
2430

2431 2432 2433 2434
    if (pInfo->delKey.ts > key.ts) {
      pInfo->delKey = key;
    }
    int32_t prevEndPos = (forwardRows - 1) * step + startPos;
2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
    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 已提交
2448 2449 2450 2451 2452 2453
    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);
    }
2454 2455 2456 2457 2458 2459
    if (startPos < 0) {
      break;
    }
  }
}

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

  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 已提交
2481 2482 2483 2484 2485 2486 2487 2488 2489
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 已提交
2490
static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
2491
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
L
Liu Jicong 已提交
2492
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
2493 2494
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
2495 2496
  SOperatorInfo*               downstream = pOperator->pDownstream[0];
  SExprSupp*                   pSup = &pOperator->exprSupp;
2497

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

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

2510
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
2511 2512 2513 2514 2515 2516
    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;
    }

2517
    doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
2518 2519 2520
    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 已提交
2521
    }
5
54liuyao 已提交
2522

L
liuyao 已提交
2523 2524 2525 2526 2527
    if (pInfo->recvGetAll) {
      pInfo->recvGetAll = false;
      resetUnCloseWinInfo(pInfo->aggSup.pResultRowHashTable);
    }

H
Haojun Liao 已提交
2528
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
2529 2530 2531 2532
    if (!IS_FINAL_OP(pInfo)) {
      clearFunctionContext(&pOperator->exprSupp);
      // semi interval operator clear disk buffer
      clearStreamIntervalOperator(pInfo);
L
liuyao 已提交
2533
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
5
54liuyao 已提交
2534 2535
      qDebug("===stream===clear semi operator");
    } else {
dengyihao's avatar
dengyihao 已提交
2536 2537
      if (pInfo->twAggSup.maxTs > 0 &&
          pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
2538 2539
        pAPI->stateStore.streamStateCommit(pInfo->pState);
        pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
2540 2541
        pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
      }
L
liuyao 已提交
2542
      qDebug("===stream===interval final close");
5
54liuyao 已提交
2543 2544
    }
    return NULL;
5
54liuyao 已提交
2545
  } else {
5
54liuyao 已提交
2546
    if (!IS_FINAL_OP(pInfo)) {
2547
      doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
2548 2549 2550 2551 2552
      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 已提交
2553
    }
5
54liuyao 已提交
2554 2555
  }

5
54liuyao 已提交
2556
  if (!pInfo->pUpdated) {
L
liuyao 已提交
2557
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
2558 2559 2560
  }
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
2561
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
2562 2563
  }

5
54liuyao 已提交
2564
  while (1) {
H
Haojun Liao 已提交
2565
    if (isTaskKilled(pTaskInfo)) {
H
Haojun Liao 已提交
2566 2567 2568 2569 2570 2571 2572 2573 2574
      if (pInfo->pUpdated != NULL) {
        pInfo->pUpdated = taosArrayDestroy(pInfo->pUpdated);
      }

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

H
Haojun Liao 已提交
2575 2576 2577
      T_LONG_JMP(pTaskInfo->env, pTaskInfo->code);
    }

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

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

      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 已提交
2612 2613 2614 2615 2616
        if (pBlock->info.type == STREAM_CLEAR) {
          pInfo->pDelRes->info.type = STREAM_CLEAR;
        } else {
          pInfo->pDelRes->info.type = STREAM_DELETE_RESULT;
        }
L
liuyao 已提交
2617 2618 2619
        return pInfo->pDelRes;
      }

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

5
54liuyao 已提交
2640 2641 2642 2643
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
2644
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
2645 2646 2647 2648
    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 已提交
2649
  }
S
shenglian zhou 已提交
2650

5
54liuyao 已提交
2651
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
5
54liuyao 已提交
2652
  if (IS_FINAL_OP(pInfo)) {
2653
    closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval,
5
54liuyao 已提交
2654
                              pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5
54liuyao 已提交
2655
  }
2656
  pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs;
5
54liuyao 已提交
2657

2658 2659 2660
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
2661
    taosArrayPush(pInfo->pUpdated, pIte);
5
54liuyao 已提交
2662
  }
H
Haojun Liao 已提交
2663

2664
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
2665
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
2666
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
5
54liuyao 已提交
2667

5
54liuyao 已提交
2668 2669
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
2670
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
2671 2672 2673 2674

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

2679
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
5
54liuyao 已提交
2680 2681 2682 2683 2684 2685
  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;
  }

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

  return NULL;
}

5
54liuyao 已提交
2695 2696 2697 2698
int64_t getDeleteMark(SIntervalPhysiNode* pIntervalPhyNode) {
  if (pIntervalPhyNode->window.deleteMark <= 0) {
    return DEAULT_DELETE_MARK;
  }
L
Liu Jicong 已提交
2699
  int64_t deleteMark = TMAX(pIntervalPhyNode->window.deleteMark, pIntervalPhyNode->window.watermark);
5
54liuyao 已提交
2700 2701 2702 2703
  deleteMark = TMAX(deleteMark, pIntervalPhyNode->interval);
  return deleteMark;
}

5
54liuyao 已提交
2704
TSKEY compareTs(void* pKey) {
dengyihao's avatar
dengyihao 已提交
2705
  SWinKey* pWinKey = (SWinKey*)pKey;
5
54liuyao 已提交
2706 2707 2708
  return pWinKey->ts;
}

L
liuyao 已提交
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
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 已提交
2732
void streamIntervalReleaseState(SOperatorInfo* pOperator) {
L
liuyao 已提交
2733 2734 2735 2736
  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 已提交
2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
  }
  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 已提交
2748 2749 2750 2751 2752 2753 2754
  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;
L
liuyao 已提交
2755
    taosMemoryFree(pBuf);
L
liuyao 已提交
2756
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, ts);
L
liuyao 已提交
2757 2758
    pInfo->statestore.streamStateReloadInfo(pInfo->pState, ts);
  }
L
liuyao 已提交
2759 2760 2761 2762 2763 2764
  SOperatorInfo* downstream = pOperator->pDownstream[0];
  if (downstream->fpSet.reloadStreamStateFn) {
    downstream->fpSet.reloadStreamStateFn(downstream);
  }
}

S
shenglian zhou 已提交
2765 2766
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                     SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
2767 2768 2769
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
2770 2771 2772
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
2773

2774
  pOperator->pTaskInfo = pTaskInfo;
2775 2776
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;

S
shenglian zhou 已提交
2777 2778 2779 2780 2781 2782 2783 2784
  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 已提交
2785 2786
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
2787
      .minTs = INT64_MAX,
5
54liuyao 已提交
2788
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
Liu Jicong 已提交
2789 2790
      .deleteMarkSaved = 0,
      .calTriggerSaved = 0,
L
liuyao 已提交
2791
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
2792 2793
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
S
shenglian zhou 已提交
2794
  };
5
54liuyao 已提交
2795
  ASSERTS(pInfo->twAggSup.calTrigger != STREAM_TRIGGER_MAX_DELAY, "trigger type should not be max delay");
5
54liuyao 已提交
2796 2797
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
2798
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
2799 2800 2801
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
2802
    int32_t    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
2803 2804 2805 2806 2807
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

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

L
liuyao 已提交
2813 2814
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2815

2816
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
Liu Jicong 已提交
2817
  int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
2818
                            pInfo->pState, &pTaskInfo->storageAPI.functionStore);
2819 2820 2821 2822
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
2823
  initStreamFunciton(pOperator->exprSupp.pCtx, pOperator->exprSupp.numOfExprs);
5
54liuyao 已提交
2824
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2825
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2826

L
liuyao 已提交
2827
  pInfo->numOfChild = numOfChild;
5
54liuyao 已提交
2828

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

5
54liuyao 已提交
2831 2832 2833 2834
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL) {
    pInfo->isFinal = true;
    pOperator->name = "StreamFinalIntervalOperator";
  } else {
5
54liuyao 已提交
2835
    // semi interval operator does not catch result
5
54liuyao 已提交
2836 2837 2838 2839
    pInfo->isFinal = false;
    pOperator->name = "StreamSemiIntervalOperator";
  }

5
54liuyao 已提交
2840
  if (!IS_FINAL_OP(pInfo) || numOfChild == 0) {
5
54liuyao 已提交
2841 2842
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
  }
2843

5
54liuyao 已提交
2844 2845 2846 2847
  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 已提交
2848
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK);
2849
  pInfo->pPullDataRes = createSpecialDataBlock(STREAM_RETRIEVE);
5
54liuyao 已提交
2850
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2851
  pInfo->ignoreExpiredDataSaved = false;
2852
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
2853
  pInfo->delIndex = 0;
H
Haojun Liao 已提交
2854
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
2855 2856
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
2857
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
2858 2859
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
2860
  int32_t funResSize= getMaxFunResSize(&pOperator->exprSupp, numOfCols);
2861
  pInfo->pState->pFileState = pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
2862
                                                  compareTs, pInfo->pState, pInfo->twAggSup.deleteMark, GET_TASKID(pTaskInfo));
L
liuyao 已提交
2863
  pInfo->dataVersion = 0;
2864
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
2865
  pInfo->recvGetAll = false;
5
54liuyao 已提交
2866

5
54liuyao 已提交
2867
  pOperator->operatorType = pPhyNode->type;
5
54liuyao 已提交
2868 2869 2870 2871
  pOperator->blocking = true;
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;

L
Liu Jicong 已提交
2872 2873
  pOperator->fpSet = createOperatorFpSet(NULL, doStreamFinalIntervalAgg, NULL, destroyStreamFinalIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
2874
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
2875
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL) {
L
liuyao 已提交
2876
    initIntervalDownStream(downstream, pPhyNode->type, pInfo);
2877
  }
5
54liuyao 已提交
2878 2879 2880 2881 2882 2883 2884 2885
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
2886
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5
54liuyao 已提交
2887 2888 2889
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
5
54liuyao 已提交
2890
}
5
54liuyao 已提交
2891 2892

void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
5
54liuyao 已提交
2893
  tSimpleHashCleanup(pSup->pResultRows);
5
54liuyao 已提交
2894 2895
  destroyDiskbasedBuf(pSup->pResultBuf);
  blockDataDestroy(pSup->pScanBlock);
5
54liuyao 已提交
2896 2897
  taosMemoryFreeClear(pSup->pState);
  taosMemoryFreeClear(pSup->pDummyCtx);
5
54liuyao 已提交
2898 2899
}

2900
void destroyStreamSessionAggOperatorInfo(void* param) {
5
54liuyao 已提交
2901
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
2902
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
2903
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
2904

2905 2906 2907
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
2908
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
2909
      destroyOperator(pChild);
2910
    }
5
54liuyao 已提交
2911
    taosArrayDestroy(pInfo->pChildren);
2912
  }
H
Haojun Liao 已提交
2913

5
54liuyao 已提交
2914 2915 2916 2917
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
  blockDataDestroy(pInfo->pWinBlock);
  blockDataDestroy(pInfo->pUpdateRes);
L
liuyao 已提交
2918
  tSimpleHashCleanup(pInfo->pStUpdated);
5
54liuyao 已提交
2919
  tSimpleHashCleanup(pInfo->pStDeleted);
2920

H
Haojun Liao 已提交
2921
  taosArrayDestroy(pInfo->historyWins);
D
dapan1121 已提交
2922
  taosMemoryFreeClear(param);
5
54liuyao 已提交
2923 2924
}

2925
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
2926
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
H
Haojun Liao 已提交
2927
  initBasicInfo(pBasicInfo, pResultBlock);
2928
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
2929 2930 2931
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
2932

H
Haojun Liao 已提交
2933
  initStreamFunciton(pSup->pCtx, pSup->numOfExprs);
5
54liuyao 已提交
2934
  for (int32_t i = 0; i < numOfCols; ++i) {
2935
    pSup->pCtx[i].saveHandle.pBuf = NULL;
5
54liuyao 已提交
2936
  }
2937

2938
  ASSERT(numOfCols > 0);
5
54liuyao 已提交
2939 2940 2941 2942 2943 2944
  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;
2945 2946
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
5
54liuyao 已提交
2947 2948
  }
}
5
54liuyao 已提交
2949

5
54liuyao 已提交
2950 2951
void initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
                    STimeWindowAggSupp* pTwSup) {
2952 2953 2954 2955 2956 2957
  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 已提交
2958
    initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup);
2959 2960
    return;
  }
2961
  SStreamScanInfo* pScanInfo = downstream->info;
5
54liuyao 已提交
2962
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
L
fix bug  
liuyao 已提交
2963
  pScanInfo->pState = pAggSup->pState;
J
jiajingbin 已提交
2964
  if (!pScanInfo->pUpdateInfo) {
2965
    pScanInfo->pUpdateInfo = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark);
5
54liuyao 已提交
2966
  }
5
54liuyao 已提交
2967
  pScanInfo->twAggSup = *pTwSup;
5
54liuyao 已提交
2968 2969
}

5
54liuyao 已提交
2970
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, int64_t gap,
L
liuyao 已提交
2971
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore, SReadHandle* pHandle, SStorageAPI* pApi) {
5
54liuyao 已提交
2972 2973 2974 2975 2976 2977 2978 2979
  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 已提交
2980
  }
H
Haojun Liao 已提交
2981

2982 2983
  pSup->stateStore = *pStore;

5
54liuyao 已提交
2984 2985 2986
  initDummyFunction(pSup->pDummyCtx, pCtx, numOfOutput);
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pSup->pState) = *pState;
2987
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1);
2988

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

5
54liuyao 已提交
2992 2993 2994
  int32_t pageSize = 4096;
  while (pageSize < pSup->resultRowSize * 4) {
    pageSize <<= 1u;
5
54liuyao 已提交
2995
  }
5
54liuyao 已提交
2996 2997 2998 2999
  // at least four pages need to be in buffer
  int32_t bufSize = 4096 * 256;
  if (bufSize <= pageSize) {
    bufSize = pageSize * 4;
5
54liuyao 已提交
3000
  }
3001

5
54liuyao 已提交
3002
  if (!osTempSpaceAvailable()) {
3003 3004
    terrno = TSDB_CODE_NO_DISKSPACE;
    qError("Init stream agg supporter failed since %s, tempDir:%s", terrstr(), tsTempDir);
5
54liuyao 已提交
3005
    return terrno;
5
54liuyao 已提交
3006
  }
H
Haojun Liao 已提交
3007

5
54liuyao 已提交
3008 3009 3010
  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 已提交
3011 3012
  }

L
liuyao 已提交
3013 3014
  pSup->pSessionAPI = pApi;

5
54liuyao 已提交
3015
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3016
}
5
54liuyao 已提交
3017 3018

bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5
54liuyao 已提交
3019
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5
54liuyao 已提交
3020 3021 3022 3023 3024
    return true;
  }
  return false;
}

5
54liuyao 已提交
3025 3026
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
5
54liuyao 已提交
3027 3028
}

5
54liuyao 已提交
3029 3030 3031 3032 3033
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SSessionKey* pKey) {
  pKey->win.skey = startTs;
  pKey->win.ekey = endTs;
  pKey->groupId = groupId;
3034
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
5
54liuyao 已提交
3035 3036
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_KEY_INVALID(pKey);
3037 3038 3039
  }
}

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

L
liuyao 已提交
3042 3043 3044 3045 3046 3047 3048
bool inWinRange(STimeWindow* range, STimeWindow* cur) {
  if (cur->skey >= range->skey && cur->ekey <= range->ekey) {
    return true;
  }
  return false;
}

5
54liuyao 已提交
3049 3050 3051
void setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SResultWindowInfo* pCurWin) {
  pCurWin->sessionWin.groupId = groupId;
3052 3053
  pCurWin->sessionWin.win.skey = startTs;
  pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3054
  int32_t size = pAggSup->resultRowSize;
3055 3056
  int32_t code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin,
                                                                     pAggSup->gap, &pCurWin->pOutputBuf, &size);
L
liuyao 已提交
3057 3058 3059
  if (code == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->sessionWin.win)) {
    code = TSDB_CODE_FAILED;
    releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)pCurWin->pOutputBuf, &pAggSup->pSessionAPI->stateStore);
L
liuyao 已提交
3060
    pCurWin->pOutputBuf = taosMemoryCalloc(1, size);
L
liuyao 已提交
3061 3062
  }

5
54liuyao 已提交
3063 3064
  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->isOutput = true;
L
liuyao 已提交
3065
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->sessionWin);
5
54liuyao 已提交
3066 3067 3068
  } else {
    pCurWin->sessionWin.win.skey = startTs;
    pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3069
  }
5
54liuyao 已提交
3070
}
5
54liuyao 已提交
3071

5
54liuyao 已提交
3072 3073
int32_t getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo) {
  int32_t size = 0;
3074
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin, &pWinInfo->pOutputBuf, &size);
5
54liuyao 已提交
3075 3076
  if (code != TSDB_CODE_SUCCESS) {
    return code;
5
54liuyao 已提交
3077
  }
3078 3079

  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
5
54liuyao 已提交
3080 3081 3082 3083 3084
  return TSDB_CODE_SUCCESS;
}
void saveDeleteInfo(SArray* pWins, SSessionKey key) {
  // key.win.ekey = key.win.skey;
  taosArrayPush(pWins, &key);
5
54liuyao 已提交
3085 3086
}

5
54liuyao 已提交
3087 3088 3089 3090
void saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
  key.win.ekey = key.win.skey;
  tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
}
3091

5
54liuyao 已提交
3092 3093 3094 3095 3096
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 已提交
3097

5
54liuyao 已提交
3098 3099 3100 3101 3102
static void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
  *pHashKey = *pKey;
  pHashKey->win.ekey = pKey->win.skey;
}

5
54liuyao 已提交
3103 3104 3105
static void removeSessionResults(SSHashObj* pHashMap, SArray* pWins) {
  if (tSimpleHashGetSize(pHashMap) == 0) {
    return;
5
54liuyao 已提交
3106
  }
5
54liuyao 已提交
3107 3108 3109 3110
  int32_t size = taosArrayGetSize(pWins);
  for (int32_t i = 0; i < size; i++) {
    SSessionKey* pWin = taosArrayGet(pWins, i);
    if (!pWin) continue;
5
54liuyao 已提交
3111 3112
    SSessionKey key = {0};
    getSessionHashKey(pWin, &key);
5
54liuyao 已提交
3113
    tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
5
54liuyao 已提交
3114 3115 3116
  }
}

dengyihao's avatar
dengyihao 已提交
3117
int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t groupId,
5
54liuyao 已提交
3118 3119
                                int32_t rows, int32_t start, int64_t gap, SSHashObj* pResultRows, SSHashObj* pStUpdated,
                                SSHashObj* pStDeleted) {
5
54liuyao 已提交
3120
  for (int32_t i = start; i < rows; ++i) {
3121
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
5
54liuyao 已提交
3122 3123
      return i - start;
    }
5
54liuyao 已提交
3124
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
5
54liuyao 已提交
3125
      if (pStDeleted && pWinInfo->isOutput) {
5
54liuyao 已提交
3126
        saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
5
54liuyao 已提交
3127
      }
5
54liuyao 已提交
3128 3129
      removeSessionResult(pStUpdated, pResultRows, pWinInfo->sessionWin);
      pWinInfo->sessionWin.win.skey = pStartTs[i];
5
54liuyao 已提交
3130
    }
5
54liuyao 已提交
3131
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
5
54liuyao 已提交
3132
    if (pEndTs) {
5
54liuyao 已提交
3133
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
5
54liuyao 已提交
3134 3135 3136 3137 3138
    }
  }
  return rows - start;
}

5
54liuyao 已提交
3139 3140
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
3141
  ASSERT(pWinInfo->sessionWin.win.skey <= pWinInfo->sessionWin.win.ekey);
5
54liuyao 已提交
3142
  *pResult = (SResultRow*)pWinInfo->pOutputBuf;
5
54liuyao 已提交
3143
  // set time window for current result
5
54liuyao 已提交
3144
  (*pResult)->win = pWinInfo->sessionWin.win;
3145
  setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
5
54liuyao 已提交
3146 3147 3148
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3149 3150
static int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
                                  int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
L
liuyao 已提交
3151
                                  SOperatorInfo* pOperator, int64_t winDelta) {
3152
  SExprSupp*     pSup = &pOperator->exprSupp;
3153
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3154
  int32_t        code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
3155
  if (code != TSDB_CODE_SUCCESS || (*pResult) == NULL) {
S
Shengliang Guan 已提交
3156
    return TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
3157
  }
L
liuyao 已提交
3158
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
H
Haojun Liao 已提交
3159
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
5
54liuyao 已提交
3160 3161 3162
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3163
static bool doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
3164
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
5
54liuyao 已提交
3165 3166 3167
  SSessionKey hashKey = {0};
  getSessionHashKey(pKey, &hashKey);
  tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
5
54liuyao 已提交
3168 3169 3170 3171 3172 3173 3174 3175 3176 3177
  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 已提交
3178 3179
}

5
54liuyao 已提交
3180 3181
SStreamStateCur* getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
                                       SResultWindowInfo* pNextWin) {
3182
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
5
54liuyao 已提交
3183 3184 3185 3186
  pNextWin->isOutput = true;
  setSessionWinOutputInfo(pStUpdated, pNextWin);
  int32_t size = 0;
  pNextWin->sessionWin = pCurWin->sessionWin;
3187
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin, &pNextWin->pOutputBuf, &size);
5
54liuyao 已提交
3188
  if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
3189
    taosMemoryFreeClear(pNextWin->pOutputBuf);
5
54liuyao 已提交
3190 3191 3192
    SET_SESSION_WIN_INVALID(*pNextWin);
  }
  return pCur;
5
54liuyao 已提交
3193 3194
}

5
54liuyao 已提交
3195
static void compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
L
liuyao 已提交
3196
                                 SSHashObj* pStDeleted, bool addGap) {
5
54liuyao 已提交
3197 3198
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3199 3200
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3201 3202 3203 3204 3205
  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 已提交
3206
  // Just look for the window behind StartIndex
5
54liuyao 已提交
3207 3208 3209
  while (1) {
    SResultWindowInfo winInfo = {0};
    SStreamStateCur*  pCur = getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
L
liuyao 已提交
3210 3211
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap) ||
        !inWinRange(&pAggSup->winRange, &winInfo.sessionWin.win)) {
dengyihao's avatar
dengyihao 已提交
3212
      taosMemoryFree(winInfo.pOutputBuf);
3213
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3214
      break;
5
54liuyao 已提交
3215
    }
5
54liuyao 已提交
3216 3217 3218
    SResultRow* pWinResult = NULL;
    initSessionOutputBuf(&winInfo, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
L
liuyao 已提交
3219
    int64_t winDelta = 0;
L
liuyao 已提交
3220
    if (addGap) {
L
liuyao 已提交
3221 3222 3223
      winDelta = pAggSup->gap;
    }
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, winDelta);
5
54liuyao 已提交
3224 3225 3226 3227 3228 3229 3230
    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);
3231
    pAPI->stateStore.streamStateFreeCur(pCur);
dengyihao's avatar
dengyihao 已提交
3232
    taosMemoryFree(winInfo.pOutputBuf);
5
54liuyao 已提交
3233 3234 3235
  }
}

5
54liuyao 已提交
3236
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
3237
  saveSessionDiscBuf(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pOutputBuf, pAggSup->resultRowSize, &pAggSup->stateStore);
L
liuyao 已提交
3238
  pWinInfo->pOutputBuf = NULL;
5
54liuyao 已提交
3239
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3240 3241
}

5
54liuyao 已提交
3242
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3243
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
X
Xiaoyu Wang 已提交
3244
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3245
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3246
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
3247
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
3248
  int64_t                        code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3249 3250 3251
  SResultRow*                    pResult = NULL;
  int32_t                        rows = pSDataBlock->info.rows;
  int32_t                        winRows = 0;
L
liuyao 已提交
3252
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
X
Xiaoyu Wang 已提交
3253

L
liuyao 已提交
3254
  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
L
liuyao 已提交
3255
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
L
liuyao 已提交
3256 3257 3258
  if (pAggSup->winRange.ekey <= 0) {
    pAggSup->winRange.ekey = INT64_MAX;
  }
L
liuyao 已提交
3259

5
54liuyao 已提交
3260
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3261
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
5
54liuyao 已提交
3262 3263 3264
  SColumnInfoData* pEndTsCol = NULL;
  if (hasEndTs) {
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
5
54liuyao 已提交
3265
  } else {
5
54liuyao 已提交
3266
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3267
  }
X
Xiaoyu Wang 已提交
3268

5
54liuyao 已提交
3269 3270
  TSKEY*               endTsCols = (int64_t*)pEndTsCol->pData;
  for (int32_t i = 0; i < rows;) {
5
54liuyao 已提交
3271
    if (pInfo->ignoreExpiredData && isOverdue(endTsCols[i], &pInfo->twAggSup)) {
5
54liuyao 已提交
3272 3273 3274
      i++;
      continue;
    }
5
54liuyao 已提交
3275 3276 3277 3278 3279
    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 已提交
3280 3281
    // coverity scan error
    if (!winInfo.pOutputBuf) {
S
Shengliang Guan 已提交
3282
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3283
    }
L
Liu Jicong 已提交
3284

L
liuyao 已提交
3285
    int64_t winDelta = 0;
3286
    if (addGap) {
L
liuyao 已提交
3287 3288
      winDelta = pAggSup->gap;
    }
5
54liuyao 已提交
3289
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
L
liuyao 已提交
3290
                              pOperator, winDelta);
5
54liuyao 已提交
3291
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
3292
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3293
    }
L
liuyao 已提交
3294
    compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted, addGap);
5
54liuyao 已提交
3295
    saveSessionOutputBuf(pAggSup, &winInfo);
5
54liuyao 已提交
3296 3297

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
5
54liuyao 已提交
3298
      code = saveResult(winInfo, pStUpdated);
5
54liuyao 已提交
3299
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
3300
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3301
      }
5
54liuyao 已提交
3302
    }
5
54liuyao 已提交
3303
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
3304 3305
      SSessionKey key = {0};
      getSessionHashKey(&winInfo.sessionWin, &key);
5
54liuyao 已提交
3306 3307 3308
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
    }

5
54liuyao 已提交
3309 3310 3311 3312
    i += winRows;
  }
}

5
54liuyao 已提交
3313
static void doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
5
54liuyao 已提交
3314
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3315
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
5
54liuyao 已提交
3316
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3317
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
3318
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3319
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
5
54liuyao 已提交
3320
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5
54liuyao 已提交
3321 3322 3323 3324
    while (1) {
      SSessionKey curWin = {0};
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
3325 3326
        break;
      }
5
54liuyao 已提交
3327 3328 3329 3330
      doDeleteSessionWindow(pAggSup, &curWin);
      if (result) {
        saveDeleteInfo(result, curWin);
      }
3331
    }
5
54liuyao 已提交
3332 3333 3334
  }
}

5
54liuyao 已提交
3335 3336 3337 3338 3339 3340 3341 3342
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 已提交
3343 3344
  }

5
54liuyao 已提交
3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357
  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) {
3358
    void* key = tSimpleHashGetKey(pIte, NULL);
5
54liuyao 已提交
3359 3360 3361 3362 3363 3364
    taosArrayPush(pUpdated, key);
  }
  taosArraySort(pUpdated, sessionKeyCompareAsc);
  return TSDB_CODE_SUCCESS;
}

3365
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
3366 3367
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;

5
54liuyao 已提交
3368 3369 3370 3371
  blockDataCleanup(pBlock);
  int32_t size = tSimpleHashGetSize(pStDeleted);
  if (size == 0) {
    return;
3372 3373
  }
  blockDataEnsureCapacity(pBlock, size);
5
54liuyao 已提交
3374 3375 3376 3377 3378
  int32_t iter = 0;
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
      break;
    }
3379
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
3380
    SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3381
    colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3382
    SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3383
    colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3384
    SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
3385
    colDataSetNULL(pUidCol, pBlock->info.rows);
5
54liuyao 已提交
3386
    SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3387
    colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false);
3388
    SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
3389
    colDataSetNULL(pCalStCol, pBlock->info.rows);
3390
    SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
3391
    colDataSetNULL(pCalEdCol, pBlock->info.rows);
3392 3393

    SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
3394 3395

    void* tbname = NULL;
3396
    pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, res->groupId, &tbname);
3397
    if (tbname == NULL) {
3398
      colDataSetNULL(pTableCol, pBlock->info.rows);
3399 3400 3401
    } else {
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
3402
      colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
3403
      pAPI->stateStore.streamStateFreeVal(tbname);
3404
    }
5
54liuyao 已提交
3405 3406 3407
    pBlock->info.rows += 1;
  }
  if ((*Ite) == NULL) {
5
54liuyao 已提交
3408
    tSimpleHashClear(pStDeleted);
5
54liuyao 已提交
3409 3410 3411
  }
}

5
54liuyao 已提交
3412 3413 3414
static void rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3415 3416
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3417 3418 3419 3420
  int32_t                        size = taosArrayGetSize(pWinArray);
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  int32_t                        numOfOutput = pSup->numOfExprs;
L
liuyao 已提交
3421
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
3422

3423
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3424 3425 3426
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
    int32_t           num = 0;
    SResultWindowInfo parentWin = {0};
L
liuyao 已提交
3427
    for (int32_t j = 0; j < numOfChild; j++) {
X
Xiaoyu Wang 已提交
3428
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
3429
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
5
54liuyao 已提交
3430
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
5
54liuyao 已提交
3431 3432
      SSessionKey                    chWinKey = {0};
      getSessionHashKey(pWinKey, &chWinKey);
3433
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
3434 3435
      SResultRow*      pResult = NULL;
      SResultRow*      pChResult = NULL;
5
54liuyao 已提交
3436 3437 3438 3439
      while (1) {
        SResultWindowInfo childWin = {0};
        childWin.sessionWin = *pWinKey;
        int32_t code = getSessionWinBuf(pChAggSup, pCur, &childWin);
L
liuyao 已提交
3440 3441 3442 3443 3444 3445

        if (code == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &childWin.sessionWin.win)) {
          continue;
        }

        if (code == TSDB_CODE_SUCCESS && inWinRange(&pWinKey->win, &childWin.sessionWin.win)) {
5
54liuyao 已提交
3446 3447 3448 3449 3450 3451
          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;
            }
3452
          }
5
54liuyao 已提交
3453
          num++;
L
liuyao 已提交
3454
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap); 
5
54liuyao 已提交
3455 3456 3457
          initSessionOutputBuf(&childWin, &pChResult, pChild->exprSupp.pCtx, numOfOutput,
                               pChild->exprSupp.rowEntryInfoOffset);
          compactFunctions(pSup->pCtx, pChild->exprSupp.pCtx, numOfOutput, pTaskInfo, &pInfo->twAggSup.timeWindowData);
L
liuyao 已提交
3458
          compactSessionWindow(pOperator, &parentWin, pStUpdated, NULL, true);
5
54liuyao 已提交
3459 3460
          saveResult(parentWin, pStUpdated);
        } else {
5
54liuyao 已提交
3461
          break;
3462 3463
        }
      }
3464
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3465 3466 3467
    }
    if (num > 0) {
      saveSessionOutputBuf(pAggSup, &parentWin);
3468 3469 3470 3471
    }
  }
}

5
54liuyao 已提交
3472 3473 3474 3475 3476 3477 3478 3479 3480 3481
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 已提交
3482 3483
        }
      }
3484
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
3485
      tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
5
54liuyao 已提交
3486 3487 3488 3489 3490
    }
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3491
static void closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
5
54liuyao 已提交
3492 3493 3494 3495 3496
  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 已提交
3497
    closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
5
54liuyao 已提交
3498 3499 3500
  }
}

5
54liuyao 已提交
3501 3502 3503 3504
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
3505
    SResultWindowInfo* pWinInfo = pIte;
5
54liuyao 已提交
3506
    saveResult(*pWinInfo, pStUpdated);
5
54liuyao 已提交
3507 3508 3509 3510
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3511
static void copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
5
54liuyao 已提交
3512 3513
  int32_t size = taosArrayGetSize(pResWins);
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3514 3515
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
    if (!pWinKey) continue;
5
54liuyao 已提交
3516 3517
    SSessionKey winInfo = {0};
    getSessionHashKey(pWinKey, &winInfo);
5
54liuyao 已提交
3518
    tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
3519 3520 3521
  }
}

H
Haojun Liao 已提交
3522
// the allocated memory comes from outer function.
5
54liuyao 已提交
3523 3524 3525
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
  pGroupResInfo->pRows = pArrayList;
  pGroupResInfo->index = 0;
H
Haojun Liao 已提交
3526
  pGroupResInfo->pBuf = NULL;
3527 3528
}

3529
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo,
5
54liuyao 已提交
3530 3531 3532 3533 3534 3535 3536
                          SSDataBlock* pBlock) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  // set output datablock version
  pBlock->info.version = pTaskInfo->version;

  blockDataCleanup(pBlock);
  if (!hasRemainResults(pGroupResInfo)) {
H
Haojun Liao 已提交
3537
    cleanupGroupResInfo(pGroupResInfo);
3538 3539 3540
    return;
  }

5
54liuyao 已提交
3541
  // clear the existed group id
H
Haojun Liao 已提交
3542
  pBlock->info.id.groupId = 0;
3543
  buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
L
liuyao 已提交
3544 3545 3546
  if (pBlock->info.rows == 0) {
    cleanupGroupResInfo(pGroupResInfo);
  }
5
54liuyao 已提交
3547
}
L
liuyao 已提交
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567
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 已提交
3568

5
54liuyao 已提交
3569
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
5
54liuyao 已提交
3570
  SExprSupp*                     pSup = &pOperator->exprSupp;
5
54liuyao 已提交
3571
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
3572
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
5
54liuyao 已提交
3573
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3574 3575 3576
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  } else if (pOperator->status == OP_RES_TO_RETURN) {
3577
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3578
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3579
      printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3580 3581
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3582 3583 3584 3585
    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 已提交
3586
    }
5
54liuyao 已提交
3587

H
Haojun Liao 已提交
3588
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
3589
    return NULL;
5
54liuyao 已提交
3590 3591 3592
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3593 3594 3595 3596
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3597
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3598 3599
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3600 3601 3602 3603 3604
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
3605
    printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "final session recv" : "single session recv");
3606

5
54liuyao 已提交
3607 3608 3609
    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 已提交
3610
      // gap must be 0
5
54liuyao 已提交
3611
      doDeleteTimeWindows(pAggSup, pBlock, pWins);
5
54liuyao 已提交
3612
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3613 3614 3615 3616 3617
      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 已提交
3618
        doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
5
54liuyao 已提交
3619
        rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
5
54liuyao 已提交
3620 3621 3622 3623
      }
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
      taosArrayDestroy(pWins);
      continue;
3624
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3625
      getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3626
      continue;
5
54liuyao 已提交
3627 3628 3629 3630
    } 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 已提交
3631
    }
5
54liuyao 已提交
3632

5
54liuyao 已提交
3633 3634 3635 3636
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
3637
    // the pDataBlock are always the same one, no need to call this again
3638
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3639
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo), true);
5
54liuyao 已提交
3640 3641 3642 3643 3644
    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++) {
3645
        SOperatorInfo* pChildOp =
L
liuyao 已提交
3646
            createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0, NULL);
5
54liuyao 已提交
3647
        if (!pChildOp) {
S
Shengliang Guan 已提交
3648
          T_LONG_JMP(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3649 3650 3651
        }
        taosArrayPush(pInfo->pChildren, &pChildOp);
      }
3652
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
3653
      setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3654
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
3655
    }
5
54liuyao 已提交
3656 3657
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
5
54liuyao 已提交
3658 3659 3660
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
3661

5
54liuyao 已提交
3662
  closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
5
54liuyao 已提交
3663
  closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
5
54liuyao 已提交
3664 3665 3666 3667
  copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pStUpdated);
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3668 3669 3670
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }
5
54liuyao 已提交
3671 3672
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
3673
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3674

3675 3676 3677 3678 3679 3680
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

3681
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3682
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3683
    printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3684 3685
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3686 3687 3688 3689 3690 3691 3692

  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 已提交
3693
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3694
  return NULL;
5
54liuyao 已提交
3695 3696
}

L
liuyao 已提交
3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
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);
  }
}

L
liuyao 已提交
3709
void resetWinRange(STimeWindow* winRange) {
L
liuyao 已提交
3710 3711
  winRange->skey = INT64_MIN;
  winRange->ekey = INT64_MAX;
L
liuyao 已提交
3712 3713
}

L
liuyao 已提交
3714 3715 3716
void streamSessionReloadState(SOperatorInfo* pOperator) {
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
L
liuyao 已提交
3717 3718
  resetWinRange(&pAggSup->winRange);

L
liuyao 已提交
3719 3720 3721 3722 3723 3724 3725 3726
  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));
L
liuyao 已提交
3727 3728 3729 3730
  if (!pInfo->pStUpdated && num > 0) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
L
liuyao 已提交
3731 3732 3733
  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);
L
liuyao 已提交
3734 3735 3736
    compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted, true);
    saveSessionOutputBuf(pAggSup, &winInfo);
    saveResult(winInfo, pInfo->pStUpdated);
L
liuyao 已提交
3737
  }
L
liuyao 已提交
3738
  taosMemoryFree(pBuf);
L
liuyao 已提交
3739 3740 3741 3742 3743 3744 3745

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

5
54liuyao 已提交
3746
SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
L
liuyao 已提交
3747
                                                  SExecTaskInfo* pTaskInfo, SReadHandle* pHandle) {
5
54liuyao 已提交
3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762
  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);
3763
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3764 3765
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
5
54liuyao 已提交
3766 3767
    }
  }
5
54liuyao 已提交
3768 3769 3770
  SExprSupp* pSup = &pOperator->exprSupp;

  SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
3771
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3772
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3773 3774 3775 3776 3777
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, pSessionNode->gap,
L
liuyao 已提交
3778
                                pTaskInfo->streamInfo.pState, 0, 0, &pTaskInfo->storageAPI.stateStore, pHandle, &pTaskInfo->storageAPI);
5
54liuyao 已提交
3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805
  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;
3806
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
3807 3808
  pInfo->pUpdated = NULL;
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3809
  pInfo->dataVersion = 0;
L
liuyao 已提交
3810 3811 3812 3813
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
L
liuyao 已提交
3814 3815 3816
  if (pHandle) {
    pInfo->isHistoryOp = pHandle->fillHistory;
  }
5
54liuyao 已提交
3817

H
Haojun Liao 已提交
3818 3819
  setOperatorInfo(pOperator, "StreamSessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
                  OP_NOT_OPENED, pInfo, pTaskInfo);
L
Liu Jicong 已提交
3820 3821
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionAgg, NULL, destroyStreamSessionAggOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
3822
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
H
Haojun Liao 已提交
3823

5
54liuyao 已提交
3824
  if (downstream) {
5
54liuyao 已提交
3825
    initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841
    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);
3842
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
5
54liuyao 已提交
3843 3844 3845 3846 3847 3848 3849
}

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

5
54liuyao 已提交
3852 3853
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3854
  }
L
Liu Jicong 已提交
3855

3856
  {
5
54liuyao 已提交
3857
    doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3858
    if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3859
      printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3860 3861 3862
      return pBInfo->pRes;
    }

3863
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3864
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3865
      printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3866 3867
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3868

3869
    if (pOperator->status == OP_RES_TO_RETURN) {
5
54liuyao 已提交
3870
      clearFunctionContext(&pOperator->exprSupp);
3871 3872
      // semi interval operator clear disk buffer
      clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3873
      setOperatorCompleted(pOperator);
3874 3875
      return NULL;
    }
5
54liuyao 已提交
3876 3877 3878
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3879 3880 3881 3882
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3883
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3884 3885
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3886 3887 3888
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
3889
      clearSpecialDataBlock(pInfo->pUpdateRes);
3890
      pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
3891 3892
      break;
    }
H
Haojun Liao 已提交
3893
    printDataBlock(pBlock, "semi session recv");
5
54liuyao 已提交
3894

5
54liuyao 已提交
3895 3896
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
3897
      // gap must be 0
3898
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
5
54liuyao 已提交
3899
      doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins);
5
54liuyao 已提交
3900
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3901
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
3902
      taosArrayDestroy(pWins);
5
54liuyao 已提交
3903
      break;
5
54liuyao 已提交
3904
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3905
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3906
      continue;
5
54liuyao 已提交
3907 3908 3909 3910
    } 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 已提交
3911 3912
    }

5
54liuyao 已提交
3913 3914 3915 3916
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
5
54liuyao 已提交
3917
    // the pDataBlock are always the same one, no need to call this again
3918
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3919
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
5
54liuyao 已提交
3920 3921 3922 3923
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
  }

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

5
54liuyao 已提交
3926 3927 3928 3929 3930 3931
  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 已提交
3932
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3933

3934 3935 3936 3937 3938 3939
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===semi session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5
54liuyao 已提交
3940
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3941
  if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3942
    printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3943 3944 3945
    return pBInfo->pRes;
  }

3946
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3947
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3948
    printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3949 3950
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3951

5
54liuyao 已提交
3952 3953 3954
  clearFunctionContext(&pOperator->exprSupp);
  // semi interval operator clear disk buffer
  clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3955
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3956
  return NULL;
5
54liuyao 已提交
3957
}
3958

3959
SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
L
liuyao 已提交
3960
                                                       SExecTaskInfo* pTaskInfo, int32_t numOfChild, SReadHandle* pHandle) {
3961
  int32_t        code = TSDB_CODE_OUT_OF_MEMORY;
L
liuyao 已提交
3962
  SOperatorInfo* pOperator = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo, pHandle);
3963 3964 3965
  if (pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3966

3967
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
3968
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
5
54liuyao 已提交
3969

H
Haojun Liao 已提交
3970
  pInfo->isFinal = (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION);
L
Liu Jicong 已提交
3971
  char* name = (pInfo->isFinal) ? "StreamSessionFinalAggOperator" : "StreamSessionSemiAggOperator";
H
Haojun Liao 已提交
3972 3973

  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
H
Haojun Liao 已提交
3974
    pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR);
5
54liuyao 已提交
3975
    blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
3976 3977
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAgg, NULL,
                                           destroyStreamSessionAggOperatorInfo, optrDefaultBufFn, NULL);
5
54liuyao 已提交
3978
  }
L
liuyao 已提交
3979
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
L
Liu Jicong 已提交
3980
  setOperatorInfo(pOperator, name, pPhyNode->type, false, OP_NOT_OPENED, pInfo, pTaskInfo);
H
Haojun Liao 已提交
3981

5
54liuyao 已提交
3982 3983 3984 3985
  pOperator->operatorType = pPhyNode->type;
  if (numOfChild > 0) {
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
    for (int32_t i = 0; i < numOfChild; i++) {
L
liuyao 已提交
3986
      SOperatorInfo* pChildOp = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0, NULL);
5
54liuyao 已提交
3987
      if (pChildOp == NULL) {
5
54liuyao 已提交
3988 3989
        goto _error;
      }
5
54liuyao 已提交
3990 3991
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
3992
      pAPI->stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i);
5
54liuyao 已提交
3993
      taosArrayPush(pInfo->pChildren, &pChildOp);
3994 3995
    }
  }
3996 3997 3998 3999 4000

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

4001 4002 4003 4004
  return pOperator;

_error:
  if (pInfo != NULL) {
4005
    destroyStreamSessionAggOperatorInfo(pInfo);
4006 4007 4008 4009 4010
  }
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
5
54liuyao 已提交
4011

4012
void destroyStreamStateOperatorInfo(void* param) {
X
Xiaoyu Wang 已提交
4013
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
4014
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
4015
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
4016 4017 4018 4019
  cleanupGroupResInfo(&pInfo->groupResInfo);
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
4020
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
4021
      destroyOperator(pChild);
5
54liuyao 已提交
4022
    }
5
54liuyao 已提交
4023
    taosArrayDestroy(pInfo->pChildren);
5
54liuyao 已提交
4024
  }
5
54liuyao 已提交
4025 4026
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
4027
  taosArrayDestroy(pInfo->historyWins);
L
liuyao 已提交
4028
  tSimpleHashCleanup(pInfo->pSeUpdated);
5
54liuyao 已提交
4029
  tSimpleHashCleanup(pInfo->pSeDeleted);
D
dapan1121 已提交
4030
  taosMemoryFreeClear(param);
5
54liuyao 已提交
4031 4032 4033
}

bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
5
54liuyao 已提交
4034
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
5
54liuyao 已提交
4035 4036 4037 4038 4039 4040
    return true;
  }
  return false;
}

bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
5
54liuyao 已提交
4041 4042 4043 4044
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
}

bool compareStateKey(void* data, void* key) {
L
liuyao 已提交
4045
  if (!data || !key) {
L
liuyao 已提交
4046
    return false;
L
liuyao 已提交
4047
  }
5
54liuyao 已提交
4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059
  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 =
4060
      pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData, pAggSup->stateKeySize,
5
54liuyao 已提交
4061 4062 4063 4064 4065 4066 4067 4068
                                    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;

L
liuyao 已提交
4069 4070 4071
  if (code == TSDB_CODE_SUCCESS && !inWinRange(&pAggSup->winRange, &pCurWin->winInfo.sessionWin.win)) {
    code = TSDB_CODE_FAILED;
    releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)pCurWin->winInfo.pOutputBuf, &pAggSup->pSessionAPI->stateStore);
L
liuyao 已提交
4072 4073 4074 4075 4076 4077 4078
    pCurWin->winInfo.pOutputBuf = taosMemoryCalloc(1, 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;
L
liuyao 已提交
4079 4080
  }

5
54liuyao 已提交
4081 4082
  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->winInfo.isOutput = true;
L
liuyao 已提交
4083
    pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, &pCurWin->winInfo.sessionWin);
L
liuyao 已提交
4084
  } else if (pKeyData) {
5
54liuyao 已提交
4085 4086 4087 4088
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
    } else {
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
5
54liuyao 已提交
4089 4090 4091
    }
  }

5
54liuyao 已提交
4092
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
L
liuyao 已提交
4093 4094 4095
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pNextWin->winInfo.sessionWin);
  int32_t nextSize = pAggSup->resultRowSize;
  code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin, &pNextWin->winInfo.pOutputBuf, &nextSize);
5
54liuyao 已提交
4096 4097
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
L
liuyao 已提交
4098 4099 4100 4101 4102 4103 4104 4105
  } else {
    pNextWin->pStateKey =
      (SStateKeys*)((char*)pNextWin->winInfo.pOutputBuf + (pAggSup->resultRowSize - pAggSup->stateKeySize));
    pNextWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
    pNextWin->pStateKey->type = pAggSup->stateKeyType;
    pNextWin->pStateKey->pData = (char*)pNextWin->pStateKey + sizeof(SStateKeys);
    pNextWin->pStateKey->isNull = false;
    pNextWin->winInfo.isOutput = true;
5
54liuyao 已提交
4106
  }
4107
  pAggSup->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
4108 4109
}

5
54liuyao 已提交
4110
int32_t updateStateWindowInfo(SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin, TSKEY* pTs, uint64_t groupId,
H
Haojun Liao 已提交
4111
                              SColumnInfoData* pKeyCol, int32_t rows, int32_t start, bool* allEqual,
5
54liuyao 已提交
4112
                              SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted) {
5
54liuyao 已提交
4113 4114 4115 4116
  *allEqual = true;
  for (int32_t i = start; i < rows; ++i) {
    char* pKeyData = colDataGetData(pKeyCol, i);
    if (!isTsInWindow(pWinInfo, pTs[i])) {
X
Xiaoyu Wang 已提交
4117
      if (isEqualStateKey(pWinInfo, pKeyData)) {
5
54liuyao 已提交
4118
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
5
54liuyao 已提交
4119
          // ts belongs to the next window
5
54liuyao 已提交
4120
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
5
54liuyao 已提交
4121 4122 4123 4124 4125 4126 4127
            return i - start;
          }
        }
      } else {
        return i - start;
      }
    }
5
54liuyao 已提交
4128 4129

    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
H
Haojun Liao 已提交
4130
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
5
54liuyao 已提交
4131
        saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
5
54liuyao 已提交
4132
      }
5
54liuyao 已提交
4133 4134
      removeSessionResult(pSeUpdated, pResultRows, pWinInfo->winInfo.sessionWin);
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
5
54liuyao 已提交
4135
    }
5
54liuyao 已提交
4136
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
5
54liuyao 已提交
4137 4138 4139 4140 4141 4142 4143
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
      *allEqual = false;
    }
  }
  return rows - start;
}

5
54liuyao 已提交
4144 4145
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
                                 SSHashObj* pStDeleted) {
4146 4147 4148
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
4149
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4150
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
4151
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
4152 4153 4154 4155
  int64_t                      code = TSDB_CODE_SUCCESS;
  TSKEY*                       tsCols = NULL;
  SResultRow*                  pResult = NULL;
  int32_t                      winRows = 0;
L
liuyao 已提交
4156
  SStreamAggSupporter*         pAggSup = &pInfo->streamAggSup;
L
liuyao 已提交
4157 4158

  pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version);
L
liuyao 已提交
4159
  pAggSup->winRange = pTaskInfo->streamInfo.fillHistoryWindow;
L
liuyao 已提交
4160 4161 4162
  if (pAggSup->winRange.ekey <= 0) {
    pAggSup->winRange.ekey = INT64_MAX;
  }
L
liuyao 已提交
4163

5
54liuyao 已提交
4164
  if (pSDataBlock->pDataBlock != NULL) {
X
Xiaoyu Wang 已提交
4165 4166
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
    tsCols = (int64_t*)pColDataInfo->pData;
5
54liuyao 已提交
4167
  } else {
X
Xiaoyu Wang 已提交
4168
    return;
5
54liuyao 已提交
4169
  }
L
Liu Jicong 已提交
4170

5
54liuyao 已提交
4171 4172
  int32_t              rows = pSDataBlock->info.rows;
  blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
L
Liu Jicong 已提交
4173
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
5
54liuyao 已提交
4174
  for (int32_t i = 0; i < rows; i += winRows) {
4175
    if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup) || colDataIsNull_s(pKeyColInfo, i)) {
5
54liuyao 已提交
4176 4177 4178
      i++;
      continue;
    }
5
54liuyao 已提交
4179 4180 4181 4182 4183 4184
    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);
L
liuyao 已提交
4185 4186 4187
    if (IS_VALID_SESSION_WIN(nextWin.winInfo)) {
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)nextWin.winInfo.pOutputBuf, &pAPI->stateStore);
    }
5
54liuyao 已提交
4188 4189 4190
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
    winRows = updateStateWindowInfo(&curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
                                    pAggSup->pResultRows, pSeUpdated, pStDeleted);
5
54liuyao 已提交
4191
    if (!allEqual) {
4192
      uint64_t uid = 0;
5
54liuyao 已提交
4193 4194 4195 4196
      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);
4197
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)curWin.winInfo.pOutputBuf, &pAPI->stateStore);
5
54liuyao 已提交
4198 4199
      continue;
    }
5
54liuyao 已提交
4200
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
L
liuyao 已提交
4201
                              pOperator, 0);
5
54liuyao 已提交
4202
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4203
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4204
    }
5
54liuyao 已提交
4205 4206
    saveSessionOutputBuf(pAggSup, &curWin.winInfo);

5
54liuyao 已提交
4207
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
5
54liuyao 已提交
4208
      code = saveResult(curWin.winInfo, pSeUpdated);
5
54liuyao 已提交
4209
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
4210
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4211 4212
      }
    }
4213 4214

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
4215 4216
      SSessionKey key = {0};
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
4217 4218
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
    }
5
54liuyao 已提交
4219 4220 4221 4222 4223 4224 4225 4226
  }
}

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

4227
  SExprSupp*                   pSup = &pOperator->exprSupp;
5
54liuyao 已提交
4228
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
4229
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
5
54liuyao 已提交
4230
  if (pOperator->status == OP_RES_TO_RETURN) {
4231
    doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4232
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4233
      printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4234 4235
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
4236 4237 4238 4239 4240

    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 已提交
4241
    }
5
54liuyao 已提交
4242

H
Haojun Liao 已提交
4243
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
4244
    return NULL;
5
54liuyao 已提交
4245 4246 4247
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
4248 4249 4250 4251
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pSeUpdated) {
4252
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4253 4254
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
4255 4256 4257 4258 4259
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
4260
    printDataBlock(pBlock, "single state recv");
4261

5
54liuyao 已提交
4262 4263 4264 4265
    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 已提交
4266
      removeSessionResults(pInfo->pSeUpdated, pWins);
5
54liuyao 已提交
4267
      copyDeleteWindowInfo(pWins, pInfo->pSeDeleted);
4268 4269
      taosArrayDestroy(pWins);
      continue;
4270
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
4271
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
5
54liuyao 已提交
4272
      continue;
5
54liuyao 已提交
4273 4274 4275 4276
    } 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 已提交
4277
    }
4278

5
54liuyao 已提交
4279 4280 4281 4282
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
4283
    // the pDataBlock are always the same one, no need to call this again
4284
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
4285 4286
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
5
54liuyao 已提交
4287 4288 4289
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
X
Xiaoyu Wang 已提交
4290

5
54liuyao 已提交
4291 4292 4293 4294 4295
  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 已提交
4296

L
liuyao 已提交
4297 4298 4299 4300
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }

5
54liuyao 已提交
4301 4302
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
4303
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
4304

5
54liuyao 已提交
4305 4306 4307 4308 4309 4310
#if 0
  char* pBuf = streamStateSessionDump(pInfo->streamAggSup.pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

4311
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4312
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4313
    printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4314 4315 4316
    return pInfo->pDelRes;
  }

5
54liuyao 已提交
4317 4318 4319 4320 4321
  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 已提交
4322
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
4323
  return NULL;
4324 4325
}

L
liuyao 已提交
4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349
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);

L
liuyao 已提交
4350
  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, 1);
L
liuyao 已提交
4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361
  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);
}

void streamStateReloadState(SOperatorInfo* pOperator) {
L
liuyao 已提交
4362
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
L
liuyao 已提交
4363
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
L
liuyao 已提交
4364 4365
  resetWinRange(&pAggSup->winRange);

L
liuyao 已提交
4366 4367 4368 4369 4370 4371 4372 4373
  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));
L
liuyao 已提交
4374 4375 4376 4377
  if (!pInfo->pSeUpdated && num > 0) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
  }
L
liuyao 已提交
4378 4379 4380
  for (int32_t i = 0; i < num; i++) {
    SStateWindowInfo curInfo = {0};
    SStateWindowInfo nextInfo = {0};
L
liuyao 已提交
4381
    SStateWindowInfo dummy = {0};
L
liuyao 已提交
4382 4383
    setStateOutputBuf(pAggSup, pSeKeyBuf[i].win.skey, pSeKeyBuf[i].groupId, NULL, &curInfo, &nextInfo);
    if (compareStateKey(curInfo.pStateKey,nextInfo.pStateKey)) {
L
liuyao 已提交
4384 4385 4386
      compactStateWindow(pOperator, &curInfo.winInfo, &nextInfo.winInfo, pInfo->pSeUpdated, pInfo->pSeUpdated);
      saveSessionOutputBuf(pAggSup, &curInfo.winInfo);
      saveResult(curInfo.winInfo, pInfo->pSeUpdated);
L
liuyao 已提交
4387 4388 4389 4390 4391 4392 4393 4394
    }

    if (IS_VALID_SESSION_WIN(curInfo.winInfo)) {
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)curInfo.winInfo.pOutputBuf, &pAggSup->pSessionAPI->stateStore);
    }

    if (IS_VALID_SESSION_WIN(nextInfo.winInfo)) {
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)nextInfo.winInfo.pOutputBuf, &pAggSup->pSessionAPI->stateStore);
L
liuyao 已提交
4395 4396
    }
  }
L
liuyao 已提交
4397
  taosMemoryFree(pBuf);
L
liuyao 已提交
4398 4399 4400 4401 4402 4403 4404

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

X
Xiaoyu Wang 已提交
4405
SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
L
liuyao 已提交
4406
                                                SExecTaskInfo* pTaskInfo, SReadHandle* pHandle) {
X
Xiaoyu Wang 已提交
4407 4408 4409
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
  SColumnNode*                 pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
H
Haojun Liao 已提交
4410
  int32_t                      code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
4411

X
Xiaoyu Wang 已提交
4412 4413
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
4414
  if (pInfo == NULL || pOperator == NULL) {
H
Haojun Liao 已提交
4415
    code = TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
4416 4417 4418 4419
    goto _error;
  }

  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
4420
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
4421 4422 4423
  if (pStateNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalar);
4424
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4425 4426 4427 4428 4429
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

X
Xiaoyu Wang 已提交
4430 4431
  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pStateNode->window.watermark,
5
54liuyao 已提交
4432 4433
      .calTrigger = pStateNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
4434
      .minTs = INT64_MAX,
X
Xiaoyu Wang 已提交
4435
  };
4436

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

5
54liuyao 已提交
4439 4440 4441
  SExprSupp*   pSup = &pOperator->exprSupp;
  int32_t      numOfCols = 0;
  SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
4442
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
4443
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4444 4445 4446
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
5
54liuyao 已提交
4447 4448 4449
  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,
L
liuyao 已提交
4450
                                type, &pTaskInfo->storageAPI.stateStore, pHandle, &pTaskInfo->storageAPI);
5
54liuyao 已提交
4451 4452 4453 4454 4455 4456
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  pInfo->primaryTsIndex = tsSlotId;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4457
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
5
54liuyao 已提交
4458
  pInfo->pDelIterator = NULL;
H
Haojun Liao 已提交
4459
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
5
54liuyao 已提交
4460
  pInfo->pChildren = NULL;
5
54liuyao 已提交
4461
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
4462
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
4463 4464
  pInfo->pUpdated = NULL;
  pInfo->pSeUpdated = NULL;
L
liuyao 已提交
4465
  pInfo->dataVersion = 0;
L
liuyao 已提交
4466 4467 4468 4469
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
L
liuyao 已提交
4470 4471 4472
  if (pHandle) {
    pInfo->isHistoryOp = pHandle->fillHistory;
  }
5
54liuyao 已提交
4473

L
Liu Jicong 已提交
4474 4475
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
L
Liu Jicong 已提交
4476 4477
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAgg, NULL, destroyStreamStateOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
4478
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
5
54liuyao 已提交
4479
  initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
4480 4481 4482 4483 4484 4485 4486
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
  return pOperator;

_error:
4487
  destroyStreamStateOperatorInfo(pInfo);
5
54liuyao 已提交
4488 4489 4490 4491
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4492

4493
void destroyMAIOperatorInfo(void* param) {
4494
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
4495
  destroyIntervalOperatorInfo(miaInfo->intervalAggOperatorInfo);
D
dapan1121 已提交
4496
  taosMemoryFreeClear(param);
4497 4498
}

4499
static SResultRow* doSetSingleOutputTupleBuf(SResultRowInfo* pResultRowInfo, SAggSupporter* pSup) {
H
Haojun Liao 已提交
4500
  SResultRow* pResult = getNewResultRow(pSup->pResultBuf, &pSup->currentPageId, pSup->resultRowSize);
4501 4502 4503
  if (NULL == pResult) {
    return pResult;
  }
H
Haojun Liao 已提交
4504
  pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
4505 4506
  return pResult;
}
4507

4508 4509 4510 4511 4512 4513 4514 4515
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;
    }
  }
4516

4517
  // set time window for current result
4518 4519
  (*pResult)->win = (*win);
  setResultRowInitCtx((*pResult), pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset);
4520
  return TSDB_CODE_SUCCESS;
4521 4522
}

4523
static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
4524
                                          SSDataBlock* pBlock, SSDataBlock* pResultBlock) {
4525
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
D
dapan1121 已提交
4526
  SIntervalAggOperatorInfo*             iaInfo = miaInfo->intervalAggOperatorInfo;
4527 4528

  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
4529
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
4530
  SInterval*     pInterval = &iaInfo->interval;
4531

5
54liuyao 已提交
4532 4533
  int32_t  startPos = 0;
  int64_t* tsCols = extractTsCol(pBlock, iaInfo);
4534

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

4537 4538
  // there is an result exists
  if (miaInfo->curTs != INT64_MIN) {
4539
    if (ts != miaInfo->curTs) {
4540
      finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4541
      resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4542
      miaInfo->curTs = ts;
4543
    }
4544 4545
  } else {
    miaInfo->curTs = ts;
4546 4547 4548
  }

  STimeWindow win = {0};
4549
  win.skey = miaInfo->curTs;
4550
  win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4551

5
54liuyao 已提交
4552
  int32_t ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4553 4554
  if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
    T_LONG_JMP(pTaskInfo->env, ret);
4555 4556
  }

4557 4558
  int32_t currPos = startPos;

4559
  STimeWindow currWin = win;
4560
  while (++currPos < pBlock->info.rows) {
4561
    if (tsCols[currPos] == miaInfo->curTs) {
4562
      continue;
4563 4564
    }

L
liuyao 已提交
4565
    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, 1);
H
Haojun Liao 已提交
4566 4567
    applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos,
                                    currPos - startPos, pBlock->info.rows, pSup->numOfExprs);
4568

4569
    finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4570
    resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4571
    miaInfo->curTs = tsCols[currPos];
4572

4573
    currWin.skey = miaInfo->curTs;
4574
    currWin.ekey = taosTimeAdd(currWin.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4575 4576

    startPos = currPos;
5
54liuyao 已提交
4577
    ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4578 4579
    if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
      T_LONG_JMP(pTaskInfo->env, ret);
4580
    }
4581 4582

    miaInfo->curTs = currWin.skey;
4583
  }
4584

L
liuyao 已提交
4585
  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, 1);
H
Haojun Liao 已提交
4586
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
L
Liu Jicong 已提交
4587
                                  pBlock->info.rows, pSup->numOfExprs);
4588 4589
}

4590
static void cleanupAfterGroupResultGen(SMergeAlignedIntervalAggOperatorInfo* pMiaInfo, SSDataBlock* pRes) {
H
Haojun Liao 已提交
4591
  pRes->info.id.groupId = pMiaInfo->groupId;
4592 4593
  pMiaInfo->curTs = INT64_MIN;
  pMiaInfo->groupId = 0;
4594 4595
}

4596
static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
S
shenglian zhou 已提交
4597
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4598

4599 4600
  SMergeAlignedIntervalAggOperatorInfo* pMiaInfo = pOperator->info;
  SIntervalAggOperatorInfo*             pIaInfo = pMiaInfo->intervalAggOperatorInfo;
4601

4602 4603 4604 4605
  SExprSupp*      pSup = &pOperator->exprSupp;
  SSDataBlock*    pRes = pIaInfo->binfo.pRes;
  SResultRowInfo* pResultRowInfo = &pIaInfo->binfo.resultRowInfo;
  SOperatorInfo*  downstream = pOperator->pDownstream[0];
4606

4607 4608
  while (1) {
    SSDataBlock* pBlock = NULL;
4609
    if (pMiaInfo->prefetchedBlock == NULL) {
4610 4611
      pBlock = downstream->fpSet.getNextFn(downstream);
    } else {
4612 4613
      pBlock = pMiaInfo->prefetchedBlock;
      pMiaInfo->prefetchedBlock = NULL;
4614

H
Haojun Liao 已提交
4615
      pMiaInfo->groupId = pBlock->info.id.groupId;
4616
    }
4617

4618
    // no data exists, all query processing is done
4619
    if (pBlock == NULL) {
4620 4621 4622
      // close last unclosed time window
      if (pMiaInfo->curTs != INT64_MIN) {
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4623 4624
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
4625
      }
4626

H
Haojun Liao 已提交
4627
      setOperatorCompleted(pOperator);
4628
      break;
4629
    }
4630

H
Haojun Liao 已提交
4631
    if (pMiaInfo->groupId == 0) {
H
Haojun Liao 已提交
4632 4633 4634
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
        pMiaInfo->groupId = pBlock->info.id.groupId;
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4635 4636
      }
    } else {
H
Haojun Liao 已提交
4637
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
H
Haojun Liao 已提交
4638
        // if there are unclosed time window, close it firstly.
4639
        ASSERT(pMiaInfo->curTs != INT64_MIN);
H
Haojun Liao 已提交
4640
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4641
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
H
Haojun Liao 已提交
4642

4643 4644
        pMiaInfo->prefetchedBlock = pBlock;
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
H
Haojun Liao 已提交
4645
        break;
5
54liuyao 已提交
4646
      } else {
H
Haojun Liao 已提交
4647
        // continue
H
Haojun Liao 已提交
4648
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4649
      }
4650
    }
4651

4652 4653
    pRes->info.scanFlag = pBlock->info.scanFlag;
    setInputDataBlock(pSup, pBlock, pIaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
4654
    doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes);
4655

H
Haojun Liao 已提交
4656
    doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
4657 4658 4659
    if (pRes->info.rows >= pOperator->resultInfo.capacity) {
      break;
    }
4660
  }
4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675
}

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 已提交
4676
    while (1) {
4677
      if (pOperator->status == OP_EXEC_DONE) {
4678 4679
        break;
      }
4680

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

4685 4686 4687 4688
      doMergeAlignedIntervalAgg(pOperator);
    }
  } else {
    doMergeAlignedIntervalAgg(pOperator);
4689 4690 4691 4692 4693 4694 4695
  }

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

4696
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode,
4697
                                                      SExecTaskInfo* pTaskInfo) {
4698
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
4699
  SOperatorInfo*                        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4700 4701 4702 4703
  if (miaInfo == NULL || pOperator == NULL) {
    goto _error;
  }

D
dapan1121 已提交
4704 4705 4706 4707 4708
  miaInfo->intervalAggOperatorInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
  if (miaInfo->intervalAggOperatorInfo == NULL) {
    goto _error;
  }

4709 4710 4711 4712 4713 4714 4715
  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 已提交
4716
  SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
4717
  SExprSupp*                pSup = &pOperator->exprSupp;
4718

H
Haojun Liao 已提交
4719 4720 4721 4722 4723
  int32_t code = filterInitFromNode((SNode*)pNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

L
Liu Jicong 已提交
4724 4725
  miaInfo->curTs = INT64_MIN;
  iaInfo->win = pTaskInfo->window;
4726 4727
  iaInfo->binfo.inputTsOrder = pNode->window.node.inputTsOrder;
  iaInfo->binfo.outputTsOrder = pNode->window.node.outputTsOrder;
L
Liu Jicong 已提交
4728
  iaInfo->interval = interval;
4729 4730
  iaInfo->primaryTsIndex = ((SColumnNode*)pNode->window.pTspk)->slotId;
  iaInfo->binfo.mergeResultBlock = pNode->window.mergeDataBlock;
4731 4732

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

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

L
Liu Jicong 已提交
4738
  code = initAggSup(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4739
                    pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4740 4741 4742
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4743

H
Haojun Liao 已提交
4744
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pNode->window.node.pOutputDataBlockDesc);
4745
  initBasicInfo(&iaInfo->binfo, pResBlock);
4746
  initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
4747

4748
  iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, num, iaInfo);
4749
  if (iaInfo->timeWindowInterpo) {
4750
    iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4751 4752
  }

4753
  initResultRowInfo(&iaInfo->binfo.resultRowInfo);
4754
  blockDataEnsureCapacity(iaInfo->binfo.pRes, pOperator->resultInfo.capacity);
L
Liu Jicong 已提交
4755 4756
  setOperatorInfo(pOperator, "TimeMergeAlignedIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
                  false, OP_NOT_OPENED, miaInfo, pTaskInfo);
4757

L
Liu Jicong 已提交
4758 4759
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, mergeAlignedIntervalAgg, NULL, destroyMAIOperatorInfo,
                                         optrDefaultBufFn, NULL);
4760 4761 4762 4763 4764 4765 4766 4767 4768

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

  return pOperator;

_error:
4769
  destroyMAIOperatorInfo(miaInfo);
4770 4771 4772 4773
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4774 4775 4776 4777 4778

//=====================================================================================================================
// merge interval operator
typedef struct SMergeIntervalAggOperatorInfo {
  SIntervalAggOperatorInfo intervalAggOperatorInfo;
L
Liu Jicong 已提交
4779 4780 4781 4782 4783 4784
  SList*                   groupIntervals;
  SListIter                groupIntervalsIter;
  bool                     hasGroupId;
  uint64_t                 groupId;
  SSDataBlock*             prefetchedBlock;
  bool                     inputBlocksFinished;
4785 4786
} SMergeIntervalAggOperatorInfo;

S
slzhou 已提交
4787
typedef struct SGroupTimeWindow {
L
Liu Jicong 已提交
4788
  uint64_t    groupId;
S
slzhou 已提交
4789 4790 4791
  STimeWindow window;
} SGroupTimeWindow;

4792
void destroyMergeIntervalOperatorInfo(void* param) {
4793
  SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
S
slzhou 已提交
4794
  tdListFree(miaInfo->groupIntervals);
4795
  destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo);
4796

D
dapan1121 已提交
4797
  taosMemoryFreeClear(param);
4798 4799 4800 4801 4802 4803
}

static int32_t outputPrevIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t tableGroupId, SSDataBlock* pResultBlock,
                                        STimeWindow* newWin) {
  SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
  SIntervalAggOperatorInfo*      iaInfo = &miaInfo->intervalAggOperatorInfo;
4804
  bool                           ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
4805

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

S
slzhou 已提交
4809 4810 4811 4812 4813
  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 已提交
4814
    if (prevGrpWin->groupId != tableGroupId) {
S
slzhou 已提交
4815 4816
      continue;
    }
4817

S
slzhou 已提交
4818
    STimeWindow* prevWin = &prevGrpWin->window;
H
Haojun Liao 已提交
4819
    if ((ascScan && newWin->skey > prevWin->ekey) || ((!ascScan) && newWin->skey < prevWin->ekey)) {
S
slzhou 已提交
4820 4821
      tdListPopNode(miaInfo->groupIntervals, listNode);
    }
4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837
  }

  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 已提交
4838
  uint64_t    tableGroupId = pBlock->info.id.groupId;
4839
  bool        ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
4840 4841 4842
  TSKEY       blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
  SResultRow* pResult = NULL;

4843
  STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
4844
                                        iaInfo->binfo.inputTsOrder);
4845 4846 4847 4848 4849

  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 已提交
4850
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4851 4852 4853 4854
  }

  TSKEY   ekey = ascScan ? win.ekey : win.skey;
  int32_t forwardRows =
4855
      getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4856
  ASSERT(forwardRows > 0);
4857 4858 4859

  // prev time window not interpolation yet.
  if (iaInfo->timeWindowInterpo) {
4860
    SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
4861 4862 4863 4864 4865 4866
    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 已提交
4867
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4868 4869 4870 4871 4872 4873
    }

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

L
liuyao 已提交
4874
  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, 1);
H
Haojun Liao 已提交
4875
  applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4876
                                  pBlock->info.rows, numOfOutput);
4877 4878 4879 4880 4881 4882 4883 4884
  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;
4885
    startPos =
4886
        getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->binfo.inputTsOrder);
4887 4888 4889 4890 4891 4892 4893 4894 4895
    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 已提交
4896
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4897 4898 4899 4900
    }

    ekey = ascScan ? nextWin.ekey : nextWin.skey;
    forwardRows =
4901
        getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4902 4903 4904 4905

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

L
liuyao 已提交
4906
    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, 1);
H
Haojun Liao 已提交
4907
    applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4908
                                    pBlock->info.rows, numOfOutput);
4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942
    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];
    while (1) {
      SSDataBlock* pBlock = NULL;
      if (miaInfo->prefetchedBlock == NULL) {
        pBlock = downstream->fpSet.getNextFn(downstream);
      } else {
        pBlock = miaInfo->prefetchedBlock;
H
Haojun Liao 已提交
4943
        miaInfo->groupId = pBlock->info.id.groupId;
4944 4945 4946 4947
        miaInfo->prefetchedBlock = NULL;
      }

      if (pBlock == NULL) {
S
slzhou 已提交
4948
        tdListInitIter(miaInfo->groupIntervals, &miaInfo->groupIntervalsIter, TD_LIST_FORWARD);
4949 4950 4951 4952 4953 4954
        miaInfo->inputBlocksFinished = true;
        break;
      }

      if (!miaInfo->hasGroupId) {
        miaInfo->hasGroupId = true;
H
Haojun Liao 已提交
4955 4956
        miaInfo->groupId = pBlock->info.id.groupId;
      } else if (miaInfo->groupId != pBlock->info.id.groupId) {
4957 4958 4959 4960
        miaInfo->prefetchedBlock = pBlock;
        break;
      }

4961 4962 4963
      pRes->info.scanFlag = pBlock->info.scanFlag;
      setInputDataBlock(pExpSupp, pBlock, iaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
      doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, pBlock->info.scanFlag, pRes);
4964 4965 4966 4967 4968 4969

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

H
Haojun Liao 已提交
4970
    pRes->info.id.groupId = miaInfo->groupId;
4971 4972 4973
  }

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

S
slzhou 已提交
4976 4977
    if (listNode != NULL) {
      SGroupTimeWindow* grpWin = (SGroupTimeWindow*)(listNode->data);
H
Haojun Liao 已提交
4978
      pRes->info.id.groupId = grpWin->groupId;
4979 4980 4981 4982
    }
  }

  if (pRes->info.rows == 0) {
H
Haojun Liao 已提交
4983
    setOperatorCompleted(pOperator);
4984 4985 4986 4987 4988 4989 4990
  }

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

4991 4992 4993
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode,
                                               SExecTaskInfo* pTaskInfo) {
  SMergeIntervalAggOperatorInfo* pMergeIntervalInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
4994
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4995
  if (pMergeIntervalInfo == NULL || pOperator == NULL) {
4996 4997 4998
    goto _error;
  }

5
54liuyao 已提交
4999 5000
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
5001 5002 5003 5004 5005 5006 5007

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

5009
  pMergeIntervalInfo->groupIntervals = tdListNew(sizeof(SGroupTimeWindow));
5010

5011
  SIntervalAggOperatorInfo* pIntervalInfo = &pMergeIntervalInfo->intervalAggOperatorInfo;
L
Liu Jicong 已提交
5012
  pIntervalInfo->win = pTaskInfo->window;
5013
  pIntervalInfo->binfo.inputTsOrder = pIntervalPhyNode->window.node.inputTsOrder;
L
Liu Jicong 已提交
5014
  pIntervalInfo->interval = interval;
5015 5016
  pIntervalInfo->binfo.mergeResultBlock = pIntervalPhyNode->window.mergeDataBlock;
  pIntervalInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
5017
  pIntervalInfo->binfo.outputTsOrder = pIntervalPhyNode->window.node.outputTsOrder;
5018 5019 5020 5021

  SExprSupp* pExprSupp = &pOperator->exprSupp;

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

L
Liu Jicong 已提交
5024
  int32_t code = initAggSup(pExprSupp, &pIntervalInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
5025
                            pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
5026 5027 5028
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
5029

H
Haojun Liao 已提交
5030
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pIntervalPhyNode->window.node.pOutputDataBlockDesc);
5031 5032
  initBasicInfo(&pIntervalInfo->binfo, pResBlock);
  initExecTimeWindowInfo(&pIntervalInfo->twAggSup.timeWindowData, &pIntervalInfo->win);
5033

5034 5035
  pIntervalInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, num, pIntervalInfo);
  if (pIntervalInfo->timeWindowInterpo) {
5036
    pIntervalInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
5037
    if (pIntervalInfo->binfo.resultRowInfo.openWindow == NULL) {
5038 5039 5040 5041
      goto _error;
    }
  }

5042
  initResultRowInfo(&pIntervalInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
5043 5044
  setOperatorInfo(pOperator, "TimeMergeIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, false,
                  OP_NOT_OPENED, pMergeIntervalInfo, pTaskInfo);
L
Liu Jicong 已提交
5045 5046
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doMergeIntervalAgg, NULL, destroyMergeIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
5047 5048 5049 5050 5051 5052 5053 5054 5055

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

  return pOperator;

_error:
H
Haojun Liao 已提交
5056 5057 5058 5059
  if (pMergeIntervalInfo != NULL) {
    destroyMergeIntervalOperatorInfo(pMergeIntervalInfo);
  }

5060 5061 5062
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
5063
}
5064 5065 5066

static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
5067
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
5068 5069
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5070
  SExprSupp* pSup = &pOperator->exprSupp;
5071 5072 5073 5074 5075 5076

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

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

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

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

H
Haojun Liao 已提交
5094
    setOperatorCompleted(pOperator);
dengyihao's avatar
dengyihao 已提交
5095 5096
    if (pInfo->twAggSup.maxTs > 0 &&
        pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
5097 5098
      pAPI->stateStore.streamStateCommit(pInfo->pState);
      pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
5099
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
L
liuyao 已提交
5100 5101
      pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
    }
5
54liuyao 已提交
5102
    return NULL;
5103 5104 5105 5106
  }

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

5
54liuyao 已提交
5107
  if (!pInfo->pUpdated) {
L
liuyao 已提交
5108
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
5109
  }
5110

5
54liuyao 已提交
5111 5112
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
5113
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
5114 5115
  }

5116 5117 5118
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
5119 5120
      qDebug("===stream===return data:single interval. recv datablock num:%" PRIu64, pInfo->numOfDatapack);
      pInfo->numOfDatapack = 0;
5121 5122
      break;
    }
5123

5
54liuyao 已提交
5124
    pInfo->numOfDatapack++;
5125 5126
    printDataBlock(pBlock, "single interval recv");

5127 5128
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
5129
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap);
5130 5131
      continue;
    } else if (pBlock->info.type == STREAM_GET_ALL) {
L
liuyao 已提交
5132
      qDebug("===stream===single interval recv|block type STREAM_GET_ALL");
L
liuyao 已提交
5133
      pInfo->recvGetAll = true;
5
54liuyao 已提交
5134
      getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
5135
      continue;
5
54liuyao 已提交
5136
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
5
54liuyao 已提交
5137
      printDataBlock(pBlock, "single interval");
5
54liuyao 已提交
5138 5139 5140
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155
    }

    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
5156
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5157 5158 5159 5160
    if (pInfo->invertible) {
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
    }

5
54liuyao 已提交
5161
    doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap);
5
54liuyao 已提交
5162 5163
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
5164 5165
  }
  pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
5166
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
5167 5168
  closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
                            pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5169

5170 5171 5172
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
5173
    taosArrayPush(pInfo->pUpdated, pIte);
5174
  }
5
54liuyao 已提交
5175
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
5176

5
54liuyao 已提交
5177 5178
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5179
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5180
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
5181
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
5182

5
54liuyao 已提交
5183 5184 5185 5186 5187 5188
#if 0
  char* pBuf = streamStateIntervalDump(pInfo->pState);
  qDebug("===stream===interval state%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5189
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
5190
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
5191
    printDataBlock(pInfo->pDelRes, "single interval delete");
5192 5193 5194
    return pInfo->pDelRes;
  }

5195
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
5196 5197 5198 5199 5200 5201
  if (pInfo->binfo.pRes->info.rows > 0) {
    printDataBlock(pInfo->binfo.pRes, "single interval");
    return pInfo->binfo.pRes;
  }

  return NULL;
5202 5203 5204 5205 5206
}

SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
5207
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5208 5209 5210 5211 5212
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;

H
Haojun Liao 已提交
5213
  int32_t    code = TSDB_CODE_SUCCESS;
5214 5215
  int32_t    numOfCols = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
5216

H
Haojun Liao 已提交
5217
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
5218 5219 5220 5221 5222 5223 5224
  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,
5225
  };
H
Haojun Liao 已提交
5226

dengyihao's avatar
dengyihao 已提交
5227
  pInfo->twAggSup = (STimeWindowAggSupp){
5228 5229 5230
      .waterMark = pIntervalPhyNode->window.watermark,
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
5231
      .minTs = INT64_MAX,
5
54liuyao 已提交
5232
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
liuyao 已提交
5233
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
5234 5235
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
5236
  };
H
Haojun Liao 已提交
5237

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

5240
  pOperator->pTaskInfo = pTaskInfo;
5241 5242
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5243
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
5244
  pInfo->ignoreExpiredDataSaved = false;
5245 5246 5247
  pInfo->isFinal = false;

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

5252
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
5253
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5254

L
liuyao 已提交
5255 5256
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
5257
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
liuyao 已提交
5258

5259
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
L
Liu Jicong 已提交
5260
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
5261
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
5262 5263 5264 5265
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
5266 5267 5268
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
5269
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
H
Haojun Liao 已提交
5270 5271 5272 5273
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }
5274 5275

  pInfo->invertible = allInvertible(pSup->pCtx, numOfCols);
5276
  pInfo->invertible = false;
5277 5278 5279 5280 5281
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
  pInfo->delIndex = 0;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
  initResultRowInfo(&pInfo->binfo.resultRowInfo);

5282 5283
  pInfo->pPhyNode = NULL;  // create new child
  pInfo->pPullDataMap = NULL;
L
liuyao 已提交
5284
  pInfo->pFinalPullDataMap = NULL;
5285 5286 5287 5288
  pInfo->pPullWins = NULL;  // SPullWindowInfo
  pInfo->pullIndex = 0;
  pInfo->pPullDataRes = NULL;
  pInfo->isFinal = false;
L
liuyao 已提交
5289
  pInfo->numOfChild = 0;
5290 5291
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
5292
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
5293 5294
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
5295
  int32_t funResSize= getMaxFunResSize(pSup, numOfCols);
5296 5297 5298 5299

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

L
Liu Jicong 已提交
5301 5302
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
5303 5304
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAgg, NULL,
                                         destroyStreamFinalIntervalOperatorInfo, optrDefaultBufFn, NULL);
L
liuyao 已提交
5305
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
5306

5307
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
5308 5309
  pInfo->recvGetAll = false;

L
liuyao 已提交
5310
  initIntervalDownStream(downstream, pPhyNode->type, pInfo);
5311 5312 5313 5314 5315 5316 5317 5318
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
5319
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5320 5321 5322 5323
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}