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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return midPos;
}

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

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

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

  return num;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

363
  TSKEY curTs = tsCols[pos];
364 365

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

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

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

  return true;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return startPos;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      break;
    }
590 591 592
  }
}

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

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

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

603
  SResultRow* pResult = NULL;
604

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return midPos;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

994
  return openWin.pos;
995 996 997 998
}

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

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

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

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

  return tsCols;
1016 1017 1018 1019 1020 1021 1022
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    char* val = colDataGetData(pStateColInfoData, j);

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

1103 1104
      pInfo->hasKey = true;

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

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

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

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

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

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

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

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

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

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

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

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

W
wangjiaming0909 已提交
1174
    pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
1175
    setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
1176 1177
    blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);

1178 1179 1180 1181 1182 1183 1184 1185 1186
    // 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);
      }
    }

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

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

1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
  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 已提交
1208
    setOperatorCompleted(pOperator);
1209 1210 1211
    return NULL;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1283
  SqlFunctionCtx* pCtx = pSup->pCtx;
5
54liuyao 已提交
1284
  for (int32_t i = 0; i < numOfOutput; ++i) {
1285
    pCtx[i].resultInfo = getResultEntryInfo(pResult, i, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
1286 1287 1288 1289 1290 1291 1292 1293 1294
    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 已提交
1295
  SFilePage* bufPage = getBufPage(pResultBuf, p1->pageId);
1296 1297 1298
  if (NULL == bufPage) {
    return;
  }
5
54liuyao 已提交
1299 1300
  setBufPageDirty(bufPage, true);
  releaseBufPage(pResultBuf, bufPage);
5
54liuyao 已提交
1301 1302
}

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

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

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

1315
static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins,
1316
                            SSHashObj* pUpdatedMap) {
1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
  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 已提交
1328
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
H
Haojun Liao 已提交
1329
    SResultRowInfo dumyInfo = {0};
5
54liuyao 已提交
1330
    dumyInfo.cur.pageId = -1;
H
Haojun Liao 已提交
1331

1332 1333 1334 1335 1336 1337 1338 1339
    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 已提交
1340
    do {
L
liuyao 已提交
1341
      if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i], pBlock->info.type)) {
1342
        getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
1343 1344
        continue;
      }
5
54liuyao 已提交
1345 1346
      uint64_t winGpId = pGpDatas[i];
      SWinKey  winRes = {.ts = win.skey, .groupId = winGpId};
dengyihao's avatar
dengyihao 已提交
1347
      void*    chIds = taosHashGet(pInfo->pPullDataMap, &winRes, sizeof(SWinKey));
L
liuyao 已提交
1348
      if (chIds) {
L
liuyao 已提交
1349 1350 1351 1352 1353 1354 1355 1356
        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 已提交
1357
      }
dengyihao's avatar
dengyihao 已提交
1358
      bool res = doDeleteWindow(pOperator, win.skey, winGpId);
5
54liuyao 已提交
1359 1360 1361 1362
      if (pUpWins && res) {
        taosArrayPush(pUpWins, &winRes);
      }
      if (pUpdatedMap) {
1363
        tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey));
5
54liuyao 已提交
1364
      }
1365
      getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC);
5
54liuyao 已提交
1366
    } while (win.ekey <= endTsCols[i]);
5
54liuyao 已提交
1367 1368 1369
  }
}

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

5
54liuyao 已提交
1385
static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval,
1386
                                         SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins,
1387
                                         SOperatorInfo* pOperator) {
5
54liuyao 已提交
1388
  qDebug("===stream===close interval window");
1389 1390 1391
  void*                        pIte = NULL;
  int32_t                      iter = 0;
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
1392
  int32_t                      delSize = taosArrayGetSize(pDelWins);
5
54liuyao 已提交
1393
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
1394
    void*    key = tSimpleHashGetKey(pIte, NULL);
1395 1396 1397 1398 1399 1400 1401 1402 1403
    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 已提交
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422
    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 已提交
1423
        int32_t code = saveWinResult(pWinKey, *(SRowBuffPos**)pIte, closeWins);
5
54liuyao 已提交
1424 1425 1426 1427 1428
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
      }
      tSimpleHashIterateRemove(pHashMap, pWinKey, sizeof(SWinKey), &pIte, &iter);
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
    }
  }
  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;
}

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

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

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

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

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

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

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

  pInfo->pPrevValues = NULL;
1496

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
    {  // 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);
    }
1568 1569
  }

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

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

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

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

  return needed;
}

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

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

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

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

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

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

H
Haojun Liao 已提交
1625
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->window.node.pOutputDataBlockDesc);
H
Haojun Liao 已提交
1626 1627 1628 1629 1630 1631
  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 已提交
1632 1633
  initResultSizeInfo(&pOperator->resultInfo, 512);
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
H
Haojun Liao 已提交
1634 1635 1636

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

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

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

L
Liu Jicong 已提交
1656
  pInfo->win = pTaskInfo->window;
1657 1658
  pInfo->binfo.inputTsOrder = pPhyNode->window.node.inputTsOrder;
  pInfo->binfo.outputTsOrder = pPhyNode->window.node.outputTsOrder;
H
Haojun Liao 已提交
1659 1660
  pInfo->interval = interval;
  pInfo->twAggSup = as;
1661
  pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock;
1662 1663 1664 1665

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

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

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

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

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

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

  return pOperator;

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

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

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

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

  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) {
1733 1734 1735
    if (gid != pRowSup->groupId || pInfo->winSup.prevTs == INT64_MIN) {
      doKeepNewWindowStartInfo(pRowSup, tsList, j, gid);
      doKeepTuple(pRowSup, tsList[j], gid);
H
Haojun Liao 已提交
1736 1737
    } else if (((tsList[j] - pRowSup->prevTs >= 0) && (tsList[j] - pRowSup->prevTs <= gap)) ||
               ((pRowSup->prevTs - tsList[j] >= 0) && (pRowSup->prevTs - tsList[j] <= gap))) {
1738
      // The gap is less than the threshold, so it belongs to current session window that has been opened already.
1739
      doKeepTuple(pRowSup, tsList[j], gid);
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
      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;
1750 1751
      int32_t ret = setTimeWindowOutputBuf(&pInfo->binfo.resultRowInfo, &window, masterScan, &pResult, gid, pSup->pCtx,
                                           numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
1752
      if (ret != TSDB_CODE_SUCCESS) {  // null data, too many state code
S
Shengliang Guan 已提交
1753
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR);
1754 1755 1756 1757
      }

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

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

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

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

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

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

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

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

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

1808
  int64_t st = taosGetTimestampUs();
1809
  int32_t order = pInfo->binfo.inputTsOrder;
1810

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

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

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

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

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

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

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

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

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

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

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

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

1873
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
1874 1875 1876 1877 1878 1879
  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;
  }
1880 1881
  pInfo->binfo.inputTsOrder = pStateNode->window.node.inputTsOrder;
  pInfo->binfo.outputTsOrder = pStateNode->window.node.outputTsOrder;
1882

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

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

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

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

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

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

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

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

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

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

1921 1922
  return pOperator;

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

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

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

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

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

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

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

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

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

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

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

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

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

1997 1998
  return pOperator;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return NULL;
}

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

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

L
liuyao 已提交
2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
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 已提交
2733
void streamIntervalReleaseState(SOperatorInfo* pOperator) {
L
liuyao 已提交
2734 2735 2736 2737
  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 已提交
2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748
  }
  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 已提交
2749 2750 2751 2752 2753 2754 2755
  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 已提交
2756
    taosMemoryFree(pBuf);
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);
5
54liuyao 已提交
2918
  tSimpleHashCleanup(pInfo->pStDeleted);
2919

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

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

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

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

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

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

2981 2982
  pSup->stateStore = *pStore;

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

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

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

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

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

