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

L
Liu Jicong 已提交
29
#define IS_FINAL_OP(op)    ((op)->isFinal)
5
54liuyao 已提交
30
#define DEAULT_DELETE_MARK (1000LL * 60LL * 60LL * 24LL * 365LL * 10LL);
H
Haojun Liao 已提交
31

32 33 34 35 36
typedef struct SStateWindowInfo {
  SResultWindowInfo winInfo;
  SStateKeys*       pStateKey;
} SStateWindowInfo;

H
Haojun Liao 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
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;

61 62 63 64 65
typedef enum SResultTsInterpType {
  RESULT_ROW_START_INTERP = 1,
  RESULT_ROW_END_INTERP = 2,
} SResultTsInterpType;

5
54liuyao 已提交
66 67
typedef struct SPullWindowInfo {
  STimeWindow window;
L
Liu Jicong 已提交
68
  uint64_t    groupId;
5
54liuyao 已提交
69
  STimeWindow calWin;
5
54liuyao 已提交
70 71
} SPullWindowInfo;

72 73
typedef struct SOpenWindowInfo {
  SResultRowPosition pos;
L
Liu Jicong 已提交
74
  uint64_t           groupId;
75 76
} SOpenWindowInfo;

77 78
static int64_t* extractTsCol(SSDataBlock* pBlock, const SIntervalAggOperatorInfo* pInfo);

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

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

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

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

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

100
  *pResult = pResultRow;
101
  setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowEntryInfoOffset);
102

103 104 105
  return TSDB_CODE_SUCCESS;
}

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

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

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

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

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

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

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

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

H
Haojun Liao 已提交
164
  ASSERT(forwardRows >= 0);
165
  return forwardRows;
166 167
}

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

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

      if (key < keyList[midPos]) {
        firstPos = midPos + 1;
200 201
      } else if (key > keyList[midPos]) {
        lastPos = midPos - 1;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
      } 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 已提交
237 238
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 已提交
239
  ASSERT(startPos >= 0 && startPos < pDataBlockInfo->rows);
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259

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

  return num;
}

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

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

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

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

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

297
    GET_TYPED_DATA(v2, double, pColInfo->info.type, colDataGetData(pColInfo, curRowIndex));
298

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

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

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

X
Xiaoyu Wang 已提交
328 329 330 331 332 333
    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;
334
    }
X
Xiaoyu Wang 已提交
335 336 337

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

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

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

359
  TSKEY curTs = tsCols[pos];
360 361

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

  // 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) {
368
    setNotInterpoWindowKey(pSup->pCtx, pSup->numOfExprs, RESULT_ROW_START_INTERP);
369 370 371
    return true;
  }

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

  return true;
}

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

  TSKEY actualEndKey = tsCols[endRowIndex];
390
  TSKEY key = (order == TSDB_ORDER_ASC) ? win->ekey : win->skey;
391 392

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

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

404
  int32_t nextRowIndex = endRowIndex + 1;
H
Haojun Liao 已提交
405
  ASSERT(nextRowIndex >= 0);
406 407

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

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

5
54liuyao 已提交
419 420 421
  return true;
}

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

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

  int32_t precision = pInterval->precision;
431
  getNextTimeWindow(pInterval, pNext, order);
432 433 434 435 436 437 438

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

443
  TSKEY   skey = ascQuery ? pNext->skey : pNext->ekey;
444 445 446 447
  int32_t startPos = 0;

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

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

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

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

520
  ASSERT(pBlock != NULL);
521 522 523 524 525
  if (pBlock->pDataBlock == NULL) {
    //    tscError("pBlock->pDataBlock == NULL");
    return;
  }

526
  SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, pInfo->primaryTsIndex);
527 528

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

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

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

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

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

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

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

      break;
    }
586 587 588
  }
}

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

593
  SIntervalAggOperatorInfo* pInfo = (SIntervalAggOperatorInfo*)pOperatorInfo->info;
594
  SExprSupp*                pSup = &pOperatorInfo->exprSupp;
595

L
Liu Jicong 已提交
596 597
  int32_t startPos = 0;
  int32_t numOfOutput = pSup->numOfExprs;
598

599
  SResultRow* pResult = NULL;
600

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

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

615
    ASSERT(pr->offset == p1->offset && pr->pageId == p1->pageId);
616

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

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

632
    ASSERT(!isResultRowInterpolated(pResult, RESULT_ROW_END_INTERP));
633

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

    setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
642
    setNotInterpoWindowKey(pSup->pCtx, numOfExprs, RESULT_ROW_START_INTERP);
643

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

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

5
54liuyao 已提交
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
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 已提交
714
typedef int64_t (*__get_value_fn_t)(void* data, int32_t index);
715

X
Xiaoyu Wang 已提交
716 717 718
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 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764

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

5
54liuyao 已提交
767 768 769
  return midPos;
}

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

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

5
54liuyao 已提交
812 813 814
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 已提交
815 816
}

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

5
54liuyao 已提交
822 823 824 825
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 已提交
826 827
}

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

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

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

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

5
54liuyao 已提交
870 871 872 873 874
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 已提交
875

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

880
  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
881
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
882

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

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

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

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

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

915
    // window start key interpolation
916
    doWindowBorderInterpolation(pInfo, pBlock, pResult, &win, startPos, forwardRows, pSup);
917
  }
918

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

  doCloseWindow(pResultRowInfo, pInfo, pResult);
924 925 926

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

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

  if (pInfo->timeWindowInterpo) {
961
    saveDataBlockLastRow(pInfo->pPrevValues, pBlock, pInfo->pInterpCols);
962
  }
963 964 965 966 967 968
}

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

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

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

990
  return openWin.pos;
991 992 993 994
}

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

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

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

  return tsCols;
1012 1013 1014 1015 1016 1017 1018
}

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

1019 1020 1021
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SOperatorInfo* downstream = pOperator->pDownstream[0];

1022
  SIntervalAggOperatorInfo* pInfo = pOperator->info;
1023
  SExprSupp*                pSup = &pOperator->exprSupp;
1024

1025
  int32_t scanFlag = MAIN_SCAN;
1026
  int64_t st = taosGetTimestampUs();
1027 1028

  while (1) {
1029
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
1030 1031 1032 1033
    if (pBlock == NULL) {
      break;
    }

1034
    pInfo->binfo.pRes->info.scanFlag = scanFlag = pBlock->info.scanFlag;
1035

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

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

1046
  initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, pInfo->binfo.outputTsOrder);
1047
  OPTR_SET_OPENED(pOperator);
1048 1049

  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
1050 1051 1052
  return TSDB_CODE_SUCCESS;
}

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

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

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

  bool    masterScan = true;
1073
  int32_t numOfOutput = pOperator->exprSupp.numOfExprs;
1074
  int32_t bytes = pStateColInfoData->info.bytes;
1075

1076
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
1077 1078 1079 1080 1081
  TSKEY*           tsList = (TSKEY*)pColInfoData->pData;

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

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

    char* val = colDataGetData(pStateColInfoData, j);

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

1099 1100
      pInfo->hasKey = true;

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

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

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

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

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

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

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

  SStateWindowOperatorInfo* pInfo = pOperator->info;
1157
  SExecTaskInfo*            pTaskInfo = pOperator->pTaskInfo;
1158

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

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

W
wangjiaming0909 已提交
1170
    pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
1171
    setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
1172 1173
    blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);

1174 1175 1176 1177 1178 1179 1180 1181 1182
    // 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);
      }
    }

1183 1184 1185
    doStateWindowAggImpl(pOperator, pInfo, pBlock);
  }

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

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

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

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

1219 1220 1221 1222
    if (pBInfo->pRes->info.rows > 0) {
      break;
    }
  }
1223

1224
  pOperator->resultInfo.totalRows += pBInfo->pRes->info.rows;
1225
  return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
1226 1227
}

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

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

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

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

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

1252 1253 1254
    if (pBlock->info.rows > 0) {
      break;
    }
1255
  }
1256 1257 1258 1259 1260

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

  return (rows == 0) ? NULL : pBlock;
1261 1262
}

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

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

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

1299
static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) {
1300 1301
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

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

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

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

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

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

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

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

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

D
dapan1121 已提交
1472
  taosMemoryFreeClear(param);
1473 1474
}

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

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

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

H
Haojun Liao 已提交
1488 1489 1490 1491
  pInfo->pInterpCols = taosArrayDestroy(pInfo->pInterpCols);
  taosArrayDestroyEx(pInfo->pPrevValues, freeItem);

  pInfo->pPrevValues = NULL;
1492

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

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

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

D
dapan1121 已提交
1521
  taosMemoryFreeClear(param);
5
54liuyao 已提交
1522 1523
}

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

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

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

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

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

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

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

      SColumn c = *pParam->pCol;
1573
      taosArrayPush(pInfo->pInterpCols, &c);
1574 1575

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

  return needed;
}

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

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

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

L
liuyao 已提交
1602 1603 1604
  pScanInfo->interval = pInfo->interval;
  pScanInfo->twAggSup = pInfo->twAggSup;
  pScanInfo->pState = pInfo->pState;
5
54liuyao 已提交
1605 1606
}

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

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

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

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

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

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

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

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

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

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

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

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

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

  return pOperator;

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

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

1710
  SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
1711 1712

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

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

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

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

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

L
liuyao 已提交
1771
  updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pRowSup->win, 0);
L
Liu Jicong 已提交
1772 1773
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
                                  pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
1774 1775
}

1776
static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
1777 1778 1779 1780 1781 1782
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  }

  SSessionAggOperatorInfo* pInfo = pOperator->info;
  SOptrBasicInfo*          pBInfo = &pInfo->binfo;
1783
  SExprSupp*               pSup = &pOperator->exprSupp;
1784 1785

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

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

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

1804
  int64_t st = taosGetTimestampUs();
1805
  int32_t order = pInfo->binfo.inputTsOrder;
1806

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

  while (1) {
1810
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
1811 1812 1813 1814
    if (pBlock == NULL) {
      break;
    }

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

1820 1821 1822
    doSessionWindowAggImpl(pOperator, pInfo, pBlock);
  }

1823 1824
  pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;

1825 1826 1827
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;

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

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

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

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

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

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

1869
  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
1870 1871 1872 1873 1874 1875
  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;
  }
1876 1877
  pInfo->binfo.inputTsOrder = pStateNode->window.node.inputTsOrder;
  pInfo->binfo.outputTsOrder = pStateNode->window.node.outputTsOrder;
1878

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

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

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

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

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

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

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

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

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

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

1917 1918
  return pOperator;

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

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

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

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

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

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

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

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

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

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

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

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

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

1993 1994
  return pOperator;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2507
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
2508 2509 2510 2511 2512 2513
    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;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return NULL;
}

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

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

L
liuyao 已提交
2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
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;
}

S
shenglian zhou 已提交
2729 2730
SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                     SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
2731 2732 2733
  SIntervalPhysiNode*          pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode;
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
2734 2735 2736
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
2737

2738
  pOperator->pTaskInfo = pTaskInfo;
2739 2740
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;

S
shenglian zhou 已提交
2741 2742 2743 2744 2745 2746 2747 2748
  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 已提交
2749 2750
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
2751
      .minTs = INT64_MAX,
5
54liuyao 已提交
2752
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
Liu Jicong 已提交
2753 2754
      .deleteMarkSaved = 0,
      .calTriggerSaved = 0,
L
liuyao 已提交
2755
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
2756 2757
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
S
shenglian zhou 已提交
2758
  };
5
54liuyao 已提交
2759
  ASSERTS(pInfo->twAggSup.calTrigger != STREAM_TRIGGER_MAX_DELAY, "trigger type should not be max delay");
5
54liuyao 已提交
2760 2761
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
2762
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
2763 2764 2765
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
2766
    int32_t    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
2767 2768 2769 2770 2771
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

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

L
liuyao 已提交
2777 2778
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
2779

2780
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
Liu Jicong 已提交
2781
  int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
2782
                            pInfo->pState, &pTaskInfo->storageAPI.functionStore);
2783 2784 2785 2786
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
2787
  initStreamFunciton(pOperator->exprSupp.pCtx, pOperator->exprSupp.numOfExprs);
5
54liuyao 已提交
2788
  initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
2789
  initResultRowInfo(&pInfo->binfo.resultRowInfo);
2790

L
liuyao 已提交
2791
  pInfo->numOfChild = numOfChild;
5
54liuyao 已提交
2792

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

5
54liuyao 已提交
2795 2796 2797 2798
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL) {
    pInfo->isFinal = true;
    pOperator->name = "StreamFinalIntervalOperator";
  } else {
5
54liuyao 已提交
2799
    // semi interval operator does not catch result
5
54liuyao 已提交
2800 2801 2802 2803
    pInfo->isFinal = false;
    pOperator->name = "StreamSemiIntervalOperator";
  }