5
54liuyao 已提交
3012
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3013
}
5
54liuyao 已提交
3014 3015

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

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

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

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

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

5
54liuyao 已提交
3055 3056
int32_t getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo) {
  int32_t size = 0;
3057
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin, &pWinInfo->pOutputBuf, &size);
5
54liuyao 已提交
3058 3059
  if (code != TSDB_CODE_SUCCESS) {
    return code;
5
54liuyao 已提交
3060
  }
3061 3062

  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
5
54liuyao 已提交
3063 3064 3065 3066 3067
  return TSDB_CODE_SUCCESS;
}
void saveDeleteInfo(SArray* pWins, SSessionKey key) {
  // key.win.ekey = key.win.skey;
  taosArrayPush(pWins, &key);
5
54liuyao 已提交
3068 3069
}

5
54liuyao 已提交
3070 3071 3072 3073
void saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
  key.win.ekey = key.win.skey;
  tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
}
3074

5
54liuyao 已提交
3075 3076 3077 3078 3079
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 已提交
3080

5
54liuyao 已提交
3081 3082 3083 3084 3085
static void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
  *pHashKey = *pKey;
  pHashKey->win.ekey = pKey->win.skey;
}

5
54liuyao 已提交
3086 3087 3088
static void removeSessionResults(SSHashObj* pHashMap, SArray* pWins) {
  if (tSimpleHashGetSize(pHashMap) == 0) {
    return;
5
54liuyao 已提交
3089
  }
5
54liuyao 已提交
3090 3091 3092 3093
  int32_t size = taosArrayGetSize(pWins);
  for (int32_t i = 0; i < size; i++) {
    SSessionKey* pWin = taosArrayGet(pWins, i);
    if (!pWin) continue;
5
54liuyao 已提交
3094 3095
    SSessionKey key = {0};
    getSessionHashKey(pWin, &key);
5
54liuyao 已提交
3096
    tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
5
54liuyao 已提交
3097 3098 3099
  }
}

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

5
54liuyao 已提交
3122 3123
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
3124
  ASSERT(pWinInfo->sessionWin.win.skey <= pWinInfo->sessionWin.win.ekey);
5
54liuyao 已提交
3125
  *pResult = (SResultRow*)pWinInfo->pOutputBuf;
5
54liuyao 已提交
3126
  // set time window for current result
5
54liuyao 已提交
3127
  (*pResult)->win = pWinInfo->sessionWin.win;
3128
  setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
5
54liuyao 已提交
3129 3130 3131
  return TSDB_CODE_SUCCESS;
}

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

5
54liuyao 已提交
3146
static bool doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
3147
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
5
54liuyao 已提交
3148 3149 3150
  SSessionKey hashKey = {0};
  getSessionHashKey(pKey, &hashKey);
  tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
5
54liuyao 已提交
3151 3152 3153 3154 3155 3156 3157 3158 3159 3160
  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 已提交
3161 3162
}

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

5
54liuyao 已提交
3178 3179 3180 3181
static void compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
                                 SSHashObj* pStDeleted) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3182 3183
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3184 3185 3186 3187 3188
  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 已提交
3189
  // Just look for the window behind StartIndex
5
54liuyao 已提交
3190 3191 3192 3193
  while (1) {
    SResultWindowInfo winInfo = {0};
    SStreamStateCur*  pCur = getNextSessionWinInfo(pAggSup, pStUpdated, pCurWin, &winInfo);
    if (!IS_VALID_SESSION_WIN(winInfo) || !isInWindow(pCurWin, winInfo.sessionWin.win.skey, pAggSup->gap)) {
dengyihao's avatar
dengyihao 已提交
3194
      taosMemoryFree(winInfo.pOutputBuf);
3195
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3196
      break;
5
54liuyao 已提交
3197
    }
5
54liuyao 已提交
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208
    SResultRow* pWinResult = NULL;
    initSessionOutputBuf(&winInfo, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, true);
    compactFunctions(pSup->pCtx, pAggSup->pDummyCtx, numOfOutput, pTaskInfo, &pInfo->twAggSup.timeWindowData);
    tSimpleHashRemove(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey));
    if (winInfo.isOutput && pStDeleted) {
      saveDeleteRes(pStDeleted, winInfo.sessionWin);
    }
    removeSessionResult(pStUpdated, pAggSup->pResultRows, winInfo.sessionWin);
    doDeleteSessionWindow(pAggSup, &winInfo.sessionWin);
3209
    pAPI->stateStore.streamStateFreeCur(pCur);
dengyihao's avatar
dengyihao 已提交
3210
    taosMemoryFree(winInfo.pOutputBuf);
5
54liuyao 已提交
3211 3212 3213
  }
}

5
54liuyao 已提交
3214
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
3215
  saveSessionDiscBuf(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pOutputBuf, pAggSup->resultRowSize, &pAggSup->stateStore);
5
54liuyao 已提交
3216
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3217 3218
}

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

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

5
54liuyao 已提交
3232
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3233
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
5
54liuyao 已提交
3234 3235 3236
  SColumnInfoData* pEndTsCol = NULL;
  if (hasEndTs) {
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
5
54liuyao 已提交
3237
  } else {
5
54liuyao 已提交
3238
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3239
  }
X
Xiaoyu Wang 已提交
3240

5
54liuyao 已提交
3241
  TSKEY*               endTsCols = (int64_t*)pEndTsCol->pData;
5
54liuyao 已提交
3242
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3243
  for (int32_t i = 0; i < rows;) {
5
54liuyao 已提交
3244
    if (pInfo->ignoreExpiredData && isOverdue(endTsCols[i], &pInfo->twAggSup)) {
5
54liuyao 已提交
3245 3246 3247
      i++;
      continue;
    }
5
54liuyao 已提交
3248 3249 3250 3251 3252
    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 已提交
3253 3254
    // coverity scan error
    if (!winInfo.pOutputBuf) {
S
Shengliang Guan 已提交
3255
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3256
    }
L
Liu Jicong 已提交
3257

5
54liuyao 已提交
3258 3259
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
                              pOperator);
5
54liuyao 已提交
3260
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
3261
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3262
    }
5
54liuyao 已提交
3263 3264
    compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted);
    saveSessionOutputBuf(pAggSup, &winInfo);
5
54liuyao 已提交
3265 3266

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
5
54liuyao 已提交
3267
      code = saveResult(winInfo, pStUpdated);
5
54liuyao 已提交
3268
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
3269
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3270
      }
5
54liuyao 已提交
3271
    }
5
54liuyao 已提交
3272
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
3273 3274
      SSessionKey key = {0};
      getSessionHashKey(&winInfo.sessionWin, &key);
5
54liuyao 已提交
3275 3276 3277
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
    }

5
54liuyao 已提交
3278 3279 3280 3281
    i += winRows;
  }
}

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

5
54liuyao 已提交
3304 3305 3306 3307 3308 3309 3310 3311
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 已提交
3312 3313
  }

5
54liuyao 已提交
3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
  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) {
3327
    void* key = tSimpleHashGetKey(pIte, NULL);
5
54liuyao 已提交
3328 3329 3330 3331 3332 3333
    taosArrayPush(pUpdated, key);
  }
  taosArraySort(pUpdated, sessionKeyCompareAsc);
  return TSDB_CODE_SUCCESS;
}

3334
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
3335 3336
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;

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

    SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
3363 3364

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

5
54liuyao 已提交
3381 3382 3383
static void rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3384 3385
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3386 3387 3388 3389
  int32_t                        size = taosArrayGetSize(pWinArray);
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  int32_t                        numOfOutput = pSup->numOfExprs;
L
liuyao 已提交
3390
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
3391

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

5
54liuyao 已提交
3437 3438 3439 3440 3441 3442 3443 3444 3445 3446
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 已提交
3447 3448
        }
      }