5
54liuyao 已提交
2804
  if (!IS_FINAL_OP(pInfo) || numOfChild == 0) {
5
54liuyao 已提交
2805 2806
    pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
  }
2807

5
54liuyao 已提交
2808 2809 2810 2811
  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 已提交
2812
  pInfo->pFinalPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK);
2813
  pInfo->pPullDataRes = createSpecialDataBlock(STREAM_RETRIEVE);
5
54liuyao 已提交
2814
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
2815
  pInfo->ignoreExpiredDataSaved = false;
2816
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
2817
  pInfo->delIndex = 0;
H
Haojun Liao 已提交
2818
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
2819 2820
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
2821
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
2822 2823
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
2824
  int32_t funResSize= getMaxFunResSize(&pOperator->exprSupp, numOfCols);
2825
  pInfo->pState->pFileState = pAPI->stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
dengyihao's avatar
dengyihao 已提交
2826
                                                  compareTs, pInfo->pState, pInfo->twAggSup.deleteMark);
L
liuyao 已提交
2827
  pInfo->dataVersion = 0;
2828
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
2829
  pInfo->recvGetAll = false;
5
54liuyao 已提交
2830

5
54liuyao 已提交
2831
  pOperator->operatorType = pPhyNode->type;
5
54liuyao 已提交
2832 2833 2834 2835
  pOperator->blocking = true;
  pOperator->status = OP_NOT_OPENED;
  pOperator->info = pInfo;

L
Liu Jicong 已提交
2836 2837
  pOperator->fpSet = createOperatorFpSet(NULL, doStreamFinalIntervalAgg, NULL, destroyStreamFinalIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
2838
  if (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL) {
L
liuyao 已提交
2839
    initIntervalDownStream(downstream, pPhyNode->type, pInfo);
2840
  }
5
54liuyao 已提交
2841 2842 2843 2844 2845 2846 2847 2848
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
2849
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5
54liuyao 已提交
2850 2851 2852
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
5
54liuyao 已提交
2853
}
5
54liuyao 已提交
2854 2855

void destroyStreamAggSupporter(SStreamAggSupporter* pSup) {
5
54liuyao 已提交
2856
  tSimpleHashCleanup(pSup->pResultRows);
5
54liuyao 已提交
2857 2858
  destroyDiskbasedBuf(pSup->pResultBuf);
  blockDataDestroy(pSup->pScanBlock);
5
54liuyao 已提交
2859 2860
  taosMemoryFreeClear(pSup->pState);
  taosMemoryFreeClear(pSup->pDummyCtx);
5
54liuyao 已提交
2861 2862
}

2863
void destroyStreamSessionAggOperatorInfo(void* param) {
5
54liuyao 已提交
2864
  SStreamSessionAggOperatorInfo* pInfo = (SStreamSessionAggOperatorInfo*)param;
2865
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
2866
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
2867

2868 2869 2870
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
2871
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
2872
      destroyOperator(pChild);
2873
    }
5
54liuyao 已提交
2874
    taosArrayDestroy(pInfo->pChildren);
2875
  }
5
54liuyao 已提交
2876 2877 2878 2879
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
  blockDataDestroy(pInfo->pWinBlock);
  blockDataDestroy(pInfo->pUpdateRes);
5
54liuyao 已提交
2880
  tSimpleHashCleanup(pInfo->pStDeleted);
2881

D
dapan1121 已提交
2882
  taosMemoryFreeClear(param);
5
54liuyao 已提交
2883 2884
}

2885
int32_t initBasicInfoEx(SOptrBasicInfo* pBasicInfo, SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfCols,
2886
                        SSDataBlock* pResultBlock, SFunctionStateStore* pStore) {
H
Haojun Liao 已提交
2887
  initBasicInfo(pBasicInfo, pResultBlock);
2888
  int32_t code = initExprSupp(pSup, pExprInfo, numOfCols, pStore);
2889 2890 2891
  if (code != TSDB_CODE_SUCCESS) {
    return code;
  }
2892

H
Haojun Liao 已提交
2893
  initStreamFunciton(pSup->pCtx, pSup->numOfExprs);
5
54liuyao 已提交
2894
  for (int32_t i = 0; i < numOfCols; ++i) {
2895
    pSup->pCtx[i].saveHandle.pBuf = NULL;
5
54liuyao 已提交
2896
  }
2897

2898
  ASSERT(numOfCols > 0);
5
54liuyao 已提交
2899 2900 2901 2902 2903 2904
  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;
2905 2906
    pDummy[i].isNotNullFunc = pCtx[i].isNotNullFunc;
    pDummy[i].isPseudoFunc = pCtx[i].isPseudoFunc;
5
54liuyao 已提交
2907 2908
  }
}
5
54liuyao 已提交
2909

5
54liuyao 已提交
2910 2911
void initDownStream(SOperatorInfo* downstream, SStreamAggSupporter* pAggSup, uint16_t type, int32_t tsColIndex,
                    STimeWindowAggSupp* pTwSup) {
2912 2913 2914 2915 2916 2917
  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 已提交
2918
    initDownStream(downstream->pDownstream[0], pAggSup, type, tsColIndex, pTwSup);
2919 2920
    return;
  }
2921
  SStreamScanInfo* pScanInfo = downstream->info;
5
54liuyao 已提交
2922
  pScanInfo->windowSup = (SWindowSupporter){.pStreamAggSup = pAggSup, .gap = pAggSup->gap, .parentType = type};
L
fix bug  
liuyao 已提交
2923
  pScanInfo->pState = pAggSup->pState;
J
jiajingbin 已提交
2924
  if (!pScanInfo->pUpdateInfo) {
2925
    pScanInfo->pUpdateInfo = pAggSup->stateStore.updateInfoInit(60000, TSDB_TIME_PRECISION_MILLI, pTwSup->waterMark);
5
54liuyao 已提交
2926
  }
5
54liuyao 已提交
2927
  pScanInfo->twAggSup = *pTwSup;
5
54liuyao 已提交
2928 2929
}

5
54liuyao 已提交
2930
int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, int64_t gap,
H
Haojun Liao 已提交
2931
                               SStreamState* pState, int32_t keySize, int16_t keyType, SStateStore* pStore) {
5
54liuyao 已提交
2932 2933 2934 2935 2936 2937 2938 2939
  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 已提交
2940
  }
H
Haojun Liao 已提交
2941

2942 2943
  pSup->stateStore = *pStore;

5
54liuyao 已提交
2944 2945 2946
  initDummyFunction(pSup->pDummyCtx, pCtx, numOfOutput);
  pSup->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pSup->pState) = *pState;
2947
  pSup->stateStore.streamStateSetNumber(pSup->pState, -1);
2948

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

5
54liuyao 已提交
2952 2953 2954
  int32_t pageSize = 4096;
  while (pageSize < pSup->resultRowSize * 4) {
    pageSize <<= 1u;
5
54liuyao 已提交
2955
  }
5
54liuyao 已提交
2956 2957 2958 2959
  // at least four pages need to be in buffer
  int32_t bufSize = 4096 * 256;
  if (bufSize <= pageSize) {
    bufSize = pageSize * 4;
5
54liuyao 已提交
2960
  }
2961

5
54liuyao 已提交
2962
  if (!osTempSpaceAvailable()) {
2963 2964
    terrno = TSDB_CODE_NO_DISKSPACE;
    qError("Init stream agg supporter failed since %s, tempDir:%s", terrstr(), tsTempDir);
5
54liuyao 已提交
2965
    return terrno;
5
54liuyao 已提交
2966
  }
H
Haojun Liao 已提交
2967

5
54liuyao 已提交
2968 2969 2970
  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 已提交
2971 2972
  }

5
54liuyao 已提交
2973
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
2974
}
5
54liuyao 已提交
2975 2976

bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap) {
5
54liuyao 已提交
2977
  if (ts + gap >= pWin->skey && ts - gap <= pWin->ekey) {
5
54liuyao 已提交
2978 2979 2980 2981 2982
    return true;
  }
  return false;
}

5
54liuyao 已提交
2983 2984
bool isInWindow(SResultWindowInfo* pWinInfo, TSKEY ts, int64_t gap) {
  return isInTimeWindow(&pWinInfo->sessionWin.win, ts, gap);
5
54liuyao 已提交
2985 2986
}

5
54liuyao 已提交
2987 2988 2989 2990 2991
void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SSessionKey* pKey) {
  pKey->win.skey = startTs;
  pKey->win.ekey = endTs;
  pKey->groupId = groupId;
2992
  int32_t code = pAggSup->stateStore.streamStateSessionGetKeyByRange(pAggSup->pState, pKey, pKey);
5
54liuyao 已提交
2993 2994
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_KEY_INVALID(pKey);
2995 2996 2997
  }
}

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

5
54liuyao 已提交
3000 3001 3002
void setSessionOutputBuf(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId,
                         SResultWindowInfo* pCurWin) {
  pCurWin->sessionWin.groupId = groupId;
3003 3004
  pCurWin->sessionWin.win.skey = startTs;
  pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3005
  int32_t size = pAggSup->resultRowSize;
3006 3007
  int32_t code = pAggSup->stateStore.streamStateSessionAddIfNotExist(pAggSup->pState, &pCurWin->sessionWin,
                                                                     pAggSup->gap, &pCurWin->pOutputBuf, &size);
5
54liuyao 已提交
3008 3009 3010 3011 3012
  if (code == TSDB_CODE_SUCCESS) {
    pCurWin->isOutput = true;
  } else {
    pCurWin->sessionWin.win.skey = startTs;
    pCurWin->sessionWin.win.ekey = endTs;
5
54liuyao 已提交
3013
  }
5
54liuyao 已提交
3014
}
5
54liuyao 已提交
3015

5
54liuyao 已提交
3016 3017
int32_t getSessionWinBuf(SStreamAggSupporter* pAggSup, SStreamStateCur* pCur, SResultWindowInfo* pWinInfo) {
  int32_t size = 0;
3018
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pWinInfo->sessionWin, &pWinInfo->pOutputBuf, &size);
5
54liuyao 已提交
3019 3020
  if (code != TSDB_CODE_SUCCESS) {
    return code;
5
54liuyao 已提交
3021
  }
3022 3023

  pAggSup->stateStore.streamStateCurNext(pAggSup->pState, pCur);
5
54liuyao 已提交
3024 3025 3026 3027 3028
  return TSDB_CODE_SUCCESS;
}
void saveDeleteInfo(SArray* pWins, SSessionKey key) {
  // key.win.ekey = key.win.skey;
  taosArrayPush(pWins, &key);
5
54liuyao 已提交
3029 3030
}

5
54liuyao 已提交
3031 3032 3033 3034
void saveDeleteRes(SSHashObj* pStDelete, SSessionKey key) {
  key.win.ekey = key.win.skey;
  tSimpleHashPut(pStDelete, &key, sizeof(SSessionKey), NULL, 0);
}
3035

5
54liuyao 已提交
3036 3037 3038 3039 3040
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 已提交
3041

5
54liuyao 已提交
3042 3043 3044 3045 3046
static void getSessionHashKey(const SSessionKey* pKey, SSessionKey* pHashKey) {
  *pHashKey = *pKey;
  pHashKey->win.ekey = pKey->win.skey;
}

5
54liuyao 已提交
3047 3048 3049
static void removeSessionResults(SSHashObj* pHashMap, SArray* pWins) {
  if (tSimpleHashGetSize(pHashMap) == 0) {
    return;
5
54liuyao 已提交
3050
  }
5
54liuyao 已提交
3051 3052 3053 3054
  int32_t size = taosArrayGetSize(pWins);
  for (int32_t i = 0; i < size; i++) {
    SSessionKey* pWin = taosArrayGet(pWins, i);
    if (!pWin) continue;
5
54liuyao 已提交
3055 3056
    SSessionKey key = {0};
    getSessionHashKey(pWin, &key);
5
54liuyao 已提交
3057
    tSimpleHashRemove(pHashMap, &key, sizeof(SSessionKey));
5
54liuyao 已提交
3058 3059 3060
  }
}

dengyihao's avatar
dengyihao 已提交
3061
int32_t updateSessionWindowInfo(SResultWindowInfo* pWinInfo, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t groupId,
5
54liuyao 已提交
3062 3063
                                int32_t rows, int32_t start, int64_t gap, SSHashObj* pResultRows, SSHashObj* pStUpdated,
                                SSHashObj* pStDeleted) {
5
54liuyao 已提交
3064
  for (int32_t i = start; i < rows; ++i) {
3065
    if (!isInWindow(pWinInfo, pStartTs[i], gap) && (!pEndTs || !isInWindow(pWinInfo, pEndTs[i], gap))) {
5
54liuyao 已提交
3066 3067
      return i - start;
    }
5
54liuyao 已提交
3068
    if (pWinInfo->sessionWin.win.skey > pStartTs[i]) {
5
54liuyao 已提交
3069
      if (pStDeleted && pWinInfo->isOutput) {
5
54liuyao 已提交
3070
        saveDeleteRes(pStDeleted, pWinInfo->sessionWin);
5
54liuyao 已提交
3071
      }
5
54liuyao 已提交
3072 3073
      removeSessionResult(pStUpdated, pResultRows, pWinInfo->sessionWin);
      pWinInfo->sessionWin.win.skey = pStartTs[i];
5
54liuyao 已提交
3074
    }
5
54liuyao 已提交
3075
    pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pStartTs[i]);
5
54liuyao 已提交
3076
    if (pEndTs) {
5
54liuyao 已提交
3077
      pWinInfo->sessionWin.win.ekey = TMAX(pWinInfo->sessionWin.win.ekey, pEndTs[i]);
5
54liuyao 已提交
3078 3079 3080 3081 3082
    }
  }
  return rows - start;
}

5
54liuyao 已提交
3083 3084
static int32_t initSessionOutputBuf(SResultWindowInfo* pWinInfo, SResultRow** pResult, SqlFunctionCtx* pCtx,
                                    int32_t numOfOutput, int32_t* rowEntryInfoOffset) {
3085
  ASSERT(pWinInfo->sessionWin.win.skey <= pWinInfo->sessionWin.win.ekey);
5
54liuyao 已提交
3086
  *pResult = (SResultRow*)pWinInfo->pOutputBuf;
5
54liuyao 已提交
3087
  // set time window for current result
5
54liuyao 已提交
3088
  (*pResult)->win = pWinInfo->sessionWin.win;
3089
  setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset);
5
54liuyao 已提交
3090 3091 3092
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3093 3094
static int32_t doOneWindowAggImpl(SColumnInfoData* pTimeWindowData, SResultWindowInfo* pCurWin, SResultRow** pResult,
                                  int32_t startIndex, int32_t winRows, int32_t rows, int32_t numOutput,
L
liuyao 已提交
3095
                                  SOperatorInfo* pOperator, int64_t winDelta) {
3096
  SExprSupp*     pSup = &pOperator->exprSupp;
3097
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3098
  int32_t        code = initSessionOutputBuf(pCurWin, pResult, pSup->pCtx, numOutput, pSup->rowEntryInfoOffset);
5
54liuyao 已提交
3099
  if (code != TSDB_CODE_SUCCESS || (*pResult) == NULL) {
S
Shengliang Guan 已提交
3100
    return TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
3101
  }
L
liuyao 已提交
3102
  updateTimeWindowInfo(pTimeWindowData, &pCurWin->sessionWin.win, winDelta);
H
Haojun Liao 已提交
3103
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, pTimeWindowData, startIndex, winRows, rows, numOutput);
5
54liuyao 已提交
3104 3105 3106
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3107
static bool doDeleteSessionWindow(SStreamAggSupporter* pAggSup, SSessionKey* pKey) {
3108
  pAggSup->stateStore.streamStateSessionDel(pAggSup->pState, pKey);
5
54liuyao 已提交
3109 3110 3111
  SSessionKey hashKey = {0};
  getSessionHashKey(pKey, &hashKey);
  tSimpleHashRemove(pAggSup->pResultRows, &hashKey, sizeof(SSessionKey));
5
54liuyao 已提交
3112 3113 3114 3115 3116 3117 3118 3119 3120 3121
  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 已提交
3122 3123
}

5
54liuyao 已提交
3124 3125
SStreamStateCur* getNextSessionWinInfo(SStreamAggSupporter* pAggSup, SSHashObj* pStUpdated, SResultWindowInfo* pCurWin,
                                       SResultWindowInfo* pNextWin) {
3126
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->sessionWin);
5
54liuyao 已提交
3127 3128 3129 3130
  pNextWin->isOutput = true;
  setSessionWinOutputInfo(pStUpdated, pNextWin);
  int32_t size = 0;
  pNextWin->sessionWin = pCurWin->sessionWin;
3131
  int32_t code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->sessionWin, &pNextWin->pOutputBuf, &size);
5
54liuyao 已提交
3132
  if (code != TSDB_CODE_SUCCESS) {
dengyihao's avatar
dengyihao 已提交
3133
    taosMemoryFreeClear(pNextWin->pOutputBuf);
5
54liuyao 已提交
3134 3135 3136
    SET_SESSION_WIN_INVALID(*pNextWin);
  }
  return pCur;
5
54liuyao 已提交
3137 3138
}

5
54liuyao 已提交
3139 3140 3141 3142
static void compactSessionWindow(SOperatorInfo* pOperator, SResultWindowInfo* pCurWin, SSHashObj* pStUpdated,
                                 SSHashObj* pStDeleted) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3143 3144
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3145 3146 3147 3148 3149
  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 已提交
3150
  // Just look for the window behind StartIndex
5
54liuyao 已提交
3151 3152 3153 3154
  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 已提交
3155
      taosMemoryFree(winInfo.pOutputBuf);
3156
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3157
      break;
5
54liuyao 已提交
3158
    }
5
54liuyao 已提交
3159 3160 3161
    SResultRow* pWinResult = NULL;
    initSessionOutputBuf(&winInfo, &pWinResult, pAggSup->pDummyCtx, numOfOutput, pSup->rowEntryInfoOffset);
    pCurWin->sessionWin.win.ekey = TMAX(pCurWin->sessionWin.win.ekey, winInfo.sessionWin.win.ekey);
L
liuyao 已提交
3162 3163 3164 3165 3166
    int64_t winDelta = 0;
    if (IS_FINAL_OP(pInfo)) {
      winDelta = pAggSup->gap;
    }
    updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pCurWin->sessionWin.win, winDelta);
5
54liuyao 已提交
3167 3168 3169 3170 3171 3172 3173
    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);
3174
    pAPI->stateStore.streamStateFreeCur(pCur);
dengyihao's avatar
dengyihao 已提交
3175
    taosMemoryFree(winInfo.pOutputBuf);
5
54liuyao 已提交
3176 3177 3178
  }
}

5
54liuyao 已提交
3179
int32_t saveSessionOutputBuf(SStreamAggSupporter* pAggSup, SResultWindowInfo* pWinInfo) {
3180
  saveSessionDiscBuf(pAggSup->pState, &pWinInfo->sessionWin, pWinInfo->pOutputBuf, pAggSup->resultRowSize, &pAggSup->stateStore);
5
54liuyao 已提交
3181
  return TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3182 3183
}

5
54liuyao 已提交
3184
static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pStUpdated,
3185
                                   SSHashObj* pStDeleted, bool hasEndTs, bool addGap) {
X
Xiaoyu Wang 已提交
3186
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
5
54liuyao 已提交
3187
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
3188
  int32_t                        numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
3189
  uint64_t                       groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
3190
  int64_t                        code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
3191 3192 3193
  SResultRow*                    pResult = NULL;
  int32_t                        rows = pSDataBlock->info.rows;
  int32_t                        winRows = 0;
X
Xiaoyu Wang 已提交
3194

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

5
54liuyao 已提交
3197
  SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3198
  TSKEY*           startTsCols = (int64_t*)pStartTsCol->pData;
5
54liuyao 已提交
3199 3200 3201
  SColumnInfoData* pEndTsCol = NULL;
  if (hasEndTs) {
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->endTsIndex);
5
54liuyao 已提交
3202
  } else {
5
54liuyao 已提交
3203
    pEndTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
5
54liuyao 已提交
3204
  }
X
Xiaoyu Wang 已提交
3205

5
54liuyao 已提交
3206
  TSKEY*               endTsCols = (int64_t*)pEndTsCol->pData;
5
54liuyao 已提交
3207
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3208
  for (int32_t i = 0; i < rows;) {
5
54liuyao 已提交
3209
    if (pInfo->ignoreExpiredData && isOverdue(endTsCols[i], &pInfo->twAggSup)) {
5
54liuyao 已提交
3210 3211 3212
      i++;
      continue;
    }
5
54liuyao 已提交
3213 3214 3215 3216 3217
    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 已提交
3218 3219
    // coverity scan error
    if (!winInfo.pOutputBuf) {
S
Shengliang Guan 已提交
3220
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3221
    }
L
Liu Jicong 已提交
3222

L
liuyao 已提交
3223
    int64_t winDelta = 0;
3224
    if (addGap) {
L
liuyao 已提交
3225 3226
      winDelta = pAggSup->gap;
    }
5
54liuyao 已提交
3227
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &winInfo, &pResult, i, winRows, rows, numOfOutput,
L
liuyao 已提交
3228
                              pOperator, winDelta);
5
54liuyao 已提交
3229
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
3230
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3231
    }
5
54liuyao 已提交
3232 3233
    compactSessionWindow(pOperator, &winInfo, pStUpdated, pStDeleted);
    saveSessionOutputBuf(pAggSup, &winInfo);
5
54liuyao 已提交
3234 3235

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE && pStUpdated) {
5
54liuyao 已提交
3236
      code = saveResult(winInfo, pStUpdated);
5
54liuyao 已提交
3237
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
3238
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3239
      }
5
54liuyao 已提交
3240
    }
5
54liuyao 已提交
3241
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
3242 3243
      SSessionKey key = {0};
      getSessionHashKey(&winInfo.sessionWin, &key);
5
54liuyao 已提交
3244 3245 3246
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo));
    }

5
54liuyao 已提交
3247 3248 3249 3250
    i += winRows;
  }
}

5
54liuyao 已提交
3251
static void doDeleteTimeWindows(SStreamAggSupporter* pAggSup, SSDataBlock* pBlock, SArray* result) {
5
54liuyao 已提交
3252
  SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3253
  TSKEY*           startDatas = (TSKEY*)pStartTsCol->pData;
5
54liuyao 已提交
3254
  SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3255
  TSKEY*           endDatas = (TSKEY*)pEndTsCol->pData;
3256
  SColumnInfoData* pGroupCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3257
  uint64_t*        gpDatas = (uint64_t*)pGroupCol->pData;
5
54liuyao 已提交
3258
  for (int32_t i = 0; i < pBlock->info.rows; i++) {
5
54liuyao 已提交
3259 3260 3261 3262
    while (1) {
      SSessionKey curWin = {0};
      getCurSessionWindow(pAggSup, startDatas[i], endDatas[i], gpDatas[i], &curWin);
      if (IS_INVALID_SESSION_WIN_KEY(curWin)) {
3263 3264
        break;
      }
5
54liuyao 已提交
3265 3266 3267 3268
      doDeleteSessionWindow(pAggSup, &curWin);
      if (result) {
        saveDeleteInfo(result, curWin);
      }
3269
    }
5
54liuyao 已提交
3270 3271 3272
  }
}

5
54liuyao 已提交
3273 3274 3275 3276 3277 3278 3279 3280
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 已提交
3281 3282
  }

5
54liuyao 已提交
3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295
  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) {
3296
    void* key = tSimpleHashGetKey(pIte, NULL);
5
54liuyao 已提交
3297 3298 3299 3300 3301 3302
    taosArrayPush(pUpdated, key);
  }
  taosArraySort(pUpdated, sessionKeyCompareAsc);
  return TSDB_CODE_SUCCESS;
}

3303
void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlock* pBlock, void** Ite) {
3304 3305
  SStorageAPI* pAPI = &pOp->pTaskInfo->storageAPI;

5
54liuyao 已提交
3306 3307 3308 3309
  blockDataCleanup(pBlock);
  int32_t size = tSimpleHashGetSize(pStDeleted);
  if (size == 0) {
    return;
3310 3311
  }
  blockDataEnsureCapacity(pBlock, size);
5
54liuyao 已提交
3312 3313 3314 3315 3316
  int32_t iter = 0;
  while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) {
    if (pBlock->info.rows + 1 > pBlock->info.capacity) {
      break;
    }
3317
    SSessionKey*     res = tSimpleHashGetKey(*Ite, NULL);
3318
    SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX);
3319
    colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3320
    SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX);
3321
    colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false);
3322
    SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX);
3323
    colDataSetNULL(pUidCol, pBlock->info.rows);
5
54liuyao 已提交
3324
    SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX);
3325
    colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false);
3326
    SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX);
3327
    colDataSetNULL(pCalStCol, pBlock->info.rows);
3328
    SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX);
3329
    colDataSetNULL(pCalEdCol, pBlock->info.rows);
3330 3331

    SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX);
3332 3333

    void* tbname = NULL;
3334
    pAPI->stateStore.streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, res->groupId, &tbname);
3335
    if (tbname == NULL) {
3336
      colDataSetNULL(pTableCol, pBlock->info.rows);
3337 3338 3339
    } else {
      char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN];
      STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName));
3340
      colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false);
3341
      pAPI->stateStore.streamStateFreeVal(tbname);