3449
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
3450
      tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
5
54liuyao 已提交
3451 3452 3453 3454 3455
    }
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3456
static void closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
5
54liuyao 已提交
3457 3458 3459 3460 3461
  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 已提交
3462
    closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
5
54liuyao 已提交
3463 3464 3465
  }
}

5
54liuyao 已提交
3466 3467 3468 3469
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
3470
    SResultWindowInfo* pWinInfo = pIte;
5
54liuyao 已提交
3471
    saveResult(*pWinInfo, pStUpdated);
5
54liuyao 已提交
3472 3473 3474 3475
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3476
static void copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
5
54liuyao 已提交
3477 3478
  int32_t size = taosArrayGetSize(pResWins);
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3479 3480
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
    if (!pWinKey) continue;
5
54liuyao 已提交
3481 3482
    SSessionKey winInfo = {0};
    getSessionHashKey(pWinKey, &winInfo);
5
54liuyao 已提交
3483
    tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
3484 3485 3486
  }
}

H
Haojun Liao 已提交
3487
// the allocated memory comes from outer function.
5
54liuyao 已提交
3488 3489 3490
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
  pGroupResInfo->pRows = pArrayList;
  pGroupResInfo->index = 0;
H
Haojun Liao 已提交
3491
  pGroupResInfo->pBuf = NULL;
3492 3493
}

3494
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo,
5
54liuyao 已提交
3495 3496 3497 3498 3499 3500 3501
                          SSDataBlock* pBlock) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  // set output datablock version
  pBlock->info.version = pTaskInfo->version;

  blockDataCleanup(pBlock);
  if (!hasRemainResults(pGroupResInfo)) {
H
Haojun Liao 已提交
3502
    cleanupGroupResInfo(pGroupResInfo);
3503 3504 3505
    return;
  }

5
54liuyao 已提交
3506
  // clear the existed group id
H
Haojun Liao 已提交
3507
  pBlock->info.id.groupId = 0;
3508
  buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
5
54liuyao 已提交
3509
}
L
liuyao 已提交
3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529
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 已提交
3530

5
54liuyao 已提交
3531
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
5
54liuyao 已提交
3532
  SExprSupp*                     pSup = &pOperator->exprSupp;
5
54liuyao 已提交
3533
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
3534
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
5
54liuyao 已提交
3535
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3536 3537 3538
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  } else if (pOperator->status == OP_RES_TO_RETURN) {
3539
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3540
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3541
      printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3542 3543
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3544 3545 3546 3547
    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 已提交
3548
    }
5
54liuyao 已提交
3549

H
Haojun Liao 已提交
3550
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
3551
    return NULL;
5
54liuyao 已提交
3552 3553 3554
  }

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

5
54liuyao 已提交
3569 3570 3571
    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 已提交
3572
      // gap must be 0
5
54liuyao 已提交
3573
      doDeleteTimeWindows(pAggSup, pBlock, pWins);
5
54liuyao 已提交
3574
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3575 3576 3577 3578 3579
      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 已提交
3580
        doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
5
54liuyao 已提交
3581
        rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
5
54liuyao 已提交
3582 3583 3584 3585
      }
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
      taosArrayDestroy(pWins);
      continue;
3586
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3587
      getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3588
      continue;
5
54liuyao 已提交
3589 3590 3591 3592
    } 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 已提交
3593
    }
5
54liuyao 已提交
3594

5
54liuyao 已提交
3595 3596 3597 3598
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
3599
    // the pDataBlock are always the same one, no need to call this again
3600
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3601
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo));
5
54liuyao 已提交
3602 3603 3604 3605 3606
    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++) {
3607 3608
        SOperatorInfo* pChildOp =
            createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0);
5
54liuyao 已提交
3609
        if (!pChildOp) {
S
Shengliang Guan 已提交
3610
          T_LONG_JMP(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3611 3612 3613
        }
        taosArrayPush(pInfo->pChildren, &pChildOp);
      }
3614
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
3615
      setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3616
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true);
3617
    }
5
54liuyao 已提交
3618 3619
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
5
54liuyao 已提交
3620 3621 3622
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
3623

5
54liuyao 已提交
3624
  closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
5
54liuyao 已提交
3625
  closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
5
54liuyao 已提交
3626 3627 3628 3629
  copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pStUpdated);
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3630 3631 3632
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }
5
54liuyao 已提交
3633 3634
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
3635
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3636

3637 3638 3639 3640 3641 3642
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

3643
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3644
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3645
    printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3646 3647
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3648 3649 3650 3651 3652 3653 3654

  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 已提交
3655
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3656
  return NULL;
5
54liuyao 已提交
3657 3658
}

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

void streamSessionReloadState(SOperatorInfo* pOperator) {
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
  SResultWindowInfo winInfo = {0};
  int32_t size = 0;
  void* pBuf = NULL;
  int32_t code = pAggSup->stateStore.streamStateGetInfo(pAggSup->pState, STREAM_SESSION_OP_STATE_NAME,
                                                        strlen(STREAM_SESSION_OP_STATE_NAME), &pBuf, &size);
  int32_t num = size / sizeof(SSessionKey);
  SSessionKey* pSeKeyBuf = (SSessionKey*) pBuf;
  ASSERT(size == num * sizeof(SSessionKey));
  for (int32_t i = 0; i < num; i++) {
    SResultWindowInfo winInfo = {0};
    setSessionOutputBuf(pAggSup, pSeKeyBuf[i].win.skey, pSeKeyBuf[i].win.ekey, pSeKeyBuf[i].groupId, &winInfo);
    compactSessionWindow(pOperator, &winInfo, pInfo->pStUpdated, pInfo->pStDeleted);
  }
L
liuyao 已提交
3687
  taosMemoryFree(pBuf);
L
liuyao 已提交
3688 3689 3690 3691 3692 3693 3694

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

5
54liuyao 已提交
3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711
SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                  SExecTaskInfo* pTaskInfo) {
  SSessionWinodwPhysiNode*       pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode;
  int32_t                        numOfCols = 0;
  int32_t                        code = TSDB_CODE_OUT_OF_MEMORY;
  SStreamSessionAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamSessionAggOperatorInfo));
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }

  pOperator->pTaskInfo = pTaskInfo;

  initResultSizeInfo(&pOperator->resultInfo, 4096);
  if (pSessionNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pSessionNode->window.pExprs, NULL, &numOfScalar);
3712
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3713 3714
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
5
54liuyao 已提交
3715 3716
    }
  }
5
54liuyao 已提交
3717 3718 3719
  SExprSupp* pSup = &pOperator->exprSupp;

  SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
3720
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3721
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3722 3723 3724 3725 3726
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, pSessionNode->gap,
H
Haojun Liao 已提交
3727
                                pTaskInfo->streamInfo.pState, 0, 0, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754
  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;
3755
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
3756 3757
  pInfo->pUpdated = NULL;
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3758
  pInfo->dataVersion = 0;
L
liuyao 已提交
3759 3760 3761 3762 3763
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
  pInfo->isHistoryOp = false;
5
54liuyao 已提交
3764

H
Haojun Liao 已提交
3765 3766
  setOperatorInfo(pOperator, "StreamSessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
                  OP_NOT_OPENED, pInfo, pTaskInfo);
L
Liu Jicong 已提交
3767 3768
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionAgg, NULL, destroyStreamSessionAggOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
3769
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
H
Haojun Liao 已提交
3770

5
54liuyao 已提交
3771
  if (downstream) {
5
54liuyao 已提交
3772
    initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
    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);
3789
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
5
54liuyao 已提交
3790 3791 3792 3793 3794 3795 3796
}

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

5
54liuyao 已提交
3799 3800
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3801
  }
L
Liu Jicong 已提交
3802

3803
  {
5
54liuyao 已提交
3804
    doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3805
    if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3806
      printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3807 3808 3809
      return pBInfo->pRes;
    }

3810
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3811
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3812
      printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3813 3814
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3815

3816
    if (pOperator->status == OP_RES_TO_RETURN) {
5
54liuyao 已提交
3817
      clearFunctionContext(&pOperator->exprSupp);
3818 3819
      // semi interval operator clear disk buffer
      clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3820
      setOperatorCompleted(pOperator);
3821 3822
      return NULL;
    }
5
54liuyao 已提交
3823 3824 3825
  }

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

5
54liuyao 已提交
3842 3843
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
3844
      // gap must be 0
3845
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
5
54liuyao 已提交
3846
      doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins);
5
54liuyao 已提交
3847
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3848
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
3849
      taosArrayDestroy(pWins);
5
54liuyao 已提交
3850
      break;
5
54liuyao 已提交
3851
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3852
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3853
      continue;
5
54liuyao 已提交
3854 3855 3856 3857
    } 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 已提交
3858 3859
    }

5
54liuyao 已提交
3860 3861 3862 3863
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
5
54liuyao 已提交
3864
    // the pDataBlock are always the same one, no need to call this again
3865
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
3866
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false);
5
54liuyao 已提交
3867 3868 3869 3870
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
  }

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

5
54liuyao 已提交
3873 3874 3875 3876 3877 3878
  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 已提交
3879
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3880

3881 3882 3883 3884 3885 3886
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===semi session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5
54liuyao 已提交
3887
  doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3888
  if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3889
    printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3890 3891 3892
    return pBInfo->pRes;
  }

3893
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3894
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3895
    printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3896 3897
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3898

5
54liuyao 已提交
3899 3900 3901
  clearFunctionContext(&pOperator->exprSupp);
  // semi interval operator clear disk buffer
  clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3902
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3903
  return NULL;
5
54liuyao 已提交
3904
}
3905

3906 3907
SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                       SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
3908 3909
  int32_t        code = TSDB_CODE_OUT_OF_MEMORY;
  SOperatorInfo* pOperator = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo);
3910 3911 3912
  if (pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3913

3914
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
3915
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
5
54liuyao 已提交
3916

H
Haojun Liao 已提交
3917
  pInfo->isFinal = (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION);
L
Liu Jicong 已提交
3918
  char* name = (pInfo->isFinal) ? "StreamSessionFinalAggOperator" : "StreamSessionSemiAggOperator";
H
Haojun Liao 已提交
3919 3920

  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
H
Haojun Liao 已提交
3921
    pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR);
5
54liuyao 已提交
3922
    blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
3923 3924
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAgg, NULL,
                                           destroyStreamSessionAggOperatorInfo, optrDefaultBufFn, NULL);
5
54liuyao 已提交
3925
  }
L
liuyao 已提交
3926
  setOperatorStreamStateFn(pOperator, streamSessionReleaseState, streamSessionReloadState);
L
Liu Jicong 已提交
3927
  setOperatorInfo(pOperator, name, pPhyNode->type, false, OP_NOT_OPENED, pInfo, pTaskInfo);
H
Haojun Liao 已提交
3928

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

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

3948 3949 3950 3951
  return pOperator;

_error:
  if (pInfo != NULL) {
3952
    destroyStreamSessionAggOperatorInfo(pInfo);
3953 3954 3955 3956 3957
  }
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
5
54liuyao 已提交
3958

3959
void destroyStreamStateOperatorInfo(void* param) {
X
Xiaoyu Wang 已提交
3960
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
3961
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
3962
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
3963 3964 3965 3966
  cleanupGroupResInfo(&pInfo->groupResInfo);
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3967
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
3968
      destroyOperator(pChild);
5
54liuyao 已提交
3969
    }
5
54liuyao 已提交
3970
    taosArrayDestroy(pInfo->pChildren);
5
54liuyao 已提交
3971
  }
5
54liuyao 已提交
3972 3973
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
3974
  taosArrayDestroy(pInfo->historyWins);
5
54liuyao 已提交
3975
  tSimpleHashCleanup(pInfo->pSeDeleted);
D
dapan1121 已提交
3976
  taosMemoryFreeClear(param);
5
54liuyao 已提交
3977 3978 3979
}

bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
5
54liuyao 已提交
3980
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
5
54liuyao 已提交
3981 3982 3983 3984 3985 3986
    return true;
  }
  return false;
}

bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
5
54liuyao 已提交
3987 3988 3989 3990
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
}

bool compareStateKey(void* data, void* key) {
L
liuyao 已提交
3991 3992 3993
  if (!data || !key) {
    return true;
  }
5
54liuyao 已提交
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005
  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 =
4006
      pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData, pAggSup->stateKeySize,
5
54liuyao 已提交
4007 4008 4009 4010 4011 4012 4013 4014 4015 4016
                                    compareStateKey, &pCurWin->winInfo.pOutputBuf, &size);
  pCurWin->pStateKey =
      (SStateKeys*)((char*)pCurWin->winInfo.pOutputBuf + (pAggSup->resultRowSize - pAggSup->stateKeySize));
  pCurWin->pStateKey->bytes = pAggSup->stateKeySize - sizeof(SStateKeys);
  pCurWin->pStateKey->type = pAggSup->stateKeyType;
  pCurWin->pStateKey->pData = (char*)pCurWin->pStateKey + sizeof(SStateKeys);
  pCurWin->pStateKey->isNull = false;

  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->winInfo.isOutput = true;
L
liuyao 已提交
4017
  } else if (pKeyData) {
5
54liuyao 已提交
4018 4019 4020 4021
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
    } else {
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
5
54liuyao 已提交
4022 4023 4024
    }
  }

5
54liuyao 已提交
4025 4026
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
  pNextWin->winInfo.pOutputBuf = NULL;
4027 4028
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->winInfo.sessionWin);
  code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin, NULL, 0);
5
54liuyao 已提交
4029 4030
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
5
54liuyao 已提交
4031
  }
4032
  pAggSup->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
4033 4034
}

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

    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
H
Haojun Liao 已提交
4055
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
5
54liuyao 已提交
4056
        saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
5
54liuyao 已提交
4057
      }
5
54liuyao 已提交
4058 4059
      removeSessionResult(pSeUpdated, pResultRows, pWinInfo->winInfo.sessionWin);
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
5
54liuyao 已提交
4060
    }
5
54liuyao 已提交
4061
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
5
54liuyao 已提交
4062 4063 4064 4065 4066 4067 4068
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
      *allEqual = false;
    }
  }
  return rows - start;
}

5
54liuyao 已提交
4069 4070
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
                                 SSHashObj* pStDeleted) {
4071 4072 4073
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
4074
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
4075
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
4076
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
4077 4078 4079 4080
  int64_t                      code = TSDB_CODE_SUCCESS;
  TSKEY*                       tsCols = NULL;
  SResultRow*                  pResult = NULL;
  int32_t                      winRows = 0;
L
liuyao 已提交
4081 4082 4083

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

5
54liuyao 已提交
4084
  if (pSDataBlock->pDataBlock != NULL) {
X
Xiaoyu Wang 已提交
4085 4086
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
    tsCols = (int64_t*)pColDataInfo->pData;
5
54liuyao 已提交
4087
  } else {
X
Xiaoyu Wang 已提交
4088
    return;
5
54liuyao 已提交
4089
  }
L
Liu Jicong 已提交
4090

5
54liuyao 已提交
4091
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
4092 4093
  int32_t              rows = pSDataBlock->info.rows;
  blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
L
Liu Jicong 已提交
4094
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
5
54liuyao 已提交
4095
  for (int32_t i = 0; i < rows; i += winRows) {
4096
    if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup) || colDataIsNull_s(pKeyColInfo, i)) {
5
54liuyao 已提交
4097 4098 4099
      i++;
      continue;
    }