3342
    }
5
54liuyao 已提交
3343 3344 3345
    pBlock->info.rows += 1;
  }
  if ((*Ite) == NULL) {
5
54liuyao 已提交
3346
    tSimpleHashClear(pStDeleted);
5
54liuyao 已提交
3347 3348 3349
  }
}

5
54liuyao 已提交
3350 3351 3352
static void rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pStUpdated) {
  SExprSupp*                     pSup = &pOperator->exprSupp;
  SExecTaskInfo*                 pTaskInfo = pOperator->pTaskInfo;
3353 3354
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3355 3356 3357 3358
  int32_t                        size = taosArrayGetSize(pWinArray);
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
  int32_t                        numOfOutput = pSup->numOfExprs;
L
liuyao 已提交
3359
  int32_t                        numOfChild = taosArrayGetSize(pInfo->pChildren);
3360

3361
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3362 3363 3364
    SSessionKey*      pWinKey = taosArrayGet(pWinArray, i);
    int32_t           num = 0;
    SResultWindowInfo parentWin = {0};
L
liuyao 已提交
3365
    for (int32_t j = 0; j < numOfChild; j++) {
X
Xiaoyu Wang 已提交
3366
      SOperatorInfo*                 pChild = taosArrayGetP(pInfo->pChildren, j);
3367
      SStreamSessionAggOperatorInfo* pChInfo = pChild->info;
5
54liuyao 已提交
3368
      SStreamAggSupporter*           pChAggSup = &pChInfo->streamAggSup;
5
54liuyao 已提交
3369 3370
      SSessionKey                    chWinKey = {0};
      getSessionHashKey(pWinKey, &chWinKey);
3371
      SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyCurrentNext(pChAggSup->pState, &chWinKey);
3372 3373
      SResultRow*      pResult = NULL;
      SResultRow*      pChResult = NULL;
5
54liuyao 已提交
3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385
      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;
            }
3386
          }
5
54liuyao 已提交
3387
          num++;
L
liuyao 已提交
3388
          updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &parentWin.sessionWin.win, pAggSup->gap); 
5
54liuyao 已提交
3389 3390 3391 3392 3393 3394
          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 已提交
3395
          break;
3396 3397
        }
      }
3398
      pAPI->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3399 3400 3401
    }
    if (num > 0) {
      saveSessionOutputBuf(pAggSup, &parentWin);
3402 3403 3404 3405
    }
  }
}

5
54liuyao 已提交
3406 3407 3408 3409 3410 3411 3412 3413 3414 3415
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 已提交
3416 3417
        }
      }
3418
      SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL);
3419
      tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter);
5
54liuyao 已提交
3420 3421 3422 3423 3424
    }
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3425
static void closeChildSessionWindow(SArray* pChildren, TSKEY maxTs) {
5
54liuyao 已提交
3426 3427 3428 3429 3430
  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 已提交
3431
    closeSessionWindow(pChInfo->streamAggSup.pResultRows, &pChInfo->twAggSup, NULL);
5
54liuyao 已提交
3432 3433 3434
  }
}

5
54liuyao 已提交
3435 3436 3437 3438
int32_t getAllSessionWindow(SSHashObj* pHashMap, SSHashObj* pStUpdated) {
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) {
3439
    SResultWindowInfo* pWinInfo = pIte;
5
54liuyao 已提交
3440
    saveResult(*pWinInfo, pStUpdated);
5
54liuyao 已提交
3441 3442 3443 3444
  }
  return TSDB_CODE_SUCCESS;
}

5
54liuyao 已提交
3445
static void copyDeleteWindowInfo(SArray* pResWins, SSHashObj* pStDeleted) {
5
54liuyao 已提交
3446 3447
  int32_t size = taosArrayGetSize(pResWins);
  for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3448 3449
    SSessionKey* pWinKey = taosArrayGet(pResWins, i);
    if (!pWinKey) continue;
5
54liuyao 已提交
3450 3451
    SSessionKey winInfo = {0};
    getSessionHashKey(pWinKey, &winInfo);
5
54liuyao 已提交
3452
    tSimpleHashPut(pStDeleted, &winInfo, sizeof(SSessionKey), NULL, 0);
3453 3454 3455
  }
}

H
Haojun Liao 已提交
3456
// the allocated memory comes from outer function.
5
54liuyao 已提交
3457 3458 3459
void initGroupResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
  pGroupResInfo->pRows = pArrayList;
  pGroupResInfo->index = 0;
H
Haojun Liao 已提交
3460
  pGroupResInfo->pBuf = NULL;
3461 3462
}

3463
void doBuildSessionResult(SOperatorInfo* pOperator, void* pState, SGroupResInfo* pGroupResInfo,
5
54liuyao 已提交
3464 3465 3466 3467 3468 3469 3470
                          SSDataBlock* pBlock) {
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  // set output datablock version
  pBlock->info.version = pTaskInfo->version;

  blockDataCleanup(pBlock);
  if (!hasRemainResults(pGroupResInfo)) {
H
Haojun Liao 已提交
3471
    cleanupGroupResInfo(pGroupResInfo);
3472 3473 3474
    return;
  }

5
54liuyao 已提交
3475
  // clear the existed group id
H
Haojun Liao 已提交
3476
  pBlock->info.id.groupId = 0;
3477
  buildSessionResultDataBlock(pOperator, pState, pBlock, &pOperator->exprSupp, pGroupResInfo);
5
54liuyao 已提交
3478 3479
}

5
54liuyao 已提交
3480
static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) {
5
54liuyao 已提交
3481
  SExprSupp*                     pSup = &pOperator->exprSupp;
5
54liuyao 已提交
3482
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
3483
  SOptrBasicInfo*                pBInfo = &pInfo->binfo;
5
54liuyao 已提交
3484
  SStreamAggSupporter*           pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3485 3486 3487
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
  } else if (pOperator->status == OP_RES_TO_RETURN) {
3488
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3489
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3490
      printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3491 3492
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3493 3494 3495 3496
    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 已提交
3497
    }
5
54liuyao 已提交
3498

H
Haojun Liao 已提交
3499
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
3500
    return NULL;
5
54liuyao 已提交
3501 3502 3503
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3504 3505 3506 3507
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3508
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3509 3510
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3511 3512 3513 3514 3515
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
3516
    printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "final session recv" : "single session recv");
3517

5
54liuyao 已提交
3518 3519 3520
    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 已提交
3521
      // gap must be 0
5
54liuyao 已提交
3522
      doDeleteTimeWindows(pAggSup, pBlock, pWins);
5
54liuyao 已提交
3523
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3524 3525 3526 3527 3528
      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 已提交
3529
        doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL);
5
54liuyao 已提交
3530
        rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated);
5
54liuyao 已提交
3531 3532 3533 3534
      }
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
      taosArrayDestroy(pWins);
      continue;
3535
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3536
      getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3537
      continue;
5
54liuyao 已提交
3538 3539 3540 3541
    } 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 已提交
3542
    }
5
54liuyao 已提交
3543

5
54liuyao 已提交
3544 3545 3546 3547
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
3548
    // the pDataBlock are always the same one, no need to call this again
3549
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3550
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo), true);
5
54liuyao 已提交
3551 3552 3553 3554 3555
    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++) {
3556 3557
        SOperatorInfo* pChildOp =
            createStreamFinalSessionAggOperatorInfo(NULL, pInfo->pPhyNode, pOperator->pTaskInfo, 0);
5
54liuyao 已提交
3558
        if (!pChildOp) {
S
Shengliang Guan 已提交
3559
          T_LONG_JMP(pOperator->pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
3560 3561 3562
        }
        taosArrayPush(pInfo->pChildren, &pChildOp);
      }
3563
      SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, chIndex);
3564
      setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3565
      doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true, false);
3566
    }
5
54liuyao 已提交
3567 3568
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark);
5
54liuyao 已提交
3569 3570 3571
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
H
Haojun Liao 已提交
3572

5
54liuyao 已提交
3573
  closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated);
5
54liuyao 已提交
3574
  closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs);
5
54liuyao 已提交
3575 3576 3577 3578 3579 3580
  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 已提交
3581
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3582

3583 3584 3585 3586 3587 3588
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

3589
  doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
3590
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3591
    printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "final session" : "single session");
5
54liuyao 已提交
3592 3593
    return pInfo->pDelRes;
  }
5
54liuyao 已提交
3594 3595 3596 3597 3598 3599 3600

  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 已提交
3601
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3602
  return NULL;
5
54liuyao 已提交
3603 3604
}

5
54liuyao 已提交
3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621
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);
3622
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3623 3624
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
5
54liuyao 已提交
3625 3626
    }
  }
5
54liuyao 已提交
3627 3628 3629
  SExprSupp* pSup = &pOperator->exprSupp;

  SExprInfo*   pExprInfo = createExprInfo(pSessionNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
3630
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
3631
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
3632 3633 3634 3635 3636
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  code = initStreamAggSupporter(&pInfo->streamAggSup, pSup->pCtx, numOfCols, pSessionNode->gap,
H
Haojun Liao 已提交
3637
                                pTaskInfo->streamInfo.pState, 0, 0, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664
  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;
3665
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
3666 3667
  pInfo->pUpdated = NULL;
  pInfo->pStUpdated = NULL;
L
liuyao 已提交
3668
  pInfo->dataVersion = 0;
5
54liuyao 已提交
3669

H
Haojun Liao 已提交
3670 3671
  setOperatorInfo(pOperator, "StreamSessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true,
                  OP_NOT_OPENED, pInfo, pTaskInfo);
L
Liu Jicong 已提交
3672 3673
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionAgg, NULL, destroyStreamSessionAggOperatorInfo,
                                         optrDefaultBufFn, NULL);
H
Haojun Liao 已提交
3674

5
54liuyao 已提交
3675
  if (downstream) {
5
54liuyao 已提交
3676
    initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692
    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);
3693
  pInfo->streamAggSup.stateStore.streamStateSessionClear(pInfo->streamAggSup.pState);
5
54liuyao 已提交
3694 3695 3696 3697 3698 3699 3700
}

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

5
54liuyao 已提交
3703 3704
  if (pOperator->status == OP_EXEC_DONE) {
    return NULL;
3705
  }
L
Liu Jicong 已提交
3706

3707
  {
5
54liuyao 已提交
3708
    doBuildSessionResult(pOperator, pAggSup->pState, &pInfo->groupResInfo, pBInfo->pRes);
5
54liuyao 已提交
3709
    if (pBInfo->pRes->info.rows > 0) {
H
Haojun Liao 已提交
3710
      printDataBlock(pBInfo->pRes, "semi session");
5
54liuyao 已提交
3711 3712 3713
      return pBInfo->pRes;
    }

3714
    doBuildDeleteDataBlock(pOperator, pInfo->pStDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
3715
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
3716
      printDataBlock(pInfo->pDelRes, "semi session delete");
5
54liuyao 已提交
3717 3718
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
3719

3720
    if (pOperator->status == OP_RES_TO_RETURN) {
5
54liuyao 已提交
3721
      clearFunctionContext(&pOperator->exprSupp);
3722 3723
      // semi interval operator clear disk buffer
      clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3724
      setOperatorCompleted(pOperator);
3725 3726
      return NULL;
    }
5
54liuyao 已提交
3727 3728 3729
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
3730 3731 3732 3733
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pStUpdated) {
3734
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
3735 3736
    pInfo->pStUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
3737 3738 3739
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
3740
      clearSpecialDataBlock(pInfo->pUpdateRes);
3741
      pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
3742 3743
      break;
    }
H
Haojun Liao 已提交
3744
    printDataBlock(pBlock, "semi session recv");
5
54liuyao 已提交
3745

5
54liuyao 已提交
3746 3747
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
3748
      // gap must be 0
3749
      SArray* pWins = taosArrayInit(16, sizeof(SSessionKey));
5
54liuyao 已提交
3750
      doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins);
5
54liuyao 已提交
3751
      removeSessionResults(pInfo->pStUpdated, pWins);
5
54liuyao 已提交
3752
      copyDeleteWindowInfo(pWins, pInfo->pStDeleted);
3753
      taosArrayDestroy(pWins);
5
54liuyao 已提交
3754
      break;
5
54liuyao 已提交
3755
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
3756
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated);
5
54liuyao 已提交
3757
      continue;
5
54liuyao 已提交
3758 3759 3760 3761
    } 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 已提交
3762 3763
    }

5
54liuyao 已提交
3764 3765 3766 3767
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
5
54liuyao 已提交
3768
    // the pDataBlock are always the same one, no need to call this again
3769
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
3770
    doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false, false);
5
54liuyao 已提交
3771 3772 3773 3774
    maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
  }

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