5
54liuyao 已提交
4100 4101 4102 4103 4104 4105 4106 4107 4108
    char*            pKeyData = colDataGetData(pKeyColInfo, i);
    int32_t          winIndex = 0;
    bool             allEqual = true;
    SStateWindowInfo curWin = {0};
    SStateWindowInfo nextWin = {0};
    setStateOutputBuf(pAggSup, tsCols[i], groupId, pKeyData, &curWin, &nextWin);
    setSessionWinOutputInfo(pSeUpdated, &curWin.winInfo);
    winRows = updateStateWindowInfo(&curWin, &nextWin, tsCols, groupId, pKeyColInfo, rows, i, &allEqual,
                                    pAggSup->pResultRows, pSeUpdated, pStDeleted);
5
54liuyao 已提交
4109
    if (!allEqual) {
4110
      uint64_t uid = 0;
5
54liuyao 已提交
4111 4112 4113 4114
      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);
4115
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)curWin.winInfo.pOutputBuf, &pAPI->stateStore);
5
54liuyao 已提交
4116 4117
      continue;
    }
5
54liuyao 已提交
4118 4119
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
                              pOperator);
5
54liuyao 已提交
4120
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4121
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4122
    }
5
54liuyao 已提交
4123 4124
    saveSessionOutputBuf(pAggSup, &curWin.winInfo);

5
54liuyao 已提交
4125
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
5
54liuyao 已提交
4126
      code = saveResult(curWin.winInfo, pSeUpdated);
5
54liuyao 已提交
4127
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
4128
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4129 4130
      }
    }
4131 4132

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
4133 4134
      SSessionKey key = {0};
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
4135 4136
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
    }
5
54liuyao 已提交
4137 4138 4139 4140 4141 4142 4143 4144
  }
}

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

4145
  SExprSupp*                   pSup = &pOperator->exprSupp;
5
54liuyao 已提交
4146
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
4147
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
5
54liuyao 已提交
4148
  if (pOperator->status == OP_RES_TO_RETURN) {
4149
    doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4150
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4151
      printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4152 4153
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
4154 4155 4156 4157 4158

    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 已提交
4159
    }
5
54liuyao 已提交
4160

H
Haojun Liao 已提交
4161
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
4162
    return NULL;
5
54liuyao 已提交
4163 4164 4165
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
4166 4167 4168 4169
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pSeUpdated) {
4170
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4171 4172
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
4173 4174 4175 4176 4177
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
4178
    printDataBlock(pBlock, "single state recv");
4179

5
54liuyao 已提交
4180 4181 4182 4183
    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 已提交
4184
      removeSessionResults(pInfo->pSeUpdated, pWins);
5
54liuyao 已提交
4185
      copyDeleteWindowInfo(pWins, pInfo->pSeDeleted);
4186 4187
      taosArrayDestroy(pWins);
      continue;
4188
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
4189
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
5
54liuyao 已提交
4190
      continue;
5
54liuyao 已提交
4191 4192 4193 4194
    } 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 已提交
4195
    }
4196

5
54liuyao 已提交
4197 4198 4199 4200
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
4201
    // the pDataBlock are always the same one, no need to call this again
4202
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
4203 4204
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
5
54liuyao 已提交
4205 4206 4207
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
X
Xiaoyu Wang 已提交
4208

5
54liuyao 已提交
4209 4210 4211 4212 4213
  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 已提交
4214

L
liuyao 已提交
4215 4216 4217 4218
  if(pInfo->isHistoryOp) {
    getMaxTsWins(pInfo->pUpdated, pInfo->historyWins);
  }

5
54liuyao 已提交
4219 4220
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
4221
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
4222

5
54liuyao 已提交
4223 4224 4225 4226 4227 4228
#if 0
  char* pBuf = streamStateSessionDump(pInfo->streamAggSup.pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

4229
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4230
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4231
    printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4232 4233 4234
    return pInfo->pDelRes;
  }

5
54liuyao 已提交
4235 4236 4237 4238 4239
  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 已提交
4240
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
4241
  return NULL;
4242 4243
}

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

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

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

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

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

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

X
Xiaoyu Wang 已提交
4307 4308 4309 4310 4311
SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamStateWinodwPhysiNode* pStateNode = (SStreamStateWinodwPhysiNode*)pPhyNode;
  int32_t                      tsSlotId = ((SColumnNode*)pStateNode->window.pTspk)->slotId;
  SColumnNode*                 pColNode = (SColumnNode*)((STargetNode*)pStateNode->pStateKey)->pExpr;
H
Haojun Liao 已提交
4312
  int32_t                      code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
4313

X
Xiaoyu Wang 已提交
4314 4315
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
4316
  if (pInfo == NULL || pOperator == NULL) {
H
Haojun Liao 已提交
4317
    code = TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
4318 4319 4320 4321
    goto _error;
  }

  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
4322
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
4323 4324 4325
  if (pStateNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalar);
4326
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4327 4328 4329 4330 4331
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

X
Xiaoyu Wang 已提交
4332 4333
  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pStateNode->window.watermark,
5
54liuyao 已提交
4334 4335
      .calTrigger = pStateNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
4336
      .minTs = INT64_MAX,
X
Xiaoyu Wang 已提交
4337
  };
4338

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

5
54liuyao 已提交
4341 4342 4343
  SExprSupp*   pSup = &pOperator->exprSupp;
  int32_t      numOfCols = 0;
  SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
4344
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
4345
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4346 4347 4348
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
5
54liuyao 已提交
4349 4350 4351
  int32_t keySize = sizeof(SStateKeys) + pColNode->node.resType.bytes;
  int16_t type = pColNode->node.resType.type;
  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, 0, pTaskInfo->streamInfo.pState, keySize,
H
Haojun Liao 已提交
4352
                                type, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
4353 4354 4355 4356 4357 4358
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  pInfo->primaryTsIndex = tsSlotId;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4359
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
5
54liuyao 已提交
4360
  pInfo->pDelIterator = NULL;
H
Haojun Liao 已提交
4361
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
5
54liuyao 已提交
4362
  pInfo->pChildren = NULL;
5
54liuyao 已提交
4363
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
4364
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
4365 4366
  pInfo->pUpdated = NULL;
  pInfo->pSeUpdated = NULL;
L
liuyao 已提交
4367
  pInfo->dataVersion = 0;
L
liuyao 已提交
4368 4369 4370 4371 4372
  pInfo->historyWins = taosArrayInit(4, sizeof(SSessionKey));
  if (!pInfo->historyWins) {
    goto _error;
  }
  pInfo->isHistoryOp = false;
5
54liuyao 已提交
4373

L
Liu Jicong 已提交
4374 4375
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
L
Liu Jicong 已提交
4376 4377
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAgg, NULL, destroyStreamStateOperatorInfo,
                                         optrDefaultBufFn, NULL);
L
liuyao 已提交
4378
  setOperatorStreamStateFn(pOperator, streamStateReleaseState, streamStateReloadState);
5
54liuyao 已提交
4379
  initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
4380 4381 4382 4383 4384 4385 4386
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
  return pOperator;

_error:
4387
  destroyStreamStateOperatorInfo(pInfo);
5
54liuyao 已提交
4388 4389 4390 4391
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4392

4393
void destroyMAIOperatorInfo(void* param) {
4394
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
4395
  destroyIntervalOperatorInfo(miaInfo->intervalAggOperatorInfo);
D
dapan1121 已提交
4396
  taosMemoryFreeClear(param);
4397 4398
}

4399
static SResultRow* doSetSingleOutputTupleBuf(SResultRowInfo* pResultRowInfo, SAggSupporter* pSup) {
H
Haojun Liao 已提交
4400
  SResultRow* pResult = getNewResultRow(pSup->pResultBuf, &pSup->currentPageId, pSup->resultRowSize);
4401 4402 4403
  if (NULL == pResult) {
    return pResult;
  }
H
Haojun Liao 已提交
4404
  pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
4405 4406
  return pResult;
}
4407

4408 4409 4410 4411 4412 4413 4414 4415
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;
    }
  }
4416

4417
  // set time window for current result
4418 4419
  (*pResult)->win = (*win);
  setResultRowInitCtx((*pResult), pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset);
4420
  return TSDB_CODE_SUCCESS;
4421 4422
}

4423
static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
4424
                                          SSDataBlock* pBlock, SSDataBlock* pResultBlock) {
4425
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
D
dapan1121 已提交
4426
  SIntervalAggOperatorInfo*             iaInfo = miaInfo->intervalAggOperatorInfo;
4427 4428

  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
4429
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
4430
  SInterval*     pInterval = &iaInfo->interval;
4431

5
54liuyao 已提交
4432 4433
  int32_t  startPos = 0;
  int64_t* tsCols = extractTsCol(pBlock, iaInfo);
4434

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

4437 4438
  // there is an result exists
  if (miaInfo->curTs != INT64_MIN) {
4439
    if (ts != miaInfo->curTs) {
4440
      finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4441
      resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4442
      miaInfo->curTs = ts;
4443
    }
4444 4445
  } else {
    miaInfo->curTs = ts;
4446 4447 4448
  }

  STimeWindow win = {0};
4449
  win.skey = miaInfo->curTs;
4450
  win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4451

5
54liuyao 已提交
4452
  int32_t ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4453 4454
  if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
    T_LONG_JMP(pTaskInfo->env, ret);
4455 4456
  }

4457 4458
  int32_t currPos = startPos;

4459
  STimeWindow currWin = win;
4460
  while (++currPos < pBlock->info.rows) {
4461
    if (tsCols[currPos] == miaInfo->curTs) {
4462
      continue;
4463 4464 4465
    }

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

4469
    finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4470
    resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4471
    miaInfo->curTs = tsCols[currPos];
4472

4473
    currWin.skey = miaInfo->curTs;
4474
    currWin.ekey = taosTimeAdd(currWin.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4475 4476

    startPos = currPos;
5
54liuyao 已提交
4477
    ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4478 4479
    if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
      T_LONG_JMP(pTaskInfo->env, ret);
4480
    }
4481 4482

    miaInfo->curTs = currWin.skey;
4483
  }
4484

4485
  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, true);
H
Haojun Liao 已提交
4486
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
L
Liu Jicong 已提交
4487
                                  pBlock->info.rows, pSup->numOfExprs);
4488 4489
}

4490
static void cleanupAfterGroupResultGen(SMergeAlignedIntervalAggOperatorInfo* pMiaInfo, SSDataBlock* pRes) {
H
Haojun Liao 已提交
4491
  pRes->info.id.groupId = pMiaInfo->groupId;
4492 4493
  pMiaInfo->curTs = INT64_MIN;
  pMiaInfo->groupId = 0;
4494 4495
}

4496
static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
S
shenglian zhou 已提交
4497
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4498

4499 4500
  SMergeAlignedIntervalAggOperatorInfo* pMiaInfo = pOperator->info;
  SIntervalAggOperatorInfo*             pIaInfo = pMiaInfo->intervalAggOperatorInfo;
4501

4502 4503 4504 4505
  SExprSupp*      pSup = &pOperator->exprSupp;
  SSDataBlock*    pRes = pIaInfo->binfo.pRes;
  SResultRowInfo* pResultRowInfo = &pIaInfo->binfo.resultRowInfo;
  SOperatorInfo*  downstream = pOperator->pDownstream[0];
4506

4507 4508
  while (1) {
    SSDataBlock* pBlock = NULL;
4509
    if (pMiaInfo->prefetchedBlock == NULL) {
4510 4511
      pBlock = downstream->fpSet.getNextFn(downstream);
    } else {
4512 4513
      pBlock = pMiaInfo->prefetchedBlock;
      pMiaInfo->prefetchedBlock = NULL;
4514

H
Haojun Liao 已提交
4515
      pMiaInfo->groupId = pBlock->info.id.groupId;
4516
    }
4517

4518
    // no data exists, all query processing is done
4519
    if (pBlock == NULL) {
4520 4521 4522
      // close last unclosed time window
      if (pMiaInfo->curTs != INT64_MIN) {
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4523 4524
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
4525
      }
4526

H
Haojun Liao 已提交
4527
      setOperatorCompleted(pOperator);
4528
      break;
4529
    }
4530

H
Haojun Liao 已提交
4531
    if (pMiaInfo->groupId == 0) {
H
Haojun Liao 已提交
4532 4533 4534
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
        pMiaInfo->groupId = pBlock->info.id.groupId;
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4535 4536
      }
    } else {
H
Haojun Liao 已提交
4537
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
H
Haojun Liao 已提交
4538
        // if there are unclosed time window, close it firstly.
4539
        ASSERT(pMiaInfo->curTs != INT64_MIN);
H
Haojun Liao 已提交
4540
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4541
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
H
Haojun Liao 已提交
4542

4543 4544
        pMiaInfo->prefetchedBlock = pBlock;
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
H
Haojun Liao 已提交
4545
        break;
5
54liuyao 已提交
4546
      } else {
H
Haojun Liao 已提交
4547
        // continue
H
Haojun Liao 已提交
4548
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4549
      }
4550
    }
4551

4552 4553
    pRes->info.scanFlag = pBlock->info.scanFlag;
    setInputDataBlock(pSup, pBlock, pIaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
4554
    doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes);
4555

H
Haojun Liao 已提交
4556
    doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
4557 4558 4559
    if (pRes->info.rows >= pOperator->resultInfo.capacity) {
      break;
    }
4560
  }
4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575
}

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 已提交
4576
    while (1) {
4577
      if (pOperator->status == OP_EXEC_DONE) {
4578 4579
        break;
      }
4580

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

4585 4586 4587 4588
      doMergeAlignedIntervalAgg(pOperator);
    }
  } else {
    doMergeAlignedIntervalAgg(pOperator);
4589 4590 4591 4592 4593 4594 4595
  }

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

4596
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode,
4597
                                                      SExecTaskInfo* pTaskInfo) {
4598
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
4599
  SOperatorInfo*                        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4600 4601 4602 4603
  if (miaInfo == NULL || pOperator == NULL) {
    goto _error;
  }

D
dapan1121 已提交
4604 4605 4606 4607 4608
  miaInfo->intervalAggOperatorInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
  if (miaInfo->intervalAggOperatorInfo == NULL) {
    goto _error;
  }

4609 4610 4611 4612 4613 4614 4615
  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 已提交
4616
  SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
4617
  SExprSupp*                pSup = &pOperator->exprSupp;
4618

H
Haojun Liao 已提交
4619 4620 4621 4622 4623
  int32_t code = filterInitFromNode((SNode*)pNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

L
Liu Jicong 已提交
4624 4625
  miaInfo->curTs = INT64_MIN;
  iaInfo->win = pTaskInfo->window;
4626 4627
  iaInfo->binfo.inputTsOrder = pNode->window.node.inputTsOrder;
  iaInfo->binfo.outputTsOrder = pNode->window.node.outputTsOrder;
L
Liu Jicong 已提交
4628
  iaInfo->interval = interval;
4629 4630
  iaInfo->primaryTsIndex = ((SColumnNode*)pNode->window.pTspk)->slotId;
  iaInfo->binfo.mergeResultBlock = pNode->window.mergeDataBlock;
4631 4632

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

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

L
Liu Jicong 已提交
4638
  code = initAggSup(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4639
                    pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4640 4641 4642
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4643

H
Haojun Liao 已提交
4644
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pNode->window.node.pOutputDataBlockDesc);
4645
  initBasicInfo(&iaInfo->binfo, pResBlock);
4646
  initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
4647

4648
  iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, num, iaInfo);
4649
  if (iaInfo->timeWindowInterpo) {
4650
    iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4651 4652
  }

4653
  initResultRowInfo(&iaInfo->binfo.resultRowInfo);
4654
  blockDataEnsureCapacity(iaInfo->binfo.pRes, pOperator->resultInfo.capacity);
L
Liu Jicong 已提交
4655 4656
  setOperatorInfo(pOperator, "TimeMergeAlignedIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
                  false, OP_NOT_OPENED, miaInfo, pTaskInfo);
4657

L
Liu Jicong 已提交
4658 4659
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, mergeAlignedIntervalAgg, NULL, destroyMAIOperatorInfo,
                                         optrDefaultBufFn, NULL);