5
54liuyao 已提交
3777 3778 3779 3780
  copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated);
  removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated);
  tSimpleHashCleanup(pInfo->pStUpdated);
  pInfo->pStUpdated = NULL;
5
54liuyao 已提交
3781

5
54liuyao 已提交
3782 3783
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
3784
  blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
3785

3786 3787 3788 3789 3790 3791
#if 0
  char* pBuf = streamStateSessionDump(pAggSup->pState);
  qDebug("===stream===semi session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

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

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

5
54liuyao 已提交
3804 3805 3806
  clearFunctionContext(&pOperator->exprSupp);
  // semi interval operator clear disk buffer
  clearStreamSessionOperator(pInfo);
H
Haojun Liao 已提交
3807
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
3808
  return NULL;
5
54liuyao 已提交
3809
}
3810

3811 3812
SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                       SExecTaskInfo* pTaskInfo, int32_t numOfChild) {
3813 3814
  int32_t        code = TSDB_CODE_OUT_OF_MEMORY;
  SOperatorInfo* pOperator = createStreamSessionAggOperatorInfo(downstream, pPhyNode, pTaskInfo);
3815 3816 3817
  if (pOperator == NULL) {
    goto _error;
  }
H
Haojun Liao 已提交
3818

3819
  SStorageAPI* pAPI = &pTaskInfo->storageAPI;
3820
  SStreamSessionAggOperatorInfo* pInfo = pOperator->info;
5
54liuyao 已提交
3821

H
Haojun Liao 已提交
3822
  pInfo->isFinal = (pPhyNode->type == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION);
L
Liu Jicong 已提交
3823
  char* name = (pInfo->isFinal) ? "StreamSessionFinalAggOperator" : "StreamSessionSemiAggOperator";
H
Haojun Liao 已提交
3824 3825

  if (pPhyNode->type != QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) {
H
Haojun Liao 已提交
3826
    pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR);
5
54liuyao 已提交
3827
    blockDataEnsureCapacity(pInfo->pUpdateRes, 128);
3828 3829
    pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamSessionSemiAgg, NULL,
                                           destroyStreamSessionAggOperatorInfo, optrDefaultBufFn, NULL);
5
54liuyao 已提交
3830
  }
3831

L
Liu Jicong 已提交
3832
  setOperatorInfo(pOperator, name, pPhyNode->type, false, OP_NOT_OPENED, pInfo, pTaskInfo);
H
Haojun Liao 已提交
3833

5
54liuyao 已提交
3834 3835 3836 3837
  pOperator->operatorType = pPhyNode->type;
  if (numOfChild > 0) {
    pInfo->pChildren = taosArrayInit(numOfChild, sizeof(void*));
    for (int32_t i = 0; i < numOfChild; i++) {
5
54liuyao 已提交
3838 3839
      SOperatorInfo* pChildOp = createStreamFinalSessionAggOperatorInfo(NULL, pPhyNode, pTaskInfo, 0);
      if (pChildOp == NULL) {
5
54liuyao 已提交
3840 3841
        goto _error;
      }
5
54liuyao 已提交
3842 3843
      SStreamSessionAggOperatorInfo* pChInfo = pChildOp->info;
      pChInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE;
3844
      pAPI->stateStore.streamStateSetNumber(pChInfo->streamAggSup.pState, i);
5
54liuyao 已提交
3845
      taosArrayPush(pInfo->pChildren, &pChildOp);
3846 3847
    }
  }
3848 3849 3850 3851 3852

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

3853 3854 3855 3856
  return pOperator;

_error:
  if (pInfo != NULL) {
3857
    destroyStreamSessionAggOperatorInfo(pInfo);
3858 3859 3860 3861 3862
  }
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
5
54liuyao 已提交
3863

3864
void destroyStreamStateOperatorInfo(void* param) {
X
Xiaoyu Wang 已提交
3865
  SStreamStateAggOperatorInfo* pInfo = (SStreamStateAggOperatorInfo*)param;
3866
  cleanupBasicInfo(&pInfo->binfo);
5
54liuyao 已提交
3867
  destroyStreamAggSupporter(&pInfo->streamAggSup);
5
54liuyao 已提交
3868 3869 3870 3871
  cleanupGroupResInfo(&pInfo->groupResInfo);
  if (pInfo->pChildren != NULL) {
    int32_t size = taosArrayGetSize(pInfo->pChildren);
    for (int32_t i = 0; i < size; i++) {
5
54liuyao 已提交
3872
      SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i);
3873
      destroyOperator(pChild);
5
54liuyao 已提交
3874
    }
5
54liuyao 已提交
3875
    taosArrayDestroy(pInfo->pChildren);
5
54liuyao 已提交
3876
  }
5
54liuyao 已提交
3877 3878
  colDataDestroy(&pInfo->twAggSup.timeWindowData);
  blockDataDestroy(pInfo->pDelRes);
5
54liuyao 已提交
3879
  tSimpleHashCleanup(pInfo->pSeDeleted);
D
dapan1121 已提交
3880
  taosMemoryFreeClear(param);
5
54liuyao 已提交
3881 3882 3883
}

bool isTsInWindow(SStateWindowInfo* pWin, TSKEY ts) {
5
54liuyao 已提交
3884
  if (pWin->winInfo.sessionWin.win.skey <= ts && ts <= pWin->winInfo.sessionWin.win.ekey) {
5
54liuyao 已提交
3885 3886 3887 3888 3889 3890
    return true;
  }
  return false;
}

bool isEqualStateKey(SStateWindowInfo* pWin, char* pKeyData) {
5
54liuyao 已提交
3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906
  return pKeyData && compareVal(pKeyData, pWin->pStateKey);
}

bool compareStateKey(void* data, void* key) {
  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 =
3907
      pAggSup->stateStore.streamStateStateAddIfNotExist(pAggSup->pState, &pCurWin->winInfo.sessionWin, pKeyData, pAggSup->stateKeySize,
5
54liuyao 已提交
3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922
                                    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;
  } else {
    if (IS_VAR_DATA_TYPE(pAggSup->stateKeyType)) {
      varDataCopy(pCurWin->pStateKey->pData, pKeyData);
    } else {
      memcpy(pCurWin->pStateKey->pData, pKeyData, pCurWin->pStateKey->bytes);
5
54liuyao 已提交
3923 3924 3925
    }
  }

5
54liuyao 已提交
3926 3927
  pNextWin->winInfo.sessionWin = pCurWin->winInfo.sessionWin;
  pNextWin->winInfo.pOutputBuf = NULL;
3928 3929
  SStreamStateCur* pCur = pAggSup->stateStore.streamStateSessionSeekKeyNext(pAggSup->pState, &pCurWin->winInfo.sessionWin);
  code = pAggSup->stateStore.streamStateSessionGetKVByCur(pCur, &pNextWin->winInfo.sessionWin, NULL, 0);
5
54liuyao 已提交
3930 3931
  if (code != TSDB_CODE_SUCCESS) {
    SET_SESSION_WIN_INVALID(pNextWin->winInfo);
5
54liuyao 已提交
3932
  }
3933
  pAggSup->stateStore.streamStateFreeCur(pCur);
5
54liuyao 已提交
3934 3935
}

5
54liuyao 已提交
3936
int32_t updateStateWindowInfo(SStateWindowInfo* pWinInfo, SStateWindowInfo* pNextWin, TSKEY* pTs, uint64_t groupId,
H
Haojun Liao 已提交
3937
                              SColumnInfoData* pKeyCol, int32_t rows, int32_t start, bool* allEqual,
5
54liuyao 已提交
3938
                              SSHashObj* pResultRows, SSHashObj* pSeUpdated, SSHashObj* pSeDeleted) {
5
54liuyao 已提交
3939 3940 3941 3942
  *allEqual = true;
  for (int32_t i = start; i < rows; ++i) {
    char* pKeyData = colDataGetData(pKeyCol, i);
    if (!isTsInWindow(pWinInfo, pTs[i])) {
X
Xiaoyu Wang 已提交
3943
      if (isEqualStateKey(pWinInfo, pKeyData)) {
5
54liuyao 已提交
3944
        if (IS_VALID_SESSION_WIN(pNextWin->winInfo)) {
5
54liuyao 已提交
3945
          // ts belongs to the next window
5
54liuyao 已提交
3946
          if (pTs[i] >= pNextWin->winInfo.sessionWin.win.skey) {
5
54liuyao 已提交
3947 3948 3949 3950 3951 3952 3953
            return i - start;
          }
        }
      } else {
        return i - start;
      }
    }
5
54liuyao 已提交
3954 3955

    if (pWinInfo->winInfo.sessionWin.win.skey > pTs[i]) {
H
Haojun Liao 已提交
3956
      if (pSeDeleted && pWinInfo->winInfo.isOutput) {
5
54liuyao 已提交
3957
        saveDeleteRes(pSeDeleted, pWinInfo->winInfo.sessionWin);
5
54liuyao 已提交
3958
      }
5
54liuyao 已提交
3959 3960
      removeSessionResult(pSeUpdated, pResultRows, pWinInfo->winInfo.sessionWin);
      pWinInfo->winInfo.sessionWin.win.skey = pTs[i];
5
54liuyao 已提交
3961
    }
5
54liuyao 已提交
3962
    pWinInfo->winInfo.sessionWin.win.ekey = TMAX(pWinInfo->winInfo.sessionWin.win.ekey, pTs[i]);
5
54liuyao 已提交
3963 3964 3965 3966 3967 3968 3969
    if (!isEqualStateKey(pWinInfo, pKeyData)) {
      *allEqual = false;
    }
  }
  return rows - start;
}

5
54liuyao 已提交
3970 3971
static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBlock, SSHashObj* pSeUpdated,
                                 SSHashObj* pStDeleted) {
3972 3973 3974
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
  SStorageAPI*   pAPI = &pOperator->pTaskInfo->storageAPI;

5
54liuyao 已提交
3975
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
3976
  int32_t                      numOfOutput = pOperator->exprSupp.numOfExprs;
H
Haojun Liao 已提交
3977
  uint64_t                     groupId = pSDataBlock->info.id.groupId;
X
Xiaoyu Wang 已提交
3978 3979 3980 3981
  int64_t                      code = TSDB_CODE_SUCCESS;
  TSKEY*                       tsCols = NULL;
  SResultRow*                  pResult = NULL;
  int32_t                      winRows = 0;
L
liuyao 已提交
3982 3983 3984

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

5
54liuyao 已提交
3985
  if (pSDataBlock->pDataBlock != NULL) {
X
Xiaoyu Wang 已提交
3986 3987
    SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex);
    tsCols = (int64_t*)pColDataInfo->pData;
5
54liuyao 已提交
3988
  } else {
X
Xiaoyu Wang 已提交
3989
    return;
5
54liuyao 已提交
3990
  }
L
Liu Jicong 已提交
3991

5
54liuyao 已提交
3992
  SStreamAggSupporter* pAggSup = &pInfo->streamAggSup;
5
54liuyao 已提交
3993 3994
  int32_t              rows = pSDataBlock->info.rows;
  blockDataEnsureCapacity(pAggSup->pScanBlock, rows);
L
Liu Jicong 已提交
3995
  SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId);
5
54liuyao 已提交
3996
  for (int32_t i = 0; i < rows; i += winRows) {
3997
    if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup) || colDataIsNull_s(pKeyColInfo, i)) {
5
54liuyao 已提交
3998 3999 4000
      i++;
      continue;
    }
5
54liuyao 已提交
4001 4002 4003 4004 4005 4006 4007 4008 4009
    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 已提交
4010
    if (!allEqual) {
4011
      uint64_t uid = 0;
5
54liuyao 已提交
4012 4013 4014 4015
      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);
4016
      releaseOutputBuf(pAggSup->pState, NULL, (SResultRow*)curWin.winInfo.pOutputBuf, &pAPI->stateStore);
5
54liuyao 已提交
4017 4018
      continue;
    }
5
54liuyao 已提交
4019
    code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
L
liuyao 已提交
4020
                              pOperator, 0);
5
54liuyao 已提交
4021
    if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
S
Shengliang Guan 已提交
4022
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4023
    }
5
54liuyao 已提交
4024 4025
    saveSessionOutputBuf(pAggSup, &curWin.winInfo);

5
54liuyao 已提交
4026
    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE) {
5
54liuyao 已提交
4027
      code = saveResult(curWin.winInfo, pSeUpdated);
5
54liuyao 已提交
4028
      if (code != TSDB_CODE_SUCCESS) {
S
Shengliang Guan 已提交
4029
        T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
5
54liuyao 已提交
4030 4031
      }
    }
4032 4033

    if (pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE) {
5
54liuyao 已提交
4034 4035
      SSessionKey key = {0};
      getSessionHashKey(&curWin.winInfo.sessionWin, &key);
4036 4037
      tSimpleHashPut(pAggSup->pResultRows, &key, sizeof(SSessionKey), &curWin.winInfo, sizeof(SResultWindowInfo));
    }