4660 4661 4662 4663 4664 4665 4666 4667 4668

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

  return pOperator;

_error:
4669
  destroyMAIOperatorInfo(miaInfo);
4670 4671 4672 4673
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4674 4675 4676 4677 4678

//=====================================================================================================================
// merge interval operator
typedef struct SMergeIntervalAggOperatorInfo {
  SIntervalAggOperatorInfo intervalAggOperatorInfo;
L
Liu Jicong 已提交
4679 4680 4681 4682 4683 4684
  SList*                   groupIntervals;
  SListIter                groupIntervalsIter;
  bool                     hasGroupId;
  uint64_t                 groupId;
  SSDataBlock*             prefetchedBlock;
  bool                     inputBlocksFinished;
4685 4686
} SMergeIntervalAggOperatorInfo;

S
slzhou 已提交
4687
typedef struct SGroupTimeWindow {
L
Liu Jicong 已提交
4688
  uint64_t    groupId;
S
slzhou 已提交
4689 4690 4691
  STimeWindow window;
} SGroupTimeWindow;

4692
void destroyMergeIntervalOperatorInfo(void* param) {
4693
  SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
S
slzhou 已提交
4694
  tdListFree(miaInfo->groupIntervals);
4695
  destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo);
4696

D
dapan1121 已提交
4697
  taosMemoryFreeClear(param);
4698 4699 4700 4701 4702 4703
}

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

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

S
slzhou 已提交
4709 4710 4711 4712 4713
  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 已提交
4714
    if (prevGrpWin->groupId != tableGroupId) {
S
slzhou 已提交
4715 4716
      continue;
    }
4717

S
slzhou 已提交
4718
    STimeWindow* prevWin = &prevGrpWin->window;
H
Haojun Liao 已提交
4719
    if ((ascScan && newWin->skey > prevWin->ekey) || ((!ascScan) && newWin->skey < prevWin->ekey)) {
S
slzhou 已提交
4720 4721
      tdListPopNode(miaInfo->groupIntervals, listNode);
    }
4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737
  }

  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 已提交
4738
  uint64_t    tableGroupId = pBlock->info.id.groupId;
4739
  bool        ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
4740 4741 4742
  TSKEY       blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
  SResultRow* pResult = NULL;

4743
  STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
4744
                                        iaInfo->binfo.inputTsOrder);
4745 4746 4747 4748 4749

  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 已提交
4750
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4751 4752 4753 4754
  }

  TSKEY   ekey = ascScan ? win.ekey : win.skey;
  int32_t forwardRows =
4755
      getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4756
  ASSERT(forwardRows > 0);
4757 4758 4759

  // prev time window not interpolation yet.
  if (iaInfo->timeWindowInterpo) {
4760
    SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
4761 4762 4763 4764 4765 4766
    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 已提交
4767
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4768 4769 4770 4771 4772 4773 4774
    }

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

  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, true);
H
Haojun Liao 已提交
4775
  applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4776
                                  pBlock->info.rows, numOfOutput);
4777 4778 4779 4780 4781 4782 4783 4784
  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;
4785
    startPos =
4786
        getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->binfo.inputTsOrder);
4787 4788 4789 4790 4791 4792 4793 4794 4795
    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 已提交
4796
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4797 4798 4799 4800
    }

    ekey = ascScan ? nextWin.ekey : nextWin.skey;
    forwardRows =
4801
        getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4802 4803 4804 4805 4806

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

    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, true);
H
Haojun Liao 已提交
4807
    applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4808
                                    pBlock->info.rows, numOfOutput);
4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842
    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 已提交
4843
        miaInfo->groupId = pBlock->info.id.groupId;
4844 4845 4846 4847
        miaInfo->prefetchedBlock = NULL;
      }

      if (pBlock == NULL) {
S
slzhou 已提交
4848
        tdListInitIter(miaInfo->groupIntervals, &miaInfo->groupIntervalsIter, TD_LIST_FORWARD);
4849 4850 4851 4852 4853 4854
        miaInfo->inputBlocksFinished = true;
        break;
      }

      if (!miaInfo->hasGroupId) {
        miaInfo->hasGroupId = true;
H
Haojun Liao 已提交
4855 4856
        miaInfo->groupId = pBlock->info.id.groupId;
      } else if (miaInfo->groupId != pBlock->info.id.groupId) {
4857 4858 4859 4860
        miaInfo->prefetchedBlock = pBlock;
        break;
      }

4861 4862 4863
      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);
4864 4865 4866 4867 4868 4869

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

H
Haojun Liao 已提交
4870
    pRes->info.id.groupId = miaInfo->groupId;
4871 4872 4873
  }

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

S
slzhou 已提交
4876 4877
    if (listNode != NULL) {
      SGroupTimeWindow* grpWin = (SGroupTimeWindow*)(listNode->data);
H
Haojun Liao 已提交
4878
      pRes->info.id.groupId = grpWin->groupId;
4879 4880 4881 4882
    }
  }

  if (pRes->info.rows == 0) {
H
Haojun Liao 已提交
4883
    setOperatorCompleted(pOperator);
4884 4885 4886 4887 4888 4889 4890
  }

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

4891 4892 4893
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode,
                                               SExecTaskInfo* pTaskInfo) {
  SMergeIntervalAggOperatorInfo* pMergeIntervalInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
4894
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4895
  if (pMergeIntervalInfo == NULL || pOperator == NULL) {
4896 4897 4898
    goto _error;
  }

5
54liuyao 已提交
4899 4900
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
4901 4902 4903 4904 4905 4906 4907

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

4909
  pMergeIntervalInfo->groupIntervals = tdListNew(sizeof(SGroupTimeWindow));
4910

4911
  SIntervalAggOperatorInfo* pIntervalInfo = &pMergeIntervalInfo->intervalAggOperatorInfo;
L
Liu Jicong 已提交
4912
  pIntervalInfo->win = pTaskInfo->window;
4913
  pIntervalInfo->binfo.inputTsOrder = pIntervalPhyNode->window.node.inputTsOrder;
L
Liu Jicong 已提交
4914
  pIntervalInfo->interval = interval;
4915 4916
  pIntervalInfo->binfo.mergeResultBlock = pIntervalPhyNode->window.mergeDataBlock;
  pIntervalInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
4917
  pIntervalInfo->binfo.outputTsOrder = pIntervalPhyNode->window.node.outputTsOrder;
4918 4919 4920 4921

  SExprSupp* pExprSupp = &pOperator->exprSupp;

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

L
Liu Jicong 已提交
4924
  int32_t code = initAggSup(pExprSupp, &pIntervalInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4925
                            pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4926 4927 4928
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4929

H
Haojun Liao 已提交
4930
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pIntervalPhyNode->window.node.pOutputDataBlockDesc);
4931 4932
  initBasicInfo(&pIntervalInfo->binfo, pResBlock);
  initExecTimeWindowInfo(&pIntervalInfo->twAggSup.timeWindowData, &pIntervalInfo->win);
4933

4934 4935
  pIntervalInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, num, pIntervalInfo);
  if (pIntervalInfo->timeWindowInterpo) {
4936
    pIntervalInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4937
    if (pIntervalInfo->binfo.resultRowInfo.openWindow == NULL) {
4938 4939 4940 4941
      goto _error;
    }
  }