5
54liuyao 已提交
4038 4039 4040 4041 4042 4043 4044 4045
  }
}

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

4046
  SExprSupp*                   pSup = &pOperator->exprSupp;
5
54liuyao 已提交
4047
  SStreamStateAggOperatorInfo* pInfo = pOperator->info;
X
Xiaoyu Wang 已提交
4048
  SOptrBasicInfo*              pBInfo = &pInfo->binfo;
5
54liuyao 已提交
4049
  if (pOperator->status == OP_RES_TO_RETURN) {
4050
    doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4051
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4052
      printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4053 4054
      return pInfo->pDelRes;
    }
5
54liuyao 已提交
4055 4056 4057 4058 4059

    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 已提交
4060
    }
5
54liuyao 已提交
4061

H
Haojun Liao 已提交
4062
    setOperatorCompleted(pOperator);
5
54liuyao 已提交
4063
    return NULL;
5
54liuyao 已提交
4064 4065 4066
  }

  SOperatorInfo* downstream = pOperator->pDownstream[0];
5
54liuyao 已提交
4067 4068 4069 4070
  if (!pInfo->pUpdated) {
    pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey));
  }
  if (!pInfo->pSeUpdated) {
4071
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4072 4073
    pInfo->pSeUpdated = tSimpleHashInit(64, hashFn);
  }
5
54liuyao 已提交
4074 4075 4076 4077 4078
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
      break;
    }
5
54liuyao 已提交
4079
    printDataBlock(pBlock, "single state recv");
4080

5
54liuyao 已提交
4081 4082 4083 4084
    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 已提交
4085
      removeSessionResults(pInfo->pSeUpdated, pWins);
5
54liuyao 已提交
4086
      copyDeleteWindowInfo(pWins, pInfo->pSeDeleted);
4087 4088
      taosArrayDestroy(pWins);
      continue;
4089
    } else if (pBlock->info.type == STREAM_GET_ALL) {
5
54liuyao 已提交
4090
      getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
5
54liuyao 已提交
4091
      continue;
5
54liuyao 已提交
4092 4093 4094 4095
    } 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 已提交
4096
    }
4097

5
54liuyao 已提交
4098 4099 4100 4101
    if (pInfo->scalarSupp.pExprInfo != NULL) {
      SExprSupp* pExprSup = &pInfo->scalarSupp;
      projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
    }
4102
    // the pDataBlock are always the same one, no need to call this again
4103
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
5
54liuyao 已提交
4104 4105
    doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
5
54liuyao 已提交
4106 4107 4108
  }
  // restore the value
  pOperator->status = OP_RES_TO_RETURN;
X
Xiaoyu Wang 已提交
4109

5
54liuyao 已提交
4110 4111 4112 4113 4114
  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 已提交
4115

5
54liuyao 已提交
4116 4117
  initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
5
54liuyao 已提交
4118
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
5
54liuyao 已提交
4119

5
54liuyao 已提交
4120 4121 4122 4123 4124 4125
#if 0
  char* pBuf = streamStateSessionDump(pInfo->streamAggSup.pState);
  qDebug("===stream===final session%s", pBuf);
  taosMemoryFree(pBuf);
#endif

4126
  doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator);
5
54liuyao 已提交
4127
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4128
    printDataBlock(pInfo->pDelRes, "single state delete");
5
54liuyao 已提交
4129 4130 4131
    return pInfo->pDelRes;
  }

5
54liuyao 已提交
4132 4133 4134 4135 4136
  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 已提交
4137
  setOperatorCompleted(pOperator);
5
54liuyao 已提交
4138
  return NULL;
4139 4140
}

X
Xiaoyu Wang 已提交
4141 4142 4143 4144 4145
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 已提交
4146
  int32_t                      code = TSDB_CODE_SUCCESS;
5
54liuyao 已提交
4147

X
Xiaoyu Wang 已提交
4148 4149
  SStreamStateAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamStateAggOperatorInfo));
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
5
54liuyao 已提交
4150
  if (pInfo == NULL || pOperator == NULL) {
H
Haojun Liao 已提交
4151
    code = TSDB_CODE_OUT_OF_MEMORY;
5
54liuyao 已提交
4152 4153 4154 4155
    goto _error;
  }

  pInfo->stateCol = extractColumnFromColumnNode(pColNode);
4156
  initResultSizeInfo(&pOperator->resultInfo, 4096);
5
54liuyao 已提交
4157 4158 4159
  if (pStateNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pStateNode->window.pExprs, NULL, &numOfScalar);
4160
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4161 4162 4163 4164 4165
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }

X
Xiaoyu Wang 已提交
4166 4167
  pInfo->twAggSup = (STimeWindowAggSupp){
      .waterMark = pStateNode->window.watermark,
5
54liuyao 已提交
4168 4169
      .calTrigger = pStateNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
4170
      .minTs = INT64_MAX,
X
Xiaoyu Wang 已提交
4171
  };
4172

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

5
54liuyao 已提交
4175 4176 4177
  SExprSupp*   pSup = &pOperator->exprSupp;
  int32_t      numOfCols = 0;
  SExprInfo*   pExprInfo = createExprInfo(pStateNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
4178
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
4179
  code = initBasicInfoEx(&pInfo->binfo, pSup, pExprInfo, numOfCols, pResBlock, &pTaskInfo->storageAPI.functionStore);
5
54liuyao 已提交
4180 4181 4182
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
5
54liuyao 已提交
4183 4184 4185
  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 已提交
4186
                                type, &pTaskInfo->storageAPI.stateStore);
5
54liuyao 已提交
4187 4188 4189 4190 4191 4192
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  pInfo->primaryTsIndex = tsSlotId;
  _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
5
54liuyao 已提交
4193
  pInfo->pSeDeleted = tSimpleHashInit(64, hashFn);
5
54liuyao 已提交
4194
  pInfo->pDelIterator = NULL;
H
Haojun Liao 已提交
4195
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
5
54liuyao 已提交
4196
  pInfo->pChildren = NULL;
5
54liuyao 已提交
4197
  pInfo->ignoreExpiredData = pStateNode->window.igExpired;
4198
  pInfo->ignoreExpiredDataSaved = false;
5
54liuyao 已提交
4199 4200
  pInfo->pUpdated = NULL;
  pInfo->pSeUpdated = NULL;
L
liuyao 已提交
4201
  pInfo->dataVersion = 0;
5
54liuyao 已提交
4202

L
Liu Jicong 已提交
4203 4204
  setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
L
Liu Jicong 已提交
4205 4206
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamStateAgg, NULL, destroyStreamStateOperatorInfo,
                                         optrDefaultBufFn, NULL);
5
54liuyao 已提交
4207
  initDownStream(downstream, &pInfo->streamAggSup, pOperator->operatorType, pInfo->primaryTsIndex, &pInfo->twAggSup);
5
54liuyao 已提交
4208 4209 4210 4211 4212 4213 4214
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
  return pOperator;

_error:
4215
  destroyStreamStateOperatorInfo(pInfo);
5
54liuyao 已提交
4216 4217 4218 4219
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4220

4221
void destroyMAIOperatorInfo(void* param) {
4222
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = (SMergeAlignedIntervalAggOperatorInfo*)param;
4223
  destroyIntervalOperatorInfo(miaInfo->intervalAggOperatorInfo);
D
dapan1121 已提交
4224
  taosMemoryFreeClear(param);
4225 4226
}

4227
static SResultRow* doSetSingleOutputTupleBuf(SResultRowInfo* pResultRowInfo, SAggSupporter* pSup) {
H
Haojun Liao 已提交
4228
  SResultRow* pResult = getNewResultRow(pSup->pResultBuf, &pSup->currentPageId, pSup->resultRowSize);
4229 4230 4231
  if (NULL == pResult) {
    return pResult;
  }
H
Haojun Liao 已提交
4232
  pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset};
4233 4234
  return pResult;
}
4235

4236 4237 4238 4239 4240 4241 4242 4243
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;
    }
  }
4244

4245
  // set time window for current result
4246 4247
  (*pResult)->win = (*win);
  setResultRowInitCtx((*pResult), pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset);
4248
  return TSDB_CODE_SUCCESS;
4249 4250
}

4251
static void doMergeAlignedIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResultRowInfo,
4252
                                          SSDataBlock* pBlock, SSDataBlock* pResultBlock) {
4253
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
D
dapan1121 已提交
4254
  SIntervalAggOperatorInfo*             iaInfo = miaInfo->intervalAggOperatorInfo;
4255 4256

  SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo;
4257
  SExprSupp*     pSup = &pOperatorInfo->exprSupp;
4258
  SInterval*     pInterval = &iaInfo->interval;
4259

5
54liuyao 已提交
4260 4261
  int32_t  startPos = 0;
  int64_t* tsCols = extractTsCol(pBlock, iaInfo);
4262

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

4265 4266
  // there is an result exists
  if (miaInfo->curTs != INT64_MIN) {
4267
    if (ts != miaInfo->curTs) {
4268
      finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4269
      resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4270
      miaInfo->curTs = ts;
4271
    }
4272 4273
  } else {
    miaInfo->curTs = ts;
4274 4275 4276
  }

  STimeWindow win = {0};
4277
  win.skey = miaInfo->curTs;
4278
  win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4279

5
54liuyao 已提交
4280
  int32_t ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4281 4282
  if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
    T_LONG_JMP(pTaskInfo->env, ret);
4283 4284
  }

4285 4286
  int32_t currPos = startPos;

4287
  STimeWindow currWin = win;
4288
  while (++currPos < pBlock->info.rows) {
4289
    if (tsCols[currPos] == miaInfo->curTs) {
4290
      continue;
4291 4292
    }

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

4297
    finalizeResultRows(iaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pResultBlock, pTaskInfo);
4298
    resetResultRow(miaInfo->pResultRow, iaInfo->aggSup.resultRowSize - sizeof(SResultRow));
4299
    miaInfo->curTs = tsCols[currPos];
4300

4301
    currWin.skey = miaInfo->curTs;
4302
    currWin.ekey = taosTimeAdd(currWin.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1;
4303 4304

    startPos = currPos;
5
54liuyao 已提交
4305
    ret = setSingleOutputTupleBuf(pResultRowInfo, &win, &miaInfo->pResultRow, pSup, &iaInfo->aggSup);
4306 4307
    if (ret != TSDB_CODE_SUCCESS || miaInfo->pResultRow == NULL) {
      T_LONG_JMP(pTaskInfo->env, ret);
4308
    }
4309 4310

    miaInfo->curTs = currWin.skey;
4311
  }
4312

L
liuyao 已提交
4313
  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &currWin, 1);
H
Haojun Liao 已提交
4314
  applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, currPos - startPos,
L
Liu Jicong 已提交
4315
                                  pBlock->info.rows, pSup->numOfExprs);
4316 4317
}

4318
static void cleanupAfterGroupResultGen(SMergeAlignedIntervalAggOperatorInfo* pMiaInfo, SSDataBlock* pRes) {
H
Haojun Liao 已提交
4319
  pRes->info.id.groupId = pMiaInfo->groupId;
4320 4321
  pMiaInfo->curTs = INT64_MIN;
  pMiaInfo->groupId = 0;
4322 4323
}

4324
static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
S
shenglian zhou 已提交
4325
  SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
4326

4327 4328
  SMergeAlignedIntervalAggOperatorInfo* pMiaInfo = pOperator->info;
  SIntervalAggOperatorInfo*             pIaInfo = pMiaInfo->intervalAggOperatorInfo;
4329

4330 4331 4332 4333
  SExprSupp*      pSup = &pOperator->exprSupp;
  SSDataBlock*    pRes = pIaInfo->binfo.pRes;
  SResultRowInfo* pResultRowInfo = &pIaInfo->binfo.resultRowInfo;
  SOperatorInfo*  downstream = pOperator->pDownstream[0];
4334

4335 4336
  while (1) {
    SSDataBlock* pBlock = NULL;
4337
    if (pMiaInfo->prefetchedBlock == NULL) {
4338 4339
      pBlock = downstream->fpSet.getNextFn(downstream);
    } else {
4340 4341
      pBlock = pMiaInfo->prefetchedBlock;
      pMiaInfo->prefetchedBlock = NULL;
4342

H
Haojun Liao 已提交
4343
      pMiaInfo->groupId = pBlock->info.id.groupId;
4344
    }
4345

4346
    // no data exists, all query processing is done
4347
    if (pBlock == NULL) {
4348 4349 4350
      // close last unclosed time window
      if (pMiaInfo->curTs != INT64_MIN) {
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4351 4352
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
4353
      }
4354

H
Haojun Liao 已提交
4355
      setOperatorCompleted(pOperator);
4356
      break;
4357
    }
4358

H
Haojun Liao 已提交
4359
    if (pMiaInfo->groupId == 0) {
H
Haojun Liao 已提交
4360 4361 4362
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
        pMiaInfo->groupId = pBlock->info.id.groupId;
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4363 4364
      }
    } else {
H
Haojun Liao 已提交
4365
      if (pMiaInfo->groupId != pBlock->info.id.groupId) {
H
Haojun Liao 已提交
4366
        // if there are unclosed time window, close it firstly.
4367
        ASSERT(pMiaInfo->curTs != INT64_MIN);
H
Haojun Liao 已提交
4368
        finalizeResultRows(pIaInfo->aggSup.pResultBuf, &pResultRowInfo->cur, pSup, pRes, pTaskInfo);
4369
        resetResultRow(pMiaInfo->pResultRow, pIaInfo->aggSup.resultRowSize - sizeof(SResultRow));
H
Haojun Liao 已提交
4370

4371 4372
        pMiaInfo->prefetchedBlock = pBlock;
        cleanupAfterGroupResultGen(pMiaInfo, pRes);
H
Haojun Liao 已提交
4373
        break;
5
54liuyao 已提交
4374
      } else {
H
Haojun Liao 已提交
4375
        // continue
H
Haojun Liao 已提交
4376
        pRes->info.id.groupId = pMiaInfo->groupId;
H
Haojun Liao 已提交
4377
      }
4378
    }
4379

4380 4381
    pRes->info.scanFlag = pBlock->info.scanFlag;
    setInputDataBlock(pSup, pBlock, pIaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
4382
    doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes);
4383

H
Haojun Liao 已提交
4384
    doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
4385 4386 4387
    if (pRes->info.rows >= pOperator->resultInfo.capacity) {
      break;
    }
4388
  }
4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403
}

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 已提交
4404
    while (1) {
4405
      if (pOperator->status == OP_EXEC_DONE) {
4406 4407
        break;
      }
4408

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

4413 4414 4415 4416
      doMergeAlignedIntervalAgg(pOperator);
    }
  } else {
    doMergeAlignedIntervalAgg(pOperator);
4417 4418 4419 4420 4421 4422 4423
  }

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

4424
SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode,
4425
                                                      SExecTaskInfo* pTaskInfo) {
4426
  SMergeAlignedIntervalAggOperatorInfo* miaInfo = taosMemoryCalloc(1, sizeof(SMergeAlignedIntervalAggOperatorInfo));
4427
  SOperatorInfo*                        pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4428 4429 4430 4431
  if (miaInfo == NULL || pOperator == NULL) {
    goto _error;
  }

D
dapan1121 已提交
4432 4433 4434 4435 4436
  miaInfo->intervalAggOperatorInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo));
  if (miaInfo->intervalAggOperatorInfo == NULL) {
    goto _error;
  }

4437 4438 4439 4440 4441 4442 4443
  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 已提交
4444
  SIntervalAggOperatorInfo* iaInfo = miaInfo->intervalAggOperatorInfo;
4445
  SExprSupp*                pSup = &pOperator->exprSupp;
4446

H
Haojun Liao 已提交
4447 4448 4449 4450 4451
  int32_t code = filterInitFromNode((SNode*)pNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

L
Liu Jicong 已提交
4452 4453
  miaInfo->curTs = INT64_MIN;
  iaInfo->win = pTaskInfo->window;
4454 4455
  iaInfo->binfo.inputTsOrder = pNode->window.node.inputTsOrder;
  iaInfo->binfo.outputTsOrder = pNode->window.node.outputTsOrder;
L
Liu Jicong 已提交
4456
  iaInfo->interval = interval;
4457 4458
  iaInfo->primaryTsIndex = ((SColumnNode*)pNode->window.pTspk)->slotId;
  iaInfo->binfo.mergeResultBlock = pNode->window.mergeDataBlock;
4459 4460

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

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

L
Liu Jicong 已提交
4466
  code = initAggSup(&pOperator->exprSupp, &iaInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4467
                    pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4468 4469 4470
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4471

H
Haojun Liao 已提交
4472
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pNode->window.node.pOutputDataBlockDesc);
4473
  initBasicInfo(&iaInfo->binfo, pResBlock);
4474
  initExecTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &iaInfo->win);
4475

4476
  iaInfo->timeWindowInterpo = timeWindowinterpNeeded(pSup->pCtx, num, iaInfo);
4477
  if (iaInfo->timeWindowInterpo) {
4478
    iaInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4479 4480
  }

4481
  initResultRowInfo(&iaInfo->binfo.resultRowInfo);
4482
  blockDataEnsureCapacity(iaInfo->binfo.pRes, pOperator->resultInfo.capacity);
L
Liu Jicong 已提交
4483 4484
  setOperatorInfo(pOperator, "TimeMergeAlignedIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL,
                  false, OP_NOT_OPENED, miaInfo, pTaskInfo);
4485

L
Liu Jicong 已提交
4486 4487
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, mergeAlignedIntervalAgg, NULL, destroyMAIOperatorInfo,
                                         optrDefaultBufFn, NULL);
4488 4489 4490 4491 4492 4493 4494 4495 4496

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

  return pOperator;

_error:
4497
  destroyMAIOperatorInfo(miaInfo);
4498 4499 4500 4501
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}
4502 4503 4504 4505 4506

//=====================================================================================================================
// merge interval operator
typedef struct SMergeIntervalAggOperatorInfo {
  SIntervalAggOperatorInfo intervalAggOperatorInfo;
L
Liu Jicong 已提交
4507 4508 4509 4510 4511 4512
  SList*                   groupIntervals;
  SListIter                groupIntervalsIter;
  bool                     hasGroupId;
  uint64_t                 groupId;
  SSDataBlock*             prefetchedBlock;
  bool                     inputBlocksFinished;
4513 4514
} SMergeIntervalAggOperatorInfo;

S
slzhou 已提交
4515
typedef struct SGroupTimeWindow {
L
Liu Jicong 已提交
4516
  uint64_t    groupId;
S
slzhou 已提交
4517 4518 4519
  STimeWindow window;
} SGroupTimeWindow;

4520
void destroyMergeIntervalOperatorInfo(void* param) {
4521
  SMergeIntervalAggOperatorInfo* miaInfo = (SMergeIntervalAggOperatorInfo*)param;
S
slzhou 已提交
4522
  tdListFree(miaInfo->groupIntervals);
4523
  destroyIntervalOperatorInfo(&miaInfo->intervalAggOperatorInfo);
4524

D
dapan1121 已提交
4525
  taosMemoryFreeClear(param);
4526 4527 4528 4529 4530 4531
}

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

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

S
slzhou 已提交
4537 4538 4539 4540 4541
  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 已提交
4542
    if (prevGrpWin->groupId != tableGroupId) {
S
slzhou 已提交
4543 4544
      continue;
    }
4545

S
slzhou 已提交
4546
    STimeWindow* prevWin = &prevGrpWin->window;
H
Haojun Liao 已提交
4547
    if ((ascScan && newWin->skey > prevWin->ekey) || ((!ascScan) && newWin->skey < prevWin->ekey)) {
S
slzhou 已提交
4548 4549
      tdListPopNode(miaInfo->groupIntervals, listNode);
    }
4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565
  }

  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 已提交
4566
  uint64_t    tableGroupId = pBlock->info.id.groupId;
4567
  bool        ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
4568 4569 4570
  TSKEY       blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
  SResultRow* pResult = NULL;

4571
  STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
4572
                                        iaInfo->binfo.inputTsOrder);
4573 4574 4575 4576 4577

  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 已提交
4578
    T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4579 4580 4581 4582
  }

  TSKEY   ekey = ascScan ? win.ekey : win.skey;
  int32_t forwardRows =
4583
      getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4584
  ASSERT(forwardRows > 0);
4585 4586 4587

  // prev time window not interpolation yet.
  if (iaInfo->timeWindowInterpo) {
4588
    SResultRowPosition pos = addToOpenWindowList(pResultRowInfo, pResult, tableGroupId);
4589 4590 4591 4592 4593 4594
    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 已提交
4595
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4596 4597 4598 4599 4600 4601 4602
    }

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

  updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &win, true);
H
Haojun Liao 已提交
4603
  applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4604
                                  pBlock->info.rows, numOfOutput);
4605 4606 4607 4608 4609 4610 4611 4612
  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;
4613
    startPos =
4614
        getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->binfo.inputTsOrder);
4615 4616 4617 4618 4619 4620 4621 4622 4623
    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 已提交
4624
      T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY);
4625 4626 4627 4628
    }

    ekey = ascScan ? nextWin.ekey : nextWin.skey;
    forwardRows =
4629
        getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
4630 4631 4632 4633

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

L
liuyao 已提交
4634
    updateTimeWindowInfo(&iaInfo->twAggSup.timeWindowData, &nextWin, 1);
H
Haojun Liao 已提交
4635
    applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &iaInfo->twAggSup.timeWindowData, startPos, forwardRows,
L
Liu Jicong 已提交
4636
                                    pBlock->info.rows, numOfOutput);
4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670
    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 已提交
4671
        miaInfo->groupId = pBlock->info.id.groupId;
4672 4673 4674 4675
        miaInfo->prefetchedBlock = NULL;
      }

      if (pBlock == NULL) {
S
slzhou 已提交
4676
        tdListInitIter(miaInfo->groupIntervals, &miaInfo->groupIntervalsIter, TD_LIST_FORWARD);
4677 4678 4679 4680 4681 4682
        miaInfo->inputBlocksFinished = true;
        break;
      }

      if (!miaInfo->hasGroupId) {
        miaInfo->hasGroupId = true;
H
Haojun Liao 已提交
4683 4684
        miaInfo->groupId = pBlock->info.id.groupId;
      } else if (miaInfo->groupId != pBlock->info.id.groupId) {
4685 4686 4687 4688
        miaInfo->prefetchedBlock = pBlock;
        break;
      }

4689 4690 4691
      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);
4692 4693 4694 4695 4696 4697

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

H
Haojun Liao 已提交
4698
    pRes->info.id.groupId = miaInfo->groupId;
4699 4700 4701
  }

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

S
slzhou 已提交
4704 4705
    if (listNode != NULL) {
      SGroupTimeWindow* grpWin = (SGroupTimeWindow*)(listNode->data);
H
Haojun Liao 已提交
4706
      pRes->info.id.groupId = grpWin->groupId;
4707 4708 4709 4710
    }
  }

  if (pRes->info.rows == 0) {
H
Haojun Liao 已提交
4711
    setOperatorCompleted(pOperator);
4712 4713 4714 4715 4716 4717 4718
  }

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

4719 4720 4721
SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode,
                                               SExecTaskInfo* pTaskInfo) {
  SMergeIntervalAggOperatorInfo* pMergeIntervalInfo = taosMemoryCalloc(1, sizeof(SMergeIntervalAggOperatorInfo));
4722
  SOperatorInfo*                 pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4723
  if (pMergeIntervalInfo == NULL || pOperator == NULL) {
4724 4725 4726
    goto _error;
  }

5
54liuyao 已提交
4727 4728
  int32_t    num = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &num);
4729 4730 4731 4732 4733 4734 4735

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

4737
  pMergeIntervalInfo->groupIntervals = tdListNew(sizeof(SGroupTimeWindow));
4738

4739
  SIntervalAggOperatorInfo* pIntervalInfo = &pMergeIntervalInfo->intervalAggOperatorInfo;
L
Liu Jicong 已提交
4740
  pIntervalInfo->win = pTaskInfo->window;
4741
  pIntervalInfo->binfo.inputTsOrder = pIntervalPhyNode->window.node.inputTsOrder;
L
Liu Jicong 已提交
4742
  pIntervalInfo->interval = interval;
4743 4744
  pIntervalInfo->binfo.mergeResultBlock = pIntervalPhyNode->window.mergeDataBlock;
  pIntervalInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
4745
  pIntervalInfo->binfo.outputTsOrder = pIntervalPhyNode->window.node.outputTsOrder;
4746 4747 4748 4749

  SExprSupp* pExprSupp = &pOperator->exprSupp;

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

L
Liu Jicong 已提交
4752
  int32_t code = initAggSup(pExprSupp, &pIntervalInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
4753
                            pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
4754 4755 4756
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }
4757

H
Haojun Liao 已提交
4758
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pIntervalPhyNode->window.node.pOutputDataBlockDesc);
4759 4760
  initBasicInfo(&pIntervalInfo->binfo, pResBlock);
  initExecTimeWindowInfo(&pIntervalInfo->twAggSup.timeWindowData, &pIntervalInfo->win);
4761