4942
  initResultRowInfo(&pIntervalInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
4943 4944
  setOperatorInfo(pOperator, "TimeMergeIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, false,
                  OP_NOT_OPENED, pMergeIntervalInfo, pTaskInfo);
L
Liu Jicong 已提交
4945 4946
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doMergeIntervalAgg, NULL, destroyMergeIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
4947 4948 4949 4950 4951 4952 4953 4954 4955

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

  return pOperator;

_error:
H
Haojun Liao 已提交
4956 4957 4958 4959
  if (pMergeIntervalInfo != NULL) {
    destroyMergeIntervalOperatorInfo(pMergeIntervalInfo);
  }

4960 4961 4962
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
4963
}
4964 4965 4966

static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
4967
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4968 4969
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

4970
  SExprSupp* pSup = &pOperator->exprSupp;
4971 4972 4973 4974 4975 4976

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

  if (pOperator->status == OP_RES_TO_RETURN) {
4977
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
4978
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4979
      printDataBlock(pInfo->pDelRes, "single interval delete");
4980 4981 4982
      return pInfo->pDelRes;
    }

4983
    doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
4984 4985 4986
    if (pInfo->binfo.pRes->info.rows > 0) {
      printDataBlock(pInfo->binfo.pRes, "single interval");
      return pInfo->binfo.pRes;
4987
    }
L
liuyao 已提交
4988 4989 4990 4991 4992 4993

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

H
Haojun Liao 已提交
4994
    setOperatorCompleted(pOperator);
dengyihao's avatar
dengyihao 已提交
4995 4996
    if (pInfo->twAggSup.maxTs > 0 &&
        pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
4997 4998
      pAPI->stateStore.streamStateCommit(pInfo->pState);
      pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
4999
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
L
liuyao 已提交
5000 5001
      pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
    }
5
54liuyao 已提交
5002
    return NULL;
5003 5004 5005 5006
  }

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

5
54liuyao 已提交
5007
  if (!pInfo->pUpdated) {
L
liuyao 已提交
5008
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
5009
  }
5010

5
54liuyao 已提交
5011 5012
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
5013
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
5014 5015
  }

5016 5017 5018
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
5019 5020
      qDebug("===stream===return data:single interval. recv datablock num:%" PRIu64, pInfo->numOfDatapack);
      pInfo->numOfDatapack = 0;
5021 5022
      break;
    }
5023

5
54liuyao 已提交
5024
    pInfo->numOfDatapack++;
5025 5026
    printDataBlock(pBlock, "single interval recv");

5027 5028
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
5029
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap);
5030 5031
      continue;
    } else if (pBlock->info.type == STREAM_GET_ALL) {
L
liuyao 已提交
5032
      qDebug("===stream===single interval recv|block type STREAM_GET_ALL");
L
liuyao 已提交
5033
      pInfo->recvGetAll = true;
5
54liuyao 已提交
5034
      getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
5035
      continue;
5
54liuyao 已提交
5036
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
5
54liuyao 已提交
5037
      printDataBlock(pBlock, "single interval");
5
54liuyao 已提交
5038 5039 5040
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055
    }

    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
5056
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5057 5058 5059 5060
    if (pInfo->invertible) {
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
    }

5
54liuyao 已提交
5061
    doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap);
5
54liuyao 已提交
5062 5063
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
5064 5065
  }
  pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
5066
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
5067 5068
  closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
                            pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
5069

5070 5071 5072
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
5073
    taosArrayPush(pInfo->pUpdated, pIte);
5074
  }
5
54liuyao 已提交
5075
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
5076

5
54liuyao 已提交
5077 5078
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5079
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5080
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
5081
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
5082

5
54liuyao 已提交
5083 5084 5085 5086 5087 5088
#if 0
  char* pBuf = streamStateIntervalDump(pInfo->pState);
  qDebug("===stream===interval state%s", pBuf);
  taosMemoryFree(pBuf);
#endif

5089
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
5090
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
5091
    printDataBlock(pInfo->pDelRes, "single interval delete");
5092 5093 5094
    return pInfo->pDelRes;
  }

5095
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
5096 5097 5098 5099 5100 5101
  if (pInfo->binfo.pRes->info.rows > 0) {
    printDataBlock(pInfo->binfo.pRes, "single interval");
    return pInfo->binfo.pRes;
  }

  return NULL;
5102 5103 5104 5105 5106
}

SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
5107
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5108 5109 5110 5111 5112
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;

H
Haojun Liao 已提交
5113
  int32_t    code = TSDB_CODE_SUCCESS;
5114 5115
  int32_t    numOfCols = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
5116

H
Haojun Liao 已提交
5117
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
5118 5119 5120 5121 5122 5123 5124
  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,
5125
  };
H
Haojun Liao 已提交
5126

dengyihao's avatar
dengyihao 已提交
5127
  pInfo->twAggSup = (STimeWindowAggSupp){
5128 5129 5130
      .waterMark = pIntervalPhyNode->window.watermark,
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
5131
      .minTs = INT64_MAX,
5
54liuyao 已提交
5132
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
liuyao 已提交
5133
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
5134 5135
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
5136
  };
H
Haojun Liao 已提交
5137

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

5140
  pOperator->pTaskInfo = pTaskInfo;
5141 5142
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5143
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
5144
  pInfo->ignoreExpiredDataSaved = false;
5145 5146 5147
  pInfo->isFinal = false;

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

5152
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
5153
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5154

L
liuyao 已提交
5155 5156
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
5157
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
liuyao 已提交
5158

5159
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
L
Liu Jicong 已提交
5160
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
5161
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
5162 5163 5164 5165
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
5166 5167 5168
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
5169
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
H
Haojun Liao 已提交
5170 5171 5172 5173
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }
5174 5175

  pInfo->invertible = allInvertible(pSup->pCtx, numOfCols);
5176
  pInfo->invertible = false;
5177 5178 5179 5180 5181
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
  pInfo->delIndex = 0;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
  initResultRowInfo(&pInfo->binfo.resultRowInfo);

5182 5183
  pInfo->pPhyNode = NULL;  // create new child
  pInfo->pPullDataMap = NULL;
L
liuyao 已提交
5184
  pInfo->pFinalPullDataMap = NULL;
5185 5186 5187 5188
  pInfo->pPullWins = NULL;  // SPullWindowInfo
  pInfo->pullIndex = 0;
  pInfo->pPullDataRes = NULL;
  pInfo->isFinal = false;
L
liuyao 已提交
5189
  pInfo->numOfChild = 0;
5190 5191
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
5192
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
5193 5194
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
5195
  int32_t funResSize= getMaxFunResSize(pSup, numOfCols);
5196 5197 5198 5199

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

L
Liu Jicong 已提交
5201 5202
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
5203 5204
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAgg, NULL,
                                         destroyStreamFinalIntervalOperatorInfo, optrDefaultBufFn, NULL);
L
liuyao 已提交
5205
  setOperatorStreamStateFn(pOperator, streamIntervalReleaseState, streamIntervalReloadState);
5206

5207
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
5208 5209
  pInfo->recvGetAll = false;

L
liuyao 已提交
5210
  initIntervalDownStream(downstream, pPhyNode->type, pInfo);
5211 5212 5213 5214 5215 5216 5217 5218
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
5219
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5220 5221 5222 5223
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}