4762 4763
  pIntervalInfo->timeWindowInterpo = timeWindowinterpNeeded(pExprSupp->pCtx, num, pIntervalInfo);
  if (pIntervalInfo->timeWindowInterpo) {
4764
    pIntervalInfo->binfo.resultRowInfo.openWindow = tdListNew(sizeof(SOpenWindowInfo));
4765
    if (pIntervalInfo->binfo.resultRowInfo.openWindow == NULL) {
4766 4767 4768 4769
      goto _error;
    }
  }

4770
  initResultRowInfo(&pIntervalInfo->binfo.resultRowInfo);
L
Liu Jicong 已提交
4771 4772
  setOperatorInfo(pOperator, "TimeMergeIntervalAggOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, false,
                  OP_NOT_OPENED, pMergeIntervalInfo, pTaskInfo);
L
Liu Jicong 已提交
4773 4774
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doMergeIntervalAgg, NULL, destroyMergeIntervalOperatorInfo,
                                         optrDefaultBufFn, NULL);
4775 4776 4777 4778 4779 4780 4781 4782 4783

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

  return pOperator;

_error:
H
Haojun Liao 已提交
4784 4785 4786 4787
  if (pMergeIntervalInfo != NULL) {
    destroyMergeIntervalOperatorInfo(pMergeIntervalInfo);
  }

4788 4789 4790
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
L
Liu Jicong 已提交
4791
}
4792 4793 4794

static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) {
  SStreamIntervalOperatorInfo* pInfo = pOperator->info;
4795
  SExecTaskInfo*               pTaskInfo = pOperator->pTaskInfo;
4796 4797
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

4798
  SExprSupp* pSup = &pOperator->exprSupp;
4799 4800 4801 4802 4803 4804

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

  if (pOperator->status == OP_RES_TO_RETURN) {
4805
    doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
4806
    if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4807
      printDataBlock(pInfo->pDelRes, "single interval delete");
4808 4809 4810
      return pInfo->pDelRes;
    }

4811
    doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
4812 4813 4814
    if (pInfo->binfo.pRes->info.rows > 0) {
      printDataBlock(pInfo->binfo.pRes, "single interval");
      return pInfo->binfo.pRes;
4815
    }
L
liuyao 已提交
4816 4817 4818 4819 4820 4821

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

H
Haojun Liao 已提交
4822
    setOperatorCompleted(pOperator);
dengyihao's avatar
dengyihao 已提交
4823 4824
    if (pInfo->twAggSup.maxTs > 0 &&
        pInfo->twAggSup.maxTs - pInfo->twAggSup.checkPointInterval > pInfo->twAggSup.checkPointTs) {
4825 4826
      pAPI->stateStore.streamStateCommit(pInfo->pState);
      pAPI->stateStore.streamStateDeleteCheckPoint(pInfo->pState, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark);
L
liuyao 已提交
4827
      setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId);
L
liuyao 已提交
4828 4829
      pInfo->twAggSup.checkPointTs = pInfo->twAggSup.maxTs;
    }
5
54liuyao 已提交
4830
    return NULL;
4831 4832 4833 4834
  }

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

5
54liuyao 已提交
4835
  if (!pInfo->pUpdated) {
L
liuyao 已提交
4836
    pInfo->pUpdated = taosArrayInit(4096, POINTER_BYTES);
5
54liuyao 已提交
4837
  }
4838

5
54liuyao 已提交
4839 4840
  if (!pInfo->pUpdatedMap) {
    _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY);
L
liuyao 已提交
4841
    pInfo->pUpdatedMap = tSimpleHashInit(4096, hashFn);
5
54liuyao 已提交
4842 4843
  }

4844 4845 4846
  while (1) {
    SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
    if (pBlock == NULL) {
5
54liuyao 已提交
4847 4848
      qDebug("===stream===return data:single interval. recv datablock num:%" PRIu64, pInfo->numOfDatapack);
      pInfo->numOfDatapack = 0;
4849 4850
      break;
    }
4851

5
54liuyao 已提交
4852
    pInfo->numOfDatapack++;
4853 4854
    printDataBlock(pBlock, "single interval recv");

4855 4856
    if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT ||
        pBlock->info.type == STREAM_CLEAR) {
5
54liuyao 已提交
4857
      doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap);
4858 4859
      continue;
    } else if (pBlock->info.type == STREAM_GET_ALL) {
L
liuyao 已提交
4860
      qDebug("===stream===single interval recv|block type STREAM_GET_ALL");
L
liuyao 已提交
4861
      pInfo->recvGetAll = true;
5
54liuyao 已提交
4862
      getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap);
4863
      continue;
5
54liuyao 已提交
4864
    } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
5
54liuyao 已提交
4865
      printDataBlock(pBlock, "single interval");
5
54liuyao 已提交
4866 4867 4868
      return pBlock;
    } else {
      ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type");
4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883
    }

    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
4884
    setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true);
4885 4886 4887 4888
    if (pInfo->invertible) {
      setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type);
    }

5
54liuyao 已提交
4889
    doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap);
5
54liuyao 已提交
4890 4891
    pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey);
    pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey);
4892 4893
  }
  pOperator->status = OP_RES_TO_RETURN;
5
54liuyao 已提交
4894
  removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins);
4895 4896
  closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL,
                            pInfo->pUpdatedMap, pInfo->pDelWins, pOperator);
4897

4898 4899 4900
  void*   pIte = NULL;
  int32_t iter = 0;
  while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) {
5
54liuyao 已提交
4901
    taosArrayPush(pInfo->pUpdated, pIte);
4902
  }
5
54liuyao 已提交
4903
  taosArraySort(pInfo->pUpdated, winPosCmprImpl);
4904

5
54liuyao 已提交
4905 4906
  initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated);
  pInfo->pUpdated = NULL;
4907
  blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
4908
  tSimpleHashCleanup(pInfo->pUpdatedMap);
5
54liuyao 已提交
4909
  pInfo->pUpdatedMap = NULL;
5
54liuyao 已提交
4910

5
54liuyao 已提交
4911 4912 4913 4914 4915 4916
#if 0
  char* pBuf = streamStateIntervalDump(pInfo->pState);
  qDebug("===stream===interval state%s", pBuf);
  taosMemoryFree(pBuf);
#endif

4917
  doBuildDeleteResult(pInfo, pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes);
4918
  if (pInfo->pDelRes->info.rows > 0) {
5
54liuyao 已提交
4919
    printDataBlock(pInfo->pDelRes, "single interval delete");
4920 4921 4922
    return pInfo->pDelRes;
  }

4923
  doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo);
5
54liuyao 已提交
4924 4925 4926 4927 4928 4929
  if (pInfo->binfo.pRes->info.rows > 0) {
    printDataBlock(pInfo->binfo.pRes, "single interval");
    return pInfo->binfo.pRes;
  }

  return NULL;
4930 4931 4932 4933 4934
}

SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode,
                                                SExecTaskInfo* pTaskInfo) {
  SStreamIntervalOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamIntervalOperatorInfo));
4935
  SOperatorInfo*               pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
4936 4937 4938 4939 4940
  if (pInfo == NULL || pOperator == NULL) {
    goto _error;
  }
  SStreamIntervalPhysiNode* pIntervalPhyNode = (SStreamIntervalPhysiNode*)pPhyNode;

H
Haojun Liao 已提交
4941
  int32_t    code = TSDB_CODE_SUCCESS;
4942 4943
  int32_t    numOfCols = 0;
  SExprInfo* pExprInfo = createExprInfo(pIntervalPhyNode->window.pFuncs, NULL, &numOfCols);
H
Haojun Liao 已提交
4944

H
Haojun Liao 已提交
4945
  SSDataBlock* pResBlock = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
dengyihao's avatar
dengyihao 已提交
4946 4947 4948 4949 4950 4951 4952
  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,
4953
  };
H
Haojun Liao 已提交
4954

dengyihao's avatar
dengyihao 已提交
4955
  pInfo->twAggSup = (STimeWindowAggSupp){
4956 4957 4958
      .waterMark = pIntervalPhyNode->window.watermark,
      .calTrigger = pIntervalPhyNode->window.triggerType,
      .maxTs = INT64_MIN,
5
54liuyao 已提交
4959
      .minTs = INT64_MAX,
5
54liuyao 已提交
4960
      .deleteMark = getDeleteMark(pIntervalPhyNode),
L
liuyao 已提交
4961
      .checkPointTs = 0,
dengyihao's avatar
dengyihao 已提交
4962 4963
      .checkPointInterval =
          convertTimePrecision(tsCheckpointInterval, TSDB_TIME_PRECISION_MILLI, pInfo->interval.precision),
4964
  };
H
Haojun Liao 已提交
4965

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

4968
  pOperator->pTaskInfo = pTaskInfo;
4969 4970
  SStorageAPI* pAPI = &pOperator->pTaskInfo->storageAPI;

4971
  pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired;
4972
  pInfo->ignoreExpiredDataSaved = false;
4973 4974 4975
  pInfo->isFinal = false;

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

4980
  pInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
4981
  initResultSizeInfo(&pOperator->resultInfo, 4096);
4982

L
liuyao 已提交
4983 4984
  pInfo->pState = taosMemoryCalloc(1, sizeof(SStreamState));
  *(pInfo->pState) = *(pTaskInfo->streamInfo.pState);
4985
  pAPI->stateStore.streamStateSetNumber(pInfo->pState, -1);
L
liuyao 已提交
4986

4987
  size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES;
L
Liu Jicong 已提交
4988
  code = initAggSup(pSup, &pInfo->aggSup, pExprInfo, numOfCols, keyBufSize, pTaskInfo->id.str,
4989
                    pInfo->pState, &pTaskInfo->storageAPI.functionStore);
4990 4991 4992 4993
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

H
Haojun Liao 已提交
4994 4995 4996
  if (pIntervalPhyNode->window.pExprs != NULL) {
    int32_t    numOfScalar = 0;
    SExprInfo* pScalarExprInfo = createExprInfo(pIntervalPhyNode->window.pExprs, NULL, &numOfScalar);
4997
    code = initExprSupp(&pInfo->scalarSupp, pScalarExprInfo, numOfScalar, &pTaskInfo->storageAPI.functionStore);
H
Haojun Liao 已提交
4998 4999 5000 5001
    if (code != TSDB_CODE_SUCCESS) {
      goto _error;
    }
  }
5002 5003

  pInfo->invertible = allInvertible(pSup->pCtx, numOfCols);
5004
  pInfo->invertible = false;
5005 5006 5007 5008 5009
  pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey));
  pInfo->delIndex = 0;
  pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT);
  initResultRowInfo(&pInfo->binfo.resultRowInfo);

5010 5011
  pInfo->pPhyNode = NULL;  // create new child
  pInfo->pPullDataMap = NULL;
L
liuyao 已提交
5012
  pInfo->pFinalPullDataMap = NULL;
5013 5014 5015 5016
  pInfo->pPullWins = NULL;  // SPullWindowInfo
  pInfo->pullIndex = 0;
  pInfo->pPullDataRes = NULL;
  pInfo->isFinal = false;
L
liuyao 已提交
5017
  pInfo->numOfChild = 0;
5018 5019
  pInfo->delKey.ts = INT64_MAX;
  pInfo->delKey.groupId = 0;
5
54liuyao 已提交
5020
  pInfo->numOfDatapack = 0;
5
54liuyao 已提交
5021 5022
  pInfo->pUpdated = NULL;
  pInfo->pUpdatedMap = NULL;
L
liuyao 已提交
5023
  int32_t funResSize= getMaxFunResSize(pSup, numOfCols);
5024
  pInfo->pState->pFileState = pTaskInfo->storageAPI.stateStore.streamFileStateInit(tsStreamBufferSize, sizeof(SWinKey), pInfo->aggSup.resultRowSize, funResSize,
dengyihao's avatar
dengyihao 已提交
5025
                                                  compareTs, pInfo->pState, pInfo->twAggSup.deleteMark);
5026

L
Liu Jicong 已提交
5027 5028
  setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED,
                  pInfo, pTaskInfo);
5029 5030
  pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doStreamIntervalAgg, NULL,
                                         destroyStreamFinalIntervalOperatorInfo, optrDefaultBufFn, NULL);
5031

5032
  pInfo->statestore = pTaskInfo->storageAPI.stateStore;
L
liuyao 已提交
5033 5034
  pInfo->recvGetAll = false;

L
liuyao 已提交
5035
  initIntervalDownStream(downstream, pPhyNode->type, pInfo);
5036 5037 5038 5039 5040 5041 5042 5043
  code = appendDownstream(pOperator, &downstream, 1);
  if (code != TSDB_CODE_SUCCESS) {
    goto _error;
  }

  return pOperator;

_error:
5044
  destroyStreamFinalIntervalOperatorInfo(pInfo);
5045 5046 5047 5048
  taosMemoryFreeClear(pOperator);
  pTaskInfo->code = code;
  return NULL;
}